// Copyright John Maddock 2015. // Use, modification and distribution are subject to 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) #ifdef _MSC_VER #define _SCL_SECURE_NO_WARNINGS #endif #include #include #include #include #include "test.hpp" #include #include #ifdef BOOST_MSVC #pragma warning(disable : 4127) #endif template struct unchecked_type { typedef T type; }; template struct unchecked_type, ExpressionTemplates> > { typedef boost::multiprecision::number, ExpressionTemplates> type; }; template T generate_random() { typedef typename unchecked_type::type unchecked_T; static const unsigned limbs = std::numeric_limits::is_specialized && std::numeric_limits::is_bounded ? std::numeric_limits::digits / std::numeric_limits::digits + 3 : 20; static boost::random::uniform_int_distribution ui(0, limbs); static boost::random::mt19937 gen; unchecked_T val = gen(); unsigned lim = ui(gen); for (unsigned i = 0; i < lim; ++i) { val *= (gen.max)(); val += gen(); } return val; } template void test_round_trip_neg(T val, const boost::mpl::true_&) { // Try some negative values: std::vector cv; T newval; val = -val; export_bits(val, std::back_inserter(cv), 8, false); import_bits(newval, cv.begin(), cv.end(), 8, false); BOOST_CHECK_EQUAL(-val, newval); } template void test_round_trip_neg(const T&, const boost::mpl::false_&) { } template void test_round_trip(T val) { std::vector cv; export_bits(val, std::back_inserter(cv), 8); T newval; import_bits(newval, cv.begin(), cv.end()); BOOST_CHECK_EQUAL(val, newval); // Should get the same value if we reverse the bytes: std::reverse(cv.begin(), cv.end()); newval = 0; import_bits(newval, cv.begin(), cv.end(), 8, false); BOOST_CHECK_EQUAL(val, newval); // Also try importing via pointers as these may memcpy: newval = 0; import_bits(newval, &cv[0], &cv[0] + cv.size(), 8, false); BOOST_CHECK_EQUAL(val, newval); cv.clear(); export_bits(val, std::back_inserter(cv), 8, false); import_bits(newval, cv.begin(), cv.end(), 8, false); BOOST_CHECK_EQUAL(val, newval); std::reverse(cv.begin(), cv.end()); newval = 0; import_bits(newval, cv.begin(), cv.end(), 8, true); BOOST_CHECK_EQUAL(val, newval); std::vector bv; export_bits(val, std::back_inserter(bv), std::numeric_limits::digits); import_bits(newval, bv.begin(), bv.end()); BOOST_CHECK_EQUAL(val, newval); // Should get the same value if we reverse the values: std::reverse(bv.begin(), bv.end()); newval = 0; import_bits(newval, bv.begin(), bv.end(), std::numeric_limits::digits, false); BOOST_CHECK_EQUAL(val, newval); // Also try importing via pointers as these may memcpy: newval = 0; import_bits(newval, &bv[0], &bv[0] + bv.size(), std::numeric_limits::digits, false); BOOST_CHECK_EQUAL(val, newval); bv.clear(); export_bits(val, std::back_inserter(bv), std::numeric_limits::digits, false); import_bits(newval, bv.begin(), bv.end(), std::numeric_limits::digits, false); BOOST_CHECK_EQUAL(val, newval); // // Try with an unconventional number of bits, to model some machine with guard bits: // bv.clear(); export_bits(val, std::back_inserter(bv), std::numeric_limits::digits - 3); import_bits(newval, bv.begin(), bv.end(), std::numeric_limits::digits - 3); BOOST_CHECK_EQUAL(val, newval); bv.clear(); export_bits(val, std::back_inserter(bv), std::numeric_limits::digits - 3, false); import_bits(newval, bv.begin(), bv.end(), std::numeric_limits::digits - 3, false); BOOST_CHECK_EQUAL(val, newval); cv.clear(); export_bits(val, std::back_inserter(cv), 6); import_bits(newval, cv.begin(), cv.end(), 6); BOOST_CHECK_EQUAL(val, newval); cv.clear(); export_bits(val, std::back_inserter(cv), 6, false); import_bits(newval, cv.begin(), cv.end(), 6, false); BOOST_CHECK_EQUAL(val, newval); test_round_trip_neg(val, boost::mpl::bool_::is_signed>()); } template void test_round_trip() { std::cout << std::hex; std::cerr << std::hex; for (unsigned i = 0; i < 1000; ++i) { T val = generate_random(); test_round_trip(val); } // // Bug cases. // See https://github.com/boostorg/multiprecision/issues/21 T bug(1); bug << std::numeric_limits::digits - 1; --bug; test_round_trip(bug); } int main() { test_round_trip(); test_round_trip(); test_round_trip(); test_round_trip > >(); test_round_trip > >(); return boost::report_errors(); }