pfactor.red 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. module pfactor; % Factorization of polynomials modulo p.
  2. % Author: A. C. Norman, 1978.
  3. fluid '(!*balanced_mod
  4. !*gcd
  5. current!-modulus
  6. m!-image!-variable
  7. modular!-info
  8. modulus!/2
  9. user!-prime);
  10. global '(largest!-small!-modulus);
  11. symbolic procedure pfactor(q,p);
  12. % Q is a standard form. Factorize and return the factors mod p.
  13. begin scalar user!-prime,current!-modulus,modulus!/2,r,x;
  14. % set!-time();
  15. if not numberp p then typerr(p,"number")
  16. else if not primep p then typerr(p,"prime")
  17. else if p>largest!-small!-modulus
  18. then rederr {p,"too large a modulus for factorization"};
  19. user!-prime:=p;
  20. set!-modulus p;
  21. if domainp q or null reduce!-mod!-p lc q then
  22. prin2t "*** Degenerate case in modular factorization";
  23. if not (length variables!-in!-form q=1) then
  24. %% rerror(factor,1,"Multivariate input to modular factorization");
  25. return fctrfkronm q;
  26. r:=reduce!-mod!-p q;
  27. % lncoeff := lc r;
  28. x := lnc r;
  29. r :=monic!-mod!-p r;
  30. % print!-time "About to call FACTOR-FORM-MOD-P";
  31. r:=errorset!*(list('factor!-form!-mod!-p,mkquote r),t);
  32. % print!-time "FACTOR-FORM-MOD-P returned";
  33. if not errorp r
  34. then return x . for each j in car r
  35. collect mod!-adjust car j . cdr j;
  36. prin2t "****** FACTORIZATION FAILED******";
  37. return list(1,prepf q) % 1 needed by factorize.
  38. end;
  39. symbolic procedure mod!-adjust u;
  40. % Make sure any modular numbers in u are in the right range.
  41. if null !*balanced_mod then u else mod!-adjust1 u;
  42. symbolic procedure mod!-adjust1 u;
  43. if domainp u
  44. then if fixp u then !*modular2f u
  45. else if eqcar(u,'!:mod!:) then !*modular2f cdr u
  46. else typerr(u,"modular number")
  47. else lpow u .* mod!-adjust1 lc u .+ mod!-adjust1 red u;
  48. symbolic procedure factor!-form!-mod!-p p;
  49. % input:
  50. % p is a reduce standard form that is to be factorized
  51. % mod prime;
  52. % result:
  53. % ((p1 . x1) (p2 . x2) .. (pn . xn))
  54. % where p<i> are standard forms and x<i> are integers,
  55. % and p= product<i> p<i>**x<i>;
  56. sort!-factors factorize!-by!-square!-free!-mod!-p p;
  57. symbolic procedure factorize!-by!-square!-free!-mod!-p p;
  58. if p=1 then nil
  59. else if domainp p then (p . 1) . nil
  60. else
  61. begin
  62. scalar dp,v;
  63. v:=(mksp(mvar p,1).* 1) .+ nil;
  64. dp:=0;
  65. while evaluate!-mod!-p(p,mvar v,0)=0 do <<
  66. p:=quotfail!-mod!-p(p,v);
  67. dp:=dp+1 >>;
  68. if dp>0 then return ((v . dp) .
  69. factorize!-by!-square!-free!-mod!-p p);
  70. dp:=derivative!-mod!-p p;
  71. if dp=nil then <<
  72. %here p is a something to the power current!-modulus;
  73. p:=divide!-exponents!-by!-p(p,current!-modulus);
  74. p:=factorize!-by!-square!-free!-mod!-p p;
  75. return multiply!-multiplicities(p,current!-modulus) >>;
  76. dp:=gcd!-mod!-p(p,dp);
  77. if dp=1 then return factorize!-pp!-mod!-p p;
  78. %now p is not square-free;
  79. p:=quotfail!-mod!-p(p,dp);
  80. %factorize p and dp separately;
  81. p:=factorize!-pp!-mod!-p p;
  82. dp:=factorize!-by!-square!-free!-mod!-p dp;
  83. % i feel that this scheme is slightly clumsy, but
  84. % square-free decomposition mod p is not as straightforward
  85. % as square free decomposition over the integers, and pfactor
  86. % is probably not going to be slowed down too badly by
  87. % this;
  88. return mergefactors(p,dp)
  89. end;
  90. %**********************************************************************;
  91. % code to factorize primitive square-free polynomials mod p;
  92. symbolic procedure divide!-exponents!-by!-p(p,n);
  93. if domainp p then p
  94. else (mksp(mvar p,exactquotient(ldeg p,n)) .* lc p) .+
  95. divide!-exponents!-by!-p(red p,n);
  96. symbolic procedure exactquotient(a,b);
  97. begin
  98. scalar w;
  99. w:=divide(a,b);
  100. if cdr w=0 then return car w;
  101. error(50,list("Inexact division",list(a,b,w)))
  102. end;
  103. symbolic procedure multiply!-multiplicities(l,n);
  104. if null l then nil
  105. else (caar l . (n*cdar l)) .
  106. multiply!-multiplicities(cdr l,n);
  107. symbolic procedure mergefactors(a,b);
  108. % a and b are lists of factors (with multiplicities),
  109. % merge them so that no factor occurs more than once in
  110. % the result;
  111. if null a then b
  112. else mergefactors(cdr a,addfactor(car a,b));
  113. symbolic procedure addfactor(a,b);
  114. %add factor a into list b;
  115. if null b then list a
  116. else if car a=caar b then
  117. (car a . (cdr a + cdar b)) . cdr b
  118. else car b . addfactor(a,cdr b);
  119. symbolic procedure factorize!-pp!-mod!-p p;
  120. %input a primitive square-free polynomial p,
  121. % output a list of irreducible factors of p;
  122. begin
  123. scalar vars;
  124. if p=1 then return nil
  125. else if domainp p then return (p . 1) . nil;
  126. % now I am certain that p is not degenerate;
  127. % print!-time "primitive square-free case detected";
  128. vars:=variables!-in!-form p;
  129. if length vars=1 then return unifac!-mod!-p p;
  130. errorf "SHAMBLED IN PFACTOR - MULTIVARIATE CASE RESURFACED"
  131. end;
  132. symbolic procedure unifac!-mod!-p p;
  133. %input p a primitive square-free univariate polynomial
  134. %output a list of the factors of p over z mod p;
  135. begin
  136. scalar modular!-info,m!-image!-variable;
  137. if domainp p then return nil
  138. else if ldeg p=1 then return (p . 1) . nil;
  139. modular!-info:=mkvect 1;
  140. m!-image!-variable:=mvar p;
  141. get!-factor!-count!-mod!-p(1,p,user!-prime,nil);
  142. % print!-time "Factor counts obtained";
  143. get!-factors!-mod!-p(1,user!-prime);
  144. % print!-time "Actual factors extracted";
  145. return for each z in getv(modular!-info,1) collect (z . 1)
  146. end;
  147. endmodule;
  148. end;