OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
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// Complex error function
25// The algorithms is based on:
26// Walter Gautschi,
27// Efficient Computation of the Complex Error Function,
28// SIAM J. Numer. Anal., Vol 7, No. 1, March 1970, pp. 187-198.
29// ------------------------------------------------------------------------
30
31std::complex<double> Werrf(std::complex<double> z) {
32 const double cc = 1.12837916709551; // 2 / sqrt(pi)
33 const double xlim = 5.33;
34 const double ylim = 4.29;
35
36 const double x = std::abs(std::real(z));
37 const double y = std::abs(std::imag(z));
38 std::complex<double> w;
39
40 if (y < ylim && x < xlim) {
41 // Inside limit rectangle: equation (3.8): q = s(z);
42 const double q = (1.0 - y / ylim) * sqrt(1.0 - (x * x) / (xlim * xlim));
43 // Equations (3.11).
44 const int nc = 6 + int(23.0 * q);
45 const int nu = 9 + int(21.0 * q);
46 const std::complex<double> zz(1.6 * q + y, -x); // h - i*z
47
48 // Equations (3.12) for n = nu, nu - 1, ..., N.
49 std::complex<double> r(0.0); // r_{nu}
50 for (int n = nu; n > nc; n--) { // for n = nu, nu-1, ..., nc+1
51 r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
52 }
53
54 // Equations (3.12) for n = N, N - 1, ..., 0.
55 double power = pow(3.2 * q, nc); // (2*h)^nc
56 const double div = 0.3125 / q; // 1 / (2*h)
57 std::complex<double> s(0.0); // s_{N}
58 for (int n = nc; n >= 0; n--) { // for n = N, N-1, ..., 0
59 r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
60 s = r * (power + s); // s_{n-1}
61 power *= div; // (2*h)^(n-1)
62 }
63
64 // Equation (3.13).
65 w = cc * s;
66 } else {
67 // Outside limit rectangle: equations (3.12) for h = 0.
68 const std::complex<double> zz(y, -x); // - i*z
69 std::complex<double> r(0.0); // r_{nu}
70 for (int n = 8; n >= 0; n--) { // for n = nu, nu-1, ..., 0
71 r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
72 }
73
74 // Equation (3.13).
75 w = cc * r;
76 }
77
78 // Equations (3.1).
79 if (std::imag(z) < 0.0) {
80 std::complex<double> zz(x, y);
81 w = 2.0 * std::exp(-zz * zz) - w;
82 if (std::real(z) > 0.0) w = std::conj(w);
83 } else {
84 if (std::real(z) < 0.0) w = std::conj(w);
85 }
86
87 return w;
88}
std::complex< double > Werrf(std::complex< double > z)
Complex error function.