/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 * @(#)root/roofitcore:$Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. 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)             *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//
// BEGIN_HTML
// Class RooParamBinning is an implementation of RooAbsBinning that constructs
// a binning with a range definition that depends on external RooAbsReal objects.
// The external RooAbsReal definitions are explicitly allowed to depend on other
// observables and parameters, and make it possible to define non-rectangular
// range definitions in RooFit. Objects of class RooParamBinning are made
// by the RooRealVar::setRange() that takes RooAbsReal references as arguments
// END_HTML
//

#include "RooFit.h"

#include "RooParamBinning.h"
#include "RooParamBinning.h"
#include "RooMsgService.h"

#include "Riostream.h"


using namespace std;

ClassImp(RooParamBinning)
;


//_____________________________________________________________________________
RooParamBinning::RooParamBinning(const char* name) : 
  RooAbsBinning(name), _xlo(0), _xhi(0), _nbins(100), _binw(0), _lp(0), _owner(0)
{  
  // Default constructor
//   cout << "RooParamBinning(" << this << ") default ctor" << endl ;
  _array = 0 ;
}


//_____________________________________________________________________________
RooParamBinning::RooParamBinning(RooAbsReal& xloIn, RooAbsReal& xhiIn, Int_t nBins, const char* name) :
  RooAbsBinning(name),
  _array(0), 
  _xlo(&xloIn),
  _xhi(&xhiIn),
  _nbins(nBins),
  _binw(0),
  _lp(0),
  _owner(0)
{
  // Construct binning with 'nBins' bins and with a range
  // parameterized by external RooAbsReals xloIn and xhiIn.
}



//_____________________________________________________________________________
RooParamBinning::~RooParamBinning() 
{
  // Destructor

  if (_array) delete[] _array ;
  if (_lp) delete _lp ;
}



//_____________________________________________________________________________
RooParamBinning::RooParamBinning(const RooParamBinning& other, const char* name) :
  RooAbsBinning(name), _binw(0), _owner(0)
{
  // Copy constructor
//   cout << "RooParamBinning::cctor(" << this << ") orig = " << &other << endl ;

  _array = 0 ;

  if (other._lp) {
//     cout << "RooParamBinning::cctor(this = " << this << ") taking addresses from orig  ListProxy" << endl ;
    _xlo = (RooAbsReal*) other._lp->at(0) ;
    _xhi = (RooAbsReal*) other._lp->at(1) ;

  } else {

//     cout << "RooParamBinning::cctor(this = " << this << ") taking addresses from orig pointers " << other._xlo << " " << other._xhi << endl ;

    _xlo   = other._xlo ;
    _xhi   = other._xhi ;
  }

  _nbins = other._nbins ;
  _lp = 0 ;

  //cout << "RooParamBinning::cctor(this = " << this << " xlo = " << &_xlo << " xhi = " << &_xhi << " _lp = " << _lp << " owner = " << _owner << ")" << endl ;
}



//_____________________________________________________________________________
void RooParamBinning::insertHook(RooAbsRealLValue& owner) const  
{
  // Hook function called by RooAbsRealLValue when this binning
  // is inserted as binning for into given owner. Create
  // list proxy registered with owner that will track and implement
  // server directs to external RooAbsReals of this binning

  _owner = &owner ;

  // If list proxy already exists update pointers from proxy
//   cout << "RooParamBinning::insertHook(" << this << "," << GetName() << ") _lp at beginning = " << _lp << endl ;
  if (_lp) {
//     cout << "updating raw pointers from list proxy contents" << endl ;
    _xlo = xlo() ;
    _xhi = xhi() ;
    delete _lp ;
  }
//   cout << "_xlo = " << _xlo << " _xhi = " << _xhi << endl ;

  // If list proxy does not exist, create it now
  _lp = new RooListProxy(Form("range::%s",GetName()),"lp",&owner,kFALSE,kTRUE) ;
  _lp->add(*_xlo) ;
  _lp->add(*_xhi) ;
  _xlo = 0 ;
  _xhi = 0 ;


}


//_____________________________________________________________________________
void RooParamBinning::removeHook(RooAbsRealLValue& /*owner*/) const  
{
  // Hook function called by RooAbsRealLValue when this binning
  // is removed as binning for into given owner. Delete list
  // proxy that was inserted in owner

  _owner = 0 ;
  
  // Remove list proxy from owner
  if (_lp) {
    _xlo = xlo() ;
    _xhi = xhi() ;
    delete _lp ;
    _lp = 0 ;
  }
}



//_____________________________________________________________________________
void RooParamBinning::setRange(Double_t newxlo, Double_t newxhi) 
{
  // Adjust range by adjusting values of external RooAbsReal values
  // Only functional when external representations are lvalues

  if (newxlo>newxhi) {
    coutE(InputArguments) << "RooParamBinning::setRange: ERROR low bound > high bound" << endl ;
    return ;
  }

  RooAbsRealLValue* xlolv = dynamic_cast<RooAbsRealLValue*>(xlo()) ;
  if (xlolv) {
    xlolv->setVal(newxlo) ;
  } else {
    coutW(InputArguments) << "RooParamBinning::setRange: WARNING lower bound not represented by lvalue, cannot set lower bound value through setRange()" << endl ;
  }

  RooAbsRealLValue* xhilv = dynamic_cast<RooAbsRealLValue*>(xhi()) ;
  if (xhilv) {
    xhilv->setVal(newxhi) ;
  } else {
    coutW(InputArguments) << "RooParamBinning::setRange: WARNING upper bound not represented by lvalue, cannot set upper bound value through setRange()" << endl ;
  }

}



//_____________________________________________________________________________
Int_t RooParamBinning::binNumber(Double_t x) const  
{
  // Return the fit bin index for the current value

  if (x >= xhi()->getVal()) return _nbins-1 ;
  if (x < xlo()->getVal()) return 0 ;

  return Int_t((x - xlo()->getVal())/averageBinWidth()) ;
}



//_____________________________________________________________________________
Double_t RooParamBinning::binCenter(Int_t i) const 
{
  // Return the central value of the 'i'-th fit bin

  if (i<0 || i>=_nbins) {
    coutE(InputArguments) << "RooParamBinning::binCenter ERROR: bin index " << i 
			  << " is out of range (0," << _nbins-1 << ")" << endl ;
    return 0 ;
  }

  return xlo()->getVal() + (i + 0.5)*averageBinWidth() ;  
}




//_____________________________________________________________________________
Double_t RooParamBinning::binWidth(Int_t /*bin*/) const 
{
  // Return average bin width

  return (xhi()->getVal()-xlo()->getVal())/_nbins ;
}



//_____________________________________________________________________________
Double_t RooParamBinning::binLow(Int_t i) const 
{
  // Return the low edge of the 'i'-th fit bin

  if (i<0 || i>=_nbins) {
    coutE(InputArguments) << "RooParamBinning::binLow ERROR: bin index " << i 
			  << " is out of range (0," << _nbins-1 << ")" << endl ;
    return 0 ;
  }

  return xlo()->getVal() + i*binWidth(i) ;
}



//_____________________________________________________________________________
Double_t RooParamBinning::binHigh(Int_t i) const 
{
  // Return the high edge of the 'i'-th fit bin

  if (i<0 || i>=_nbins) {
    coutE(InputArguments) << "RooParamBinning::fitBinHigh ERROR: bin index " << i 
			  << " is out of range (0," << _nbins-1 << ")" << endl ;
    return 0 ;
  }

  return xlo()->getVal() + (i + 1)*binWidth(i) ;
}



//_____________________________________________________________________________
Double_t* RooParamBinning::array() const 
{
  // Return array of bin boundaries

  if (_array) delete[] _array ;
  _array = new Double_t[_nbins+1] ;

  Int_t i ;
  for (i=0 ; i<=_nbins ; i++) {
    _array[i] = xlo()->getVal() + i*binWidth(i) ;
  }
  return _array ;
}



//_____________________________________________________________________________
void RooParamBinning::printMultiline(ostream &os, Int_t /*content*/, Bool_t /*verbose*/, TString indent) const
{
  // Print details of binning
  os << indent << "_xlo = " << _xlo << endl ;
  os << indent << "_xhi = " << _xhi << endl ;
  if (_lp) {
    os << indent << "xlo() = " << xlo() << endl ;
    os << indent << "xhi() = " << xhi() << endl ;
  }  
  if (xlo()) {
    xlo()->Print("t") ;
  }
  if (xhi()) {
    xhi()->Print("t") ;
  }
}


 RooParamBinning.cxx:1
 RooParamBinning.cxx:2
 RooParamBinning.cxx:3
 RooParamBinning.cxx:4
 RooParamBinning.cxx:5
 RooParamBinning.cxx:6
 RooParamBinning.cxx:7
 RooParamBinning.cxx:8
 RooParamBinning.cxx:9
 RooParamBinning.cxx:10
 RooParamBinning.cxx:11
 RooParamBinning.cxx:12
 RooParamBinning.cxx:13
 RooParamBinning.cxx:14
 RooParamBinning.cxx:15
 RooParamBinning.cxx:16
 RooParamBinning.cxx:17
 RooParamBinning.cxx:18
 RooParamBinning.cxx:19
 RooParamBinning.cxx:20
 RooParamBinning.cxx:21
 RooParamBinning.cxx:22
 RooParamBinning.cxx:23
 RooParamBinning.cxx:24
 RooParamBinning.cxx:25
 RooParamBinning.cxx:26
 RooParamBinning.cxx:27
 RooParamBinning.cxx:28
 RooParamBinning.cxx:29
 RooParamBinning.cxx:30
 RooParamBinning.cxx:31
 RooParamBinning.cxx:32
 RooParamBinning.cxx:33
 RooParamBinning.cxx:34
 RooParamBinning.cxx:35
 RooParamBinning.cxx:36
 RooParamBinning.cxx:37
 RooParamBinning.cxx:38
 RooParamBinning.cxx:39
 RooParamBinning.cxx:40
 RooParamBinning.cxx:41
 RooParamBinning.cxx:42
 RooParamBinning.cxx:43
 RooParamBinning.cxx:44
 RooParamBinning.cxx:45
 RooParamBinning.cxx:46
 RooParamBinning.cxx:47
 RooParamBinning.cxx:48
 RooParamBinning.cxx:49
 RooParamBinning.cxx:50
 RooParamBinning.cxx:51
 RooParamBinning.cxx:52
 RooParamBinning.cxx:53
 RooParamBinning.cxx:54
 RooParamBinning.cxx:55
 RooParamBinning.cxx:56
 RooParamBinning.cxx:57
 RooParamBinning.cxx:58
 RooParamBinning.cxx:59
 RooParamBinning.cxx:60
 RooParamBinning.cxx:61
 RooParamBinning.cxx:62
 RooParamBinning.cxx:63
 RooParamBinning.cxx:64
 RooParamBinning.cxx:65
 RooParamBinning.cxx:66
 RooParamBinning.cxx:67
 RooParamBinning.cxx:68
 RooParamBinning.cxx:69
 RooParamBinning.cxx:70
 RooParamBinning.cxx:71
 RooParamBinning.cxx:72
 RooParamBinning.cxx:73
 RooParamBinning.cxx:74
 RooParamBinning.cxx:75
 RooParamBinning.cxx:76
 RooParamBinning.cxx:77
 RooParamBinning.cxx:78
 RooParamBinning.cxx:79
 RooParamBinning.cxx:80
 RooParamBinning.cxx:81
 RooParamBinning.cxx:82
 RooParamBinning.cxx:83
 RooParamBinning.cxx:84
 RooParamBinning.cxx:85
 RooParamBinning.cxx:86
 RooParamBinning.cxx:87
 RooParamBinning.cxx:88
 RooParamBinning.cxx:89
 RooParamBinning.cxx:90
 RooParamBinning.cxx:91
 RooParamBinning.cxx:92
 RooParamBinning.cxx:93
 RooParamBinning.cxx:94
 RooParamBinning.cxx:95
 RooParamBinning.cxx:96
 RooParamBinning.cxx:97
 RooParamBinning.cxx:98
 RooParamBinning.cxx:99
 RooParamBinning.cxx:100
 RooParamBinning.cxx:101
 RooParamBinning.cxx:102
 RooParamBinning.cxx:103
 RooParamBinning.cxx:104
 RooParamBinning.cxx:105
 RooParamBinning.cxx:106
 RooParamBinning.cxx:107
 RooParamBinning.cxx:108
 RooParamBinning.cxx:109
 RooParamBinning.cxx:110
 RooParamBinning.cxx:111
 RooParamBinning.cxx:112
 RooParamBinning.cxx:113
 RooParamBinning.cxx:114
 RooParamBinning.cxx:115
 RooParamBinning.cxx:116
 RooParamBinning.cxx:117
 RooParamBinning.cxx:118
 RooParamBinning.cxx:119
 RooParamBinning.cxx:120
 RooParamBinning.cxx:121
 RooParamBinning.cxx:122
 RooParamBinning.cxx:123
 RooParamBinning.cxx:124
 RooParamBinning.cxx:125
 RooParamBinning.cxx:126
 RooParamBinning.cxx:127
 RooParamBinning.cxx:128
 RooParamBinning.cxx:129
 RooParamBinning.cxx:130
 RooParamBinning.cxx:131
 RooParamBinning.cxx:132
 RooParamBinning.cxx:133
 RooParamBinning.cxx:134
 RooParamBinning.cxx:135
 RooParamBinning.cxx:136
 RooParamBinning.cxx:137
 RooParamBinning.cxx:138
 RooParamBinning.cxx:139
 RooParamBinning.cxx:140
 RooParamBinning.cxx:141
 RooParamBinning.cxx:142
 RooParamBinning.cxx:143
 RooParamBinning.cxx:144
 RooParamBinning.cxx:145
 RooParamBinning.cxx:146
 RooParamBinning.cxx:147
 RooParamBinning.cxx:148
 RooParamBinning.cxx:149
 RooParamBinning.cxx:150
 RooParamBinning.cxx:151
 RooParamBinning.cxx:152
 RooParamBinning.cxx:153
 RooParamBinning.cxx:154
 RooParamBinning.cxx:155
 RooParamBinning.cxx:156
 RooParamBinning.cxx:157
 RooParamBinning.cxx:158
 RooParamBinning.cxx:159
 RooParamBinning.cxx:160
 RooParamBinning.cxx:161
 RooParamBinning.cxx:162
 RooParamBinning.cxx:163
 RooParamBinning.cxx:164
 RooParamBinning.cxx:165
 RooParamBinning.cxx:166
 RooParamBinning.cxx:167
 RooParamBinning.cxx:168
 RooParamBinning.cxx:169
 RooParamBinning.cxx:170
 RooParamBinning.cxx:171
 RooParamBinning.cxx:172
 RooParamBinning.cxx:173
 RooParamBinning.cxx:174
 RooParamBinning.cxx:175
 RooParamBinning.cxx:176
 RooParamBinning.cxx:177
 RooParamBinning.cxx:178
 RooParamBinning.cxx:179
 RooParamBinning.cxx:180
 RooParamBinning.cxx:181
 RooParamBinning.cxx:182
 RooParamBinning.cxx:183
 RooParamBinning.cxx:184
 RooParamBinning.cxx:185
 RooParamBinning.cxx:186
 RooParamBinning.cxx:187
 RooParamBinning.cxx:188
 RooParamBinning.cxx:189
 RooParamBinning.cxx:190
 RooParamBinning.cxx:191
 RooParamBinning.cxx:192
 RooParamBinning.cxx:193
 RooParamBinning.cxx:194
 RooParamBinning.cxx:195
 RooParamBinning.cxx:196
 RooParamBinning.cxx:197
 RooParamBinning.cxx:198
 RooParamBinning.cxx:199
 RooParamBinning.cxx:200
 RooParamBinning.cxx:201
 RooParamBinning.cxx:202
 RooParamBinning.cxx:203
 RooParamBinning.cxx:204
 RooParamBinning.cxx:205
 RooParamBinning.cxx:206
 RooParamBinning.cxx:207
 RooParamBinning.cxx:208
 RooParamBinning.cxx:209
 RooParamBinning.cxx:210
 RooParamBinning.cxx:211
 RooParamBinning.cxx:212
 RooParamBinning.cxx:213
 RooParamBinning.cxx:214
 RooParamBinning.cxx:215
 RooParamBinning.cxx:216
 RooParamBinning.cxx:217
 RooParamBinning.cxx:218
 RooParamBinning.cxx:219
 RooParamBinning.cxx:220
 RooParamBinning.cxx:221
 RooParamBinning.cxx:222
 RooParamBinning.cxx:223
 RooParamBinning.cxx:224
 RooParamBinning.cxx:225
 RooParamBinning.cxx:226
 RooParamBinning.cxx:227
 RooParamBinning.cxx:228
 RooParamBinning.cxx:229
 RooParamBinning.cxx:230
 RooParamBinning.cxx:231
 RooParamBinning.cxx:232
 RooParamBinning.cxx:233
 RooParamBinning.cxx:234
 RooParamBinning.cxx:235
 RooParamBinning.cxx:236
 RooParamBinning.cxx:237
 RooParamBinning.cxx:238
 RooParamBinning.cxx:239
 RooParamBinning.cxx:240
 RooParamBinning.cxx:241
 RooParamBinning.cxx:242
 RooParamBinning.cxx:243
 RooParamBinning.cxx:244
 RooParamBinning.cxx:245
 RooParamBinning.cxx:246
 RooParamBinning.cxx:247
 RooParamBinning.cxx:248
 RooParamBinning.cxx:249
 RooParamBinning.cxx:250
 RooParamBinning.cxx:251
 RooParamBinning.cxx:252
 RooParamBinning.cxx:253
 RooParamBinning.cxx:254
 RooParamBinning.cxx:255
 RooParamBinning.cxx:256
 RooParamBinning.cxx:257
 RooParamBinning.cxx:258
 RooParamBinning.cxx:259
 RooParamBinning.cxx:260
 RooParamBinning.cxx:261
 RooParamBinning.cxx:262
 RooParamBinning.cxx:263
 RooParamBinning.cxx:264
 RooParamBinning.cxx:265
 RooParamBinning.cxx:266
 RooParamBinning.cxx:267
 RooParamBinning.cxx:268
 RooParamBinning.cxx:269
 RooParamBinning.cxx:270
 RooParamBinning.cxx:271
 RooParamBinning.cxx:272
 RooParamBinning.cxx:273
 RooParamBinning.cxx:274
 RooParamBinning.cxx:275
 RooParamBinning.cxx:276
 RooParamBinning.cxx:277
 RooParamBinning.cxx:278
 RooParamBinning.cxx:279
 RooParamBinning.cxx:280
 RooParamBinning.cxx:281
 RooParamBinning.cxx:282
 RooParamBinning.cxx:283
 RooParamBinning.cxx:284
 RooParamBinning.cxx:285
 RooParamBinning.cxx:286
 RooParamBinning.cxx:287
 RooParamBinning.cxx:288
 RooParamBinning.cxx:289
 RooParamBinning.cxx:290
 RooParamBinning.cxx:291
 RooParamBinning.cxx:292
 RooParamBinning.cxx:293
 RooParamBinning.cxx:294
 RooParamBinning.cxx:295
 RooParamBinning.cxx:296
 RooParamBinning.cxx:297
 RooParamBinning.cxx:298
 RooParamBinning.cxx:299