Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
3.5 KiB

  1. /***
  2. *tan.c - tangent
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 8-15-91 GDP written
  10. * 12-30-91 GDP support IEEE exceptions
  11. * 03-11-91 GDP use 66 significant bits for representing pi
  12. * support FP_TLOSS
  13. * 06-23-92 GDP tan(denormal) now raises underflow exception
  14. * 02-06-95 JWM Mac merge
  15. * 10-07-97 RDL Added IA64.
  16. *
  17. *******************************************************************************/
  18. #include <math.h>
  19. #include <trans.h>
  20. #if defined(_M_IA64)
  21. #pragma function(tan)
  22. #endif
  23. /* constants */
  24. static double const TWO_OVER_PI = 0.63661977236758134308;
  25. static double const EPS = 1.05367121277235079465e-8; /* 2^(-53/2) */
  26. static double const YMAX = 2.98156826864790199324e8; /* 2^(53/2)*PI/2 */
  27. //
  28. // The sum of C1 and C2 is a representation of PI/2 with 66 bits in the
  29. // significand (same as x87). (PI/2 = 2 * 0.c90fdaa2 2168c234 c h)
  30. //
  31. static _dbl _C1 = {SET_DBL (0x3ff921fb, 0x54400000)};
  32. static _dbl _C2 = {SET_DBL (0x3dd0b461, 0x1a600000)};
  33. #define C1 (_C1.dbl)
  34. #define C2 (_C2.dbl)
  35. /* constants for the rational approximation */
  36. /* p0 = 1.0 is not used (avoid mult by 1) */
  37. static double const p1 = -0.13338350006421960681e+0;
  38. static double const p2 = 0.34248878235890589960e-2;
  39. static double const p3 = -0.17861707342254426711e-4;
  40. static double const q0 = 0.10000000000000000000e+1;
  41. static double const q1 = -0.46671683339755294240e+0;
  42. static double const q2 = 0.25663832289440112864e-1;
  43. static double const q3 = -0.31181531907010027307e-3;
  44. static double const q4 = 0.49819433993786512270e-6;
  45. #define Q(g) ((((q4 * (g) + q3) * (g) + q2) * (g) + q1) * (g) + q0)
  46. #define P(g,f) (((p3 * (g) + p2) * (g) + p1) * (g) * (f) + (f))
  47. #define ISODD(i) ((i)&0x1)
  48. /***
  49. *double tan(double x) - tangent
  50. *
  51. *Purpose:
  52. * Compute the tangent of a number.
  53. * The algorithm (reduction / rational approximation) is
  54. * taken from Cody & Waite.
  55. *
  56. *Entry:
  57. *
  58. *Exit:
  59. *
  60. *Exceptions:
  61. * P, I, U
  62. * if x is denormal: raise underflow
  63. *******************************************************************************/
  64. double tan(double x)
  65. {
  66. uintptr_t savedcw;
  67. unsigned long n;
  68. double xn,xnum,xden;
  69. double f,g,result;
  70. /* save user fp control word */
  71. savedcw = _maskfp();
  72. if (IS_D_SPECIAL(x)){
  73. switch(_sptype(x)) {
  74. case T_PINF:
  75. case T_NINF:
  76. return _except1(FP_I,OP_TAN,x,QNAN_TAN1,savedcw);
  77. case T_QNAN:
  78. return _handle_qnan1(OP_TAN, x, savedcw);
  79. default: //T_SNAN
  80. return _except1(FP_I,OP_TAN,x,_s2qnan(x),savedcw);
  81. }
  82. }
  83. if (x == 0.0)
  84. RETURN(savedcw, x);
  85. if (ABS(x) > YMAX) {
  86. // The argument is too large to produce a meaningful result,
  87. // so this is treated as an invalid operation.
  88. // We also set the (extra) FP_TLOSS flag for matherr
  89. // support
  90. return _except1(FP_TLOSS | FP_I,OP_TAN,x,QNAN_TAN2,savedcw);
  91. }
  92. xn = _frnd(x * TWO_OVER_PI);
  93. n = (unsigned long) fabs(xn);
  94. /* assume there is a guard digit for addition */
  95. f = (x - xn * C1) - xn * C2;
  96. if (ABS(f) < EPS) {
  97. xnum = f;
  98. xden = 1;
  99. if (IS_D_DENORM(f)) {
  100. return _except1(FP_U | FP_P,OP_TAN,x,_add_exp(f, IEEE_ADJUST),savedcw);
  101. }
  102. }
  103. else {
  104. g = f*f;
  105. xnum = P(g,f);
  106. xden = Q(g);
  107. }
  108. if (ISODD(n)) {
  109. xnum = -xnum;
  110. result = xden/xnum;
  111. }
  112. else
  113. result = xnum/xden;
  114. RETURN_INEXACT1(OP_TAN,x,result,savedcw);
  115. }