df647cf959
* add missing copyright notices * workaround for xml_iarchive bug to handle XML with comments * fixing min/max according to boost guidelines
207 lines
5.6 KiB
C++
207 lines
5.6 KiB
C++
// 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 <boost/core/lightweight_test.hpp>
|
|
#include <boost/histogram/detail/large_int.hpp>
|
|
#include <cstdint>
|
|
#include <iosfwd>
|
|
#include <limits>
|
|
#include "std_ostream.hpp"
|
|
|
|
namespace boost {
|
|
namespace histogram {
|
|
namespace detail {
|
|
template <class Allocator>
|
|
std::ostream& operator<<(std::ostream& os, const large_int<Allocator>& x) {
|
|
os << "large_int" << x.data;
|
|
return os;
|
|
}
|
|
} // namespace detail
|
|
} // namespace histogram
|
|
} // namespace boost
|
|
|
|
using namespace boost::histogram;
|
|
|
|
using large_int = detail::large_int<std::allocator<std::uint64_t>>;
|
|
|
|
template <class... Ts>
|
|
auto make_large_int(Ts... ts) {
|
|
large_int r;
|
|
r.data = {static_cast<uint64_t>(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<std::uint64_t>::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<double>::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<double>(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<double>(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();
|
|
}
|