tayexpnd.red 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. module tayexpnd;
  2. %*****************************************************************
  3. %
  4. % The Taylor expansion machinery
  5. %
  6. %*****************************************************************
  7. exports taylorexpand;
  8. imports
  9. % from the REDUCE kernel:
  10. !*k2q, !*p2q, .*, .+, ./, aeval, addsq, apply1, denr,
  11. dependsl, dfn_prop, diffsq, domainp, eqcar, error1, errorp,
  12. errorset!*, exptsq, kernp, lastpair, lc, let, lpow, lprim,
  13. mk!*sq, mkquote, mksq, multsq, mvar, nconc!*, neq, nlist, nth,
  14. numr, operator, prepsq, quotsq, red, rederr, setcar, sfp,
  15. simp!*, subsq, subtrsq,
  16. % from the header module:
  17. !*tay2q, cst!-Taylor!*, has!-Taylor!*, make!-cst!-coefficient,
  18. make!-Taylor!*, prune!-coefflist, set!-TayOrig, TayCfPl,
  19. TayCfSq, TayCoeffList, TayFlags, Taylor!*p,
  20. Taylor!-kernel!-sq!-p, Taylor!-trace, Taylor!-trace!-mprint,
  21. Taylor!:, TayMakeCoeff, TayOrig, TayTemplate, TayTpElNext,
  22. TayTpElOrder, TayTpElPoint, TayTpElVars, TayTpVars, TayVars,
  23. % from module TayBasic:
  24. addtaylor!*, multtaylor, multtaylor!*, quottaylor!-as!-sq,
  25. % from module TayConv:
  26. prepTaylor!*,
  27. % from module TayFns:
  28. inttaylorwrttayvar, taycoefflist!-union,
  29. % from module TayInterf:
  30. taylor1,
  31. % from module TayIntro:
  32. nzerolist, replace!-nth, smemberlp, Taylor!-error,
  33. Taylor!-error!*, var!-is!-nth,
  34. % from module TaySimp:
  35. expttayrat, taysimpsq, taysimpsq!*,
  36. % from module TayUtils:
  37. add!.comp!.tp!., addto!-all!-taytpelorders, enter!-sorted,
  38. mult!.comp!.tp!., subtr!-tp!-order, tayminpowerlist,
  39. taytp!-min2, tp!-greaterp, truncate!-Taylor!*;
  40. fluid '(!*backtrace
  41. !*taylor!-assoc!-list!*
  42. !*tayexpanding!*
  43. !*taylorkeeporiginal
  44. !*taylornocache
  45. !*tayrestart!*
  46. !*trtaylor);
  47. global '(!*sqvar!* erfg!*);
  48. symbolic smacro procedure !*tay2q!* u;
  49. ((u . 1) .* 1 .+ nil) ./ 1;
  50. switch taylornocache;
  51. symbolic procedure init!-taylor!-cache;
  52. !*taylor!-assoc!-list!* := nil . !*sqvar!*;
  53. put('taylornocache,'simpfg,'((t (init!-taylor!-cache))));
  54. symbolic init!-taylor!-cache();
  55. symbolic procedure taylor!-add!-to!-cache(krnl,tp,result);
  56. if null !*taylornocache
  57. then car !*taylor!-assoc!-list!* :=
  58. ({krnl,sublis({nil . nil},tp)} . result) .
  59. car !*taylor!-assoc!-list!*;
  60. fluid '(!*taylor!-max!-precision!-cycles!*);
  61. symbolic(!*taylor!-max!-precision!-cycles!* := 5);
  62. symbolic procedure taylorexpand(sq,tp);
  63. begin scalar result,oldklist,!*tayexpanding!*,!*tayrestart!*,ll;
  64. integer cycles;
  65. ll := tp;
  66. oldklist := get('taylor!*,'klist);
  67. !*tayexpanding!* := t;
  68. restart:
  69. !*tayrestart!* := nil;
  70. result := errorset!*({'taylorexpand1,mkquote sq,mkquote ll,'t},
  71. !*trtaylor);
  72. put('taylor!*,'klist,oldklist);
  73. if null errorp result
  74. then <<result := car result;
  75. if cycles>0 and Taylor!-kernel!-sq!-p result
  76. then result := !*tay2q
  77. truncate!-Taylor!*(
  78. mvar numr result,tp);
  79. return result>>;
  80. if null !*tayrestart!* then error1();
  81. erfg!* := nil;
  82. Taylor!-trace {"Failed with template",ll};
  83. cycles := cycles + 1;
  84. if cycles > !*taylor!-max!-precision!-cycles!*
  85. then Taylor!-error('max_cycles,cycles - 1);
  86. ll := addto!-all!-TayTpElOrders(ll,nlist(2,length ll));
  87. Taylor!-trace {"Restarting with template",ll};
  88. goto restart
  89. end;
  90. symbolic procedure taylorexpand1(sq,ll,flg);
  91. %
  92. % sq is a s.q. that is expanded according to the list ll
  93. % which has the form
  94. % ((var_1 var0_1 deg1) (var_2 var0_2 deg_2) ...)
  95. % flg if true indicates that the expansion order should be
  96. % automatically increased if the result has insufficient order.
  97. %
  98. begin scalar oldresult,result,lll,lmin,dorestart,nl; integer count;
  99. lll := ll;
  100. if null cadr !*taylor!-assoc!-list!*
  101. then !*taylor!-assoc!-list!* := nil . !*sqvar!*;
  102. restart:
  103. count := count + 1;
  104. if count > !*taylor!-max!-precision!-cycles!*
  105. or oldresult and TayTemplate oldresult = TayTemplate result
  106. then Taylor!-error('max_cycles,count - 1);
  107. oldresult := result;
  108. if denr sq = 1
  109. then result := taysimpsq!* taylorexpand!-sf(numr sq,lll,t)
  110. % else if not dependsl(denr sq,TayTpVars lll) then begin scalar nn;
  111. % nn := taylorexpand!-sf(numr sq,lll,t);
  112. % if Taylor!-kernel!-sq!-p nn
  113. % then result := !*tay2q multtaylorsq(
  114. % truncate!-Taylor!*(mvar numr nn,lll),
  115. % 1 ./ denr sq)
  116. % else result := taysimpsq!* quotsq(nn,1 ./ denr sq)
  117. % end
  118. % else if numr sq = 1 then begin scalar dd;
  119. % dd := taylorexpand!-sf(denr sq,lll,nil);
  120. % if null numr dd
  121. % then Taylor!-error!*('zero!-denom,'taylorexpand)
  122. % else if Taylor!-kernel!-sq!-p dd
  123. % then if Taylor!*!-zerop mvar numr dd
  124. % then <<!*tayrestart!* := t;
  125. % Taylor!-error('zero!-denom,
  126. % 'taylorexpand)>>
  127. % else result := !*tay2q invtaylor mvar numr dd
  128. % else result := taysimpsq!* invsq dd
  129. % end
  130. % else if not dependsl(numr sq,TayTpVars lll) then begin scalar dd;
  131. % dd := taylorexpand!-sf(denr sq,lll,nil);
  132. % if null numr dd
  133. % then Taylor!-error!*('zero!-denom,'taylorexpand)
  134. % else if Taylor!-kernel!-sq!-p dd
  135. % then if Taylor!*!-zerop mvar numr dd
  136. % then <<!*tayrestart!* := t;
  137. % Taylor!-error('zero!-denom,
  138. % 'taylorexpand)>>
  139. % else result := !*tay2q multtaylorsq(
  140. % truncate!-Taylor!*(
  141. % invtaylor mvar numr dd,
  142. % lll),
  143. % numr sq ./ 1)
  144. % else result := taysimpsq!* quotsq(numr sq ./ 1,dd)
  145. % end
  146. else begin scalar nn,dd;
  147. dd := taylorexpand!-sf(denr sq,lll,nil);
  148. if null numr dd
  149. then Taylor!-error!*('zero!-denom,'taylorexpand)
  150. else if not Taylor!-kernel!-sq!-p dd
  151. then return
  152. result := taysimpsq!*
  153. quotsq(taylorexpand!-sf(numr sq,lll,t),dd);
  154. lmin := prune!-coefflist TayCoeffList mvar numr dd;
  155. if null lmin then Taylor!-error!*('zero!-denom,'taylorexpand);
  156. lmin := tayminpowerlist lmin;
  157. nn := taylorexpand!-sf(
  158. numr sq,
  159. addto!-all!-TayTpElOrders(lll,lmin),t);
  160. if not (Taylor!-kernel!-sq!-p nn and Taylor!-kernel!-sq!-p dd)
  161. then result := taysimpsq!* quotsq(nn,dd)
  162. else result := quottaylor!-as!-sq(nn,dd);
  163. end;
  164. if not Taylor!-kernel!-sq!-p result
  165. then return if not smemberlp(TayTpVars ll,result)
  166. then !*tay2q cst!-Taylor!*(result,ll)
  167. else result;
  168. result := mvar numr result;
  169. dorestart := nil;
  170. Taylor!:
  171. begin scalar ll1;
  172. ll1 := TayTemplate result;
  173. for i := (length ll1 - length ll) step -1 until 1 do
  174. ll := nth(ll1,i) . ll;
  175. if flg then <<nl := subtr!-tp!-order(ll,ll1);
  176. for each o in nl do if o>0 then dorestart := t>>
  177. end;
  178. if dorestart
  179. % if tp!-greaterp(ll,TayTemplate result)
  180. then <<lll := addto!-all!-TayTpElOrders(lll,nl);
  181. Taylor!-trace {"restarting (prec loss):",
  182. "old =",ll,
  183. "result =",result,
  184. "new =",lll};
  185. goto restart>>;
  186. result := truncate!-Taylor!*(result,ll);
  187. if !*taylorkeeporiginal then set!-TayOrig(result,sq);
  188. return !*tay2q result
  189. end;
  190. symbolic procedure taylorexpand!-sf(sf,ll,flg);
  191. begin scalar lcof,lp,next,rest,x,dorestart,lll,xcl,nl,tps;
  192. integer l,count;
  193. lll := ll;
  194. restart:
  195. count := count + 1;
  196. if count > !*taylor!-max!-precision!-cycles!*
  197. then Taylor!-error('max_cycles,count - 1);
  198. x := nil ./ 1;
  199. rest := sf;
  200. while not null rest do <<
  201. if domainp rest
  202. then <<next := !*tay2q!* cst!-Taylor!*(rest ./ 1,lll);
  203. rest := nil>>
  204. else <<
  205. lp := taylorexpand!-sp(lpow rest,lll,flg);
  206. if lc rest=1 then next := lp
  207. else <<
  208. lcof := taylorexpand!-sf(lc rest,lll,flg);
  209. if Taylor!-kernel!-sq!-p lcof and Taylor!-kernel!-sq!-p lp
  210. and (tps :=
  211. mult!.comp!.tp!.(mvar numr lcof,mvar numr lp,nil))
  212. then next := !*tay2q!*
  213. multtaylor!*(mvar numr lcof,mvar numr lp,tps)
  214. else next := taysimpsq!* multsq(lcof,lp);
  215. >>;
  216. rest := red rest>>;
  217. if null numr x then x := next
  218. else if Taylor!-kernel!-sq!-p x and Taylor!-kernel!-sq!-p next
  219. and (tps := add!.comp!.tp!.(mvar numr x,mvar numr next))
  220. then x := !*tay2q!*
  221. addtaylor!*(mvar numr x,mvar numr next,car tps)
  222. else x := taysimpsq!* addsq(x,next)>>;
  223. if not Taylor!-kernel!-sq!-p x then return x;
  224. if null flg then <<
  225. xcl := prune!-coefflist TayCoeffList mvar numr x;
  226. if null xcl then <<
  227. lll := addto!-all!-TayTpElOrders(lll,nlist(2,length lll));
  228. Taylor!-trace {"restarting (no coeffs)...(",count,")"};
  229. goto restart >>
  230. else Taylor!:
  231. <<l := tayminpowerlist xcl;
  232. dorestart := nil;
  233. nl := for i := 1:length lll collect
  234. if nth(l,i)>0
  235. then <<dorestart := t;
  236. 2*nth(l,i)>>
  237. else 0;
  238. if dorestart
  239. then <<flg :=t;
  240. lll := addto!-all!-TayTpElOrders(lll,nl);
  241. Taylor!-trace
  242. {"restarting (no cst trm)...(",count,"):",
  243. "result =",mvar numr x,
  244. "new =",lll};
  245. goto restart>>>>>>;
  246. return x
  247. end;
  248. symbolic procedure taylorexpand!-sp(sp,ll,flg);
  249. Taylor!:
  250. begin scalar fn,krnl,pow,sk,vars;
  251. % if (sk := assoc({sp,ll},car !*taylor!-assoc!-list!*))
  252. % then return cdr sk;
  253. Taylor!-trace "expanding s.p.";
  254. Taylor!-trace!-mprint mk!*sq !*p2q sp;
  255. vars := TayTpVars ll;
  256. krnl := car sp;
  257. pow := cdr sp;
  258. if idp krnl and krnl memq vars
  259. then <<pow := 1;
  260. sk := !*tay2q!* make!-pow!-Taylor!*(krnl,cdr sp,ll);
  261. % taylor!-add!-to!-cache(sp,TayTemplate mvar numr sk,sk)
  262. >>
  263. else if sfp krnl then sk := taylorexpand!-sf(krnl,ll,flg)
  264. else if (sk := assoc({sp,ll},car !*taylor!-assoc!-list!*))
  265. then <<pow := 1;
  266. sk := cdr sk>>
  267. else if not(pow=1) and
  268. (sk := assoc({krnl . 1,ll},car !*taylor!-assoc!-list!*))
  269. then sk := cdr sk
  270. else <<sk := if idp krnl
  271. then if dependsl(krnl,vars)
  272. then taylorexpand!-diff(krnl,ll,flg)
  273. else !*tay2q!* cst!-Taylor!*(simp!* krnl,ll)
  274. else if Taylor!*p krnl
  275. then if smemberlp(vars,TayVars krnl)
  276. then taylorexpand!-samevar(krnl,ll,flg)
  277. else taylorexpand!-taylor(krnl,ll,flg)
  278. else if not idp car krnl
  279. then taylorexpand!-diff(krnl,ll,flg)
  280. % else if (fn := get(car krnl,'taylordef))
  281. % then
  282. else if null(fn := get(car krnl,'taylorsimpfn))
  283. then taylorexpand!-diff(krnl,ll,flg)
  284. else begin scalar res,args,flg,!*taylorautoexpand;
  285. args := for each el in cdr krnl collect
  286. if not dependsl(el,vars) then el
  287. else <<flg := t;
  288. prepsq
  289. taylorexpand(simp!* el,ll)>>;
  290. if has!-Taylor!* args
  291. then res := apply1(fn,car krnl . args)
  292. else if null flg
  293. then res :=
  294. !*tay2q!* cst!-Taylor!*(mksq(krnl,1),ll)
  295. else res := mksq(krnl,1);
  296. return res
  297. end;
  298. if Taylor!-kernel!-sq!-p sk
  299. then taylor!-add!-to!-cache(
  300. krnl . 1,TayTemplate mvar numr sk,sk)>>;
  301. if not(pow = 1)
  302. then <<if not Taylor!-kernel!-sq!-p sk
  303. then sk := taysimpsq exptsq(sk,pow)
  304. else <<sk := mvar numr sk;
  305. sk := !*tay2q!* if pow=2 then multtaylor(sk,sk)
  306. else expttayrat(sk,pow ./ 1)>>;
  307. if Taylor!-kernel!-sq!-p sk
  308. then taylor!-add!-to!-cache(
  309. sp,TayTemplate mvar numr sk,sk)>>;
  310. Taylor!-trace "result of expanding s.p. is";
  311. Taylor!-trace!-mprint mk!*sq sk;
  312. return sk
  313. end;
  314. symbolic procedure make!-pow!-Taylor!*(krnl,pow,ll);
  315. Taylor!:
  316. begin scalar pos,var0,nxt,ordr,x; integer pos1;
  317. pos := var!-is!-nth(ll,krnl);
  318. pos1 := cdr pos;
  319. pos := car pos;
  320. var0 := TayTpElPoint nth(ll,pos);
  321. ordr := TayTpElOrder nth(ll,pos);
  322. nxt := TayTpElNext nth(ll,pos);
  323. % if ordr < pow
  324. % then
  325. ll := replace!-nth(ll,pos,
  326. ({TayTpElVars tpel,
  327. TayTpElPoint tpel,
  328. max2(pow,ordr),max2(pow,ordr)+nxt-ordr}
  329. where tpel := nth(ll,pos)));
  330. % if ordr < 1 then return
  331. % make!-Taylor!*(nil,replace!-nth(ll,pos,
  332. % ({TayTpElVars tpel,
  333. % TayTpElPoint tpel,
  334. % TayTpElOrder tpel,
  335. % 1}
  336. % where tpel := nth(ll,pos))),
  337. % nil,nil)
  338. % else
  339. if var0 = 0 or var0 eq 'infinity
  340. then return make!-Taylor!*(
  341. {make!-var!-coefflist(ll,pos,pos1,pow,
  342. var0 eq 'infinity)},
  343. ll,
  344. if !*taylorkeeporiginal then mksq(krnl,pow),
  345. nil);
  346. x := make!-Taylor!*(
  347. {make!-cst!-coefficient(simp!* var0,ll),
  348. make!-var!-coefflist(ll,pos,pos1,1,nil)},
  349. ll,
  350. nil,
  351. nil);
  352. if not (pow=1) then x := expttayrat(x,pow ./ 1);
  353. if !*taylorkeeporiginal then set!-TayOrig(x,mksq(krnl,pow));
  354. return x
  355. end;
  356. symbolic procedure make!-var!-coefflist(tp,pos,pos1,pow,infflg);
  357. TayMakeCoeff(make!-var!-powerlist(tp,pos,pos1,pow,infflg),1 ./ 1);
  358. symbolic procedure make!-var!-powerlist(tp,pos,pos1,pow,infflg);
  359. if null tp then nil
  360. else ((if pos=1
  361. then for j := 1:l collect
  362. if j neq pos1 then 0
  363. else if infflg then -pow
  364. else pow
  365. else nzerolist l)
  366. where l := length TayTpElVars car tp)
  367. . make!-var!-powerlist(cdr tp,pos - 1,pos1,pow,infflg);
  368. symbolic procedure taylorexpand!-taylor(tkrnl,ll,flg);
  369. begin scalar tay,notay,x;
  370. notay := nil ./ 1;
  371. for each cc in TayCoeffList tkrnl do <<
  372. % x := taylorexpand1(TayCfSq cc,ll,t);
  373. x := taylorexpand1(TayCfSq cc,ll,flg);
  374. if Taylor!-kernel!-sq!-p x
  375. then tay := nconc(tay,
  376. for each cc2 in TayCoefflist mvar numr x
  377. collect TayMakeCoeff(
  378. append(TayCfPl cc,TayCfPl cc2),
  379. TayCfSq cc2))
  380. else Taylor!-error('expansion,"(possbile singularity)")>>;
  381. %notay := aconc!*(notay,cc)>>;
  382. return
  383. if null tay then nil ./ 1
  384. else !*tay2q!* make!-Taylor!*(tay,
  385. append(TayTemplate tkrnl,ll),
  386. nil,nil);
  387. end;
  388. comment The cache maintained in !*!*taylorexpand!-diff!-cache!*!* is
  389. the key to handle the case of a kernel whose derivative
  390. involves the kernel itself. It is guaranteed that in every
  391. recursive step the expansion order is smaller than in the
  392. previous one;
  393. fluid '(!*!*taylorexpand!-diff!-cache!*!*);
  394. symbolic procedure taylorexpand!-diff(krnl,ll,flg);
  395. begin scalar result;
  396. %
  397. % We use a very simple strategy: if we know a partial derivative
  398. % of the kernel, we pass the problem to taylorexpand!-diff1 which
  399. % will try to differentiate the kernel, expand the result and
  400. % integrate again.
  401. %
  402. % NOTE: THE FOLLOWING test can be removed, but needs more checking
  403. % removing it seems to slow down processing
  404. %
  405. if null atom krnl and get(car krnl,dfn_prop krnl)
  406. then
  407. (result := errorset!*({'taylorexpand!-diff1,
  408. mkquote krnl,mkquote ll,mkquote flg},
  409. !*backtrace)
  410. where !*!*taylorexpand!-diff!-cache!*!* :=
  411. !*!*taylorexpand!-diff!-cache!*!*);
  412. %
  413. % If this fails we fall back to simple differentiation and
  414. % substitution at the expansion point.
  415. %
  416. if result and not errorp result
  417. then result := car result
  418. else if !*tayrestart!* then error1() % propagate
  419. else <<result := !*k2q krnl;
  420. for each el in ll do
  421. %
  422. % taylor1 is the function that does the real work
  423. %
  424. result := !*tay2q!* taylor1(result,
  425. TayTpElVars el,
  426. TayTpElPoint el,
  427. TayTpElOrder el)>>;
  428. if !*taylorkeeporiginal and Taylor!-kernel!-sq!-p result
  429. then set!-TayOrig(mvar numr result,!*k2q krnl);
  430. return result
  431. end;
  432. symbolic procedure taylorexpand!-diff1(krnl,ll,flg);
  433. <<if y and TayTpVars ll = TayTpVars(y := cdr y)
  434. and not tp!-greaterp(y,ll)
  435. then ll := for each el in y collect
  436. {TayTpElVars el,TayTpElPoint el,
  437. TayTpElOrder el - 1,TayTpElNext el - 1};
  438. !*!*taylorexpand!-diff!-cache!*!* :=
  439. (krnl . ll) . !*!*taylorexpand!-diff!-cache!*!*;
  440. for each el in ll do result := taylorexpand!-diff2(result,el,nil);
  441. result>>
  442. where result := !*k2q krnl,
  443. y := assoc(krnl,!*!*taylorexpand!-diff!-cache!*!*);
  444. symbolic procedure taylorexpand!-diff2(sq,el,flg);
  445. begin scalar l,singlist,c0,tay,l0,tp,tcl,sterm;
  446. singlist := nil ./ 1;
  447. tp := {el};
  448. %
  449. % We check whether there is a rule for taylorsingularity.
  450. %
  451. sterm := simp!* {'taylorsingularity,mvar numr sq,
  452. 'list . TayTpElVars el,TayTpElPoint el};
  453. if kernp sterm and eqcar(mvar numr sterm,'taylorsingularity)
  454. then sterm := nil % failed
  455. else sq := subtrsq(sq,sterm);
  456. if TayTpElOrder el > 0 then <<
  457. l := for each var in TayTpElVars el collect begin scalar r;
  458. r := taylorexpand1(diffsq(sq,var),
  459. {{TayTpElVars el,
  460. TayTpElPoint el,
  461. TayTpElOrder el - 1,
  462. TayTpElNext el - 1}},flg);
  463. if Taylor!-kernel!-sq!-p r
  464. then return inttaylorwrttayvar(mvar numr r,var)
  465. else Taylor!-error('expansion,"(possible singularity)");
  466. end;
  467. tcl := TayCoeffList!-union
  468. for each pp in l collect TayCoeffList cdr pp;
  469. for each pp in l do
  470. if car pp then singlist := addsq(singlist,car pp);
  471. if not null numr singlist
  472. then Taylor!-error('expansion,"(possible singularity)")>>;
  473. %
  474. % If we have a special singularity, then set c0 to zero.
  475. %
  476. if not null sterm then c0 := nil ./ 1
  477. else c0 := subsq(sq,for each var in TayTpElVars el collect
  478. (var . TayTpElPoint el));
  479. l0 := {nzerolist length TayTpElVars el};
  480. if null numr c0 then nil
  481. else if not Taylor!-kernel!-sq!-p c0
  482. then tcl := TayMakeCoeff(l0,c0) . tcl
  483. else <<c0 := mvar numr c0;
  484. tp := nconc!*(TayTemplate c0,tp);
  485. for each pp in TayCoeffList c0 do
  486. tcl := enter!-sorted(TayMakeCoeff(append(TayCfPl pp,l0),
  487. TayCfSq pp),
  488. tcl)>>;
  489. if not null l
  490. then for each pp in l do
  491. tp := TayTp!-min2(tp,TayTemplate cdr pp);
  492. tay := !*tay2q!* make!-Taylor!*(tcl,tp,
  493. if !*taylorkeeporiginal then sq else nil,nil);
  494. if not null numr singlist then tay := addsq(singlist,tay);
  495. if null sterm then return tay
  496. else return taysimpsq!* addsq(taylorexpand(sterm,tp),tay)
  497. end;
  498. algebraic operator taylorsingularity;
  499. if null get('psi,'simpfn) then algebraic operator psi;
  500. algebraic let {
  501. taylorsingularity(dilog(~x),~y,~y0) => pi^2/6 - log(x)*log(1-x),
  502. taylorsingularity(ei(~x),~y,~y0) => log(x) - psi(1)
  503. };
  504. symbolic procedure taylorexpand!-samevar(u,ll,flg);
  505. Taylor!:
  506. begin scalar tpl;
  507. tpl := TayTemplate u;
  508. for each tpel in ll do begin scalar tp,varlis,mdeg,n; integer pos;
  509. varlis := TayTpElVars tpel;
  510. pos := car var!-is!-nth(tpl,car varlis);
  511. tp := nth(tpl,pos);
  512. if length varlis > 1 and not (varlis = TayTpElVars tp)
  513. then Taylor!-error('not!-implemented,
  514. "(homogeneous expansion in TAYLORSAMEVAR)");
  515. n := TayTpElOrder tpel;
  516. if TayTpElPoint tp neq TayTpElPoint tpel
  517. then u := taylor1(if not null TayOrig u then TayOrig u
  518. else simp!* prepTaylor!* u,
  519. varlis,TayTpElPoint tpel,n);
  520. mdeg := TayTpElOrder tp;
  521. if n=mdeg then nil
  522. else if n > mdeg
  523. %
  524. % further expansion required
  525. %
  526. then if null flg then nil
  527. else Taylor!-error('expansion,
  528. "Cannot expand further... truncated.")
  529. else u := make!-Taylor!*(
  530. for each cc in TayCoeffList u join
  531. if nth(nth(TayCfPl cc,pos),1) > n
  532. then nil
  533. else list cc,
  534. replace!-nth(tpl,pos,{varlis,TayTpElPoint tpel,n,n+1}),
  535. TayOrig u,TayFlags u)
  536. end;
  537. return !*tay2q!* u
  538. end;
  539. endmodule;
  540. end;