makefour.red 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. module makefour;
  2. %% User interface; all rather iffy at present
  3. symbolic procedure harmonicp u; get(u, 'fourier!-angle);
  4. symbolic procedure harmonic u;
  5. <<
  6. for each x in u do if not(get(x, 'fourier!-angle)) then <<
  7. if (next!-angle!* > 7) then rerror(fourier,3,"Too many angles");
  8. put(x, 'fourier!-angle, next!-angle!*);
  9. putv!.unsafe(fourier!-name!*, next!-angle!*, x);
  10. next!-angle!* := next!-angle!* #+ 1;
  11. >>
  12. >>;
  13. put('harmonic, 'stat, 'rlis);
  14. symbolic procedure simpfourier u;
  15. %% Handle the form fourier(...) with treating sin and cos as special
  16. begin
  17. if not(length u = 1) then
  18. rerror(fourier,1,"Argument should be single expression");
  19. return simpfourier1 prepsq simp!* car u;;
  20. end;
  21. symbolic procedure simpfourier1 u;
  22. begin scalar ff;
  23. if atom u then <<
  24. if harmonicp u
  25. then rerror(fourier,2,"Secular angle not allowed");
  26. return (!*sq2fourier simp u) . 1;
  27. >>
  28. else if eqcar(u, '!:fs!:) then return u
  29. else if (ff := get(car u, 'simpfour)) then return apply1(ff, cdr u)
  30. else <<
  31. rerror(fourier,4,"Unknown function" . car u);
  32. return (!*sq2fourier u) . 1;
  33. >>
  34. end;
  35. put('fourier, 'simpfn, 'simpfourier);
  36. symbolic procedure simpfouriersin u;
  37. % Creation of a simple angle expression and function
  38. begin scalar ans, vv;
  39. u := car u;
  40. if atom u then
  41. if harmonicp u then <<
  42. ans:=mkvect 3;
  43. fs!:set!-coeff(ans,(1 . 1));
  44. fs!:set!-fn(ans,'sin);
  45. vv := mkvect 7;
  46. for i:=0:7 do putv!.unsafe(vv,i,0);
  47. putv!.unsafe(vv, get(u, 'fourier!-angle), 1);
  48. fs!:set!-angle(ans,vv);
  49. fs!:set!-next(ans,nil);
  50. return (get('fourier,'tag) . ans) . 1 >>
  51. else return !*sq2fourier(simp list('sin, u)) . 1;
  52. if angle!-expression!-p u then <<
  53. ans:=mkvect 3;
  54. fs!:set!-coeff(ans,(1 . 1));
  55. fs!:set!-fn(ans,'sin);
  56. vv := mkvect 7;
  57. for i:=0:7 do putv!.unsafe(vv,i,0);
  58. compile!-angle!-expression(u,vv);
  59. fs!:set!-angle(ans,vv);
  60. fs!:set!-next(ans,nil);
  61. return (get('fourier,'tag) . ans) . 1 >>;
  62. rerror(fourier,99,"Not finished yet");
  63. end;
  64. put('sin, 'simpfour, 'simpfouriersin);
  65. symbolic procedure simpfouriercos u;
  66. % Creation of a simple angle expression and function
  67. begin scalar ans, vv;
  68. u := car u;
  69. if atom u then
  70. if harmonicp u then <<
  71. ans:=mkvect 3;
  72. fs!:set!-coeff(ans,(1 . 1));
  73. fs!:set!-fn(ans,'cos);
  74. vv := mkvect 7;
  75. for i:=0:7 do putv!.unsafe(vv,i,0);
  76. putv!.unsafe(vv, get(u, 'fourier!-angle), 1);
  77. fs!:set!-angle(ans,vv);
  78. fs!:set!-next(ans,nil);
  79. return (get('fourier,'tag) . ans) . 1 >>
  80. else return !*sq2fourier(simp list('cos, u)) . 1;
  81. if angle!-expression!-p u then <<
  82. ans:=mkvect 3;
  83. fs!:set!-coeff(ans,(1 . 1));
  84. fs!:set!-fn(ans,'cos);
  85. vv := mkvect 7;
  86. for i:=0:7 do putv!.unsafe(vv,i,0);
  87. compile!-angle!-expression(u,vv);
  88. fs!:set!-angle(ans,vv);
  89. fs!:set!-next(ans,nil);
  90. return (get('fourier,'tag) . ans) . 1 >>;
  91. rerror(fourier,99,"Not finished yet");
  92. end;
  93. put('cos, 'simpfour, 'simpfouriercos);
  94. %% Is the prefix expression u a sum of angles??
  95. symbolic procedure angle!-expression!-p u;
  96. if atom u and harmonicp u then t
  97. else if eqcar(u,'plus) or eqcar(u,'difference) then
  98. angle!-expression!-p cadr u and angle!-expression!-p caddr u
  99. else if eqcar(u,'minus) then angle!-expression!-p cadr u
  100. else if eqcar(u,'times) then
  101. if numberp cadr u then angle!-expression!-p caddr u
  102. else angle!-expression!-p cadr u and numberp caddr u
  103. else nil;
  104. %% We know that u is a sum of angles, so create vector of coefficients.
  105. symbolic procedure compile!-angle!-expression(u,v);
  106. if atom u and harmonicp u then
  107. putv!.unsafe(v, get(u, 'fourier!-angle),
  108. 1+getv!.unsafe(v, get(u, 'fourier!-angle)))
  109. else if eqcar(u,'plus) then <<
  110. u := cdr u;
  111. while u do <<
  112. compile!-angle!-expression(car u,v);
  113. u := cdr u
  114. >>;
  115. v >>
  116. else if eqcar(u,'difference) then begin scalar vv;
  117. compile!-angle!-expression(cadr u,v);
  118. vv := mkvect 7;
  119. for i:=0:7 do putv!.unsafe(vv,i,0);
  120. compile!-angle!-expression(caddr u,vv);
  121. for i:=0:7 do putv!.unsafe(v,i,getv!.unsafe(v,i)
  122. - getv!.unsafe(vv,i));
  123. return v
  124. end
  125. else if eqcar(u,'minus) then
  126. begin scalar vv;
  127. vv := mkvect 7;
  128. for i:=0:7 do putv!.unsafe(vv,i,0);
  129. compile!-angle!-expression(cadr u,vv);
  130. for i:=0:7 do putv!.unsafe(v,i,getv!.unsafe(v,i)
  131. - getv!.unsafe(vv,i));
  132. return v;
  133. end
  134. else if eqcar(u,'times) then
  135. if numberp cadr u then begin scalar vv;
  136. vv := mkvect 7;
  137. for i:=0:7 do putv!.unsafe(vv,i,0);
  138. compile!-angle!-expression(caddr u,vv);
  139. for i:=0:7 do putv!.unsafe(v, i,
  140. cadr u*getv!.unsafe(vv, i) + getv!.unsafe(v,i))
  141. end
  142. else begin scalar vv;
  143. vv := mkvect 7;
  144. for i:=0:7 do putv!.unsafe(vv,i,0);
  145. compile!-angle!-expression(cadr u,vv);
  146. for i:=0:7 do putv!.unsafe(v, i,
  147. caddr u * getv!.unsafe(vv, i) + getv!.unsafe(v,i))
  148. end
  149. else nil;
  150. symbolic procedure simpfouriertimes(u);
  151. begin scalar z;
  152. z := car simpfourier1 car u;
  153. u := cdr u;
  154. a: if null u then return z ./ 1;
  155. z := fs!:times!:(car simpfourier1 car u,z);
  156. u := cdr u;
  157. go to a
  158. end;
  159. put('times, 'simpfour, 'simpfouriertimes);
  160. symbolic procedure simpfourierexpt(u);
  161. fs!:expt!:(car simpfourier1 car u, cadr u) . 1;
  162. put('expt, 'simpfour, 'simpfourierexpt);
  163. symbolic procedure simpfourierplus(u);
  164. begin scalar z;
  165. z := car simpfourier1 car u;
  166. u := cdr u;
  167. a: if null u then return z ./ 1;
  168. z := fs!:plus!:(car simpfourier1 car u,z);
  169. u := cdr u;
  170. go to a
  171. end;
  172. put('plus, 'simpfour, 'simpfourierplus);
  173. symbolic procedure simpfourierdifference(u);
  174. fs!:difference!:(car simpfourier1 car u, car simpfourier1 cadr u)
  175. ./ 1;
  176. put('difference, 'simpfour, 'simpfourierdifference);
  177. symbolic procedure simpfourierminus(u);
  178. fs!:negate!:(car simpfourier1 car u) . 1;
  179. put('minus, 'simpfour, 'simpfourierminus);
  180. symbolic procedure simpfourierquot(u);
  181. begin scalar v;
  182. v := simp!* cadr u;
  183. v := cdr v . car v;
  184. return fs!:times!:(car simpfourier1 car u, !*sq2fourier v) ./ 1
  185. end;
  186. put('quotient, 'simpfour, 'simpfourierquot);
  187. symbolic procedure simphsin u;
  188. begin
  189. if not(length u = 1) then
  190. rerror(fourier,5,"Argument should be single expression");
  191. return simpfouriersin list(u := prepsq simp!* car u)
  192. end;
  193. put('hsin, 'simpfn, 'simphsin);
  194. symbolic procedure simphcos u;
  195. begin
  196. if not(length u = 1) then
  197. rerror(fourier,6,"Argument should be single expression");
  198. return simpfouriercos list(u := prepsq simp!* car u)
  199. end;
  200. put('hcos, 'simpfn, 'simphcos);
  201. endmodule;
  202. end;