tan.c 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /*
  2. floating point tangent
  3. A series is used after range reduction.
  4. Coefficients are #4285 from Hart & Cheney. (19.74D)
  5. */
  6. #include <math.h>
  7. #include <errno.h>
  8. static double invpi = 1.27323954473516268;
  9. static double p0 = -0.1306820264754825668269611177e+5;
  10. static double p1 = 0.1055970901714953193602353981e+4;
  11. static double p2 = -0.1550685653483266376941705728e+2;
  12. static double p3 = 0.3422554387241003435328470489e-1;
  13. static double p4 = 0.3386638642677172096076369e-4;
  14. static double q0 = -0.1663895238947119001851464661e+5;
  15. static double q1 = 0.4765751362916483698926655581e+4;
  16. static double q2 = -0.1555033164031709966900124574e+3;
  17. double
  18. tan(double arg)
  19. {
  20. double sign, temp, e, x, xsq;
  21. int flag, i;
  22. flag = 0;
  23. sign = 1;
  24. if(arg < 0){
  25. arg = -arg;
  26. sign = -1;
  27. }
  28. arg = arg*invpi; /* overflow? */
  29. x = modf(arg, &e);
  30. i = e;
  31. switch(i%4) {
  32. case 1:
  33. x = 1 - x;
  34. flag = 1;
  35. break;
  36. case 2:
  37. sign = - sign;
  38. flag = 1;
  39. break;
  40. case 3:
  41. x = 1 - x;
  42. sign = - sign;
  43. break;
  44. case 0:
  45. break;
  46. }
  47. xsq = x*x;
  48. temp = ((((p4*xsq+p3)*xsq+p2)*xsq+p1)*xsq+p0)*x;
  49. temp = temp/(((xsq+q2)*xsq+q1)*xsq+q0);
  50. if(flag == 1) {
  51. if(temp == 0) {
  52. errno = EDOM;
  53. if (sign > 0)
  54. return HUGE_VAL;
  55. return -HUGE_VAL;
  56. }
  57. temp = 1/temp;
  58. }
  59. return sign*temp;
  60. }