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