/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 *    File: $Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, NIKHEF, verkerke@nikhef.nl                         *
 *                                                                           *
 * Copyright (c) 2000-2008, NIKHEF, Regents of the University of California  *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 *****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
// 
// BEGIN_HTML
// RooCFunction1Binding is a templated implementation of class RooAbsReal that binds 
// generic C(++) functions to a RooAbsReal argument thus allowing generic C++
// functions to be used as RooFit functions. Instances of function binding
// classes are fully functional RooFit function objects with one exception:
// if the bound function is _not_ a standard TMath or MathMore function the
// class cannot be persisted in a RooWorkspace without registering the function
// pointer first using RooCFunction1Binding<T1,T2>::register().
// END_HTML
//

#include "Riostream.h" 
#include "RooFunctorBinding.h" 

using namespace std ;

ClassImp(RooFunctorBinding) 
ClassImp(RooFunctorPdfBinding) 
  ;


RooFunctorBinding::RooFunctorBinding(const char *name, const char *title, const ROOT::Math::IBaseFunctionMultiDim& ftor, const RooArgList& v) :
  RooAbsReal(name,title), 
  func(&ftor),
  vars("vars","vars",this) 
{ 
  // Check that function dimension and number of variables match 
  if (ftor.NDim()!=UInt_t(v.getSize())) {
    coutE(InputArguments) << "RooFunctorBinding::ctor(" << GetName() << ") ERROR number of provided variables (" << v.getSize() 
			  << ") does not match dimensionality of function (" << ftor.NDim() << ")" << endl ;
    throw string("RooFunctor::ctor ERROR") ;
  }
  x = new Double_t[func->NDim()] ;
  vars.add(v) ;
} 


RooFunctorBinding::RooFunctorBinding(const RooFunctorBinding& other, const char* name) :  
  RooAbsReal(other,name), 
  func(other.func),
  vars("vars",this,other.vars)
{ 
  // Copy constructor
  x = new Double_t[func->NDim()] ;
} 



void RooFunctorBinding::printArgs(ostream& os) const {
  // Print object arguments and name/address of function pointer
  os << "[ function=" << func << " " ;    
  for (Int_t i=0 ; i<numProxies() ; i++) {
    RooAbsProxy* p = getProxy(i) ;
    if (!TString(p->name()).BeginsWith("!")) {
      p->print(os) ;
      os << " " ;
    }
  }    
  os << "]" ;  
}

Double_t RooFunctorBinding::evaluate() const {
    // Return value of embedded function using value of referenced variable x
    for (int i=0 ; i<vars.getSize() ; i++) {
      x[i] = ((RooAbsReal*)vars.at(i))->getVal() ;
    }
    return (*func)(x) ;
  }



RooFunctorPdfBinding::RooFunctorPdfBinding(const char *name, const char *title, const ROOT::Math::IBaseFunctionMultiDim& ftor, const RooArgList& v) :
  RooAbsPdf(name,title), 
  func(&ftor),
  vars("vars","vars",this) 
{ 
  // Check that function dimension and number of variables match 
  if (ftor.NDim()!=UInt_t(v.getSize())) {
    coutE(InputArguments) << "RooFunctorPdfBinding::ctor(" << GetName() << ") ERROR number of provided variables (" << v.getSize() 
			  << ") does not match dimensionality of function (" << ftor.NDim() << ")" << endl ;
    throw string("RooFunctor::ctor ERROR") ;
  }
  x = new Double_t[func->NDim()] ;
  vars.add(v) ;
} 


RooFunctorPdfBinding::RooFunctorPdfBinding(const RooFunctorPdfBinding& other, const char* name) :  
  RooAbsPdf(other,name), 
  func(other.func),
  vars("vars",this,other.vars)
{ 
  // Copy constructor
  x = new Double_t[func->NDim()] ;
} 



void RooFunctorPdfBinding::printArgs(ostream& os) const {
  // Print object arguments and name/address of function pointer
  os << "[ function=" << func << " " ;    
  for (Int_t i=0 ; i<numProxies() ; i++) {
    RooAbsProxy* p = getProxy(i) ;
    if (!TString(p->name()).BeginsWith("!")) {
      p->print(os) ;
      os << " " ;
    }
  }    
  os << "]" ;  
}

Double_t RooFunctorPdfBinding::evaluate() const {
    // Return value of embedded function using value of referenced variable x
    for (int i=0 ; i<vars.getSize() ; i++) {
      x[i] = ((RooAbsReal*)vars.at(i))->getVal() ;
    }
    return (*func)(x) ;
  }




namespace RooFit {

  RooAbsReal* bindFunction(const char* name, const ROOT::Math::IBaseFunctionMultiDim& ftor,const RooArgList& vars) {
    return new RooFunctorBinding(name,name,ftor,vars) ;
  }

  RooAbsPdf*  bindPdf(const char* name, const ROOT::Math::IBaseFunctionMultiDim& ftor, const RooArgList& vars) {
    return new RooFunctorPdfBinding(name,name,ftor,vars) ;
  }

}



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