Skip to content

Commit a134024

Browse files
committed
[hist] Implement RHist{,Stats}::AddAtomic
1 parent 9178e3c commit a134024

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

hist/histv7/inc/ROOT/RHist.hxx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,17 @@ public:
174174
fStats.Add(other.fStats);
175175
}
176176

177+
/// Add all bin contents and statistics of another histogram using atomic instructions.
178+
///
179+
/// Throws an exception if the axes configurations are not identical.
180+
///
181+
/// \param[in] other another histogram
182+
void AddAtomic(const RHist<BinContentType> &other)
183+
{
184+
fEngine.AddAtomic(other.fEngine);
185+
fStats.AddAtomic(other.fStats);
186+
}
187+
177188
/// Clear all bin contents and statistics.
178189
void Clear()
179190
{

hist/histv7/inc/ROOT/RHistStats.hxx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ public:
6868
fSumWX4 += other.fSumWX4;
6969
}
7070

71+
void AddAtomic(const RDimensionStats &other)
72+
{
73+
Internal::AtomicAdd(&fSumWX, other.fSumWX);
74+
Internal::AtomicAdd(&fSumWX2, other.fSumWX2);
75+
Internal::AtomicAdd(&fSumWX3, other.fSumWX3);
76+
Internal::AtomicAdd(&fSumWX4, other.fSumWX4);
77+
}
78+
7179
void Clear()
7280
{
7381
fSumWX = 0.0;
@@ -125,6 +133,24 @@ public:
125133
}
126134
}
127135

136+
/// Add all entries from another statistics object using atomic instructions.
137+
///
138+
/// Throws an exception if the number of dimensions are not identical.
139+
///
140+
/// \param[in] other another statistics object
141+
void AddAtomic(const RHistStats &other)
142+
{
143+
if (fDimensionStats.size() != other.fDimensionStats.size()) {
144+
throw std::invalid_argument("number of dimensions not identical in Add");
145+
}
146+
Internal::AtomicAdd(&fNEntries, other.fNEntries);
147+
Internal::AtomicAdd(&fSumW, other.fSumW);
148+
Internal::AtomicAdd(&fSumW2, other.fSumW2);
149+
for (std::size_t i = 0; i < fDimensionStats.size(); i++) {
150+
fDimensionStats[i].AddAtomic(other.fDimensionStats[i]);
151+
}
152+
}
153+
128154
/// Clear this statistics object.
129155
void Clear()
130156
{

hist/histv7/test/hist_hist.cxx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ TEST(RHist, Add)
5252
EXPECT_EQ(histA.GetBinContent(RBinIndex(9)), 1);
5353
}
5454

55+
TEST(RHist, AddAtomic)
56+
{
57+
static constexpr std::size_t Bins = 20;
58+
const RRegularAxis axis(Bins, {0, Bins});
59+
RHist<int> histA({axis});
60+
RHist<int> histB({axis});
61+
62+
histA.Fill(8.5);
63+
histB.Fill(9.5);
64+
65+
histA.AddAtomic(histB);
66+
67+
EXPECT_EQ(histA.GetNEntries(), 2);
68+
EXPECT_EQ(histA.GetBinContent(RBinIndex(8)), 1);
69+
EXPECT_EQ(histA.GetBinContent(RBinIndex(9)), 1);
70+
}
71+
5572
TEST(RHist, Clear)
5673
{
5774
static constexpr std::size_t Bins = 20;

hist/histv7/test/hist_stats.cxx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,47 @@ TEST(RHistStats, AddDifferent)
123123
EXPECT_THROW(statsA.Add(statsB), std::invalid_argument);
124124
}
125125

126+
TEST(RHistStats, AddAtomic)
127+
{
128+
RHistStats statsA(2);
129+
RHistStats statsB(2);
130+
131+
static constexpr std::size_t Entries = 20;
132+
for (std::size_t i = 0; i < Entries; i++) {
133+
statsA.Fill(i, 2 * i);
134+
statsB.Fill(2 * i, 3 * i, RWeight(0.1 + 0.03 * i));
135+
}
136+
137+
statsA.AddAtomic(statsB);
138+
139+
ASSERT_EQ(statsA.GetNEntries(), 2 * Entries);
140+
EXPECT_DOUBLE_EQ(statsA.GetSumW(), 27.7);
141+
EXPECT_DOUBLE_EQ(statsA.GetSumW2(), 23.563);
142+
143+
{
144+
const auto &dimensionStats = statsA.GetDimensionStats(/*=0*/);
145+
EXPECT_FLOAT_EQ(dimensionStats.fSumWX, 376.2);
146+
EXPECT_FLOAT_EQ(dimensionStats.fSumWX2, 7790);
147+
EXPECT_FLOAT_EQ(dimensionStats.fSumWX3, 200019.84);
148+
EXPECT_FLOAT_EQ(dimensionStats.fSumWX4, 5846915.6);
149+
}
150+
{
151+
const auto &dimensionStats = statsA.GetDimensionStats(1);
152+
EXPECT_FLOAT_EQ(dimensionStats.fSumWX, 659.3);
153+
EXPECT_FLOAT_EQ(dimensionStats.fSumWX2, 21850);
154+
EXPECT_FLOAT_EQ(dimensionStats.fSumWX3, 842029.46);
155+
EXPECT_FLOAT_EQ(dimensionStats.fSumWX4, 35754169.6);
156+
}
157+
}
158+
159+
TEST(RHistStats, AddAtomicDifferent)
160+
{
161+
RHistStats statsA(2);
162+
RHistStats statsB(3);
163+
164+
EXPECT_THROW(statsA.AddAtomic(statsB), std::invalid_argument);
165+
}
166+
126167
TEST(RHistStats, Clear)
127168
{
128169
RHistStats stats(2);

0 commit comments

Comments
 (0)