OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
ComplexErrorFun.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: ComplexErrorFun.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.2 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Function: Werrf(complex<double>)
10 // The complex error function.
11 //
12 // ------------------------------------------------------------------------
13 // Class category: Utilities
14 // ------------------------------------------------------------------------
15 //
16 // $Date: 2001/08/24 19:33:44 $
17 // $Author: jsberg $
18 //
19 // ------------------------------------------------------------------------
20 
22 #include <complex>
23 
24 
25 // Complex error function
26 // The algorithms is based on:
27 // Walter Gautschi,
28 // Efficient Computation of the Complex Error Function,
29 // SIAM J. Numer. Anal., Vol 7, No. 1, March 1970, pp. 187-198.
30 // ------------------------------------------------------------------------
31 
32 std::complex<double> Werrf(std::complex<double> z) {
33  const double cc = 1.12837916709551; // 2 / sqrt(pi)
34  const double xlim = 5.33;
35  const double ylim = 4.29;
36 
37  const double x = std::abs(std::real(z));
38  const double y = std::abs(std::imag(z));
39  std::complex<double> w;
40 
41  if(y < ylim && x < xlim) {
42  // Inside limit rectangle: equation (3.8): q = s(z);
43  const double q = (1.0 - y / ylim) * sqrt(1.0 - (x * x) / (xlim * xlim));
44  // Equations (3.11).
45  const int nc = 6 + int(23.0 * q);
46  const int nu = 9 + int(21.0 * q);
47  const std::complex<double> zz(1.6 * q + y, - x); // h - i*z
48 
49  // Equations (3.12) for n = nu, nu - 1, ..., N.
50  std::complex<double> r(0.0); // r_{nu}
51  for(int n = nu; n > nc; n--) { // for n = nu, nu-1, ..., nc+1
52  r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
53  }
54 
55  // Equations (3.12) for n = N, N - 1, ..., 0.
56  double power = pow(3.2 * q, nc); // (2*h)^nc
57  const double div = 0.3125 / q; // 1 / (2*h)
58  std::complex<double> s(0.0); // s_{N}
59  for(int n = nc; n >= 0; n--) { // for n = N, N-1, ..., 0
60  r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
61  s = r * (power + s); // s_{n-1}
62  power *= div; // (2*h)^(n-1)
63  }
64 
65  // Equation (3.13).
66  w = cc * s;
67  } else {
68  // Outside limit rectangle: equations (3.12) for h = 0.
69  const std::complex<double> zz(y, - x); // - i*z
70  std::complex<double> r(0.0); // r_{nu}
71  for(int n = 8; n >= 0; n--) { // for n = nu, nu-1, ..., 0
72  r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
73  }
74 
75  // Equation (3.13).
76  w = cc * r;
77  }
78 
79  // Equations (3.1).
80  if(std::imag(z) < 0.0) {
81  std::complex<double> zz(x, y);
82  w = 2.0 * std::exp(- zz * zz) - w;
83  if(std::real(z) > 0.0) w = std::conj(w);
84  } else {
85  if(std::real(z) < 0.0) w = std::conj(w);
86  }
87 
88  return w;
89 }
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
m_complex conj(const m_complex &c)
Definition: MVector.h:105
std::complex< double > Werrf(std::complex< double > z)
Complex error function.
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &)
Take imaginary part of a complex generator.