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.

291 lines
6.8 KiB

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