j1f.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /* origin: FreeBSD /usr/src/lib/msun/src/e_j1f.c */
  2. /*
  3. * Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
  4. */
  5. /*
  6. * ====================================================
  7. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  8. *
  9. * Developed at SunPro, a Sun Microsystems, Inc. business.
  10. * Permission to use, copy, modify, and distribute this
  11. * software is freely granted, provided that this notice
  12. * is preserved.
  13. * ====================================================
  14. */
  15. #include "libm.h"
  16. static float ponef(float), qonef(float);
  17. static const float
  18. huge = 1e30,
  19. invsqrtpi = 5.6418961287e-01, /* 0x3f106ebb */
  20. tpi = 6.3661974669e-01, /* 0x3f22f983 */
  21. /* R0/S0 on [0,2] */
  22. r00 = -6.2500000000e-02, /* 0xbd800000 */
  23. r01 = 1.4070566976e-03, /* 0x3ab86cfd */
  24. r02 = -1.5995563444e-05, /* 0xb7862e36 */
  25. r03 = 4.9672799207e-08, /* 0x335557d2 */
  26. s01 = 1.9153760746e-02, /* 0x3c9ce859 */
  27. s02 = 1.8594678841e-04, /* 0x3942fab6 */
  28. s03 = 1.1771846857e-06, /* 0x359dffc2 */
  29. s04 = 5.0463624390e-09, /* 0x31ad6446 */
  30. s05 = 1.2354227016e-11; /* 0x2d59567e */
  31. float j1f(float x)
  32. {
  33. float z,s,c,ss,cc,r,u,v,y;
  34. int32_t hx,ix;
  35. GET_FLOAT_WORD(hx, x);
  36. ix = hx & 0x7fffffff;
  37. if (ix >= 0x7f800000)
  38. return 1.0f/x;
  39. y = fabsf(x);
  40. if (ix >= 0x40000000) { /* |x| >= 2.0 */
  41. s = sinf(y);
  42. c = cosf(y);
  43. ss = -s-c;
  44. cc = s-c;
  45. if (ix < 0x7f000000) { /* make sure y+y not overflow */
  46. z = cosf(y+y);
  47. if (s*c > 0.0f)
  48. cc = z/ss;
  49. else
  50. ss = z/cc;
  51. }
  52. /*
  53. * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
  54. * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
  55. */
  56. if (ix > 0x80000000)
  57. z = (invsqrtpi*cc)/sqrtf(y);
  58. else {
  59. u = ponef(y);
  60. v = qonef(y);
  61. z = invsqrtpi*(u*cc-v*ss)/sqrtf(y);
  62. }
  63. if (hx < 0)
  64. return -z;
  65. return z;
  66. }
  67. if (ix < 0x32000000) { /* |x| < 2**-27 */
  68. /* raise inexact if x!=0 */
  69. if (huge+x > 1.0f)
  70. return 0.5f*x;
  71. }
  72. z = x*x;
  73. r = z*(r00+z*(r01+z*(r02+z*r03)));
  74. s = 1.0f+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
  75. r *= x;
  76. return 0.5f*x + r/s;
  77. }
  78. static const float U0[5] = {
  79. -1.9605709612e-01, /* 0xbe48c331 */
  80. 5.0443872809e-02, /* 0x3d4e9e3c */
  81. -1.9125689287e-03, /* 0xbafaaf2a */
  82. 2.3525259166e-05, /* 0x37c5581c */
  83. -9.1909917899e-08, /* 0xb3c56003 */
  84. };
  85. static const float V0[5] = {
  86. 1.9916731864e-02, /* 0x3ca3286a */
  87. 2.0255257550e-04, /* 0x3954644b */
  88. 1.3560879779e-06, /* 0x35b602d4 */
  89. 6.2274145840e-09, /* 0x31d5f8eb */
  90. 1.6655924903e-11, /* 0x2d9281cf */
  91. };
  92. float y1f(float x)
  93. {
  94. float z,s,c,ss,cc,u,v;
  95. int32_t hx,ix;
  96. GET_FLOAT_WORD(hx, x);
  97. ix = 0x7fffffff & hx;
  98. /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
  99. if (ix >= 0x7f800000)
  100. return 1.0f/(x+x*x);
  101. if (ix == 0)
  102. return -1.0f/0.0f;
  103. if (hx < 0)
  104. return 0.0f/0.0f;
  105. if (ix >= 0x40000000) { /* |x| >= 2.0 */
  106. s = sinf(x);
  107. c = cosf(x);
  108. ss = -s-c;
  109. cc = s-c;
  110. if (ix < 0x7f000000) { /* make sure x+x not overflow */
  111. z = cosf(x+x);
  112. if (s*c > 0.0f)
  113. cc = z/ss;
  114. else
  115. ss = z/cc;
  116. }
  117. /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
  118. * where x0 = x-3pi/4
  119. * Better formula:
  120. * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
  121. * = 1/sqrt(2) * (sin(x) - cos(x))
  122. * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
  123. * = -1/sqrt(2) * (cos(x) + sin(x))
  124. * To avoid cancellation, use
  125. * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
  126. * to compute the worse one.
  127. */
  128. if (ix > 0x48000000)
  129. z = (invsqrtpi*ss)/sqrtf(x);
  130. else {
  131. u = ponef(x);
  132. v = qonef(x);
  133. z = invsqrtpi*(u*ss+v*cc)/sqrtf(x);
  134. }
  135. return z;
  136. }
  137. if (ix <= 0x24800000) /* x < 2**-54 */
  138. return -tpi/x;
  139. z = x*x;
  140. u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
  141. v = 1.0f+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
  142. return x*(u/v) + tpi*(j1f(x)*logf(x)-1.0f/x);
  143. }
  144. /* For x >= 8, the asymptotic expansions of pone is
  145. * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x.
  146. * We approximate pone by
  147. * pone(x) = 1 + (R/S)
  148. * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
  149. * S = 1 + ps0*s^2 + ... + ps4*s^10
  150. * and
  151. * | pone(x)-1-R/S | <= 2 ** ( -60.06)
  152. */
  153. static const float pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
  154. 0.0000000000e+00, /* 0x00000000 */
  155. 1.1718750000e-01, /* 0x3df00000 */
  156. 1.3239480972e+01, /* 0x4153d4ea */
  157. 4.1205184937e+02, /* 0x43ce06a3 */
  158. 3.8747453613e+03, /* 0x45722bed */
  159. 7.9144794922e+03, /* 0x45f753d6 */
  160. };
  161. static const float ps8[5] = {
  162. 1.1420736694e+02, /* 0x42e46a2c */
  163. 3.6509309082e+03, /* 0x45642ee5 */
  164. 3.6956207031e+04, /* 0x47105c35 */
  165. 9.7602796875e+04, /* 0x47bea166 */
  166. 3.0804271484e+04, /* 0x46f0a88b */
  167. };
  168. static const float pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
  169. 1.3199052094e-11, /* 0x2d68333f */
  170. 1.1718749255e-01, /* 0x3defffff */
  171. 6.8027510643e+00, /* 0x40d9b023 */
  172. 1.0830818176e+02, /* 0x42d89dca */
  173. 5.1763616943e+02, /* 0x440168b7 */
  174. 5.2871520996e+02, /* 0x44042dc6 */
  175. };
  176. static const float ps5[5] = {
  177. 5.9280597687e+01, /* 0x426d1f55 */
  178. 9.9140142822e+02, /* 0x4477d9b1 */
  179. 5.3532670898e+03, /* 0x45a74a23 */
  180. 7.8446904297e+03, /* 0x45f52586 */
  181. 1.5040468750e+03, /* 0x44bc0180 */
  182. };
  183. static const float pr3[6] = {
  184. 3.0250391081e-09, /* 0x314fe10d */
  185. 1.1718686670e-01, /* 0x3defffab */
  186. 3.9329774380e+00, /* 0x407bb5e7 */
  187. 3.5119403839e+01, /* 0x420c7a45 */
  188. 9.1055007935e+01, /* 0x42b61c2a */
  189. 4.8559066772e+01, /* 0x42423c7c */
  190. };
  191. static const float ps3[5] = {
  192. 3.4791309357e+01, /* 0x420b2a4d */
  193. 3.3676245117e+02, /* 0x43a86198 */
  194. 1.0468714600e+03, /* 0x4482dbe3 */
  195. 8.9081134033e+02, /* 0x445eb3ed */
  196. 1.0378793335e+02, /* 0x42cf936c */
  197. };
  198. static const float pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
  199. 1.0771083225e-07, /* 0x33e74ea8 */
  200. 1.1717621982e-01, /* 0x3deffa16 */
  201. 2.3685150146e+00, /* 0x401795c0 */
  202. 1.2242610931e+01, /* 0x4143e1bc */
  203. 1.7693971634e+01, /* 0x418d8d41 */
  204. 5.0735230446e+00, /* 0x40a25a4d */
  205. };
  206. static const float ps2[5] = {
  207. 2.1436485291e+01, /* 0x41ab7dec */
  208. 1.2529022980e+02, /* 0x42fa9499 */
  209. 2.3227647400e+02, /* 0x436846c7 */
  210. 1.1767937469e+02, /* 0x42eb5bd7 */
  211. 8.3646392822e+00, /* 0x4105d590 */
  212. };
  213. static float ponef(float x)
  214. {
  215. const float *p,*q;
  216. float z,r,s;
  217. int32_t ix;
  218. GET_FLOAT_WORD(ix, x);
  219. ix &= 0x7fffffff;
  220. if (ix >= 0x41000000){p = pr8; q = ps8;}
  221. else if (ix >= 0x40f71c58){p = pr5; q = ps5;}
  222. else if (ix >= 0x4036db68){p = pr3; q = ps3;}
  223. else if (ix >= 0x40000000){p = pr2; q = ps2;}
  224. z = 1.0f/(x*x);
  225. r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
  226. s = 1.0f+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
  227. return 1.0f + r/s;
  228. }
  229. /* For x >= 8, the asymptotic expansions of qone is
  230. * 3/8 s - 105/1024 s^3 - ..., where s = 1/x.
  231. * We approximate pone by
  232. * qone(x) = s*(0.375 + (R/S))
  233. * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
  234. * S = 1 + qs1*s^2 + ... + qs6*s^12
  235. * and
  236. * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13)
  237. */
  238. static const float qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
  239. 0.0000000000e+00, /* 0x00000000 */
  240. -1.0253906250e-01, /* 0xbdd20000 */
  241. -1.6271753311e+01, /* 0xc1822c8d */
  242. -7.5960174561e+02, /* 0xc43de683 */
  243. -1.1849806641e+04, /* 0xc639273a */
  244. -4.8438511719e+04, /* 0xc73d3683 */
  245. };
  246. static const float qs8[6] = {
  247. 1.6139537048e+02, /* 0x43216537 */
  248. 7.8253862305e+03, /* 0x45f48b17 */
  249. 1.3387534375e+05, /* 0x4802bcd6 */
  250. 7.1965775000e+05, /* 0x492fb29c */
  251. 6.6660125000e+05, /* 0x4922be94 */
  252. -2.9449025000e+05, /* 0xc88fcb48 */
  253. };
  254. static const float qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
  255. -2.0897993405e-11, /* 0xadb7d219 */
  256. -1.0253904760e-01, /* 0xbdd1fffe */
  257. -8.0564479828e+00, /* 0xc100e736 */
  258. -1.8366960144e+02, /* 0xc337ab6b */
  259. -1.3731937256e+03, /* 0xc4aba633 */
  260. -2.6124443359e+03, /* 0xc523471c */
  261. };
  262. static const float qs5[6] = {
  263. 8.1276550293e+01, /* 0x42a28d98 */
  264. 1.9917987061e+03, /* 0x44f8f98f */
  265. 1.7468484375e+04, /* 0x468878f8 */
  266. 4.9851425781e+04, /* 0x4742bb6d */
  267. 2.7948074219e+04, /* 0x46da5826 */
  268. -4.7191835938e+03, /* 0xc5937978 */
  269. };
  270. static const float qr3[6] = {
  271. -5.0783124372e-09, /* 0xb1ae7d4f */
  272. -1.0253783315e-01, /* 0xbdd1ff5b */
  273. -4.6101160049e+00, /* 0xc0938612 */
  274. -5.7847221375e+01, /* 0xc267638e */
  275. -2.2824453735e+02, /* 0xc3643e9a */
  276. -2.1921012878e+02, /* 0xc35b35cb */
  277. };
  278. static const float qs3[6] = {
  279. 4.7665153503e+01, /* 0x423ea91e */
  280. 6.7386511230e+02, /* 0x4428775e */
  281. 3.3801528320e+03, /* 0x45534272 */
  282. 5.5477290039e+03, /* 0x45ad5dd5 */
  283. 1.9031191406e+03, /* 0x44ede3d0 */
  284. -1.3520118713e+02, /* 0xc3073381 */
  285. };
  286. static const float qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
  287. -1.7838172539e-07, /* 0xb43f8932 */
  288. -1.0251704603e-01, /* 0xbdd1f475 */
  289. -2.7522056103e+00, /* 0xc0302423 */
  290. -1.9663616180e+01, /* 0xc19d4f16 */
  291. -4.2325313568e+01, /* 0xc2294d1f */
  292. -2.1371921539e+01, /* 0xc1aaf9b2 */
  293. };
  294. static const float qs2[6] = {
  295. 2.9533363342e+01, /* 0x41ec4454 */
  296. 2.5298155212e+02, /* 0x437cfb47 */
  297. 7.5750280762e+02, /* 0x443d602e */
  298. 7.3939318848e+02, /* 0x4438d92a */
  299. 1.5594900513e+02, /* 0x431bf2f2 */
  300. -4.9594988823e+00, /* 0xc09eb437 */
  301. };
  302. static float qonef(float x)
  303. {
  304. const float *p,*q;
  305. float s,r,z;
  306. int32_t ix;
  307. GET_FLOAT_WORD(ix, x);
  308. ix &= 0x7fffffff;
  309. if (ix >= 0x40200000){p = qr8; q = qs8;}
  310. else if (ix >= 0x40f71c58){p = qr5; q = qs5;}
  311. else if (ix >= 0x4036db68){p = qr3; q = qs3;}
  312. else if (ix >= 0x40000000){p = qr2; q = qs2;}
  313. z = 1.0f/(x*x);
  314. r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
  315. s = 1.0f+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
  316. return (.375f + r/s)/x;
  317. }