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 <cassert>
7#include <type_traits>
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> isZero(NUM val,
24 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> isZero(
34 NUM val,
35 double = 1e-5) { //< NB. unused tolerance parameter for ints, still needs a default value!
36 return val == 0;
37 }
38
40 template <typename NUM>
41 inline typename std::enable_if_t<std::is_floating_point_v<NUM>, bool> isNaN(NUM val) {
42 return std::isnan(val);
43 }
44
46 template <typename NUM>
47 inline typename std::enable_if_t<std::is_floating_point_v<NUM>, bool> notNaN(NUM val) {
48 return !std::isnan(val);
49 }
50
52 template <typename NUM>
53 inline typename std::enable_if<std::is_floating_point<NUM>::value, NUM>::type sqrt_signed(NUM val) {
54 return std::copysign(sqrt(std::abs(val)), val);
55 }
56
62 template <typename N1, typename N2>
63 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>
64 && (std::is_floating_point_v<N1> || std::is_floating_point_v<N2>),
65 bool>
66 fuzzyEquals(N1 a, N2 b, double tolerance = 1e-5) {
67 const double absavg = (std::abs(a) + std::abs(b)) / 2.0;
68 const double absdiff = std::abs(a - b);
69 const bool rtn = (isZero(a) && isZero(b)) || absdiff < tolerance * absavg;
70 return rtn;
71 }
72
77 template <typename N1, typename N2>
78 inline typename std::enable_if_t<std::is_integral_v<N1> && std::is_integral_v<N2>, bool> fuzzyEquals(
79 N1 a,
80 N2 b,
81 double) { //< NB. unused tolerance parameter for ints, still needs a default value!
82 return a == b;
83 }
84
85
89 template <typename N1, typename N2>
90 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>, bool> fuzzyGtrEquals(
91 N1 a,
92 N2 b,
93 double tolerance = 1e-5) {
94 return a > b || fuzzyEquals(a, b, tolerance);
95 }
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>, bool>
103 fuzzyLessEquals(N1 a, N2 b, double tolerance = 1e-5) {
104 return a < b || fuzzyEquals(a, b, tolerance);
105 }
106
110 template <typename N1, typename N2>
111 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>,
112 signed_if_mixed_t<N1, N2>>
113 min(N1 a, N2 b) {
114 using rtnT = signed_if_mixed_t<N1, N2>;
115 return ((rtnT)a > (rtnT)b) ? b : a;
116 }
117
121 template <typename N1, typename N2>
122 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>,
123 signed_if_mixed_t<N1, N2>>
124 max(N1 a, N2 b) {
125 using rtnT = signed_if_mixed_t<N1, N2>;
126 return ((rtnT)a > (rtnT)b) ? a : b;
127 }
128
130
131
134
139 enum RangeBoundary { OPEN = 0, SOFT = 0, CLOSED = 1, HARD = 1 };
140
144 template <typename N1, typename N2, typename N3>
145 inline typename std::
146 enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
147 inRange(N1 value, N2 low, N3 high, RangeBoundary lowbound = CLOSED, RangeBoundary highbound = OPEN) {
148 if (lowbound == OPEN && highbound == OPEN) {
149 return (value > low && value < high);
150 }
151 else if (lowbound == OPEN && highbound == CLOSED) {
152 return (value > low && value <= high);
153 }
154 else if (lowbound == CLOSED && highbound == OPEN) {
155 return (value >= low && value < high);
156 }
157 else { // if (lowbound == CLOSED && highbound == CLOSED) {
158 return (value >= low && value <= high);
159 }
160 }
161
166 template <typename N1, typename N2, typename N3>
167 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>
168 && std::is_arithmetic_v<N3>,
169 bool>
170 fuzzyInRange(N1 value, N2 low, N3 high, RangeBoundary lowbound = CLOSED, RangeBoundary highbound = OPEN) {
171 if (lowbound == OPEN && highbound == OPEN) {
172 return (value > low && value < high);
173 }
174 else if (lowbound == OPEN && highbound == CLOSED) {
175 return (value > low && fuzzyLessEquals(value, high));
176 }
177 else if (lowbound == CLOSED && highbound == OPEN) {
178 return (fuzzyGtrEquals(value, low) && value < high);
179 }
180 else { // if (lowbound == CLOSED && highbound == CLOSED) {
181 return (fuzzyGtrEquals(value, low) && fuzzyLessEquals(value, high));
182 }
183 }
184
186 template <typename N1, typename N2, typename N3>
187 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>
188 && std::is_arithmetic_v<N3>,
189 bool>
190 inRange(N1 value, pair<N2, N3> lowhigh, RangeBoundary lowbound = CLOSED, RangeBoundary highbound = OPEN) {
191 return inRange(value, lowhigh.first, lowhigh.second, lowbound, highbound);
192 }
193
194
195 // Alternative forms, with snake_case names and boundary types in names rather than as args -- from MCUtils
196
200 template <typename N1, typename N2, typename N3>
201 inline typename std::
202 enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
203 in_range(N1 val, N2 low, N3 high) {
204 return inRange(val, low, high, CLOSED, OPEN);
205 }
206
210 template <typename N1, typename N2, typename N3>
211 inline typename std::
212 enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
213 in_closed_range(N1 val, N2 low, N3 high) {
214 return inRange(val, low, high, CLOSED, CLOSED);
215 }
216
220 template <typename N1, typename N2, typename N3>
221 inline typename std::
222 enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2> && std::is_arithmetic_v<N3>, bool>
223 in_open_range(N1 val, N2 low, N3 high) {
224 return inRange(val, low, high, OPEN, OPEN);
225 }
226
228
230
231
234
236 template <typename NUM>
237 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM> sqr(NUM a) {
238 return a * a;
239 }
240
242 inline double subtract(double a, double b, double tolerance = 1e-5) {
243 if (fuzzyEquals(a, b, tolerance)) return 0.;
244 return a - b;
245 }
246
248 inline double add(double a, double b, double tolerance = 1e-5) {
249 return subtract(a, -b, tolerance);
250 }
251
256 // template <typename N1, typename N2>
257 template <typename NUM>
258 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
259 //std::common_type<N1, N2>::type
260 add_quad(NUM a, NUM b) {
261 return sqrt(a * a + b * b);
262 }
263
268 // template <typename N1, typename N2>
269 template <typename NUM>
270 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
271 //std::common_type<N1, N2, N3>::type
272 add_quad(NUM a, NUM b, NUM c) {
273 return sqrt(a * a + b * b + c * c);
274 }
275
278 inline double safediv(double num, double den, double fail = 0.0) {
279 return (!isZero(den)) ? num / den : fail;
280 }
281
283 template <typename NUM>
284 constexpr inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM> intpow(NUM val,
285 unsigned int exp) {
286 if (exp == 0)
287 return (NUM)1;
288 else if (exp == 1)
289 return val;
290 return val * intpow(val, exp - 1);
291 }
292
294 template <typename NUM>
295 constexpr inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, int> sign(NUM val) {
296 if (isZero(val)) return ZERO;
297 const int valsign = (val > 0) ? PLUS : MINUS;
298 return valsign;
299 }
300
302
303
306
308 inline double cdfBW(double x, double mu, double gamma) {
309 // normalize to (0;1) distribution
310 const double xn = (x - mu) / gamma;
311 return std::atan(xn) / M_PI + 0.5;
312 }
313
315 inline double invcdfBW(double p, double mu, double gamma) {
316 const double xn = std::tan(M_PI * (p - 0.5));
317 return gamma * xn + mu;
318 }
319
321
322
325
332 inline vector<double> linspace(size_t nbins, double start, double end, bool include_end = true) {
333 assert(nbins > 0);
334 vector<double> rtn;
335 const double interval = (end - start) / static_cast<double>(nbins);
336 for (size_t i = 0; i < nbins; ++i) {
337 rtn.push_back(start + i * interval);
338 }
339 assert(rtn.size() == nbins);
340 if (include_end) rtn.push_back(end); //< exact end, not result of n * interval
341 return rtn;
342 }
343
344
356 inline vector<double> aspace(double step,
357 double start,
358 double end,
359 bool include_end = true,
360 double tol = 1e-2) {
361 assert((end - start) * step > 0); //< ensure the step is going in the direction from start to end
362 vector<double> rtn;
363 double next = start;
364 while (true) {
365 if (next > end) break;
366 rtn.push_back(next);
367 next += step;
368 }
369 if (include_end) {
370 if (end - rtn[rtn.size() - 1] > tol * step) rtn.push_back(end);
371 }
372 return rtn;
373 }
374
375
379 inline vector<double> fnspace(size_t nbins,
380 double start,
381 double end,
382 const std::function<double(double)>& fn,
383 const std::function<double(double)>& invfn,
384 bool include_end = true) {
385 // assert(end >= start);
386 assert(nbins > 0);
387 const double pmin = fn(start);
388 const double pmax = fn(end);
389 const vector<double> edges = linspace(nbins, pmin, pmax, false);
390 assert(edges.size() == nbins);
391 vector<double> rtn;
392 rtn.reserve(nbins + 1);
393 rtn.push_back(start); //< exact start, not round-tripped
394 for (size_t i = 1; i < edges.size(); ++i) {
395 rtn.push_back(invfn(edges[i]));
396 }
397 assert(rtn.size() == nbins);
398 if (include_end) rtn.push_back(end); //< exact end
399 return rtn;
400 }
401
402
412 inline vector<double> logspace(size_t nbins, double start, double end, bool include_end = true) {
413 return fnspace(
414 nbins, start, end, [](double x) { return std::log(x); }, [](double x) { return std::exp(x); },
415 include_end);
416 }
417
418
428 inline vector<double> powspace(size_t nbins,
429 double start,
430 double end,
431 double npow,
432 bool include_end = true) {
433 assert(start >= 0); //< non-integer powers are complex for negative numbers... don't go there
434 return fnspace(
435 nbins, start, end, [&](double x) { return std::pow(x, npow); },
436 [&](double x) { return std::pow(x, 1 / npow); }, include_end);
437 }
438
450 inline vector<double> powdbnspace(size_t nbins,
451 double start,
452 double end,
453 double npow,
454 bool include_end = true) {
455 assert(start >= 0); //< non-integer powers are complex for negative numbers... don't go there
456 return fnspace(
457 nbins, start, end, [&](double x) { return std::pow(x, npow + 1) / (npow + 1); },
458 [&](double x) { return std::pow((npow + 1) * x, 1 / (npow + 1)); }, include_end);
459 }
460
461
469 inline vector<double> bwdbnspace(size_t nbins,
470 double start,
471 double end,
472 double mu,
473 double gamma,
474 bool include_end = true) {
475 return fnspace(
476 nbins, start, end, [&](double x) { return cdfBW(x, mu, gamma); },
477 [&](double x) { return invcdfBW(x, mu, gamma); }, include_end);
478 }
479
480
482 template <typename NUM, typename CONTAINER>
483 inline typename std::
484 enable_if_t<std::is_arithmetic_v<NUM> && std::is_arithmetic_v<typename CONTAINER::value_type>, int>
485 _binIndex(NUM val, const CONTAINER& binedges, bool allow_overflow = false) {
486 if (val < *begin(binedges)) return -1;
487 // CONTAINER::iterator_type itend =
488 if (val >= *(end(binedges) - 1))
489 return allow_overflow ? int(binedges.size()) - 1 : -1;
490 auto it = std::upper_bound(begin(binedges), end(binedges), val);
491 return std::distance(begin(binedges), --it);
492 }
493
502 template <typename NUM1, typename NUM2>
503 inline typename std::enable_if_t<std::is_arithmetic_v<NUM1> && std::is_arithmetic_v<NUM2>, int> binIndex(
504 NUM1 val,
505 std::initializer_list<NUM2> binedges,
506 bool allow_overflow = false) {
507 return _binIndex(val, binedges, allow_overflow);
508 }
509
518 template <typename NUM, typename CONTAINER>
519 inline typename std::
520 enable_if_t<std::is_arithmetic_v<NUM> && std::is_arithmetic_v<typename CONTAINER::value_type>, int>
521 binIndex(NUM val, const CONTAINER& binedges, bool allow_overflow = false) {
522 return _binIndex(val, binedges, allow_overflow);
523 }
524
526
527
530
533 template <typename NUM>
534 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM> median(const vector<NUM>& sample) {
535 if (sample.empty()) throw RangeError("Can't compute median of an empty set");
536 vector<NUM> tmp = sample;
537 std::sort(tmp.begin(), tmp.end());
538 const size_t imid = tmp.size() / 2; // len1->idx0, len2->idx1, len3->idx1, len4->idx2, ...
539 if (sample.size() % 2 == 0)
540 return (tmp.at(imid - 1) + tmp.at(imid)) / 2.0;
541 else
542 return tmp.at(imid);
543 }
544
545
548 template <typename NUM>
549 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double> mean(const vector<NUM>& sample) {
550 if (sample.empty()) throw RangeError("Can't compute mean of an empty set");
551 double mean = 0.0;
552 for (size_t i = 0; i < sample.size(); ++i) {
553 mean += sample[i];
554 }
555 return mean / sample.size();
556 }
557
558 // Calculate the error on the mean, assuming Poissonian errors
560 template <typename NUM>
561 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double> mean_err(const vector<NUM>& sample) {
562 if (sample.empty()) throw RangeError("Can't compute mean_err of an empty set");
563 double mean_e = 0.0;
564 for (size_t i = 0; i < sample.size(); ++i) {
565 mean_e += sqrt(sample[i]);
566 }
567 return mean_e / sample.size();
568 }
569
570
573 template <typename NUM>
574 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double> covariance(const vector<NUM>& sample1,
575 const vector<NUM>& sample2) {
576 if (sample1.empty() || sample2.empty()) throw RangeError("Can't compute covariance of an empty set");
577 if (sample1.size() != sample2.size())
578 throw RangeError("Sizes of samples must be equal for covariance calculation");
579 const double mean1 = mean(sample1);
580 const double mean2 = mean(sample2);
581 const size_t N = sample1.size();
582 double cov = 0.0;
583 for (size_t i = 0; i < N; i++) {
584 const double cov_i = (sample1[i] - mean1) * (sample2[i] - mean2);
585 cov += cov_i;
586 }
587 if (N > 1)
588 return cov / (N - 1);
589 else
590 return 0.0;
591 }
592
595 template <typename NUM>
596 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double> covariance_err(
597 const vector<NUM>& sample1,
598 const vector<NUM>& sample2) {
599 if (sample1.empty() || sample2.empty()) throw RangeError("Can't compute covariance_err of an empty set");
600 if (sample1.size() != sample2.size())
601 throw RangeError("Sizes of samples must be equal for covariance_err calculation");
602 const double mean1 = mean(sample1);
603 const double mean2 = mean(sample2);
604 const double mean1_e = mean_err(sample1);
605 const double mean2_e = mean_err(sample2);
606 const size_t N = sample1.size();
607 double cov_e = 0.0;
608 for (size_t i = 0; i < N; i++) {
609 const double cov_i = (sqrt(sample1[i]) - mean1_e) * (sample2[i] - mean2)
610 + (sample1[i] - mean1) * (sqrt(sample2[i]) - mean2_e);
611 cov_e += cov_i;
612 }
613 if (N > 1)
614 return cov_e / (N - 1);
615 else
616 return 0.0;
617 }
618
619
622 template <typename NUM>
623 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double> correlation(
624 const vector<NUM>& sample1,
625 const vector<NUM>& sample2) {
626 const double cov = covariance(sample1, sample2);
627 const double var1 = covariance(sample1, sample1);
628 const double var2 = covariance(sample2, sample2);
629 const double correlation = cov / sqrt(var1 * var2);
630 const double corr_strength = correlation * sqrt(var2 / var1);
631 return corr_strength;
632 }
633
636 template <typename NUM>
637 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double> correlation_err(
638 const vector<NUM>& sample1,
639 const vector<NUM>& sample2) {
640 const double cov = covariance(sample1, sample2);
641 const double var1 = covariance(sample1, sample1);
642 const double var2 = covariance(sample2, sample2);
643 const double cov_e = covariance_err(sample1, sample2);
644 const double var1_e = covariance_err(sample1, sample1);
645 const double var2_e = covariance_err(sample2, sample2);
646
647 // Calculate the correlation
648 const double correlation = cov / sqrt(var1 * var2);
649 // Calculate the error on the correlation
650 const double correlation_err = cov_e / sqrt(var1 * var2)
651 - cov / (2 * pow(3. / 2., var1 * var2)) * (var1_e * var2 + var1 * var2_e);
652
653 // Calculate the error on the correlation strength
654 const double corr_strength_err = correlation_err * sqrt(var2 / var1)
655 + correlation / (2 * sqrt(var2 / var1)) * (var2_e / var1 - var2 * var1_e / pow(2, var2));
656
657 return corr_strength_err;
658 }
659
661
662
665
670 inline double _mapAngleM2PITo2Pi(double angle) {
671 double rtn = fmod(angle, TWOPI);
672 if (isZero(rtn)) return 0;
673 assert(rtn >= -TWOPI && rtn <= TWOPI);
674 return rtn;
675 }
676
678 inline double mapAngleMPiToPi(double angle) {
679 double rtn = _mapAngleM2PITo2Pi(angle);
680 if (isZero(rtn)) return 0;
681 if (rtn > PI) rtn -= TWOPI;
682 if (rtn <= -PI) rtn += TWOPI;
683 assert(rtn > -PI && rtn <= PI);
684 return rtn;
685 }
686
688 inline double mapAngle0To2Pi(double angle) {
689 double rtn = _mapAngleM2PITo2Pi(angle);
690 if (isZero(rtn)) return 0;
691 if (rtn < 0) rtn += TWOPI;
692 if (rtn == TWOPI) rtn = 0;
693 assert(rtn >= 0 && rtn < TWOPI);
694 return rtn;
695 }
696
698 inline double mapAngle0ToPi(double angle) {
699 double rtn = fabs(mapAngleMPiToPi(angle));
700 if (isZero(rtn)) return 0;
701 assert(rtn > 0 && rtn <= PI);
702 return rtn;
703 }
704
706 inline double mapAngle(double angle, PhiMapping mapping) {
707 switch (mapping) {
708 case MINUSPI_PLUSPI: return mapAngleMPiToPi(angle);
709 case ZERO_2PI: return mapAngle0To2Pi(angle);
710 case ZERO_PI: return mapAngle0ToPi(angle);
711 default: throw Rivet::UserError("The specified phi mapping scheme is not implemented");
712 }
713 }
714
716
717
720
724 inline double deltaPhi(double phi1, double phi2, bool sign = false) {
725 const double x = mapAngleMPiToPi(phi1 - phi2);
726 return sign ? x : fabs(x);
727 }
728
732 inline double deltaEta(double eta1, double eta2, bool sign = false) {
733 const double x = eta1 - eta2;
734 return sign ? x : fabs(x);
735 }
736
740 inline double deltaRap(double y1, double y2, bool sign = false) {
741 const double x = y1 - y2;
742 return sign ? x : fabs(x);
743 }
744
747 inline double deltaR2(double rap1, double phi1, double rap2, double phi2) {
748 const double dphi = deltaPhi(phi1, phi2);
749 return sqr(rap1 - rap2) + sqr(dphi);
750 }
751
754 inline double deltaR(double rap1, double phi1, double rap2, double phi2) {
755 return sqrt(deltaR2(rap1, phi1, rap2, phi2));
756 }
757
759 inline double rapidity(double E, double pz) {
760 if (isZero(E - pz)) {
761 throw std::runtime_error("Divergent positive rapidity");
762 return DBL_MAX;
763 }
764 if (isZero(E + pz)) {
765 throw std::runtime_error("Divergent negative rapidity");
766 return -DBL_MAX;
767 }
768 return 0.5 * log((E + pz) / (E - pz));
769 }
770
772
773
777 inline double mT(double pT1, double pT2, double dphi) {
778 return sqrt(2 * pT1 * pT2 * (1 - cos(dphi)));
779 }
780
781
782}
783
784
785#endif
double E(const ParticleBase &p)
Unbound function access to E.
Definition ParticleBaseUtils.hh:829
double p(const ParticleBase &p)
Unbound function access to p.
Definition ParticleBaseUtils.hh:819
Definition LHCbCommon.hh:9
constexpr std::enable_if_t< std::is_arithmetic_v< NUM >, int > sign(NUM val)
Find the sign of a number.
Definition MathUtils.hh:295
double deltaR(double rap1, double phi1, double rap2, double phi2)
Definition MathUtils.hh:754
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:53
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:90
double deltaPhi(double phi1, double phi2, bool sign=false)
Calculate the difference between two angles in radians.
Definition MathUtils.hh:724
double subtract(double a, double b, double tolerance=1e-5)
Subtract two numbers with FP fuzziness.
Definition MathUtils.hh:242
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:356
double deltaEta(double eta1, double eta2, bool sign=false)
Definition MathUtils.hh:732
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:412
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > median(const vector< NUM > &sample)
Definition MathUtils.hh:534
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:124
double mapAngle0To2Pi(double angle)
Map an angle into the range [0, 2PI).
Definition MathUtils.hh:688
std::enable_if_t< std::is_arithmetic_v< NUM >, double > correlation_err(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition MathUtils.hh:637
double deltaR2(double rap1, double phi1, double rap2, double phi2)
Definition MathUtils.hh:747
double mT(double pT1, double pT2, double dphi)
Definition MathUtils.hh:777
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:260
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:23
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > sqr(NUM a)
Named number-type squaring operation.
Definition MathUtils.hh:237
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:203
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:379
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:678
std::enable_if_t< std::is_arithmetic_v< NUM >, double > covariance_err(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition MathUtils.hh:596
RangeBoundary
Definition MathUtils.hh:139
double add(double a, double b, double tolerance=1e-5)
Add two numbers with FP fuzziness.
Definition MathUtils.hh:248
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:428
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:113
std::enable_if_t< std::is_arithmetic_v< NUM >, double > correlation(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition MathUtils.hh:623
double cdfBW(double x, double mu, double gamma)
CDF for the Breit-Wigner distribution.
Definition MathUtils.hh:308
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:147
double safediv(double num, double den, double fail=0.0)
Definition MathUtils.hh:278
constexpr double PI
Definition MathConstants.hh:13
double deltaRap(double y1, double y2, bool sign=false)
Definition MathUtils.hh:740
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:213
double mapAngle(double angle, PhiMapping mapping)
Map an angle into the enum-specified range.
Definition MathUtils.hh:706
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:332
std::enable_if_t< std::is_arithmetic_v< NUM >, double > mean_err(const vector< NUM > &sample)
Definition MathUtils.hh:561
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:223
std::enable_if_t< std::is_arithmetic_v< NUM >, double > covariance(const vector< NUM > &sample1, const vector< NUM > &sample2)
Definition MathUtils.hh:574
double mapAngle0ToPi(double angle)
Map an angle into the range [0, PI].
Definition MathUtils.hh:698
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:284
double invcdfBW(double p, double mu, double gamma)
Inverse CDF for the Breit-Wigner distribution.
Definition MathUtils.hh:315
double angle(const Vector2 &a, const Vector2 &b)
Angle (in radians) between two 2-vectors.
Definition Vector2.hh:194
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:503
std::enable_if_t< std::is_floating_point_v< NUM >, bool > notNaN(NUM val)
Check if a number is non-NaN.
Definition MathUtils.hh:47
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:450
std::enable_if_t< std::is_arithmetic_v< NUM >, double > mean(const vector< NUM > &sample)
Definition MathUtils.hh:549
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:66
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:469
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:103
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:170
double rapidity(double E, double pz)
Calculate a rapidity value from the supplied energy E and longitudinal momentum pz.
Definition MathUtils.hh:759
Error for e.g. use of invalid bin ranges.
Definition Exceptions.hh:23
Error specialisation for where the problem is between the chair and the computer.
Definition Exceptions.hh:75