// Copyright 2018-2019 Hans Dembinski // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include "std_ostream.hpp" namespace boost { namespace histogram { namespace detail { template std::ostream& operator<<(std::ostream& os, const large_int& x) { os << "large_int" << x.data; return os; } } // namespace detail } // namespace histogram } // namespace boost using namespace boost::histogram; using large_int = detail::large_int>; template auto make_large_int(Ts... ts) { large_int r; r.data = {static_cast(ts)...}; return r; } int main() { // low-level tools { uint8_t c = 0; BOOST_TEST_EQ(detail::safe_increment(c), true); BOOST_TEST_EQ(c, 1); c = 255; BOOST_TEST_EQ(detail::safe_increment(c), false); BOOST_TEST_EQ(c, 255); c = 0; BOOST_TEST_EQ(detail::safe_radd(c, 255u), true); BOOST_TEST_EQ(c, 255); c = 1; BOOST_TEST_EQ(detail::safe_radd(c, 255u), false); BOOST_TEST_EQ(c, 1); c = 255; BOOST_TEST_EQ(detail::safe_radd(c, 1u), false); BOOST_TEST_EQ(c, 255); } const auto vmax = (std::numeric_limits::max)(); // ctors, assign { large_int a(42); large_int b(a); BOOST_TEST_EQ(b.data.front(), 42); large_int c(std::move(b)); BOOST_TEST_EQ(c.data.front(), 42); large_int d, e; d = a; BOOST_TEST_EQ(d.data.front(), 42); e = std::move(c); BOOST_TEST_EQ(e.data.front(), 42); } // comparison { BOOST_TEST_EQ(large_int(), 0u); BOOST_TEST_EQ(large_int(1u), 1u); BOOST_TEST_EQ(large_int(1u), 1.0); BOOST_TEST_EQ(large_int(1u), large_int(1u)); BOOST_TEST_NE(large_int(1u), 2u); BOOST_TEST_NE(large_int(1u), 2.0); BOOST_TEST_NE(large_int(1u), 2.0f); BOOST_TEST_NE(large_int(1u), large_int(2u)); BOOST_TEST_LT(large_int(1u), 2u); BOOST_TEST_LT(large_int(1u), 2.0); BOOST_TEST_LT(large_int(1u), 2.0f); BOOST_TEST_LT(large_int(1u), large_int(2u)); BOOST_TEST_LE(large_int(1u), 2u); BOOST_TEST_LE(large_int(1u), 2.0); BOOST_TEST_LE(large_int(1u), 2.0f); BOOST_TEST_LE(large_int(1u), large_int(2u)); BOOST_TEST_LE(large_int(1u), 1u); BOOST_TEST_GT(large_int(1u), 0u); BOOST_TEST_GT(large_int(1u), 0.0); BOOST_TEST_GT(large_int(1u), 0.0f); BOOST_TEST_GT(large_int(1u), large_int(0u)); BOOST_TEST_GE(large_int(1u), 0u); BOOST_TEST_GE(large_int(1u), 0.0); BOOST_TEST_GE(large_int(1u), 0.0f); BOOST_TEST_GE(large_int(1u), 1u); BOOST_TEST_GE(large_int(1u), large_int(0u)); BOOST_TEST_NOT(large_int(1u) < large_int(1u)); BOOST_TEST_NOT(large_int(1u) > large_int(1u)); BOOST_TEST_GT(1, large_int()); BOOST_TEST_LT(-1, large_int()); BOOST_TEST_GE(1, large_int()); BOOST_TEST_LE(-1, large_int()); BOOST_TEST_NE(1, large_int()); constexpr auto nan = std::numeric_limits::quiet_NaN(); BOOST_TEST_NOT(large_int(1u) < nan); BOOST_TEST_NOT(large_int(1u) > nan); BOOST_TEST_NOT(large_int(1u) == nan); BOOST_TEST(large_int(1u) != nan); // same behavior as int compared to nan BOOST_TEST_NOT(large_int(1u) <= nan); BOOST_TEST_NOT(large_int(1u) >= nan); BOOST_TEST_NOT(nan < large_int(1u)); BOOST_TEST_NOT(nan > large_int(1u)); BOOST_TEST_NOT(nan == large_int(1u)); BOOST_TEST(nan != large_int(1u)); // same behavior as int compared to nan BOOST_TEST_NOT(nan <= large_int(1u)); BOOST_TEST_NOT(nan >= large_int(1u)); } // increment { auto a = large_int(); ++a; BOOST_TEST_EQ(a.data.size(), 1); BOOST_TEST_EQ(a.data[0], 1); ++a; BOOST_TEST_EQ(a.data[0], 2); a = vmax; BOOST_TEST_EQ(a, vmax); BOOST_TEST_EQ(a, static_cast(vmax)); ++a; BOOST_TEST_EQ(a, make_large_int(0, 1)); ++a; BOOST_TEST_EQ(a, make_large_int(1, 1)); a += a; BOOST_TEST_EQ(a, make_large_int(2, 2)); BOOST_TEST_EQ(a, 2 * static_cast(vmax) + 2); // carry once A a.data[0] = vmax; a.data[1] = 1; ++a; BOOST_TEST_EQ(a, make_large_int(0, 2)); // carry once B a.data[0] = vmax; a.data[1] = 1; a += 1; BOOST_TEST_EQ(a, make_large_int(0, 2)); // carry once C a.data[0] = vmax; a.data[1] = 1; a += make_large_int(1, 1); BOOST_TEST_EQ(a, make_large_int(0, 3)); a.data[0] = vmax - 1; a.data[1] = vmax; ++a; BOOST_TEST_EQ(a, make_large_int(vmax, vmax)); // carry two times A ++a; BOOST_TEST_EQ(a, make_large_int(0, 0, 1)); // carry two times B a = make_large_int(vmax, vmax); a += 1; BOOST_TEST_EQ(a, make_large_int(0, 0, 1)); // carry two times C a = make_large_int(vmax, vmax); a += large_int(1); BOOST_TEST_EQ(a, make_large_int(0, 0, 1)); // carry and enlarge a = make_large_int(vmax, vmax); a += a; BOOST_TEST_EQ(a, make_large_int(vmax - 1, vmax, 1)); // add smaller to larger a = make_large_int(1, 1, 1); a += make_large_int(1, 1); BOOST_TEST_EQ(a, make_large_int(2, 2, 1)); // add larger to smaller a = make_large_int(1, 1); a += make_large_int(1, 1, 1); BOOST_TEST_EQ(a, make_large_int(2, 2, 1)); a = large_int(1); auto b = 1.0; BOOST_TEST_EQ(a, b); for (unsigned i = 0; i < 80; ++i) { b += b; BOOST_TEST_NE(a, b); a += a; BOOST_TEST_EQ(a, b); } BOOST_TEST_GT(a.data.size(), 1u); } return boost::report_errors(); }