/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitBabar                                                      *
 * @(#)root/roofit:$Id$
 * Author:                                                                   *
 *    Tristan du Pree, Nikhef, Amsterdam, tdupree@nikhef.nl                  *
 *    Wouter Verkerke, Nikhef, Amsterdam, verkerke@nikhef.nl
 *                                                                           *
 * Copyright (c) 2009, NIKHEF. All rights reserved.                          *
 *           
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// The  Step Function is a binned function whose parameters 
// are the heights of each bin.  
// 
// This function may be used to describe oddly shaped distributions. A RooStepFunction
// has free parameters. In particular, any statistical uncertainty 
// used to model this efficiency may be understood with these free parameters.
//
// Note that in contrast to RooParametricStepFunction, a RooStepFunction is NOT a PDF,
// but a not-normalized function (RooAbsReal)
//

#include "RooFit.h"

#include "Riostream.h"
#include "TArrayD.h"
#include <math.h>

#include "RooStepFunction.h"
#include "RooAbsReal.h"
#include "RooRealVar.h"
#include "RooArgList.h"
#include "RooMsgService.h"
#include "RooMath.h"

using namespace std;

ClassImp(RooStepFunction)
  ;


//_____________________________________________________________________________
RooStepFunction::RooStepFunction()
{
  // Constructor
  _coefIter = _coefList.createIterator() ;
  _boundIter = _boundaryList.createIterator() ;
  _interpolate = kFALSE ;
}
				 


//_____________________________________________________________________________
RooStepFunction::RooStepFunction(const char* name, const char* title, 
				 RooAbsReal& x, const RooArgList& coefList, const RooArgList& boundaryList, Bool_t interpolate) :
  RooAbsReal(name, title),
  _x("x", "Dependent", this, x),
  _coefList("coefList","List of coefficients",this),
  _boundaryList("boundaryList","List of boundaries",this),
  _interpolate(interpolate)
{
  // Constructor

  _coefIter = _coefList.createIterator() ;
  TIterator* coefIter = coefList.createIterator() ;
  RooAbsArg* coef ;
  while((coef = (RooAbsArg*)coefIter->Next())) {
    if (!dynamic_cast<RooAbsReal*>(coef)) {
      cout << "RooStepFunction::ctor(" << GetName() << ") ERROR: coefficient " << coef->GetName() 
	   << " is not of type RooAbsReal" << endl ;
      assert(0) ;
    }
    _coefList.add(*coef) ;
  }
  delete coefIter ;

  _boundIter = _boundaryList.createIterator() ;
  TIterator* boundaryIter = boundaryList.createIterator() ;
  RooAbsArg* boundary ;
  while((boundary = (RooAbsArg*)boundaryIter->Next())) {
    if (!dynamic_cast<RooAbsReal*>(boundary)) {
      cout << "RooStepFunction::ctor(" << GetName() << ") ERROR: boundary " << boundary->GetName() 
	   << " is not of type RooAbsReal" << endl ;
      assert(0) ;
    }
    _boundaryList.add(*boundary) ;
  }

  if (_boundaryList.getSize()!=_coefList.getSize()+1) {
    coutE(InputArguments) << "RooStepFunction::ctor(" << GetName() << ") ERROR: Number of boundaries must be number of coefficients plus 1" << endl ;
    throw string("RooStepFunction::ctor() ERROR: Number of boundaries must be number of coefficients plus 1") ;
  }

}



//_____________________________________________________________________________
RooStepFunction::RooStepFunction(const RooStepFunction& other, const char* name) :
  RooAbsReal(other, name), 
  _x("x", this, other._x), 
  _coefList("coefList",this,other._coefList),
  _boundaryList("boundaryList",this,other._boundaryList),
  _interpolate(other._interpolate)
{
  // Copy constructor
  _coefIter = _coefList.createIterator();
  _boundIter = _boundaryList.createIterator();
}



//_____________________________________________________________________________
RooStepFunction::~RooStepFunction()
{
  // Destructor
  delete _coefIter ;
  delete _boundIter ;
}



//_____________________________________________________________________________
Double_t RooStepFunction::evaluate() const 
{
  // Transfer contents to vector for use below
  vector<double> b(_boundaryList.getSize()) ;
  vector<double> c(_coefList.getSize()+3) ;
  Int_t nb(0) ;
  _boundIter->Reset() ;
  RooAbsReal* boundary ;
  while ((boundary=(RooAbsReal*)_boundIter->Next())) {
    b[nb++] = boundary->getVal() ;
  }

  // Return zero if outside any boundaries
  if ((_x<b[0]) || (_x>b[nb-1])) return 0 ;

  if (!_interpolate) {

    // No interpolation -- Return values bin-by-bin
    for (Int_t i=0;i<nb-1;i++){
      if (_x>b[i]&&_x<=b[i+1]) {
	return ((RooAbsReal*)_coefList.at(i))->getVal() ;
      }
    } 
    return 0 ;

  } else {

    // Interpolation

    // Make array of (b[0],bin centers,b[last])
    c[0] = b[0] ; c[nb] = b[nb-1] ;
    for (Int_t i=0 ; i<nb-1 ; i++) {
      c[i+1] = (b[i]+b[i+1])/2 ;
    }

    // Make array of (0,coefficient values,0)
    Int_t nc(0) ;
    _coefIter->Reset() ;
    RooAbsReal* coef ;
    vector<double> y(_coefList.getSize()+3) ;
    y[nc++] = 0 ;
    while ((coef=(RooAbsReal*)_coefIter->Next())) {
      y[nc++] = coef->getVal() ;
    }
    y[nc++] = 0 ;

    for (Int_t i=0;i<nc-1;i++){
      if (_x>c[i]&&_x<=c[i+1]) {
	Double_t xx[2] ; xx[0]=c[i] ; xx[1]=c[i+1] ;
	Double_t yy[2] ; yy[0]=y[i] ; yy[1]=y[i+1] ;
	return RooMath::interpolate(xx,yy,2,_x) ;
      }
    } 
    return 0;   
  }  
}

 RooStepFunction.cxx:1
 RooStepFunction.cxx:2
 RooStepFunction.cxx:3
 RooStepFunction.cxx:4
 RooStepFunction.cxx:5
 RooStepFunction.cxx:6
 RooStepFunction.cxx:7
 RooStepFunction.cxx:8
 RooStepFunction.cxx:9
 RooStepFunction.cxx:10
 RooStepFunction.cxx:11
 RooStepFunction.cxx:12
 RooStepFunction.cxx:13
 RooStepFunction.cxx:14
 RooStepFunction.cxx:15
 RooStepFunction.cxx:16
 RooStepFunction.cxx:17
 RooStepFunction.cxx:18
 RooStepFunction.cxx:19
 RooStepFunction.cxx:20
 RooStepFunction.cxx:21
 RooStepFunction.cxx:22
 RooStepFunction.cxx:23
 RooStepFunction.cxx:24
 RooStepFunction.cxx:25
 RooStepFunction.cxx:26
 RooStepFunction.cxx:27
 RooStepFunction.cxx:28
 RooStepFunction.cxx:29
 RooStepFunction.cxx:30
 RooStepFunction.cxx:31
 RooStepFunction.cxx:32
 RooStepFunction.cxx:33
 RooStepFunction.cxx:34
 RooStepFunction.cxx:35
 RooStepFunction.cxx:36
 RooStepFunction.cxx:37
 RooStepFunction.cxx:38
 RooStepFunction.cxx:39
 RooStepFunction.cxx:40
 RooStepFunction.cxx:41
 RooStepFunction.cxx:42
 RooStepFunction.cxx:43
 RooStepFunction.cxx:44
 RooStepFunction.cxx:45
 RooStepFunction.cxx:46
 RooStepFunction.cxx:47
 RooStepFunction.cxx:48
 RooStepFunction.cxx:49
 RooStepFunction.cxx:50
 RooStepFunction.cxx:51
 RooStepFunction.cxx:52
 RooStepFunction.cxx:53
 RooStepFunction.cxx:54
 RooStepFunction.cxx:55
 RooStepFunction.cxx:56
 RooStepFunction.cxx:57
 RooStepFunction.cxx:58
 RooStepFunction.cxx:59
 RooStepFunction.cxx:60
 RooStepFunction.cxx:61
 RooStepFunction.cxx:62
 RooStepFunction.cxx:63
 RooStepFunction.cxx:64
 RooStepFunction.cxx:65
 RooStepFunction.cxx:66
 RooStepFunction.cxx:67
 RooStepFunction.cxx:68
 RooStepFunction.cxx:69
 RooStepFunction.cxx:70
 RooStepFunction.cxx:71
 RooStepFunction.cxx:72
 RooStepFunction.cxx:73
 RooStepFunction.cxx:74
 RooStepFunction.cxx:75
 RooStepFunction.cxx:76
 RooStepFunction.cxx:77
 RooStepFunction.cxx:78
 RooStepFunction.cxx:79
 RooStepFunction.cxx:80
 RooStepFunction.cxx:81
 RooStepFunction.cxx:82
 RooStepFunction.cxx:83
 RooStepFunction.cxx:84
 RooStepFunction.cxx:85
 RooStepFunction.cxx:86
 RooStepFunction.cxx:87
 RooStepFunction.cxx:88
 RooStepFunction.cxx:89
 RooStepFunction.cxx:90
 RooStepFunction.cxx:91
 RooStepFunction.cxx:92
 RooStepFunction.cxx:93
 RooStepFunction.cxx:94
 RooStepFunction.cxx:95
 RooStepFunction.cxx:96
 RooStepFunction.cxx:97
 RooStepFunction.cxx:98
 RooStepFunction.cxx:99
 RooStepFunction.cxx:100
 RooStepFunction.cxx:101
 RooStepFunction.cxx:102
 RooStepFunction.cxx:103
 RooStepFunction.cxx:104
 RooStepFunction.cxx:105
 RooStepFunction.cxx:106
 RooStepFunction.cxx:107
 RooStepFunction.cxx:108
 RooStepFunction.cxx:109
 RooStepFunction.cxx:110
 RooStepFunction.cxx:111
 RooStepFunction.cxx:112
 RooStepFunction.cxx:113
 RooStepFunction.cxx:114
 RooStepFunction.cxx:115
 RooStepFunction.cxx:116
 RooStepFunction.cxx:117
 RooStepFunction.cxx:118
 RooStepFunction.cxx:119
 RooStepFunction.cxx:120
 RooStepFunction.cxx:121
 RooStepFunction.cxx:122
 RooStepFunction.cxx:123
 RooStepFunction.cxx:124
 RooStepFunction.cxx:125
 RooStepFunction.cxx:126
 RooStepFunction.cxx:127
 RooStepFunction.cxx:128
 RooStepFunction.cxx:129
 RooStepFunction.cxx:130
 RooStepFunction.cxx:131
 RooStepFunction.cxx:132
 RooStepFunction.cxx:133
 RooStepFunction.cxx:134
 RooStepFunction.cxx:135
 RooStepFunction.cxx:136
 RooStepFunction.cxx:137
 RooStepFunction.cxx:138
 RooStepFunction.cxx:139
 RooStepFunction.cxx:140
 RooStepFunction.cxx:141
 RooStepFunction.cxx:142
 RooStepFunction.cxx:143
 RooStepFunction.cxx:144
 RooStepFunction.cxx:145
 RooStepFunction.cxx:146
 RooStepFunction.cxx:147
 RooStepFunction.cxx:148
 RooStepFunction.cxx:149
 RooStepFunction.cxx:150
 RooStepFunction.cxx:151
 RooStepFunction.cxx:152
 RooStepFunction.cxx:153
 RooStepFunction.cxx:154
 RooStepFunction.cxx:155
 RooStepFunction.cxx:156
 RooStepFunction.cxx:157
 RooStepFunction.cxx:158
 RooStepFunction.cxx:159
 RooStepFunction.cxx:160
 RooStepFunction.cxx:161
 RooStepFunction.cxx:162
 RooStepFunction.cxx:163
 RooStepFunction.cxx:164
 RooStepFunction.cxx:165
 RooStepFunction.cxx:166
 RooStepFunction.cxx:167
 RooStepFunction.cxx:168
 RooStepFunction.cxx:169
 RooStepFunction.cxx:170
 RooStepFunction.cxx:171
 RooStepFunction.cxx:172
 RooStepFunction.cxx:173
 RooStepFunction.cxx:174
 RooStepFunction.cxx:175
 RooStepFunction.cxx:176
 RooStepFunction.cxx:177
 RooStepFunction.cxx:178
 RooStepFunction.cxx:179
 RooStepFunction.cxx:180
 RooStepFunction.cxx:181
 RooStepFunction.cxx:182
 RooStepFunction.cxx:183
 RooStepFunction.cxx:184
 RooStepFunction.cxx:185
 RooStepFunction.cxx:186
 RooStepFunction.cxx:187