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.

135 lines
3.2 KiB

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