elem.red 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. module elem; % Simplification rules for elementary functions.
  2. % Author: Anthony C. Hearn.
  3. % Modifications by: Herbert Melenk, Rainer Schoepf.
  4. % Copyright (c) 1993 The RAND Corporation. All rights reserved.
  5. fluid '(!*!*sqrt !*complex !*keepsqrts !*precise !*rounded dmode!*
  6. !*elem!-inherit);
  7. % No references to RPLAC-based functions in this module.
  8. % For a proper bootstrapping the following order of operator
  9. % declarations is essential:
  10. % sqrt
  11. % sign with reference to sqrt
  12. % trigonometrical functions using abs which uses sign
  13. algebraic;
  14. % Square roots.
  15. deflist('((sqrt simpsqrt)),'simpfn);
  16. % for all x let sqrt x**2=x;
  17. % !*!*sqrt: used to indicate that SQRTs have been used.
  18. % !*keepsqrts: causes SQRT rather than EXPT to be used.
  19. symbolic procedure mksqrt u;
  20. if not !*keepsqrts then list('expt,u,list('quotient,1,2))
  21. else <<if null !*!*sqrt then <<!*!*sqrt := t;
  22. algebraic for all x let sqrt x**2=x>>;
  23. list('sqrt,u)>>;
  24. for all x let df(sqrt x,x)=sqrt x/(2*x);
  25. % SIGN operator.
  26. symbolic procedure sign!-of u;
  27. % Returns -1,0 or 1 if the sign of u is known. Otherwise nil.
  28. (numberp s and s) where s = numr simp!-sign{u};
  29. symbolic procedure simp!-sign u;
  30. begin scalar s,n;
  31. u:=reval car u;
  32. s:=if eqcar(u,'abs) then '(1 . 1)
  33. else if eqcar(u,'times) then simp!-sign!-times u
  34. else if eqcar(u,'plus) then simp!-sign!-plus u
  35. else simpiden{'sign,u};
  36. if not numberp(n:=numr s) or n=1 or n=-1 then return s;
  37. typerr(n,"sign value");
  38. end;
  39. symbolic procedure simp!-sign!-times w;
  40. % Factor all known signs out of the product.
  41. begin scalar n,s,x;
  42. n:=1;
  43. for each f in cdr w do
  44. <<x:=simp!-sign {f};
  45. if fixp numr x then n:=n * numr x else s:=f.s>>;
  46. n:=(n/abs n) ./ 1;
  47. s:=if null s then '(1 . 1) else
  48. simpiden {'sign, if cdr s then 'times.reversip s else car s};
  49. return multsq (n,s)
  50. end;
  51. symbolic procedure simp!-sign!-plus w;
  52. % Stop sign evaluation as soon as two different signs
  53. % or one unknown sign were found.
  54. begin scalar n,m,x,q;
  55. for each f in cdr w do if null q then
  56. <<x:=simp!-sign {f};
  57. m:=if fixp numr x then numr x/abs denr x;
  58. if null m or n and m neq n then q:=t;
  59. n:=m>>;
  60. return if null q then n ./ 1 else
  61. simpiden {'sign,w};
  62. end;
  63. fluid '(rd!-sign!*);
  64. symbolic procedure rd!-sign u;
  65. % if U is constant evaluable return sign of u.
  66. % the value is set aside.
  67. if pairp rd!-sign!* and u=car rd!-sign!* then cdr rd!-sign!*
  68. else
  69. if !*complex or !*rounded or not constant_exprp u then nil
  70. else
  71. (begin scalar x,y,dmode!*;
  72. setdmode('rounded,t);
  73. x := aeval u;
  74. if evalnumberp x and 0=reval {'impart,x}
  75. then y := if evalgreaterp(x,0) then 1 else
  76. if evalequal(x,0) then 0 else -1;
  77. setdmode('rounded,nil);
  78. rd!-sign!*:=(u.y);
  79. return y
  80. end) where alglist!*=alglist!*;
  81. symbolic operator rd!-sign;
  82. operator sign;
  83. put('sign,'simpfn,'simp!-sign);
  84. % The rules for products and sums are covered by the routines
  85. % below in order to avoid a combinatoric explosion. Abs (sign ~x)
  86. % cannot be defined by a rule because the evaluation of abs needs
  87. % sign.
  88. sign_rules :=
  89. { sign ~x => (if x>0 then 1 else if x<0 then -1 else 0)
  90. when numberp x and impart x=0,
  91. sign(-~x) => -sign(x),
  92. %% sign( ~x * ~y) => sign x * sign y
  93. %% when numberp sign x or numberp sign y,
  94. sign( ~x / ~y) => sign x * sign y
  95. when y neq 1 and (numberp sign x or numberp sign y),
  96. %% sign( ~x + ~y) => sign x when sign x = sign y,
  97. sign( ~x ^ ~n) => 1 when fixp (n/2) and lisp(not !*complex),
  98. sign( ~x ^ ~n) => sign x^n when fixp n and numberp sign x,
  99. sign( ~x ^ ~n) => sign x when fixp n and lisp(not !*complex),
  100. sign(sqrt ~a) => 1 when sign a=1,
  101. sign( ~a ^ ~x) => 1 when sign a=1 and impart x=0,
  102. %% sign(abs ~a) => 1,
  103. sign ~a => rd!-sign a when rd!-sign a,
  104. % Next rule here for convenience.
  105. abs(~x)^2 => x^2 when symbolic not !*precise}$
  106. % $ above needed for bootstrap.
  107. let sign_rules;
  108. % Rule for I**2.
  109. remflag('(i),'reserved);
  110. let i**2= -1;
  111. flag('(e i nil pi),'reserved); % Leave out T for now.
  112. % Logarithms.
  113. let log(e)= 1,
  114. log(1)= 0;
  115. for all x let log(e**x)=x; % e**log x=x now done by simpexpt.
  116. % The next rule is implemented via combine/expand logs.
  117. % for all x,y let log(x*y) = log x + log y, log(x/y) = log x - log y;
  118. let df(log(~x),~x) => 1/x;
  119. let df(log(~x/~y),~z) => df(log x,z) - df(log y,z);
  120. % Trigonometrical functions.
  121. deflist('((acos simpiden) (asin simpiden) (atan simpiden)
  122. (acosh simpiden) (asinh simpiden) (atanh simpiden)
  123. (acot simpiden) (cos simpiden) (sin simpiden) (tan simpiden)
  124. (sec simpiden) (sech simpiden) (csc simpiden) (csch simpiden)
  125. (cot simpiden)(acot simpiden)(coth simpiden)(acoth simpiden)
  126. (cosh simpiden) (sinh simpiden) (tanh simpiden)
  127. (asec simpiden) (acsc simpiden)
  128. (asech simpiden) (acsch simpiden)
  129. ),'simpfn);
  130. % The following declaration causes the simplifier to pass the full
  131. % expression (including the function) to simpiden.
  132. flag ('(acos asin atan acosh acot asinh atanh cos sin tan cosh sinh tanh
  133. csc csch sec sech cot acot coth acoth asec acsc asech acsch),
  134. 'full);
  135. % flag ('(atan),'oddreal);
  136. flag('(acoth acsc acsch asin asinh atan atanh sin tan csc csch sinh
  137. tanh cot coth),
  138. 'odd);
  139. flag('(cos sec sech cosh),'even);
  140. flag('(cot coth csc csch),'nonzero);
  141. % In the following rules, it is not necessary to let f(0)=0, when f
  142. % is odd, since simpiden already does this.
  143. % Some value have been commented out since these can be computed from
  144. % other functions.
  145. let cos(0)= 1,
  146. % sec(0)= 1,
  147. % cos(pi/12)=sqrt(2)/4*(sqrt 3+1),
  148. sin(pi/12)=sqrt(2)/4*(sqrt 3-1),
  149. sin(5pi/12)=sqrt(2)/4*(sqrt 3+1),
  150. % cos(pi/6)=sqrt 3/2,
  151. sin(pi/6)= 1/2,
  152. % cos(pi/4)=sqrt 2/2,
  153. sin(pi/4)=sqrt 2/2,
  154. % cos(pi/3) = 1/2,
  155. sin(pi/3) = sqrt(3)/2,
  156. cos(pi/2)= 0,
  157. sin(pi/2)= 1,
  158. sin(pi)= 0,
  159. cos(pi)=-1,
  160. cosh 0=1,
  161. sech(0) =1,
  162. sinh(i) => i*sin(1),
  163. cosh(i) => cos(1),
  164. acosh(1) => 0,
  165. acosh(-1) => i*pi
  166. % acos(0)= pi/2,
  167. % acos(1)=0,
  168. % acos(1/2)=pi/3,
  169. % acos(sqrt 3/2) = pi/6,
  170. % acos(sqrt 2/2) = pi/4,
  171. % acos(1/sqrt 2) = pi/4
  172. % asin(1/2)=pi/6,
  173. % asin(-1/2)=-pi/6,
  174. % asin(1)=pi/2,
  175. % asin(-1)=-pi/2
  176. ;
  177. for all x let cos acos x=x, sin asin x=x, tan atan x=x,
  178. cosh acosh x=x, sinh asinh x=x, tanh atanh x=x,
  179. cot acot x=x, coth acoth x=x, sec asec x=x,
  180. csc acsc x=x, sech asech x=x, csch acsch x=x;
  181. for all x let acos(-x)=pi-acos(x),
  182. acot(-x)=pi-acot(x);
  183. % Fold the elementary trigonometric functions down to the origin.
  184. let
  185. sin( (~~w + ~~k*pi)/~~d)
  186. => (if evenp fix(k/d) then 1 else -1)
  187. * sin((w + remainder(k,d)*pi)/d)
  188. when w freeof pi and ratnump(k/d) and fixp k and abs(k/d) >= 1,
  189. sin( ~~k*pi/~~d) => sin((1-k/d)*pi)
  190. when ratnump(k/d) and k/d > 1/2,
  191. cos( (~~w + ~~k*pi)/~~d)
  192. => (if evenp fix(k/d) then 1 else -1)
  193. * cos((w + remainder(k,d)*pi)/d)
  194. when w freeof pi and ratnump(k/d) and fixp k and abs(k/d) >= 1,
  195. cos( ~~k*pi/~~d) => -cos((1-k/d)*pi)
  196. when ratnump(k/d) and k/d > 1/2,
  197. tan( (~~w + ~~k*pi)/~~d)
  198. => tan((w + remainder(k,d)*pi)/d)
  199. when w freeof pi and ratnump(k/d) and fixp k and abs(k/d) >= 1,
  200. cot( (~~w + ~~k*pi)/~~d)
  201. => cot((w + remainder(k,d)*pi)/d)
  202. when w freeof pi and ratnump(k/d) and fixp k and abs(k/d) >= 1;
  203. % The following rules follow the pattern
  204. % sin(~x + pi/2)=> cos(x) when x freeof pi
  205. % however allowing x to be a quotient and a negative pi/2 shift.
  206. % We need to handleonly pi/2 shifts here because
  207. % the bigger shifts are already covered by the rules above.
  208. let sin((~x + ~~k*pi)/~d) => sign(k/d)*cos(x/d)
  209. when x freeof pi and abs(k/d) = 1/2,
  210. cos((~x + ~~k*pi)/~d) => -sign(k/d)*sin(x/d)
  211. when x freeof pi and abs(k/d) = 1/2,
  212. tan((~x + ~~k*pi)/~d) => -cot(x/d)
  213. when x freeof pi and abs(k/d) = 1/2,
  214. cot((~x + ~~k*pi)/~d) => -tan(x/d)
  215. when x freeof pi and abs(k/d) = 1/2;
  216. % Inherit function values.
  217. symbolic (!*elem!-inherit := t);
  218. symbolic procedure knowledge_about(op,arg,top);
  219. % True if the form '(op arg) can be formally simplified.
  220. % Avoiding recursion from rules for the target operator top by
  221. % a local remove of the property opmtch.
  222. % The internal switch !*elem!-inherit!* allows us to turn the
  223. % inheritage temporarily off.
  224. if dmode!* eq '!:rd!: or dmode!* eq '!:cr!:
  225. or null !*elem!-inherit then nil else
  226. (begin scalar r,old;
  227. old:=get(top,'opmtch); put(top,'opmtch,nil);
  228. r:= errorset!*({'aeval,mkquote{op,arg}},nil);
  229. put(top,'opmtch,old);
  230. return not errorp r and not smemq(op,car r)
  231. and not smemq(top,car r);
  232. end) where varstack!*=nil;
  233. symbolic operator knowledge_about;
  234. symbolic procedure trigquot(n,d);
  235. % Form a quotient n/d, replacing sin and cos by tan/cot
  236. % whenver possible.
  237. begin scalar m,u,w;
  238. u:=if eqcar(n,'minus) then <<m:=t; cadr n>> else n;
  239. if pairp u and pairp d then
  240. if car u eq 'sin and car d eq 'cos and cadr u=cadr d
  241. then w:='tan else
  242. if car u eq 'cos and car d eq 'sin and cadr u=cadr d
  243. then w:='cot;
  244. if null w then return{'quotient,n,d};
  245. w:={w,cadr u};
  246. return if m then {'minus,w} else w;
  247. end;
  248. symbolic operator trigquot;
  249. % cos, tan, cot, sec, csc inherit from sin.
  250. let cos(~x)=>sin(x+pi/2)
  251. when (x+pi/2)/pi freeof pi and knowledge_about(sin,x+pi/2,cos),
  252. cos(~x)=>-sin(x-pi/2)
  253. when (x-pi/2)/pi freeof pi and knowledge_about(sin,x-pi/2,cos),
  254. tan(~x)=>trigquot(sin(x),cos(x)) when knowledge_about(sin,x,tan),
  255. cot(~x)=>trigquot(cos(x),sin(x)) when knowledge_about(sin,x,cot),
  256. sec(~x)=>1/cos(x) when knowledge_about(cos,x,sec),
  257. csc(~x)=>1/sin(x) when knowledge_about(sin,x,csc);
  258. % area functions
  259. let asin(~x)=>pi/2 - acos(x) when knowledge_about(acos,x,asin),
  260. acot(~x)=>pi/2 - atan(x) when knowledge_about(atan,x,acot),
  261. acsc(~x) => asin(1/x) when knowledge_about(asin,1/x,acsc),
  262. asec(~x) => acos(1/x) when knowledge_about(acos,1/x,asec),
  263. acsch(~x) => acsc(-i*x)/i when knowledge_about(acsc,-i*x,acsch),
  264. asech(~x) => asec(x)/i when knowledge_about(asec,x,asech);
  265. % hyperbolic functions
  266. let sinh(i*~x)=>i*sin(x) when knowledge_about(sin,x,sinh),
  267. sinh(i*~x/~n)=>i*sin(x/n) when knowledge_about(sin,x/n,sinh),
  268. cosh(i*~x)=>cos(x) when knowledge_about(cos,x,cosh),
  269. cosh(i*~x/~n)=>cos(x/n) when knowledge_about(cos,x/n,cosh),
  270. cosh(~x)=>-i*sinh(x+i*pi/2)
  271. when (x+i*pi/2)/pi freeof pi
  272. and knowledge_about(sinh,x+i*pi/2,cosh),
  273. cosh(~x)=>i*sinh(x-i*pi/2)
  274. when (x-i*pi/2)/pi freeof pi
  275. and knowledge_about(sinh,x-i*pi/2,cosh),
  276. tanh(~x)=>sinh(x)/cosh(x) when knowledge_about(sinh,x,tanh),
  277. coth(~x)=>cosh(x)/sinh(x) when knowledge_about(sinh,x,coth),
  278. sech(~x)=>1/cosh(x) when knowledge_about(cosh,x,sech),
  279. csch(~x)=>1/sinh(x) when knowledge_about(sinh,x,csch);
  280. let acsch(~x) => asinh(1/x) when knowledge_about(asinh,1/x,acsch),
  281. asech(~x) => acosh(1/x) when knowledge_about(acosh,1/x,asech),
  282. asinh(~x) => -i*asin(i*x) when i*x freeof i
  283. and knowledge_about(asin,i*x,asinh);
  284. % hyperbolic functions
  285. let
  286. sinh( (~~w + ~~k*pi)/~~d)
  287. => (if evenp fix(i*k/d) then 1 else -1)
  288. * sinh((w + remainder(i*k,d)*pi/i)/d)
  289. when w freeof pi and ratnump(i*k/d) and fixp k and abs(i*k/d)>=1,
  290. sinh( ~~k*pi/~~d) => sinh((i-k/d)*pi)
  291. when ratnump(i*k/d) and abs(i*k/d) > 1/2,
  292. cosh( (~~w + ~~k*pi)/~~d)
  293. => (if evenp fix(i*k/d) then 1 else -1)
  294. * cosh((w + remainder(i*k,d)*pi/i)/d)
  295. when w freeof pi and ratnump(i*k/d) and fixp k and abs(i*k/d)>=1,
  296. cosh( ~~k*pi/~~d) => -cosh((i-k/d)*pi)
  297. when ratnump(i*k/d) and abs(i*k/d) > 1/2,
  298. tanh( (~~w + ~~k*pi)/~~d)
  299. => tanh((w + remainder(i*k,d)*pi/i)/d)
  300. when w freeof pi and ratnump(i*k/d) and fixp k and abs(i*k/d)>=1,
  301. coth( (~~w + ~~k*pi)/~~d)
  302. => coth((w + remainder(i*k,d)*pi/i)/d)
  303. when w freeof pi and ratnump(i*k/d) and fixp k and abs(i*k/d)>=1;
  304. % The following rules follow the pattern
  305. % sinh(~x + i*pi/2)=> cosh(x) when x freeof pi
  306. % however allowing x to be a quotient and a negative i*pi/2 shift.
  307. % We need to handle only pi/2 shifts here because
  308. % the bigger shifts are already covered by the rules above.
  309. let sinh((~x + ~~k*pi)/~d) => i*sign(-i*k/d)*cosh(x/d)
  310. when x freeof pi and abs(i*k/d) = 1/2,
  311. cosh((~x + ~~k*pi)/~d) => i*sign(-i*k/d)*sinh(x/d)
  312. when x freeof pi and abs(i*k/d) = 1/2,
  313. tanh((~x + ~~k*pi)/~d) => coth(x/d)
  314. when x freeof pi and abs(i*k/d) = 1/2,
  315. coth((~x + ~~k*pi)/~d) => tanh(x/d)
  316. when x freeof pi and abs(i*k/d) = 1/2;
  317. % Transfer inverse function values from cos to acos and tan to atan.
  318. % Negative values not needed.
  319. %symbolic procedure simpabs u;
  320. % if null u or cdr u then mksq('abs . revlis u, 1) % error?.
  321. % else begin scalar x;
  322. % u := car u;
  323. % if eqcar(u,'quotient) and fixp cadr u and fixp caddr u
  324. % and cadr u>0 and caddr u>0 then return simp u;
  325. % if x := rd!-abs u then return x;
  326. % u := simp!* u;
  327. % return if null numr u then nil ./ 1
  328. % else quotsq(mkabsf1 absf numr u,mkabsf1 denr u)
  329. % end;
  330. acos_rules :=
  331. symbolic(
  332. 'list . for j:=0:12 join
  333. (if eqcar(q,'acos) and cadr q=w then {{'replaceby,q,u}})
  334. where q=reval{'acos,w}
  335. where w=reval{'cos,u}
  336. where u=reval{'quotient,{'times,'pi,j},12})$
  337. let acos_rules;
  338. clear acos_rules;
  339. atan_rules :=
  340. symbolic(
  341. 'list . for j:=0:5 join
  342. (if eqcar(q,'atan) and cadr q=w then {{'replaceby,q,u}})
  343. where q= reval{'atan,w}
  344. where w= reval{'tan,u}
  345. where u= reval{'quotient,{'times,'pi,j},12})$
  346. let atan_rules;
  347. clear atan_rules;
  348. repart(pi) := pi$ % $ used for bootstrapping purposes.
  349. impart(pi) := 0$
  350. % ***** Differentiation rules *****.
  351. for all x let df(acos(x),x)= -sqrt(1-x**2)/(1-x**2),
  352. df(asin(x),x)= sqrt(1-x**2)/(1-x**2),
  353. df(atan(x),x)= 1/(1+x**2),
  354. df(acosh(x),x)= sqrt(x**2-1)/(x**2-1),
  355. df(acot(x),x)= -1/(1+x**2),
  356. df(acoth(x),x)= -1/(1-x**2),
  357. df(asinh(x),x)= sqrt(x**2+1)/(x**2+1),
  358. df(atanh(x),x)= 1/(1-x**2),
  359. df(acoth(x),x)= 1/(1-x**2),
  360. df(cos x,x)= -sin(x),
  361. df(sin x,x)= cos(x),
  362. df(sec x,x) = sec(x)*tan(x),
  363. df(csc x,x) = -csc(x)*cot(x),
  364. df(tan x,x)=1 + tan x**2,
  365. df(sinh x,x)=cosh x,
  366. df(cosh x,x)=sinh x,
  367. df(sech x,x) = -sech(x)*tanh(x),
  368. % df(tanh x,x)=sech x**2,
  369. % J.P. Fitch prefers this one for integration purposes
  370. df(tanh x,x)=1-tanh(x)**2,
  371. df(csch x,x)= -csch x*coth x,
  372. df(cot x,x)=-1-cot x**2,
  373. df(coth x,x)=1-coth x**2;
  374. let df(acsc(~x),x) => -1/(x*sqrt(x**2 - 1)),
  375. % df(asec(~x),x) => 1/(x*sqrt(x**2 - 1)), % Only true for abs x>1.
  376. df(asec(~x),x) => 1/(x^2*sqrt(1-1/x^2)),
  377. df(acsch(~x),x)=> -1/(x*sqrt(1+ x**2)),
  378. df(asech(~x),x)=> -1/(x*sqrt(1- x**2));
  379. %for all x let e**log x=x; % Requires every power to be checked.
  380. for all x,y let df(x**y,x)= y*x**(y-1),
  381. df(x**y,y)= log x*x**y;
  382. % Ei, erf, exp and dilog.
  383. operator dilog,ei,erf,exp;
  384. let dilog(0)=pi**2/6;
  385. for all x let df(dilog x,x)=-log x/(x-1);
  386. for all x let df(ei(x),x)=e**x/x;
  387. let erf 0=0;
  388. for all x let erf(-x)=-erf x;
  389. for all x let df(erf x,x)=2*sqrt(pi)*e**(-x**2)/pi;
  390. for all x let exp(x)=e**x;
  391. % Supply missing argument and simplify 1/4 roots of unity.
  392. let e**(i*pi/2) = i,
  393. e**(i*pi) = -1;
  394. % e**(3*i*pi/2)=-i;
  395. % Rule for derivative of absolute value.
  396. for all x let df(abs x,x)=abs x/x;
  397. % More trigonometrical rules.
  398. invtrigrules := {
  399. sin(atan ~u) => u/sqrt(1+u^2),
  400. cos(atan ~u) => 1/sqrt(1+u^2),
  401. sin(2*atan ~u) => 2*u/(1+u^2),
  402. cos(2*atan ~u) => (1-u^2)/(1+u^2),
  403. sin(~n*atan ~u) => sin((n-2)*atan u) * (1-u^2)/(1+u^2) +
  404. cos((n-2)*atan u) * 2*u/(1+u^2)
  405. when fixp n and n>2,
  406. cos(~n*atan ~u) => cos((n-2)*atan u) * (1-u^2)/(1+u^2) -
  407. sin((n-2)*atan u) * 2*u/(1+u^2)
  408. when fixp n and n>2,
  409. sin(acos ~u) => sqrt(1-u^2),
  410. cos(asin ~u) => sqrt(1-u^2),
  411. sin(2*acos ~u) => 2 * u * sqrt(1-u^2),
  412. cos(2*acos ~u) => 2*u^2 - 1,
  413. sin(2*asin ~u) => 2 * u * sqrt(1-u^2),
  414. cos(2*asin ~u) => 1 - 2*u^2,
  415. sin(~n*acos ~u) => sin((n-2)*acos u) * (2*u^2 - 1) +
  416. cos((n-2)*acos u) * 2 * u * sqrt(1-u^2)
  417. when fixp n and n>2,
  418. cos(~n*acos ~u) => cos((n-2)*acos u) * (2*u^2 - 1) -
  419. sin((n-2)*acos u) * 2 * u * sqrt(1-u^2)
  420. when fixp n and n>2,
  421. sin(~n*asin ~u) => sin((n-2)*asin u) * (1 - 2*u^2) +
  422. cos((n-2)*asin u) * 2 * u * sqrt(1-u^2)
  423. when fixp n and n>2,
  424. cos(~n*asin ~u) => cos((n-2)*asin u) * (1 - 2*u^2) -
  425. sin((n-2)*asin u) * 2 * u * sqrt(1-u^2)
  426. when fixp n and n>2
  427. % Next rule causes a simplification loop in solve(atan y=y).
  428. % atan(~x) => acos((1-x^2)/(1+x^2)) * sign (x) / 2
  429. % when symbolic(not !*complex) and x^2 neq -1
  430. % and acos((1-x^2)/(1+x^2)) freeof acos
  431. }$
  432. invhyprules := {
  433. sinh(atanh ~u) => u/sqrt(1-u^2),
  434. cosh(atanh ~u) => 1/sqrt(1-u^2),
  435. sinh(2*atanh ~u) => 2*u/(1-u^2),
  436. cosh(2*atanh ~u) => (1+u^2)/(1-u^2),
  437. sinh(~n*atanh ~u) => sinh((n-2)*atanh u) * (1+u^2)/(1-u^2) +
  438. cosh((n-2)*atanh u) * 2*u/(1-u^2)
  439. when fixp n and n>2,
  440. cosh(~n*atanh ~u) => cosh((n-2)*atanh u) * (1+u^2)/(1-u^2) +
  441. sinh((n-2)*atanh u) * 2*u/(1-u^2)
  442. when fixp n and n>2,
  443. sinh(acosh ~u) => sqrt(u^2-1),
  444. cosh(asinh ~u) => sqrt(1+u^2),
  445. sinh(2*acosh ~u) => 2 * u * sqrt(u^2-1),
  446. cosh(2*acosh ~u) => 2*u^2 - 1,
  447. sinh(2*asinh ~u) => 2 * u * sqrt(1+u^2),
  448. cosh(2*asinh ~u) => 1 + 2*u^2,
  449. sinh(~n*acosh ~u) => sinh((n-2)*acosh u) * (2*u^2 - 1) +
  450. cosh((n-2)*acosh u) * 2 * u * sqrt(u^2-1)
  451. when fixp n and n>2,
  452. cosh(~n*acosh ~u) => cosh((n-2)*acosh u) * (2*u^2 - 1) +
  453. sinh((n-2)*acosh u) * 2 * u * sqrt(u^2-1)
  454. when fixp n and n>2,
  455. sinh(~n*asinh ~u) => sinh((n-2)*asinh u) * (1 + 2*u^2) +
  456. cosh((n-2)*asinh u) * 2 * u * sqrt(1+u^2)
  457. when fixp n and n>2,
  458. cosh(~n*asinh ~u) => cosh((n-2)*asinh u) * (1 + 2*u^2) +
  459. sinh((n-2)*asinh u) * 2 * u * sqrt(1+u^2)
  460. when fixp n and n>2,
  461. atanh(~x) => acosh((1+x^2)/(1-x^2)) * sign (x) / 2
  462. when symbolic(not !*complex)
  463. and acosh((1+x^2)/(1-x^2)) freeof acosh
  464. }$
  465. let invtrigrules,invhyprules;
  466. trig_imag_rules := {
  467. sin(i * ~~x / ~~y) => i * sinh(x/y) when impart(y)=0,
  468. cos(i * ~~x / ~~y) => cosh(x/y) when impart(y)=0,
  469. sinh(i * ~~x / ~~y) => i * sin(x/y) when impart(y)=0,
  470. cosh(i * ~~x / ~~y) => cos(x/y) when impart(y)=0,
  471. asin(i * ~~x / ~~y) => i * asinh(x/y) when impart(y)=0,
  472. atan(i * ~~x / ~~y) => i * atanh(x/y) when impart(y)=0
  473. and not(x=1 and y=1),
  474. asinh(i * ~~x / ~~y) => i * asin(x/y) when impart(y)=0,
  475. atanh(i * ~~x / ~~y) => i * atan(x/y) when impart(y)=0
  476. }$
  477. let trig_imag_rules;
  478. % Generalized periodicity rules for trigonometric functions.
  479. % FJW, 16 October 1996.
  480. let {
  481. cos(~n*pi*arbint(~i) + ~~x) => cos(remainder(n,2)*pi*arbint(i) + x)
  482. when fixp n,
  483. sin(~n*pi*arbint(~i) + ~~x) => sin(remainder(n,2)*pi*arbint(i) + x)
  484. when fixp n,
  485. tan(~n*pi*arbint(~i) + ~~x) => tan(x) when fixp n,
  486. sec(~n*pi*arbint(~i) + ~~x) => sec(remainder(n,2)*pi*arbint(i) + x)
  487. when fixp n,
  488. csc(~n*pi*arbint(~i) + ~~x) => csc(remainder(n,2)*pi*arbint(i) + x)
  489. when fixp n,
  490. cot(~n*pi*arbint(~i) + ~~x) => cot(x) when fixp n
  491. };
  492. endmodule;
  493. end;