tidysqrt.red 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. module tidysqrt; % General tidying up of square roots.
  2. % Authors: Mary Ann Moore and Arthur C. Norman.
  3. % Modifications by J.H. Davenport.
  4. exports sqrt2top,tidysqrt;
  5. %symbolic procedure tidysqrtdf a;
  6. % if null a then nil
  7. % else begin scalar tt,r;
  8. % tt:=tidysqrt lc a;
  9. % r:=tidysqrtdf red a;
  10. % if null numr tt then return r;
  11. % return ((lpow a) .* tt) .+ r
  12. % end;
  13. %
  14. symbolic procedure tidysqrt q;
  15. begin scalar n1,dd;
  16. n1:=tidysqrtf numr q;
  17. if null n1 then return nil ./ 1; %answer is zero.
  18. dd:=tidysqrtf denr q;
  19. return multsq(n1,invsq dd)
  20. end;
  21. symbolic procedure tidysqrtf p;
  22. %Input - standard form.
  23. %Output - standard quotient.
  24. %Simplifies sqrt(a)**n with n>1.
  25. if domainp p then p ./ 1
  26. else begin scalar v,w;
  27. v:=lpow p;
  28. if car v='i then v:=mksp('(sqrt -1),cdr v); %I->sqrt(-1);
  29. if eqcar(car v,'sqrt) and not onep cdr v
  30. then begin scalar x;
  31. %here we have a reduction to apply.
  32. x:=divide(cdr v,2); %halve exponent.
  33. w:=exptsq(simp cadar v,car x); %rational part of answer.
  34. if cdr x neq 0
  35. then w := multsq(w,((mksp(car v,1) .* 1) .+ nil) ./ 1);
  36. %the next line allows for the horrors of nested sqrts.
  37. w:=tidysqrt w
  38. end
  39. else w:=((v .* 1) .+ nil) ./ 1;
  40. v:=multsq(w,tidysqrtf lc p);
  41. return addsq(v,tidysqrtf red p)
  42. end;
  43. symbolic procedure multoutdenr q;
  44. % Move sqrts in a sq to the numerator.
  45. begin scalar n,d,root,conj;
  46. n:=numr q;
  47. d:=denr q;
  48. while (root:=findsquareroot d) do <<
  49. conj:=conjugatewrt(d,root);
  50. n:=!*multf(n,conj);
  51. d:=!*multf(d,conj) >>;
  52. while (root:=findnthroot d) do <<
  53. conj:=conjugateexpt(d,root,kord!*);
  54. n:=!*multf(n,conj);
  55. d:=!*multf(d,conj) >>;
  56. return (n . d);
  57. end;
  58. symbolic procedure conjugateexpt(d,root,kord!*);
  59. begin scalar ord,ans,repl,xi;
  60. ord:=caddr caddr root; % the denominator of the exponent;
  61. ans:=1;
  62. kord!*:= (xi:=gensym()) . kord!*;
  63. % XI is an ORD'th root of unity;
  64. for i:=1:ord-1 do <<
  65. ans:=!*multf(ans,numr subf(d,
  66. list(root . list('times,root,list('explt,xi,i)))));
  67. while (mvar ans eq xi) and ldeg ans > ord do
  68. ans:=addf(red ans,(xi) to (ldeg ans - ord) .* lc ans .+ nil);
  69. if (mvar ans eq xi) and ldeg ans = ord then
  70. ans:=addf(red ans,lc ans) >>;
  71. if (mvar ans eq xi) and ldeg ans = ord-1 then <<
  72. repl:=-1;
  73. for i:=1:ord-2 do
  74. repl:=(xi) to i .* -1 .+ repl;
  75. ans:=addf(red ans,!*multf(lc ans,repl)) >>;
  76. if not domainp ans and mvar ans eq xi
  77. then interr "Conjugation failure";
  78. return ans;
  79. end;
  80. symbolic procedure sqrt2top q;
  81. begin
  82. scalar n,d;
  83. n:=multoutdenr q;
  84. d:=denr n;
  85. n:=numr n;
  86. if d eq denr q
  87. then return q;%no change.
  88. if d iequal 1
  89. then return (n ./ 1);
  90. q:=gcdcoeffsofsqrts n;
  91. if q iequal 1
  92. then if minusf d
  93. then return (negf n ./ negf d)
  94. else return (n ./ d);
  95. q:=gcdf(q,d);
  96. n:=quotf(n,q);
  97. d:=quotf(d,q);
  98. if minusf d
  99. then return (negf n ./ negf d)
  100. else return (n ./ d)
  101. end;
  102. %symbolic procedure denrsqrt2top q;
  103. %begin
  104. % scalar n,d;
  105. % n:=multoutdenr q;
  106. % d:=denr n;
  107. % n:=numr n;
  108. % if d eq denr q
  109. % then return d; % no changes;
  110. % if d iequal 1
  111. % then return 1;
  112. % q:=gcdcoeffsofsqrts n;
  113. % if q iequal 1
  114. % then return d;
  115. % q:=gcdf(q,d);
  116. % if q iequal 1
  117. % then return d
  118. % else return quotf(d,q)
  119. % end;
  120. symbolic procedure findsquareroot p;
  121. % Locate a sqrt symbol in poly p.
  122. if domainp p then nil
  123. else begin scalar w;
  124. w:=mvar p; %check main var first.
  125. if atom w
  126. then return nil; %we have passed all sqrts.
  127. if eqcar(w,'sqrt) then return w;
  128. w:=findsquareroot lc p;
  129. if null w then w:=findsquareroot red p;
  130. return w
  131. end;
  132. symbolic procedure findnthroot p;
  133. nil; % Until corrected.
  134. % symbolic procedure x!-findnthroot p;
  135. % % Locate an n-th root symbol in poly p.
  136. % if domainp p then nil
  137. % else begin scalar w;
  138. % w:=mvar p; %check main var first.
  139. % if atom w
  140. % then return nil; %we have passed all sqrts.
  141. % if eqcar(w,'expt) and eqcar(caddr w,'quotient) then return w;
  142. % w:=findnthroot lc p;
  143. % if null w then w:=findnthroot red p;
  144. % return w
  145. % end;
  146. symbolic procedure conjugatewrt(p,var);
  147. % Var -> -var in form p.
  148. if domainp p then p
  149. else if mvar p=var then begin
  150. scalar x,c,r;
  151. x:=tdeg lt p; %degree
  152. c:=lc p; %coefficient
  153. r:=red p; %reductum
  154. x:=remainder(x,2); %now just 0 or 1.
  155. if x=1 then c:=negf c; %-coefficient.
  156. return (lpow p .* c) .+ conjugatewrt(r,var) end
  157. else if ordop(var,mvar p) then p
  158. else (lpow p .* conjugatewrt(lc p,var)) .+
  159. conjugatewrt(red p,var);
  160. symbolic procedure gcdcoeffsofsqrts u;
  161. if atom u
  162. then if numberp u and minusp u
  163. then -u
  164. else u
  165. else if eqcar(mvar u,'sqrt)
  166. then begin
  167. scalar v;
  168. v:=gcdcoeffsofsqrts lc u;
  169. if v iequal 1
  170. then return v
  171. else return gcdf(v,gcdcoeffsofsqrts red u)
  172. end
  173. else begin
  174. scalar root;
  175. root:=findsquareroot u;
  176. if null root
  177. then return u;
  178. u:=makemainvar(u,root);
  179. root:=gcdcoeffsofsqrts lc u;
  180. if root iequal 1
  181. then return 1
  182. else return gcdf(root,gcdcoeffsofsqrts red u)
  183. end;
  184. endmodule;
  185. end;