Rivet API documentation

Rivet 4.1.3
MathUtils.hh
1// -*- C++ -*-
2#ifndef RIVET_MathUtils_HH
3#define RIVET_MathUtils_HH
4
5#include "Rivet/Math/MathConstants.hh"
6#include <type_traits>
7#include <cassert>
8
9namespace Rivet {
10
11
13
14
17
22 template <typename NUM>
23 inline typename std::enable_if_t<std::is_floating_point_v<NUM>, bool>
24 isZero(NUM val, double tolerance=1e-8) {
25 return fabs(val) < tolerance;
26 }
27
32 template <typename NUM>
33 inline typename std::enable_if_t<std::is_integral_v<NUM>, bool>
34 isZero(NUM val, double=1e-5) { //< NB. unused tolerance parameter for ints, still needs a default value!
35 return val == 0;
36 }
37
39 template <typename NUM>
40 inline typename std::enable_if_t<std::is_floating_point_v<NUM>, bool>
41 isNaN(NUM val) { return std::isnan(val); }
42
44 template <typename NUM>
45 inline typename std::enable_if_t<std::is_floating_point_v<NUM>, bool>
46 notNaN(NUM val) { return !std::isnan(val); }
47
49 template <typename NUM>
50 inline typename std::enable_if<std::is_floating_point<NUM>::value, NUM>::type
51 sqrt_signed(NUM val) { return std::copysign(sqrt(std::abs(val)), val); }
52
58 template <typename N1, typename N2>
59 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> &&
60 (std::is_floating_point_v<N1> || std::is_floating_point_v<N2>), bool>
61 fuzzyEquals(N1 a, N2 b, double tolerance=1e-5) {
62 const double absavg = (std::abs(a) + std::abs(b))/2.0;
63 const double absdiff = std::abs(a - b);
64 const bool rtn = (isZero(a) && isZero(b)) || absdiff < tolerance*absavg;
65 return rtn;
66 }
67
72 template <typename N1, typename N2>
73 inline typename std::enable_if_t<std::is_integral_v<N1> && std::is_integral_v<N2>, bool>
74 fuzzyEquals(N1 a, N2 b, double) { //< NB. unused tolerance parameter for ints, still needs a default value!
75 return a == b;
76 }
77
78
82 template <typename N1, typename N2>
83 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>, bool>
84 fuzzyGtrEquals(N1 a, N2 b, double tolerance=1e-5) {
85 return a > b || fuzzyEquals(a, b, tolerance);
86 }
87
88
92 template <typename N1, typename N2>
93 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>, bool>
94 fuzzyLessEquals(N1 a, N2 b, double tolerance=1e-5) {
95 return a < b || fuzzyEquals(a, b, tolerance);
96 }
97
101 template <typename N1, typename N2>
102 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>,
103 signed_if_mixed_t<N1,N2> >
104 min(N1 a, N2 b) {
105 using rtnT = signed_if_mixed_t<N1,N2>;
106 return ((rtnT)a > (rtnT)b)? b : a;
107 }
108
112 template <typename N1, typename N2>
113 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>,
114 signed_if_mixed_t<N1,N2> >
115 max(N1 a, N2 b) {
116 using rtnT = signed_if_mixed_t<N1,N2>;
117 return ((rtnT)a > (rtnT)b)? a : b;
118 }
119
121
122
125
130 enum RangeBoundary { OPEN=0, SOFT=0, CLOSED=1, HARD=1 };
131
135 template <typename N1, typename N2, typename N3>
136 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
137 inRange(N1 value, N2 low, N3 high,
138 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
139 if (lowbound == OPEN && highbound == OPEN) {
140 return (value > low && value < high);
141 } else if (lowbound == OPEN && highbound == CLOSED) {
142 return (value > low && value <= high);
143 } else if (lowbound == CLOSED && highbound == OPEN) {
144 return (value >= low && value < high);
145 } else { // if (lowbound == CLOSED && highbound == CLOSED) {
146 return (value >= low && value <= high);
147 }
148 }
149
154 template <typename N1, typename N2, typename N3>
155 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
156 fuzzyInRange(N1 value, N2 low, N3 high,
157 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
158 if (lowbound == OPEN && highbound == OPEN) {
159 return (value > low && value < high);
160 } else if (lowbound == OPEN && highbound == CLOSED) {
161 return (value > low && fuzzyLessEquals(value, high));
162 } else if (lowbound == CLOSED && highbound == OPEN) {
163 return (fuzzyGtrEquals(value, low) && value < high);
164 } else { // if (lowbound == CLOSED && highbound == CLOSED) {
165 return (fuzzyGtrEquals(value, low) && fuzzyLessEquals(value, high));
166 }
167 }
168
170 template <typename N1, typename N2, typename N3>
171 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
172 inRange(N1 value, pair<N2, N3> lowhigh,
173 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
174 return inRange(value, lowhigh.first, lowhigh.second, lowbound, highbound);
175 }
176
177
178 // Alternative forms, with snake_case names and boundary types in names rather than as args -- from MCUtils
179
183 template <typename N1, typename N2, typename N3>
184 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
185 in_range(N1 val, N2 low, N3 high) {
186 return inRange(val, low, high, CLOSED, OPEN);
187 }
188
192 template <typename N1, typename N2, typename N3>
193 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
194 in_closed_range(N1 val, N2 low, N3 high) {
195 return inRange(val, low, high, CLOSED, CLOSED);
196 }
197
201 template <typename N1, typename N2, typename N3>
202 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
203 in_open_range(N1 val, N2 low, N3 high) {
204 return inRange(val, low, high, OPEN, OPEN);
205 }
206
208
210
211
214
216 template <typename NUM>
217 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
218 sqr(NUM a) {
219 return a*a;
220 }
221
223 inline double subtract(double a, double b, double tolerance = 1e-5) {
224 if (fuzzyEquals(a,b,tolerance)) return 0.;
225 return a - b;
226 }
227
229 inline double add(double a, double b, double tolerance = 1e-5) {
230 return subtract(a,-b,tolerance);
231 }
232
237 // template <typename N1, typename N2>
238 template <typename NUM>
239 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
240 //std::common_type<N1, N2>::type
241 add_quad(NUM a, NUM b) {
242 return sqrt(a*a + b*b);
243 }
244
249 // template <typename N1, typename N2>
250 template <typename NUM>
251 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
252 //std::common_type<N1, N2, N3>::type
253 add_quad(NUM a, NUM b, NUM c) {
254 return sqrt(a*a + b*b + c*c);
255 }
256
259 inline double safediv(double num, double den, double fail=0.0) {
260 return (!isZero(den)) ? num/den : fail;
261 }
262
264 template <typename NUM>
265 constexpr inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
266 intpow(NUM val, unsigned int exp) {
267 if (exp == 0) return (NUM) 1;
268 else if (exp == 1) return val;
269 return val * intpow(val, exp-1);
270 }
271
273 template <typename NUM>
274 constexpr inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, int>
275 sign(NUM val) {
276 if (isZero(val)) return ZERO;
277 const int valsign = (val > 0) ? PLUS : MINUS;
278 return valsign;
279 }
280
282
283
286
288 inline double cdfBW(double x, double mu, double gamma) {
289 // normalize to (0;1) distribution
290 const double xn = (x - mu)/gamma;
291 return std::atan(xn)/M_PI + 0.5;
292 }
293
295 inline double invcdfBW(double p, double mu, double gamma) {
296 const double xn = std::tan(M_PI*(p-0.5));
297 return gamma*xn + mu;
298 }
299
301
302
305
312 inline vector<double> linspace(size_t nbins, double start, double end, bool include_end=true) {
313 assert(nbins > 0);
314 vector<double> rtn;
315 const double interval = (end-start)/static_cast<double>(nbins);
316 for (size_t i = 0; i < nbins; ++i) {
317 rtn.push_back(start + i*interval);
318 }
319 assert(rtn.size() == nbins);
320 if (include_end) rtn.push_back(end); //< exact end, not result of n * interval
321 return rtn;
322 }
323
324
336 inline vector<double> aspace(double step, double start, double end, bool include_end=true, double tol=1e-2) {
337 assert( (end-start)*step > 0); //< ensure the step is going in the direction from start to end
338 vector<double> rtn;
339 double next = start;
340 while (true) {
341 if (next > end) break;
342 rtn.push_back(next);
343 next += step;
344 }
345 if (include_end) {
346 if (end - rtn[rtn.size()-1] > tol*step) rtn.push_back(end);
347 }
348 return rtn;
349 }
350
351
355 inline vector<double> fnspace(size_t nbins, double start, double end,
356 const std::function<double(double)>& fn, const std::function<double(double)>& invfn,
357 bool include_end=true) {
358 // assert(end >= start);
359 assert(nbins > 0);
360 const double pmin = fn(start);
361 const double pmax = fn(end);
362 const vector<double> edges = linspace(nbins, pmin, pmax, false);
363 assert(edges.size() == nbins);
364 vector<double> rtn; rtn.reserve(nbins+1);
365 rtn.push_back(start); //< exact start, not round-tripped
366 for (size_t i = 1; i < edges.size(); ++i) {
367 rtn.push_back(invfn(edges[i]));
368 }
369 assert(rtn.size() == nbins);
370 if (include_end) rtn.push_back(end); //< exact end
371 return rtn;
372 }
373
374
384 inline vector<double> logspace(size_t nbins, double start, double end, bool include_end=true) {
385 return fnspace(nbins, start, end,
386 [](double x){ return std::log(x); },
387 [](double x){ return std::exp(x); },
388 include_end);
389 }
390
391
401 inline vector<double> powspace(size_t nbins, double start, double end, double npow, bool include_end=true) {
402 assert(start >= 0); //< non-integer powers are complex for negative numbers... don't go there
403 return fnspace(nbins, start, end,
404 [&](double x){ return std::pow(x, npow); },
405 [&](double x){ return std::pow(x, 1/npow); },
406 include_end);
407 }
408
420 inline vector<double> powdbnspace(size_t nbins, double start, double end, double npow, bool include_end=true) {
421 assert(start >= 0); //< non-integer powers are complex for negative numbers... don't go there
422 return fnspace(nbins, start, end,
423 [&](double x){ return std::pow(x, npow+1) / (npow+1); },
424 [&](double x){ return std::pow((npow+1) * x, 1/(npow+1)); },
425 include_end);
426 }
427
428
436 inline vector<double> bwdbnspace(size_t nbins, double start, double end, double mu, double gamma, bool include_end=true) {
437 return fnspace(nbins, start, end,
438 [&](double x){ return cdfBW(x, mu, gamma); },
439 [&](double x){ return invcdfBW(x, mu, gamma); },
440 include_end);
441 }
442
443
445 template <typename NUM, typename CONTAINER>
446 inline typename std::enable_if_t<std::is_arithmetic_v<NUM> && std::is_arithmetic_v<typename CONTAINER::value_type>, int>
447 _binIndex(NUM val, const CONTAINER& binedges, bool allow_overflow=false) {
448 if (val < *begin(binedges)) return -1;
449 // CONTAINER::iterator_type itend =
450 if (val >= *(end(binedges)-1)) return allow_overflow ? int(binedges.size())-1 : -1;
451 auto it = std::upper_bound(begin(binedges), end(binedges), val);
452 return std::distance(begin(binedges), --it);
453 }
454
463 template <typename NUM1, typename NUM2>
464 inline typename std::enable_if_t<std::is_arithmetic_v<NUM1> && std::is_arithmetic_v<NUM2>, int>
465 binIndex(NUM1 val, std::initializer_list<NUM2> binedges, bool allow_overflow=false) {
466 return _binIndex(val, binedges, allow_overflow);
467 }
468
477 template <typename NUM, typename CONTAINER>
478 inline typename std::enable_if_t<std::is_arithmetic_v<NUM> && std::is_arithmetic_v<typename CONTAINER::value_type>, int>
479 binIndex(NUM val, const CONTAINER& binedges, bool allow_overflow=false) {
480 return _binIndex(val, binedges, allow_overflow);
481 }
482
484
485
488
491 template <typename NUM>
492 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
493 median(const vector<NUM>& sample) {
494 if (sample.empty()) throw RangeError("Can't compute median of an empty set");
495 vector<NUM> tmp = sample;
496 std::sort(tmp.begin(), tmp.end());
497 const size_t imid = tmp.size()/2; // len1->idx0, len2->idx1, len3->idx1, len4->idx2, ...
498 if (sample.size() % 2 == 0) return (tmp.at(imid-1) + tmp.at(imid)) / 2.0;
499 else return tmp.at(imid);
500 }
501
502
505 template <typename NUM>
506 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
507 mean(const vector<NUM>& sample) {
508 if (sample.empty()) throw RangeError("Can't compute mean of an empty set");
509 double mean = 0.0;
510 for (size_t i = 0; i < sample.size(); ++i) {
511 mean += sample[i];
512 }
513 return mean/sample.size();
514 }
515
516 // Calculate the error on the mean, assuming Poissonian errors
518 template <typename NUM>
519 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
520 mean_err(const vector<NUM>& sample) {
521 if (sample.empty()) throw RangeError("Can't compute mean_err of an empty set");
522 double mean_e = 0.0;
523 for (size_t i = 0; i < sample.size(); ++i) {
524 mean_e += sqrt(sample[i]);
525 }
526 return mean_e/sample.size();
527 }
528
529
532 template <typename NUM>
533 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
534 covariance(const vector<NUM>& sample1, const vector<NUM>& sample2) {
535 if (sample1.empty() || sample2.empty()) throw RangeError("Can't compute covariance of an empty set");
536 if (sample1.size() != sample2.size()) throw RangeError("Sizes of samples must be equal for covariance calculation");
537 const double mean1 = mean(sample1);
538 const double mean2 = mean(sample2);
539 const size_t N = sample1.size();
540 double cov = 0.0;
541 for (size_t i = 0; i < N; i++) {
542 const double cov_i = (sample1[i] - mean1)*(sample2[i] - mean2);
543 cov += cov_i;
544 }
545 if (N > 1) return cov/(N-1);
546 else return 0.0;
547 }
548
551 template <typename NUM>
552 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
553 covariance_err(const vector<NUM>& sample1, const vector<NUM>& sample2) {
554 if (sample1.empty() || sample2.empty()) throw RangeError("Can't compute covariance_err of an empty set");
555 if (sample1.size() != sample2.size()) throw RangeError("Sizes of samples must be equal for covariance_err calculation");
556 const double mean1 = mean(sample1);
557 const double mean2 = mean(sample2);
558 const double mean1_e = mean_err(sample1);
559 const double mean2_e = mean_err(sample2);
560 const size_t N = sample1.size();
561 double cov_e = 0.0;
562 for (size_t i = 0; i < N; i++) {
563 const double cov_i = (sqrt(sample1[i]) - mean1_e)*(sample2[i] - mean2) +
564 (sample1[i] - mean1)*(sqrt(sample2[i]) - mean2_e);
565 cov_e += cov_i;
566 }
567 if (N > 1) return cov_e/(N-1);
568 else return 0.0;
569 }
570
571
574 template <typename NUM>
575 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
576 correlation(const vector<NUM>& sample1, const vector<NUM>& sample2) {
577 const double cov = covariance(sample1, sample2);
578 const double var1 = covariance(sample1, sample1);
579 const double var2 = covariance(sample2, sample2);
580 const double correlation = cov/sqrt(var1*var2);
581 const double corr_strength = correlation*sqrt(var2/var1);
582 return corr_strength;
583 }
584
587 template <typename NUM>
588 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
589 correlation_err(const vector<NUM>& sample1, const vector<NUM>& sample2) {
590 const double cov = covariance(sample1, sample2);
591 const double var1 = covariance(sample1, sample1);
592 const double var2 = covariance(sample2, sample2);
593 const double cov_e = covariance_err(sample1, sample2);
594 const double var1_e = covariance_err(sample1, sample1);
595 const double var2_e = covariance_err(sample2, sample2);
596
597 // Calculate the correlation
598 const double correlation = cov/sqrt(var1*var2);
599 // Calculate the error on the correlation
600 const double correlation_err = cov_e/sqrt(var1*var2) -
601 cov/(2*pow(3./2., var1*var2)) * (var1_e * var2 + var1 * var2_e);
602
603 // Calculate the error on the correlation strength
604 const double corr_strength_err = correlation_err*sqrt(var2/var1) +
605 correlation/(2*sqrt(var2/var1)) * (var2_e/var1 - var2*var1_e/pow(2, var2));
606
607 return corr_strength_err;
608 }
609
611
612
615
620 inline double _mapAngleM2PITo2Pi(double angle) {
621 double rtn = fmod(angle, TWOPI);
622 if (isZero(rtn)) return 0;
623 assert(rtn >= -TWOPI && rtn <= TWOPI);
624 return rtn;
625 }
626
628 inline double mapAngleMPiToPi(double angle) {
629 double rtn = _mapAngleM2PITo2Pi(angle);
630 if (isZero(rtn)) return 0;
631 if (rtn > PI) rtn -= TWOPI;
632 if (rtn <= -PI) rtn += TWOPI;
633 assert(rtn > -PI && rtn <= PI);
634 return rtn;
635 }
636
638 inline double mapAngle0To2Pi(double angle) {
639 double rtn = _mapAngleM2PITo2Pi(angle);
640 if (isZero(rtn)) return 0;
641 if (rtn < 0) rtn += TWOPI;
642 if (rtn == TWOPI) rtn = 0;
643 assert(rtn >= 0 && rtn < TWOPI);
644 return rtn;
645 }
646
648 inline double mapAngle0ToPi(double angle) {
649 double rtn = fabs(mapAngleMPiToPi(angle));
650 if (isZero(rtn)) return 0;
651 assert(rtn > 0 && rtn <= PI);
652 return rtn;
653 }
654
656 inline double mapAngle(double angle, PhiMapping mapping) {
657 switch (mapping) {
658 case MINUSPI_PLUSPI:
659 return mapAngleMPiToPi(angle);
660 case ZERO_2PI:
661 return mapAngle0To2Pi(angle);
662 case ZERO_PI:
663 return mapAngle0ToPi(angle);
664 default:
665 throw Rivet::UserError("The specified phi mapping scheme is not implemented");
666 }
667 }
668
670
671
674
678 inline double deltaPhi(double phi1, double phi2, bool sign=false) {
679 const double x = mapAngleMPiToPi(phi1 - phi2);
680 return sign ? x : fabs(x);
681 }
682
686 inline double deltaEta(double eta1, double eta2, bool sign=false) {
687 const double x = eta1 - eta2;
688 return sign ? x : fabs(x);
689 }
690
694 inline double deltaRap(double y1, double y2, bool sign=false) {
695 const double x = y1 - y2;
696 return sign? x : fabs(x);
697 }
698
701 inline double deltaR2(double rap1, double phi1, double rap2, double phi2) {
702 const double dphi = deltaPhi(phi1, phi2);
703 return sqr(rap1-rap2) + sqr(dphi);
704 }
705
708 inline double deltaR(double rap1, double phi1, double rap2, double phi2) {
709 return sqrt(deltaR2(rap1, phi1, rap2, phi2));
710 }
711
713 inline double rapidity(double E, double pz) {
714 if (isZero(E - pz)) {
715 throw std::runtime_error("Divergent positive rapidity");
716 return DBL_MAX;
717 }
718 if (isZero(E + pz)) {
719 throw std::runtime_error("Divergent negative rapidity");
720 return -DBL_MAX;
721 }
722 return 0.5*log((E+pz)/(E-pz));
723 }
724
726
727
731 inline double mT(double pT1, double pT2, double dphi) {
732 return sqrt(2*pT1*pT2 * (1 - cos(dphi)) );
733 }
734
735
736}
737
738
739#endif
double E(const ParticleBase &p)
Unbound function access to E.
Definition ParticleBaseUtils.hh:659
double p(const ParticleBase &p)
Unbound function access to p.
Definition ParticleBaseUtils.hh:653
Definition MC_CENT_PPB_Projections.hh:10
constexpr std::enable_if_t< std::is_arithmetic_v< NUM >, int > sign(NUM val)
Find the sign of a number.
Definition MathUtils.hh:275
double deltaR(double rap1, double phi1, double rap2, double phi2)
Definition MathUtils.hh:708
std::enable_if< std::is_floating_point< NUM >::value, NUM >::type sqrt_signed(NUM val)
Square root of the absolute value with the sign of the argument propagated.
Definition MathUtils.hh:51
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, bool > fuzzyGtrEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two numbers for >= with a degree of fuzziness.
Definition MathUtils.hh:84
double deltaPhi(double phi1, double phi2, bool sign=false)
Calculate the difference between two angles in radians.
Definition MathUtils.hh:678
double subtract(double a, double b, double tolerance=1e-5)
Subtract two numbers with FP fuzziness.
Definition MathUtils.hh:223
vector< double > aspace(double step, double start, double end, bool include_end=true, double tol=1e-2)
Make a list of values equally spaced by step between start and end inclusive.
Definition MathUtils.hh:336
double deltaEta(double eta1, double eta2, bool sign=false)
Definition MathUtils.hh:686
PhiMapping
Enum for range of to be mapped into.
Definition MathConstants.hh:49
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:384
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > median(const vector< NUM > &sample)
Definition MathUtils.hh:493
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > max(N1 a, N2 b)
Get the maximum of two numbers.
Definition MathUtils.hh:115
double mapAngle0To2Pi(double angle)
Map an angle into the range [0, 2PI).
Definition MathUtils.hh:638
std::enable_if_t< std::is_arithmetic_v< NUM >, double > correlation_err(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition MathUtils.hh:589
double deltaR2(double rap1, double phi1, double rap2, double phi2)
Definition MathUtils.hh:701
double mT(double pT1, double pT2, double dphi)
Definition MathUtils.hh:731
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > add_quad(NUM a, NUM b)
Named number-type addition in quadrature operation.
Definition MathUtils.hh:241
std::enable_if_t< std::is_floating_point_v< NUM >, bool > isZero(NUM val, double tolerance=1e-8)
Compare a number to zero.
Definition MathUtils.hh:24
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > sqr(NUM a)
Named number-type squaring operation.
Definition MathUtils.hh:218
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 > &&std::is_arithmetic_v< N3 >, bool > in_range(N1 val, N2 low, N3 high)
Boolean function to determine if value is within the given range.
Definition MathUtils.hh:185
vector< double > fnspace(size_t nbins, double start, double end, const std::function< double(double)> &fn, const std::function< double(double)> &invfn, bool include_end=true)
Definition MathUtils.hh:355
constexpr double TWOPI
A pre-defined value of .
Definition MathConstants.hh:16
double mapAngleMPiToPi(double angle)
Map an angle into the range (-PI, PI].
Definition MathUtils.hh:628
std::enable_if_t< std::is_arithmetic_v< NUM >, double > covariance_err(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition MathUtils.hh:553
RangeBoundary
Definition MathUtils.hh:130
double add(double a, double b, double tolerance=1e-5)
Add two numbers with FP fuzziness.
Definition MathUtils.hh:229
vector< double > powspace(size_t nbins, double start, double end, double npow, bool include_end=true)
Make a list of nbins + 1 values power-law spaced between start and end inclusive.
Definition MathUtils.hh:401
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, signed_if_mixed_t< N1, N2 > > min(N1 a, N2 b)
Get the minimum of two numbers.
Definition MathUtils.hh:104
std::enable_if_t< std::is_arithmetic_v< NUM >, double > correlation(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition MathUtils.hh:576
double cdfBW(double x, double mu, double gamma)
CDF for the Breit-Wigner distribution.
Definition MathUtils.hh:288
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 > &&std::is_arithmetic_v< N3 >, bool > 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:137
double safediv(double num, double den, double fail=0.0)
Definition MathUtils.hh:259
constexpr double PI
Definition MathConstants.hh:13
double deltaRap(double y1, double y2, bool sign=false)
Definition MathUtils.hh:694
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 > &&std::is_arithmetic_v< N3 >, bool > in_closed_range(N1 val, N2 low, N3 high)
Boolean function to determine if value is within the given range.
Definition MathUtils.hh:194
double mapAngle(double angle, PhiMapping mapping)
Map an angle into the enum-specified range.
Definition MathUtils.hh:656
std::enable_if_t< std::is_floating_point_v< NUM >, bool > isNaN(NUM val)
Check if a number is NaN.
Definition MathUtils.hh:41
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:312
std::enable_if_t< std::is_arithmetic_v< NUM >, double > mean_err(const vector< NUM > &sample)
Definition MathUtils.hh:520
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 > &&std::is_arithmetic_v< N3 >, bool > in_open_range(N1 val, N2 low, N3 high)
Boolean function to determine if value is within the given range.
Definition MathUtils.hh:203
std::enable_if_t< std::is_arithmetic_v< NUM >, double > covariance(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition MathUtils.hh:534
double mapAngle0ToPi(double angle)
Map an angle into the range [0, PI].
Definition MathUtils.hh:648
constexpr std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > intpow(NUM val, unsigned int exp)
A more efficient version of pow for raising numbers to integer powers.
Definition MathUtils.hh:266
double invcdfBW(double p, double mu, double gamma)
Inverse CDF for the Breit-Wigner distribution.
Definition MathUtils.hh:295
double angle(const Vector2 &a, const Vector2 &b)
Angle (in radians) between two 2-vectors.
Definition Vector2.hh:177
std::enable_if_t< std::is_arithmetic_v< NUM1 > &&std::is_arithmetic_v< NUM2 >, int > 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:465
std::enable_if_t< std::is_floating_point_v< NUM >, bool > notNaN(NUM val)
Check if a number is non-NaN.
Definition MathUtils.hh:46
vector< double > powdbnspace(size_t nbins, double start, double end, double npow, bool include_end=true)
Make a list of nbins + 1 values equally spaced in the CDF of x^n between start and end inclusive.
Definition MathUtils.hh:420
std::enable_if_t< std::is_arithmetic_v< NUM >, double > mean(const vector< NUM > &sample)
Definition MathUtils.hh:507
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 > &&(std::is_floating_point_v< N1 >||std::is_floating_point_v< N2 >), bool > fuzzyEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two numbers for equality with a degree of fuzziness.
Definition MathUtils.hh:61
vector< double > bwdbnspace(size_t nbins, double start, double end, double mu, double gamma, bool include_end=true)
Make a list of nbins + 1 values spaced for equal area Breit-Wigner binning between start and end incl...
Definition MathUtils.hh:436
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 >, bool > fuzzyLessEquals(N1 a, N2 b, double tolerance=1e-5)
Compare two floating point numbers for <= with a degree of fuzziness.
Definition MathUtils.hh:94
std::enable_if_t< std::is_arithmetic_v< N1 > &&std::is_arithmetic_v< N2 > &&std::is_arithmetic_v< N3 >, bool > 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:156
double rapidity(double E, double pz)
Calculate a rapidity value from the supplied energy E and longitudinal momentum pz.
Definition MathUtils.hh:713
Error for e.g. use of invalid bin ranges.
Definition Exceptions.hh:22
Error specialisation for where the problem is between the chair and the computer.
Definition Exceptions.hh:67