Logo ROOT   6.13/01
Reference Guide
FitUtil.h
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Author: L. Moneta Tue Nov 28 10:52:47 2006
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Header file for class FitUtil
12 
13 #ifndef ROOT_Fit_FitUtil
14 #define ROOT_Fit_FitUtil
15 
16 #include "Math/IParamFunctionfwd.h"
17 #include "Math/IParamFunction.h"
18 
19 #ifdef R__USE_IMT
20 #include "ROOT/TThreadExecutor.hxx"
21 #endif
22 
23 // #include "ROOT/TProcessExecutor.hxx"
24 
25 #include "Fit/BinData.h"
26 #include "Fit/UnBinData.h"
27 #include "Fit/FitExecutionPolicy.h"
28 
29 #include "Math/Integrator.h"
31 
32 #include "TError.h"
33 #include "TSystem.h"
34 
35 // using parameter cache is not thread safe but needed for normalizing the functions
36 #define USE_PARAMCACHE
37 
38 //#define DEBUG_FITUTIL
39 
40 #ifdef R__HAS_VECCORE
41 namespace vecCore {
42 template <class T>
43 vecCore::Mask<T> Int2Mask(unsigned i)
44 {
45  T x;
46  for (unsigned j = 0; j < vecCore::VectorSize<T>(); j++)
47  vecCore::Set<T>(x, j, j);
48  return vecCore::Mask<T>(x < T(i));
49 }
50 }
51 #endif
52 
53 namespace ROOT {
54 
55  namespace Fit {
56 
57 /**
58  namespace defining utility free functions using in Fit for evaluating the various fit method
59  functions (chi2, likelihood, etc..) given the data and the model function
60 
61  @ingroup FitMain
62 */
63 namespace FitUtil {
64 
67 
68  template <class T>
70 
71  template <class T>
73 
74  // internal class defining
75  template <class T>
76  class LikelihoodAux {
77  public:
78  LikelihoodAux(T logv = {}, T w = {}, T w2 = {}) : logvalue(logv), weight(w), weight2(w2) {}
79 
81  {
82  return LikelihoodAux<T>(logvalue + l.logvalue, weight + l.weight, weight2 + l.weight2);
83  }
84 
86  {
87  logvalue += l.logvalue;
88  weight += l.weight;
89  weight2 += l.weight2;
90  return *this;
91  }
92 
96  };
97 
98  template <>
99  class LikelihoodAux<double> {
100  public:
101  LikelihoodAux(double logv = 0.0, double w = 0.0, double w2 = 0.0) : logvalue(logv), weight(w), weight2(w2){};
102 
104  {
105  return LikelihoodAux<double>(logvalue + l.logvalue, weight + l.weight, weight2 + l.weight2);
106  }
107 
109  {
110  logvalue += l.logvalue;
111  weight += l.weight;
112  weight2 += l.weight2;
113  return *this;
114  }
115 
116  double logvalue;
117  double weight;
118  double weight2;
119  };
120 
121  // internal class to evaluate the function or the integral
122  // and cached internal integration details
123  // if useIntegral is false no allocation is done
124  // and this is a dummy class
125  // class is templated on any parametric functor implementing operator()(x,p) and NDim()
126  // contains a constant pointer to the function
127 
128  template <class ParamFunc = ROOT::Math::IParamMultiFunctionTempl<double>>
130 
131  public:
132  IntegralEvaluator(const ParamFunc &func, const double *p, bool useIntegral = true)
133  : fDim(0), fParams(0), fFunc(0), fIg1Dim(0), fIgNDim(0), fFunc1Dim(0), fFuncNDim(0)
134  {
135  if (useIntegral) {
136  SetFunction(func, p);
137  }
138  }
139 
140  void SetFunction(const ParamFunc &func, const double *p = 0)
141  {
142  // set the integrand function and create required wrapper
143  // to perform integral in (x) of a generic f(x,p)
144  fParams = p;
145  fDim = func.NDim();
146  // copy the function object to be able to modify the parameters
147  // fFunc = dynamic_cast<ROOT::Math::IParamMultiFunction *>( func.Clone() );
148  fFunc = &func;
149  assert(fFunc != 0);
150  // set parameters in function
151  // fFunc->SetParameters(p);
152  if (fDim == 1) {
153  fFunc1Dim =
155  *this, &IntegralEvaluator::F1);
156  fIg1Dim = new ROOT::Math::IntegratorOneDim();
157  // fIg1Dim->SetFunction( static_cast<const ROOT::Math::IMultiGenFunction & >(*fFunc),false);
158  fIg1Dim->SetFunction(static_cast<const ROOT::Math::IGenFunction &>(*fFunc1Dim));
159  } else if (fDim > 1) {
160  fFuncNDim =
161  new ROOT::Math::WrappedMemMultiFunction<IntegralEvaluator, double (IntegralEvaluator::*)(const double *)
162  const>(*this, &IntegralEvaluator::FN, fDim);
163  fIgNDim = new ROOT::Math::IntegratorMultiDim();
164  fIgNDim->SetFunction(*fFuncNDim);
165  } else
166  assert(fDim > 0);
167  }
168 
169  void SetParameters(const double *p)
170  {
171  // copy just the pointer
172  fParams = p;
173  }
174 
176  {
177  if (fIg1Dim)
178  delete fIg1Dim;
179  if (fIgNDim)
180  delete fIgNDim;
181  if (fFunc1Dim)
182  delete fFunc1Dim;
183  if (fFuncNDim)
184  delete fFuncNDim;
185  // if (fFunc) delete fFunc;
186  }
187 
188  // evaluation of integrand function (one-dim)
189  double F1(double x) const
190  {
191  double xx = x;
192  return ExecFunc(fFunc, &xx, fParams);
193  }
194  // evaluation of integrand function (multi-dim)
195  double FN(const double *x) const { return ExecFunc(fFunc, x, fParams); }
196 
197  double Integral(const double *x1, const double *x2)
198  {
199  // return unormalized integral
200  return (fIg1Dim) ? fIg1Dim->Integral(*x1, *x2) : fIgNDim->Integral(x1, x2);
201  }
202 
203  double operator()(const double *x1, const double *x2)
204  {
205  // return normalized integral, divided by bin volume (dx1*dx...*dxn)
206  if (fIg1Dim) {
207  double dV = *x2 - *x1;
208  return fIg1Dim->Integral(*x1, *x2) / dV;
209  } else if (fIgNDim) {
210  double dV = 1;
211  for (unsigned int i = 0; i < fDim; ++i)
212  dV *= (x2[i] - x1[i]);
213  return fIgNDim->Integral(x1, x2) / dV;
214  // std::cout << " do integral btw x " << x1[0] << " " << x2[0] << " y " << x1[1] << " "
215  // << x2[1] << " dV = " << dV << " result = " << result << std::endl; return result;
216  } else
217  assert(1.); // should never be here
218  return 0;
219  }
220 
221  private:
222  template <class T>
223  inline double ExecFunc(T *f, const double *x, const double *p) const
224  {
225  return (*f)(x, p);
226  }
227 
228 #ifdef R__HAS_VECCORE
229  inline double ExecFunc(const IModelFunctionTempl<ROOT::Double_v> *f, const double *x, const double *p) const
230  {
231  if (fDim == 1) {
232  ROOT::Double_v xx;
233  vecCore::Load<ROOT::Double_v>(xx, x);
234  const double *p0 = p;
235  auto res = (*f)(&xx, (const double *)p0);
236  return vecCore::Get<ROOT::Double_v>(res, 0);
237  } else {
238  std::vector<ROOT::Double_v> xx(fDim);
239  for (unsigned int i = 0; i < fDim; ++i) {
240  vecCore::Load<ROOT::Double_v>(xx[i], x + i);
241  }
242  auto res = (*f)(xx.data(), p);
243  return vecCore::Get<ROOT::Double_v>(res, 0);
244  }
245  }
246 #endif
247 
248  // objects of this class are not meant to be copied / assigned
250  IntegralEvaluator &operator=(const IntegralEvaluator &rhs);
251 
252  unsigned int fDim;
253  const double *fParams;
254  // ROOT::Math::IParamMultiFunction * fFunc; // copy of function in order to be able to change parameters
255  // const ParamFunc * fFunc; // reference to a generic parametric function
256  const ParamFunc *fFunc;
261  };
262 
263  /** Chi2 Functions */
264 
265  /**
266  evaluate the Chi2 given a model function and the data at the point x.
267  return also nPoints as the effective number of used points in the Chi2 evaluation
268  */
269  double EvaluateChi2(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints,
270  ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks = 0);
271 
272  /**
273  evaluate the effective Chi2 given a model function and the data at the point x.
274  The effective chi2 uses the errors on the coordinates : W = 1/(sigma_y**2 + ( sigma_x_i * df/dx_i )**2 )
275  return also nPoints as the effective number of used points in the Chi2 evaluation
276  */
277  double EvaluateChi2Effective(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints);
278 
279  /**
280  evaluate the Chi2 gradient given a model function and the data at the point x.
281  return also nPoints as the effective number of used points in the Chi2 evaluation
282  */
283  void EvaluateChi2Gradient(const IModelFunction &func, const BinData &data, const double *x, double *grad,
284  unsigned int &nPoints,
286  unsigned nChunks = 0);
287 
288  /**
289  evaluate the LogL given a model function and the data at the point x.
290  return also nPoints as the effective number of used points in the LogL evaluation
291  */
292  double EvaluateLogL(const IModelFunction &func, const UnBinData &data, const double *p, int iWeight, bool extended,
293  unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks = 0);
294 
295  /**
296  evaluate the LogL gradient given a model function and the data at the point x.
297  return also nPoints as the effective number of used points in the LogL evaluation
298  */
299  void EvaluateLogLGradient(const IModelFunction &func, const UnBinData &data, const double *x, double *grad,
300  unsigned int &nPoints,
302  unsigned nChunks = 0);
303 
304  // #ifdef R__HAS_VECCORE
305  // template <class NotCompileIfScalarBackend = std::enable_if<!(std::is_same<double, ROOT::Double_v>::value)>>
306  // void EvaluateLogLGradient(const IModelFunctionTempl<ROOT::Double_v> &, const UnBinData &, const double *, double
307  // *, unsigned int & ) {}
308  // #endif
309 
310  /**
311  evaluate the Poisson LogL given a model function and the data at the point x.
312  return also nPoints as the effective number of used points in the LogL evaluation
313  By default is extended, pass extedend to false if want to be not extended (MultiNomial)
314  */
315  double EvaluatePoissonLogL(const IModelFunction &func, const BinData &data, const double *x, int iWeight,
316  bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy,
317  unsigned nChunks = 0);
318 
319  /**
320  evaluate the Poisson LogL given a model function and the data at the point x.
321  return also nPoints as the effective number of used points in the LogL evaluation
322  */
323  void EvaluatePoissonLogLGradient(const IModelFunction &func, const BinData &data, const double *x, double *grad,
324  unsigned int &nPoints,
326  unsigned nChunks = 0);
327 
328  // methods required by dedicate minimizer like Fumili
329 
330  /**
331  evaluate the residual contribution to the Chi2 given a model function and the BinPoint data
332  and if the pointer g is not null evaluate also the gradient of the residual.
333  If the function provides parameter derivatives they are used otherwise a simple derivative calculation
334  is used
335  */
336  double EvaluateChi2Residual(const IModelFunction &func, const BinData &data, const double *x, unsigned int ipoint,
337  double *g = 0);
338 
339  /**
340  evaluate the pdf contribution to the LogL given a model function and the BinPoint data.
341  If the pointer g is not null evaluate also the gradient of the pdf.
342  If the function provides parameter derivatives they are used otherwise a simple derivative calculation
343  is used
344  */
345  double
346  EvaluatePdf(const IModelFunction &func, const UnBinData &data, const double *x, unsigned int ipoint, double *g = 0);
347 
348 #ifdef R__HAS_VECCORE
349  template <class NotCompileIfScalarBackend = std::enable_if<!(std::is_same<double, ROOT::Double_v>::value)>>
350  double EvaluatePdf(const IModelFunctionTempl<ROOT::Double_v> &func, const UnBinData &data, const double *p, unsigned int i, double *) {
351  // evaluate the pdf contribution to the generic logl function in case of bin data
352  // return actually the log of the pdf and its derivatives
353  // func.SetParameters(p);
354  const auto x = vecCore::FromPtr<ROOT::Double_v>(data.GetCoordComponent(i, 0));
355  auto fval = func(&x, p);
356  auto logPdf = ROOT::Math::Util::EvalLog(fval);
357  return vecCore::Get<ROOT::Double_v>(logPdf, 0);
358  }
359 #endif
360 
361  /**
362  evaluate the pdf contribution to the Poisson LogL given a model function and the BinPoint data.
363  If the pointer g is not null evaluate also the gradient of the Poisson pdf.
364  If the function provides parameter derivatives they are used otherwise a simple derivative calculation
365  is used
366  */
367  double EvaluatePoissonBinPdf(const IModelFunction & func, const BinData & data, const double * x, unsigned int ipoint, double * g = 0);
368 
369  unsigned setAutomaticChunking(unsigned nEvents);
370 
371  template<class T>
372  struct Evaluate {
373 #ifdef R__HAS_VECCORE
374  static double EvalChi2(const IModelFunctionTempl<T> &func, const BinData &data, const double *p,
375  unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks = 0)
376  {
377  // evaluate the chi2 given a vectorized function reference , the data and returns the value and also in nPoints
378  // the actual number of used points
379  // normal chi2 using only error on values (from fitting histogram)
380  // optionally the integral of function in the bin is used
381 
382  //Info("EvalChi2","Using vecorized implementation %d",(int) data.Opt().fIntegral);
383 
384  unsigned int n = data.Size();
385 
386  nPoints = 0; // count the effective non-zero points
387  // set parameters of the function to cache integral value
388 #ifdef USE_PARAMCACHE
389  (const_cast<IModelFunctionTempl<T> &>(func)).SetParameters(p);
390 #endif
391  // do not cache parameter values (it is not thread safe)
392  //func.SetParameters(p);
393 
394 
395  // get fit option and check case if using integral of bins
396  const DataOptions &fitOpt = data.Opt();
397  if (fitOpt.fBinVolume || fitOpt.fIntegral || fitOpt.fExpErrors)
398  Error("FitUtil::EvaluateChi2", "The vectorized implementation doesn't support Integrals, BinVolume or ExpErrors\n. Aborting operation.");
399 
400  (const_cast<IModelFunctionTempl<T> &>(func)).SetParameters(p);
401 
402  double maxResValue = std::numeric_limits<double>::max() / n;
403  std::vector<double> ones{1, 1, 1, 1};
404  auto vecSize = vecCore::VectorSize<T>();
405 
406  auto mapFunction = [&](unsigned int i) {
407  // in case of no error in y invError=1 is returned
408  T x1, y, invErrorVec;
409  vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
410  vecCore::Load<T>(y, data.ValuePtr(i * vecSize));
411  const auto invError = data.ErrorPtr(i * vecSize);
412  auto invErrorptr = (invError != nullptr) ? invError : &ones.front();
413  vecCore::Load<T>(invErrorVec, invErrorptr);
414 
415  const T *x;
416  std::vector<T> xc;
417  if(data.NDim() > 1) {
418  xc.resize(data.NDim());
419  xc[0] = x1;
420  for (unsigned int j = 1; j < data.NDim(); ++j)
421  vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
422  x = xc.data();
423  } else {
424  x = &x1;
425  }
426 
427  T fval{};
428 
429 #ifdef USE_PARAMCACHE
430  fval = func(x);
431 #else
432  fval = func(x, p);
433 #endif
434  nPoints++;
435 
436  T tmp = (y - fval) * invErrorVec;
437  T chi2 = tmp * tmp;
438 
439 
440  // avoid inifinity or nan in chi2 values due to wrong function values
441  auto m = vecCore::Mask_v<T>(chi2 > maxResValue);
442 
443  vecCore::MaskedAssign<T>(chi2, m, maxResValue);
444 
445  return chi2;
446  };
447 
448 #ifdef R__USE_IMT
449  auto redFunction = [](const std::vector<T> &objs) {
450  return std::accumulate(objs.begin(), objs.end(), T{});
451  };
452 #else
453  (void)nChunks;
454 
455  // If IMT is disabled, force the execution policy to the serial case
456  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
457  Warning("FitUtil::EvaluateChi2", "Multithread execution policy requires IMT, which is disabled. Changing "
458  "to ROOT::Fit::ExecutionPolicy::kSerial.");
459  executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
460  }
461 #endif
462 
463  T res{};
464  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
465  for (unsigned int i = 0; i < (data.Size() / vecSize); i++) {
466  res += mapFunction(i);
467  }
468 
469 #ifdef R__USE_IMT
470  } else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
471  auto chunks = nChunks != 0 ? nChunks : setAutomaticChunking(data.Size() / vecSize);
472  ROOT::TThreadExecutor pool;
473  res = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, data.Size() / vecSize), redFunction, chunks);
474 #endif
475  // } else if(executionPolicy == ROOT::Fit::ExecutionPolicy::kMultiprocess){
476  // ROOT::TProcessExecutor pool;
477  // res = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, data.Size()/vecSize), redFunction);
478  } else {
479  Error("FitUtil::EvaluateChi2", "Execution policy unknown. Avalaible choices:\n ROOT::Fit::ExecutionPolicy::kSerial (default)\n ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
480  }
481  nPoints = n;
482 
483  // Last SIMD vector of elements (if padding needed)
484  vecCore::MaskedAssign(res, vecCore::Int2Mask<T>(data.Size() % vecSize),
485  res + mapFunction(data.Size() / vecSize));
486 
487  return vecCore::ReduceAdd(res);
488  }
489 
490  static double EvalLogL(const IModelFunctionTempl<T> &func, const UnBinData &data, const double *const p,
491  int iWeight, bool extended, unsigned int &nPoints,
492  ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks = 0)
493  {
494  // evaluate the LogLikelihood
495  unsigned int n = data.Size();
496 
497  //unsigned int nRejected = 0;
498  bool normalizeFunc = false;
499 
500  // set parameters of the function to cache integral value
501 #ifdef USE_PARAMCACHE
502  (const_cast<IModelFunctionTempl<T> &>(func)).SetParameters(p);
503 #endif
504 
505 #ifdef R__USE_IMT
506  // in case parameter needs to be propagated to user function use trick to set parameters by calling one time the function
507  // this will be done in sequential mode and parameters can be set in a thread safe manner
508  if (!normalizeFunc) {
509  if (data.NDim() == 1) {
510  T x;
511  vecCore::Load<T>(x, data.GetCoordComponent(0, 0));
512  func( &x, p);
513  }
514  else {
515  std::vector<T> x(data.NDim());
516  for (unsigned int j = 0; j < data.NDim(); ++j)
517  vecCore::Load<T>(x[j], data.GetCoordComponent(0, j));
518  func( x.data(), p);
519  }
520  }
521 #endif
522 
523  // this is needed if function must be normalized
524  double norm = 1.0;
525  if (normalizeFunc) {
526  // compute integral of the function
527  std::vector<double> xmin(data.NDim());
528  std::vector<double> xmax(data.NDim());
529  IntegralEvaluator<IModelFunctionTempl<T>> igEval(func, p, true);
530  // compute integral in the ranges where is defined
531  if (data.Range().Size() > 0) {
532  norm = 0;
533  for (unsigned int ir = 0; ir < data.Range().Size(); ++ir) {
534  data.Range().GetRange(&xmin[0], &xmax[0], ir);
535  norm += igEval.Integral(xmin.data(), xmax.data());
536  }
537  } else {
538  // use (-inf +inf)
539  data.Range().GetRange(&xmin[0], &xmax[0]);
540  // check if funcition is zero at +- inf
541  T xmin_v, xmax_v;
542  vecCore::Load<T>(xmin_v, xmin.data());
543  vecCore::Load<T>(xmax_v, xmax.data());
544  if (vecCore::ReduceAdd(func(&xmin_v, p)) != 0 || vecCore::ReduceAdd(func(&xmax_v, p)) != 0) {
545  MATH_ERROR_MSG("FitUtil::EvaluateLogLikelihood", "A range has not been set and the function is not zero at +/- inf");
546  return 0;
547  }
548  norm = igEval.Integral(&xmin[0], &xmax[0]);
549  }
550  }
551 
552  // needed to compute effective global weight in case of extended likelihood
553 
554  auto vecSize = vecCore::VectorSize<T>();
555  unsigned int numVectors = n / vecSize;
556 
557  auto mapFunction = [ &, p](const unsigned i) {
558  T W{};
559  T W2{};
560  T fval{};
561 
562  (void)p; /* avoid unused lambda capture warning if PARAMCACHE is disabled */
563 
564  T x1;
565  vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
566  const T *x = nullptr;
567  unsigned int ndim = data.NDim();
568  std::vector<T> xc;
569  if (ndim > 1) {
570  xc.resize(ndim);
571  xc[0] = x1;
572  for (unsigned int j = 1; j < ndim; ++j)
573  vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
574  x = xc.data();
575  } else {
576  x = &x1;
577  }
578 
579 #ifdef USE_PARAMCACHE
580  fval = func(x);
581 #else
582  fval = func(x, p);
583 #endif
584 
585 #ifdef DEBUG_FITUTIL
586  if (i < 5 || (i > numVectors-5) ) {
587  if (ndim == 1) std::cout << i << " x " << x[0] << " fval = " << fval;
588  else std::cout << i << " x " << x[0] << " y " << x[1] << " fval = " << fval;
589  }
590 #endif
591 
592  if (normalizeFunc) fval = fval * (1 / norm);
593 
594  // function EvalLog protects against negative or too small values of fval
595  auto logval = ROOT::Math::Util::EvalLog(fval);
596  if (iWeight > 0) {
597  T weight{};
598  if (data.WeightsPtr(i) == nullptr)
599  weight = 1;
600  else
601  vecCore::Load<T>(weight, data.WeightsPtr(i*vecSize));
602  logval *= weight;
603  if (iWeight == 2) {
604  logval *= weight; // use square of weights in likelihood
605  if (!extended) {
606  // needed sum of weights and sum of weight square if likelkihood is extended
607  W = weight;
608  W2 = weight * weight;
609  }
610  }
611  }
612 #ifdef DEBUG_FITUTIL
613  if (i < 5 || (i > numVectors-5) ) {
614  std::cout << " " << fval << " logfval " << logval << std::endl;
615  }
616 #endif
617 
618  nPoints++;
619  return LikelihoodAux<T>(logval, W, W2);
620  };
621 
622 #ifdef R__USE_IMT
623  auto redFunction = [](const std::vector<LikelihoodAux<T>> &objs) {
624  return std::accumulate(objs.begin(), objs.end(), LikelihoodAux<T>(),
625  [](const LikelihoodAux<T> &l1, const LikelihoodAux<T> &l2) {
626  return l1 + l2;
627  });
628  };
629 #else
630  (void)nChunks;
631 
632  // If IMT is disabled, force the execution policy to the serial case
633  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
634  Warning("FitUtil::EvaluateLogL", "Multithread execution policy requires IMT, which is disabled. Changing "
635  "to ROOT::Fit::ExecutionPolicy::kSerial.");
636  executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
637  }
638 #endif
639 
640  T logl_v{};
641  T sumW_v{};
642  T sumW2_v{};
643  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
644  for (unsigned int i = 0; i < numVectors; ++i) {
645  auto resArray = mapFunction(i);
646  logl_v += resArray.logvalue;
647  sumW_v += resArray.weight;
648  sumW2_v += resArray.weight2;
649  }
650 #ifdef R__USE_IMT
651  } else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
652  auto chunks = nChunks != 0 ? nChunks : setAutomaticChunking( numVectors);
653  ROOT::TThreadExecutor pool;
654  auto resArray = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, data.Size() / vecSize), redFunction, chunks);
655  logl_v = resArray.logvalue;
656  sumW_v = resArray.weight;
657  sumW2_v = resArray.weight2;
658  // } else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultiprocess) {
659  // ROOT::TProcessExecutor pool;
660  // res = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, n), redFunction);
661 #endif
662  } else {
663  Error("FitUtil::EvaluateLogL", "Execution policy unknown. Avalaible choices:\n ROOT::Fit::ExecutionPolicy::kSerial (default)\n ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
664  }
665 
666  // Compute the contribution from the remaining points ( Last padded SIMD vector of elements )
667  unsigned int remainingPoints = n % vecSize;
668  if (remainingPoints > 0) {
669  auto remainingPointsContribution = mapFunction(numVectors);
670  // Add the contribution from the valid remaining points and store the result in the output variable
671  auto remainingMask = vecCore::Int2Mask<T>(remainingPoints);
672  vecCore::MaskedAssign(logl_v, remainingMask, logl_v + remainingPointsContribution.logvalue);
673  vecCore::MaskedAssign(sumW_v, remainingMask, sumW_v + remainingPointsContribution.weight);
674  vecCore::MaskedAssign(sumW2_v, remainingMask, sumW2_v + remainingPointsContribution.weight2);
675  }
676 
677 
678  //reduce vector type to double.
679  double logl = 0.;
680  double sumW = 0.;
681  double sumW2 = 0;;
682 
683  for (unsigned vIt = 0; vIt < vecSize; vIt++) {
684  logl += logl_v[vIt];
685  sumW += sumW_v[vIt];
686  sumW2 += sumW2_v[vIt];
687  }
688 
689  if (extended) {
690  // add Poisson extended term
691  double extendedTerm = 0; // extended term in likelihood
692  double nuTot = 0;
693  // nuTot is integral of function in the range
694  // if function has been normalized integral has been already computed
695  if (!normalizeFunc) {
696  IntegralEvaluator<IModelFunctionTempl<T>> igEval(func, p, true);
697  std::vector<double> xmin(data.NDim());
698  std::vector<double> xmax(data.NDim());
699 
700  // compute integral in the ranges where is defined
701  if (data.Range().Size() > 0) {
702  nuTot = 0;
703  for (unsigned int ir = 0; ir < data.Range().Size(); ++ir) {
704  data.Range().GetRange(&xmin[0], &xmax[0], ir);
705  nuTot += igEval.Integral(xmin.data(), xmax.data());
706  }
707  } else {
708  // use (-inf +inf)
709  data.Range().GetRange(&xmin[0], &xmax[0]);
710  // check if funcition is zero at +- inf
711  T xmin_v, xmax_v;
712  vecCore::Load<T>(xmin_v, xmin.data());
713  vecCore::Load<T>(xmax_v, xmax.data());
714  if (vecCore::ReduceAdd(func(&xmin_v, p)) != 0 || vecCore::ReduceAdd(func(&xmax_v, p)) != 0) {
715  MATH_ERROR_MSG("FitUtil::EvaluateLogLikelihood", "A range has not been set and the function is not zero at +/- inf");
716  return 0;
717  }
718  nuTot = igEval.Integral(&xmin[0], &xmax[0]);
719  }
720 
721  // force to be last parameter value
722  //nutot = p[func.NDim()-1];
723  if (iWeight != 2)
724  extendedTerm = - nuTot; // no need to add in this case n log(nu) since is already computed before
725  else {
726  // case use weight square in likelihood : compute total effective weight = sw2/sw
727  // ignore for the moment case when sumW is zero
728  extendedTerm = - (sumW2 / sumW) * nuTot;
729  }
730 
731  } else {
732  nuTot = norm;
733  extendedTerm = - nuTot + double(n) * ROOT::Math::Util::EvalLog(nuTot);
734  // in case of weights need to use here sum of weights (to be done)
735  }
736 
737  logl += extendedTerm;
738  }
739 
740 #ifdef DEBUG_FITUTIL
741  std::cout << "Evaluated log L for parameters (";
742  for (unsigned int ip = 0; ip < func.NPar(); ++ip)
743  std::cout << " " << p[ip];
744  std::cout << ") nll = " << -logl << std::endl;
745 #endif
746 
747  // reset the number of fitting data points
748  // nPoints = n;
749  // std::cout<<", n: "<<nPoints<<std::endl;
750  nPoints = 0;
751  return -logl;
752 
753  }
754 
755  static double EvalPoissonLogL(const IModelFunctionTempl<T> &func, const BinData &data, const double *p,
756  int iWeight, bool extended, unsigned int,
757  ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks = 0)
758  {
759  // evaluate the Poisson Log Likelihood
760  // for binned likelihood fits
761  // this is Sum ( f(x_i) - y_i * log( f (x_i) ) )
762  // add as well constant term for saturated model to make it like a Chi2/2
763  // by default is etended. If extended is false the fit is not extended and
764  // the global poisson term is removed (i.e is a binomial fit)
765  // (remember that in this case one needs to have a function with a fixed normalization
766  // like in a non extended binned fit)
767  //
768  // if use Weight use a weighted dataset
769  // iWeight = 1 ==> logL = Sum( w f(x_i) )
770  // case of iWeight==1 is actually identical to weight==0
771  // iWeight = 2 ==> logL = Sum( w*w * f(x_i) )
772  //
773 
774 #ifdef USE_PARAMCACHE
775  (const_cast<IModelFunctionTempl<T> &>(func)).SetParameters(p);
776 #endif
777  auto vecSize = vecCore::VectorSize<T>();
778  // get fit option and check case of using integral of bins
779  const DataOptions &fitOpt = data.Opt();
780  if (fitOpt.fExpErrors || fitOpt.fIntegral)
781  Error("FitUtil::EvaluateChi2",
782  "The vectorized implementation doesn't support Integrals or BinVolume\n. Aborting operation.");
783  bool useW2 = (iWeight == 2);
784 
785  auto mapFunction = [&](unsigned int i) {
786  T y;
787  vecCore::Load<T>(y, data.ValuePtr(i * vecSize));
788  T fval{};
789 
790  if (data.NDim() > 1) {
791  std::vector<T> x(data.NDim());
792  for (unsigned int j = 0; j < data.NDim(); ++j)
793  vecCore::Load<T>(x[j], data.GetCoordComponent(i * vecSize, j));
794 #ifdef USE_PARAMCACHE
795  fval = func(x.data());
796 #else
797  fval = func(x.data(), p);
798 #endif
799  // one -dim case
800  } else {
801  T x;
802  vecCore::Load<T>(x, data.GetCoordComponent(i * vecSize, 0));
803 #ifdef USE_PARAMCACHE
804  fval = func(&x);
805 #else
806  fval = func(&x, p);
807 #endif
808  }
809 
810  // EvalLog protects against 0 values of fval but don't want to add in the -log sum
811  // negative values of fval
812  vecCore::MaskedAssign<T>(fval, fval < 0.0, 0.0);
813 
814  T nloglike{}; // negative loglikelihood
815 
816  if (useW2) {
817  // apply weight correction . Effective weight is error^2/ y
818  // and expected events in bins is fval/weight
819  // can apply correction only when y is not zero otherwise weight is undefined
820  // (in case of weighted likelihood I don't care about the constant term due to
821  // the saturated model)
822  assert (data.GetErrorType() != ROOT::Fit::BinData::ErrorType::kNoError);
823  T error = 0.0;
824  vecCore::Load<T>(error, data.ErrorPtr(i * vecSize));
825  // for empty bin use the average weight computed from the total data weight
826  auto m = vecCore::Mask_v<T>(y != 0.0);
827  auto weight = vecCore::Blend(m,(error * error) / y, T(data.SumOfError2()/ data.SumOfContent()) );
828  if (extended) {
829  nloglike = weight * ( fval - y);
830  }
831  vecCore::MaskedAssign<T>(nloglike, y != 0, nloglike + weight * y *( ROOT::Math::Util::EvalLog(y) - ROOT::Math::Util::EvalLog(fval)) );
832 
833  } else {
834  // standard case no weights or iWeight=1
835  // this is needed for Poisson likelihood (which are extened and not for multinomial)
836  // the formula below include constant term due to likelihood of saturated model (f(x) = y)
837  // (same formula as in Baker-Cousins paper, page 439 except a factor of 2
838  if (extended) nloglike = fval - y;
839 
840  vecCore::MaskedAssign<T>(
841  nloglike, y > 0, nloglike + y * (ROOT::Math::Util::EvalLog(y) - ROOT::Math::Util::EvalLog(fval)));
842  }
843 
844  return nloglike;
845  };
846 
847 #ifdef R__USE_IMT
848  auto redFunction = [](const std::vector<T> &objs) { return std::accumulate(objs.begin(), objs.end(), T{}); };
849 #else
850  (void)nChunks;
851 
852  // If IMT is disabled, force the execution policy to the serial case
853  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
854  Warning("FitUtil::Evaluate<T>::EvalPoissonLogL",
855  "Multithread execution policy requires IMT, which is disabled. Changing "
856  "to ROOT::Fit::ExecutionPolicy::kSerial.");
857  executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
858  }
859 #endif
860 
861  T res{};
862  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
863  for (unsigned int i = 0; i < (data.Size() / vecSize); i++) {
864  res += mapFunction(i);
865  }
866 #ifdef R__USE_IMT
867  } else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
868  auto chunks = nChunks != 0 ? nChunks : setAutomaticChunking(data.Size() / vecSize);
869  ROOT::TThreadExecutor pool;
870  res = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, data.Size() / vecSize), redFunction, chunks);
871 #endif
872  // } else if(executionPolicy == ROOT::Fit::ExecutionPolicy::kMultiprocess){
873  // ROOT::TProcessExecutor pool;
874  // res = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, data.Size()/vecSize), redFunction);
875  } else {
876  Error(
877  "FitUtil::Evaluate<T>::EvalPoissonLogL",
878  "Execution policy unknown. Avalaible choices:\n ROOT::Fit::ExecutionPolicy::kSerial (default)\n ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
879  }
880 
881  // Last padded SIMD vector of elements
882  vecCore::MaskedAssign(res, vecCore::Int2Mask<T>(data.Size() % vecSize),
883  res + mapFunction(data.Size() / vecSize));
884 
885  return vecCore::ReduceAdd(res);
886  }
887 
888  static double EvalChi2Effective(const IModelFunctionTempl<T> &, const BinData &, const double *, unsigned int &)
889  {
890  Error("FitUtil::Evaluate<T>::EvalChi2Effective", "The vectorized evaluation of the Chi2 with coordinate errors is still not supported");
891  return -1.;
892  }
893 
894  // Compute a mask to filter out infinite numbers and NaN values.
895  // The argument rval is updated so infinite numbers and NaN values are replaced by
896  // maximum finite values (preserving the original sign).
897  static vecCore::Mask<T> CheckInfNaNValues(T &rval)
898  {
899  auto mask = rval > -vecCore::NumericLimits<T>::Max() && rval < vecCore::NumericLimits<T>::Max();
900 
901  // Case +inf or nan
902  vecCore::MaskedAssign(rval, !mask, +vecCore::NumericLimits<T>::Max());
903 
904  // Case -inf
905  vecCore::MaskedAssign(rval, !mask && rval < 0, -vecCore::NumericLimits<T>::Max());
906 
907  return mask;
908  }
909 
910  static void EvalChi2Gradient(const IModelFunctionTempl<T> &f, const BinData &data, const double *p, double *grad,
911  unsigned int &nPoints,
913  unsigned nChunks = 0)
914  {
915  // evaluate the gradient of the chi2 function
916  // this function is used when the model function knows how to calculate the derivative and we can
917  // avoid that the minimizer re-computes them
918  //
919  // case of chi2 effective (errors on coordinate) is not supported
920 
921  if (data.HaveCoordErrors()) {
922  MATH_ERROR_MSG("FitUtil::EvaluateChi2Gradient",
923  "Error on the coordinates are not used in calculating Chi2 gradient");
924  return; // it will assert otherwise later in GetPoint
925  }
926 
927  const IGradModelFunctionTempl<T> *fg = dynamic_cast<const IGradModelFunctionTempl<T> *>(&f);
928  assert(fg != nullptr); // must be called by a gradient function
929 
930  const IGradModelFunctionTempl<T> &func = *fg;
931 
932  const DataOptions &fitOpt = data.Opt();
933  if (fitOpt.fBinVolume || fitOpt.fIntegral || fitOpt.fExpErrors)
934  Error("FitUtil::EvaluateChi2Gradient", "The vectorized implementation doesn't support Integrals,"
935  "BinVolume or ExpErrors\n. Aborting operation.");
936 
937  unsigned int npar = func.NPar();
938  auto vecSize = vecCore::VectorSize<T>();
939  unsigned initialNPoints = data.Size();
940  unsigned numVectors = initialNPoints / vecSize;
941 
942  // numVectors + 1 because of the padded data (call to mapFunction with i = numVectors after the main loop)
943  std::vector<vecCore::Mask<T>> validPointsMasks(numVectors + 1);
944 
945  auto mapFunction = [&](const unsigned int i) {
946  // set all vector values to zero
947  std::vector<T> gradFunc(npar);
948  std::vector<T> pointContributionVec(npar);
949 
950  T x1, y, invError;
951 
952  vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
953  vecCore::Load<T>(y, data.ValuePtr(i * vecSize));
954  const auto invErrorPtr = data.ErrorPtr(i * vecSize);
955 
956  if (invErrorPtr == nullptr)
957  invError = 1;
958  else
959  vecCore::Load<T>(invError, invErrorPtr);
960 
961  // TODO: Check error options and invert if needed
962 
963  T fval = 0;
964 
965  const T *x = nullptr;
966 
967  unsigned int ndim = data.NDim();
968  // need to declare vector outside if statement
969  // otherwise pointer will be invalid
970  std::vector<T> xc;
971  if (ndim > 1) {
972  xc.resize(ndim);
973  xc[0] = x1;
974  for (unsigned int j = 1; j < ndim; ++j)
975  vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
976  x = xc.data();
977  } else {
978  x = &x1;
979  }
980 
981  fval = func(x, p);
982  func.ParameterGradient(x, p, &gradFunc[0]);
983 
984 // #ifdef DEBUG_FITUTIL
985 // std::cout << x[0] << " " << y << " " << 1. / invError << " params : ";
986 // for (unsigned int ipar = 0; ipar < npar; ++ipar)
987 // std::cout << p[ipar] << "\t";
988 // std::cout << "\tfval = " << fval << std::endl;
989 // #endif
990 
991  validPointsMasks[i] = CheckInfNaNValues(fval);
992  if (vecCore::MaskEmpty(validPointsMasks[i])) {
993  // Return a zero contribution to all partial derivatives on behalf of the current points
994  return pointContributionVec;
995  }
996 
997  // loop on the parameters
998  for (unsigned int ipar = 0; ipar < npar; ++ipar) {
999  // avoid singularity in the function (infinity and nan ) in the chi2 sum
1000  // eventually add possibility of excluding some points (like singularity)
1001  validPointsMasks[i] = CheckInfNaNValues(gradFunc[ipar]);
1002 
1003  if (vecCore::MaskEmpty(validPointsMasks[i])) {
1004  break; // exit loop on parameters
1005  }
1006 
1007  // calculate derivative point contribution (only for valid points)
1008  vecCore::MaskedAssign(pointContributionVec[ipar], validPointsMasks[i],
1009  -2.0 * (y - fval) * invError * invError * gradFunc[ipar]);
1010  }
1011 
1012  return pointContributionVec;
1013  };
1014 
1015  // Reduce the set of vectors by summing its equally-indexed components
1016  auto redFunction = [&](const std::vector<std::vector<T>> &partialResults) {
1017  std::vector<T> result(npar);
1018 
1019  for (auto const &pointContributionVec : partialResults) {
1020  for (unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1021  result[parameterIndex] += pointContributionVec[parameterIndex];
1022  }
1023 
1024  return result;
1025  };
1026 
1027  std::vector<T> gVec(npar);
1028  std::vector<double> g(npar);
1029 
1030 #ifndef R__USE_IMT
1031  // to fix compiler warning
1032  (void)nChunks;
1033 
1034  // If IMT is disabled, force the execution policy to the serial case
1035  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1036  Warning("FitUtil::EvaluateChi2Gradient",
1037  "Multithread execution policy requires IMT, which is disabled. Changing "
1038  "to ROOT::Fit::ExecutionPolicy::kSerial.");
1039  executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
1040  }
1041 #endif
1042 
1043  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
1044  std::vector<std::vector<T>> allGradients(numVectors);
1045  for (unsigned int i = 0; i < numVectors; ++i) {
1046  allGradients[i] = mapFunction(i);
1047  }
1048 
1049  gVec = redFunction(allGradients);
1050  }
1051 #ifdef R__USE_IMT
1052  else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1053  auto chunks = nChunks != 0 ? nChunks : setAutomaticChunking(numVectors);
1054  ROOT::TThreadExecutor pool;
1055  gVec = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, numVectors), redFunction, chunks);
1056  }
1057 #endif
1058  // else if(executionPolicy == ROOT::Fit::kMultiprocess){
1059  // ROOT::TProcessExecutor pool;
1060  // g = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, n), redFunction);
1061  // }
1062  else {
1063  Error(
1064  "FitUtil::EvaluateChi2Gradient",
1065  "Execution policy unknown. Avalaible choices:\n 0: Serial (default)\n 1: MultiThread (requires IMT)\n");
1066  }
1067 
1068  // Compute the contribution from the remaining points
1069  unsigned int remainingPoints = initialNPoints % vecSize;
1070  if (remainingPoints > 0) {
1071  auto remainingPointsContribution = mapFunction(numVectors);
1072  // Add the contribution from the valid remaining points and store the result in the output variable
1073  auto remainingMask = vecCore::Int2Mask<T>(remainingPoints);
1074  for (unsigned int param = 0; param < npar; param++) {
1075  vecCore::MaskedAssign(gVec[param], remainingMask, gVec[param] + remainingPointsContribution[param]);
1076  }
1077  }
1078  // reduce final gradient result from T to double
1079  for (unsigned int param = 0; param < npar; param++) {
1080  grad[param] = vecCore::ReduceAdd(gVec[param]);
1081  }
1082 
1083  // correct the number of points
1084  nPoints = initialNPoints;
1085 
1086  if (std::any_of(validPointsMasks.begin(), validPointsMasks.end(),
1087  [](vecCore::Mask<T> validPoints) { return !vecCore::MaskFull(validPoints); })) {
1088  unsigned nRejected = 0;
1089 
1090  for (const auto &mask : validPointsMasks) {
1091  for (unsigned int i = 0; i < vecSize; i++) {
1092  nRejected += !vecCore::Get(mask, i);
1093  }
1094  }
1095 
1096  assert(nRejected <= initialNPoints);
1097  nPoints = initialNPoints - nRejected;
1098 
1099  if (nPoints < npar) {
1100  MATH_ERROR_MSG("FitUtil::EvaluateChi2Gradient",
1101  "Too many points rejected for overflow in gradient calculation");
1102  }
1103  }
1104  }
1105 
1106  static double EvalChi2Residual(const IModelFunctionTempl<T> &, const BinData &, const double *, unsigned int, double *)
1107  {
1108  Error("FitUtil::Evaluate<T>::EvalChi2Residual", "The vectorized evaluation of the Chi2 with the ith residual is still not supported");
1109  return -1.;
1110  }
1111 
1112  /// evaluate the pdf (Poisson) contribution to the logl (return actually log of pdf)
1113  /// and its gradient
1114  static double EvalPoissonBinPdf(const IModelFunctionTempl<T> &, const BinData &, const double *, unsigned int , double * ) {
1115  Error("FitUtil::Evaluate<T>::EvaluatePoissonBinPdf", "The vectorized evaluation of the BinnedLikelihood fit evaluated point by point is still not supported");
1116  return -1.;
1117  }
1118 
1119  static void
1120  EvalPoissonLogLGradient(const IModelFunctionTempl<T> &f, const BinData &data, const double *p, double *grad,
1121  unsigned int &,
1123  unsigned nChunks = 0)
1124  {
1125  // evaluate the gradient of the Poisson log likelihood function
1126 
1127  const IGradModelFunctionTempl<T> *fg = dynamic_cast<const IGradModelFunctionTempl<T> *>(&f);
1128  assert(fg != nullptr); // must be called by a grad function
1129 
1130  const IGradModelFunctionTempl<T> &func = *fg;
1131 
1132  (const_cast<IGradModelFunctionTempl<T> &>(func)).SetParameters(p);
1133 
1134 
1135  const DataOptions &fitOpt = data.Opt();
1136  if (fitOpt.fBinVolume || fitOpt.fIntegral || fitOpt.fExpErrors)
1137  Error("FitUtil::EvaluatePoissonLogLGradient", "The vectorized implementation doesn't support Integrals,"
1138  "BinVolume or ExpErrors\n. Aborting operation.");
1139 
1140  unsigned int npar = func.NPar();
1141  auto vecSize = vecCore::VectorSize<T>();
1142  unsigned initialNPoints = data.Size();
1143  unsigned numVectors = initialNPoints / vecSize;
1144 
1145  auto mapFunction = [&](const unsigned int i) {
1146  // set all vector values to zero
1147  std::vector<T> gradFunc(npar);
1148  std::vector<T> pointContributionVec(npar);
1149 
1150  T x1, y;
1151 
1152  vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
1153  vecCore::Load<T>(y, data.ValuePtr(i * vecSize));
1154 
1155  T fval = 0;
1156 
1157  const T *x = nullptr;
1158 
1159  unsigned ndim = data.NDim();
1160  std::vector<T> xc;
1161  if (ndim > 1) {
1162  xc.resize(ndim);
1163  xc[0] = x1;
1164  for (unsigned int j = 1; j < ndim; ++j)
1165  vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
1166  x = xc.data();
1167  } else {
1168  x = &x1;
1169  }
1170 
1171  fval = func(x, p);
1172  func.ParameterGradient(x, p, &gradFunc[0]);
1173 
1174  // correct the gradient
1175  for (unsigned int ipar = 0; ipar < npar; ++ipar) {
1176  vecCore::Mask<T> positiveValuesMask = fval > 0;
1177 
1178  // df/dp * (1. - y/f )
1179  vecCore::MaskedAssign(pointContributionVec[ipar], positiveValuesMask, gradFunc[ipar] * (1. - y / fval));
1180 
1181  vecCore::Mask<T> validNegativeValuesMask = !positiveValuesMask && gradFunc[ipar] != 0;
1182 
1183  if (!vecCore::MaskEmpty(validNegativeValuesMask)) {
1184  const T kdmax1 = vecCore::math::Sqrt(vecCore::NumericLimits<T>::Max());
1185  const T kdmax2 = vecCore::NumericLimits<T>::Max() / (4 * initialNPoints);
1186  T gg = kdmax1 * gradFunc[ipar];
1187  pointContributionVec[ipar] = -vecCore::Blend(gg > 0, vecCore::math::Min(gg, kdmax2), vecCore::math::Max(gg, -kdmax2));
1188  }
1189  }
1190 
1191 #ifdef DEBUG_FITUTIL
1192  {
1193  R__LOCKGUARD(gROOTMutex);
1194  if (i < 5 || (i > data.Size()-5) ) {
1195  if (data.NDim() > 1) std::cout << i << " x " << x[0] << " y " << x[1];
1196  else std::cout << i << " x " << x[0];
1197  std::cout << " func " << fval << " gradient ";
1198  for (unsigned int ii = 0; ii < npar; ++ii) std::cout << " " << pointContributionVec[ii];
1199  std::cout << "\n";
1200  }
1201  }
1202 #endif
1203 
1204  return pointContributionVec;
1205  };
1206 
1207  // Vertically reduce the set of vectors by summing its equally-indexed components
1208  auto redFunction = [&](const std::vector<std::vector<T>> &partialResults) {
1209  std::vector<T> result(npar);
1210 
1211  for (auto const &pointContributionVec : partialResults) {
1212  for (unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1213  result[parameterIndex] += pointContributionVec[parameterIndex];
1214  }
1215 
1216  return result;
1217  };
1218 
1219  std::vector<T> gVec(npar);
1220 
1221 #ifndef R__USE_IMT
1222  // to fix compiler warning
1223  (void)nChunks;
1224 
1225  // If IMT is disabled, force the execution policy to the serial case
1226  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1227  Warning("FitUtil::EvaluatePoissonLogLGradient",
1228  "Multithread execution policy requires IMT, which is disabled. Changing "
1229  "to ROOT::Fit::ExecutionPolicy::kSerial.");
1230  executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
1231  }
1232 #endif
1233 
1234  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
1235  std::vector<std::vector<T>> allGradients(numVectors);
1236  for (unsigned int i = 0; i < numVectors; ++i) {
1237  allGradients[i] = mapFunction(i);
1238  }
1239 
1240  gVec = redFunction(allGradients);
1241  }
1242 #ifdef R__USE_IMT
1243  else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1244  auto chunks = nChunks != 0 ? nChunks : setAutomaticChunking(numVectors);
1245  ROOT::TThreadExecutor pool;
1246  gVec = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, numVectors), redFunction, chunks);
1247  }
1248 #endif
1249  // else if(executionPolicy == ROOT::Fit::ExecutionPolicy::kMultiprocess){
1250  // ROOT::TProcessExecutor pool;
1251  // g = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, n), redFunction);
1252  // }
1253  else {
1254  Error("FitUtil::EvaluatePoissonLogLGradient", "Execution policy unknown. Avalaible choices:\n "
1255  "ROOT::Fit::ExecutionPolicy::kSerial (default)\n "
1256  "ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
1257  }
1258 
1259 
1260  // Compute the contribution from the remaining points
1261  unsigned int remainingPoints = initialNPoints % vecSize;
1262  if (remainingPoints > 0) {
1263  auto remainingPointsContribution = mapFunction(numVectors);
1264  // Add the contribution from the valid remaining points and store the result in the output variable
1265  auto remainingMask = vecCore::Int2Mask<T>(remainingPoints);
1266  for (unsigned int param = 0; param < npar; param++) {
1267  vecCore::MaskedAssign(gVec[param], remainingMask, gVec[param] + remainingPointsContribution[param]);
1268  }
1269  }
1270  // reduce final gradient result from T to double
1271  for (unsigned int param = 0; param < npar; param++) {
1272  grad[param] = vecCore::ReduceAdd(gVec[param]);
1273  }
1274 
1275 #ifdef DEBUG_FITUTIL
1276  std::cout << "***** Final gradient : ";
1277  for (unsigned int ii = 0; ii< npar; ++ii) std::cout << grad[ii] << " ";
1278  std::cout << "\n";
1279 #endif
1280 
1281  }
1282 
1283  static void EvalLogLGradient(const IModelFunctionTempl<T> &f, const UnBinData &data, const double *p,
1284  double *grad, unsigned int &,
1286  unsigned nChunks = 0)
1287  {
1288  // evaluate the gradient of the log likelihood function
1289 
1290  const IGradModelFunctionTempl<T> *fg = dynamic_cast<const IGradModelFunctionTempl<T> *>(&f);
1291  assert(fg != nullptr); // must be called by a grad function
1292 
1293  const IGradModelFunctionTempl<T> &func = *fg;
1294 
1295 
1296  unsigned int npar = func.NPar();
1297  auto vecSize = vecCore::VectorSize<T>();
1298  unsigned initialNPoints = data.Size();
1299  unsigned numVectors = initialNPoints / vecSize;
1300 
1301 #ifdef DEBUG_FITUTIL
1302  std::cout << "\n===> Evaluate Gradient for parameters ";
1303  for (unsigned int ip = 0; ip < npar; ++ip)
1304  std::cout << " " << p[ip];
1305  std::cout << "\n";
1306 #endif
1307 
1308  (const_cast<IGradModelFunctionTempl<T> &>(func)).SetParameters(p);
1309 
1310  const T kdmax1 = vecCore::math::Sqrt(vecCore::NumericLimits<T>::Max());
1311  const T kdmax2 = vecCore::NumericLimits<T>::Max() / (4 * initialNPoints);
1312 
1313  auto mapFunction = [&](const unsigned int i) {
1314  std::vector<T> gradFunc(npar);
1315  std::vector<T> pointContributionVec(npar);
1316 
1317  T x1;
1318  vecCore::Load<T>(x1, data.GetCoordComponent(i * vecSize, 0));
1319 
1320  const T *x = nullptr;
1321 
1322  unsigned int ndim = data.NDim();
1323  std::vector<T> xc(ndim);
1324  if (ndim > 1) {
1325  xc.resize(ndim);
1326  xc[0] = x1;
1327  for (unsigned int j = 1; j < ndim; ++j)
1328  vecCore::Load<T>(xc[j], data.GetCoordComponent(i * vecSize, j));
1329  x = xc.data();
1330  } else {
1331  x = &x1;
1332  }
1333 
1334 
1335  T fval = func(x, p);
1336  func.ParameterGradient(x, p, &gradFunc[0]);
1337 
1338 #ifdef DEBUG_FITUTIL
1339  if (i < 5 || (i > numVectors-5) ) {
1340  if (ndim > 1) std::cout << i << " x " << x[0] << " y " << x[1] << " gradient " << gradFunc[0] << " " << gradFunc[1] << " " << gradFunc[3] << std::endl;
1341  else std::cout << i << " x " << x[0] << " gradient " << gradFunc[0] << " " << gradFunc[1] << " " << gradFunc[3] << std::endl;
1342  }
1343 #endif
1344 
1345  vecCore::Mask<T> positiveValues = fval > 0;
1346 
1347  for (unsigned int kpar = 0; kpar < npar; ++kpar) {
1348  if (!vecCore::MaskEmpty(positiveValues))
1349  vecCore::MaskedAssign<T>(pointContributionVec[kpar], positiveValues, -1. / fval * gradFunc[kpar]);
1350 
1351  vecCore::Mask<T> nonZeroGradientValues = !positiveValues && gradFunc[kpar] != 0;
1352  if (!vecCore::MaskEmpty(nonZeroGradientValues)) {
1353  T gg = kdmax1 * gradFunc[kpar];
1354  pointContributionVec[kpar] =
1355  vecCore::Blend(nonZeroGradientValues && gg > 0, -vecCore::math::Min(gg, kdmax2),
1356  -vecCore::math::Max(gg, -kdmax2));
1357  }
1358  // if func derivative is zero term is also zero so do not add in g[kpar]
1359  }
1360 
1361  return pointContributionVec;
1362  };
1363 
1364  // Vertically reduce the set of vectors by summing its equally-indexed components
1365  auto redFunction = [&](const std::vector<std::vector<T>> &pointContributions) {
1366  std::vector<T> result(npar);
1367 
1368  for (auto const &pointContributionVec : pointContributions) {
1369  for (unsigned int parameterIndex = 0; parameterIndex < npar; parameterIndex++)
1370  result[parameterIndex] += pointContributionVec[parameterIndex];
1371  }
1372 
1373  return result;
1374  };
1375 
1376  std::vector<T> gVec(npar);
1377  std::vector<double> g(npar);
1378 
1379 #ifndef R__USE_IMT
1380  // to fix compiler warning
1381  (void)nChunks;
1382 
1383  // If IMT is disabled, force the execution policy to the serial case
1384  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1385  Warning("FitUtil::EvaluateLogLGradient",
1386  "Multithread execution policy requires IMT, which is disabled. Changing "
1387  "to ROOT::Fit::ExecutionPolicy::kSerial.");
1388  executionPolicy = ROOT::Fit::ExecutionPolicy::kSerial;
1389  }
1390 #endif
1391 
1392  if (executionPolicy == ROOT::Fit::ExecutionPolicy::kSerial) {
1393  std::vector<std::vector<T>> allGradients(numVectors);
1394  for (unsigned int i = 0; i < numVectors; ++i) {
1395  allGradients[i] = mapFunction(i);
1396  }
1397  gVec = redFunction(allGradients);
1398  }
1399 #ifdef R__USE_IMT
1400  else if (executionPolicy == ROOT::Fit::ExecutionPolicy::kMultithread) {
1401  auto chunks = nChunks != 0 ? nChunks : setAutomaticChunking(numVectors);
1402  ROOT::TThreadExecutor pool;
1403  gVec = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, numVectors), redFunction, chunks);
1404  }
1405 #endif
1406  // else if(executionPolicy == ROOT::Fit::ExecutionPolicy::kMultiprocess){
1407  // ROOT::TProcessExecutor pool;
1408  // g = pool.MapReduce(mapFunction, ROOT::TSeq<unsigned>(0, n), redFunction);
1409  // }
1410  else {
1411  Error("FitUtil::EvaluateLogLGradient", "Execution policy unknown. Avalaible choices:\n "
1412  "ROOT::Fit::ExecutionPolicy::kSerial (default)\n "
1413  "ROOT::Fit::ExecutionPolicy::kMultithread (requires IMT)\n");
1414  }
1415 
1416  // Compute the contribution from the remaining points
1417  unsigned int remainingPoints = initialNPoints % vecSize;
1418  if (remainingPoints > 0) {
1419  auto remainingPointsContribution = mapFunction(numVectors);
1420  // Add the contribution from the valid remaining points and store the result in the output variable
1421  auto remainingMask = vecCore::Int2Mask<T>(initialNPoints % vecSize);
1422  for (unsigned int param = 0; param < npar; param++) {
1423  vecCore::MaskedAssign(gVec[param], remainingMask, gVec[param] + remainingPointsContribution[param]);
1424  }
1425  }
1426  // reduce final gradient result from T to double
1427  for (unsigned int param = 0; param < npar; param++) {
1428  grad[param] = vecCore::ReduceAdd(gVec[param]);
1429  }
1430 
1431 #ifdef DEBUG_FITUTIL
1432  std::cout << "Final gradient ";
1433  for (unsigned int param = 0; param < npar; param++) {
1434  std::cout << " " << grad[param];
1435  }
1436  std::cout << "\n";
1437 #endif
1438  }
1439  };
1440 
1441  template<>
1442  struct Evaluate<double>{
1443 #endif
1444 
1445  static double EvalChi2(const IModelFunction &func, const BinData &data, const double *p, unsigned int &nPoints,
1446  ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks = 0)
1447  {
1448  // evaluate the chi2 given a function reference, the data and returns the value and also in nPoints
1449  // the actual number of used points
1450  // normal chi2 using only error on values (from fitting histogram)
1451  // optionally the integral of function in the bin is used
1452 
1453 
1454  //Info("EvalChi2","Using non-vecorized implementation %d",(int) data.Opt().fIntegral);
1455 
1456  return FitUtil::EvaluateChi2(func, data, p, nPoints, executionPolicy, nChunks);
1457  }
1458 
1459  static double EvalLogL(const IModelFunctionTempl<double> &func, const UnBinData &data, const double *p,
1460  int iWeight, bool extended, unsigned int &nPoints,
1461  ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks = 0)
1462  {
1463  return FitUtil::EvaluateLogL(func, data, p, iWeight, extended, nPoints, executionPolicy, nChunks);
1464  }
1465 
1466  static double EvalPoissonLogL(const IModelFunctionTempl<double> &func, const BinData &data, const double *p,
1467  int iWeight, bool extended, unsigned int &nPoints,
1468  ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks = 0)
1469  {
1470  return FitUtil::EvaluatePoissonLogL(func, data, p, iWeight, extended, nPoints, executionPolicy, nChunks);
1471  }
1472 
1473  static double EvalChi2Effective(const IModelFunctionTempl<double> &func, const BinData & data, const double * p, unsigned int &nPoints)
1474  {
1475  return FitUtil::EvaluateChi2Effective(func, data, p, nPoints);
1476  }
1477  static void EvalChi2Gradient(const IModelFunctionTempl<double> &func, const BinData &data, const double *p,
1478  double *g, unsigned int &nPoints,
1480  unsigned nChunks = 0)
1481  {
1482  FitUtil::EvaluateChi2Gradient(func, data, p, g, nPoints, executionPolicy, nChunks);
1483  }
1484  static double EvalChi2Residual(const IModelFunctionTempl<double> &func, const BinData & data, const double * p, unsigned int i, double *g = 0)
1485  {
1486  return FitUtil::EvaluateChi2Residual(func, data, p, i, g);
1487  }
1488 
1489  /// evaluate the pdf (Poisson) contribution to the logl (return actually log of pdf)
1490  /// and its gradient
1491  static double EvalPoissonBinPdf(const IModelFunctionTempl<double> &func, const BinData & data, const double *p, unsigned int i, double *g ) {
1492  return FitUtil::EvaluatePoissonBinPdf(func, data, p, i, g);
1493  }
1494 
1495  static void
1496  EvalPoissonLogLGradient(const IModelFunctionTempl<double> &func, const BinData &data, const double *p, double *g,
1497  unsigned int &nPoints,
1499  unsigned nChunks = 0)
1500  {
1501  FitUtil::EvaluatePoissonLogLGradient(func, data, p, g, nPoints, executionPolicy, nChunks);
1502  }
1503 
1504  static void EvalLogLGradient(const IModelFunctionTempl<double> &func, const UnBinData &data, const double *p,
1505  double *g, unsigned int &nPoints,
1507  unsigned nChunks = 0)
1508  {
1509  FitUtil::EvaluateLogLGradient(func, data, p, g, nPoints, executionPolicy, nChunks);
1510  }
1511  };
1512 
1513 } // end namespace FitUtil
1514 
1515  } // end namespace Fit
1516 
1517 } // end namespace ROOT
1518 
1519 #if defined (R__HAS_VECCORE) && defined(R__HAS_VC)
1520 //Fixes alignment for structures of SIMD structures
1522 #endif
1523 
1524 #endif /* ROOT_Fit_FitUtil */
LikelihoodAux & operator+=(const LikelihoodAux &l)
Definition: FitUtil.h:85
void SetFunction(const ParamFunc &func, const double *p=0)
Definition: FitUtil.h:140
static double EvalChi2Residual(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, unsigned int i, double *g=0)
Definition: FitUtil.h:1484
ROOT::Math::IntegratorOneDim * fIg1Dim
Definition: FitUtil.h:257
LikelihoodAux operator+(const LikelihoodAux &l) const
Definition: FitUtil.h:80
Interface (abstract class) for generic functions objects of one-dimension Provides a method to evalua...
Definition: IFunction.h:135
void SetParameters(const double *p)
Definition: FitUtil.h:169
unsigned int NDim() const
return coordinate data dimension
Definition: UnBinData.h:280
double ExecFunc(T *f, const double *x, const double *p) const
Definition: FitUtil.h:223
Namespace for new ROOT classes and functions.
Definition: TFoamSampler.h:19
double EvaluateChi2(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
Chi2 Functions.
Definition: FitUtil.cxx:226
void EvaluateLogLGradient(const IModelFunction &func, const UnBinData &data, const double *x, double *grad, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
evaluate the LogL gradient given a model function and the data at the point x.
Definition: FitUtil.cxx:1126
double EvaluatePoissonBinPdf(const IModelFunction &func, const BinData &data, const double *x, unsigned int ipoint, double *g=0)
evaluate the pdf contribution to the Poisson LogL given a model function and the BinPoint data...
Definition: FitUtil.cxx:1268
ROOT::Math::IMultiGenFunction * fFuncNDim
Definition: FitUtil.h:260
ErrorType GetErrorType() const
retrieve the errortype
Definition: BinData.h:545
double T(double x)
Definition: ChebyshevPol.h:34
static double EvalLogL(const IModelFunctionTempl< double > &func, const UnBinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
Definition: FitUtil.h:1459
const double * ValuePtr(unsigned int ipoint) const
return a pointer to the value for the given fit point
Definition: BinData.h:229
static void EvalChi2Gradient(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, double *g, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
Definition: FitUtil.h:1477
unsigned setAutomaticChunking(unsigned nEvents)
Definition: FitUtil.cxx:1756
Class describing the unbinned data sets (just x coordinates values) of any dimensions.
Definition: UnBinData.h:42
Interface (abstract class) for parametric gradient multi-dimensional functions providing in addition ...
ROOT::Math::IParamMultiGradFunction IGradModelFunction
Definition: FitUtil.h:66
ROOT::Math::IntegratorMultiDim * fIgNDim
Definition: FitUtil.h:258
static double EvalPoissonBinPdf(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, unsigned int i, double *g)
evaluate the pdf (Poisson) contribution to the logl (return actually log of pdf) and its gradient ...
Definition: FitUtil.h:1491
static double EvalPoissonLogL(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
Definition: FitUtil.h:1466
you should not use this method at all Int_t y
Definition: TRolke.cxx:630
double SumOfError2() const
compute the total sum of the error square (sum of weight square in case of a weighted data set) ...
Definition: BinData.h:560
LikelihoodAux(double logv=0.0, double w=0.0, double w2=0.0)
Definition: FitUtil.h:101
void GetRange(unsigned int irange, unsigned int icoord, double &xmin, double &xmax) const
get the i-th range for given coordinate.
Definition: DataRange.h:103
const double * GetCoordComponent(unsigned int ipoint, unsigned int icoord) const
returns a single coordinate component of a point.
Definition: FitData.h:229
void EvaluatePoissonLogLGradient(const IModelFunction &func, const BinData &data, const double *x, double *grad, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
evaluate the Poisson LogL given a model function and the data at the point x.
Definition: FitUtil.cxx:1572
static double EvalChi2(const IModelFunction &func, const BinData &data, const double *p, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
Definition: FitUtil.h:1445
double EvaluatePoissonLogL(const IModelFunction &func, const BinData &data, const double *x, int iWeight, bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
evaluate the Poisson LogL given a model function and the data at the point x.
Definition: FitUtil.cxx:1371
double FN(const double *x) const
Definition: FitUtil.h:195
unsigned int Size() const
return number of fit points
Definition: FitData.h:303
#define MATH_ERROR_MSG(loc, str)
Definition: Error.h:50
T EvalLog(T x)
safe evaluation of log(x) with a protections against negative or zero argument to the log smooth line...
Definition: Util.h:56
Double_t Double_v
Definition: Types.h:50
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t Int_t m
Definition: TRolke.cxx:637
Documentation for the abstract class IBaseFunctionMultiDim.
Definition: IFunction.h:62
void EvaluateChi2Gradient(const IModelFunction &func, const BinData &data, const double *x, double *grad, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
evaluate the Chi2 gradient given a model function and the data at the point x.
Definition: FitUtil.cxx:638
virtual unsigned int NPar() const =0
Return the number of Parameters.
DataOptions : simple structure holding the options on how the data are filled.
Definition: DataOptions.h:28
double EvaluateChi2Effective(const IModelFunction &func, const BinData &data, const double *x, unsigned int &nPoints)
evaluate the effective Chi2 given a model function and the data at the point x.
Definition: FitUtil.cxx:410
LikelihoodAux & operator+=(const LikelihoodAux &l)
Definition: FitUtil.h:108
unsigned int Size(unsigned int icoord=0) const
return range size for coordinate icoord (starts from zero) Size == 0 indicates no range is present [-...
Definition: DataRange.h:70
double EvaluateChi2Residual(const IModelFunction &func, const BinData &data, const double *x, unsigned int ipoint, double *g=0)
evaluate the residual contribution to the Chi2 given a model function and the BinPoint data and if th...
Definition: FitUtil.cxx:531
IntegralEvaluator(const ParamFunc &func, const double *p, bool useIntegral=true)
Definition: FitUtil.h:132
User Class for performing numerical integration of a function in one dimension.
Definition: Integrator.h:94
LikelihoodAux operator+(const LikelihoodAux &l) const
Definition: FitUtil.h:103
const DataOptions & Opt() const
access to options
Definition: FitData.h:319
virtual void ParameterGradient(const T *x, const double *p, T *grad) const
Evaluate the all the derivatives (gradient vector) of the function with respect to the parameters at ...
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
Definition: BinData.h:53
bool HaveCoordErrors() const
flag to control if data provides error on the coordinates
Definition: BinData.h:131
* x
Deprecated and error prone model selection interface.
Definition: TRolke.cxx:630
ROOT::Math::IParamMultiFunction IModelFunction
Definition: FitUtil.h:65
ROOT::Math::IGenFunction * fFunc1Dim
Definition: FitUtil.h:259
static void EvalPoissonLogLGradient(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, double *g, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
Definition: FitUtil.h:1496
IParamFunction interface (abstract class) describing multi-dimensional parameteric functions It is a ...
virtual void SetParameters(const double *p)=0
Set the parameter values.
const double * ErrorPtr(unsigned int ipoint) const
return error on the value for the given fit point Safe (but slower) method returning correctly the er...
Definition: BinData.h:240
static void EvalLogLGradient(const IModelFunctionTempl< double > &func, const UnBinData &data, const double *p, double *g, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy=ROOT::Fit::ExecutionPolicy::kSerial, unsigned nChunks=0)
Definition: FitUtil.h:1504
double F1(double x) const
Definition: FitUtil.h:189
double EvaluatePdf(const IModelFunction &func, const UnBinData &data, const double *x, unsigned int ipoint, double *g=0)
evaluate the pdf contribution to the LogL given a model function and the BinPoint data...
Definition: FitUtil.cxx:850
static double EvalChi2Effective(const IModelFunctionTempl< double > &func, const BinData &data, const double *p, unsigned int &nPoints)
Definition: FitUtil.h:1473
double EvaluateLogL(const IModelFunction &func, const UnBinData &data, const double *p, int iWeight, bool extended, unsigned int &nPoints, ROOT::Fit::ExecutionPolicy executionPolicy, unsigned nChunks=0)
evaluate the LogL given a model function and the data at the point x.
double SumOfContent() const
compute the total sum of the data content (sum of weights in case of weighted data set) ...
Definition: BinData.h:554
LikelihoodAux(T logv={}, T w={}, T w2={})
Definition: FitUtil.h:78
User class for performing multidimensional integration.
unsigned int NDim() const
return coordinate data dimension
Definition: FitData.h:311
const DataRange & Range() const
access to range
Definition: FitData.h:331
double Integral(const double *x1, const double *x2)
Definition: FitUtil.h:197
Double_t Sqrt(Double_t x)
Definition: TMath.h:690
Template class to wrap any member function of a class taking a double and returning a double in a 1D ...
double operator()(const double *x1, const double *x2)
Definition: FitUtil.h:203
const double * WeightsPtr(unsigned int ipoint) const
Definition: UnBinData.h:265