File indexing completed on 2025-09-15 09:12:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef ROOT_TF1
0014 #define ROOT_TF1
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "RConfigure.h"
0025 #include <functional>
0026 #include <cassert>
0027 #include <memory>
0028 #include <string>
0029 #include <vector>
0030 #include "TFormula.h"
0031 #include "TMethodCall.h"
0032 #include "TAttLine.h"
0033 #include "TAttFill.h"
0034 #include "TAttMarker.h"
0035 #include "TF1AbsComposition.h"
0036 #include "TMath.h"
0037 #include "TMatrixDSymfwd.h"
0038 #include "Math/Types.h"
0039 #include "Math/ParamFunctor.h"
0040
0041 #include <string>
0042
0043 class TF1;
0044 class TH1;
0045 class TAxis;
0046 class TRandom;
0047
0048 namespace ROOT {
0049 namespace Fit {
0050 class FitResult;
0051 }
0052 }
0053
0054 class TF1Parameters {
0055 public:
0056 TF1Parameters() {}
0057 TF1Parameters(Int_t npar) :
0058 fParameters(std::vector<Double_t>(npar)),
0059 fParNames(std::vector<std::string>(npar))
0060 {
0061 for (int i = 0; i < npar; ++i) {
0062 fParNames[i] = std::string(TString::Format("p%d", i).Data());
0063 }
0064 }
0065
0066 TF1Parameters(const TF1Parameters &rhs) :
0067 fParameters(rhs.fParameters),
0068 fParNames(rhs.fParNames)
0069 {}
0070
0071 TF1Parameters &operator=(const TF1Parameters &rhs)
0072 {
0073 if (&rhs == this) return *this;
0074 fParameters = rhs.fParameters;
0075 fParNames = rhs.fParNames;
0076 return *this;
0077 }
0078 virtual ~TF1Parameters() {}
0079
0080
0081 Double_t GetParameter(Int_t iparam) const
0082 {
0083 return (CheckIndex(iparam)) ? fParameters[iparam] : 0;
0084 }
0085 Double_t GetParameter(const char *name) const
0086 {
0087 return GetParameter(GetParNumber(name));
0088 }
0089 const Double_t *GetParameters() const
0090 {
0091 return fParameters.data();
0092 }
0093 const std::vector<double> &ParamsVec() const
0094 {
0095 return fParameters;
0096 }
0097
0098 Int_t GetParNumber(const char *name) const;
0099
0100 const char *GetParName(Int_t iparam) const
0101 {
0102 return (CheckIndex(iparam)) ? fParNames[iparam].c_str() : "";
0103 }
0104
0105
0106
0107 void SetParameter(Int_t iparam, Double_t value)
0108 {
0109 if (!CheckIndex(iparam)) return;
0110 fParameters[iparam] = value;
0111 }
0112 void SetParameters(const Double_t *params)
0113 {
0114 std::copy(params, params + fParameters.size(), fParameters.begin());
0115 }
0116 template <typename... Args>
0117 void SetParameters(Double_t arg1, Args &&... args);
0118
0119 void SetParameter(const char *name, Double_t value)
0120 {
0121 SetParameter(GetParNumber(name), value);
0122 }
0123 void SetParName(Int_t iparam, const char *name)
0124 {
0125 if (!CheckIndex(iparam)) return;
0126 fParNames[iparam] = std::string(name);
0127 }
0128 template <typename... Args>
0129 void SetParNames(Args &&... args);
0130
0131 ClassDef(TF1Parameters, 1)
0132 private:
0133
0134 bool CheckIndex(Int_t i) const
0135 {
0136 return (i >= 0 && i < int(fParameters.size()));
0137 }
0138
0139 std::vector<Double_t> fParameters;
0140 std::vector<std::string> fParNames;
0141 };
0142
0143
0144
0145 template <typename... Args>
0146 void TF1Parameters::SetParameters(Double_t arg1, Args &&...args)
0147 {
0148 int i = 0;
0149 for (double val : {arg1, static_cast<Double_t>(args)...}) {
0150 if(!TMath::IsNaN(val)) SetParameter(i++, val);
0151 }
0152 }
0153
0154
0155
0156 template <typename... Args>
0157 void TF1Parameters::SetParNames(Args &&...args)
0158 {
0159 int i = 0;
0160 for (auto name : {static_cast<std::string const&>(args)...}) {
0161 if(!name.empty()) SetParName(i++, name.c_str());
0162 }
0163 }
0164
0165 namespace ROOT {
0166 namespace Internal {
0167
0168
0169 template<class Func>
0170 struct TF1Builder {
0171 static void Build(TF1 *f, Func func);
0172 };
0173
0174 template<class Func>
0175 struct TF1Builder<Func *> {
0176 static void Build(TF1 *f, Func *func);
0177 };
0178
0179
0180
0181 template<typename T>
0182 struct GetFunctorType {
0183 };
0184
0185 template<typename F, typename T>
0186 struct GetFunctorType<T(F::*)(const T *, const double *)> {
0187 using type = T;
0188 };
0189
0190 template<typename F, typename T>
0191 struct GetFunctorType<T(F::*)(const T *, const double *) const> {
0192 using type = T;
0193 };
0194
0195 template<typename F, typename T>
0196 struct GetFunctorType<T(F::*)(T *, double *)> {
0197 using type = T;
0198 };
0199
0200 template<typename F, typename T>
0201 struct GetFunctorType<T(F::*)(T *, double *) const> {
0202 using type = T;
0203 };
0204
0205
0206
0207 template<typename T, typename F>
0208 auto GetTheRightOp(T(F::*opPtr)(const T *, const double *)) -> decltype(opPtr)
0209 {
0210 return opPtr;
0211 }
0212
0213 template<typename T, typename F>
0214 auto GetTheRightOp(T(F::*opPtr)(const T *, const double *) const) -> decltype(opPtr)
0215 {
0216 return opPtr;
0217 }
0218
0219 template<typename T, typename F>
0220 auto GetTheRightOp(T(F::*opPtr)(T *, double *)) -> decltype(opPtr)
0221 {
0222 return opPtr;
0223 }
0224
0225 template<typename T, typename F>
0226 auto GetTheRightOp(T(F::*opPtr)(T *, double *) const) -> decltype(opPtr)
0227 {
0228 return opPtr;
0229 }
0230 }
0231 }
0232
0233
0234 class TF1 : public TNamed, public TAttLine, public TAttFill, public TAttMarker {
0235
0236 template<class Func>
0237 friend struct ROOT::Internal::TF1Builder;
0238
0239 public:
0240
0241 enum class EAddToList {
0242 kDefault,
0243 kAdd,
0244 kNo
0245 };
0246
0247
0248 struct TF1FunctorPointer {
0249 virtual ~TF1FunctorPointer() {}
0250 virtual TF1FunctorPointer * Clone() const = 0;
0251 };
0252
0253 protected:
0254
0255 enum EFType {
0256 kFormula = 0,
0257 kPtrScalarFreeFcn,
0258 kInterpreted,
0259 kTemplVec,
0260 kTemplScalar,
0261 kCompositionFcn
0262 };
0263
0264 Double_t fXmin{-1111};
0265 Double_t fXmax{-1111};
0266 Int_t fNpar{};
0267 Int_t fNdim{};
0268 Int_t fNpx{100};
0269 EFType fType{EFType::kTemplScalar};
0270 Int_t fNpfits{};
0271 Int_t fNDF{};
0272 Double_t fChisquare{};
0273 Double_t fMinimum{-1111};
0274 Double_t fMaximum{-1111};
0275 std::vector<Double_t> fParErrors;
0276 std::vector<Double_t> fParMin;
0277 std::vector<Double_t> fParMax;
0278 std::vector<Double_t> fSave;
0279 std::vector<Double_t> fIntegral;
0280 std::vector<Double_t> fAlpha;
0281 std::vector<Double_t> fBeta;
0282 std::vector<Double_t> fGamma;
0283 TObject *fParent{nullptr};
0284 TH1 *fHistogram{nullptr};
0285 std::unique_ptr<TMethodCall> fMethodCall;
0286 Bool_t fNormalized{false};
0287 Double_t fNormIntegral{};
0288 std::unique_ptr<TF1FunctorPointer> fFunctor;
0289 std::unique_ptr<TFormula> fFormula;
0290 std::unique_ptr<TF1Parameters> fParams;
0291 std::unique_ptr<TF1AbsComposition> fComposition;
0292
0293
0294 TF1(EFType functionType, const char *name, Double_t xmin, Double_t xmax, Int_t npar, Int_t ndim, EAddToList addToGlobList, TF1Parameters *params = nullptr, TF1FunctorPointer * functor = nullptr):
0295 TNamed(name, name), TAttLine(), TAttFill(), TAttMarker(), fXmin(xmin), fXmax(xmax), fNpar(npar), fNdim(ndim),
0296 fType(functionType), fParErrors(npar), fParMin(npar), fParMax(npar)
0297 {
0298 fParams.reset(params);
0299 fFunctor.reset(functor);
0300 DoInitialize(addToGlobList);
0301 }
0302
0303 private:
0304
0305 void DefineNSUMTerm(TObjArray *newFuncs, TObjArray *coeffNames,
0306 TString &fullFormula,
0307 TString &formula, int termStart, int termEnd,
0308 Double_t xmin, Double_t xmax);
0309 int TermCoeffLength(TString &term);
0310
0311 protected:
0312
0313 template <class T>
0314 struct TF1FunctorPointerImpl: TF1FunctorPointer {
0315 TF1FunctorPointerImpl(const ROOT::Math::ParamFunctorTempl<T> &func): fImpl(func) {};
0316 TF1FunctorPointerImpl(const std::function<T(const T *f, const Double_t *param)> &func) : fImpl(func){};
0317 ~TF1FunctorPointerImpl() override {}
0318 TF1FunctorPointer * Clone() const override { return new TF1FunctorPointerImpl<T>(fImpl); }
0319 ROOT::Math::ParamFunctorTempl<T> fImpl;
0320 };
0321
0322
0323
0324
0325 static std::atomic<Bool_t> fgAbsValue;
0326 static Bool_t fgRejectPoint;
0327 static std::atomic<Bool_t> fgAddToGlobList;
0328 static TF1 *fgCurrent;
0329
0330
0331
0332 void DoInitialize(EAddToList addToGlobList);
0333
0334 void IntegrateForNormalization();
0335
0336 Bool_t ComputeCdfTable(Option_t * opt);
0337
0338 virtual Double_t GetMinMaxNDim(Double_t *x , Bool_t findmax, Double_t epsilon = 0, Int_t maxiter = 0) const;
0339 virtual void GetRange(Double_t *xmin, Double_t *xmax) const;
0340 virtual TH1 *DoCreateHistogram(Double_t xmin, Double_t xmax, Bool_t recreate = kFALSE);
0341
0342 TString ProvideSaveName(Option_t *option);
0343
0344 public:
0345
0346
0347 enum EStatusBits {
0348 kNotGlobal = BIT(10),
0349 kNotDraw = BIT(9)
0350 };
0351
0352 TF1();
0353 TF1(const char *name, const char *formula, Double_t xmin = 0, Double_t xmax = 1, EAddToList addToGlobList = EAddToList::kDefault, bool vectorize = false);
0354 TF1(const char *name, const char *formula, Double_t xmin, Double_t xmax, Option_t * option);
0355 TF1(const char *name, Double_t xmin, Double_t xmax, Int_t npar, Int_t ndim = 1, EAddToList addToGlobList = EAddToList::kDefault);
0356 TF1(const char *name, Double_t (*fcn)(Double_t *, Double_t *), Double_t xmin = 0, Double_t xmax = 1, Int_t npar = 0, Int_t ndim = 1, EAddToList addToGlobList = EAddToList::kDefault);
0357 TF1(const char *name, Double_t (*fcn)(const Double_t *, const Double_t *), Double_t xmin = 0, Double_t xmax = 1, Int_t npar = 0, Int_t ndim = 1, EAddToList addToGlobList = EAddToList::kDefault);
0358
0359 template <class T>
0360 TF1(const char *name, std::function<T(const T *data, const Double_t *param)> &fcn, Double_t xmin = 0, Double_t xmax = 1, Int_t npar = 0, Int_t ndim = 1, EAddToList addToGlobList = EAddToList::kDefault):
0361 TF1(EFType::kTemplScalar, name, xmin, xmax, npar, ndim, addToGlobList, new TF1Parameters(npar), new TF1FunctorPointerImpl<T>(fcn))
0362 {
0363 fType = std::is_same<T, double>::value ? TF1::EFType::kTemplScalar : TF1::EFType::kTemplVec;
0364 }
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 template <class T>
0384 TF1(const char *name, T(*fcn)(const T *, const Double_t *), Double_t xmin = 0, Double_t xmax = 1, Int_t npar = 0, Int_t ndim = 1, EAddToList addToGlobList = EAddToList::kDefault):
0385 TF1(EFType::kTemplVec, name, xmin, xmax, npar, ndim, addToGlobList, new TF1Parameters(npar), new TF1FunctorPointerImpl<T>(fcn))
0386 {}
0387
0388
0389 TF1(const char *name, ROOT::Math::ParamFunctor f, Double_t xmin = 0, Double_t xmax = 1, Int_t npar = 0, Int_t ndim = 1, EAddToList addToGlobList = EAddToList::kDefault);
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399 template <typename Func>
0400 TF1(const char *name, Func f, Double_t xmin, Double_t xmax, Int_t npar, Int_t ndim = 1, EAddToList addToGlobList = EAddToList::kDefault) :
0401 TF1(EFType::kTemplScalar, name, xmin, xmax, npar, ndim, addToGlobList)
0402 {
0403
0404 ROOT::Internal::TF1Builder<Func>::Build(this, f);
0405 }
0406
0407
0408 template <typename Func>
0409 TF1(const char *name, Func f, Double_t xmin, Double_t xmax, Int_t npar, const char *, EAddToList addToGlobList = EAddToList::kDefault) :
0410 TF1(EFType::kTemplScalar, name, xmin, xmax, npar, 1, addToGlobList, new TF1Parameters(npar))
0411 {
0412 ROOT::Internal::TF1Builder<Func>::Build(this, f);
0413 }
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424 template <class PtrObj, typename MemFn>
0425 TF1(const char *name, const PtrObj &p, MemFn memFn, Double_t xmin, Double_t xmax, Int_t npar, Int_t ndim = 1, EAddToList addToGlobList = EAddToList::kDefault) :
0426 TF1(EFType::kTemplScalar, name, xmin, xmax, npar, ndim, addToGlobList, new TF1Parameters(npar), new TF1FunctorPointerImpl<double>(ROOT::Math::ParamFunctor(p, memFn)))
0427 {}
0428
0429
0430 template <class PtrObj, typename MemFn>
0431 TF1(const char *name, const PtrObj &p, MemFn memFn, Double_t xmin, Double_t xmax, Int_t npar, const char *, const char *, EAddToList addToGlobList = EAddToList::kDefault) :
0432 TF1(EFType::kTemplScalar, name, xmin, xmax, npar, 1, addToGlobList, new TF1Parameters(npar), new TF1FunctorPointerImpl<double>(ROOT::Math::ParamFunctor(p, memFn)))
0433 {}
0434
0435 TF1(const TF1 &f1);
0436 TF1 &operator=(const TF1 &rhs);
0437 ~TF1() override;
0438 virtual void AddParameter(const TString &name, Double_t value)
0439 {
0440 if (fFormula) fFormula->AddParameter(name, value);
0441 }
0442
0443
0444
0445 virtual Bool_t AddToGlobalList(Bool_t on = kTRUE);
0446 static Bool_t DefaultAddToGlobalList(Bool_t on = kTRUE);
0447 void Browse(TBrowser *b) override;
0448 void Copy(TObject &f1) const override;
0449 TObject *Clone(const char *newname = nullptr) const override;
0450 virtual Double_t Derivative(Double_t x, Double_t *params = nullptr, Double_t epsilon = 0.001) const;
0451 virtual Double_t Derivative2(Double_t x, Double_t *params = nullptr, Double_t epsilon = 0.001) const;
0452 virtual Double_t Derivative3(Double_t x, Double_t *params = nullptr, Double_t epsilon = 0.001) const;
0453 static Double_t DerivativeError();
0454 Int_t DistancetoPrimitive(Int_t px, Int_t py) override;
0455 void Draw(Option_t *option = "") override;
0456 virtual TF1 *DrawCopy(Option_t *option = "") const;
0457 virtual TObject *DrawDerivative(Option_t *option = "al");
0458 virtual TObject *DrawIntegral(Option_t *option = "al");
0459 virtual void DrawF1(Double_t xmin, Double_t xmax, Option_t *option = "");
0460 virtual Double_t Eval(Double_t x, Double_t y = 0, Double_t z = 0, Double_t t = 0) const;
0461
0462 virtual Double_t EvalPar(const Double_t *x, const Double_t *params = nullptr);
0463 template <class T> T EvalPar(const T *x, const Double_t *params = nullptr);
0464 virtual Double_t operator()(Double_t x, Double_t y = 0, Double_t z = 0, Double_t t = 0) const;
0465 template <class T> T operator()(const T *x, const Double_t *params = nullptr);
0466 Double_t EvalUncertainty(Double_t x, const TMatrixDSym *covMatrix = nullptr) const;
0467 void ExecuteEvent(Int_t event, Int_t px, Int_t py) override;
0468 virtual void FixParameter(Int_t ipar, Double_t value);
0469
0470 Bool_t HasSave() const { return !fSave.empty(); }
0471 bool IsVectorized()
0472 {
0473 return (fType == EFType::kTemplVec) || (fType == EFType::kFormula && fFormula && fFormula->IsVectorized());
0474 }
0475
0476 Double_t GetChisquare() const
0477 {
0478 return fChisquare;
0479 }
0480 virtual TH1 *GetHistogram() const;
0481 virtual TH1 *CreateHistogram()
0482 {
0483 return DoCreateHistogram(fXmin, fXmax);
0484 }
0485 virtual TFormula *GetFormula()
0486 {
0487 return fFormula.get();
0488 }
0489 virtual const TFormula *GetFormula() const
0490 {
0491 return fFormula.get();
0492 }
0493 virtual TString GetExpFormula(Option_t *option = "") const
0494 {
0495 return (fFormula) ? fFormula->GetExpFormula(option) : TString();
0496 }
0497 virtual const TObject *GetLinearPart(Int_t i) const
0498 {
0499 return (fFormula) ? fFormula->GetLinearPart(i) : nullptr;
0500 }
0501 virtual Double_t GetMaximum(Double_t xmin = 0, Double_t xmax = 0, Double_t epsilon = 1.E-10, Int_t maxiter = 100, Bool_t logx = false) const;
0502 virtual Double_t GetMinimum(Double_t xmin = 0, Double_t xmax = 0, Double_t epsilon = 1.E-10, Int_t maxiter = 100, Bool_t logx = false) const;
0503 virtual Double_t GetMaximumX(Double_t xmin = 0, Double_t xmax = 0, Double_t epsilon = 1.E-10, Int_t maxiter = 100, Bool_t logx = false) const;
0504 virtual Double_t GetMinimumX(Double_t xmin = 0, Double_t xmax = 0, Double_t epsilon = 1.E-10, Int_t maxiter = 100, Bool_t logx = false) const;
0505 virtual Double_t GetMaximumStored() const
0506 {
0507 return fMaximum;
0508 }
0509 virtual Double_t GetMinimumStored() const
0510 {
0511 return fMinimum;
0512 }
0513 virtual Int_t GetNpar() const
0514 {
0515 return fNpar;
0516 }
0517 virtual Int_t GetNdim() const
0518 {
0519 return fNdim;
0520 }
0521 virtual Int_t GetNDF() const;
0522 virtual Int_t GetNpx() const
0523 {
0524 return fNpx;
0525 }
0526 TMethodCall *GetMethodCall() const
0527 {
0528 return fMethodCall.get();
0529 }
0530 virtual Int_t GetNumber() const
0531 {
0532 return (fFormula) ? fFormula->GetNumber() : 0;
0533 }
0534 virtual Int_t GetNumberFreeParameters() const;
0535 virtual Int_t GetNumberFitPoints() const
0536 {
0537 return fNpfits;
0538 }
0539 char *GetObjectInfo(Int_t px, Int_t py) const override;
0540 TObject *GetParent() const
0541 {
0542 return fParent;
0543 }
0544 virtual Double_t GetParameter(Int_t ipar) const
0545 {
0546 return (fFormula) ? fFormula->GetParameter(ipar) : fParams->GetParameter(ipar);
0547 }
0548 virtual Double_t GetParameter(const TString &name) const
0549 {
0550 return (fFormula) ? fFormula->GetParameter(name) : fParams->GetParameter(name);
0551 }
0552 virtual Double_t *GetParameters() const
0553 {
0554 return (fFormula) ? fFormula->GetParameters() : const_cast<Double_t *>(fParams->GetParameters());
0555 }
0556 virtual void GetParameters(Double_t *params)
0557 {
0558 if (fFormula) fFormula->GetParameters(params);
0559 else std::copy(fParams->ParamsVec().begin(), fParams->ParamsVec().end(), params);
0560 }
0561 virtual const char *GetParName(Int_t ipar) const
0562 {
0563 return (fFormula) ? fFormula->GetParName(ipar) : fParams->GetParName(ipar);
0564 }
0565 virtual Int_t GetParNumber(const char *name) const
0566 {
0567 return (fFormula) ? fFormula->GetParNumber(name) : fParams->GetParNumber(name);
0568 }
0569 virtual Double_t GetParError(Int_t ipar) const;
0570 virtual Double_t GetParError(const char *name) const
0571 {
0572 return GetParError(GetParNumber(name));
0573 }
0574 virtual const Double_t *GetParErrors() const
0575 {
0576 return fParErrors.data();
0577 }
0578 virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const;
0579 virtual Double_t GetProb() const;
0580 virtual Int_t GetQuantiles(Int_t n, Double_t *xp, const Double_t *p);
0581 virtual Double_t GetRandom(TRandom * rng = nullptr, Option_t * opt = nullptr);
0582 virtual Double_t GetRandom(Double_t xmin, Double_t xmax, TRandom * rng = nullptr, Option_t * opt = nullptr);
0583 virtual void GetRange(Double_t &xmin, Double_t &xmax) const;
0584 virtual void GetRange(Double_t &xmin, Double_t &ymin, Double_t &xmax, Double_t &ymax) const;
0585 virtual void GetRange(Double_t &xmin, Double_t &ymin, Double_t &zmin, Double_t &xmax, Double_t &ymax, Double_t &zmax) const;
0586 virtual Double_t GetSave(const Double_t *x);
0587 virtual Double_t GetX(Double_t y, Double_t xmin = 0, Double_t xmax = 0, Double_t epsilon = 1.E-10, Int_t maxiter = 100, Bool_t logx = false) const;
0588 virtual Double_t GetXmin() const
0589 {
0590 return fXmin;
0591 }
0592 virtual Double_t GetXmax() const
0593 {
0594 return fXmax;
0595 }
0596 TAxis *GetXaxis() const ;
0597 TAxis *GetYaxis() const ;
0598 TAxis *GetZaxis() const ;
0599 virtual Double_t GetVariable(const TString &name)
0600 {
0601 return (fFormula) ? fFormula->GetVariable(name) : 0;
0602 }
0603 virtual Double_t GradientPar(Int_t ipar, const Double_t *x, Double_t eps = 0.01) const;
0604 template <class T>
0605 T GradientPar(Int_t ipar, const T *x, Double_t eps = 0.01) const;
0606 template <class T>
0607 T GradientParTempl(Int_t ipar, const T *x, Double_t eps = 0.01) const;
0608
0609 virtual void GradientPar(const Double_t *x, Double_t *grad, Double_t eps = 0.01) const;
0610 template <class T>
0611 void GradientPar(const T *x, T *grad, Double_t eps = 0.01) const;
0612 template <class T>
0613 void GradientParTempl(const T *x, T *grad, Double_t eps = 0.01) const;
0614
0615 virtual void InitArgs(const Double_t *x, const Double_t *params);
0616 static void InitStandardFunctions();
0617 virtual Double_t Integral(Double_t a, Double_t b, Double_t epsrel = 1.e-12);
0618 virtual Double_t IntegralOneDim(Double_t a, Double_t b, Double_t epsrel, Double_t epsabs, Double_t &err);
0619 virtual Double_t IntegralError(Double_t a, Double_t b, const Double_t *params = nullptr, const Double_t *covmat = nullptr, Double_t epsilon = 1.E-2);
0620 virtual Double_t IntegralError(Int_t n, const Double_t *a, const Double_t *b, const Double_t *params = nullptr, const Double_t *covmat = nullptr, Double_t epsilon = 1.E-2);
0621
0622 virtual Double_t IntegralFast(Int_t num, Double_t *x, Double_t *w, Double_t a, Double_t b, Double_t *params = nullptr, Double_t epsilon = 1e-12);
0623 virtual Double_t 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);
0624 virtual Double_t IntegralMultiple(Int_t n, const Double_t *a, const Double_t *b, Int_t , Int_t maxpts, Double_t epsrel, Double_t &relerr, Int_t &nfnevl, Int_t &ifail)
0625 {
0626 return IntegralMultiple(n, a, b, maxpts, epsrel, epsrel, relerr, nfnevl, ifail);
0627 }
0628 virtual Double_t IntegralMultiple(Int_t n, const Double_t *a, const Double_t *b, Double_t epsrel, Double_t &relerr);
0629 virtual Bool_t IsEvalNormalized() const
0630 {
0631 return fNormalized;
0632 }
0633
0634 virtual Bool_t IsInside(const Double_t *x) const
0635 {
0636 return !((x[0] < fXmin) || (x[0] > fXmax));
0637 }
0638 virtual Bool_t IsLinear() const
0639 {
0640 return (fFormula) ? fFormula->IsLinear() : false;
0641 }
0642 virtual Bool_t IsValid() const;
0643 void Print(Option_t *option = "") const override;
0644 void Paint(Option_t *option = "") override;
0645 virtual void ReleaseParameter(Int_t ipar);
0646 virtual void Save(Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax);
0647 void SavePrimitive(std::ostream &out, Option_t *option = "") override;
0648 virtual void SetChisquare(Double_t chi2)
0649 {
0650 fChisquare = chi2;
0651 }
0652 virtual void SetFitResult(const ROOT::Fit::FitResult &result, const Int_t *indpar = nullptr);
0653 template <class PtrObj, typename MemFn>
0654 void SetFunction(PtrObj &p, MemFn memFn);
0655 template <typename Func>
0656 void SetFunction(Func f);
0657 virtual void SetMaximum(Double_t maximum = -1111);
0658 virtual void SetMinimum(Double_t minimum = -1111);
0659 virtual void SetNDF(Int_t ndf);
0660 virtual void SetNumberFitPoints(Int_t npfits)
0661 {
0662 fNpfits = npfits;
0663 }
0664 virtual void SetNormalized(Bool_t flag)
0665 {
0666 fNormalized = flag;
0667 Update();
0668 }
0669 inline void SetNdim(Int_t ndim)
0670 {
0671 fNdim = ndim;
0672 Update();
0673 }
0674 virtual void SetNpx(Int_t npx = 100);
0675 virtual void SetParameter(Int_t param, Double_t value)
0676 {
0677 (fFormula) ? fFormula->SetParameter(param, value) : fParams->SetParameter(param, value);
0678 Update();
0679 }
0680 virtual void SetParameter(const TString &name, Double_t value)
0681 {
0682 (fFormula) ? fFormula->SetParameter(name, value) : fParams->SetParameter(name, value);
0683 Update();
0684 }
0685 virtual void SetParameters(const Double_t *params)
0686 {
0687 (fFormula) ? fFormula->SetParameters(params) : fParams->SetParameters(params);
0688 Update();
0689 }
0690
0691
0692 virtual void SetParameters(double p0, double p1 = TMath::QuietNaN(), double p2 = TMath::QuietNaN(),
0693 double p3 = TMath::QuietNaN(), double p4 = TMath::QuietNaN(), double p5 = TMath::QuietNaN(),
0694 double p6 = TMath::QuietNaN(), double p7 = TMath::QuietNaN(), double p8 = TMath::QuietNaN(),
0695 double p9 = TMath::QuietNaN(), double p10 = TMath::QuietNaN())
0696 {
0697
0698
0699
0700
0701
0702 if (fFormula) fFormula->SetParameters(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
0703 else fParams->SetParameters(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
0704 Update();
0705 }
0706 virtual void SetParName(Int_t ipar, const char *name);
0707 virtual void SetParNames(const char *name0 = "", const char *name1 = "", const char *name2 = "",
0708 const char *name3 = "", const char *name4 = "", const char *name5 = "",
0709 const char *name6 = "", const char *name7 = "", const char *name8 = "",
0710 const char *name9 = "", const char *name10 = "");
0711 virtual void SetParError(Int_t ipar, Double_t error);
0712 virtual void SetParErrors(const Double_t *errors);
0713 virtual void SetParLimits(Int_t ipar, Double_t parmin, Double_t parmax);
0714 virtual void SetParent(TObject *p = nullptr)
0715 {
0716 fParent = p;
0717 }
0718 virtual void SetRange(Double_t xmin, Double_t xmax);
0719 virtual void SetRange(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax);
0720 virtual void SetRange(Double_t xmin, Double_t ymin, Double_t zmin, Double_t xmax, Double_t ymax, Double_t zmax);
0721 virtual void SetSavedPoint(Int_t point, Double_t value);
0722 void SetTitle(const char *title = "") override;
0723 virtual void SetVectorized(Bool_t vectorized)
0724 {
0725 if (fType == EFType::kFormula && fFormula)
0726 fFormula->SetVectorized(vectorized);
0727 else
0728 Warning("SetVectorized", "Can only set vectorized flag on formula-based TF1");
0729 }
0730 virtual void Update();
0731
0732 static TF1 *GetCurrent();
0733 static void AbsValue(Bool_t reject = kTRUE);
0734 static void RejectPoint(Bool_t reject = kTRUE);
0735 static Bool_t RejectedPoint();
0736 static void SetCurrent(TF1 *f1);
0737
0738
0739 virtual Double_t Moment(Double_t n, Double_t a, Double_t b, const Double_t *params = nullptr, Double_t epsilon = 0.000001);
0740 virtual Double_t CentralMoment(Double_t n, Double_t a, Double_t b, const Double_t *params = nullptr, Double_t epsilon = 0.000001);
0741 virtual Double_t Mean(Double_t a, Double_t b, const Double_t *params = nullptr, Double_t epsilon = 0.000001)
0742 {
0743 return Moment(1, a, b, params, epsilon);
0744 }
0745 virtual Double_t Variance(Double_t a, Double_t b, const Double_t *params = nullptr, Double_t epsilon = 0.000001)
0746 {
0747 return CentralMoment(2, a, b, params, epsilon);
0748 }
0749
0750
0751
0752
0753 static void CalcGaussLegendreSamplingPoints(Int_t num, Double_t *x, Double_t *w, Double_t eps = 3.0e-11);
0754
0755 private:
0756 template <class T>
0757 T EvalParTempl(const T *data, const Double_t *params = nullptr);
0758
0759 #ifdef R__HAS_VECCORE
0760 inline double EvalParVec(const Double_t *data, const Double_t *params);
0761 #endif
0762
0763 ClassDefOverride(TF1, 12)
0764 };
0765
0766 namespace ROOT {
0767 namespace Internal {
0768
0769 template<class Func>
0770 void TF1Builder<Func>::Build(TF1 *f, Func func)
0771 {
0772 using Fnc_t = typename ROOT::Internal::GetFunctorType<decltype(ROOT::Internal::GetTheRightOp(&Func::operator()))>::type;
0773 f->fType = std::is_same<Fnc_t, double>::value? TF1::EFType::kTemplScalar : TF1::EFType::kTemplVec;
0774 f->fFunctor.reset(new TF1::TF1FunctorPointerImpl<Fnc_t>(ROOT::Math::ParamFunctorTempl<Fnc_t>(func)));
0775 f->fParams = std::make_unique<TF1Parameters>(f->fNpar);
0776 }
0777
0778 template<class Func>
0779 void TF1Builder<Func *>::Build(TF1 *f, Func *func)
0780 {
0781 using Fnc_t = typename ROOT::Internal::GetFunctorType<decltype(ROOT::Internal::GetTheRightOp(&Func::operator()))>::type;
0782 f->fType = std::is_same<Fnc_t, double>::value? TF1::EFType::kTemplScalar : TF1::EFType::kTemplVec;
0783 f->fFunctor.reset(new TF1::TF1FunctorPointerImpl<Fnc_t>(ROOT::Math::ParamFunctorTempl<Fnc_t>(func)));
0784 f->fParams = std::make_unique<TF1Parameters>(f->fNpar);
0785 }
0786
0787
0788
0789 template<>
0790 struct TF1Builder<const char *> {
0791 static void Build(TF1 *f, const char *formula)
0792 {
0793 f->fType = TF1::EFType::kFormula;
0794 f->fFormula = std::make_unique<TFormula>("tf1lambda", formula, f->fNdim, f->fNpar, false);
0795 TString formulaExpression(formula);
0796 Ssiz_t first = formulaExpression.Index("return") + 7;
0797 Ssiz_t last = formulaExpression.Last(';');
0798 TString title = formulaExpression(first, last - first);
0799 f->SetTitle(title);
0800 }
0801 };
0802
0803 inline void
0804 EvalParMultiDim(TF1 *func, Double_t *out, const Double_t *x, std::size_t size, std::size_t rows, Double_t *params)
0805 {
0806 for (size_t i = 0; i < rows; i++) {
0807 out[i] = func->EvalPar(x + i * size, params);
0808 }
0809 }
0810 }
0811 }
0812
0813 inline Double_t TF1::operator()(Double_t x, Double_t y, Double_t z, Double_t t) const
0814 {
0815 return Eval(x, y, z, t);
0816 }
0817
0818 template <class T>
0819 inline T TF1::operator()(const T *x, const Double_t *params)
0820 {
0821 return EvalPar(x, params);
0822 }
0823
0824
0825
0826 template <class T>
0827 T TF1::EvalPar(const T *x, const Double_t *params)
0828 {
0829 if (fType == EFType::kTemplVec || fType == EFType::kTemplScalar) {
0830 return EvalParTempl(x, params);
0831 } else if (fType == EFType::kFormula) {
0832 return fFormula->EvalPar(x, params);
0833 } else
0834 return TF1::EvalPar((double *)x, params);
0835 }
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851 template <class T>
0852 inline T TF1::EvalParTempl(const T *data, const Double_t *params)
0853 {
0854 assert(fType == EFType::kTemplScalar || fType == EFType::kTemplVec);
0855 if (!params) params = (Double_t *)fParams->GetParameters();
0856 if (fFunctor)
0857 return ((TF1FunctorPointerImpl<T> *)fFunctor.get())->fImpl(data, params);
0858
0859
0860
0861 return TMath::SignalingNaN();
0862 }
0863
0864 #ifdef R__HAS_VECCORE
0865
0866 inline double TF1::EvalParVec(const Double_t *data, const Double_t *params)
0867 {
0868 assert(fType == EFType::kTemplVec);
0869 std::vector<ROOT::Double_v> d(fNdim);
0870 ROOT::Double_v res;
0871
0872 for(auto i=0; i<fNdim; i++) {
0873 d[i] = ROOT::Double_v(data[i]);
0874 }
0875
0876 if (fFunctor) {
0877 res = ((TF1FunctorPointerImpl<ROOT::Double_v> *) fFunctor.get())->fImpl(d.data(), params);
0878 } else {
0879
0880 return TMath::SignalingNaN();
0881 }
0882 return vecCore::Get<ROOT::Double_v>(res, 0);
0883 }
0884 #endif
0885
0886 inline void TF1::SetRange(Double_t xmin, Double_t, Double_t xmax, Double_t)
0887 {
0888 TF1::SetRange(xmin, xmax);
0889 }
0890 inline void TF1::SetRange(Double_t xmin, Double_t, Double_t, Double_t xmax, Double_t, Double_t)
0891 {
0892 TF1::SetRange(xmin, xmax);
0893 }
0894
0895 template <typename Func>
0896 void TF1::SetFunction(Func f)
0897 {
0898
0899 fType = EFType::kPtrScalarFreeFcn;
0900 fFunctor = std::make_unique<TF1::TF1FunctorPointerImpl<double>>(ROOT::Math::ParamFunctor(f));
0901 }
0902 template <class PtrObj, typename MemFn>
0903 void TF1::SetFunction(PtrObj &p, MemFn memFn)
0904 {
0905
0906 fType = EFType::kPtrScalarFreeFcn;
0907 fFunctor = std::make_unique<TF1::TF1FunctorPointerImpl<double>>(ROOT::Math::ParamFunctor(p, memFn));
0908 }
0909
0910 template <class T>
0911 inline T TF1::GradientPar(Int_t ipar, const T *x, Double_t eps) const
0912 {
0913 if (fType == EFType::kTemplVec || fType == EFType::kTemplScalar) {
0914 return GradientParTempl<T>(ipar, x, eps);
0915 } else
0916 return GradientParTempl<Double_t>(ipar, (const Double_t *)x, eps);
0917 }
0918
0919 template <class T>
0920 inline T TF1::GradientParTempl(Int_t ipar, const T *x, Double_t eps) const
0921 {
0922 if (GetNpar() == 0)
0923 return 0;
0924
0925 if (eps < 1e-10 || eps > 1) {
0926 Warning("Derivative", "parameter esp=%g out of allowed range[1e-10,1], reset to 0.01", eps);
0927 eps = 0.01;
0928 }
0929 Double_t h;
0930 TF1 *func = (TF1 *)this;
0931 Double_t *parameters = GetParameters();
0932
0933
0934 std::vector<Double_t> parametersCopy(parameters, parameters + GetNpar());
0935 parameters = parametersCopy.data();
0936
0937 Double_t al, bl, h2;
0938 T f1, f2, g1, g2, d0, d2;
0939
0940 ((TF1 *)this)->GetParLimits(ipar, al, bl);
0941 if (al * bl != 0 && al >= bl) {
0942
0943 return 0;
0944 }
0945
0946
0947 if (func->GetParError(ipar) != 0)
0948 h = eps * func->GetParError(ipar);
0949 else
0950 h = eps;
0951
0952
0953 Double_t par0 = parameters[ipar];
0954
0955 parameters[ipar] = par0 + h;
0956 f1 = func->EvalPar(x, parameters);
0957 parameters[ipar] = par0 - h;
0958 f2 = func->EvalPar(x, parameters);
0959 parameters[ipar] = par0 + h / 2;
0960 g1 = func->EvalPar(x, parameters);
0961 parameters[ipar] = par0 - h / 2;
0962 g2 = func->EvalPar(x, parameters);
0963
0964
0965 h2 = 1 / (2. * h);
0966 d0 = f1 - f2;
0967 d2 = 2 * (g1 - g2);
0968
0969 T grad = h2 * (4 * d2 - d0) / 3.;
0970
0971
0972 parameters[ipar] = par0;
0973
0974 return grad;
0975 }
0976
0977 template <class T>
0978 inline void TF1::GradientPar(const T *x, T *grad, Double_t eps) const
0979 {
0980 if (fType == EFType::kTemplVec || fType == EFType::kTemplScalar) {
0981 GradientParTempl<T>(x, grad, eps);
0982 } else
0983 GradientParTempl<Double_t>((const Double_t *)x, (Double_t *)grad, eps);
0984 }
0985
0986 template <class T>
0987 inline void TF1::GradientParTempl(const T *x, T *grad, Double_t eps) const
0988 {
0989 if (eps < 1e-10 || eps > 1) {
0990 Warning("Derivative", "parameter esp=%g out of allowed range[1e-10,1], reset to 0.01", eps);
0991 eps = 0.01;
0992 }
0993
0994 for (Int_t ipar = 0; ipar < GetNpar(); ipar++) {
0995 grad[ipar] = GradientParTempl<T>(ipar, x, eps);
0996 }
0997 }
0998
0999 #endif