Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / histogram / test / indexed_test.cpp
1 // Copyright 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 <algorithm>
8 #include <boost/core/lightweight_test.hpp>
9 #include <boost/histogram/axis/integer.hpp>
10 #include <boost/histogram/axis/ostream.hpp>
11 #include <boost/histogram/axis/variable.hpp>
12 #include <boost/histogram/histogram.hpp>
13 #include <boost/histogram/indexed.hpp>
14 #include <boost/histogram/literals.hpp>
15 #include <boost/histogram/ostream.hpp>
16 #include <boost/mp11/algorithm.hpp>
17 #include <boost/mp11/list.hpp>
18 #include <iterator>
19 #include <ostream>
20 #include <type_traits>
21 #include <vector>
22 #include "throw_exception.hpp"
23 #include "utility_histogram.hpp"
24
25 using namespace boost::histogram;
26 using namespace boost::histogram::literals;
27 using namespace boost::mp11;
28
29 template <class IsDynamic, class Coverage>
30 void run_1d_tests(mp_list<IsDynamic, Coverage>) {
31   auto h = make(IsDynamic(), axis::integer<>(0, 3));
32   h(-1, weight(1));
33   h(0, weight(2));
34   h(1, weight(3));
35   h(2, weight(4));
36   h(3, weight(5));
37
38   auto ind = indexed(h, Coverage());
39   auto it = ind.begin();
40   BOOST_TEST_EQ(it->indices().size(), 1);
41   BOOST_TEST_EQ(it->indices()[0], Coverage() == coverage::all ? -1 : 0);
42
43   if (Coverage() == coverage::all) {
44     BOOST_TEST_EQ(it->index(0), -1);
45     BOOST_TEST_EQ(**it, 1);
46     BOOST_TEST_EQ(it->bin(0), h.axis().bin(-1));
47     ++it;
48   }
49   BOOST_TEST_EQ(it->index(0), 0);
50   BOOST_TEST_EQ(**it, 2);
51   BOOST_TEST_EQ(it->bin(0), h.axis().bin(0));
52   ++it;
53   BOOST_TEST_EQ(it->index(0), 1);
54   BOOST_TEST_EQ(**it, 3);
55   BOOST_TEST_EQ(it->bin(0), h.axis().bin(1));
56   ++it;
57   // check post-increment
58   auto prev = it++;
59   BOOST_TEST_EQ(prev->index(0), 2);
60   BOOST_TEST_EQ(**prev, 4);
61   BOOST_TEST_EQ(prev->bin(0), h.axis().bin(2));
62   if (Coverage() == coverage::all) {
63     BOOST_TEST_EQ(it->index(0), 3);
64     BOOST_TEST_EQ(**it, 5);
65     BOOST_TEST_EQ(it->bin(0), h.axis().bin(3));
66     ++it;
67   }
68   BOOST_TEST(it == ind.end());
69
70   for (auto&& x : indexed(h, Coverage())) *x = 0;
71
72   for (auto&& x : indexed(static_cast<const decltype(h)&>(h), Coverage()))
73     BOOST_TEST_EQ(*x, 0);
74 }
75
76 template <class IsDynamic, class Coverage>
77 void run_3d_tests(mp_list<IsDynamic, Coverage>) {
78   auto h = make_s(IsDynamic(), std::vector<int>(), axis::integer<>(0, 2),
79                   axis::integer<int, axis::null_type, axis::option::none_t>(0, 3),
80                   axis::integer<int, axis::null_type, axis::option::overflow_t>(0, 4));
81
82   for (int i = -1; i < 3; ++i)
83     for (int j = -1; j < 4; ++j)
84       for (int k = -1; k < 5; ++k) h(i, j, k, weight(i * 100 + j * 10 + k));
85
86   auto ind = indexed(h, Coverage());
87   auto it = ind.begin();
88   BOOST_TEST_EQ(it->indices().size(), 3);
89
90   const int d = Coverage() == coverage::all;
91
92   // imitate iteration order of indexed loop
93   for (int k = 0; k < 4 + d; ++k)
94     for (int j = 0; j < 3; ++j)
95       for (int i = -d; i < 2 + d; ++i) {
96         BOOST_TEST_EQ(it->index(0), i);
97         BOOST_TEST_EQ(it->index(1), j);
98         BOOST_TEST_EQ(it->index(2), k);
99         BOOST_TEST_EQ(it->bin(0_c), h.axis(0_c).bin(i));
100         BOOST_TEST_EQ(it->bin(1_c), h.axis(1_c).bin(j));
101         BOOST_TEST_EQ(it->bin(2_c), h.axis(2_c).bin(k));
102         BOOST_TEST_EQ(**it, i * 100 + j * 10 + k);
103         ++it;
104       }
105   BOOST_TEST(it == ind.end());
106 }
107
108 template <class IsDynamic, class Coverage>
109 void run_density_tests(mp_list<IsDynamic, Coverage>) {
110   auto ax = axis::variable<>({0.0, 0.1, 0.3, 0.6});
111   auto ay = axis::integer<int>(0, 2);
112   auto az = ax;
113   auto h = make_s(IsDynamic(), std::vector<int>(), ax, ay, az);
114
115   // fill uniformly
116   for (auto&& x : h) x = 1;
117
118   for (auto&& x : indexed(h, Coverage())) {
119     BOOST_TEST_EQ(x.density(), *x / (x.bin(0).width() * x.bin(2).width()));
120   }
121 }
122
123 template <class IsDynamic, class Coverage>
124 void run_stdlib_tests(mp_list<IsDynamic, Coverage>) {
125   auto ax = axis::regular<>(3, 0, 1);
126   auto ay = axis::integer<>(0, 2);
127   auto h = make_s(IsDynamic(), std::array<int, 20>(), ax, ay);
128
129   struct generator {
130     int i = 0;
131     int operator()() { return ++i; }
132   };
133
134   auto ind = indexed(h, Coverage());
135   std::generate(ind.begin(), ind.end(), generator{});
136
137   {
138     int i = 0;
139     for (auto&& x : ind) BOOST_TEST_EQ(*x, ++i);
140   }
141
142   {
143     auto it = std::min_element(ind.begin(), ind.end());
144     BOOST_TEST(it == ind.begin());
145     BOOST_TEST(it != ind.end());
146   }
147
148   {
149     auto it = std::max_element(ind.begin(), ind.end());
150     // get last before end()
151     auto it2 = ind.begin();
152     auto it3 = it2;
153     while (it2 != ind.end()) it3 = it2++;
154     BOOST_TEST(it == it3);
155     BOOST_TEST(it != ind.begin());
156   }
157 }
158
159 int main() {
160   mp_for_each<mp_product<mp_list, mp_list<mp_false, mp_true>,
161                          mp_list<std::integral_constant<coverage, coverage::inner>,
162                                  std::integral_constant<coverage, coverage::all>>>>(
163       [](auto&& x) {
164         run_1d_tests(x);
165         run_3d_tests(x);
166         run_density_tests(x);
167         run_stdlib_tests(x);
168       });
169   return boost::report_errors();
170 }