Logo ROOT  
Reference Guide
RHistImpl.hxx
Go to the documentation of this file.
1 /// \file ROOT/RHistImpl.hxx
2 /// \ingroup Hist ROOT7
3 /// \author Axel Naumann <axel@cern.ch>
4 /// \date 2015-03-23
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6 /// is welcome!
7 
8 /*************************************************************************
9  * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. *
10  * All rights reserved. *
11  * *
12  * For the licensing terms see $ROOTSYS/LICENSE. *
13  * For the list of contributors see $ROOTSYS/README/CREDITS. *
14  *************************************************************************/
15 
16 #ifndef ROOT7_RHistImpl
17 #define ROOT7_RHistImpl
18 
19 #include <cassert>
20 #include <cctype>
21 #include <functional>
22 #include "ROOT/RSpan.hxx"
23 #include "ROOT/RTupleApply.hxx"
24 
25 #include "ROOT/RAxis.hxx"
26 #include "ROOT/RHistBinIter.hxx"
27 #include "ROOT/RHistUtils.hxx"
28 #include "ROOT/RLogger.hxx"
29 
30 class TRootIOCtor;
31 
32 namespace ROOT {
33 namespace Experimental {
34 
35 template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
36 class RHist;
37 
38 namespace Hist {
39 /// Iterator over n dimensional axes - an array of n axis iterators.
40 template <int NDIMS>
41 using AxisIter_t = std::array<RAxisBase::const_iterator, NDIMS>;
42 /// Range over n dimensional axes - a pair of arrays of n axis iterators.
43 template <int NDIMS>
44 using AxisIterRange_t = std::array<AxisIter_t<NDIMS>, 2>;
45 
46 /// Kinds of under- and overflow handling.
47 enum class EOverflow {
48  kNoOverflow = 0x0, ///< Exclude under- and overflows
49  kUnderflow = 0x1, ///< Include underflows
50  kOverflow = 0x2, ///< Include overflows
51  kUnderOver = 0x3, ///< Include both under- and overflows
52 };
53 
55 {
56  return static_cast<int>(a) & static_cast<int>(b);
57 }
58 } // namespace Hist
59 
60 namespace Detail {
61 
62 /**
63  \class RHistImplPrecisionAgnosticBase
64  Base class for `RHistImplBase` that abstracts out the histogram's `PRECISION`.
65 
66  For operations such as painting a histogram, the `PRECISION` (type of the bin
67  content) is not relevant; painting will cast the underlying bin type to double.
68  To facilitate this, `RHistImplBase` itself inherits from the
69  `RHistImplPrecisionAgnosticBase` interface.
70  */
71 template <int DIMENSIONS>
73 public:
74  /// Type of the coordinates.
76  /// Type of the local per-axis bin indices.
77  using BinArray_t = std::array<int, DIMENSIONS>;
78  /// Range type.
80 
86 
87  /// Number of dimensions of the coordinates.
88  static constexpr int GetNDim() { return DIMENSIONS; }
89  /// Number of bins of this histogram, including all overflow and underflow
90  /// bins. Simply the product of all axes' total number of bins.
91  virtual int GetNBins() const noexcept = 0;
92  /// Number of bins of this histogram, excluding all overflow and underflow
93  /// bins. Simply the product of all axes' number of regular bins.
94  virtual int GetNBinsNoOver() const noexcept = 0;
95  /// Number of under- and overflow bins of this histogram, excluding all
96  /// regular bins.
97  virtual int GetNOverflowBins() const noexcept = 0;
98 
99  /// Get the histogram title.
100  const std::string &GetTitle() const { return fTitle; }
101 
102  /// Given the coordinate `x`, determine the index of the bin.
103  virtual int GetBinIndex(const CoordArray_t &x) const = 0;
104  /// Given the coordinate `x`, determine the index of the bin, possibly
105  /// growing axes for which `x` is out of range.
106  virtual int GetBinIndexAndGrow(const CoordArray_t &x) const = 0;
107 
108  /// Given the local per-axis bins `x`, determine the index of the bin.
109  virtual int GetBinIndexFromLocalBins(const BinArray_t &x) const = 0;
110  /// Given the index of the bin, determine the local per-axis bins `x`.
111  virtual BinArray_t GetLocalBins(int binidx) const = 0;
112 
113  /// Get the center in all dimensions of the bin with index `binidx`.
114  virtual CoordArray_t GetBinCenter(int binidx) const = 0;
115  /// Get the lower edge in all dimensions of the bin with index `binidx`.
116  virtual CoordArray_t GetBinFrom(int binidx) const = 0;
117  /// Get the upper edge in all dimensions of the bin with index `binidx`.
118  virtual CoordArray_t GetBinTo(int binidx) const = 0;
119 
120  /// Get the uncertainty of the bin with index `binidx`.
121  virtual double GetBinUncertainty(int binidx) const = 0;
122 
123  /// Whether this histogram's statistics provide storage for uncertainties, or
124  /// whether uncertainties are determined as poisson uncertainty of the content.
125  virtual bool HasBinUncertainty() const = 0;
126 
127  /// The bin content, cast to double.
128  virtual double GetBinContentAsDouble(int binidx) const = 0;
129 
130  /// Get a base-class view on axis with index `iAxis`.
131  ///
132  /// \param iAxis - index of the axis, must be `0 <= iAxis < DIMENSION`.
133  virtual const RAxisBase &GetAxis(int iAxis) const = 0;
134 
135  /// Get an `AxisIterRange_t` for the whole histogram,
136  /// excluding under- and overflow.
137  virtual AxisIterRange_t GetRange() const = 0;
138 
139 private:
140  std::string fTitle; ///< The histogram's title.
141 };
142 
143 /**
144  \class RHistImplBase
145  Interface class for `RHistImpl`.
146 
147  `RHistImpl` is templated for a specific configuration of axes. To enable access
148  through `RHist`, `RHistImpl` inherits from `RHistImplBase`, exposing only dimension
149  (`DIMENSION`) and bin type (`PRECISION`).
150  */
151 template <class DATA>
152 class RHistImplBase: public RHistImplPrecisionAgnosticBase<DATA::GetNDim()> {
153 public:
154  /// Type of the statistics (bin content, uncertainties etc).
155  using Stat_t = DATA;
156  /// Type of the coordinates.
157  using CoordArray_t = Hist::CoordArray_t<DATA::GetNDim()>;
158  /// Type of the local per-axis bin indices.
159  using BinArray_t = std::array<int, DATA::GetNDim()>;
160  /// Type of the bin content (and thus weights).
161  using Weight_t = typename DATA::Weight_t;
162 
163  /// Type of the `Fill(x, w)` function
165 
166 private:
167  /// The histogram's bin content, uncertainties etc.
169 
170 public:
171  RHistImplBase() = default;
172  RHistImplBase(size_t numBins, size_t numOverflowBins): fStatistics(numBins, numOverflowBins) {}
173  RHistImplBase(std::string_view title, size_t numBins, size_t numOverflowBins)
174  : RHistImplPrecisionAgnosticBase<DATA::GetNDim()>(title), fStatistics(numBins, numOverflowBins)
175  {}
176  RHistImplBase(const RHistImplBase &) = default;
178 
179  virtual std::unique_ptr<RHistImplBase> Clone() const = 0;
180 
181  /// Interface function to fill a vector or array of coordinates with
182  /// corresponding weights.
183  /// \note the size of `xN` and `weightN` must be the same!
184  virtual void FillN(const std::span<const CoordArray_t> xN, const std::span<const Weight_t> weightN) = 0;
185 
186  /// Interface function to fill a vector or array of coordinates.
187  virtual void FillN(const std::span<const CoordArray_t> xN) = 0;
188 
189  /// Retrieve the pointer to the overridden `Fill(x, w)` function.
190  virtual FillFunc_t GetFillFunc() const = 0;
191 
192  /// Get the bin content (sum of weights) for the bin at coordinate `x`.
193  virtual Weight_t GetBinContent(const CoordArray_t &x) const = 0;
194 
196 
197  /// Get the bin uncertainty for the bin at coordinate x.
198  virtual double GetBinUncertainty(const CoordArray_t &x) const = 0;
199 
200  /// Get the number of bins in this histogram, including possible under- and
201  /// overflow bins.
202  int GetNBins() const noexcept final { return fStatistics.size(); }
203 
204  /// Get the number of bins in this histogram, excluding possible under- and
205  /// overflow bins.
206  int GetNBinsNoOver() const noexcept final { return fStatistics.sizeNoOver(); }
207 
208  /// Get the number of under- and overflow bins of this histogram, excluding all
209  /// regular bins.
210  int GetNOverflowBins() const noexcept final { return fStatistics.sizeUnderOver(); }
211 
212  /// Get the bin content (sum of weights) for bin index `binidx`.
213  Weight_t GetBinContent(int binidx) const
214  {
215  assert(binidx != 0);
216  return fStatistics[binidx];
217  }
218 
219  /// Get the bin content (sum of weights) for bin index `binidx` (non-const).
220  Weight_t &GetBinContent(int binidx)
221  {
222  assert(binidx != 0);
223  return fStatistics[binidx];
224  }
225 
226  /// Const access to statistics.
227  const Stat_t &GetStat() const noexcept { return fStatistics; }
228 
229  /// Non-const access to statistics.
230  Stat_t &GetStat() noexcept { return fStatistics; }
231 
232  /// Get the bin content (sum of weights) for bin index `binidx`, cast to
233  /// `double`.
234  double GetBinContentAsDouble(int binidx) const final { return (double)GetBinContent(binidx); }
235 
236  /// Add `w` to the bin at index `bin`.
237  void AddBinContent(int binidx, Weight_t w)
238  {
239  assert(binidx != 0);
240  fStatistics[binidx] += w;
241  }
242 };
243 } // namespace Detail
244 
245 namespace Internal {
246 /** \name Histogram traits
247  Helper traits for histogram operations.
248  */
249 ///\{
250 
251 /// Specifies if the wanted result is the bin's lower edge, center or higher edge.
252 enum class EBinCoord {
253  kBinFrom, ///< Get the lower bin edge
254  kBinCenter, ///< Get the bin center
255  kBinTo ///< Get the bin high edge
256 };
257 
258 /// Status of FindBin(x) and FindAdjustedBin(x)
259 enum class EFindStatus {
260  kCanGrow, ///< The coordinate could fit after growing the axis
261  kValid ///< The returned bin index is valid
262 };
263 
264 /// \name Axis tuple operations
265 /// Template operations on axis tuple.
266 ///@{
267 
268 /// Recursively gets the total number of bins in whole hist, excluding under- and overflow.
269 /// Each call gets the current axis' number of bins (excluding under- and overflow) multiplied
270 /// by that of the next axis.
271 template <int IDX, class AXISTUPLE>
272 struct RGetNBinsNoOverCount;
273 
274 template <class AXES>
275 struct RGetNBinsNoOverCount<0, AXES> {
276  int operator()(const AXES &axes) const { return std::get<0>(axes).GetNBinsNoOver(); }
277 };
278 
279 template <int I, class AXES>
281  int operator()(const AXES &axes) const { return std::get<I>(axes).GetNBinsNoOver() * RGetNBinsNoOverCount<I - 1, AXES>()(axes); }
282 };
283 
284 /// Get the number of bins in whole hist, excluding under- and overflow.
285 template <class... AXISCONFIG>
286 int GetNBinsNoOverFromAxes(AXISCONFIG... axisArgs)
287 {
288  using axesTuple = std::tuple<AXISCONFIG...>;
289  return RGetNBinsNoOverCount<sizeof...(AXISCONFIG) - 1, axesTuple>()(axesTuple{axisArgs...});
290 }
291 
292 /// Recursively gets the total number of bins in whole hist, including under- and overflow.
293 /// Each call gets the current axis' number of bins (including under- and overflow) multiplied
294 /// by that of the next axis.
295 template <int IDX, class AXISTUPLE>
296 struct RGetNBinsCount;
297 
298 template <class AXES>
299 struct RGetNBinsCount<0, AXES> {
300  int operator()(const AXES &axes) const { return std::get<0>(axes).GetNBins(); }
301 };
302 
303 template <int I, class AXES>
305  int operator()(const AXES &axes) const { return std::get<I>(axes).GetNBins() * RGetNBinsCount<I - 1, AXES>()(axes); }
306 };
307 
308 /// Get the number of bins in whole hist, including under- and overflow.
309 template <class... AXISCONFIG>
310 int GetNBinsFromAxes(AXISCONFIG... axisArgs)
311 {
312  using axesTuple = std::tuple<AXISCONFIG...>;
313  return RGetNBinsCount<sizeof...(AXISCONFIG) - 1, axesTuple>()(axesTuple{axisArgs...});
314 }
315 
316 /// Get the number of under- and overflow bins in whole hist, excluding regular bins.
317 template <class... AXISCONFIG>
318 int GetNOverflowBinsFromAxes(AXISCONFIG... axisArgs)
319 {
320  using axesTuple = std::tuple<AXISCONFIG...>;
321  return RGetNBinsCount<sizeof...(AXISCONFIG) - 1, axesTuple>()(axesTuple{axisArgs...}) - RGetNBinsNoOverCount<sizeof...(AXISCONFIG) - 1, axesTuple>()(axesTuple{axisArgs...});
322 }
323 
324 /// Recursively fills the ranges of all axes, excluding under- and overflow.
325 /// Each call fills `range` with `begin()` and `end()` of the current axis, excluding
326 /// under- and overflow.
327 template <int I, class AXES>
328 struct RFillIterRange;
329 
330 template <class AXES>
331 struct RFillIterRange<-1, AXES> {
332  void operator()(Hist::AxisIterRange_t<std::tuple_size<AXES>::value> & /*range*/, const AXES & /*axes*/) const
333  {}
334 };
335 
336 template <int I, class AXES>
338  void operator()(Hist::AxisIterRange_t<std::tuple_size<AXES>::value> &range, const AXES &axes) const
339  {
340  range[0][I] = std::get<I>(axes).begin();
341  range[1][I] = std::get<I>(axes).end();
342  RFillIterRange<I - 1, AXES>()(range, axes);
343  }
344 };
345 
346 /// Recursively gets the number of regular bins just before the current dimension.
347 /// Each call gets the previous axis' number of regular bins multiplied
348 /// by the number of regular bins before the previous axis.
349 template <int I, int NDIMS, typename BINS, class AXES>
350 struct RGetNRegularBinsBefore;
351 
352 template <int NDIMS, typename BINS, class AXES>
353 struct RGetNRegularBinsBefore<-1, NDIMS, BINS, AXES> {
354  void operator()(BINS &/*binSizes*/, const AXES &/*axes*/) const
355  {}
356 };
357 
358 template <int I, int NDIMS, typename BINS, class AXES>
360  void operator()(BINS &binSizes, const AXES &axes) const
361  {
362  constexpr const int thisAxis = NDIMS - I - 1;
363  binSizes[thisAxis] = binSizes[thisAxis-1] * std::get<thisAxis-1>(axes).GetNBinsNoOver();
364  RGetNRegularBinsBefore<I - 1, NDIMS, BINS, AXES>()(binSizes, axes);
365  }
366 };
367 
368 /// Recursively gets the total number of regular bins before the current dimension,
369 /// when computing a global bin that is in under- or overflow in at least one
370 /// dimension. That global bin's local per-axis bin indices are passed through
371 /// the `localBins` parameter. These `localBins` were translated to 0-based bins,
372 /// which is more convenient for some operations and which are the `virtualBins`
373 /// parameter.
374 /// Each call gets the current axis' number of regular bins before the global_bin
375 /// in the current dimension multiplied by the number of regular bins before the
376 /// current axis.
377 /// If the global_bin is in under- or overflow in the current dimension (local bin),
378 /// there is no need to process further.
379 
380 // - We want to know how many regular bins lie before the current overflow bin in the
381 // histogram's global binning order (which so far I thought was row-major, but now I'm
382 // not sure, maybe it's actually column-major... it doesn't matter, we don't need to spell out what is the global binning order anyway).
383 
384 template <int I, int NDIMS, typename BINS, class AXES>
385 struct RComputeGlobalBin;
386 
387 template <int NDIMS, typename BINS, class AXES>
388 struct RComputeGlobalBin<-1, NDIMS, BINS, AXES> {
389  int operator()(int total_regular_bins_before, const AXES &/*axes*/, const BINS &/*virtualBins*/, const BINS &/*binSizes*/, const BINS &/*localBins*/) const
390  {
391  return total_regular_bins_before;
392  }
393 };
394 
395 template <int I, int NDIMS, typename BINS, class AXES>
397  int operator()(int total_regular_bins_before, const AXES &axes, const BINS &virtualBins, const BINS &binSizes, const BINS &localBins) const
398  {
399  // We can tell how many regular bins lie before us on this axis,
400  // accounting for the underflow bin of this axis if it has one.
401  const int num_underflow_bins = static_cast<int>(!std::get<I>(axes).CanGrow());
402  const int num_regular_bins_before =
403  std::max(virtualBins[I] - num_underflow_bins, 0);
404  total_regular_bins_before += num_regular_bins_before * binSizes[I];
405 
406  // If we are on an overflow or underflow bin on this axis, we know that
407  // we don't need to look at the remaining axes. Projecting on those
408  // dimensions would only take us into an hyperplane of over/underflow
409  // bins for the current axis, and we know that by construction there
410  // will be no regular bins in there.
411  if (localBins[I] < 1)
412  return total_regular_bins_before;
413 
414  return RComputeGlobalBin<I - 1, NDIMS, BINS, AXES>()(total_regular_bins_before, axes, virtualBins, binSizes, localBins);
415  }
416 };
417 
418 /// Recursively compute some quantities needed for `ComputeLocalBins`, namely
419 /// the total number of bins per hyperplane (overflow and regular) and the
420 /// number of regular bins per hyperplane on the hyperplanes that have them.
421 template <int I, int NDIMS, class AXES>
422 struct RComputeLocalBinsInitialisation;
423 
424 template <int NDIMS, class AXES>
425 struct RComputeLocalBinsInitialisation<0, NDIMS, AXES> {
426  void operator()(std::array<int, NDIMS-1> /* bins_per_hyperplane */, std::array<int, NDIMS-1> /* regular_bins_per_hyperplane */, const AXES & /*axes*/) const
427  {}
428 };
429 
430 template <int I, int NDIMS, class AXES>
432  void operator()(std::array<int, NDIMS-1>& bins_per_hyperplane, std::array<int, NDIMS-1>& regular_bins_per_hyperplane, const AXES &axes) const
433  {
434  constexpr const int thisAxis = NDIMS - I - 1;
435  bins_per_hyperplane[thisAxis] = Internal::RGetNBinsCount<thisAxis, AXES>()(axes);
436  regular_bins_per_hyperplane[thisAxis] = Internal::RGetNBinsNoOverCount<thisAxis, AXES>()(axes);
437  RComputeLocalBinsInitialisation<I - 1, NDIMS, AXES>()(bins_per_hyperplane, regular_bins_per_hyperplane, axes);
438  }
439 };
440 
441 /// Recursively computes the number of regular bins before the current dimension,
442 /// as well as the number of under- and overflow bins left to account for, after
443 /// the current dimension. If the latter is equal to 0, there is no need to process
444 /// further.
445 /// It is computing local bins that are in under- or overflow in at least one
446 /// dimension.
447 /// Starting at the highest dimension, it examines how many full hyperplanes of
448 /// regular bins lie before, then projects on the remaining dimensions.
449 
450 template <int I, int NDIMS, class AXES>
451 struct RComputeLocalBins;
452 
453 template <int NDIMS, class AXES>
454 struct RComputeLocalBins<0, NDIMS, AXES> {
455  void operator()(const AXES &/*axes*/, int &/*unprocessed_previous_overflow_bin*/,
456  int &/*num_regular_bins_before*/, std::array<int, NDIMS-1> /* bins_per_hyperplane */,
457  std::array<int, NDIMS-1> /* regular_bins_per_hyperplane */, int /* curr_bins_per_hyperplane */,
458  int /* curr_regular_bins_per_hyperplane */) const
459  {}
460 };
461 
462 template <int I, int NDIMS, class AXES>
464  void operator()(const AXES &axes, int &unprocessed_previous_overflow_bin,
465  int &num_regular_bins_before, std::array<int, NDIMS-1> bins_per_hyperplane,
466  std::array<int, NDIMS-1> regular_bins_per_hyperplane, int curr_bins_per_hyperplane,
467  int curr_regular_bins_per_hyperplane) const
468  {
469  // Let's start by computing the contribution of the underflow
470  // hyperplane (if any), in which we know there will be no regular bins
471  const int num_underflow_hyperplanes =
472  static_cast<int>(!std::get<I>(axes).CanGrow());
473  const int bins_in_underflow_hyperplane =
474  num_underflow_hyperplanes * bins_per_hyperplane[I-1];
475 
476  // Next, from the total number of bins per hyperplane and the number of
477  // regular bins per hyperplane that has them, we deduce the number of
478  // overflow bins per hyperplane that has regular bins.
479  const int overflow_bins_per_regular_hyperplane =
480  bins_per_hyperplane[I-1] - regular_bins_per_hyperplane[I-1];
481 
482  // This allows us to answer a key question: are there any under/overflow
483  // bins on the hyperplanes that have regular bins? It may not be the
484  // case if all of their axes are growable, and thus don't have overflow bins.
485  if (overflow_bins_per_regular_hyperplane != 0) {
486  // If so, we start by cutting off the contribution of the underflow
487  // and overflow hyperplanes, to focus specifically on regular bins.
488  const int overflow_bins_in_regular_hyperplanes =
489  std::min(
490  std::max(
491  unprocessed_previous_overflow_bin
492  - bins_in_underflow_hyperplane,
493  0
494  ),
495  overflow_bins_per_regular_hyperplane
496  * std::get<I>(axes).GetNBinsNoOver()
497  );
498 
499  // We count how many _complete_ "regular" hyperplanes that leaves
500  // before us, and account for those in our regular bin count.
501  const int num_regular_hyperplanes_before =
502  overflow_bins_in_regular_hyperplanes
503  / overflow_bins_per_regular_hyperplane;
504  num_regular_bins_before +=
505  num_regular_hyperplanes_before
506  * regular_bins_per_hyperplane[I-1];
507 
508  // This only leaves the _current_ hyperplane as a possible source of
509  // more regular bins that we haven't accounted for yet. We'll take
510  // those into account while processing previous dimensions.
511  unprocessed_previous_overflow_bin =
512  overflow_bins_in_regular_hyperplanes
513  % overflow_bins_per_regular_hyperplane;
514  } else {
515  // If there are no overflow bins in regular hyperplane, then the
516  // rule changes: observing _one_ overflow bin after the underflow
517  // hyperplane means that _all_ regular hyperplanes on this axis are
518  // already before us.
519  if (unprocessed_previous_overflow_bin >= bins_in_underflow_hyperplane) {
520  num_regular_bins_before +=
521  std::get<I>(axes).GetNBinsNoOver()
522  * regular_bins_per_hyperplane[I-1];
523  }
524 
525  // In this case, we're done, because the current bin may only lie
526  // in the underflow or underflow hyperplane of this axis. Which
527  // means that there are no further regular bins to be accounted for
528  // in the current hyperplane.
529  unprocessed_previous_overflow_bin = 0;
530  }
531 
532  // No need to continue this loop if we've taken into account all
533  // overflow bins that were associated with regular bins.
534  if (unprocessed_previous_overflow_bin == 0)
535  return;
536 
537  return Internal::RComputeLocalBins<I - 1, NDIMS, AXES>()
538  (axes, unprocessed_previous_overflow_bin, num_regular_bins_before, bins_per_hyperplane,
539  regular_bins_per_hyperplane, curr_bins_per_hyperplane, curr_regular_bins_per_hyperplane);
540  }
541 };
542 
543 /// Recursively computes zero-based local bin indices, given...
544 ///
545 /// - A zero-based global bin index
546 /// - The number of considered bins on each axis (can be either `GetNBinsNoOver`
547 /// or `GetNBins` depending on what you are trying to do)
548 /// - A policy of treating all bins as regular (i.e. no negative indices)
549 template <int I, int NDIMS, typename BINS, class AXES, class BINTYPE>
550 struct RComputeLocalBinsRaw;
551 
552 template <int NDIMS, typename BINS, class AXES, class BINTYPE>
553 struct RComputeLocalBinsRaw<-1, NDIMS, BINS, AXES, BINTYPE> {
554  void operator()(BINS & /*virtualBins*/, const AXES & /*axes*/, int /*zeroBasedGlobalBin*/, BINTYPE /*GetNBinType*/) const
555  {}
556 };
557 
558 template <int I, int NDIMS, typename BINS, class AXES, class BINTYPE>
560  void operator()(BINS &virtualBins, const AXES &axes, int zeroBasedGlobalBin, BINTYPE GetNBinType) const
561  {
562  constexpr const int thisAxis = NDIMS - I - 1;
563  virtualBins[thisAxis] = zeroBasedGlobalBin % (std::get<thisAxis>(axes).*GetNBinType)();
564  RComputeLocalBinsRaw<I - 1, NDIMS, BINS, AXES, BINTYPE>()(virtualBins, axes, zeroBasedGlobalBin / (std::get<thisAxis>(axes).*GetNBinType)(), GetNBinType);
565  }
566 };
567 
568 /// Recursively computes a zero-based global bin index, given...
569 ///
570 /// - A set of zero-based per-axis bin indices
571 /// - The number of considered bins on each axis (can be either `GetNBinsNoOver`
572 /// or `GetNBins` depending on what you are trying to do)
573 /// - A policy of treating all bins qs regular (i.e. no negative indices)
574 template <int I, int NDIMS, typename BINS, class AXES, class BINTYPE>
575 struct RComputeGlobalBinRaw;
576 
577 template <int NDIMS, typename BINS, class AXES, class BINTYPE>
578 struct RComputeGlobalBinRaw<-1, NDIMS, BINS, AXES, BINTYPE> {
579  int operator()(int globalVirtualBin, const AXES & /*axes*/, const BINS & /*zeroBasedLocalBins*/, int /*binSize*/, BINTYPE /*GetNBinType*/) const
580  {
581  return globalVirtualBin;
582  }
583 };
584 
585 template <int I, int NDIMS, typename BINS, class AXES, class BINTYPE>
587  int operator()(int globalVirtualBin, const AXES &axes, const BINS &zeroBasedLocalBins, int binSize, BINTYPE GetNBinType) const
588  {
589  constexpr const int thisAxis = NDIMS - I - 1;
590  globalVirtualBin += zeroBasedLocalBins[thisAxis] * binSize;
591  binSize *= (std::get<thisAxis>(axes).*GetNBinType)();
592  return Internal::RComputeGlobalBinRaw<I - 1, NDIMS, BINS, AXES, BINTYPE>()(globalVirtualBin, axes, zeroBasedLocalBins, binSize, GetNBinType);
593  }
594 };
595 
596 /// Recursively converts zero-based virtual bins where the underflow bin
597 /// has index `0` and the overflow bin has index `N+1` where `N` is the axis'
598 /// number of regular bins, to the standard `kUnderflowBin`/`kOverflowBin` for under/overflow
599 /// bin indexing convention.
600 ///
601 /// For growable axes, must add 1 to go back to standard indices as their virtual
602 /// indexing convention is also 0-based, with zero designating the first regular bin.
603 template <int I, int NDIMS, typename BINS, class AXES>
604 struct RVirtualBinsToLocalBins;
605 
606 template <int NDIMS, typename BINS, class AXES>
607 struct RVirtualBinsToLocalBins<-1, NDIMS, BINS, AXES> {
608  void operator()(BINS & /*localBins*/, const AXES & /*axes*/, const BINS & /*virtualBins*/) const
609  {}
610 };
611 
612 template <int I, int NDIMS, typename BINS, class AXES>
614  void operator()(BINS &localBins, const AXES &axes, const BINS &virtualBins) const
615  {
616  constexpr const int thisAxis = NDIMS - I - 1;
617  if ((!std::get<thisAxis>(axes).CanGrow()) && (virtualBins[thisAxis] == 0)) {
618  localBins[thisAxis] = RAxisBase::kUnderflowBin;
619  } else if ((!std::get<thisAxis>(axes).CanGrow()) && (virtualBins[thisAxis] == (std::get<thisAxis>(axes).GetNBins() - 1))) {
620  localBins[thisAxis] = RAxisBase::kOverflowBin;
621  } else {
622  const int regular_bin_offset = -static_cast<int>(std::get<thisAxis>(axes).CanGrow());
623  localBins[thisAxis] = virtualBins[thisAxis] - regular_bin_offset;
624  }
625  RVirtualBinsToLocalBins<I - 1, NDIMS, BINS, AXES>()(localBins, axes, virtualBins);
626  }
627 };
628 
629 /// Recursively converts local axis bins from the standard `kUnderflowBin`/`kOverflowBin` for under/overflow
630 /// bin indexing convention, to a "virtual bin" convention where the underflow bin
631 /// has index `0` and the overflow bin has index `N+1` where `N` is the axis'
632 /// number of regular bins.
633 ///
634 /// For growable axes, subtract 1 from regular indices so that the indexing
635 /// convention remains zero-based (this means that there will be no "holes" in
636 /// global binning, which matters more than the choice of regular index base)
637 template <int I, int NDIMS, typename BINS, class AXES>
638 struct RLocalBinsToVirtualBins;
639 
640 template <int NDIMS, typename BINS, class AXES>
641 struct RLocalBinsToVirtualBins<-1, NDIMS, BINS, AXES> {
642  void operator()(BINS & /*virtualBins*/, const AXES & /*axes*/, const BINS & /*localBins*/) const
643  {}
644 };
645 
646 template <int I, int NDIMS, typename BINS, class AXES>
648  void operator()(BINS &virtualBins, const AXES &axes, const BINS &localBins) const
649  {
650  constexpr const int thisAxis = NDIMS - I - 1;
651  switch (localBins[thisAxis]) {
653  virtualBins[thisAxis] = 0; break;
655  virtualBins[thisAxis] = std::get<thisAxis>(axes).GetNBins() - 1; break;
656  default:
657  virtualBins[thisAxis] = localBins[thisAxis] - static_cast<int>(std::get<thisAxis>(axes).CanGrow());
658  }
659  RLocalBinsToVirtualBins<I - 1, NDIMS, BINS, AXES>()(virtualBins, axes, localBins);
660  }
661 };
662 
663 /// Find the per-axis local bin indices associated with a certain set of coordinates.
664 template <int I, int NDIMS, typename BINS, typename COORD, class AXES>
665 struct RFindLocalBins;
666 
667 template <int NDIMS, typename BINS, typename COORD, class AXES>
668 struct RFindLocalBins<-1, NDIMS, BINS, COORD, AXES> {
669  void operator()(BINS & /*localBins*/, const AXES & /*axes*/, const COORD & /*coords*/) const
670  {}
671 };
672 
673 template <int I, int NDIMS, typename BINS, typename COORD, class AXES>
675  void operator()(BINS &localBins, const AXES &axes, const COORD &coords) const
676  {
677  constexpr const int thisAxis = NDIMS - I - 1;
678  localBins[thisAxis] = std::get<thisAxis>(axes).FindBin(coords[thisAxis]);
679  RFindLocalBins<I - 1, NDIMS, BINS, COORD, AXES>()(localBins, axes, coords);
680  }
681 };
682 
683 /// Recursively converts local axis bins from the standard `kUnderflowBin`/`kOverflowBin` for
684 /// under/overflow bin indexing convention, to the corresponding bin coordinates.
685 template <int I, int NDIMS, typename BINS, typename COORD, class AXES>
686 struct RLocalBinsToCoords;
687 
688 template <int NDIMS, typename BINS, typename COORD, class AXES>
689 struct RLocalBinsToCoords<-1, NDIMS, BINS, COORD, AXES> {
690  void operator()(COORD & /*coords*/, const AXES & /*axes*/, const BINS & /*localBins*/, EBinCoord /*kind*/) const
691  {}
692 };
693 
694 template <int I, int NDIMS, typename BINS, typename COORD, class AXES>
696  void operator()(COORD &coords, const AXES &axes, const BINS &localBins, EBinCoord kind) const
697  {
698  constexpr const int thisAxis = NDIMS - I - 1;
699  int axisbin = localBins[thisAxis];
700  switch (kind) {
701  case EBinCoord::kBinFrom: coords[thisAxis] = std::get<thisAxis>(axes).GetBinFrom(axisbin); break;
702  case EBinCoord::kBinCenter: coords[thisAxis] = std::get<thisAxis>(axes).GetBinCenter(axisbin); break;
703  case EBinCoord::kBinTo: coords[thisAxis] = std::get<thisAxis>(axes).GetBinTo(axisbin); break;
704  }
705  RLocalBinsToCoords<I - 1, NDIMS, BINS, COORD, AXES>()(coords, axes, localBins, kind);
706  }
707 };
708 
709 template <class... AXISCONFIG>
710 static std::array<const RAxisBase *, sizeof...(AXISCONFIG)> GetAxisView(const AXISCONFIG &... axes) noexcept
711 {
712  std::array<const RAxisBase *, sizeof...(AXISCONFIG)> axisViews{{&axes...}};
713  return axisViews;
714 }
715 
716 ///\}
717 } // namespace Internal
718 
719 namespace Detail {
720 
721 template <class DATA, class... AXISCONFIG>
722 class RHistImpl final: public RHistImplBase<DATA> {
723  static_assert(sizeof...(AXISCONFIG) == DATA::GetNDim(), "Number of axes must equal histogram dimension");
724 
725  friend typename DATA::Hist_t;
726 
727 public:
731  using Weight_t = typename ImplBase_t::Weight_t;
732  using typename ImplBase_t::FillFunc_t;
733  template <int NDIMS = DATA::GetNDim()>
735 
736 private:
737  std::tuple<AXISCONFIG...> fAxes; ///< The histogram's axes
738 
739 public:
741  RHistImpl(AXISCONFIG... axisArgs);
742  RHistImpl(std::string_view title, AXISCONFIG... axisArgs);
743 
744  std::unique_ptr<ImplBase_t> Clone() const override {
745  return std::unique_ptr<ImplBase_t>(new RHistImpl(*this));
746  }
747 
748  /// Retrieve the fill function for this histogram implementation, to prevent
749  /// the virtual function call for high-frequency fills.
750  FillFunc_t GetFillFunc() const final {
751  return (FillFunc_t)&RHistImpl::Fill;
752  }
753 
754  /// Get the axes of this histogram.
755  const std::tuple<AXISCONFIG...> &GetAxes() const { return fAxes; }
756 
757  /// Normalized axes access, converting from actual axis type to base class.
758  const RAxisBase &GetAxis(int iAxis) const final { return *std::apply(Internal::GetAxisView<AXISCONFIG...>, fAxes)[iAxis]; }
759 
760  /// Computes a zero-based global bin index, given...
761  ///
762  /// - A set of zero-based per-axis bin indices
763  /// - The number of considered bins on each axis (can be either `GetNBinsNoOver`
764  /// or `GetNBins` depending on what you are trying to do)
765  /// - A policy of treating all bins qs regular (i.e. no negative indices)
766  template <int NDIMS, typename BINTYPE>
767  int ComputeGlobalBinRaw(const BinArray_t& zeroBasedLocalBins, BINTYPE GetNBinType) const {
768  int result = 0;
769  int binSize = 1;
770  return Internal::RComputeGlobalBinRaw<NDIMS - 1, NDIMS, BinArray_t, decltype(fAxes), BINTYPE>()(result, fAxes, zeroBasedLocalBins, binSize, GetNBinType);
771  }
772 
773  /// Computes zero-based local bin indices, given...
774  ///
775  /// - A zero-based global bin index
776  /// - The number of considered bins on each axis (can be either `GetNBinsNoOver`
777  /// or `GetNBins` depending on what you are trying to do)
778  /// - A policy of treating all bins as regular (i.e. no negative indices)
779  template <int NDIMS, typename BINTYPE>
780  BinArray_t ComputeLocalBinsRaw(int zeroBasedGlobalBin, BINTYPE GetNBinType) const {
781  BinArray_t result;
782  Internal::RComputeLocalBinsRaw<NDIMS - 1, NDIMS, BinArray_t, decltype(fAxes), BINTYPE>()(result, fAxes, zeroBasedGlobalBin, GetNBinType);
783  return result;
784  }
785 
786  /// Converts local axis bins from the standard `kUnderflowBin`/`kOverflowBin` for under/overflow
787  /// bin indexing convention, to a "virtual bin" convention where the underflow bin
788  /// has index `0` and the overflow bin has index `N+1` where `N` is the axis'
789  /// number of regular bins.
790  template <int NDIMS>
791  BinArray_t LocalBinsToVirtualBins(const BinArray_t& localBins) const {
792  BinArray_t virtualBins;
793  Internal::RLocalBinsToVirtualBins<NDIMS - 1, NDIMS, BinArray_t, decltype(fAxes)>()(virtualBins, fAxes, localBins);
794  return virtualBins;
795  }
796 
797  /// Converts zero-based virtual bins where the underflow bin has
798  /// index `0` and the overflow bin has index `N+1` where `N` is the axis'
799  /// number of regular bins, to the standard `kUnderflowBin`/`kOverflowBin` for under/overflow
800  /// bin indexing convention.
801  template <int NDIMS>
802  BinArray_t VirtualBinsToLocalBins(const BinArray_t& virtualBins) const {
803  BinArray_t localBins = {};
804  Internal::RVirtualBinsToLocalBins<NDIMS - 1, NDIMS, BinArray_t, decltype(fAxes)>()(localBins, fAxes, virtualBins);
805  return localBins;
806  }
807 
808  /// Computes the global index of a certain bin on an `NDIMS`-dimensional histogram,
809  /// knowing the local per-axis bin indices as returned by calling `FindBin()` on each axis.
810  template <int NDIMS>
811  int ComputeGlobalBin(BinArray_t& local_bins) const {
812  // Get regular bins out of the way
813  if (std::all_of(local_bins.cbegin(), local_bins.cend(),
814  [](int bin) { return bin >= 1; })) {
815  for (int bin = 0; bin < NDIMS; bin++)
816  local_bins[bin] -= 1;
817  return ComputeGlobalBinRaw<NDIMS>(local_bins, &ROOT::Experimental::RAxisBase::GetNBinsNoOver) + 1;
818  }
819 
820  // Convert bin indices to a zero-based coordinate system where the underflow
821  // bin (if any) has coordinate 0 and the overflow bin (if any) has
822  // coordinate N-1, where N is the axis' total number of bins.
823  BinArray_t virtual_bins = LocalBinsToVirtualBins<NDIMS>(local_bins);
824 
825  // Deduce what the global bin index would be in this coordinate system that
826  // unifies regular and overflow bins.
827  const int global_virtual_bin = ComputeGlobalBinRaw<NDIMS>(virtual_bins, &ROOT::Experimental::RAxisBase::GetNBins);
828 
829  // Move to 1-based and negative indexing
830  const int neg_1based_virtual_bin = -global_virtual_bin - 1;
831 
832  // At this point, we have an index that represents a count of all bins, both
833  // regular and overflow, that are located before the current bin when
834  // enumerating histogram bins in row-major order.
835  //
836  // We will next count the number of _regular_ bins which are located before
837  // the current bin, and by removing this offset from the above index, we
838  // will get a count of overflow bins that are located before the current bin
839  // in row-major order. Which is what we want as our overflow bin index.
840  //
841  int total_regular_bins_before = 0;
842 
843  // First, we need to know how many regular bins we leave behind us for each
844  // step on each axis, assuming that the bin from which we come was regular.
845  //
846  // If mathematically inclined, you can also think of this as the size of an
847  // hyperplane of regular bins when projecting on lower-numbered dimensions.
848  // See the docs of ComputeLocalBins for more on this worldview.
849  //
850  BinArray_t bin_sizes;
851  bin_sizes[0] = 1;
852  Internal::RGetNRegularBinsBefore<NDIMS - 2, NDIMS, BinArray_t, decltype(fAxes)>()(bin_sizes, fAxes);
853 
854  // With that, we can deduce how many regular bins lie before us.
855  total_regular_bins_before = Internal::RComputeGlobalBin<NDIMS - 1, NDIMS, BinArray_t, decltype(fAxes)>()
856  (total_regular_bins_before, fAxes, virtual_bins, bin_sizes, local_bins);
857 
858  // Now that we know how many bins lie before us, and how many of those are
859  // regular bins, we can trivially deduce how many overflow bins lie before
860  // us, and emit that as our global overflow bin index.
861  return neg_1based_virtual_bin + total_regular_bins_before;
862  }
863 
864  /// Computes the local per-axis bin indices of a certain bin on an `NDIMS`-dimensional histogram,
865  /// knowing the global histogram bin index.
866  template <int NDIMS>
867  BinArray_t ComputeLocalBins(int global_bin) const {
868  // Get regular bins out of the way
869  if (global_bin >= 1) {
870  BinArray_t computed_bins = ComputeLocalBinsRaw<NDIMS>(global_bin - 1, &ROOT::Experimental::RAxisBase::GetNBinsNoOver);
871  for (int bin = 0; bin < NDIMS; ++bin)
872  computed_bins[bin] += 1;
873  return computed_bins;
874  }
875 
876  // Convert our negative index to something positive and 0-based, as that is
877  // more convenient to work with. Note, however, that this is _not_
878  // equivalent to the virtual_bin that we had before, because what we have
879  // here is a count of overflow bins, not of all bins...
880  const int corrected_virtual_overflow_bin = -global_bin - 1;
881 
882  // ...so we need to retrieve and bring back the regular bin count, and this
883  // is where the fun begins.
884  //
885  // The main difficulty is that the number of regular bins is not fixed as
886  // one slides along a histogram axis. Using a 2D binning case as a simple
887  // motivating example...
888  //
889  // -1 -2 -3 -4 <- No regular bins on the underflow line of axis 1
890  // -5 1 2 -6 <- Some of them on middle lines of axis 1
891  // -7 3 4 -8
892  // -9 -10 -11 -12 <- No regular bins on the overflow line of axis 1
893  //
894  // As we go to higher dimensions, the geometry becomes more complex, but
895  // if we replace "line" with "plane", we get a similar picture in 3D when we
896  // slide along axis 2:
897  //
898  // No regular bins on the Some of them on the No regular bins again
899  // UF plane of axis 2 regular planes of ax.2 on the OF plane of ax.2
900  //
901  // -1 -2 -3 -4 -17 -18 -19 -20 -29 -30 -31 -32
902  // -5 -6 -7 -8 -21 1 2 -22 -33 -34 -35 -36
903  // -9 -10 -11 -12 -23 3 4 -24 -37 -37 -39 -40
904  // -13 -14 -15 -16 -25 -26 -27 -28 -41 -42 -43 -44
905  //
906  // We can generalize this to N dimensions by saying that as we slide along
907  // the last axis of an N-d histogram, we see an hyperplane full of overflow
908  // bins, then some hyperplanes with regular bins in the "middle" surrounded
909  // by overflow bins, then a last hyperplane full of overflow bins.
910  //
911  // From this, we can devise a recursive algorithm to recover the number of
912  // regular bins before the overflow bin we're currently looking at:
913  //
914  // - Start by processing the last histogram axis.
915  // - Ignore the first and last hyperplane on this axis, which only contain
916  // underflow and overflow bins respectively.
917  // - Count how many complete hyperplanes of regular bins lie before us on
918  // this axis, which we can do indirectly in our overflow bin based
919  // reasoning by computing the perimeter of the regular region and dividing
920  // our "regular" overflow bin count by that amount.
921  // - Now we counted previous hyperplanes on this last histogram axis, but
922  // we need to process the hyperplane that our bin is located in, if any.
923  // * For this, we reduce our overflow bin count to a count of
924  // _unaccounted_ overflow bins in the current hyperplane...
925  // * ...which allows us to recursively continue the computation by
926  // processing the next (well, previous) histogram axis in the context
927  // of this hyperplane, in the same manner as above.
928  //
929  // Alright, now that the general plan is sorted out, let's compute some
930  // quantities that we are going to need, namely the total number of bins per
931  // hyperplane (overflow and regular) and the number of regular bins per
932  // hyperplane on the hyperplanes that have them.
933  //
934  std::array<int, NDIMS - 1> bins_per_hyperplane;
935  std::array<int, NDIMS - 1> regular_bins_per_hyperplane;
936  Internal::RComputeLocalBinsInitialisation<NDIMS - 1, NDIMS, decltype(fAxes)>()(bins_per_hyperplane, regular_bins_per_hyperplane, fAxes);
937 
938  int curr_bins_per_hyperplane = Internal::RGetNBinsCount<NDIMS - 1, decltype(fAxes)>()(fAxes);
939  int curr_regular_bins_per_hyperplane = Internal::RGetNBinsNoOverCount<NDIMS - 1, decltype(fAxes)>()(fAxes);
940 
941  // Given that, we examine each axis, starting from the last one.
942  int unprocessed_previous_overflow_bin = corrected_virtual_overflow_bin;
943  int num_regular_bins_before = 0;
944  Internal::RComputeLocalBins<NDIMS - 1, NDIMS, decltype(fAxes)>()
945  (fAxes, unprocessed_previous_overflow_bin, num_regular_bins_before, bins_per_hyperplane,
946  regular_bins_per_hyperplane, curr_bins_per_hyperplane, curr_regular_bins_per_hyperplane);
947 
948  // By the time we reach the first axis, there should only be at most one
949  // full row of regular bins before us:
950  //
951  // -1 1 2 3 -2
952  // ^ ^
953  // | |
954  // | Option 2: one overflow bin before us
955  // |
956  // Option 1: no overflow bin before us
957  //
958  num_regular_bins_before +=
959  unprocessed_previous_overflow_bin * std::get<0>(fAxes).GetNBinsNoOver();
960 
961  // Now that we know the number of regular bins before us, we can add this to
962  // to the zero-based overflow bin index that we started with to get a global
963  // zero-based bin index accounting for both under/overflow bins and regular
964  // bins, just like what we had in the ComputeGlobalBin<DATA::GetNDim()>() implementation.
965  const int global_virtual_bin =
966  corrected_virtual_overflow_bin + num_regular_bins_before;
967 
968  // We can then easily go back to zero-based "virtual" bin indices...
969  const BinArray_t virtual_bins = ComputeLocalBinsRaw<NDIMS>(global_virtual_bin, &ROOT::Experimental::RAxisBase::GetNBins);
970 
971  // ...and from that go back to the -1/-2 overflow bin indexing convention.
972  return VirtualBinsToLocalBins<NDIMS>(virtual_bins);
973  }
974 
975  /// Get the bin index for the given coordinates `x`. The use of `RFindLocalBins`
976  /// allows to convert the coordinates to local per-axis bin indices before using
977  /// `ComputeGlobalBin()`.
978  int GetBinIndex(const CoordArray_t &x) const final
979  {
980  BinArray_t localBins = {};
981  Internal::RFindLocalBins<DATA::GetNDim() - 1, DATA::GetNDim(), BinArray_t, CoordArray_t, decltype(fAxes)>()(localBins, fAxes, x);
982  int result = ComputeGlobalBin<DATA::GetNDim()>(localBins);
983  return result;
984  }
985 
986  /// Get the bin index for the given coordinates `x`, growing the axes as needed.
987  /// The use of `RFindLocalBins` allows to convert the coordinates to local
988  /// per-axis bin indices before using `ComputeGlobalBin()`.
989  ///
990  /// TODO: implement growable behavior
991  int GetBinIndexAndGrow(const CoordArray_t &x) const final
992  {
994  int ret = 0;
995  BinArray_t localBins = {};
996  while (status == Internal::EFindStatus::kCanGrow) {
997  Internal::RFindLocalBins<DATA::GetNDim() - 1, DATA::GetNDim(), BinArray_t, CoordArray_t, decltype(fAxes)>()(localBins, fAxes, x);
998  ret = ComputeGlobalBin<DATA::GetNDim()>(localBins);
1000  }
1001  return ret;
1002  }
1003 
1004  /// Get the bin index for the given local per-axis bin indices `x`, using
1005  /// `ComputeGlobalBin()`.
1006  int GetBinIndexFromLocalBins(const BinArray_t &x) const final
1007  {
1008  BinArray_t localBins = x;
1009  int result = ComputeGlobalBin<DATA::GetNDim()>(localBins);
1010  return result;
1011  }
1012 
1013  /// Get the local per-axis bin indices `x` for the given bin index, using
1014  /// `ComputeLocalBins()`.
1015  BinArray_t GetLocalBins(int binidx) const final
1016  {
1017  BinArray_t localBins = ComputeLocalBins<DATA::GetNDim()>(binidx);
1018  return localBins;
1019  }
1020 
1021  /// Get the center coordinates of the bin with index `binidx`.
1022  CoordArray_t GetBinCenter(int binidx) const final
1023  {
1024  BinArray_t localBins = ComputeLocalBins<DATA::GetNDim()>(binidx);
1025  CoordArray_t coords;
1026  Internal::RLocalBinsToCoords<DATA::GetNDim() - 1, DATA::GetNDim(), BinArray_t, CoordArray_t, decltype(fAxes)>()(coords, fAxes, localBins, Internal::EBinCoord::kBinCenter);
1027  return coords;
1028  }
1029 
1030  /// Get the coordinates of the low limit of the bin with index `binidx`.
1031  CoordArray_t GetBinFrom(int binidx) const final
1032  {
1033  BinArray_t localBins = ComputeLocalBins<DATA::GetNDim()>(binidx);
1034  CoordArray_t coords;
1035  Internal::RLocalBinsToCoords<DATA::GetNDim() - 1, DATA::GetNDim(), BinArray_t, CoordArray_t, decltype(fAxes)>()(coords, fAxes, localBins, Internal::EBinCoord::kBinFrom);
1036  return coords;
1037  }
1038 
1039  /// Get the coordinates of the high limit of the bin with index `binidx`.
1040  CoordArray_t GetBinTo(int binidx) const final
1041  {
1042  BinArray_t localBins = ComputeLocalBins<DATA::GetNDim()>(binidx);
1043  CoordArray_t coords;
1044  Internal::RLocalBinsToCoords<DATA::GetNDim() - 1, DATA::GetNDim(), BinArray_t, CoordArray_t, decltype(fAxes)>()(coords, fAxes, localBins, Internal::EBinCoord::kBinTo);
1045  return coords;
1046  }
1047 
1048  /// Fill an array of `weightN` to the bins specified by coordinates `xN`.
1049  /// For each element `i`, the weight `weightN[i]` will be added to the bin
1050  /// at the coordinate `xN[i]`
1051  /// \note `xN` and `weightN` must have the same size!
1052  void FillN(const std::span<const CoordArray_t> xN, const std::span<const Weight_t> weightN) final
1053  {
1054 #ifndef NDEBUG
1055  if (xN.size() != weightN.size()) {
1056  R__LOG_ERROR(HistLog()) << "Not the same number of points and weights!";
1057  return;
1058  }
1059 #endif
1060 
1061  for (size_t i = 0; i < xN.size(); ++i) {
1062  Fill(xN[i], weightN[i]);
1063  }
1064  }
1065 
1066  /// Fill an array of `weightN` to the bins specified by coordinates `xN`.
1067  /// For each element `i`, the weight `weightN[i]` will be added to the bin
1068  /// at the coordinate `xN[i]`
1069  void FillN(const std::span<const CoordArray_t> xN) final
1070  {
1071  for (auto &&x: xN) {
1072  Fill(x);
1073  }
1074  }
1075 
1076  /// Add a single weight `w` to the bin at coordinate `x`.
1077  void Fill(const CoordArray_t &x, Weight_t w = 1.)
1078  {
1079  int bin = GetBinIndexAndGrow(x);
1080  this->GetStat().Fill(x, bin, w);
1081  }
1082 
1083  /// Get the content of the bin at position `x`.
1084  Weight_t GetBinContent(const CoordArray_t &x) const final
1085  {
1086  int bin = GetBinIndex(x);
1087  return ImplBase_t::GetBinContent(bin);
1088  }
1089 
1090  /// Return the uncertainties for the given bin index.
1091  double GetBinUncertainty(int binidx) const final { return this->GetStat().GetBinUncertainty(binidx); }
1092 
1093  /// Get the bin uncertainty for the bin at coordinate `x`.
1094  double GetBinUncertainty(const CoordArray_t &x) const final
1095  {
1096  const int bin = GetBinIndex(x);
1097  return this->GetBinUncertainty(bin);
1098  }
1099 
1100  /// Whether this histogram's statistics provide storage for uncertainties, or
1101  /// whether uncertainties are determined as poisson uncertainty of the content.
1102  bool HasBinUncertainty() const final { return this->GetStat().HasBinUncertainty(); }
1103 
1104  /// Get the begin() and end() for each axis.
1105  AxisIterRange_t<DATA::GetNDim()>
1106  GetRange() const final
1107  {
1108  std::array<std::array<RAxisBase::const_iterator, DATA::GetNDim()>, 2> ret;
1109  Internal::RFillIterRange<DATA::GetNDim() - 1, decltype(fAxes)>()(ret, fAxes);
1110  return ret;
1111  }
1112 
1113  /// Grow the axis number `iAxis` to fit the coordinate `x`.
1114  ///
1115  /// The histogram (conceptually) combines pairs of bins along this axis until
1116  /// `x` is within the range of the axis.
1117  /// The axis must support growing for this to work (e.g. a `RAxisGrow`).
1118  void GrowAxis(int /*iAxis*/, double /*x*/)
1119  {
1120  // TODO: Implement GrowAxis()
1121  }
1122 
1123  /// \{
1124  /// \name Iterator interface
1127  iterator begin() noexcept { return iterator(*this); }
1128  const_iterator begin() const noexcept { return const_iterator(*this); }
1129  iterator end() noexcept { return iterator(*this, this->GetNBinsNoOver()); }
1130  const_iterator end() const noexcept { return const_iterator(*this, this->GetNBinsNoOver()); }
1131  /// \}
1132 };
1133 
1134 template <class DATA, class... AXISCONFIG>
1136 {}
1137 
1138 template <class DATA, class... AXISCONFIG>
1140  : ImplBase_t(Internal::GetNBinsNoOverFromAxes(axisArgs...), Internal::GetNOverflowBinsFromAxes(axisArgs...)), fAxes{axisArgs...}
1141 {}
1142 
1143 template <class DATA, class... AXISCONFIG>
1145  : ImplBase_t(title, Internal::GetNBinsNoOverFromAxes(axisArgs...), Internal::GetNOverflowBinsFromAxes(axisArgs...)), fAxes{axisArgs...}
1146 {}
1147 
1148 #if 0
1149 // In principle we can also have a runtime version of RHistImpl, that does not
1150 // contain a tuple of concrete axis types but a vector of `RAxisConfig`.
1151 template <class DATA>
1152 class RHistImplRuntime: public RHistImplBase<DATA> {
1153 public:
1154  RHistImplRuntime(std::array<RAxisConfig, DATA::GetNDim()>&& axisCfg);
1155 };
1156 #endif
1157 
1158 } // namespace Detail
1159 
1160 } // namespace Experimental
1161 } // namespace ROOT
1162 
1163 #endif
ROOT::Experimental::Detail::RHistImpl::Fill
void Fill(const CoordArray_t &x, Weight_t w=1.)
Add a single weight w to the bin at coordinate x.
Definition: RHistImpl.hxx:1077
ROOT::Experimental::Internal::RGetNRegularBinsBefore
Recursively gets the number of regular bins just before the current dimension.
Definition: RHistImpl.hxx:359
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetBinContentAsDouble
virtual double GetBinContentAsDouble(int binidx) const =0
The bin content, cast to double.
RAxis.hxx
ROOT::Experimental::Detail::RHistBinIter
Iterates over the bins of a RHist or RHistImpl.
Definition: RHistBinIter.hxx:97
ROOT::Experimental::Detail::RHistImpl::BinArray_t
typename ImplBase_t::BinArray_t BinArray_t
Definition: RHistImpl.hxx:730
ROOT::Experimental::RAxisConfig
Objects used to configure the different axis types.
Definition: RAxisConfig.hxx:35
ROOT::Experimental::Detail::RHistImplBase::GetBinContentAsDouble
double GetBinContentAsDouble(int binidx) const final
Get the bin content (sum of weights) for bin index binidx, cast to double.
Definition: RHistImpl.hxx:234
ROOT::Experimental::Internal::EBinCoord::kBinTo
@ kBinTo
Get the bin high edge.
R__LOG_ERROR
#define R__LOG_ERROR(...)
Definition: RLogger.hxx:362
ROOT::Experimental::Internal::RLocalBinsToVirtualBins
Recursively converts local axis bins from the standard kUnderflowBin/kOverflowBin for under/overflow ...
Definition: RHistImpl.hxx:647
ROOT::Experimental::Detail::RHistImpl::GetBinIndexFromLocalBins
int GetBinIndexFromLocalBins(const BinArray_t &x) const final
Get the bin index for the given local per-axis bin indices x, using ComputeGlobalBin().
Definition: RHistImpl.hxx:1006
ROOT::Experimental::Detail::RHistImpl::GetBinUncertainty
double GetBinUncertainty(const CoordArray_t &x) const final
Get the bin uncertainty for the bin at coordinate x.
Definition: RHistImpl.hxx:1094
ROOT::Experimental::Internal::RLocalBinsToCoords::operator()
void operator()(COORD &coords, const AXES &axes, const BINS &localBins, EBinCoord kind) const
Definition: RHistImpl.hxx:696
ROOT::Experimental::Detail::RHistImplBase::RHistImplBase
RHistImplBase(RHistImplBase &&)=default
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::RHistImplPrecisionAgnosticBase
RHistImplPrecisionAgnosticBase(const RHistImplPrecisionAgnosticBase &)=default
ROOT::Experimental::Detail::RHistImpl::end
iterator end() noexcept
Definition: RHistImpl.hxx:1129
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetNBins
virtual int GetNBins() const noexcept=0
Number of bins of this histogram, including all overflow and underflow bins.
ROOT::Experimental::Internal::RLocalBinsToVirtualBins::operator()
void operator()(BINS &virtualBins, const AXES &axes, const BINS &localBins) const
Definition: RHistImpl.hxx:648
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetBinCenter
virtual CoordArray_t GetBinCenter(int binidx) const =0
Get the center in all dimensions of the bin with index binidx.
ROOT::Experimental::Internal::RFindLocalBins
Find the per-axis local bin indices associated with a certain set of coordinates.
Definition: RHistImpl.hxx:674
ROOT::Experimental::Detail::RHistImplBase::AddBinContent
void AddBinContent(int binidx, Weight_t w)
Add w to the bin at index bin.
Definition: RHistImpl.hxx:237
ROOT::Experimental::Detail::RHistImplBase::Clone
virtual std::unique_ptr< RHistImplBase > Clone() const =0
ROOT::Experimental::Hist::EOverflow::kUnderOver
@ kUnderOver
Include both under- and overflows.
ROOT::Experimental::Detail::RHistImplBase::BinArray_t
std::array< int, DATA::GetNDim()> BinArray_t
Type of the local per-axis bin indices.
Definition: RHistImpl.hxx:159
ROOT::Experimental::Internal::RComputeLocalBinsInitialisation< 0, NDIMS, AXES >::operator()
void operator()(std::array< int, NDIMS-1 >, std::array< int, NDIMS-1 >, const AXES &) const
Definition: RHistImpl.hxx:426
ROOT::Experimental::Detail::RHistImpl::RHistImpl
RHistImpl(TRootIOCtor *)
Definition: RHistImpl.hxx:1135
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetNDim
static constexpr int GetNDim()
Number of dimensions of the coordinates.
Definition: RHistImpl.hxx:88
ROOT::Experimental::Internal::RFillIterRange::operator()
void operator()(Hist::AxisIterRange_t< std::tuple_size< AXES >::value > &range, const AXES &axes) const
Definition: RHistImpl.hxx:338
ROOT::Experimental::Detail::RHistImpl::ComputeLocalBinsRaw
BinArray_t ComputeLocalBinsRaw(int zeroBasedGlobalBin, BINTYPE GetNBinType) const
Computes zero-based local bin indices, given...
Definition: RHistImpl.hxx:780
ROOT::Experimental::Detail::RHistImpl::begin
const_iterator begin() const noexcept
Definition: RHistImpl.hxx:1128
ROOT::Experimental::Internal::RComputeGlobalBin
Recursively gets the total number of regular bins before the current dimension, when computing a glob...
Definition: RHistImpl.hxx:396
ROOT::Experimental::Internal::RGetNBinsCount::operator()
int operator()(const AXES &axes) const
Definition: RHistImpl.hxx:305
string_view
basic_string_view< char > string_view
Definition: libcpp_string_view.h:785
ROOT::Experimental::Detail::RHistImpl::end
const_iterator end() const noexcept
Definition: RHistImpl.hxx:1130
ROOT::Experimental::Detail::RHistImpl::ComputeGlobalBinRaw
int ComputeGlobalBinRaw(const BinArray_t &zeroBasedLocalBins, BINTYPE GetNBinType) const
Computes a zero-based global bin index, given...
Definition: RHistImpl.hxx:767
ROOT::Experimental::Internal::RComputeLocalBinsRaw
Recursively computes zero-based local bin indices, given...
Definition: RHistImpl.hxx:559
ROOT::Experimental::Hist::EOverflow::kOverflow
@ kOverflow
Include overflows.
ROOT::Experimental::Internal::EBinCoord
EBinCoord
Specifies if the wanted result is the bin's lower edge, center or higher edge.
Definition: RHistImpl.hxx:252
ROOT::Experimental::Internal::EFindStatus::kCanGrow
@ kCanGrow
The coordinate could fit after growing the axis.
ROOT::Experimental::Internal::GetNBinsFromAxes
int GetNBinsFromAxes(AXISCONFIG... axisArgs)
Get the number of bins in whole hist, including under- and overflow.
Definition: RHistImpl.hxx:310
ROOT::Experimental::Internal::RGetNBinsCount
Recursively gets the total number of bins in whole hist, including under- and overflow.
Definition: RHistImpl.hxx:304
ROOT::Experimental::Detail::RHistImplBase::Weight_t
typename DATA::Weight_t Weight_t
Type of the bin content (and thus weights).
Definition: RHistImpl.hxx:161
x
Double_t x[n]
Definition: legend1.C:17
ROOT::Experimental::Detail::RHistImpl::GetFillFunc
FillFunc_t GetFillFunc() const final
Retrieve the fill function for this histogram implementation, to prevent the virtual function call fo...
Definition: RHistImpl.hxx:750
ROOT::Experimental::Detail::RHistImpl::GetBinCenter
CoordArray_t GetBinCenter(int binidx) const final
Get the center coordinates of the bin with index binidx.
Definition: RHistImpl.hxx:1022
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetBinFrom
virtual CoordArray_t GetBinFrom(int binidx) const =0
Get the lower edge in all dimensions of the bin with index binidx.
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetBinTo
virtual CoordArray_t GetBinTo(int binidx) const =0
Get the upper edge in all dimensions of the bin with index binidx.
ROOT::Experimental::RAxisBase::kOverflowBin
constexpr static const int kOverflowBin
Index of the overflow bin, if any.
Definition: RAxis.hxx:232
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase
Base class for RHistImplBase that abstracts out the histogram's PRECISION.
Definition: RHistImpl.hxx:72
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetBinUncertainty
virtual double GetBinUncertainty(int binidx) const =0
Get the uncertainty of the bin with index binidx.
ROOT::Experimental::Internal::GetNOverflowBinsFromAxes
int GetNOverflowBinsFromAxes(AXISCONFIG... axisArgs)
Get the number of under- and overflow bins in whole hist, excluding regular bins.
Definition: RHistImpl.hxx:318
ROOT::Experimental::Detail::RHistImplBase::Stat_t
DATA Stat_t
Type of the statistics (bin content, uncertainties etc).
Definition: RHistImpl.hxx:155
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetNBinsNoOver
virtual int GetNBinsNoOver() const noexcept=0
Number of bins of this histogram, excluding all overflow and underflow bins.
ROOT::Experimental::Detail::RHistImplBase::GetBinUncertainty
virtual double GetBinUncertainty(const CoordArray_t &x) const =0
Get the bin uncertainty for the bin at coordinate x.
ROOT::Experimental::HistLog
RLogChannel & HistLog()
Log channel for Hist diagnostics.
Definition: RAxis.cxx:25
ROOT::Experimental::Detail::RHistImplBase::GetStat
Stat_t & GetStat() noexcept
Non-const access to statistics.
Definition: RHistImpl.hxx:230
ROOT::Experimental::Detail::RHistImplBase::GetBinContent
Weight_t & GetBinContent(int binidx)
Get the bin content (sum of weights) for bin index binidx (non-const).
Definition: RHistImpl.hxx:220
ROOT::Experimental::Internal::GetAxisView
static std::array< const RAxisBase *, sizeof...(AXISCONFIG)> GetAxisView(const AXISCONFIG &... axes) noexcept
Definition: RHistImpl.hxx:710
b
#define b(i)
Definition: RSha256.hxx:100
ROOT::Experimental::Detail::RHistImpl
Definition: RHistImpl.hxx:722
ROOT::Experimental::Internal::GetNBinsNoOverFromAxes
int GetNBinsNoOverFromAxes(AXISCONFIG... axisArgs)
Get the number of bins in whole hist, excluding under- and overflow.
Definition: RHistImpl.hxx:286
ROOT::Experimental::Detail::RHistImpl::GetBinFrom
CoordArray_t GetBinFrom(int binidx) const final
Get the coordinates of the low limit of the bin with index binidx.
Definition: RHistImpl.hxx:1031
ROOT::Experimental::Hist::EOverflow
EOverflow
Kinds of under- and overflow handling.
Definition: RHistImpl.hxx:47
RHistBinIter.hxx
ROOT::Experimental::Internal::RGetNBinsCount< 0, AXES >::operator()
int operator()(const AXES &axes) const
Definition: RHistImpl.hxx:300
ROOT::Experimental::Detail::RHistImplBase::GetBinContent
Weight_t GetBinContent(int binidx) const
Get the bin content (sum of weights) for bin index binidx.
Definition: RHistImpl.hxx:213
ROOT::Experimental::Hist::AxisIter_t
std::array< RAxisBase::const_iterator, NDIMS > AxisIter_t
Iterator over n dimensional axes - an array of n axis iterators.
Definition: RHistImpl.hxx:41
ROOT::Experimental::Detail::RHistImplBase::GetStat
const Stat_t & GetStat() const noexcept
Const access to statistics.
Definition: RHistImpl.hxx:227
RLogger.hxx
ROOT::Experimental::Internal::RGetNRegularBinsBefore<-1, NDIMS, BINS, AXES >::operator()
void operator()(BINS &, const AXES &) const
Definition: RHistImpl.hxx:354
ROOT::Experimental::Internal::RComputeLocalBins::operator()
void operator()(const AXES &axes, int &unprocessed_previous_overflow_bin, int &num_regular_bins_before, std::array< int, NDIMS-1 > bins_per_hyperplane, std::array< int, NDIMS-1 > regular_bins_per_hyperplane, int curr_bins_per_hyperplane, int curr_regular_bins_per_hyperplane) const
Definition: RHistImpl.hxx:464
ROOT::Experimental::Detail::RHistImpl::GetBinUncertainty
double GetBinUncertainty(int binidx) const final
Return the uncertainties for the given bin index.
Definition: RHistImpl.hxx:1091
ROOT::Experimental::Internal::RLocalBinsToCoords
Recursively converts local axis bins from the standard kUnderflowBin/kOverflowBin for under/overflow ...
Definition: RHistImpl.hxx:695
ROOT::Experimental::Hist::EOverflow::kNoOverflow
@ kNoOverflow
Exclude under- and overflows.
ROOT::Experimental::RAxisBase::const_iterator
Random const_iterator through bins.
Definition: RAxis.hxx:127
ROOT::Experimental::Internal::RGetNBinsNoOverCount::operator()
int operator()(const AXES &axes) const
Definition: RHistImpl.hxx:281
ROOT::Experimental::Detail::RHistImplBase
Interface class for RHistImpl.
Definition: RHistImpl.hxx:152
ROOT::Experimental::Internal::RFindLocalBins::operator()
void operator()(BINS &localBins, const AXES &axes, const COORD &coords) const
Definition: RHistImpl.hxx:675
ROOT::Experimental::Hist::operator&
bool operator&(EOverflow a, EOverflow b)
Definition: RHistImpl.hxx:54
ROOT::Experimental::Detail::RHistImplBase::RHistImplBase
RHistImplBase(std::string_view title, size_t numBins, size_t numOverflowBins)
Definition: RHistImpl.hxx:173
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::RHistImplPrecisionAgnosticBase
RHistImplPrecisionAgnosticBase(std::string_view title)
Definition: RHistImpl.hxx:84
ROOT::Experimental::Internal::RLocalBinsToVirtualBins<-1, NDIMS, BINS, AXES >::operator()
void operator()(BINS &, const AXES &, const BINS &) const
Definition: RHistImpl.hxx:642
a
auto * a
Definition: textangle.C:12
ROOT::Experimental::Internal::RComputeLocalBinsRaw<-1, NDIMS, BINS, AXES, BINTYPE >::operator()
void operator()(BINS &, const AXES &, int, BINTYPE) const
Definition: RHistImpl.hxx:554
ROOT::Experimental::Internal::RFillIterRange<-1, AXES >::operator()
void operator()(Hist::AxisIterRange_t< std::tuple_size< AXES >::value > &, const AXES &) const
Definition: RHistImpl.hxx:332
ROOT::Experimental::Detail::RHistImplBase::GetNBinsNoOver
int GetNBinsNoOver() const noexcept final
Get the number of bins in this histogram, excluding possible under- and overflow bins.
Definition: RHistImpl.hxx:206
ROOT::Experimental::Internal::RComputeGlobalBinRaw::operator()
int operator()(int globalVirtualBin, const AXES &axes, const BINS &zeroBasedLocalBins, int binSize, BINTYPE GetNBinType) const
Definition: RHistImpl.hxx:587
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetBinIndex
virtual int GetBinIndex(const CoordArray_t &x) const =0
Given the coordinate x, determine the index of the bin.
TRootIOCtor
Definition: TRootIOCtor.h:33
STAT
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetAxis
virtual const RAxisBase & GetAxis(int iAxis) const =0
Get a base-class view on axis with index iAxis.
ROOT::Experimental::RAxisBase::kUnderflowBin
constexpr static const int kUnderflowBin
Index of the underflow bin, if any.
Definition: RAxis.hxx:229
ROOT::Experimental::Detail::RHistImpl::FillN
void FillN(const std::span< const CoordArray_t > xN, const std::span< const Weight_t > weightN) final
Fill an array of weightN to the bins specified by coordinates xN.
Definition: RHistImpl.hxx:1052
ROOT::Experimental::Detail::RHistImpl::CoordArray_t
typename ImplBase_t::CoordArray_t CoordArray_t
Definition: RHistImpl.hxx:729
ROOT::Experimental::Detail::RHistImpl::AxisIterRange_t
typename Hist::AxisIterRange_t< NDIMS > AxisIterRange_t
Definition: RHistImpl.hxx:734
ROOT::Experimental::Detail::RHistImpl::Clone
std::unique_ptr< ImplBase_t > Clone() const override
Definition: RHistImpl.hxx:744
ROOT::Experimental::Detail::RHistImpl::iterator
RHistBinIter< ImplBase_t > iterator
Definition: RHistImpl.hxx:1126
ROOT::Experimental::Detail::RHistImpl::GetBinContent
Weight_t GetBinContent(const CoordArray_t &x) const final
Get the content of the bin at position x.
Definition: RHistImpl.hxx:1084
ROOT::Experimental::Detail::RHistImpl::VirtualBinsToLocalBins
BinArray_t VirtualBinsToLocalBins(const BinArray_t &virtualBins) const
Converts zero-based virtual bins where the underflow bin has index 0 and the overflow bin has index N...
Definition: RHistImpl.hxx:802
ROOT::Experimental::Internal::EBinCoord::kBinFrom
@ kBinFrom
Get the lower bin edge.
ROOT::Experimental::Detail::RHistImpl::GetLocalBins
BinArray_t GetLocalBins(int binidx) const final
Get the local per-axis bin indices x for the given bin index, using ComputeLocalBins().
Definition: RHistImpl.hxx:1015
ROOT::Experimental::Detail::RHistImpl::GetAxis
const RAxisBase & GetAxis(int iAxis) const final
Normalized axes access, converting from actual axis type to base class.
Definition: RHistImpl.hxx:758
ROOT::Experimental::Internal::EBinCoord::kBinCenter
@ kBinCenter
Get the bin center.
ROOT::Experimental::Hist::RCoordArray
Definition: RHistUtils.hxx:31
ROOT::Experimental::RAxisBase
Histogram axis base class.
Definition: RAxis.hxx:44
ROOT::Experimental::RAxisBase::GetNBins
int GetNBins() const noexcept
Get the number of bins, including under- and overflow.
Definition: RAxis.hxx:244
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetBinIndexAndGrow
virtual int GetBinIndexAndGrow(const CoordArray_t &x) const =0
Given the coordinate x, determine the index of the bin, possibly growing axes for which x is out of r...
void
typedef void((*Func_t)())
ROOT::Experimental::Detail::RHistImpl::ComputeGlobalBin
int ComputeGlobalBin(BinArray_t &local_bins) const
Computes the global index of a certain bin on an NDIMS-dimensional histogram, knowing the local per-a...
Definition: RHistImpl.hxx:811
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::HasBinUncertainty
virtual bool HasBinUncertainty() const =0
Whether this histogram's statistics provide storage for uncertainties, or whether uncertainties are d...
ROOT::Experimental::Internal::EFindStatus
EFindStatus
Status of FindBin(x) and FindAdjustedBin(x)
Definition: RHistImpl.hxx:259
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetBinIndexFromLocalBins
virtual int GetBinIndexFromLocalBins(const BinArray_t &x) const =0
Given the local per-axis bins x, determine the index of the bin.
ROOT::Experimental::Detail::RHistImpl::GetAxes
const std::tuple< AXISCONFIG... > & GetAxes() const
Get the axes of this histogram.
Definition: RHistImpl.hxx:755
ROOT::Experimental::Detail::RHistImpl::GetRange
AxisIterRange_t< DATA::GetNDim()> GetRange() const final
Get the begin() and end() for each axis.
Definition: RHistImpl.hxx:1106
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase< DATA::GetNDim()>::BinArray_t
std::array< int, DIMENSIONS > BinArray_t
Type of the local per-axis bin indices.
Definition: RHistImpl.hxx:77
ROOT::Experimental::Detail::RHistImpl::GetBinTo
CoordArray_t GetBinTo(int binidx) const final
Get the coordinates of the high limit of the bin with index binidx.
Definition: RHistImpl.hxx:1040
ROOT::Experimental::Internal::RGetNBinsNoOverCount
Recursively gets the total number of bins in whole hist, excluding under- and overflow.
Definition: RHistImpl.hxx:280
ROOT::Experimental::Detail::RHistImplBase::fStatistics
Stat_t fStatistics
The histogram's bin content, uncertainties etc.
Definition: RHistImpl.hxx:168
ROOT::Experimental::Detail::RHistImplBase::RHistImplBase
RHistImplBase()=default
ROOT::Experimental::Internal::RComputeLocalBins
Recursively computes the number of regular bins before the current dimension, as well as the number o...
Definition: RHistImpl.hxx:463
ROOT::Experimental::Detail::RHistImplBase::GetNBins
int GetNBins() const noexcept final
Get the number of bins in this histogram, including possible under- and overflow bins.
Definition: RHistImpl.hxx:202
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetNOverflowBins
virtual int GetNOverflowBins() const noexcept=0
Number of under- and overflow bins of this histogram, excluding all regular bins.
ROOT::Experimental::Internal::EFindStatus::kValid
@ kValid
The returned bin index is valid.
ROOT::Experimental::Internal::RComputeGlobalBinRaw<-1, NDIMS, BINS, AXES, BINTYPE >::operator()
int operator()(int globalVirtualBin, const AXES &, const BINS &, int, BINTYPE) const
Definition: RHistImpl.hxx:579
ROOT::Experimental::Internal::RFillIterRange
Recursively fills the ranges of all axes, excluding under- and overflow.
Definition: RHistImpl.hxx:337
ROOT::Experimental::RAxisBase::GetNBinsNoOver
virtual int GetNBinsNoOver() const noexcept=0
Get the number of bins, excluding under- and overflow.
ROOT::Experimental::Internal::RComputeLocalBinsInitialisation::operator()
void operator()(std::array< int, NDIMS-1 > &bins_per_hyperplane, std::array< int, NDIMS-1 > &regular_bins_per_hyperplane, const AXES &axes) const
Definition: RHistImpl.hxx:432
ROOT::Experimental::Detail::RHistImplBase::GetFillFunc
virtual FillFunc_t GetFillFunc() const =0
Retrieve the pointer to the overridden Fill(x, w) function.
ROOT::Experimental::Internal::RVirtualBinsToLocalBins<-1, NDIMS, BINS, AXES >::operator()
void operator()(BINS &, const AXES &, const BINS &) const
Definition: RHistImpl.hxx:608
ROOT::Experimental::Internal::RComputeGlobalBin<-1, NDIMS, BINS, AXES >::operator()
int operator()(int total_regular_bins_before, const AXES &, const BINS &, const BINS &, const BINS &) const
Definition: RHistImpl.hxx:389
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetLocalBins
virtual BinArray_t GetLocalBins(int binidx) const =0
Given the index of the bin, determine the local per-axis bins x.
ROOT::Experimental::Detail::RHistImpl::FillN
void FillN(const std::span< const CoordArray_t > xN) final
Fill an array of weightN to the bins specified by coordinates xN.
Definition: RHistImpl.hxx:1069
ROOT::Experimental::Detail::RHistImpl::ComputeLocalBins
BinArray_t ComputeLocalBins(int global_bin) const
Computes the local per-axis bin indices of a certain bin on an NDIMS-dimensional histogram,...
Definition: RHistImpl.hxx:867
ROOT::Experimental::Detail::RHistImpl::begin
iterator begin() noexcept
Definition: RHistImpl.hxx:1127
ROOT::Experimental::Detail::RHistImpl::HasBinUncertainty
bool HasBinUncertainty() const final
Whether this histogram's statistics provide storage for uncertainties, or whether uncertainties are d...
Definition: RHistImpl.hxx:1102
ROOT::Experimental::Internal::RComputeGlobalBinRaw
Recursively computes a zero-based global bin index, given...
Definition: RHistImpl.hxx:586
ROOT::Experimental::Internal::RComputeLocalBinsInitialisation
Recursively compute some quantities needed for ComputeLocalBins, namely the total number of bins per ...
Definition: RHistImpl.hxx:431
ROOT::Experimental::Detail::RHistImpl::LocalBinsToVirtualBins
BinArray_t LocalBinsToVirtualBins(const BinArray_t &localBins) const
Converts local axis bins from the standard kUnderflowBin/kOverflowBin for under/overflow bin indexing...
Definition: RHistImpl.hxx:791
ROOT::Experimental::Detail::RHistImplBase::GetBinContent
virtual Weight_t GetBinContent(const CoordArray_t &x) const =0
Get the bin content (sum of weights) for the bin at coordinate x.
ROOT::Experimental::Detail::RHistImpl::GetBinIndexAndGrow
int GetBinIndexAndGrow(const CoordArray_t &x) const final
Get the bin index for the given coordinates x, growing the axes as needed.
Definition: RHistImpl.hxx:991
ROOT::Experimental::Detail::RHistImpl::fAxes
std::tuple< AXISCONFIG... > fAxes
The histogram's axes.
Definition: RHistImpl.hxx:737
ROOT::Experimental::Detail::RHistImplBase::CoordArray_t
Hist::CoordArray_t< DATA::GetNDim()> CoordArray_t
Type of the coordinates.
Definition: RHistImpl.hxx:157
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetRange
virtual AxisIterRange_t GetRange() const =0
Get an AxisIterRange_t for the whole histogram, excluding under- and overflow.
ROOT::Experimental::Internal::RComputeLocalBinsRaw::operator()
void operator()(BINS &virtualBins, const AXES &axes, int zeroBasedGlobalBin, BINTYPE GetNBinType) const
Definition: RHistImpl.hxx:560
ROOT::Experimental::Internal::RLocalBinsToCoords<-1, NDIMS, BINS, COORD, AXES >::operator()
void operator()(COORD &, const AXES &, const BINS &, EBinCoord) const
Definition: RHistImpl.hxx:690
I
#define I(x, y, z)
RTupleApply.hxx
ROOT::Experimental::Internal::RComputeGlobalBin::operator()
int operator()(int total_regular_bins_before, const AXES &axes, const BINS &virtualBins, const BINS &binSizes, const BINS &localBins) const
Definition: RHistImpl.hxx:397
ROOT::Experimental::Detail::RHistImplBase::FillN
virtual void FillN(const std::span< const CoordArray_t > xN, const std::span< const Weight_t > weightN)=0
Interface function to fill a vector or array of coordinates with corresponding weights.
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::GetTitle
const std::string & GetTitle() const
Get the histogram title.
Definition: RHistImpl.hxx:100
ROOT::Experimental::Detail::RHistImplBase::FillFunc_t
void(RHistImplBase::*)(const CoordArray_t &x, Weight_t w) FillFunc_t
Type of the Fill(x, w) function.
Definition: RHistImpl.hxx:164
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase< DATA::GetNDim()>::AxisIterRange_t
Hist::AxisIterRange_t< DIMENSIONS > AxisIterRange_t
Range type.
Definition: RHistImpl.hxx:79
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::RHistImplPrecisionAgnosticBase
RHistImplPrecisionAgnosticBase()=default
ROOT::Experimental::Detail::RHistImplBase::GetNOverflowBins
int GetNOverflowBins() const noexcept final
Get the number of under- and overflow bins of this histogram, excluding all regular bins.
Definition: RHistImpl.hxx:210
ROOT::Experimental::Internal::RFindLocalBins<-1, NDIMS, BINS, COORD, AXES >::operator()
void operator()(BINS &, const AXES &, const COORD &) const
Definition: RHistImpl.hxx:669
ROOT::Experimental::Internal::RGetNBinsNoOverCount< 0, AXES >::operator()
int operator()(const AXES &axes) const
Definition: RHistImpl.hxx:276
RSpan.hxx
ROOT::Experimental::Internal::RComputeLocalBins< 0, NDIMS, AXES >::operator()
void operator()(const AXES &, int &, int &, std::array< int, NDIMS-1 >, std::array< int, NDIMS-1 >, int, int) const
Definition: RHistImpl.hxx:455
ROOT::Experimental::Hist::AxisIterRange_t
std::array< AxisIter_t< NDIMS >, 2 > AxisIterRange_t
Range over n dimensional axes - a pair of arrays of n axis iterators.
Definition: RHistImpl.hxx:44
ROOT::Experimental::Detail::RHistImpl::const_iterator
RHistBinIter< const ImplBase_t > const_iterator
Definition: RHistImpl.hxx:1125
ROOT::Experimental::Detail::RHistImpl::GrowAxis
void GrowAxis(int, double)
Grow the axis number iAxis to fit the coordinate x.
Definition: RHistImpl.hxx:1118
ROOT::Experimental::Detail::RHistImplBase::RHistImplBase
RHistImplBase(size_t numBins, size_t numOverflowBins)
Definition: RHistImpl.hxx:172
RHistUtils.hxx
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::~RHistImplPrecisionAgnosticBase
virtual ~RHistImplPrecisionAgnosticBase()
Definition: RHistImpl.hxx:85
ROOT
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: EExecutionPolicy.hxx:4
ROOT::Experimental::Internal::RVirtualBinsToLocalBins::operator()
void operator()(BINS &localBins, const AXES &axes, const BINS &virtualBins) const
Definition: RHistImpl.hxx:614
ROOT::Experimental::Detail::RHistImplBase::FillN
virtual void FillN(const std::span< const CoordArray_t > xN)=0
Interface function to fill a vector or array of coordinates.
ROOT::Experimental::Detail::RHistImpl::GetBinIndex
int GetBinIndex(const CoordArray_t &x) const final
Get the bin index for the given coordinates x.
Definition: RHistImpl.hxx:978
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::RHistImplPrecisionAgnosticBase
RHistImplPrecisionAgnosticBase(RHistImplPrecisionAgnosticBase &&)=default
ROOT::Experimental::Detail::RHistImplPrecisionAgnosticBase::fTitle
std::string fTitle
The histogram's title.
Definition: RHistImpl.hxx:140
ROOT::Experimental::Internal::RGetNRegularBinsBefore::operator()
void operator()(BINS &binSizes, const AXES &axes) const
Definition: RHistImpl.hxx:360
int
ROOT::Experimental::Hist::EOverflow::kUnderflow
@ kUnderflow
Include underflows.
ROOT::Experimental::Internal::RVirtualBinsToLocalBins
Recursively converts zero-based virtual bins where the underflow bin has index 0 and the overflow bin...
Definition: RHistImpl.hxx:613
ROOT::Experimental::Detail::RHistImplBase::RHistImplBase
RHistImplBase(const RHistImplBase &)=default