polyexns.red 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. module polyexns;
  2. % Additional functions which manipulate polynomials.
  3. switch distribute;
  4. symbolic procedure fix_or_str u;
  5. fixp u or stringp u;
  6. symbolic procedure rgcdnl u;
  7. % Searches the common gcd of all the integers inside the list u.
  8. ( if length x = 1 then abs car x else
  9. eval expand(x,'gcdn) ) where x=cdr revlis car u;
  10. put('gcdnl,'psopfn,'rgcdnl);
  11. symbolic procedure alg_to_symb u;
  12. % transforms standard quotient expressions into prefix symbolic ones.
  13. % dd => (LIST 1 (!*SQ ((((A . 2) . 1)) . 1) T)
  14. % !*SQ ((((A . 1) . 1)) . 1) T) 3 (LIST 4))
  15. % alg_to_symb dd ==> (1 (EXPT A 2) A 3 (4))
  16. %
  17. if null u then nil else
  18. if atom u then u else
  19. if car u neq 'list then reval u else
  20. if car u eq 'list then
  21. for each i in cdr u collect alg_to_symb i;
  22. symbolic procedure symb_to_alg u;
  23. % transforms prefix lisp list into an algebraic list.
  24. % if null u then nil else
  25. if null u then list('list) else
  26. if fix_or_str u then u else
  27. if atom u then mk!*sq simp!* u else
  28. if listp u and (getd car u or get(car u,'simpfn) )
  29. then mk!*sq simp!* u else
  30. if atomlis u then 'list . for each i in u collect
  31. if null i then list('list) else
  32. if fix_or_str i then i else
  33. mk!*sq simp!* i
  34. else
  35. 'list . for each i in u collect symb_to_alg i ;
  36. algebraic procedure mkdepth_one x;
  37. % Flattens an algebraic list.
  38. % Not clear if it is really useful.
  39. lisp symb_to_alg flattens1 alg_to_symb algebraic x;
  40. % Elementary functions to manipulate polynomials in
  41. % a DISTRIBUTIVE way.
  42. symbolic procedure addfd (u,v);
  43. % It contains a modification to ADDF to avoid
  44. % a recursive representation.
  45. % U and V are standard forms. Value is a standard form.
  46. if null u then v
  47. else if null v then u
  48. else if domainp u then addd(u,v)
  49. else if domainp v then addd(v,u)
  50. else if ordp(lpow u,lpow v)
  51. then lt u .+ addfd(red u,v)
  52. else lt v .+ addfd (u,red v);
  53. symbolic procedure distribute u;
  54. % Works ONLY when RATIONAL is ON.
  55. begin scalar s, !*rational;
  56. !*rational:=t;
  57. s:=simp!* u;
  58. return mk!*sq (distri!_pol(numr s) ./ denr s)
  59. end;
  60. flag('(distribute),'opfn);
  61. symbolic procedure distri!_pol u;
  62. % This function assumes that u is a polynomial given
  63. % as a standard form. It transforms its recursive representation into
  64. % a distributive representation.
  65. if null u then nil else
  66. if atom u then u else
  67. if red u then
  68. addfd(distri!_pol !*t2f lt u,distri!_pol red u)
  69. else
  70. begin scalar x,y;
  71. x:=1 ;
  72. y:=u;
  73. while not atom y and null red y do
  74. <<x:=multf(x,!*p2f lpow y); y:=lc y>>;
  75. if atom y then return multf(x,y) else
  76. return
  77. addfd(distri!_pol multf(x,distri!_pol !*t2f lt y),
  78. distri!_pol multf(x,distri!_pol red y))
  79. end;
  80. symbolic procedure leadterm u;
  81. <<u:=simp!* u; if !*distribute then u:=distri!_pol numr u ./ denr u
  82. else u; if domainp u then mk!*sq u
  83. else mk!*sq(!*t2f lt numr u ./ denr u)>>;
  84. flag('(leadterm redexpr ),'opfn);
  85. symbolic procedure redexpr u;
  86. <<u:=simp!* u; if !*distribute then u:=distri!_pol numr u ./ denr u
  87. else u; if domainp u then mk!*sq(nil ./ 1) else
  88. mk!*sq( red numr u ./ denr u)>>;
  89. % Various decompositions.
  90. symbolic procedure list!_of!_monom u;
  91. % It takes a polynomial in distributive form.
  92. % returns a list of monoms.
  93. % u is numr simp!* (algebraic expression)
  94. % if domainp u then u else ELIMINATED
  95. begin scalar exp,lmon,mon;
  96. exp:=u;
  97. % l: if null exp then return lmon ; OLD statement
  98. l: if null exp then return lmon else
  99. if domainp exp then return exp . lmon ;
  100. mon:=if atom exp then exp else lt exp;
  101. lmon:=(!*t2f mon ) . lmon;
  102. exp:=red exp;
  103. go to l;
  104. end;
  105. symbolic procedure monom y;
  106. if !*rational then rederr "MONOM does only work on rings of integers"
  107. else
  108. begin scalar x;
  109. x:=numr simp!* y;
  110. x:=distri!_pol x;
  111. x:=reversip list!_of!_monom x;
  112. x:=for each m in x collect mk!*sq(m ./ 1);
  113. return 'list . x end;
  114. flag('(monom),'opfn);
  115. symbolic procedure coeff_mon u;
  116. % argument is lt numr simp!* "algebraic value".
  117. if atom u then u else
  118. coeff_mon((if atom x then x else lt x)where x=red u);
  119. algebraic procedure list_coeff_pol u;
  120. % Gives the list of coefficients of multivariate polynomial u.
  121. % Terms are distributed.
  122. for each i in monom u collect (lisp coeff_mon (if atom i then i else
  123. lt numr simp!* i));
  124. algebraic procedure norm_mon u;
  125. % Sets the coefficient of the monom u to 1.
  126. if u=0 then 0 else u/(lisp coeff_mon lt numr simp!* algebraic u);
  127. algebraic procedure norm_pol u;
  128. % Tries to put the leading coefficient to 1 i.e. u to normal form.
  129. % If not, it puts the coefficient of the leading term positive.
  130. if u=0 then 0 else
  131. begin scalar uu,sign;
  132. uu:=list_coeff_pol u;
  133. sign:=first uu /(abs first uu);
  134. if gcdnl uu = abs first uu then return u:= u/first uu
  135. else return sign * u
  136. end ;
  137. symbolic procedure pol_ordp(u,v);
  138. % u and v are multivariate polynomials.
  139. % General ordering function.
  140. (x<y or (x=y and ordp(u,v))) where x = length u, y = length v;
  141. flag('(pol_ordp),'opfn);
  142. symbolic procedure !&dpol u$
  143. % Returns a list which contains the quotient and
  144. % the remainder.
  145. if length u neq 2 then rederr "divpol must have two arguments"
  146. else
  147. begin scalar poln,pold,aa,ratsav$
  148. if lisp (!*factor) then off factor; % This restriction is
  149. % necessary for some implementatins .
  150. poln:= simp!* car u$
  151. pold:= simp!* cadr u$
  152. if denr poln neq 1 or denr pold neq 1 then
  153. rederr(" arguments must be polynomials")$
  154. poln:=numr poln$ pold:=numr pold$
  155. if lc poln neq 1 or lc poln neq lc pold then
  156. <<ratsav:=lisp (!*rational); on rational>>;
  157. aa:=qremf(poln,pold)$
  158. aa:=mksq(list('list ,prepsq!*( car aa . 1), prepsq!*(cdr aa . 1)),1)$
  159. if not ratsav then off rational;
  160. return aa end$
  161. put('divpol,'simpfn,'!&dpol)$
  162. symbolic procedure lowestdeg(u,v)$
  163. % It extracts the lowest degree in v of the polynomial u.
  164. begin scalar x,y,uu,vv;
  165. uu:=simp!* u$
  166. if domainp uu then return 0;
  167. uu:=!*q2f uu;
  168. vv:=erase_pol_cst uu;
  169. if vv neq uu then return 0;
  170. vv:=!*a2k v;
  171. x:=setkorder list v;
  172. y:=reorder uu; setkorder x;
  173. y:=reverse y;
  174. uu:=mvar y;
  175. if not atom uu then if car uu eq 'expt then
  176. rederr("exponents must be integers")$
  177. if uu neq vv then return 0 else
  178. return ldeg y
  179. end;
  180. flag('(lowestdeg),'opfn)$
  181. symbolic procedure erase_pol_cst u;
  182. % u is a standard form.
  183. if null u or numberp u then nil
  184. else lt u . erase_pol_cst red u;
  185. % Splitting functions.
  186. % For instance 'splitterms' returns a list of plus-terms and minus-terms.
  187. symbolic operator splitterms;
  188. symbolic procedure splitterms u;
  189. begin scalar a,b;
  190. if fixp u and evallessp(u, 0) then return
  191. 'list . ('list . 0 . nil) . ('list . list('minus, u)
  192. . nil) . nil
  193. else if
  194. atom u or not(car u member(list('plus,'minus))) then return
  195. 'list . ('list . u . nil) . ('list . 0 . nil) . nil
  196. else if
  197. car u eq 'minus then return
  198. 'list . ('list . 0 . nil) . ('list . cdr u) . nil;
  199. while(u:=cdr u) do
  200. if atom car u or not (caar u eq 'minus) then a:= car u . a
  201. else b:=cadar u . b;
  202. if null a then a:=0 . nil;
  203. if null b then b:=0 . nil;
  204. return 'list . ('list . reversip a) . ('list . reversip b) . nil;
  205. end;
  206. algebraic procedure splitplusminus(u);
  207. % Applies to rational functions.
  208. % u ==> {u+,u-}
  209. begin scalar uu;
  210. uu:=splitterms num u;
  211. return list((for each j in first uu sum j) /den u,
  212. - (for each j in second uu sum j)/den u)
  213. end;
  214. endmodule;
  215. end;