trcase.red 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. module trcase; % Driving routine for integration of transcendental fns.
  2. % Authors: Mary Ann Moore and Arthur C. Norman.
  3. % Modifications by: John P. Fitch.
  4. fluid '(!*backtrace
  5. !*failhard
  6. !*nowarnings
  7. !*purerisch
  8. !*reverse
  9. !*trint
  10. badpart
  11. ccount
  12. cmap
  13. cmatrix
  14. content
  15. cval
  16. denbad
  17. denominator!*
  18. indexlist
  19. lhs!*
  20. loglist
  21. lorder
  22. orderofelim
  23. power!-list!*
  24. rhs!*
  25. sillieslist
  26. sqfr
  27. sqrtflag
  28. sqrtlist
  29. tanlist
  30. svar
  31. varlist
  32. xlogs
  33. zlist);
  34. % !*reverse: flag to re-order zlist.
  35. % !*nowarnings: flag to lose messages.
  36. global '(!*number!*
  37. !*ratintspecial
  38. !*seplogs
  39. !*spsize!*
  40. !*statistics
  41. gensymcount);
  42. switch failhard;
  43. exports transcendentalcase;
  44. imports backsubst4cs,countz,createcmap,createindices,df2q,dfnumr,
  45. difflogs,fsdf,factorlistlist,findsqrts,findtrialdivs,gcdf,mkvect,
  46. interr,logstosq,mergin,multbyarbpowers,!*multf, % multsqfree,
  47. printdf,printsq,quotf,rationalintegrate,putv,
  48. simpint1,solve!-for!-u,sqfree,sqmerge,sqrt2top,substinulist,trialdiv,
  49. mergein,negsq,addsq,f2df,mknill,pnth,invsq,multsq,domainp,mk!*sq,
  50. mksp,prettyprint;
  51. % Note that SEPLOGS keeps logarithmic part of result together as a
  52. % kernel form, but this can lead to quite messy results.
  53. symbolic
  54. procedure transcendentalcase(integrand,svar,xlogs,zlist,varlist);
  55. begin scalar divlist,jhd!-content,content,prim,sqfr,dfu,indexlist,
  56. % JHD!-CONTENT is local, while CONTENT is free (set in SQFREE).
  57. sillieslist,originalorder,wrongway,power!-list!*,
  58. sqrtlist,tanlist,loglist,dflogs,eprim,dfun,unintegrand,
  59. sqrtflag,badpart,rhs!*,lhs!*,gcdq,cmap,cval,orderofelim,cmatrix;
  60. scalar ccount,denominator!*,result,denbad,temp;
  61. gensymcount:=0;
  62. integrand:=sqrt2top integrand; % Move the sqrts to the numerator.
  63. if !*trint then << printc "Extension variables z<i> are";
  64. print zlist>>;
  65. % if !*ratintspecial and null cdr zlist then
  66. % return rationalintegrate(integrand,svar);
  67. % *** now unnormalize integrand, maybe ***.
  68. begin scalar w,gg;
  69. gg:=1;
  70. foreach z in zlist do
  71. <<w := subs2 diffsq(simp z,svar); % subs2q?
  72. gg := !*multf(gg,quotf(denr w,gcdf(denr w,gg)))>>;
  73. gg := quotf(gg,gcdf(gg,denr integrand));
  74. unintegrand := (!*multf(gg,numr integrand)
  75. ./ !*multf(gg,denr integrand)); % multf?
  76. if !*trint then <<
  77. printc "After unnormalization the integrand is ";
  78. printsq unintegrand >>
  79. end;
  80. divlist := findtrialdivs zlist;
  81. % Also puts some things on loglist sometimes.
  82. sqrtlist := findsqrts zlist;
  83. divlist := trialdiv(denr unintegrand,divlist);
  84. % N.B. the next line also sets 'content' as a free variable.
  85. % Since SQFREE may be used later, we copy it into JHD!-CONTENT.
  86. prim := sqfree(cdr divlist,zlist);
  87. jhd!-content := content;
  88. printfactors(prim,nil);
  89. eprim := sqmerge(countz car divlist,prim,nil);
  90. printfactors(eprim,t);
  91. % if !*trint then <<terpri();
  92. % printsf denominator!*;
  93. % terpri();
  94. % printc "...content is:";
  95. % printsf jhd!-content>>;
  96. sqfr := for each u in eprim collect multup u;
  97. % sqfr := multsqfree eprim;
  98. % if !*trint then <<printc "...sqfr is:";
  99. % prettyprint sqfr>>;
  100. if !*reverse then zlist := reverse zlist; % Alter order function.
  101. indexlist := createindices zlist;
  102. % if !*trint then << printc "...indices are:";
  103. % prettyprint indexlist>>;
  104. dfu:=dfnumr(svar,car divlist);
  105. % if !*trint then << terpri();
  106. % printc "************ Derivative of u is:";
  107. % printsq dfu>>;
  108. loglist := append(loglist,factorlistlist prim); %%% nconc?
  109. loglist := mergein(xlogs,loglist);
  110. loglist := mergein(tanlist,loglist);
  111. cmap := createcmap();
  112. ccount := length cmap;
  113. if !*trint then <<printc "Loglist "; print loglist>>;
  114. dflogs := difflogs(loglist,denr unintegrand,svar);
  115. if !*trint
  116. then <<printc "************ 'Derivative' of logs is:";
  117. printsq dflogs>>;
  118. dflogs := addsq((numr unintegrand) ./ 1,negsq dflogs);
  119. % Put everything in reduction eqn over common denominator.
  120. gcdq := gcdf(denr dflogs,denr dfu);
  121. dfun := !*multf(numr dfu,denbad:=quotf(denr dflogs,gcdq));
  122. denbad := !*multf(denr dfu,denbad);
  123. denbad := !*multf(denr unintegrand,denbad);
  124. dflogs := !*multf(numr dflogs,quotf(denr dfu,gcdq));
  125. dfu := dfun;
  126. % Now DFU and DFLOGS are S.F.s.
  127. rhs!* := multbyarbpowers f2df dfu;
  128. if checkdffail(rhs!*,svar)
  129. then <<if !*trint then printsq checkdffail(rhs!*,svar);
  130. interr "Simplification fails on above expression">>;
  131. if !*trint then <<
  132. printc "Distributed Form of Numerator is:";
  133. printdf rhs!*>>;
  134. lhs!* := f2df dflogs;
  135. % if checkdffail(lhs!*,svar) then interr "Simplification failure";
  136. if !*trint then << printc "Distributed Form of integrand is:";
  137. printdf lhs!*;
  138. terpri()>>;
  139. cval := mkvect(ccount);
  140. for i := 0:ccount do putv(cval,i,nil ./ 1);
  141. power!-list!* := tansfrom(rhs!*,zlist,indexlist,0);
  142. lorder:=maxorder(power!-list!*,zlist,0);
  143. originalorder := for each x in lorder collect x;
  144. % Must copy as it is overwritten.
  145. if !*trint then <<
  146. printc "Maximum order for variables determined as ";
  147. print lorder >>;
  148. if !*statistics then << !*number!*:=0;
  149. !*spsize!*:=1;
  150. foreach xx in lorder do
  151. !*spsize!*:=!*spsize!* * (xx+1) >>;
  152. % That calculates the largest U that can appear.
  153. dfun:=solve!-for!-u(rhs!*,lhs!*,nil);
  154. backsubst4cs(nil,orderofelim,cmatrix);
  155. % if !*trint then if ccount neq 0 then printvecsq cval;
  156. if !*statistics then << prin2 !*number!*; prin2 " used out of ";
  157. printc !*spsize!* >>;
  158. badpart:=substinulist badpart;
  159. %substitute for c<i> still in badpart.
  160. dfun:=df2q substinulist dfun;
  161. result:= !*multsq(dfun,!*invsq(denominator!* ./ 1));
  162. result:= !*multsq(result,!*invsq(jhd!-content ./ 1));
  163. dflogs:=logstosq();
  164. if not null numr dflogs then <<
  165. if !*seplogs and (not domainp numr result) then <<
  166. result:=mk!*sq result;
  167. result:=(mksp(result,1) .* 1) .+ nil;
  168. result:=result ./ 1 >>;
  169. result:=addsq(result,dflogs)>>;
  170. if !*trint
  171. then << %% prettyprint result;
  172. terpri();
  173. printc
  174. "*****************************************************";
  175. printc
  176. "************ THE INTEGRAL IS : **********************";
  177. printc
  178. "*****************************************************";
  179. terpri();
  180. printsq result;
  181. terpri()>>;
  182. if badpart then begin scalar n,oorder;
  183. if !*trint
  184. then printc "plus a part which has not been integrated";
  185. lhs!*:=badpart;
  186. lorder:=maxorder(power!-list!*,zlist,0);
  187. oorder:=originalorder;
  188. n:=length lorder;
  189. while lorder do <<
  190. if car lorder > car originalorder then
  191. wrongway:=t;
  192. if car lorder=car originalorder then n:= n-1;
  193. lorder:=cdr lorder;
  194. originalorder:=cdr originalorder >>;
  195. %% if n=0 then wrongway:=t; % Nothing changed
  196. if !*trint and wrongway then printc "Went wrong way";
  197. dfun:=df2q badpart;
  198. %% if !*trint
  199. %% then <<printsq dfun; printc "Denbad = "; printsf denbad>>;
  200. dfun:= !*multsq(dfun,invsq(denbad ./ 1));
  201. badpart := dfun; %%% *****
  202. if wrongway then <<
  203. if !*trint then printc "Resetting....";
  204. result:=nil ./ 1;
  205. dfun := integrand; badpart:=dfun >>;
  206. if rootcheckp(unintegrand,svar) then
  207. return simpint1(integrand . svar.nil) . (nil ./ 1)
  208. else if !*purerisch or allowedfns zlist then
  209. << badpart := dfun;
  210. dfun := nil ./ 1 >> % JPff
  211. else << !*purerisch:=t;
  212. if !*trint
  213. then <<printc " Applying transformations ...";
  214. printsq dfun>>;
  215. % We do not want any rules for tan at this point. In fact,
  216. % this may not be enough.
  217. temp := get('tan,'opmtch);
  218. remprop('tan,'opmtch);
  219. denbad:=transform(dfun,svar);
  220. if denbad=dfun
  221. then <<dfun:=nil ./ 1;
  222. badpart:=denbad;
  223. put('tan,'opmtch,temp)>>
  224. else <<denbad:=errorset!*(list('integratesq,mkquote denbad,
  225. mkquote svar,mkquote xlogs, nil),
  226. !*backtrace);
  227. put('tan,'opmtch,temp);
  228. %%% JPF fix for distributive version
  229. if not atom denbad then <<
  230. denbad:=car denbad; % As from an errorset
  231. dfun:=untan car denbad;
  232. if (dfun neq '(nil . 1)) then
  233. badpart:=untan cdr denbad;
  234. % There is still a chance that we went the wrong way.
  235. % Decide that it is better if there is no bad part
  236. if car badpart and not(badpart=denbad) then <<
  237. wrongway:=nil;
  238. lhs!*:=f2df car badpart;
  239. lorder:=maxorder(power!-list!*,zlist,0);
  240. n:=length lorder;
  241. while lorder do <<
  242. if car lorder > car oorder then
  243. wrongway:=t;
  244. if car lorder=car oorder then n:= n-1;
  245. lorder:=cdr lorder;
  246. oorder:=cdr oorder >>;
  247. if wrongway or (n=0) then <<
  248. if !*trint then printc "Still backwards";
  249. dfun := nil ./ 1;
  250. badpart := integrand>>>>>>
  251. else <<badpart := dfun; dfun := nil ./ 1 >>>>>>;
  252. if !*failhard then rerror(int,9,"FAILHARD switch set");
  253. if !*seplogs and not domainp result then <<
  254. result:=mk!*sq result;
  255. if not numberp result
  256. then result:=(mksp(result,1) .* 1) .+ nil;
  257. result:=result ./ 1>>;
  258. result:=addsq(result,dfun) end
  259. else badpart:=nil ./ 1;
  260. return (sqrt2top result . badpart) % JPff
  261. end;
  262. symbolic procedure checkdffail(u,v);
  263. % Sometimes simplification fails and this gives the integrator the
  264. % idea that something is a constant when it is not. Check for this.
  265. if null u then nil
  266. else if depends(lc u,v) then lc u
  267. else checkdffail(red u,v);
  268. symbolic procedure printfactors(w,prdenom);
  269. % W is a list of factors to each power. If PRDENOM is true
  270. % this prints denominator of answer, else prints square-free
  271. % decomposition.
  272. begin scalar i,wx;
  273. i:=1;
  274. if prdenom then <<
  275. denominator!* := 1;
  276. if !*trint
  277. then printc "Denominator of 1st part of answer is:";
  278. if not null w then w:=cdr w >>;
  279. loopx: if w=nil then return;
  280. if !*trint then <<prin2 "Factors of multiplicity ";
  281. prin2 i;
  282. prin2t ":";
  283. terpri()>>;
  284. wx:=car w;
  285. while not null wx do <<
  286. if !*trint then printsf car wx;
  287. for j:=1 : i do
  288. denominator!*:= !*multf(car wx,denominator!*);
  289. wx:=cdr wx >>;
  290. i:=i+1;
  291. w:=cdr w;
  292. go to loopx
  293. end;
  294. % unfluid '(dfun svar xlogs);
  295. endmodule;
  296. end;