00001
00002 #ifndef RIVET_MathUtils_HH
00003 #define RIVET_MathUtils_HH
00004
00005 #include "Rivet/Math/MathHeader.hh"
00006 #include <cassert>
00007
00008 namespace Rivet {
00009
00010
00011
00012
00013
00014
00015
00016 inline bool isZero(double val, double tolerance=1E-8) {
00017 return (fabs(val) < tolerance);
00018 }
00019
00020
00021
00022
00023
00024 inline bool isZero(long val, double UNUSED(tolerance)=1E-8) {
00025 return val == 0;
00026 }
00027
00028
00029 inline int sign(double val) {
00030 if (isZero(val)) return ZERO;
00031 const int valsign = (val > 0) ? PLUS : MINUS;
00032 return valsign;
00033 }
00034
00035
00036 inline int sign(int val) {
00037 if (val == 0) return ZERO;
00038 return (val > 0) ? PLUS : MINUS;
00039 }
00040
00041
00042 inline int sign(long val) {
00043 if (val == 0) return ZERO;
00044 return (val > 0) ? PLUS : MINUS;
00045 }
00046
00047
00048
00049 inline bool fuzzyEquals(double a, double b, double tolerance=1E-5) {
00050 const double absavg = fabs(a + b)/2.0;
00051 const double absdiff = fabs(a - b);
00052 const bool rtn = (absavg == 0.0 && absdiff == 0.0) || absdiff < tolerance*absavg;
00053 return rtn;
00054 }
00055
00056
00057
00058
00059
00060
00061
00062 inline bool fuzzyEquals(long a, long b, double UNUSED(tolerance)=1E-5) {
00063 return a == b;
00064 }
00065
00066
00067
00068
00069 enum RangeBoundary { OPEN=0, SOFT=0, CLOSED=1, HARD=1 };
00070
00071
00072
00073
00074 template<typename NUM>
00075 inline bool inRange(NUM value, NUM low, NUM high,
00076 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=OPEN) {
00077 if (lowbound == OPEN && highbound == OPEN) {
00078 return (value > low && value < high);
00079 } else if (lowbound == OPEN && highbound == CLOSED) {
00080 return (value > low && value <= high);
00081 } else if (lowbound == CLOSED && highbound == OPEN) {
00082 return (value >= low && value < high);
00083 } else {
00084 return (value >= low && value <= high);
00085 }
00086 }
00087
00088
00089
00090
00091
00092 inline bool inRange(int value, int low, int high,
00093 RangeBoundary lowbound=CLOSED, RangeBoundary highbound=CLOSED) {
00094 if (lowbound == OPEN && highbound == OPEN) {
00095 return (value > low && value < high);
00096 } else if (lowbound == OPEN && highbound == CLOSED) {
00097 return (value > low && value <= high);
00098 } else if (lowbound == CLOSED && highbound == OPEN) {
00099 return (value >= low && value < high);
00100 } else {
00101 return (value >= low && value <= high);
00102 }
00103 }
00104
00105
00106
00107 template <typename Num>
00108 inline Num sqr(Num a) {
00109 return a*a;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 inline double mean(const vector<int>& sample) {
00121 double mean = 0.0;
00122 for (size_t i=0; i<sample.size(); ++i) {
00123 mean += sample[i];
00124 }
00125 return mean/sample.size();
00126 }
00127
00128
00129
00130 inline double covariance(const vector<int>& sample1, const vector<int>& sample2) {
00131 double mean1 = mean(sample1);
00132 double mean2 = mean(sample2);
00133 int N = sample1.size();
00134 double cov = 0.0;
00135 for (int i = 0; i < N; i++) {
00136 double cov_i = (sample1[i] - mean1)*(sample2[i] - mean2);
00137 cov += cov_i;
00138 }
00139 if (N > 1) return cov/(N-1);
00140 else return 0.0;
00141 }
00142
00143
00144
00145 inline double correlation(const vector<int>& sample1, const vector<int>& sample2) {
00146 const double cov = covariance(sample1, sample2);
00147 const double var1 = covariance(sample1, sample1);
00148 const double var2 = covariance(sample2, sample2);
00149 const double correlation = cov/sqrt(var1*var2);
00150 const double corr_strength = correlation*sqrt(var2/var1);
00151 return corr_strength;
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 inline double _mapAngleM2PITo2Pi(double angle) {
00163 double rtn = fmod(angle, TWOPI);
00164 if (isZero(rtn)) return 0;
00165 assert(rtn >= -TWOPI && rtn <= TWOPI);
00166 return rtn;
00167 }
00168
00169
00170 inline double mapAngleMPiToPi(double angle) {
00171 double rtn = _mapAngleM2PITo2Pi(angle);
00172 if (isZero(rtn)) return 0;
00173 rtn = (rtn > PI ? rtn-TWOPI :
00174 rtn <= -PI ? rtn+TWOPI : rtn);
00175 assert(rtn > -PI && rtn <= PI);
00176 return rtn;
00177 }
00178
00179
00180 inline double mapAngle0To2Pi(double angle) {
00181 double rtn = _mapAngleM2PITo2Pi(angle);
00182 if (isZero(rtn)) return 0;
00183 if (rtn < 0) rtn += TWOPI;
00184 if (rtn == TWOPI) rtn = 0;
00185 assert(rtn >= 0 && rtn < TWOPI);
00186 return rtn;
00187 }
00188
00189
00190 inline double mapAngle0ToPi(double angle) {
00191 double rtn = fabs(mapAngleMPiToPi(angle));
00192 if (isZero(rtn)) return 0;
00193 assert(rtn > 0 && rtn <= PI);
00194 return rtn;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 inline double deltaPhi(double phi1, double phi2) {
00206 return mapAngle0ToPi(phi1 - phi2);
00207 }
00208
00209
00210
00211 inline double deltaR(double y1, double phi1, double y2, double phi2) {
00212 const double dphi = deltaPhi(phi1, phi2);
00213 return sqrt( sqr(y1-y2) + sqr(dphi) );
00214 }
00215
00216
00217 inline double rapidity(double E, double pz) {
00218 if (isZero(E - pz)) {
00219 throw std::runtime_error("Divergent positive rapidity");
00220 return MAXDOUBLE;
00221 }
00222 if (isZero(E + pz)) {
00223 throw std::runtime_error("Divergent negative rapidity");
00224 return -MAXDOUBLE;
00225 }
00226 return 0.5*log((E+pz)/(E-pz));
00227 }
00228
00229
00230 }
00231
00232
00233
00234 #endif