Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

753 lines
23 KiB

  1. /***
  2. *bessel.c - defines the bessel functions for C.
  3. *
  4. * Copyright (c) 1983-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. * This is a collection of routines for computing the bessel functions j0, j1,
  9. * y0, y1, jn and yn. The approximations used for j0, j1, y0, and y1 are
  10. * from the approximations listed in Hart, Computer Approximations, 1978.
  11. * For these functions, a rational approximation with 18 places of accuracy
  12. * after the decimal point has been selected. jn and yn are computed using
  13. * the recursive formula that the bessel functions satisfy. Using these
  14. * formulas their values can be computed from the values of the bessel
  15. * functions of order 0 and 1. In the case of jn, the recursive formula
  16. *
  17. * jn(n-1,x) = (2.0*n/x)*jn(n,x) - jn(n+1,x)
  18. *
  19. * is used to stabily compute in the downward direction, normalizing in the
  20. * the end by j0(x) in the usual manner. In the case of yn, the recursive
  21. * formula
  22. *
  23. * yn(n+1,x) = (2.0*n/x)*yn(n,x) - yn(n-1,x)
  24. *
  25. * is used to stably compute the functions in the forward direction.
  26. *
  27. *
  28. * Note: upon testing and experimentation the low range approximations were
  29. * found to have an error on the order of 1.0e-14 in the neighborhood of
  30. * 8.0. Moving the boundary point between the low range and high
  31. * range approximations down to 7.5 reduced this error to less than
  32. * 1.0e-14. This is not suprising. The high range asymptotoic is
  33. * likely to have greater precision in the neighborhood of 8.0.
  34. *
  35. *Revision History:
  36. *
  37. * 06/05/89 WAJ Added this header. Made changes for C6 and -W3
  38. * 06/06/89 WAJ Moved some of the routines into _RTEXT if MTHREAD.
  39. * 08/17/90 WAJ Now uses _stdcall.
  40. * 01/13/92 GDP changed domain_err. No full IEEE support yet
  41. * 04-06-93 SKS Replace _CALLTYPE* with __cdecl
  42. * 08-28-96 JWM Disabled warning 4056.
  43. *
  44. *******************************************************************************/
  45. /*
  46. * The functions sqrt, sin, cos, and log from the math library are used in
  47. * the computations of the bessel functions.
  48. */
  49. #include <math.h>
  50. #include <trans.h>
  51. #ifdef _M_IX86
  52. #pragma warning(disable:4056)
  53. #endif
  54. #ifdef _X86SEG_
  55. #include <os2supp.h>
  56. #define _CALLTYPE1 _PASCAL
  57. #else
  58. #include <cruntime.h>
  59. #endif
  60. #ifdef LD_VER
  61. #define D_TYPE long double
  62. #else
  63. #define D_TYPE double
  64. #endif
  65. static D_TYPE domain_err( int who, D_TYPE arg1, D_TYPE arg2 ); /* error routine for y0, y1, yn */
  66. static D_TYPE evaluate( D_TYPE x, D_TYPE p[], int n1, D_TYPE q[], int n2 );
  67. #ifdef FAR_CODE
  68. #ifdef LD_VER
  69. #pragma alloc_text( _RTEXT, _y0l, _y1l, _ynl, _j0l, _j1l, _jnl )
  70. #else
  71. #pragma alloc_text( _RTEXT, _y0, _y1, _yn, _j0, _j1, _jn )
  72. #endif
  73. #endif
  74. /*
  75. * Following are the constants needed for the computations of the bessel
  76. * functions as in Hart.
  77. */
  78. #define PI 3.14159265358979323846264338327950288
  79. /* coefficients for Hart JZERO 5848, the low range approximation for _j0 */
  80. static D_TYPE J0p[12] = {
  81. 0.1208181340866561224763662419e+12 ,
  82. -0.2956513002312076810191727211e+11 ,
  83. 0.1729413174598080383355729444e+10 ,
  84. -0.4281611621547871420502838045e+08 ,
  85. 0.5645169313685735094277826749e+06 ,
  86. -0.4471963251278787165486324342e+04 ,
  87. 0.2281027164345610253338043760e+02 ,
  88. -0.7777570245675629906097285039e-01 ,
  89. 0.1792464784997734953753734861e-03 ,
  90. -0.2735011670747987792661294323e-06 ,
  91. 0.2553996162031530552738418047e-09 ,
  92. -0.1135416951138795305302383379e-12
  93. };
  94. static D_TYPE J0q[5] = {
  95. 0.1208181340866561225104607422e+12 ,
  96. 0.6394034985432622416780183619e+09 ,
  97. 0.1480704129894421521840387092e+07 ,
  98. 0.1806405145147135549477896097e+04 ,
  99. 0.1e+01
  100. };
  101. /* coefficients for Hart 6548, P0 of the high range approximation for j0
  102. and _y0 */
  103. static D_TYPE P0p[6] = {
  104. 0.2277909019730468430227002627e+05 ,
  105. 0.4134538663958076579678016384e+05 ,
  106. 0.2117052338086494432193395727e+05 ,
  107. 0.3480648644324927034744531110e+04 ,
  108. 0.1537620190900835429577172500e+03 ,
  109. 0.8896154842421045523607480000e+00
  110. };
  111. static D_TYPE P0q[6] = {
  112. 0.2277909019730468431768423768e+05 ,
  113. 0.4137041249551041663989198384e+05 ,
  114. 0.2121535056188011573042256764e+05 ,
  115. 0.3502873513823560820735614230e+04 ,
  116. 0.1571115985808089364906848200e+03 ,
  117. 0.1e+01
  118. };
  119. /* coefficients for Hart 6948, Q0 of the high range approximation for _j0
  120. and _y0 */
  121. static D_TYPE Q0p[6] = {
  122. -0.8922660020080009409846916000e+02 ,
  123. -0.1859195364434299380025216900e+03 ,
  124. -0.1118342992048273761126212300e+03 ,
  125. -0.2230026166621419847169915000e+02 ,
  126. -0.1244102674583563845913790000e+01 ,
  127. -0.8803330304868075181663000000e-02
  128. };
  129. static D_TYPE Q0q[6] = {
  130. 0.5710502412851206190524764590e+04 ,
  131. 0.1195113154343461364695265329e+05 ,
  132. 0.7264278016921101883691345060e+04 ,
  133. 0.1488723123228375658161346980e+04 ,
  134. 0.9059376959499312585881878000e+02 ,
  135. 0.1e+01
  136. };
  137. /* coefficients for Hart JONE 6047, the low range approximation for _j1 */
  138. static D_TYPE J1p[11] = {
  139. 0.4276440148317146125749678272e+11 ,
  140. -0.5101551390663600782363700742e+10 ,
  141. 0.1928444249391651825203957853e+09 ,
  142. -0.3445216851469225845312168656e+07 ,
  143. 0.3461845033978656620861683039e+05 ,
  144. -0.2147334276854853222870548439e+03 ,
  145. 0.8645934990693258061130801001e+00 ,
  146. -0.2302415336775925186376173217e-02 ,
  147. 0.3991878933072250766608485041e-05 ,
  148. -0.4179409142757237977587032616e-08 ,
  149. 0.2060434024597835939153003596e-11
  150. };
  151. static D_TYPE J1q[5] = {
  152. 0.8552880296634292263013618479e+11 ,
  153. 0.4879975894656629161544052051e+09 ,
  154. 0.1226033111836540909388789681e+07 ,
  155. 0.1635396109098603257687643236e+04 ,
  156. 0.1e+01
  157. };
  158. /* coefficients for Hart PONE 6749, P1 of the high range approximation for
  159. _j1 and y1 */
  160. static D_TYPE P1p[6] = {
  161. 0.3522466491336797983417243730e+05 ,
  162. 0.6275884524716128126900567500e+05 ,
  163. 0.3135396311091595742386698880e+05 ,
  164. 0.4985483206059433843450045500e+04 ,
  165. 0.2111529182853962382105718000e+03 ,
  166. 0.1257171692914534155849500000e+01
  167. };
  168. static D_TYPE P1q[6] = {
  169. 0.3522466491336797980683904310e+05 ,
  170. 0.6269434695935605118888337310e+05 ,
  171. 0.3124040638190410399230157030e+05 ,
  172. 0.4930396490181088978386097000e+04 ,
  173. 0.2030775189134759322293574000e+03 ,
  174. 0.1e+01
  175. };
  176. /* coefficients for Hart QONE 7149, Q1 of the high range approximation for _j1
  177. and y1 */
  178. static D_TYPE Q1p[6] = {
  179. 0.3511751914303552822533318000e+03 ,
  180. 0.7210391804904475039280863000e+03 ,
  181. 0.4259873011654442389886993000e+03 ,
  182. 0.8318989576738508273252260000e+02 ,
  183. 0.4568171629551226706440500000e+01 ,
  184. 0.3532840052740123642735000000e-01
  185. };
  186. static D_TYPE Q1q[6] = {
  187. 0.7491737417180912771451950500e+04 ,
  188. 0.1541417733926509704998480510e+05 ,
  189. 0.9152231701516992270590472700e+04 ,
  190. 0.1811186700552351350672415800e+04 ,
  191. 0.1038187587462133728776636000e+03 ,
  192. 0.1e+01
  193. };
  194. /* coeffiecients for Hart YZERO 6245, the low range approximation for y0 */
  195. static D_TYPE Y0p[9] = {
  196. -0.2750286678629109583701933175e+20 ,
  197. 0.6587473275719554925999402049e+20 ,
  198. -0.5247065581112764941297350814e+19 ,
  199. 0.1375624316399344078571335453e+18 ,
  200. -0.1648605817185729473122082537e+16 ,
  201. 0.1025520859686394284509167421e+14 ,
  202. -0.3436371222979040378171030138e+11 ,
  203. 0.5915213465686889654273830069e+08 ,
  204. -0.4137035497933148554125235152e+05
  205. };
  206. static D_TYPE Y0q[9] = {
  207. 0.3726458838986165881989980739e+21 ,
  208. 0.4192417043410839973904769661e+19 ,
  209. 0.2392883043499781857439356652e+17 ,
  210. 0.9162038034075185262489147968e+14 ,
  211. 0.2613065755041081249568482092e+12 ,
  212. 0.5795122640700729537480087915e+09 ,
  213. 0.1001702641288906265666651753e+07 ,
  214. 0.1282452772478993804176329391e+04 ,
  215. 0.1e+01
  216. };
  217. /* coefficients for Hart YONE 6444, the low range approximation for y1 */
  218. static D_TYPE Y1p[8] = {
  219. -0.2923821961532962543101048748e+20 ,
  220. 0.7748520682186839645088094202e+19 ,
  221. -0.3441048063084114446185461344e+18 ,
  222. 0.5915160760490070618496315281e+16 ,
  223. -0.4863316942567175074828129117e+14 ,
  224. 0.2049696673745662182619800495e+12 ,
  225. -0.4289471968855248801821819588e+09 ,
  226. 0.3556924009830526056691325215e+06
  227. };
  228. static D_TYPE Y1q[9] = {
  229. 0.1491311511302920350174081355e+21 ,
  230. 0.1818662841706134986885065935e+19 ,
  231. 0.1131639382698884526905082830e+17 ,
  232. 0.4755173588888137713092774006e+14 ,
  233. 0.1500221699156708987166369115e+12 ,
  234. 0.3716660798621930285596927703e+09 ,
  235. 0.7269147307198884569801913150e+06 ,
  236. 0.1072696143778925523322126700e+04 ,
  237. 0.1e+01
  238. };
  239. /*
  240. * Function name: evaluate
  241. *
  242. * Arguments: x - double
  243. * p, q - double arrays of coefficients
  244. * n1, n2 - the order of the numerator and denominator
  245. * polynomials
  246. *
  247. * Description: evaluate is meant strictly as a helper routine for the
  248. * bessel function routines to evaluate the rational polynomial
  249. * aproximations appearing in _j0, _j1, y0, and y1. Given the
  250. * coefficient arrays in p and q, it evaluates the numerator
  251. * and denominator polynomials through orders n1 and n2
  252. * respectively, returning p(x)/q(x). This routine is not
  253. * available to the user of the bessel function routines.
  254. *
  255. * Side Effects: evaluate uses the global data stored in the coefficients
  256. * above. No other global data is used or affected.
  257. *
  258. * Author: written R.K. Wyss, Microsoft, Sept. 9, 1983
  259. *
  260. * History:
  261. */
  262. static D_TYPE evaluate( D_TYPE x, D_TYPE p[], int n1, D_TYPE q[], int n2 )
  263. {
  264. D_TYPE numerator, denominator;
  265. int i;
  266. numerator = x*p[n1];
  267. for ( i = n1-1 ; i > 0 ; i-- )
  268. numerator = x*(p[i] + numerator);
  269. numerator += p[0];
  270. denominator = x*q[n2];
  271. for ( i = n2-1 ; i > 0 ; i-- )
  272. denominator = x*(q[i] + denominator);
  273. denominator += q[0];
  274. return( numerator/denominator );
  275. }
  276. /*
  277. * Function name: _j0
  278. *
  279. * Arguments: x - double
  280. *
  281. * Description: _j0 computes the bessel function of the first kind of zero
  282. * order for real values of its argument x, where x can range
  283. * from - infinity to + infinity. The algorithm is taken
  284. * from Hart, Computer Approximations, 1978, and yields full
  285. * double precision accuracy.
  286. *
  287. * Side Effects: no global data other than the static coefficients above
  288. * is used or affected.
  289. *
  290. * Author: written R.K. Wyss, Microsoft, Sept. 9, 1983
  291. *
  292. * History:
  293. */
  294. #ifdef LD_VER
  295. D_TYPE _
  296. cdecl _j0l( D_TYPE x )
  297. #else
  298. D_TYPE __cdecl _j0( D_TYPE x )
  299. #endif
  300. {
  301. D_TYPE z, P0, Q0;
  302. /* if the argument is negative, take the absolute value */
  303. if ( x < 0.0 )
  304. x = - x;
  305. /* if x <= 7.5 use Hart JZERO 5847 */
  306. if ( x <= 7.5 )
  307. return( evaluate( x*x, J0p, 11, J0q, 4) );
  308. /* else if x >= 7.5 use Hart PZERO 6548 and QZERO 6948, the high range
  309. approximation */
  310. else {
  311. z = 8.0/x;
  312. P0 = evaluate( z*z, P0p, 5, P0q, 5);
  313. Q0 = z*evaluate( z*z, Q0p, 5, Q0q, 5);
  314. return( sqrt(2.0/(PI*x))*(P0*cos(x-PI/4) - Q0*sin(x-PI/4)) );
  315. }
  316. }
  317. /*
  318. * Function name: _j1
  319. *
  320. * Arguments: x - double
  321. *
  322. * Description: _j1 computes the bessel function of the first kind of the
  323. * first order for real values of its argument x, where x can
  324. * range from - infinity to + infinity. The algorithm is taken
  325. * from Hart, Computer Approximations, 1978, and yields full
  326. * D_TYPE precision accuracy.
  327. *
  328. * Side Effects: no global data other than the static coefficients above
  329. * is used or affected.
  330. *
  331. * Author: written R.K. Wyss, Microsoft, Sept. 9, 1983
  332. *
  333. * History:
  334. */
  335. #ifdef LD_VER
  336. D_TYPE _cdecl _j1l( D_TYPE x )
  337. #else
  338. D_TYPE __cdecl _j1( D_TYPE x )
  339. #endif
  340. {
  341. D_TYPE z, P1, Q1;
  342. int sign;
  343. /* if the argument is negative, take the absolute value and set sign */
  344. sign = 1;
  345. if( x < 0.0 ){
  346. x = -x;
  347. sign = -1;
  348. }
  349. /* if x <= 7.5 use Hart JONE 6047 */
  350. if ( x <= 7.5 )
  351. return( sign*x*evaluate( x*x, J1p, 10, J1q, 4) );
  352. /* else if x > 7.5 use Hart PONE 6749 and QONE 7149, the high range
  353. approximation */
  354. else {
  355. z = 8.0/x;
  356. P1 = evaluate( z*z, P1p, 5, P1q, 5);
  357. Q1 = z*evaluate( z*z, Q1p, 5, Q1q, 5);
  358. return( sign*sqrt(2.0/(PI*x))*
  359. ( P1*cos(x-3.0*PI/4.0) - Q1*sin(x-3.0*PI/4.0) ) );
  360. }
  361. }
  362. /*
  363. * Function name: _y0
  364. *
  365. * Arguments: x - double
  366. *
  367. * Description: y0 computes the bessel function of the second kind of zero
  368. * order for real values of its argument x, where x can range
  369. * from 0 to + infinity. The algorithm is taken from Hart,
  370. * Computer Approximations, 1978, and yields full double
  371. * precision accuracy.
  372. *
  373. * Side Effects: no global data other than the static coefficients above
  374. * is used or affected.
  375. *
  376. * Author: written R.K. Wyss, Microsoft, Sept. 9, 1983
  377. *
  378. * History:
  379. */
  380. #ifdef LD_VER
  381. D_TYPE _cdecl _y0l( D_TYPE x )
  382. #else
  383. D_TYPE __cdecl _y0( D_TYPE x )
  384. #endif
  385. {
  386. D_TYPE z, P0, Q0;
  387. /* if the argument is negative, set EDOM error, print an error message,
  388. * and return -HUGE
  389. */
  390. if (x < 0.0)
  391. return( domain_err(OP_Y0 , x, D_IND) );
  392. /* if x <= 7.5 use Hart YZERO 6245, the low range approximation */
  393. if ( x <= 7.5 )
  394. return( evaluate( x*x, Y0p, 8, Y0q, 8) + (2.0/PI)*_j0(x)*log(x) );
  395. /* else if x > 7.5 use Hart PZERO 6548 and QZERO 6948, the high range
  396. approximation */
  397. else {
  398. z = 8.0/x;
  399. P0 = evaluate( z*z, P0p, 5, P0q, 5);
  400. Q0 = z*evaluate( z*z, Q0p, 5, Q0q, 5);
  401. return( sqrt(2.0/(PI*x))*(P0*sin(x-PI/4) + Q0*cos(x-PI/4)) );
  402. }
  403. }
  404. /*
  405. * Function name: _y1
  406. *
  407. * Arguments: x - double
  408. *
  409. * Description: y1 computes the bessel function of the second kind of first
  410. * order for real values of its argument x, where x can range
  411. * from 0 to + infinity. The algorithm is taken from Hart,
  412. * Computer Approximations, 1978, and yields full double
  413. * precision accuracy.
  414. *
  415. * Side Effects: no global data other than the static coefficients above
  416. * is used or affected.
  417. *
  418. * Author: written R.K. Wyss, Microsoft, Sept. 9, 1983
  419. *
  420. * History:
  421. */
  422. #ifdef LD_VER
  423. D_TYPE _cdecl _y1l( D_TYPE x )
  424. #else
  425. D_TYPE __cdecl _y1( D_TYPE x )
  426. #endif
  427. {
  428. D_TYPE z, P1, Q1;
  429. /* if the argument is negative, set EDOM error, print an error message,
  430. * and return -HUGE
  431. */
  432. if (x < 0.0)
  433. return( domain_err(OP_Y1, x, D_IND) );
  434. /* if x <= 7.5 use Hart YONE 6444, the low range approximation */
  435. if ( x <= 7.5 )
  436. return( x*evaluate( x*x, Y1p, 7, Y1q, 8)
  437. + (2.0/PI)*(_j1(x)*log(x) - 1.0/x) );
  438. /* else if x > 7.5 use Hart PONE 6749 and QONE 7149, the high range
  439. approximation */
  440. else {
  441. z = 8.0/x;
  442. P1 = evaluate( z*z, P1p, 5, P1q, 5);
  443. Q1 = z*evaluate( z*z, Q1p, 5, Q1q, 5);
  444. return( sqrt(2.0/(PI*x))*
  445. ( P1*sin(x-3.0*PI/4.0) + Q1*cos(x-3.0*PI/4.0) ) );
  446. }
  447. }
  448. /*
  449. * Function name: _jn
  450. *
  451. * Arguments: n - integer
  452. * x - double
  453. *
  454. * Description: _jn computes the bessel function of the first kind of order
  455. * n for real values of its argument, where x can range from
  456. * - infinity to + infinity, and n can range over the integers
  457. * from - infinity to + infinity. The function is computed
  458. * by recursion, using the formula
  459. *
  460. * _jn(n-1,x) = (2.0*n/x)*_jn(n,x) - _jn(n+1,x)
  461. *
  462. * stabilly in the downward direction, normalizing by _j0(x)
  463. * in the end in the usual manner.
  464. *
  465. * Side Effects: the routines _j0, y0, and yn are called during the
  466. * execution of this routine.
  467. *
  468. * Author: written R.K. Wyss, Microsoft, Sept. 9, 1983
  469. *
  470. * History:
  471. * 07/29/85 Greg Whitten
  472. * rewrote _jn to use Hart suggested algorithm
  473. */
  474. #ifdef LD_VER
  475. D_TYPE _cdecl _jnl( int n, D_TYPE x )
  476. #else
  477. D_TYPE __cdecl _jn( int n, D_TYPE x )
  478. #endif
  479. {
  480. int i;
  481. D_TYPE x2, jm1, j, jnratio, hold;
  482. /* use symmetry relationships: _j(-n,x) = _j(n,-x) */
  483. if( n < 0 ){
  484. n = -n;
  485. x = -x;
  486. }
  487. /* if n = 0 use _j0(x) and if n = 1 use _j1(x) functions */
  488. if (n == 0)
  489. return (_j0(x));
  490. if (n == 1)
  491. return (_j1(x));
  492. /* if x = 0.0 then _j(n,0.0) = 0.0 for n > 0 (_j(0,x) = 1.0) */
  493. if (x == 0.0)
  494. return (0.0);
  495. /* otherwise - must use the recurrence relation
  496. *
  497. * _jn(n+1,x) = (2.0*n/x)*_jn(n,x) - _jn(n-1,x) forward
  498. * _jn(n-1,x) = (2.0*n/x)*_jn(n,x) - _jn(n+1,x) backward
  499. */
  500. if( (double)n < fabs(x) ) {
  501. /* stably compute _jn using forward recurrence above */
  502. n <<= 1; /* n *= 2 (n is positive) */
  503. jm1 = _j0(x);
  504. j = _j1(x);
  505. i = 2;
  506. for(;;) {
  507. hold = j;
  508. j = ((double)(i))*j/x - jm1;
  509. i += 2;
  510. if (i == n)
  511. return (j);
  512. jm1 = hold;
  513. }
  514. }
  515. else {
  516. /* stably compute _jn using backward recurrence above */
  517. /* use Hart continued fraction formula for j(n,x)/j(n-1,x)
  518. * so that we can compute a normalization factor
  519. */
  520. n <<= 1; /* n *= 2 (n is positive) */
  521. x2 = x*x;
  522. hold = 0.0; /* initial continued fraction tail value */
  523. for (i=n+36; i>n; i-=2)
  524. hold = x2/((double)(i) - hold);
  525. jnratio = j = x/((double)(n) - hold);
  526. jm1 = 1.0;
  527. /* have jn/jn-1 ratio - now use backward recurrence */
  528. i = n-2;
  529. for (;;) {
  530. hold = jm1;
  531. jm1 = ((double)(i))*jm1/x - j;
  532. i -= 2;
  533. if (i == 0)
  534. break;
  535. j = hold;
  536. }
  537. /* jm1 is relative j0(x) so normalize it for final result
  538. *
  539. * jnratio = K*j(n,x) and jm1 = K*_j0(x)
  540. */
  541. return(_j0(x)*jnratio/jm1);
  542. }
  543. }
  544. /*
  545. * Function name: _yn
  546. *
  547. * Arguments: n - integer
  548. * x - double
  549. *
  550. * Description: yn computes the bessel function of the second kind of order
  551. * n for real values of its argument x, where x can range from
  552. * 0 to + infinity, and n can range over the integers from
  553. * - infinity to + infinity. The function is computed by
  554. * recursion from y0 and y1, using the recursive formula
  555. *
  556. * yn(n+1,x) = (2.0*n/x)*yn(n,x) - yn(n-1,x)
  557. *
  558. * in the forward direction.
  559. *
  560. * Side Effects: the routines y0 and y1 are called during the execution
  561. * of this routine.
  562. *
  563. * Author: written R.K. Wyss, Microsoft, Sept. 9, 1983
  564. *
  565. * History:
  566. * 08/09/85 Greg Whitten
  567. * added check for n==0 and n==1
  568. * 04/20/87 Barry McCord
  569. * eliminated use of "const" as an identifier for ANSI conformance
  570. */
  571. #ifdef LD_VER
  572. D_TYPE _cdecl _ynl( int n, D_TYPE x )
  573. #else
  574. D_TYPE __cdecl _yn( int n, D_TYPE x )
  575. #endif
  576. {
  577. int i;
  578. int sign;
  579. D_TYPE constant, yn2, yn1, yn0;
  580. /* if the argument is negative, set EDOM error, print an error message,
  581. * and return -HUGE
  582. */
  583. if (x < 0.0)
  584. return(domain_err(OP_YN, x, D_IND));
  585. /* take the absolute value of n, and set sign accordingly */
  586. sign = 1;
  587. if( n < 0 ){
  588. n = -n;
  589. if( n&1 )
  590. sign = -1;
  591. }
  592. if( n == 0 )
  593. return( sign*_y0(x) );
  594. if (n == 1)
  595. return( sign*_y1(x) );
  596. /* otherwise go ahead and compute the function by iteration */
  597. yn0 = _y0(x);
  598. yn1 = _y1(x);
  599. constant = 2.0/x;
  600. for( i = 1 ; i < n ; i++ ){
  601. yn2 = constant*i*yn1 - yn0;
  602. yn0 = yn1;
  603. yn1 = yn2;
  604. }
  605. return( sign*yn2 );
  606. }
  607. static D_TYPE domain_err( int who, D_TYPE arg1, D_TYPE arg2 )
  608. {
  609. #ifdef LD_VER
  610. #error long double version not supported
  611. #endif
  612. uintptr_t savedcw;
  613. savedcw = _maskfp();
  614. return _except1(FP_I, who, arg1, arg2, savedcw);
  615. }