tan.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  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 <u.h>
  7. #include <libc.h>
  8. static double p0 = -0.1306820264754825668269611177e+5;
  9. static double p1 = 0.1055970901714953193602353981e+4;
  10. static double p2 = -0.1550685653483266376941705728e+2;
  11. static double p3 = 0.3422554387241003435328470489e-1;
  12. static double p4 = 0.3386638642677172096076369e-4;
  13. static double q0 = -0.1663895238947119001851464661e+5;
  14. static double q1 = 0.4765751362916483698926655581e+4;
  15. static double q2 = -0.1555033164031709966900124574e+3;
  16. double
  17. tan(double arg)
  18. {
  19. double temp, e, x, xsq;
  20. int flag, sign, i;
  21. flag = 0;
  22. sign = 0;
  23. if(arg < 0){
  24. arg = -arg;
  25. sign++;
  26. }
  27. arg = 2*arg/PIO2; /* overflow? */
  28. x = modf(arg, &e);
  29. i = e;
  30. switch(i%4) {
  31. case 1:
  32. x = 1 - x;
  33. flag = 1;
  34. break;
  35. case 2:
  36. sign = !sign;
  37. flag = 1;
  38. break;
  39. case 3:
  40. x = 1 - x;
  41. sign = !sign;
  42. break;
  43. case 0:
  44. break;
  45. }
  46. xsq = x*x;
  47. temp = ((((p4*xsq+p3)*xsq+p2)*xsq+p1)*xsq+p0)*x;
  48. temp = temp/(((xsq+q2)*xsq+q1)*xsq+q0);
  49. if(flag) {
  50. if(temp == 0)
  51. return NaN();
  52. temp = 1/temp;
  53. }
  54. if(sign)
  55. temp = -temp;
  56. return temp;
  57. }