54 std::atomic<Bool_t> TF1::fgAbsValue(kFALSE);
55 Bool_t TF1::fgRejectPoint = kFALSE;
56 std::atomic<Bool_t> TF1::fgAddToGlobList(kTRUE);
57 static Double_t gErrorTF1 = 0;
59 using TF1Updater_t = void (*)(Int_t nobjects, TObject **from, TObject **to);
60 bool R__SetClonesArrayTF1Updater(TF1Updater_t func);
64 struct TF1v5Convert :
public TF1 {
66 void Convert(ROOT::v5::TF1Data &from)
69 fNpar = from.GetNpar();
70 fNdim = from.GetNdim();
71 if (from.fType == 0) {
74 double xmin = from.fXmin;
75 double xmax = from.fXmax;
80 TF1 fnew(from.GetName(), from.GetExpFormula(), xmin, xmax);
82 fnew.SetRange(from.fXmin, from.fXmax);
86 if (from.GetParameters())
87 fFormula->SetParameters(from.GetParameters());
90 fParams =
new TF1Parameters(fNpar);
91 fName = from.GetName();
92 fTitle = from.GetTitle();
94 if (from.GetParameters())
95 fParams->SetParameters(from.GetParameters());
99 fType = (EFType)from.fType;
100 fNpfits = from.fNpfits;
102 fChisquare = from.fChisquare;
103 fMaximum = from.fMaximum;
104 fMinimum = from.fMinimum;
109 fParErrors = std::vector<Double_t>(from.fParErrors, from.fParErrors + fNpar);
111 fParMin = std::vector<Double_t>(from.fParMin, from.fParMin + fNpar);
113 fParMax = std::vector<Double_t>(from.fParMax, from.fParMax + fNpar);
114 if (from.fNsave > 0) {
116 fSave = std::vector<Double_t>(from.fSave, from.fSave + from.fNsave);
119 for (
int ibit = 0; ibit < 24; ++ibit)
120 if (from.TestBit(BIT(ibit)))
124 auto &fromLine =
static_cast<TAttLine &
>(from);
125 fromLine.Copy(*
this);
126 auto &fromFill =
static_cast<TAttFill &
>(from);
127 fromFill.Copy(*
this);
128 auto &fromMarker =
static_cast<TAttMarker &
>(from);
129 fromMarker.Copy(*
this);
134 static void R__v5TF1Updater(Int_t nobjects, TObject **from, TObject **to)
136 auto **fromv5 = (ROOT::v5::TF1Data **)from;
137 auto **target = (TF1v5Convert **)to;
139 for (
int i = 0; i < nobjects; ++i) {
140 if (fromv5[i] && target[i])
141 target[i]->Convert(*fromv5[i]);
145 int R__RegisterTF1UpdaterTrigger = R__SetClonesArrayTF1Updater(R__v5TF1Updater);
151 const TF1 *fFunction;
154 GFunc(
const TF1 *
function ,
double y): fFunction(function), fY0(y) {}
155 double operator()(
double x)
const
157 return fFunction->Eval(x) - fY0;
163 const TF1 *fFunction;
165 GInverseFunc(
const TF1 *
function): fFunction(function) {}
167 double operator()(
double x)
const
169 return - fFunction->Eval(x);
173 class GInverseFuncNdim {
176 GInverseFuncNdim(TF1 *
function): fFunction(function) {}
178 double operator()(
const double *x)
const
180 return - fFunction->EvalPar(x, (Double_t *)0);
187 class TF1_EvalWrapper :
public ROOT::Math::IGenFunction {
189 TF1_EvalWrapper(TF1 *f,
const Double_t *par,
bool useAbsVal, Double_t n = 1, Double_t x0 = 0) :
191 fPar(((par) ? par : f->GetParameters())),
196 fFunc->InitArgs(fX, fPar);
197 if (par) fFunc->SetParameters(par);
200 ROOT::Math::IGenFunction *Clone()
const
203 TF1_EvalWrapper *f =
new TF1_EvalWrapper(*
this);
204 f->fFunc->InitArgs(f->fX, f->fPar);
208 Double_t DoEval(Double_t x)
const
212 Double_t fval = fFunc->EvalPar(fX, 0);
213 if (fAbsVal && fval < 0)
return -fval;
217 Double_t EvalFirstMom(Double_t x)
220 return fX[0] * TMath::Abs(fFunc->EvalPar(fX, 0));
223 Double_t EvalNMom(Double_t x)
const
226 return TMath::Power(fX[0] - fX0, fN) * TMath::Abs(fFunc->EvalPar(fX, 0));
230 mutable Double_t fX[1];
485 TF1 *TF1::fgCurrent = 0;
492 TNamed(), TAttLine(), TAttFill(), TAttMarker(),
493 fXmin(0), fXmax(0), fNpar(0), fNdim(0), fType(EFType::kFormula)
513 TF1::TF1(
const char *name,
const char *formula, Double_t xmin, Double_t xmax, EAddToList addToGlobList,
bool vectorize) :
514 TNamed(name, formula), TAttLine(), TAttFill(), TAttMarker(), fType(EFType::kFormula)
526 if (TString(formula, 5) ==
"CONV(" && formula[strlen(formula) - 1] ==
')') {
528 int delimPosition = -1;
530 for (
unsigned int i = 5; i < strlen(formula) - 1; i++) {
531 if (formula[i] ==
'(')
533 else if (formula[i] ==
')')
535 else if (formula[i] ==
',' && parenCount == 0) {
536 if (delimPosition == -1)
539 Error(
"TF1",
"CONV takes 2 arguments. Too many arguments found in : %s", formula);
542 if (delimPosition == -1)
543 Error(
"TF1",
"CONV takes 2 arguments. Only one argument found in : %s", formula);
546 TString formula1 = TString(TString(formula)(5, delimPosition - 5));
547 TString formula2 = TString(TString(formula)(delimPosition + 1, strlen(formula) - 1 - (delimPosition + 1)));
549 formula1.ReplaceAll(
' ',
"");
550 formula2.ReplaceAll(
' ',
"");
552 TF1 *function1 = (TF1 *)(gROOT->GetListOfFunctions()->FindObject(formula1));
553 if (function1 ==
nullptr)
554 function1 =
new TF1((
const char *)formula1, (
const char *)formula1, xmin, xmax);
555 TF1 *function2 = (TF1 *)(gROOT->GetListOfFunctions()->FindObject(formula2));
556 if (function2 ==
nullptr)
557 function2 =
new TF1((
const char *)formula2, (
const char *)formula2, xmin, xmax);
561 TF1Convolution *conv =
new TF1Convolution(function1, function2);
564 fNpar = conv->GetNpar();
567 fType = EFType::kCompositionFcn;
568 fComposition = std::unique_ptr<TF1AbsComposition>(conv);
570 fParams =
new TF1Parameters(fNpar);
572 for (
int i = 0; i < fNpar; i++)
573 this->SetParName(i, conv->GetParName(i));
575 int f1Npar = function1->GetNpar();
576 int f2Npar = function2->GetNpar();
578 for (
int i = 0; i < f1Npar; i++)
579 this->SetParameter(i, function1->GetParameter(i));
582 if (conv->GetNpar() == f1Npar + f2Npar - 1) {
583 int cst1 = function1->GetParNumber(
"Constant");
584 int cst2 = function2->GetParNumber(
"Constant");
585 this->SetParameter(cst1, function1->GetParameter(cst1) * function2->GetParameter(cst2));
587 for (
int i = 0; i < f2Npar; i++)
589 this->SetParameter(f1Npar + i, function2->GetParameter(i));
591 this->SetParameter(f1Npar + i - 1, function2->GetParameter(i));
594 for (
int i = 0; i < f2Npar; i++)
595 this->SetParameter(i + f1Npar, function2->GetParameter(i));
599 }
else if (TString(formula, 5) ==
"NSUM(" && formula[strlen(formula) - 1] ==
')') {
601 char delimiter =
',';
603 TString formDense = TString(formula)(5,strlen(formula)-5-1);
604 formDense.ReplaceAll(
' ',
"");
607 InitStandardFunctions();
612 TObjArray *newFuncs =
new TObjArray();
613 newFuncs->SetOwner(kTRUE);
614 TObjArray *coeffNames =
new TObjArray();
615 coeffNames->SetOwner(kTRUE);
616 TString fullFormula(
"");
617 for (
int i = 0; i < formDense.Length(); ++i) {
618 if (formDense[i] ==
'(')
620 else if (formDense[i] ==
')')
622 else if (formDense[i] == delimiter && parenCount == 0) {
624 DefineNSUMTerm(newFuncs, coeffNames, fullFormula, formDense, termStart, i, xmin, xmax);
628 DefineNSUMTerm(newFuncs, coeffNames, fullFormula, formDense, termStart, formDense.Length(), xmin, xmax);
630 TF1NormSum *normSum =
new TF1NormSum(fullFormula, xmin, xmax);
632 if (xmin == 0 && xmax == 1.) Info(
"TF1",
"Created TF1NormSum object using the default [0,1] range");
634 fNpar = normSum->GetNpar();
637 fType = EFType::kCompositionFcn;
638 fComposition = std::unique_ptr<TF1AbsComposition>(normSum);
640 fParams =
new TF1Parameters(fNpar);
641 fParams->SetParameters(&(normSum->GetParameters())[0]);
644 for (
int i = 0; i < fNpar; i++) {
645 if (coeffNames->At(i) !=
nullptr) {
646 TString coeffName = ((TObjString *)coeffNames->At(i))->GetString();
647 this->SetParName(i, (
const char *)coeffName);
649 this->SetParName(i, normSum->GetParName(i));
654 fFormula =
new TFormula(name, formula,
false, vectorize);
655 fNpar = fFormula->GetNpar();
657 fNdim = fFormula->GetNdim() == 0 ? 1 : fFormula->GetNdim();
660 fParErrors.resize(fNpar);
661 fParMin.resize(fNpar);
662 fParMax.resize(fNpar);
666 if (fNdim > 1 && xmin < xmax) {
667 Error(
"TF1",
"function: %s/%s has dimension %d instead of 1", name, formula, fNdim);
671 DoInitialize(addToGlobList);
673 TF1::EAddToList GetGlobalListOption(Option_t * opt) {
674 if (opt ==
nullptr)
return TF1::EAddToList::kDefault;
677 if (option.Contains(
"NL"))
return TF1::EAddToList::kNo;
678 if (option.Contains(
"GL"))
return TF1::EAddToList::kAdd;
679 return TF1::EAddToList::kDefault;
681 bool GetVectorizedOption(Option_t * opt) {
682 if (opt ==
nullptr)
return false;
685 if (option.Contains(
"VEC"))
return true;
688 TF1::TF1(
const char *name,
const char *formula, Double_t xmin, Double_t xmax, Option_t * opt) :
697 TF1(name, formula, xmin, xmax, GetGlobalListOption(opt), GetVectorizedOption(opt) )
713 TF1::TF1(
const char *name, Double_t xmin, Double_t xmax, Int_t npar, Int_t ndim, EAddToList addToGlobList) :
714 TF1(EFType::kInterpreted, name, xmin, xmax, npar, ndim, addToGlobList, new TF1Parameters(npar))
716 if (fName.Data()[0] ==
'*') {
717 Info(
"TF1",
"TF1 has a name starting with a \'*\' - it is for saved TF1 objects in a .C file");
719 }
else if (fName.IsNull()) {
720 Error(
"TF1",
"requires a proper function name!");
724 fMethodCall =
new TMethodCall();
725 fMethodCall->InitWithPrototype(fName,
"Double_t*,Double_t*");
727 if (! fMethodCall->IsValid()) {
728 Error(
"TF1",
"No function found with the signature %s(Double_t*,Double_t*)", name);
747 TF1::TF1(
const char *name, Double_t (*fcn)(Double_t *, Double_t *), Double_t xmin, Double_t xmax, Int_t npar, Int_t ndim, EAddToList addToGlobList) :
748 TF1(EFType::kPtrScalarFreeFcn, name, xmin, xmax, npar, ndim, addToGlobList, new TF1Parameters(npar), new TF1FunctorPointerImpl<double>(ROOT::Math::ParamFunctor(fcn)))
764 TF1::TF1(
const char *name, Double_t (*fcn)(
const Double_t *,
const Double_t *), Double_t xmin, Double_t xmax, Int_t npar, Int_t ndim, EAddToList addToGlobList) :
765 TF1(EFType::kPtrScalarFreeFcn, name, xmin, xmax, npar, ndim, addToGlobList, new TF1Parameters(npar), new TF1FunctorPointerImpl<double>(ROOT::Math::ParamFunctor(fcn)))
779 TF1::TF1(
const char *name, ROOT::Math::ParamFunctor f, Double_t xmin, Double_t xmax, Int_t npar, Int_t ndim, EAddToList addToGlobList) :
780 TF1(EFType::kPtrScalarFreeFcn, name, xmin, xmax, npar, ndim, addToGlobList, new TF1Parameters(npar), new TF1FunctorPointerImpl<double>(ROOT::Math::ParamFunctor(f)))
787 void TF1::DoInitialize(EAddToList addToGlobalList)
790 bool doAdd = ((addToGlobalList == EAddToList::kDefault && fgAddToGlobList)
791 || addToGlobalList == EAddToList::kAdd);
792 if (doAdd && gROOT) {
793 SetBit(kNotGlobal, kFALSE);
794 R__LOCKGUARD(gROOTMutex);
796 TF1 *f1old = (TF1 *)gROOT->GetListOfFunctions()->FindObject(fName);
798 gROOT->GetListOfFunctions()->Remove(f1old);
801 f1old->SetBit(kNotGlobal, kTRUE);
803 gROOT->GetListOfFunctions()->Add(
this);
805 SetBit(kNotGlobal, kTRUE);
808 SetLineColor(gStyle->GetFuncColor());
809 SetLineWidth(gStyle->GetFuncWidth());
810 SetLineStyle(gStyle->GetFuncStyle());
823 Bool_t TF1::DefaultAddToGlobalList(Bool_t on)
825 return fgAddToGlobList.exchange(on);
832 Bool_t TF1::AddToGlobalList(Bool_t on)
834 if (!gROOT)
return false;
836 bool prevStatus = !TestBit(kNotGlobal);
839 R__LOCKGUARD(gROOTMutex);
840 assert(gROOT->GetListOfFunctions()->FindObject(
this) !=
nullptr);
846 R__LOCKGUARD(gROOTMutex);
847 gROOT->GetListOfFunctions()->Add(
this);
848 SetBit(kNotGlobal, kFALSE);
849 }
else if (prevStatus) {
851 SetBit(kNotGlobal, kTRUE);
852 R__LOCKGUARD(gROOTMutex);
853 TF1 *old =
dynamic_cast<TF1 *
>(gROOT->GetListOfFunctions()->FindObject(GetName()));
855 Warning(
"AddToGlobalList",
"Function is supposed to be in the global list but it is not present");
858 gROOT->GetListOfFunctions()->Remove(
this);
868 void TF1::DefineNSUMTerm(TObjArray *newFuncs, TObjArray *coeffNames, TString &fullFormula, TString &formula,
869 int termStart,
int termEnd, Double_t xmin, Double_t xmax)
871 TString originalTerm = formula(termStart, termEnd-termStart);
872 int coeffLength = TermCoeffLength(originalTerm);
873 if (coeffLength != -1)
874 termStart += coeffLength + 1;
879 TString originalFunc = formula(termStart, termEnd-termStart);
880 TString cleanedFunc = TString(formula(termStart, termEnd-termStart))
881 .ReplaceAll(
'+',
"<plus>")
882 .ReplaceAll(
'*',
"<times>");
885 if (!gROOT->GetListOfFunctions()->FindObject(cleanedFunc))
886 newFuncs->Add(
new TF1(cleanedFunc, originalFunc, xmin, xmax));
889 if (fullFormula.Length() != 0)
890 fullFormula.Append(
'+');
893 if (coeffLength != -1 && originalTerm[0] !=
'[')
894 fullFormula.Append(originalTerm(0, coeffLength+1));
897 if (coeffLength != -1 && originalTerm[0] ==
'[')
898 coeffNames->Add(
new TObjString(TString(originalTerm(1,coeffLength-2))));
900 coeffNames->Add(
nullptr);
902 fullFormula.Append(cleanedFunc);
909 int TF1::TermCoeffLength(TString &term) {
910 int firstAsterisk = term.First(
'*');
911 if (firstAsterisk == -1)
914 if (TString(term(0,firstAsterisk)).IsFloat())
915 return firstAsterisk;
917 if (term[0] ==
'[' && term[firstAsterisk-1] ==
']'
918 && TString(term(1,firstAsterisk-2)).IsAlnum())
919 return firstAsterisk;
927 TF1 &TF1::operator=(
const TF1 &rhs)
941 if (fHistogram)
delete fHistogram;
942 if (fMethodCall)
delete fMethodCall;
946 R__LOCKGUARD(gROOTMutex);
947 if (gROOT) gROOT->GetListOfFunctions()->Remove(
this);
950 if (fParent) fParent->RecursiveRemove(
this);
952 if (fFormula)
delete fFormula;
953 if (fParams)
delete fParams;
954 if (fFunctor)
delete fFunctor;
960 TF1::TF1(
const TF1 &f1) :
961 TNamed(f1), TAttLine(f1), TAttFill(f1), TAttMarker(f1),
962 fXmin(0), fXmax(0), fNpar(0), fNdim(0), fType(EFType::kFormula)
964 ((TF1 &)f1).Copy(*
this);
974 void TF1::AbsValue(Bool_t flag)
983 void TF1::Browse(TBrowser *b)
985 Draw(b ? b->GetDrawOption() :
"");
995 void TF1::Copy(TObject &obj)
const
997 delete((TF1 &)obj).fHistogram;
998 delete((TF1 &)obj).fMethodCall;
1000 TNamed::Copy((TF1 &)obj);
1001 TAttLine::Copy((TF1 &)obj);
1002 TAttFill::Copy((TF1 &)obj);
1003 TAttMarker::Copy((TF1 &)obj);
1004 ((TF1 &)obj).fXmin = fXmin;
1005 ((TF1 &)obj).fXmax = fXmax;
1006 ((TF1 &)obj).fNpx = fNpx;
1007 ((TF1 &)obj).fNpar = fNpar;
1008 ((TF1 &)obj).fNdim = fNdim;
1009 ((TF1 &)obj).fType = fType;
1010 ((TF1 &)obj).fChisquare = fChisquare;
1011 ((TF1 &)obj).fNpfits = fNpfits;
1012 ((TF1 &)obj).fNDF = fNDF;
1013 ((TF1 &)obj).fMinimum = fMinimum;
1014 ((TF1 &)obj).fMaximum = fMaximum;
1016 ((TF1 &)obj).fParErrors = fParErrors;
1017 ((TF1 &)obj).fParMin = fParMin;
1018 ((TF1 &)obj).fParMax = fParMax;
1019 ((TF1 &)obj).fParent = fParent;
1020 ((TF1 &)obj).fSave = fSave;
1021 ((TF1 &)obj).fHistogram = 0;
1022 ((TF1 &)obj).fMethodCall = 0;
1023 ((TF1 &)obj).fNormalized = fNormalized;
1024 ((TF1 &)obj).fNormIntegral = fNormIntegral;
1025 ((TF1 &)obj).fFormula = 0;
1027 if (fFormula) assert(fFormula->GetNpar() == fNpar);
1031 if (((TF1 &)obj).fMethodCall)
delete((TF1 &)obj).fMethodCall;
1032 TMethodCall *m =
new TMethodCall(*fMethodCall);
1034 ((TF1 &)obj).fMethodCall = m;
1037 TFormula *formulaToCopy = ((TF1 &)obj).fFormula;
1038 if (formulaToCopy)
delete formulaToCopy;
1039 formulaToCopy =
new TFormula();
1040 fFormula->Copy(*formulaToCopy);
1041 ((TF1 &)obj).fFormula = formulaToCopy;
1044 TF1Parameters *paramsToCopy = ((TF1 &)obj).fParams;
1045 if (paramsToCopy) *paramsToCopy = *fParams;
1046 else ((TF1 &)obj).fParams =
new TF1Parameters(*fParams);
1050 if (((TF1 &)obj).fFunctor)
delete((TF1 &)obj).fFunctor;
1051 ((TF1 &)obj).fFunctor = fFunctor->Clone();
1055 TF1AbsComposition *comp = (TF1AbsComposition *)fComposition->IsA()->New();
1056 fComposition->Copy(*comp);
1057 ((TF1 &)obj).fComposition = std::unique_ptr<TF1AbsComposition>(comp);
1097 Double_t TF1::Derivative(Double_t x, Double_t *params, Double_t eps)
const
1099 if (GetNdim() > 1) {
1100 Warning(
"Derivative",
"Function dimension is larger than one");
1103 ROOT::Math::RichardsonDerivator rd;
1105 GetRange(xmin, xmax);
1107 double h = eps * std::abs(xmax - xmin);
1108 if (h <= 0) h = 0.001;
1111 ROOT::Math::WrappedTF1 wtf(*(const_cast<TF1 *>(
this)));
1112 wtf.SetParameters(params);
1113 der = rd.Derivative1(wtf, x, h);
1117 ROOT::Math::WrappedFunction<const TF1 & > wf(*
this);
1118 der = rd.Derivative1(wf, x, h);
1121 gErrorTF1 = rd.Error();
1162 Double_t TF1::Derivative2(Double_t x, Double_t *params, Double_t eps)
const
1164 if (GetNdim() > 1) {
1165 Warning(
"Derivative2",
"Function dimension is larger than one");
1168 ROOT::Math::RichardsonDerivator rd;
1170 GetRange(xmin, xmax);
1172 double h = eps * std::abs(xmax - xmin);
1173 if (h <= 0) h = 0.001;
1176 ROOT::Math::WrappedTF1 wtf(*(const_cast<TF1 *>(
this)));
1177 wtf.SetParameters(params);
1178 der = rd.Derivative2(wtf, x, h);
1182 ROOT::Math::WrappedFunction<const TF1 & > wf(*
this);
1183 der = rd.Derivative2(wf, x, h);
1186 gErrorTF1 = rd.Error();
1227 Double_t TF1::Derivative3(Double_t x, Double_t *params, Double_t eps)
const
1229 if (GetNdim() > 1) {
1230 Warning(
"Derivative3",
"Function dimension is larger than one");
1233 ROOT::Math::RichardsonDerivator rd;
1235 GetRange(xmin, xmax);
1237 double h = eps * std::abs(xmax - xmin);
1238 if (h <= 0) h = 0.001;
1241 ROOT::Math::WrappedTF1 wtf(*(const_cast<TF1 *>(
this)));
1242 wtf.SetParameters(params);
1243 der = rd.Derivative3(wtf, x, h);
1247 ROOT::Math::WrappedFunction<const TF1 & > wf(*
this);
1248 der = rd.Derivative3(wf, x, h);
1251 gErrorTF1 = rd.Error();
1261 Double_t TF1::DerivativeError()
1277 Int_t TF1::DistancetoPrimitive(Int_t px, Int_t py)
1279 if (!fHistogram)
return 9999;
1280 Int_t distance = 9999;
1282 distance = fHistogram->DistancetoPrimitive(px, py);
1283 if (distance <= 1)
return distance;
1289 Double_t x = gPad->AbsPixeltoX(px);
1290 xx[0] = gPad->PadtoX(x);
1291 if (xx[0] < fXmin || xx[0] > fXmax)
return distance;
1292 Double_t fval = Eval(xx[0]);
1293 Double_t y = gPad->YtoPad(fval);
1294 Int_t pybin = gPad->YtoAbsPixel(y);
1295 return TMath::Abs(py - pybin);
1317 void TF1::Draw(Option_t *option)
1319 TString opt = option;
1321 if (gPad && !opt.Contains(
"same")) gPad->Clear();
1325 gPad->IncrementPaletteColor(1, opt);
1347 TF1 *TF1::DrawCopy(Option_t *option)
const
1349 TF1 *newf1 = (TF1 *)this->IsA()->New();
1351 newf1->AppendPad(option);
1352 newf1->SetBit(kCanDelete);
1369 TObject *TF1::DrawDerivative(Option_t *option)
1371 TVirtualPad *pad = gROOT->GetSelectedPad();
1372 TVirtualPad *padsav = gPad;
1375 TGraph *gr =
new TGraph(
this,
"d");
1377 if (padsav) padsav->cd();
1394 TObject *TF1::DrawIntegral(Option_t *option)
1396 TVirtualPad *pad = gROOT->GetSelectedPad();
1397 TVirtualPad *padsav = gPad;
1400 TGraph *gr =
new TGraph(
this,
"i");
1402 if (padsav) padsav->cd();
1410 void TF1::DrawF1(Double_t xmin, Double_t xmax, Option_t *option)
1413 SetRange(xmin, xmax);
1429 Double_t TF1::Eval(Double_t x, Double_t y, Double_t z, Double_t t)
const
1431 if (fType == EFType::kFormula)
return fFormula->Eval(x, y, z, t);
1433 Double_t xx[4] = {x, y, z, t};
1434 Double_t *pp = (Double_t *)fParams->GetParameters();
1436 return ((TF1 *)
this)->EvalPar(xx, pp);
1458 Double_t TF1::EvalPar(
const Double_t *x,
const Double_t *params)
1462 if (fType == EFType::kFormula) {
1465 if (fNormalized && fNormIntegral != 0)
1466 return fFormula->EvalPar(x, params) / fNormIntegral;
1468 return fFormula->EvalPar(x, params);
1470 Double_t result = 0;
1471 if (fType == EFType::kPtrScalarFreeFcn || fType == EFType::kTemplScalar) {
1474 if (params) result = ((TF1FunctorPointerImpl<Double_t> *)fFunctor)->fImpl((Double_t *)x, (Double_t *)params);
1475 else result = ((TF1FunctorPointerImpl<Double_t> *)fFunctor)->fImpl((Double_t *)x, (Double_t *)fParams->GetParameters());
1477 }
else result = GetSave(x);
1479 if (fNormalized && fNormIntegral != 0)
1480 result = result / fNormIntegral;
1484 if (fType == EFType::kInterpreted) {
1485 if (fMethodCall) fMethodCall->Execute(result);
1486 else result = GetSave(x);
1488 if (fNormalized && fNormIntegral != 0)
1489 result = result / fNormIntegral;
1494 #ifdef R__HAS_VECCORE
1495 if (fType == EFType::kTemplVec) {
1497 if (params) result = EvalParVec(x, params);
1498 else result = EvalParVec(x, (Double_t *) fParams->GetParameters());
1501 result = GetSave(x);
1504 if (fNormalized && fNormIntegral != 0)
1505 result = result / fNormIntegral;
1511 if (fType == EFType::kCompositionFcn) {
1513 Error(
"EvalPar",
"Composition function not found");
1515 result = (*fComposition)(x, params);
1526 void TF1::ExecuteEvent(Int_t event, Int_t px, Int_t py)
1530 if (fHistogram) fHistogram->ExecuteEvent(event, px, py);
1532 if (!gPad->GetView()) {
1533 if (event == kMouseMotion) gPad->SetCursor(kHand);
1542 void TF1::FixParameter(Int_t ipar, Double_t value)
1544 if (ipar < 0 || ipar > GetNpar() - 1)
return;
1545 SetParameter(ipar, value);
1546 if (value != 0) SetParLimits(ipar, value, value);
1547 else SetParLimits(ipar, 1, 1);
1554 TF1 *TF1::GetCurrent()
1556 ::Warning(
"TF1::GetCurrent",
"This function is obsolete and is working only for the current painted functions");
1564 TH1 *TF1::GetHistogram()
const
1566 if (fHistogram)
return fHistogram;
1570 const_cast<TF1 *
>(
this)->fHistogram = const_cast<TF1 *>(
this)->CreateHistogram();
1571 if (!fHistogram) Error(
"GetHistogram",
"Error creating histogram for function %s of type %s", GetName(), IsA()->GetName());
1594 Double_t TF1::GetMaximum(Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter, Bool_t logx)
const
1601 if (!logx && gPad != 0) logx = gPad->GetLogx();
1603 ROOT::Math::BrentMinimizer1D bm;
1604 GInverseFunc g(
this);
1605 ROOT::Math::WrappedFunction<GInverseFunc> wf1(g);
1606 bm.SetFunction(wf1, xmin, xmax);
1608 bm.SetLogScan(logx);
1609 bm.Minimize(maxiter, epsilon, epsilon);
1611 x = - bm.FValMinimum();
1635 Double_t TF1::GetMaximumX(Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter, Bool_t logx)
const
1642 if (!logx && gPad != 0) logx = gPad->GetLogx();
1644 ROOT::Math::BrentMinimizer1D bm;
1645 GInverseFunc g(
this);
1646 ROOT::Math::WrappedFunction<GInverseFunc> wf1(g);
1647 bm.SetFunction(wf1, xmin, xmax);
1649 bm.SetLogScan(logx);
1650 bm.Minimize(maxiter, epsilon, epsilon);
1676 Double_t TF1::GetMinimum(Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter, Bool_t logx)
const
1683 if (!logx && gPad != 0) logx = gPad->GetLogx();
1685 ROOT::Math::BrentMinimizer1D bm;
1686 ROOT::Math::WrappedFunction<const TF1 &> wf1(*
this);
1687 bm.SetFunction(wf1, xmin, xmax);
1689 bm.SetLogScan(logx);
1690 bm.Minimize(maxiter, epsilon, epsilon);
1692 x = bm.FValMinimum();
1703 Double_t TF1::GetMinMaxNDim(Double_t *x ,
bool findmax, Double_t epsilon, Int_t maxiter)
const
1707 int ndim = GetNdim();
1709 Error(
"GetMinimumNDim",
"Function of dimension 0 - return Eval(x)");
1710 return (const_cast<TF1 &>(*
this))(x);
1714 const char *minimName = ROOT::Math::MinimizerOptions::DefaultMinimizerType().c_str();
1715 const char *minimAlgo = ROOT::Math::MinimizerOptions::DefaultMinimizerAlgo().c_str();
1716 ROOT::Math::Minimizer *min = ROOT::Math::Factory::CreateMinimizer(minimName, minimAlgo);
1719 Error(
"GetMinimumNDim",
"Error creating minimizer %s", minimName);
1724 if (epsilon > 0) min->SetTolerance(epsilon);
1725 if (maxiter > 0) min->SetMaxFunctionCalls(maxiter);
1728 ROOT::Math::WrappedMultiFunction<TF1 &> objFunc(const_cast<TF1 &>(*
this), ndim);
1730 GInverseFuncNdim invFunc(const_cast<TF1 *>(
this));
1731 ROOT::Math::WrappedMultiFunction<GInverseFuncNdim &> objFuncInv(invFunc, ndim);
1733 min->SetFunction(objFunc);
1735 min->SetFunction(objFuncInv);
1737 std::vector<double> rmin(ndim);
1738 std::vector<double> rmax(ndim);
1739 GetRange(&rmin[0], &rmax[0]);
1740 for (
int i = 0; i < ndim; ++i) {
1741 const char *xname = 0;
1742 double stepSize = 0.1;
1744 if (rmax[i] > rmin[i])
1745 stepSize = (rmax[i] - rmin[i]) / 100;
1746 else if (std::abs(x[i]) > 1.)
1747 stepSize = 0.1 * x[i];
1753 }
else if (i == 1) {
1759 xname = TString::Format(
"x_%d", i);
1763 if (rmin[i] < rmax[i]) {
1765 min->SetLimitedVariable(i, xname, x[i], stepSize, rmin[i], rmax[i]);
1767 min->SetVariable(i, xname, x[i], stepSize);
1771 bool ret = min->Minimize();
1773 Error(
"GetMinimumNDim",
"Error minimizing function %s", GetName());
1775 if (min->X()) std::copy(min->X(), min->X() + ndim, x);
1776 double fmin = min->MinValue();
1779 return (findmax) ? -fmin : fmin;
1803 Double_t TF1::GetMinimumX(Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter, Bool_t logx)
const
1810 ROOT::Math::BrentMinimizer1D bm;
1811 ROOT::Math::WrappedFunction<const TF1 &> wf1(*
this);
1812 bm.SetFunction(wf1, xmin, xmax);
1814 bm.SetLogScan(logx);
1815 bm.Minimize(maxiter, epsilon, epsilon);
1843 Double_t TF1::GetX(Double_t fy, Double_t xmin, Double_t xmax, Double_t epsilon, Int_t maxiter, Bool_t logx)
const
1850 if (!logx && gPad != 0) logx = gPad->GetLogx();
1853 ROOT::Math::WrappedFunction<GFunc> wf1(g);
1854 ROOT::Math::BrentRootFinder brf;
1855 brf.SetFunction(wf1, xmin, xmax);
1857 brf.SetLogScan(logx);
1858 bool ret = brf.Solve(maxiter, epsilon, epsilon);
1859 if (!ret) Error(
"GetX",
"[%f,%f] is not a valid interval",xmin,xmax);
1860 return (ret) ? brf.Root() : TMath::QuietNaN();
1869 Int_t TF1::GetNDF()
const
1871 Int_t npar = GetNpar();
1872 if (fNDF == 0 && (fNpfits > npar))
return fNpfits - npar;
1880 Int_t TF1::GetNumberFreeParameters()
const
1882 Int_t ntot = GetNpar();
1885 for (Int_t i = 0; i < ntot; i++) {
1886 ((TF1 *)
this)->GetParLimits(i, al, bl);
1887 if (al * bl != 0 && al >= bl) nfree--;
1898 char *TF1::GetObjectInfo(Int_t px, Int_t )
const
1900 static char info[64];
1901 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
1902 snprintf(info, 64,
"(x=%g, f=%g)", x, ((TF1 *)
this)->Eval(x));
1910 Double_t TF1::GetParError(Int_t ipar)
const
1912 if (ipar < 0 || ipar > GetNpar() - 1)
return 0;
1913 return fParErrors[ipar];
1920 void TF1::GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax)
const
1924 int n = fParMin.size();
1925 assert(n ==
int(fParMax.size()) && n <= fNpar);
1926 if (ipar < 0 || ipar > n - 1)
return;
1927 parmin = fParMin[ipar];
1928 parmax = fParMax[ipar];
1935 Double_t TF1::GetProb()
const
1937 if (fNDF <= 0)
return 0;
1938 return TMath::Prob(fChisquare, fNDF);
1973 Int_t TF1::GetQuantiles(Int_t nprobSum, Double_t *q,
const Double_t *probSum)
1978 const Int_t npx = TMath::Max(fNpx, 2 * nprobSum);
1979 const Double_t xMin = GetXmin();
1980 const Double_t xMax = GetXmax();
1981 const Double_t dx = (xMax - xMin) / npx;
1983 TArrayD integral(npx + 1);
1989 Int_t intNegative = 0;
1991 for (i = 0; i < npx; i++) {
1992 Double_t integ = Integral(Double_t(xMin + i * dx), Double_t(xMin + i * dx + dx), 0.0);
1997 integral[i + 1] = integral[i] + integ;
2000 if (intNegative > 0)
2001 Warning(
"GetQuantiles",
"function:%s has %d negative values: abs assumed",
2002 GetName(), intNegative);
2003 if (integral[npx] == 0) {
2004 Error(
"GetQuantiles",
"Integral of function is zero");
2008 const Double_t total = integral[npx];
2009 for (i = 1; i <= npx; i++) integral[i] /= total;
2013 for (i = 0; i < npx; i++) {
2014 const Double_t x0 = xMin + dx * i;
2015 const Double_t r2 = integral[i + 1] - integral[i];
2016 const Double_t r1 = Integral(x0, x0 + 0.5 * dx, 0.0) / total;
2017 gamma[i] = (2 * r2 - 4 * r1) / (dx * dx);
2018 beta[i] = r2 / dx - gamma[i] * dx;
2025 for (i = 0; i < nprobSum; i++) {
2026 const Double_t r = probSum[i];
2027 Int_t bin = TMath::Max(TMath::BinarySearch(npx + 1, integral.GetArray(), r), (Long64_t)0);
2034 while (bin < npx - 1 && TMath::AreEqualRel(integral[bin + 1], r, 1E-12)) {
2035 if (TMath::AreEqualRel(integral[bin + 2], r, 1E-12)) bin++;
2039 const Double_t rr = r - integral[bin];
2042 const Double_t fac = -2.*gamma[bin] * rr / beta[bin] / beta[bin];
2043 if (fac != 0 && fac <= 1)
2044 xx = (-beta[bin] + TMath::Sqrt(beta[bin] * beta[bin] + 2 * gamma[bin] * rr)) / gamma[bin];
2045 else if (beta[bin] != 0.)
2046 xx = rr / beta[bin];
2047 q[i] = alpha[bin] + xx;
2050 if (integral[bin + 1] == r) q[i] += dx;
2074 Double_t TF1::GetRandom()
2077 if (fIntegral.size() == 0) {
2078 fIntegral.resize(fNpx + 1);
2079 fAlpha.resize(fNpx + 1);
2081 fGamma.resize(fNpx);
2085 Int_t intNegative = 0;
2087 Bool_t logbin = kFALSE;
2089 Double_t xmin = fXmin;
2090 Double_t xmax = fXmax;
2091 if (xmin > 0 && xmax / xmin > fNpx) {
2094 xmin = TMath::Log10(fXmin);
2095 xmax = TMath::Log10(fXmax);
2097 dx = (xmax - xmin) / fNpx;
2099 Double_t *xx =
new Double_t[fNpx + 1];
2100 for (i = 0; i < fNpx; i++) {
2101 xx[i] = xmin + i * dx;
2104 for (i = 0; i < fNpx; i++) {
2106 integ = Integral(TMath::Power(10, xx[i]), TMath::Power(10, xx[i + 1]), 0.0);
2108 integ = Integral(xx[i], xx[i + 1], 0.0);
2114 fIntegral[i + 1] = fIntegral[i] + integ;
2116 if (intNegative > 0) {
2117 Warning(
"GetRandom",
"function:%s has %d negative values: abs assumed", GetName(), intNegative);
2119 if (fIntegral[fNpx] == 0) {
2121 Error(
"GetRandom",
"Integral of function is zero");
2124 Double_t total = fIntegral[fNpx];
2125 for (i = 1; i <= fNpx; i++) {
2126 fIntegral[i] /= total;
2131 Double_t x0, r1, r2, r3;
2132 for (i = 0; i < fNpx; i++) {
2134 r2 = fIntegral[i + 1] - fIntegral[i];
2135 if (logbin) r1 = Integral(TMath::Power(10, x0), TMath::Power(10, x0 + 0.5 * dx), 0.0) / total;
2136 else r1 = Integral(x0, x0 + 0.5 * dx, 0.0) / total;
2137 r3 = 2 * r2 - 4 * r1;
2138 if (TMath::Abs(r3) > 1e-8) fGamma[i] = r3 / (dx * dx);
2140 fBeta[i] = r2 / dx - fGamma[i] * dx;
2148 Double_t r = gRandom->Rndm();
2149 Int_t bin = TMath::BinarySearch(fNpx, fIntegral.data(), r);
2150 Double_t rr = r - fIntegral[bin];
2153 if (fGamma[bin] != 0)
2154 yy = (-fBeta[bin] + TMath::Sqrt(fBeta[bin] * fBeta[bin] + 2 * fGamma[bin] * rr)) / fGamma[bin];
2156 yy = rr / fBeta[bin];
2157 Double_t x = fAlpha[bin] + yy;
2158 if (fAlpha[fNpx] > 0)
return TMath::Power(10, x);
2186 Double_t TF1::GetRandom(Double_t xmin, Double_t xmax)
2189 if (fIntegral.size() == 0) {
2190 fIntegral.resize(fNpx + 1);
2191 fAlpha.resize(fNpx+1);
2193 fGamma.resize(fNpx);
2195 Double_t dx = (fXmax - fXmin) / fNpx;
2197 Int_t intNegative = 0;
2199 for (i = 0; i < fNpx; i++) {
2200 integ = Integral(Double_t(fXmin + i * dx), Double_t(fXmin + i * dx + dx), 0.0);
2205 fIntegral[i + 1] = fIntegral[i] + integ;
2207 if (intNegative > 0) {
2208 Warning(
"GetRandom",
"function:%s has %d negative values: abs assumed", GetName(), intNegative);
2210 if (fIntegral[fNpx] == 0) {
2211 Error(
"GetRandom",
"Integral of function is zero");
2214 Double_t total = fIntegral[fNpx];
2215 for (i = 1; i <= fNpx; i++) {
2216 fIntegral[i] /= total;
2221 Double_t x0, r1, r2, r3;
2222 for (i = 0; i < fNpx; i++) {
2223 x0 = fXmin + i * dx;
2224 r2 = fIntegral[i + 1] - fIntegral[i];
2225 r1 = Integral(x0, x0 + 0.5 * dx, 0.0) / total;
2226 r3 = 2 * r2 - 4 * r1;
2227 if (TMath::Abs(r3) > 1e-8) fGamma[i] = r3 / (dx * dx);
2229 fBeta[i] = r2 / dx - fGamma[i] * dx;
2236 Double_t dx = (fXmax - fXmin) / fNpx;
2237 Int_t nbinmin = (Int_t)((xmin - fXmin) / dx);
2238 Int_t nbinmax = (Int_t)((xmax - fXmin) / dx) + 2;
2239 if (nbinmax > fNpx) nbinmax = fNpx;
2241 Double_t pmin = fIntegral[nbinmin];
2242 Double_t pmax = fIntegral[nbinmax];
2244 Double_t r, x, xx, rr;
2246 r = gRandom->Uniform(pmin, pmax);
2248 Int_t bin = TMath::BinarySearch(fNpx, fIntegral.data(), r);
2249 rr = r - fIntegral[bin];
2251 if (fGamma[bin] != 0)
2252 xx = (-fBeta[bin] + TMath::Sqrt(fBeta[bin] * fBeta[bin] + 2 * fGamma[bin] * rr)) / fGamma[bin];
2254 xx = rr / fBeta[bin];
2255 x = fAlpha[bin] + xx;
2256 }
while (x < xmin || x > xmax);
2263 void TF1::GetRange(Double_t *rmin, Double_t *rmax)
const
2265 int ndim = GetNdim();
2267 double xmin = 0, ymin = 0, zmin = 0, xmax = 0, ymax = 0, zmax = 0;
2268 GetRange(xmin, ymin, zmin, xmax, ymax, zmax);
2269 for (
int i = 0; i < ndim; ++i) {
2273 }
else if (i == 1) {
2276 }
else if (i == 2) {
2290 void TF1::GetRange(Double_t &xmin, Double_t &xmax)
const
2300 void TF1::GetRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax)
const
2312 void TF1::GetRange(Double_t &xmin, Double_t &ymin, Double_t &zmin, Double_t &xmax, Double_t &ymax, Double_t &zmax)
const
2326 Double_t TF1::GetSave(
const Double_t *xx)
2328 if (fSave.size() == 0)
return 0;
2330 int fNsave = fSave.size();
2331 Double_t x = Double_t(xx[0]);
2332 Double_t y, dx, xmin, xmax, xlow, xup, ylow, yup;
2333 if (fParent && fParent->InheritsFrom(TH1::Class())) {
2336 xmin = fSave[fNsave - 3];
2337 xmax = fSave[fNsave - 2];
2338 if (fSave[fNsave - 1] == xmax) {
2339 TH1 *h = (TH1 *)fParent;
2340 TAxis *xaxis = h->GetXaxis();
2341 Int_t bin1 = xaxis->FindBin(xmin);
2342 Int_t binup = xaxis->FindBin(xmax);
2343 Int_t bin = xaxis->FindBin(x);
2345 xlow = xaxis->GetBinCenter(bin);
2346 xup = xaxis->GetBinCenter(bin + 1);
2347 ylow = fSave[bin - bin1];
2348 yup = fSave[bin - bin1 + 1];
2350 xlow = xaxis->GetBinCenter(bin - 1);
2351 xup = xaxis->GetBinCenter(bin);
2352 ylow = fSave[bin - bin1 - 1];
2353 yup = fSave[bin - bin1];
2356 y = ((xup * ylow - xlow * yup) + x * (yup - ylow)) / dx;
2360 Int_t np = fNsave - 3;
2361 xmin = Double_t(fSave[np + 1]);
2362 xmax = Double_t(fSave[np + 2]);
2363 dx = (xmax - xmin) / np;
2364 if (x < xmin || x > xmax)
return 0;
2366 if (TMath::IsNaN(x))
return x;
2367 if (dx <= 0)
return 0;
2369 Int_t bin = Int_t((x - xmin) / dx);
2370 xlow = xmin + bin * dx;
2373 yup = fSave[bin + 1];
2374 y = ((xup * ylow - xlow * yup) + x * (yup - ylow)) / dx;
2382 TAxis *TF1::GetXaxis()
const
2384 TH1 *h = GetHistogram();
2386 return h->GetXaxis();
2393 TAxis *TF1::GetYaxis()
const
2395 TH1 *h = GetHistogram();
2397 return h->GetYaxis();
2404 TAxis *TF1::GetZaxis()
const
2406 TH1 *h = GetHistogram();
2408 return h->GetZaxis();
2427 Double_t TF1::GradientPar(Int_t ipar,
const Double_t *x, Double_t eps)
2429 return GradientParTempl<Double_t>(ipar, x, eps);
2446 void TF1::GradientPar(
const Double_t *x, Double_t *grad, Double_t eps)
2448 GradientParTempl<Double_t>(x, grad, eps);
2454 void TF1::InitArgs(
const Double_t *x,
const Double_t *params)
2458 args[0] = (Long_t)x;
2459 if (params) args[1] = (Long_t)params;
2460 else args[1] = (Long_t)GetParameters();
2461 fMethodCall->SetParamPtrs(args);
2469 void TF1::InitStandardFunctions()
2472 R__LOCKGUARD(gROOTMutex);
2473 if (!gROOT->GetListOfFunctions()->FindObject(
"gaus")) {
2474 f1 =
new TF1(
"gaus",
"gaus", -1, 1);
2475 f1->SetParameters(1, 0, 1);
2476 f1 =
new TF1(
"gausn",
"gausn", -1, 1);
2477 f1->SetParameters(1, 0, 1);
2478 f1 =
new TF1(
"landau",
"landau", -1, 1);
2479 f1->SetParameters(1, 0, 1);
2480 f1 =
new TF1(
"landaun",
"landaun", -1, 1);
2481 f1->SetParameters(1, 0, 1);
2482 f1 =
new TF1(
"expo",
"expo", -1, 1);
2483 f1->SetParameters(1, 1);
2484 for (Int_t i = 0; i < 10; i++) {
2485 f1 =
new TF1(Form(
"pol%d", i), Form(
"pol%d", i), -1, 1);
2486 f1->SetParameters(1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
2490 ROOT::Math::ChebyshevPol *pol =
new ROOT::Math::ChebyshevPol(i);
2493 f1 =
new TF1(TString::Format(
"chebyshev%d", i), pol, min, max, i + 1, 1);
2494 f1->SetParameters(1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
2502 Double_t TF1::Integral(Double_t a, Double_t b, Double_t epsrel)
2505 if (GetNumber() > 0) {
2506 Double_t result = 0.;
2508 Info(
"computing analytical integral for function %s with number %d", GetName(), GetNumber());
2510 result = AnalyticalIntegral(
this, a, b);
2512 if (!TMath::IsNaN(result))
return result;
2514 Warning(
"analytical integral not available for %s - with number %d compute numerical integral", GetName(), GetNumber());
2516 return IntegralOneDim(a, b, epsrel, epsrel, error);
2592 Double_t TF1::IntegralOneDim(Double_t a, Double_t b, Double_t epsrel, Double_t epsabs, Double_t &error)
2595 TF1_EvalWrapper wf1(
this, 0, fgAbsValue);
2596 Double_t result = 0;
2598 if (epsrel <= 0) epsrel = ROOT::Math::IntegratorOneDimOptions::DefaultRelTolerance();
2599 if (epsabs <= 0) epsabs = ROOT::Math::IntegratorOneDimOptions::DefaultAbsTolerance();
2600 if (ROOT::Math::IntegratorOneDimOptions::DefaultIntegratorType() == ROOT::Math::IntegrationOneDim::kGAUSS) {
2601 ROOT::Math::GaussIntegrator iod(epsabs, epsrel);
2602 iod.SetFunction(wf1);
2603 if (a != - TMath::Infinity() && b != TMath::Infinity())
2604 result = iod.Integral(a, b);
2605 else if (a == - TMath::Infinity() && b != TMath::Infinity())
2606 result = iod.IntegralLow(b);
2607 else if (a != - TMath::Infinity() && b == TMath::Infinity())
2608 result = iod.IntegralUp(a);
2609 else if (a == - TMath::Infinity() && b == TMath::Infinity())
2610 result = iod.Integral();
2611 error = iod.Error();
2612 status = iod.Status();
2614 ROOT::Math::IntegratorOneDim iod(wf1, ROOT::Math::IntegratorOneDimOptions::DefaultIntegratorType(), epsabs, epsrel);
2615 if (a != - TMath::Infinity() && b != TMath::Infinity())
2616 result = iod.Integral(a, b);
2617 else if (a == - TMath::Infinity() && b != TMath::Infinity())
2618 result = iod.IntegralLow(b);
2619 else if (a != - TMath::Infinity() && b == TMath::Infinity())
2620 result = iod.IntegralUp(a);
2621 else if (a == - TMath::Infinity() && b == TMath::Infinity())
2622 result = iod.Integral();
2623 error = iod.Error();
2624 status = iod.Status();
2627 std::string igName = ROOT::Math::IntegratorOneDim::GetName(ROOT::Math::IntegratorOneDimOptions::DefaultIntegratorType());
2628 Warning(
"IntegralOneDim",
"Error found in integrating function %s in [%f,%f] using %s. Result = %f +/- %f - status = %d", GetName(), a, b, igName.c_str(), result, error, status);
2629 TString msg(
"\t\tFunction Parameters = {");
2630 for (
int ipar = 0; ipar < GetNpar(); ++ipar) {
2631 msg += TString::Format(
" %s = %f ", GetParName(ipar), GetParameter(ipar));
2632 if (ipar < GetNpar() - 1) msg += TString(
",");
2633 else msg += TString(
"}");
2635 Info(
"IntegralOneDim",
"%s", msg.Data());
2689 Double_t TF1::IntegralError(Double_t a, Double_t b,
const Double_t *params,
const Double_t *covmat, Double_t epsilon)
2693 x1[0] = a, x2[0] = b;
2694 return ROOT::TF1Helper::IntegralError(
this, 1, x1, x2, params, covmat, epsilon);
2728 Double_t TF1::IntegralError(Int_t n,
const Double_t *a,
const Double_t *b,
const Double_t *params,
const Double_t *covmat, Double_t epsilon)
2730 return ROOT::TF1Helper::IntegralError(
this, n, a, b, params, covmat, epsilon);
2737 Double_t TF1::IntegralFast(
const TGraph *g, Double_t a, Double_t b, Double_t *params)
2740 return IntegralFast(g->GetN(), g->GetX(), g->GetY(), a, b, params);
2748 Double_t TF1::IntegralFast(Int_t num, Double_t * , Double_t * , Double_t a, Double_t b, Double_t *params, Double_t epsilon)
2752 ROOT::Math::WrappedTF1 wf1(*
this);
2754 wf1.SetParameters(params);
2755 ROOT::Math::GaussLegendreIntegrator gli(num, epsilon);
2756 gli.SetFunction(wf1);
2757 return gli.Integral(a, b);
2768 Double_t TF1::IntegralMultiple(Int_t n,
const Double_t *a,
const Double_t *b, Double_t epsrel, Double_t &relerr)
2770 Int_t nfnevl, ifail;
2771 UInt_t maxpts = TMath::Max(UInt_t(20 * TMath::Power(fNpx, GetNdim())), ROOT::Math::IntegratorMultiDimOptions::DefaultNCalls());
2772 Double_t result = IntegralMultiple(n, a, b, maxpts, epsrel, epsrel, relerr, nfnevl, ifail);
2774 Warning(
"IntegralMultiple",
"failed code=%d, ", ifail);
2821 Double_t TF1::IntegralMultiple(Int_t n,
const Double_t *a,
const Double_t *b, Int_t maxpts, Double_t epsrel, Double_t epsabs, Double_t &relerr, Int_t &nfnevl, Int_t &ifail)
2823 ROOT::Math::WrappedMultiFunction<TF1 &> wf1(*
this, n);
2826 if (epsrel <= 0) epsrel = ROOT::Math::IntegratorMultiDimOptions::DefaultRelTolerance();
2827 if (epsabs <= 0) epsabs = ROOT::Math::IntegratorMultiDimOptions::DefaultAbsTolerance();
2828 if (ROOT::Math::IntegratorMultiDimOptions::DefaultIntegratorType() == ROOT::Math::IntegrationMultiDim::kADAPTIVE) {
2829 ROOT::Math::AdaptiveIntegratorMultiDim aimd(wf1, epsabs, epsrel, maxpts);
2831 result = aimd.Integral(a, b);
2832 relerr = aimd.RelError();
2833 nfnevl = aimd.NEval();
2834 ifail = aimd.Status();
2837 ROOT::Math::IntegratorMultiDim imd(wf1, ROOT::Math::IntegratorMultiDimOptions::DefaultIntegratorType(), epsabs, epsrel, maxpts);
2838 result = imd.Integral(a, b);
2839 relerr = (result != 0) ? imd.Error() / std::abs(result) : imd.Error();
2841 ifail = imd.Status();
2852 Bool_t TF1::IsValid()
const
2854 if (fFormula)
return fFormula->IsValid();
2855 if (fMethodCall)
return fMethodCall->IsValid();
2859 if (!fFunctor && fSave.empty())
return kFALSE;
2867 void TF1::Print(Option_t *option)
const
2869 if (fType == EFType::kFormula) {
2870 printf(
"Formula based function: %s \n", GetName());
2872 fFormula->Print(option);
2873 }
else if (fType > 0) {
2874 if (fType == EFType::kInterpreted)
2875 printf(
"Interpreted based function: %s(double *x, double *p). Ndim = %d, Npar = %d \n", GetName(), GetNdim(),
2877 else if (fType == EFType::kCompositionFcn) {
2878 printf(
"Composition based function: %s. Ndim = %d, Npar = %d \n", GetName(), GetNdim(), GetNpar());
2880 printf(
"fComposition not found!\n");
2883 printf(
"Compiled based function: %s based on a functor object. Ndim = %d, Npar = %d\n", GetName(),
2884 GetNdim(), GetNpar());
2886 printf(
"Function based on a list of points from a compiled based function: %s. Ndim = %d, Npar = %d, Npx "
2888 GetName(), GetNdim(), GetNpar(), fSave.size());
2890 Warning(
"Print",
"Function %s is based on a list of points but list is empty", GetName());
2893 TString opt(option);
2895 if (opt.Contains(
"V")) {
2898 printf(
"List of Parameters: \n");
2899 for (
int i = 0; i < fNpar; ++i)
2900 printf(
" %20s = %10f \n", GetParName(i), GetParameter(i));
2902 if (!fSave.empty()) {
2904 printf(
"List of Saved points (N=%d): \n",
int(fSave.size()));
2905 for (
auto &x : fSave)
2906 printf(
"( %10f ) ", x);
2912 printf(
"Contained histogram\n");
2913 fHistogram->Print(option);
2923 void TF1::Paint(Option_t *choptin)
2928 strlcpy(option,choptin,32);
2930 TString opt = option;
2933 Bool_t optSAME = kFALSE;
2934 if (opt.Contains(
"same")) {
2935 opt.ReplaceAll(
"same",
"");
2938 opt.ReplaceAll(
' ',
"");
2940 Double_t xmin = fXmin, xmax = fXmax, pmin = fXmin, pmax = fXmax;
2942 pmin = gPad->PadtoX(gPad->GetUxmin());
2943 pmax = gPad->PadtoX(gPad->GetUxmax());
2946 if (xmax < pmin)
return;
2947 if (xmin > pmax)
return;
2948 if (xmin < pmin) xmin = pmin;
2949 if (xmax > pmax) xmax = pmax;
2953 fHistogram = DoCreateHistogram(xmin, xmax, kFALSE);
2955 char *l1 = strstr(option,
"PFC");
2956 char *l2 = strstr(option,
"PLC");
2957 char *l3 = strstr(option,
"PMC");
2958 if (l1 || l2 || l3) {
2959 Int_t i = gPad->NextPaletteColor();
2960 if (l1) {memcpy(l1,
" ",3); fHistogram->SetFillColor(i);}
2961 if (l2) {memcpy(l2,
" ",3); fHistogram->SetLineColor(i);}
2962 if (l3) {memcpy(l3,
" ",3); fHistogram->SetMarkerColor(i);}
2966 Double_t minimum = fHistogram->GetMinimumStored();
2967 Double_t maximum = fHistogram->GetMaximumStored();
2968 if (minimum <= 0 && gPad && gPad->GetLogy()) minimum = -1111;
2969 if (gPad && gPad->GetUymin() < fHistogram->GetMinimum() &&
2970 !fHistogram->TestBit(TH1::kIsZoomed)) minimum = -1111;
2971 if (minimum == -1111) {
2972 if (fHistogram->TestBit(TH1::kIsZoomed)) {
2973 minimum = fHistogram->GetYaxis()->GetXmin();
2978 if (minimum == -1111) {
2980 if (optSAME && gPad) hmin = gPad->GetUymin();
2981 else hmin = fHistogram->GetMinimum();
2984 Double_t hminpos = hmin;
2985 if (optSAME && gPad) hmax = gPad->GetUymax();
2986 else hmax = fHistogram->GetMaximum();
2987 hmin -= 0.05 * (hmax - hmin);
2988 if (hmin < 0) hmin = 0;
2989 if (hmin <= 0 && gPad && gPad->GetLogy()) hmin = hminpos;
2994 fHistogram->SetMinimum(minimum);
2996 if (maximum == -1111) {
2997 if (fHistogram->TestBit(TH1::kIsZoomed)) {
2998 maximum = fHistogram->GetYaxis()->GetXmax();
3002 fHistogram->SetMaximum(maximum);
3008 if (opt.Length() == 0) {
3009 if (optSAME) fHistogram->Paint(
"lfsame");
3010 else fHistogram->Paint(
"lf");
3012 fHistogram->Paint(option);
3022 TH1 *TF1::DoCreateHistogram(Double_t xmin, Double_t xmax, Bool_t recreate)
3032 TString xtitle =
"";
3033 TString ytitle =
"";
3034 char *semicol = (
char *)strstr(GetTitle(),
";");
3036 Int_t nxt = strlen(semicol);
3037 char *ctemp =
new char[nxt];
3038 strlcpy(ctemp, semicol + 1, nxt);
3039 semicol = (
char *)strstr(ctemp,
";");
3042 ytitle = semicol + 1;
3049 xtitle = fHistogram->GetXaxis()->GetTitle();
3050 ytitle = fHistogram->GetYaxis()->GetTitle();
3051 if (!gPad->GetLogx() && fHistogram->TestBit(TH1::kLogX)) {
3056 if (gPad->GetLogx() && !fHistogram->TestBit(TH1::kLogX)) {
3063 if (fHistogram && !recreate) {
3064 histogram = fHistogram;
3065 fHistogram->GetXaxis()->SetLimits(xmin, xmax);
3069 if (xmin > 0 && gPad && gPad->GetLogx()) {
3070 Double_t *xbins =
new Double_t[fNpx + 1];
3071 Double_t xlogmin = TMath::Log10(xmin);
3072 Double_t xlogmax = TMath::Log10(xmax);
3073 Double_t dlogx = (xlogmax - xlogmin) / ((Double_t)fNpx);
3074 for (i = 0; i <= fNpx; i++) {
3075 xbins[i] = gPad->PadtoX(xlogmin + i * dlogx);
3077 histogram =
new TH1D(
"Func", GetTitle(), fNpx, xbins);
3078 histogram->SetBit(TH1::kLogX);
3081 histogram =
new TH1D(
"Func", GetTitle(), fNpx, xmin, xmax);
3083 if (fMinimum != -1111) histogram->SetMinimum(fMinimum);
3084 if (fMaximum != -1111) histogram->SetMaximum(fMaximum);
3085 histogram->SetDirectory(0);
3087 R__ASSERT(histogram);
3090 histogram->GetXaxis()->SetTitle(xtitle.Data());
3091 histogram->GetYaxis()->SetTitle(ytitle.Data());
3092 Double_t *parameters = GetParameters();
3094 InitArgs(xv, parameters);
3095 for (i = 1; i <= fNpx; i++) {
3096 xv[0] = histogram->GetBinCenter(i);
3097 histogram->SetBinContent(i, EvalPar(xv, parameters));
3101 histogram->SetBit(TH1::kNoStats);
3102 histogram->SetLineColor(GetLineColor());
3103 histogram->SetLineStyle(GetLineStyle());
3104 histogram->SetLineWidth(GetLineWidth());
3105 histogram->SetFillColor(GetFillColor());
3106 histogram->SetFillStyle(GetFillStyle());
3107 histogram->SetMarkerColor(GetMarkerColor());
3108 histogram->SetMarkerStyle(GetMarkerStyle());
3109 histogram->SetMarkerSize(GetMarkerSize());
3113 if (!fHistogram) fHistogram = histogram;
3123 void TF1::ReleaseParameter(Int_t ipar)
3125 if (ipar < 0 || ipar > GetNpar() - 1)
return;
3126 SetParLimits(ipar, 0, 0);
3133 void TF1::Save(Double_t xmin, Double_t xmax, Double_t, Double_t, Double_t, Double_t)
3135 Double_t *parameters = GetParameters();
3137 if (fParent && fParent->InheritsFrom(TH1::Class())) {
3139 if ((xmin > 0 && xmax > 0) && TMath::Abs(TMath::Log10(xmax / xmin) > TMath::Log10(fNpx))) {
3140 TH1 *h = (TH1 *)fParent;
3141 Int_t bin1 = h->GetXaxis()->FindBin(xmin);
3142 Int_t bin2 = h->GetXaxis()->FindBin(xmax);
3143 int fNsave = bin2 - bin1 + 4;
3145 fSave.resize(fNsave);
3148 InitArgs(xv, parameters);
3149 for (Int_t i = bin1; i <= bin2; i++) {
3150 xv[0] = h->GetXaxis()->GetBinCenter(i);
3151 fSave[i - bin1] = EvalPar(xv, parameters);
3153 fSave[fNsave - 3] = xmin;
3154 fSave[fNsave - 2] = xmax;
3155 fSave[fNsave - 1] = xmax;
3159 int fNsave = fNpx + 3;
3164 fSave.resize(fNsave);
3165 Double_t dx = (xmax - xmin) / fNpx;
3167 dx = (fXmax - fXmin) / fNpx;
3169 xmin = fXmin + 0.5 * dx;
3170 xmax = fXmax - 0.5 * dx;
3173 InitArgs(xv, parameters);
3174 for (Int_t i = 0; i <= fNpx; i++) {
3175 xv[0] = xmin + dx * i;
3176 fSave[i] = EvalPar(xv, parameters);
3178 fSave[fNpx + 1] = xmin;
3179 fSave[fNpx + 2] = xmax;
3186 void TF1::SavePrimitive(std::ostream &out, Option_t *option )
3192 if (strstr(option,
"cc")) {
3193 out <<
"double " << GetName() <<
"(double xv) {" << std::endl;
3194 Double_t dx = (fXmax - fXmin) / (fNpx - 1);
3195 out <<
" double x[" << fNpx <<
"] = {" << std::endl;
3198 for (i = 0; i < fNpx; i++) {
3199 out << fXmin + dx *i ;
3200 if (i < fNpx - 1) out <<
", ";
3208 out <<
" };" << std::endl;
3209 out <<
" double y[" << fNpx <<
"] = {" << std::endl;
3212 for (i = 0; i < fNpx; i++) {
3213 out << Eval(fXmin + dx * i);
3214 if (i < fNpx - 1) out <<
", ";
3222 out <<
" };" << std::endl;
3223 out <<
" if (xv<x[0]) return y[0];" << std::endl;
3224 out <<
" if (xv>x[" << fNpx - 1 <<
"]) return y[" << fNpx - 1 <<
"];" << std::endl;
3225 out <<
" int i, j=0;" << std::endl;
3226 out <<
" for (i=1; i<" << fNpx <<
"; i++) { if (xv < x[i]) break; j++; }" << std::endl;
3227 out <<
" return y[j] + (y[j + 1] - y[j]) / (x[j + 1] - x[j]) * (xv - x[j]);" << std::endl;
3228 out <<
"}" << std::endl;
3232 out <<
" " << std::endl;
3235 static Int_t f1Number = 0;
3236 TString f1Name(GetName());
3237 const char *l = strstr(option,
"#");
3239 sscanf(&l[1],
"%d", &f1Number);
3245 const char *addToGlobList = fParent ?
", TF1::EAddToList::kNo" :
", TF1::EAddToList::kDefault";
3248 out <<
" TF1 *" << f1Name.Data() <<
" = new TF1(" << quote << GetName() << quote <<
"," << quote << GetTitle() << quote <<
"," << fXmin <<
"," << fXmax << addToGlobList <<
");" << std::endl;
3250 out <<
" " << f1Name.Data() <<
"->SetNpx(" << fNpx <<
");" << std::endl;
3253 out <<
" TF1 *" << f1Name.Data() <<
" = new TF1(" << quote <<
"*" << GetName() << quote <<
"," << fXmin <<
"," << fXmax <<
"," << GetNpar() <<
");" << std::endl;
3254 out <<
" //The original function : " << GetTitle() <<
" had originally been created by:" << std::endl;
3255 out <<
" //TF1 *" << GetName() <<
" = new TF1(" << quote << GetName() << quote <<
"," << GetTitle() <<
"," << fXmin <<
"," << fXmax <<
"," << GetNpar();
3256 out <<
", 1" << addToGlobList <<
");" << std::endl;
3257 out <<
" " << f1Name.Data() <<
"->SetRange(" << fXmin <<
"," << fXmax <<
");" << std::endl;
3258 out <<
" " << f1Name.Data() <<
"->SetName(" << quote << GetName() << quote <<
");" << std::endl;
3259 out <<
" " << f1Name.Data() <<
"->SetTitle(" << quote << GetTitle() << quote <<
");" << std::endl;
3261 out <<
" " << f1Name.Data() <<
"->SetNpx(" << fNpx <<
");" << std::endl;
3263 Double_t dx = (fXmax - fXmin) / fNpx;
3265 Double_t *parameters = GetParameters();
3266 InitArgs(xv, parameters);
3267 for (i = 0; i <= fNpx; i++) {
3268 xv[0] = fXmin + dx * i;
3269 Double_t save = EvalPar(xv, parameters);
3270 out <<
" " << f1Name.Data() <<
"->SetSavedPoint(" << i <<
"," << save <<
");" << std::endl;
3272 out <<
" " << f1Name.Data() <<
"->SetSavedPoint(" << fNpx + 1 <<
"," << fXmin <<
");" << std::endl;
3273 out <<
" " << f1Name.Data() <<
"->SetSavedPoint(" << fNpx + 2 <<
"," << fXmax <<
");" << std::endl;
3276 if (TestBit(kNotDraw)) {
3277 out <<
" " << f1Name.Data() <<
"->SetBit(TF1::kNotDraw);" << std::endl;
3279 if (GetFillColor() != 0) {
3280 if (GetFillColor() > 228) {
3281 TColor::SaveColor(out, GetFillColor());
3282 out <<
" " << f1Name.Data() <<
"->SetFillColor(ci);" << std::endl;
3284 out <<
" " << f1Name.Data() <<
"->SetFillColor(" << GetFillColor() <<
");" << std::endl;
3286 if (GetFillStyle() != 1001) {
3287 out <<
" " << f1Name.Data() <<
"->SetFillStyle(" << GetFillStyle() <<
");" << std::endl;
3289 if (GetMarkerColor() != 1) {
3290 if (GetMarkerColor() > 228) {
3291 TColor::SaveColor(out, GetMarkerColor());
3292 out <<
" " << f1Name.Data() <<
"->SetMarkerColor(ci);" << std::endl;
3294 out <<
" " << f1Name.Data() <<
"->SetMarkerColor(" << GetMarkerColor() <<
");" << std::endl;
3296 if (GetMarkerStyle() != 1) {
3297 out <<
" " << f1Name.Data() <<
"->SetMarkerStyle(" << GetMarkerStyle() <<
");" << std::endl;
3299 if (GetMarkerSize() != 1) {
3300 out <<
" " << f1Name.Data() <<
"->SetMarkerSize(" << GetMarkerSize() <<
");" << std::endl;
3302 if (GetLineColor() != 1) {
3303 if (GetLineColor() > 228) {
3304 TColor::SaveColor(out, GetLineColor());
3305 out <<
" " << f1Name.Data() <<
"->SetLineColor(ci);" << std::endl;
3307 out <<
" " << f1Name.Data() <<
"->SetLineColor(" << GetLineColor() <<
");" << std::endl;
3309 if (GetLineWidth() != 4) {
3310 out <<
" " << f1Name.Data() <<
"->SetLineWidth(" << GetLineWidth() <<
");" << std::endl;
3312 if (GetLineStyle() != 1) {
3313 out <<
" " << f1Name.Data() <<
"->SetLineStyle(" << GetLineStyle() <<
");" << std::endl;
3315 if (GetChisquare() != 0) {
3316 out <<
" " << f1Name.Data() <<
"->SetChisquare(" << GetChisquare() <<
");" << std::endl;
3317 out <<
" " << f1Name.Data() <<
"->SetNDF(" << GetNDF() <<
");" << std::endl;
3320 if (GetXaxis()) GetXaxis()->SaveAttributes(out, f1Name.Data(),
"->GetXaxis()");
3321 if (GetYaxis()) GetYaxis()->SaveAttributes(out, f1Name.Data(),
"->GetYaxis()");
3323 Double_t parmin, parmax;
3324 for (i = 0; i < GetNpar(); i++) {
3325 out <<
" " << f1Name.Data() <<
"->SetParameter(" << i <<
"," << GetParameter(i) <<
");" << std::endl;
3326 out <<
" " << f1Name.Data() <<
"->SetParError(" << i <<
"," << GetParError(i) <<
");" << std::endl;
3327 GetParLimits(i, parmin, parmax);
3328 out <<
" " << f1Name.Data() <<
"->SetParLimits(" << i <<
"," << parmin <<
"," << parmax <<
");" << std::endl;
3330 if (!strstr(option,
"nodraw")) {
3331 out <<
" " << f1Name.Data() <<
"->Draw("
3332 << quote << option << quote <<
");" << std::endl;
3342 void TF1::SetCurrent(TF1 *f1)
3354 void TF1::SetFitResult(
const ROOT::Fit::FitResult &result,
const Int_t *indpar)
3356 Int_t npar = GetNpar();
3357 if (result.IsEmpty()) {
3358 Warning(
"SetFitResult",
"Empty Fit result - nothing is set in TF1");
3361 if (indpar == 0 && npar != (
int) result.NPar()) {
3362 Error(
"SetFitResult",
"Invalid Fit result passed - number of parameter is %d , different than TF1::GetNpar() = %d", npar, result.NPar());
3365 if (result.Chi2() > 0)
3366 SetChisquare(result.Chi2());
3368 SetChisquare(result.MinFcnValue());
3370 SetNDF(result.Ndf());
3371 SetNumberFitPoints(result.Ndf() + result.NFreeParameters());
3374 for (Int_t i = 0; i < npar; ++i) {
3375 Int_t ipar = (indpar != 0) ? indpar[i] : i;
3376 if (ipar < 0)
continue;
3377 GetParameters()[i] = result.Parameter(ipar);
3379 if (ipar < (
int) result.Errors().size())
3380 fParErrors[i] = result.Error(ipar);
3393 void TF1::SetMaximum(Double_t maximum)
3396 if (fHistogram) fHistogram->SetMaximum(maximum);
3397 if (gPad) gPad->Modified();
3406 void TF1::SetMinimum(Double_t minimum)
3409 if (fHistogram) fHistogram->SetMinimum(minimum);
3410 if (gPad) gPad->Modified();
3418 void TF1::SetNDF(Int_t ndf)
3432 void TF1::SetNpx(Int_t npx)
3434 const Int_t minPx = 4;
3435 Int_t maxPx = 10000000;
3436 if (GetNdim() > 1) maxPx = 10000;
3437 if (npx >= minPx && npx <= maxPx) {
3440 if (npx < minPx) fNpx = minPx;
3441 if (npx > maxPx) fNpx = maxPx;
3442 Warning(
"SetNpx",
"Number of points must be >=%d && <= %d, fNpx set to %d", minPx, maxPx, fNpx);
3449 void TF1::SetParName(Int_t ipar,
const char *name)
3452 if (ipar < 0 || ipar >= GetNpar())
return;
3453 fFormula->SetParName(ipar, name);
3455 fParams->SetParName(ipar, name);
3461 void TF1::SetParNames(
const char *name0,
const char *name1,
const char *name2,
const char *name3,
const char *name4,
3462 const char *name5,
const char *name6,
const char *name7,
const char *name8,
const char *name9,
const char *name10)
3465 fFormula->SetParNames(name0, name1, name2, name3, name4, name5, name6, name7, name8, name9, name10);
3467 fParams->SetParNames(name0, name1, name2, name3, name4, name5, name6, name7, name8, name9, name10);
3472 void TF1::SetParError(Int_t ipar, Double_t error)
3474 if (ipar < 0 || ipar > GetNpar() - 1)
return;
3475 fParErrors[ipar] = error;
3483 void TF1::SetParErrors(
const Double_t *errors)
3485 if (!errors)
return;
3486 for (Int_t i = 0; i < GetNpar(); i++) fParErrors[i] = errors[i];
3497 void TF1::SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax)
3499 Int_t npar = GetNpar();
3500 if (ipar < 0 || ipar > npar - 1)
return;
3501 if (
int(fParMin.size()) != npar) {
3502 fParMin.resize(npar);
3504 if (
int(fParMax.size()) != npar) {
3505 fParMax.resize(npar);
3507 fParMin[ipar] = parmin;
3508 fParMax[ipar] = parmax;
3518 void TF1::SetRange(Double_t xmin, Double_t xmax)
3522 if (fType == EFType::kCompositionFcn && fComposition) {
3523 fComposition->SetRange(xmin, xmax);
3532 void TF1::SetSavedPoint(Int_t point, Double_t value)
3534 if (fSave.size() == 0) {
3535 fSave.resize(fNpx + 3);
3537 if (point < 0 || point >=
int(fSave.size()))
return;
3538 fSave[point] = value;
3548 void TF1::SetTitle(
const char *title)
3552 if (!fHistogram)
return;
3553 fHistogram->SetTitle(title);
3554 if (gPad) gPad->Modified();
3561 void TF1::Streamer(TBuffer &b)
3563 if (b.IsReading()) {
3565 Version_t v = b.ReadVersion(&R__s, &R__c);
3572 b.ReadClassBuffer(TF1::Class(),
this, v, R__s, R__c);
3573 if (!TestBit(kNotGlobal)) {
3574 R__LOCKGUARD(gROOTMutex);
3575 gROOT->GetListOfFunctions()->Add(
this);
3578 fComposition = std::unique_ptr<TF1AbsComposition>(fComposition_ptr);
3581 ROOT::v5::TF1Data fold;
3583 fold.Streamer(b, v, R__s, R__c, TF1::Class());
3585 ((TF1v5Convert *)
this)->Convert(fold);
3593 if (fType > 0 && fSave.empty() && fType != EFType::kCompositionFcn) {
3595 Save(fXmin, fXmax, 0, 0, 0, 0);
3597 if (fType == EFType::kCompositionFcn)
3598 fComposition_ptr = fComposition.get();
3600 fComposition_ptr =
nullptr;
3601 b.WriteClassBuffer(TF1::Class(),
this);
3619 if (!fIntegral.empty()) {
3627 fNormalized =
false;
3628 fNormIntegral = Integral(fXmin, fXmax, 0.0);
3635 if (fType == EFType::kCompositionFcn && fComposition) {
3637 fComposition->SetParameters(GetParameters());
3639 fComposition->Update();
3650 void TF1::RejectPoint(Bool_t reject)
3652 fgRejectPoint = reject;
3659 Bool_t TF1::RejectedPoint()
3661 return fgRejectPoint;
3669 Double_t TF1::Moment(Double_t n, Double_t a, Double_t b,
const Double_t *params, Double_t epsilon)
3674 TF1_EvalWrapper func(
this, params, kTRUE, n);
3676 ROOT::Math::GaussIntegrator giod;
3678 giod.SetFunction(func);
3679 giod.SetRelTolerance(epsilon);
3681 Double_t norm = giod.Integral(a, b);
3683 Error(
"Moment",
"Integral zero over range");
3689 ROOT::Math::Functor1D xnfunc(&func, &TF1_EvalWrapper::EvalNMom);
3690 giod.SetFunction(xnfunc);
3692 Double_t res = giod.Integral(a, b) / norm;
3706 Double_t TF1::CentralMoment(Double_t n, Double_t a, Double_t b,
const Double_t *params, Double_t epsilon)
3708 TF1_EvalWrapper func(
this, params, kTRUE, n);
3710 ROOT::Math::GaussIntegrator giod;
3712 giod.SetFunction(func);
3713 giod.SetRelTolerance(epsilon);
3715 Double_t norm = giod.Integral(a, b);
3717 Error(
"Moment",
"Integral zero over range");
3723 ROOT::Math::Functor1D xfunc(&func, &TF1_EvalWrapper::EvalFirstMom);
3724 giod.SetFunction(xfunc);
3727 Double_t xbar = giod.Integral(a, b) / norm;
3731 ROOT::Math::Functor1D xnfunc(&func, &TF1_EvalWrapper::EvalNMom);
3732 giod.SetFunction(xnfunc);
3734 Double_t res = giod.Integral(a, b) / norm;
3746 void TF1::CalcGaussLegendreSamplingPoints(TGraph *g, Double_t eps)
3749 CalcGaussLegendreSamplingPoints(g->GetN(), g->GetX(), g->GetY(), eps);
3760 TGraph *TF1::CalcGaussLegendreSamplingPoints(Int_t num, Double_t eps)
3765 TGraph *g =
new TGraph(num);
3766 CalcGaussLegendreSamplingPoints(g->GetN(), g->GetX(), g->GetY(), eps);
3793 void TF1::CalcGaussLegendreSamplingPoints(Int_t num, Double_t *x, Double_t *w, Double_t eps)
3797 ROOT::Math::GaussLegendreIntegrator gli(num, eps);
3798 gli.GetWeightVectors(x, w);
3813 Int_t TF1Parameters::GetParNumber(
const char *name)
const
3815 for (
unsigned int i = 0; i < fParNames.size(); ++i) {
3816 if (fParNames[i] == std::string(name))
return i;
3824 void TF1Parameters::SetParameters(Double_t p0, Double_t p1, Double_t p2, Double_t p3, Double_t p4,
3825 Double_t p5, Double_t p6, Double_t p7, Double_t p8,
3826 Double_t p9, Double_t p10)
3828 unsigned int npar = fParameters.size();
3829 if (npar > 0) fParameters[0] = p0;
3830 if (npar > 1) fParameters[1] = p1;
3831 if (npar > 2) fParameters[2] = p2;
3832 if (npar > 3) fParameters[3] = p3;
3833 if (npar > 4) fParameters[4] = p4;
3834 if (npar > 5) fParameters[5] = p5;
3835 if (npar > 6) fParameters[6] = p6;
3836 if (npar > 7) fParameters[7] = p7;
3837 if (npar > 8) fParameters[8] = p8;
3838 if (npar > 9) fParameters[9] = p9;
3839 if (npar > 10) fParameters[10] = p10;
3845 void TF1Parameters::SetParNames(
const char *name0,
const char *name1,
const char *name2,
const char *name3,
3846 const char *name4,
const char *name5,
const char *name6,
const char *name7,
3847 const char *name8,
const char *name9,
const char *name10)
3849 unsigned int npar = fParNames.size();
3850 if (npar > 0) fParNames[0] = name0;
3851 if (npar > 1) fParNames[1] = name1;
3852 if (npar > 2) fParNames[2] = name2;
3853 if (npar > 3) fParNames[3] = name3;
3854 if (npar > 4) fParNames[4] = name4;
3855 if (npar > 5) fParNames[5] = name5;
3856 if (npar > 6) fParNames[6] = name6;
3857 if (npar > 7) fParNames[7] = name7;
3858 if (npar > 8) fParNames[8] = name8;
3859 if (npar > 9) fParNames[9] = name9;
3860 if (npar > 10) fParNames[10] = name10;