RooCFunction2Binding.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  *    File: $Id: RooCFunction2Binding.h 36207 2010-10-08 19:00:29Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, NIKHEF, verkerke@nikhef.nl                         *
00007  *                                                                           *
00008  * Copyright (c) 2000-2008, NIKHEF, Regents of the University of California  *
00009  *                          and Stanford University. All rights reserved.    *
00010  *                                                                           *
00011  *****************************************************************************/
00012 
00013 #ifndef ROOCFUNCTION2BINDING
00014 #define ROOCFUNCTION2BINDING
00015 
00016 #include "TString.h"
00017 #include "RooAbsReal.h"
00018 #include "RooAbsPdf.h"
00019 #include "RooRealProxy.h"
00020 #include "RooMsgService.h"
00021 #include <string>
00022 #include <map>
00023 #include <vector>
00024 
00025 namespace RooFit {
00026 
00027 typedef Double_t (*CFUNCD2DD)(Double_t,Double_t) ;
00028 typedef Double_t (*CFUNCD2ID)(Int_t,Double_t) ;
00029 typedef Double_t (*CFUNCD2UD)(UInt_t,Double_t) ;
00030 typedef Double_t (*CFUNCD2DI)(Double_t,Int_t) ;
00031 typedef Double_t (*CFUNCD2II)(Int_t,Int_t) ;
00032 
00033 
00034 RooAbsReal* bindFunction(const char* name,void* func,RooAbsReal& x, RooAbsReal& y) ;
00035 RooAbsPdf* bindPdf(const char* name,void* func,RooAbsReal& x, RooAbsReal& y) ;
00036 #ifndef __CINT__
00037 RooAbsReal* bindFunction(const char* name,CFUNCD2DD func,RooAbsReal& x, RooAbsReal& y) ;
00038 RooAbsReal* bindFunction(const char* name,CFUNCD2ID func,RooAbsReal& x, RooAbsReal& y) ;
00039 RooAbsReal* bindFunction(const char* name,CFUNCD2UD func,RooAbsReal& x, RooAbsReal& y) ;
00040 RooAbsReal* bindFunction(const char* name,CFUNCD2DI func,RooAbsReal& x, RooAbsReal& y) ;
00041 RooAbsReal* bindFunction(const char* name,CFUNCD2II func,RooAbsReal& x, RooAbsReal& y) ;
00042 RooAbsPdf* bindPdf(const char* name,CFUNCD2DD func,RooAbsReal& x, RooAbsReal& y) ;
00043 RooAbsPdf* bindPdf(const char* name,CFUNCD2ID func,RooAbsReal& x, RooAbsReal& y) ;
00044 RooAbsPdf* bindPdf(const char* name,CFUNCD2UD func,RooAbsReal& x, RooAbsReal& y) ;
00045 RooAbsPdf* bindPdf(const char* name,CFUNCD2DI func,RooAbsReal& x, RooAbsReal& y) ;
00046 RooAbsPdf* bindPdf(const char* name,CFUNCD2II func,RooAbsReal& x, RooAbsReal& y) ;
00047 #endif
00048 
00049 }
00050 
00051 template<class VO, class VI1, class VI2>
00052 class RooCFunction2Map {
00053  public:
00054   RooCFunction2Map() {} ;
00055 
00056   void add(const char* name, VO (*ptr)(VI1,VI2), const char* arg1name="x", const char* arg2name="y") {
00057     // Register function with given name and argument name
00058     _ptrmap[name] = ptr ;
00059     _namemap[ptr] = name ;
00060     _argnamemap[ptr].push_back(arg1name) ;
00061     _argnamemap[ptr].push_back(arg2name) ;
00062   }
00063 
00064 
00065   const char* lookupName(VO (*ptr)(VI1,VI2)) {
00066     // Return name of function given by pointer
00067     return _namemap[ptr].c_str() ;
00068   }
00069 
00070   VO (*lookupPtr(const char* name))(VI1,VI2) {
00071     // Return pointer of function given by name
00072     return _ptrmap[name] ;
00073   }
00074 
00075   const char* lookupArgName(VO (*ptr)(VI1,VI2), UInt_t iarg) {
00076     // Return name of i-th argument of function. If function is
00077     // not registered, argument names 0,1,2 are x,y,z
00078     if (iarg<_argnamemap[ptr].size()) {
00079       return (_argnamemap[ptr])[iarg].c_str() ;
00080     }
00081     switch (iarg) {
00082     case 0: return "x" ;
00083     case 1: return "y" ;
00084     case 2: return "z" ;
00085     }
00086     return "w" ;
00087   }
00088 
00089  private:
00090 
00091 #ifndef __CINT__
00092   std::map<std::string,VO (*)(VI1,VI2)> _ptrmap ; // Pointer-to-name map
00093   std::map<VO (*)(VI1,VI2),std::string> _namemap ; // Name-to-pointer map
00094   std::map<VO (*)(VI1,VI2),std::vector<std::string> > _argnamemap ; // Pointer-to-argnamelist map
00095 #endif
00096 } ;
00097 
00098 
00099 
00100 template<class VO, class VI1, class VI2>
00101 class RooCFunction2Ref : public TObject {
00102  public:
00103   RooCFunction2Ref(VO (*ptr)(VI1,VI2)=0) : _ptr(ptr) {
00104     // Constructor of persistable function reference
00105   } ;
00106   ~RooCFunction2Ref() {} ;
00107 
00108   VO operator()(VI1 x,VI2 y) const {
00109     // Evaluate embedded function
00110     return (*_ptr)(x,y) ;
00111   }
00112 
00113   const char* name() const {
00114     // Return registered name of embedded function. If function
00115     // is not registered return string with hex presentation
00116     // of function pointer value
00117     const char* result = fmap().lookupName(_ptr) ;
00118     if (result && strlen(result)) {
00119       return result ;
00120     }
00121     // This union is to avoid a warning message:
00122     union { 
00123        void *_ptr;
00124        func_t _funcptr;
00125     } temp;
00126     temp._funcptr = _ptr;
00127     return Form("(%p)",temp._ptr) ;
00128   }
00129 
00130   const char* argName(Int_t iarg) {
00131     // Return suggested name for i-th argument
00132     return fmap().lookupArgName(_ptr,iarg) ;
00133   }
00134 
00135   static RooCFunction2Map<VO,VI1,VI2>& fmap() {
00136     // Return reference to function pointer-to-name mapping service
00137     if (!_fmap) {
00138       _fmap = new RooCFunction2Map<VO,VI1,VI2> ;
00139     }
00140     return *_fmap ;
00141   }
00142 
00143  private:
00144 
00145   static VO dummyFunction(VI1,VI2) {
00146     // Dummy function used when registered function was not
00147     // found in un-persisting object
00148     return 0 ;
00149   }
00150 
00151   typedef VO (*func_t)(VI1,VI2);
00152   func_t _ptr; //! Pointer to embedded function
00153 
00154   static RooCFunction2Map<VO,VI1,VI2>* _fmap ; // Pointer to mapping service object
00155 
00156   ClassDef(RooCFunction2Ref,1) // Persistable reference to C function pointer
00157 } ;
00158 
00159 
00160 
00161 template<class VO, class VI1, class VI2>
00162 void RooCFunction2Ref<VO,VI1,VI2>::Streamer(TBuffer &R__b)
00163 {
00164   // Custom streamer for function pointer reference object. When writing,
00165   // the function pointer is substituted by its registerd name. When function
00166   // is unregistered name 'UNKNOWN' is written and a warning is issues. When
00167   // reading back, the embedded name is converted back to a function pointer
00168   // using the mapping service. When name UNKNOWN is encountered a warning is
00169   // issues and a dummy null function is substituted. When the registered function
00170   // name can not be mapped to a function pointer an ERROR is issued and a pointer
00171   // to the dummy null function is substituted
00172 
00173   typedef ::RooCFunction2Ref<VO,VI1,VI2> thisClass;
00174 
00175    // Stream an object of class RooCFunction2Ref
00176    if (R__b.IsReading()) {
00177 
00178      UInt_t R__s, R__c;
00179      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
00180 
00181      // Read name from file
00182      TString tmpName ;
00183      tmpName.Streamer(R__b) ;
00184 
00185      if (tmpName=="UNKNOWN" && R__v>0) {
00186 
00187        coutW(ObjectHandling) << "WARNING: Objected embeds function pointer to unknown function, object will not be functional" << endl ;
00188        _ptr = dummyFunction ;
00189 
00190      } else {
00191 
00192        // Lookup pointer to C function wih given name
00193        _ptr = fmap().lookupPtr(tmpName.Data()) ;
00194 
00195        if (_ptr==0) {
00196          coutW(ObjectHandling) << "ERROR: Objected embeds pointer to function named " << tmpName
00197                                << " but no such function is registered, object will not be functional" << endl ;
00198        }
00199      }
00200 
00201 
00202      R__b.CheckByteCount(R__s, R__c, thisClass::IsA());
00203 
00204    } else {
00205 
00206      UInt_t R__c;
00207      R__c = R__b.WriteVersion(thisClass::IsA(), kTRUE);
00208 
00209      // Lookup name of reference C function
00210      TString tmpName = fmap().lookupName(_ptr) ;
00211      if (tmpName.Length()==0) {
00212        coutW(ObjectHandling) << "WARNING: Cannot persist unknown function pointer " << Form("0x%lx", (ULong_t)_ptr)
00213                              << " written object will not be functional when read back" <<  endl ;
00214        tmpName="UNKNOWN" ;
00215      }
00216 
00217      // Persist the name
00218      tmpName.Streamer(R__b) ;
00219 
00220      R__b.SetByteCount(R__c, kTRUE);
00221 
00222    }
00223 }
00224 
00225 
00226 
00227 template<class VO,class VI1, class VI2>
00228 class RooCFunction2Binding : public RooAbsReal {
00229 public:
00230   RooCFunction2Binding() {
00231     // Default constructor
00232   } ;
00233   RooCFunction2Binding(const char *name, const char *title, VO (*_func)(VI1,VI2), RooAbsReal& _x, RooAbsReal& _y);
00234   RooCFunction2Binding(const RooCFunction2Binding& other, const char* name=0) ;
00235   virtual TObject* clone(const char* newname) const { return new RooCFunction2Binding(*this,newname); }
00236   inline virtual ~RooCFunction2Binding() { }
00237 
00238   void printArgs(ostream& os) const {
00239     // Print object arguments and name/address of function pointer
00240     os << "[ function=" << func.name() << " " ;
00241     for (Int_t i=0 ; i<numProxies() ; i++) {
00242       RooAbsProxy* p = getProxy(i) ;
00243       if (!TString(p->name()).BeginsWith("!")) {
00244         p->print(os) ;
00245         os << " " ;
00246       }
00247     }
00248     os << "]" ;
00249   }
00250 
00251 protected:
00252 
00253   RooCFunction2Ref<VO,VI1,VI2> func ; // Function pointer reference
00254   RooRealProxy x ;              // Argument reference
00255   RooRealProxy y ;              // Argument reference
00256 
00257   Double_t evaluate() const {
00258     // Return value of embedded function using value of referenced variable x
00259     return func(x,y) ;
00260   }
00261 
00262 private:
00263 
00264   ClassDef(RooCFunction2Binding,1) // RooAbsReal binding to external C functions
00265 };
00266 
00267 template<class VO,class VI1, class VI2>
00268 RooCFunction2Binding<VO,VI1,VI2>::RooCFunction2Binding(const char *name, const char *title, VO (*_func)(VI1,VI2),
00269                                                        RooAbsReal& _x, RooAbsReal& _y) :
00270   RooAbsReal(name,title),
00271   func(_func),
00272   x(func.argName(0),func.argName(0),this,_x),
00273   y(func.argName(1),func.argName(1),this,_y)
00274 {
00275   // Constructor of C function binding object given a pointer to a function and a RooRealVar to which the function
00276   // argument should be bound. This object is fully functional as a RooFit function object. The only restriction is
00277   // if the referenced function is _not_ a standard ROOT TMath or MathCore function it can not be persisted in a
00278   // a RooWorkspace
00279 }
00280 
00281 
00282 template<class VO,class VI1, class VI2>
00283 RooCFunction2Binding<VO,VI1,VI2>::RooCFunction2Binding(const RooCFunction2Binding& other, const char* name) :
00284   RooAbsReal(other,name),
00285   func(other.func),
00286   x("x",this,other.x),
00287   y("y",this,other.y)
00288 {
00289   // Copy constructor
00290 }
00291 
00292 
00293 
00294 
00295 template<class VO,class VI1, class VI2>
00296 class RooCFunction2PdfBinding : public RooAbsPdf {
00297 public:
00298   RooCFunction2PdfBinding() {
00299     // Default constructor
00300   } ;
00301   RooCFunction2PdfBinding(const char *name, const char *title, VO (*_func)(VI1,VI2), RooAbsReal& _x, RooAbsReal& _y);
00302   RooCFunction2PdfBinding(const RooCFunction2PdfBinding& other, const char* name=0) ;
00303   virtual TObject* clone(const char* newname) const { return new RooCFunction2PdfBinding(*this,newname); }
00304   inline virtual ~RooCFunction2PdfBinding() { }
00305 
00306   void printArgs(ostream& os) const {
00307     // Print object arguments and name/address of function pointer
00308     os << "[ function=" << func.name() << " " ;
00309     for (Int_t i=0 ; i<numProxies() ; i++) {
00310       RooAbsProxy* p = getProxy(i) ;
00311       if (!TString(p->name()).BeginsWith("!")) {
00312         p->print(os) ;
00313         os << " " ;
00314       }
00315     }
00316     os << "]" ;
00317   }
00318 
00319 protected:
00320 
00321   RooCFunction2Ref<VO,VI1,VI2> func ; // Function pointer reference
00322   RooRealProxy x ;              // Argument reference
00323   RooRealProxy y ;              // Argument reference
00324 
00325   Double_t evaluate() const {
00326     // Return value of embedded function using value of referenced variable x
00327     return func(x,y) ;
00328   }
00329 
00330 private:
00331 
00332   ClassDef(RooCFunction2PdfBinding,1) // RooAbsReal binding to external C functions
00333 };
00334 
00335 template<class VO,class VI1, class VI2>
00336 RooCFunction2PdfBinding<VO,VI1,VI2>::RooCFunction2PdfBinding(const char *name, const char *title, VO (*_func)(VI1,VI2),
00337                                                        RooAbsReal& _x, RooAbsReal& _y) :
00338   RooAbsPdf(name,title),
00339   func(_func),
00340   x(func.argName(0),func.argName(0),this,_x),
00341   y(func.argName(1),func.argName(1),this,_y)
00342 {
00343   // Constructor of C function binding object given a pointer to a function and a RooRealVar to which the function
00344   // argument should be bound. This object is fully functional as a RooFit function object. The only restriction is
00345   // if the referenced function is _not_ a standard ROOT TMath or MathCore function it can not be persisted in a
00346   // a RooWorkspace
00347 }
00348 
00349 
00350 template<class VO,class VI1, class VI2>
00351 RooCFunction2PdfBinding<VO,VI1,VI2>::RooCFunction2PdfBinding(const RooCFunction2PdfBinding& other, const char* name) :
00352   RooAbsPdf(other,name),
00353   func(other.func),
00354   x("x",this,other.x),
00355   y("y",this,other.y)
00356 {
00357   // Copy constructor
00358 }
00359 
00360 #endif

Generated on Tue Jul 5 14:26:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1