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.

188 lines
4.8 KiB

  1. /***
  2. *asincos.c - inverse sin, cos
  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-26-91 GDP support IEEE exceptions
  11. * 06-23-92 GDP asin(denormal) now raises underflow exception
  12. * 02-06-95 JWM Mac merge
  13. * 10-07-97 RDL Added IA64.
  14. *
  15. *******************************************************************************/
  16. #include <math.h>
  17. #include <trans.h>
  18. #if defined(_M_IA64)
  19. #pragma function(asin, acos)
  20. #endif
  21. static double _asincos(double x, int flag);
  22. static double const a[2] = {
  23. 0.0,
  24. 0.78539816339744830962
  25. };
  26. static double const b[2] = {
  27. 1.57079632679489661923,
  28. 0.78539816339744830962
  29. };
  30. static double const EPS = 1.05367121277235079465e-8; /* 2^(-53/2) */
  31. /* constants for the rational approximation */
  32. static double const p1 = -0.27368494524164255994e+2;
  33. static double const p2 = 0.57208227877891731407e+2;
  34. static double const p3 = -0.39688862997504877339e+2;
  35. static double const p4 = 0.10152522233806463645e+2;
  36. static double const p5 = -0.69674573447350646411e+0;
  37. static double const q0 = -0.16421096714498560795e+3;
  38. static double const q1 = 0.41714430248260412556e+3;
  39. static double const q2 = -0.38186303361750149284e+3;
  40. static double const q3 = 0.15095270841030604719e+3;
  41. static double const q4 = -0.23823859153670238830e+2;
  42. /* q5 = 1 is not needed (avoid myltiplying by 1) */
  43. #define Q(g) (((((g + q4) * g + q3) * g + q2) * g + q1) * g + q0)
  44. #define R(g) (((((p5 * g + p4) * g + p3) * g + p2) * g + p1) * g) / Q(g)
  45. /***
  46. *double asin(double x) - inverse sin
  47. *double acos(double x) - inverse cos
  48. *
  49. *Purpose:
  50. * Compute arc sin, arc cos.
  51. * The algorithm (reduction / rational approximation) is
  52. * taken from Cody & Waite.
  53. *
  54. *Entry:
  55. *
  56. *Exit:
  57. *
  58. *Exceptions:
  59. * P, I
  60. * (denormals are accepted)
  61. *******************************************************************************/
  62. double asin(double x)
  63. {
  64. return _asincos(x,0);
  65. }
  66. double acos(double x)
  67. {
  68. return _asincos(x,1);
  69. }
  70. static double _asincos(double x, int flag)
  71. {
  72. uintptr_t savedcw;
  73. double qnan;
  74. int who;
  75. double y,result;
  76. double g;
  77. int i;
  78. /* save user fp control word */
  79. savedcw = _maskfp();
  80. if (flag) {
  81. who = OP_ACOS;
  82. qnan = QNAN_ACOS;
  83. }
  84. else {
  85. who = OP_ASIN;
  86. qnan = QNAN_ASIN;
  87. }
  88. /* check for infinity or NAN */
  89. if (IS_D_SPECIAL(x)){
  90. switch(_sptype(x)) {
  91. case T_PINF:
  92. case T_NINF:
  93. return _except1(FP_I,who,x,qnan,savedcw);
  94. case T_QNAN:
  95. return _handle_qnan1(who,x,savedcw);
  96. default: //T_SNAN
  97. return _except1(FP_I,who,x,_s2qnan(x),savedcw);
  98. }
  99. }
  100. // do test for zero after making sure that x is not special
  101. // because the compiler does not handle NaNs for the time
  102. if (x == 0.0 && !flag) {
  103. RETURN(savedcw, x);
  104. }
  105. y = ABS(x);
  106. if (y < EPS) {
  107. i = flag;
  108. result = y;
  109. if (IS_D_DENORM(result)) {
  110. // this should only happen for sin(denorm). Use x as a result
  111. return _except1(FP_U | FP_P,who,x,_add_exp(x, IEEE_ADJUST),savedcw);
  112. }
  113. }
  114. else {
  115. if (y > .5) {
  116. i = 1-flag;
  117. if (y > 1.0) {
  118. return _except1(FP_I,who,x,qnan,savedcw);
  119. }
  120. else if (y == 1.0) {
  121. /* separate case to avoid domain error in sqrt */
  122. if (flag && x >= 0.0) {
  123. //
  124. // acos(1.0) is exactly computed as 0.0
  125. //
  126. RETURN(savedcw, 0.0);
  127. }
  128. y = 0.0;
  129. g = 0.0;
  130. }
  131. else {
  132. /* now even if y is as close to 1 as possible,
  133. * 1-y is still not a denormal.
  134. * e.g. for y=3fefffffffffffff, 1-y is about 10^(-16)
  135. * So we can speed up division
  136. */
  137. g = _add_exp(1.0 - y,-1);
  138. /* g and sqrt(g) are not denomrals either,
  139. * even in the worst case
  140. * So we can speed up multiplication
  141. */
  142. y = _add_exp(-_fsqrt(g),1);
  143. }
  144. }
  145. else {
  146. /* y <= .5 */
  147. i = flag;
  148. g = y*y;
  149. }
  150. result = y + y * R(g);
  151. }
  152. if (flag == 0) {
  153. /* compute asin */
  154. if (i) {
  155. /* a[i] is non zero if i is nonzero */
  156. result = (a[i] + result) + a[i];
  157. }
  158. if (x < 0)
  159. result = -result;
  160. }
  161. else {
  162. /* compute acos */
  163. if (x < 0)
  164. result = (b[i] + result) + b[i];
  165. else
  166. result = (a[i] - result) + a[i];
  167. }
  168. RETURN_INEXACT1 (who,x,result,savedcw);
  169. }