51using std::endl, std::vector, std::string;
74bool makeAndCompileClass(std::string
const &baseClassName, std::string
const &
name, std::string
const &expression,
81 ClassInfo(std::string
const &baseClassName, std::string
const &
name, std::string
const &expression,
107 static std::vector<ClassInfo>
infosVec;
115 if (*found ==
info) {
118 std::stringstream
ss;
119 ss <<
"RooClassFactory ERROR The type, expressions, or variables for the class \"" <<
name
120 <<
"\" are not identical to what you passed last time this class was compiled! This is not allowed.";
121 oocoutE(
nullptr, InputArguments) <<
ss.str() << std::endl;
122 throw std::runtime_error(
ss.str());
137 }
else if (arg->isCategory()) {
142 oocoutE(
nullptr, InputArguments) <<
"RooClassFactory ERROR input argument " << arg->GetName()
143 <<
" is neither RooAbsReal nor RooAbsCategory and is ignored" << std::endl;
170 std::string
line = std::string(
"new ") + className +
"(\"" +
name +
"\",\"" +
name +
"\"";
180 argList +=
Form(
",*reinterpret_cast<RooAbsReal*>(0x%zx)",
reinterpret_cast<std::size_t
>(var));
185 if (var->isCategory()) {
186 argList +=
Form(
",*reinterpret_cast<RooAbsCategory*>(0x%zx)",
reinterpret_cast<std::size_t
>(var));
190 line += argList +
") ;";
251 string className =
"Roo" +
tmpName +
"Func";
277 std::string
const &expression,
const RooArgList &vars,
296 string className =
"Roo" +
tmpName +
"Pdf";
322 std::string
const &expression,
const RooArgList &vars,
367std::string
listVars(std::vector<std::string>
const &alist, std::vector<bool>
const &
isCat = {})
369 std::stringstream
ss;
370 for (std::size_t i = 0; i < alist.size(); ++i) {
371 if (!
isCat.empty()) {
372 ss << (
isCat[i] ?
"int" :
"double") <<
" ";
375 if (i < alist.size() - 1) {
384 std::stringstream
ss;
385 for (std::size_t i = 0; i < alist.size(); ++i) {
387 <<
"std::span<const double> " << alist[i] <<
"Span = ctx.at(" << alist[i] <<
");\n";
394 std::stringstream
ss;
395 for (std::size_t i = 0; i < alist.size(); ++i) {
396 std::string
name = alist[i] +
"Span";
397 ss <<
name <<
".size() > 1 ? " <<
name <<
"[i] : " <<
name <<
"[0]";
398 if (i < alist.size() - 1) {
407 return c !=
'_' && !std::isalnum(
c);
410bool isComplex(std::string
const &expression)
414 for (std::size_t i = 0; i < expression.size(); ++i) {
451 oocoutE(
nullptr, InputArguments)
452 <<
"RooClassFactory::makeClass: ERROR: A list of input argument names must be given" << std::endl;
457 oocoutE(
nullptr, InputArguments) <<
"RooClassFactory::makeClass: ERROR no analytical integration code "
458 "requestion, but expression for analytical integral provided"
468 alist.push_back(
token);
469 isCat.push_back(
false);
472 alist.push_back(
token);
473 isCat.push_back(
true);
477 std::stringstream
hf;
478 hf << R
"(/*****************************************************************************
481 * This code was autogenerated by RooClassFactory *
482 *****************************************************************************/
487#include <BASE_NAME.h>
488#include <RooRealProxy.h>
489#include <RooCategoryProxy.h>
490#include <RooAbsReal.h>
491#include <RooAbsCategory.h>
495class CLASS_NAME : public BASE_NAME {
498 CLASS_NAME(const char *name, const char *title,)";
501 for (std::size_t i=0 ; i<alist.size() ; i++) {
503 hf <<
" RooAbsReal& _" ;
505 hf <<
" RooAbsCategory& _" ;
508 if (i==alist.size()-1) {
509 hf <<
");" << std::endl ;
511 hf <<
"," << std::endl ;
515 hf << R
"( CLASS_NAME(CLASS_NAME const &other, const char *name=nullptr);
516 TObject* clone(const char *newname) const override { return new CLASS_NAME(*this, newname); }
521 int getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char *rangeName=nullptr) const override;
522 double analyticalIntegral(int code, const char *rangeName=nullptr) const override;
528 int getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, bool staticInitOK=true) const override;
529 void initGenerator(int code) override {} // optional pre-generation initialization
530 void generateEvent(int code) override;
534 hf << "" << std::endl ;
537 for (std::size_t i=0 ; i<alist.size() ; i++) {
539 hf <<
" RooRealProxy " << alist[i] <<
" ;" << std::endl ;
541 hf <<
" RooCategoryProxy " << alist[i] <<
" ;" << std::endl ;
546 double evaluate() const override;
547 void doEval(RooFit::EvalContext &) const override;
551 ClassDefOverride(CLASS_NAME, 1) // Your description goes here...
555namespace Experimental {
557void codegenImpl(CLASS_NAME &arg, CodegenContext &ctx);
559} // namespace Experimental
565 hf << "inline double CLASS_NAME_evaluate(" <<
listVars(alist,
isCat) <<
")";
572 // Support also using the imaginary unit
573 using namespace std::complex_literals;
574 // To be able to also comile C code, we define a variable that behaves like the "I" macro from C.
575 constexpr auto I = 1i;
580 // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE
583 << " return " << expression <<
";" << std::endl
587 hf <<
"\n#endif // CLASS_NAME_h";
589 std::stringstream
cf;
591 cf << R
"(/*****************************************************************************
594 * This code was autogenerated by RooClassFactory *
595 *****************************************************************************/
597// Your description goes here...
599#include "CLASS_NAME.h"
601#include <RooAbsReal.h>
602#include <RooAbsCategory.h>
604#include <Riostream.h>
610CLASS_NAME::CLASS_NAME(const char *name, const char *title,
614 for (std::size_t i=0 ; i<alist.size() ; i++) {
616 cf <<
" RooAbsReal& _" << alist[i] ;
618 cf <<
" RooAbsCategory& _" << alist[i] ;
620 if (i<alist.size()-1) {
629 cf <<
" : BASE_NAME(name,title)," << std::endl ;
632 for (std::size_t i=0 ; i<alist.size() ; i++) {
633 cf <<
" " << alist[i] <<
"(\"" << alist[i] <<
"\",\"" << alist[i] <<
"\",this,_" << alist[i] <<
")" ;
634 if (i<alist.size()-1) {
640 cf <<
"{" << std::endl
644 <<
"CLASS_NAME::CLASS_NAME(CLASS_NAME const &other, const char *name)" << std::endl
645 <<
" : BASE_NAME(other,name)," << std::endl ;
647 for (std::size_t i=0 ; i<alist.size() ; i++) {
648 cf <<
" " << alist[i] <<
"(\"" << alist[i] <<
"\",this,other." << alist[i] <<
")" ;
649 if (i<alist.size()-1) {
659 <<
"double CLASS_NAME::evaluate() const " << std::endl
661 <<
" return CLASS_NAME_evaluate(" <<
listVars(alist) <<
");" << std::endl
664 <<
"void CLASS_NAME::doEval(RooFit::EvalContext &ctx) const" << std::endl
668 <<
" std::size_t n = ctx.output().size();\n"
669 <<
" for (std::size_t i = 0; i < n; ++i) {\n"
670 <<
" ctx.output()[i] = CLASS_NAME_evaluate(" <<
getFromVarSpans(alist) <<
");\n"
676 for (std::size_t i = 0; i < alist.size(); ++i) {
678 if (i < alist.size() - 1) {
683 cf <<
"void RooFit::Experimental::codegenImpl(CLASS_NAME &arg, RooFit::Experimental::CodegenContext &ctx)\n"
685 <<
" ctx.addResult(&arg, ctx.buildCall(\"CLASS_NAME_evaluate\", " <<
varsGetters.str() <<
"));\n"
697 std::vector<char> buf(
bufSize);
699 char* ptr =
strtok(buf.data(),
":") ;
703 ptr =
strtok(
nullptr,
":") ;
708int CLASS_NAME::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char */*rangeName*/) const
710 // Support also using the imaginary unit
711 using namespace std::complex_literals;
712 // To be able to also comile C code, we define a variable that behaves like the "I" macro from C.
713 constexpr auto I = 1i;
715 // LIST HERE OVER WHICH VARIABLES ANALYTICAL INTEGRATION IS SUPPORTED,
716 // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS. THE EXAMPLE
717 // BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X YOU CAN ALSO
718 // IMPLEMENT MORE THAN ONE ANALYTICAL INTEGRAL BY REPEATING THE matchArgs
719 // EXPRESSION MULTIPLE TIMES.
724 cf <<
" if (matchArgs(allVars,analVars," <<
intObs[
ii] <<
")) return " <<
ii+1 <<
" ; " << std::endl ;
727 cf <<
" // if (matchArgs(allVars,analVars,x)) return 1 ; " << std::endl ;
730 cf <<
" return 0 ; " << std::endl
735 << R
"(double CLASS_NAME::analyticalIntegral(int code, const char *rangeName) const
737 // RETURN ANALYTICAL INTEGRAL DEFINED BY RETURN CODE ASSIGNED BY
738 // getAnalyticalIntegral(). THE MEMBER FUNCTION x.min(rangeName) AND
739 // x.max(rangeName) WILL RETURN THE INTEGRATION BOUNDARIES FOR EACH
745 cf <<
" if (code==" <<
ii+1 <<
") { return (" <<
intExpr[
ii] <<
") ; } " << std::endl ;
748 cf <<
" // assert(code==1) ; " << std::endl
749 <<
" // return (x.max(rangeName)-x.min(rangeName)) ; " << std::endl ;
752 cf <<
" return 0 ; " << std::endl
753 <<
"} " << std::endl;
758int CLASS_NAME::getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, bool /*staticInitOK*/) const
760 // LIST HERE OVER WHICH VARIABLES INTERNAL GENERATION IS SUPPORTED, ASSIGN A
761 // NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS. THE EXAMPLE BELOW
762 // ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X. YOU CAN ALSO IMPLEMENT
763 // MORE THAN ONE GENERATOR CONFIGURATION BY REPEATING THE matchArgs
764 // EXPRESSION MULTIPLE TIMES. IF THE FLAG staticInitOK IS TRUE, THEN IT IS
765 // SAFE TO PRECALCULATE INTERMEDIATE QUANTITIES IN initGenerator(), IF IT IS
766 // NOT SET THEN YOU SHOULD NOT ADVERTISE ANY GENERATOR METHOD THAT RELIES ON
767 // PRECALCULATIONS IN initGenerator().
769 // if (matchArgs(directVars,generateVars,x)) return 1;
773void CLASS_NAME::generateEvent(int code)
775 // GENERATE SET OF OBSERVABLES DEFINED BY RETURN CODE ASSIGNED BY
776 // getGenerator(). RETURN THE GENERATED VALUES BY ASSIGNING THEM TO THE
777 // PROXY DATA MEMBERS THAT REPRESENT THE CHOSEN OBSERVABLES.
788 std::ofstream
ohf(className +
".h");
789 std::ofstream
ocf(className +
".cxx");
807 std::vector<std::string> args)
813 if (args.size() < 2) {
814 throw std::runtime_error(
Form(
"RooClassFactory::ClassFacIFace::create() ERROR: CEXPR requires at least 2 "
815 "arguments (expr,var,...), but only %u args found",
823 expr[args[0].size() - 2] = 0;
827 if (args.size() == 2) {
831 for (
unsigned int i = 1; i < args.size(); i++) {
838 className =
Form(
"RooCFAuto%03d%s%s",
classCounter, (
tn ==
"CEXPR") ?
"Pdf" :
"Func",
ft.autoClassNamePostFix());
852 throw std::runtime_error(
853 Form(
"RooClassFactory::ClassFacIFace::create() ERROR creating %s %s with RooClassFactory",
861 ft.ws().importClassCode(
ret->IsA());
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Bool_t operator==(const TDatime &d1, const TDatime &d2)
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
const_iterator begin() const
const_iterator end() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Storage_t::size_type size() const
Abstract interface for all probability density functions.
Abstract base class for objects that represent a real value and implements functionality common to al...
RooArgList is a container object that can hold multiple RooAbsArg objects.
static bool makePdf(std::string const &name, std::string const &realArgNames="", std::string const &catArgNames="", std::string const &expression="1.0", bool hasAnaInt=false, bool hasIntGen=false, std::string const &intExpression="")
Write code for a RooAbsPdf implementation with class name 'name'.
static bool makeAndCompilePdf(std::string const &name, std::string const &expression, const RooArgList &vars, std::string const &intExpression="")
static RooAbsReal * makeFunctionInstance(std::string const &className, std::string const &name, std::string const &expression, const RooArgList &vars, std::string const &intExpression="")
Write, compile and load code and instantiate object for a RooAbsReal implementation with class name '...
static bool makeFunction(std::string const &name, std::string const &realArgNames="", std::string const &catArgNames="", std::string const &expression="1.0", bool hasAnaInt=false, std::string const &intExpression="")
Write code for a RooAbsReal implementation with class name 'name', taking RooAbsReal arguments with n...
static RooAbsPdf * makePdfInstance(std::string const &className, std::string const &name, std::string const &expression, const RooArgList &vars, std::string const &intExpression="")
Write, compile and load code and instantiate object for a RooAbsPdf implementation with class name 'n...
static bool makeClass(std::string const &baseName, const std::string &className, std::string const &realArgNames="", std::string const &catArgNames="", std::string const &expression="1.0", bool hasAnaInt=false, bool hasIntGen=false, std::string const &intExpression="")
Write code for a 'baseName' implementation with class name 'className', taking RooAbsReal arguments w...
static bool makeAndCompileFunction(std::string const &name, std::string const &expression, const RooArgList &args, std::string const &intExpression="")
Write, compile and load code for a RooAbsReal implementation with class name 'name',...
static void softAbort()
Soft abort function that interrupts macro execution but doesn't kill ROOT.
TClass instances represent classes, structs and namespaces in the ROOT type system.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
RooCmdArg Silence(bool flag=true)
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
void replaceAll(std::string &inOut, std::string_view what, std::string_view with)