Skip to content

Commit 38650b6

Browse files
committed
[hist] Support weighted filling with user-defined types
Weaken SupportsWeightedFilling to forbid integral types.
1 parent 4a215ce commit 38650b6

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

hist/histv7/inc/ROOT/RHist.hxx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ hist.Fill(8.5);
3232
// hist.GetBinContent(ROOT::Experimental::RBinIndex(3)) will return 1
3333
\endcode
3434
35-
The class is templated on the bin content type. For counting, as in the example above, it may be an integer type such as
36-
`int` or `long`. Narrower types such as `unsigned char` or `short` are supported, but may overflow due to their limited
37-
range and must be used with care. For weighted filling, the bin content type must be a floating-point type such as
38-
`float` or `double`, or the special type RBinWithError. Note that `float` has a limited significand precision of 24
39-
bits.
35+
The class is templated on the bin content type. For counting, as in the example above, it may be an integral type such
36+
as `int` or `long`. Narrower types such as `unsigned char` or `short` are supported, but may overflow due to their
37+
limited range and must be used with care. For weighted filling, the bin content type must not be an integral type, but
38+
a floating-point type such as `float` or `double`, or the special type RBinWithError. Note that `float` has a limited
39+
significand precision of 24 bits.
4040
4141
An object can have arbitrary dimensionality determined at run-time. The axis configuration is passed as a vector of
4242
RAxisVariant:
@@ -220,8 +220,7 @@ public:
220220

221221
/// Fill an entry into the histogram with a weight.
222222
///
223-
/// This overload is only available for floating-point bin content types (see
224-
/// \ref RHistEngine::SupportsWeightedFilling).
223+
/// This overload is not available for integral bin content types (see \ref RHistEngine::SupportsWeightedFilling).
225224
///
226225
/// \code
227226
/// ROOT::Experimental::RHist<float> hist({/* two dimensions */});
@@ -259,7 +258,7 @@ public:
259258
/// ROOT::Experimental::RHist<float> hist({/* two dimensions */});
260259
/// hist.Fill(8.5, 10.5, ROOT::Experimental::RWeight(0.8));
261260
/// \endcode
262-
/// This is only available for floating-point bin content types (see \ref RHistEngine::SupportsWeightedFilling).
261+
/// This is not available for integral bin content types (see \ref RHistEngine::SupportsWeightedFilling).
263262
///
264263
/// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
265264
/// discarded.

hist/histv7/inc/ROOT/RHistEngine.hxx

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
#include "RAxes.hxx"
99
#include "RBinIndex.hxx"
10-
#include "RBinWithError.hxx"
1110
#include "RHistUtils.hxx"
1211
#include "RLinearizedIndex.hxx"
1312
#include "RRegularAxis.hxx"
@@ -37,11 +36,11 @@ hist.Fill(8.5);
3736
// hist.GetBinContent(ROOT::Experimental::RBinIndex(3)) will return 1
3837
\endcode
3938
40-
The class is templated on the bin content type. For counting, as in the example above, it may be an integer type such as
41-
`int` or `long`. Narrower types such as `unsigned char` or `short` are supported, but may overflow due to their limited
42-
range and must be used with care. For weighted filling, the bin content type must be a floating-point type such as
43-
`float` or `double`, or the special type RBinWithError. Note that `float` has a limited significand precision of 24
44-
bits.
39+
The class is templated on the bin content type. For counting, as in the example above, it may be an integral type such
40+
as `int` or `long`. Narrower types such as `unsigned char` or `short` are supported, but may overflow due to their
41+
limited range and must be used with care. For weighted filling, the bin content type must not be an integral type, but
42+
a floating-point type such as `float` or `double`, or the special type RBinWithError. Note that `float` has a limited
43+
significand precision of 24 bits.
4544
4645
An object can have arbitrary dimensionality determined at run-time. The axis configuration is passed as a vector of
4746
RAxisVariant:
@@ -209,8 +208,7 @@ public:
209208
}
210209

211210
/// Whether this histogram engine type supports weighted filling.
212-
static constexpr bool SupportsWeightedFilling =
213-
std::is_floating_point_v<BinContentType> || std::is_same_v<BinContentType, RBinWithError>;
211+
static constexpr bool SupportsWeightedFilling = !std::is_integral_v<BinContentType>;
214212

215213
/// Fill an entry into the histogram.
216214
///
@@ -247,7 +245,7 @@ public:
247245

248246
/// Fill an entry into the histogram with a weight.
249247
///
250-
/// This overload is only available for floating-point bin content types (see \ref SupportsWeightedFilling).
248+
/// This overload is not available for integral bin content types (see \ref SupportsWeightedFilling).
251249
///
252250
/// \code
253251
/// ROOT::Experimental::RHistEngine<float> hist({/* two dimensions */});
@@ -269,7 +267,7 @@ public:
269267
template <typename... A>
270268
void Fill(const std::tuple<A...> &args, RWeight weight)
271269
{
272-
static_assert(SupportsWeightedFilling, "weighted filling is only supported for floating-point bin content types");
270+
static_assert(SupportsWeightedFilling, "weighted filling is not supported for integral bin content types");
273271

274272
// We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
275273
// be confusing for users.
@@ -295,7 +293,7 @@ public:
295293
/// ROOT::Experimental::RHistEngine<float> hist({/* two dimensions */});
296294
/// hist.Fill(8.5, 10.5, ROOT::Experimental::RWeight(0.8));
297295
/// \endcode
298-
/// This is only available for floating-point bin content types (see \ref SupportsWeightedFilling).
296+
/// This is not available for integral bin content types (see \ref SupportsWeightedFilling).
299297
///
300298
/// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
301299
/// discarded.
@@ -312,8 +310,7 @@ public:
312310
{
313311
auto t = std::forward_as_tuple(args...);
314312
if constexpr (std::is_same_v<typename Internal::LastType<A...>::type, RWeight>) {
315-
static_assert(SupportsWeightedFilling,
316-
"weighted filling is only supported for floating-point bin content types");
313+
static_assert(SupportsWeightedFilling, "weighted filling is not supported for integral bin content types");
317314
static constexpr std::size_t N = sizeof...(A) - 1;
318315
if (N != fAxes.GetNDimensions()) {
319316
throw std::invalid_argument("invalid number of arguments to Fill");

hist/histv7/test/hist_user.cxx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ struct User {
1919
return old;
2020
}
2121

22+
User &operator+=(double w)
23+
{
24+
fValue += w;
25+
return *this;
26+
}
27+
2228
User &operator+=(const User &rhs)
2329
{
2430
fValue += rhs.fValue;
@@ -98,3 +104,18 @@ TEST(RHistEngineUser, Fill)
98104
std::array<RBinIndex, 1> indices = {9};
99105
EXPECT_EQ(engine.GetBinContent(indices).fValue, 1);
100106
}
107+
108+
TEST(RHistEngineUser, FillWeight)
109+
{
110+
// Weighted filling uses operator+=(double)
111+
static constexpr std::size_t Bins = 20;
112+
const RRegularAxis axis(Bins, {0, Bins});
113+
RHistEngine<User> engine({axis});
114+
115+
engine.Fill(8.5, RWeight(0.8));
116+
engine.Fill(std::make_tuple(9.5), RWeight(0.9));
117+
118+
EXPECT_EQ(engine.GetBinContent(RBinIndex(8)).fValue, 0.8);
119+
std::array<RBinIndex, 1> indices = {9};
120+
EXPECT_EQ(engine.GetBinContent(indices).fValue, 0.9);
121+
}

0 commit comments

Comments
 (0)