dipoly1.red 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. module dipoly1;% Distributive polynomial algorithms.
  2. % Authors: R. Gebauer, A. C. Hearn, H. Kredel.
  3. % Modification for REDUCE > 3.3: H. Melenk.
  4. % Modification of the function 'dipprodin' by Arthur Norman (august 2002,
  5. % REDUCE 3.7).
  6. fluid'(dipvars!* dipzero);
  7. symbolic procedure dipconst!? p;
  8. not dipzero!? p and dipzero!? dipmred p and evzero!? dipevlmon p;
  9. symbolic procedure terprit n;for i:=1:n do terpri();
  10. symbolic procedure dfcprint pl;
  11. % h polynomial factor list of distributive polynomials print.
  12. for each p in pl do dfcprintin p;
  13. symbolic procedure dfcprintin p;
  14. % factor with exponent print.
  15. (if cdr p neq 1 then <<prin2 "(";dipprint1(p1,nil);prin2 ")** ";
  16. prin2 cdr p;terprit 2>> else <<prin2 " ";dipprint p1>>)
  17. where p1:= dipmonic a2dip prepf car p;
  18. symbolic procedure dfcprin p;
  19. % print content,factors and exponents of factorized polynomial p.
  20. <<terpri();prin2 " content of factorized polynomials=";
  21. prin2 car p;
  22. terprit 2;dfcprint cdr p>>;
  23. symbolic procedure diplcm p;
  24. % Distributive polynomial least common multiple of denominators.
  25. % p is a distributive rational polynomial. diplcm(p) calculates
  26. % the least common multiple of the denominators and returns a
  27. % base coefficient of the form 1/lcm(denom bc1,.....,denom bci).
  28. if dipzero!? p then mkbc(1,1)
  29. else bclcmd(diplbc p,diplcm dipmred p);
  30. symbolic procedure diprectoint(p,u);
  31. % Distributive polynomial conversion rational to integral.
  32. % p is a distributive rational polynomial,u is a base coefficient
  33. %(1/lcm denom p). diprectoint(p,u) returns a primitive
  34. % associate pseudo integral(denominators are 1)distributive
  35. % polynomial.
  36. if bczero!? u then dipzero else if bcone!? u then p else diprectoint1(p,u);
  37. symbolic procedure diprectoint1(p,u);
  38. % Distributive polynomial conversion rational to integral internal 1.
  39. % diprectoint1 is used in diprectoint.
  40. if dipzero!? p then dipzero
  41. else dipmoncomp(bclcmdprod(u,diplbc p),dipevlmon p,
  42. diprectoint1(dipmred p,u));
  43. symbolic procedure dipbcprod(p,a);
  44. % Distributive polynomial base coefficient product.
  45. % p is a distributive polynomial,a is a base coefficient.
  46. % dipbcprod(p,a) computes p*a,a distributive polynomial.
  47. if bczero!? a then dipzero else if bcone!? a then p else dipbcprodin(p,a);
  48. symbolic procedure dipbcprodin(p,a);
  49. % Distributive polynomial base coefficient product internal.
  50. % p is a distributive polynomial,a is a base coefficient,
  51. % where a is not equal 0 and not equal 1.
  52. % dipbcprodin(p,a) computes p*a,a distributive polynomial.
  53. if dipzero!? p then dipzero
  54. else dipmoncomp(bcprod(a,diplbc p),
  55. dipevlmon p,
  56. dipbcprodin(dipmred p,a));
  57. symbolic procedure dipdif(p1,p2);
  58. % Distributive polynomial difference. p1 and p2 are distributive
  59. % polynomials. dipdif(p1,p2) calculates the difference of the
  60. % two distributive polynomials p1 and p2,a distributive polynomial
  61. if dipzero!? p1 then dipneg p2
  62. else if dipzero!? p2 then p1
  63. else(if sl=1 then dipmoncomp(diplbc p1,
  64. ep1,
  65. dipdif(dipmred p1,p2))
  66. else if sl=-1 then dipmoncomp(bcneg diplbc p2,
  67. ep2,
  68. dipdif(p1,dipmred p2))
  69. else(if bczero!? al
  70. then dipdif(dipmred p1,dipmred p2)
  71. else dipmoncomp(al,
  72. ep1,
  73. dipdif(dipmred p1,
  74. dipmred p2))
  75. )where al=bcdif(diplbc p1,diplbc p2)
  76. )where sl=evcomp(ep1,ep2)
  77. where ep1=dipevlmon p1,ep2=dipevlmon p2;
  78. symbolic procedure diplength p;
  79. % Distributive polynomial length. p is a distributive
  80. % polynomial. diplength(p) returns the number of terms
  81. % of the distributive polynomial p,a digit.
  82. if dipzero!? p then 0 else 1 + diplength dipmred p;
  83. symbolic procedure diplistsum pl;
  84. % Distributive polynomial list sum. pl is a list of distributive
  85. % polynomials. diplistsum(pl) calculates the sum of all polynomials
  86. % and returns a list of one distributive polynomial.
  87. if null pl or null cdr pl then pl
  88. else diplistsum(dipsum(car pl,cadr pl).diplistsum cddr pl);
  89. symbolic procedure diplmerge(pl1,pl2);
  90. % Distributive polynomial list merge. pl1 and pl2 are lists
  91. % of distributive polynomials where pl1 and pl2 are in non
  92. % decreasing order. diplmerge(pl1,pl2) returns the merged
  93. % distributive polynomial list of pl1 and pl2.
  94. if null pl1 then pl2
  95. else if null pl2 then pl1
  96. else(if sl >= 0 then cpl1.diplmerge(cdr pl1,pl2)
  97. else cpl2.diplmerge(cdr pl2,pl1)
  98. )where sl=evcomp(ep1,ep2)
  99. where ep1=dipevlmon cpl1,ep2=dipevlmon cpl2
  100. where cpl1=car pl1,cpl2=car pl2;
  101. symbolic procedure diplsort pl;
  102. % Distributive polynomial list sort. pl is a list of
  103. % distributive polynomials. diplsort(pl) returns the
  104. % sorted distributive polynomial list of pl.
  105. sort(pl,function dipevlcomp);
  106. symbolic procedure dipevlcomp(p1,p2);
  107. % Distributive polynomial exponent vector leading monomial
  108. % compare. p1 and p2 are distributive polynomials.
  109. % dipevlcomp(p1,p2) returns a boolean expression true if the
  110. % distributive polynomial p1 is smaller or equal the distributive
  111. % polynomial p2 else false.
  112. not evcompless!?(dipevlmon p1,dipevlmon p2);
  113. symbolic procedure dipmonic p;
  114. % Distributive polynomial monic. p is a distributive
  115. % polynomial. dipmonic(p) computes p/lbc(p) if p is
  116. % not equal dipzero and returns a distributive
  117. % polynomial,else dipmonic(p) returns dipzero.
  118. if dipzero!? p then p else dipbcprod(p,bcinv diplbc p);
  119. symbolic procedure dipneg p;
  120. % Distributive polynomial negative. p is a distributive
  121. % polynomial. dipneg(p) returns the negative of the distributive
  122. % polynomial p,a distributive polynomial.
  123. if dipzero!? p then p
  124. else dipmoncomp(bcneg diplbc p,dipevlmon p,dipneg dipmred p);
  125. symbolic procedure dipone!? p;
  126. % Distributive polynomial one. p is a distributive polynomial.
  127. % dipone!?(p) returns a boolean value. If p is the distributive
  128. % polynomial one then true else false.
  129. not dipzero!? p
  130. and dipzero!? dipmred p
  131. and evzero!? dipevlmon p
  132. and bcone!? diplbc p;
  133. symbolic procedure dippairsort pl;
  134. % Distributive polynomial list pair merge sort. pl is a list
  135. % of distributive polynomials. dippairsort(pl) returns the
  136. % list of merged and in non decreasing order sorted
  137. % distributive polynomials.
  138. if null pl or null cdr pl then pl
  139. else diplmerge(diplmerge(car pl.nil,cadr pl.nil),
  140. dippairsort cddr pl);
  141. symbolic procedure dipprod(p1,p2);
  142. % Distributive polynomial product. p1 and p2 are distributive
  143. % polynomials. dipprod(p1,p2) calculates the product of the
  144. % two distributive polynomials p1 and p2,a distributive polynomial
  145. if diplength p1 <= diplength p2 then dipprodin(p1,p2) else dipprodin(p2,p1);
  146. % The following function was observed recursing very deeply indeed when
  147. % certain examples were attempted. Automatic recursion to iteration
  148. % conversion in the compiler was not applicable in this case, so a hand
  149. % adjustment follows.
  150. % symbolic procedure dipprodin(p1,p2);
  151. % Distributive polynomial product internal. p1 and p2 are distrib
  152. % polynomials. dipprodin(p1,p2) calculates the product of the
  153. % two distributive polynomials p1 and p2,a distributive polynomial.
  154. % if dipzero!? p1 or dipzero!? p2 then dipzero
  155. % else(dipmoncomp(bcprod(bp1,diplbc p2),
  156. % evsum(ep1,dipevlmon p2),
  157. % dipsum(dipprodin(dipfmon(bp1,ep1),dipmred p2),
  158. % dipprodin(dipmred p1,p2))))
  159. % where bp1=diplbc p1,ep1=dipevlmon p1;
  160. % This next definition is one that recursion elimination can handle.
  161. % As compared to the original code it introduces a slight time
  162. % inefficiency. The original version exploited the fact that the leading
  163. % monomial in the result was the product of the two input leading
  164. % monomials. In this version dipsum will have to do an exponent
  165. % comparison to re-discover this. But the assymptotic overhead grows
  166. % linearly while the overall cost here grows quadratically (or worse) if
  167. % the two input polys are around the same length, so the cost is ok.
  168. symbolic procedure dipprodin(p1, p2);
  169. % Distributive polynomial product internal. p1 and p2 are distrib
  170. % polynomials. dipprodin(p1,p2) calculates the product of the
  171. % two distributive polynomials p1 and p2,a distributive polynomial.
  172. if dipzero!? p1 or dipzero!? p2 then dipzero
  173. else dipsum(dipprodin1(diplbc p1,dipevlmon p1,p2),
  174. dipprodin(dipmred p1,p2));
  175. symbolic procedure dipprodin1(p1lbc,p1lmon,p2);
  176. if dipzero!? p2 then dipzero
  177. else dipmoncomp(bcprod(p1lbc,diplbc p2),
  178. evsum(p1lmon,dipevlmon p2),
  179. dipprodin1(p1lbc,p1lmon,dipmred p2));
  180. symbolic procedure dipprodls(p1,p2);
  181. % Distributive polynomial product. p1 and p2 are distributive
  182. % polynomials. dipprod(p1,p2) calculates the product of the
  183. % two distributive polynomials p1 and p2,a distributive polynomial
  184. % using distributive polynomials list sum(diplistsum).
  185. if dipzero!? p1 or dipzero!? p2 then dipzero
  186. else car diplistsum if diplength p1 <= diplength p2
  187. then dipprodlsin(p1,p2)
  188. else dipprodlsin(p2,p1);
  189. symbolic procedure dipprodlsin(p1,p2);
  190. % Distributive polynomial product. p1 and p2 are distributive
  191. % polynomials. dipprod(p1,p2) calculates the product of the
  192. % two distributive polynomials p1 and p2,a distributive polynomial
  193. % using distributive polynomials list sum(diplistsum).
  194. if dipzero!? p1 or dipzero!? p2 then nil
  195. else(dipmoncomp(bcprod(bp1,diplbc p2),evsum(ep1,dipevlmon p2),
  196. car dipprodlsin(dipfmon(bp1,ep1),dipmred p2))
  197. .dipprodlsin(dipmred p1,p2)
  198. )where bp1=diplbc p1,ep1=dipevlmon p1;
  199. symbolic procedure dipsum(p1,p2);
  200. % Distributive polynomial sum. p1 and p2 are distributive
  201. % polynomials. dipsum(p1,p2)calculates the sum of the
  202. % two distributive polynomials p1 and p2.
  203. % Iterative version,better suited for very long polynomials.
  204. if null p1 then p2 else if null p2 then p1 else
  205. begin scalar al,done,ep1,ep2,nt,rw,sl,w;
  206. while not done do
  207. <<if dipzero!? p1 then <<nt:=p2;done:=t>> else
  208. if dipzero!? p2 then <<nt:=p1;done:=t>> else
  209. <<ep1:=dipevlmon p1;ep2:=dipevlmon p2;
  210. sl:=evcomp(ep1,ep2);
  211. % Compute the next term.
  212. if sl #= 1 then
  213. <<nt:=dipmoncomp(diplbc p1,ep1,nil);
  214. p1:=dipmred p1>> else
  215. if sl #= -1 then
  216. <<nt:=dipmoncomp(diplbc p2,ep2,nil);
  217. p2:=dipmred p2>> else
  218. <<al:=bcsum(diplbc p1,diplbc p2);
  219. nt:=if not bczero!? al then dipmoncomp(al,ep1,nil)else nil;
  220. p1:=dipmred p1;p2:=dipmred p2>>>>;
  221. % Append the term to the sum polynomial.
  222. if nt then
  223. if null w then w:=rw:=nt
  224. else <<cdr cdr rw:=nt;rw:=nt>>;
  225. >>;return w end;
  226. endmodule;;end;