From 51fa2e1edd00b93c9c77b1f36b129893a93224f0 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Sat, 10 Oct 2026 16:42:10 +0200 Subject: [PATCH 1/2] [RF] Share one name <-> pointer map between the RooCFunctionNRef classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RooCFunction[1-4]Map classes were four copies of the same class, differing only in the function pointer type. Replace them with a single `RooFit::Detail::CFunctionMap` template, keeping the old names as alias templates so that `RooCFunctionNRef<...>::fmap().add(...)` keeps working. Argument names are now passed variadically; unnamed arguments still fall back to x, y, z, w. The "registered name or hex address" logic of the RooCFunctionNRef::name() functions is moved into the map as well. No class layout or persisted class name changes. 🤖 Done with the help of AI --- roofit/roofit/CMakeLists.txt | 1 + roofit/roofit/inc/RooCFunction1Binding.h | 62 +----------- roofit/roofit/inc/RooCFunction2Binding.h | 63 +----------- roofit/roofit/inc/RooCFunction3Binding.h | 64 +----------- roofit/roofit/inc/RooCFunction4Binding.h | 67 +------------ .../inc/RooFit/Detail/CFunctionBinding.h | 97 +++++++++++++++++++ 6 files changed, 114 insertions(+), 240 deletions(-) create mode 100644 roofit/roofit/inc/RooFit/Detail/CFunctionBinding.h diff --git a/roofit/roofit/CMakeLists.txt b/roofit/roofit/CMakeLists.txt index 9df36a28f25aa..8f6926ddd67c2 100644 --- a/roofit/roofit/CMakeLists.txt +++ b/roofit/roofit/CMakeLists.txt @@ -38,6 +38,7 @@ set(ROOFIT_HEADERS RooDecay.h RooDstD0BG.h RooExponential.h + RooFit/Detail/CFunctionBinding.h RooFunctor1DBinding.h RooFunctorBinding.h RooGExpModel.h diff --git a/roofit/roofit/inc/RooCFunction1Binding.h b/roofit/roofit/inc/RooCFunction1Binding.h index 802b67ac96a4d..79b19bff59195 100644 --- a/roofit/roofit/inc/RooCFunction1Binding.h +++ b/roofit/roofit/inc/RooCFunction1Binding.h @@ -17,14 +17,11 @@ #include "RooAbsPdf.h" #include "RooRealProxy.h" #include "RooMsgService.h" +#include "RooFit/Detail/CFunctionBinding.h" #include "TBuffer.h" #include "TString.h" -#include -#include -#include - namespace RooFit { @@ -39,49 +36,8 @@ RooAbsPdf* bindPdf(const char* name,CFUNCD1I func,RooAbsReal& x) ; } -template -class RooCFunction1Map { - public: - RooCFunction1Map() {} ; - - void add(const char* name, VO (*ptr)(VI), const char* arg1name="x") { - // Register function with given name and argument name - _ptrmap[name] = ptr ; - _namemap[ptr] = name ; - _argnamemap[ptr].push_back(arg1name) ; - } - - - const char* lookupName(VO (*ptr)(VI)) { - // Return name of function given by pointer - return _namemap[ptr].c_str() ; - } - - VO (*lookupPtr(const char* name))(VI) { - // Return pointer of function given by name - return _ptrmap[name] ; - } - - const char* lookupArgName(VO (*ptr)(VI), UInt_t iarg) { - // Return name of i-th argument of function. If function is - // not registered, argument names 0,1,2 are x,y,z - if (iarg<_argnamemap[ptr].size()) { - return (_argnamemap[ptr])[iarg].c_str() ; - } - switch (iarg) { - case 0: return "x" ; - case 1: return "y" ; - case 2: return "z" ; - } - return "w" ; - } - - private: - - std::map _ptrmap ; // Pointer-to-name map - std::map _namemap ; // Name-to-pointer map - std::map > _argnamemap ; // Pointer-to-argnamelist map -} ; +template +using RooCFunction1Map = RooFit::Detail::CFunctionMap; @@ -101,17 +57,7 @@ class RooCFunction1Ref : public TObject { // Return registered name of embedded function. If function // is not registered return string with hex presentation // of function pointer value - const char* result = fmap().lookupName(_ptr) ; - if (result && strlen(result)) { - return result ; - } - // This union is to avoid a warning message: - union { - void *_ptr; - func_t _funcptr; - } temp; - temp._funcptr = _ptr; - return Form("(%p)",temp._ptr) ; + return fmap().nameOrAddress(_ptr); } const char* argName(Int_t iarg) { diff --git a/roofit/roofit/inc/RooCFunction2Binding.h b/roofit/roofit/inc/RooCFunction2Binding.h index 76e30a43a1bfc..ebb7a02c269ae 100644 --- a/roofit/roofit/inc/RooCFunction2Binding.h +++ b/roofit/roofit/inc/RooCFunction2Binding.h @@ -17,14 +17,11 @@ #include "RooAbsPdf.h" #include "RooRealProxy.h" #include "RooMsgService.h" +#include "RooFit/Detail/CFunctionBinding.h" #include "TBuffer.h" #include "TString.h" -#include -#include -#include - namespace RooFit { typedef double (*CFUNCD2DD)(double,double) ; @@ -47,50 +44,8 @@ RooAbsPdf* bindPdf(const char* name,CFUNCD2II func,RooAbsReal& x, RooAbsReal& y) } -template -class RooCFunction2Map { - public: - RooCFunction2Map() {} ; - - void add(const char* name, VO (*ptr)(VI1,VI2), const char* arg1name="x", const char* arg2name="y") { - // Register function with given name and argument name - _ptrmap[name] = ptr ; - _namemap[ptr] = name ; - _argnamemap[ptr].push_back(arg1name) ; - _argnamemap[ptr].push_back(arg2name) ; - } - - - const char* lookupName(VO (*ptr)(VI1,VI2)) { - // Return name of function given by pointer - return _namemap[ptr].c_str() ; - } - - VO (*lookupPtr(const char* name))(VI1,VI2) { - // Return pointer of function given by name - return _ptrmap[name] ; - } - - const char* lookupArgName(VO (*ptr)(VI1,VI2), UInt_t iarg) { - // Return name of i-th argument of function. If function is - // not registered, argument names 0,1,2 are x,y,z - if (iarg<_argnamemap[ptr].size()) { - return (_argnamemap[ptr])[iarg].c_str() ; - } - switch (iarg) { - case 0: return "x" ; - case 1: return "y" ; - case 2: return "z" ; - } - return "w" ; - } - - private: - - std::map _ptrmap ; // Pointer-to-name map - std::map _namemap ; // Name-to-pointer map - std::map > _argnamemap ; // Pointer-to-argnamelist map -} ; +template +using RooCFunction2Map = RooFit::Detail::CFunctionMap; @@ -110,17 +65,7 @@ class RooCFunction2Ref : public TObject { // Return registered name of embedded function. If function // is not registered return string with hex presentation // of function pointer value - const char* result = fmap().lookupName(_ptr) ; - if (result && strlen(result)) { - return result ; - } - // This union is to avoid a warning message: - union { - void *_ptr; - func_t _funcptr; - } temp; - temp._funcptr = _ptr; - return Form("(%p)",temp._ptr) ; + return fmap().nameOrAddress(_ptr); } const char* argName(Int_t iarg) { diff --git a/roofit/roofit/inc/RooCFunction3Binding.h b/roofit/roofit/inc/RooCFunction3Binding.h index 8bfbb86ec8bc4..d058dbd278d8e 100644 --- a/roofit/roofit/inc/RooCFunction3Binding.h +++ b/roofit/roofit/inc/RooCFunction3Binding.h @@ -16,14 +16,11 @@ #include "RooRealProxy.h" #include "RooMsgService.h" #include "RooAbsPdf.h" +#include "RooFit/Detail/CFunctionBinding.h" #include "TBuffer.h" #include "TString.h" -#include -#include -#include - namespace RooFit { @@ -49,51 +46,8 @@ RooAbsPdf* bindPdf(const char* name,CFUNCD3UUD func,RooAbsReal& x, RooAbsReal& y } -template -class RooCFunction3Map { - public: - RooCFunction3Map() {} ; - - void add(const char* name, VO (*ptr)(VI1,VI2,VI3), const char* arg1name="x", const char* arg2name="y", const char* arg3name="z") { - // Register function with given name and argument name - _ptrmap[name] = ptr ; - _namemap[ptr] = name ; - _argnamemap[ptr].push_back(arg1name) ; - _argnamemap[ptr].push_back(arg2name) ; - _argnamemap[ptr].push_back(arg3name) ; - } - - - const char* lookupName(VO (*ptr)(VI1,VI2,VI3)) { - // Return name of function given by pointer - return _namemap[ptr].c_str() ; - } - - VO (*lookupPtr(const char* name))(VI1,VI2,VI3) { - // Return pointer of function given by name - return _ptrmap[name] ; - } - - const char* lookupArgName(VO (*ptr)(VI1,VI2,VI3), UInt_t iarg) { - // Return name of i-th argument of function. If function is - // not registered, argument names 0,1,2 are x,y,z - if (iarg<_argnamemap[ptr].size()) { - return (_argnamemap[ptr])[iarg].c_str() ; - } - switch (iarg) { - case 0: return "x" ; - case 1: return "y" ; - case 2: return "z" ; - } - return "w" ; - } - - private: - - std::map _ptrmap ; // Pointer-to-name map - std::map _namemap ; // Name-to-pointer map - std::map > _argnamemap ; // Pointer-to-argnamelist map -} ; +template +using RooCFunction3Map = RooFit::Detail::CFunctionMap; template @@ -112,17 +66,7 @@ class RooCFunction3Ref : public TObject { // Return registered name of embedded function. If function // is not registered return string with hex presentation // of function pointer value - const char* result = fmap().lookupName(_ptr) ; - if (result && strlen(result)) { - return result ; - } - // This union is to avoid a warning message: - union { - void *_ptr; - func_t _funcptr; - } temp; - temp._funcptr = _ptr; - return Form("(%p)",temp._ptr) ; + return fmap().nameOrAddress(_ptr); } const char* argName(Int_t iarg) { diff --git a/roofit/roofit/inc/RooCFunction4Binding.h b/roofit/roofit/inc/RooCFunction4Binding.h index 0e3a8c02cb62e..1da4beadbb16a 100644 --- a/roofit/roofit/inc/RooCFunction4Binding.h +++ b/roofit/roofit/inc/RooCFunction4Binding.h @@ -17,14 +17,11 @@ #include "RooAbsPdf.h" #include "RooRealProxy.h" #include "RooMsgService.h" +#include "RooFit/Detail/CFunctionBinding.h" #include "TBuffer.h" #include "TString.h" -#include -#include -#include - namespace RooFit { typedef double (*CFUNCD4DDDD)(double,double,double,double) ; @@ -41,54 +38,8 @@ RooAbsPdf* bindPdf(const char* name,CFUNCD4DDDB func,RooAbsReal& x, RooAbsReal& } -template -class RooCFunction4Map { - public: - RooCFunction4Map() {} ; - - void add(const char* name, VO (*ptr)(VI1,VI2,VI3,VI4), const char* arg1name="x", const char* arg2name="y", - const char* arg3name="z", const char* arg4name="w") { - // Register function with given name and argument name - _ptrmap[name] = ptr ; - _namemap[ptr] = name ; - _argnamemap[ptr].push_back(arg1name) ; - _argnamemap[ptr].push_back(arg2name) ; - _argnamemap[ptr].push_back(arg3name) ; - _argnamemap[ptr].push_back(arg4name) ; - } - - - const char* lookupName(VO (*ptr)(VI1,VI2,VI3,VI4)) { - // Return name of function given by pointer - return _namemap[ptr].c_str() ; - } - - VO (*lookupPtr(const char* name))(VI1,VI2,VI3,VI4) { - // Return pointer of function given by name - return _ptrmap[name] ; - } - - const char* lookupArgName(VO (*ptr)(VI1,VI2,VI3,VI4), UInt_t iarg) { - // Return name of i-th argument of function. If function is - // not registered, argument names 0,1,2 are x,y,z - if (iarg<_argnamemap[ptr].size()) { - return (_argnamemap[ptr])[iarg].c_str() ; - } - switch (iarg) { - case 0: return "x" ; - case 1: return "y" ; - case 2: return "z" ; - case 3: return "w" ; - } - return "v" ; - } - - private: - - std::map _ptrmap ; // Pointer-to-name map - std::map _namemap ; // Name-to-pointer map - std::map > _argnamemap ; // Pointer-to-argnamelist map -} ; +template +using RooCFunction4Map = RooFit::Detail::CFunctionMap; @@ -108,17 +59,7 @@ class RooCFunction4Ref : public TObject { // Return registered name of embedded function. If function // is not registered return string with hex presentation // of function pointer value - const char* result = fmap().lookupName(_ptr) ; - if (result && strlen(result)) { - return result ; - } - // This union is to avoid a warning message: - union { - void *_ptr; - func_t _funcptr; - } temp; - temp._funcptr = _ptr; - return Form("(%p)",temp._ptr) ; + return fmap().nameOrAddress(_ptr); } const char* argName(Int_t iarg) { diff --git a/roofit/roofit/inc/RooFit/Detail/CFunctionBinding.h b/roofit/roofit/inc/RooFit/Detail/CFunctionBinding.h new file mode 100644 index 0000000000000..9667b37efda61 --- /dev/null +++ b/roofit/roofit/inc/RooFit/Detail/CFunctionBinding.h @@ -0,0 +1,97 @@ +/* + * Project: RooFit + * 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. + * + * 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) + */ + +#ifndef RooFit_Detail_CFunctionBinding_h +#define RooFit_Detail_CFunctionBinding_h + +// Implementation details shared by the RooCFunction[1-4]Binding classes. + +#include + +#include +#include +#include +#include + +namespace RooFit { +namespace Detail { + +/// Name <-> pointer mapping service for C functions of type `Func`, used to +/// persist the RooCFunction[1-4]Ref function pointer references. +template +class CFunctionMap { +public: + /// Register function with given name and argument names. Arguments without + /// a name are called x, y, z, w. + template + void add(const char *name, Func ptr, ArgNames... argNames) + { + _ptrmap[name] = ptr; + _namemap[ptr] = name; + (_argnamemap[ptr].emplace_back(argNames), ...); + } + + /// Return name of function given by pointer. + const char *lookupName(Func ptr) { return _namemap[ptr].c_str(); } + + /// Return pointer of function given by name. + Func lookupPtr(const char *name) { return _ptrmap[name]; } + + /// Return name of i-th argument of function. If no name was registered, + /// the arguments are called x, y, z, w. + const char *lookupArgName(Func ptr, UInt_t iarg) + { + if (iarg < _argnamemap[ptr].size()) { + return (_argnamemap[ptr])[iarg].c_str(); + } + switch (iarg) { + case 0: return "x"; + case 1: return "y"; + case 2: return "z"; + case 3: return "w"; + } + return "v"; + } + + /// Return registered name of a function. If the function is not + /// registered, return a string with the hex representation of the pointer. + const char *nameOrAddress(Func ptr) + { + const char *result = lookupName(ptr); + if (result && strlen(result)) { + return result; + } + return Form("(%p)", toVoidPtr(ptr)); + } + + static void *toVoidPtr(Func ptr) + { + // This union is to avoid a warning message: + union { + void *_ptr; + Func _funcptr; + } temp; + temp._funcptr = ptr; + return temp._ptr; + } + +private: + std::map _ptrmap; // Name-to-pointer map + std::map _namemap; // Pointer-to-name map + std::map> _argnamemap; // Pointer-to-argnamelist map +}; + +} // namespace Detail +} // namespace RooFit + +#endif From 25017ce4edd2727e4f20658bb1e7423af06aa516 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Sun, 11 Oct 2026 11:42:26 +0200 Subject: [PATCH 2/2] [RF] Share the streamer and printArgs code of the C function bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The custom `Streamer()` of the RooCFunction[1-4]Ref classes and the `printArgs()` of the RooCFunction[1-4]Binding and PdfBinding classes were identical copies. Implement them once in `RooFit::Detail::streamCFunctionRef()` and `RooFit::Detail::printCFunctionArgs()`. The on-file format is unchanged: files written before this change are read back identically and vice versa. 🤖 Done with the help of AI --- roofit/roofit/inc/RooCFunction1Binding.h | 91 +------------------ roofit/roofit/inc/RooCFunction2Binding.h | 85 +---------------- roofit/roofit/inc/RooCFunction3Binding.h | 91 +------------------ roofit/roofit/inc/RooCFunction4Binding.h | 85 +---------------- .../inc/RooFit/Detail/CFunctionBinding.h | 82 +++++++++++++++++ 5 files changed, 94 insertions(+), 340 deletions(-) diff --git a/roofit/roofit/inc/RooCFunction1Binding.h b/roofit/roofit/inc/RooCFunction1Binding.h index 79b19bff59195..cd215117b69bf 100644 --- a/roofit/roofit/inc/RooCFunction1Binding.h +++ b/roofit/roofit/inc/RooCFunction1Binding.h @@ -16,12 +16,8 @@ #include "RooAbsReal.h" #include "RooAbsPdf.h" #include "RooRealProxy.h" -#include "RooMsgService.h" #include "RooFit/Detail/CFunctionBinding.h" -#include "TBuffer.h" -#include "TString.h" - namespace RooFit { @@ -90,72 +86,7 @@ RooCFunction1Map* RooCFunction1Ref::_fmap = nullptr; template void RooCFunction1Ref::Streamer(TBuffer &R__b) { - // Custom streamer for function pointer reference object. When writing, - // the function pointer is substituted by its registered name. When function - // is unregistered name 'UNKNOWN' is written and a warning is issues. When - // reading back, the embedded name is converted back to a function pointer - // using the mapping service. When name UNKNOWN is encountered a warning is - // issues and a dummy null function is substituted. When the registered function - // name can not be mapped to a function pointer an ERROR is issued and a pointer - // to the dummy null function is substituted - - typedef ::RooCFunction1Ref thisClass; - - // Stream an object of class RooCFunction1Ref - if (R__b.IsReading()) { - - UInt_t R__s; - UInt_t R__c; - Version_t R__v = R__b.ReadVersion(&R__s, &R__c); - - // Read name from file - TString tmpName ; - tmpName.Streamer(R__b) ; - - if (tmpName=="UNKNOWN" && R__v>0) { - - coutW(ObjectHandling) << "WARNING: Objected embeds function pointer to unknown function, object will not be functional" << std::endl ; - _ptr = dummyFunction ; - - } else { - - // Lookup pointer to C function with given name - _ptr = fmap().lookupPtr(tmpName.Data()) ; - - if (_ptr==nullptr) { - coutW(ObjectHandling) << "ERROR: Objected embeds pointer to function named " << tmpName - << " but no such function is registered, object will not be functional" << std::endl ; - } - } - - - R__b.CheckByteCount(R__s, R__c, thisClass::IsA()); - - } else { - - UInt_t R__c; - R__c = R__b.WriteVersion(thisClass::IsA(), true); - - // Lookup name of reference C function - TString tmpName = fmap().lookupName(_ptr) ; - if (tmpName.Length()==0) { - // This union is to avoid a warning message: - union { - void *_ptr; - func_t _funcptr; - } temp; - temp._funcptr = _ptr; - coutW(ObjectHandling) << "WARNING: Cannot persist unknown function pointer " << Form("%p",temp._ptr) - << " written object will not be functional when read back" << std::endl ; - tmpName="UNKNOWN" ; - } - - // Persist the name - tmpName.Streamer(R__b) ; - - R__b.SetByteCount(R__c, true); - - } + RooFit::Detail::streamCFunctionRef(R__b, *this, _ptr, dummyFunction, fmap()); } @@ -172,15 +103,7 @@ class RooCFunction1Binding : public RooAbsReal { void printArgs(std::ostream& os) const override { // Print object arguments and name/address of function pointer - os << "[ function=" << func.name() << " " ; - for (Int_t i=0 ; iname()).BeginsWith("!")) { - p->print(os) ; - os << " " ; - } - } - os << "]" ; + RooFit::Detail::printCFunctionArgs(os, *this, func.name()); } protected: @@ -235,15 +158,7 @@ class RooCFunction1PdfBinding : public RooAbsPdf { void printArgs(std::ostream& os) const override { // Print object arguments and name/address of function pointer - os << "[ function=" << func.name() << " " ; - for (Int_t i=0 ; iname()).BeginsWith("!")) { - p->print(os) ; - os << " " ; - } - } - os << "]" ; + RooFit::Detail::printCFunctionArgs(os, *this, func.name()); } protected: diff --git a/roofit/roofit/inc/RooCFunction2Binding.h b/roofit/roofit/inc/RooCFunction2Binding.h index ebb7a02c269ae..b26c7c2cecee1 100644 --- a/roofit/roofit/inc/RooCFunction2Binding.h +++ b/roofit/roofit/inc/RooCFunction2Binding.h @@ -16,12 +16,8 @@ #include "RooAbsReal.h" #include "RooAbsPdf.h" #include "RooRealProxy.h" -#include "RooMsgService.h" #include "RooFit/Detail/CFunctionBinding.h" -#include "TBuffer.h" -#include "TString.h" - namespace RooFit { typedef double (*CFUNCD2DD)(double,double) ; @@ -105,66 +101,7 @@ RooCFunction2Map* RooCFunction2Ref::_fmap = nullptr; template void RooCFunction2Ref::Streamer(TBuffer &R__b) { - // Custom streamer for function pointer reference object. When writing, - // the function pointer is substituted by its registered name. When function - // is unregistered name 'UNKNOWN' is written and a warning is issues. When - // reading back, the embedded name is converted back to a function pointer - // using the mapping service. When name UNKNOWN is encountered a warning is - // issues and a dummy null function is substituted. When the registered function - // name can not be mapped to a function pointer an ERROR is issued and a pointer - // to the dummy null function is substituted - - typedef ::RooCFunction2Ref thisClass; - - // Stream an object of class RooCFunction2Ref - if (R__b.IsReading()) { - - UInt_t R__s; - UInt_t R__c; - Version_t R__v = R__b.ReadVersion(&R__s, &R__c); - - // Read name from file - TString tmpName ; - tmpName.Streamer(R__b) ; - - if (tmpName=="UNKNOWN" && R__v>0) { - - coutW(ObjectHandling) << "WARNING: Objected embeds function pointer to unknown function, object will not be functional" << std::endl ; - _ptr = dummyFunction ; - - } else { - - // Lookup pointer to C function with given name - _ptr = fmap().lookupPtr(tmpName.Data()) ; - - if (_ptr==nullptr) { - coutW(ObjectHandling) << "ERROR: Objected embeds pointer to function named " << tmpName - << " but no such function is registered, object will not be functional" << std::endl ; - } - } - - - R__b.CheckByteCount(R__s, R__c, thisClass::IsA()); - - } else { - - UInt_t R__c; - R__c = R__b.WriteVersion(thisClass::IsA(), true); - - // Lookup name of reference C function - TString tmpName = fmap().lookupName(_ptr) ; - if (tmpName.Length()==0) { - coutW(ObjectHandling) << "WARNING: Cannot persist unknown function pointer " << Form("0x%zx", (size_t)_ptr) - << " written object will not be functional when read back" << std::endl ; - tmpName="UNKNOWN" ; - } - - // Persist the name - tmpName.Streamer(R__b) ; - - R__b.SetByteCount(R__c, true); - - } + RooFit::Detail::streamCFunctionRef(R__b, *this, _ptr, dummyFunction, fmap()); } @@ -181,15 +118,7 @@ class RooCFunction2Binding : public RooAbsReal { void printArgs(std::ostream& os) const override { // Print object arguments and name/address of function pointer - os << "[ function=" << func.name() << " " ; - for (Int_t i=0 ; iname()).BeginsWith("!")) { - p->print(os) ; - os << " " ; - } - } - os << "]" ; + RooFit::Detail::printCFunctionArgs(os, *this, func.name()); } protected: @@ -248,15 +177,7 @@ class RooCFunction2PdfBinding : public RooAbsPdf { void printArgs(std::ostream& os) const override { // Print object arguments and name/address of function pointer - os << "[ function=" << func.name() << " " ; - for (Int_t i=0 ; iname()).BeginsWith("!")) { - p->print(os) ; - os << " " ; - } - } - os << "]" ; + RooFit::Detail::printCFunctionArgs(os, *this, func.name()); } protected: diff --git a/roofit/roofit/inc/RooCFunction3Binding.h b/roofit/roofit/inc/RooCFunction3Binding.h index d058dbd278d8e..97839c15c0348 100644 --- a/roofit/roofit/inc/RooCFunction3Binding.h +++ b/roofit/roofit/inc/RooCFunction3Binding.h @@ -14,13 +14,9 @@ #include "RooAbsReal.h" #include "RooRealProxy.h" -#include "RooMsgService.h" #include "RooAbsPdf.h" #include "RooFit/Detail/CFunctionBinding.h" -#include "TBuffer.h" -#include "TString.h" - namespace RooFit { @@ -108,72 +104,7 @@ RooCFunction3Map* RooCFunction3Ref::_fmap = null template void RooCFunction3Ref::Streamer(TBuffer &R__b) { - // Custom streamer for function pointer reference object. When writing, - // the function pointer is substituted by its registered name. When function - // is unregistered name 'UNKNOWN' is written and a warning is issues. When - // reading back, the embedded name is converted back to a function pointer - // using the mapping service. When name UNKNOWN is encountered a warning is - // issues and a dummy null function is substituted. When the registered function - // name can not be mapped to a function pointer an ERROR is issued and a pointer - // to the dummy null function is substituted - - typedef ::RooCFunction3Ref thisClass; - - // Stream an object of class RooCFunction3Ref - if (R__b.IsReading()) { - - UInt_t R__s; - UInt_t R__c; - Version_t R__v = R__b.ReadVersion(&R__s, &R__c); - - // Read name from file - TString tmpName ; - tmpName.Streamer(R__b) ; - - if (tmpName=="UNKNOWN" && R__v>0) { - - coutW(ObjectHandling) << "WARNING: Objected embeds function pointer to unknown function, object will not be functional" << std::endl ; - _ptr = dummyFunction ; - - } else { - - // Lookup pointer to C function with given name - _ptr = fmap().lookupPtr(tmpName.Data()) ; - - if (_ptr==nullptr) { - coutW(ObjectHandling) << "ERROR: Objected embeds pointer to function named " << tmpName - << " but no such function is registered, object will not be functional" << std::endl ; - } - } - - - R__b.CheckByteCount(R__s, R__c, thisClass::IsA()); - - } else { - - UInt_t R__c; - R__c = R__b.WriteVersion(thisClass::IsA(), true); - - // Lookup name of reference C function - TString tmpName = fmap().lookupName(_ptr) ; - if (tmpName.Length()==0) { - // This union is to avoid a warning message: - union { - void *_ptr; - func_t _funcptr; - } temp; - temp._funcptr = _ptr; - coutW(ObjectHandling) << "WARNING: Cannot persist unknown function pointer " << Form("%p",temp._ptr) - << " written object will not be functional when read back" << std::endl ; - tmpName="UNKNOWN" ; - } - - // Persist the name - tmpName.Streamer(R__b) ; - - R__b.SetByteCount(R__c, true); - - } + RooFit::Detail::streamCFunctionRef(R__b, *this, _ptr, dummyFunction, fmap()); } @@ -190,15 +121,7 @@ class RooCFunction3Binding : public RooAbsReal { void printArgs(std::ostream& os) const override { // Print object arguments and name/address of function pointer - os << "[ function=" << func.name() << " " ; - for (Int_t i=0 ; iname()).BeginsWith("!")) { - p->print(os) ; - os << " " ; - } - } - os << "]" ; + RooFit::Detail::printCFunctionArgs(os, *this, func.name()); } protected: @@ -260,15 +183,7 @@ class RooCFunction3PdfBinding : public RooAbsPdf { void printArgs(std::ostream& os) const override { // Print object arguments and name/address of function pointer - os << "[ function=" << func.name() << " " ; - for (Int_t i=0 ; iname()).BeginsWith("!")) { - p->print(os) ; - os << " " ; - } - } - os << "]" ; + RooFit::Detail::printCFunctionArgs(os, *this, func.name()); } protected: diff --git a/roofit/roofit/inc/RooCFunction4Binding.h b/roofit/roofit/inc/RooCFunction4Binding.h index 1da4beadbb16a..ef9ba07d3194a 100644 --- a/roofit/roofit/inc/RooCFunction4Binding.h +++ b/roofit/roofit/inc/RooCFunction4Binding.h @@ -16,12 +16,8 @@ #include "RooAbsReal.h" #include "RooAbsPdf.h" #include "RooRealProxy.h" -#include "RooMsgService.h" #include "RooFit/Detail/CFunctionBinding.h" -#include "TBuffer.h" -#include "TString.h" - namespace RooFit { typedef double (*CFUNCD4DDDD)(double,double,double,double) ; @@ -98,66 +94,7 @@ RooCFunction4Map* RooCFunction4Ref::_fma template void RooCFunction4Ref::Streamer(TBuffer &R__b) { - // Custom streamer for function pointer reference object. When writing, - // the function pointer is substituted by its registered name. When function - // is unregistered name 'UNKNOWN' is written and a warning is issues. When - // reading back, the embedded name is converted back to a function pointer - // using the mapping service. When name UNKNOWN is encountered a warning is - // issues and a dummy null function is substituted. When the registered function - // name can not be mapped to a function pointer an ERROR is issued and a pointer - // to the dummy null function is substituted - - typedef ::RooCFunction4Ref thisClass; - - // Stream an object of class RooCFunction4Ref - if (R__b.IsReading()) { - - UInt_t R__s; - UInt_t R__c; - Version_t R__v = R__b.ReadVersion(&R__s, &R__c); - - // Read name from file - TString tmpName ; - tmpName.Streamer(R__b) ; - - if (tmpName=="UNKNOWN" && R__v>0) { - - coutW(ObjectHandling) << "WARNING: Objected embeds function pointer to unknown function, object will not be functional" << std::endl ; - _ptr = dummyFunction ; - - } else { - - // Lookup pointer to C function with given name - _ptr = fmap().lookupPtr(tmpName.Data()) ; - - if (_ptr==nullptr) { - coutW(ObjectHandling) << "ERROR: Objected embeds pointer to function named " << tmpName - << " but no such function is registered, object will not be functional" << std::endl ; - } - } - - - R__b.CheckByteCount(R__s, R__c, thisClass::IsA()); - - } else { - - UInt_t R__c; - R__c = R__b.WriteVersion(thisClass::IsA(), true); - - // Lookup name of reference C function - TString tmpName = fmap().lookupName(_ptr) ; - if (tmpName.Length()==0) { - coutW(ObjectHandling) << "WARNING: Cannot persist unknown function pointer " << Form("0x%zx",(size_t)_ptr) - << " written object will not be functional when read back" << std::endl ; - tmpName="UNKNOWN" ; - } - - // Persist the name - tmpName.Streamer(R__b) ; - - R__b.SetByteCount(R__c, true); - - } + RooFit::Detail::streamCFunctionRef(R__b, *this, _ptr, dummyFunction, fmap()); } @@ -174,15 +111,7 @@ class RooCFunction4Binding : public RooAbsReal { void printArgs(std::ostream& os) const override { // Print object arguments and name/address of function pointer - os << "[ function=" << func.name() << " " ; - for (Int_t i=0 ; iname()).BeginsWith("!")) { - p->print(os) ; - os << " " ; - } - } - os << "]" ; + RooFit::Detail::printCFunctionArgs(os, *this, func.name()); } protected: @@ -246,15 +175,7 @@ class RooCFunction4PdfBinding : public RooAbsPdf { void printArgs(std::ostream& os) const override { // Print object arguments and name/address of function pointer - os << "[ function=" << func.name() << " " ; - for (Int_t i=0 ; iname()).BeginsWith("!")) { - p->print(os) ; - os << " " ; - } - } - os << "]" ; + RooFit::Detail::printCFunctionArgs(os, *this, func.name()); } protected: diff --git a/roofit/roofit/inc/RooFit/Detail/CFunctionBinding.h b/roofit/roofit/inc/RooFit/Detail/CFunctionBinding.h index 9667b37efda61..1fe467362cbcd 100644 --- a/roofit/roofit/inc/RooFit/Detail/CFunctionBinding.h +++ b/roofit/roofit/inc/RooFit/Detail/CFunctionBinding.h @@ -16,10 +16,16 @@ // Implementation details shared by the RooCFunction[1-4]Binding classes. +#include +#include +#include + +#include #include #include #include +#include #include #include @@ -91,6 +97,82 @@ class CFunctionMap { std::map> _argnamemap; // Pointer-to-argnamelist map }; +/// Custom streamer for function pointer reference objects. When writing, +/// the function pointer is substituted by its registered name. When function +/// is unregistered name 'UNKNOWN' is written and a warning is issued. When +/// reading back, the embedded name is converted back to a function pointer +/// using the mapping service. When name UNKNOWN is encountered a warning is +/// issued and a dummy null function is substituted. When the registered function +/// name can not be mapped to a function pointer an ERROR is issued. +template +void streamCFunctionRef(TBuffer &R__b, TObject const &self, Func &ptr, Func dummyFunction, CFunctionMap &fmap) +{ + if (R__b.IsReading()) { + + UInt_t R__s; + UInt_t R__c; + Version_t R__v = R__b.ReadVersion(&R__s, &R__c); + + // Read name from file + TString tmpName; + tmpName.Streamer(R__b); + + if (tmpName == "UNKNOWN" && R__v > 0) { + + oocoutW(&self, ObjectHandling) + << "WARNING: Objected embeds function pointer to unknown function, object will not be functional" + << std::endl; + ptr = dummyFunction; + + } else { + + // Lookup pointer to C function with given name + ptr = fmap.lookupPtr(tmpName.Data()); + + if (ptr == nullptr) { + oocoutW(&self, ObjectHandling) + << "ERROR: Objected embeds pointer to function named " << tmpName + << " but no such function is registered, object will not be functional" << std::endl; + } + } + + R__b.CheckByteCount(R__s, R__c, self.IsA()); + + } else { + + UInt_t R__c; + R__c = R__b.WriteVersion(self.IsA(), true); + + // Lookup name of reference C function + TString tmpName = fmap.lookupName(ptr); + if (tmpName.Length() == 0) { + oocoutW(&self, ObjectHandling) << "WARNING: Cannot persist unknown function pointer " + << Form("%p", CFunctionMap::toVoidPtr(ptr)) + << " written object will not be functional when read back" << std::endl; + tmpName = "UNKNOWN"; + } + + // Persist the name + tmpName.Streamer(R__b); + + R__b.SetByteCount(R__c, true); + } +} + +/// Print arguments of a function binding and name/address of the function pointer. +inline void printCFunctionArgs(std::ostream &os, RooAbsArg const &arg, const char *funcName) +{ + os << "[ function=" << funcName << " "; + for (Int_t i = 0; i < arg.numProxies(); i++) { + RooAbsProxy *p = arg.getProxy(i); + if (!TString(p->name()).BeginsWith("!")) { + p->print(os); + os << " "; + } + } + os << "]"; +} + } // namespace Detail } // namespace RooFit