Back to home page

EIC code displayed by LXR

 
 

    


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 // @(#)root/hist:$Id$
0002 // Author: Rene Brun   18/08/95
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
0006  * All rights reserved.                                                  *
0007  *                                                                       *
0008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0010  *************************************************************************/
0011 // ---------------------------------- F1.h
0012 
0013 #ifndef ROOT_TF1
0014 #define ROOT_TF1
0015 
0016 //////////////////////////////////////////////////////////////////////////
0017 //                                                                      //
0018 // TF1                                                                  //
0019 //                                                                      //
0020 // The Parametric 1-D function                                          //
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() {} // needed for the I/O
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    // copy constructor
0063    TF1Parameters(const TF1Parameters &rhs) :
0064       fParameters(rhs.fParameters),
0065       fParNames(rhs.fParNames)
0066    {}
0067    // assignment
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    // getter methods
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    // setter methods
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)  // The Parameters of a parameteric function
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;    // parameter values
0142    std::vector<std::string> fParNames;   // parameter names
0143 };
0144 
0145 namespace ROOT {
0146    namespace Internal {
0147       /// %Internal class used by TF1 for defining
0148       /// template specialization for different TF1 constructors
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       /// %Internal class used by TF1 for obtaining the type from a functor
0160       /// out of the set of valid operator() signatures.
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       /// %Internal class used by TF1 to get the right operator() signature
0186       /// from a Functor with several ones.
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    /// Add to list behavior
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,      ///< Formula functions which can be stored,
0237       kPtrScalarFreeFcn, ///< Pointer to scalar free function,
0238       kInterpreted,      ///< Interpreted functions constructed by name,
0239       kTemplVec,         ///< Vectorized free functions or TemplScalar functors evaluating on vectorized parameters,
0240       kTemplScalar,      ///< TemplScalar functors evaluating on scalar parameters
0241       kCompositionFcn
0242    }; // formula based on composition class (e.g. NSUM, CONV)
0243 
0244    Double_t    fXmin{-1111};                        ///<  Lower bounds for the range
0245    Double_t    fXmax{-1111};                        ///<  Upper bounds for the range
0246    Int_t       fNpar{};                             ///<  Number of parameters
0247    Int_t       fNdim{};                             ///<  Function dimension
0248    Int_t       fNpx{100};                           ///<  Number of points used for the graphical representation
0249    EFType      fType{EFType::kTemplScalar};
0250    Int_t       fNpfits{};                           ///<  Number of points used in the fit
0251    Int_t       fNDF{};                              ///<  Number of degrees of freedom in the fit
0252    Double_t    fChisquare{};                        ///<  Function fit chisquare
0253    Double_t    fMinimum{-1111};                     ///<  Minimum value for plotting
0254    Double_t    fMaximum{-1111};                     ///<  Maximum value for plotting
0255    std::vector<Double_t>    fParErrors;             ///<  Array of errors of the fNpar parameters
0256    std::vector<Double_t>    fParMin;                ///<  Array of lower limits of the fNpar parameters
0257    std::vector<Double_t>    fParMax;                ///<  Array of upper limits of the fNpar parameters
0258    std::vector<Double_t>    fSave;                  ///<  Array of fNsave function values
0259    std::vector<Double_t>    fIntegral;              ///<! Integral of function binned on fNpx bins
0260    std::vector<Double_t>    fAlpha;                 ///<! Array alpha. for each bin in x the deconvolution r of fIntegral
0261    std::vector<Double_t>    fBeta;                  ///<! Array beta.  is approximated by x = alpha +beta*r *gamma*r**2
0262    std::vector<Double_t>    fGamma;                 ///<! Array gamma.
0263    TObject     *fParent{nullptr};                   ///<! Parent object hooking this function (if one)
0264    TH1         *fHistogram{nullptr};                ///<! Pointer to histogram used for visualisation
0265    std::unique_ptr<TMethodCall> fMethodCall;        ///<! Pointer to MethodCall in case of interpreted function
0266    Bool_t      fNormalized{false};                  ///<  Normalization option (false by default)
0267    Double_t    fNormIntegral{};                     ///<  Integral of the function before being normalized
0268    std::unique_ptr<TF1FunctorPointer>  fFunctor;    ///<! Functor object to wrap any C++ callable object
0269    std::unique_ptr<TFormula>   fFormula;            ///<  Pointer to TFormula in case when user define formula
0270    std::unique_ptr<TF1Parameters> fParams;          ///<  Pointer to Function parameters object (exists only for not-formula functions)
0271    std::unique_ptr<TF1AbsComposition> fComposition; ///<  Pointer to composition (NSUM or CONV)
0272 
0273    /// General constructor for TF1. Most of the other constructors delegate on it
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    // NSUM parsing helper functions
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;  //use absolute value of function when computing integral
0306    static Bool_t fgRejectPoint;  //True if point must be rejected in a fit
0307    static std::atomic<Bool_t> fgAddToGlobList; //True if we want to register the function in the global list
0308    static TF1   *fgCurrent;   //pointer to current function being processed
0309 
0310 
0311    //void CreateFromFunctor(const char *name, Int_t npar, Int_t ndim = 1);
0312    void DoInitialize(EAddToList addToGlobList);
0313 
0314    void IntegrateForNormalization();
0315    // tabulate the cumulative function integral at  fNpx points. Used by GetRandom
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    // TF1 status bits
0325    enum EStatusBits {
0326       kNotGlobal   = BIT(10),  // don't register in global list of functions
0327       kNotDraw     = BIT(9)  // don't draw the function when in a TH1
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);  // same as above but using a string for 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    /// Constructor using a pointer to function.
0346    ///
0347    /// \param[in] name object name
0348    /// \param[in] fcn pointer to function
0349    /// \param[in] xmin,xmax x axis limits
0350    /// \param[in] npar is the number of free parameters used by the function
0351    /// \param[in] ndim number of dimensions
0352    /// \param[in] addToGlobList boolean marking if it should be added to global list
0353    ///
0354    /// This constructor creates a function of type C when invoked
0355    /// with the normal C++ compiler.
0356    ///
0357    ///
0358    /// \warning A function created with this constructor cannot be Cloned
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    // Constructors using functors (compiled mode only)
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    // Template constructors from any  C++ callable object,  defining  the operator() (double * , double *)
0370    // and returning a double.
0371    // The class name is not needed when using compile code, while it is required when using
0372    // interpreted code via the specialized constructor with void *.
0373    // An instance of the C++ function class or its pointer can both be used. The former is reccomended when using
0374    // C++ compiled code, but if CINT compatibility is needed, then a pointer to the function class must be used.
0375    // xmin and xmax specify the plotting range,  npar is the number of parameters.
0376    // See the tutorial math/exampleFunctor.C for an example of using this constructor
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       //actual fType set in TF1Builder
0382       ROOT::Internal::TF1Builder<Func>::Build(this, f);
0383    }
0384 
0385    // backward compatible interface
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    // Template constructors from a pointer to any C++ class of type PtrObj with a specific member function of type
0395    // MemFn.
0396    // The member function must have the signature of  (double * , double *) and returning a double.
0397    // The class name and the method name are not needed when using compile code
0398    // (the member function pointer is used in this case), while they are required when using interpreted
0399    // code via the specialized constructor with void *.
0400    // xmin and xmax specify the plotting range,  npar is the number of parameters.
0401    // See the tutorial math/exampleFunctor.C for an example of using this constructor
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    // backward compatible interface
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    // virtual void     AddParameters(const pair<TString,Double_t> *pairs, Int_t size) { fFormula->AddParameters(pairs,size); }
0421    // virtual void     AddVariable(const TString &name, Double_t value = 0) { if (fFormula) fFormula->AddVariable(name,value); }
0422    // virtual void     AddVariables(const TString *vars, Int_t size) { if (fFormula) fFormula->AddVariables(vars,size); }
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"); // *MENU*
0436    virtual TObject *DrawIntegral(Option_t *option = "al"); // *MENU*
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    //template <class T> T Eval(T x, T y = 0, T z = 0, T t = 0) const;
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    // virtual Double_t IntegralFast(const TGraph *g, Double_t a, Double_t b, Double_t *params = nullptr);
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 /*minpts*/, 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    /// return kTRUE if the point is inside the function range
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); // *MENU*
0628    virtual void     SetMinimum(Double_t minimum = -1111); // *MENU*
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); // *MENU*
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    } // *MENU*
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"); // *MENU*
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); // *MENU*
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; // *MENU*
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    //Moments
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    //some useful static utility functions to compute sampling points for Integral
0708    //static  void     CalcGaussLegendreSamplingPoints(TGraph *g, Double_t eps=3.0e-11);
0709    //static  TGraph  *CalcGaussLegendreSamplingPoints(Int_t num=21, Double_t eps=3.0e-11);
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) // The Parametric 1-D function
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       /// TF1 building from a string
0745       /// used to build a TFormula based on a lambda function
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 ///   EvalPar for vectorized
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 ///   Eval for vectorized functions
0788 // template <class T>
0789 // T TF1::Eval(T x, T y, T z, T t) const
0790 // {
0791 //    if (fType == EFType::kFormula)
0792 //       return fFormula->Eval(x, y, z, t);
0793 
0794 //    T xx[] = {x, y, z, t};
0795 //    Double_t *pp = (Double_t *)fParams->GetParameters();
0796 //    return ((TF1 *)this)->EvalPar(xx, pp);
0797 // }
0798 
0799 // Internal to TF1. Evaluates Templated interfaces
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    // this should throw an error
0809    // we nned to implement a vectorized GetSave(x)
0810    return TMath::SignalingNaN();
0811 }
0812 
0813 #ifdef R__HAS_VECCORE
0814 // Internal to TF1. Evaluates Vectorized TF1 on data of type Double_v
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       //    res = GetSave(x);
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    // set function from a generic C++ callable object
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    // set from a pointer to a member function
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    // Copy parameters for thread safety
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       // this parameter is fixed
0892       return 0;
0893    }
0894 
0895    // check if error has been computer (is not zero)
0896    if (func->GetParError(ipar) != 0)
0897       h = eps * func->GetParError(ipar);
0898    else
0899       h = eps;
0900 
0901    // save original parameters
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    // compute the central differences
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    // restore original value
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