trigint.red 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %
  3. % Neil Langmead November 1996 ZIB Berlin
  4. % routines to evaluate trigonometric integrals
  5. %
  6. % main routine is trigint
  7. % substitution variable is always u
  8. %
  9. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  10. module trigint;
  11. create!-package ('(trigint),nil);
  12. global '(!*tracetrig);
  13. switch tracetrig;
  14. off tracetrig; % off by default;
  15. algebraic;
  16. load_package limits;
  17. on usetaylor;
  18. load_package misc;
  19. % need a knowledge base of the substitutions
  20. expr procedure sub_a(exp,var);
  21. sub({sin(var)=2*u/(1+u^2), cos(var)=(1-u^2)/(1+u^2)},exp);
  22. expr procedure sub_b(exp,var);
  23. sub({sin(var)=(u^2-1)/(u^2+1),
  24. cos(var)=2*u/(u^2+1)},exp);
  25. expr procedure sub_c(exp,var);
  26. sub({sin(var)=2*u/(1+u^2), cos(var)=(u^2-1)/(1+u^2)},exp);
  27. expr procedure sub_d(exp,var);
  28. sub({sin(var)=u/(sqrt(1+u^2)), cos(var)=1/(sqrt(1+u^2))},exp);
  29. % applying the substitutions to their integrals
  30. expr procedure apply_a(exp,var);
  31. begin scalar answer, result;
  32. answer:=sub_a(exp,var);
  33. answer:=answer* 2/(1+u^2);
  34. result:=int(answer,u);
  35. result:=sub({u=tan(var/2)},result);
  36. result:=result+k(result,var,pi)*floor((var-pi)/(2*pi));
  37. return result;
  38. end;
  39. expr procedure apply_b(exp,var);
  40. begin scalar answer, result;
  41. answer:=sub_b(exp,var); answer:=answer*2/(1+u^2);
  42. result:=int(answer,u); result:= sub({u=tan(var/2+pi/4)}, result);
  43. result:=result+k(result,var,pi/2)*floor((var-pi/2)/(2*pi));
  44. return result;
  45. end;
  46. expr procedure apply_c(exp, var);
  47. begin scalar answer, result;
  48. answer:=sub_c(exp,var); answer:= answer*(-2/(1+u^2));
  49. result:=int(answer,u); result:=sub({u=1/(tan(var/2))},result);
  50. result:=result+k(result,var,0)*floor(var/(2*pi));
  51. return result;
  52. end;
  53. expr procedure apply_d(exp, var);
  54. begin scalar answer, result;
  55. answer:=sub_d(exp,var);
  56. answer:=answer*(1/(1+u^2));
  57. result:=int(answer,u); result:= sub({u=tan(var)},result);
  58. result:=result+k(result,var,pi/2)*floor((var-pi/2)/pi);
  59. return result;
  60. end;
  61. % some trigonometric substitutions which occur very frequently
  62. trig_rules:= {
  63. (sec(~x))^2 => 1/(cos(x))^2,
  64. %tan(~x) => sin(x)/cos(x),
  65. (tan(~x))^2 => (sec(x))^2-1
  66. %2*sin(~x/2)*cos(~x/2) => sin(x)
  67. %(cos(~x))^2 => 1-(sin(x))^2 % (sin(~x))^2 => 1-(cos(x))^2
  68. };
  69. %let trig_rules;
  70. %for all x let sin(x)^2+cos(x)^2=1,
  71. % 2*sin(x/2)*cos(x/2)=sin(x);
  72. % procedure to see if integral is returned unevaluated
  73. expr procedure unevalp(exp);
  74. begin scalar finished, k; k:=0; finished:=0;
  75. while ( finished=0 and k<=arglength(exp)) do
  76. <<
  77. if(part(exp,k)=int) then finished:=1 else k:=k+1;
  78. >>;
  79. if (finished=1) then return t else nil;
  80. end;
  81. % procedure to evaluate K
  82. expr procedure k(exp,var,val);
  83. limit!-(exp,var,val)-limit!+(exp,var,val);
  84. % two routines to see if we have either unevaluated limits or ints in our
  85. % result. If we have, then try a different substitution
  86. expr procedure uneval_int(exp);
  87. begin scalar temp;
  88. if( not freeof(exp,int)) then return temp:=t else temp:=nil;
  89. return temp;
  90. end;
  91. expr procedure uneval_lim(exp);
  92. begin scalar temp;
  93. if(not freeof(exp,limit!-)) then return t else
  94. <<
  95. if(not freeof(exp,limit!+)) then return t else nil;
  96. >>;
  97. end;
  98. expr procedure fail_a(exp,var);
  99. begin scalar temp;
  100. temp:=apply_a(exp,var);
  101. if(uneval_lim(temp)) then return t else
  102. <<
  103. if(uneval_int(temp)) then return t
  104. else return nil;
  105. >>;
  106. end;
  107. expr procedure fail_b(exp,var);
  108. begin scalar temp;
  109. temp:=apply_b(exp,var);
  110. %temp:=temp+k(temp,var,pi/2)*floor((var-pi/2)/(2*pi));
  111. if(uneval_lim(temp)) then return t else
  112. <<
  113. if(uneval_int(temp)) then return t else return nil;
  114. >>;
  115. end;
  116. expr procedure fail_c(exp,var);
  117. begin scalar temp;
  118. temp:=apply_c(exp,var);
  119. %temp:=temp+k(temp,var,0)*floor(var/(pi));
  120. if(uneval_lim(temp)) then return t else
  121. <<
  122. if(uneval_int(temp)) then return t else return nil;
  123. >>;
  124. end;
  125. expr procedure fail_d(exp,var);
  126. begin scalar temp;
  127. temp:=apply_d(exp,var);
  128. %temp:=temp+k(temp,var,pi/2)*floor((var-pi/2)/pi);
  129. if(uneval_lim(temp)) then return t else
  130. <<
  131. if(uneval_int(temp)) then return t else return nil;
  132. >>;
  133. end;
  134. expr procedure fail(exp);
  135. if(uneval_lim(exp)) then t else
  136. << if(uneval_int(exp)) then t else nil; >>;
  137. let log(-1) => i*pi; % really important. If further log rules are needed,
  138. % take a look at the ratint package, and the module
  139. % convert, which contains an extensive list of such
  140. % rules
  141. expr procedure trigint(exp,var);
  142. begin scalar answer, answer_1, answer_2, answer_3, answer_4, result;
  143. %off mesgs; % off by default
  144. % check for correct input
  145. if(freeof(exp,sin) and freeof(exp,cos) and freeof(exp,tan)) then <<
  146. if(lisp !*tracetrig) then
  147. write "expression free of sin, cos tan, proceeding with standard integration";
  148. return int(exp,x); >>;
  149. on usetaylor;
  150. if freeof(exp,sin(var)) then % we use substitution (a)
  151. <<
  152. answer:=apply_a(exp,var);
  153. %answer:=answer+k(answer,var,pi)*floor((var-pi)/(2*pi));
  154. if(fail(answer)) then % system can't evaluate after subs
  155. <<
  156. if(lisp !*tracetrig) then
  157. write "system can't integrate after substitution A,
  158. trying again";
  159. answer_2:=apply_b(exp,var);
  160. if(fail(answer_2)) then
  161. <<
  162. if(lisp !*tracetrig) then write "trying again with substitution B";
  163. answer_3:=apply_c(exp,var);
  164. if(fail(answer_3)) then
  165. <<
  166. if(lisp !*tracetrig) then
  167. write "and again with substitution C";
  168. answer_4:=apply_d(exp,var);
  169. if(fail(answer_4)) then
  170. <<
  171. if(lisp !*tracetrig) then
  172. write "failed in all attempts, system cannot integrate";
  173. return answer;
  174. >> else return answer_4;
  175. >> else return answer_3;
  176. >> else return answer_2;
  177. >> else return answer;
  178. %let trig_rules;
  179. %if(unevalp(answer)) then rederr "system cannot integrate after subs"
  180. %else nil;
  181. >>
  182. else
  183. % we use substitution b,c or d
  184. <<
  185. if(freeof(exp,cos(var))) then % use substitution b
  186. <<
  187. answer:=apply_b(exp,var);
  188. if(fail(answer)) then
  189. <<
  190. if(lisp !*tracetrig) then write "failed with substitution B: system could not
  191. integrate after subs, trying A";
  192. answer_2:=apply_a(exp,var);
  193. if(fail(answer_2)) then
  194. <<
  195. if(lisp !*tracetrig) then write "failed with A: trying C now";
  196. answer_3:=apply_c(exp,var);
  197. if(fail(answer_3)) then
  198. <<
  199. if(lisp !*tracetrig) then write "failed with C: trying D now";
  200. answer_4:=apply_d(exp,var);
  201. if(lisp !*tracetrig) then
  202. write "trying all possible substitutions";
  203. if(fail(answer_4)) then rederr "system can't integrate after
  204. subs"
  205. else return answer_4;
  206. >> else return answer_3;
  207. >> else return answer_2;
  208. >> else return answer;
  209. >>
  210. else <<
  211. % now describe situations best for (c) and (d) G and R sect 2.504
  212. if(sub({sin(var)=-sin(var),cos(var)=-cos(var)},exp)=exp) then
  213. % d is the best sub in this case
  214. <<
  215. if(lisp !*tracetrig) then write
  216. "using heuristics: G & R section 2.504 to integrate ";
  217. answer:=apply_d(exp,var);
  218. if(fail(answer)) then
  219. <<
  220. if(lisp !*tracetrig) then write "subs D failed, trying now with A";
  221. answer_2:=apply_a(exp,var);
  222. if(fail(answer_2)) then
  223. <<
  224. if(lisp !*tracetrig) then write "subs B falied, trying with sub C";
  225. answer_3:=apply_b(exp,var);
  226. if(fail(answer_3)) then
  227. <<
  228. if(lisp !*tracetrig) then write "sub C falied, trying sub D";
  229. answer_4:=apply_c(exp,var);
  230. if(fail(answer_4)) then rederr "can't integrate after subs"
  231. else return answer_4;
  232. >> else return answer_3;
  233. >> else return answer_2;
  234. >> else return answer;
  235. >>
  236. else << % no guidelines, try each substitution in turn, and return the
  237. % best possible answer, if there is one
  238. answer:=apply_a(exp,var);
  239. if(fail(answer)) then
  240. <<
  241. if(lisp !*tracetrig) then write "not using heuristics,
  242. attempting subs in order: trying A";
  243. answer_2:=apply_b(exp,var);
  244. if(fail(answer_2)) then
  245. <<
  246. if(lisp !*tracetrig) then write "A failed, trying B";
  247. answer_3:=apply_c(exp,var);
  248. if(fail(answer_3)) then
  249. << answer_4:=apply_d(exp,var);
  250. if(fail(answer_4)) then rederr "can't do it"
  251. else return answer_4;
  252. >> else return answer_3;
  253. >> else return answer_2;
  254. >> else return answer;
  255. >>;
  256. >>; % for the else just before the comment on G and R
  257. >>;
  258. return answer;
  259. end;
  260. endmodule;
  261. end;