Skip to content

Commit c620481

Browse files
committed
[hist] Implement RBinIndex
This is a typed version of a bin number, with special values for underflow and overflow bins.
1 parent c84322f commit c620481

File tree

5 files changed

+281
-0
lines changed

5 files changed

+281
-0
lines changed

hist/histv7/headers.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
set(histv7_headers
22
ROOT/RAxes.hxx
3+
ROOT/RBinIndex.hxx
34
ROOT/RLinearizedIndex.hxx
45
ROOT/RRegularAxis.hxx
56
ROOT/RVariableBinAxis.hxx

hist/histv7/inc/ROOT/RBinIndex.hxx

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/// \file
2+
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
3+
/// is welcome!
4+
5+
#ifndef ROOT_RBinIndex
6+
#define ROOT_RBinIndex
7+
8+
#include <cassert>
9+
#include <cstddef>
10+
11+
namespace ROOT {
12+
namespace Experimental {
13+
14+
/**
15+
A bin index with special values for underflow and overflow bins.
16+
17+
Objects of this type should be passed by value.
18+
19+
\warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is
20+
welcome!
21+
*/
22+
class RBinIndex final {
23+
static constexpr std::size_t UnderflowIndex = -3;
24+
static constexpr std::size_t OverflowIndex = -2;
25+
static constexpr std::size_t InvalidIndex = -1;
26+
27+
std::size_t fIndex = InvalidIndex;
28+
29+
public:
30+
/// Construct an invalid bin index.
31+
RBinIndex() = default;
32+
33+
/// Construct a bin index for a normal bin.
34+
RBinIndex(std::size_t index) : fIndex(index) { assert(IsNormal()); }
35+
36+
/// Return the index for a normal bin.
37+
std::size_t GetIndex() const
38+
{
39+
assert(IsNormal());
40+
return fIndex;
41+
}
42+
43+
/// A bin index is normal iff it is not one of the special values.
44+
///
45+
/// Note that a normal bin index may not actually be valid for a given axis if it is outside its range.
46+
bool IsNormal() const { return fIndex < UnderflowIndex; }
47+
bool IsUnderflow() const { return fIndex == UnderflowIndex; }
48+
bool IsOverflow() const { return fIndex == OverflowIndex; }
49+
bool IsInvalid() const { return fIndex == InvalidIndex; }
50+
51+
RBinIndex &operator+=(std::size_t a)
52+
{
53+
assert(IsNormal());
54+
fIndex += a;
55+
// TODO: is it possible to catch overflows?
56+
assert(IsNormal());
57+
return *this;
58+
}
59+
60+
RBinIndex operator+(std::size_t a) const
61+
{
62+
RBinIndex ret = *this;
63+
ret += a;
64+
return ret;
65+
}
66+
67+
RBinIndex &operator++()
68+
{
69+
operator+=(1);
70+
return *this;
71+
}
72+
73+
RBinIndex operator++(int)
74+
{
75+
RBinIndex old = *this;
76+
operator++();
77+
return old;
78+
}
79+
80+
RBinIndex &operator-=(std::size_t a)
81+
{
82+
assert(IsNormal());
83+
assert(fIndex >= a);
84+
fIndex -= a;
85+
assert(IsNormal());
86+
return *this;
87+
}
88+
89+
RBinIndex operator-(std::size_t a) const
90+
{
91+
RBinIndex ret = *this;
92+
ret -= a;
93+
return ret;
94+
}
95+
96+
RBinIndex &operator--()
97+
{
98+
operator-=(1);
99+
return *this;
100+
}
101+
102+
RBinIndex operator--(int)
103+
{
104+
RBinIndex old = *this;
105+
operator--();
106+
return old;
107+
}
108+
109+
friend bool operator==(RBinIndex lhs, RBinIndex rhs) { return lhs.fIndex == rhs.fIndex; }
110+
friend bool operator!=(RBinIndex lhs, RBinIndex rhs) { return !(lhs == rhs); }
111+
112+
friend bool operator<(RBinIndex lhs, RBinIndex rhs)
113+
{
114+
if (lhs.IsNormal() && rhs.IsNormal()) {
115+
return lhs.fIndex < rhs.fIndex;
116+
}
117+
return false;
118+
}
119+
friend bool operator<=(RBinIndex lhs, RBinIndex rhs) { return lhs == rhs || lhs < rhs; }
120+
121+
friend bool operator>(RBinIndex lhs, RBinIndex rhs)
122+
{
123+
if (lhs.IsNormal() && rhs.IsNormal()) {
124+
return lhs.fIndex > rhs.fIndex;
125+
}
126+
return false;
127+
}
128+
friend bool operator>=(RBinIndex lhs, RBinIndex rhs) { return lhs == rhs || lhs > rhs; }
129+
130+
static RBinIndex Underflow()
131+
{
132+
RBinIndex underflow;
133+
underflow.fIndex = UnderflowIndex;
134+
return underflow;
135+
}
136+
137+
static RBinIndex Overflow()
138+
{
139+
RBinIndex overflow;
140+
overflow.fIndex = OverflowIndex;
141+
return overflow;
142+
}
143+
};
144+
145+
} // namespace Experimental
146+
} // namespace ROOT
147+
148+
#endif

hist/histv7/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
HIST_ADD_GTEST(hist_axes hist_axes.cxx)
2+
HIST_ADD_GTEST(hist_index hist_index.cxx)
23
HIST_ADD_GTEST(hist_regular hist_regular.cxx)
34
HIST_ADD_GTEST(hist_variable hist_variable.cxx)
45

hist/histv7/test/hist_index.cxx

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#include "hist_test.hxx"
2+
3+
TEST(RBinIndex, Constructor)
4+
{
5+
const RBinIndex invalid;
6+
EXPECT_TRUE(invalid.IsInvalid());
7+
8+
const RBinIndex index(0);
9+
EXPECT_TRUE(index.IsNormal());
10+
EXPECT_EQ(index.GetIndex(), 0);
11+
12+
const auto underflow = RBinIndex::Underflow();
13+
EXPECT_FALSE(underflow.IsNormal());
14+
EXPECT_TRUE(underflow.IsUnderflow());
15+
16+
const auto overflow = RBinIndex::Overflow();
17+
EXPECT_FALSE(overflow.IsNormal());
18+
EXPECT_TRUE(overflow.IsOverflow());
19+
}
20+
21+
TEST(RBinIndex, Plus)
22+
{
23+
const RBinIndex index1(1);
24+
ASSERT_EQ(index1.GetIndex(), 1);
25+
26+
{
27+
auto index2 = index1;
28+
EXPECT_EQ((++index2).GetIndex(), 2);
29+
EXPECT_EQ(index2.GetIndex(), 2);
30+
}
31+
32+
{
33+
auto index2 = index1;
34+
EXPECT_EQ((index2++).GetIndex(), 1);
35+
EXPECT_EQ(index2.GetIndex(), 2);
36+
}
37+
38+
{
39+
auto index3 = index1;
40+
EXPECT_EQ((index3 += 2).GetIndex(), 3);
41+
EXPECT_EQ(index3.GetIndex(), 3);
42+
}
43+
44+
{
45+
const auto index3 = index1 + 2;
46+
EXPECT_EQ(index3.GetIndex(), 3);
47+
}
48+
}
49+
50+
TEST(RBinIndex, Minus)
51+
{
52+
const RBinIndex index3(3);
53+
ASSERT_EQ(index3.GetIndex(), 3);
54+
55+
{
56+
auto index2 = index3;
57+
EXPECT_EQ((--index2).GetIndex(), 2);
58+
EXPECT_EQ(index2.GetIndex(), 2);
59+
}
60+
61+
{
62+
auto index2 = index3;
63+
EXPECT_EQ((index2--).GetIndex(), 3);
64+
EXPECT_EQ(index2.GetIndex(), 2);
65+
}
66+
67+
{
68+
auto index1 = index3;
69+
EXPECT_EQ((index1 -= 2).GetIndex(), 1);
70+
EXPECT_EQ(index1.GetIndex(), 1);
71+
}
72+
73+
{
74+
const auto index1 = index3 - 2;
75+
EXPECT_EQ(index1.GetIndex(), 1);
76+
}
77+
}
78+
79+
TEST(RBinIndex, Equality)
80+
{
81+
RBinIndex index(1);
82+
EXPECT_EQ(index, RBinIndex(1));
83+
index++;
84+
EXPECT_EQ(index, RBinIndex(2));
85+
EXPECT_NE(index, RBinIndex(3));
86+
87+
const auto underflow = RBinIndex::Underflow();
88+
EXPECT_EQ(underflow, RBinIndex::Underflow());
89+
EXPECT_NE(index, underflow);
90+
91+
const auto overflow = RBinIndex::Overflow();
92+
EXPECT_EQ(overflow, RBinIndex::Overflow());
93+
EXPECT_NE(index, overflow);
94+
EXPECT_NE(underflow, overflow);
95+
}
96+
97+
TEST(RBinIndex, Relation)
98+
{
99+
const RBinIndex index1(1);
100+
EXPECT_LE(index1, index1);
101+
EXPECT_GE(index1, index1);
102+
103+
const RBinIndex index2(2);
104+
EXPECT_LT(index1, index2);
105+
EXPECT_LE(index1, index2);
106+
EXPECT_GT(index2, index1);
107+
EXPECT_GE(index2, index1);
108+
109+
const auto underflow = RBinIndex::Underflow();
110+
EXPECT_LE(underflow, RBinIndex::Underflow());
111+
EXPECT_GE(underflow, RBinIndex::Underflow());
112+
EXPECT_FALSE(index1 < underflow);
113+
EXPECT_FALSE(index1 <= underflow);
114+
EXPECT_FALSE(index1 > underflow);
115+
EXPECT_FALSE(index1 >= underflow);
116+
117+
const auto overflow = RBinIndex::Overflow();
118+
EXPECT_LE(overflow, RBinIndex::Overflow());
119+
EXPECT_GE(overflow, RBinIndex::Overflow());
120+
EXPECT_FALSE(index1 < overflow);
121+
EXPECT_FALSE(index1 <= overflow);
122+
EXPECT_FALSE(index1 > overflow);
123+
EXPECT_FALSE(index1 >= overflow);
124+
125+
EXPECT_FALSE(underflow < overflow);
126+
EXPECT_FALSE(underflow <= overflow);
127+
EXPECT_FALSE(underflow > overflow);
128+
EXPECT_FALSE(underflow >= overflow);
129+
}

hist/histv7/test/hist_test.hxx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
#define hist_test
33

44
#include <ROOT/RAxes.hxx>
5+
#include <ROOT/RBinIndex.hxx>
56
#include <ROOT/RRegularAxis.hxx>
67
#include <ROOT/RVariableBinAxis.hxx>
78

89
#include "gtest/gtest.h"
910

11+
using ROOT::Experimental::RBinIndex;
1012
using ROOT::Experimental::RRegularAxis;
1113
using ROOT::Experimental::RVariableBinAxis;
1214
using ROOT::Experimental::Internal::RAxes;

0 commit comments

Comments
 (0)