00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "BAT/BCMath.h"
00011
00012 #include <math.h>
00013
00014 #include <TMath.h>
00015
00016
00017
00018 double BCMath::LogGaus(double x, double mean, double sigma, bool norm)
00019 {
00020
00021 if(sigma==0.)
00022 return 0;
00023
00024
00025 if(sigma<0.)
00026 sigma *= -1.;
00027
00028 double arg = (x-mean)/sigma;
00029 double result = -.5 * arg * arg;
00030
00031
00032 if(!norm)
00033 return result;
00034
00035
00036
00037 return result - log( sqrt( 2.* M_PI ) * sigma );
00038 }
00039
00040
00041
00042 double BCMath::LogPoisson(double x, double par)
00043 {
00044 if (par > 899)
00045 return BCMath::LogGaus(x,par,sqrt(par),true);
00046
00047 if (x<0)
00048 return 0;
00049
00050 if (x == 0.)
00051 return -par;
00052
00053 return x*log(par)-par-BCMath::ApproxLogFact(x);
00054 }
00055
00056
00057
00058 double BCMath::ApproxBinomial(int n, int k, double p)
00059 {
00060 return exp( BCMath::LogApproxBinomial(n, k, p) );
00061 }
00062
00063
00064
00065 double BCMath::LogApproxBinomial(int n, int k, double p)
00066 {
00067
00068 if (p == 0)
00069 return -1e99;
00070
00071 else if (p == 1)
00072 return 0;
00073
00074
00075 if(n<k)
00076 {
00077 int a=n;
00078 n=k;
00079 k=a;
00080 }
00081
00082 return BCMath::LogBinomFactor(n,k) + (double)k*log(p) + (double)(n-k)*log(1.-p);
00083 }
00084
00085
00086
00087 double BCMath::LogBinomFactor(int n, int k)
00088 {
00089
00090 if(n<k)
00091 {
00092 int a=n;
00093 n=k;
00094 k=a;
00095 }
00096
00097 if(n==k || k==0) return 0.;
00098 if(k==1 || k==n-1) return log((double)n);
00099
00100
00101 if(n<BCMATH_NFACT_ALIMIT || (n-k)<5) return BCMath::LogNoverK(n,k);
00102
00103
00104 return BCMath::ApproxLogFact((double)n) - BCMath::ApproxLogFact((double)k) - BCMath::ApproxLogFact((double)(n-k));
00105 }
00106
00107
00108
00109 double BCMath::ApproxLogFact(double x)
00110 {
00111 if(x>BCMATH_NFACT_ALIMIT)
00112 return x*log(x) - x + log(x*(1.+4.*x*(1.+2.*x)))/6. + log(M_PI)/2.;
00113
00114 else
00115 return BCMath::LogFact((int)x);
00116 }
00117
00118
00119 double BCMath::LogFact(int n)
00120 {
00121 double ln = 0.;
00122
00123 for(int i=1;i<=n;i++)
00124 ln += log((double)i);
00125
00126 return ln;
00127 }
00128
00129
00130
00131 double BCMath::LogNoverK(int n, int k)
00132 {
00133
00134 if(n<k)
00135 {
00136 int a = n;
00137 n = k;
00138 k = a;
00139 }
00140
00141 if(n==k || k==0) return 0.;
00142 if(k==1 || k==n-1) return log((double)n);
00143
00144 int lmax = BCMath::Max(k,n-k);
00145 int lmin = BCMath::Min(k,n-k);
00146
00147 double ln = 0.;
00148
00149 for(int i=n;i>lmax;i--)
00150 ln += log((double)i);
00151 ln -= BCMath::LogFact(lmin);
00152
00153 return ln;
00154 }
00155
00156
00157
00158 int BCMath::Nint(double x)
00159 {
00160
00161 int i;
00162
00163 if (x >= 0)
00164 {
00165 i = (int)(x + .5);
00166
00167 if (x + .5 == (double)i && i & 1)
00168 i--;
00169 }
00170
00171 else
00172 {
00173 i = int(x - 0.5);
00174
00175 if (x - 0.5 == double(i) && i & 1)
00176 i++;
00177 }
00178
00179 return i;
00180 }
00181
00182
00183
00184 double BCMath::rms(int n, const double *a)
00185 {
00186 if (n <= 0 || !a)
00187 return 0;
00188
00189 double sum = 0., sum2 = 0.;
00190
00191 for (int i = 0; i < n; i++)
00192 {
00193 sum += a[i];
00194 sum2 += a[i] * a[i];
00195 }
00196
00197 double n1 = 1./(double)n;
00198 double mean = sum * n1;
00199
00200 return sqrt(fabs(sum2 * n1 - mean * mean));
00201 }
00202
00203
00204
00205 double BCMath::LogBreitWignerNonRel(double x, double mean, double Gamma, bool norm)
00206 {
00207 double bw = log(Gamma) - log( (x - mean) * (x - mean) + Gamma * Gamma / 4.0);
00208
00209 if (norm)
00210 bw -= log(2. * M_PI);
00211
00212 return bw;
00213 }
00214
00215
00216
00217 double BCMath::LogBreitWignerRel(double x, double mean, double Gamma)
00218 {
00219 return -log( (x*x - mean*mean) * (x*x - mean*mean) + mean*mean*Gamma*Gamma );
00220 }
00221
00222
00223