1 // Copyright 2019 Przemyslaw Bartosik
2 // Copyright 2019 Hans Dembinski
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt
6 // or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8 #include <boost/core/lightweight_test.hpp>
9 #include <boost/histogram/accumulators/mean.hpp>
10 #include <boost/histogram/accumulators/ostream.hpp>
11 #include <boost/histogram/axis/category.hpp>
12 #include <boost/histogram/axis/integer.hpp>
13 #include <boost/histogram/axis/option.hpp>
14 #include <boost/histogram/axis/regular.hpp>
15 #include <boost/histogram/make_histogram.hpp>
16 #include <boost/histogram/ostream.hpp>
17 #include <limits>
18 #include <sstream>
19 #include <string>
20 #include "throw_exception.hpp"
21 #include "utility_histogram.hpp"
22
23 using namespace boost::histogram;
24
25 template <class Histogram>
str(const Histogram & h,const unsigned width=0)26 auto str(const Histogram& h, const unsigned width = 0) {
27 std::ostringstream os;
28 // BEGIN and END make nicer error messages
29 os << "BEGIN\n" << std::setw(width) << h << "END";
30 return os.str();
31 }
32
33 template <class Tag>
run_tests()34 void run_tests() {
35 using R = axis::regular<>;
36 using R2 =
37 axis::regular<double, boost::use_default, axis::null_type, axis::option::none_t>;
38 using R3 = axis::regular<double, axis::transform::log>;
39 using C = axis::category<std::string>;
40 using I = axis::integer<>;
41
42 // regular
43 {
44 auto h = make(Tag(), R(3, -0.5, 1.0));
45 h.at(0) = 1;
46 h.at(1) = 10;
47 h.at(2) = 5;
48
49 const auto expected =
50 "BEGIN\n"
51 "histogram(regular(3, -0.5, 1, options=underflow | overflow))\n"
52 " +------------------------------------------------------------+\n"
53 "[-inf, -0.5) 0 | |\n"
54 "[-0.5, 0) 1 |====== |\n"
55 "[ 0, 0.5) 10 |=========================================================== |\n"
56 "[ 0.5, 1) 5 |============================== |\n"
57 "[ 1, inf) 0 | |\n"
58 " +------------------------------------------------------------+\n"
59 "END";
60
61 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
62 }
63
64 // regular, narrow
65 {
66 auto h = make(Tag(), R2(3, -0.5, 1.0));
67 h.at(0) = 1;
68 h.at(1) = 10;
69 h.at(2) = 2;
70
71 const auto expected = "BEGIN\n"
72 "histogram(regular(3, -0.5, 1, options=none))\n"
73 " +-----------------------+\n"
74 "[-0.5, 0) 1 |== |\n"
75 "[ 0, 0.5) 10 |====================== |\n"
76 "[ 0.5, 1) 2 |==== |\n"
77 " +-----------------------+\n"
78 "END";
79
80 BOOST_TEST_CSTR_EQ(str(h, 40).c_str(), expected);
81
82 // too narrow
83 BOOST_TEST_CSTR_EQ(str(h, 10).c_str(),
84 "BEGIN\n"
85 "histogram(regular(3, -0.5, 1, options=none))END");
86 }
87
88 // regular2
89 {
90 auto h = make(Tag(), R2(3, -0.5, 1.0));
91 h.at(0) = 1;
92 h.at(1) = -5;
93 h.at(2) = 2;
94
95 const auto expected =
96 "BEGIN\n"
97 "histogram(regular(3, -0.5, 1, options=none))\n"
98 " +-------------------------------------------------------------+\n"
99 "[-0.5, 0) 1 | ========= |\n"
100 "[ 0, 0.5) -5 |=========================================== |\n"
101 "[ 0.5, 1) 2 | ================= |\n"
102 " +-------------------------------------------------------------+\n"
103 "END";
104
105 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
106 }
107
108 // regular with log
109 {
110 auto h = make(Tag(), R3(6, 1e-3, 1e3, "foo"));
111
112 const auto expected =
113 "BEGIN\n"
114 "histogram(regular(transform::log{}, 6, 0.001, 1000, metadata=\"foo\", "
115 "options=underflow | overflow))\n"
116 " +-----------------------------------------------------------+\n"
117 "[ 0, 0.001) 0 | |\n"
118 "[0.001, 0.01) 0 | |\n"
119 "[ 0.01, 0.1) 0 | |\n"
120 "[ 0.1, 1) 0 | |\n"
121 "[ 1, 10) 0 | |\n"
122 "[ 10, 100) 0 | |\n"
123 "[ 100, 1000) 0 | |\n"
124 "[ 1000, inf) 0 | |\n"
125 " +-----------------------------------------------------------+\n"
126 "END";
127
128 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
129 }
130
131 // integer
132 {
133 auto h = make(Tag(), I(0, 1));
134 h.at(0) = -10;
135 h.at(1) = 5;
136
137 const auto expected =
138 "BEGIN\n"
139 "histogram(integer(0, 1, options=underflow | overflow))\n"
140 " +---------------------------------------------------------------------+\n"
141 "-1 0 | |\n"
142 " 0 -10 |============================================= |\n"
143 " 1 5 | ======================= |\n"
144 " +---------------------------------------------------------------------+\n"
145 "END";
146
147 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
148 }
149
150 // catorgy<string>
151 {
152 auto h = make(Tag(), C({"a", "bb", "ccc", "dddd"}));
153 h.at(0) = 1.23;
154 h.at(1) = 1;
155 h.at(2) = 1.2345789e-3;
156 h.at(3) = 1.2345789e-12;
157 h.at(4) = std::numeric_limits<double>::quiet_NaN();
158
159 const auto expected =
160 "BEGIN\n"
161 "histogram(category(\"a\", \"bb\", \"ccc\", \"dddd\", options=overflow))\n"
162 " +------------------------------------------------------------+\n"
163 " a 1.23 |=========================================================== |\n"
164 " bb 1 |================================================ |\n"
165 " ccc 0.001235 | |\n"
166 " dddd 1.235e-12 | |\n"
167 "other nan | |\n"
168 " +------------------------------------------------------------+\n"
169 "END";
170
171 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
172 }
173
174 // histogram with axis that has no value method
175 {
176 struct minimal_axis {
177 int index(int x) const { return x % 2; }
178 int size() const { return 2; }
179 };
180
181 auto h = make(Tag(), minimal_axis{});
182 h.at(0) = 3;
183 h.at(1) = 4;
184
185 const auto expected =
186 "BEGIN\n"
187 "histogram(" +
188 detail::type_name<minimal_axis>() +
189 ")\n"
190 " +------------------------------------------------------------------------+\n"
191 "0 3 |===================================================== |\n"
192 "1 4 |======================================================================= |\n"
193 " +------------------------------------------------------------------------+\n"
194 "END";
195
196 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected.c_str());
197 }
198
199 // fallback for 2D
200 {
201 auto h = make(Tag(), R(1, -1, 1), R(2, -4, 7));
202 h.at(-1, 0) = 1000;
203 h.at(-1, -1) = 123;
204 h.at(1, 0) = 1.23456789;
205 h.at(-1, 2) = std::numeric_limits<double>::quiet_NaN();
206
207 const auto expected =
208 "BEGIN\n"
209 "histogram(\n"
210 " regular(1, -1, 1, options=underflow | overflow)\n"
211 " regular(2, -4, 7, options=underflow | overflow)\n"
212 " (-1 -1): 123 ( 0 -1): 0 ( 1 -1): 0 (-1 0): 1000 \n"
213 " ( 0 0): 0 ( 1 0): 1.235 (-1 1): 0 ( 0 1): 0 \n"
214 " ( 1 1): 0 (-1 2): nan ( 0 2): 0 ( 1 2): 0 \n"
215 ")END";
216
217 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
218 }
219
220 // fallback for profile
221 {
222 auto h = make_s(Tag(), profile_storage(), R(1, -1, 1));
223 h.at(0) = accumulators::mean<>(10, 100, 1000);
224
225 const auto expected = "BEGIN\n"
226 "histogram(\n"
227 " regular(1, -1, 1, options=underflow | overflow)\n"
228 " (-1): mean(0, 0, -0) ( 0): mean(10, 100, 1000)\n"
229 " ( 1): mean(0, 0, -0) \n"
230 ")END";
231
232 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
233 }
234 }
235
main()236 int main() {
237 run_tests<static_tag>();
238 run_tests<dynamic_tag>();
239
240 {
241 // cannot make empty static histogram
242 auto h = histogram<std::vector<axis::regular<>>>();
243
244 const auto expected = "BEGIN\n"
245 "histogram()END";
246
247 BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
248 }
249
250 return boost::report_errors();
251 }
252