24 #include <initializer_list> 
   27 namespace Experimental {
 
   30 template <
int DIMENSIONS, 
class PRECISION, 
template <
int D_, 
class P_> 
class... STAT>
 
   34 template <
int DIMENSIONS, 
class PRECISION, 
template <
int D_, 
class P_> 
class... STAT>
 
   35 class RHist<DIMENSIONS, PRECISION, STAT...>
 
   36 HistFromImpl(std::unique_ptr<typename RHist<DIMENSIONS, PRECISION, STAT...>::ImplBase_t> pHistImpl);
 
   50 template <int DIMENSIONS, class PRECISION, template <int D_, class P_> class... STAT>
 
   55       Detail::RHistImplBase<Detail::RHistData<DIMENSIONS, PRECISION, std::vector<PRECISION>, STAT...>>;
 
   57    using CoordArray_t = 
typename ImplBase_t::CoordArray_t;
 
   59    using Weight_t = PRECISION;
 
   61    using FillFunc_t = 
typename ImplBase_t::FillFunc_t;
 
   63    using AxisRange_t = 
typename ImplBase_t::AxisIterRange_t;
 
   65    using const_iterator = Detail::RHistBinIter<ImplBase_t>;
 
   68    static constexpr 
int GetNDim() noexcept { 
return DIMENSIONS; }
 
   71    RHist(RHist &&) = 
default;
 
   72    RHist(
const RHist &other): fImpl(other.fImpl->Clone()), fFillFunc(other.fFillFunc)
 
   90    explicit RHist(std::array<RAxisConfig, DIMENSIONS> axes);
 
   93    RHist(std::string_view histTitle, std::array<RAxisConfig, DIMENSIONS> axes);
 
   96    template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 1>::type>
 
   97    explicit RHist(
const RAxisConfig &xaxis): RHist(std::array<RAxisConfig, 1>{{xaxis}})
 
  102    template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 1>::type>
 
  103    RHist(std::string_view histTitle, 
const RAxisConfig &xaxis): RHist(histTitle, std::array<RAxisConfig, 1>{{xaxis}})
 
  107    template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 2>::type>
 
  108    RHist(
const RAxisConfig &xaxis, 
const RAxisConfig &yaxis): RHist(std::array<RAxisConfig, 2>{{xaxis, yaxis}})
 
  113    template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 2>::type>
 
  114    RHist(std::string_view histTitle, 
const RAxisConfig &xaxis, 
const RAxisConfig &yaxis)
 
  115       : RHist(histTitle, std::array<RAxisConfig, 2>{{xaxis, yaxis}})
 
  119    template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 3>::type>
 
  120    RHist(
const RAxisConfig &xaxis, 
const RAxisConfig &yaxis, 
const RAxisConfig &zaxis)
 
  121       : RHist(std::array<RAxisConfig, 3>{{xaxis, yaxis, zaxis}})
 
  126    template <int ENABLEIF_NDIM = DIMENSIONS, class = typename std::enable_if<ENABLEIF_NDIM == 3>::type>
 
  127    RHist(std::string_view histTitle, 
const RAxisConfig &xaxis, 
const RAxisConfig &yaxis, 
const RAxisConfig &zaxis)
 
  128       : RHist(histTitle, std::array<RAxisConfig, 3>{{xaxis, yaxis, zaxis}})
 
  132    ImplBase_t *GetImpl() const noexcept { 
return fImpl.get(); }
 
  135    std::unique_ptr<ImplBase_t> TakeImpl() && noexcept { 
return std::move(fImpl); }
 
  138    void Fill(
const CoordArray_t &x, Weight_t weight = (Weight_t)1) noexcept { (fImpl.get()->*fFillFunc)(x, weight); }
 
  143    void FillN(
const std::span<const CoordArray_t> xN, 
const std::span<const Weight_t> weightN) noexcept
 
  145       fImpl->FillN(xN, weightN);
 
  149    void FillN(
const std::span<const CoordArray_t> xN) noexcept { fImpl->FillN(xN); }
 
  152    int64_t GetEntries() const noexcept { 
return fImpl->GetStat().GetEntries(); }
 
  155    Weight_t GetBinContent(
const CoordArray_t &x)
 const { 
return fImpl->GetBinContent(x); }
 
  158    double GetBinUncertainty(
const CoordArray_t &x)
 const { 
return fImpl->GetBinUncertainty(x); }
 
  160    const_iterator begin()
 const { 
return const_iterator(*fImpl); }
 
  162    const_iterator end()
 const { 
return const_iterator(*fImpl, fImpl->GetNBins()); }
 
  167    void swap(RHist<DIMENSIONS, PRECISION, STAT...> &other) noexcept
 
  169       std::swap(fImpl, other.fImpl);
 
  170       std::swap(fFillFunc, other.fFillFunc);
 
  174    std::unique_ptr<ImplBase_t> fImpl; 
 
  175    FillFunc_t fFillFunc = 
nullptr;    
 
  177    friend RHist HistFromImpl<>(std::unique_ptr<ImplBase_t>);
 
  181 template <
int DIMENSIONS, 
class PRECISION>
 
  182 class RHist<DIMENSIONS, PRECISION>: 
public RHist<DIMENSIONS, PRECISION, RHistStatContent> {
 
  183    using RHist<DIMENSIONS, PRECISION, RHistStatContent>::RHist;
 
  189 template <
int DIMENSIONS, 
class PRECISION, 
template <
int D_, 
class P_> 
class... STAT>
 
  190 void swap(RHist<DIMENSIONS, PRECISION, STAT...> &a, RHist<DIMENSIONS, PRECISION, STAT...> &b) noexcept
 
  199 template <
int NDIM, 
int IDIM, 
class DATA, 
class... PROCESSEDAXISCONFIG>
 
  200 struct RHistImplGen {
 
  203    template <RAxisConfig::EKind KIND>
 
  204    std::unique_ptr<Detail::RHistImplBase<DATA>>
 
  205    MakeNextAxis(std::string_view title, 
const std::array<RAxisConfig, NDIM> &axes,
 
  206                 PROCESSEDAXISCONFIG... processedAxisArgs)
 
  208       using NextAxis_t = 
typename AxisConfigToType<KIND>::Axis_t;
 
  209       NextAxis_t nextAxis = AxisConfigToType<KIND>()(axes[IDIM]);
 
  210       using HistImpl_t = RHistImplGen<NDIM, IDIM + 1, DATA, PROCESSEDAXISCONFIG..., NextAxis_t>;
 
  211       return HistImpl_t()(title, axes, processedAxisArgs..., nextAxis);
 
  226    std::unique_ptr<Detail::RHistImplBase<DATA>> operator()(std::string_view title,
 
  227                                                            const std::array<RAxisConfig, NDIM> &axes,
 
  228                                                            PROCESSEDAXISCONFIG... processedAxisArgs)
 
  230       switch (axes[IDIM].GetKind()) {
 
  231       case RAxisConfig::kEquidistant: 
return MakeNextAxis<RAxisConfig::kEquidistant>(title, axes, processedAxisArgs...);
 
  232       case RAxisConfig::kGrow: 
return MakeNextAxis<RAxisConfig::kGrow>(title, axes, processedAxisArgs...);
 
  233       case RAxisConfig::kIrregular: 
return MakeNextAxis<RAxisConfig::kIrregular>(title, axes, processedAxisArgs...);
 
  234       default: R__ERROR_HERE(
"HIST") << 
"Unhandled axis kind";
 
  241 template <
int NDIM, 
class DATA, 
class... PROCESSEDAXISCONFIG>
 
  244 struct RHistImplGen<NDIM, NDIM, DATA, PROCESSEDAXISCONFIG...> {
 
  245    using HistImplBase_t = ROOT::Experimental::Detail::RHistImplBase<DATA>;
 
  246    std::unique_ptr<HistImplBase_t>
 
  247    operator()(std::string_view title, 
const std::array<RAxisConfig, DATA::GetNDim()> &, PROCESSEDAXISCONFIG... axisArgs)
 
  249       using HistImplt_t = Detail::RHistImpl<DATA, PROCESSEDAXISCONFIG...>;
 
  250       return std::make_unique<HistImplt_t>(title, axisArgs...);
 
  255 template <
int DIMENSIONS, 
class PRECISION, 
template <
int D_, 
class P_> 
class... STAT>
 
  256 RHist<DIMENSIONS, PRECISION, STAT...>::RHist(std::string_view title, std::array<RAxisConfig, DIMENSIONS> axes)
 
  258         Internal::RHistImplGen<RHist::GetNDim(), 0,
 
  259                                Detail::RHistData<DIMENSIONS, PRECISION, std::vector<PRECISION>, STAT...>>()(
 
  262    fFillFunc = fImpl->GetFillFunc();
 
  265 template <
int DIMENSIONS, 
class PRECISION, 
template <
int D_, 
class P_> 
class... STAT>
 
  266 RHist<DIMENSIONS, PRECISION, STAT...>::RHist(std::array<RAxisConfig, DIMENSIONS> axes): RHist(
"", axes)
 
  270 template <
int DIMENSIONS, 
class PRECISION, 
template <
int D_, 
class P_> 
class... STAT>
 
  271 RHist<DIMENSIONS, PRECISION, STAT...>
 
  272 HistFromImpl(std::unique_ptr<
typename RHist<DIMENSIONS, PRECISION, STAT...>::ImplBase_t> pHistImpl)
 
  274    RHist<DIMENSIONS, PRECISION, STAT...> ret;
 
  275    ret.fFillFunc = pHistImpl->GetFillFunc();
 
  276    std::swap(ret.fImpl, pHistImpl);
 
  284 using RH1D = RHist<1, double, RHistStatContent, RHistStatUncertainty>;
 
  285 using RH1F = RHist<1, float, RHistStatContent, RHistStatUncertainty>;
 
  286 using RH1C = RHist<1, char, RHistStatContent>;
 
  287 using RH1I = RHist<1, int, RHistStatContent>;
 
  288 using RH1LL = RHist<1, int64_t, RHistStatContent>;
 
  290 using RH2D = RHist<2, double, RHistStatContent, RHistStatUncertainty>;
 
  291 using RH2F = RHist<2, float, RHistStatContent, RHistStatUncertainty>;
 
  292 using RH2C = RHist<2, char, RHistStatContent>;
 
  293 using RH2I = RHist<2, int, RHistStatContent>;
 
  294 using RH2LL = RHist<2, int64_t, RHistStatContent>;
 
  296 using RH3D = RHist<3, double, RHistStatContent, RHistStatUncertainty>;
 
  297 using RH3F = RHist<3, float, RHistStatContent, RHistStatUncertainty>;
 
  298 using RH3C = RHist<3, char, RHistStatContent>;
 
  299 using RH3I = RHist<3, int, RHistStatContent>;
 
  300 using RH3LL = RHist<3, int64_t, RHistStatContent>;
 
  305 template <
int DIMENSIONS, 
class PRECISION_TO, 
class PRECISION_FROM,
 
  306           template <
int D_, 
class P_> 
class... STAT_TO,
 
  307           template <
int D_, 
class P_> 
class... STAT_FROM>
 
  308 void Add(RHist<DIMENSIONS, PRECISION_TO, STAT_TO...> &to, 
const RHist<DIMENSIONS, PRECISION_FROM, STAT_FROM...> &from)
 
  310    auto toImpl = to.GetImpl();
 
  311    auto fillFuncTo = toImpl->GetFillFunc();
 
  312    using HistFrom_t = RHist<DIMENSIONS, PRECISION_FROM, STAT_FROM...>;
 
  313    using FromCoord_t = 
typename HistFrom_t::CoordArray_t;
 
  314    using FromWeight_t = 
typename HistFrom_t::Weight_t;
 
  315    auto add = [fillFuncTo, toImpl](
const FromCoord_t &x, FromWeight_t c) {
 
  316       (toImpl->*fillFuncTo)(x, c);
 
  319    from.GetImpl()->ApplyXC(add);