2 /*Code added 7/5/80 by ELL for mapping all trig and hyper trig functions
3 into sin and cos (in lower case)*/
4 /* 4:00pm Tuesday, 11 August 1981 -GJC
5 Added more eval_when conditionals to complement the improvement
6 in Defrule translation and to invoke TRANSCOMPILE.
8 reformatting and some streamlining for translation. -asb
11 eval_when([translate],
13 tr_bound_function_applyp:false,
14 mode_declare(function(expnlength,argslength),fixnum))$
16 /* Variable definitions */
18 define_variable(bestlength,0,fixnum)$
19 define_variable(trylength,0,fixnum)$
23 /* The following properties are used to implement the four identities:
25 FOO^2=GET(FOO,'UNITCOF)
26 +GET(FOO,'COMPLEMENT_COF)*GET(FOO,'COMPLEMENT_FUNCTION)^2*/
28 put('sin,'cos,'complement_function)$
29 put('cos,'sin,'complement_function)$
30 put('sinh,'cosh,'complement_function)$
31 put('cosh,'sinh,'complement_function)$
34 put('cosh,1,'unitcof)$
35 put('sinh,-1,'unitcof)$
36 put('cos,-1,'complement_cof)$
37 put('sin,-1,'complement_cof)$
38 put('cosh,1,'complement_cof)$
39 put('sinh,1,'complement_cof)$
41 put('sin,'trigonometric,'type)$
42 put('cos,'trigonometric,'type)$
43 put('sinh,'hyper_trigonometric,'type)$
44 put('cosh,'hyper_trigonometric,'type)$
48 eval_when([translate,batch,demo],
49 matchdeclare(a,true))$
54 if not atom(exp) and symbolp(inpart(exp, 0))
55 then is(get(inpart(exp,0),'type)='trigonometric
56 or get(piece,'type)='hyper_trigonometric)$
60 defrule(trigrule1,tan(a),sin(a)/cos(a))$
61 defrule(trigrule2,sec(a),1/cos(a))$
62 defrule(trigrule3,csc(a),1/sin(a))$
63 defrule(trigrule4,cot(a),cos(a)/sin(a))$
64 defrule(htrigrule1,tanh(a),sinh(a)/cosh(a))$
65 defrule(htrigrule2,sech(a),1/cosh(a))$
66 defrule(htrigrule3,csch(a),1/sinh(a))$
67 defrule(htrigrule4,coth(a),cosh(a)/sinh(a))$
72 trigsimp3(ratsimp(apply1(x%,
73 trigrule1,trigrule2,trigrule3,trigrule4,
74 htrigrule1,htrigrule2,htrigrule3,htrigrule4)))$
77 * Original version, left for posterity
81 (expn:totaldisrep(expn),
82 ratsimp(trigsimp1(num(expn))/trigsimp1(denom(expn)))) $
86 * Like the original except that if expn is a list, we recurse over
87 * the list one at a time instead of doing it all at once. This
88 * prevents quadratic (or exponential) behavior as the list gets
101 cons(ratsimp(trigsimp1(num(expn[1]))/trigsimp1(denom(expn[1]))),
102 trigsimp3(rest(expn)))
104 ratsimp(trigsimp1(num(expn))/trigsimp1(denom(expn)))$
106 trigsimp1(expn):=block(
107 [listoftrigsq, bestlength, trylength],
108 listoftrigsq: listoftrigsq(expn),
111 then improve(expn,expn,listoftrigsq)
114 improve(expn,subsofar,listoftrigsq):=
116 then (if (trylength:expnlength(subsofar))<bestlength
117 then (bestlength:trylength,subsofar)
119 else (subsofar:improve(expn,subsofar,rest(listoftrigsq)),
120 for alt in first(listoftrigsq) do
123 ratsubst(get(inpart(alt,0),'unitcof)
124 +get(piece,'complement_cof)
125 *get(piece,'complement_function)(first(alt))^2,
133 else block([inflag, ans:[]],
134 if inpart(expn,0)="^" and integerp(inpart(expn,2))
136 then if atom(expn:inpart(expn,1))
138 else if trigonometricp(expn)
139 then return([[expn]]),
142 ans:specialunion(listoftrigsq(arg),ans),
145 specialunion(list1,list2):=
150 else block([alternates:first(list1)],
151 for alt in alternates do
152 list2:update(alt,get(inpart(alt,0),'complement_function)),
153 specialunion(rest(list1),list2))$
155 update(form, complement):=block(
157 complement: apply(complement,[inpart(form,1)]),
158 ans: for element in list2 do
159 if member(form, element) then return('found)
160 else if member(complement,element) then return(
161 cons([form,complement], delete(element,list2))),
165 then cons([form],list2)
168 expnlength(expr):=block(
172 else 1+argslength(args(expr)))$
175 apply("+",map('expnlength,args))$