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.

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