00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "RooFit.h"
00024
00025 #include "RooMath.h"
00026 #include "RooMath.h"
00027 #include "TMath.h"
00028 #include <math.h>
00029 #include "Riostream.h"
00030 #include "RooMsgService.h"
00031 #include "RooSentinel.h"
00032 #include "TSystem.h"
00033
00034 ClassImp(RooMath)
00035 ;
00036
00037
00038 RooComplex RooMath::FastComplexErrFunc(const RooComplex& z)
00039 {
00040 return ITPComplexErrFunc(z,z.im()>0?3:4) ;
00041 }
00042
00043 Double_t RooMath::FastComplexErrFuncRe(const RooComplex& z)
00044 {
00045 return ITPComplexErrFuncRe(z,z.im()>0?3:4) ;
00046 }
00047
00048 Double_t RooMath::FastComplexErrFuncIm(const RooComplex& z)
00049 {
00050 return ITPComplexErrFuncIm(z,z.im()>0?3:4) ;
00051 }
00052
00053 void RooMath::cacheCERF(Bool_t flag)
00054 {
00055 _cacheTable = flag ;
00056 }
00057
00058
00059 RooComplex RooMath::ComplexErrFunc(Double_t re, Double_t im) {
00060
00061 return ComplexErrFunc(RooComplex(re,im));
00062 }
00063
00064 RooComplex RooMath::ComplexErrFunc(const RooComplex& Z) {
00065
00066
00067
00068
00069
00070 RooComplex ZH,S,T,V;
00071 static RooComplex R[38];
00072
00073 static const Double_t Z1= 1, HF= Z1/2, Z10= 10;
00074 static const Double_t C1= 74/Z10, C2= 83/Z10, C3= Z10/32, C4 = 16/Z10;
00075 static const Double_t C = 1.12837916709551257, P = pow(2*C4,33);
00076 static const RooComplex zero(0);
00077
00078 Double_t X(Z.re()),Y(Z.im()), XA(fabs(X)), YA(fabs(Y));
00079 int N;
00080 if((YA < C1) && (XA < C2)) {
00081 ZH= RooComplex(YA+C4,XA);
00082 R[37]=zero;
00083 N= 36;
00084 while(N > 0) {
00085 T=ZH+R[N+1].conj()*N;
00086 R[N--]=(T*HF)/T.abs2();
00087 }
00088 Double_t XL=P;
00089 S=zero;
00090 N= 33;
00091 while(N > 0) {
00092 XL=C3*XL;
00093 S=R[N--]*(S+XL);
00094 }
00095 V=S*C;
00096 }
00097 else {
00098 ZH=RooComplex(YA,XA);
00099 R[1]=zero;
00100 N= 9;
00101 while(N > 0) {
00102 T=ZH+R[1].conj()*N;
00103 R[1]=(T*HF)/T.abs2();
00104 N--;
00105 }
00106 V=R[1]*C;
00107 }
00108 if(YA==0) V=RooComplex(exp(-(XA*XA)),V.im());
00109
00110 if(Y < 0) {
00111 RooComplex tmp(XA,YA);
00112 tmp= -tmp*tmp;
00113 V=tmp.exp()*2-V;
00114 if(X > 0) V= V.conj();
00115 }
00116 else {
00117 if(X < 0) V= V.conj();
00118 }
00119 return V;
00120 }
00121
00122
00123
00124 void RooMath::initFastCERF(Int_t reBins, Double_t reMin, Double_t reMax, Int_t imBins, Double_t imMin, Double_t imMax)
00125 {
00126
00127
00128
00129
00130 _reBins = reBins ;
00131 _imBins = imBins ;
00132 _reMin = reMin ;
00133 _reMax = reMax ;
00134 _reRange = _reMax-_reMin ;
00135 _reStep = _reRange/_reBins ;
00136
00137 _imMin = imMin ;
00138 _imMax = imMax ;
00139 _imRange = _imMax-_imMin ;
00140 _imStep = _imRange/_imBins ;
00141
00142 oocxcoutD((TObject*)0,Eval) << endl
00143 << "RooMath::initFastCERF: Allocating Complex Error Function lookup table" << endl
00144 << " Re: " << _reBins << " bins in range (" << _reMin << "," << _reMax << ")" << endl
00145 << " Im: " << _imBins << " bins in range (" << _imMin << "," << _imMax << ")" << endl
00146 << " Allocation size : " << _reBins*_imBins * 2 * sizeof(Double_t) / 1024 << " kB" << endl ;
00147
00148
00149
00150 RooSentinel::activate() ;
00151 Int_t imIdx,reIdx ;
00152 _reCerfArray = new pDouble_t[_imBins] ;
00153 _imCerfArray = new pDouble_t[_imBins] ;
00154 for (imIdx=0 ; imIdx<_imBins ; imIdx++) {
00155 _reCerfArray[imIdx] = new Double_t[_reBins] ;
00156 _imCerfArray[imIdx] = new Double_t[_reBins] ;
00157 }
00158
00159 Bool_t cacheLoaded(kFALSE) ;
00160 if (!_cacheTable || !(cacheLoaded=loadCache())) {
00161
00162 oocxcoutD((TObject*)0,Eval) << endl
00163 << " Filling table: |..................................................|\r"
00164 << " Filling table: |" ;
00165
00166
00167 for (imIdx=0 ; imIdx<_imBins ; imIdx++) {
00168 if (imIdx % (_imBins/50) ==0) {
00169 ooccxcoutD((TObject*)0,Eval) << ">" ; cout.flush() ;
00170 }
00171 for (reIdx=0 ; reIdx<_reBins ; reIdx++) {
00172 RooComplex val=ComplexErrFunc(_reMin+reIdx*_reStep,_imMin+imIdx*_imStep) ;
00173 _reCerfArray[imIdx][reIdx] = val.re();
00174 _imCerfArray[imIdx][reIdx] = val.im() ;
00175 }
00176 }
00177 ooccoutI((TObject*)0,Eval) << endl ;
00178 }
00179
00180 if (_cacheTable && !cacheLoaded) storeCache() ;
00181 }
00182
00183
00184 void RooMath::cleanup()
00185 {
00186 if (_reCerfArray) {
00187 for (Int_t imIdx=0 ; imIdx<_imBins ; imIdx++) {
00188 delete[] _reCerfArray[imIdx] ;
00189 delete[] _imCerfArray[imIdx] ;
00190 }
00191 delete[] _reCerfArray ;
00192 delete[] _imCerfArray ;
00193 _reCerfArray = 0 ;
00194 _imCerfArray = 0 ;
00195 }
00196
00197 }
00198
00199
00200 RooComplex RooMath::ITPComplexErrFunc(const RooComplex& z, Int_t nOrder)
00201 {
00202
00203
00204
00205
00206
00207 if (!_reCerfArray) initFastCERF() ;
00208
00209
00210 Double_t imPrime = (z.im()-_imMin) / _imStep ;
00211 Double_t rePrime = (z.re()-_reMin) / _reStep ;
00212
00213
00214 Int_t imIdxLo = Int_t(imPrime - 1.0*nOrder/2 + 0.5) ;
00215 Int_t imIdxHi = imIdxLo+nOrder-1 ;
00216 Int_t reIdxLo = Int_t(rePrime - 1.0*nOrder/2 + 0.5) ;
00217 Int_t reIdxHi = reIdxLo+nOrder-1 ;
00218
00219
00220 if (imIdxLo<0 || imIdxHi>_imBins-1 || reIdxLo<0 || reIdxHi>_reBins-1) {
00221 return ComplexErrFunc(z) ;
00222 }
00223
00224
00225 Int_t imIdx ;
00226 Double_t imYR[10] ;
00227 Double_t imYI[10] ;
00228
00229
00230 for (imIdx=imIdxLo ; imIdx<=imIdxHi ; imIdx++) {
00231
00232 imYR[imIdx-imIdxLo] = interpolate(&_reCerfArray[imIdx][reIdxLo],nOrder,rePrime-reIdxLo) ;
00233 imYI[imIdx-imIdxLo] = interpolate(&_imCerfArray[imIdx][reIdxLo],nOrder,rePrime-reIdxLo) ;
00234 }
00235
00236 Double_t re = interpolate(imYR,nOrder,imPrime-imIdxLo) ;
00237 Double_t im = interpolate(imYI,nOrder,imPrime-imIdxLo) ;
00238 return RooComplex(re,im) ;
00239 }
00240
00241
00242
00243
00244
00245 Double_t RooMath::ITPComplexErrFuncRe(const RooComplex& z, Int_t nOrder)
00246 {
00247
00248
00249
00250
00251
00252
00253
00254 if (!_reCerfArray) initFastCERF() ;
00255
00256
00257 Double_t imPrime = (z.im()-_imMin) / _imStep ;
00258 Double_t rePrime = (z.re()-_reMin) / _reStep ;
00259
00260
00261 Int_t imIdxLo = Int_t(imPrime - 1.0*nOrder/2 + 0.5) ;
00262 Int_t imIdxHi = imIdxLo+nOrder-1 ;
00263 Int_t reIdxLo = Int_t(rePrime - 1.0*nOrder/2 + 0.5) ;
00264 Int_t reIdxHi = reIdxLo+nOrder-1 ;
00265
00266
00267 if (imIdxLo<0 || imIdxHi>_imBins-1 || reIdxLo<0 || reIdxHi>_reBins-1) {
00268
00269 return ComplexErrFunc(z).re() ;
00270 }
00271
00272 if (nOrder==1) return _reCerfArray[imIdxLo][reIdxLo] ;
00273
00274 Int_t imIdx ;
00275 Double_t imYR[10] ;
00276
00277
00278 for (imIdx=imIdxLo ; imIdx<=imIdxHi ; imIdx++) {
00279
00280 imYR[imIdx-imIdxLo] = interpolate(&_reCerfArray[imIdx][reIdxLo],nOrder,rePrime-reIdxLo) ;
00281 }
00282
00283 return interpolate(imYR,nOrder,imPrime-imIdxLo) ;
00284 }
00285
00286
00287
00288 Double_t RooMath::ITPComplexErrFuncIm(const RooComplex& z, Int_t nOrder)
00289 {
00290
00291
00292
00293
00294
00295
00296
00297 if (!_reCerfArray) initFastCERF() ;
00298
00299
00300 Double_t imPrime = (z.im()-_imMin) / _imStep ;
00301 Double_t rePrime = (z.re()-_reMin) / _reStep ;
00302
00303
00304 Int_t imIdxLo = Int_t(imPrime - 1.0*nOrder/2 + 0.5) ;
00305 Int_t imIdxHi = imIdxLo+nOrder-1 ;
00306 Int_t reIdxLo = Int_t(rePrime - 1.0*nOrder/2 + 0.5) ;
00307 Int_t reIdxHi = reIdxLo+nOrder-1 ;
00308
00309
00310 if (imIdxLo<0 || imIdxHi>_imBins-1 || reIdxLo<0 || reIdxHi>_reBins-1) {
00311 return ComplexErrFunc(z).im() ;
00312 }
00313
00314
00315 Int_t imIdx ;
00316 Double_t imYI[10] ;
00317
00318
00319 for (imIdx=imIdxLo ; imIdx<=imIdxHi ; imIdx++) {
00320
00321 imYI[imIdx-imIdxLo] = interpolate(&_imCerfArray[imIdx][reIdxLo],nOrder,rePrime-reIdxLo) ;
00322 }
00323
00324 return interpolate(imYI,nOrder,imPrime-imIdxLo) ;
00325 }
00326
00327
00328
00329
00330
00331
00332 Double_t RooMath::interpolate(Double_t ya[], Int_t n, Double_t x)
00333 {
00334
00335
00336
00337 static Double_t itod[20] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,
00338 10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0} ;
00339 int i,m,ns=1 ;
00340 Double_t den,dif,dift,y,dy ;
00341 Double_t c[20], d[20] ;
00342
00343 dif = fabs(x) ;
00344 for(i=1 ; i<=n ; i++) {
00345 if ((dift=fabs(x-itod[i-1]))<dif) {
00346 ns=i ;
00347 dif=dift ;
00348 }
00349 c[i] = ya[i-1] ;
00350 d[i] = ya[i-1] ;
00351 }
00352
00353 y=ya[--ns] ;
00354 for(m=1 ; m<n; m++) {
00355 for(i=1 ; i<=n-m ; i++) {
00356 den=(c[i+1] - d[i])/itod[m] ;
00357 d[i]=(x-itod[i+m-1])*den ;
00358 c[i]=(x-itod[i-1])*den ;
00359 }
00360 dy = (2*ns)<(n-m) ? c[ns+1] : d[ns--] ;
00361 y += dy ;
00362 }
00363 return y ;
00364 }
00365
00366
00367
00368 Double_t RooMath::interpolate(Double_t xa[], Double_t ya[], Int_t n, Double_t x)
00369 {
00370
00371
00372
00373
00374
00375 int i,m,ns=1 ;
00376 Double_t den,dif,dift,ho,hp,w,y,dy ;
00377 Double_t c[20], d[20] ;
00378
00379 dif = fabs(x-xa[0]) ;
00380 for(i=1 ; i<=n ; i++) {
00381 if ((dift=fabs(x-xa[i-1]))<dif) {
00382 ns=i ;
00383 dif=dift ;
00384 }
00385 c[i] = ya[i-1] ;
00386 d[i] = ya[i-1] ;
00387 }
00388
00389 y=ya[--ns] ;
00390 for(m=1 ; m<n; m++) {
00391 for(i=1 ; i<=n-m ; i++) {
00392 ho=xa[i-1]-x ;
00393 hp=xa[i-1+m]-x ;
00394 w=c[i+1]-d[i] ;
00395 den=ho-hp ;
00396 if (den==0.) {
00397 oocoutE((TObject*)0,Eval) << "RooMath::interpolate ERROR: zero distance between points not allowed" << endl ;
00398 return 0 ;
00399 }
00400 den = w/den ;
00401 d[i]=hp*den ;
00402 c[i]=ho*den;
00403 }
00404 dy = (2*ns)<(n-m) ? c[ns+1] : d[ns--] ;
00405 y += dy ;
00406 }
00407 return y ;
00408 }
00409
00410
00411
00412 Bool_t RooMath::loadCache()
00413 {
00414
00415
00416 const char* fName = cacheFileName() ;
00417
00418 ifstream ifs(fName) ;
00419
00420
00421 if (ifs.fail()) return kFALSE ;
00422
00423 oocxcoutD((TObject*)0,Eval) << endl << " Filling table from cache file " << fName << endl ;
00424
00425
00426 Bool_t ok(kTRUE) ;
00427 Int_t i ;
00428 for (i=0 ; i<_imBins ; i++) {
00429 ifs.read((char*)_imCerfArray[i],_reBins*sizeof(Double_t)) ;
00430 if (ifs.fail()) ok=kFALSE ;
00431 ifs.read((char*)_reCerfArray[i],_reBins*sizeof(Double_t)) ;
00432 if (ifs.fail()) ok=kFALSE ;
00433 }
00434
00435
00436 if (!ok) {
00437 oocoutE((TObject*)0,Eval) << "RooMath::loadCERFCache: error reading file " << cacheFileName() << endl ;
00438 }
00439 return ok ;
00440 }
00441
00442
00443 void RooMath::storeCache()
00444 {
00445
00446
00447 ofstream ofs(cacheFileName()) ;
00448
00449 oocxcoutI((TObject*)0,Eval) << endl << " Writing table to cache file " << cacheFileName() << endl ;
00450 Int_t i ;
00451 for (i=0 ; i<_imBins ; i++) {
00452 ofs.write((char*)_imCerfArray[i],_reBins*sizeof(Double_t)) ;
00453 ofs.write((char*)_reCerfArray[i],_reBins*sizeof(Double_t)) ;
00454 }
00455 }
00456
00457
00458
00459 const char* RooMath::cacheFileName()
00460 {
00461
00462 static char fileName[1024] ;
00463 snprintf(fileName,1024,"/tmp/RooMath_CERFcache_R%04d_I%04d_%d.dat",_reBins,_imBins,gSystem->GetUid()) ;
00464 return fileName ;
00465 }
00466
00467
00468 Double_t RooMath::erf(Double_t x)
00469 {
00470 return TMath::Erf(x) ;
00471 }
00472
00473 Double_t RooMath::erfc(Double_t x)
00474 {
00475 return TMath::Erfc(x) ;
00476 }
00477
00478
00479
00480
00481 Int_t RooMath::_reBins(0) ;
00482 Int_t RooMath::_imBins(0) ;
00483 Double_t RooMath::_reMin(0) ;
00484 Double_t RooMath::_reMax(0) ;
00485 Double_t RooMath::_reRange(0) ;
00486 Double_t RooMath::_reStep(0) ;
00487 Double_t RooMath::_imMin(0) ;
00488 Double_t RooMath::_imMax(0) ;
00489 Double_t RooMath::_imRange(0) ;
00490 Double_t RooMath::_imStep(0) ;
00491 pDouble_t* RooMath::_reCerfArray = 0;
00492 pDouble_t* RooMath::_imCerfArray = 0;
00493 Bool_t RooMath::_cacheTable(kTRUE) ;
00494