Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / histogram / test / detail_large_int_test.cpp
1 // Copyright 2018-2019 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/detail/large_int.hpp>
9 #include <cstdint>
10 #include <iosfwd>
11 #include <limits>
12 #include "std_ostream.hpp"
13
14 namespace boost {
15 namespace histogram {
16 namespace detail {
17 template <class Allocator>
18 std::ostream& operator<<(std::ostream& os, const large_int<Allocator>& x) {
19   os << "large_int" << x.data;
20   return os;
21 }
22 } // namespace detail
23 } // namespace histogram
24 } // namespace boost
25
26 using namespace boost::histogram;
27
28 using large_int = detail::large_int<std::allocator<std::uint64_t>>;
29
30 template <class... Ts>
31 auto make_large_int(Ts... ts) {
32   large_int r;
33   r.data = {static_cast<uint64_t>(ts)...};
34   return r;
35 }
36
37 int main() {
38   // low-level tools
39   {
40     uint8_t c = 0;
41     BOOST_TEST_EQ(detail::safe_increment(c), true);
42     BOOST_TEST_EQ(c, 1);
43     c = 255;
44     BOOST_TEST_EQ(detail::safe_increment(c), false);
45     BOOST_TEST_EQ(c, 255);
46     c = 0;
47     BOOST_TEST_EQ(detail::safe_radd(c, 255u), true);
48     BOOST_TEST_EQ(c, 255);
49     c = 1;
50     BOOST_TEST_EQ(detail::safe_radd(c, 255u), false);
51     BOOST_TEST_EQ(c, 1);
52     c = 255;
53     BOOST_TEST_EQ(detail::safe_radd(c, 1u), false);
54     BOOST_TEST_EQ(c, 255);
55   }
56
57   const auto vmax = (std::numeric_limits<std::uint64_t>::max)();
58
59   // ctors, assign
60   {
61     large_int a(42);
62     large_int b(a);
63     BOOST_TEST_EQ(b.data.front(), 42);
64     large_int c(std::move(b));
65     BOOST_TEST_EQ(c.data.front(), 42);
66     large_int d, e;
67     d = a;
68     BOOST_TEST_EQ(d.data.front(), 42);
69     e = std::move(c);
70     BOOST_TEST_EQ(e.data.front(), 42);
71   }
72
73   // comparison
74   {
75     BOOST_TEST_EQ(large_int(), 0u);
76     BOOST_TEST_EQ(large_int(1u), 1u);
77     BOOST_TEST_EQ(large_int(1u), 1.0);
78     BOOST_TEST_EQ(large_int(1u), large_int(1u));
79     BOOST_TEST_NE(large_int(1u), 2u);
80     BOOST_TEST_NE(large_int(1u), 2.0);
81     BOOST_TEST_NE(large_int(1u), 2.0f);
82     BOOST_TEST_NE(large_int(1u), large_int(2u));
83     BOOST_TEST_LT(large_int(1u), 2u);
84     BOOST_TEST_LT(large_int(1u), 2.0);
85     BOOST_TEST_LT(large_int(1u), 2.0f);
86     BOOST_TEST_LT(large_int(1u), large_int(2u));
87     BOOST_TEST_LE(large_int(1u), 2u);
88     BOOST_TEST_LE(large_int(1u), 2.0);
89     BOOST_TEST_LE(large_int(1u), 2.0f);
90     BOOST_TEST_LE(large_int(1u), large_int(2u));
91     BOOST_TEST_LE(large_int(1u), 1u);
92     BOOST_TEST_GT(large_int(1u), 0u);
93     BOOST_TEST_GT(large_int(1u), 0.0);
94     BOOST_TEST_GT(large_int(1u), 0.0f);
95     BOOST_TEST_GT(large_int(1u), large_int(0u));
96     BOOST_TEST_GE(large_int(1u), 0u);
97     BOOST_TEST_GE(large_int(1u), 0.0);
98     BOOST_TEST_GE(large_int(1u), 0.0f);
99     BOOST_TEST_GE(large_int(1u), 1u);
100     BOOST_TEST_GE(large_int(1u), large_int(0u));
101     BOOST_TEST_NOT(large_int(1u) < large_int(1u));
102     BOOST_TEST_NOT(large_int(1u) > large_int(1u));
103
104     BOOST_TEST_GT(1, large_int());
105     BOOST_TEST_LT(-1, large_int());
106     BOOST_TEST_GE(1, large_int());
107     BOOST_TEST_LE(-1, large_int());
108     BOOST_TEST_NE(1, large_int());
109
110     constexpr auto nan = std::numeric_limits<double>::quiet_NaN();
111     BOOST_TEST_NOT(large_int(1u) < nan);
112     BOOST_TEST_NOT(large_int(1u) > nan);
113     BOOST_TEST_NOT(large_int(1u) == nan);
114     BOOST_TEST(large_int(1u) != nan); // same behavior as int compared to nan
115     BOOST_TEST_NOT(large_int(1u) <= nan);
116     BOOST_TEST_NOT(large_int(1u) >= nan);
117
118     BOOST_TEST_NOT(nan < large_int(1u));
119     BOOST_TEST_NOT(nan > large_int(1u));
120     BOOST_TEST_NOT(nan == large_int(1u));
121     BOOST_TEST(nan != large_int(1u)); // same behavior as int compared to nan
122     BOOST_TEST_NOT(nan <= large_int(1u));
123     BOOST_TEST_NOT(nan >= large_int(1u));
124   }
125
126   // increment
127   {
128     auto a = large_int();
129     ++a;
130     BOOST_TEST_EQ(a.data.size(), 1);
131     BOOST_TEST_EQ(a.data[0], 1);
132     ++a;
133     BOOST_TEST_EQ(a.data[0], 2);
134     a = vmax;
135     BOOST_TEST_EQ(a, vmax);
136     BOOST_TEST_EQ(a, static_cast<double>(vmax));
137     ++a;
138     BOOST_TEST_EQ(a, make_large_int(0, 1));
139     ++a;
140     BOOST_TEST_EQ(a, make_large_int(1, 1));
141     a += a;
142     BOOST_TEST_EQ(a, make_large_int(2, 2));
143     BOOST_TEST_EQ(a, 2 * static_cast<double>(vmax) + 2);
144
145     // carry once A
146     a.data[0] = vmax;
147     a.data[1] = 1;
148     ++a;
149     BOOST_TEST_EQ(a, make_large_int(0, 2));
150     // carry once B
151     a.data[0] = vmax;
152     a.data[1] = 1;
153     a += 1;
154     BOOST_TEST_EQ(a, make_large_int(0, 2));
155     // carry once C
156     a.data[0] = vmax;
157     a.data[1] = 1;
158     a += make_large_int(1, 1);
159     BOOST_TEST_EQ(a, make_large_int(0, 3));
160
161     a.data[0] = vmax - 1;
162     a.data[1] = vmax;
163     ++a;
164     BOOST_TEST_EQ(a, make_large_int(vmax, vmax));
165
166     // carry two times A
167     ++a;
168     BOOST_TEST_EQ(a, make_large_int(0, 0, 1));
169     // carry two times B
170     a = make_large_int(vmax, vmax);
171     a += 1;
172     BOOST_TEST_EQ(a, make_large_int(0, 0, 1));
173     // carry two times C
174     a = make_large_int(vmax, vmax);
175     a += large_int(1);
176     BOOST_TEST_EQ(a, make_large_int(0, 0, 1));
177
178     // carry and enlarge
179     a = make_large_int(vmax, vmax);
180     a += a;
181     BOOST_TEST_EQ(a, make_large_int(vmax - 1, vmax, 1));
182
183     // add smaller to larger
184     a = make_large_int(1, 1, 1);
185     a += make_large_int(1, 1);
186     BOOST_TEST_EQ(a, make_large_int(2, 2, 1));
187
188     // add larger to smaller
189     a = make_large_int(1, 1);
190     a += make_large_int(1, 1, 1);
191     BOOST_TEST_EQ(a, make_large_int(2, 2, 1));
192
193     a = large_int(1);
194     auto b = 1.0;
195     BOOST_TEST_EQ(a, b);
196     for (unsigned i = 0; i < 80; ++i) {
197       b += b;
198       BOOST_TEST_NE(a, b);
199       a += a;
200       BOOST_TEST_EQ(a, b);
201     }
202     BOOST_TEST_GT(a.data.size(), 1u);
203   }
204
205   return boost::report_errors();
206 }