FEDRA emulsion software from the OPERA Collaboration
Erf.hh
Go to the documentation of this file.
1#ifndef __ERF_HH
2#define __ERF_HH
3// ********************************************************************
4//
5// source:
6//
7// type: source code
8//
9// created: 19. Apr 2001
10//
11// author: Thorsten Glebe
12// HERA-B Collaboration
13// Max-Planck-Institut fuer Kernphysik
14// Saupfercheckweg 1
15// 69117 Heidelberg
16// Germany
17// E-mail: T.Glebe@mpi-hd.mpg.de
18//
19// Description: Error (errf) and complementary error (errfc).
20//
21// changes:
22// 19 Apr 2001 (TG) creation
23//
24// ********************************************************************
25#include <cmath>
26
32template <class T>
33T erf_0_(int n, const T& rhs) {
34
35 /* Initialized data */
36 static const T p10 = 3.6767877;
37 static const T q10 = 3.2584593;
38 static const T p11 = -.097970465;
39 static const T p2[5] = { 7.3738883,6.8650185,3.0317993,.56316962,4.3187787e-5 };
40 static const T q2[5] = { 7.3739609,15.184908,12.79553,5.3542168,1. };
41 static const T p30 = -.12436854;
42 static const T q30 = .44091706;
43 static const T p31 = -.096821036;
44
45 /* Local variables */
46 static T h;
47 static int i;
48 static T hc, ap, aq;
49 static bool lef;
50
51 /* Above the value of VMAX any calculation is pointless. The value is
52 */
53 /* choosen with a big safety margin - even the double precision */
54 /* version only returns 1. for V (=ABS(X)) >= 5.9 */
55 /* The value for SWITCH is badly chosen for the single precision */
56 /* version, which returns 1. already for V >= 3.9 */
57
58 if(n==1)
59 lef = false;
60 else
61 lef = true;
62
63 const T v = fabs(rhs);
64 const T v2 = v*v;
65
66 if (v < .5) {
67 /* Computing 2nd power */
68 h = rhs * (p10 + p11 * v2) / (q10 + v2);
69 hc = 1 - h;
70 } else {
71 if (v < 4.) {
72 ap = p2[4];
73 aq = q2[4];
74 for (i = 3; i >= 0; --i) {
75 ap = p2[i] + v * ap;
76 aq = q2[i] + v * aq;
77 }
78 /* Computing 2nd power */
79 hc = exp(-v2) * ap / aq;
80 h = 1 - hc;
81 } else if (v < 7.) {
82 /* Computing 2nd power */
83 const T y = 1 / v2;
84 /* Computing 2nd power */
85 hc = exp(-v2) * (y * (p30 + p31 * y) / (q30 + y) + .56418958) / v;
86 h = 1 - hc;
87 /* for very big values we can save us any calculation, and the
88 */
89 /* FP-exceptions we would get from EXP. */
90 } else {
91 h = 1.;
92 hc = 0.;
93 }
94 if (rhs < 0.) {
95 h = -h;
96 hc = 2 - hc;
97 }
98 }
99
100 if (lef) {
101 return h;
102 } else {
103 return hc;
104 }
105}
106
114template <class T>
115T erf(const T& rhs) {
116 return erf_0_(0, rhs);
117}
118
126template <class T>
127T erfc(const T& rhs) {
128 return erf_0_(1, rhs);
129}
130#endif
T erf_0_(int n, const T &rhs)
Definition: Erf.hh:33
T erf(const T &rhs)
Definition: Erf.hh:115
T erfc(const T &rhs)
Definition: Erf.hh:127
Expr< UnaryOp< Fabs< T >, Expr< A, T, D >, T >, T, D > fabs(const Expr< A, T, D > &rhs)
Definition: UnaryOperators.hh:96