Utilities/Math/Math.cc
Go to the documentation of this file.
1 #include <sstream>
2 #include <vector>
3 #include <limits>
4 
5 #include <utl/Math.h>
6 #include <utl/ErrorLogger.h>
7 
8 using namespace std;
9 
10 
11 namespace utl {
12 
21  /*double
22  LogGamma(const double x)
23  {
24  const double p[7] = {
25  1.000000000190015,
26  76.18009172947146,
27  -86.50532032941677,
28  24.01409824083091,
29  -1.231739572450155,
30  1.208650973866179e-3,
31  -5.395239384953e-6
32  };
33 
34  double series = p[0];
35  for (int i = 1; i < 7; ++i)
36  series += p[i]/(x+i);
37 
38  const double xx = x + 5.5;
39  const double xxx = xx - log(xx) * (x + 0.5);
40  const double sqrt2pi = 2.5066282746310005;
41 
42  return log(sqrt2pi/x * series) - xxx;
43  }*/
44 
45 
54  double
55  IncompleteGammaPSeries(const double a, const double x)
56  {
57  if (x <= 0) {
58  if (x < 0)
59  ERROR("x less than 0 in function IncompleteGammaPSeries()");
60  return 0;
61  } else if (a <= 0) {
62  ERROR("Invalid arguments in function IncompleteGammaP()");
63  return 0;
64  } else {
65  const double eps = 1e-12;
66  const double lnga = LogGamma(a);
67  double ap = a;
68  double del = 1/a;
69  double sum = del;
70  for (int n = 1; n <= 100; ++n) {
71  ++ap;
72  del *= x/ap;
73  sum += del;
74  if (fabs(del) < fabs(sum)*eps)
75  return sum*exp(-x + a*log(x) - lnga);
76  }
77  ERROR("Too many iterations in function IncompleteGammaPSeries()");
78  return 0;
79  }
80  }
81 
82 
91  double
92  IncompleteGammaPCF(const double a, const double x)
93  {
94  if (x < 0 || a <= 0) {
95  ERROR("Invalid arguments in function IncompleteGammaP()");
96  return 0;
97  }
98 
99  // Continued fractions by modified Lentz’s method (section 5.2)
100  const int maxIt = 100;
101  const double eps = 3e-7;
102  const double fpMin = 1e-30;
103 
104  double b = x + 1 - a;
105  double c = 1 / fpMin;
106  double d = 1 / b;
107  double h = d;
108  int i;
109  for (i = 1; i <= maxIt; ++i) {
110  double an = -i * (i-a);
111  b += 2;
112  d = an*d + b;
113  if (fabs(d) < fpMin)
114  d = fpMin;
115  c = b + an/c;
116  if (fabs(c) < fpMin)
117  c = fpMin;
118  d = 1 / d;
119  double del = d*c;
120  h *= del;
121  if (fabs(del - 1) < eps)
122  break;
123  }
124  if (i > maxIt)
125  ERROR("Too many iterations in function IncompleteGammaPCF()");
126 
127  const double lnga = LogGamma(a);
128  return h*exp(-x + a*log(x) - lnga);
129  }
130 
131 
142  double
143  BetaCF(const double a, const double b, const double x)
144  {
145  const int maxIt = 100;
146  const double eps = 3e-7;
147  const double fpMin = 1e-30;
148 
149  const double qab = a + b; // These q's will be used in factors that occur
150  const double qap = a + 1; // in the coefficients (6.4.6).
151  const double qam = a - 1;
152  double c = 1; // First step of Lentz's method.
153  double d = 1 - qab*x/qap;
154  if (fabs(d) < fpMin)
155  d = fpMin;
156  d = 1/d;
157  double h = d;
158 
159  int m;
160  for (m = 1; m <= maxIt; ++m) {
161  const int m2 = 2*m;
162  // One step (the even one) of the recurrence.
163  const double aa1 = m * (b-m) * x / ((qam+m2) * (a+m2));
164  d = 1 + aa1*d;
165  if (fabs(d) < fpMin)
166  d = fpMin;
167  c = 1 + aa1/c;
168  if (fabs(c) < fpMin)
169  c = fpMin;
170  d = 1/d;
171  h *= d*c;
172  // Next step of the recurrence (the odd one).
173  const double aa2 = -(a+m) * (qab+m) * x / ((a+m2) * (qap+m2));
174  d = 1 + aa2*d;
175  if (fabs(d) < fpMin)
176  d = fpMin;
177  c = 1 + aa2/c;
178  if (fabs(c) < fpMin)
179  c = fpMin;
180  d = 1/d;
181  const double del = d*c;
182  h *= del;
183  if (fabs(del - 1) < eps)
184  break; // Are we done?
185  }
186  if (m > maxIt)
187  ERROR("Too many iterations in BetaCF()");
188 
189  return h;
190  }
191 
192 
206  double
207  IncompleteBeta(const double a, const double b, const double x)
208  {
209  double bt;
210 
211  if (x < 0 || x > 1)
212  ERROR("Bad x in routine incompleteBeta");
213 
214  if (!x || x == 1)
215  bt = 0;
216  else // Factors in front of the continued fraction.
217  bt = exp(LogGamma(a + b) - LogGamma(a) - LogGamma(b) + a*log(x) + b*log(1-x));
218 
219  if (x < (a+1)/(a+b+2))
220  // Use continued fraction directly.
221  return bt * BetaCF(a, b, x) / a;
222  else
223  // Use continued fraction after making the symmetry transformation.
224  return 1 - bt * BetaCF(b, a, 1-x) / b;
225  }
226 
227 
228  void
230  const Vector::Triple& sigma_u2_uv_v2,
231  double& thetaError, double& phiError, double& thetaPhiCorrelation)
232  {
233  double u;
234  double v;
235  double w;
236  boost::tie(u, v, w) = u_v_w;
237  double sigmaU2;
238  double sigmaUV;
239  double sigmaV2;
240  boost::tie(sigmaU2, sigmaUV, sigmaV2) = sigma_u2_uv_v2;
241 
242  const double u2 = u*u;
243  const double uv = u*v;
244  const double v2 = v*v;
245  const double duvsigmaUV = 2*uv*sigmaUV;
246  const double u2pv2 = u2 + v2;
247 
248  thetaError = sqrt((u2*sigmaU2 + v2*sigmaV2 + duvsigmaUV) / u2pv2) / w;
249  phiError = sqrt(v2*sigmaU2 + u2*sigmaV2 - duvsigmaUV) / u2pv2;
250  thetaPhiCorrelation =
251  (-u*v*sigmaU2 + (u2-v2)*sigmaUV + u*v*sigmaV2) / (w*pow(u2pv2, 1.5)*thetaError*phiError);
252  }
253 
254 }
double IncompleteGammaPCF(const double a, const double x)
Continued Fraction for incomplete gamma function Q(a, x)
double IncompleteGammaPSeries(const double a, const double x)
logarithm of Gamma function
boost::tuple< double, double, double > Triple
Coordinate triple for easy getting or setting of coordinates.
Definition: BasicVector.h:147
constexpr double m2
Definition: AugerUnits.h:122
double pow(const double x, const unsigned int i)
double IncompleteBeta(const double a, const double b, const double x)
Incomplete Beta function.
void PropagateAxisErrors(const Vector::Triple &u_v_w, const Vector::Triple &sigma_u2_uv_v2, double &thetaError, double &phiError, double &thetaPhiCorrelation)
double LogGamma(const double x)
double BetaCF(const double a, const double b, const double x)
BetaCF.
double eps
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121

, generated on Tue Sep 26 2023.