// @(#)root/minuit2:$Id$
// Authors: M. Winkler, F. James, L. Moneta, A. Zsenei   2003-2005

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2005 LCG ROOT Math team,  CERN/PH-SFT                *
 *                                                                    *
 **********************************************************************/

#include "Minuit2/ParametricFunction.h"
#include "Minuit2/MnFcn.h"
#include "Minuit2/MnStrategy.h"
#include "Minuit2/MnUserParameterState.h"
#include "Minuit2/Numerical2PGradientCalculator.h"
#include "Minuit2/FunctionGradient.h"
#include "Minuit2/MnVectorTransform.h"

namespace ROOT {

   namespace Minuit2 {

//#include "Minuit2/MnPrint.h"



std::vector<double>  ParametricFunction::GetGradient(const std::vector<double>& x) const {
   // calculate the numerical gradient (using Numerical2PGradientCalculator)

   //LM:  this I believe is not very efficient
   MnFcn mfcn(*this);

   MnStrategy strategy(1);

   // ????????? how does it know the transformation????????
   std::vector<double> err(x.size());
   err.assign(x.size(), 0.1);
   // need to use parameters
   MnUserParameterState st(x, err);

   Numerical2PGradientCalculator gc(mfcn, st.Trafo(), strategy);
   FunctionGradient g = gc(x);
   const MnAlgebraicVector & grad = g.Vec();
   assert( grad.size() == x.size() );
   MnVectorTransform vt;
   //  std::cout << "Param Function Gradient " << grad << std::endl;
   return vt( grad );
}

   }  // namespace Minuit2

}  // namespace ROOT
