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.

292 lines
6.2 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. atan.c
  5. Abstract:
  6. This module implements arithmatic tan function used in wow.
  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. static double _atanhlp(double x);
  14. static double const a[4] = {
  15. 0.0,
  16. 0.52359877559829887308, /* pi/6 */
  17. 1.57079632679489661923, /* pi/2 */
  18. 1.04719755119659774615 /* pi/3 */
  19. };
  20. /* constants */
  21. static double const EPS = 1.05367121277235079465e-8; /* 2^(-53/2) */
  22. static double const PI_OVER_TWO = 1.57079632679489661923;
  23. static double const PI = 3.14159265358979323846;
  24. static double const TWO_M_SQRT3 = 0.26794919243112270647;
  25. static double const SQRT3_M_ONE = 0.73205080756887729353;
  26. static double const SQRT3 = 1.73205080756887729353;
  27. /* chose MAX_ARG s.t. 1/MAX_ARG does not underflow */
  28. static double const MAX_ARG = 4.494232837155790e+307;
  29. /* constants for rational approximation */
  30. static double const p0 = -0.13688768894191926929e+2;
  31. static double const p1 = -0.20505855195861651981e+2;
  32. static double const p2 = -0.84946240351320683534e+1;
  33. static double const p3 = -0.83758299368150059274e+0;
  34. static double const q0 = 0.41066306682575781263e+2;
  35. static double const q1 = 0.86157349597130242515e+2;
  36. static double const q2 = 0.59578436142597344465e+2;
  37. static double const q3 = 0.15024001160028576121e+2;
  38. static double const q4 = 0.10000000000000000000e+1;
  39. #define Q(g) (((((g) + q3) * (g) + q2) * (g) + q1) * (g) + q0)
  40. #define R(g) ((((p3 * (g) + p2) * (g) + p1) * (g) + p0) * (g)) / Q(g)
  41. /***
  42. *double atan(double x) - arctangent
  43. *
  44. *Purpose:
  45. *
  46. *Entry:
  47. *
  48. *Exit:
  49. *
  50. *Exceptions:
  51. * P, I
  52. \*******************************************************************************/
  53. double Proxyatan(double x)
  54. {
  55. unsigned int savedcw;
  56. double result;
  57. /* save user fp control word */
  58. savedcw = _maskfp();
  59. /* check for infinity or NAN */
  60. if (IS_D_SPECIAL(x)){
  61. switch(_sptype(x)) {
  62. case T_PINF:
  63. result = PI_OVER_TWO;
  64. break;
  65. case T_NINF:
  66. result = -PI_OVER_TWO;
  67. break;
  68. case T_QNAN:
  69. return _handle_qnan1(OP_ATAN,x,savedcw);
  70. default: //T_SNAN
  71. return _except1(FP_I,OP_ATAN,x,_s2qnan(x),savedcw);
  72. }
  73. }
  74. if (x == 0.0)
  75. RETURN(savedcw,x);
  76. result = _atanhlp(x);
  77. RETURN_INEXACT1(OP_ATAN,x,result,savedcw);
  78. }
  79. /***
  80. *double atan2(double x, double y) - arctangent (x/y)
  81. *
  82. *Purpose:
  83. *
  84. *Entry:
  85. *
  86. *Exit:
  87. *
  88. *Exceptions:
  89. * NAN or both args 0: DOMAIN error
  90. *******************************************************************************/
  91. double Proxyatan2(double v, double u)
  92. {
  93. unsigned int savedcw;
  94. double result;
  95. /* save user fp control word */
  96. savedcw = _maskfp();
  97. /* check for infinity or NAN */
  98. if (IS_D_SPECIAL(v) || IS_D_SPECIAL(u)){
  99. if (IS_D_SNAN(v) || IS_D_SNAN(u)){
  100. return _except2(FP_I,OP_ATAN2,v,u,_d_snan2(v,u),savedcw);
  101. }
  102. if (IS_D_QNAN(v) || IS_D_QNAN(u)){
  103. return _handle_qnan2(OP_ATAN2,v,u,savedcw);
  104. }
  105. if ((IS_D_INF(v) || IS_D_MINF(v)) &&
  106. (IS_D_INF(u) || IS_D_MINF(u))){
  107. return _except2(FP_I,OP_ATAN2,v,u,QNAN_ATAN2,savedcw);
  108. }
  109. /* the other combinations of infinities will be handled
  110. * later by the division v/u
  111. */
  112. }
  113. if (u == 0) {
  114. if (v == 0) {
  115. return _except2(FP_I,OP_ATAN2,v,u,QNAN_ATAN2,savedcw);
  116. }
  117. else {
  118. result = PI_OVER_TWO;
  119. }
  120. }
  121. else if (INTEXP(v) - INTEXP(u) > MAXEXP - 3) {
  122. /* v/u overflow */
  123. result = PI_OVER_TWO;
  124. }
  125. else {
  126. double arg = v/u;
  127. if (ABS(arg) < D_MIN) {
  128. if (v == 0.0 || IS_D_INF(u) || IS_D_MINF(u)) {
  129. result = (u < 0) ? PI : 0;
  130. if (v < 0) {
  131. result = -result;
  132. }
  133. if (result == 0) {
  134. RETURN(savedcw, result);
  135. }
  136. else {
  137. RETURN_INEXACT2(OP_ATAN2,v,u,result,savedcw);
  138. }
  139. }
  140. else {
  141. double v1, u1;
  142. int vexp, uexp;
  143. int exc_flags;
  144. //
  145. // in this case an underflow has occurred
  146. // re-compute the result in order to raise
  147. // an IEEE underflow exception
  148. //
  149. if (u < 0) {
  150. result = v < 0 ? -PI: PI;
  151. RETURN_INEXACT2(OP_ATAN2,v,u,result,savedcw);
  152. }
  153. v1 = _decomp(v, &vexp);
  154. u1 = _decomp(u, &uexp);
  155. result = _add_exp(v1/u1, vexp-uexp+IEEE_ADJUST);
  156. result = ABS(result);
  157. if (v < 0) {
  158. result = -result;
  159. }
  160. // this is not a perfect solution. In the future
  161. // we may want to have a way to let the division
  162. // generate an exception and propagate the IEEE result
  163. // to the user's handler
  164. exc_flags = FP_U;
  165. if (_statfp() & ISW_INEXACT) {
  166. exc_flags |= FP_P;
  167. }
  168. return _except2(exc_flags,OP_ATAN2,v,u,result,savedcw);
  169. }
  170. }
  171. else {
  172. result = _atanhlp( ABS(arg) );
  173. }
  174. }
  175. /* set sign of the result */
  176. if (u < 0) {
  177. result = PI - result;
  178. }
  179. if (v < 0) {
  180. result = -result;
  181. }
  182. RETURN_INEXACT2(OP_ATAN2,v,u,result,savedcw);
  183. }
  184. /***
  185. *double _atanhlp(double x) - arctangent helper
  186. *
  187. *Purpose:
  188. * Compute arctangent of x, assuming x is a valid, non infinite
  189. * number.
  190. * The algorithm (reduction / rational approximation) is
  191. * taken from Cody & Waite.
  192. *
  193. *Entry:
  194. *
  195. *Exit:
  196. *
  197. *Exceptions:
  198. *
  199. *******************************************************************************/
  200. static double _atanhlp(double x)
  201. {
  202. double f,g,result;
  203. int n;
  204. f = ABS(x);
  205. if (f > MAX_ARG) {
  206. // if this step is ommited, 1.0/f might underflow in the
  207. // following block
  208. return x > 0.0 ? PI_OVER_TWO : -PI_OVER_TWO;
  209. }
  210. if (f > 1.0) {
  211. f = 1.0/f;
  212. n = 2;
  213. }
  214. else {
  215. n = 0;
  216. }
  217. if (f > TWO_M_SQRT3) {
  218. f = (((SQRT3_M_ONE * f - .5) - .5) + f) / (SQRT3 + f);
  219. n++;
  220. }
  221. if (ABS(f) < EPS) {
  222. result = f;
  223. }
  224. else {
  225. g = f*f;
  226. result = f + f * R(g);
  227. }
  228. if (n > 1)
  229. result = -result;
  230. result += a[n];
  231. if (x < 0.0)
  232. result = -result;
  233. return result;
  234. }