jpatches.red 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. module jpatches; % Routines for manipulating sf's with power folding.
  2. % Author: James H. Davenport.
  3. fluid '(!*noncomp sqrtflag);
  4. exports !*addsq,!*multsq,!*invsq,!*multf,!*exptsq,!*exptf; %squashsqrtsq
  5. % !*MULTF(A,B) multiplies the polynomials (standard forms) U and V
  6. % in much the same way as MULTF(U,V) would, EXCEPT...
  7. % (1) !*MULTF inhibits the action of OFF EXP and of non-commutative
  8. % multiplications
  9. % (2) Within !*MULTF powers of square roots, and powers of
  10. % exponential kernels are reduced as if substitution rules
  11. % such as FOR ALL X LET SQRT(X)**2=X were being applied;
  12. % Note that !*MULTF comes between MULTF and !*Q2F SUBS2F MULTF in its
  13. % behaviour, and that it is the responsibility of the user to call it
  14. % in sensible places where its services are needed.
  15. % Similarly for the other functions defined here.
  16. %symbolic procedure !*addsq(u,v);
  17. %U and V are standard quotients.
  18. % %Value is canonical sum of U and V;
  19. % if null numr u then v
  20. % else if null numr v then u
  21. % else if denr u=1 and denr v=1 then addf(numr u,numr v) ./ 1
  22. % else begin scalar nu,du,nv,dv,x;
  23. % x := gcdf(du:=denr u,dv:=denr v);
  24. % du:=quotf(du,x); dv:=quotf(dv,x);
  25. % nu:=numr u; nv:=numr v;
  26. % u:=addf(!*multf(nu,dv),!*multf(nv,du));
  27. % if u=nil then return nil ./ 1;
  28. % v:=!*multf(du,denr v);
  29. % return !*ff2sq(u,v)
  30. % end;
  31. %symbolic procedure !*multsq(a,b);
  32. % begin
  33. % scalar n,d;
  34. % n:=!*multf(numr a,numr b);
  35. % d:=!*multf(denr a,denr b);
  36. % return !*ff2sq(n,d)
  37. % end;
  38. %symbolic procedure !*ff2sq(a,b);
  39. % begin
  40. % scalar gg;
  41. % if null a then return nil ./ 1;
  42. % gg:=gcdf(a,b);
  43. % if not (gg=1) then <<
  44. % a:=quotf(a,gg);
  45. % b:=quotf(b,gg) >>;
  46. % if minusf b then <<
  47. % a:=negf a;
  48. % b:=negf b >>;
  49. % return a ./ b
  50. % end;
  51. symbolic procedure !*addsq(u,v);
  52. %U and V are standard quotients.
  53. %Value is canonical sum of U and V;
  54. if null numr u then v
  55. else if null numr v then u
  56. else if denr u=1 and denr v=1 then addf(numr u,numr v) ./ 1
  57. else begin scalar du,dv,x,y,z;
  58. x := gcdf(du:=denr u,dv:=denr v);
  59. du:=quotf(du,x); dv:=quotf(dv,x);
  60. y:=addf(!*multf(dv,numr u),!*multf(du,numr v));
  61. if null y then return nil ./ 1;
  62. z:=!*multf(denr u,dv);
  63. if minusf z then <<y := negf y; z := negf z>>;
  64. % In this case (as opposed to ADDSQ), Y and Z may have
  65. % developed common factors from SQRT expansion, so a
  66. % gcd of Y and Z is needed.
  67. x := gcdf(y,z);
  68. return if x=1 then y ./ z else quotf(y,x) ./ quotf(z,x)
  69. end;
  70. symbolic procedure !*multsq(u,v);
  71. %U and V are standard quotients. Result is the canonical product of
  72. %U and V with surd powers suitably reduced.
  73. if null numr u or null numr v then nil ./ 1
  74. else if denr u=1 and denr v=1 then !*multf(numr u,numr v) ./ 1
  75. else begin scalar w,x,y;
  76. x := gcdf(numr u,denr v);
  77. y := gcdf(numr v,denr u);
  78. w := !*multf(quotf(numr u,x),quotf(numr v,y));
  79. x := !*multf(quotf(denr u,y),quotf(denr v,x));
  80. if minusf x then <<w := negf w; x := negf x>>;
  81. y := gcdf(w,x); % another factor may have been generated.
  82. return if y=1 then w ./ x else quotf(w,y) ./ quotf(x,y)
  83. end;
  84. symbolic procedure !*invsq a;
  85. % Note that several examples (e.g., int(1/(x**8+1),x)) give a more
  86. % compact result when SQRTFLAG is true if SQRT2TOP is not called.
  87. if sqrtflag then sqrt2top invsq a else invsq a;
  88. symbolic procedure !*multf(u,v);
  89. % U and V are standard forms
  90. % Value is SF for U*V;
  91. begin scalar x,y;
  92. if null u or null v then return nil
  93. else if u=1 then return squashsqrt v
  94. else if v=1 then return squashsqrt u
  95. else if domainp u then return multd(u,squashsqrt v)
  96. else if domainp v then return multd(v,squashsqrt u)
  97. else if !*noncomp then return multf(u,v);
  98. x:=mvar u;
  99. y:=mvar v;
  100. if x eq y then go to c else if ordop(x,y) then go to b;
  101. x:=!*multf(u,lc v);
  102. y:=!*multf(u,red v);
  103. return if null x then y
  104. else if not domainp lc v
  105. and mvar u eq mvar lc v
  106. and not atom mvar u
  107. and car mvar u memq '(expt sqrt)
  108. then addf(!*multf(x,!*p2f lpow v),y)
  109. else makeupsf(lpow v,x,y);
  110. b: x:=!*multf(lc u,v);
  111. y:=!*multf(red u,v);
  112. return if null x then y
  113. else if not domainp lc u
  114. and mvar lc u eq mvar v
  115. and not atom mvar v
  116. and car mvar v memq '(expt sqrt)
  117. then addf(!*multf(!*p2f lpow u,x),y)
  118. else makeupsf(lpow u,x,y);
  119. c: y:=addf(!*multf(list lt u,red v),!*multf(red u,v));
  120. if eqcar(x,'sqrt)
  121. then return addf(squashsqrt y,!*multfsqrt(x,
  122. !*multf(lc u,lc v),ldeg u + ldeg v))
  123. else if eqcar(x,'expt) and prefix!-rational!-numberp caddr x
  124. then return addf(squashsqrt y,!*multfexpt(x,
  125. !*multf(lc u,lc v),ldeg u + ldeg v));
  126. x:=mkspm(x,ldeg u + ldeg v);
  127. return if null x or null (u:=!*multf(lc u,lc v))
  128. then y
  129. else addf(multpf(x,u),y)
  130. end;
  131. symbolic procedure makeupsf(u,x,y);
  132. % Makes u .* x .+ y except when u is not a valid lpow (because of
  133. % sqrts).
  134. if atom car u or cdr u = 1 then addf(multpf(u,x),y)
  135. else if caar u eq 'sqrt then addf(!*multfsqrt(car u,x,cdr u),y)
  136. else if <<begin scalar v;
  137. v:=car u;
  138. if car v neq 'expt then return nil;
  139. v:=caddr v;
  140. if atom v then return nil;
  141. return (car v eq 'quotient
  142. and numberp cadr v
  143. and numberp caddr v)
  144. end >>
  145. then addf(!*multfexpt(car u,x,cdr u),y)
  146. else addf(multpf(u,x),y);
  147. symbolic procedure !*multfsqrt(x,u,w);
  148. % This code (Due to Norman a& Davenport) squashes SQRT(...)**2.
  149. begin scalar v;
  150. w:=divide(w,2);
  151. v:=!*q2f simp cadr x;
  152. u:=!*multf(u,exptf(v,car w));
  153. if cdr w neq 0 then u:=!*multf(u,!*p2f mksp(x,1));
  154. return u
  155. end;
  156. symbolic procedure !*multfexpt(x,u,w);
  157. begin scalar expon,v;
  158. expon:=caddr x;
  159. x:=cadr x;
  160. w:=w * cadr expon;
  161. expon:=caddr expon;
  162. v:=gcdn(w,expon);
  163. w:=w/v;
  164. v:=expon/v;
  165. if not (w > 0) then rerror(int,8,"Invalid exponent")
  166. else if v = 1
  167. then return !*multf(u,exptf(if numberp x then x
  168. else if atom x then !*k2f x
  169. else !*q2f if car x eq '!*sq
  170. then argof x
  171. else simp x,
  172. w));
  173. expon:=0;
  174. while not (w < v) do <<expon:=expon + 1; w:=w-v>>;
  175. if expon>0 then u:=!*multf(u,exptf(!*q2f simp x,expon));
  176. if w = 0 then return u;
  177. x:=list('expt,x,list('quotient,1,v));
  178. return multf(squashsqrt u,!*p2f mksp(x,w)) % Cannot be *MULTF.
  179. end;
  180. symbolic procedure prefix!-rational!-numberp u;
  181. % Tests for m/n in prefix representation.
  182. eqcar(u,'quotient) and numberp cadr u and numberp caddr u;
  183. % symbolic procedure squashsqrtsq sq;
  184. % !*multsq(squashsqrt numr sq ./ 1,1 ./ squashsqrt denr sq);
  185. symbolic procedure squashsqrt sf;
  186. if (not sqrtflag) or atom sf or atom mvar sf
  187. then sf
  188. else if car mvar sf eq 'sqrt and ldeg sf > 1
  189. then addf(squashsqrt red sf,!*multfsqrt(mvar sf,lc sf,ldeg sf))
  190. else if car mvar sf eq 'expt
  191. and prefix!-rational!-numberp caddr mvar sf
  192. and ldeg sf >= caddr caddr mvar sf
  193. then addf(squashsqrt red sf,!*multfexpt(mvar sf,lc sf,ldeg sf))
  194. else (if null x then squashsqrt red sf
  195. else lpow sf .* x .+ squashsqrt red sf)
  196. where x = squashsqrt lc sf;
  197. %remd 'simpx1;
  198. % The following definition requires frlis!* declared global.
  199. %symbolic procedure simpx1(u,m,n);
  200. % %u,m and n are prefix expressions;
  201. % %value is the standard quotient expression for u**(m/n);
  202. % begin scalar flg,z;
  203. % if null frlis!* or null intersection(frlis!*,flatten (m . n))
  204. % then go to a;
  205. % exptp!* := t;
  206. % return !*k2q list('expt,u,if n=1 then m
  207. % else list('quotient,m,n));
  208. % a: if numberp m and fixp m then go to e
  209. % else if atom m then go to b
  210. % else if car m eq 'minus then go to mns
  211. % else if car m eq 'plus then go to pls
  212. % else if car m eq 'times and numberp cadr m and fixp cadr m
  213. % and numberp n
  214. % then go to tms;
  215. % b: z := 1;
  216. % c: if atom u and not numberp u then flag(list u,'used!*);
  217. % u := list('expt,u,if n=1 then m else list('quotient,m,n));
  218. % if not(u member exptl!*) then exptl!* := u . exptl!*;
  219. % d: return mksq(u,if flg then -z else z); %u is already in lowest
  220. %% %terms;
  221. % e: if numberp n and fixp n then go to int;
  222. % z := m;
  223. % m := 1;
  224. % go to c;
  225. % mns: m := cadr m;
  226. % if !*mcd then return invsq simpx1(u,m,n);
  227. % flg := not flg;
  228. % go to a;
  229. % pls: z := 1 ./ 1;
  230. % pl1: m := cdr m;
  231. % if null m then return z;
  232. % z := multsq(simpexpt list(u,
  233. % list('quotient,if flg then list('minus,car m)
  234. % else car m,n)),
  235. % z);
  236. % go to pl1;
  237. % tms: z := gcdn(n,cadr m);
  238. % n := n/z;
  239. % z := cadr m/z;
  240. % m := retimes cddr m;
  241. % go to c;
  242. % int:z := divide(m,n);
  243. % if cdr z<0 then z:= (car z - 1) . (cdr z+n);
  244. % if 0 = cdr z
  245. % then return simpexpt list(u,car z);
  246. % if n = 2
  247. % then return multsq(simpexpt list(u,car z),
  248. % simpsqrti u);
  249. % return multsq(simpexpt list(u,car z),
  250. % mksq(list('expt,u,list('quotient,1,n)),cdr z))
  251. % end;
  252. symbolic procedure !*exptsq(a,n);
  253. % Raises A to the power N using !*MULTSQ.
  254. if n=0 then 1 ./ 1
  255. else if n=1 then a
  256. else if n<0 then !*exptsq(invsq a,-n)
  257. else begin
  258. scalar q,r;
  259. q:=divide(n,2);
  260. r:=cdr q; q:=car q;
  261. q:=!*exptsq(!*multsq(a,a),q);
  262. if r=0 then return q
  263. else return !*multsq(a,q)
  264. end;
  265. symbolic procedure !*exptf(a,n);
  266. % Raises A to the power N using !*MULTF.
  267. if n=0 then 1
  268. else if n=1 then a
  269. else begin
  270. scalar q,r;
  271. q:=divide(n,2);
  272. r:=cdr q; q:=car q;
  273. q:=!*exptf(!*multf(a,a),q);
  274. if r=0 then return q
  275. else return !*multf(a,q)
  276. end;
  277. endmodule;
  278. end;