OpenMD
3.2
Molecular Dynamics in the Open
Toggle main menu visibility
Loading...
Searching...
No Matches
erfc.hpp
1
/*
2
* Borrowed from OpenMM.
3
*/
4
5
#include <config.h>
6
#ifndef MATH_ERFC_H
7
#define MATH_ERFC_H
8
9
/*
10
* Up to version 11 (VC++ 2012), Microsoft does not support the
11
* standard C99 erf() and erfc() functions so we have to fake them
12
* here. These were added in version 12 (VC++ 2013), which sets
13
* _MSC_VER=1800 (VC11 has _MSC_VER=1700).
14
*/
15
16
#ifdef _MSC_VER
17
#if _MSC_VER <= 1700
// 1700 is VC11, 1800 is VC12
18
19
/***************************
20
* erf.cpp
21
* author: Steve Strand
22
* written: 29-Jan-04
23
***************************/
24
25
#include <cmath>
26
27
static
const
RealType rel_error = 1E-12;
// calculate 12 significant figures
28
// you can adjust rel_error to trade off between accuracy and speed
29
// but don't ask for > 15 figures (assuming usual 52 bit mantissa in a double)
30
31
static
RealType erfc(RealType x);
32
33
static
RealType erf(RealType x)
34
// erf(x) = 2/sqrt(pi)*integral(exp(-t^2),t,0,x)
35
// = 2/sqrt(pi)*[x - x^3/3 + x^5/5*2! - x^7/7*3! + ...]
36
// = 1-erfc(x)
37
{
38
static
const
RealType two_sqrtpi = 1.128379167095512574;
// 2/sqrt(pi)
39
if
(fabs(x) > 2.2) {
40
return
1.0 - erfc(x);
// use continued fraction when fabs(x) > 2.2
41
}
42
RealType sum = x, term = x, xsqr = x * x;
43
int
j = 1;
44
do
{
45
term *= xsqr / j;
46
sum -= term / (2 * j + 1);
47
++j;
48
term *= xsqr / j;
49
sum += term / (2 * j + 1);
50
++j;
51
}
while
(fabs(term) / sum > rel_error);
52
return
two_sqrtpi * sum;
53
}
54
55
static
RealType erfc(RealType x)
56
// erfc(x) = 2/sqrt(pi)*integral(exp(-t^2),t,x,inf)
57
// = exp(-x^2)/sqrt(pi) * [1/x+ (1/2)/x+ (2/2)/x+ (3/2)/x+ (4/2)/x+ ...]
58
// = 1-erf(x)
59
// expression inside [] is a continued fraction so '+' means add to denominator
60
// only
61
{
62
static
const
RealType one_sqrtpi = 0.564189583547756287;
// 1/sqrt(pi)
63
if
(fabs(x) < 2.2) {
64
return
1.0 - erf(x);
// use series when fabs(x) < 2.2
65
}
66
// Don't look for x==0 here!
67
if
(x < 0) {
// continued fraction only valid for x>0
68
return
2.0 - erfc(-x);
69
}
70
RealType a = 1, b = x;
// last two convergent numerators
71
RealType c = x, d = x * x + 0.5;
// last two convergent denominators
72
RealType q1, q2 = b / d;
// last two convergents (a/c and b/d)
73
RealType n = 1.0, t;
74
do
{
75
t = a * n + b * x;
76
a = b;
77
b = t;
78
t = c * n + d * x;
79
c = d;
80
d = t;
81
n += 0.5;
82
q1 = q2;
83
q2 = b / d;
84
}
while
(fabs(q1 - q2) / q2 > rel_error);
85
return
one_sqrtpi * exp(-x * x) * q2;
86
}
87
88
#endif
// _MSC_VER <= 1700
89
#endif
// _MSC_VER
90
#endif
math
erfc.hpp
Generated on
for OpenMD by
1.17.0