/*****************************************************************************
 * Project: RooFit                                                           *
 *                                                                           *
  * This code was autogenerated by RooClassFactory                            *
 *****************************************************************************/

#ifndef ROOMOMENTMORPH
#define ROOMOMENTMORPH

#include "RooAbsPdf.h"
#include "RooRealProxy.h"
#include "RooCategoryProxy.h"
#include "RooAbsReal.h"
#include "RooAbsCategory.h"
#include "RooSetProxy.h"
#include "RooListProxy.h"
#include "RooArgList.h"

#include "TMatrixD.h"
#include "TVectorD.h"

#include <string>

class RooChangeTracker;

class RooMomentMorph : public RooAbsPdf {
public:

  enum Setting { Linear, NonLinear, NonLinearPosFractions, NonLinearLinFractions, SineLinear } ;

  RooMomentMorph() ;

  RooMomentMorph(const char *name, const char *title, RooAbsReal& _m, const RooArgList& varList,
          const RooArgList& pdfList, const RooArgList& mrefList, Setting setting = NonLinearPosFractions);
  RooMomentMorph(const char *name, const char *title, RooAbsReal& _m, const RooArgList& varList,
          const RooArgList& pdfList, const TVectorD& mrefpoints, Setting setting = NonLinearPosFractions );
  RooMomentMorph(const RooMomentMorph& other, const char* name=0) ;
  virtual TObject* clone(const char* newname) const { return new RooMomentMorph(*this,newname); }
  virtual ~RooMomentMorph();

  void     setMode(const Setting& setting) { _setting = setting; }

  void useHorizontalMorphing(bool val) { _useHorizMorph = val; }

  virtual Bool_t selfNormalized() const {
    // P.d.f is self normalized
    return kTRUE ;
  }

  virtual Double_t getVal(const RooArgSet* set=0) const ;
  RooAbsPdf* sumPdf(const RooArgSet* nset) ;


protected:

  class CacheElem : public RooAbsCacheElement {
  public:
    CacheElem(RooAbsPdf& sumPdf, RooChangeTracker& tracker, const RooArgList& flist) : _sumPdf(&sumPdf), _tracker(&tracker) { _frac.add(flist) ; } ;
    void operModeHook(RooAbsArg::OperMode) {};
    virtual ~CacheElem() ;
    virtual RooArgList containedArgs(Action) ;
    RooAbsPdf* _sumPdf ;
    RooChangeTracker* _tracker ;
    RooArgList _frac ;

    RooRealVar* frac(Int_t i ) ;
    const RooRealVar* frac(Int_t i ) const ;
    void calculateFractions(const RooMomentMorph& self, Bool_t verbose=kTRUE) const;
  } ;
  mutable RooObjCacheManager _cacheMgr ; //! The cache manager
  mutable RooArgSet* _curNormSet ; //! Current normalization set

  friend class CacheElem ; // Cache needs to be able to clear _norm pointer

  Double_t evaluate() const ;

  void     initialize();
  CacheElem* getCache(const RooArgSet* nset) const ;

  inline   Int_t ij(const Int_t& i, const Int_t& j) const { return (i*_varList.getSize()+j); }
  int      idxmin(const double& m) const;
  int      idxmax(const double& m) const;

  RooRealProxy m ;
  RooSetProxy  _varList ;
  RooListProxy _pdfList ;
  mutable TVectorD* _mref;

  TIterator* _varItr ;   //! do not persist
  TIterator* _pdfItr ;   //!
  mutable TMatrixD* _M; //

  Setting _setting;

  bool _useHorizMorph;

  ClassDef(RooMomentMorph,3) // Your description goes here...
};

#endif