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],
12 tr_bound_function_applyp:false,
13 mode_declare(function(expnlength,argslength),fixnum))$
15 /* Variable definitions */
17 define_variable(bestlength,0,fixnum)$
18 define_variable(trylength,0,fixnum)$
22 /* The following properties are used to implement the four identities:
24 FOO^2=GET(FOO,'UNITCOF)
25 +GET(FOO,'COMPLEMENT_COF)*GET(FOO,'COMPLEMENT_FUNCTION)^2*/
27 put('sin,'cos,'complement_function)$
28 put('cos,'sin,'complement_function)$
29 put('sinh,'cosh,'complement_function)$
30 put('cosh,'sinh,'complement_function)$
33 put('cosh,1,'unitcof)$
34 put('sinh,-1,'unitcof)$
35 put('cos,-1,'complement_cof)$
36 put('sin,-1,'complement_cof)$
37 put('cosh,1,'complement_cof)$
38 put('sinh,1,'complement_cof)$
40 put('sin,'trigonometric,'type)$
41 put('cos,'trigonometric,'type)$
42 put('sinh,'hyper_trigonometric,'type)$
43 put('cosh,'hyper_trigonometric,'type)$
47 eval_when([translate,batch,demo],
48 matchdeclare(a,true))$
53 if not atom(exp) and symbolp(inpart(exp, 0))
54 then is(get(inpart(exp,0),'type)='trigonometric
55 or get(piece,'type)='hyper_trigonometric)$
59 defrule(trigrule1,tan(a),sin(a)/cos(a))$
60 defrule(trigrule2,sec(a),1/cos(a))$
61 defrule(trigrule3,csc(a),1/sin(a))$
62 defrule(trigrule4,cot(a),cos(a)/sin(a))$
63 defrule(htrigrule1,tanh(a),sinh(a)/cosh(a))$
64 defrule(htrigrule2,sech(a),1/cosh(a))$
65 defrule(htrigrule3,csch(a),1/sinh(a))$
66 defrule(htrigrule4,coth(a),cosh(a)/sinh(a))$
71 trigsimp3(ratsimp(apply1(x%,
72 trigrule1,trigrule2,trigrule3,trigrule4,
73 htrigrule1,htrigrule2,htrigrule3,htrigrule4)))$
76 * Original version, left for posterity
80 (expn:totaldisrep(expn),
81 ratsimp(trigsimp1(num(expn))/trigsimp1(denom(expn)))) $
85 * Like the original except that if expn is a list, we recurse over
86 * the list one at a time instead of doing it all at once. This
87 * prevents quadratic (or exponential) behavior as the list gets
100 cons(ratsimp(trigsimp1(num(expn[1]))/trigsimp1(denom(expn[1]))),
101 trigsimp3(rest(expn)))
103 ratsimp(trigsimp1(num(expn))/trigsimp1(denom(expn)))$
105 trigsimp1(expn):=block(
106 [listoftrigsq, bestlength, trylength],
107 listoftrigsq: listoftrigsq(expn),
110 then improve(expn,expn,listoftrigsq)
113 improve(expn,subsofar,listoftrigsq):=
115 then (if (trylength:expnlength(subsofar))<bestlength
116 then (bestlength:trylength,subsofar)
118 else (subsofar:improve(expn,subsofar,rest(listoftrigsq)),
119 for alt in first(listoftrigsq) do
122 ratsubst(get(inpart(alt,0),'unitcof)
123 +get(piece,'complement_cof)
124 *get(piece,'complement_function)(first(alt))^2,
132 else block([inflag, ans:[]],
133 if inpart(expn,0)="^" and integerp(inpart(expn,2))
135 then if atom(expn:inpart(expn,1))
137 else if trigonometricp(expn)
138 then return([[expn]]),
141 ans:specialunion(listoftrigsq(arg),ans),
144 specialunion(list1,list2):=
149 else block([alternates:first(list1)],
150 for alt in alternates do
151 list2:update(alt,get(inpart(alt,0),'complement_function)),
152 specialunion(rest(list1),list2))$
154 update(form, complement):=block(
156 complement: apply(complement,[inpart(form,1)]),
157 ans: for element in list2 do
158 if member(form, element) then return('found)
159 else if member(complement,element) then return(
160 cons([form,complement], delete(element,list2))),
164 then cons([form],list2)
167 expnlength(expr):=block(
171 else 1+argslength(args(expr)))$
174 apply("+",map('expnlength,args))$