afactor.red 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. module afactor;
  2. % Author: James H. Davenport.
  3. fluid '(!*galois !*noextend !*sqfree !*trfield afactorvar listofnewsqrts
  4. monicpart varlist zlist sqrtlist sqrtflag indexlist);
  5. switch trfield; % traces the algebraic number field manipluation
  6. exports afactor, jfactor;
  7. imports exptf,ordop,!*multf,addf,makemainvar,algebraicsf,divsf,contents;
  8. imports quotf!*,negf,sqfr!-norm2,prepf,algint!-subf,!*q2f;
  9. imports printsf;
  10. % internal!-fluid '(monicpart);
  11. % This routine, and its subsidiaries, do factorization over algebraic
  12. % extensions, by the Trager modification of van der Waerden's algorithm
  13. % See SYMSAC '76.
  14. symbolic procedure afactor(u,v);
  15. % Factorises U over the algebraics as a polynomial in V (=afactorvar).
  16. begin
  17. scalar afactorvar,!*noextend,!*sqfree;
  18. % !*sqfree is known to be square free (from sqfr-norm).
  19. !*noextend:=t; % else we get recursion.
  20. afactorvar:=v;
  21. if !*trfield
  22. then <<
  23. princ "We must factorise the following over: ";
  24. for each u in listofnewsqrts do <<princ u; princ " " >>;
  25. terpri();
  26. printsf u >>;
  27. v:=algfactor u;
  28. if !*trfield then <<
  29. printc "factorizes as ";
  30. mapc(v,function printsf) >>;
  31. return v
  32. end;
  33. symbolic procedure algfactor2(f,a);
  34. if null a
  35. then for each u in cdr factorf f collect %car factorf is a constant
  36. if cdr u = 1
  37. then car u
  38. else interr "repeated factors found while processing algebraics"
  39. else if algebraicsf f
  40. then algfactor3(f,a)
  41. else begin
  42. scalar w;
  43. if !*trfield then <<
  44. princ "to be factorized over ";
  45. for each u in a do << princ u; princ " " >>;
  46. terpri();
  47. printsf f >>;
  48. if (!*galois neq 2) and
  49. (numberp red f) and
  50. (not numberp argof car a)
  51. then return algfactor2(f,cdr a);
  52. % assumes we need never express a root of a number in terms of
  53. % non-numbers.
  54. w:=algfactor2(f,nil);
  55. if w and null cdr w then return algfactor3(f,a)
  56. else return 'partial . w
  57. end;
  58. symbolic procedure algfactor3(f,a);
  59. begin
  60. scalar ff,w,gg,h,p;
  61. w:=sqfr!-norm2(f,mvar f,car a);
  62. !*sqfree:=car w;
  63. w:=cdr w;
  64. ff:=algfactor2(!*sqfree,cdr a);
  65. if null ff then return list f % does not factor.
  66. else if car ff eq 'partial then <<p := 'partial; ff := cdr ff>>;
  67. if null cdr ff then return list f; % does not factor.
  68. a:=car a;
  69. gg:=cadr w;
  70. w:=list list(afactorvar,'plus,afactorvar,prepf car w);
  71. h:=for each u in ff
  72. collect (!*q2f algint!-subf(gcdinonevar(u,gg,afactorvar),w));
  73. if p eq 'partial then h := p.h;
  74. return h
  75. end;
  76. symbolic procedure algfactor u;
  77. begin
  78. scalar a,aa,z,w,monicpart;
  79. z:= makemainvar(u,afactorvar);
  80. if ldeg z iequal 1
  81. then return list u;
  82. z:=lc z;
  83. if z iequal 1
  84. then go to monic;
  85. if algebraicsf z
  86. then u:=!*multf(u,numr divsf(1,z));
  87. % this de-algebraicises the top coefficient.
  88. u:=quotf!*(u,contents(u,afactorvar));
  89. z:=makemainvar(u,afactorvar);
  90. if lc z neq 1
  91. then if lc z iequal -1
  92. then u:=negf u
  93. else <<
  94. w:=lc z;
  95. u:=makemonic z >>;
  96. monic:
  97. aa:=listofnewsqrts;
  98. if algebraicsf u
  99. then go to normal;
  100. a:=cdr aa;
  101. % we need not try for the first one, since algfactor2
  102. % will do this for us.
  103. z:=t;
  104. while a and z do begin
  105. scalar alg,v;
  106. alg:=car a;
  107. a:=cdr a;
  108. v:=algfactor3(u,list alg);
  109. if null cdr v
  110. then return;
  111. if car v eq 'partial
  112. then v:=cdr v;
  113. % we do not mind if the factorization is only partial.
  114. a:=mapcan(v,function algfactor);
  115. z:=nil
  116. end;
  117. monicpart:=w;
  118. if null z
  119. then if null w
  120. then return a
  121. else return for each j in a collect demonise j;
  122. normal:
  123. z:=algfactor2(u,aa);
  124. monicpart:=w;
  125. if null cdr z or (car z neq 'partial)
  126. then if null w
  127. then return z
  128. else return for each j in z collect demonise j;
  129. % does not factor.
  130. if null w
  131. then return mapcan(cdr z,function algfactor)
  132. else return for each u in z conc
  133. algfactor demonise u;
  134. end;
  135. symbolic procedure demonise u;
  136. % Replaces afactorvar by afactorvar*monicpart in u.
  137. if atom u
  138. then u
  139. else if afactorvar eq mvar u
  140. then addf(demonise red u,
  141. !*multf(lt u .+ nil,exptf(monicpart,ldeg u)))
  142. else if ordop(afactorvar,mvar u)
  143. then u
  144. else addf(demonise red u,
  145. !*multf(!*p2f lpow u,demonise lc u));
  146. symbolic procedure gcdinonevar(u,v,x);
  147. % Gcd of u and v, regarded as polynomials in x.
  148. if null u
  149. then v
  150. else if null v
  151. then u
  152. else begin
  153. scalar u1,v1,z,w;
  154. u1:=stt(u,x);
  155. v1:=stt(v,x);
  156. loop:
  157. if (car u1) > (car v1)
  158. then go to ok;
  159. z:=u1;u1:=v1;v1:=z;
  160. z:=u;u:=v;v:=z;
  161. ok:
  162. if car v1 iequal 0
  163. then interr "Coprimeness in gcd";
  164. z:=gcdf(cdr u1,cdr v1);
  165. w:=quotf(cdr u1,z);
  166. if (car u1) neq (car v1)
  167. then w:=!*multf(w,!*p2f mksp(x,(car u1)-(car v1)));
  168. u:=addf(!*multf(v,w),
  169. !*multf(u,negf quotf(cdr v1,z)));
  170. if null u
  171. then return v;
  172. u1:=stt(u,x);
  173. go to loop
  174. end;
  175. symbolic procedure makemonic u;
  176. % U is a makemainvar'd polynomial.
  177. begin
  178. scalar v,w,x,xx;
  179. v:=mvar u;
  180. x:=lc u;
  181. xx:=1;
  182. w:=!*p2f lpow u;% the monic term.
  183. u:=red u;
  184. for i:=(isub1 ldeg w) step -1 until 1 do begin
  185. if atom u
  186. then go to next;
  187. if mvar u neq v
  188. then go to next;
  189. if ldeg u iequal i
  190. then w:=addf(w,!*multf(lc u,
  191. !*multf(!*p2f lpow u,xx)));
  192. u:=red u;
  193. next:
  194. xx:=!*multf(x,xx)
  195. end;
  196. w:=addf(w,!*multf(u,xx));
  197. return w
  198. end;
  199. symbolic procedure jfactor(sf,var);
  200. % Algebraic integrator's sole interface to factorization.
  201. % except for a direct call to the true factoriser from
  202. % inside afactor
  203. begin
  204. scalar varlist,zlist,indexlist,sqrtlist,sqrtflag;
  205. scalar prim,res,answer,u,v,x,y; % scalar var2
  206. prim:=jsqfree(sf,var);
  207. indexlist:=createindices zlist;
  208. while not null prim do <<
  209. x:=car prim;
  210. while not null x do <<
  211. y:=facbypp(car x,varlist);
  212. while not null y do <<
  213. res:=append(int!-fac car y,res);
  214. y:=cdr y >>;
  215. x:=cdr x >>;
  216. prim:=cdr prim >>;
  217. while res do <<
  218. if caar res eq 'log then <<
  219. u:=cdar res;
  220. u:=!*multsq(numr u ./ 1,1 ./ cdr stt(numr u,var));
  221. v:=denr u;
  222. while not atom v do v:=lc v;
  223. if (numberp v) and (0> v)
  224. then u:=(negf numr u) ./ (negf denr u);
  225. if u neq '(1 . 1) then answer := u . answer>>
  226. else if caar res eq 'atan then nil
  227. % We can ignore this, since we also get LOG (U**2+1) as another
  228. % term.
  229. else interr "Unexpected term in jfactor";
  230. res:=cdr res >>;
  231. return answer
  232. end;
  233. % unfluid '(monicpart);
  234. endmodule;
  235. end;