tan.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Tangent function of numerical and symbolic arguments
  2. #include "stdafx.h"
  3. #include "defs.h"
  4. void
  5. eval_tan(void)
  6. {
  7. push(cadr(p1));
  8. eval();
  9. tangent();
  10. }
  11. void
  12. tangent(void)
  13. {
  14. save();
  15. yytangent();
  16. restore();
  17. }
  18. void
  19. yytangent(void)
  20. {
  21. int n;
  22. double d;
  23. p1 = pop();
  24. if (car(p1) == symbol(ARCTAN)) {
  25. push(cadr(p1));
  26. return;
  27. }
  28. if (isdouble(p1)) {
  29. d = tan(p1->u.d);
  30. if (fabs(d) < 1e-10)
  31. d = 0.0;
  32. push_double(d);
  33. return;
  34. }
  35. // tan function is antisymmetric, tan(-x) = -tan(x)
  36. if (isnegative(p1)) {
  37. push(p1);
  38. negate();
  39. tangent();
  40. negate();
  41. return;
  42. }
  43. // multiply by 180/pi
  44. push(p1);
  45. push_integer(180);
  46. multiply();
  47. push_symbol(PI);
  48. divide();
  49. n = pop_integer();
  50. if (n < 0) {
  51. push(symbol(TAN));
  52. push(p1);
  53. list(2);
  54. return;
  55. }
  56. switch (n % 360) {
  57. case 0:
  58. case 180:
  59. push_integer(0);
  60. break;
  61. case 30:
  62. case 210:
  63. push_rational(1, 3);
  64. push_integer(3);
  65. push_rational(1, 2);
  66. power();
  67. multiply();
  68. break;
  69. case 150:
  70. case 330:
  71. push_rational(-1, 3);
  72. push_integer(3);
  73. push_rational(1, 2);
  74. power();
  75. multiply();
  76. break;
  77. case 45:
  78. case 225:
  79. push_integer(1);
  80. break;
  81. case 135:
  82. case 315:
  83. push_integer(-1);
  84. break;
  85. case 60:
  86. case 240:
  87. push_integer(3);
  88. push_rational(1, 2);
  89. power();
  90. break;
  91. case 120:
  92. case 300:
  93. push_integer(3);
  94. push_rational(1, 2);
  95. power();
  96. negate();
  97. break;
  98. default:
  99. push(symbol(TAN));
  100. push(p1);
  101. list(2);
  102. break;
  103. }
  104. }
  105. #if SELFTEST
  106. static char *s[] = {
  107. "tan(x)",
  108. "tan(x)",
  109. "tan(-x)",
  110. "-tan(x)",
  111. "tan(b-a)",
  112. "-tan(a-b)",
  113. // check against the floating point math library
  114. "f(a,x)=1+tan(float(a/360*2*pi))-float(x)+tan(a/360*2*pi)-x",
  115. "",
  116. "f(0,0)", // 0
  117. "1",
  118. "f(180,0)", // 180
  119. "1",
  120. "f(360,0)", // 360
  121. "1",
  122. "f(-180,0)", // -180
  123. "1",
  124. "f(-360,0)", // -360
  125. "1",
  126. "f(45,1)", // 45
  127. "1",
  128. "f(135,-1)", // 135
  129. "1",
  130. "f(225,1)", // 225
  131. "1",
  132. "f(315,-1)", // 315
  133. "1",
  134. "f(-45,-1)", // -45
  135. "1",
  136. "f(-135,1)", // -135
  137. "1",
  138. "f(-225,-1)", // -225
  139. "1",
  140. "f(-315,1)", // -315
  141. "1",
  142. "f(30,sqrt(3)/3)", // 30
  143. "1",
  144. "f(150,-sqrt(3)/3)", // 150
  145. "1",
  146. "f(210,sqrt(3)/3)", // 210
  147. "1",
  148. "f(330,-sqrt(3)/3)", // 330
  149. "1",
  150. "f(-30,-sqrt(3)/3)", // -30
  151. "1",
  152. "f(-150,sqrt(3)/3)", // -150
  153. "1",
  154. "f(-210,-sqrt(3)/3)", // -210
  155. "1",
  156. "f(-330,sqrt(3)/3)", // -330
  157. "1",
  158. "f(60,sqrt(3))", // 60
  159. "1",
  160. "f(120,-sqrt(3))", // 120
  161. "1",
  162. "f(240,sqrt(3))", // 240
  163. "1",
  164. "f(300,-sqrt(3))", // 300
  165. "1",
  166. "f(-60,-sqrt(3))", // -60
  167. "1",
  168. "f(-120,sqrt(3))", // -120
  169. "1",
  170. "f(-240,-sqrt(3))", // -240
  171. "1",
  172. "f(-300,sqrt(3))", // -300
  173. "1",
  174. "f=quote(f)",
  175. "",
  176. "tan(arctan(x))",
  177. "x",
  178. // check the default case
  179. "tan(1/12*pi)",
  180. "tan(1/12*pi)",
  181. };
  182. void
  183. test_tan(void)
  184. {
  185. test(__FILE__, s, sizeof s / sizeof (char *));
  186. }
  187. #endif