sin.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. // Sine function of numerical and symbolic arguments
  2. #include "stdafx.h"
  3. #include "defs.h"
  4. void
  5. eval_sin(void)
  6. {
  7. push(cadr(p1));
  8. eval();
  9. sine();
  10. }
  11. void
  12. sine(void)
  13. {
  14. save();
  15. p1 = pop();
  16. if (car(p1) == symbol(ADD))
  17. sine_of_angle_sum();
  18. else
  19. sine_of_angle();
  20. restore();
  21. }
  22. // Use angle sum formula for special angles.
  23. #define A p3
  24. #define B p4
  25. void
  26. sine_of_angle_sum(void)
  27. {
  28. p2 = cdr(p1);
  29. while (iscons(p2)) {
  30. B = car(p2);
  31. if (isnpi(B)) {
  32. push(p1);
  33. push(B);
  34. subtract();
  35. A = pop();
  36. push(A);
  37. sine();
  38. push(B);
  39. cosine();
  40. multiply();
  41. push(A);
  42. cosine();
  43. push(B);
  44. sine();
  45. multiply();
  46. add();
  47. return;
  48. }
  49. p2 = cdr(p2);
  50. }
  51. sine_of_angle();
  52. }
  53. void
  54. sine_of_angle(void)
  55. {
  56. int n;
  57. double d;
  58. if (car(p1) == symbol(ARCSIN)) {
  59. push(cadr(p1));
  60. return;
  61. }
  62. if (isdouble(p1)) {
  63. d = sin(p1->u.d);
  64. if (fabs(d) < 1e-10)
  65. d = 0.0;
  66. push_double(d);
  67. return;
  68. }
  69. // sine function is antisymmetric, sin(-x) = -sin(x)
  70. if (isnegative(p1)) {
  71. push(p1);
  72. negate();
  73. sine();
  74. negate();
  75. return;
  76. }
  77. // sin(arctan(x)) = x / sqrt(1 + x^2)
  78. // see p. 173 of the CRC Handbook of Mathematical Sciences
  79. if (car(p1) == symbol(ARCTAN)) {
  80. push(cadr(p1));
  81. push_integer(1);
  82. push(cadr(p1));
  83. push_integer(2);
  84. power();
  85. add();
  86. push_rational(-1, 2);
  87. power();
  88. multiply();
  89. return;
  90. }
  91. // multiply by 180/pi
  92. push(p1);
  93. push_integer(180);
  94. multiply();
  95. push_symbol(PI);
  96. divide();
  97. n = pop_integer();
  98. if (n < 0) {
  99. push(symbol(SIN));
  100. push(p1);
  101. list(2);
  102. return;
  103. }
  104. switch (n % 360) {
  105. case 0:
  106. case 180:
  107. push_integer(0);
  108. break;
  109. case 30:
  110. case 150:
  111. push_rational(1, 2);
  112. break;
  113. case 210:
  114. case 330:
  115. push_rational(-1, 2);
  116. break;
  117. case 45:
  118. case 135:
  119. push_rational(1, 2);
  120. push_integer(2);
  121. push_rational(1, 2);
  122. power();
  123. multiply();
  124. break;
  125. case 225:
  126. case 315:
  127. push_rational(-1, 2);
  128. push_integer(2);
  129. push_rational(1, 2);
  130. power();
  131. multiply();
  132. break;
  133. case 60:
  134. case 120:
  135. push_rational(1, 2);
  136. push_integer(3);
  137. push_rational(1, 2);
  138. power();
  139. multiply();
  140. break;
  141. case 240:
  142. case 300:
  143. push_rational(-1, 2);
  144. push_integer(3);
  145. push_rational(1, 2);
  146. power();
  147. multiply();
  148. break;
  149. case 90:
  150. push_integer(1);
  151. break;
  152. case 270:
  153. push_integer(-1);
  154. break;
  155. default:
  156. push(symbol(SIN));
  157. push(p1);
  158. list(2);
  159. break;
  160. }
  161. }
  162. #if SELFTEST
  163. static char *s[] = {
  164. "sin(x)",
  165. "sin(x)",
  166. "sin(-x)",
  167. "-sin(x)",
  168. "sin(b-a)",
  169. "-sin(a-b)",
  170. // check against the floating point math library
  171. "f(a,x)=1+sin(float(a/360*2*pi))-float(x)+sin(a/360*2*pi)-x",
  172. "",
  173. "f(0,0)", // 0
  174. "1",
  175. "f(90,1)", // 90
  176. "1",
  177. "f(180,0)", // 180
  178. "1",
  179. "f(270,-1)", // 270
  180. "1",
  181. "f(360,0)", // 360
  182. "1",
  183. "f(-90,-1)", // -90
  184. "1",
  185. "f(-180,0)", // -180
  186. "1",
  187. "f(-270,1)", // -270
  188. "1",
  189. "f(-360,0)", // -360
  190. "1",
  191. "f(45,sqrt(2)/2)", // 45
  192. "1",
  193. "f(135,sqrt(2)/2)", // 135
  194. "1",
  195. "f(225,-sqrt(2)/2)", // 225
  196. "1",
  197. "f(315,-sqrt(2)/2)", // 315
  198. "1",
  199. "f(-45,-sqrt(2)/2)", // -45
  200. "1",
  201. "f(-135,-sqrt(2)/2)", // -135
  202. "1",
  203. "f(-225,sqrt(2)/2)", // -225
  204. "1",
  205. "f(-315,sqrt(2)/2)", // -315
  206. "1",
  207. "f(30,1/2)", // 30
  208. "1",
  209. "f(150,1/2)", // 150
  210. "1",
  211. "f(210,-1/2)", // 210
  212. "1",
  213. "f(330,-1/2)", // 330
  214. "1",
  215. "f(-30,-1/2)", // -30
  216. "1",
  217. "f(-150,-1/2)", // -150
  218. "1",
  219. "f(-210,1/2)", // -210
  220. "1",
  221. "f(-330,1/2)", // -330
  222. "1",
  223. "f(60,sqrt(3)/2)", // 60
  224. "1",
  225. "f(120,sqrt(3)/2)", // 120
  226. "1",
  227. "f(240,-sqrt(3)/2)", // 240
  228. "1",
  229. "f(300,-sqrt(3)/2)", // 300
  230. "1",
  231. "f(-60,-sqrt(3)/2)", // -60
  232. "1",
  233. "f(-120,-sqrt(3)/2)", // -120
  234. "1",
  235. "f(-240,sqrt(3)/2)", // -240
  236. "1",
  237. "f(-300,sqrt(3)/2)", // -300
  238. "1",
  239. "f=quote(f)",
  240. "",
  241. "sin(arcsin(x))",
  242. "x",
  243. // check the default case
  244. "sin(1/12*pi)",
  245. "sin(1/12*pi)",
  246. "sin(arctan(4/3))",
  247. "4/5",
  248. "sin(-arctan(4/3))",
  249. "-4/5",
  250. // phase
  251. "sin(x-8/2*pi)",
  252. "sin(x)",
  253. "sin(x-7/2*pi)",
  254. "cos(x)",
  255. "sin(x-6/2*pi)",
  256. "-sin(x)",
  257. "sin(x-5/2*pi)",
  258. "-cos(x)",
  259. "sin(x-4/2*pi)",
  260. "sin(x)",
  261. "sin(x-3/2*pi)",
  262. "cos(x)",
  263. "sin(x-2/2*pi)",
  264. "-sin(x)",
  265. "sin(x-1/2*pi)",
  266. "-cos(x)",
  267. "sin(x+0/2*pi)",
  268. "sin(x)",
  269. "sin(x+1/2*pi)",
  270. "cos(x)",
  271. "sin(x+2/2*pi)",
  272. "-sin(x)",
  273. "sin(x+3/2*pi)",
  274. "-cos(x)",
  275. "sin(x+4/2*pi)",
  276. "sin(x)",
  277. "sin(x+5/2*pi)",
  278. "cos(x)",
  279. "sin(x+6/2*pi)",
  280. "-sin(x)",
  281. "sin(x+7/2*pi)",
  282. "-cos(x)",
  283. "sin(x+8/2*pi)",
  284. "sin(x)",
  285. };
  286. void
  287. test_sin(void)
  288. {
  289. test(__FILE__, s, sizeof s / sizeof (char *));
  290. }
  291. #endif