airyf.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /* airy.c
  2. *
  3. * Airy function
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * float x, ai, aip, bi, bip;
  10. * int airyf();
  11. *
  12. * airyf( x, _&ai, _&aip, _&bi, _&bip );
  13. *
  14. *
  15. *
  16. * DESCRIPTION:
  17. *
  18. * Solution of the differential equation
  19. *
  20. * y"(x) = xy.
  21. *
  22. * The function returns the two independent solutions Ai, Bi
  23. * and their first derivatives Ai'(x), Bi'(x).
  24. *
  25. * Evaluation is by power series summation for small x,
  26. * by rational minimax approximations for large x.
  27. *
  28. *
  29. *
  30. * ACCURACY:
  31. * Error criterion is absolute when function <= 1, relative
  32. * when function > 1, except * denotes relative error criterion.
  33. * For large negative x, the absolute error increases as x^1.5.
  34. * For large positive x, the relative error increases as x^1.5.
  35. *
  36. * Arithmetic domain function # trials peak rms
  37. * IEEE -10, 0 Ai 50000 7.0e-7 1.2e-7
  38. * IEEE 0, 10 Ai 50000 9.9e-6* 6.8e-7*
  39. * IEEE -10, 0 Ai' 50000 2.4e-6 3.5e-7
  40. * IEEE 0, 10 Ai' 50000 8.7e-6* 6.2e-7*
  41. * IEEE -10, 10 Bi 100000 2.2e-6 2.6e-7
  42. * IEEE -10, 10 Bi' 50000 2.2e-6 3.5e-7
  43. *
  44. */
  45. /* airy.c */
  46. /*
  47. Cephes Math Library Release 2.2: June, 1992
  48. Copyright 1984, 1987, 1989, 1992 by Stephen L. Moshier
  49. Direct inquiries to 30 Frost Street, Cambridge, MA 02140
  50. */
  51. #include <math.h>
  52. static float c1 = 0.35502805388781723926;
  53. static float c2 = 0.258819403792806798405;
  54. static float sqrt3 = 1.732050807568877293527;
  55. static float sqpii = 5.64189583547756286948E-1;
  56. extern float PIF;
  57. extern float MAXNUMF, MACHEPF;
  58. #define MAXAIRY 25.77
  59. /* Note, these expansions are for double precision accuracy;
  60. * they have not yet been redesigned for single precision.
  61. */
  62. static float AN[8] = {
  63. 3.46538101525629032477e-1,
  64. 1.20075952739645805542e1,
  65. 7.62796053615234516538e1,
  66. 1.68089224934630576269e2,
  67. 1.59756391350164413639e2,
  68. 7.05360906840444183113e1,
  69. 1.40264691163389668864e1,
  70. 9.99999999999999995305e-1,
  71. };
  72. static float AD[8] = {
  73. 5.67594532638770212846e-1,
  74. 1.47562562584847203173e1,
  75. 8.45138970141474626562e1,
  76. 1.77318088145400459522e2,
  77. 1.64234692871529701831e2,
  78. 7.14778400825575695274e1,
  79. 1.40959135607834029598e1,
  80. 1.00000000000000000470e0,
  81. };
  82. static float APN[8] = {
  83. 6.13759184814035759225e-1,
  84. 1.47454670787755323881e1,
  85. 8.20584123476060982430e1,
  86. 1.71184781360976385540e2,
  87. 1.59317847137141783523e2,
  88. 6.99778599330103016170e1,
  89. 1.39470856980481566958e1,
  90. 1.00000000000000000550e0,
  91. };
  92. static float APD[8] = {
  93. 3.34203677749736953049e-1,
  94. 1.11810297306158156705e1,
  95. 7.11727352147859965283e1,
  96. 1.58778084372838313640e2,
  97. 1.53206427475809220834e2,
  98. 6.86752304592780337944e1,
  99. 1.38498634758259442477e1,
  100. 9.99999999999999994502e-1,
  101. };
  102. static float BN16[5] = {
  103. -2.53240795869364152689e-1,
  104. 5.75285167332467384228e-1,
  105. -3.29907036873225371650e-1,
  106. 6.44404068948199951727e-2,
  107. -3.82519546641336734394e-3,
  108. };
  109. static float BD16[5] = {
  110. /* 1.00000000000000000000e0,*/
  111. -7.15685095054035237902e0,
  112. 1.06039580715664694291e1,
  113. -5.23246636471251500874e0,
  114. 9.57395864378383833152e-1,
  115. -5.50828147163549611107e-2,
  116. };
  117. static float BPPN[5] = {
  118. 4.65461162774651610328e-1,
  119. -1.08992173800493920734e0,
  120. 6.38800117371827987759e-1,
  121. -1.26844349553102907034e-1,
  122. 7.62487844342109852105e-3,
  123. };
  124. static float BPPD[5] = {
  125. /* 1.00000000000000000000e0,*/
  126. -8.70622787633159124240e0,
  127. 1.38993162704553213172e1,
  128. -7.14116144616431159572e0,
  129. 1.34008595960680518666e0,
  130. -7.84273211323341930448e-2,
  131. };
  132. static float AFN[9] = {
  133. -1.31696323418331795333e-1,
  134. -6.26456544431912369773e-1,
  135. -6.93158036036933542233e-1,
  136. -2.79779981545119124951e-1,
  137. -4.91900132609500318020e-2,
  138. -4.06265923594885404393e-3,
  139. -1.59276496239262096340e-4,
  140. -2.77649108155232920844e-6,
  141. -1.67787698489114633780e-8,
  142. };
  143. static float AFD[9] = {
  144. /* 1.00000000000000000000e0,*/
  145. 1.33560420706553243746e1,
  146. 3.26825032795224613948e1,
  147. 2.67367040941499554804e1,
  148. 9.18707402907259625840e0,
  149. 1.47529146771666414581e0,
  150. 1.15687173795188044134e-1,
  151. 4.40291641615211203805e-3,
  152. 7.54720348287414296618e-5,
  153. 4.51850092970580378464e-7,
  154. };
  155. static float AGN[11] = {
  156. 1.97339932091685679179e-2,
  157. 3.91103029615688277255e-1,
  158. 1.06579897599595591108e0,
  159. 9.39169229816650230044e-1,
  160. 3.51465656105547619242e-1,
  161. 6.33888919628925490927e-2,
  162. 5.85804113048388458567e-3,
  163. 2.82851600836737019778e-4,
  164. 6.98793669997260967291e-6,
  165. 8.11789239554389293311e-8,
  166. 3.41551784765923618484e-10,
  167. };
  168. static float AGD[10] = {
  169. /* 1.00000000000000000000e0,*/
  170. 9.30892908077441974853e0,
  171. 1.98352928718312140417e1,
  172. 1.55646628932864612953e1,
  173. 5.47686069422975497931e0,
  174. 9.54293611618961883998e-1,
  175. 8.64580826352392193095e-2,
  176. 4.12656523824222607191e-3,
  177. 1.01259085116509135510e-4,
  178. 1.17166733214413521882e-6,
  179. 4.91834570062930015649e-9,
  180. };
  181. static float APFN[9] = {
  182. 1.85365624022535566142e-1,
  183. 8.86712188052584095637e-1,
  184. 9.87391981747398547272e-1,
  185. 4.01241082318003734092e-1,
  186. 7.10304926289631174579e-2,
  187. 5.90618657995661810071e-3,
  188. 2.33051409401776799569e-4,
  189. 4.08718778289035454598e-6,
  190. 2.48379932900442457853e-8,
  191. };
  192. static float APFD[9] = {
  193. /* 1.00000000000000000000e0,*/
  194. 1.47345854687502542552e1,
  195. 3.75423933435489594466e1,
  196. 3.14657751203046424330e1,
  197. 1.09969125207298778536e1,
  198. 1.78885054766999417817e0,
  199. 1.41733275753662636873e-1,
  200. 5.44066067017226003627e-3,
  201. 9.39421290654511171663e-5,
  202. 5.65978713036027009243e-7,
  203. };
  204. static float APGN[11] = {
  205. -3.55615429033082288335e-2,
  206. -6.37311518129435504426e-1,
  207. -1.70856738884312371053e0,
  208. -1.50221872117316635393e0,
  209. -5.63606665822102676611e-1,
  210. -1.02101031120216891789e-1,
  211. -9.48396695961445269093e-3,
  212. -4.60325307486780994357e-4,
  213. -1.14300836484517375919e-5,
  214. -1.33415518685547420648e-7,
  215. -5.63803833958893494476e-10,
  216. };
  217. static float APGD[11] = {
  218. /* 1.00000000000000000000e0,*/
  219. 9.85865801696130355144e0,
  220. 2.16401867356585941885e1,
  221. 1.73130776389749389525e1,
  222. 6.17872175280828766327e0,
  223. 1.08848694396321495475e0,
  224. 9.95005543440888479402e-2,
  225. 4.78468199683886610842e-3,
  226. 1.18159633322838625562e-4,
  227. 1.37480673554219441465e-6,
  228. 5.79912514929147598821e-9,
  229. };
  230. #define fabsf(x) ( (x) < 0 ? -(x) : (x) )
  231. float polevlf(float, float *, int);
  232. float p1evlf(float, float *, int);
  233. float sinf(float), cosf(float), expf(float), sqrtf(float);
  234. int airyf( float xx, float *ai, float *aip, float *bi, float *bip )
  235. {
  236. float x, z, zz, t, f, g, uf, ug, k, zeta, theta;
  237. int domflg;
  238. x = xx;
  239. domflg = 0;
  240. if( x > MAXAIRY )
  241. {
  242. *ai = 0;
  243. *aip = 0;
  244. *bi = MAXNUMF;
  245. *bip = MAXNUMF;
  246. return(-1);
  247. }
  248. if( x < -2.09 )
  249. {
  250. domflg = 15;
  251. t = sqrtf(-x);
  252. zeta = -2.0 * x * t / 3.0;
  253. t = sqrtf(t);
  254. k = sqpii / t;
  255. z = 1.0/zeta;
  256. zz = z * z;
  257. uf = 1.0 + zz * polevlf( zz, AFN, 8 ) / p1evlf( zz, AFD, 9 );
  258. ug = z * polevlf( zz, AGN, 10 ) / p1evlf( zz, AGD, 10 );
  259. theta = zeta + 0.25 * PIF;
  260. f = sinf( theta );
  261. g = cosf( theta );
  262. *ai = k * (f * uf - g * ug);
  263. *bi = k * (g * uf + f * ug);
  264. uf = 1.0 + zz * polevlf( zz, APFN, 8 ) / p1evlf( zz, APFD, 9 );
  265. ug = z * polevlf( zz, APGN, 10 ) / p1evlf( zz, APGD, 10 );
  266. k = sqpii * t;
  267. *aip = -k * (g * uf + f * ug);
  268. *bip = k * (f * uf - g * ug);
  269. return(0);
  270. }
  271. if( x >= 2.09 ) /* cbrt(9) */
  272. {
  273. domflg = 5;
  274. t = sqrtf(x);
  275. zeta = 2.0 * x * t / 3.0;
  276. g = expf( zeta );
  277. t = sqrtf(t);
  278. k = 2.0 * t * g;
  279. z = 1.0/zeta;
  280. f = polevlf( z, AN, 7 ) / polevlf( z, AD, 7 );
  281. *ai = sqpii * f / k;
  282. k = -0.5 * sqpii * t / g;
  283. f = polevlf( z, APN, 7 ) / polevlf( z, APD, 7 );
  284. *aip = f * k;
  285. if( x > 8.3203353 ) /* zeta > 16 */
  286. {
  287. f = z * polevlf( z, BN16, 4 ) / p1evlf( z, BD16, 5 );
  288. k = sqpii * g;
  289. *bi = k * (1.0 + f) / t;
  290. f = z * polevlf( z, BPPN, 4 ) / p1evlf( z, BPPD, 5 );
  291. *bip = k * t * (1.0 + f);
  292. return(0);
  293. }
  294. }
  295. f = 1.0;
  296. g = x;
  297. t = 1.0;
  298. uf = 1.0;
  299. ug = x;
  300. k = 1.0;
  301. z = x * x * x;
  302. while( t > MACHEPF )
  303. {
  304. uf *= z;
  305. k += 1.0;
  306. uf /=k;
  307. ug *= z;
  308. k += 1.0;
  309. ug /=k;
  310. uf /=k;
  311. f += uf;
  312. k += 1.0;
  313. ug /=k;
  314. g += ug;
  315. t = fabsf(uf/f);
  316. }
  317. uf = c1 * f;
  318. ug = c2 * g;
  319. if( (domflg & 1) == 0 )
  320. *ai = uf - ug;
  321. if( (domflg & 2) == 0 )
  322. *bi = sqrt3 * (uf + ug);
  323. /* the deriviative of ai */
  324. k = 4.0;
  325. uf = x * x/2.0;
  326. ug = z/3.0;
  327. f = uf;
  328. g = 1.0 + ug;
  329. uf /= 3.0;
  330. t = 1.0;
  331. while( t > MACHEPF )
  332. {
  333. uf *= z;
  334. ug /=k;
  335. k += 1.0;
  336. ug *= z;
  337. uf /=k;
  338. f += uf;
  339. k += 1.0;
  340. ug /=k;
  341. uf /=k;
  342. g += ug;
  343. k += 1.0;
  344. t = fabsf(ug/g);
  345. }
  346. uf = c1 * f;
  347. ug = c2 * g;
  348. if( (domflg & 4) == 0 )
  349. *aip = uf - ug;
  350. if( (domflg & 8) == 0 )
  351. *bip = sqrt3 * (uf + ug);
  352. return(0);
  353. }