asin.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /* asin.c
  2. *
  3. * Inverse circular sine
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * double x, y, asin();
  10. *
  11. * y = asin( x );
  12. *
  13. *
  14. *
  15. * DESCRIPTION:
  16. *
  17. * Returns radian angle between -pi/2 and +pi/2 whose sine is x.
  18. *
  19. * A rational function of the form x + x**3 P(x**2)/Q(x**2)
  20. * is used for |x| in the interval [0, 0.5]. If |x| > 0.5 it is
  21. * transformed by the identity
  22. *
  23. * asin(x) = pi/2 - 2 asin( sqrt( (1-x)/2 ) ).
  24. *
  25. *
  26. * ACCURACY:
  27. *
  28. * Relative error:
  29. * arithmetic domain # trials peak rms
  30. * DEC -1, 1 40000 2.6e-17 7.1e-18
  31. * IEEE -1, 1 10^6 1.9e-16 5.4e-17
  32. *
  33. *
  34. * ERROR MESSAGES:
  35. *
  36. * message condition value returned
  37. * asin domain |x| > 1 NAN
  38. *
  39. */
  40. /* acos()
  41. *
  42. * Inverse circular cosine
  43. *
  44. *
  45. *
  46. * SYNOPSIS:
  47. *
  48. * double x, y, acos();
  49. *
  50. * y = acos( x );
  51. *
  52. *
  53. *
  54. * DESCRIPTION:
  55. *
  56. * Returns radian angle between 0 and pi whose cosine
  57. * is x.
  58. *
  59. * Analytically, acos(x) = pi/2 - asin(x). However if |x| is
  60. * near 1, there is cancellation error in subtracting asin(x)
  61. * from pi/2. Hence if x < -0.5,
  62. *
  63. * acos(x) = pi - 2.0 * asin( sqrt((1+x)/2) );
  64. *
  65. * or if x > +0.5,
  66. *
  67. * acos(x) = 2.0 * asin( sqrt((1-x)/2) ).
  68. *
  69. *
  70. * ACCURACY:
  71. *
  72. * Relative error:
  73. * arithmetic domain # trials peak rms
  74. * DEC -1, 1 50000 3.3e-17 8.2e-18
  75. * IEEE -1, 1 10^6 2.2e-16 6.5e-17
  76. *
  77. *
  78. * ERROR MESSAGES:
  79. *
  80. * message condition value returned
  81. * asin domain |x| > 1 NAN
  82. */
  83. /* asin.c */
  84. /*
  85. Cephes Math Library Release 2.8: June, 2000
  86. Copyright 1984, 1995, 2000 by Stephen L. Moshier
  87. */
  88. #include "mconf.h"
  89. /* arcsin(x) = x + x^3 P(x^2)/Q(x^2)
  90. 0 <= x <= 0.625
  91. Peak relative error = 1.2e-18 */
  92. #if UNK
  93. static double P[6] = {
  94. 4.253011369004428248960E-3, -6.019598008014123785661E-1,
  95. 5.444622390564711410273E0, -1.626247967210700244449E1,
  96. 1.956261983317594739197E1, -8.198089802484824371615E0,
  97. };
  98. static double Q[5] = {
  99. /* 1.000000000000000000000E0, */
  100. -1.474091372988853791896E1, 7.049610280856842141659E1,
  101. -1.471791292232726029859E2, 1.395105614657485689735E2,
  102. -4.918853881490881290097E1,
  103. };
  104. #endif
  105. #if DEC
  106. static short P[24] = {
  107. 0036213, 0056330, 0057244, 0053234, 0140032, 0015011, 0114762, 0160255,
  108. 0040656, 0035130, 0136121, 0067313, 0141202, 0014616, 0170474, 0101731,
  109. 0041234, 0100076, 0151674, 0111310, 0141003, 0025540, 0033165, 0077246,
  110. };
  111. static short Q[20] = {
  112. /* 0040200,0000000,0000000,0000000, */
  113. 0141153, 0155310, 0055360, 0072530, 0041614, 0177001, 0027764,
  114. 0101237, 0142023, 0026733, 0064653, 0133266, 0042013, 0101264,
  115. 0023775, 0176351, 0141504, 0140420, 0050660, 0036543,
  116. };
  117. #endif
  118. #if IBMPC
  119. static short P[24] = {
  120. 0x8ad3, 0x0bd4, 0x6b9b, 0x3f71, 0x5c16, 0x333e, 0x4341, 0xbfe3,
  121. 0x2dd9, 0x178a, 0xc74b, 0x4015, 0x907b, 0xde27, 0x4331, 0xc030,
  122. 0x9259, 0xda77, 0x9007, 0x4033, 0xafd5, 0x06ce, 0x656c, 0xc020,
  123. };
  124. static short Q[20] = {
  125. /* 0x0000,0x0000,0x0000,0x3ff0, */
  126. 0x0eab, 0x0b5e, 0x7b59, 0xc02d, 0x9054, 0x25fe, 0x9fc0,
  127. 0x4051, 0x76d7, 0x6d35, 0x65bb, 0xc062, 0xbf9d, 0x84ff,
  128. 0x7056, 0x4061, 0x07ac, 0x0a36, 0x9822, 0xc048,
  129. };
  130. #endif
  131. #if MIEEE
  132. static short P[24] = {
  133. 0x3f71, 0x6b9b, 0x0bd4, 0x8ad3, 0xbfe3, 0x4341, 0x333e, 0x5c16,
  134. 0x4015, 0xc74b, 0x178a, 0x2dd9, 0xc030, 0x4331, 0xde27, 0x907b,
  135. 0x4033, 0x9007, 0xda77, 0x9259, 0xc020, 0x656c, 0x06ce, 0xafd5,
  136. };
  137. static short Q[20] = {
  138. /* 0x3ff0,0x0000,0x0000,0x0000, */
  139. 0xc02d, 0x7b59, 0x0b5e, 0x0eab, 0x4051, 0x9fc0, 0x25fe,
  140. 0x9054, 0xc062, 0x65bb, 0x6d35, 0x76d7, 0x4061, 0x7056,
  141. 0x84ff, 0xbf9d, 0xc048, 0x9822, 0x0a36, 0x07ac,
  142. };
  143. #endif
  144. /* arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x))
  145. 0 <= x <= 0.5
  146. Peak relative error = 4.2e-18 */
  147. #if UNK
  148. static double R[5] = {
  149. 2.967721961301243206100E-3, -5.634242780008963776856E-1,
  150. 6.968710824104713396794E0, -2.556901049652824852289E1,
  151. 2.853665548261061424989E1,
  152. };
  153. static double S[4] = {
  154. /* 1.000000000000000000000E0, */
  155. -2.194779531642920639778E1,
  156. 1.470656354026814941758E2,
  157. -3.838770957603691357202E2,
  158. 3.424398657913078477438E2,
  159. };
  160. #endif
  161. #if DEC
  162. static short R[20] = {
  163. 0036102, 0077034, 0142164, 0174103, 0140020, 0036222, 0147711,
  164. 0044173, 0040736, 0177655, 0153631, 0171523, 0141314, 0106525,
  165. 0060015, 0055474, 0041344, 0045422, 0003630, 0040344,
  166. };
  167. static short S[16] = {
  168. /* 0040200,0000000,0000000,0000000, */
  169. 0141257, 0112425, 0132772, 0166136, 0042023, 0010315, 0075523, 0175020,
  170. 0142277, 0170104, 0126203, 0017563, 0042253, 0034115, 0102662, 0022757,
  171. };
  172. #endif
  173. #if IBMPC
  174. static short R[20] = {
  175. 0x9f08, 0x988e, 0x4fc3, 0x3f68, 0x290f, 0x59f9, 0x0792,
  176. 0xbfe2, 0x3e6a, 0xbaf3, 0xdff5, 0x401b, 0xab68, 0xac01,
  177. 0x91aa, 0xc039, 0x081d, 0x40f3, 0x8962, 0x403c,
  178. };
  179. static short S[16] = {
  180. /* 0x0000,0x0000,0x0000,0x3ff0, */
  181. 0x5d8c, 0xb6bf, 0xf2a2, 0xc035, 0x7f42, 0xaf6a, 0x6219, 0x4062,
  182. 0x63ee, 0x9590, 0xfe08, 0xc077, 0x44be, 0xb0b6, 0x6709, 0x4075,
  183. };
  184. #endif
  185. #if MIEEE
  186. static short R[20] = {
  187. 0x3f68, 0x4fc3, 0x988e, 0x9f08, 0xbfe2, 0x0792, 0x59f9,
  188. 0x290f, 0x401b, 0xdff5, 0xbaf3, 0x3e6a, 0xc039, 0x91aa,
  189. 0xac01, 0xab68, 0x403c, 0x8962, 0x40f3, 0x081d,
  190. };
  191. static short S[16] = {
  192. /* 0x3ff0,0x0000,0x0000,0x0000, */
  193. 0xc035, 0xf2a2, 0xb6bf, 0x5d8c, 0x4062, 0x6219, 0xaf6a, 0x7f42,
  194. 0xc077, 0xfe08, 0x9590, 0x63ee, 0x4075, 0x6709, 0xb0b6, 0x44be,
  195. };
  196. #endif
  197. /* pi/2 = PIO2 + MOREBITS. */
  198. #ifdef DEC
  199. #define MOREBITS 5.721188726109831840122E-18
  200. #else
  201. #define MOREBITS 6.123233995736765886130E-17
  202. #endif
  203. #ifdef ANSIPROT
  204. extern double polevl(double, void *, int);
  205. extern double p1evl(double, void *, int);
  206. extern double sqrt(double);
  207. double asin(double);
  208. #else
  209. double sqrt(), polevl(), p1evl();
  210. double asin();
  211. #endif
  212. extern double PIO2, PIO4, NAN;
  213. double asin(x) double x;
  214. {
  215. double a, p, z, zz;
  216. short sign;
  217. if (x > 0) {
  218. sign = 1;
  219. a = x;
  220. } else {
  221. sign = -1;
  222. a = -x;
  223. }
  224. if (a > 1.0) {
  225. mtherr("asin", DOMAIN);
  226. return (NAN);
  227. }
  228. if (a > 0.625) {
  229. /* arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x)) */
  230. zz = 1.0 - a;
  231. p = zz * polevl(zz, R, 4) / p1evl(zz, S, 4);
  232. zz = sqrt(zz + zz);
  233. z = PIO4 - zz;
  234. zz = zz * p - MOREBITS;
  235. z = z - zz;
  236. z = z + PIO4;
  237. } else {
  238. if (a < 1.0e-8) {
  239. return (x);
  240. }
  241. zz = a * a;
  242. z = zz * polevl(zz, P, 5) / p1evl(zz, Q, 5);
  243. z = a * z + a;
  244. }
  245. if (sign < 0)
  246. z = -z;
  247. return (z);
  248. }
  249. double acos(x) double x;
  250. {
  251. double z;
  252. if ((x < -1.0) || (x > 1.0)) {
  253. mtherr("acos", DOMAIN);
  254. return (NAN);
  255. }
  256. if (x > 0.5) {
  257. return (2.0 * asin(sqrt(0.5 - 0.5 * x)));
  258. }
  259. z = PIO4 - asin(x);
  260. z = z + MOREBITS;
  261. z = z + PIO4;
  262. return (z);
  263. }