Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
CodegenImpl.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Garima Singh, CERN 2023
5 * Jonas Rembser, CERN 2024
6 *
7 * Copyright (c) 2024, CERN
8 *
9 * Redistribution and use in source and binary forms,
10 * with or without modification, are permitted according to the terms
11 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
12 */
13
14#include <RooFit/CodegenImpl.h>
15
17
18#include <RooAddPdf.h>
19#include <RooAddition.h>
20#include <RooBernstein.h>
21#include <RooBifurGauss.h>
22#include <RooCBShape.h>
23#include <RooChebychev.h>
24#include <RooConstVar.h>
25#include <RooConstraintSum.h>
26#include <RooEffProd.h>
27#include <RooEfficiency.h>
28#include <RooExponential.h>
29#include <RooExtendPdf.h>
32#include <RooFormulaVar.h>
33#include <RooGamma.h>
34#include <RooGaussian.h>
35#include <RooGenericPdf.h>
36#include <RooHistFunc.h>
37#include <RooHistPdf.h>
38#include <RooLandau.h>
39#include <RooLognormal.h>
40#include <RooMultiVarGaussian.h>
41#include <RooParamHistFunc.h>
42#include <RooPoisson.h>
43#include <RooPolyVar.h>
44#include <RooPolynomial.h>
45#include <RooProdPdf.h>
46#include <RooProduct.h>
47#include <RooRatio.h>
48#include <RooRealIntegral.h>
49#include <RooRealSumFunc.h>
50#include <RooRealSumPdf.h>
51#include <RooRealVar.h>
56#include <RooUniform.h>
57#include <RooWrapperPdf.h>
58
59#include "RooFitImplHelpers.h"
60
61#include <TInterpreter.h>
62
63namespace RooFit {
64namespace Experimental {
65
66namespace {
67
68std::string mathFunc(std::string const &name)
69{
70 return "RooFit::Detail::MathFuncs::" + name;
71}
72
73void rooHistTranslateImpl(RooAbsArg const &arg, CodegenContext &ctx, int intOrder, RooDataHist const &dataHist,
74 const RooArgSet &obs, bool correctForBinSize, bool cdfBoundaries)
75{
76 if (intOrder != 0 && !(!cdfBoundaries && !correctForBinSize && intOrder == 1 && obs.size() == 1)) {
77 ooccoutE(&arg, InputArguments) << "RooHistPdf::weight(" << arg.GetName()
78 << ") ERROR: codegen currently only supports non-interpolation cases."
79 << std::endl;
80 return;
81 }
82
83 if (intOrder == 1) {
84 RooAbsBinning const &binning = *dataHist.getBinnings()[0];
85 std::string weightArr = dataHist.declWeightArrayForCodeSquash(ctx, correctForBinSize);
86 ctx.addResult(&arg, ctx.buildCall(mathFunc("interpolate1d"), binning.lowBound(), binning.highBound(), *obs[0],
87 binning.numBins(), weightArr));
88 return;
89 }
90 std::string const &offset = dataHist.calculateTreeIndexForCodeSquash(ctx, obs);
91 std::string weightArr = dataHist.declWeightArrayForCodeSquash(ctx, correctForBinSize);
92 ctx.addResult(&arg, "*(" + weightArr + " + " + offset + ")");
93}
94
95std::string realSumPdfTranslateImpl(CodegenContext &ctx, RooAbsArg const &arg, RooArgList const &funcList,
96 RooArgList const &coefList, bool normalize)
97{
98 bool noLastCoeff = funcList.size() != coefList.size();
99
100 std::string const &funcName = ctx.buildArg(funcList);
101 std::string const &coeffName = ctx.buildArg(coefList);
102 std::string const &coeffSize = std::to_string(coefList.size());
103
104 std::string sum = ctx.getTmpVarName();
105 std::string coeffSum = ctx.getTmpVarName();
106 ctx.addToCodeBody(&arg, "double " + sum + " = 0;\ndouble " + coeffSum + "= 0;\n");
107
108 std::string iterator = "i_" + ctx.getTmpVarName();
109 std::string subscriptExpr = "[" + iterator + "]";
110
111 std::string code = "for(int " + iterator + " = 0; " + iterator + " < " + coeffSize + "; " + iterator + "++) {\n" +
112 sum + " += " + funcName + subscriptExpr + " * " + coeffName + subscriptExpr + ";\n";
113 code += coeffSum + " += " + coeffName + subscriptExpr + ";\n";
114 code += "}\n";
115
116 if (noLastCoeff) {
117 code += sum + " += " + funcName + "[" + coeffSize + "]" + " * (1 - " + coeffSum + ");\n";
118 } else if (normalize) {
119 code += sum + " /= " + coeffSum + ";\n";
120 }
121 ctx.addToCodeBody(&arg, code);
122
123 return sum;
124}
125
126} // namespace
127
129{
130 if (arg.cache()._isRearranged) {
131 ctx.addResult(&arg, ctx.buildCall(mathFunc("ratio"), *arg.cache()._rearrangedNum, *arg.cache()._rearrangedDen));
132 } else {
133 ctx.addResult(&arg, ctx.buildCall(mathFunc("product"), arg.cache()._partList, arg.cache()._partList.size()));
134 }
135}
136
138{
139 std::string const &idx = arg.dataHist().calculateTreeIndexForCodeSquash(ctx, arg.dataVars(), true);
140 std::string const &paramNames = ctx.buildArg(arg.paramList());
141
142 ctx.addResult(&arg, paramNames + "[" + idx + "]");
143}
144
146{
147 auto const &interpCodes = arg.interpolationCodes();
148
149 std::size_t n = interpCodes.size();
150
151 std::string resName = "total_" + ctx.getTmpVarName();
152 for (std::size_t i = 0; i < n; ++i) {
153 if (interpCodes[i] != interpCodes[0]) {
155 << "FlexibleInterpVar::evaluate ERROR: Code Squashing AD does not yet support having "
156 "different interpolation codes for the same class object "
157 << std::endl;
158 }
159 }
160
161 // The PiecewiseInterpolation class is used in the context of HistFactory
162 // models, where is is always used the same way: all RooAbsReals in _lowSet,
163 // _histSet, and also nominal are 1D RooHistFuncs with with same structure.
164 //
165 // Therefore, we can make a big optimization: we get the bin index only once
166 // here in the generated code for PiecewiseInterpolation. Then, we also
167 // rearrange the histogram data in such a way that we can always pass the
168 // same arrays to the free function that implements the interpolation, just
169 // with a dynamic offset calculated from the bin index.
170 RooDataHist const &nomHist = dynamic_cast<RooHistFunc const &>(*arg.nominalHist()).dataHist();
171 int nBins = nomHist.numEntries();
172 std::vector<double> valsNominal;
173 std::vector<double> valsLow;
174 std::vector<double> valsHigh;
175 for (int i = 0; i < nBins; ++i) {
176 valsNominal.push_back(nomHist.weight(i));
177 }
178 for (int i = 0; i < nBins; ++i) {
179 for (std::size_t iParam = 0; iParam < n; ++iParam) {
180 valsLow.push_back(dynamic_cast<RooHistFunc const &>(arg.lowList()[iParam]).dataHist().weight(i));
181 valsHigh.push_back(dynamic_cast<RooHistFunc const &>(arg.highList()[iParam]).dataHist().weight(i));
182 }
183 }
184 std::string idxName = ctx.getTmpVarName();
185 std::string valsNominalStr = ctx.buildArg(valsNominal);
186 std::string valsLowStr = ctx.buildArg(valsLow);
187 std::string valsHighStr = ctx.buildArg(valsHigh);
188 std::string nStr = std::to_string(n);
189 std::string code;
190
191 std::string lowName = ctx.getTmpVarName();
192 std::string highName = ctx.getTmpVarName();
193 std::string nominalName = ctx.getTmpVarName();
194 code +=
195 "unsigned int " + idxName + " = " +
196 nomHist.calculateTreeIndexForCodeSquash(ctx, dynamic_cast<RooHistFunc const &>(*arg.nominalHist()).variables()) +
197 ";\n";
198 code += "double const* " + lowName + " = " + valsLowStr + " + " + nStr + " * " + idxName + ";\n";
199 code += "double const* " + highName + " = " + valsHighStr + " + " + nStr + " * " + idxName + ";\n";
200 code += "double " + nominalName + " = *(" + valsNominalStr + " + " + idxName + ");\n";
201
202 std::string funcCall = ctx.buildCall(mathFunc("flexibleInterp"), interpCodes[0], arg.paramList(), n, lowName,
203 highName, 1.0, nominalName, 0.0);
204 code += "double " + resName + " = " + funcCall + ";\n";
205
206 if (arg.positiveDefinite()) {
207 code += resName + " = " + resName + " < 0 ? 0 : " + resName + ";\n";
208 }
209
210 ctx.addToCodeBody(&arg, code);
211 ctx.addResult(&arg, resName);
212}
213
214////////////////////////////////////////////////////////////////////////////////
215/// This function defines a translation for each RooAbsReal based object that can be used
216/// to express the class as simple C++ code. The function adds the code represented by
217/// each class as an std::string (that is later concatenated with code strings from translate calls)
218/// to form the C++ code that AD tools can understand. Any class that wants to support AD, has to
219/// implement this function.
220///
221/// \param[in] ctx An object to manage auxiliary information for code-squashing. Also takes the
222/// code string that this class outputs into the squashed code through the 'addToCodeBody' function.
224{
225 std::stringstream errorMsg;
226 errorMsg << "Translate function for class \"" << arg.ClassName() << "\" has not yet been implemented.";
227 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
228 return ctx.addResult(&arg, "1.0");
229}
230
232{
233 ctx.addResult(&arg, realSumPdfTranslateImpl(ctx, arg, arg.pdfList(), arg.coefList(), true));
234}
235
237{
238 auto const &covI = arg.covarianceMatrixInverse();
239 std::span<const double> covISpan{covI.GetMatrixArray(), static_cast<size_t>(covI.GetNoElements())};
240 ctx.addResult(&arg,
241 ctx.buildCall(mathFunc("multiVarGaussian"), arg.xVec().size(), arg.xVec(), arg.muVec(), covISpan));
242}
243
245{
246 if (arg.list().empty()) {
247 ctx.addResult(&arg, "0.0");
248 }
249 std::string result;
250 if (arg.list().size() > 1)
251 result += "(";
252
253 std::size_t i = 0;
254 for (auto *component : static_range_cast<RooAbsReal *>(arg.list())) {
255
256 if (!dynamic_cast<RooFit::Detail::RooNLLVarNew *>(component) || arg.list().size() == 1) {
257 result += ctx.getResult(*component);
258 ++i;
259 if (i < arg.list().size())
260 result += '+';
261 continue;
262 }
263 result += ctx.buildFunction(*component, ctx.outputSizes()) + "(params, obs, xlArr)";
264 ++i;
265 if (i < arg.list().size())
266 result += '+';
267 }
268 if (arg.list().size() > 1)
269 result += ')';
270 ctx.addResult(&arg, result);
271}
272
274{
275 arg.fillBuffer();
276 ctx.addResult(&arg, ctx.buildCall(mathFunc("bernstein"), arg.x(), arg.xmin(), arg.xmax(), arg.coefList(),
277 arg.coefList().size()));
278}
279
281{
282 ctx.addResult(&arg,
283 ctx.buildCall(mathFunc("bifurGauss"), arg.getX(), arg.getMean(), arg.getSigmaL(), arg.getSigmaR()));
284}
285
287{
288 ctx.addResult(
289 &arg, ctx.buildCall(mathFunc("cbShape"), arg.getM(), arg.getM0(), arg.getSigma(), arg.getAlpha(), arg.getN()));
290}
291
293{
294 // first bring the range of the variable _x to the normalised range [-1, 1]
295 // calculate sum_k c_k T_k(x) where x is given in the normalised range,
296 // c_0 = 1, and the higher coefficients are given in _coefList
297 double xmax = static_cast<RooAbsRealLValue const &>(arg.x()).getMax(arg.refRangeName());
298 double xmin = static_cast<RooAbsRealLValue const &>(arg.x()).getMin(arg.refRangeName());
299
300 ctx.addResult(&arg,
301 ctx.buildCall(mathFunc("chebychev"), arg.coefList(), arg.coefList().size(), arg.x(), xmin, xmax));
302}
303
305{
306 // Just return a stringy-field version of the const value.
307 // Formats to the maximum precision.
308 constexpr auto max_precision{std::numeric_limits<double>::digits10 + 1};
309 std::stringstream ss;
310 ss.precision(max_precision);
311 // Just use toString to make sure we do not output 'inf'.
312 // This is really ugly for large numbers...
313 ss << std::fixed << RooNumber::toString(arg.getVal());
314 ctx.addResult(&arg, ss.str());
315}
316
318{
319 ctx.addResult(&arg, ctx.buildCall(mathFunc("constraintSum"), arg.list(), arg.list().size()));
320}
321
323{
324 ctx.addResult(&arg, ctx.buildCall("TMath::GammaDist", arg.getX(), arg.getGamma(), arg.getMu(), arg.getBeta()));
325}
326
328{
329 arg.getVal(); // to trigger the creation of the TFormula
330 std::string funcName = arg.getUniqueFuncName();
331 ctx.collectFunction(funcName);
332 ctx.addResult(&arg, ctx.buildCall(funcName, arg.dependents()));
333}
334
336{
337 ctx.addResult(&arg, ctx.buildCall(mathFunc("effProd"), arg.eff(), arg.pdf()));
338}
339
341{
342 RooAbsCategory const &cat = arg.cat();
343 int sigCatIndex = cat.lookupIndex(arg.sigCatName());
344 ctx.addResult(&arg, ctx.buildCall(mathFunc("efficiency"), arg.effFunc(), cat, sigCatIndex));
345}
346
348{
349 // Build a call to the stateless exponential defined later.
350 std::string coef;
351 if (arg.negateCoefficient()) {
352 coef += "-";
353 }
354 coef += ctx.getResult(arg.coefficient());
355 ctx.addResult(&arg, "std::exp(" + coef + " * " + ctx.getResult(arg.variable()) + ")");
356}
357
359{
360 // Use the result of the underlying pdf.
361 ctx.addResult(&arg, ctx.getResult(arg.pdf()));
362}
363
365{
366 // Build a call to the stateless gaussian defined later.
367 ctx.addResult(&arg, ctx.buildCall(mathFunc("gaussian"), arg.getX(), arg.getMean(), arg.getSigma()));
368}
369
371{
372 arg.getVal(); // to trigger the creation of the TFormula
373 std::string funcName = arg.getUniqueFuncName();
374 ctx.collectFunction(funcName);
375 ctx.addResult(&arg, ctx.buildCall(funcName, arg.dependents()));
376}
377
379{
380 rooHistTranslateImpl(arg, ctx, arg.getInterpolationOrder(), arg.dataHist(), arg.variables(), false,
381 arg.getCdfBoundaries());
382}
383
385{
386 rooHistTranslateImpl(arg, ctx, arg.getInterpolationOrder(), arg.dataHist(), arg.variables(), !arg.haveUnitNorm(),
387 arg.getCdfBoundaries());
388}
389
391{
392 ctx.addResult(&arg, ctx.buildCall(mathFunc("landau"), arg.getX(), arg.getMean(), arg.getSigma()));
393}
394
396{
397 std::string funcName = arg.useStandardParametrization() ? "logNormalEvaluateStandard" : "logNormal";
398 ctx.addResult(&arg, ctx.buildCall(mathFunc(funcName), arg.getX(), arg.getShapeK(), arg.getMedian()));
399}
400
401void codegenImpl(RooFit::Detail::RooNLLVarNew &arg, CodegenContext &ctx)
402{
403 if (arg.binnedL() && !arg.pdf().getAttribute("BinnedLikelihoodActiveYields")) {
404 std::stringstream errorMsg;
405 errorMsg << "codegen: binned likelihood optimization is only supported when raw pdf "
406 "values can be interpreted as yields."
407 << " This is not the case for HistFactory models written with ROOT versions before 6.26.00";
408 oocoutE(&arg, InputArguments) << errorMsg.str() << std::endl;
409 throw std::runtime_error(errorMsg.str());
410 }
411
412 std::string weightSumName = RooFit::Detail::makeValidVarName(arg.GetName()) + "WeightSum";
413 std::string resName = RooFit::Detail::makeValidVarName(arg.GetName()) + "Result";
414 ctx.addResult(&arg, resName);
415 ctx.addToGlobalScope("double " + weightSumName + " = 0.0;\n");
416 ctx.addToGlobalScope("double " + resName + " = 0.0;\n");
417
418 const bool needWeightSum = arg.expectedEvents() || arg.simCount() > 1;
419
420 if (needWeightSum) {
421 auto scope = ctx.beginLoop(&arg);
422 ctx.addToCodeBody(weightSumName + " += " + ctx.getResult(arg.weightVar()) + ";\n");
423 }
424 if (arg.simCount() > 1) {
425 std::string simCountStr = std::to_string(static_cast<double>(arg.simCount()));
426 ctx.addToCodeBody(resName + " += " + weightSumName + " * std::log(" + simCountStr + ");\n");
427 }
428
429 // Begin loop scope for the observables and weight variable. If the weight
430 // is a scalar, the context will ignore it for the loop scope. The closing
431 // brackets of the loop is written at the end of the scopes lifetime.
432 {
433 auto scope = ctx.beginLoop(&arg);
434 std::string term = ctx.buildCall(mathFunc("nll"), arg.pdf(), arg.weightVar(), arg.binnedL(), 0);
435 ctx.addToCodeBody(&arg, resName + " += " + term + ";");
436 }
437 if (arg.expectedEvents()) {
438 std::string expected = ctx.getResult(*arg.expectedEvents());
439 ctx.addToCodeBody(resName + " += " + expected + " - " + weightSumName + " * std::log(" + expected + ");\n");
440 }
441}
442
444{
445 // For now just return function/normalization integral.
446 ctx.addResult(&arg, ctx.getResult(arg.pdf()) + "/" + ctx.getResult(arg.normIntegral()));
447}
448
450{
451 std::string const &idx = arg.dataHist().calculateTreeIndexForCodeSquash(ctx, arg.xList());
452 std::string arrName = ctx.buildArg(arg.paramList());
453 std::string result = arrName + "[" + idx + "]";
454 if (arg.relParam()) {
455 // get weight[idx] * binv[idx]. Here we get the bin volume for the first element as we assume the distribution to
456 // be binned uniformly.
457 double binV = arg.dataHist().binVolume(0);
458 std::string weightArr = arg.dataHist().declWeightArrayForCodeSquash(ctx, false);
459 result += " * *(" + weightArr + " + " + idx + ") * " + std::to_string(binV);
460 }
461 ctx.addResult(&arg, result);
462}
463
465{
466 std::string xName = ctx.getResult(arg.getX());
467 if (!arg.getNoRounding())
468 xName = "std::floor(" + xName + ")";
469
470 ctx.addResult(&arg, ctx.buildCall(mathFunc("poisson"), xName, arg.getMean()));
471}
472
474{
475 const unsigned sz = arg.coefList().size();
476 if (!sz) {
477 ctx.addResult(&arg, std::to_string(arg.lowestOrder() ? 1. : 0.));
478 return;
479 }
480
481 ctx.addResult(&arg, ctx.buildCall(mathFunc("polynomial"), arg.coefList(), sz, arg.lowestOrder(), arg.x()));
482}
483
485{
486 const unsigned sz = arg.coefList().size();
487 if (!sz) {
488 ctx.addResult(&arg, std::to_string(arg.lowestOrder() ? 1. : 0.));
489 return;
490 }
491
492 ctx.addResult(&arg, ctx.buildCall(mathFunc("polynomial<true>"), arg.coefList(), sz, arg.lowestOrder(), arg.x()));
493}
494
496{
497 ctx.addResult(&arg, ctx.buildCall(mathFunc("product"), arg.realComponents(), arg.realComponents().size()));
498}
499
501{
502 ctx.addResult(&arg, ctx.buildCall(mathFunc("ratio"), arg.numerator(), arg.denominator()));
503}
504
505namespace {
506
507std::string codegenIntegral(RooAbsReal &arg, int code, const char *rangeName, CodegenContext &ctx)
508{
509 using Func = std::string (*)(RooAbsReal &, int, const char *, CodegenContext &);
510
511 Func func;
512
513 TClass *tclass = arg.IsA();
514
515 // Cache the overload resolutions
516 static std::unordered_map<TClass *, Func> dispatchMap;
517
518 auto found = dispatchMap.find(tclass);
519
520 if (found != dispatchMap.end()) {
521 func = found->second;
522 } else {
523 // Can probably done with CppInterop in the future to avoid string manipulation.
524 std::stringstream cmd;
525 cmd << "&RooFit::Experimental::CodegenIntegralImplCaller<" << tclass->GetName() << ">::call;";
526 func = reinterpret_cast<Func>(gInterpreter->ProcessLine(cmd.str().c_str()));
527 dispatchMap[tclass] = func;
528 }
529
530 return func(arg, code, rangeName, ctx);
531}
532
533} // namespace
534
536{
537 if (arg.numIntCatVars().empty() && arg.numIntRealVars().empty()) {
538 ctx.addResult(&arg, codegenIntegral(const_cast<RooAbsReal &>(arg.integrand()), arg.mode(), arg.intRange(), ctx));
539 return;
540 }
541
542 if (arg.intVars().size() != 1 || arg.numIntRealVars().size() != 1) {
543 std::stringstream errorMsg;
544 errorMsg << "Only analytical integrals and 1D numeric integrals are supported for AD for class"
545 << arg.integrand().GetName();
546 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
547 throw std::runtime_error(errorMsg.str().c_str());
548 }
549
550 auto &intVar = static_cast<RooAbsRealLValue &>(*arg.numIntRealVars()[0]);
551
552 std::string obsName = ctx.getTmpVarName();
553 std::string oldIntVarResult = ctx.getResult(intVar);
554 ctx.addResult(&intVar, "obs[0]");
555
556 std::string funcName = ctx.buildFunction(arg.integrand(), {});
557
558 std::stringstream ss;
559
560 ss << "double " << obsName << "[1];\n";
561
562 std::string resName = RooFit::Detail::makeValidVarName(arg.GetName()) + "Result";
563 ctx.addResult(&arg, resName);
564 ctx.addToGlobalScope("double " + resName + " = 0.0;\n");
565
566 // TODO: once Clad has support for higher-order functions (follow also the
567 // Clad issue #637), we could refactor this code into an actual function
568 // instead of hardcoding it here as a string.
569 ss << "{\n"
570 << " const int n = 1000; // number of sampling points\n"
571 << " double d = " << intVar.getMax(arg.intRange()) << " - " << intVar.getMin(arg.intRange()) << ";\n"
572 << " double eps = d / n;\n"
573 << " for (int i = 0; i < n; ++i) {\n"
574 << " " << obsName << "[0] = " << intVar.getMin(arg.intRange()) << " + eps * i;\n"
575 << " double tmpA = " << funcName << "(params, " << obsName << ", xlArr);\n"
576 << " " << obsName << "[0] = " << intVar.getMin(arg.intRange()) << " + eps * (i + 1);\n"
577 << " double tmpB = " << funcName << "(params, " << obsName << ", xlArr);\n"
578 << " " << resName << " += (tmpA + tmpB) * 0.5 * eps;\n"
579 << " }\n"
580 << "}\n";
581
582 ctx.addToGlobalScope(ss.str());
583
585}
586
588{
589 ctx.addResult(&arg, realSumPdfTranslateImpl(ctx, arg, arg.funcList(), arg.coefList(), false));
590}
591
593{
594 ctx.addResult(&arg, realSumPdfTranslateImpl(ctx, arg, arg.funcList(), arg.coefList(), false));
595}
596
598{
599 if (!arg.isConstant()) {
600 ctx.addResult(&arg, arg.GetName());
601 }
602 // Just return a formatted version of the const value.
603 // Formats to the maximum precision.
604 constexpr auto max_precision{std::numeric_limits<double>::digits10 + 1};
605 std::stringstream ss;
606 ss.precision(max_precision);
607 // Just use toString to make sure we do not output 'inf'.
608 // This is really ugly for large numbers...
609 ss << std::fixed << RooNumber::toString(arg.getVal());
610 ctx.addResult(&arg, ss.str());
611}
612
614{
615 ctx.addResult(&arg, ctx.buildCall(mathFunc("recursiveFraction"), arg.variables(), arg.variables().size()));
616}
617
619{
620 auto const &interpCodes = arg.interpolationCodes();
621
622 unsigned int n = interpCodes.size();
623
624 int interpCode = interpCodes[0];
625 // To get consistent codes with the PiecewiseInterpolation
626 if (interpCode == 4) {
627 interpCode = 5;
628 }
629
630 for (unsigned int i = 1; i < n; i++) {
631 if (interpCodes[i] != interpCodes[0]) {
633 << "FlexibleInterpVar::evaluate ERROR: Code Squashing AD does not yet support having "
634 "different interpolation codes for the same class object "
635 << std::endl;
636 }
637 }
638
639 std::string const &resName = ctx.buildCall(mathFunc("flexibleInterp"), interpCode, arg.variables(), n, arg.low(),
640 arg.high(), arg.globalBoundary(), arg.nominal(), 1.0);
641 ctx.addResult(&arg, resName);
642}
643
645{
646 ctx.addResult(&arg, "1.0");
647}
648
650{
651 ctx.addResult(&arg, ctx.getResult(arg.function()));
652}
653
654////////////////////////////////////////////////////////////////////////////////
655/// This function defines the analytical integral translation for the class.
656///
657/// \param[in] code The code that decides the integrands.
658/// \param[in] rangeName Name of the normalization range.
659/// \param[in] ctx An object to manage auxiliary information for code-squashing.
660///
661/// \returns The representative code string of the integral for the given object.
662std::string codegenIntegralImpl(RooAbsReal &arg, int, const char *, CodegenContext &)
663{
664 std::stringstream errorMsg;
665 errorMsg << "An analytical integral function for class \"" << arg.ClassName() << "\" has not yet been implemented.";
666 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
667 throw std::runtime_error(errorMsg.str().c_str());
668}
669
670std::string codegenIntegralImpl(RooBernstein &arg, int, const char *rangeName, CodegenContext &ctx)
671{
672 arg.fillBuffer(); // to get the right xmin() and xmax()
673 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.x());
674 return ctx.buildCall(mathFunc("bernsteinIntegral"), x.getMin(rangeName), x.getMax(rangeName), arg.xmin(), arg.xmax(),
675 arg.coefList(), arg.coefList().size());
676}
677
678std::string codegenIntegralImpl(RooBifurGauss &arg, int code, const char *rangeName, CodegenContext &ctx)
679{
680 auto &constant = code == 1 ? arg.getMean() : arg.getX();
681 auto &integrand = dynamic_cast<RooAbsRealLValue const &>(code == 1 ? arg.getX() : arg.getMean());
682
683 return ctx.buildCall(mathFunc("bifurGaussIntegral"), integrand.getMin(rangeName), integrand.getMax(rangeName),
684 constant, arg.getSigmaL(), arg.getSigmaR());
685}
686
687std::string codegenIntegralImpl(RooCBShape &arg, int /*code*/, const char *rangeName, CodegenContext &ctx)
688{
689 auto &m = dynamic_cast<RooAbsRealLValue const &>(arg.getM());
690 return ctx.buildCall(mathFunc("cbShapeIntegral"), m.getMin(rangeName), m.getMax(rangeName), arg.getM0(),
691 arg.getSigma(), arg.getAlpha(), arg.getN());
692}
693
694std::string codegenIntegralImpl(RooChebychev &arg, int, const char *rangeName, CodegenContext &ctx)
695{
696 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.x());
697 double xmax = x.getMax(arg.refRangeName());
698 double xmin = x.getMin(arg.refRangeName());
699 unsigned int sz = arg.coefList().size();
700
701 return ctx.buildCall(mathFunc("chebychevIntegral"), arg.coefList(), sz, xmin, xmax, x.getMin(rangeName),
702 x.getMax(rangeName));
703}
704
705std::string codegenIntegralImpl(RooEfficiency &, int, const char *, CodegenContext &)
706{
707 return "1.0";
708}
709
710std::string codegenIntegralImpl(RooExponential &arg, int code, const char *rangeName, CodegenContext &ctx)
711{
712 bool isOverX = code == 1;
713
714 std::string constant;
715 if (arg.negateCoefficient() && isOverX) {
716 constant += "-";
717 }
718 constant += ctx.getResult(isOverX ? arg.coefficient() : arg.variable());
719
720 auto &integrand = dynamic_cast<RooAbsRealLValue const &>(isOverX ? arg.variable() : arg.coefficient());
721
722 double min = integrand.getMin(rangeName);
723 double max = integrand.getMax(rangeName);
724
725 if (!isOverX && arg.negateCoefficient()) {
726 std::swap(min, max);
727 min = -min;
728 max = -max;
729 }
730
731 return ctx.buildCall(mathFunc("exponentialIntegral"), min, max, constant);
732}
733
734std::string codegenIntegralImpl(RooGamma &arg, int, const char *rangeName, CodegenContext &ctx)
735{
736 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.getX());
737 const std::string a =
738 ctx.buildCall("ROOT::Math::gamma_cdf", x.getMax(rangeName), arg.getGamma(), arg.getBeta(), arg.getMu());
739 const std::string b =
740 ctx.buildCall("ROOT::Math::gamma_cdf", x.getMin(rangeName), arg.getGamma(), arg.getBeta(), arg.getMu());
741 return a + " - " + b;
742}
743
744std::string codegenIntegralImpl(RooGaussian &arg, int code, const char *rangeName, CodegenContext &ctx)
745{
746 auto &constant = code == 1 ? arg.getMean() : arg.getX();
747 auto &integrand = dynamic_cast<RooAbsRealLValue const &>(code == 1 ? arg.getX() : arg.getMean());
748
749 return ctx.buildCall(mathFunc("gaussianIntegral"), integrand.getMin(rangeName), integrand.getMax(rangeName),
750 constant, arg.getSigma());
751}
752
753namespace {
754
755std::string rooHistIntegralTranslateImpl(int code, RooAbsArg const &arg, RooDataHist const &dataHist,
756 const RooArgSet &obs, bool histFuncMode)
757{
758 if (((2 << obs.size()) - 1) != code) {
759 oocoutE(&arg, InputArguments) << "RooHistPdf::integral(" << arg.GetName()
760 << ") ERROR: AD currently only supports integrating over all histogram observables."
761 << std::endl;
762 return "";
763 }
764 return std::to_string(dataHist.sum(histFuncMode));
765}
766
767} // namespace
768
769std::string codegenIntegralImpl(RooHistFunc &arg, int code, const char *, CodegenContext &)
770{
771 return rooHistIntegralTranslateImpl(code, arg, arg.dataHist(), arg.variables(), true);
772}
773
774std::string codegenIntegralImpl(RooHistPdf &arg, int code, const char *, CodegenContext &)
775{
776 return rooHistIntegralTranslateImpl(code, arg, arg.dataHist(), arg.variables(), false);
777}
778
779std::string codegenIntegralImpl(RooLandau &arg, int, const char *rangeName, CodegenContext &ctx)
780{
781 // Don't do anything with "code". It can only be "1" anyway (see
782 // implementation of getAnalyticalIntegral).
783 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.getX());
784 const std::string a = ctx.buildCall("ROOT::Math::landau_cdf", x.getMax(rangeName), arg.getSigma(), arg.getMean());
785 const std::string b = ctx.buildCall("ROOT::Math::landau_cdf", x.getMin(rangeName), arg.getSigma(), arg.getMean());
786 return ctx.getResult(arg.getSigma()) + " * " + "(" + a + " - " + b + ")";
787}
788
789std::string codegenIntegralImpl(RooLognormal &arg, int, const char *rangeName, CodegenContext &ctx)
790{
791 std::string funcName = arg.useStandardParametrization() ? "logNormalIntegralStandard" : "logNormalIntegral";
792 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.getX());
793 return ctx.buildCall(mathFunc(funcName), x.getMin(rangeName), x.getMax(rangeName), arg.getMedian(), arg.getShapeK());
794}
795
796std::string codegenIntegralImpl(RooMultiVarGaussian &arg, int code, const char *rangeName, CodegenContext &)
797{
798 if (code != -1) {
799 std::stringstream errorMsg;
800 errorMsg << "Partial integrals over RooMultiVarGaussian are not supported.";
801 oocoutE(&arg, Minimization) << errorMsg.str() << std::endl;
802 throw std::runtime_error(errorMsg.str().c_str());
803 }
804
805 return std::to_string(arg.analyticalIntegral(code, rangeName));
806}
807
808std::string codegenIntegralImpl(RooPoisson &arg, int code, const char *rangeName, CodegenContext &ctx)
809{
810 assert(code == 1 || code == 2);
811 std::string xName = ctx.getResult(arg.getX());
812 if (!arg.getNoRounding())
813 xName = "std::floor(" + xName + ")";
814
815 auto &integrand = dynamic_cast<RooAbsRealLValue const &>(code == 1 ? arg.getX() : arg.getMean());
816 // Since the integral function is the same for both codes, we need to make sure the indexed observables do not appear
817 // in the function if they are not required.
818 xName = code == 1 ? "0" : xName;
819 return ctx.buildCall(mathFunc("poissonIntegral"), code, arg.getMean(), xName, integrand.getMin(rangeName),
820 integrand.getMax(rangeName), arg.getProtectNegativeMean());
821}
822
823std::string codegenIntegralImpl(RooPolyVar &arg, int, const char *rangeName, CodegenContext &ctx)
824{
825 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.x());
826 const double xmin = x.getMin(rangeName);
827 const double xmax = x.getMax(rangeName);
828 const unsigned sz = arg.coefList().size();
829 if (!sz)
830 return std::to_string(arg.lowestOrder() ? xmax - xmin : 0.0);
831
832 return ctx.buildCall(mathFunc("polynomialIntegral"), arg.coefList(), sz, arg.lowestOrder(), xmin, xmax);
833}
834
835std::string codegenIntegralImpl(RooPolynomial &arg, int, const char *rangeName, CodegenContext &ctx)
836{
837 auto &x = dynamic_cast<RooAbsRealLValue const &>(arg.x());
838 const double xmin = x.getMin(rangeName);
839 const double xmax = x.getMax(rangeName);
840 const unsigned sz = arg.coefList().size();
841 if (!sz)
842 return std::to_string(arg.lowestOrder() ? xmax - xmin : 0.0);
843
844 return ctx.buildCall(mathFunc("polynomialIntegral<true>"), arg.coefList(), sz, arg.lowestOrder(), xmin, xmax);
845}
846
847std::string codegenIntegralImpl(RooRealSumPdf &arg, int code, const char *rangeName, CodegenContext &ctx)
848{
849 // Re-use translate, since integration is linear.
850 return realSumPdfTranslateImpl(ctx, arg, arg.funcIntListFromCache(code, rangeName), arg.coefList(), false);
851}
852
853std::string codegenIntegralImpl(RooUniform &arg, int code, const char *rangeName, CodegenContext &)
854{
855 // The integral of a uniform distribution is static, so we can just hardcode
856 // the result in a string.
857 return std::to_string(arg.analyticalIntegral(code, rangeName));
858}
859
860} // namespace Experimental
861} // namespace RooFit
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
#define oocoutE(o, a)
#define ooccoutE(o, a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
char name[80]
Definition TGX11.cxx:110
float xmin
float xmax
#define gInterpreter
A class which maps the current values of a RooRealVar (or a set of RooRealVars) to one of a number of...
const RooArgList & paramList() const
const RooArgList & dataVars() const
RooDataHist const & dataHist() const
The PiecewiseInterpolation is a class that can morph distributions into each other,...
const RooArgList & highList() const
const RooAbsReal * nominalHist() const
Return pointer to the nominal hist function.
const RooArgList & lowList() const
const RooArgList & paramList() const
const std::vector< int > & interpolationCodes() const
const_iterator end() const
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
bool isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:304
Abstract base class for RooRealVar binning definitions.
Int_t numBins() const
Return number of bins.
virtual double highBound() const =0
virtual double lowBound() const =0
A space to attach TBranches.
value_type lookupIndex(const std::string &stateName) const
Find the index number corresponding to the state name.
Storage_t::size_type size() const
Abstract base class for objects that represent a real value that may appear on the left hand side of ...
virtual double getMin(const char *name=nullptr) const
Get minimum of currently defined range.
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
TClass * IsA() const override
Definition RooAbsReal.h:547
Efficient implementation of a sum of PDFs of the form.
Definition RooAddPdf.h:33
const RooArgList & coefList() const
Definition RooAddPdf.h:74
const RooArgList & pdfList() const
Definition RooAddPdf.h:70
Calculates the sum of a set of RooAbsReal terms, or when constructed with two sets,...
Definition RooAddition.h:27
const RooArgList & list() const
Definition RooAddition.h:42
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Bernstein basis polynomials are positive-definite in the range [0,1].
void fillBuffer() const
RooAbsRealLValue const & x() const
RooArgList const & coefList() const
double xmax() const
double xmin() const
Bifurcated Gaussian p.d.f with different widths on left and right side of maximum value.
RooAbsReal const & getSigmaL() const
Get the left sigma parameter.
RooAbsReal const & getSigmaR() const
Get the right sigma parameter.
RooAbsReal const & getX() const
Get the x variable.
RooAbsReal const & getMean() const
Get the mean parameter.
PDF implementing the Crystal Ball line shape.
Definition RooCBShape.h:24
RooAbsReal const & getSigma() const
Definition RooCBShape.h:43
RooAbsReal const & getM() const
Definition RooCBShape.h:41
RooAbsReal const & getN() const
Definition RooCBShape.h:45
RooAbsReal const & getM0() const
Definition RooCBShape.h:42
RooAbsReal const & getAlpha() const
Definition RooCBShape.h:44
Chebychev polynomial p.d.f.
RooAbsReal const & x() const
RooArgList const & coefList() const
const char * refRangeName() const
Represents a constant real-valued object.
Definition RooConstVar.h:23
Calculates the sum of the -(log) likelihoods of a set of RooAbsPfs that represent constraint function...
const RooArgList & list()
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
double sum(bool correctForBinSize, bool inverseCorr=false) const
Return the sum of the weights of all bins in the histogram.
std::vector< std::unique_ptr< const RooAbsBinning > > const & getBinnings() const
std::string declWeightArrayForCodeSquash(RooFit::Experimental::CodegenContext &ctx, bool correctForBinSize) const
double weight(std::size_t i) const
Return weight of i-th bin.
std::string calculateTreeIndexForCodeSquash(RooFit::Experimental::CodegenContext &ctx, const RooAbsCollection &coords, bool reverse=false) const
The class RooEffProd implements the product of a PDF with an efficiency function.
Definition RooEffProd.h:19
RooAbsReal const & pdf() const
Definition RooEffProd.h:31
RooAbsReal const & eff() const
Definition RooEffProd.h:32
A PDF helper class to fit efficiencies parameterized by a supplied function F.
RooAbsCategory const & cat() const
RooAbsReal const & effFunc() const
std::string sigCatName() const
Exponential PDF.
bool negateCoefficient() const
RooAbsReal const & coefficient() const
Get the coefficient "c".
RooAbsReal const & variable() const
Get the x variable.
RooExtendPdf is a wrapper around an existing PDF that adds a parameteric extended likelihood term to ...
RooAbsPdf const & pdf() const
A RooProdPdf with a fixed normalization set can be replaced by this class.
Definition RooProdPdf.h:220
RooProdPdf::CacheElem const & cache() const
Definition RooProdPdf.h:264
RooAbsReal const & normIntegral() const
RooAbsPdf const & pdf() const
A class to maintain the context for squashing of RooFit models into code.
void addToGlobalScope(std::string const &str)
Adds the given string to the string block that will be emitted at the top of the squashed function.
std::string const & getResult(RooAbsArg const &arg)
Gets the result for the given node using the node name.
std::string getTmpVarName() const
Get a unique variable name to be used in the generated code.
void addResult(RooAbsArg const *key, std::string const &value)
A function to save an expression that includes/depends on the result of the input node.
void addToCodeBody(RooAbsArg const *klass, std::string const &in)
Adds the input string to the squashed code body.
std::unique_ptr< LoopScope > beginLoop(RooAbsArg const *in)
Create a RAII scope for iterating over vector observables.
void collectFunction(std::string const &name)
Register a function that is only know to the interpreter to the context.
std::string buildFunction(RooAbsArg const &arg, std::map< RooFit::Detail::DataKey, std::size_t > const &outputSizes={})
Assemble and return the final code with the return expression and global statements.
std::string buildCall(std::string const &funcname, Args_t const &...args)
Build the code to call the function with name funcname, passing some arguments.
std::string buildArg(RooAbsCollection const &x)
Function to save a RooListProxy as an array in the squashed code.
A RooFormulaVar is a generic implementation of a real-valued object, which takes a RooArgList of serv...
const RooArgList & dependents() const
std::string getUniqueFuncName() const
Implementation of the Gamma PDF for RooFit/RooStats.
Definition RooGamma.h:20
RooAbsReal const & getX() const
Definition RooGamma.h:34
RooAbsReal const & getGamma() const
Definition RooGamma.h:35
RooAbsReal const & getBeta() const
Definition RooGamma.h:36
RooAbsReal const & getMu() const
Definition RooGamma.h:37
Plain Gaussian p.d.f.
Definition RooGaussian.h:24
RooAbsReal const & getX() const
Get the x variable.
Definition RooGaussian.h:45
RooAbsReal const & getMean() const
Get the mean parameter.
Definition RooGaussian.h:48
RooAbsReal const & getSigma() const
Get the sigma parameter.
Definition RooGaussian.h:51
Implementation of a probability density function that takes a RooArgList of servers and a C++ express...
const RooArgList & dependents() const
std::string getUniqueFuncName() const
A real-valued function sampled from a multidimensional histogram.
Definition RooHistFunc.h:31
Int_t getInterpolationOrder() const
Return histogram interpolation order.
Definition RooHistFunc.h:69
bool getCdfBoundaries() const
If true, special boundary conditions for c.d.f.s are used.
Definition RooHistFunc.h:85
RooDataHist & dataHist()
Return RooDataHist that is represented.
Definition RooHistFunc.h:45
RooArgSet const & variables() const
A probability density function sampled from a multidimensional histogram.
Definition RooHistPdf.h:30
Int_t getInterpolationOrder() const
Definition RooHistPdf.h:59
RooDataHist & dataHist()
Definition RooHistPdf.h:42
bool haveUnitNorm() const
Definition RooHistPdf.h:82
bool getCdfBoundaries() const
Definition RooHistPdf.h:73
RooArgSet const & variables() const
Definition RooHistPdf.h:98
Landau distribution p.d.f.
Definition RooLandau.h:24
RooAbsReal const & getSigma() const
Definition RooLandau.h:42
RooAbsReal const & getMean() const
Definition RooLandau.h:41
RooAbsReal const & getX() const
Definition RooLandau.h:40
RooFit Lognormal PDF.
bool useStandardParametrization() const
RooAbsReal const & getMedian() const
Get the median parameter.
RooAbsReal const & getShapeK() const
Get the shape parameter.
RooAbsReal const & getX() const
Get the x variable.
Multivariate Gaussian p.d.f.
double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const override
Handle full integral here.
const RooArgList & xVec() const
const TMatrixDSym & covarianceMatrixInverse() const
const RooArgList & muVec() const
static std::string toString(double x)
Returns an std::to_string compatible number (i.e.
Definition RooNumber.cxx:31
A histogram function that assigns scale parameters to every bin.
const RooArgList & paramList() const
const RooArgList & xList() const
const RooDataHist & dataHist() const
bool relParam() const
Poisson pdf.
Definition RooPoisson.h:19
RooAbsReal const & getX() const
Get the x variable.
Definition RooPoisson.h:45
bool getProtectNegativeMean() const
Definition RooPoisson.h:42
bool getNoRounding() const
Definition RooPoisson.h:37
RooAbsReal const & getMean() const
Get the mean parameter.
Definition RooPoisson.h:48
A RooAbsReal implementing a polynomial in terms of a list of RooAbsReal coefficients.
Definition RooPolyVar.h:25
RooRealProxy const & x() const
Definition RooPolyVar.h:37
RooArgList const & coefList() const
Definition RooPolyVar.h:38
int lowestOrder() const
Definition RooPolyVar.h:39
RooPolynomial implements a polynomial p.d.f of the form.
RooAbsReal const & x() const
Get the x variable.
int lowestOrder() const
Return the order for the first coefficient in the list.
RooArgList const & coefList() const
Get the coefficient list.
std::unique_ptr< RooAbsReal > _rearrangedNum
Definition RooProdPdf.h:115
std::unique_ptr< RooAbsReal > _rearrangedDen
Definition RooProdPdf.h:116
Represents the product of a given set of RooAbsReal objects.
Definition RooProduct.h:29
const RooArgList & realComponents() const
Definition RooProduct.h:50
Represents the ratio of two RooAbsReal objects.
Definition RooRatio.h:21
RooAbsReal const & numerator() const
Definition RooRatio.h:34
RooAbsReal const & denominator() const
Definition RooRatio.h:35
Performs hybrid numerical/analytical integrals of RooAbsReal objects.
const RooArgSet & numIntRealVars() const
RooArgSet intVars() const
const RooAbsReal & integrand() const
const RooArgSet & numIntCatVars() const
const char * intRange() const
const RooArgList & coefList() const
const RooArgList & funcList() const
Implements a PDF constructed from a sum of functions:
const RooArgList & funcList() const
const RooArgList & funcIntListFromCache(Int_t code, const char *rangeName=nullptr) const
Collect the list of functions to be integrated from the cache.
const RooArgList & coefList() const
Variable that can be changed from the outside.
Definition RooRealVar.h:37
A RooAbsReal implementation that calculates the plain fraction of sum of RooAddPdf components from a ...
RooArgList const & variables() const
const std::vector< int > & interpolationCodes() const
const RooListProxy & variables() const
const std::vector< double > & high() const
const std::vector< double > & low() const
Flat p.d.f.
Definition RooUniform.h:24
double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const override
Implement analytical integral.
The RooWrapperPdf is a class that can be used to convert a function into a PDF.
RooAbsReal const & function() const
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
std::string makeValidVarName(std::string const &in)
void codegenImpl(RooFit::Detail::RooFixedProdPdf &arg, CodegenContext &ctx)
std::string codegenIntegralImpl(RooAbsReal &arg, int code, const char *rangeName, CodegenContext &ctx)
This function defines the analytical integral translation for the class.
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:65
@ InputArguments
TMarker m
Definition textangle.C:8
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345