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