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>
operator <<(std::ostream & os,const large_int<Allocator> & x)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>
make_large_int(Ts...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
main()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 }
207