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.

219 lines
5.6 KiB

  1. /***
  2. *sincosh.c - hyperbolic sine and cosine
  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-20-91 GDP support IEEE exceptions
  11. * 02-03-92 GDP use _exphlp for computing e^x
  12. * 06-23-92 GDP sinh(denormal) now raises underflow exception (NCEG)
  13. * 07-16-93 SRW ALPHA Merge
  14. * 11-18-93 GJF Merged in NT SDK version.
  15. * 02-06-95 JWM Mac merge
  16. * 05-17-99 PML Remove all Macintosh support.
  17. * 07-15-01 PML Remove all ALPHA, MIPS, and PPC code
  18. *
  19. *******************************************************************************/
  20. #include <math.h>
  21. #include <trans.h>
  22. extern double _exphlp(double, int *);
  23. static double const EPS = 5.16987882845642297e-26; /* 2^(-53) / 2 */
  24. /* exp(YBAR) should be close to but less than XMAX
  25. * and 1/exp(YBAR) should not underflow
  26. */
  27. static double const YBAR = 7.00e2;
  28. /* WMAX=ln(OVFX)+0.69 (Cody & Waite),ommited LNV, used OVFX instead of BIGX */
  29. static double const WMAX = 1.77514678223345998953e+003;
  30. /* constants for the rational approximation */
  31. static double const p0 = -0.35181283430177117881e+6;
  32. static double const p1 = -0.11563521196851768270e+5;
  33. static double const p2 = -0.16375798202630751372e+3;
  34. static double const p3 = -0.78966127417357099479e+0;
  35. static double const q0 = -0.21108770058106271242e+7;
  36. static double const q1 = 0.36162723109421836460e+5;
  37. static double const q2 = -0.27773523119650701667e+3;
  38. /* q3 = 1 is not used (avoid myltiplication by 1) */
  39. #define P(f) (((p3 * (f) + p2) * (f) + p1) * (f) + p0)
  40. #define Q(f) ((((f) + q2) * (f) + q1) * (f) + q0)
  41. #if !defined(_M_AMD64)
  42. #pragma function(sinh, cosh)
  43. #endif
  44. /***
  45. *double sinh(double x) - hyperbolic sine
  46. *
  47. *Purpose:
  48. * Compute the hyperbolic sine of a number.
  49. * The algorithm (reduction / rational approximation) is
  50. * taken from Cody & Waite.
  51. *
  52. *Entry:
  53. *
  54. *Exit:
  55. *
  56. *Exceptions:
  57. * I P
  58. * no exception if x is denormal: return x
  59. *******************************************************************************/
  60. double sinh(double x)
  61. {
  62. uintptr_t savedcw;
  63. double result;
  64. double y,f,z,r;
  65. int newexp;
  66. int sgn;
  67. /* save user fp control word */
  68. savedcw = _maskfp();
  69. if (IS_D_SPECIAL(x)){
  70. switch(_sptype(x)) {
  71. case T_PINF:
  72. case T_NINF:
  73. RETURN(savedcw,x);
  74. case T_QNAN:
  75. return _handle_qnan1(OP_SINH, x, savedcw);
  76. default: //T_SNAN
  77. return _except1(FP_I,OP_SINH,x,_s2qnan(x),savedcw);
  78. }
  79. }
  80. if (x == 0.0) {
  81. RETURN(savedcw,x); // no precision ecxeption
  82. }
  83. y = ABS(x);
  84. sgn = x<0 ? -1 : +1;
  85. if (y > 1.0) {
  86. if (y > YBAR) {
  87. if (y > WMAX) {
  88. // result too large, even after scaling
  89. return _except1(FP_O | FP_P,OP_SINH,x,x*D_INF,savedcw);
  90. }
  91. //
  92. // result = exp(y)/2
  93. //
  94. result = _exphlp(y, &newexp);
  95. newexp --; //divide by 2
  96. if (newexp > MAXEXP) {
  97. result = _set_exp(result, newexp-IEEE_ADJUST);
  98. return _except1(FP_O|FP_P,OP_SINH,x,result,savedcw);
  99. }
  100. else {
  101. result = _set_exp(result, newexp);
  102. }
  103. }
  104. else {
  105. z = _exphlp(y, &newexp);
  106. z = _set_exp(z, newexp);
  107. result = (z - 1/z) / 2;
  108. }
  109. if (sgn < 0) {
  110. result = -result;
  111. }
  112. }
  113. else {
  114. if (y < EPS) {
  115. result = x;
  116. if (IS_D_DENORM(result)) {
  117. return _except1(FP_U | FP_P,OP_SINH,x,_add_exp(result, IEEE_ADJUST),savedcw);
  118. }
  119. }
  120. else {
  121. f = x * x;
  122. r = f * (P(f) / Q(f));
  123. result = x + x * r;
  124. }
  125. }
  126. RETURN_INEXACT1(OP_SINH,x,result,savedcw);
  127. }
  128. /***
  129. *double cosh(double x) - hyperbolic cosine
  130. *
  131. *Purpose:
  132. * Compute the hyperbolic cosine of a number.
  133. * The algorithm (reduction / rational approximation) is
  134. * taken from Cody & Waite.
  135. *
  136. *Entry:
  137. *
  138. *Exit:
  139. *
  140. *Exceptions:
  141. * I P
  142. * no exception if x is denormal: return 1
  143. *******************************************************************************/
  144. double cosh(double x)
  145. {
  146. uintptr_t savedcw;
  147. double y,z,result;
  148. int newexp;
  149. /* save user fp control word */
  150. savedcw = _maskfp();
  151. if (IS_D_SPECIAL(x)){
  152. switch(_sptype(x)) {
  153. case T_PINF:
  154. case T_NINF:
  155. RETURN(savedcw,D_INF);
  156. case T_QNAN:
  157. return _handle_qnan1(OP_COSH, x, savedcw);
  158. default: //T_SNAN
  159. return _except1(FP_I,OP_COSH,x,_s2qnan(x),savedcw);
  160. }
  161. }
  162. if (x == 0.0) {
  163. RETURN(savedcw,1.0);
  164. }
  165. y = ABS(x);
  166. if (y > YBAR) {
  167. if (y > WMAX) {
  168. return _except1(FP_O | FP_P,OP_COSH,x,D_INF,savedcw);
  169. }
  170. //
  171. // result = exp(y)/2
  172. //
  173. result = _exphlp(y, &newexp);
  174. newexp --; //divide by 2
  175. if (newexp > MAXEXP) {
  176. result = _set_exp(result, newexp-IEEE_ADJUST);
  177. return _except1(FP_O|FP_P,OP_COSH,x,result,savedcw);
  178. }
  179. else {
  180. result = _set_exp(result, newexp);
  181. }
  182. }
  183. else {
  184. z = _exphlp(y, &newexp);
  185. z = _set_exp(z, newexp);
  186. result = (z + 1/z) / 2;
  187. }
  188. RETURN_INEXACT1(OP_COSH,x,result,savedcw);
  189. }