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 (
auto const &
elem : alist) {
387 <<
"std::span<const double> " <<
elem <<
"Span = ctx.at(" <<
elem <<
");\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>
608// Workaround for https://github.com/llvm/llvm-project/issues/138683
609// Include <chrono> before <fstream> to ensure _FilesystemClock is defined
610// Can be removed once the upstream issue is fixed.
617CLASS_NAME::CLASS_NAME(const char *name, const char *title,
621 for (std::size_t i=0 ; i<alist.size() ; i++) {
623 cf <<
" RooAbsReal& _" << alist[i] ;
625 cf <<
" RooAbsCategory& _" << alist[i] ;
627 if (i<alist.size()-1) {
636 cf <<
" : BASE_NAME(name,title)," << std::endl ;
639 for (std::size_t i=0 ; i<alist.size() ; i++) {
640 cf <<
" " << alist[i] <<
"(\"" << alist[i] <<
"\",\"" << alist[i] <<
"\",this,_" << alist[i] <<
")" ;
641 if (i<alist.size()-1) {
647 cf <<
"{" << std::endl
651 <<
"CLASS_NAME::CLASS_NAME(CLASS_NAME const &other, const char *name)" << std::endl
652 <<
" : BASE_NAME(other,name)," << std::endl ;
654 for (std::size_t i=0 ; i<alist.size() ; i++) {
655 cf <<
" " << alist[i] <<
"(\"" << alist[i] <<
"\",this,other." << alist[i] <<
")" ;
656 if (i<alist.size()-1) {
666 <<
"double CLASS_NAME::evaluate() const " << std::endl
668 <<
" return CLASS_NAME_evaluate(" <<
listVars(alist) <<
");" << std::endl
671 <<
"void CLASS_NAME::doEval(RooFit::EvalContext &ctx) const" << std::endl
675 <<
" std::size_t n = ctx.output().size();\n"
676 <<
" for (std::size_t i = 0; i < n; ++i) {\n"
677 <<
" ctx.output()[i] = CLASS_NAME_evaluate(" <<
getFromVarSpans(alist) <<
");\n"
683 for (std::size_t i = 0; i < alist.size(); ++i) {
685 if (i < alist.size() - 1) {
690 cf <<
"void RooFit::Experimental::codegenImpl(CLASS_NAME &arg, RooFit::Experimental::CodegenContext &ctx)\n"
692 <<
" ctx.addResult(&arg, ctx.buildCall(\"CLASS_NAME_evaluate\", " <<
varsGetters.str() <<
"));\n"
710 ptr =
strtok(
nullptr,
":") ;
715int CLASS_NAME::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char */*rangeName*/) const
717 // Support also using the imaginary unit
718 using namespace std::complex_literals;
719 // To be able to also comile C code, we define a variable that behaves like the "I" macro from C.
720 constexpr auto I = 1i;
722 // LIST HERE OVER WHICH VARIABLES ANALYTICAL INTEGRATION IS SUPPORTED,
723 // ASSIGN A NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS. THE EXAMPLE
724 // BELOW ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X YOU CAN ALSO
725 // IMPLEMENT MORE THAN ONE ANALYTICAL INTEGRAL BY REPEATING THE matchArgs
726 // EXPRESSION MULTIPLE TIMES.
731 cf <<
" if (matchArgs(allVars,analVars," <<
intObs[
ii] <<
")) return " <<
ii+1 <<
" ; " << std::endl ;
734 cf <<
" // if (matchArgs(allVars,analVars,x)) return 1 ; " << std::endl ;
737 cf <<
" return 0 ; " << std::endl
742 << R
"(double CLASS_NAME::analyticalIntegral(int code, const char *rangeName) const
744 // RETURN ANALYTICAL INTEGRAL DEFINED BY RETURN CODE ASSIGNED BY
745 // getAnalyticalIntegral(). THE MEMBER FUNCTION x.min(rangeName) AND
746 // x.max(rangeName) WILL RETURN THE INTEGRATION BOUNDARIES FOR EACH
752 cf <<
" if (code==" <<
ii+1 <<
") { return (" <<
intExpr[
ii] <<
") ; } " << std::endl ;
755 cf <<
" // assert(code==1) ; " << std::endl
756 <<
" // return (x.max(rangeName)-x.min(rangeName)) ; " << std::endl ;
759 cf <<
" return 0 ; " << std::endl
760 <<
"} " << std::endl;
765int CLASS_NAME::getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, bool /*staticInitOK*/) const
767 // LIST HERE OVER WHICH VARIABLES INTERNAL GENERATION IS SUPPORTED, ASSIGN A
768 // NUMERIC CODE FOR EACH SUPPORTED (SET OF) PARAMETERS. THE EXAMPLE BELOW
769 // ASSIGNS CODE 1 TO INTEGRATION OVER VARIABLE X. YOU CAN ALSO IMPLEMENT
770 // MORE THAN ONE GENERATOR CONFIGURATION BY REPEATING THE matchArgs
771 // EXPRESSION MULTIPLE TIMES. IF THE FLAG staticInitOK IS TRUE, THEN IT IS
772 // SAFE TO PRECALCULATE INTERMEDIATE QUANTITIES IN initGenerator(), IF IT IS
773 // NOT SET THEN YOU SHOULD NOT ADVERTISE ANY GENERATOR METHOD THAT RELIES ON
774 // PRECALCULATIONS IN initGenerator().
776 // if (matchArgs(directVars,generateVars,x)) return 1;
780void CLASS_NAME::generateEvent(int code)
782 // GENERATE SET OF OBSERVABLES DEFINED BY RETURN CODE ASSIGNED BY
783 // getGenerator(). RETURN THE GENERATED VALUES BY ASSIGNING THEM TO THE
784 // PROXY DATA MEMBERS THAT REPRESENT THE CHOSEN OBSERVABLES.
795 std::ofstream
ohf(className +
".h");
796 std::ofstream
ocf(className +
".cxx");
814 std::vector<std::string> args)
820 if (args.size() < 2) {
821 throw std::runtime_error(
Form(
"RooClassFactory::ClassFacIFace::create() ERROR: CEXPR requires at least 2 "
822 "arguments (expr,var,...), but only %u args found",
830 expr[args[0].size() - 2] = 0;
834 if (args.size() == 2) {
838 for (
unsigned int i = 1; i < args.size(); i++) {
845 className =
Form(
"RooCFAuto%03d%s%s",
classCounter, (
tn ==
"CEXPR") ?
"Pdf" :
"Func",
ft.autoClassNamePostFix());
859 throw std::runtime_error(
860 Form(
"RooClassFactory::ClassFacIFace::create() ERROR creating %s %s with RooClassFactory",
868 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)