// @(#)root/mathcore:$Id$ // Authors: L. Moneta, J.T. Offermann, E.G.P. Bos 2013-2018 // /********************************************************************** * * * Copyright (c) 2013 , LCG ROOT MathLib Team * * * **********************************************************************/ /* * NumericalDerivator.h * * Original version created on: Aug 14, 2013 * Authors: L. Moneta, J. T. Offermann * Modified version created on: Sep 27, 2017 * Author: E. G. P. Bos */ #ifndef ROOT_Minuit2_NumericalDerivator #define ROOT_Minuit2_NumericalDerivator #include #include #include "Fit/ParameterSettings.h" #include "Minuit2/SinParameterTransformation.h" #include "Minuit2/SqrtUpParameterTransformation.h" #include "Minuit2/SqrtLowParameterTransformation.h" #include "Minuit2/MnMachinePrecision.h" namespace ROOT { namespace Minuit2 { // Holds all necessary derivatives and associated numbers (per parameter) used in the NumericalDerivator class. struct DerivatorElement { double derivative; double second_derivative; double step_size; }; class NumericalDerivator { public: explicit NumericalDerivator(bool always_exactly_mimic_minuit2 = true); NumericalDerivator(const NumericalDerivator &other); NumericalDerivator(double step_tolerance, double grad_tolerance, unsigned int ncycles, double error_level, bool always_exactly_mimic_minuit2 = true); void SetupDifferentiate(const ROOT::Math::IBaseFunctionMultiDim *function, const double *cx, const std::vector ¶meters); std::vector Differentiate(const ROOT::Math::IBaseFunctionMultiDim *function, const double *x, const std::vector ¶meters, const std::vector &previous_gradient); DerivatorElement PartialDerivative(const ROOT::Math::IBaseFunctionMultiDim *function, const double *x, const std::vector ¶meters, unsigned int i_component, DerivatorElement previous); DerivatorElement FastPartialDerivative(const ROOT::Math::IBaseFunctionMultiDim *function, const std::vector ¶meters, unsigned int i_component, const DerivatorElement &previous); DerivatorElement operator()(const ROOT::Math::IBaseFunctionMultiDim *function, const double *x, const std::vector ¶meters, unsigned int i_component, const DerivatorElement &previous); double GetValue() const { return fVal; } inline void SetStepTolerance(double value) { fStepTolerance = value; } inline void SetGradTolerance(double value) { fGradTolerance = value; } inline void SetNCycles(unsigned int value) { fNCycles = value; } inline void SetErrorLevel(double value) { fUp = value; } double Int2ext(const ROOT::Fit::ParameterSettings ¶meter, double val) const; double Ext2int(const ROOT::Fit::ParameterSettings ¶meter, double val) const; double DInt2Ext(const ROOT::Fit::ParameterSettings ¶meter, double val) const; void SetInitialGradient(const ROOT::Math::IBaseFunctionMultiDim *function, const std::vector ¶meters, std::vector &gradient); inline bool AlwaysExactlyMimicMinuit2() const { return fAlwaysExactlyMimicMinuit2; } inline void SetAlwaysExactlyMimicMinuit2(bool flag) { fAlwaysExactlyMimicMinuit2 = flag; } private: double fStepTolerance = 0.5; double fGradTolerance = 0.1; double fUp = 1; double fVal = 0; std::vector fVx; std::vector fVxExternal; std::vector fVxFValCache; double fDfmin; double fVrysml; // MODIFIED: Minuit2 determines machine precision in a slightly different way than // std::numeric_limits::epsilon()). We go with the Minuit2 one. ROOT::Minuit2::MnMachinePrecision fPrecision; ROOT::Minuit2::SinParameterTransformation fDoubleLimTrafo; ROOT::Minuit2::SqrtUpParameterTransformation fUpperLimTrafo; ROOT::Minuit2::SqrtLowParameterTransformation fLowerLimTrafo; unsigned int fNCycles = 2; bool fAlwaysExactlyMimicMinuit2; }; std::ostream &operator<<(std::ostream &out, const DerivatorElement &value); } // namespace Minuit2 } // namespace ROOT #endif // ROOT_Minuit2_NumericalDerivator