polrep.red 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. module polrep; % Arithmetic operations on standard forms and quotients.
  2. % Author: Anthony C. Hearn.
  3. % Copyright (c) 1991 RAND. All rights reserved.
  4. fluid '(!*asymp!* !*exp !*factor !*gcd !*lcm !*mcd !*rationalize frlis!*
  5. !*roundall !*rounded !*sqfree !*sub2 asymplis!* dmode!* subfg!*
  6. ncmp!* powlis!* wtl!* !*!*processed !*ncmp);
  7. global '(!*group rd!-tolerance!* cr!-tolerance!*);
  8. put('roundall,'simpfg,'((t (rmsubs))));
  9. switch roundall;
  10. !*roundall := t; % Default is on.
  11. symbolic smacro procedure subtrsq(u,v); addsq(u,negsq v);
  12. symbolic procedure addsq(u,v);
  13. % U and V are standard quotients.
  14. % Value is canonical sum of U and V.
  15. if null numr u then v
  16. else if null numr v then u
  17. else if denr u=1 and denr v=1 then addf(numr u,numr v) ./ 1
  18. else begin scalar x,y,z;
  19. if null !*exp then <<u := numr u ./ mkprod denr u;
  20. v := numr v ./ mkprod denr v>>;
  21. if !*lcm then x := gcdf!*(denr u,denr v)
  22. else x := gcdf(denr u,denr v);
  23. z := canonsq(quotf(denr u,x) ./ quotf(denr v,x));
  24. y := addf(multf(denr z,numr u),multf(numr z,numr v));
  25. if null y then return nil ./ 1;
  26. z := multf(denr u,denr z);
  27. return if x=1 or (x := gcdf(y,x))=1 then y ./ z
  28. else canonsq(quotf(y,x) ./ quotf(z,x))
  29. end;
  30. symbolic procedure multsq(u,v);
  31. % U and V are standard quotients.
  32. % Value is canonical product of U and V.
  33. if null numr u or null numr v then nil ./ 1
  34. else if denr u=1 and denr v=1 then multf(numr u,numr v) ./ 1
  35. else begin scalar x,y,z;
  36. x := gcdf(numr u,denr v);
  37. y := gcdf(numr v,denr u);
  38. z := multf(quotf(numr u,x),quotf(numr v,y));
  39. x := multf(quotf(denr u,y),quotf(denr v,x));
  40. return canonsq(z ./ x)
  41. end;
  42. symbolic procedure negsq u; negf numr u ./ denr u;
  43. smacro procedure multpq(u,v);
  44. multsq(!*p2q u,v);
  45. symbolic procedure cancel u;
  46. %returns canonical form of non-canonical standard form U;
  47. if !*mcd or denr u=1 then multsq(numr u ./ 1,1 ./ denr u)
  48. else multsq(numr u ./ 1,simpexpt list(mk!*sq(denr u ./ 1),-1));
  49. % ***** FUNCTIONS FOR ADDING AND MULTIPLYING STANDARD FORMS *****
  50. symbolic smacro procedure peq(u,v);
  51. %tests for equality of powers U and V;
  52. u = v;
  53. symbolic procedure addf(u,v);
  54. % U and V are standard forms. Value is standard form for U+V.
  55. if null u then v
  56. else if null v then u
  57. else if domainp u then addd(u,v)
  58. else if domainp v then addd(v,u)
  59. else if peq(lpow u,lpow v)
  60. then (if null x then y else lpow u .* x .+ y)
  61. where x=addf(lc u,lc v),y=addf(red u,red v)
  62. else if ordpp(lpow u,lpow v) then lt u .+ addf(red u,v)
  63. else lt v .+ addf(u,red v);
  64. symbolic procedure addd(u,v);
  65. % U is a domain element, V a standard form.
  66. % Value is a standard form for U+V.
  67. if null v then u
  68. else if domainp v then adddm(u,v)
  69. else lt v .+ addd(u,red v);
  70. symbolic procedure adddm(u,v);
  71. % U and V are both non-zero domain elements.
  72. % Value is standard form for U+V.
  73. % The int-equiv-chk is needed to convert say (:MOD: . 0) to NIL.
  74. % A simpler function might therefore be possible and more efficient.
  75. if atom u and atom v
  76. then (if null dmode!* or not flagp(dmode!*,'convert) then !*n2f x
  77. else int!-equiv!-chk apply1(get(dmode!*,'i2d),x))
  78. where x=plus2(u,v)
  79. else dcombine(u,v,'plus);
  80. symbolic procedure domainp u; atom u or atom car u;
  81. symbolic procedure noncomp u;
  82. !*ncmp and noncomp1 u;
  83. symbolic procedure noncomp1 u;
  84. if null pairp u then nil
  85. else if pairp car u then noncomfp u
  86. else flagp(car u,'noncom) or noncomlistp cdr u;
  87. symbolic procedure noncomlistp u;
  88. pairp u and (noncomp1 car u or noncomlistp cdr u);
  89. symbolic procedure multf(u,v);
  90. % U and V are standard forms.
  91. % Value is standard form for U*V.
  92. begin scalar x,y;
  93. a: if null u or null v then return nil
  94. else if u=1 then return v % ONEP
  95. else if v=1 then return u % ONEP
  96. else if domainp u then return multd(u,v)
  97. else if domainp v then return multd(v,u)
  98. else if not(!*exp or ncmp!* or wtl!* or x)
  99. then <<u := mkprod u; v := mkprod v; x := t; go to a>>;
  100. x := mvar u;
  101. y := mvar v;
  102. if noncomfp v and (noncomp x or null !*!*processed)
  103. then return multfnc(u,v)
  104. else if x eq y
  105. then <<% Allow for free variables in rules.
  106. if not fixp ldeg u or not fixp ldeg v
  107. then x := x .** reval list('plus,ldeg u,ldeg v)
  108. else x := mkspm(x,ldeg u+ldeg v);
  109. % The order in the next line is IMPORTANT. See analysis
  110. % by J.H. Davenport et al. for details.
  111. y := addf(multf(red u,v),multf(!*t2f lt u,red v));
  112. return if null x or null(u := multf(lc u,lc v))
  113. then <<!*asymp!* := t; y>>
  114. else if x=1 then addf(u,y)
  115. else if null !*mcd then addf(!*t2f(x .* u),y)
  116. else x .* u .+ y>>
  117. else if ordop(x,y)
  118. then <<x := multf(lc u,v);
  119. y := multf(red u,v);
  120. return if null x then y else lpow u .* x .+ y>>;
  121. x := multf(u,lc v);
  122. y := multf(u,red v);
  123. return if null x then y else lpow v .* x .+ y
  124. end;
  125. symbolic procedure noncomfp u;
  126. % It's possible that ncmp!* would work here.
  127. !*ncmp and noncomfp1 u;
  128. symbolic procedure noncomfp1 u;
  129. not domainp u
  130. and (noncomp mvar u or noncomfp1 lc u or noncomfp1 red u);
  131. symbolic procedure multfnc(u,v);
  132. % Returns canonical product of U and V, with both main vars non-
  133. % commutative.
  134. begin scalar x,y;
  135. x := multf(lc u,!*t2f lt v);
  136. if null x then nil
  137. else if not domainp x and mvar x eq mvar u
  138. then x := addf(if null (y := mkspm(mvar u,ldeg u+ldeg x))
  139. then nil
  140. else if y = 1 then lc x
  141. else !*t2f(y .* lc x),
  142. multf(!*p2f lpow u,red x))
  143. else if noncomp mvar u then x := !*t2f(lpow u .* x)
  144. else x := multf(!*p2f lpow u,x) where !*!*processed=t;
  145. return addf(x,addf(multf(red u,v),multf(!*t2f lt u,red v)))
  146. end;
  147. symbolic procedure multd(u,v);
  148. % U is a domain element, V a standard form.
  149. % Value is standard form for U*V.
  150. if null v then nil
  151. else if v=1 then u % Common enough to be tested.
  152. else if domainp v then multdm(u,v)
  153. else lpow v .* multd(u,lc v) .+ multd(u,red v);
  154. symbolic procedure multdm(u,v);
  155. % U and V are both non-zero domain elements.
  156. % Value is standard form for U*V;
  157. if atom u and atom v
  158. then (lambda x; if null dmode!*
  159. or not flagp(dmode!*,'convert) then x
  160. else % int!-equiv!-chk
  161. apply1(get(dmode!*,'i2d),x))
  162. times2(u,v)
  163. else dcombine(u,v,'times);
  164. smacro procedure multpf(u,v); multf(!*p2f u,v);
  165. symbolic procedure negf u;
  166. if null u then nil
  167. else if domainp u
  168. then !:minus if atom u and flagp(dmode!*,'convert)
  169. then apply1(get(dmode!*,'i2d),u)
  170. else u
  171. else lpow u .* negf lc u .+ negf red u;
  172. symbolic procedure degreef(pol,var);
  173. % Find degree of kernel in standard form pol.
  174. % Note: uniqueness of kernel assumed.
  175. if domainp pol then 0
  176. else if mvar pol eq var then ldeg pol
  177. else max(degreef(lc pol,var),degreef(red pol,var));
  178. put('!*sq,'lengthfn,'!*sqlength);
  179. symbolic procedure !*sqlength u;
  180. (if denr car u=1 then x else x+termsf denr car u)
  181. where x = termsf numr car u;
  182. symbolic procedure terms u;
  183. <<lprim "Please use LENGTH instead"; termsf numr simp!* u>>;
  184. flag('(terms),'opfn);
  185. flag('(terms),'noval);
  186. symbolic procedure termsf u;
  187. % U is a standard form.
  188. % Value is number of terms in U (excluding kernel structure).
  189. begin integer n;
  190. while not domainp u do <<n := n + termsf lc u; u := red u>>;
  191. return if null u then n else n+1
  192. end;
  193. symbolic procedure tmsf u;
  194. % U is a standard form.
  195. % Value is number of terms in U (including kernel structure).
  196. begin integer n; scalar x;
  197. % Integer declaration initializes N to 0.
  198. while not domainp u do
  199. <<n := n+(if sfp(x := mvar u) then tmsf x else 1)+tmsf!* lc u;
  200. if ldeg u neq 1 then if ldeg u=2 then n := n+1 else n := n+2;
  201. u := red u>>; % Previously, if U was non-zero, we used to add
  202. % one more here.
  203. return if null u then n else n+1
  204. end;
  205. symbolic procedure tmsf!* u;
  206. if numberp u and abs fix u=1 then 0 else tmsf u; % Was tmsf u+1.
  207. symbolic procedure tms u; tmsf numr simp!* u;
  208. flag('(tms),'opfn);
  209. flag('(tms),'noval);
  210. % ***** FUNCTIONS FOR WORKING WITH STRUCTURED FORMS *****
  211. fluid '(!*really_off_exp);
  212. symbolic procedure offexpchk u;
  213. % Return structured form for standard quotient u.
  214. % The freevar check is required to correctly evaluate rules like
  215. % for all n let f(a^n-b^n)=c when exp is off and gcd on.
  216. if !*really_off_exp or
  217. (frlis!* and freevarinexptchk numr u or freevarinexptchk denr u)
  218. then u
  219. else canprod(mkprod numr u,mkprod denr u);
  220. symbolic procedure freevarinexptchk u;
  221. not domainp u and(not numberp ldeg u or freevarinexptchk lc u
  222. or freevarinexptchk red u);
  223. symbolic procedure mkprod u;
  224. begin scalar w,x,y,z,!*exp,!*sub2;
  225. if null u or kernlp u then return u;
  226. % First make sure there are no further simplifications.
  227. !*sub2 := t;
  228. x := subs2(u ./ 1);
  229. if denr x neq 1 then return u % We can't do much more here.
  230. else if numr x neq u
  231. then <<u := numr x; if null u or kernlp u then return u>>;
  232. !*exp := t;
  233. w := ckrn u;
  234. u := quotf(u,w);
  235. x := expnd u;
  236. if null x or kernlp x then return multf(w,x);
  237. % After this point, X is not KERNLP.
  238. % The check below for *MCD was suggested by James Davenport.
  239. % Without it, on gcd; off mcd,exp; (x**2+2x+1)/x+1; loops
  240. % forever.
  241. if !*mcd and (!*sqfree or !*factor or !*gcd)
  242. then y := fctrf x
  243. else <<y := ckrn x; x := quotf(x,y); y := list(y,x . 1)>>;
  244. if cdadr y>1 or cddr y
  245. then <<z := car y;
  246. for each j in cdr y do
  247. z := multf(mksp!*(car j,cdr j),z)>>
  248. else if not !*group and tmsf u>tmsf caadr y
  249. then z := multf(mksp!*(caadr y,cdadr y),car y)
  250. else z := mksp!*(u,1);
  251. return multf(w,z)
  252. end;
  253. symbolic procedure expnd u;
  254. if !*really_off_exp then u else
  255. begin scalar !*sub2,v;
  256. u := expnd1 u;
  257. return if !*sub2 and denr(v := subs2f u) = 1 then numr v
  258. else u
  259. end;
  260. symbolic procedure expnd1 u;
  261. if domainp u then u
  262. else addf(if not sfp mvar u or ldeg u<0
  263. then multpf(lpow u,expnd1 lc u)
  264. else multf(exptf(expnd1 mvar u,ldeg u),expnd1 lc u),
  265. expnd1 red u);
  266. symbolic procedure canprod(p,q);
  267. % P and Q are kernel product standard forms, value is P/Q in
  268. % which a top level standard form kernel by itself has been
  269. % unwound.
  270. begin scalar v,w,x,y,z;
  271. if domainp q or red q or (not domainp p and red p)
  272. then return cancel(p ./ q);
  273. % Look for possible cancellations.
  274. while not domainp p or not domainp q do
  275. if sfpf p then <<z := cprod1(mvar p,ldeg p,v,w);
  276. v := car z; w := cdr z; p := lc p>>
  277. else if sfpf q then <<z := cprod1(mvar q,ldeg q,w,v);
  278. w := car z; v := cdr z; q := lc q>>
  279. else if domainp p then <<y := lpow q . y; q := lc q>>
  280. else if domainp q then <<x := lpow p . x; p := lc p>>
  281. else <<x := lpow p . x; y := lpow q . y;
  282. p := lc p; q := lc q>>;
  283. v := reprod(v,reprod(x,p));
  284. w := reprod(w,reprod(y,q));
  285. if minusf w then <<v := negf v; w := negf w>>;
  286. w := cancel(v ./ w);
  287. % Final check for unnecessary structure.
  288. v := numr w;
  289. if not domainp v and null red v and lc v=1
  290. and ldeg v=1 and sfp(x := mvar v)
  291. then v := x;
  292. w := denr w;
  293. if not domainp w and null red w and lc w=1
  294. and ldeg w=1 and sfp(x := mvar w)
  295. then w := x;
  296. return canonsq(v ./ w)
  297. end;
  298. symbolic procedure sfpf u;
  299. not domainp u and sfp mvar u;
  300. symbolic procedure sfp u;
  301. % True if mvar U is a standard form.
  302. not atom u and not atom car u;
  303. symbolic procedure reprod(u,v);
  304. % U is a list of powers, V a standard form.
  305. % Value is product of terms in U with V.
  306. <<while u do <<v := multpf(car u,v); u := cdr u>>; v>>;
  307. symbolic procedure cprod1(p,m,v,w);
  308. % U is a standard form, which occurs in a kernel raised to power M.
  309. % V is a list of powers multiplying P**M, W a list dividing it.
  310. % Value is a dotted pair of lists of powers after all possible
  311. % kernels have been cancelled.
  312. begin scalar z;
  313. z := cprod2(p,m,w,nil);
  314. w := cadr z;
  315. v := append(cddr z,v);
  316. z := cprod2(car z,m,v,t);
  317. v := cadr z;
  318. w := append(cddr z,w);
  319. if car z neq 1 then v := mksp(car z,m) . v;
  320. return v . w
  321. end;
  322. symbolic procedure cprod2(p,m,u,b);
  323. %P and M are as in CPROD1. U is a list of powers. B is true if P**M
  324. %multiplies U, false if it divides.
  325. %Value has three parts: the first is the part of P which does not
  326. %have any common factors with U, the second a list of powers (plus
  327. %U) which multiply U, and the third a list of powers which divide U;
  328. %it is implicit here that the kernel standard forms are positive;
  329. begin scalar n,v,w,y,z;
  330. while u and p neq 1 do
  331. <<if (z := gcdf(p,caar u)) neq 1
  332. then
  333. <<p := quotf(p,z);
  334. y := quotf(caar u,z);
  335. if y neq 1 then v := mksp(y,cdar u) . v;
  336. if b then v := mksp(z,m+cdar u) . v
  337. else if (n := m-cdar u)>0 then w := mksp(z,n) . w
  338. else if n<0 then v := mksp(z,-n) . v>>
  339. else v := car u . v;
  340. u := cdr u>>;
  341. return (p . nconc!*(u,v) . w)
  342. end;
  343. symbolic procedure mkspm(u,p);
  344. %U is a unique kernel, P an integer;
  345. %value is 1 if P=0, NIL if U**P is 0, else standard power of U**P;
  346. % should we add a check for NOT(U EQ K!*) in first line?
  347. if p=0 then 1
  348. else begin scalar x;
  349. if subfg!* and (x:= atsoc(u,asymplis!*)) and cdr x<=p
  350. then return nil;
  351. sub2chk u;
  352. return u .** p
  353. end;
  354. symbolic procedure sub2chk u;
  355. %determines if kernel U is such that a power substitution is
  356. %necessary;
  357. if subfg!*
  358. and(atsoc(u,powlis!*) or not atom u and car u memq '(expt sqrt))
  359. then !*sub2 := t;
  360. % ***** FUNCTIONS FOR DIVIDING STANDARD FORMS *****
  361. symbolic procedure quotsq(u,v);
  362. multsq(u,invsq v);
  363. symbolic procedure quotf!*(u,v);
  364. % We do the rationalizesq step to allow for surd divisors.
  365. if null u then nil
  366. else (if x then x
  367. else (if denr y = 1 then numr y
  368. else errach list("DIVISION FAILED",u,v))
  369. where y=rationalizesq(u ./ v))
  370. where x=quotf(u,v);
  371. symbolic procedure quotf(u,v);
  372. % begin scalar xexp;
  373. % xexp := !*exp;
  374. % !*exp := t;
  375. % u := quotf1(u,v);
  376. % !*exp := xexp;
  377. % return u
  378. % end;
  379. quotf1(u,v) where !*exp = t;
  380. symbolic procedure quotf1(p,q);
  381. % P and Q are standard forms.
  382. % Value is the quotient of P and Q if it exists or NIL.
  383. if null p then nil
  384. else if p=q then 1
  385. else if q=1 then p
  386. else if domainp q then quotfd(p,q)
  387. else if domainp p then nil
  388. else if mvar p eq mvar q
  389. then begin scalar u,v,w,x,xx,y,z,z1; integer n;
  390. a:if idp(u := rank p) or idp(v := rank q) or u<v then return nil;
  391. % The above IDP test is because of the possibility of a free
  392. % variable in the degree position from LET statements.
  393. u := lt!* p;
  394. v := lt!* q;
  395. w := mvar q;
  396. x := quotf1(tc u,tc v);
  397. if null x then return nil;
  398. n := tdeg u-tdeg v;
  399. if n neq 0 then y := w .** n;
  400. % p := addf2zro(p,multf(if n=0 then q
  401. % p := addf(p,multf(negf x,if n=0 then q else multpf(y,q)));
  402. xx := multf(negf x,red q);
  403. % The following expression for p explicitly calculates the
  404. % needed remainder. It has to be this way for non-commuting
  405. % expressions.
  406. p := addf(red p,if n=0 then xx else multpf(y,xx));
  407. % Leading terms of P and Q do not cancel if MCD is off. However,
  408. % there may be a problem with off exp.
  409. if p and (domainp p or not(mvar p eq w)) then return nil
  410. else if n=0 then go to b;
  411. z := aconc!*(z,y .* x);
  412. %provided we have a non-zero power of X, terms
  413. %come out in right order;
  414. if null p then return if z1 then rnconc(z,z1) else z;
  415. go to a;
  416. b: if null p then return rnconc(z,x)
  417. else if !*mcd then return nil
  418. else z1 := x;
  419. go to a
  420. end
  421. else if ordop(mvar p,mvar q) then quotk(p,q)
  422. else nil;
  423. % symbolic procedure addf2zro(p,q);
  424. % <<q := addf(p,q);
  425. % if not dmode!* memq '(!:rd!: !:cr!:)
  426. % or null q or null (p := quotf(q,p)) then q
  427. % else if domainp p then
  428. % if eqcar(p,'!:rd!:)
  429. % and lessp!:(abs!: bfloat round!* p,rd!-tolerance!*)
  430. % or eqcar(p,'!:cr!:)
  431. % and (lessp!:(plus!:(times!:(x,x),times!:(y,y)),cr!-tolerance!*)
  432. % where x=bfloat round!* tagrl p,y=bfloat round!* tagim p)
  433. % then nil else q>>;
  434. symbolic procedure rnconc(u,v);
  435. if null u then v
  436. else if !*ncmp and noncomfp1 u and noncomfp1 v then addf(u,v)
  437. else begin scalar w;
  438. % This is like nconc, but doesn't assume its second argument is a
  439. % list.
  440. w := u;
  441. while cdr w do <<w := cdr w>>;
  442. rplacd(w,v);
  443. return u
  444. end;
  445. symbolic procedure quotfd(p,q);
  446. % P is a standard form, Q a domain element.
  447. % Value is P/Q if exact division is possible, or NIL otherwise.
  448. if p=q then 1
  449. else if flagp(dmode!*,'field) then divd(p,q)
  450. else if domainp p then quotdd(p,q)
  451. else quotk(p,q);
  452. symbolic procedure divd(v,u);
  453. % U is a domain element, V a standard form.
  454. % Value is standard form for V/U.
  455. if null u
  456. then if null v then rerror(poly,1,"0/0 formed")
  457. else rerror(poly,2,"Zero divisor")
  458. else if null v then nil
  459. else if domainp v then divdm(v,u)
  460. else lpow v .* divd(lc v,u) .+ divd(red v,u);
  461. symbolic procedure divdm(v,u);
  462. % U and V are both non-zero domain elements.
  463. % Value is standard form for V/U.
  464. if atom v and atom u
  465. then if remainder(v,u)=0 then v/u
  466. else !:rn2rd mkrn(v,u)
  467. else y % (if null dmode!* then y else int!-equiv!-chk y)
  468. where y=dcombine(v,u,'quotient);
  469. symbolic procedure quotdd(u,v);
  470. % U and V are domain elements. Value is U/V if division is exact,
  471. % NIL otherwise.
  472. begin scalar w;
  473. if atom u then
  474. if atom v then
  475. <<w := divide(u,v); return if cdr w = 0 then car w else nil>>
  476. else if (w := get(car v,'i2d)) then u := apply1(w,u)
  477. else if atom v and (w := get(car u,'i2d)) then v := apply1(w,v);
  478. return dcombine(u,v,'quotient)
  479. end;
  480. symbolic procedure quotk(p,q);
  481. (lambda w;
  482. if w then if null red p then list (lpow p .* w)
  483. else (lambda y;if y then lpow p .* w .+ y else nil)
  484. quotf1(red p,q)
  485. else nil)
  486. quotf1(lc p,q);
  487. symbolic procedure rank p;
  488. %P is a standard form
  489. %Value is the rank of P;
  490. if !*mcd then ldeg p
  491. else begin integer m,n; scalar y;
  492. n := ldeg p;
  493. y := mvar p;
  494. a: m := ldeg p;
  495. if null red p then return n-m;
  496. p := red p;
  497. if degr(p,y)=0 then return if m<0 then if n<0 then -m
  498. else n-m else n;
  499. go to a
  500. end;
  501. symbolic procedure lt!* p;
  502. %Returns true leading term of polynomial P;
  503. if !*mcd or ldeg p>0 then car p
  504. else begin scalar x,y;
  505. x := lt p;
  506. y := mvar p;
  507. a: p := red p;
  508. if null p then return x
  509. else if degr(p,y)=0 then return (y . 0) .* p;
  510. go to a
  511. end;
  512. symbolic procedure remf(u,v);
  513. %returns the remainder of U divided by V;
  514. if null v then rerror(poly,201,"Zero divisor") else cdr qremf(u,v);
  515. put('remainder,'polyfn,'remf);
  516. symbolic procedure qremf(u,v);
  517. % Returns the quotient and remainder of U divided by V.
  518. % Exp cannot be off, otherwise a loop can occur. e.g.,
  519. % qremf('(((x . 1) . -1) . 1),'(((x . 2) . -3) . 4)).
  520. begin integer n; scalar !*exp,x,y,z;
  521. !*exp := t;
  522. if domainp v then return qremd(u,v);
  523. z := list nil; % Final value.
  524. a: if domainp u then return praddf(z,nil . u)
  525. else if mvar u eq mvar v
  526. then if (n := ldeg u-ldeg v)<0 then return praddf(z,nil . u)
  527. else <<x := qremf(lc u,lc v);
  528. y := multpf(lpow u,cdr x);
  529. z := praddf(z,(if n=0 then car x
  530. else multpf(mvar u .** n,car x))
  531. . y);
  532. u := if null car x then red u
  533. else addf(addf(u,multf(if n=0 then v
  534. else multpf(mvar u .** n,v),
  535. negf car x)), negf y);
  536. go to a>>
  537. else if not ordop(mvar u,mvar v)
  538. then return praddf(z,nil . u);
  539. x := qremf(lc u,v);
  540. z := praddf(z,multpf(lpow u,car x) . multpf(lpow u,cdr x));
  541. u := red u;
  542. go to a
  543. end;
  544. symbolic procedure praddf(u,v);
  545. % U and V are dotted pairs of standard forms.
  546. addf(car u,car v) . addf(cdr u,cdr v);
  547. symbolic procedure qremd(u,v);
  548. % Returns a dotted pair of quotient and remainder of form U
  549. % divided by domain element V.
  550. if null u then u . u
  551. else if v=1 then list u
  552. else if flagp(dmode!*,'field) then list multd(!:recip v,u)
  553. else if domainp u then !:divide(u,v)
  554. else begin scalar x;
  555. x := qremf(lc u,v);
  556. return praddf(multpf(lpow u,car x) . multpf(lpow u,cdr x),
  557. qremd(red u,v))
  558. end;
  559. symbolic procedure lqremf(u,v);
  560. %returns a list of coeffs of powers of V in U, constant term first;
  561. begin scalar x,y;
  562. y := list u;
  563. while car(x := qremf(car y,v)) do y := car x . cdr x . cdr y;
  564. return reversip!* y
  565. end;
  566. symbolic procedure minusf u;
  567. %U is a non-zero standard form.
  568. %Value is T if U has a negative leading numerical coeff,
  569. %NIL otherwise;
  570. if null u then nil
  571. else if domainp u
  572. then if atom u then u<0 else apply1(get(car u,'minusp),u)
  573. else minusf lc u;
  574. symbolic procedure absf!* u;
  575. % Returns representation for absolute value of standard form U.
  576. (if domainp u then x else !*p2f mksp(list('abs,prepf x),1))
  577. where x = absf u;
  578. symbolic procedure absf u;
  579. if minusf u then negf u else u;
  580. symbolic procedure canonsq u;
  581. % U is a standard quotient. Value is a standard quotient in which
  582. % the leading power of the denominator has a positive numerical
  583. % coefficient and the denominator is normalized where possible.
  584. if denr u=1 then u
  585. else if null numr u then nil ./ 1
  586. else begin scalar x,y;
  587. % This example shows the following gcd check is needed:
  588. % a:=1+x/2; let x**2=0; a*a;
  589. % Should only be needed when an asymptotic reduction occurs.
  590. if asymplis!* and ((x := gcdf(numr u,denr u)) neq 1)
  591. then u := quotf(numr u,x) ./ quotf(denr u,x);
  592. % Now adjust for a positive leading numerical coeff in denr.
  593. x := lnc denr u;
  594. if x=1 then return u
  595. else if atom x then if minusp x
  596. then <<u := negf numr u ./ negf denr u;
  597. x := -x>>
  598. else nil
  599. else if apply1(get(car x,'minusp),x)
  600. then <<u := negf numr u ./ negf denr u;
  601. x:= apply2(get(car x,'difference),
  602. apply1(get(car x,'i2d),0),
  603. x)>>;
  604. % Now check for a global field mode, a leading domain coeff
  605. % with field properties or "unit" properties so we can adjust
  606. % numr and denr. The tests are done in the following order
  607. % since the other order will give wrong results with some
  608. % polynomials with decimal coefficients in dmode :gi:.
  609. return if not numberp x and (y := get(dmode!*,'unitsfn))
  610. then apply2(y,u,x)
  611. else if flagp(dmode!*,'field)
  612. or not atom x and flagp(car x,'field) then fieldconv(x,u)
  613. else u
  614. end;
  615. symbolic procedure fieldconv(x,u);
  616. % U is a standard quotient and x the leading numerical coefficient
  617. % of the denominator. Returns inverse(x)*numr u/denr u.
  618. % X is a domain, but d may not be; dmode!* or x is field.
  619. begin scalar n,d,y; n := numr u; d := denr u;
  620. if null dmode!* then
  621. <<if not eqcar(x,'!:rn!:)
  622. then if (y := get(car x,'!:rn!:)) and atom y
  623. then x := apply1(y,x)
  624. else if get(car x,'quotient)
  625. then <<x := dcombine(1,x,'quotient);
  626. return multd(x,numr u) ./ multd(x,denr u)>>
  627. else errach list("field conversion",x);
  628. x := (car x) . (cddr x) . cadr x;
  629. return simpgd if domainp d then multd(x,n) ./ 1
  630. else multd(x,n) ./ multd(x,d)>>;
  631. return if domainp d then divd(n,d) ./ 1
  632. else divd(n,x) ./ divd(d,x)
  633. end;
  634. symbolic procedure simpgd u;
  635. if null flagp(dmode!*,'field) then u
  636. else begin scalar x;
  637. if (x := gcdf(numr u,denr u)) neq 1
  638. then u := quotf(numr u,x) ./ quotf(denr u,x);
  639. return u
  640. end;
  641. symbolic procedure lnc u;
  642. % U is a standard form. Value is the leading numerical coefficient.
  643. if null u then 0
  644. else if domainp u then u
  645. else lnc lc u;
  646. symbolic procedure invsq u;
  647. begin
  648. if null numr u then rerror(poly,3,"Zero divisor");
  649. u := revpr u;
  650. if !*rationalize then u := gcdchk u;
  651. % Since result may not be in lowest terms.
  652. return canonsq u
  653. end;
  654. symbolic procedure gcdchk u;
  655. % Makes sure standard quotient u is in lowest terms.
  656. (if x neq 1 then quotf(numr u,x) ./ quotf(denr u,x) else u)
  657. where x = gcdf(numr u,denr u);
  658. endmodule;
  659. end;