dipoly1.red 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. module dipoly1; % Distributive polynomial algorithms.
  2. % Authors: R. Gebauer, A. C. Hearn, H. Kredel.
  3. % Modification for REDUCE > 3.3: H. Melenk.
  4. fluid '(dipvars!* dipzero);
  5. symbolic procedure dipconst!? p;
  6. not dipzero!? p
  7. and dipzero!? dipmred p
  8. and evzero!? dipevlmon p;
  9. symbolic procedure terprit n;
  10. for i:=1:n do terpri();
  11. symbolic procedure dfcprint pl;
  12. % h polynomial factor list of distributive polynomials print.
  13. for each p in pl do dfcprintin p;
  14. symbolic procedure dfcprintin p;
  15. % factor with exponent print.
  16. ( if cdr p neq 1 then << prin2 " ( "; dipprint1(p1,nil); prin2 " )** ";
  17. prin2 cdr p; terprit 2 >> else << prin2 " "; dipprint p1>> )
  18. where p1:= dipmonic a2dip prepf car p;
  19. symbolic procedure dfcprin p;
  20. % print content, factors and exponents of factorized polynomial p.
  21. << terpri(); prin2 " content of factorized polynomials = ";
  22. prin2 car p;
  23. terprit 2; dfcprint cdr p >>;
  24. symbolic procedure diplcm p;
  25. % Distributive polynomial least common multiple of denominators.
  26. % p is a distributive rational polynomial. diplcm(p) calculates
  27. % the least common multiple of the denominators and returns a
  28. % base coefficient of the form 1/lcm(denom bc1,.....,denom bci).
  29. if dipzero!? p then mkbc(1,1)
  30. else bclcmd(diplbc p, diplcm dipmred p);
  31. symbolic procedure diprectoint(p,u);
  32. % Distributive polynomial conversion rational to integral.
  33. % p is a distributive rational polynomial, u is a base coefficient
  34. % ( 1/lcm denom p ). diprectoint(p,u) returns a primitive
  35. % associate pseudo integral ( denominators are 1 ) distributive
  36. % polynomial.
  37. if bczero!? u then dipzero
  38. else if bcone!? u then p
  39. else diprectoint1(p,u);
  40. symbolic procedure diprectoint1(p,u);
  41. % Distributive polynomial conversion rational to integral internal 1.
  42. % diprectoint1 is used in diprectoint.
  43. if dipzero!? p then dipzero
  44. else dipmoncomp(bclcmdprod(u,diplbc p),dipevlmon p,
  45. diprectoint1(dipmred p,u));
  46. symbolic procedure dipresul(p1,p2);
  47. % test for fast downwards calculation
  48. % p1 and p2 are two bivariate distributive polynomials.
  49. % dipresul(p1,p2) returns the resultant of p1 and p2 with respect
  50. % respect to the first variable of the variable list (car dipvars!*).
  51. begin scalar q1,q2,q,ct;
  52. q1:=dip2a diprectoint(p1,diplcm p1);
  53. q2:=dip2a diprectoint(p2,diplcm p2);
  54. ct := time();
  55. q:= a2dip prepsq simpresultant list(q1,q2,car dipvars!*);
  56. ct := time() - ct;
  57. prin2 " resultant : "; dipprint dipmonic q; terpri();
  58. prin2 " time resultant : "; prin2 ct; terpri();
  59. end;
  60. symbolic procedure dipbcprod (p,a);
  61. % /* Distributive polynomial base coefficient product.
  62. % p is a distributive polynomial, a is a base coefficient.
  63. % dipbcprod(p,a) computes p*a, a distributive polynomial. */
  64. if bczero!? a then dipzero
  65. else if bcone!? a then p
  66. else dipbcprodin(p,a);
  67. symbolic procedure dipbcprodin (p,a);
  68. % /* Distributive polynomial base coefficient product internal.
  69. % p is a distributive polynomial, a is a base coefficient,
  70. % where a is not equal 0 and not equal 1.
  71. % dipbcprodin(p,a) computes p*a, a distributive polynomial. */
  72. if dipzero!? p then dipzero
  73. else dipmoncomp(bcprod(a, diplbc p),
  74. dipevlmon p,
  75. dipbcprodin(dipmred p, a));
  76. symbolic procedure dipdif (p1,p2);
  77. % /* Distributive polynomial difference. p1 and p2 are distributive
  78. % polynomials. dipdif(p1,p2) calculates the difference of the
  79. % two distributive polynomials p1 and p2, a distributive polynomial*/
  80. if dipzero!? p1 then dipneg p2
  81. else if dipzero!? p2 then p1
  82. else ( if sl = 1 then dipmoncomp(diplbc p1,
  83. ep1,
  84. dipdif(dipmred p1, p2) )
  85. else if sl = -1 then dipmoncomp(bcneg diplbc p2,
  86. ep2,
  87. dipdif(p1,dipmred p2))
  88. else ( if bczero!? al
  89. then dipdif(dipmred p1, dipmred p2)
  90. else dipmoncomp(al,
  91. ep1,
  92. dipdif(dipmred p1,
  93. dipmred p2) )
  94. ) where al = bcdif(diplbc p1, diplbc p2)
  95. ) where sl = evcomp(ep1, ep2)
  96. where ep1 = dipevlmon p1, ep2 = dipevlmon p2;
  97. symbolic procedure diplength p;
  98. % /* Distributive polynomial length. p is a distributive
  99. % polynomial. diplength(p) returns the number of terms
  100. % of the distributive polynomial p, a digit.*/
  101. if dipzero!? p then 0 else 1 + diplength dipmred p;
  102. symbolic procedure diplistsum pl;
  103. % /* Distributive polynomial list sum. pl is a list of distributive
  104. % polynomials. diplistsum(pl) calculates the sum of all polynomials
  105. % and returns a list of one distributive polynomial. */
  106. if null pl or null cdr pl then pl
  107. else diplistsum(dipsum(car pl, cadr pl) . diplistsum cddr pl);
  108. symbolic procedure diplmerge (pl1,pl2);
  109. % /* Distributive polynomial list merge. pl1 and pl2 are lists
  110. % of distributive polynomials where pl1 and pl2 are in non
  111. % decreasing order. diplmerge(pl1,pl2) returns the merged
  112. % distributive polynomial list of pl1 and pl2. */
  113. if null pl1 then pl2
  114. else if null pl2 then pl1
  115. else ( if sl >= 0 then cpl1 . diplmerge(cdr pl1, pl2)
  116. else cpl2 . diplmerge(cdr pl2, pl1)
  117. ) where sl = evcomp(ep1, ep2)
  118. where ep1 = dipevlmon cpl1, ep2 = dipevlmon cpl2
  119. where cpl1 = car pl1, cpl2 = car pl2;
  120. symbolic procedure diplsort pl;
  121. % /* Distributive polynomial list sort. pl is a list of
  122. % distributive polynomials. diplsort(pl) returns the
  123. % sorted distributive polynomial list of pl.
  124. sort(pl, function dipevlcomp);
  125. symbolic procedure dipevlcomp (p1,p2);
  126. % /* Distributive polynomial exponent vector leading monomial
  127. % compare. p1 and p2 are distributive polynomials.
  128. % dipevlcomp(p1,p2) returns a boolean expression true if the
  129. % distributive polynomial p1 is smaller or equal the distributive
  130. % polynomial p2 else false. */
  131. not evcompless!?(dipevlmon p1, dipevlmon p2);
  132. symbolic procedure dipmonic p;
  133. % /* Distributive polynomial monic. p is a distributive
  134. % polynomial. dipmonic(p) computes p/lbc(p) if p is
  135. % not equal dipzero and returns a distributive
  136. % polynomial, else dipmonic(p) returns dipzero. */
  137. if dipzero!? p then p
  138. else dipbcprod(p, bcinv diplbc p);
  139. symbolic procedure dipneg p;
  140. % /* Distributive polynomial negative. p is a distributive
  141. % polynomial. dipneg(p) returns the negative of the distributive
  142. % polynomial p, a distributive polynomial. */
  143. if dipzero!? p then p
  144. else dipmoncomp ( bcneg diplbc p,
  145. dipevlmon p,
  146. dipneg dipmred p );
  147. symbolic procedure dipone!? p;
  148. % /* Distributive polynomial one. p is a distributive polynomial.
  149. % dipone!?(p) returns a boolean value. If p is the distributive
  150. % polynomial one then true else false. */
  151. not dipzero!? p
  152. and dipzero!? dipmred p
  153. and evzero!? dipevlmon p
  154. and bcone!? diplbc p;
  155. symbolic procedure dippairsort pl;
  156. % /* Distributive polynomial list pair merge sort. pl is a list
  157. % of distributive polynomials. dippairsort(pl) returns the
  158. % list of merged and in non decreasing order sorted
  159. % distributive polynomials. */
  160. if null pl or null cdr pl then pl
  161. else diplmerge(diplmerge( car(pl) . nil, cadr(pl) . nil ),
  162. dippairsort cddr pl);
  163. symbolic procedure dipprod (p1,p2);
  164. % /* Distributive polynomial product. p1 and p2 are distributive
  165. % polynomials. dipprod(p1,p2) calculates the product of the
  166. % two distributive polynomials p1 and p2, a distributive polynomial*/
  167. if diplength p1 <= diplength p2 then dipprodin(p1, p2)
  168. else dipprodin(p2, p1);
  169. symbolic procedure dipprodin (p1,p2);
  170. % /* Distributive polynomial product internal. p1 and p2 are distrib
  171. % polynomials. dipprod(p1,p2) calculates the product of the
  172. % two distributive polynomials p1 and p2, a distributive polynomial*/
  173. if dipzero!? p1 or dipzero!? p2 then dipzero
  174. else ( dipmoncomp(bcprod(bp1, diplbc p2),
  175. evsum(ep1, dipevlmon p2),
  176. dipsum(dipprodin(dipfmon(bp1, ep1),
  177. dipmred p2),
  178. dipprodin(dipmred p1, p2) ) )
  179. ) where bp1 = diplbc p1,
  180. ep1 = dipevlmon p1;
  181. symbolic procedure dipprodls (p1,p2);
  182. % /* Distributive polynomial product. p1 and p2 are distributive
  183. % polynomials. dipprod(p1,p2) calculates the product of the
  184. % two distributive polynomials p1 and p2, a distributive polynomial
  185. % using distributive polynomials list sum (diplistsum). */
  186. if dipzero!? p1 or dipzero!? p2 then dipzero
  187. else car diplistsum if diplength p1 <= diplength p2
  188. then dipprodlsin(p1, p2)
  189. else dipprodlsin(p2, p1);
  190. symbolic procedure dipprodlsin (p1,p2);
  191. % /* Distributive polynomial product. p1 and p2 are distributive
  192. % polynomials. dipprod(p1,p2) calculates the product of the
  193. % two distributive polynomials p1 and p2, a distributive polynomial
  194. % using distributive polynomials list sum (diplistsum). */
  195. if dipzero!? p1 or dipzero!? p2 then nil
  196. else ( dipmoncomp(bcprod(bp1, diplbc p2),
  197. evsum(ep1, dipevlmon p2),
  198. car dipprodlsin(dipfmon(bp1, ep1),
  199. dipmred p2))
  200. . dipprodlsin(dipmred p1, p2)
  201. ) where bp1 = diplbc p1,
  202. ep1 = dipevlmon p1;
  203. %symbolic procedure dipsum (p1,p2);
  204. % /* Distributive polynomial sum. p1 and p2 are distributive
  205. % polynomials. dipsum(p1,p2) calculates the sum of the
  206. % two distributive polynomials p1 and p2, a distributive polynomial*/
  207. %
  208. % if dipzero!? p1 then p2
  209. % else if dipzero!? p2 then p1
  210. % else ( if sl = 1 then dipmoncomp(diplbc p1,
  211. % ep1,
  212. % dipsum(dipmred p1, p2) )
  213. % else if sl = -1 then dipmoncomp(diplbc p2,
  214. % ep2,
  215. % dipsum(p1,dipmred p2))
  216. % else ( if bczero!? al then dipsum(dipmred p1,
  217. % dipmred p2)
  218. % else dipmoncomp(al,
  219. % ep1,
  220. % dipsum(dipmred p1,
  221. % dipmred p2) )
  222. % ) where al = bcsum(diplbc p1, diplbc p2)
  223. % ) where sl = evcomp(ep1, ep2)
  224. % where ep1 = dipevlmon p1, ep2 = dipevlmon p2;
  225. symbolic procedure dipsum (p1,p2);
  226. % Distributive polynomial sum. p1 and p2 are distributive
  227. % polynomials. dipsum(p1,p2) calculates the sum of the
  228. % two distributive polynomials p1 and p2.
  229. % Iterative version, better suited for very long polynomials.
  230. % Warning: this routine uses "dipmred" == "cdr cdr" for a
  231. % destructive concatenation.
  232. begin scalar w,rw,sl,ep1,ep2,nt,al,done;
  233. while not done do
  234. <<if dipzero!? p1 then <<nt:=p2; done:=t>>
  235. else
  236. if dipzero!? p2 then <<nt:=p1; done:=t>>
  237. else
  238. <<ep1 := dipevlmon p1;
  239. ep2 := dipevlmon p2;
  240. sl := evcomp(ep1, ep2);
  241. % Compute the next term.
  242. if sl #= 1 then
  243. <<nt := dipmoncomp(diplbc p1, ep1, nil);
  244. p1 := dipmred p1>>
  245. else
  246. if sl #= -1 then
  247. <<nt := dipmoncomp(diplbc p2, ep2, nil);
  248. p2 := dipmred p2>>
  249. else
  250. <<al := bcsum(diplbc p1, diplbc p2);
  251. nt := if not bczero!? al then dipmoncomp(al,ep1,nil);
  252. p1 := dipmred p1; p2 := dipmred p2>>;
  253. >>;
  254. % Append the term to the sum polynomial.
  255. if nt then
  256. if null w then w:=rw:=nt
  257. else <<cdr cdr rw := nt; rw := nt>>;
  258. >>;
  259. return w;
  260. end;
  261. endmodule;
  262. end;