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
00017
00018
00019 double BCMath::LogGaus(double x, double mean, double sigma, bool norm)
00020 {
00021
00022 if(sigma==0.)
00023 return 0;
00024
00025
00026 if(sigma<0.)
00027 sigma *= -1.;
00028
00029 double arg = (x-mean)/sigma;
00030 double result = -.5 * arg * arg;
00031
00032
00033 if(!norm)
00034 return result;
00035
00036
00037
00038 return result - log( sqrt( 2.* M_PI ) * sigma );
00039 }
00040
00041
00042
00043 double BCMath::LogPoisson(double x, double par)
00044 {
00045 if (par > 899)
00046 return BCMath::LogGaus(x,par,sqrt(par),true);
00047
00048 if (x<0)
00049 return 0;
00050
00051 if (x == 0.)
00052 return -par;
00053
00054 return x*log(par)-par-BCMath::ApproxLogFact(x);
00055 }
00056
00057
00058
00059 double BCMath::ApproxBinomial(int n, int k, double p)
00060 {
00061 return exp( BCMath::LogApproxBinomial(n, k, p) );
00062 }
00063
00064
00065
00066 double BCMath::LogApproxBinomial(int n, int k, double p)
00067 {
00068
00069 if (p == 0)
00070 return -1e99;
00071
00072 else if (p == 1)
00073 return 0;
00074
00075
00076 if(n<k)
00077 {
00078 int a=n;
00079 n=k;
00080 k=a;
00081 }
00082
00083 return BCMath::LogBinomFactor(n,k) + (double)k*log(p) + (double)(n-k)*log(1.-p);
00084 }
00085
00086
00087
00088 double BCMath::LogBinomFactor(int n, int k)
00089 {
00090
00091 if(n<k)
00092 {
00093 int a=n;
00094 n=k;
00095 k=a;
00096 }
00097
00098 if(n==k || k==0) return 0.;
00099 if(k==1 || k==n-1) return log((double)n);
00100
00101
00102 if(n<BCMATH_NFACT_ALIMIT || (n-k)<5) return BCMath::LogNoverK(n,k);
00103
00104
00105 return BCMath::ApproxLogFact((double)n) - BCMath::ApproxLogFact((double)k) - BCMath::ApproxLogFact((double)(n-k));
00106 }
00107
00108
00109
00110 double BCMath::ApproxLogFact(double x)
00111 {
00112 if(x>BCMATH_NFACT_ALIMIT)
00113 return x*log(x) - x + log(x*(1.+4.*x*(1.+2.*x)))/6. + log(M_PI)/2.;
00114
00115 else
00116 return BCMath::LogFact((int)x);
00117 }
00118
00119
00120 double BCMath::LogFact(int n)
00121 {
00122 double ln = 0.;
00123
00124 for(int i=1;i<=n;i++)
00125 ln += log((double)i);
00126
00127 return ln;
00128 }
00129
00130
00131
00132 double BCMath::LogNoverK(int n, int k)
00133 {
00134
00135 if(n<k)
00136 {
00137 int a = n;
00138 n = k;
00139 k = a;
00140 }
00141
00142 if(n==k || k==0) return 0.;
00143 if(k==1 || k==n-1) return log((double)n);
00144
00145 int lmax = BCMath::Max(k,n-k);
00146 int lmin = BCMath::Min(k,n-k);
00147
00148 double ln = 0.;
00149
00150 for(int i=n;i>lmax;i--)
00151 ln += log((double)i);
00152 ln -= BCMath::LogFact(lmin);
00153
00154 return ln;
00155 }
00156
00157
00158
00159 int BCMath::Nint(double x)
00160 {
00161
00162 int i;
00163
00164 if (x >= 0)
00165 {
00166 i = (int)(x + .5);
00167
00168 if (x + .5 == (double)i && i & 1)
00169 i--;
00170 }
00171
00172 else
00173 {
00174 i = int(x - 0.5);
00175
00176 if (x - 0.5 == double(i) && i & 1)
00177 i++;
00178 }
00179
00180 return i;
00181 }
00182
00183
00184
00185 double BCMath::rms(int n, const double *a)
00186 {
00187 if (n <= 0 || !a)
00188 return 0;
00189
00190 double sum = 0., sum2 = 0.;
00191
00192 for (int i = 0; i < n; i++)
00193 {
00194 sum += a[i];
00195 sum2 += a[i] * a[i];
00196 }
00197
00198 double n1 = 1./(double)n;
00199 double mean = sum * n1;
00200
00201 return sqrt(fabs(sum2 * n1 - mean * mean));
00202 }
00203
00204
00205
00206 double BCMath::LogBreitWignerNonRel(double x, double mean, double Gamma, bool norm)
00207 {
00208 double bw = log(Gamma) - log( (x - mean) * (x - mean) + Gamma * Gamma / 4.0);
00209
00210 if (norm)
00211 bw -= log(2. * M_PI);
00212
00213 return bw;
00214 }
00215
00216
00217
00218 double BCMath::LogBreitWignerRel(double x, double mean, double Gamma)
00219 {
00220 return -log( (x*x - mean*mean) * (x*x - mean*mean) + mean*mean*Gamma*Gamma );
00221 }
00222
00223
00224
00225 double BCMath::LogChi2(double x, int n)
00226 {
00227 if (x<0) {
00228 BCLog::OutWarning("BCMath::LogChi2 : parameter cannot be negative!");
00229 return -1e99;
00230 }
00231
00232 if (x==0 && n==1) {
00233 BCLog::OutWarning("BCMath::LogChi2 : returned value is infinity!");
00234 return 1e99;
00235 }
00236
00237 double nOver2 = ((double) n)/2.;
00238
00239 return (nOver2-1.)*log(x) - x/2. - nOver2*log(2) - log(TMath::Gamma(nOver2));
00240 }
00241
00242
00243
00244 double BCMath::LogVoigtian(double x, double sigma, double gamma)
00245 {
00246 if (sigma<=0 || gamma<=0) {
00247 BCLog::OutWarning("BCMath::LogVoigtian : widths are negative or zero!");
00248 return -1e99;
00249 }
00250
00251 return log(TMath::Voigt(x,sigma,gamma));
00252 }
00253
00254
00255