// Copyright John Maddock 2011. // 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 #if !defined(TEST_MPZ) && !defined(TEST_TOMMATH) && !defined(TEST_CPP_INT) #define TEST_TOMMATH #define TEST_MPZ #define TEST_CPP_INT #ifdef _MSC_VER #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") #endif #ifdef __GNUC__ #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" #endif #endif #if defined(TEST_MPZ) #include #endif #if defined(TEST_TOMMATH) #include #endif #ifdef TEST_CPP_INT #include #endif #include #include #include #include "test.hpp" #include #include #ifdef BOOST_MSVC #pragma warning(disable : 4127) #endif template struct unchecked_type { typedef T type; }; #ifdef TEST_CPP_INT template struct unchecked_type, ExpressionTemplates> > { typedef boost::multiprecision::number, ExpressionTemplates> type; }; #endif 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 do_round_trip(const T& val, std::ios_base::fmtflags f) { std::stringstream ss; #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS ss << std::setprecision(std::numeric_limits::max_digits10); #else ss << std::setprecision(std::numeric_limits::digits10 + 5); #endif ss.flags(f); ss << val; T new_val = static_cast(ss.str()); BOOST_CHECK_EQUAL(new_val, val); new_val = static_cast(val.str(0, f)); BOOST_CHECK_EQUAL(new_val, val); ss >> new_val; BOOST_CHECK_EQUAL(new_val, val); } template void do_round_trip(const T& val) { do_round_trip(val, std::ios_base::fmtflags(0)); if (val >= 0) { do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase | std::ios_base::hex)); do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase | std::ios_base::oct)); } } template void negative_round_trip(T val, const boost::mpl::true_&) { do_round_trip(T(-val)); } template void negative_round_trip(T, const boost::mpl::false_&) { } template void negative_spots(const boost::mpl::true_&) { BOOST_CHECK_EQUAL(T(-1002).str(), "-1002"); if (!std::numeric_limits::is_modulo) { #ifndef BOOST_NO_EXCEPTIONS BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::oct), std::runtime_error); BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::hex), std::runtime_error); #endif } } template void negative_spots(const boost::mpl::false_&) { } template void test_round_trip() { for (unsigned i = 0; i < 1000; ++i) { T val = generate_random(); do_round_trip(val); negative_round_trip(val, boost::mpl::bool_::is_signed>()); } BOOST_CHECK_EQUAL(T(1002).str(), "1002"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::showpos), "+1002"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct), "1752"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct | std::ios_base::showbase), "01752"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::hex), "3ea"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::hex | std::ios_base::showbase), "0x3ea"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::hex | std::ios_base::uppercase), "3EA"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::hex | std::ios_base::showbase | std::ios_base::uppercase), "0X3EA"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec), "1002"); BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec | std::ios_base::showbase), "1002"); negative_spots(boost::mpl::bool_::is_signed>()); } int main() { #ifdef TEST_MPZ test_round_trip(); #endif #ifdef TEST_TOMMATH test_round_trip(); #endif #ifdef TEST_CPP_INT test_round_trip(); test_round_trip(); test_round_trip(); test_round_trip > >(); test_round_trip > >(); #endif return boost::report_errors(); }