• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015-2018 Hans Dembinski
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <boost/core/lightweight_test.hpp>
8 #include <boost/histogram/algorithm/sum.hpp>
9 #include <boost/histogram/axis.hpp>
10 #include <boost/histogram/axis/ostream.hpp>
11 #include <boost/histogram/histogram.hpp>
12 #include <boost/histogram/ostream.hpp>
13 #include <string>
14 #include <utility>
15 #include "std_ostream.hpp"
16 #include "throw_exception.hpp"
17 #include "utility_histogram.hpp"
18 
19 using namespace boost::histogram;
20 
21 using def = use_default;
22 
23 using regular = axis::regular<double, def, def, axis::option::growth_t>;
24 
25 using integer = axis::integer<double, def,
26                               decltype(axis::option::underflow | axis::option::overflow |
27                                        axis::option::growth)>;
28 
29 using category = axis::category<std::string, def, axis::option::growth_t>;
30 
31 class custom_2d_axis {
32 public:
index(std::tuple<double,double> xy) const33   auto index(std::tuple<double, double> xy) const {
34     const auto x = std::get<0>(xy);
35     const auto y = std::get<1>(xy);
36     const auto r = std::sqrt(x * x + y * y);
37     return (std::min)(static_cast<axis::index_type>(r), size());
38   }
39 
update(std::tuple<double,double> xy)40   auto update(std::tuple<double, double> xy) {
41     const auto x = std::get<0>(xy);
42     const auto y = std::get<1>(xy);
43     const auto r = std::sqrt(x * x + y * y);
44     const auto n = static_cast<int>(r);
45     const auto old = size_;
46     if (n >= size_) size_ = n + 1;
47     return std::make_pair(n, old - size_);
48   }
49 
size() const50   axis::index_type size() const { return size_; }
51 
52 private:
53   axis::index_type size_ = 0;
54 };
55 
56 template <typename Tag>
run_tests()57 void run_tests() {
58   {
59     auto h = make(Tag(), regular(2, 0, 1));
60     const auto& a = h.axis();
61     BOOST_TEST_EQ(a.size(), 2);
62     BOOST_TEST_EQ(h.size(), 2);
63     // [0.0, 0.5, 1.0]
64     h(0.1);
65     h(0.9);
66     BOOST_TEST_EQ(a.size(), 2);
67     BOOST_TEST_EQ(h.size(), 2);
68     h(-std::numeric_limits<double>::infinity());
69     h(std::numeric_limits<double>::quiet_NaN());
70     h(std::numeric_limits<double>::infinity());
71     BOOST_TEST_EQ(a.size(), 2);
72     BOOST_TEST_EQ(h.size(), 2);
73     h(-0.3);
74     // [-0.5, 0.0, 0.5, 1.0]
75     BOOST_TEST_EQ(a.size(), 3);
76     BOOST_TEST_EQ(h.size(), 3);
77     BOOST_TEST_EQ(h[0], 1);
78     BOOST_TEST_EQ(h[1], 1);
79     BOOST_TEST_EQ(h[2], 1);
80     h(1.9);
81     // [-0.5, 0.0, 0.5, 1.0, 1.5, 2.0]
82     BOOST_TEST_EQ(a.size(), 5);
83     BOOST_TEST_EQ(h.size(), 5);
84     BOOST_TEST_EQ(h[0], 1);
85     BOOST_TEST_EQ(h[1], 1);
86     BOOST_TEST_EQ(h[2], 1);
87     BOOST_TEST_EQ(h[3], 0);
88     BOOST_TEST_EQ(h[4], 1);
89   }
90 
91   {
92     auto h = make_s(Tag(), std::vector<int>(), integer());
93     const auto& a = h.axis();
94     h(-std::numeric_limits<double>::infinity());
95     h(std::numeric_limits<double>::quiet_NaN());
96     h(std::numeric_limits<double>::infinity());
97     BOOST_TEST_EQ(a.size(), 0);
98     BOOST_TEST_EQ(h.size(), 2);
99     BOOST_TEST_EQ(h[-1], 1);
100     BOOST_TEST_EQ(h[0], 2);
101     h(0);
102     BOOST_TEST_EQ(a.size(), 1);
103     BOOST_TEST_EQ(h.size(), 3);
104     BOOST_TEST_EQ(h[-1], 1);
105     BOOST_TEST_EQ(h[0], 1);
106     BOOST_TEST_EQ(h[1], 2);
107     h(2);
108     BOOST_TEST_EQ(a.size(), 3);
109     BOOST_TEST_EQ(h.size(), 5);
110     BOOST_TEST_EQ(h[-1], 1);
111     BOOST_TEST_EQ(h[0], 1);
112     BOOST_TEST_EQ(h[1], 0);
113     BOOST_TEST_EQ(h[2], 1);
114     BOOST_TEST_EQ(h[3], 2);
115     h(-2);
116     BOOST_TEST_EQ(a.size(), 5);
117     BOOST_TEST_EQ(h.size(), 7);
118     // BOOST_TEST_EQ(h[-1], 1)
119     BOOST_TEST_EQ(h[0], 1);
120     BOOST_TEST_EQ(h[1], 0);
121     BOOST_TEST_EQ(h[2], 1);
122     BOOST_TEST_EQ(h[3], 0);
123     BOOST_TEST_EQ(h[4], 1);
124     BOOST_TEST_EQ(h[5], 2);
125   }
126 
127   {
128     auto h = make_s(Tag(), std::vector<int>(), integer(), category());
129     const auto& a = h.axis(0);
130     const auto& b = h.axis(1);
131     BOOST_TEST_EQ(a.size(), 0);
132     BOOST_TEST_EQ(b.size(), 0);
133     BOOST_TEST_EQ(h.size(), 0);
134     h(0, "x");
135     h(-std::numeric_limits<double>::infinity(), "x");
136     h(std::numeric_limits<double>::infinity(), "x");
137     h(std::numeric_limits<double>::quiet_NaN(), "x");
138     BOOST_TEST_EQ(a.size(), 1);
139     BOOST_TEST_EQ(b.size(), 1);
140     BOOST_TEST_EQ(h.size(), 3);
141     h(2, "x");
142     BOOST_TEST_EQ(a.size(), 3);
143     BOOST_TEST_EQ(b.size(), 1);
144     BOOST_TEST_EQ(h.size(), 5);
145     h(1, "y");
146     BOOST_TEST_EQ(a.size(), 3);
147     BOOST_TEST_EQ(b.size(), 2);
148     BOOST_TEST_EQ(h.size(), 10);
149     BOOST_TEST_EQ(h.at(-1, 0), 1);
150     BOOST_TEST_EQ(h.at(-1, 1), 0);
151     BOOST_TEST_EQ(h.at(3, 0), 2);
152     BOOST_TEST_EQ(h.at(3, 1), 0);
153     BOOST_TEST_EQ(h.at(a.index(0), b.index("x")), 1);
154     BOOST_TEST_EQ(h.at(a.index(1), b.index("x")), 0);
155     BOOST_TEST_EQ(h.at(a.index(2), b.index("x")), 1);
156     BOOST_TEST_EQ(h.at(a.index(0), b.index("y")), 0);
157     BOOST_TEST_EQ(h.at(a.index(1), b.index("y")), 1);
158     BOOST_TEST_EQ(h.at(a.index(2), b.index("y")), 0);
159 
160     BOOST_TEST_THROWS(h(0, "x", 42), std::invalid_argument);
161   }
162 
163   {
164     auto h = make_s(Tag{}, std::vector<int>{}, custom_2d_axis{});
165     BOOST_TEST_EQ(h.size(), 0);
166     h(0, 0);
167     BOOST_TEST_EQ(h.size(), 1);
168     h(1, 0);
169     h(0, 1);
170     BOOST_TEST_EQ(h.size(), 2);
171     h(10, 0);
172     BOOST_TEST_EQ(h.size(), 11);
173     BOOST_TEST_EQ(h[0], 1);
174     BOOST_TEST_EQ(h[1], 2);
175     BOOST_TEST_EQ(h[10], 1);
176     BOOST_TEST_THROWS(h(0), std::invalid_argument);
177   }
178 
179   // mix of a growing and a non-growing axis
180   {
181     using reg_nogrow = axis::regular<>;
182     auto h = make(Tag(), reg_nogrow{2, 0.0, 1.0}, regular{2, 0.0, 1.0});
183     BOOST_TEST_EQ(h.size(), 4 * 2);
184     h(0.0, 0.0);
185     BOOST_TEST_EQ(h.size(), 4 * 2);
186     BOOST_TEST_EQ(h.at(0, 0), 1);
187     h(-1.0, -0.1);
188     BOOST_TEST_EQ(h.size(), 4 * 3);
189     BOOST_TEST_EQ(h.at(-1, 0), 1);
190     h(2.0, 1.1);
191     BOOST_TEST_EQ(h.size(), 4 * 4);
192     // axis 0: [0.0, 0.5, 1.0] + under/overflow
193     // axis 1: [-0.5, 0.0, 0.5, 1.0, 1.5]
194     BOOST_TEST_EQ(h.at(-1, 0), 1);
195     BOOST_TEST_EQ(h.at(0, 1), 1);
196     BOOST_TEST_EQ(h.at(2, 3), 1);
197     BOOST_TEST_EQ(algorithm::sum(h), 3);
198   }
199 }
200 
main()201 int main() {
202   run_tests<static_tag>();
203   run_tests<dynamic_tag>();
204 
205   return boost::report_errors();
206 }
207