kronf.red 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. module kronf; % Kronecker factorization of univariate forms.
  2. % Author: Anthony C. Hearn.
  3. % Based on code first written by Mary Ann Moore and Arthur C. Norman.
  4. % Copyright (c) 1987 The RAND Corporation. All rights reserved.
  5. % exports linfacf,quadfacf;
  6. % imports zfactor;
  7. % Note that only linear and quadratic factors are found here.
  8. symbolic procedure linfacf u; trykrf(u,'(0 1));
  9. symbolic procedure quadfacf u; trykrf(u,'(-1 0 1));
  10. symbolic procedure trykrf(u,points);
  11. % Look for factor of u by evaluation at points and interpolation.
  12. % Return (fac . cofac), with fac = nil if none found,
  13. % and cofac = nil if nothing worthwhile is left.
  14. begin scalar attempt,mv,values;
  15. if null u then return nil . nil
  16. else if length points > ldeg u then return nil . u;
  17. % Degree is too small to find factors.
  18. mv := mvar u;
  19. values := for each j in points collect subuf(j,u);
  20. if 0 member values
  21. then <<attempt := ((mv .** 1) .* 1) . -1; % mv - 1
  22. return attempt . quotf(u,attempt)>>;
  23. values := for each j in values collect dfactors j;
  24. values := for each j in values
  25. collect append(j,for each k in j collect !:minus k);
  26. attempt := search4facf(u,values,nil);
  27. if null attempt then attempt := nil . u;
  28. return attempt
  29. end;
  30. symbolic procedure subuf(u,v);
  31. % Substitute integer u for main variable in univariate polynomial v.
  32. % Return an integer or a structured domain element.
  33. begin scalar z;
  34. if u=0 then u := nil;
  35. z := nil;
  36. while v do
  37. if domainp v then <<z := adddm!*(v,z); v := nil>>
  38. else <<if u then z := adddm!*(multdm!*(u**ldeg v,lc v),z);
  39. % we should do better here.
  40. v := red v>>;
  41. return if null z then 0 else z
  42. end;
  43. symbolic procedure adddm!*(u,v);
  44. % Adds two domain elements u and v, returning a standard form.
  45. if null u then v else if null v then u else adddm(u,v);
  46. symbolic procedure multdm!*(u,v);
  47. % Multiplies two domain elements u and v, returning a standard form.
  48. if null u or null v then nil else multdm(u,v);
  49. symbolic procedure dfactors n;
  50. % Produces a list of all (positive) factors of the domain element n.
  51. begin scalar x;
  52. if n=0 then return list 0
  53. else if n=1 then return list 1
  54. else if !:minusp n then n := !:minus n;
  55. return if not atom n
  56. then if (x := get(car n,'factorfn))
  57. then combinationtimes apply1(x,n)
  58. else list n
  59. else combinationtimes zfactor n
  60. end;
  61. symbolic procedure combinationtimes fl;
  62. if null fl then list 1
  63. else begin scalar n,c,res,pr;
  64. n := caar fl;
  65. c := cdar fl;
  66. pr := combinationtimes cdr fl;
  67. while c>=0 do <<res := putin(expt(n,c),pr,res); c := c-1>>;
  68. return res
  69. end;
  70. symbolic procedure putin(n,l,w);
  71. if null l then w else putin(n,cdr l,(n*car l) . w);
  72. symbolic procedure search4facf(u,values,cv);
  73. % combinatorial search for factors. cv gets current value set.
  74. if null values then tryfactorf(u,cv)
  75. else begin scalar q,w;
  76. w := car values;
  77. loop: if null w then return nil; % no factor found
  78. q := search4facf(u,cdr values,car w . cv);
  79. if null q then <<w := cdr w; go to loop>>;
  80. return q
  81. end;
  82. symbolic procedure tryfactorf(u,cv);
  83. % Tests if cv represents a factor of u.
  84. % For the time being, does not work on structured domain elements.
  85. begin scalar w;
  86. if null atomlis cv then return nil;
  87. if null cddr cv then w := linethroughf(cadr cv,car cv,mvar u)
  88. else w := quadthroughf(caddr cv,cadr cv,car cv,mvar u);
  89. if w eq 'failed or null (u := quotf(u,w)) then return nil
  90. else return w . u
  91. end;
  92. symbolic procedure linethroughf(y0,y1,mv);
  93. begin scalar x;
  94. x := y1-y0;
  95. if x=0 then return 'failed
  96. else if x<0 then <<x:= -x; y0 := -y0>>;
  97. return if y0 = 0 or gcdn(x,y0) neq 1 then 'failed
  98. else (mv .** 1) .* x .+ y0
  99. end;
  100. symbolic procedure quadthroughf(ym1,y0,y1,mv);
  101. begin scalar x,y,z;
  102. x := divide(ym1+y1,2);
  103. if cdr x=0 then x := car x-y0 else return 'failed;
  104. if x=0 then return 'failed;
  105. z := y0;
  106. y := divide(y1-ym1,2);
  107. if cdr y=0 then y := car y else return 'failed;
  108. if gcdn(x,gcdn(y,z)) neq 1 then return 'failed;
  109. if x<0 then <<x := -x; y := -y; z := -z>>;
  110. if z=0 then return 'failed
  111. else if y=0 then return ((mv .** 2) .* x) .+ z
  112. else return ((mv .** 2) .* x) .+ (((mv .** 1) .* y) .+ z)
  113. end;
  114. endmodule;
  115. end;