BCMath.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008, Daniel Kollar, Kevin Kroeninger and Jing Liu
00003  * All rights reserved.
00004  *
00005  * For the licensing terms see doc/COPYING.
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    // if we have a delta function, return fixed value
00025    if(sigma==0.)
00026       return 0;
00027 
00028    // if sigma is negative use absolute value
00029    if(sigma<0.)
00030       sigma *= -1.;
00031 
00032    double arg = (x-mean)/sigma;
00033    double result = -.5 * arg * arg;
00034 
00035    // check if we should add the normalization constant
00036    if(!norm)
00037       return result;
00038 
00039    // subtract the log of the denominator of the normalization constant
00040    // and return
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    // check p
00072    if (p == 0)
00073       return -1e99;
00074 
00075    else if (p == 1)
00076       return 0;
00077 
00078    // switch parameters if n < k
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    // switch parameters if n < k
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    // if no approximation needed
00105    if(n<BCMATH_NFACT_ALIMIT || (n-k)<5) return BCMath::LogNoverK(n,k);
00106 
00107    // calculate final log(n over k) using approximations if necessary
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    // switch parameters if n < k
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    // round to integer
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 //wrapper with signature to construct a TF1
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    //fixed upper cutoff to 1000, might be too small
00267    TF1 *f = new TF1("chi2", chi2, 0.0, 1000, 1);
00268    f->SetParameter(0, K);
00269    f->SetNpx(500);
00270    //uses inverse-transform method
00271    //fortunately CDF only built once
00272    for (unsigned int i = 0; i < randoms.size(); i++)
00273       randoms.at(i) = f->GetRandom();
00274    delete f;
00275 }
00276 
00278 //double expDistribution(double *x, double *par) {
00279 // return ROOT::Math::exponential_pdf(x[0], par[0]);
00280 //}
00281 //
00282 //void BCMath::RandomExponential(std::vector<double> &randoms, double lambda, unsigned int seed){
00283 //
00284 // //fixed upper cutoff to 1000 such that CDF(t|lambda)=1-10-5
00285 // double cutoff = 5.0/lambda*log(10);
00286 // TF1 *f = new TF1("Exp", expDistribution, 0.0, cutoff, 1);
00287 // f->SetParameter(0, lambda);
00288 // f->SetNpx(500);
00289 //
00290 // //uses inverse-transform method
00291 // //fortunately CDF only built once
00292 // gRandom->SetSeed(seed);
00293 // for (unsigned int i = 0; i < randoms.size(); i++)
00294 //    randoms.at(i) = f->GetRandom();
00295 // delete f;
00296 //}
00297 
00298 
00299 

Generated on Thu Feb 11 11:29:30 2010 for BayesianAnalysisToolkit by  doxygen 1.5.1