'Computes ONLY the Ei function of a given argument, x.
Where x is a real number
'Not to be confused with Expint(n,x) as this function doesn't compute Expint(n,x) 'Ei(x) = -[int(-x,inf)(exp(-u)*(1/u)*du), where x>0 'To find Ei(-x), the argument x, should be negative when entering values on the spreadsheet 'Computation is done using the Series representation, Continued fraction representation and 'Asymptotic expansion '================================================================================================== 'The Continued fraction is applied for Ei(-x) values where |x|>=1. 'Ei(-x)=-E1(x) by analytic continuation. 'The Ei(-x) is computed by taking a branch cut on the negative real axis and then, defined 'by analytic continuation on the complex plane. E1(x)=Expint(1,x); it is the case of n=1 'E1(x)= int(x,inf)(exp(-u)*(1/u)*du); where x is in the complex plane and x> 0 'Ei(-x)=-E1(x) 'Applying the more rapidly converging even form of the continued fraction: 'Ei(-x)=-[(exp(x))(1/x+n-(1*n)/x+n+2-(2*(n+1))/x+n+4-...)] where n=1 'The above continued fraction is solved using the Lentz's algorithm. '================================================================================================== 'The Power series representation is used for two different conditions: ' - To compute Ei(-x) when 0<|x|<=1: 'Ei(-x) = -[-EulerMascheroni Constant - ln(x) - [sum(((-x)^n)/(n*n!));where n starts from 1 to inf]; 'where x is now in the complex plane. Since the series representation converges fast enough for 'conditions, 0<x<=1, a maximum value of n=100 was used, although, there are situtations when it 'could exit the loop. ' - To compute Ei(x) when 0<x<=ll: 'where ll is the lower limit for the use of the asymptotic expansion and is given by: ll=|ln(EPS)| 'Ei(x) = Euler-Mascheroni Constant + ln(x) + [sum((x^n)/(n*n!));where n starts from 1 to inf] 'Also a maximum value of n=100 was used '================================================================================================== 'The Asymptotic expansion is used to approximate larger values of x. When x>=|ln(EPS)| 'Ei(x)~=(exp(x)/x)*(1 + [sum(n!/x^n); where n starts from 1 to inf]) 'A maximum value of n=100 was used 'The divergent characteristic of the expansion as the iteration proceeds was also taken in to 'consideration. '================================================================================================== 'References: Press W.H., Teukolsky S. A., Vetterling W. T. and Flannery B. P. 1986, ' Numerical Recipes in Fortran 77, The Art of Scientific Computing, ' 2nd Ed., Vol 1, (Newyork: Cambridge University Press), p. 216-220 ' Adewole, E.S. and Bello, K.O. 2004, Application of the Gauss-Laguerre ' Quadrature for Computing the Exponential Integral Functions, (Ei), ' Society of Petroleum Engineers (Nigeria), SPE 98829, pp. 2. ' Abramowitz, M., and Stegun, I.A. 1964, Handbook of Mathematical Functions, ' Applied Mathematics Series, Volume 55 (Washington: National Bureau of Standards; ' reprinted 1968 by Dover Publications, New York), Chapter 5. '================================================================================================== Option Explicit Public Function Ei(x As Double) As Variant Dim i, n, nmax As Integer Dim sum, fact, nterm, prevterm, ll As Double Dim a, b, c, d, h, del As Double Const EPS As Double = 0.000000000000002 'EPS is the floating point precision; an approximation of 'the significance of the nth term in the sum of all the terms 'FPMIN is a number near the smallest representable positive floating-point number; for Microsoft Excel, 'the smallest representable positive floating-point number is 4.94065645841247E-324 Const FPMIN As Double = 4.9E-308 Const EulerMascheroni As Double = 0.577215664901533 ll = -Log(EPS) Select Case x Case 0# Ei = "-inf" Case 0# To ll sum = 0# fact = 1# nmax = 100 For i = 1 To nmax fact = fact * (x / i) nterm = fact / i sum = sum + nterm If nterm < sum * EPS Then Exit For End If Next i Ei = EulerMascheroni + Log(x) + sum Case Is > ll sum = 0# nterm = 1# 'Value of the first term nmax = 100 For i = 1 To nmax prevterm = nterm nterm = nterm * i / x If nterm < EPS Then 'Since the final sum will involve adding 1, it will be GoTo 2 'greater than 1. Therefore, the "nterm" Else 'could act as an approximation for the relative error. If nterm < prevterm Then 'Expansion still converging: add new term. sum = sum + nterm Else 'Expansion diverging: Subtract previous term and exit sum = sum - prevterm GoTo 2 End If End If Next i 2: Ei = Exp(x) * (1# + sum) / x Case -1# To 0# x = -x sum = 0# fact = 1# nmax = 100 For i = 1 To nmax fact = fact * (-x / i) nterm = fact / i sum = sum + nterm If Abs(nterm) < Abs(sum) * EPS Then Exit For End If Next i Ei = -(-EulerMascheroni - Log(x) - sum) Case Is < -1# nmax = 100 x = -x n = 1 b = x + n c = 1# / FPMIN d = 1# / b h = d For i = 1 To nmax a = -i * i b = b + 2# d = 1# / (a * d + b) 'Denominators cannot be zero. c = b + a / c del = c * d h = h * del If (Abs(del - 1#) < EPS) Then Ei = -(h * Exp(-x)) Exit For End If Next i End Select End Function '===================================================================================================== 'An added function to compute the Exponential Integral, E(n,x) when n=1 'when n=1; E(n,x)=E1(x) 'This function EXCLUSIVELY defines E1(x) as Expint(x) Public Function Expint(x As Double) As Variant If x = 0# Then Expint = "inf" Else If x < 0# Then Expint = "NaN" 'x>0 Else Expint = -Ei(-x) 'Ei(-x)=-E1(x) by analytic continuation; therefore, E1(x)=-Ei(-x) End If End If End Function