rivet is hosted by Hepforge, IPPP Durham
Rivet  2.7.0
MathUtils.hh
1 // -*- C++ -*-
2 #ifndef RIVET_MathUtils_HH
3 #define RIVET_MathUtils_HH
4 
5 #include "Rivet/Math/MathHeader.hh"
6 #include <type_traits>
7 #include <cassert>
8 
9 namespace Rivet {
10 
11 
13 
14 
19  template <typename NUM>
20  inline typename std::enable_if<std::is_floating_point<NUM>::value, bool>::type
21  isZero(NUM val, double tolerance=1e-8) {
22  return fabs(val) < tolerance;
23  }
24 
29  template <typename NUM>
30  inline typename std::enable_if<std::is_integral<NUM>::value, bool>::type
31  isZero(NUM val, double=1e-5) { //< NB. unused tolerance parameter for ints, still needs a default value!
32  return val == 0;
33  }
34 
35 
41  template <typename N1, typename N2>
42  inline typename std::enable_if<
43  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value &&
44  (std::is_floating_point<N1>::value || std::is_floating_point<N2>::value), bool>::type
45  fuzzyEquals(N1 a, N2 b, double tolerance=1e-5) {
46  const double absavg = (std::abs(a) + std::abs(b))/2.0;
47  const double absdiff = std::abs(a - b);
48  const bool rtn = (isZero(a) && isZero(b)) || absdiff < tolerance*absavg;
49  return rtn;
50  }
51 
56  template <typename N1, typename N2>
57  inline typename std::enable_if<
58  std::is_integral<N1>::value && std::is_integral<N2>::value, bool>::type
59  fuzzyEquals(N1 a, N2 b, double) { //< NB. unused tolerance parameter for ints, still needs a default value!
60  return a == b;
61  }
62 
63 
67  template <typename N1, typename N2>
68  inline typename std::enable_if<
69  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value, bool>::type
70  fuzzyGtrEquals(N1 a, N2 b, double tolerance=1e-5) {
71  return a > b || fuzzyEquals(a, b, tolerance);
72  }
73 
74 
78  template <typename N1, typename N2>
79  inline typename std::enable_if<
80  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value, bool>::type
81  fuzzyLessEquals(N1 a, N2 b, double tolerance=1e-5) {
82  return a < b || fuzzyEquals(a, b, tolerance);
83  }
84 
86 
87 
89 
90 
95  enum RangeBoundary { OPEN=0, SOFT=0, CLOSED=1, HARD=1 };
96 
100  template <typename N1, typename N2, typename N3>
101  inline typename std::enable_if<
102  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value && std::is_arithmetic<N3>::value, bool>::type
103  inRange(N1 value, N2 low, N3 high,
104  RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
105  if (lowbound == OPEN && highbound == OPEN) {
106  return (value > low && value < high);
107  } else if (lowbound == OPEN && highbound == CLOSED) {
108  return (value > low && value <= high);
109  } else if (lowbound == CLOSED && highbound == OPEN) {
110  return (value >= low && value < high);
111  } else { // if (lowbound == CLOSED && highbound == CLOSED) {
112  return (value >= low && value <= high);
113  }
114  }
115 
120  template <typename N1, typename N2, typename N3>
121  inline typename std::enable_if<
122  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value && std::is_arithmetic<N3>::value, bool>::type
123  fuzzyInRange(N1 value, N2 low, N3 high,
124  RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
125  if (lowbound == OPEN && highbound == OPEN) {
126  return (value > low && value < high);
127  } else if (lowbound == OPEN && highbound == CLOSED) {
128  return (value > low && fuzzyLessEquals(value, high));
129  } else if (lowbound == CLOSED && highbound == OPEN) {
130  return (fuzzyGtrEquals(value, low) && value < high);
131  } else { // if (lowbound == CLOSED && highbound == CLOSED) {
132  return (fuzzyGtrEquals(value, low) && fuzzyLessEquals(value, high));
133  }
134  }
135 
137  template <typename N1, typename N2, typename N3>
138  inline typename std::enable_if<
139  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value && std::is_arithmetic<N3>::value, bool>::type
140  inRange(N1 value, pair<N2, N3> lowhigh,
141  RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
142  return inRange(value, lowhigh.first, lowhigh.second, lowbound, highbound);
143  }
144 
145 
146  // Alternative forms, with snake_case names and boundary types in names rather than as args -- from MCUtils
147 
151  template <typename N1, typename N2, typename N3>
152  inline typename std::enable_if<
153  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value && std::is_arithmetic<N3>::value, bool>::type
154  in_range(N1 val, N2 low, N3 high) {
155  return inRange(val, low, high, CLOSED, OPEN);
156  }
157 
161  template <typename N1, typename N2, typename N3>
162  inline typename std::enable_if<
163  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value && std::is_arithmetic<N3>::value, bool>::type
164  in_closed_range(N1 val, N2 low, N3 high) {
165  return inRange(val, low, high, CLOSED, CLOSED);
166  }
167 
171  template <typename N1, typename N2, typename N3>
172  inline typename std::enable_if<
173  std::is_arithmetic<N1>::value && std::is_arithmetic<N2>::value && std::is_arithmetic<N3>::value, bool>::type
174  in_open_range(N1 val, N2 low, N3 high) {
175  return inRange(val, low, high, OPEN, OPEN);
176  }
177 
179 
181 
182 
184 
185 
187  template <typename NUM>
188  inline typename std::enable_if<std::is_arithmetic<NUM>::value, NUM>::type
189  sqr(NUM a) {
190  return a*a;
191  }
192 
197  // template <typename N1, typename N2>
198  template <typename NUM>
199  inline typename std::enable_if<std::is_arithmetic<NUM>::value, NUM>::type
200  //std::common_type<N1, N2>::type
201  add_quad(NUM a, NUM b) {
202  return sqrt(a*a + b*b);
203  }
204 
209  // template <typename N1, typename N2>
210  template <typename NUM>
211  inline typename std::enable_if<std::is_arithmetic<NUM>::value, NUM>::type
212  //std::common_type<N1, N2, N3>::type
213  add_quad(NUM a, NUM b, NUM c) {
214  return sqrt(a*a + b*b + c*c);
215  }
216 
219  inline double safediv(double num, double den, double fail=0.0) {
220  return (!isZero(den)) ? num/den : fail;
221  }
222 
224  template <typename NUM>
225  inline typename std::enable_if<std::is_arithmetic<NUM>::value, NUM>::type
226  intpow(NUM val, unsigned int exp) {
227  assert(exp >= 0);
228  if (exp == 0) return (NUM) 1;
229  else if (exp == 1) return val;
230  return val * intpow(val, exp-1);
231  }
232 
234  template <typename NUM>
235  inline typename std::enable_if<std::is_arithmetic<NUM>::value, int>::type
236  sign(NUM val) {
237  if (isZero(val)) return ZERO;
238  const int valsign = (val > 0) ? PLUS : MINUS;
239  return valsign;
240  }
241 
243 
244 
246 
247 
249  inline double cdfBW(double x, double mu, double gamma) {
250  // normalize to (0;1) distribution
251  const double xn = (x - mu)/gamma;
252  return std::atan(xn)/M_PI + 0.5;
253  }
254 
256  inline double invcdfBW(double p, double mu, double gamma) {
257  const double xn = std::tan(M_PI*(p-0.5));
258  return gamma*xn + mu;
259  }
260 
262 
263 
265 
266 
271  inline vector<double> linspace(size_t nbins, double start, double end, bool include_end=true) {
272  assert(end >= start);
273  assert(nbins > 0);
274  vector<double> rtn;
275  const double interval = (end-start)/static_cast<double>(nbins);
276  for (size_t i = 0; i < nbins; ++i) {
277  rtn.push_back(start + i*interval);
278  }
279  assert(rtn.size() == nbins);
280  if (include_end) rtn.push_back(end); //< exact end, not result of n * interval
281  return rtn;
282  }
283 
284 
290  inline vector<double> logspace(size_t nbins, double start, double end, bool include_end=true) {
291  assert(end >= start);
292  assert(start > 0);
293  assert(nbins > 0);
294  const double logstart = std::log(start);
295  const double logend = std::log(end);
296  const vector<double> logvals = linspace(nbins, logstart, logend, false);
297  assert(logvals.size() == nbins);
298  vector<double> rtn; rtn.reserve(nbins+1);
299  rtn.push_back(start); //< exact start, not exp(log(start))
300  for (size_t i = 1; i < logvals.size(); ++i) {
301  rtn.push_back(std::exp(logvals[i]));
302  }
303  assert(rtn.size() == nbins);
304  if (include_end) rtn.push_back(end); //< exact end, not exp(n * loginterval)
305  return rtn;
306  }
307 
308 
310 
311 
319  inline vector<double> bwspace(size_t nbins, double start, double end, double mu, double gamma) {
320  assert(end >= start);
321  assert(nbins > 0);
322  const double pmin = cdfBW(start, mu, gamma);
323  const double pmax = cdfBW(end, mu, gamma);
324  const vector<double> edges = linspace(nbins, pmin, pmax);
325  assert(edges.size() == nbins+1);
326  vector<double> rtn;
327  for (double edge : edges) {
328  rtn.push_back(invcdfBW(edge, mu, gamma));
329  }
330  assert(rtn.size() == nbins+1);
331  return rtn;
332  }
333 
334 
336  template <typename NUM, typename CONTAINER>
337  inline typename std::enable_if<std::is_arithmetic<NUM>::value && std::is_arithmetic<typename CONTAINER::value_type>::value, int>::type
338  _binIndex(NUM val, const CONTAINER& binedges, bool allow_overflow=false) {
339  if (val < *begin(binedges)) return -1;
340  // CONTAINER::iterator_type itend =
341  if (val >= *(end(binedges)-1)) return allow_overflow ? int(binedges.size())-1 : -1;
342  auto it = std::upper_bound(begin(binedges), end(binedges), val);
343  return std::distance(begin(binedges), --it);
344  }
345 
354  template <typename NUM1, typename NUM2>
355  inline typename std::enable_if<std::is_arithmetic<NUM1>::value && std::is_arithmetic<NUM2>::value, int>::type
356  binIndex(NUM1 val, std::initializer_list<NUM2> binedges, bool allow_overflow=false) {
357  return _binIndex(val, binedges, allow_overflow);
358  }
359 
368  template <typename NUM, typename CONTAINER>
369  inline typename std::enable_if<std::is_arithmetic<NUM>::value && std::is_arithmetic<typename CONTAINER::value_type>::value, int>::type
370  binIndex(NUM val, const CONTAINER& binedges, bool allow_overflow=false) {
371  return _binIndex(val, binedges, allow_overflow);
372  }
373 
375 
376 
378 
379 
382  template <typename NUM>
383  inline typename std::enable_if<std::is_arithmetic<NUM>::value, NUM>::type
384  median(const vector<NUM>& sample) {
385  if (sample.empty()) throw RangeError("Can't compute median of an empty set");
386  vector<NUM> tmp = sample;
387  std::sort(tmp.begin(), tmp.end());
388  const size_t imid = tmp.size()/2; // len1->idx0, len2->idx1, len3->idx1, len4->idx2, ...
389  if (sample.size() % 2 == 0) return (tmp.at(imid-1) + tmp.at(imid)) / 2.0;
390  else return tmp.at(imid);
391  }
392 
393 
396  template <typename NUM>
397  inline typename std::enable_if<std::is_arithmetic<NUM>::value, double>::type
398  mean(const vector<NUM>& sample) {
399  if (sample.empty()) throw RangeError("Can't compute mean of an empty set");
400  double mean = 0.0;
401  for (size_t i = 0; i < sample.size(); ++i) {
402  mean += sample[i];
403  }
404  return mean/sample.size();
405  }
406 
407  // Calculate the error on the mean, assuming Poissonian errors
409  template <typename NUM>
410  inline typename std::enable_if<std::is_arithmetic<NUM>::value, double>::type
411  mean_err(const vector<NUM>& sample) {
412  if (sample.empty()) throw RangeError("Can't compute mean_err of an empty set");
413  double mean_e = 0.0;
414  for (size_t i = 0; i < sample.size(); ++i) {
415  mean_e += sqrt(sample[i]);
416  }
417  return mean_e/sample.size();
418  }
419 
420 
423  template <typename NUM>
424  inline typename std::enable_if<std::is_arithmetic<NUM>::value, double>::type
425  covariance(const vector<NUM>& sample1, const vector<NUM>& sample2) {
426  if (sample1.empty() || sample2.empty()) throw RangeError("Can't compute covariance of an empty set");
427  if (sample1.size() != sample2.size()) throw RangeError("Sizes of samples must be equal for covariance calculation");
428  const double mean1 = mean(sample1);
429  const double mean2 = mean(sample2);
430  const size_t N = sample1.size();
431  double cov = 0.0;
432  for (size_t i = 0; i < N; i++) {
433  const double cov_i = (sample1[i] - mean1)*(sample2[i] - mean2);
434  cov += cov_i;
435  }
436  if (N > 1) return cov/(N-1);
437  else return 0.0;
438  }
439 
442  template <typename NUM>
443  inline typename std::enable_if<std::is_arithmetic<NUM>::value, double>::type
444  covariance_err(const vector<NUM>& sample1, const vector<NUM>& sample2) {
445  if (sample1.empty() || sample2.empty()) throw RangeError("Can't compute covariance_err of an empty set");
446  if (sample1.size() != sample2.size()) throw RangeError("Sizes of samples must be equal for covariance_err calculation");
447  const double mean1 = mean(sample1);
448  const double mean2 = mean(sample2);
449  const double mean1_e = mean_err(sample1);
450  const double mean2_e = mean_err(sample2);
451  const size_t N = sample1.size();
452  double cov_e = 0.0;
453  for (size_t i = 0; i < N; i++) {
454  const double cov_i = (sqrt(sample1[i]) - mean1_e)*(sample2[i] - mean2) +
455  (sample1[i] - mean1)*(sqrt(sample2[i]) - mean2_e);
456  cov_e += cov_i;
457  }
458  if (N > 1) return cov_e/(N-1);
459  else return 0.0;
460  }
461 
462 
465  template <typename NUM>
466  inline typename std::enable_if<std::is_arithmetic<NUM>::value, double>::type
467  correlation(const vector<NUM>& sample1, const vector<NUM>& sample2) {
468  const double cov = covariance(sample1, sample2);
469  const double var1 = covariance(sample1, sample1);
470  const double var2 = covariance(sample2, sample2);
471  const double correlation = cov/sqrt(var1*var2);
472  const double corr_strength = correlation*sqrt(var2/var1);
473  return corr_strength;
474  }
475 
478  template <typename NUM>
479  inline typename std::enable_if<std::is_arithmetic<NUM>::value, double>::type
480  correlation_err(const vector<NUM>& sample1, const vector<NUM>& sample2) {
481  const double cov = covariance(sample1, sample2);
482  const double var1 = covariance(sample1, sample1);
483  const double var2 = covariance(sample2, sample2);
484  const double cov_e = covariance_err(sample1, sample2);
485  const double var1_e = covariance_err(sample1, sample1);
486  const double var2_e = covariance_err(sample2, sample2);
487 
488  // Calculate the correlation
489  const double correlation = cov/sqrt(var1*var2);
490  // Calculate the error on the correlation
491  const double correlation_err = cov_e/sqrt(var1*var2) -
492  cov/(2*pow(3./2., var1*var2)) * (var1_e * var2 + var1 * var2_e);
493 
494  // Calculate the error on the correlation strength
495  const double corr_strength_err = correlation_err*sqrt(var2/var1) +
496  correlation/(2*sqrt(var2/var1)) * (var2_e/var1 - var2*var1_e/pow(2, var2));
497 
498  return corr_strength_err;
499  }
500 
502 
503 
505 
506 
511  inline double _mapAngleM2PITo2Pi(double angle) {
512  double rtn = fmod(angle, TWOPI);
513  if (isZero(rtn)) return 0;
514  assert(rtn >= -TWOPI && rtn <= TWOPI);
515  return rtn;
516  }
517 
519  inline double mapAngleMPiToPi(double angle) {
520  double rtn = _mapAngleM2PITo2Pi(angle);
521  if (isZero(rtn)) return 0;
522  if (rtn > PI) rtn -= TWOPI;
523  if (rtn <= -PI) rtn += TWOPI;
524  assert(rtn > -PI && rtn <= PI);
525  return rtn;
526  }
527 
529  inline double mapAngle0To2Pi(double angle) {
530  double rtn = _mapAngleM2PITo2Pi(angle);
531  if (isZero(rtn)) return 0;
532  if (rtn < 0) rtn += TWOPI;
533  if (rtn == TWOPI) rtn = 0;
534  assert(rtn >= 0 && rtn < TWOPI);
535  return rtn;
536  }
537 
539  inline double mapAngle0ToPi(double angle) {
540  double rtn = fabs(mapAngleMPiToPi(angle));
541  if (isZero(rtn)) return 0;
542  assert(rtn > 0 && rtn <= PI);
543  return rtn;
544  }
545 
547  inline double mapAngle(double angle, PhiMapping mapping) {
548  switch (mapping) {
549  case MINUSPI_PLUSPI:
550  return mapAngleMPiToPi(angle);
551  case ZERO_2PI:
552  return mapAngle0To2Pi(angle);
553  case ZERO_PI:
554  return mapAngle0To2Pi(angle);
555  default:
556  throw Rivet::UserError("The specified phi mapping scheme is not implemented");
557  }
558  }
559 
561 
562 
564 
565 
569  inline double deltaPhi(double phi1, double phi2, bool sign=false) {
570  const double x = mapAngleMPiToPi(phi1 - phi2);
571  return sign ? x : fabs(x);
572  }
573 
577  inline double deltaEta(double eta1, double eta2) {
578  return fabs(eta1 - eta2);
579  }
580 
584  inline double deltaRap(double y1, double y2) {
585  return fabs(y1 - y2);
586  }
587 
590  inline double deltaR2(double rap1, double phi1, double rap2, double phi2) {
591  const double dphi = deltaPhi(phi1, phi2);
592  return sqr(rap1-rap2) + sqr(dphi);
593  }
594 
597  inline double deltaR(double rap1, double phi1, double rap2, double phi2) {
598  return sqrt(deltaR2(rap1, phi1, rap2, phi2));
599  }
600 
602  inline double rapidity(double E, double pz) {
603  if (isZero(E - pz)) {
604  throw std::runtime_error("Divergent positive rapidity");
605  return MAXDOUBLE;
606  }
607  if (isZero(E + pz)) {
608  throw std::runtime_error("Divergent negative rapidity");
609  return -MAXDOUBLE;
610  }
611  return 0.5*log((E+pz)/(E-pz));
612  }
613 
615 
616 
619  inline double mT(double pT1, double pT2, double dphi) {
620  return sqrt(2*pT1*pT2 * (1 - cos(dphi)) );
621  }
622 
623 
624 }
625 
626 
627 #endif
Definition: ALICE_2010_I880049.cc:13
std::enable_if< std::is_arithmetic< NUM1 >::value &&std::is_arithmetic< NUM2 >::value, int >::type binIndex(NUM1 val, std::initializer_list< NUM2 > binedges, bool allow_overflow=false)
Return the bin index of the given value, val, given a vector of bin edges.
Definition: MathUtils.hh:356
double rapidity(double E, double pz)
Calculate a rapidity value from the supplied energy E and longitudinal momentum pz.
Definition: MathUtils.hh:602
double mapAngleMPiToPi(double angle)
Map an angle into the range (-PI, PI].
Definition: MathUtils.hh:519
double safediv(double num, double den, double fail=0.0)
Definition: MathUtils.hh:219
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&std::is_arithmetic< N3 >::value, bool >::type in_range(N1 val, N2 low, N3 high)
Boolean function to determine if value is within the given range.
Definition: MathUtils.hh:154
static const double PI
A pre-defined value of .
Definition: MathHeader.hh:16
double deltaRap(double y1, double y2)
Definition: MathUtils.hh:584
Error specialisation for where the problem is between the chair and the computer. ...
Definition: Exceptions.hh:55
double mapAngle(double angle, PhiMapping mapping)
Map an angle into the enum-specified range.
Definition: MathUtils.hh:547
std::enable_if< std::is_arithmetic< NUM >::value, NUM >::type add_quad(NUM a, NUM b)
Named number-type addition in quadrature operation.
Definition: MathUtils.hh:201
vector< double > linspace(size_t nbins, double start, double end, bool include_end=true)
Make a list of nbins + 1 values equally spaced between start and end inclusive.
Definition: MathUtils.hh:271
double cdfBW(double x, double mu, double gamma)
CDF for the Breit-Wigner distribution.
Definition: MathUtils.hh:249
vector< double > logspace(size_t nbins, double start, double end, bool include_end=true)
Make a list of nbins + 1 values exponentially spaced between start and end inclusive.
Definition: MathUtils.hh:290
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&std::is_arithmetic< N3 >::value, bool >::type in_open_range(N1 val, N2 low, N3 high)
Boolean function to determine if value is within the given range.
Definition: MathUtils.hh:174
PhiMapping
Enum for range of to be mapped into.
Definition: MathHeader.hh:31
std::enable_if< std::is_arithmetic< NUM >::value, double >::type covariance(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition: MathUtils.hh:425
double deltaPhi(double phi1, double phi2, bool sign=false)
Calculate the difference between two angles in radians.
Definition: MathUtils.hh:569
std::enable_if< std::is_arithmetic< NUM >::value, double >::type mean_err(const vector< NUM > &sample)
Definition: MathUtils.hh:411
double angle(const Vector3 &a, const Vector3 &b)
Angle (in radians) between two 3-vectors.
Definition: Vector3.hh:286
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&std::is_arithmetic< N3 >::value, bool >::type inRange(N1 value, N2 low, N3 high, RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN)
Determine if value is in the range low to high, for floating point numbers.
Definition: MathUtils.hh:103
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&std::is_arithmetic< N3 >::value, bool >::type in_closed_range(N1 val, N2 low, N3 high)
Boolean function to determine if value is within the given range.
Definition: MathUtils.hh:164
double mT(double pT1, double pT2, double dphi)
Definition: MathUtils.hh:619
double invcdfBW(double p, double mu, double gamma)
Inverse CDF for the Breit-Wigner distribution.
Definition: MathUtils.hh:256
static const double MAXDOUBLE
Definition: MathHeader.hh:12
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&(std::is_floating_point< N1 >::value||std::is_floating_point< N2 >::value), bool >::type fuzzyEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two numbers for equality with a degree of fuzziness.
Definition: MathUtils.hh:45
static const double TWOPI
A pre-defined value of .
Definition: MathHeader.hh:19
double deltaEta(double eta1, double eta2)
Definition: MathUtils.hh:577
double deltaR2(double rap1, double phi1, double rap2, double phi2)
Definition: MathUtils.hh:590
double deltaR(double rap1, double phi1, double rap2, double phi2)
Definition: MathUtils.hh:597
RangeBoundary
Definition: MathUtils.hh:95
double mapAngle0To2Pi(double angle)
Map an angle into the range [0, 2PI).
Definition: MathUtils.hh:529
double mapAngle0ToPi(double angle)
Map an angle into the range [0, PI].
Definition: MathUtils.hh:539
std::enable_if< std::is_arithmetic< NUM >::value, double >::type covariance_err(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition: MathUtils.hh:444
std::enable_if< std::is_floating_point< NUM >::value, bool >::type isZero(NUM val, double tolerance=1e-8)
Compare a number to zero.
Definition: MathUtils.hh:21
std::enable_if< std::is_arithmetic< NUM >::value, double >::type correlation_err(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition: MathUtils.hh:480
std::enable_if< std::is_arithmetic< NUM >::value, NUM >::type median(const vector< NUM > &sample)
Definition: MathUtils.hh:384
std::enable_if< std::is_arithmetic< NUM >::value, double >::type mean(const vector< NUM > &sample)
Definition: MathUtils.hh:398
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value, bool >::type fuzzyGtrEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two numbers for >= with a degree of fuzziness.
Definition: MathUtils.hh:70
std::enable_if< std::is_arithmetic< NUM >::value, NUM >::type sqr(NUM a)
Named number-type squaring operation.
Definition: MathUtils.hh:189
std::enable_if< std::is_arithmetic< NUM >::value, NUM >::type intpow(NUM val, unsigned int exp)
A more efficient version of pow for raising numbers to integer powers.
Definition: MathUtils.hh:226
Error for e.g. use of invalid bin ranges.
Definition: Exceptions.hh:22
vector< double > bwspace(size_t nbins, double start, double end, double mu, double gamma)
Make a list of nbins + 1 values spaced for equal area Breit-Wigner binning between start and end incl...
Definition: MathUtils.hh:319
std::enable_if< std::is_arithmetic< NUM >::value, int >::type sign(NUM val)
Find the sign of a number.
Definition: MathUtils.hh:236
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value &&std::is_arithmetic< N3 >::value, bool >::type fuzzyInRange(N1 value, N2 low, N3 high, RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN)
Determine if value is in the range low to high, for floating point numbers.
Definition: MathUtils.hh:123
std::enable_if< std::is_arithmetic< N1 >::value &&std::is_arithmetic< N2 >::value, bool >::type fuzzyLessEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two floating point numbers for <= with a degree of fuzziness.
Definition: MathUtils.hh:81
std::enable_if< std::is_arithmetic< NUM >::value, double >::type correlation(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition: MathUtils.hh:467