|
|
Rivet 4.0.2
|
2#ifndef RIVET_MathUtils_HH
3#define RIVET_MathUtils_HH
5#include "Rivet/Math/MathConstants.hh"
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;
32 template < typename NUM>
33 inline typename std::enable_if_t<std::is_integral_v<NUM>, bool>
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); }
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); }
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); }
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>
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;
72 template < typename N1, typename N2>
73 inline typename std::enable_if_t<std::is_integral_v<N1> && std::is_integral_v<N2>, bool>
82 template < typename N1, typename N2>
83 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>, bool>
92 template < typename N1, typename N2>
93 inline typename std::enable_if_t<std::is_arithmetic_v<N1> && std::is_arithmetic_v<N2>, bool>
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> >
105 using rtnT = signed_if_mixed_t<N1,N2>;
106 return ((rtnT)a > (rtnT)b)? b : a;
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> >
116 using rtnT = signed_if_mixed_t<N1,N2>;
117 return ((rtnT)a > (rtnT)b)? a : b;
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>
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);
146 return (value >= low && value <= high);
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>
158 if (lowbound == OPEN && highbound == OPEN) {
159 return (value > low && value < high);
160 } else if (lowbound == OPEN && highbound == CLOSED) {
162 } else if (lowbound == CLOSED && highbound == OPEN) {
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>
174 return inRange(value, lowhigh.first, lowhigh.second, lowbound, highbound);
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>
186 return inRange(val, low, high, CLOSED, OPEN);
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>
195 return inRange(val, low, high, CLOSED, CLOSED);
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>
204 return inRange(val, low, high, OPEN, OPEN);
216 template < typename NUM>
217 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
227 template < typename NUM>
228 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
231 return sqrt(a*a + b*b);
239 template < typename NUM>
240 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
243 return sqrt(a*a + b*b + c*c);
248 inline double safediv( double num, double den, double fail=0.0) {
249 return (! isZero(den)) ? num/den : fail;
253 template < typename NUM>
254 constexpr inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
256 if (exp == 0) return (NUM) 1;
257 else if (exp == 1) return val;
258 return val * intpow(val, exp-1);
262 template < typename NUM>
263 constexpr inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, int>
265 if ( isZero(val)) return ZERO;
266 const int valsign = (val > 0) ? PLUS : MINUS;
277 inline double cdfBW( double x, double mu, double gamma) {
279 const double xn = (x - mu)/gamma;
280 return std::atan(xn)/M_PI + 0.5;
284 inline double invcdfBW( double p, double mu, double gamma) {
285 const double xn = std::tan(M_PI*(p-0.5));
286 return gamma*xn + mu;
301 inline vector<double> linspace( size_t nbins, double start, double end, bool include_end= true) {
304 const double interval = (end-start)/ static_cast<double>(nbins);
305 for ( size_t i = 0; i < nbins; ++i) {
306 rtn.push_back(start + i*interval);
308 assert(rtn.size() == nbins);
309 if (include_end) rtn.push_back(end);
325 inline vector<double> aspace( double step, double start, double end, bool include_end= true, double tol=1e-2) {
326 assert( (end-start)*step > 0);
330 if (next > end) break;
335 if (end - rtn[rtn.size()-1] > tol*step) rtn.push_back(end);
344 inline vector<double> fnspace( size_t nbins, double start, double end,
345 const std::function< double( double)>& fn, const std::function< double( double)>& invfn,
346 bool include_end= true) {
349 const double pmin = fn(start);
350 const double pmax = fn(end);
351 const vector<double> edges = linspace(nbins, pmin, pmax, false);
352 assert(edges.size() == nbins);
353 vector<double> rtn; rtn.reserve(nbins+1);
354 rtn.push_back(start);
355 for ( size_t i = 1; i < edges.size(); ++i) {
356 rtn.push_back(invfn(edges[i]));
358 assert(rtn.size() == nbins);
359 if (include_end) rtn.push_back(end);
373 inline vector<double> logspace( size_t nbins, double start, double end, bool include_end= true) {
374 return fnspace(nbins, start, end,
375 []( double x){ return std::log(x); },
376 []( double x){ return std::exp(x); },
390 inline vector<double> powspace( size_t nbins, double start, double end, double npow, bool include_end= true) {
392 return fnspace(nbins, start, end,
393 [&]( double x){ return std::pow(x, npow); },
394 [&]( double x){ return std::pow(x, 1/npow); },
409 inline vector<double> powdbnspace( size_t nbins, double start, double end, double npow, bool include_end= true) {
411 return fnspace(nbins, start, end,
412 [&]( double x){ return std::pow(x, npow+1) / (npow+1); },
413 [&]( double x){ return std::pow((npow+1) * x, 1/(npow+1)); },
425 inline vector<double> bwdbnspace( size_t nbins, double start, double end, double mu, double gamma, bool include_end= true) {
426 return fnspace(nbins, start, end,
427 [&]( double x){ return cdfBW(x, mu, gamma); },
428 [&]( double x){ return invcdfBW(x, mu, gamma); },
434 template < typename NUM, typename CONTAINER>
435 inline typename std::enable_if_t<std::is_arithmetic_v<NUM> && std::is_arithmetic_v<typename CONTAINER::value_type>, int>
436 _binIndex(NUM val, const CONTAINER& binedges, bool allow_overflow= false) {
437 if (val < *begin(binedges)) return -1;
439 if (val >= *(end(binedges)-1)) return allow_overflow ? int(binedges.size())-1 : -1;
440 auto it = std::upper_bound(begin(binedges), end(binedges), val);
441 return std::distance(begin(binedges), --it);
452 template < typename NUM1, typename NUM2>
453 inline typename std::enable_if_t<std::is_arithmetic_v<NUM1> && std::is_arithmetic_v<NUM2>, int>
454 binIndex(NUM1 val, std::initializer_list<NUM2> binedges, bool allow_overflow= false) {
455 return _binIndex(val, binedges, allow_overflow);
466 template < typename NUM, typename CONTAINER>
467 inline typename std::enable_if_t<std::is_arithmetic_v<NUM> && std::is_arithmetic_v<typename CONTAINER::value_type>, int>
468 binIndex(NUM val, const CONTAINER& binedges, bool allow_overflow= false) {
469 return _binIndex(val, binedges, allow_overflow);
480 template < typename NUM>
481 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, NUM>
483 if (sample.empty()) throw RangeError( "Can't compute median of an empty set");
484 vector<NUM> tmp = sample;
485 std::sort(tmp.begin(), tmp.end());
486 const size_t imid = tmp.size()/2;
487 if (sample.size() % 2 == 0) return (tmp.at(imid-1) + tmp.at(imid)) / 2.0;
488 else return tmp.at(imid);
494 template < typename NUM>
495 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
496 mean( const vector<NUM>& sample) {
497 if (sample.empty()) throw RangeError( "Can't compute mean of an empty set");
499 for ( size_t i = 0; i < sample.size(); ++i) {
502 return mean/sample.size();
507 template < typename NUM>
508 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
510 if (sample.empty()) throw RangeError( "Can't compute mean_err of an empty set");
512 for ( size_t i = 0; i < sample.size(); ++i) {
513 mean_e += sqrt(sample[i]);
515 return mean_e/sample.size();
521 template < typename NUM>
522 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
523 covariance( const vector<NUM>& sample1, const vector<NUM>& sample2) {
524 if (sample1.empty() || sample2.empty()) throw RangeError( "Can't compute covariance of an empty set");
525 if (sample1.size() != sample2.size()) throw RangeError( "Sizes of samples must be equal for covariance calculation");
526 const double mean1 = mean(sample1);
527 const double mean2 = mean(sample2);
528 const size_t N = sample1.size();
530 for ( size_t i = 0; i < N; i++) {
531 const double cov_i = (sample1[i] - mean1)*(sample2[i] - mean2);
534 if (N > 1) return cov/(N-1);
540 template < typename NUM>
541 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
543 if (sample1.empty() || sample2.empty()) throw RangeError( "Can't compute covariance_err of an empty set");
544 if (sample1.size() != sample2.size()) throw RangeError( "Sizes of samples must be equal for covariance_err calculation");
545 const double mean1 = mean(sample1);
546 const double mean2 = mean(sample2);
547 const double mean1_e = mean_err(sample1);
548 const double mean2_e = mean_err(sample2);
549 const size_t N = sample1.size();
551 for ( size_t i = 0; i < N; i++) {
552 const double cov_i = (sqrt(sample1[i]) - mean1_e)*(sample2[i] - mean2) +
553 (sample1[i] - mean1)*(sqrt(sample2[i]) - mean2_e);
556 if (N > 1) return cov_e/(N-1);
563 template < typename NUM>
564 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
565 correlation( const vector<NUM>& sample1, const vector<NUM>& sample2) {
566 const double cov = covariance(sample1, sample2);
567 const double var1 = covariance(sample1, sample1);
568 const double var2 = covariance(sample2, sample2);
570 const double corr_strength = correlation*sqrt(var2/var1);
571 return corr_strength;
576 template < typename NUM>
577 inline typename std::enable_if_t<std::is_arithmetic_v<NUM>, double>
579 const double cov = covariance(sample1, sample2);
580 const double var1 = covariance(sample1, sample1);
581 const double var2 = covariance(sample2, sample2);
590 cov/(2*pow(3./2., var1*var2)) * (var1_e * var2 + var1 * var2_e);
594 correlation/(2*sqrt(var2/var1)) * (var2_e/var1 - var2*var1_e/pow(2, var2));
596 return corr_strength_err;
609 inline double _mapAngleM2PITo2Pi( double angle) {
611 if ( isZero(rtn)) return 0;
618 double rtn = _mapAngleM2PITo2Pi( angle);
619 if ( isZero(rtn)) return 0;
622 assert(rtn > - PI && rtn <= PI);
628 double rtn = _mapAngleM2PITo2Pi( angle);
629 if ( isZero(rtn)) return 0;
630 if (rtn < 0) rtn += TWOPI;
631 if (rtn == TWOPI) rtn = 0;
632 assert(rtn >= 0 && rtn < TWOPI);
639 if ( isZero(rtn)) return 0;
640 assert(rtn > 0 && rtn <= PI);
654 throw Rivet::UserError( "The specified phi mapping scheme is not implemented");
669 return sign ? x : fabs(x);
676 const double x = eta1 - eta2;
677 return sign ? x : fabs(x);
684 const double x = y1 - y2;
685 return sign? x : fabs(x);
690 inline double deltaR2( double rap1, double phi1, double rap2, double phi2) {
691 const double dphi = deltaPhi(phi1, phi2);
692 return sqr(rap1-rap2) + sqr(dphi);
697 inline double deltaR( double rap1, double phi1, double rap2, double phi2) {
698 return sqrt( deltaR2(rap1, phi1, rap2, phi2));
704 throw std::runtime_error( "Divergent positive rapidity");
708 throw std::runtime_error( "Divergent negative rapidity");
711 return 0.5*log((E+pz)/(E-pz));
719 inline double mT( double pT1, double pT2, double dphi) {
720 return sqrt(2*pT1*pT2 * (1 - cos(dphi)) );
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:264
double deltaR(double rap1, double phi1, double rap2, double phi2) Definition MathUtils.hh:697
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:667
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:325
double deltaEta(double eta1, double eta2, bool sign=false) Definition MathUtils.hh:675
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:373
std::enable_if_t< std::is_arithmetic_v< NUM >, NUM > median(const vector< NUM > &sample) Definition MathUtils.hh:482
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:627
std::enable_if_t< std::is_arithmetic_v< NUM >, double > correlation_err(const vector< NUM > &sample1, const vector< NUM > &sample2) Definition MathUtils.hh:578
double deltaR2(double rap1, double phi1, double rap2, double phi2) Definition MathUtils.hh:690
double mT(double pT1, double pT2, double dphi) Definition MathUtils.hh:719
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:230
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:344
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:617
std::enable_if_t< std::is_arithmetic_v< NUM >, double > covariance_err(const vector< NUM > &sample1, const vector< NUM > &sample2) Definition MathUtils.hh:542
RangeBoundary Definition MathUtils.hh:130
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:390
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:565
double cdfBW(double x, double mu, double gamma) CDF for the Breit-Wigner distribution. Definition MathUtils.hh:277
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:248
constexpr double PI Definition MathConstants.hh:13
double deltaRap(double y1, double y2, bool sign=false) Definition MathUtils.hh:683
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:645
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:301
std::enable_if_t< std::is_arithmetic_v< NUM >, double > mean_err(const vector< NUM > &sample) Definition MathUtils.hh:509
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:523
double mapAngle0ToPi(double angle) Map an angle into the range [0, PI]. Definition MathUtils.hh:637
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:255
double invcdfBW(double p, double mu, double gamma) Inverse CDF for the Breit-Wigner distribution. Definition MathUtils.hh:284
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:454
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:409
std::enable_if_t< std::is_arithmetic_v< NUM >, double > mean(const vector< NUM > &sample) Definition MathUtils.hh:496
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:425
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:702
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:61
|