asin.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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 <math.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,
  95. -6.019598008014123785661E-1,
  96. 5.444622390564711410273E0,
  97. -1.626247967210700244449E1,
  98. 1.956261983317594739197E1,
  99. -8.198089802484824371615E0,
  100. };
  101. static double Q[5] = {
  102. /* 1.000000000000000000000E0, */
  103. -1.474091372988853791896E1,
  104. 7.049610280856842141659E1,
  105. -1.471791292232726029859E2,
  106. 1.395105614657485689735E2,
  107. -4.918853881490881290097E1,
  108. };
  109. #endif
  110. #if DEC
  111. static short P[24] = {
  112. 0036213,0056330,0057244,0053234,
  113. 0140032,0015011,0114762,0160255,
  114. 0040656,0035130,0136121,0067313,
  115. 0141202,0014616,0170474,0101731,
  116. 0041234,0100076,0151674,0111310,
  117. 0141003,0025540,0033165,0077246,
  118. };
  119. static short Q[20] = {
  120. /* 0040200,0000000,0000000,0000000, */
  121. 0141153,0155310,0055360,0072530,
  122. 0041614,0177001,0027764,0101237,
  123. 0142023,0026733,0064653,0133266,
  124. 0042013,0101264,0023775,0176351,
  125. 0141504,0140420,0050660,0036543,
  126. };
  127. #endif
  128. #if IBMPC
  129. static short P[24] = {
  130. 0x8ad3,0x0bd4,0x6b9b,0x3f71,
  131. 0x5c16,0x333e,0x4341,0xbfe3,
  132. 0x2dd9,0x178a,0xc74b,0x4015,
  133. 0x907b,0xde27,0x4331,0xc030,
  134. 0x9259,0xda77,0x9007,0x4033,
  135. 0xafd5,0x06ce,0x656c,0xc020,
  136. };
  137. static short Q[20] = {
  138. /* 0x0000,0x0000,0x0000,0x3ff0, */
  139. 0x0eab,0x0b5e,0x7b59,0xc02d,
  140. 0x9054,0x25fe,0x9fc0,0x4051,
  141. 0x76d7,0x6d35,0x65bb,0xc062,
  142. 0xbf9d,0x84ff,0x7056,0x4061,
  143. 0x07ac,0x0a36,0x9822,0xc048,
  144. };
  145. #endif
  146. #if MIEEE
  147. static short P[24] = {
  148. 0x3f71,0x6b9b,0x0bd4,0x8ad3,
  149. 0xbfe3,0x4341,0x333e,0x5c16,
  150. 0x4015,0xc74b,0x178a,0x2dd9,
  151. 0xc030,0x4331,0xde27,0x907b,
  152. 0x4033,0x9007,0xda77,0x9259,
  153. 0xc020,0x656c,0x06ce,0xafd5,
  154. };
  155. static short Q[20] = {
  156. /* 0x3ff0,0x0000,0x0000,0x0000, */
  157. 0xc02d,0x7b59,0x0b5e,0x0eab,
  158. 0x4051,0x9fc0,0x25fe,0x9054,
  159. 0xc062,0x65bb,0x6d35,0x76d7,
  160. 0x4061,0x7056,0x84ff,0xbf9d,
  161. 0xc048,0x9822,0x0a36,0x07ac,
  162. };
  163. #endif
  164. /* arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x))
  165. 0 <= x <= 0.5
  166. Peak relative error = 4.2e-18 */
  167. #if UNK
  168. static double R[5] = {
  169. 2.967721961301243206100E-3,
  170. -5.634242780008963776856E-1,
  171. 6.968710824104713396794E0,
  172. -2.556901049652824852289E1,
  173. 2.853665548261061424989E1,
  174. };
  175. static double S[4] = {
  176. /* 1.000000000000000000000E0, */
  177. -2.194779531642920639778E1,
  178. 1.470656354026814941758E2,
  179. -3.838770957603691357202E2,
  180. 3.424398657913078477438E2,
  181. };
  182. #endif
  183. #if DEC
  184. static short R[20] = {
  185. 0036102,0077034,0142164,0174103,
  186. 0140020,0036222,0147711,0044173,
  187. 0040736,0177655,0153631,0171523,
  188. 0141314,0106525,0060015,0055474,
  189. 0041344,0045422,0003630,0040344,
  190. };
  191. static short S[16] = {
  192. /* 0040200,0000000,0000000,0000000, */
  193. 0141257,0112425,0132772,0166136,
  194. 0042023,0010315,0075523,0175020,
  195. 0142277,0170104,0126203,0017563,
  196. 0042253,0034115,0102662,0022757,
  197. };
  198. #endif
  199. #if IBMPC
  200. static short R[20] = {
  201. 0x9f08,0x988e,0x4fc3,0x3f68,
  202. 0x290f,0x59f9,0x0792,0xbfe2,
  203. 0x3e6a,0xbaf3,0xdff5,0x401b,
  204. 0xab68,0xac01,0x91aa,0xc039,
  205. 0x081d,0x40f3,0x8962,0x403c,
  206. };
  207. static short S[16] = {
  208. /* 0x0000,0x0000,0x0000,0x3ff0, */
  209. 0x5d8c,0xb6bf,0xf2a2,0xc035,
  210. 0x7f42,0xaf6a,0x6219,0x4062,
  211. 0x63ee,0x9590,0xfe08,0xc077,
  212. 0x44be,0xb0b6,0x6709,0x4075,
  213. };
  214. #endif
  215. #if MIEEE
  216. static short R[20] = {
  217. 0x3f68,0x4fc3,0x988e,0x9f08,
  218. 0xbfe2,0x0792,0x59f9,0x290f,
  219. 0x401b,0xdff5,0xbaf3,0x3e6a,
  220. 0xc039,0x91aa,0xac01,0xab68,
  221. 0x403c,0x8962,0x40f3,0x081d,
  222. };
  223. static short S[16] = {
  224. /* 0x3ff0,0x0000,0x0000,0x0000, */
  225. 0xc035,0xf2a2,0xb6bf,0x5d8c,
  226. 0x4062,0x6219,0xaf6a,0x7f42,
  227. 0xc077,0xfe08,0x9590,0x63ee,
  228. 0x4075,0x6709,0xb0b6,0x44be,
  229. };
  230. #endif
  231. /* pi/2 = PIO2 + MOREBITS. */
  232. #ifdef DEC
  233. #define MOREBITS 5.721188726109831840122E-18
  234. #else
  235. #define MOREBITS 6.123233995736765886130E-17
  236. #endif
  237. #ifdef ANSIPROT
  238. extern double polevl ( double, void *, int );
  239. extern double p1evl ( double, void *, int );
  240. extern double sqrt ( double );
  241. double asin ( double );
  242. #else
  243. double sqrt(), polevl(), p1evl();
  244. double asin();
  245. #endif
  246. extern double PIO2, PIO4, NAN;
  247. double asin(x)
  248. double x;
  249. {
  250. double a, p, z, zz;
  251. short sign;
  252. if( x > 0 )
  253. {
  254. sign = 1;
  255. a = x;
  256. }
  257. else
  258. {
  259. sign = -1;
  260. a = -x;
  261. }
  262. if( a > 1.0 )
  263. {
  264. mtherr( "asin", DOMAIN );
  265. return( NAN );
  266. }
  267. if( a > 0.625 )
  268. {
  269. /* arcsin(1-x) = pi/2 - sqrt(2x)(1+R(x)) */
  270. zz = 1.0 - a;
  271. p = zz * polevl( zz, R, 4)/p1evl( zz, S, 4);
  272. zz = sqrt(zz+zz);
  273. z = PIO4 - zz;
  274. zz = zz * p - MOREBITS;
  275. z = z - zz;
  276. z = z + PIO4;
  277. }
  278. else
  279. {
  280. if( a < 1.0e-8 )
  281. {
  282. return(x);
  283. }
  284. zz = a * a;
  285. z = zz * polevl( zz, P, 5)/p1evl( zz, Q, 5);
  286. z = a * z + a;
  287. }
  288. if( sign < 0 )
  289. z = -z;
  290. return(z);
  291. }
  292. double acos(x)
  293. double x;
  294. {
  295. double z;
  296. if( (x < -1.0) || (x > 1.0) )
  297. {
  298. mtherr( "acos", DOMAIN );
  299. return( NAN );
  300. }
  301. if( x > 0.5 )
  302. {
  303. return( 2.0 * asin( sqrt(0.5 - 0.5*x) ) );
  304. }
  305. z = PIO4 - asin(x);
  306. z = z + MOREBITS;
  307. z = z + PIO4;
  308. return( z );
  309. }