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 
32 template <class T>
33 T 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 
114 template <class T>
115 T erf(const T& rhs) {
116  return erf_0_(0, rhs);
117 }
118 
126 template <class T>
127 T 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