convert.red 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. %to be included in the same set of modules as ratint, these procedures all
  2. %ammend the output of ratint, converting complex logs to real arctans, and
  3. %providing alternative forms for the answer
  4. % want a procedure to convert the log sum notation to a sum involving
  5. % radicals. We typically get something like
  6. %
  7. % log(x+1)+log_sum(alpha,alpha^2+alpha+1,0,alpha*log(alpha*2+x*alpha),x)
  8. %
  9. % as our output from the ratint program,
  10. % and we want to sub alpha into the log expression and sum.
  11. % other possibilies include transforming the logarithmic expression (which
  12. % often contains complex logarithms, to real arctangents.
  13. % This could be important if definite integration is the goal
  14. % Example
  15. % in symbolic mode, we have
  16. %
  17. % exp: (log_sum alpha (plus (expt alpha 2) alpha 1) 0
  18. % (times (log (plus (times alpha x) 1)) alpha) x)
  19. % need a procedure to get rid of parts of the expression not involving
  20. % log_sum
  21. algebraic <<
  22. logcomplex:=
  23. {
  24. log(~x+i) =>
  25. log(sqrt(x^2+1))+i*atan((1/sqrt(x^2+1))+i*(x/(sqrt(x^2+1)))), %when
  26. %repart(x)=x,
  27. log(~x- i) =>
  28. log(sqrt(x^2+1))-i*atan(1/sqrt(x^2+1)+i*(x/(sqrt(x^2+1)))),
  29. %when repart(x)=x,
  30. log(~x+i*~y) =>
  31. log(sqrt(x*x+y*y))+i*atan(y/sqrt(x*x+y*y)+i*x/(sqrt(x*x+y*y))),% when
  32. %repart(x)=x and repart(y)=y,
  33. log(~x-i*~y) =>
  34. log(sqrt(x*x+y*y))-i*atan(y/(sqrt(x*x+y*y))+i*(x/(sqrt(x*x+y*y)))), % when
  35. % repart(x)=x and repart(y)=y,
  36. log(~x/~y) => log(x)-log(y), %when repart(y)=y,
  37. log(sqrt ~x) => (log x)/2,
  38. log(-1) => i*pi,
  39. log(-i) => -i*pi/2,
  40. log(i) => i*pi/2,
  41. log(-~x) => i*pi+log(x), % when repart(x)=x and numberp x and x>0,
  42. log(-i*~x) => -i*pi/2+log(x),
  43. %when repart(x)=x and numberp x and x>0,
  44. log(i*~x) => i*pi/2 +log(x) %when repart(x)=x and numberp x and x>0
  45. }$
  46. >>;
  47. %algebraic let logcomplex;
  48. %letrules logcomplex
  49. symbolic procedure evalplus(a,b);
  50. if numberp a and numberp b then a+b
  51. else prepsq simp!* aeval {'plus,a,b};
  52. procedure my_plus(a,b); lisp evalplus(a,b);
  53. symbolic procedure evalmax(a,b);
  54. if numberp a and numberp b then max(a,b)
  55. else if evalgreaterp(a,b) then a else b;
  56. procedure my_max(a,b); lisp evalmax(a,b);
  57. %remove(log_sum(alpha,alpha^2+alpha+1,0,alpha*log(alpha*2+x*alpha))+log(1+x));
  58. symbolic procedure convert(exp);
  59. begin scalar temp,solution, answer;
  60. if(freeof(exp,'log_sum)) then return exp else
  61. <<
  62. if(null exp) then return nil else
  63. <<
  64. if(car exp='log_sum) then
  65. <<
  66. temp:=caddr exp;
  67. if(not freeof(temp,'beta)) then
  68. <<
  69. temp:=subeval(list (list('equal,'beta,'alpha), temp));
  70. exp:=subeval(list (list('equal,'beta,'alpha),exp));
  71. >>;
  72. temp:=reval temp; exp:=reval exp;
  73. %temp:=sub(beta=alpha,temp) % so temp now depends on alpha
  74. if(deg(temp,'alpha))>2 then
  75. << %write "degree of", reval exp, " is >2";
  76. rederr "cannot convert to radicals, degree > 2";
  77. >>
  78. else
  79. <<
  80. % temp is of the form alpha^2+alpha+1 or something similar
  81. if(deg(temp,'alpha)=2) then % solve the quadratic eqn, obtain
  82. % radicals, and substitute
  83. << %temp:=reval temp
  84. solution:= algebraic solve(temp=0,alpha);
  85. write reval cadr solution;
  86. %now have a solution list, with two elements
  87. answer:=subeval(list (reval cadr solution, algebraic reval part(exp,4)));
  88. answer:=list('plus, answer,subeval(list (reval caddr solution,
  89. algebraic reval part(exp,4))));
  90. %answer:=car answer;
  91. answer:=reval answer;
  92. >>
  93. >>
  94. >>
  95. else <<
  96. if null cdr exp then return convert(car exp) else
  97. return convert (cdr exp);
  98. >>
  99. >>
  100. >>;
  101. return answer;
  102. end;
  103. procedure conv(exp); lisp convert(exp);
  104. %conv(log(x+1)+log_sum(alpha,alpha^2+alpha-1,0,alpha*log(alpha*x^2+alpha*x-1),x%));
  105. % procedure to separate real and imaginary parts in a log sum expression
  106. symbolic procedure separate_real(exp);
  107. begin scalar re, im, ans;
  108. re:=algebraic repart(exp);
  109. im:=algebraic impart(exp);
  110. ans:= 'list.list(re,im);
  111. ans:=reval ans;
  112. return ans;
  113. end;
  114. procedure sep(exp); lisp separate_real(exp);
  115. % input an expression with complex logs, output real arctangents
  116. symbolic procedure convert_log(exp,var);
  117. begin scalar sepp,re,im, answer;
  118. algebraic repart(var):=var; algebraic impart(var):=0;
  119. if(car exp='log) then <<
  120. sepp:=separate_real(exp); %now have a list of re and im parts
  121. % can pass these to logtoatan function now
  122. re:=car exp; im:=cadr exp;
  123. answer:=logtotan1(re,im,var);
  124. return answer;
  125. >> else nil;
  126. end;
  127. procedure convertlog(exp,var); lisp convert_log(exp,var);
  128. % now need an assume real facility, so extract terms dependent on i only
  129. %
  130. % This algorithm transforms some complex logarithmic expressions to real
  131. % arctangents.
  132. %
  133. % the algorithm apppears in Manuel Bronsteins book Symbolic Integration I :
  134. % Transendental Functions, published by Springer Verlag, 1997
  135. %
  136. % Given a field K of characteristic 0 such that sqrt(-1) is not in K and A,
  137. % B are in K[x] with B neq 0, this returns a sum f of real arctangents of
  138. % polynomials in K[x] such that
  139. %
  140. % df = d (A+i*B)
  141. % -- -- i* log ------
  142. % dx dx (A-i*B)
  143. %
  144. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  145. algebraic;
  146. expr procedure logtoAtan(exp1,exp2,x);
  147. begin scalar D,C,G, temp, rem;
  148. rem:=pseudorem(exp1,exp2,x);
  149. if(part(rem,1)=0) then return (2*atan(exp1/exp2))
  150. %if(numberp(exp1/exp2)) then return (2*atan(exp1/exp2))
  151. else <<
  152. if(deg(exp1,x)<deg(exp2,x)) then return logtoAtan(-exp2,exp1,x)
  153. else <<
  154. temp:=gcd_ex(exp2,-exp1,x);
  155. D:=part(temp,1);
  156. C:=part(temp,2);
  157. G:=exp2*D-exp1*C;
  158. return(2*atan((exp1*D+exp2*C)/G)+ logtoAtan(D,C,x));
  159. >>;
  160. >>;
  161. end;
  162. %log_sum(alpha,alpha^2+alpha+1,0,alpha*log(alpha*2+x*alpha),x);
  163. %trst convert;
  164. %conv(ws);
  165. %conv(log_sum(beta,beta^2+beta-4,0,beta*log(beta*x^2+beta^2+1),x));
  166. %------------------------------------------------------------------------------
  167. end;