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

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

#ifndef ROOT_Minuit2_FumiliStandardMaximumLikelihoodFCN
#define ROOT_Minuit2_FumiliStandardMaximumLikelihoodFCN


#include "Minuit2/FumiliMaximumLikelihoodFCN.h"
#include "Minuit2/ParametricFunction.h"
#include <vector>

namespace ROOT {

   namespace Minuit2 {




/**

Class implementing the Elements member function for the standard
maximum likelihood method.

@author Andras Zsenei and Lorenzo Moneta, Creation date: 4 Sep 2004

@see FumiliMaximumLikelihoodFCN

@ingroup Minuit

*/

class FumiliStandardMaximumLikelihoodFCN : public FumiliMaximumLikelihoodFCN {

public:


  /**

  Constructor which initializes the measurement points for the one dimensional model function.

  @param modelFCN the model function used for describing the data.

  @param pos vector containing the x values corresponding to the
  measurements

  */

   FumiliStandardMaximumLikelihoodFCN(const ParametricFunction& modelFCN,
                                      const std::vector<double>& pos)
  {
    this->SetModelFunction(modelFCN);
    unsigned int n = pos.size();
    fPositions.reserve( n );
    std::vector<double> x(1);
    for (unsigned int i = 0; i < n; ++i) {
      x[0] = pos[i];
      fPositions.push_back(x);
    }
  }



  /**

  Constructor which initializes the measurement points for the multi dimensional model function.

  @param modelFCN the model function used for describing the data.

  @param pos vector containing the x values corresponding to the
  measurements

  */

   FumiliStandardMaximumLikelihoodFCN(const ParametricFunction& modelFCN,
                                      const std::vector<std::vector<double> >& pos) {
      this->SetModelFunction(modelFCN);
    fPositions = pos;

  }




  ~FumiliStandardMaximumLikelihoodFCN() {}




  /**

  Evaluates the model function for the different measurement points and
  the Parameter values supplied.

  @param par vector of Parameter values to feed to the model function.

  @return A vector containing the model function evaluated
  for each measurement point.

  */

  std::vector<double> Elements(const std::vector<double>& par) const;




  /**

  Accessor to the position of the measurement (x coordinate).

  @param Index Index of the measuerement the position of which to return.

  @return the position of the measurement.

  */

  virtual const std::vector<double> & GetMeasurement(int Index) const;


  /**

  Accessor to the number of measurements used for calculating
  the maximum likelihood.

  @return the number of measurements.

  */

  virtual int GetNumberOfMeasurements() const;

  /**

  Evaluate function Value, Gradient and Hessian using Fumili approximation, for values of parameters p
  The resul is cached inside and is return from the FumiliFCNBase::Value ,  FumiliFCNBase::Gradient and
  FumiliFCNBase::Hessian methods

  @param par vector of parameters

  **/

  virtual  void EvaluateAll( const std::vector<double> & par );


 private:

  std::vector<std::vector<double> > fPositions;
};

  }  // namespace Minuit2

}  // namespace ROOT

#endif  // ROOT_Minuit2_FumiliStandardMaximumLikelihoodFCN