asinl.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /* asinl.c
  2. *
  3. * Inverse circular sine, long double precision
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * double x, y, asinl();
  10. *
  11. * y = asinl( 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. * IEEE -1, 1 30000 2.7e-19 4.8e-20
  31. *
  32. *
  33. * ERROR MESSAGES:
  34. *
  35. * message condition value returned
  36. * asinl domain |x| > 1 NANL
  37. *
  38. */
  39. /* acosl()
  40. *
  41. * Inverse circular cosine, long double precision
  42. *
  43. *
  44. *
  45. * SYNOPSIS:
  46. *
  47. * double x, y, acosl();
  48. *
  49. * y = acosl( x );
  50. *
  51. *
  52. *
  53. * DESCRIPTION:
  54. *
  55. * Returns radian angle between -pi/2 and +pi/2 whose cosine
  56. * is x.
  57. *
  58. * Analytically, acos(x) = pi/2 - asin(x). However if |x| is
  59. * near 1, there is cancellation error in subtracting asin(x)
  60. * from pi/2. Hence if x < -0.5,
  61. *
  62. * acos(x) = pi - 2.0 * asin( sqrt((1+x)/2) );
  63. *
  64. * or if x > +0.5,
  65. *
  66. * acos(x) = 2.0 * asin( sqrt((1-x)/2) ).
  67. *
  68. *
  69. * ACCURACY:
  70. *
  71. * Relative error:
  72. * arithmetic domain # trials peak rms
  73. * IEEE -1, 1 30000 1.4e-19 3.5e-20
  74. *
  75. *
  76. * ERROR MESSAGES:
  77. *
  78. * message condition value returned
  79. * acosl domain |x| > 1 NANL
  80. */
  81. /* asin.c */
  82. /*
  83. Cephes Math Library Release 2.7: May, 1998
  84. Copyright 1984, 1990, 1998 by Stephen L. Moshier
  85. */
  86. #include <math.h>
  87. #ifdef UNK
  88. static long double P[] = {
  89. 3.7769340062433674871612E-3L,
  90. -6.1212919176969202969441E-1L,
  91. 5.9303993515791417710775E0L,
  92. -1.8631697621590161441592E1L,
  93. 2.3314603132141795720634E1L,
  94. -1.0087146579384916260197E1L,
  95. };
  96. static long double Q[] = {
  97. /* 1.0000000000000000000000E0L,*/
  98. -1.5684335624873146511217E1L,
  99. 7.8702951549021104258866E1L,
  100. -1.7078401170625864261444E2L,
  101. 1.6712291455718995937376E2L,
  102. -6.0522879476309497128868E1L,
  103. };
  104. #endif
  105. #ifdef IBMPC
  106. static short P[] = {
  107. 0x59d1,0x3509,0x7009,0xf786,0x3ff6, XPD
  108. 0xbe97,0x93e6,0x7fab,0x9cb4,0xbffe, XPD
  109. 0x8bf5,0x6810,0xd4dc,0xbdc5,0x4001, XPD
  110. 0x9bd4,0x8d86,0xb77b,0x950d,0xc003, XPD
  111. 0x3b0f,0x9e25,0x4ea5,0xba84,0x4003, XPD
  112. 0xea38,0xc6a9,0xf3cf,0xa164,0xc002, XPD
  113. };
  114. static short Q[] = {
  115. /*0x0000,0x0000,0x0000,0x8000,0x3fff,*/
  116. 0x1229,0x8516,0x09e9,0xfaf3,0xc002, XPD
  117. 0xb5c3,0xf36f,0xe943,0x9d67,0x4005, XPD
  118. 0xe11a,0xbe0f,0xb4fd,0xaac8,0xc006, XPD
  119. 0x4c69,0x1355,0x7754,0xa71f,0x4006, XPD
  120. 0xded7,0xa9fe,0x6db7,0xf217,0xc004, XPD
  121. };
  122. #endif
  123. #ifdef MIEEE
  124. static long P[] = {
  125. 0x3ff60000,0xf7867009,0x350959d1,
  126. 0xbffe0000,0x9cb47fab,0x93e6be97,
  127. 0x40010000,0xbdc5d4dc,0x68108bf5,
  128. 0xc0030000,0x950db77b,0x8d869bd4,
  129. 0x40030000,0xba844ea5,0x9e253b0f,
  130. 0xc0020000,0xa164f3cf,0xc6a9ea38,
  131. };
  132. static long Q[] = {
  133. /*0x3fff0000,0x80000000,0x00000000,*/
  134. 0xc0020000,0xfaf309e9,0x85161229,
  135. 0x40050000,0x9d67e943,0xf36fb5c3,
  136. 0xc0060000,0xaac8b4fd,0xbe0fe11a,
  137. 0x40060000,0xa71f7754,0x13554c69,
  138. 0xc0040000,0xf2176db7,0xa9feded7,
  139. };
  140. #endif
  141. #ifdef NANS
  142. extern long double NANL;
  143. #endif
  144. #ifdef ANSIPROT
  145. extern long double ldexpl ( long double, int );
  146. extern long double sqrtl ( long double );
  147. extern long double polevll ( long double, void *, int );
  148. extern long double p1evll ( long double, void *, int );
  149. long double asinl ( long double );
  150. #else
  151. long double ldexpl(), sqrtl(), polevll(), p1evll();
  152. long double asinl();
  153. #endif
  154. long double asinl(x)
  155. long double x;
  156. {
  157. long double a, p, z, zz;
  158. short sign, flag;
  159. extern long double PIO2L;
  160. if( x > 0 )
  161. {
  162. sign = 1;
  163. a = x;
  164. }
  165. else
  166. {
  167. sign = -1;
  168. a = -x;
  169. }
  170. if( a > 1.0L )
  171. {
  172. mtherr( "asinl", DOMAIN );
  173. #ifdef NANS
  174. return( NANL );
  175. #else
  176. return( 0.0L );
  177. #endif
  178. }
  179. if( a < 1.0e-8L )
  180. {
  181. z = a;
  182. goto done;
  183. }
  184. if( a > 0.5L )
  185. {
  186. zz = 0.5L -a;
  187. zz = ldexpl( zz + 0.5L, -1 );
  188. z = sqrtl( zz );
  189. flag = 1;
  190. }
  191. else
  192. {
  193. z = a;
  194. zz = z * z;
  195. flag = 0;
  196. }
  197. p = zz * polevll( zz, P, 5)/p1evll( zz, Q, 5);
  198. z = z * p + z;
  199. if( flag != 0 )
  200. {
  201. z = z + z;
  202. z = PIO2L - z;
  203. }
  204. done:
  205. if( sign < 0 )
  206. z = -z;
  207. return(z);
  208. }
  209. extern long double PIO2L, PIL;
  210. long double acosl(x)
  211. long double x;
  212. {
  213. if( x < -1.0L )
  214. goto domerr;
  215. if( x < -0.5L)
  216. return( PIL - 2.0L * asinl( sqrtl(0.5L*(1.0L+x)) ) );
  217. if( x > 1.0L )
  218. {
  219. domerr: mtherr( "acosl", DOMAIN );
  220. #ifdef NANS
  221. return( NANL );
  222. #else
  223. return( 0.0L );
  224. #endif
  225. }
  226. if( x > 0.5L )
  227. return( 2.0L * asinl( sqrtl(0.5L*(1.0L-x) ) ) );
  228. return( PIO2L - asinl(x) );
  229. }