Mantid
Loading...
Searching...
No Matches
SpecialFunctionHelper.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8#include <gsl/gsl_math.h>
9#include <limits>
10
12
13using std::complex;
14
22complex<double> exponentialIntegral(const complex<double> &z) {
23 double z_abs = abs(z);
24
25 if (z_abs == 0.0) {
26 // Basically function is infinite in along the real axis for this case
27 return complex<double>(std::numeric_limits<double>::max(), 0.0);
28 } else if (z_abs < 10.0) // 10.0 is a guess based on formula 5.1.55 (no idea
29 // how good it really is)
30 {
31 // use formula 5.1.11 in A&S. rewrite last term in 5.1.11 as
32 // x*sum_n=0 (-1)^n x^n / (n+1)*(n+1)! and then calculate the
33 // terms in the sum recursively
34 complex<double> z1(1.0, 0.0);
35 complex<double> z2(1.0, 0.0);
36 for (int i = 1; i <= 100; i++) // is max of 100 here best?
37 {
38 z2 = -static_cast<double>(i) * (z2 * z) / ((i + 1.0) * (i + 1.0));
39 z1 += z2;
40 if (abs(z2) < 1.0E-10 * abs(z1))
41 break; // i.e. if break loop if little change to term added
42 }
43 return exp(z) * (-log(z) - M_EULER + z * z1);
44 } else {
45 // use formula 5.1.22 in A&S. See discussion page 231
46 complex<double> z1(0.0, 0.0);
47 for (int i = 20; i >= 1; i--) // not sure if 20 is always sensible?
48 z1 = static_cast<double>(i) / (1.0 + static_cast<double>(i) / (z + z1));
49 complex<double> retVal = 1.0 / (z + z1);
50 if (z.real() <= 0.0 && z.imag() == 0.0)
51 retVal -= exp(z) * complex<double>(0.0, 1.0) * M_PI; // see formula 5.1.7
52 return retVal;
53 }
54}
55
56} // namespace Mantid::CurveFitting::SpecialFunctionSupport
std::complex< double > MANTID_CURVEFITTING_DLL exponentialIntegral(const std::complex< double > &z)
Compute exp(z)*E1(z) where z is complex and E1(z) is the Exponential Integral.