1 |
#include <math.h>
|
2 |
#include <TMath.h>
|
3 |
|
4 |
|
5 |
|
6 |
//************** EXPONENTIAL INTEGRALS En *****
|
7 |
// define: E_n(x) = \int_1^infty{exp(-xt)/t^n}dt, x>0, n=0,1,...
|
8 |
double expint(int n, double x) {
|
9 |
// based on Numerical Recipes in C
|
10 |
const double euler = 0.57721566; // Euler's constant, gamma
|
11 |
const int maxit = 100; // max. no. of iterations allowed
|
12 |
const double fpmin = 1.0e-30; // close to smallest floating-point number
|
13 |
const double eps = 6.0e-8; // relative error, or absolute error near
|
14 |
// the zero of Ei at x=0.3725
|
15 |
|
16 |
int i, ii, nm1;
|
17 |
double a,b,c,d,del,fact,h,psi,ans;
|
18 |
|
19 |
nm1=n-1;
|
20 |
if(n<0 || x<0 || (x==0 && (n==0 || n==1))) {
|
21 |
cout << "Bad argument for expint(n,x)" << endl; return -1;
|
22 |
}
|
23 |
else {
|
24 |
if(n==0) ans=exp(-x)/x;
|
25 |
else {
|
26 |
if(x==0) ans=1.0/nm1;
|
27 |
else {
|
28 |
if(x>1) {
|
29 |
b=x+n;
|
30 |
c=1.0/fpmin;
|
31 |
d=1.0/b;
|
32 |
h=d;
|
33 |
for(i=1; i<maxit; i++) {
|
34 |
a = -i*(nm1+i);
|
35 |
b += 2.0;
|
36 |
d=1.0/(a*d+b);
|
37 |
c=b+a/c;
|
38 |
del=c*d;
|
39 |
h *= del;
|
40 |
if(fabs(del-1.0)<eps) {
|
41 |
ans=h*exp(-x);
|
42 |
return ans;
|
43 |
}
|
44 |
}
|
45 |
cout << "***continued fraction failed in expint(n,x)!!!" << endl;
|
46 |
return -1;
|
47 |
} else {
|
48 |
ans = (nm1!=0 ? 1.0/nm1 : -log(x)-euler);
|
49 |
fact=1;
|
50 |
for(i=1; i<=maxit; i++) {
|
51 |
fact *= -x/i;
|
52 |
if(i!=nm1) del = -fact/(i-nm1);
|
53 |
else {
|
54 |
psi = -euler;
|
55 |
for(ii=1; ii<=nm1; ii++) psi += 1.0/ii;
|
56 |
del = fact*(-log(x)+psi);
|
57 |
}
|
58 |
ans += del;
|
59 |
if(fabs(del)<fabs(ans)*eps) return ans;
|
60 |
}
|
61 |
cout << "***series failed in expint!!!" << endl;
|
62 |
return -1;
|
63 |
}
|
64 |
}
|
65 |
}
|
66 |
}
|
67 |
|
68 |
return ans;
|
69 |
}
|
70 |
//*********************************************
|
71 |
|
72 |
|
73 |
//************** EXPONENTIAL INTEGRAL Ei ******
|
74 |
// define: ei(x) = -\int_{-x}^{\infty}{exp(-t)/t}dt, for x>0
|
75 |
// power series: ei(x) = eulerconst + ln(x) + x/(1*1!) + x^2/(2*2!) + ...
|
76 |
double ei(double x)
|
77 |
{ // taken from Numerical Recipes in C
|
78 |
const double euler = 0.57721566; // Euler's constant, gamma
|
79 |
const int maxit = 100; // max. no. of iterations allowed
|
80 |
const double fpmin = 1.0e-40; // close to smallest floating-point number
|
81 |
const double eps = 1.0e-30; // relative error, or absolute error near
|
82 |
// the zero of Ei at x=0.3725
|
83 |
// I actually changed fpmin and eps into smaller values than in NR
|
84 |
|
85 |
int k;
|
86 |
double fact, prev, sum, term;
|
87 |
|
88 |
// special case
|
89 |
if(x < 0) return -expint(1,-x);
|
90 |
|
91 |
if(x == 0.0) { cout << "Bad argument for ei(x)" << endl; return -1; }
|
92 |
if(x < fpmin) return log(x)+euler;
|
93 |
if(x <= -log(eps)) {
|
94 |
sum = 0;
|
95 |
fact = 1;
|
96 |
for(k=1; k<=maxit; k++) {
|
97 |
fact *= x/k;
|
98 |
term = fact/k;
|
99 |
sum += term;
|
100 |
if(term < eps*sum) break;
|
101 |
}
|
102 |
if(k>maxit) { cout << "Series failed in ei(x)" << endl; return -1; }
|
103 |
return sum+log(x)+euler;
|
104 |
} else {
|
105 |
sum = 0;
|
106 |
term = 1;
|
107 |
for(k=1; k<=maxit; k++) {
|
108 |
prev = term;
|
109 |
term *= k/x;
|
110 |
if(term<eps) break;
|
111 |
if(term<prev) sum+=term;
|
112 |
else {
|
113 |
sum -= prev;
|
114 |
break;
|
115 |
}
|
116 |
}
|
117 |
return exp(x)*(1.0+sum)/x;
|
118 |
}
|
119 |
}
|
120 |
//*********************************************
|