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