Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / histogram / test / histogram_operators_test.cpp
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/is_same.hpp>
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/histogram.hpp>
13 #include <boost/histogram/ostream.hpp>
14 #include <boost/throw_exception.hpp>
15 #include <string>
16 #include <vector>
17 #include "std_ostream.hpp"
18 #include "throw_exception.hpp"
19 #include "utility_histogram.hpp"
20
21 using namespace boost::histogram;
22
23 template <typename Tag>
24 void run_tests() {
25   // arithmetic operators
26   {
27     auto a = make(Tag(), axis::integer<int, use_default, axis::option::none_t>(0, 2));
28     auto b = a;
29     a(0);
30     b(1);
31     auto c = a + b;
32     BOOST_TEST_EQ(c.at(0), 1);
33     BOOST_TEST_EQ(c.at(1), 1);
34     c += b;
35     BOOST_TEST_EQ(c.at(0), 1);
36     BOOST_TEST_EQ(c.at(1), 2);
37     auto d = a + b + c;
38     BOOST_TEST_TRAIT_SAME(decltype(d), decltype(a));
39     BOOST_TEST_EQ(d.at(0), 2);
40     BOOST_TEST_EQ(d.at(1), 3);
41
42     auto d2 = d - a - b - c;
43     BOOST_TEST_TRAIT_SAME(decltype(d2), decltype(a));
44     BOOST_TEST_EQ(d2.at(0), 0);
45     BOOST_TEST_EQ(d2.at(1), 0);
46     d2 -= a;
47     BOOST_TEST_EQ(d2.at(0), -1);
48     BOOST_TEST_EQ(d2.at(1), 0);
49
50     auto d3 = d;
51     d3 *= d;
52     BOOST_TEST_EQ(d3.at(0), 4);
53     BOOST_TEST_EQ(d3.at(1), 9);
54     auto d4 = d3 * (1 * d); // converted return type
55     BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(d4), decltype(d3)>));
56     BOOST_TEST_EQ(d4.at(0), 8);
57     BOOST_TEST_EQ(d4.at(1), 27);
58     d4 /= d;
59     BOOST_TEST_EQ(d4.at(0), 4);
60     BOOST_TEST_EQ(d4.at(1), 9);
61     auto d5 = d4 / d;
62     BOOST_TEST_EQ(d5.at(0), 2);
63     BOOST_TEST_EQ(d5.at(1), 3);
64
65     auto e = 3 * a; // converted return type
66     auto f = b * 2; // converted return type
67     BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(e), decltype(a)>));
68     BOOST_TEST_TRAIT_FALSE((boost::core::is_same<decltype(f), decltype(a)>));
69     BOOST_TEST_EQ(e.at(0), 3);
70     BOOST_TEST_EQ(e.at(1), 0);
71     BOOST_TEST_EQ(f.at(0), 0);
72     BOOST_TEST_EQ(f.at(1), 2);
73     auto r = 1.0 * a;
74     r += b;
75     r += e;
76     BOOST_TEST_EQ(r.at(0), 4);
77     BOOST_TEST_EQ(r.at(1), 1);
78     BOOST_TEST_EQ(r, a + b + 3 * a);
79     auto s = r / 4;
80     r /= 4;
81     BOOST_TEST_EQ(r.at(0), 1);
82     BOOST_TEST_EQ(r.at(1), 0.25);
83     BOOST_TEST_EQ(r, s);
84   }
85
86   // arithmetic operators with mixed storage: unlimited vs. vector<unsigned>
87   {
88     auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
89     auto a = make(Tag(), ia);
90     a(0, weight(2));
91     a(1, weight(2));
92     auto b = a;
93     auto c = make_s(Tag(), std::vector<int>(), ia);
94     c(0, weight(2));
95     c(1, weight(2));
96     auto a2 = a;
97     a2 += c;
98     BOOST_TEST_EQ(a2, (a + b));
99     auto a3 = a;
100     a3 *= c;
101     BOOST_TEST_EQ(a3, (a * b));
102     auto a4 = a;
103     a4 -= c;
104     BOOST_TEST_EQ(a4, (a - b));
105     auto a5 = a;
106     a5 /= c;
107     BOOST_TEST_EQ(a5, (a / b));
108   }
109
110   // arithmetic operators with mixed storage: vector<unsigned char> vs. vector<unsigned>
111   {
112     auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
113     auto a = make_s(Tag(), std::vector<unsigned long>{}, ia);
114     auto c = make_s(Tag(), std::vector<unsigned>(), ia);
115     a(0, weight(2u));
116     a(1, weight(2u));
117     auto b = a;
118     c(0, weight(2u));
119     c(1, weight(2u));
120     auto a2 = a;
121     a2 += c;
122     BOOST_TEST_EQ(a2, (a + b));
123     auto a3 = a;
124     a3 *= c;
125     BOOST_TEST_EQ(a3, (a * b));
126     auto a4 = a;
127     a4 -= c;
128     BOOST_TEST_EQ(a4, (a - b));
129     auto a5 = a;
130     a5 /= c;
131     BOOST_TEST_EQ(a5, (a / b));
132   }
133
134   // add operators with weighted storage
135   {
136     auto ia = axis::integer<int, axis::null_type, axis::option::none_t>(0, 2);
137     auto a = make_s(Tag(), std::vector<accumulators::weighted_sum<>>(), ia);
138     auto b = make_s(Tag(), std::vector<accumulators::weighted_sum<>>(), ia);
139
140     a(0);
141     BOOST_TEST_EQ(a.at(0).variance(), 1);
142     b(weight(3), 1);
143     BOOST_TEST_EQ(b.at(1).variance(), 9);
144     auto c = a;
145     c += b;
146     BOOST_TEST_EQ(c.at(0).value(), 1);
147     BOOST_TEST_EQ(c.at(0).variance(), 1);
148     BOOST_TEST_EQ(c.at(1).value(), 3);
149     BOOST_TEST_EQ(c.at(1).variance(), 9);
150     auto d = a;
151     d += b;
152     BOOST_TEST_EQ(d.at(0).value(), 1);
153     BOOST_TEST_EQ(d.at(0).variance(), 1);
154     BOOST_TEST_EQ(d.at(1).value(), 3);
155     BOOST_TEST_EQ(d.at(1).variance(), 9);
156   }
157
158   // bad operations
159   {
160     auto a = make(Tag(), axis::integer<>(0, 2));
161     auto b = make(Tag(), axis::integer<>(0, 3));
162     BOOST_TEST_THROWS(a += b, std::invalid_argument);
163     BOOST_TEST_THROWS(a -= b, std::invalid_argument);
164     BOOST_TEST_THROWS(a *= b, std::invalid_argument);
165     BOOST_TEST_THROWS(a /= b, std::invalid_argument);
166   }
167 }
168
169 int main() {
170   run_tests<static_tag>();
171   run_tests<dynamic_tag>();
172
173   return boost::report_errors();
174 }