/*****************************************************************************
 * 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
// Implementation of RooAbsFunc that represent the the integrand
// of a generic (numeric) convolution A (x) B so that it can be
// passed to a numeric integrator. This is a utility class for
// RooNumConvPdf
// END_HTML
//

#include "RooFit.h"

#include "RooConvIntegrandBinding.h"
#include "RooAbsReal.h"
#include "RooArgSet.h"
#include "RooAbsRealLValue.h"
#include "RooMsgService.h"

#include <assert.h>

using namespace std;

ClassImp(RooConvIntegrandBinding)
;


//_____________________________________________________________________________
RooConvIntegrandBinding::RooConvIntegrandBinding(const RooAbsReal& func, const RooAbsReal& model, 
				       RooAbsReal& xprime, RooAbsReal& x, 
				       const RooArgSet* nset, Bool_t clipInvalid) :

  RooAbsFunc(2), _func(&func), _model(&model), _vars(0), _nset(nset), _clipInvalid(clipInvalid)
{
  // Constructor where func and model 
  //
  // 'func'  = func(xprime)
  // 'model' = model(xprime)
  // 
  // and 

  // 'xprime' is the RRV that should be connected to func and model 
  //          (i.e. the variable that will be integrated over)
  // 'x'      is RRV that represents the value at which the convolution is calculated
  //          (this variable should _not_ be connected to func and model)
  //
  // this function returns RCBB[x',x] = f[x']*g[x-x'], i.e. the substiturion g[x'] --> g[x-x'] 
  // is taken care internally
  // 
  // The integral of this binding over its 1st arg yields the convolution (f (x) g)[x]
  //
        
  // allocate memory
  _vars= new RooAbsRealLValue*[2];
  if(0 == _vars) {
    _valid= kFALSE;
    return;
  }

  // check that all of the arguments are real valued and store them
  _vars[0]= dynamic_cast<RooAbsRealLValue*>(&xprime);
  if(0 == _vars[0]) {
    oocoutE(&func,InputArguments) << "RooConvIntegrandBinding: cannot bind to ";
    xprime.Print("1");
    _valid= kFALSE;
  }

  _vars[1]= dynamic_cast<RooAbsRealLValue*>(&x);
  if(0 == _vars[1]) {
    oocoutE(&func,InputArguments) << "RooConvIntegrandBinding: cannot bind to ";
    x.Print("1");
    _valid= kFALSE;
  }

  _xvecValid = kTRUE ;
}



//_____________________________________________________________________________
RooConvIntegrandBinding::~RooConvIntegrandBinding() 
{
  // Destructor
  if(0 != _vars) delete[] _vars;
}


//_____________________________________________________________________________
void RooConvIntegrandBinding::loadValues(const Double_t xvector[], Bool_t clipInvalid) const 
{
  // Load external input values

  _xvecValid = kTRUE ;
  for(UInt_t index= 0; index < _dimension; index++) {
    if (clipInvalid && !_vars[index]->isValidReal(xvector[index])) {
      _xvecValid = kFALSE ;
    } else {
      //cout << "RooConvBasBinding::loadValues[" << index << "] loading value " << xvector[index] << endl ;
      _vars[index]->setVal(xvector[index]);
    }
  }
}  


//_____________________________________________________________________________
Double_t RooConvIntegrandBinding::operator()(const Double_t xvector[]) const 
{
  // Evaluate self at given parameter values

  assert(isValid());
  _ncall++ ;

  // First evaluate function at x'
  loadValues(xvector);
  if (!_xvecValid) return 0 ;
  //cout << "RooConvIntegrandBinding::operator(): evaluating f(x') at x' = " << xvector[0] << endl ;
  Double_t f_xp = _func->getVal(_nset) ;

  // Next evaluate model at x-x'
  const Double_t xvec_tmp[2] = { xvector[1]-xvector[0] , xvector[1] } ;
  loadValues(xvec_tmp,kTRUE);
  if (!_xvecValid) return 0 ;
  Double_t g_xmxp = _model->getVal(_nset) ;

  //cout << "RooConvIntegrandBinding::operator(): evaluating g(x-x') at x-x' = " << _vars[0]->getVal() << " = " << g_xmxp << endl ; 
  //cout << "RooConvIntegrandBinding::operator(): return value = " << f_xp << " * " << g_xmxp << " = " << f_xp*g_xmxp << endl ;

  //cout << "_vars[0] = " << _vars[0]->getVal() << " _vars[1] = " << _vars[1]->getVal() << endl ;
  //cout << "_xvec[0] = " <<  xvector[0]        << " _xvec[1] = " <<  xvector[1] << endl ;

  return f_xp*g_xmxp ;
}


//_____________________________________________________________________________
Double_t RooConvIntegrandBinding::getMinLimit(UInt_t index) const 
{
  // Retrieve lower limit of i-th observable 
  assert(isValid());
  return _vars[index]->getMin();
}


//_____________________________________________________________________________
Double_t RooConvIntegrandBinding::getMaxLimit(UInt_t index) const 
{
  // Retrieve upper limit of i-th observable 

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