Leaked source code of windows server 2003
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.

108 lines
2.8 KiB

  1. /***
  2. *tanh.c - hyperbolic 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-22-91 GDP support IEEE exceptions
  11. * 06-23-92 GDP tanh(denormal) now raises underflow exception (NCEG)
  12. * 02-06-95 JWM Mac merge
  13. * 05-17-99 PML Remove all Macintosh support.
  14. * 07-15-01 PML Remove all ALPHA, MIPS, and PPC code
  15. *
  16. *******************************************************************************/
  17. #include <math.h>
  18. #include <trans.h>
  19. /* constants */
  20. static double const EPS = 5.16987882845642297e-26; /* 2^(-53) / 2 */
  21. static double const XBIG = 1.90615474653984960096e+001; /* ln(2)(53+2)/2 */
  22. static double const C0 = 0.54930614433405484570; /* ln(3)/2 */
  23. /* constants for rational approximation */
  24. static double const p0 = -0.16134119023996228053e+4;
  25. static double const p1 = -0.99225929672236083313e+2;
  26. static double const p2 = -0.96437492777225469787e+0;
  27. static double const q0 = 0.48402357071988688686e+4;
  28. static double const q1 = 0.22337720718962312926e+4;
  29. static double const q2 = 0.11274474380534949335e+3;
  30. static double const q3 = 0.10000000000000000000e+1;
  31. #define Q(g) ((((g) + q2) * (g) + q1) * (g) + q0)
  32. #define R(g) ((((p2 * (g) + p1) * (g) + p0) * (g)) / Q(g))
  33. #if !defined(_M_AMD64)
  34. #pragma function(tanh)
  35. #endif
  36. /***
  37. *double tanh(double x) - hyperbolic tangent
  38. *
  39. *Purpose:
  40. * Compute the hyperbolic tangent of a number.
  41. * The algorithm (reduction / rational approximation) is
  42. * taken from Cody & Waite.
  43. *
  44. *Entry:
  45. *
  46. *Exit:
  47. *
  48. *Exceptions:
  49. * I P
  50. *******************************************************************************/
  51. double tanh(double x)
  52. {
  53. uintptr_t savedcw;
  54. double f,g;
  55. double result;
  56. /* save user fp control word */
  57. savedcw = _maskfp();
  58. if (IS_D_SPECIAL(x)){
  59. switch(_sptype(x)) {
  60. case T_PINF:
  61. RETURN(savedcw,1.0);
  62. case T_NINF:
  63. RETURN(savedcw,-1.0);
  64. case T_QNAN:
  65. return _handle_qnan1(OP_TANH, x, savedcw);
  66. default: //T_SNAN
  67. return _except1(FP_I,OP_TANH,x,_s2qnan(x),savedcw);
  68. }
  69. }
  70. if (x == 0.0) {
  71. // no precision exception
  72. RETURN(savedcw,x);
  73. }
  74. f = ABS(x);
  75. if (f > XBIG) {
  76. result = 1;
  77. }
  78. else if (f > C0) {
  79. result = 0.5 - 1.0 / (exp(f+f) + 1.0);
  80. result = result + result;
  81. }
  82. else if (f < EPS) {
  83. result = f;
  84. if (IS_D_DENORM(result)) {
  85. return _except1(FP_U | FP_P,OP_TANH,x,_add_exp(x, IEEE_ADJUST),savedcw);
  86. }
  87. }
  88. else {
  89. g = f * f;
  90. result = f + f * R(g);
  91. }
  92. if (x < 0)
  93. result = -result;
  94. RETURN_INEXACT1(OP_TANH,x,result,savedcw);
  95. }