expnf.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /* expnf.c
  2. *
  3. * Exponential integral En
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * int n;
  10. * float x, y, expnf();
  11. *
  12. * y = expnf( n, x );
  13. *
  14. *
  15. *
  16. * DESCRIPTION:
  17. *
  18. * Evaluates the exponential integral
  19. *
  20. * inf.
  21. * -
  22. * | | -xt
  23. * | e
  24. * E (x) = | ---- dt.
  25. * n | n
  26. * | | t
  27. * -
  28. * 1
  29. *
  30. *
  31. * Both n and x must be nonnegative.
  32. *
  33. * The routine employs either a power series, a continued
  34. * fraction, or an asymptotic formula depending on the
  35. * relative values of n and x.
  36. *
  37. * ACCURACY:
  38. *
  39. * Relative error:
  40. * arithmetic domain # trials peak rms
  41. * IEEE 0, 30 10000 5.6e-7 1.2e-7
  42. *
  43. */
  44. /* expn.c */
  45. /* Cephes Math Library Release 2.2: July, 1992
  46. * Copyright 1985, 1992 by Stephen L. Moshier
  47. * Direct inquiries to 30 Frost Street, Cambridge, MA 02140 */
  48. #include <math.h>
  49. #define EUL 0.57721566490153286060
  50. #define BIG 16777216.
  51. extern float MAXNUMF, MACHEPF, MAXLOGF;
  52. #ifdef ANSIC
  53. float powf(float, float), gammaf(float), logf(float), expf(float);
  54. #else
  55. float powf(), gammaf(), logf(), expf();
  56. #endif
  57. #define fabsf(x) ( (x) < 0 ? -(x) : (x) )
  58. float expnf( int n, float xx )
  59. {
  60. float x, ans, r, t, yk, xk;
  61. float pk, pkm1, pkm2, qk, qkm1, qkm2;
  62. float psi, z;
  63. int i, k;
  64. static float big = BIG;
  65. x = xx;
  66. if( n < 0 )
  67. goto domerr;
  68. if( x < 0 )
  69. {
  70. domerr: mtherr( "expnf", DOMAIN );
  71. return( MAXNUMF );
  72. }
  73. if( x > MAXLOGF )
  74. return( 0.0 );
  75. if( x == 0.0 )
  76. {
  77. if( n < 2 )
  78. {
  79. mtherr( "expnf", SING );
  80. return( MAXNUMF );
  81. }
  82. else
  83. return( 1.0/(n-1.0) );
  84. }
  85. if( n == 0 )
  86. return( expf(-x)/x );
  87. /* expn.c */
  88. /* Expansion for large n */
  89. if( n > 5000 )
  90. {
  91. xk = x + n;
  92. yk = 1.0 / (xk * xk);
  93. t = n;
  94. ans = yk * t * (6.0 * x * x - 8.0 * t * x + t * t);
  95. ans = yk * (ans + t * (t - 2.0 * x));
  96. ans = yk * (ans + t);
  97. ans = (ans + 1.0) * expf( -x ) / xk;
  98. goto done;
  99. }
  100. if( x > 1.0 )
  101. goto cfrac;
  102. /* expn.c */
  103. /* Power series expansion */
  104. psi = -EUL - logf(x);
  105. for( i=1; i<n; i++ )
  106. psi = psi + 1.0/i;
  107. z = -x;
  108. xk = 0.0;
  109. yk = 1.0;
  110. pk = 1.0 - n;
  111. if( n == 1 )
  112. ans = 0.0;
  113. else
  114. ans = 1.0/pk;
  115. do
  116. {
  117. xk += 1.0;
  118. yk *= z/xk;
  119. pk += 1.0;
  120. if( pk != 0.0 )
  121. {
  122. ans += yk/pk;
  123. }
  124. if( ans != 0.0 )
  125. t = fabsf(yk/ans);
  126. else
  127. t = 1.0;
  128. }
  129. while( t > MACHEPF );
  130. k = xk;
  131. t = n;
  132. r = n - 1;
  133. ans = (powf(z, r) * psi / gammaf(t)) - ans;
  134. goto done;
  135. /* expn.c */
  136. /* continued fraction */
  137. cfrac:
  138. k = 1;
  139. pkm2 = 1.0;
  140. qkm2 = x;
  141. pkm1 = 1.0;
  142. qkm1 = x + n;
  143. ans = pkm1/qkm1;
  144. do
  145. {
  146. k += 1;
  147. if( k & 1 )
  148. {
  149. yk = 1.0;
  150. xk = n + (k-1)/2;
  151. }
  152. else
  153. {
  154. yk = x;
  155. xk = k/2;
  156. }
  157. pk = pkm1 * yk + pkm2 * xk;
  158. qk = qkm1 * yk + qkm2 * xk;
  159. if( qk != 0 )
  160. {
  161. r = pk/qk;
  162. t = fabsf( (ans - r)/r );
  163. ans = r;
  164. }
  165. else
  166. t = 1.0;
  167. pkm2 = pkm1;
  168. pkm1 = pk;
  169. qkm2 = qkm1;
  170. qkm1 = qk;
  171. if( fabsf(pk) > big )
  172. {
  173. pkm2 *= MACHEPF;
  174. pkm1 *= MACHEPF;
  175. qkm2 *= MACHEPF;
  176. qkm1 *= MACHEPF;
  177. }
  178. }
  179. while( t > MACHEPF );
  180. ans *= expf( -x );
  181. done:
  182. return( ans );
  183. }