00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "BAT/BCMath.h"
00011 #include "BAT/BCLog.h"
00012
00013 #include <math.h>
00014
00015 #include <TMath.h>
00016 #include <TF1.h>
00017
00018 #include <Math/PdfFuncMathCore.h>
00019
00020
00021
00022 double BCMath::LogGaus(double x, double mean, double sigma, bool norm)
00023 {
00024
00025 if(sigma==0.)
00026 return 0;
00027
00028
00029 if(sigma<0.)
00030 sigma *= -1.;
00031
00032 double arg = (x-mean)/sigma;
00033 double result = -.5 * arg * arg;
00034
00035
00036 if(!norm)
00037 return result;
00038
00039
00040
00041 return result - log( sqrt( 2.* M_PI ) * sigma );
00042 }
00043
00044
00045
00046 double BCMath::LogPoisson(double x, double par)
00047 {
00048 if (par > 899)
00049 return BCMath::LogGaus(x,par,sqrt(par),true);
00050
00051 if (x<0)
00052 return 0;
00053
00054 if (x == 0.)
00055 return -par;
00056
00057 return x*log(par)-par-BCMath::ApproxLogFact(x);
00058 }
00059
00060
00061
00062 double BCMath::ApproxBinomial(int n, int k, double p)
00063 {
00064 return exp( BCMath::LogApproxBinomial(n, k, p) );
00065 }
00066
00067
00068
00069 double BCMath::LogApproxBinomial(int n, int k, double p)
00070 {
00071
00072 if (p == 0)
00073 return -1e99;
00074
00075 else if (p == 1)
00076 return 0;
00077
00078
00079 if(n<k)
00080 {
00081 int a=n;
00082 n=k;
00083 k=a;
00084 }
00085
00086 return BCMath::LogBinomFactor(n,k) + (double)k*log(p) + (double)(n-k)*log(1.-p);
00087 }
00088
00089
00090
00091 double BCMath::LogBinomFactor(int n, int k)
00092 {
00093
00094 if(n<k)
00095 {
00096 int a=n;
00097 n=k;
00098 k=a;
00099 }
00100
00101 if(n==k || k==0) return 0.;
00102 if(k==1 || k==n-1) return log((double)n);
00103
00104
00105 if(n<BCMATH_NFACT_ALIMIT || (n-k)<5) return BCMath::LogNoverK(n,k);
00106
00107
00108 return BCMath::ApproxLogFact((double)n) - BCMath::ApproxLogFact((double)k) - BCMath::ApproxLogFact((double)(n-k));
00109 }
00110
00111
00112
00113 double BCMath::ApproxLogFact(double x)
00114 {
00115 if(x>BCMATH_NFACT_ALIMIT)
00116 return x*log(x) - x + log(x*(1.+4.*x*(1.+2.*x)))/6. + log(M_PI)/2.;
00117
00118 else
00119 return BCMath::LogFact((int)x);
00120 }
00121
00122
00123 double BCMath::LogFact(int n)
00124 {
00125 double ln = 0.;
00126
00127 for(int i=1;i<=n;i++)
00128 ln += log((double)i);
00129
00130 return ln;
00131 }
00132
00133
00134
00135 double BCMath::LogNoverK(int n, int k)
00136 {
00137
00138 if(n<k)
00139 {
00140 int a = n;
00141 n = k;
00142 k = a;
00143 }
00144
00145 if(n==k || k==0) return 0.;
00146 if(k==1 || k==n-1) return log((double)n);
00147
00148 int lmax = BCMath::Max(k,n-k);
00149 int lmin = BCMath::Min(k,n-k);
00150
00151 double ln = 0.;
00152
00153 for(int i=n;i>lmax;i--)
00154 ln += log((double)i);
00155 ln -= BCMath::LogFact(lmin);
00156
00157 return ln;
00158 }
00159
00160
00161
00162 int BCMath::Nint(double x)
00163 {
00164
00165 int i;
00166
00167 if (x >= 0)
00168 {
00169 i = (int)(x + .5);
00170
00171 if (x + .5 == (double)i && i & 1)
00172 i--;
00173 }
00174
00175 else
00176 {
00177 i = int(x - 0.5);
00178
00179 if (x - 0.5 == double(i) && i & 1)
00180 i++;
00181 }
00182
00183 return i;
00184 }
00185
00186
00187
00188 double BCMath::rms(int n, const double *a)
00189 {
00190 if (n <= 0 || !a)
00191 return 0;
00192
00193 double sum = 0., sum2 = 0.;
00194
00195 for (int i = 0; i < n; i++)
00196 {
00197 sum += a[i];
00198 sum2 += a[i] * a[i];
00199 }
00200
00201 double n1 = 1./(double)n;
00202 double mean = sum * n1;
00203
00204 return sqrt(fabs(sum2 * n1 - mean * mean));
00205 }
00206
00207
00208
00209 double BCMath::LogBreitWignerNonRel(double x, double mean, double Gamma, bool norm)
00210 {
00211 double bw = log(Gamma) - log( (x - mean) * (x - mean) + Gamma * Gamma / 4.0);
00212
00213 if (norm)
00214 bw -= log(2. * M_PI);
00215
00216 return bw;
00217 }
00218
00219
00220
00221 double BCMath::LogBreitWignerRel(double x, double mean, double Gamma)
00222 {
00223 return -log( (x*x - mean*mean) * (x*x - mean*mean) + mean*mean*Gamma*Gamma );
00224 }
00225
00226
00227
00228 double BCMath::LogChi2(double x, int n)
00229 {
00230 if (x<0) {
00231 BCLog::OutWarning("BCMath::LogChi2 : parameter cannot be negative!");
00232 return -1e99;
00233 }
00234
00235 if (x==0 && n==1) {
00236 BCLog::OutWarning("BCMath::LogChi2 : returned value is infinity!");
00237 return 1e99;
00238 }
00239
00240 double nOver2 = ((double) n)/2.;
00241
00242 return (nOver2-1.)*log(x) - x/2. - nOver2*log(2) - log(TMath::Gamma(nOver2));
00243 }
00244
00245
00246
00247 double BCMath::LogVoigtian(double x, double sigma, double gamma)
00248 {
00249 if (sigma<=0 || gamma<=0) {
00250 BCLog::OutWarning("BCMath::LogVoigtian : widths are negative or zero!");
00251 return -1e99;
00252 }
00253
00254 return log(TMath::Voigt(x,sigma,gamma));
00255 }
00256
00257
00258
00259
00260 double chi2(double *x, double *par) {
00261 return ROOT::Math::chisquared_pdf(x[0], par[0]);
00262 }
00263
00264 void BCMath::RandomChi2(std::vector<double> &randoms, int K){
00265
00266
00267 TF1 *f = new TF1("chi2", chi2, 0.0, 1000, 1);
00268 f->SetParameter(0, K);
00269 f->SetNpx(500);
00270
00271
00272 for (unsigned int i = 0; i < randoms.size(); i++)
00273 randoms.at(i) = f->GetRandom();
00274 delete f;
00275 }
00276
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299