patches.red 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497
  1. module patches; % Patches to correct problems in REDUCE 3.7.
  2. % Author: Anthony C. Hearn.
  3. % Copyright (c) 2001 Anthony C. Hearn. All Rights Reserved.
  4. global '(patch!-date!*);
  5. patch!-date!* := "6-Mar-2001";
  6. % Bugs fixed by these patches.
  7. % 28 Jun 99. Gnuplot handling on the Macintosh was not correct.
  8. % 7 Aug 99. The evaluation of df(tan((sqrt(1-x^2)*asin acos x
  9. % + 2*sqrt(1-x^2)*x)/x),x) did not terminate.
  10. % 20 Oct 99. The sequence a1:=12x^2-16x+3; a2:=3x-4; off mcd;
  11. % on combineexpt; e^(a1/a2); gave the wrong answer.
  12. % 8 Nov 99. factorize(2*c*s*u^3*v^5-2*c*s*u^3*v +2*c*s*u*v^5-2*c*s*u*v
  13. % -s^2*u^4*v^4+s^2*u^4+s^2*u^2*v^6-s^2*u^2*v^4-s^2*u^2*v^2
  14. % +s^2*u^2 +s^2*v^6-s^2*v^2+u^4*v^4-u^4*v^2 -v^4+v^2) gave
  15. % a catastrophic error.
  16. % 9 Nov 99. Patched procedures generated a "redefined" message.
  17. % 16 Nov 99. Some EXCALC calculations could cause a catastrophic error.
  18. % 18 Dec 99. Integrations could give catastrophic errors because some
  19. % kernels were not unique.
  20. % 31 Jan 00. The sequence weight x=1,y=1; wtlevel 10; factor x; led to
  21. % the error that x was invalid as a kernel.
  22. % 5 Feb 00. The sequence x := mat((1,2)); sign sqrt 42; led to a
  23. % spurious error.
  24. % 6 Feb 00. The sequence on complex; sqrt(i*sqrt(3)-1); gave a wrong
  25. % result.
  26. % 10 Feb 00. Some root evaluations could lead to an error like
  27. % <equation> invalid as scalar.
  28. % 18 Feb 00. A sequence like m := mat((a,b),(c,d)); det sub(a=1,m);
  29. % would cause a type mismatch error.
  30. % 18 Apr 00. Complaints about the pattern matching limit of 5 terms
  31. % are resolved by the addition of a variable matchlength!*,
  32. % whose initial value of 5 can be changed as needed.
  33. % 22 Apr 00. The RULE mechanism left spurious expressions in various
  34. % non-local variables.
  35. % 28 Jul 00. A sum index within a derivative was treated as an identifier
  36. % (e.g., sum(x^n/factorial n*sub(x=0,df(cos x,x,n)),n,0,5);
  37. % 2 Aug 00. With complex on, some factorizations seemed to run forever
  38. % (e.g., factorize (400y^12+400y^10*z+40y^9*z^2+100y^8*z^2
  39. % +20y^7*z^5+120y^7*z^4+20y^7*z^3+41y^6*z^4+60y^5*z^7
  40. % +60y^5*z^5+20y^4*z^7+6y^4*z^6+20y^4*z^5
  41. % +2y^3*z^6+9y^2*z^8+6y*z^8+z^8))
  42. % 29 Aug 00. The sequence load_package gentran,scope; matrix a(10,10);
  43. % on gentranopt; gentran a(1,1) ::=: a(1,1); caused a
  44. % segmentation violation or similar error.
  45. % 19 Sep 00. Clearing some sqrt rules could lead to a spurious
  46. % "not found" message.
  47. % 20 Sep 00. The sequence load_package algint;
  48. % int(1/sqrt((2*e^c-y)/(e^c*y)),y);
  49. % caused a catastrophic error.
  50. % 8 Nov 00. Some sequences did not optimize completely when the SCOPE
  51. % command "optimize" was used.
  52. % 20 Nov 00. The sum operator did not always preserve a noncom order
  53. % (e.g., noncom u,v; sum(u(m)*v(1-m),m,0,1);)
  54. % 12 Dec 00. int with four arguments did not automatically load the
  55. % defint package.
  56. % 13 Dec 00. Some gcd calculations could produce an endless loop. E.g.,
  57. % in on numval,rounded; y:=x^4+x3*x^3+x2*x^2+x1*x+x0;
  58. % on fullroots; solve(y,x);
  59. % 9 Jan 01. SOLVE did not return results in same order as the given
  60. % variables (e.g., solve({y=x+t^2,x=y+u^2},{x,y,u,t});
  61. % 14 Jan 01. Some resultants (e.g. resultant(p^3-3p^2-a,3p*(p-2),p))
  62. % caused an error.
  63. % 19 Jan 01. Some algebraic integrals could produce a catastrophic
  64. % error when the algint package was loaded.
  65. % 22 Jan 01. Some algebraic integrals could produce a spurious zero
  66. % divisor message when the algint package was loaded (e.g.,
  67. % int((sqrt((-sqrt(a^4*x^2+4)+a^2*x)/(2*x))
  68. % *(-sqrt(a^4*x^2+4)*a^2*x-a^4*x^2-4))/(2*(a^4*x^2+4)),x))
  69. % 23 Jan 01. Inverses of matrices containing non-commuting objects
  70. % could be incorrect (e.g. noncom q; 1/mat((1,0,0),
  71. % (x/p*q 1,1,0),(x*y/(2p*(p-1))*q 1*q 1,y/(p-2)*q 1,1))).
  72. % 2 Feb 01. Some calls of SOLVE could produce a "zero divisor" error
  73. % error (e.g., solve(sqrt x*sqrt((4x^2*x+1)/x)-1=0,x)).
  74. % 9 Feb 01. The patched version of combine!-logs included an undefined
  75. % macro.
  76. % 20 Feb 01. Even with combineexpt on, expressions like a*a^x and
  77. % e*e^(2/(2-x)) did not simplify adequately.
  78. % 6 Mar 01. With algint loaded, some integrals would abort before
  79. % completion (e.g., int((x^(2/3)*sqrt(sqrt(y)*sqrt(pi) + 2pi
  80. % *y*x)*sqrt(- sqrt(y)*sqrt(pi)+2pi*y*x))/(4pi*y*x^3 - x),x)).
  81. % Alg declarations.
  82. fluid '(matchlength!*);
  83. matchlength!* := 5;
  84. flag('(matchlength!*),'share);
  85. patch alg;
  86. % 20 Oct 99, 20 Feb 01.
  87. symbolic procedure exptunwind(u,v);
  88. begin scalar x,x1,x2,y,z,z2;
  89. a: if null v then return u;
  90. x := caar v;
  91. x1 := cadr x;
  92. x2 := caddr x;
  93. y := cdar v;
  94. v := cdr v;
  95. if !*combineexpt and length u=1 and null cdr(z2 := kernels u)
  96. then u := {(({'expt,car z2,ldeg u} . 1) . lc u)};
  97. while (z := assocp1(x1,v)) and
  98. (z2 := simp {'plus,{'times,x2,y},{'times,caddar z,cdr z}})
  99. and (!*combineexpt or (fixp numr z2 and fixp denr z2))
  100. do <<if fixp numr z2 and fixp denr z2
  101. then <<x2 := divide(numr z2,denr z2);
  102. if car x2>0
  103. then <<if fixp x1 then u := multf(x1**car x2,u)
  104. else u := multpf(mksp(x1,car x2),u);
  105. z2 := cdr x2 ./ denr z2>>;
  106. y := numr z2>>
  107. else y := 1;
  108. x2 := prepsq(quotf(numr z2,y) ./ denr z2);
  109. v := delete(z,v)>>;
  110. if !*combineexpt and y=1 and fixp x1 then
  111. <<while (z := assocp2(x2,v)) and cdr z=1 and fixp cadar z do
  112. <<x1 := cadar z * x1; v := delete(z,v)>>;
  113. if eqcar(x2,'quotient) and fixp cadr x2 and fixp caddr x2
  114. and cadr x2<caddr x2
  115. then <<z := nrootn(x1**cadr x2,caddr x2);
  116. if cdr z = 1 then u := multd(car z,u)
  117. else if car z = 1
  118. then u := multf(formsf(x1,x2,1),u)
  119. else <<u := multd(car z,u);
  120. v := (list('expt,cdr z,x2) . 1) . v>>>>
  121. else u := multf(formsf(x1,x2,y),u)>>
  122. else u := multf(formsf(x1,x2,y),u);
  123. go to a
  124. end;
  125. % 31 Jan 00.
  126. symbolic procedure factor1(u,v,w);
  127. begin scalar x,y,z,r;
  128. y := lispeval w;
  129. for each j in u do
  130. if (x := getrtype j) and (z := get(x,'factor1fn))
  131. then apply2(z,u,v)
  132. else <<while eqcar(j:=reval j,'list) and cdr j do
  133. <<r:=append(r,cddr j); j:=cadr j>>;
  134. x := !*a2kwoweight j;
  135. if v then y := aconc!*(delete(x,y),x)
  136. else if not(x member y)
  137. then msgpri(nil,j,"not found",nil,nil)
  138. else y := delete(x,y)>>;
  139. set(w,y);
  140. if r then return factor1(r,v,w)
  141. end;
  142. % 5 Feb 00.
  143. algebraic (let sign(sqrt ~a) => 1 when sign a=1);
  144. % 18 Feb 00.
  145. symbolic procedure getrtype u;
  146. begin scalar x,y;
  147. return
  148. if null u then nil
  149. else if atom u
  150. then if not idp u then not numberp u and getrtype1 u
  151. else if flagp(u,'share)
  152. then if (x := eval u) eq u then nil else getrtype x
  153. else if (x := get(u,'avalue)) and
  154. not(car x memq '(scalar generic))
  155. or (x := get(u,'rtype)) and (x := list x)
  156. then if y := get(car x,'rtypefn) then apply1(y,nil)
  157. else car x
  158. else nil
  159. else if not idp car u then nil
  160. else if (x := get(car u,'avalue)) and (x := get(car x,'rtypefn))
  161. then apply1(x,cdr u)
  162. else if car u eq 'sub then 'yetunknowntype
  163. else getrtype2 u
  164. end;
  165. symbolic procedure let3(u,v,w,b,flgg);
  166. begin scalar x,y1,y2,z;
  167. x := u;
  168. if null x then <<u := 0; return errpri1 u>>
  169. else if numberp x then return errpri1 u;
  170. y2 := getrtype v;
  171. if b and idp x then <<remprop(x,'rtype); remprop(x,'avalue)>>;
  172. if (y1 := getrtype x)
  173. then return if z := get(y1,'typeletfn)
  174. then lispapply(z,list(x,v,y1,b,getrtype v))
  175. else typelet(x,v,y1,b,getrtype v)
  176. else if y2 and not(y2 eq 'yetunknowntype)
  177. then return if z := get(y2,'typeletfn)
  178. then lispapply(z,list(x,v,nil,b,y2))
  179. else typelet(x,v,nil,b,y2)
  180. else letscalar(u,v,w,x,b,flgg)
  181. end;
  182. % 18 Apr 00.
  183. symbolic procedure mcharg1(u,v,w);
  184. if null u and null v then list nil
  185. else begin integer m,n;
  186. m := length u;
  187. n := length v;
  188. if flagp(w,'nary) and m>2
  189. then if m<=matchlength!* and flagp(w,'symmetric)
  190. then return mchcomb(u,v,w)
  191. else if n=2 then <<u := cdr mkbin(w,u); m := 2>>
  192. else return nil;
  193. return if m neq n then nil
  194. else if flagp(w,'symmetric) then mchsarg(u,v,w)
  195. else if mtp v then list pair(v,u)
  196. else mcharg2(u,v,list nil,w)
  197. end;
  198. % 19 Sep 00.
  199. symbolic procedure letscalar(u,v,w,x,b,flgg);
  200. begin
  201. if not atom x
  202. then if not idp car x then return errpri2(u,'hold)
  203. else if car x eq 'df
  204. then if null letdf(u,v,w,x,b) then nil
  205. else return nil
  206. else if getrtype car x
  207. then return let2(reval x,v,w,b)
  208. else if not get(car x,'simpfn)
  209. then <<redmsg(car x,"operator");
  210. mkop car x;
  211. return let3(u,v,w,b,flgg)>>
  212. else nil
  213. else if null b and null w
  214. then <<remprop(x,'avalue);
  215. remprop(x,'rtype);
  216. remflag(list x,'antisymmetric);
  217. remprop(x,'infix);
  218. remprop(x,'kvalue);
  219. remflag(list x,'linear);
  220. remflag(list x,'noncom);
  221. remprop(x,'op);
  222. remprop(x,'opmtch);
  223. remprop(x,'simpfn);
  224. remflag(list x,'symmetric);
  225. wtl!* := delasc(x,wtl!*);
  226. if flagp(x,'opfn)
  227. then <<remflag(list x,'opfn); remd x>>;
  228. rmsubs();
  229. return nil>>;
  230. if eqcar(x,'expt) and caddr x memq frlis!*
  231. then letexprn(u,v,w,!*k2q x,b,flgg)
  232. else if eqcar(x,'sqrt)
  233. then let2({'expt,cadr x,'(quotient 1 2)},v,w,
  234. if b then b else 'sqrt);
  235. x := simp0 x;
  236. return if not domainp numr x then letexprn(u,v,w,x,b,flgg)
  237. else errpri1 u
  238. end;
  239. symbolic procedure setk1(u,v,b);
  240. begin scalar x,y,z,!*uncached;
  241. !*uncached := t;
  242. if atom u
  243. then <<if null b
  244. then <<if not get(u,'avalue)
  245. then msgpri(nil,u,"not found",nil,nil)
  246. else remprop(u,'avalue);
  247. return nil>>
  248. else if (x:= get(u,'avalue)) then put!-avalue(u,car x,v)
  249. else put!-avalue(u,'scalar,v);
  250. return v>>
  251. else if not atom car u
  252. then rerror(alg,25,"Invalid syntax: improper assignment");
  253. u := car u . revlis cdr u;
  254. if null b or b eq 'sqrt
  255. then <<z:=assoc(u,wtl!*);
  256. if not(y := get(car u,'kvalue))
  257. or not (x := assoc(u,y))
  258. then <<if null z and null(b eq 'sqrt) then
  259. msgpri(nil,u,"not found",nil,nil)>>
  260. else put(car u,'kvalue,delete(x,y));
  261. if z then wtl!*:=delasc(u,wtl!*);
  262. return nil>>
  263. else if not (y := get(car u,'kvalue))
  264. then put!-kvalue(car u,nil,u,v)
  265. else <<if x := assoc(u,y)
  266. then <<updoldrules(u,v); y := delasc(car x,y)>>;
  267. put!-kvalue(car u,y,u,v)>>;
  268. return v
  269. end;
  270. % 2 Feb 01.
  271. symbolic procedure simprad(u,n);
  272. if !*reduced then multsq(radfa(numr u,n),invsq radfa(denr u,n))
  273. else begin scalar iflag,x,y,z;
  274. if !*rationalize then <<
  275. y:=list(denr u,1);
  276. u:=multf(numr u, exptf(denr u,n-1)) ./ 1 >>
  277. else y := radf(denr u,n);
  278. if n=2 and minusf numr u
  279. then <<iflag := t; x := radf(negf numr u,n)>>
  280. else x := radf(numr u,n);
  281. z := simp list('quotient,retimes cdr x, retimes cdr y);
  282. if domainp numr z and domainp denr z
  283. then z := multsq(mkrootsq(prepf numr z,n),
  284. invsq mkrootsq(prepf denr z,n))
  285. else <<if iflag
  286. then <<iflag := nil;
  287. z := negsq z>>;
  288. z := mkrootsq(prepsq z,n)>>;
  289. z := multsq(multsq(if !*precise and evenp n
  290. then car x ./ 1
  291. else car x ./ 1, 1 ./ car y), z);
  292. if iflag then z := multsq(z,mkrootsq(-1,2));
  293. return z
  294. end;
  295. symbolic procedure radfa(u,n);
  296. begin scalar x,y;
  297. x := fctrf u;
  298. if numberp car x then x := append(zfactor car x,cdr x)
  299. else x := (car x ./ 1) . cdr x;
  300. y := 1 ./ 1;
  301. for each j in x do y := multsq(y,radfb(car j,cdr j,n));
  302. return y
  303. end;
  304. symbolic procedure radfb(u,m,n);
  305. begin scalar x,y;
  306. x := radf(u,n);
  307. y := exptf(car x,m) ./ 1;
  308. return multsq(exptsq(mkrootlsq(cdr x,n),m),y)
  309. end;
  310. % 20 Feb 01.
  311. symbolic procedure reval2(u,v);
  312. if v or null !*combineexpt or dmode!* then !*q2a1(simp!* u,v)
  313. else !*q2a1((simp!* u where !*mcd = nil),v);
  314. endpatch;
  315. % Algint declarations.
  316. fluid '(!*noacn !*structure !*tra !*trmin gaussiani intvar sqrtflag);
  317. fluid '(!*pvar listofallsqrts listofnewsqrts);
  318. global '(modevalcount);
  319. patch algint;
  320. % 20 Sep 00.
  321. symbolic procedure algebraiccase(expression,zlist,varlist);
  322. begin
  323. scalar rischpart,deriv,w,firstterm;
  324. scalar sqrtflag,!*structure;
  325. sqrtflag:=t;
  326. sqrtsave(listofallsqrts,listofnewsqrts,list(intvar . intvar));
  327. rischpart:= errorset!*(list('doalggeom,mkquote expression),
  328. !*backtrace);
  329. newplace list (intvar.intvar);
  330. if atom rischpart
  331. then <<
  332. if !*tra then printc "Inner integration failed";
  333. deriv:=nil ./ 1;
  334. rischpart:=deriv >>
  335. else
  336. if atom car rischpart
  337. then <<
  338. if !*tra or !*trmin then
  339. printc "The 'logarithmic part' is not elementary";
  340. return (nil ./ 1) . expression >>
  341. else <<
  342. rischpart:=car rischpart;
  343. deriv:=!*diffsq(rischpart,intvar) where sqrtflag=nil;
  344. if !*tra or !*trmin then <<
  345. printc "Inner working yields";
  346. printsq rischpart;
  347. printc "with derivative";
  348. printsq deriv >> >>;
  349. deriv:=!*addsq(expression,negsq deriv);
  350. if null numr deriv
  351. then return rischpart . (nil ./ 1);
  352. if null involvesq(deriv,intvar)
  353. then return !*addsq(rischpart,
  354. !*multsq(deriv,((mksp(intvar,1) .* 1) .+ nil) ./ 1))
  355. . (nil ./ 1);
  356. varlist:=getvariables deriv;
  357. zlist:=findzvars(varlist,list intvar,intvar,nil);
  358. varlist:=setdiff(varlist,zlist);
  359. firstterm:=simp!* car zlist;
  360. w:=sqrt2top !*multsq(deriv,invsq !*diffsq(firstterm,intvar));
  361. if null involvesq(w,intvar)
  362. then return !*addsq(rischpart,!*multsq(w,firstterm)) . (nil ./ 1);
  363. if !*noacn then interr "Testing only logarithmic code";
  364. deriv:=transcendentalcase(deriv,intvar,nil,zlist,varlist);
  365. return !*addsq(car deriv, rischpart) . cdr deriv
  366. end;
  367. % 22 Jan 01, 9 Feb 01.
  368. symbolic procedure combine!-logs(coef,logarg);
  369. begin
  370. scalar ans,dencoef,parts,logs,lparts,!*rationalize,trueimag;
  371. !*rationalize:=t;
  372. coef:=simp!* coef;
  373. if null numr logarg then return coef;
  374. parts:=split!-real!-imag numr coef;
  375. if null numr cdr parts then return multsq(coef,logarg);
  376. dencoef:=multf(denr coef,denr logarg);
  377. if !*tra then <<
  378. printc "attempting to find 'real' form for";
  379. mathprint list('times,list('plus,prepsq car parts,
  380. list('times,prepsq cdr parts,'i)),
  381. prepsq logarg) >>;
  382. logarg:=numr logarg;
  383. logs:= 1 ./ 1;
  384. while pairp logarg do <<
  385. if ldeg logarg neq 1 then interr "what a log";
  386. if atom mvar logarg then interr "what a log";
  387. if car mvar logarg neq 'log then interr "what a log";
  388. logs:=!*multsq(logs,
  389. !*exptsq(simp!* cadr mvar logarg,lc logarg));
  390. logarg:=red logarg >>;
  391. logs:=rationalizesq logs;
  392. ans:=multsq(!*multsq(car parts,logs),1 ./ dencoef);
  393. lparts:=split!-real!-imag numr logs;
  394. if numr difff(denr cdr lparts,intvar)
  395. then interr "unexpected denominator";
  396. lparts:=!*multsq(denr cdr lparts ./ 1,car lparts) . cdr lparts;
  397. if not onep denr car lparts then interr "unexpected denominator";
  398. trueimag:=quotsq(addf(!*exptf(numr car lparts,2),
  399. !*exptf(numr cdr lparts,2)) ./ 1,
  400. !*exptf(denr logs,2) ./ 1);
  401. if numr diffsq(trueimag,intvar)
  402. then ans:=!*addsq(ans,
  403. !*multsq(gaussiani ./ multf(2,dencoef),
  404. !*multsq(simplogsq trueimag,cdr parts)));
  405. trueimag:=!*multsq(car lparts,!*invsq(numr cdr lparts ./ 1));
  406. if numr diffsq(trueimag,intvar)
  407. then ans:=!*addsq(ans,!*multsq(!*multsq(cdr parts,1 ./ dencoef),
  408. !*k2q list('atan,prepsq!* trueimag)));
  409. return ans;
  410. end;
  411. % 6 Mar 01.
  412. symbolic procedure modevalvar v;
  413. begin scalar w;
  414. if atom v
  415. then <<if (w := get(v,'modvalue)) then return w;
  416. put(v,'modvalue,modevalcount);
  417. modevalcount := modevalcount+1;
  418. return modevalcount-1>>
  419. else if car v neq 'sqrt
  420. then <<if !*tra then <<princ "Unexpected algebraic:"; print v>>;
  421. error1()>>
  422. else if numberp cadr v then return (mksp(v,1) .* 1) .+ nil;
  423. w := modeval(!*q2f simp cadr v,!*pvar);
  424. w := assoc(w,listofallsqrts);
  425. if w then return cdr w else return 'failed
  426. end;
  427. endpatch;
  428. % Excalc declarations.
  429. global '(basisforml!* detm!* indxl!* metricd!* metricu!*);
  430. smacro procedure ldpf u;
  431. caar u;
  432. smacro procedure lowerind u;
  433. list('minus,u);
  434. patch excalc;
  435. % 16 Nov 99.
  436. symbolic procedure mkmetric u;
  437. begin scalar x,y,z,okord;
  438. putform(list(cadr u,nil,nil),0);
  439. put(cadr u,'indxsymmetries,
  440. '((lambda (indl) (tot!-sym!-indp
  441. (evlis '((nth indl 1)
  442. (nth indl 2)))))));
  443. put(cadr u,'indxsymmetrize,
  444. '((lambda (indl) (symmetrize!-inds '(1 2) indl))));
  445. flag(list cadr u,'covariant);
  446. okord := kord!*;
  447. kord!* := basisforml!*;
  448. x := simp!* caddr u;
  449. y := indxl!*;
  450. metricu!* := t;
  451. for each j in indxl!* do
  452. <<for each k in y do
  453. setk(list(cadr u,lowerind j,lowerind k),0);
  454. y := cdr y>>;
  455. for each j on partitsq(x,'basep) do
  456. if ldeg ldpf j = 2 then
  457. setk(list(cadr u,lowerind cadr mvar ldpf j,
  458. lowerind cadr mvar ldpf j),
  459. mk!*sq lc j)
  460. else
  461. setk(list(cadr u,lowerind cadr mvar ldpf j,
  462. lowerind cadr mvar lc ldpf j),
  463. mk!*sq multsq(lc j,1 ./ 2));
  464. kord!* := okord;
  465. x := for each j in indxl!* collect
  466. for each k in indxl!* collect
  467. simpindexvar list(cadr u,lowerind j,lowerind k);
  468. z := subfg!*;
  469. subfg!* := nil;
  470. y := lnrsolve(x,generateident length indxl!*);
  471. subfg!* := z;
  472. metricd!* := mkasmetric x;
  473. metricu!* := mkasmetric y;
  474. detm!* := mk!*sq detq x
  475. end;
  476. endpatch;
  477. % Ezgcd declarations.
  478. fluid '(image!-set reduced!-degree!-lclst unlucky!-case);
  479. symbolic smacro procedure polyzerop u; null u;
  480. patch ezgcd;
  481. % 8 Nov 99.
  482. symbolic procedure ezgcdf(u,v);
  483. begin scalar kordx,x;
  484. kordx := kord!*;
  485. x := errorset2{'ezgcdf1,mkquote u,mkquote v};
  486. if null errorp x then return first x;
  487. setkorder kordx;
  488. return gcdf1(u,v)
  489. end;
  490. symbolic procedure poly!-gcd(u,v);
  491. begin scalar !*exp,z;
  492. if polyzerop u then return poly!-abs v
  493. else if polyzerop v then return poly!-abs u
  494. else if u=1 or v=1 then return 1;
  495. !*exp := t;
  496. if quotf1(u,v) then z := v
  497. else if quotf1(v,u) then z := u
  498. else if !*gcd then z := gcdlist list(u,v)
  499. else z := 1;
  500. return poly!-abs z
  501. end;
  502. symbolic procedure gcdlist3(l,onestep,vlist);
  503. begin
  504. scalar unlucky!-case,image!-set,gg,gcont,l1,w,w1,w2,
  505. reduced!-degree!-lclst,p1,p2;
  506. l1:=for each p in l collect p . ezgcd!-comfac p;
  507. l:=for each c in l1 collect
  508. quotfail1(car c,comfac!-to!-poly cdr c,
  509. "Content divison in GCDLIST3 failed");
  510. gcont:=gcdlist for each c in l1 collect cddr c;
  511. if domainp gcont then if not(gcont=1)
  512. then errorf "GCONT has numeric part";
  513. l := sort(for each p in l collect poly!-abs p,function ordp);
  514. w := nil;
  515. while l do <<
  516. w := car l . w;
  517. repeat l := cdr l until null l or not(car w = car l)>>;
  518. l := reversip w;
  519. w := nil;
  520. if null cdr l then return multf(gcont,car l);
  521. if domainp (gg:=car (l:=sort(l,function degree!-order))) then
  522. return gcont;
  523. if ldeg gg=1 then <<
  524. if division!-test(gg,l) then return multf(poly!-abs gg,gcont)
  525. else return gcont >>;
  526. if onestep then <<
  527. p1 := poly!-abs car l; p2 := poly!-abs cadr l;
  528. if p1=p2 then <<
  529. if division!-test(p1,cddr l) then return multf(p1,gcont) >>
  530. else <<
  531. gg := poly!-gcd(lc p1,lc p2);
  532. w1 := multf(red p1, quotfail1(lc p2, gg,
  533. "Division failure when just one pseudoremainder step needed"));
  534. w2 := multf(red p2,negf quotfail1(lc p1, gg,
  535. "Division failure when just one pseudoremainder step needed"));
  536. w := ldeg p1 - ldeg p2;
  537. if w > 0 then w2 := multf(w2, (mksp(mvar p2, w) .* 1) .+ nil)
  538. else if w < 0
  539. then w1 := multf(w1, (mksp(mvar p1, -w) .* 1) .+ nil);
  540. gg := ezgcd!-pp addf(w1, w2);
  541. if division!-test(gg,l) then return multf(gg,gcont) >>>>;
  542. return gcdlist31(l,vlist,gcont,gg,l1)
  543. end;
  544. endpatch;
  545. % Int declarations.
  546. fluid '(tanlist);
  547. patch int;
  548. % 18 Dec 99.
  549. symbolic procedure findtrialdivs zl;
  550. begin scalar dlists1,args1;
  551. for each z in zl do
  552. if exportan z
  553. then <<if car z eq 'tan
  554. then <<args1 := (mksp(z,2) .* 1) .+ 1;
  555. tanlist := (args1 ./ 1) . tanlist>>
  556. else args1 := !*kk2f z;
  557. dlists1 := (z . args1) . dlists1>>;
  558. return dlists1
  559. end;
  560. % 12 Dec 00.
  561. symbolic procedure simpdint u;
  562. begin scalar low,upp,fn,var,x,y;
  563. if length u neq 4
  564. then rerror(int,2,"Improper number of arguments to INT");
  565. load!-package 'defint;
  566. fn := car u;
  567. var := cadr u;
  568. low := caddr u;
  569. upp := cadddr u;
  570. low := reval low;
  571. upp := reval upp;
  572. if low = upp then return nil ./ 1
  573. else if null getd 'new_defint then nil
  574. else if upp = 'infinity
  575. then if low = 0
  576. then if not smemql('(infinity unknown),
  577. x := defint!* {fn,var})
  578. then return simp!* x else nil
  579. else if low = '(minus infinity)
  580. then return mkinfint(fn,var)
  581. else if freeof(var,low)
  582. then if not smemql('(infinity unknown),
  583. x := defint!* {fn,var})
  584. and not smemql('(infinity unknown),
  585. y := indefint!* {fn,var,low})
  586. then return simp!* {'difference,x,y} else nil
  587. else nil
  588. else if upp = '(minus infinity) or low = 'infinity
  589. then return negsq simpdint {fn,var,upp,low}
  590. else if low = '(minus infinity)
  591. then return
  592. simpdint{prepsq simp{'sub,{'equal,var,{'minus,var}},fn},
  593. var,{'minus,upp},'infinity}
  594. else if low = 0
  595. then if freeof(var,upp)
  596. and not smemql('(infinity unknown),
  597. x := indefint!* {fn,var,upp})
  598. then return simp!* x else nil
  599. else if freeof(var,upp) and freeof(var,low)
  600. and not smemq('(infinity unknown),
  601. x := indefint!* {fn,var,upp})
  602. and not smemql('(infinity unknown),
  603. y := indefint!* {fn,var,low})
  604. then return simp!* {'difference,x,y};
  605. return mkdint(fn,var,low,upp)
  606. end;
  607. endpatch;
  608. patch matrix;
  609. % 7 Aug 99.
  610. symbolic procedure quotfexf!*1(u,v);
  611. if null u then nil
  612. else (if x then x
  613. else (if denr y = 1 then numr y
  614. else if denr (y := rationalizesq y)=1 then numr y
  615. else rerror(matrix,11,
  616. "Catastrophic division failure"))
  617. where y=rationalizesq(u ./ v))
  618. where x=quotf(u,v);
  619. % 14 Jan 01.
  620. algebraic procedure polyresultant(u,v,var);
  621. begin scalar g,h,delta,beta,temp,uu,vv;
  622. uu := coeff(u,var); vv := coeff(v,var);
  623. if length uu<length vv
  624. then return (-1 * polyresultant(v,u,var))
  625. else if (notunivariatep(uu) > 0) or (notunivariatep(vv)>0)
  626. then <<u := for i:=1:length uu sum
  627. (if fixp part(uu,i) then part(uu,i)
  628. else (co(0,part(uu,i))))*var^(i-1);
  629. v := for i:=1:length vv sum
  630. (if fixp part(vv,i) then part(vv,i)
  631. else (co(0,part(vv,i))))*var^(i-1)>>;
  632. g := h := 1;
  633. while not (v=0) do
  634. <<delta := deg(u,var) - deg(v,var);
  635. beta := (-1)^(delta +1) * g * h^delta;
  636. h := h*(lcof(v,var)/h)^delta;
  637. temp := u;
  638. u := v;
  639. beta := co(0,1/beta);
  640. v := pseudo_remainder(temp,v,var)*beta;
  641. g := lcof(u,var)>>;
  642. if deg(u,var) = 0 then u := u^delta else return 0;
  643. let co_off; u := u; clearrules co_off;
  644. return u
  645. end;
  646. % 23 Jan 01.
  647. symbolic procedure lnrsolve(u,v);
  648. begin scalar temp,vlhs,vrhs,ok,
  649. !*exp,!*solvesingular;
  650. if !*ncmp then return clnrsolve(u,v);
  651. !*exp := t;
  652. if asymplis!* or wtl!* then
  653. <<temp := asymplis!* . wtl!*;
  654. asymplis!* := wtl!* := nil>>;
  655. vlhs := for i:=1:length car u collect intern gensym();
  656. vrhs := for i:=1:length car v collect intern gensym();
  657. u := car normmat augment(u,v);
  658. v := append(vlhs,vrhs);
  659. ok := setkorder v;
  660. u := foreach r in u collect prsum(v,r);
  661. v := errorset!*({function solvebareiss, mkquote u,mkquote vlhs},t);
  662. if caar v memq {'singular,'inconsistent} then
  663. <<setkorder ok; rerror(matrix,13,"Singular matrix")>>;
  664. v := pair(cadr s,car s) where s = cadar v;
  665. u := foreach j in vlhs collect
  666. coeffrow(negf numr q,vrhs,denr q) where q = cdr atsoc(j,v);
  667. setkorder ok;
  668. if temp then <<asymplis!* := car temp; wtl!* := cdr temp>>;
  669. return for each j in u collect
  670. for each k in j collect
  671. if temp then resimp k else cancel k;
  672. end;
  673. endpatch;
  674. % Ncpoly declarations.
  675. fluid '(!*complex !*trnc dipvars!*);
  676. patch ncpoly;
  677. % 9 Jan 01.
  678. symbolic procedure nc_factsolve(s,vl,all);
  679. begin scalar v,sb,ns,so,soa,sol,nz,w,q,z,r,abort;
  680. v:= numr simp car vl;
  681. ns:=for each e in s collect numr simp e;
  682. r:=t;
  683. while r do
  684. <<r:=nil; s:=ns; ns:=nil;
  685. for each e in s do if not abort then
  686. <<e:=absf numr subf(e,sb);
  687. while(q:=quotf(e,v)) do e:=q;
  688. if null e then nil else
  689. if domainp e or not(mvar e member vl) then abort:=t else
  690. if null red e and domainp lc e then
  691. <<w:=mvar e; sb:=(w . 0).sb; r:=t;
  692. vl:=delete(w,vl)>>
  693. else if not member(e,ns) then ns:=e.ns
  694. >>;
  695. >>;
  696. if abort or null vl then return nil;
  697. nc_factorize_timecheck();
  698. if null ns and vl then
  699. <<sol:={for each x in vl collect x.1};
  700. goto done>>;
  701. s:=for each e in ns collect prepf e;
  702. if !*trnc then
  703. <<prin2 "solving ";
  704. prin2 length s; prin2 " polynomial equations for ";
  705. prin2 length vl;
  706. prin2t "variables";
  707. for each e in s do writepri(mkquote e,'only);>>;
  708. w:=(cdr solveeval{'list.s,'list.vl} where dipvars!*=nil);
  709. loop:
  710. nc_factorize_timecheck();
  711. if null w then goto done;
  712. so:= cdr car w; w:=cdr w; soa:=nil;
  713. if smemq('i,so) and null !*complex then go to loop;
  714. for each y in vl do if not smember(y,so) then
  715. <<soa:=(y . 1) . soa; nz:=t>>;
  716. for each y in so do
  717. <<z:=nc_factorize_unwrap(reval caddr y,soa);
  718. nz:=nz or z neq 0;
  719. soa:=(cadr y . z).soa;
  720. >>;
  721. if not nz then goto loop;
  722. q:=assoc(car vl,soa);
  723. if null q or cdr q=0 then go to loop;
  724. soa := for each j in soa collect (car j . sublis(soa,cdr j));
  725. sol := soa . sol;
  726. if all then go to loop;
  727. done:
  728. sol:=for each s in sol collect append(sb,s);
  729. if !*trnc then
  730. <<prin2t "solutions:";
  731. for each w in sol do
  732. writepri(mkquote('list.
  733. for each s in w collect {'equal,car s,cdr s}),'only);
  734. prin2t "-------------------------";
  735. >>;
  736. return sol
  737. end;
  738. endpatch;
  739. % Plot declarations.
  740. global '(!*plotpause !*plotusepipe dirchar!* opsys!* plotcleanup!*
  741. plotcmds!* plotcommand!* plotdir!* plotdta!* plotheader!*
  742. tempdir!*);
  743. patch plot;
  744. % 28 Jun 99.
  745. symbolic procedure init_gnuplot();
  746. <<
  747. !*plotpause := -1;
  748. plotcleanup!* := {};
  749. tempdir!* := getenv 'tmp;
  750. if null tempdir!* then tempdir!* := getenv 'temp;
  751. dirchar!* := "/";
  752. plotcommand!* := "gnuplot";
  753. opsys!* := assoc('opsys, lispsystem!*);
  754. if null opsys!* then opsys!* := 'unknown
  755. else opsys!* := cdr opsys!*;
  756. if getenv "gnuplot" then plotdir!* := getenv "gnuplot"
  757. else if null plotdir!* and not (opsys!* = 'unix)
  758. then plotdir!* := get!-lisp!-directory();
  759. if opsys!* = 'win32 then <<
  760. plotcommand!* := "wgnuplot";
  761. plotheader!* := "";
  762. dirchar!* := "\";
  763. plotdta!* := for each n in
  764. {"gnutmp.tm1", "gnutmp.tm2", "gnutmp.tm3", "gnutmp.tm4",
  765. "gnutmp.tm5", "gnutmp.tm6", "gnutmp.tm7", "gnutmp.tm8"}
  766. collect gtmpnam n;
  767. plotcleanup!* := if null tempdir!* then {"erase gnutmp.tm*"}
  768. else {bldmsg("erase %w\gnutmp.tm*", tempdir!*)} >>
  769. else if opsys!* = 'msdos then <<
  770. plotheader!* := ""; % ?? "set term vga";
  771. dirchar!* := "\";
  772. plotdta!* := for each n in
  773. {"gnutmp.tm1", "gnutmp.tm2", "gnutmp.tm3", "gnutmp.tm4",
  774. "gnutmp.tm5", "gnutmp.tm6", "gnutmp.tm7", "gnutmp.tm8"}
  775. collect gtmpnam n;
  776. plotcmds!*:= gtmpnam "gnutmp.tm0";
  777. plotcleanup!* := if null tempdir!* then {"erase gnutmp.tm*"}
  778. else {bldmsg("erase %w\gnutmp.tm*", tempdir!*)} >>
  779. else if opsys!* = 'riscos then <<
  780. plotheader!* := "";
  781. dirchar!* := ".";
  782. plotdta!* := for i:=1:10 collect tmpnam();
  783. plotcmds!*:= tmpnam();
  784. plotcleanup!* :=
  785. bldmsg("remove %w", plotcmds!*) .
  786. for each f in plotdta!* collect bldmsg("remove %w", f)
  787. >>
  788. else if opsys!* = 'unix then <<
  789. plotheader!* := "set term x11";
  790. plotdta!* := for i:=1:10 collect tmpnam();
  791. plotcmds!*:= tmpnam();
  792. plotcleanup!* :=
  793. bldmsg("rm %w", plotcmds!*) .
  794. for each f in plotdta!* collect bldmsg("rm %w", f) >>
  795. else if opsys!* = 'finder then <<
  796. plotcommand!* := "gnuplot";
  797. plotcmds!*:= "::::gnuplot:reduce.plt";
  798. plotheader!* := "";
  799. dirchar!* := ":";
  800. plotdta!* := for each n in
  801. {"::::gnuplot:gnutmp.tm1", "::::gnuplot:gnutmp.tm2",
  802. "::::gnuplot:gnutmp.tm3", "::::gnuplot:gnutmp.tm4",
  803. "::::gnuplot:gnutmp.tm5", "::::gnuplot:gnutmp.tm6",
  804. "::::gnuplot:gnutmp.tm7", "::::gnuplot:gnutmp.tm8"}
  805. collect gtmpnam n;
  806. plotcleanup!* := nil >>
  807. else <<
  808. rederr bldmsg("gnuplot for %w not available yet", opsys!*);
  809. plotdta!* := for i:=1:10 collect tmpnam();
  810. plotcmds!*:= tmpnam();
  811. plotheader!* := "set term dumb" >>;
  812. if 'pipes member lispsystem!* then !*plotusepipe:=t
  813. else plotcommand!* := bldmsg("%w %w", plotcommand!*, plotcmds!*);
  814. if plotdir!* then
  815. plotcommand!* := bldmsg("%w%w%w",
  816. plotdir!*, dirchar!*, plotcommand!*);
  817. nil >>;
  818. endpatch;
  819. patch poly;
  820. % 7 Aug 99.
  821. symbolic procedure rationalizesq u;
  822. begin scalar !*structure,!*sub2,v,x;
  823. if x := get(dmode!*,'rationalizefn) then u := apply1(x,u);
  824. powlis!* := '(i 2 (nil . t) -1 nil) . powlis!*;
  825. v := subs2q u;
  826. powlis!* := cdr powlis!*;
  827. return if domainp denr v then v
  828. else if (x := rationalizef denr v) neq 1
  829. then <<v := multf(numr v,x) ./ multf(denr v,x);
  830. if null !*algint and null !*rationalize
  831. then v := gcdchk v;
  832. subs2q v>>
  833. else u
  834. end;
  835. % 6 Feb 00.
  836. symbolic procedure sqfrf u;
  837. begin integer n; scalar !*gcd,units,v,w,x,y,z,!*msg,r;
  838. !*gcd := t;
  839. if (r := !*rounded) then
  840. <<on rational; u := numr resimp !*f2q u>>;
  841. n := 1;
  842. x := mvar u;
  843. v := gcdf(u,diff(u,x));
  844. u := quotf(u,v);
  845. if flagp(dmode!*,'field) and ((y := lnc u) neq 1)
  846. then <<u := multd(!:recip y,u); v := multd(y,v)>>;
  847. while degr(v,x)>0 do
  848. <<w := gcdf(v,u);
  849. if u neq w then z := (quotf(u,w) . n) . z;
  850. v := quotf(v,w);
  851. u := w;
  852. n := n + 1>>;
  853. if r then
  854. <<on rounded;
  855. u := numr resimp !*f2q u;
  856. z := for each j in z
  857. collect numr resimp !*f2q car j . cdr j>>;
  858. if v neq 1 and assoc(v,units) then v := 1;
  859. if v neq 1 then if n=1 then u := multf(v,u)
  860. else if (w := rassoc(1,z)) then rplaca(w,multf(v,car w))
  861. else if null z and not domainp v then z := {v . 1}
  862. else if null z and ((w := rootxf(v,n)) neq 'failed)
  863. then u := multf(w,u)
  864. else errach {"sqfrf failure",u,n,z};
  865. return (u . n) . z
  866. end;
  867. % 2 Aug 00.
  868. symbolic procedure sqfrp u;
  869. begin scalar !*ezgcd, dmode!*;
  870. if null getd 'ezgcdf1 then load_package ezgcd;
  871. !*ezgcd := t;
  872. return domainp gcdf!*(u,diff(u,mvar u))
  873. end;
  874. % 13 Dec 00.
  875. symbolic procedure gcdk(u,v);
  876. begin scalar lclst,var,w,x;
  877. if u=v then return u
  878. else if domainp u or degr(v,(var := mvar u))=0 then return 1
  879. else if ldeg u<ldeg v then <<w := u; u := v; v := w>>;
  880. if quotf1(u,v) then return v
  881. else if !*heugcd and (x := heu!-gcd(u,v)) then return x
  882. else if ldeg v=1
  883. or getd 'modular!-multicheck and modular!-multicheck(u,v,var)
  884. or not !*mcd
  885. then return 1;
  886. a: w := remk(u,v);
  887. if null w then return v
  888. else if degr(w,var)=0 then return 1;
  889. lclst := addlc(v,lclst);
  890. if x := quotf1(w,lc w) then w := x
  891. else for each y in lclst do
  892. if atom y and not flagp(dmode!*,'field)
  893. or not
  894. (domainp y and (flagp(dmode!*,'field)
  895. or ((x := get(car y,'units))
  896. and y member (for each z in x collect car z))))
  897. then while (x := quotf1(w,y)) do w := x;
  898. u := v; v := prim!-part w;
  899. if degr(v,var)=0 then return 1 else go to a
  900. end;
  901. % 19 Jan 01.
  902. symbolic procedure quarticf pol;
  903. begin scalar !*sub2,a,a2,a0,b,dsc,p,p1,p2,q,shift,var;
  904. var := mvar pol;
  905. p := shift!-pol pol;
  906. a := coeffs car p;
  907. shift := caddr p;
  908. if cadr a then rerror(poly,16,list(pol,"not correctly shifted"))
  909. else if cadddr a then return list(1,pol);
  910. a2 := cddr a;
  911. a0 := caddr a2;
  912. a2 := car a2;
  913. a := car a;
  914. q := quadraticf1(a,a2,a0);
  915. if not(q eq 'failed)
  916. then <<a2 := car q; q := cdr q;
  917. a := exptsq(addsq(!*k2q mvar pol,shift),2);
  918. b := numr subs2q quotsq(addsq(multsq(!*f2q car q,a),
  919. !*f2q cadr q),
  920. !*f2q cadr p);
  921. a := numr subs2q quotsq(addsq(multsq(!*f2q caddr q,a),
  922. !*f2q cadddr q),
  923. !*f2q cadr p);
  924. a := quadraticf!*(a,var);
  925. b := quadraticf!*(b,var);
  926. return multf(a2,multf(car a,car b))
  927. . nconc!*(cdr a,cdr b)>>
  928. else if null !*surds or denr shift neq 1
  929. then return list(1,pol);
  930. shift := numr shift;
  931. if knowndiscrimsign eq 'negative then go to complex;
  932. dsc := powsubsf addf(exptf(a2,2),multd(-4,multf(a,a0)));
  933. p2 := minusf a0;
  934. if not p2 and minusf dsc then go to complex;
  935. p1 := not a2 or minusf a2;
  936. if not p1 then if p2 then p1 := t else p2 := t;
  937. p1 := if p1 then 'positive else 'negative;
  938. p2 := if p2 then 'negative else 'positive;
  939. a := rootxf(a,2);
  940. if a eq 'failed then return list(1,pol);
  941. dsc := rootxf(dsc,2);
  942. if dsc eq 'failed then return list(1,pol);
  943. p := invsq !*f2q addf(a,a);
  944. q := multsq(!*f2q addf(a2,negf dsc),p);
  945. p := multsq(!*f2q addf(a2,dsc),p);
  946. b := multf(a,exptf(addf(!*k2f mvar pol,shift),2));
  947. a := powsubsf addf(b,q);
  948. b := powsubsf addf(b,p);
  949. knowndiscrimsign := p1;
  950. a := quadraticf!*(a,var);
  951. knowndiscrimsign := p2;
  952. b := quadraticf!*(b,var);
  953. knowndiscrimsign := nil;
  954. return multf(car a,car b) . nconc!*(cdr a,cdr b);
  955. complex:
  956. a := rootxf(a,2);
  957. if a eq 'failed then return list(1,pol);
  958. a0 := rootxf(a0,2);
  959. if a0 eq 'failed then return list(1,pol);
  960. a2 := powsubsf addf(multf(2,multf(a,a0)),negf a2);
  961. a2 := rootxf(a2,2);
  962. if a2 eq 'failed then return list(1,pol);
  963. p := addf(!*k2f mvar pol,shift);
  964. q := addf(multf(a,exptf(p,2)),a0);
  965. p := multf(a2,p);
  966. a := powsubsf addf(q,p);
  967. b := powsubsf addf(q,negf p);
  968. knowndiscrimsign := 'negative;
  969. a := quadraticf!*(a,var);
  970. b := quadraticf!*(b,var);
  971. knowndiscrimsign := nil;
  972. return multf(car a,car b) . nconc!*(cdr a,cdr b)
  973. end;
  974. endpatch;
  975. % Rlisp declarations.
  976. fluid '(newrules!*);
  977. patch rlisp;
  978. % 9 Nov 99.
  979. symbolic procedure load!-package u;
  980. begin scalar x,y;
  981. if stringp u then return load!-package intern compress explode2 u
  982. else if null idp u then rederr list(u,"is not a package name")
  983. else if memq(u,loaded!-packages!*)
  984. then return u
  985. else if or(atom(x:= errorset(list('evload,list('quote,list u)),
  986. nil,!*backtrace)),
  987. cdr x)
  988. then rederr
  989. list("error in loading package",u,"or package not found");
  990. loaded!-packages!* := u . loaded!-packages!*;
  991. x := get(u,'package);
  992. if x then x := cdr x;
  993. a: if null x then go to b
  994. else if null atom get(car x,'package) then load!-package car x
  995. else if or(atom(y := errorset(list('evload,
  996. list('quote,list car x)),
  997. nil,!*backtrace)),
  998. cdr y)
  999. then rederr list("module",car x,"of package",u,
  1000. "cannot be loaded");
  1001. x := cdr x;
  1002. go to a;
  1003. b: if (x := get(u,'patchfn))
  1004. then begin scalar !*usermode,!*redefmsg; eval list x end
  1005. end;
  1006. % 22 April 00.
  1007. symbolic procedure begin11 x;
  1008. begin scalar mode,result,newrule!*;
  1009. if cursym!* eq 'end
  1010. then if terminalp() and null !*lisp!_hook
  1011. then progn(cursym!* := '!*semicol!*, !*nosave!* := t,
  1012. return nil)
  1013. else progn(comm1 'end, return 'end)
  1014. else if eqcar((if !*reduce4 then x else cadr x),'retry)
  1015. then if programl!* then x := programl!*
  1016. else progn(lprim "No previous expression",return nil);
  1017. if null !*reduce4 then progn(mode := car x,x := cadr x);
  1018. program!* := x;
  1019. if eofcheck() then return 'c else eof!* := 0;
  1020. add2inputbuf(x,if !*reduce4 then nil else mode);
  1021. if null atom x
  1022. and car x memq '(bye quit)
  1023. then if getd 'bye
  1024. then progn(lispeval x, !*nosave!* := t, return nil)
  1025. else progn(!*byeflag!* := t, return nil)
  1026. else if null !*reduce4 and eqcar(x,'ed)
  1027. then progn((if getd 'cedit and terminalp()
  1028. then cedit cdr x
  1029. else lprim "ED not supported"),
  1030. !*nosave!* := t, return nil)
  1031. else if !*defn
  1032. then if erfg!* then return nil
  1033. else if null flagp(key!*,'ignore)
  1034. and null eqcar(x,'quote)
  1035. then progn((if x then dfprint x else nil),
  1036. if null flagp(key!*,'eval) then return nil);
  1037. if !*output and ifl!* and !*echo and null !*lessspace
  1038. then terpri();
  1039. result := errorset!*(x,t);
  1040. if errorp result or erfg!*
  1041. then progn(programl!* := list(mode,x),return 'err2)
  1042. else if !*defn then return nil;
  1043. if null !*reduce4
  1044. then if null(mode eq 'symbolic) then x := getsetvars x else nil
  1045. else progn(result := car result,
  1046. (if null result then result := mkobject(nil,'noval)),
  1047. mode := type result,
  1048. result := value result);
  1049. add2resultbuf((if null !*reduce4 then car result else result),
  1050. mode);
  1051. if null !*output then return nil
  1052. else if null(semic!* eq '!$)
  1053. then if !*reduce4 then (begin
  1054. terpri();
  1055. if mode eq 'noval then return nil
  1056. else if !*debug then prin2t "Value:";
  1057. rapply1('print,list list(mode,result))
  1058. end)
  1059. else if mode eq 'symbolic
  1060. then if null car result and null(!*mode eq 'symbolic)
  1061. then nil
  1062. else begin
  1063. terpri();
  1064. result:=
  1065. errorset!*(list('print,mkquote car result),t)
  1066. end
  1067. else if car result
  1068. then result := errorset!*(list('assgnpri,mkquote car result,
  1069. (if x then 'list . x else nil),
  1070. mkquote 'only),
  1071. t);
  1072. if null !*reduce4
  1073. then return if errorp result then 'err3 else nil
  1074. else if null(!*mode eq 'noval)
  1075. then progn(terpri(), prin2 "of type: ", print mode);
  1076. return nil
  1077. end;
  1078. endpatch;
  1079. % Roots declarations.
  1080. fluid '(rootacc!#!# rootacc!#!# !*noeqns);
  1081. patch roots;
  1082. % 10 Feb 00.
  1083. symbolic procedure root_val x;
  1084. roots x
  1085. where rootacc!#!#=p, iniprec!#=p where p=precision 0, !*msg=nil,
  1086. !*noeqns=t;
  1087. endpatch;
  1088. % Scope declarations.
  1089. global '(kvarlst prevlst varlst!*);
  1090. patch scope;
  1091. % 29 Aug 00.
  1092. symbolic procedure maxtype type;
  1093. if atom type then type
  1094. else if pairp cdr type then cadr type else car type;
  1095. % 8 Nov 00.
  1096. symbolic procedure prepmultmat(preprefixlist);
  1097. begin scalar tlcm,var,varexp,kvl,kfound,pvl,pfound,tel,ratval,ratlst,
  1098. newvarlst,hvarlst;
  1099. hvarlst:= nil;
  1100. while not null (varlst!*) do
  1101. <<var := car varlst!*; varlst!* := cdr varlst!*;
  1102. if flagp(var,'ratexp)
  1103. then
  1104. <<tlcm:=1;
  1105. remflag(list var,'ratexp);
  1106. foreach elem in get(var,'varlst!*) do
  1107. if pairp cdr elem then tlcm := lcm2(tlcm,cddr elem);
  1108. varexp:=fnewsym();
  1109. tel:=(varexp.(if tlcm = 2
  1110. then list('sqrt,var)
  1111. else list('expt,var,
  1112. if onep cdr(tel:=simpquot list(1,tlcm)) then
  1113. car tel
  1114. else
  1115. list('quotient,car tel,cdr tel))));
  1116. if assoc(var,kvarlst)
  1117. then
  1118. <<kvl:=kfound:=nil;
  1119. while kvarlst and not(kfound) do
  1120. if caar(kvarlst) eq var
  1121. then
  1122. << kvl:=tel.kvl; kfound:=t;
  1123. pvl:=pfound:=nil; prevlst:=reverse(prevlst);
  1124. while prevlst and not(pfound) do
  1125. if cdar(prevlst) eq var
  1126. then << pvl:=cons(caar prevlst,varexp).pvl;
  1127. pfound:=t
  1128. >>
  1129. else << pvl:=car(prevlst).pvl;
  1130. prevlst:=cdr(prevlst)
  1131. >>;
  1132. if pvl then
  1133. if prevlst then prevlst:=append(reverse prevlst,pvl)
  1134. else prevlst:=pvl
  1135. >>
  1136. else
  1137. << kvl:=car(kvarlst).kvl; kvarlst:=cdr kvarlst>>;
  1138. if kvl then
  1139. if kvarlst then kvarlst:=append(reverse kvl,kvarlst)
  1140. else kvarlst:=reverse kvl
  1141. >>
  1142. else preprefixlist:=tel.preprefixlist;
  1143. ratlst:=newvarlst:=nil;
  1144. foreach elem in get(var,'varlst!*) do
  1145. if pairp cdr elem
  1146. then
  1147. << ratval:=divide((tlcm * cadr elem)/(cddr elem),tlcm);
  1148. ratlst:=cons(car elem,cdr ratval).ratlst;
  1149. if car(ratval)>0
  1150. then newvarlst:=cons(car elem,car ratval).newvarlst
  1151. >>
  1152. else newvarlst:=elem.newvarlst;
  1153. if ratlst
  1154. then << put(varexp,'varlst!*,reverse ratlst);
  1155. hvarlst:=varexp.hvarlst
  1156. >>;
  1157. if newvarlst
  1158. then << put(var,'varlst!*,reverse newvarlst);
  1159. hvarlst:=var.hvarlst
  1160. >>
  1161. else remprop(var,'varlst!*)
  1162. >>
  1163. else hvarlst:=var.hvarlst
  1164. >>;
  1165. varlst!* := hvarlst;
  1166. return preprefixlist
  1167. end;
  1168. endpatch;
  1169. % Solve declarations.
  1170. fluid '(!*multiplicities vars!*);
  1171. global '(multiplicities!*);
  1172. patch solve;
  1173. % 9 Jan 01.
  1174. symbolic procedure !*solvelist2solveeqlist u;
  1175. begin scalar x,y,z;
  1176. u := for each j in u collect solveorder j;
  1177. for each j in u do
  1178. <<if caddr j=0 then rerror(solve,2,"zero multiplicity")
  1179. else if null cadr j
  1180. then x := for each k in car j collect
  1181. list('equal,!*q2a k,0)
  1182. else x := for each k in pair(cadr j,car j)
  1183. collect list('equal,car k,!*q2a cdr k);
  1184. if length vars!* > 1 then x := 'list . x else x := car x;
  1185. z := (caddr j . x) . z>>;
  1186. z := sort(z,function ordp);
  1187. x := nil;
  1188. if !*multiplicities
  1189. then <<for each k in z do for i := 1:car k do x := cdr k . x;
  1190. multiplicities!* := nil>>
  1191. else <<for each k in z do << x := cdr k . x; y := car k . y>>;
  1192. multiplicities!* := 'list . reversip y>>;
  1193. return 'list . reversip x
  1194. end;
  1195. symbolic procedure solveorder u;
  1196. begin scalar v,x,y,z;
  1197. v := vars!*;
  1198. x := cadr u;
  1199. if length x<length v then v := setdiff(v,setdiff(v,x));
  1200. if null x or x=v then return u;
  1201. y := car u;
  1202. while x do <<z := (car x . car y) . z; x := cdr x; y := cdr y>>;
  1203. x := for each j in v collect
  1204. if null (y := assoc(j,z)) then errach "SOLVE confusion"
  1205. else cdr y;
  1206. return x . v . cddr u
  1207. end;
  1208. % 2 Feb 01.
  1209. symbolic procedure check!-solns(z,ex,var);
  1210. begin scalar x;
  1211. if errorp (x :=
  1212. errorset2 {'check!-solns1,mkquote z,mkquote ex,mkquote var})
  1213. then return
  1214. check!-solns1(z,(numr simp!* prepf ex where !*reduced=t),var)
  1215. else return car x
  1216. end;
  1217. symbolic procedure check!-solns1(z,ex,var);
  1218. begin scalar x,y,fv,sx,vs;
  1219. fv := freevarl(ex,var);
  1220. for each z1 in z do
  1221. fv := union(fv,union(freevarl(numr caar z1,var),
  1222. freevarl(denr caar z1,var)));
  1223. fv := delete('i,fv);
  1224. if fv then for each v in fv do
  1225. if not flagp(v,'constant) then
  1226. vs := (v . list('quotient,1+random 999,1000)) . vs;
  1227. sx := if vs then numr subf(ex,vs) else ex;
  1228. while z do
  1229. if null cadar z then <<z := nil; x := 'unsolved>>
  1230. else if
  1231. <<y := numr subf(ex,list(caadar z . mk!*sq caaar z));
  1232. null y
  1233. or fv and null(y := numr subf(sx,list(caadar z .
  1234. mk!*sq subsq(caaar z,vs))))
  1235. or null numvalue y>>
  1236. then <<x := car z . x; z := cdr z>>
  1237. else z := cdr z;
  1238. return if null x then 'unsolved else x
  1239. end;
  1240. endpatch;
  1241. % Sum declarations.
  1242. fluid '(sum_last_attempt_rules!* !*zeilberg);
  1243. patch sum;
  1244. % 28 Jul 00.
  1245. symbolic procedure freeof!-df(u, v);
  1246. if atom u then t
  1247. else if car(u) eq 'df
  1248. then freeof!-df(cadr u, v) and not smember(v,cddr u)
  1249. else freeof!-dfl(cdr u, v);
  1250. symbolic procedure freeof!-dfl(u, v);
  1251. if null u then t else freeof!-df(car u,v) and freeof!-dfl(cdr u,v);
  1252. symbolic procedure simp!-sum u;
  1253. begin scalar y;
  1254. y := cdr u;
  1255. u := car u;
  1256. if not atom y and not freeof!-df(u, car y) then
  1257. if atom y
  1258. then return !*p2f(car fkern(list('sum,u)) .* 1) ./ 1
  1259. else return sum!-df(u, y);
  1260. u := simp!* u;
  1261. return if null numr u then u
  1262. else if atom y
  1263. then !*p2f(car fkern(list('sum,prepsq u)) .* 1) ./ 1
  1264. else if !*zeilberg then gosper!*(mk!*sq u,y)
  1265. else simp!-sum0(u,y)
  1266. end;
  1267. symbolic procedure sum!-subst(u,x,a);
  1268. if u = x then a
  1269. else if atom u then u
  1270. else sum!-subst(car u, x,a) . sum!-subst(cdr u,x,a);
  1271. symbolic procedure sum!-df(u,y);
  1272. begin scalar w,z,upper,lower,dif;
  1273. if length(y) = 3 then <<
  1274. lower := cadr y;
  1275. upper := caddr y;
  1276. dif := addsq(simp!* upper, negsq simp!* lower);
  1277. if denr dif = 1 then
  1278. if null numr dif
  1279. then return simp!* sum!-subst(u, car y, upper)
  1280. else if fixp numr dif then dif := numr dif
  1281. else dif := nil
  1282. else dif := nil;
  1283. if dif and dif <= 0 then return nil ./ 1 >>;
  1284. if null dif then <<
  1285. z := 'sum . (u . y);
  1286. let sum_last_attempt_rules!*;
  1287. w:= opmtch z;
  1288. rule!-list (list sum_last_attempt_rules!*,nil);
  1289. return if w then simp w else mksq(z,1)>>;
  1290. z := nil ./ 1;
  1291. a: if dif < 0 then return z;
  1292. z := addsq(z,simp!* sum!-subst(u, car y, list('plus,lower,dif)));
  1293. dif := dif - 1;
  1294. go to a
  1295. end;
  1296. % 20 Nov 00.
  1297. symbolic procedure termlst(u,v,klst);
  1298. begin scalar x,kern,lst;
  1299. if null u then return nil
  1300. else if null klst or domainp u
  1301. then return list multsq(v,!*f2q u);
  1302. kern := car klst;
  1303. klst := cdr klst;
  1304. x := setkorder list kern;
  1305. u := reorder u;
  1306. v := reorder(numr v) ./ reorder(denr v);
  1307. while not domainp u and mvar u eq kern do <<
  1308. lst := nconc(termlst(lc u, multsq(!*p2q lpow u, v),klst),lst);
  1309. u := red u>>;
  1310. if u then lst := nconc(termlst(u,v,klst),lst);
  1311. setkorder x;
  1312. return lst
  1313. end;
  1314. endpatch;
  1315. endmodule;
  1316. end;