intfac.red 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. module intfac; % Interface between integrator and factorizer.
  2. % Author: Anthony C. Hearn.
  3. % Based on earlier versions by James Davenport, Mary Ann Moore and
  4. % Arthur Norman.
  5. fluid '(!*intfac !*surds kord!* zlist); % clogflag
  6. exports int!-fac;
  7. symbolic procedure int!-fac x;
  8. % X is a primitive, square-free polynomial, except for monomial
  9. % factors. Result is a list of 'factors' wrt zlist.
  10. % Throughout most of the integrator we want to add new surds, so we
  11. % turn surds on. However, we use *intfac to inhibit use of quadratic
  12. % factorizer in the poly/primfac module, since things don't work
  13. % properly if this is used.
  14. begin scalar !*intfac,!*surds;
  15. !*intfac := !*surds := t;
  16. return int!-fac!-inner x;
  17. end;
  18. symbolic procedure int!-fac!-inner x;
  19. % X is a primitive, square-free polynomial, except for monomial
  20. % factors. Result is a list of 'factors' wrt zlist.
  21. begin scalar factors;
  22. factors := fctrf x;
  23. factors := cdr factors; % Ignore monomial factor.
  24. % Make sure x really square-free.
  25. factors := for each u in factors
  26. collect if cdr u=1 then car u
  27. else interr list(x,"not square free");
  28. % It seems we need the logs ordered ahead of atans, hence reverse.
  29. return reversip for each u in factors join fac2int u
  30. end;
  31. symbolic procedure fac2int u;
  32. % Returns a list of all the arctangents and logarithms arising from
  33. % an attempt to take the one irreducible (but not necessarily the
  34. % absolutely irreducible) factor u.
  35. begin scalar degrees,x;
  36. degrees := for each w in zlist collect (degreef(u,w) . w);
  37. if assoc(1,degrees) then return list ('log . (u ./ 1))
  38. % An irreducible polynomial of degree 1 is absolutely irreducible.
  39. else if x := assoc(2,degrees) then return int!-quadterm(u,cdr x)
  40. else if assoc(0,degrees) then return list('log . (u ./ 1));
  41. % This suggests a surd occurs. Should that be an error?
  42. if !*trint
  43. then <<printc "*** Polynomial";
  44. printsf u;
  45. printc "has not been completely factored">>;
  46. return list ('log . (u ./ 1))
  47. end;
  48. symbolic procedure int!-quadterm(pol,var);
  49. % Add in logs and atans corresponding to splitting the polynomial pol
  50. % given it is quadratic wrt var. Does not assume pol is univariate.
  51. % We need to rootxf!* so that
  52. % int(1/(x**2*y0+x**2+x*y0**2+3*x*y0+x+y0**2+y0),x) comes out in
  53. % terms of real functions.
  54. begin scalar a,b,c,discrim,kord,res,w;
  55. kord := setkorder(var . kord!*); % It shouldn't matter if
  56. % var occurs twice.
  57. c := reorder pol;
  58. if ldeg c neq 2
  59. then <<setkorder kord;
  60. rerror(int,5,"Invalid polynomial in int-quadterm")>>;
  61. a := lc c;
  62. c := red c;
  63. if not domainp c and mvar c = var and ldeg c = 1
  64. then <<b := lc c; c := red c>>;
  65. setkorder kord;
  66. discrim := powsubsf addf(multf(b,b),multd(-4,multf(a,c)));
  67. if null discrim then interr "discrim is zero in quadterm";
  68. % A quadratic usually implies an atan term.
  69. % if not clogflag
  70. % then <<w := rootxf(negf discrim,2);
  71. % if not(w eq 'failed) then go to atancase>>;
  72. w := rootxf!*(negf discrim,2);
  73. if not(w eq 'failed) then go to atancase;
  74. w := rootxf!*(discrim,2); % Maybe only rootxf is needed here.
  75. if w eq 'failed then return list ('log . !*f2q pol);
  76. % if w eq 'failed then rederr "Integration failure in int-quadterm";
  77. discrim := w;
  78. w := multpf(mksp(var,1),a);
  79. w := addf(multd(2,w),b); % 2*a*x + b.
  80. a := addf(w,discrim);
  81. b := addf(w,negf discrim);
  82. % Remove monomial multipliers.
  83. a := quotf(a,cdr comfac a);
  84. b := quotf(b,cdr comfac b);
  85. return ('log . !*f2q a) . ('log . !*f2q b) . res;
  86. atancase:
  87. res := ('log . !*f2q pol) . res; % One part of answer.
  88. a := multpf(mksp(var,1),a);
  89. a := addf(b,multd(2,a));
  90. a := fquotf(a,w);
  91. return ('atan . a) . res
  92. end;
  93. symbolic procedure rootxf!*(u,n);
  94. (if x eq 'failed or smemq('i,x) and not smemq('i,u)
  95. then (rootxf(u,n) where !*surds=nil)
  96. else x)
  97. where x=rootxf(u,n);
  98. endmodule;
  99. end;