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