49 TF3::TF3(
const char *name,
const char *formula, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Option_t * opt)
50 :TF2(name,formula,xmin,xmax,ymax,ymin,opt)
55 Int_t ndim = GetNdim();
57 if (ndim < 3) fNdim = 3;
58 if (ndim > 3 && xmin < xmax && ymin < ymax && zmin < zmax) {
59 Error(
"TF3",
"function: %s/%s has dimension %d instead of 3",name,formula,ndim);
77 TF3::TF3(
const char *name,Double_t (*fcn)(Double_t *, Double_t *), Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar,Int_t ndim)
78 :TF2(name,fcn,xmin,xmax,ymin,ymax,npar,ndim)
98 TF3::TF3(
const char *name,Double_t (*fcn)(
const Double_t *,
const Double_t *), Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar, Int_t ndim)
99 : TF2(name,fcn,xmin,xmax,ymin,ymax,npar,ndim),
115 TF3::TF3(
const char *name, ROOT::Math::ParamFunctor f, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax, Int_t npar, Int_t ndim)
116 : TF2(name, f, xmin, xmax, ymin, ymax, npar, ndim),
126 TF3& TF3::operator=(
const TF3 &rhs)
144 TF3::TF3(
const TF3 &f3) : TF2()
146 ((TF3&)f3).Copy(*
this);
152 void TF3::Copy(TObject &obj)
const
155 ((TF3&)obj).fZmin = fZmin;
156 ((TF3&)obj).fZmax = fZmax;
157 ((TF3&)obj).fNpz = fNpz;
167 Int_t TF3::DistancetoPrimitive(Int_t px, Int_t py)
169 return TF1::DistancetoPrimitive(px, py);
176 void TF3::Draw(Option_t *option)
178 TString opt = option;
180 if (gPad && !opt.Contains(
"same")) gPad->Clear();
191 void TF3::ExecuteEvent(Int_t event, Int_t px, Int_t py)
193 TF1::ExecuteEvent(event, px, py);
212 Double_t TF3::FindMinMax(Double_t *x, Bool_t findmax)
const
217 Double_t rsign = (findmax) ? -1. : 1.;
218 TF3 &
function =
const_cast<TF3&
>(*this);
219 Double_t xxmin = 0, yymin = 0, zzmin = 0, ttmin = 0;
220 if (x == NULL || ( (x!= NULL) && ( !TMath::Finite(x[0]) || !TMath::Finite(x[1]) || !TMath::Finite(x[2]) ) ) ){
221 Double_t dx = (fXmax - fXmin)/fNpx;
222 Double_t dy = (fYmax - fYmin)/fNpy;
223 Double_t dz = (fZmax - fZmin)/fNpz;
227 ttmin = rsign * TMath::Infinity();
228 for (Int_t i=0; i<fNpx; i++){
229 xx[0]=fXmin + (i+0.5)*dx;
230 for (Int_t j=0; j<fNpy; j++){
231 xx[1]=fYmin+(j+0.5)*dy;
232 for (Int_t k=0; k<fNpz; k++){
233 xx[2] = fZmin+(k+0.5)*dz;
234 Double_t tt =
function(xx);
235 if (rsign*tt < rsign*ttmin) {xxmin = xx[0], yymin = xx[1]; zzmin = xx[2]; ttmin=tt;}
240 xxmin = TMath::Min(fXmax, xxmin);
241 yymin = TMath::Min(fYmax, yymin);
242 zzmin = TMath::Min(fZmax, zzmin);
248 zzmin =
function(xx);
254 double fmin = GetMinMaxNDim(xx,findmax);
255 if (rsign*fmin < rsign*zzmin) {
256 if (x) {x[0] = xx[0]; x[1] = xx[1]; x[2] = xx[2];}
260 if (x) { x[0] = xxmin; x[1] = yymin; x[2] = zzmin; }
280 Double_t TF3::GetMinimumXYZ(Double_t &x, Double_t &y, Double_t &z)
282 double xx[3] = { 0,0,0 };
283 xx[0] = TMath::QuietNaN();
284 double fmin = FindMinMax(xx,
false);
285 x = xx[0]; y = xx[1]; z = xx[2];
296 Double_t TF3::GetMaximumXYZ(Double_t &x, Double_t &y, Double_t &z)
298 double xx[3] = { 0,0,0 };
299 xx[0] = TMath::QuietNaN();
300 double fmax = FindMinMax(xx,
true);
301 x = xx[0]; y = xx[1]; z = xx[2];
324 void TF3::GetRandom3(Double_t &xrandom, Double_t &yrandom, Double_t &zrandom)
328 Double_t dx = (fXmax-fXmin)/fNpx;
329 Double_t dy = (fYmax-fYmin)/fNpy;
330 Double_t dz = (fZmax-fZmin)/fNpz;
331 Int_t ncells = fNpx*fNpy*fNpz;
333 Double_t *parameters = GetParameters();
334 InitArgs(xx,parameters);
335 if (fIntegral.empty() ) {
336 fIntegral.resize(ncells+1);
340 Int_t intNegative = 0;
342 for (k=0;k<fNpz;k++) {
343 xx[2] = fZmin+(k+0.5)*dz;
344 for (j=0;j<fNpy;j++) {
345 xx[1] = fYmin+(j+0.5)*dy;
346 for (i=0;i<fNpx;i++) {
347 xx[0] = fXmin+(i+0.5)*dx;
348 integ = EvalPar(xx,parameters);
349 if (integ < 0) {intNegative++; integ = -integ;}
350 fIntegral[cell+1] = fIntegral[cell] + integ;
355 if (intNegative > 0) {
356 Warning(
"GetRandom3",
"function:%s has %d negative values: abs assumed",GetName(),intNegative);
358 if (fIntegral[ncells] == 0) {
359 Error(
"GetRandom3",
"Integral of function is zero");
362 for (i=1;i<=ncells;i++) {
363 fIntegral[i] /= fIntegral[ncells];
370 cell = TMath::BinarySearch(ncells,fIntegral.data(),r);
371 k = cell/(fNpx*fNpy);
372 j = (cell -k*fNpx*fNpy)/fNpx;
373 i = cell -fNpx*(j +fNpy*k);
374 xrandom = fXmin +dx*i +dx*gRandom->Rndm();
375 yrandom = fYmin +dy*j +dy*gRandom->Rndm();
376 zrandom = fZmin +dz*k +dz*gRandom->Rndm();
382 void TF3::GetRange(Double_t &xmin, Double_t &ymin, Double_t &zmin, Double_t &xmax, Double_t &ymax, Double_t &zmax)
const
396 Double_t TF3::GetSave(
const Double_t *xx)
399 if (fSave.empty())
return 0;
400 Int_t np = fSave.size() - 9;
401 Double_t xmin = Double_t(fSave[np+0]);
402 Double_t xmax = Double_t(fSave[np+1]);
403 Double_t ymin = Double_t(fSave[np+2]);
404 Double_t ymax = Double_t(fSave[np+3]);
405 Double_t zmin = Double_t(fSave[np+4]);
406 Double_t zmax = Double_t(fSave[np+5]);
407 Int_t npx = Int_t(fSave[np+6]);
408 Int_t npy = Int_t(fSave[np+7]);
409 Int_t npz = Int_t(fSave[np+8]);
410 Double_t x = Double_t(xx[0]);
411 Double_t dx = (xmax-xmin)/npx;
412 if (x < xmin || x > xmax)
return 0;
413 if (dx <= 0)
return 0;
414 Double_t y = Double_t(xx[1]);
415 Double_t dy = (ymax-ymin)/npy;
416 if (y < ymin || y > ymax)
return 0;
417 if (dy <= 0)
return 0;
418 Double_t z = Double_t(xx[2]);
419 Double_t dz = (zmax-zmin)/npz;
420 if (z < zmin || z > zmax)
return 0;
421 if (dz <= 0)
return 0;
424 Int_t ibin = Int_t((x-xmin)/dx);
425 Int_t jbin = Int_t((y-ymin)/dy);
426 Int_t kbin = Int_t((z-zmin)/dz);
427 Double_t xlow = xmin + ibin*dx;
428 Double_t ylow = ymin + jbin*dy;
429 Double_t zlow = zmin + kbin*dz;
430 Double_t t = (x-xlow)/dx;
431 Double_t u = (y-ylow)/dy;
432 Double_t v = (z-zlow)/dz;
433 Int_t k1 = (ibin ) + (npx+1)*((jbin ) + (npy+1)*(kbin ));
434 Int_t k2 = (ibin+1) + (npx+1)*((jbin ) + (npy+1)*(kbin ));
435 Int_t k3 = (ibin+1) + (npx+1)*((jbin+1) + (npy+1)*(kbin ));
436 Int_t k4 = (ibin ) + (npx+1)*((jbin+1) + (npy+1)*(kbin ));
437 Int_t k5 = (ibin ) + (npx+1)*((jbin ) + (npy+1)*(kbin+1));
438 Int_t k6 = (ibin+1) + (npx+1)*((jbin ) + (npy+1)*(kbin+1));
439 Int_t k7 = (ibin+1) + (npx+1)*((jbin+1) + (npy+1)*(kbin+1));
440 Int_t k8 = (ibin ) + (npx+1)*((jbin+1) + (npy+1)*(kbin+1));
441 Double_t r = (1-t)*(1-u)*(1-v)*fSave[k1] + t*(1-u)*(1-v)*fSave[k2] + t*u*(1-v)*fSave[k3] + (1-t)*u*(1-v)*fSave[k4] +
442 (1-t)*(1-u)*v*fSave[k5] + t*(1-u)*v*fSave[k6] + t*u*v*fSave[k7] + (1-t)*u*v*fSave[k8];
450 Double_t TF3::Integral(Double_t ax, Double_t bx, Double_t ay, Double_t by, Double_t az, Double_t bz, Double_t epsrel)
461 Int_t maxpts = TMath::Min(100000, 20*fNpx*fNpy*fNpz);
463 Double_t result = IntegralMultiple(n,a,b,maxpts,epsrel,epsrel, relerr,nfnevl,ifail);
465 Warning(
"Integral",
"failed code=%d, maxpts=%d, epsrel=%g, nfnevl=%d, relerr=%g ",ifail,maxpts,epsrel,nfnevl,relerr);
473 Bool_t TF3::IsInside(
const Double_t *x)
const
475 if (x[0] < fXmin || x[0] > fXmax)
return kFALSE;
476 if (x[1] < fYmin || x[1] > fYmax)
return kFALSE;
477 if (x[2] < fZmin || x[2] > fZmax)
return kFALSE;
484 TH1* TF3::CreateHistogram()
486 TH1* h =
new TH3F(
"R__TF3",(
char*)GetTitle(),fNpx,fXmin,fXmax
496 void TF3::Paint(Option_t *option)
499 TString opt = option;
504 fHistogram =
new TH3F(
"R__TF3",(
char*)GetTitle(),fNpx,fXmin,fXmax
507 fHistogram->SetDirectory(0);
510 fHistogram->GetPainter(option)->ProcessMessage(
"SetF3",
this);
511 if (opt.Length() == 0 ) {
512 fHistogram->Paint(
"tf3");
515 fHistogram->Paint(opt.Data());
522 void TF3::SetClippingBoxOff()
525 fHistogram =
new TH3F(
"R__TF3",(
char*)GetTitle(),fNpx,fXmin,fXmax
528 fHistogram->SetDirectory(0);
530 fHistogram->GetPainter()->ProcessMessage(
"SetF3ClippingBoxOff",0);
536 void TF3::Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax)
538 if (!fSave.empty()) fSave.clear();
539 Int_t nsave = (fNpx+1)*(fNpy+1)*(fNpz+1);
540 Int_t fNsave = nsave+9;
543 fSave.resize(fNsave);
545 Double_t dx = (xmax-xmin)/fNpx;
546 Double_t dy = (ymax-ymin)/fNpy;
547 Double_t dz = (zmax-zmin)/fNpz;
549 dx = (fXmax-fXmin)/fNpx;
550 xmin = fXmin +0.5*dx;
551 xmax = fXmax -0.5*dx;
554 dy = (fYmax-fYmin)/fNpy;
555 ymin = fYmin +0.5*dy;
556 ymax = fYmax -0.5*dy;
559 dz = (fZmax-fZmin)/fNpz;
560 zmin = fZmin +0.5*dz;
561 zmax = fZmax -0.5*dz;
564 Double_t *pp = GetParameters();
566 for (k=0;k<=fNpz;k++) {
568 for (j=0;j<=fNpy;j++) {
570 for (i=0;i<=fNpx;i++) {
572 fSave[l] = EvalPar(xv,pp);
577 fSave[nsave+0] = xmin;
578 fSave[nsave+1] = xmax;
579 fSave[nsave+2] = ymin;
580 fSave[nsave+3] = ymax;
581 fSave[nsave+4] = zmin;
582 fSave[nsave+5] = zmax;
583 fSave[nsave+6] = fNpx;
584 fSave[nsave+7] = fNpy;
585 fSave[nsave+8] = fNpz;
591 void TF3::SavePrimitive(std::ostream &out, Option_t *option )
595 if (gROOT->ClassSaved(TF3::Class())) {
601 out<<GetName()<<
" = new TF3("<<quote<<GetName()<<quote<<
","<<quote<<GetTitle()<<quote<<
","<<fXmin<<
","<<fXmax<<
","<<fYmin<<
","<<fYmax<<
","<<fZmin<<
","<<fZmax<<
");"<<std::endl;
603 out<<GetName()<<
" = new TF3("<<quote<<GetName()<<quote<<
","<<GetTitle()<<
","<<fXmin<<
","<<fXmax<<
","<<fYmin<<
","<<fYmax<<
","<<fZmin<<
","<<fZmax<<
","<<GetNpar()<<
");"<<std::endl;
606 if (GetFillColor() != 0) {
607 if (GetFillColor() > 228) {
608 TColor::SaveColor(out, GetFillColor());
609 out<<
" "<<GetName()<<
"->SetFillColor(ci);" << std::endl;
611 out<<
" "<<GetName()<<
"->SetFillColor("<<GetFillColor()<<
");"<<std::endl;
613 if (GetLineColor() != 1) {
614 if (GetLineColor() > 228) {
615 TColor::SaveColor(out, GetLineColor());
616 out<<
" "<<GetName()<<
"->SetLineColor(ci);" << std::endl;
618 out<<
" "<<GetName()<<
"->SetLineColor("<<GetLineColor()<<
");"<<std::endl;
620 if (GetNpz() != 100) {
621 out<<
" "<<GetName()<<
"->SetNpz("<<GetNpz()<<
");"<<std::endl;
623 if (GetChisquare() != 0) {
624 out<<
" "<<GetName()<<
"->SetChisquare("<<GetChisquare()<<
");"<<std::endl;
626 Double_t parmin, parmax;
627 for (Int_t i=0;i<GetNpar();i++) {
628 out<<
" "<<GetName()<<
"->SetParameter("<<i<<
","<<GetParameter(i)<<
");"<<std::endl;
629 out<<
" "<<GetName()<<
"->SetParError("<<i<<
","<<GetParError(i)<<
");"<<std::endl;
630 GetParLimits(i,parmin,parmax);
631 out<<
" "<<GetName()<<
"->SetParLimits("<<i<<
","<<parmin<<
","<<parmax<<
");"<<std::endl;
633 out<<
" "<<GetName()<<
"->Draw("
634 <<quote<<option<<quote<<
");"<<std::endl;
642 void TF3::SetClippingBoxOn(Double_t xclip, Double_t yclip, Double_t zclip)
645 fHistogram =
new TH3F(
"R__TF3",(
char*)GetTitle(),fNpx,fXmin,fXmax
648 fHistogram->SetDirectory(0);
655 fHistogram->GetPainter()->ProcessMessage(
"SetF3ClippingBoxOn",&v);
666 void TF3::SetNpz(Int_t npz)
669 Warning(
"SetNpz",
"Number of points must be >=4 && <= 10000, fNpz set to 4");
671 }
else if(npz > 10000) {
672 Warning(
"SetNpz",
"Number of points must be >=4 && <= 10000, fNpz set to 10000");
683 void TF3::SetRange(Double_t xmin, Double_t ymin, Double_t zmin, Double_t xmax, Double_t ymax, Double_t zmax)
697 void TF3::Streamer(TBuffer &R__b)
699 if (R__b.IsReading()) {
701 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
703 R__b.ReadClassBuffer(TF3::Class(),
this, R__v, R__s, R__c);
709 if (fType != EFType::kFormula && fSave.empty() ) { saved = 1; Save(fXmin,fXmax,fYmin,fYmax,fZmin,fZmax);}
711 R__b.WriteClassBuffer(TF3::Class(),
this);
713 if (saved) { fSave.clear(); }
721 Double_t TF3::Moment3(Double_t nx, Double_t ax, Double_t bx, Double_t ny, Double_t ay, Double_t by, Double_t nz, Double_t az, Double_t bz, Double_t epsilon)
723 Double_t norm = Integral(ax,bx,ay,by,az,bz,epsilon);
725 Error(
"Moment3",
"Integral zero over range");
729 TF3 fnc(
"TF3_ExpValHelper",Form(
"%s*pow(x,%f)*pow(y,%f)*pow(z,%f)",GetName(),nx,ny,nz));
730 return fnc.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
737 Double_t TF3::CentralMoment3(Double_t nx, Double_t ax, Double_t bx, Double_t ny, Double_t ay, Double_t by, Double_t nz, Double_t az, Double_t bz, Double_t epsilon)
739 Double_t norm = Integral(ax,bx,ay,by,az,bz,epsilon);
741 Error(
"CentralMoment3",
"Integral zero over range");
749 TF3 fncx(
"TF3_ExpValHelperx",Form(
"%s*x",GetName()));
750 xbar = fncx.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
753 TF3 fncy(
"TF3_ExpValHelpery",Form(
"%s*y",GetName()));
754 ybar = fncy.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
757 TF3 fncz(
"TF3_ExpValHelperz",Form(
"%s*z",GetName()));
758 zbar = fncz.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;
760 TF3 fnc(
"TF3_ExpValHelper",Form(
"%s*pow(x-%f,%f)*pow(y-%f,%f)*pow(z-%f,%f)",GetName(),xbar,nx,ybar,ny,zbar,nz));
761 return fnc.Integral(ax,bx,ay,by,az,bz,epsilon)/norm;