• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015-2017 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 <array>
8 #include <boost/core/lightweight_test.hpp>
9 #include <boost/core/lightweight_test_trait.hpp>
10 #include <boost/histogram/axis.hpp>
11 #include <boost/histogram/axis/ostream.hpp>
12 #include <boost/histogram/detail/axes.hpp>
13 #include <limits>
14 #include <tuple>
15 #include <utility>
16 #include <vector>
17 #include "std_ostream.hpp"
18 #include "throw_exception.hpp"
19 
20 using namespace boost::histogram;
21 
main()22 int main() {
23   // dynamic axis_get with tuples
24   {
25     auto a1 = axis::integer<>(0, 1);
26     auto a2 = axis::integer<>(1, 2);
27     auto tup = std::make_tuple(a1, a2);
28     using E1 = axis::variant<axis::integer<>*>;
29     BOOST_TEST_TRAIT_SAME(decltype(detail::axis_get(tup, 0)), E1);
30     BOOST_TEST_EQ(detail::axis_get(tup, 0), a1);
31     BOOST_TEST_EQ(detail::axis_get(tup, 1), a2);
32     BOOST_TEST_NE(detail::axis_get(tup, 0), a2);
33   }
34 
35   // sequence equality
36   {
37     using R = axis::regular<>;
38     using I = axis::integer<>;
39     using V = axis::variable<>;
40     auto r = R(2, -1, 1);
41     auto i = I(-1, 1);
42     auto v = V{-1, 0, 1};
43 
44     std::vector<axis::variant<R, I, V>> v1 = {r, i};
45     std::vector<axis::variant<R, I>> v2 = {r, i};
46     std::vector<axis::variant<R, I>> v3 = {i, r};
47     std::vector<axis::variant<I, R>> v4 = {r, i};
48     std::vector<axis::variant<R, I>> v5 = {r, r};
49     std::vector<R> v6 = {r, r};
50 
51     BOOST_TEST(detail::axes_equal(v1, v2));
52     BOOST_TEST(detail::axes_equal(v1, v4));
53     BOOST_TEST(detail::axes_equal(v5, v6));
54     BOOST_TEST_NOT(detail::axes_equal(v1, v3));
55     BOOST_TEST_NOT(detail::axes_equal(v2, v3));
56     BOOST_TEST_NOT(detail::axes_equal(v3, v4));
57     BOOST_TEST_NOT(detail::axes_equal(v1, v5));
58 
59     auto t1 = std::make_tuple(r, i);
60     auto t2 = std::make_tuple(i, r);
61     auto t3 = std::make_tuple(v, i);
62     auto t4 = std::make_tuple(r, r);
63 
64     BOOST_TEST(detail::axes_equal(t1, t1));
65     BOOST_TEST(detail::axes_equal(t1, v1));
66     BOOST_TEST(detail::axes_equal(t1, v2));
67     BOOST_TEST(detail::axes_equal(t1, v4));
68     BOOST_TEST(detail::axes_equal(v1, t1));
69     BOOST_TEST(detail::axes_equal(v2, t1));
70     BOOST_TEST(detail::axes_equal(v4, t1));
71     BOOST_TEST(detail::axes_equal(t2, v3));
72     BOOST_TEST(detail::axes_equal(v3, t2));
73     BOOST_TEST(detail::axes_equal(t4, v5));
74     BOOST_TEST(detail::axes_equal(t4, v6));
75     BOOST_TEST_NOT(detail::axes_equal(t1, t2));
76     BOOST_TEST_NOT(detail::axes_equal(t2, t3));
77     BOOST_TEST_NOT(detail::axes_equal(t1, v3));
78     BOOST_TEST_NOT(detail::axes_equal(t1, v3));
79     BOOST_TEST_NOT(detail::axes_equal(t3, v1));
80     BOOST_TEST_NOT(detail::axes_equal(t3, v2));
81     BOOST_TEST_NOT(detail::axes_equal(t3, v3));
82     BOOST_TEST_NOT(detail::axes_equal(t3, v4));
83   }
84 
85   // sequence assign
86   {
87     using R = axis::regular<>;
88     using I = axis::integer<>;
89     using V = axis::variable<>;
90     auto r = R(2, -1, 1);
91     auto i = I(-1, 1);
92     auto v = V{-1, 0, 1};
93 
94     std::vector<axis::variant<R, V, I>> v1 = {r, i};
95     std::vector<axis::variant<I, R>> v2;
96     std::vector<R> v3 = {r, r};
97 
98     BOOST_TEST_NOT(detail::axes_equal(v2, v1));
99     detail::axes_assign(v2, v1);
100     BOOST_TEST(detail::axes_equal(v2, v1));
101     detail::axes_assign(v2, v3);
102     BOOST_TEST(detail::axes_equal(v2, v3));
103 
104     auto t1 = std::make_tuple(r);
105     detail::axes_assign(v3, t1);
106     BOOST_TEST(detail::axes_equal(v3, t1));
107 
108     auto t2 = std::make_tuple(r, i);
109     detail::axes_assign(v2, t2);
110     BOOST_TEST(detail::axes_equal(v2, t2));
111 
112     auto t3 = std::make_tuple(R{3, -1, 1}, i);
113     BOOST_TEST_NOT(detail::axes_equal(t2, t3));
114     detail::axes_assign(t2, t3);
115     BOOST_TEST(detail::axes_equal(t2, t3));
116   }
117 
118   // axes_transform
119   {
120     using R = axis::regular<>;
121     using I = axis::integer<double>;
122 
123     {
124       auto t = std::make_tuple(R(1, 0, 1), R(2, 0, 2), I(0, 3));
125       auto t2 = detail::axes_transform(
126           t, [](std::size_t, const auto& a) { return I(0, a.size()); });
127       BOOST_TEST_EQ(t2, std::make_tuple(I(0, 1), I(0, 2), I(0, 3)));
128     }
129     {
130       auto t = std::vector<I>{{I(0, 1), I(0, 2)}};
131       auto t2 = detail::axes_transform(
132           t, [](std::size_t, const auto& a) { return I(0, a.size() + 1); });
133       auto t3 = std::vector<I>{{I(0, 2), I(0, 3)}};
134       BOOST_TEST(detail::axes_equal(t2, t3));
135     }
136     {
137       using V = axis::variant<R, I>;
138       auto t = std::vector<V>{{V{I(0, 1)}, V{R(2, 0, 2)}}};
139       auto t2 = detail::axes_transform(
140           t, [](std::size_t, const auto& a) { return I(0, a.size() + 1); });
141       auto t3 = std::vector<V>{{I(0, 2), I(0, 3)}};
142       BOOST_TEST(detail::axes_equal(t2, t3));
143     }
144 
145     {
146       using V = axis::variant<R, I>;
147       auto t1 = std::vector<V>{{V{I(0, 1)}, V{R(2, 0, 2)}}};
148       auto t2 = std::vector<V>{{V{I(0, 1)}, V{R(2, 0, 2)}}};
149       auto t3 = detail::axes_transform(
150           t1, t2, [](const auto& a, const auto& b) { return I(0, a.size() + b.size()); });
151       auto t4 = std::vector<V>{{I(0, 2), I(0, 4)}};
152       BOOST_TEST(detail::axes_equal(t3, t4));
153     }
154 
155     {
156       // test otherwise unreachable code
157       auto a = R(2, 0, 2);
158       auto b = I(0, 2);
159       BOOST_TEST_THROWS(detail::axis_merger{}(a, b), std::invalid_argument);
160     }
161   }
162 
163   // axes_rank
164   {
165     std::tuple<int, int> a;
166     std::vector<int> b(3);
167     std::array<int, 4> c;
168     const std::tuple<int> d;
169     BOOST_TEST_EQ(detail::axes_rank(a), 2);
170     BOOST_TEST_EQ(detail::axes_rank(b), 3);
171     BOOST_TEST_EQ(detail::axes_rank(c), 4);
172     BOOST_TEST_EQ(detail::axes_rank(d), 1);
173   }
174 
175   // bincount overflow
176   {
177     auto v = std::vector<axis::integer<>>(
178         100, axis::integer<>(0, (std::numeric_limits<int>::max)() - 2));
179     BOOST_TEST_THROWS(detail::bincount(v), std::overflow_error);
180   }
181 
182   // has_growing_axis
183   {
184     struct growing {
185       auto update(int) { return std::make_pair(0, 0); }
186     };
187     using T = growing;
188     using I = axis::integer<>;
189 
190     using A = std::tuple<I, T>;
191     using B = std::vector<T>;
192     using C = std::vector<axis::variant<I, T>>;
193     using D = std::tuple<I>;
194     using E = std::vector<I>;
195     using F = std::vector<axis::variant<I>>;
196 
197     BOOST_TEST_TRAIT_TRUE((detail::has_growing_axis<A>));
198     BOOST_TEST_TRAIT_TRUE((detail::has_growing_axis<B>));
199     BOOST_TEST_TRAIT_TRUE((detail::has_growing_axis<C>));
200     BOOST_TEST_TRAIT_FALSE((detail::has_growing_axis<D>));
201     BOOST_TEST_TRAIT_FALSE((detail::has_growing_axis<E>));
202     BOOST_TEST_TRAIT_FALSE((detail::has_growing_axis<F>));
203   }
204 
205   // value_types
206   {
207     using R = axis::regular<float>;
208     using I = axis::integer<int>;
209     using CI = axis::category<int>;
210     using CS = axis::category<std::string>;
211     using A = std::vector<axis::variant<R, I, CS>>;
212     using B = std::vector<axis::variant<CS, I, CI, R>>;
213     using C = std::tuple<I, R, CS>;
214     using D = std::tuple<CS, I, CI, R>;
215     using Expected = boost::mp11::mp_list<int, float, std::string>;
216     BOOST_TEST_TRAIT_SAME(detail::value_types<A>, Expected);
217     BOOST_TEST_TRAIT_SAME(detail::value_types<B>, Expected);
218     BOOST_TEST_TRAIT_SAME(detail::value_types<C>, Expected);
219     BOOST_TEST_TRAIT_SAME(detail::value_types<D>, Expected);
220   }
221 
222   return boost::report_errors();
223 }
224