Tools/CIC/utl/Math.h
Go to the documentation of this file.
1 // \author Darko Veberic
2 // \date 2014
3 
4 #ifndef _cic_utl_Math_h_
5 #define _cic_utl_Math_h_
6 
7 #include <TRandom3.h>
8 #include <TMath.h>
9 #include <cmath>
10 #include <functional>
11 #include <iostream>
12 #include <algorithm>
13 #include <numeric>
14 
15 
16 namespace utl {
17 
18  constexpr double degree = M_PI / 180;
19 
20 
21  template<typename T>
22  inline
23  constexpr
24  T
25  Sqr(const T& x)
26  {
27  return x*x;
28  }
29 
30 
31  inline
32  double
33  Sin2(const double x)
34  {
35  return Sqr(std::sin(x));
36  }
37 
38 
39  inline
40  double
41  Sin2Deg(const double x)
42  {
43  return Sin2(x*degree);
44  }
45 
46 
47  extern TRandom3* const gRandom3;
48 
49 
50  inline
51  double
52  Fermi(const double x)
53  {
54  return 1 / (1 + std::exp(-x));
55  }
56 
57 
58  inline
59  constexpr
60  double
61  StepFunction(const double x)
62  {
63  return x > 0;
64  }
65 
66 
67  inline
68  constexpr
69  double
70  LinearSigmoid(const double x, const double delta)
71  {
72  return (x < -delta) ?
73  0 :
74  ((x > delta) ?
75  1 :
76  0.5*(1 + x/delta));
77  }
78 
79 
80  inline
81  double
82  QuadraticSigmoid(const double x, const double delta)
83  {
84  // for x in interval [-2*delta, 2*delta] gives smooth transiton from 0 to 1.
85  const double d = 2*delta;
86  return
87  (x <= -d) ?
88  0 :
89  ((x >= d) ?
90  1 :
91  ((x <= 0) ?
92  0.5*Sqr(1 + x/d) :
93  1 - 0.5*Sqr(x/d - 1)
94  )
95  );
96  }
97 
98 
99  const std::function<double(double, double)> gQuad =
100  [](const double x, const double d) { return QuadraticSigmoid(x, d); };
101 
102 
103  inline
104  double
105  ErfSigmoid(const double x, const double delta)
106  {
107  return 0.5*(1 + std::erf(x/delta));
108  }
109 
110 
111  inline
112  constexpr
113  double
114  Interpolate(const double dx, const double dy,
115  const double x)
116  {
117  return dy * x / dx;
118  }
119 
120 
121  inline
122  constexpr
123  double
124  Interpolate(const double x1, const double y1,
125  const double x2, const double y2,
126  const double x)
127  {
128  return y1 + Interpolate(x2 - x1, y2 - y1, x - x1);
129  }
130 
131 
132  // Kolmogorov-Smirnov measure of uniformity
133  double UniformKolmogorovSmirnov(const std::vector<double>& cdf);
134 
135  double UniformKolmogorovSmirnov(const std::vector<std::pair<double, double>>& wcdf,
136  const double totalWeight = 0);
137 
138 
139  // Anderson-Darling measure of uniformity
140  double UniformAndersonDarling(const std::vector<std::pair<double, double>>& wcdf,
141  const double totalWeight = 0);
142 
143 
144  inline
145  double
146  UniformAndersonDarling(const std::vector<std::vector<std::pair<double, double>>>& wcdf)
147  {
148  double ad = 0;
149  for (const auto& row : wcdf)
150  ad += UniformAndersonDarling(row);
151  return ad;
152  }
153 
154 
155  // Chi^2 measure of uniformity
156  template<typename T>
157  double
158  UniformChi2Ndof(const std::vector<T>& counts, double nTot = 0)
159  {
160  if (!nTot) {
161  nTot = std::accumulate(counts.begin(), counts.end(), T(0));
162  if (!nTot)
163  return 0;
164  }
165  const unsigned int n = counts.size();
166  const double nExp = nTot / n;
167  double chi2 = 0;
168  for (const T c : counts)
169  chi2 += Sqr(nExp - c);
170  return chi2 / (nExp * (n - 1));
171  }
172 
173 
174  template<typename T>
175  double
176  UniformChi2Ndof(const std::vector<std::vector<T>>& counts)
177  {
178  double chi2 = 0;
179  double nTot = 0;
180  for (const auto& row : counts) {
181  const double rowTot = std::accumulate(row.begin(), row.end(), T(0));
182  if (!rowTot)
183  continue;
184  nTot += rowTot;
185  const unsigned int bins = row.size();
186  const double mean = rowTot / bins;
187  double rowChi2 = 0;
188  for (const T nBin : row)
189  rowChi2 += Sqr(mean - nBin);
190  chi2 += rowChi2 * bins / (bins - 1);
191  }
192  return chi2 / nTot;
193  }
194 
195 
196  inline
197  double
198  PoissonDeviance(const double mean, const double n)
199  {
200  using namespace std;
201  if (mean < 0 || n < 0)
202  return numeric_limits<double>::infinity();
203  if (mean == 0)
204  return (n == 0) ? 0 : numeric_limits<double>::infinity();
205  return mean - n * log(mean) + TMath::LnGamma(n + 1);
206  }
207 
208 
209  inline
210  double
211  PoissonProbability(const double mean, const double n)
212  {
213  using namespace std;
214  if (mean < 0 || n < 0)
215  return 0;
216  if (mean == 0)
217  return n == 0;
218  return std::exp(-PoissonDeviance(mean, n));
219  }
220 
221 
222  inline
223  double
224  NemesLnGamma(const double z)
225  {
226  return 0.5*(std::log(2*M_PI) - std::log(z)) + z * (std::log(z + 1/(12*z - 1/(10*z))) - 1);
227  }
228 
229 
230  template<typename T>
231  double
232  UniformPoissonChi2(const std::vector<T>& counts, double nTot = 0)
233  {
234  if (!nTot) {
235  nTot = std::accumulate(counts.begin(), counts.end(), T(0));
236  if (!nTot)
237  return 0;
238  }
239  const unsigned int n = counts.size();
240  const double nExp = nTot / n;
241  double chi2 = 0;
242  for (const T c : counts)
243  chi2 += (c ? c * std::log(c) : 0);
244  chi2 -= nTot * std::log(nExp);
245  return 2*chi2;
246  }
247 
248 
249  template<typename T>
250  inline
251  double
252  UniformPoissonChi2(const std::vector<std::vector<T>>& counts)
253  {
254  double chi2 = 0;
255  for (const auto& row : counts)
256  chi2 += UniformPoissonChi2(row);
257  return chi2;
258  }
259 
260 }
261 
262 
263 #endif
constexpr double Interpolate(const double dx, const double dy, const double x)
constexpr T Sqr(const T &x)
double UniformKolmogorovSmirnov(const vector< pair< double, double >> &wcdf, double wtot)
double Sin2Deg(const double x)
double Fermi(const double x)
constexpr double LinearSigmoid(const double x, const double delta)
double PoissonProbability(const double mean, const double n)
constexpr double degree
double ErfSigmoid(const double x, const double delta)
double PoissonDeviance(const double mean, const double n)
double UniformPoissonChi2(const std::vector< T > &counts, double nTot=0)
double UniformAndersonDarling(const vector< pair< double, double >> &wcdf, double wtot)
double QuadraticSigmoid(const double x, const double delta)
double Sin2(const double x)
TRandom3 *const gRandom3
const std::function< double(double, double)> gQuad
constexpr double StepFunction(const double x)
double NemesLnGamma(const double z)
double UniformChi2Ndof(const std::vector< T > &counts, double nTot=0)

, generated on Tue Sep 26 2023.