tayfns.red 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. module TayFns;
  2. %*****************************************************************
  3. %
  4. % Simplification functions for special functions
  5. %
  6. %*****************************************************************
  7. exports taysimpexpt, taysimpatan, taysimplog, taysimpexp,
  8. taysimptan, taysimpsin, taysimpsinh, taysimpasin;
  9. imports
  10. % from the REDUCE kernel:
  11. !*f2q, !:minusp, addsq, aeval, denr, domainp, eqcar, evenp,
  12. freeof, invsq, kernp, lastpair, let, lprim, lnc, mk!*sq, mksq,
  13. multsq, mvar, negsq, neq, nlist, nth, numr, over, prepd,
  14. prepsq, quotsq, retimes, reval, reversip, simp, simp!*,
  15. simplogi, simplogsq, subs2!*, subsq, subtrsq,
  16. % from the header module:
  17. !*tay2q, !*TayExp2q, constant!-sq!-p, cst!-Taylor!*,
  18. find!-non!-zero, get!-degree, has!-TayVars,
  19. make!-cst!-powerlist, make!-Taylor!*, prune!-coefflist,
  20. set!-TayCoeffList, set!-TayFlags, set!-TayOrig, TayCfPl,
  21. TayCfSq, TayCoeffList, TayFlags, TayGetCoeff, Taylor!*p,
  22. Taylor!-kernel!-sq!-p, Taylor!:, TayMakeCoeff, TayOrig,
  23. TayTemplate, TayTpElNext, TayTpElOrder, TayTpElPoint,
  24. TayTpElVars, TayTpVars, TayVars, TpNextList,
  25. % from the module Tayintro:
  26. confusion, delete!-nth, delete!-nth!-nth, replace!-nth,
  27. replace!-nth!-nth, Taylor!-error, Taylor!-error!*,
  28. var!-is!-nth,
  29. % from the module Tayutils:
  30. addto!-all!-TayTpElORders, get!-cst!-coeff, is!-neg!-pl,
  31. smallest!-increment, subtr!-degrees, Taylor!*!-constantp,
  32. Taylor!*!-zerop,
  33. % from the module Taybasic:
  34. addtaylor, addtaylor!-as!-sq, invtaylor, makecoeffs0,
  35. makecoeffpairs, makecoeffpairs1, multtaylor,
  36. multtaylor!-as!-sq, multtaylorsq, negtaylor, negtaylor1,
  37. quottaylor,
  38. % from the module TayExpnd:
  39. taylorexpand,
  40. % from the module Taysimp:
  41. expttayrat, taysimpsq, taysimpsq!*,
  42. % from the module Taydiff:
  43. difftaylorwrttayvar,
  44. % from the module TayConv:
  45. prepTayCoeff, prepTaylor!*,
  46. % from the module Tayfrontend:
  47. taylorcombine, taylortostandard;
  48. fluid '(!*taylorkeeporiginal !*!*taylor!-epsilon!*!* frlis!*);
  49. symbolic procedure taysimpexpt u;
  50. %
  51. % Argument is of the form ('expt base exponent)
  52. % where both base and exponent (but a least one of them)
  53. % may contain Taylor kernels given as prefix forms.
  54. % Value is the equivalent Taylor kernel.
  55. %
  56. if not (car u eq 'expt) or cdddr u then confusion 'taysimpexpt
  57. else if cadr u eq 'e then taysimpexp {'exp, caddr u}
  58. else begin scalar bas, expn;
  59. bas := taysimpsq simp!* cadr u;
  60. expn := taysimpsq simp!* caddr u;
  61. if constant!-sq!-p bas then return taysimpexp
  62. {'exp,mk!*sq multsq(simp!*{'log,mk!*sq bas},expn)};
  63. if null kernp bas
  64. then if not(denr bas = 1)
  65. then return mksq({'expt,prepsq bas,prepsq expn},1)
  66. else if domainp numr bas
  67. then return taysimpexp {'exp,
  68. prepsq multsq(simp!* {'log,prepd numr bas},expn)}
  69. else return mksq({'expt,prepsq bas,prepsq expn},1);
  70. if fixp numr expn and fixp denr expn
  71. then return !*tay2q expttayrat(mvar numr bas,expn);
  72. if denr expn = 1 and eqcar(numr expn,'!:rn!:)
  73. then return !*tay2q expttayrat(mvar numr bas,cdr numr expn);
  74. bas := mvar numr bas;
  75. return
  76. if Taylor!*p bas
  77. then if Taylor!-kernel!-sq!-p expn
  78. then if TayTemplate bas = TayTemplate mvar numr expn
  79. then taysimpexp {'exp,
  80. mk!*sq taysimpsq
  81. multtaylor!-as!-sq(
  82. expn,
  83. taysimplog {'log,bas})}
  84. else mksq({'expt,bas,mvar numr expn},1)
  85. else if not has!-TayVars(bas,expn)
  86. then begin scalar logterm;
  87. logterm := taysimplog{'log,bas};
  88. return
  89. if Taylor!-kernel!-sq!-p logterm
  90. then taysimpexp{'exp,
  91. multtaylorsq(mvar numr logterm,
  92. expn)}
  93. else taysimpsq
  94. simp!* {'exp,mk!*sq multsq(logterm,expn)}
  95. end
  96. else mksq({'expt,bas,mk!*sq expn},1)
  97. else if Taylor!-kernel!-sq!-p expn
  98. then if not has!-TayVars(mvar numr expn,bas)
  99. then taysimpexp{'exp,
  100. multtaylorsq(mvar numr expn,
  101. simp!*{'log,bas})}
  102. else if Taylor!*!-constantp mvar numr expn
  103. then taylorexpand(
  104. simp!* {'expt,bas,
  105. prepTaylor!* mvar numr expn},
  106. TayTemplate mvar numr expn)
  107. else mksq({'expt,bas,mk!*sq expn},1)
  108. else mksq({'expt,bas,mk!*sq expn},1);
  109. end;
  110. put('expt,'taylorsimpfn,'taysimpexpt);
  111. symbolic procedure TayCoeffList!-union u;
  112. if null cdr u then car u
  113. else TayCoeffList!-union2 (car u, TayCoeffList!-union cdr u)$
  114. symbolic procedure TayCoeffList!-union2 (x, y);
  115. %
  116. % returns union of TayCoeffLists x and y
  117. %
  118. << for each w in y do
  119. if null (assoc (car w, x)) then x := w . x;
  120. x >>$
  121. symbolic procedure inttaylorwrttayvar(tay,var);
  122. %
  123. % integrates Taylor kernel tay wrt variable var
  124. %
  125. inttaylorwrttayvar1(TayCoeffList tay,TayTemplate tay,var)$
  126. symbolic procedure inttaylorwrttayvar1(tcl,tp,var);
  127. %
  128. % integrates Taylor kernel with TayCoeffList tcl and template tp
  129. % wrt variable var
  130. %
  131. Taylor!:
  132. begin scalar tt,u,w,singlist,csing; integer n,n1,m;
  133. u := var!-is!-nth(tp,var);
  134. n := car u;
  135. n1 := cdr u;
  136. tt := nth(tp,n);
  137. u := for each cc in tcl join <<
  138. m := nth(nth(TayCfPl cc,n),n1);
  139. if TayTpElPoint nth(tp,n) eq 'infinity
  140. then <<
  141. if m=1 then <<singlist :=
  142. TayMakeCoeff(
  143. delete!-nth!-nth(TayCfPl cc,n,n1),
  144. TayCfSq cc) . singlist;nil>>
  145. else {TayMakeCoeff(
  146. replace!-nth!-nth(TayCfPl cc,n,n1,m-1),
  147. multsq(TayCfSq cc,invsq !*TayExp2q(-m + 1)))}>>
  148. else <<
  149. if m=-1 then <<singlist :=
  150. TayMakeCoeff(
  151. delete!-nth!-nth(TayCfPl cc,n,n1),
  152. TayCfSq cc) . singlist;nil>>
  153. else {TayMakeCoeff(
  154. replace!-nth!-nth(TayCfPl cc,n,n1,m+1),
  155. multsq(TayCfSq cc,invsq !*TayExp2q(m + 1)))}>>>>;
  156. w := {TayTpElVars tt,TayTpElPoint tt,
  157. if var member TayTpElVars tt
  158. then if TayTpElPoint tt eq 'infinity
  159. then TayTpElOrder tt - 1
  160. else TayTpElOrder tt + 1
  161. else TayTpElOrder tt,
  162. if var member TayTpElVars tt
  163. then if TayTpElPoint tt eq 'infinity
  164. then TayTpElNext tt - 1
  165. else TayTpElNext tt + 1
  166. else TayTpElOrder tt};
  167. if singlist then begin scalar tpel;
  168. tpel := nth(tp,n);
  169. singlist := reversip singlist;
  170. if TayCfPl car singlist = '(nil) % no Taylor left
  171. then csing := TayCfSq car singlist
  172. else csing := !*tay2q
  173. make!-Taylor!*(
  174. singlist,
  175. replace!-nth(
  176. tp,n,
  177. {delete!-nth(TayTpElVars tpel,n1),
  178. TayTpElPoint tpel,
  179. TayTpElOrder tpel,
  180. TayTpElNext tpel}),
  181. nil,nil);
  182. csing := multsq(csing,simp!* {'log,nth(TayTpElVars tpel,n1)})
  183. end;
  184. return (csing . make!-Taylor!*(u,replace!-nth(tp,n,w),nil,nil))
  185. %
  186. % The following is not needed yet
  187. %
  188. % return make!-Taylor!*(
  189. % u,
  190. % replace!-nth(TayTemplate tay,n,w),
  191. % if !*taylorkeeporiginal and TayOrig tay
  192. % then simp {'int,mk!*sq TayOrig tay,var}
  193. % else nil,
  194. % TayFlags u)
  195. end;
  196. comment The inverse trigonometric and inverse hyperbolic functions
  197. of a Taylor kernel are calculated by first computing the
  198. derivative(s) with respect to the Taylor variable(s) and
  199. integrating the result. The derivatives can easily be
  200. calculated by the manipulation functions defined above.
  201. The method is best illustrated with an example. Let T(x)
  202. be a Taylor kernel depending on one variable x. To compute
  203. the inverse tangent T1(x) = atan(T(x)) we calculate the
  204. derivative
  205. T'(x)
  206. T1'(x) = ----------- .
  207. 2
  208. 1 + T(x)
  209. (If T and T1 depend on more than one variable replace
  210. the derivatives by gradients.)
  211. This is integrated again with the integration constant
  212. T1(x0) = atan(T(x0)) yielding the desired result.
  213. If there is more than variable we have to find the
  214. potential function T1(x1,...,xn) corresponding to
  215. the vector grad T1(x1,...,xn) which is always possible
  216. by construction.
  217. The prescriptions for the eight functions asin, acos, asec,
  218. acsc, asinh, acosh, asech, and acsch can be put together
  219. in one procedure since the expressions for their derivatives
  220. differ only in certain signs. The same remark applies to
  221. the four functions atan, acot, atanh, and acoth.
  222. These expressions are:
  223. d 1
  224. -- asin x = ------------- ,
  225. dx sqrt(1-x^2)
  226. d -1
  227. -- acos x = ------------- ,
  228. dx sqrt(1-x^2)
  229. d 1
  230. -- asinh x = ------------- ,
  231. dx sqrt(1+x^2)
  232. d 1
  233. -- acosh x = ------------- ,
  234. dx sqrt(x^2-1)
  235. d 1
  236. -- atan x = --------- ,
  237. dx 1 + x^2
  238. d -1
  239. -- acot x = --------- ,
  240. dx 1 + x^2
  241. d 1
  242. -- atanh x = --------- ,
  243. dx 1 - x^2
  244. d 1
  245. -- acoth x = --------- ,
  246. dx 1 - x^2
  247. together with the relations
  248. 1
  249. asec x = acos - ,
  250. x
  251. 1
  252. acsc x = asin - ,
  253. x
  254. 1
  255. asech x = acosh - ,
  256. x
  257. 1
  258. acsch x = asinh -
  259. x .
  260. This method has one drawback: it is applicable only when T(x0)
  261. is a regular point of the function in question. E.g., if T(x0)
  262. = 0, then asech(T(x)) cannot be calculated by this method, as
  263. asech has a logarithmic singularity at 0. This means that the
  264. constant term of the series cannot be determined by computing
  265. asech(T(x0)). In that case, we use the following relations
  266. instead:
  267. asin z = -i log(i z + sqrt(1 - z^2)),
  268. acos z = -i log(z + sqrt(z^2 - 1)),
  269. 1 1 + i z
  270. atan z = ----- log ---------,
  271. 2 i 1 - i z
  272. -1 i z + 1
  273. acot z = ----- log ---------,
  274. 2 i i z - 1
  275. asinh z = log(z + sqrt(1 + z^2)),
  276. acosh z = log(z + sqrt(z^2 - 1)),
  277. 1 1 + z
  278. atanh z = --- log -------,
  279. 2 1 - z
  280. 1 z + 1
  281. acoth z = --- log -------.
  282. 2 z - 1
  283. These formulas are applied at the following points:
  284. infinity for all functions,
  285. +i/-i for atan and acot,
  286. +1/-1 for atanh and acoth.
  287. There are still some branch points, where the calculation is
  288. not always possible:
  289. +1/-1 for asin and acos, and consequently for asec and acsc,
  290. +i/-i for asinh, acosh, asech and acsch.
  291. In these cases, the above formulas are applied as well, but
  292. simplification of the square roots and the logarithm may lead
  293. to a rather complicated result;
  294. symbolic procedure taysimpasin u;
  295. if not (car u memq '(asin acos acsc asec asinh acosh acsch asech))
  296. or cddr u
  297. then confusion 'taysimpasin
  298. else Taylor!:
  299. begin scalar l,l0,c0,v,tay0,tay,tay2,tp,singlist;
  300. tay0 := taysimpsq simp!* cadr u;
  301. if not Taylor!-kernel!-sq!-p tay0
  302. then return mksq({car u,mk!*sq tay0},1);
  303. tay0 := mvar numr tay0; % asin's argument
  304. l0 := make!-cst!-powerlist TayTemplate tay0;
  305. c0 := TayGetCoeff(l0,TayCoeffList tay0);
  306. if car u memq '(asec acsc asech acsch)
  307. then if null numr c0 then return taysimpasec!*(car u,tay0)
  308. else tay := invtaylor tay0
  309. else tay := tay0;
  310. tp := TayTemplate tay;
  311. l := prune!-coefflist TayCoeffList tay;
  312. if null l then return !*tay2q cst!-Taylor!*(simp!* {car u,0},tp);
  313. if is!-neg!-pl TayCfPl car l then return taysimpasin!*(car u,tay);
  314. tay2 := multtaylor(tay,tay);
  315. if car u memq '(asin acos acsc asec)
  316. then tay2 := negtaylor tay2;
  317. tay2 := addtaylor(
  318. cst!-Taylor!*(
  319. !*f2q(if car u memq '(acosh asech) then -1 else 1),
  320. tp),
  321. tay2);
  322. if Taylor!*!-zerop tay2
  323. then Taylor!-error!*('branch!-point,car u)
  324. else if null numr TayGetCoeff(l0,TayCoeffList tay2)
  325. then return taysimpasin!*(car u,tay);
  326. tay2 := invtaylor expttayrat(tay2,1 ./ 2);
  327. if car u memq '(acos asec) then tay2 := negtaylor tay2;
  328. l := for each krnl in TayVars tay collect
  329. inttaylorwrttayvar(
  330. multtaylor(difftaylorwrttayvar(tay,krnl),tay2),
  331. krnl);
  332. v := TayCoeffList!-union
  333. for each pp in l collect TayCoeffList cdr pp;
  334. singlist := nil ./ 1;
  335. for each pp in l do
  336. if car pp then singlist := addsq(singlist,car pp);
  337. %
  338. % special treatment for zeroth coefficient
  339. %
  340. c0 := simp {car u,mk!*sq c0};
  341. v := TayMakeCoeff(l0,c0) . v;
  342. tay := make!-Taylor!*(
  343. v,
  344. tp,
  345. if !*taylorkeeporiginal and TayOrig tay
  346. then simp {car u,mk!*sq TayOrig tay}
  347. else nil,
  348. TayFlags tay);
  349. if null numr singlist then return !*tay2q tay;
  350. if !*taylorkeeporiginal and TayOrig tay
  351. then set!-TayOrig(tay,subtrsq(TayOrig tay,singlist));
  352. return addsq(singlist,!*tay2q tay)
  353. end;
  354. symbolic procedure taysimpasec!*(fn,tay);
  355. begin scalar result,tay1,tay2,i1;
  356. i1 := simp 'i;
  357. if fn memq '(asin acsc) then tay := multtaylorsq(tay,i1);
  358. tay1 := cst!-Taylor!*(1 ./ 1,TayTemplate tay);
  359. tay2 := multtaylor(tay,tay);
  360. if fn memq '(asec asech) then tay2 := negtaylor tay2;
  361. result := taysimplog {'log,
  362. addtaylor(
  363. expttayrat(addtaylor(tay2,tay1),1 ./ 2),
  364. tay1)};
  365. tay1 := taysimplog {'log,tay};
  366. if fn memq '(asin acos asec acsc)
  367. then <<result := taysimpsq negsq multsq(result,i1);
  368. result := addtaylor!-as!-sq(result,multsq(i1,tay1))>>
  369. else result := addtaylor!-as!-sq(result,
  370. negsq taysimplog {'log,tay});
  371. return taysimpsq!* result
  372. end;
  373. symbolic procedure taysimpasin!*(fn,tay);
  374. begin scalar result,tay1;
  375. if fn memq '(asin acsc)
  376. then tay := multtaylorsq(tay,simp 'i);
  377. tay1 := cst!-Taylor!*(
  378. (if fn memq '(asin asinh acsc acsch)
  379. then 1
  380. else -1) ./ 1,
  381. TayTemplate tay);
  382. result := taysimplog {'log,
  383. addtaylor(
  384. expttayrat(addtaylor(multtaylor(tay,tay),
  385. tay1),
  386. 1 ./ 2),
  387. tay)};
  388. if fn memq '(asin acos asec acsc)
  389. then result := quotsq(result,simp 'i);
  390. return taysimpsq!* result
  391. end;
  392. put('asin,'taylorsimpfn,'taysimpasin);
  393. put('acos,'taylorsimpfn,'taysimpasin);
  394. put('asec,'taylorsimpfn,'taysimpasin);
  395. put('acsc,'taylorsimpfn,'taysimpasin);
  396. put('asinh,'taylorsimpfn,'taysimpasin);
  397. put('acosh,'taylorsimpfn,'taysimpasin);
  398. put('asech,'taylorsimpfn,'taysimpasin);
  399. put('acsch,'taylorsimpfn,'taysimpasin);
  400. symbolic procedure taysimpatan u;
  401. if not (car u memq '(atan acot atanh acoth)) or cddr u
  402. then confusion 'taysimpatan
  403. else begin scalar l,l0,c0,v,tay,tay2,tp,singlist;
  404. tay := taysimpsq simp!* cadr u;
  405. if not Taylor!-kernel!-sq!-p tay
  406. then return mksq({car u,mk!*sq tay},1);
  407. tay := mvar numr tay; % atan's argument
  408. tp := TayTemplate tay;
  409. l0 := make!-cst!-powerlist tp;
  410. l := prune!-coefflist TayCoeffList tay;
  411. if null l then return !*tay2q cst!-Taylor!*(simp!* {car u,0},tp);
  412. if is!-neg!-pl TayCfPl car l then return taysimpatan!*(car u,tay);
  413. c0 := get!-cst!-coeff tay;
  414. if car u memq '(atan acot)
  415. then c0 := subs2!* multsq(c0,simp 'i);
  416. if c0 = (1 ./ 1) or c0 = (-1 ./ 1)
  417. then return taysimpatan!*(car u,tay);
  418. tay2 := multtaylor(tay,tay);
  419. if car u memq '(atanh acoth) then tay2 := negtaylor tay2;
  420. tay2 := invtaylor addtaylor(cst!-Taylor!*(1 ./ 1,tp),tay2);
  421. if car u eq 'acot then tay2 := negtaylor tay2;
  422. l := for each krnl in TayVars tay collect
  423. inttaylorwrttayvar(
  424. multtaylor(difftaylorwrttayvar(tay,krnl),tay2),
  425. krnl);
  426. v := TayCoeffList!-union
  427. for each pp in l collect TayCoeffList cdr pp;
  428. singlist := nil ./ 1;
  429. for each pp in l do
  430. if car pp then singlist := addsq(singlist,car pp);
  431. %
  432. % special treatment for zeroth coefficient
  433. %
  434. c0 := simp {car u,
  435. mk!*sq TayGetCoeff(l0,TayCoeffList tay)};
  436. v := TayMakeCoeff (l0,c0) . v;
  437. tay := make!-Taylor!*(
  438. v,
  439. tp,
  440. if !*taylorkeeporiginal and TayOrig tay
  441. then simp {car u,mk!*sq TayOrig tay}
  442. else nil,
  443. TayFlags tay);
  444. if null numr singlist then return !*tay2q tay;
  445. if !*taylorkeeporiginal and TayOrig tay
  446. then set!-TayOrig(tay,subtrsq(TayOrig tay,singlist));
  447. return addsq(singlist,!*tay2q tay)
  448. end;
  449. symbolic procedure taysimpatan!*(fn,tay);
  450. begin scalar result,tay1;
  451. if fn memq '(atan acot)
  452. then tay := multtaylorsq(tay,simp 'i);
  453. tay1 := cst!-Taylor!*(1 ./ 1,TayTemplate tay);
  454. tay := quottaylor(addtaylor(tay1,tay),
  455. addtaylor(tay1,negtaylor tay));
  456. result := multsq(taysimplog {'log,tay},1 ./ 2);
  457. if fn eq 'atan then result := quotsq(result,simp 'i)
  458. else if fn eq 'acot then result := multsq(result,simp 'i);
  459. return taysimpsq!* result
  460. end;
  461. put('atan,'taylorsimpfn,'taysimpatan);
  462. put('acot,'taylorsimpfn,'taysimpatan);
  463. put('atanh,'taylorsimpfn,'taysimpatan);
  464. put('acoth,'taylorsimpfn,'taysimpatan);
  465. comment For the logarithm and exponential we use the extension of
  466. an algorithm quoted by Knuth who shows how to do this for
  467. series in one expansion variable.
  468. We extended this to the case of several variables which is
  469. straightforward except for one point, see below.
  470. Knuth's algorithm works as follows: Assume you want to compute
  471. the series W(x) where
  472. W(x) = log V(x)
  473. Differentiation of this equation gives
  474. V'(x)
  475. W'(x) = ----- , or V'(x) = W'(x)V(x) .
  476. V(x)
  477. You make now the ansatz
  478. -----
  479. \ n
  480. W(x) = > W x ,
  481. / n
  482. -----
  483. substitute this into the above equation and compare
  484. powers of x. This yields the recursion formula
  485. n-1
  486. V -----
  487. n 1 \
  488. W = ---- - ------ > m W V .
  489. n V n V / m n-m
  490. 0 0 -----
  491. m=0
  492. The first coefficient must be calculated directly, it is
  493. W = log V .
  494. 0 0
  495. To use this for series in more than one variable you have to
  496. calculate all partial derivatives: n and m refer then to the
  497. corresponding component of the multi index. Looking closely
  498. one finds that there is an ambiguity: the same coefficient
  499. can be calculated using any of the partial derivatives. The
  500. only restriction is that the corresponding component of the
  501. multi index must not be zero, since we have to divide by it.
  502. We resolve this ambiguity by simply taking the first nonzero
  503. component.
  504. The case of the exponential is nearly the same: differentiation
  505. gives
  506. W'(x) = V'(x) W(x) ,
  507. from which we derive the recursion formula
  508. n-1
  509. -----
  510. \ n-m
  511. W = > --- W V , W = exp V .
  512. n / m m n-m 0 0
  513. -----
  514. m=0
  515. ;
  516. symbolic procedure taysimplog u;
  517. %
  518. % Special Taylor expansion function for logarithms
  519. %
  520. if not (car u eq 'log) or cddr u then confusion 'taysimplog
  521. else Taylor!:
  522. begin scalar a0,clist,coefflis,il,l0,l,tay,tp,csing,singterm;
  523. u := simplogi cadr u;
  524. if not kernp u then return taysimpsq u;
  525. u := mvar numr u;
  526. if not (car u eq 'log) then confusion 'taysimplog;
  527. u := taysimpsq simp!* cadr u;
  528. if not Taylor!-kernel!-sq!-p u then return mksq({'log,mk!*sq u},1);
  529. tay := mvar numr u;
  530. tp := TayTemplate tay;
  531. l0 := make!-cst!-powerlist tp;
  532. %
  533. % The following relies on the standard ordering of the
  534. % TayCoeffList.
  535. %
  536. l := prune!-coefflist TayCoeffList tay;
  537. if null l then Taylor!-error!*('not!-a!-unit,'taysimplog);
  538. %
  539. % The assumption at this point is that the first term is the one
  540. % with lowest degree, i.e. dividing by this term yields a series
  541. % which starts with a constant term.
  542. %
  543. if TayCfPl car l neq l0 then
  544. <<csing := TayCfPl car l;
  545. l := for each pp in l collect begin scalar newpl;
  546. newpl := subtr!-degrees(TayCfPl pp,csing);
  547. if is!-neg!-pl newpl
  548. then Taylor!-error('not!-a!-unit,'taysimplog)
  549. else return TayMakeCoeff(newpl,TayCfSQ pp);
  550. end;
  551. tp := addto!-all!-TayTpElOrders(
  552. tp,
  553. for each nl in csing collect
  554. - get!-degree nl);
  555. singterm := simp!* retimes preptaycoeff(csing,tp);
  556. if !:minusp lnc numr TayCfSq car l
  557. then <<singterm := negsq singterm;
  558. l := negtaylor1 l>>>>;
  559. a0 := TayGetCoeff(l0,l);
  560. clist := {TayMakeCoeff(l0,simplogi mk!*sq a0)};
  561. il := if null l then nlist(1,length tp)
  562. else smallest!-increment l;
  563. coefflis := makecoeffs0(tp,TpNextList tp,il);
  564. if not null coefflis
  565. then for each cc in cdr coefflis do
  566. begin scalar s,pos,pp,n,n1;
  567. s := nil ./ 1;
  568. pos := find!-non!-zero cc;
  569. n := nth(nth(cc,car pos),cdr pos);
  570. pp := makecoeffpairs(l0,cc,TayCfPl car l,il);
  571. for each p in pp do <<
  572. n1 := nth(nth(car p,car pos),cdr pos);
  573. s := addsq(s,
  574. multsq(!*TayExp2q n1,
  575. multsq(TayGetCoeff(car p,clist),
  576. TayGetCoeff(cdr p,l))))>>;
  577. % for each p in pp addsq
  578. % multsq(!*TayExp2q nth(nth(car p,car pos),cdr pos),
  579. % multsq(TayGetCoeff(car p,clist),
  580. % TayGetCoeff(cdr p,l)));
  581. s := subtrsq(TayGetCoeff(cc,l),quotsq(s,!*TayExp2q n));
  582. if not null numr s
  583. then clist := TayMakeCoeff(cc,quotsq(s,a0)) . clist;
  584. end;
  585. tay := make!-Taylor!*(
  586. reversip clist,
  587. tp,
  588. if !*taylorkeeporiginal and TayOrig tay
  589. then simplogi mk!*sq TayOrig tay
  590. else nil,
  591. TayFlags tay);
  592. if null csing then return !*tay2q tay;
  593. singterm := simplogsq singterm;
  594. if Taylor!*!-zerop tay then return singterm;
  595. if !*taylorkeeporiginal and TayOrig tay
  596. then set!-TayOrig(tay,subtrsq(TayOrig tay,singterm));
  597. return addsq(singterm,!*tay2q tay)
  598. end;
  599. put('log,'taylorsimpfn,'taysimplog);
  600. symbolic procedure taysimpexp u;
  601. %
  602. % Special Taylor expansion function for exponentials
  603. %
  604. if not (car u eq 'exp) or cddr u then confusion 'taysimpexp
  605. else Taylor!:
  606. begin scalar a0,clist,coefflis,il,l0,l,lm,lp,tay,tp;
  607. u := taysimpsq simp!* cadr u;
  608. if not Taylor!-kernel!-sq!-p u
  609. then return mksq ({'exp,mk!*sq u},1);
  610. tay := mvar numr u;
  611. tp := TayTemplate tay;
  612. l0 := make!-cst!-powerlist tp;
  613. %
  614. % The following relies on the standard ordering of the
  615. % TayCoeffList.
  616. %
  617. l := prune!-coefflist TayCoeffList tay;
  618. if null l then return !*tay2q cst!-Taylor!*(1 ./ 1,tp);
  619. for each pp in l do
  620. if is!-neg!-pl TayCfPl pp then lm := pp . lm
  621. else if not null numr TayCfSq pp then lp := pp . lp;
  622. lm := reversip lm;
  623. l := reversip lp;
  624. if lm
  625. then lm := simp!* {'exp,
  626. preptaylor!* make!-Taylor!*(lm,tp,nil,nil)};
  627. if null l then return lm;
  628. a0 := TayGetCoeff(l0,l);
  629. clist := {TayMakeCoeff(l0,simp!* {'exp,mk!*sq a0})};
  630. il := smallest!-increment l;
  631. coefflis := makecoeffs0(tp,TpNextList tp,il);
  632. if not null coefflis
  633. then for each cc in cdr coefflis do
  634. begin scalar s,pos,pp,n,n1;
  635. s := nil ./ 1;
  636. pos := find!-non!-zero cc;
  637. n := nth(nth(cc,car pos),cdr pos);
  638. pp := makecoeffpairs(l0,cc,l0,il);
  639. for each p in pp do <<
  640. n1 := nth(nth(car p,car pos),cdr pos);
  641. s := addsq(s,
  642. multsq(!*TayExp2q(n - n1),
  643. multsq(TayGetCoeff(car p,clist),
  644. TayGetCoeff(cdr p,l))))>>;
  645. s := subs2!* quotsq(s,!*TayExp2q n);
  646. if not null numr s
  647. then clist := TayMakeCoeff(cc,s) . clist
  648. end;
  649. clist := reversip clist;
  650. u := !*tay2q
  651. make!-Taylor!*(
  652. clist,
  653. tp,
  654. if !*taylorkeeporiginal and TayOrig tay
  655. then simp {'exp,mk!*sq TayOrig tay}
  656. else nil,
  657. TayFlags tay);
  658. return if null lm then u else multsq(u,lm)
  659. end;
  660. put('exp,'taylorsimpfn,'taysimpexp);
  661. comment The algorithm for the trigonometric functions is also
  662. derived from their differential equation.
  663. The simplest case is that of tangent whose equation is
  664. 2
  665. tan'(x) = 1 + tan (x) . (*)
  666. For the others we have
  667. 2
  668. cot'(x) = - (1 + cot (x)),
  669. 2
  670. tanh'(x) = 1 - tanh (x),
  671. 2
  672. coth'(x) = 1 - coth (x) .
  673. Let T(x) be a Taylor series,
  674. -----
  675. \ N
  676. T(x) = > a x
  677. / N
  678. -----
  679. N=0
  680. Now, let
  681. -----
  682. \ N
  683. T1(x) = tan T(x) = > b x
  684. / N
  685. -----
  686. N=0
  687. from which we immediately deduce that b = tan a .
  688. 0 0
  689. From (*) we get
  690. 2
  691. T1'(x) = (1 + T1(x) ) T'(x) ,
  692. or, written in terms of the series:
  693. Inserting this into (*) we get
  694. ----- / / ----- \ 2 \ -----
  695. \ N-1 | | \ N | | \ L
  696. > N b x = | 1 + | > b x | | > L a x
  697. / N | | / N | | / L
  698. ----- \ \ ----- / / -----
  699. N=1 N=0 L=1
  700. We perform the square on the r.h.s. using Cauchy's rule
  701. and obtain:
  702. -----
  703. \ N-1
  704. > N b x =
  705. / N
  706. -----
  707. N=1
  708. N
  709. / ----- ----- \ -----
  710. | \ \ N | \ L
  711. | 1 + > > b b x | > L a x .
  712. | / / N-M M | / L
  713. \ ----- ----- / -----
  714. N=0 M=0 L=1
  715. Expanding this once again with Cauchy's product rule we get
  716. -----
  717. \ N-1
  718. > N b x =
  719. / N
  720. -----
  721. N=1
  722. L-1 N
  723. ----- / ----- ----- \
  724. \ L-1 | \ \ |
  725. > x | L a + > > b b (L-N) a | .
  726. / | L / / N-M M L-N |
  727. ----- \ ----- ----- /
  728. L=1 N=0 M=0
  729. From this we immediately deduce the recursion relation
  730. L-1 N
  731. ----- -----
  732. \ L-N \
  733. b = a + > ----- a > b b . (**)
  734. L L / L L-N / N-M M
  735. ----- -----
  736. N=0 M=0
  737. This relation is easily generalized to the case of a
  738. series in more than one variable, where the same comments
  739. apply as in the case of log and exp above.
  740. For the hyperbolic tangent the relation is nearly the same.
  741. Since its differential equation has a `-' where that of
  742. tangent has a `+' we simply have to do the same substitution
  743. in the relation (**). For the cotangent we get an additional
  744. overall minus sign.
  745. There is one additional problem to be handled: if the constant
  746. term of T(x), i.e. T(x0) is a pole of tangent. This can be
  747. solved quite easily: for a small quantity TAYEPS we calculate
  748. Te(x) = T(x) + TAYEPS .
  749. and perform the above calculation for Te(x). Then we recover
  750. the desired result via the relation
  751. tan T(x) = tan (Te(x) - TAYEPS)
  752. tan Te(x) - tan TAYEPS
  753. = ---------------------------- .
  754. 1 + tan Te(x) * tan TAYEPS
  755. For the other functions we have similar relations:
  756. tanh T(x) = tanh (Te(x) - TAYEPS)
  757. tanh Te(x) - tanh TAYEPS
  758. = ------------------------------ ,
  759. 1 - tanh Te(x) * tanh TAYEPS
  760. cot T(x) = cot (Te(x) - TAYEPS)
  761. 1 + cot Te(x) * cot TAYEPS
  762. = ---------------------------- ,
  763. cot TAYEPS - cot Te(x)
  764. coth T(x) = coth (Te(x) - TAYEPS)
  765. 1 - coth Te(x) * coth TAYEPS
  766. = ------------------------------ .
  767. coth Te(x) - coth TAYEPS
  768. We know that this result is independent of TAYEPS, and we can
  769. thus evaluate it for any value of TAYEPS.
  770. Since we further know that T(x0) is a pole of the function in
  771. question, we can express tan (T(x0) + TAYEPS) as
  772. 1
  773. - ------------ ,
  774. tan TAYEPS
  775. and similarly all the other possible expressions involving
  776. TAYEPS can be written in terms of tan TAYEPS and tanh TAYEPS,
  777. respectively. This makes it possible to just substitute any
  778. occurrence of tan TAYEPS or tanh TAYEPS by zero, which greatly
  779. simplifies the final calculation
  780. ;
  781. !*!*taylor!-epsilon!*!* := compress '(t a y e p s);
  782. symbolic procedure taysimptan u;
  783. %
  784. % Special Taylor expansion function for circular and hyperbolic
  785. % tangent and cotangent
  786. %
  787. if not (car u memq '(tan cot tanh coth)) or cddr u
  788. then confusion 'taysimptan
  789. else Taylor!:
  790. begin scalar a,a0,clist,coefflis,il,l0,l,poleflag,tay,tp;
  791. tay := taysimpsq simp!* cadr u;
  792. if not Taylor!-kernel!-sq!-p tay
  793. then return mksq({car u,mk!*sq tay},1);
  794. tay := mvar numr tay;
  795. tp := TayTemplate tay;
  796. l0 := make!-cst!-powerlist tp;
  797. %
  798. % First we get rid of possible zero coefficients.
  799. %
  800. l := prune!-coefflist TayCoeffList tay;
  801. % if null l then return !*tay2q cst!-Taylor!*(simp!* {car u,0},tp);
  802. %
  803. % The following relies on the standard ordering of the
  804. % TayCoeffList.
  805. %
  806. if not null l and is!-neg!-pl TayCfPl car l
  807. then Taylor!-error('essential!-singularity,car u);
  808. a0 := TayGetCoeff(l0,l);
  809. il := if null l then nlist(1,length tp)
  810. else smallest!-increment l;
  811. %
  812. %%% handle poles of function
  813. %
  814. a := quotsq(a0,simp 'pi);
  815. if car u memq '(tanh coth) then a := subs2!* multsq(a,simp 'i);
  816. if car u memq '(tan tanh) and
  817. denr(a := multsq(a,simp '2)) = 1 and
  818. fixp (a := numr a) and not evenp a
  819. or car u memq '(cot coth) and denr a = 1 and
  820. (null (a := numr a) or fixp a)
  821. then <<
  822. %
  823. % OK, now we are at a pole, so we add a small quantity, compute
  824. % the series and use the addition formulas to get the real
  825. % result.
  826. %
  827. poleflag := t;
  828. a0 := if car u eq 'tan
  829. then negsq invsq simp!* {'tan,!*!*taylor!-epsilon!*!*}
  830. else if car u eq 'tanh
  831. then invsq simp!* {'tanh,!*!*taylor!-epsilon!*!*}
  832. else if car u eq 'cot
  833. then invsq simp!* {'tan,!*!*taylor!-epsilon!*!*}
  834. else invsq simp!* {'tanh,!*!*taylor!-epsilon!*!*};
  835. clist := {TayMakeCoeff(l0,a0)};
  836. >>
  837. else clist := {TayMakeCoeff(l0,simp!* {car u,mk!*sq a0})};
  838. %
  839. coefflis := makecoeffs0(tp,TpNextList tp,il);
  840. if not null coefflis
  841. then for each cc in cdr coefflis do
  842. begin scalar cf,s,pos,x,y,n,n1;
  843. s := nil ./ 1;
  844. pos := find!-non!-zero cc;
  845. n := nth(nth(cc,car pos),cdr pos);
  846. for each p in makecoeffpairs(l0,cc,l0,il) do <<
  847. x := reversip makecoeffpairs1(l0,car p,l0,il);
  848. y := nil ./ 1;
  849. for each z in x do
  850. y := addsq(y,multsq(TayGetCoeff(car z,clist),
  851. TayGetCoeff(cdr z,clist)));
  852. n1 := nth(nth(car p,car pos),cdr pos);
  853. s := addsq(s,
  854. multsq(!*TayExp2q(n - n1),
  855. multsq(y,TayGetCoeff(cdr p,l))))>>;
  856. cf := quotsq(s,!*TayExp2q n);
  857. if car u memq '(tanh coth) then cf := negsq cf;
  858. cf := addsq(TayGetCoeff(cc,l),cf);
  859. if null numr cf then return; % short cut for efficiency
  860. if car u eq 'cot then cf := negsq cf;
  861. clist := TayMakeCoeff(cc,cf) . clist
  862. end;
  863. a := make!-Taylor!*(reversip clist,tp,nil,nil);
  864. %
  865. % Construct ``real'' series in case of pole
  866. %
  867. if poleflag then begin scalar x;
  868. x := if car u eq 'cot
  869. then cst!-Taylor!*(
  870. invsq simp {'tan,!*!*taylor!-epsilon!*!*},tp)
  871. else if car u eq 'coth
  872. then cst!-Taylor!*(
  873. invsq simp {'tanh,!*!*taylor!-epsilon!*!*},tp)
  874. else cst!-Taylor!*(
  875. simp {car u,!*!*taylor!-epsilon!*!*},tp);
  876. if car u eq 'tan then
  877. a := quottaylor(addtaylor(a,negtaylor x),
  878. addtaylor(cst!-taylor!*(1 ./ 1,tp),
  879. multtaylor(a,x)))
  880. else if car u eq 'cot then
  881. a := quottaylor(addtaylor(multtaylor(a,x),
  882. cst!-taylor!*(1 ./ 1,tp)),
  883. addtaylor(x,negtaylor a))
  884. else if car u eq 'tanh then
  885. a := quottaylor(addtaylor(a,negtaylor x),
  886. addtaylor(cst!-taylor!*(1 ./ 1,tp),
  887. negtaylor multtaylor(a,x)))
  888. else if car u eq 'coth then
  889. a := quottaylor(addtaylor(multtaylor(a,x),
  890. cst!-taylor!*(-1 ./ 1,tp)),
  891. addtaylor(x,negtaylor a));
  892. if not (a freeof !*!*taylor!-epsilon!*!*)
  893. then set!-TayCoeffList(a,
  894. for each pp in TayCoeffList a collect
  895. TayMakeCoeff(TayCfPl pp,
  896. subsq(TayCfSq pp,
  897. {!*!*taylor!-epsilon!*!* . 0})));
  898. end;
  899. %
  900. if !*taylorkeeporiginal and TayOrig tay
  901. then set!-TayOrig(a,simp {car u,mk!*sq TayOrig tay});
  902. set!-Tayflags(a,TayFlags tay);
  903. return !*tay2q a
  904. end;
  905. put('tan,'taylorsimpfn,'taysimptan);
  906. put('cot,'taylorsimpfn,'taysimptan);
  907. put('tanh,'taylorsimpfn,'taysimptan);
  908. put('coth,'taylorsimpfn,'taysimptan);
  909. comment For the circular sine and cosine and their reciprocals
  910. we calculate the exponential and use it via the formulas
  911. exp(+I*x) - exp(-I*x)
  912. sin x = ----------------------- ,
  913. 2
  914. exp(+I*x) + exp(-I*x)
  915. cos x = ----------------------- ,
  916. 2
  917. etc. To avoid clumsy expressions we separate the constant term
  918. of the argument,
  919. T(x) = a0 + T1(x),
  920. and use the addition theorems which give
  921. 1
  922. sin T(x) = - exp(+I*T1(x)) * (sin a0 - I*cos a0) +
  923. 2
  924. 1
  925. - exp(-I*T1(x)) * (sin a0 + I*cos a0) ,
  926. 2
  927. 1
  928. cos T(x) = - exp(+I*T1(x)) * (cos a0 + I*sin a0) +
  929. 2
  930. 1
  931. - exp(-I*T1(x)) * (cos a0 - I*sin a0) .
  932. 2
  933. ;
  934. symbolic procedure taysimpsin u;
  935. %
  936. % Special Taylor expansion function for circular sine, cosine,
  937. % and their reciprocals
  938. %
  939. if not (car u memq '(sin cos sec csc)) or cddr u
  940. then confusion 'taysimpsin
  941. else Taylor!:
  942. begin scalar l,tay,result,tp,i1,l0,a0,a1,a2;
  943. tay := taysimpsq simp!* cadr u;
  944. if not Taylor!-kernel!-sq!-p tay
  945. then return mksq({car u,mk!*sq tay},1);
  946. tay := mvar numr tay;
  947. tp := TayTemplate tay;
  948. l0 := make!-cst!-powerlist tp;
  949. l := prune!-coefflist TayCoeffList tay;
  950. % if null l then return !*tay2q cst!-Taylor!*(simp!* {car u,0},tp);
  951. % if is!-neg!-pl TayCfPl car l
  952. % then Taylor!-error('essential!-singularity,car u);
  953. a0 := TayGetCoeff(l0,l);
  954. %
  955. % make constant term to 0
  956. %
  957. i1 := simp 'i;
  958. if not null numr a0
  959. then tay := addtaylor(tay,cst!-Taylor!*(negsq a0,tp));
  960. result := taysimpexp{'exp,multtaylor(tay,cst!-Taylor!*(i1,tp))};
  961. a1 := simp!* {'sin,mk!*sq a0} . simp!* {'cos,mk!*sq a0};
  962. if car u memq '(sin csc) then <<
  963. a2 := addsq(car a1,multsq(i1,cdr a1));
  964. a1 := addsq(car a1,negsq multsq(i1,cdr a1));
  965. >>
  966. else <<
  967. a2 := addsq(cdr a1,negsq multsq(i1,car a1));
  968. a1 := addsq(cdr a1,multsq(i1,car a1));
  969. >>;
  970. result := multsq(addsq(multsq(result,a1),
  971. multsq(taysimpsq!* invsq result,a2)),
  972. 1 ./ 2);
  973. if car u memq '(sec csc) then result := invsq result;
  974. return taysimpsq!* result
  975. end;
  976. put('sin,'taylorsimpfn,'taysimpsin);
  977. put('cos,'taylorsimpfn,'taysimpsin);
  978. put('sec,'taylorsimpfn,'taysimpsin);
  979. put('csc,'taylorsimpfn,'taysimpsin);
  980. comment For the hyperbolic sine and cosine and their reciprocals
  981. we calculate the exponential and use it via the formulas
  982. exp(+x) - exp(-x)
  983. sinh x = ------------------- ,
  984. 2
  985. exp(+x) + exp(-x)
  986. cosh x = ------------------- ,
  987. 2
  988. etc. To avoid clumsy expressions we separate the constant term
  989. of the argument,
  990. T(x) = a0 + T1(x),
  991. and use the addition theorems which give
  992. 1
  993. sinh T(x) = - exp(+T1(x)) * (sinh a0 + cosh a0) +
  994. 2
  995. 1
  996. - exp(-T1(x)) * (sinh a0 - cosh a0) ,
  997. 2
  998. 1
  999. cosh T(x) = - exp(+T1(x)) * (cosh a0 + sinh a0) +
  1000. 2
  1001. 1
  1002. - exp(-T1(x)) * (cosh a0 - sinh a0) .
  1003. 2
  1004. ;
  1005. symbolic procedure taysimpsinh u;
  1006. %
  1007. % Special Taylor expansion function for circular sine, cosine,
  1008. % and their reciprocals
  1009. %
  1010. if not (car u memq '(sinh cosh sech csch)) or cddr u
  1011. then confusion 'taysimpsin
  1012. else Taylor!:
  1013. begin scalar l,tay,result,tp,l0,a0,a1,a2;
  1014. tay := taysimpsq simp!* cadr u;
  1015. if not Taylor!-kernel!-sq!-p tay
  1016. then return mksq({car u,mk!*sq tay},1);
  1017. tay := mvar numr tay;
  1018. tp := TayTemplate tay;
  1019. l0 := make!-cst!-powerlist tp;
  1020. l := prune!-coefflist TayCoeffList tay;
  1021. % if null l then return !*tay2q cst!-Taylor!*(simp!* {car u,0},tp);
  1022. % if is!-neg!-pl TayCfPl car l
  1023. % then Taylor!-error('essential!-singularity,car u);
  1024. a0 := TayGetCoeff(l0,l);
  1025. %
  1026. % make constant term to 0
  1027. %
  1028. if not null numr a0
  1029. then tay := addtaylor(tay,cst!-Taylor!*(negsq a0,tp));
  1030. result := taysimpexp{'exp,tay};
  1031. a1 := simp!* {'sinh,mk!*sq a0} . simp!* {'cosh,mk!*sq a0};
  1032. if car u memq '(sinh csch) then <<
  1033. a2 := addsq(car a1,cdr a1);
  1034. a1 := subtrsq(car a1,cdr a1);
  1035. >>
  1036. else <<
  1037. a2 := addsq(cdr a1,car a1);
  1038. a1 := subtrsq(cdr a1,car a1);
  1039. >>;
  1040. result := multsq(addsq(multsq(result,a2),
  1041. multsq(taysimpsq!* invsq result,a1)),
  1042. 1 ./ 2);
  1043. if car u memq '(sech csch) then result := invsq result;
  1044. return taysimpsq!* result
  1045. end;
  1046. put('sinh, 'taylorsimpfn, 'taysimpsinh);
  1047. put('cosh, 'taylorsimpfn, 'taysimpsinh);
  1048. put('sech, 'taylorsimpfn, 'taysimpsinh);
  1049. put('csch, 'taylorsimpfn, 'taysimpsinh);
  1050. comment Support for the integration of Taylor kernels.
  1051. Unfortunately, with the current interface, only Taylor kernels
  1052. on toplevel can be treated successfully.
  1053. The way it is down means stretching certain interfaces beyond
  1054. what they were designed for...but it works!
  1055. First we add a rule that replaces a call to INT with a Taylor
  1056. kernel as argument by a call to TAYLORINT, then we define
  1057. REVALTAYLORINT as simplification function for that;
  1058. algebraic let {
  1059. int(symbolic algebraic(taylor!*(~x,~y,~z,~w)),~u)
  1060. => taylorint(~x,~y,~z,~w,~u),
  1061. int(log(~u)^~~n * symbolic algebraic(taylor!*(~x,~y,~z,~w)),~u)
  1062. => log(u)^n * int(symbolic('(taylor!* x y z w)),u)
  1063. - int(log(u)^(n-1)
  1064. * taylorcombine(int(symbolic('(taylor!* x y z w)),u)/u),u),
  1065. int(~x,~y) => taylorint1(~x,~y)
  1066. when not symbolic algebraic(~x freeof 'Taylor!*)
  1067. };
  1068. put('taylorint1, 'psopfn, 'revaltaylorint1);
  1069. symbolic procedure revaltaylorint1 x;
  1070. begin scalar u,v;
  1071. u := car x;
  1072. v := cadr x;
  1073. if Taylor!*p u then return revaltaylorint append(cdr u,{v});
  1074. u := reval taylorcombine u;
  1075. if Taylor!*p u then return revaltaylorint append(cdr u,{v});
  1076. if not atom u
  1077. then if car u memq '(plus minus difference)
  1078. then return
  1079. reval (car u . for each term in cdr u collect
  1080. {'int,term,v});
  1081. lprim "Converting Taylor kernels to standard representation";
  1082. return aeval {'int,taylortostandard car x,v}
  1083. end;
  1084. put('taylorint, 'psopfn, 'revaltaylorint);
  1085. symbolic procedure revaltaylorint u;
  1086. begin scalar taycfl, taytp, tayorg, tayflgs, var;
  1087. taycfl := car u;
  1088. taytp := cadr u;
  1089. tayorg := caddr u;
  1090. tayflgs := cadddr u;
  1091. var := car cddddr u;
  1092. if null (var member TayTpVars taytp)
  1093. then return mk!*sq !*tay2q
  1094. make!-Taylor!*(
  1095. for each pp in taycfl collect
  1096. TayCfPl pp . simp!* {'int,mk!*sq TayCfSq pp,var},
  1097. taytp,
  1098. if not null tayorg
  1099. then simp!* {'int,mk!*sq tayorg,var}
  1100. else nil,
  1101. nil)
  1102. else return mk!*sq
  1103. ((if null car result then !*tay2q cdr result
  1104. else addsq(car result,!*tay2q cdr result))
  1105. where result := inttaylorwrttayvar1(taycfl,taytp,var))
  1106. end;
  1107. endmodule;
  1108. end;