00001
00002 #ifndef RIVET_MathUtils_HH
00003 #define RIVET_MathUtils_HH
00004
00005 #include "Rivet/Math/MathHeader.hh"
00006 #include "Rivet/RivetBoost.hh"
00007 #include <cassert>
00008
00009 namespace Rivet {
00010
00011
00012
00013
00014
00015
00016
00017 inline bool isZero(double val, double tolerance=1E-8) {
00018 return (fabs(val) < tolerance);
00019 }
00020
00021
00022
00023
00024
00025 inline bool isZero(long val, double UNUSED(tolerance)=1E-8) {
00026 return val == 0;
00027 }
00028
00029
00030
00031
00032 inline bool fuzzyEquals(double a, double b, double tolerance=1E-5) {
00033 const double absavg = fabs(a + b)/2.0;
00034 const double absdiff = fabs(a - b);
00035 const bool rtn = (absavg == 0.0 && absdiff == 0.0) || absdiff < tolerance*absavg;
00036 return rtn;
00037 }
00038
00039
00040
00041
00042
00043
00044
00045 inline bool fuzzyEquals(long a, long b, double UNUSED(tolerance)=1E-5) {
00046 return a == b;
00047 }
00048
00049
00050
00051
00052 inline bool fuzzyGtrEquals(double a, double b, double tolerance=1E-5) {
00053 return a > b || fuzzyEquals(a, b, tolerance);
00054 }
00055
00056
00057
00058
00059
00060
00061
00062 inline bool fuzzyGtrEquals(long a, long b, double UNUSED(tolerance)=1E-5) {
00063 return a >= b;
00064 }
00065
00066
00067
00068
00069 inline bool fuzzyLessEquals(double a, double b, double tolerance=1E-5) {
00070 return a < b || fuzzyEquals(a, b, tolerance);
00071 }
00072
00073
00074
00075
00076
00077
00078
00079 inline bool fuzzyLessEquals(long a, long b, double UNUSED(tolerance)=1E-5) {
00080 return a <= b;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 enum RangeBoundary { OPEN=0, SOFT=0, CLOSED=1, HARD=1 };
00093
00094
00095
00096
00097
00098 template<typename NUM>
00099 inline bool inRange(NUM value, NUM low, NUM high,
00100 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
00101 if (lowbound == OPEN && highbound == OPEN) {
00102 return (value > low && value < high);
00103 } else if (lowbound == OPEN && highbound == CLOSED) {
00104 return (value > low && (value < high || fuzzyEquals(value, high)));
00105 } else if (lowbound == CLOSED && highbound == OPEN) {
00106 return ((value > low || fuzzyEquals(value, low)) && value < high);
00107 } else {
00108 return ((value > low || fuzzyEquals(value, low)) && (value < high || fuzzyEquals(value, high)));
00109 }
00110 }
00111
00112
00113 template<typename NUM>
00114 inline bool inRange(NUM value, pair<NUM, NUM> lowhigh,
00115 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
00116 return inRange(value, lowhigh.first, lowhigh.second, lowbound, highbound);
00117 }
00118
00119
00120
00121
00122
00123 inline bool inRange(int value, int low, int high,
00124 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=CLOSED) {
00125 if (lowbound == OPEN && highbound == OPEN) {
00126 return (value > low && value < high);
00127 } else if (lowbound == OPEN && highbound == CLOSED) {
00128 return (value > low && value <= high);
00129 } else if (lowbound == CLOSED && highbound == OPEN) {
00130 return (value >= low && value < high);
00131 } else {
00132 return (value >= low && value <= high);
00133 }
00134 }
00135
00136
00137 inline bool inRange(int value, pair<int, int> lowhigh,
00138 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
00139 return inRange(value, lowhigh.first, lowhigh.second, lowbound, highbound);
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149 template <typename NUM>
00150 inline NUM sqr(NUM a) {
00151 return a*a;
00152 }
00153
00154
00155 inline int sign(double val) {
00156 if (isZero(val)) return ZERO;
00157 const int valsign = (val > 0) ? PLUS : MINUS;
00158 return valsign;
00159 }
00160
00161
00162 inline int sign(int val) {
00163 if (val == 0) return ZERO;
00164 return (val > 0) ? PLUS : MINUS;
00165 }
00166
00167
00168 inline int sign(long val) {
00169 if (val == 0) return ZERO;
00170 return (val > 0) ? PLUS : MINUS;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180 inline vector<double> linspace(double start, double end, size_t nbins) {
00181 assert(end >= start);
00182 assert(nbins > 0);
00183 vector<double> rtn;
00184 const double interval = (end-start)/static_cast<double>(nbins);
00185 double edge = start;
00186 while (inRange(edge, start, end, CLOSED, CLOSED)) {
00187 rtn.push_back(edge);
00188 edge += interval;
00189 }
00190 assert(rtn.size() == nbins+1);
00191 return rtn;
00192 }
00193
00194
00195
00196 inline vector<double> logspace(double start, double end, size_t nbins) {
00197 assert(end >= start);
00198 assert(start > 0);
00199 assert(nbins > 0);
00200 const double logstart = std::log(start);
00201 const double logend = std::log(end);
00202 const vector<double> logvals = linspace(logstart, logend, nbins);
00203 vector<double> rtn;
00204 foreach (double logval, logvals) {
00205 rtn.push_back(std::exp(logval));
00206 }
00207 assert(rtn.size() == nbins+1);
00208 return rtn;
00209 }
00210
00211
00212
00213
00214 template <typename NUM>
00215 inline int index_between(const NUM& val, const vector<NUM>& binedges) {
00216 if (!inRange(val, binedges.front(), binedges.back())) return -1;
00217 int index = -1;
00218 for (size_t i = 1; i < binedges.size(); ++i) {
00219 if (val < binedges[i]) {
00220 index = i-1;
00221 break;
00222 }
00223 }
00224 assert(inRange(index, -1, binedges.size()-1));
00225 return index;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235 inline double mean(const vector<int>& sample) {
00236 double mean = 0.0;
00237 for (size_t i=0; i<sample.size(); ++i) {
00238 mean += sample[i];
00239 }
00240 return mean/sample.size();
00241 }
00242
00243
00244
00245 inline double covariance(const vector<int>& sample1, const vector<int>& sample2) {
00246 const double mean1 = mean(sample1);
00247 const double mean2 = mean(sample2);
00248 const int N = sample1.size();
00249 double cov = 0.0;
00250 for (int i = 0; i < N; i++) {
00251 const double cov_i = (sample1[i] - mean1)*(sample2[i] - mean2);
00252 cov += cov_i;
00253 }
00254 if (N > 1) return cov/(N-1);
00255 else return 0.0;
00256 }
00257
00258
00259
00260 inline double correlation(const vector<int>& sample1, const vector<int>& sample2) {
00261 const double cov = covariance(sample1, sample2);
00262 const double var1 = covariance(sample1, sample1);
00263 const double var2 = covariance(sample2, sample2);
00264 const double correlation = cov/sqrt(var1*var2);
00265 const double corr_strength = correlation*sqrt(var2/var1);
00266 return corr_strength;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 inline double _mapAngleM2PITo2Pi(double angle) {
00278 double rtn = fmod(angle, TWOPI);
00279 if (isZero(rtn)) return 0;
00280 assert(rtn >= -TWOPI && rtn <= TWOPI);
00281 return rtn;
00282 }
00283
00284
00285 inline double mapAngleMPiToPi(double angle) {
00286 double rtn = _mapAngleM2PITo2Pi(angle);
00287 if (isZero(rtn)) return 0;
00288 rtn = (rtn > PI ? rtn-TWOPI :
00289 rtn <= -PI ? rtn+TWOPI : rtn);
00290 assert(rtn > -PI && rtn <= PI);
00291 return rtn;
00292 }
00293
00294
00295 inline double mapAngle0To2Pi(double angle) {
00296 double rtn = _mapAngleM2PITo2Pi(angle);
00297 if (isZero(rtn)) return 0;
00298 if (rtn < 0) rtn += TWOPI;
00299 if (rtn == TWOPI) rtn = 0;
00300 assert(rtn >= 0 && rtn < TWOPI);
00301 return rtn;
00302 }
00303
00304
00305 inline double mapAngle0ToPi(double angle) {
00306 double rtn = fabs(mapAngleMPiToPi(angle));
00307 if (isZero(rtn)) return 0;
00308 assert(rtn > 0 && rtn <= PI);
00309 return rtn;
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 inline double deltaPhi(double phi1, double phi2) {
00321 return mapAngle0ToPi(phi1 - phi2);
00322 }
00323
00324
00325
00326 inline double deltaR(double rap1, double phi1, double rap2, double phi2) {
00327 const double dphi = deltaPhi(phi1, phi2);
00328 return sqrt( sqr(rap1-rap2) + sqr(dphi) );
00329 }
00330
00331
00332 inline double rapidity(double E, double pz) {
00333 if (isZero(E - pz)) {
00334 throw std::runtime_error("Divergent positive rapidity");
00335 return MAXDOUBLE;
00336 }
00337 if (isZero(E + pz)) {
00338 throw std::runtime_error("Divergent negative rapidity");
00339 return -MAXDOUBLE;
00340 }
00341 return 0.5*log((E+pz)/(E-pz));
00342 }
00343
00344
00345
00346
00347 }
00348
00349
00350 #endif