/////////////////////////////////////////////////////////////// // Copyright 2012 John Maddock. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt #ifdef _MSC_VER #define _SCL_SECURE_NO_WARNINGS #endif #ifdef HAS_TOMMATH #include #include #include #include "test.hpp" #if defined(HAS_GMP) #include #endif #if defined(HAS_MPFR) #include #endif #if defined(HAS_MPFI) #include #endif #ifdef HAS_FLOAT128 #include #endif #include #include using namespace boost::multiprecision; #ifdef BOOST_MSVC #pragma warning(disable : 4127) #endif template T generate_random_int(unsigned bits_wanted) { static boost::random::mt19937 gen; typedef boost::random::mt19937::result_type random_type; T max_val; unsigned digits; if (std::numeric_limits::is_bounded && (bits_wanted == (unsigned)std::numeric_limits::digits)) { max_val = (std::numeric_limits::max)(); digits = std::numeric_limits::digits; } else { max_val = T(1) << bits_wanted; digits = bits_wanted; } unsigned bits_per_r_val = std::numeric_limits::digits - 1; while ((random_type(1) << bits_per_r_val) > (gen.max)()) --bits_per_r_val; unsigned terms_needed = digits / bits_per_r_val + 1; T val = 0; for (unsigned i = 0; i < terms_needed; ++i) { val *= (gen.max)(); val += gen(); } val %= max_val; return val; } template T generate_random(unsigned bits_wanted) { typedef typename component_type::type int_type; T val(generate_random_int(bits_wanted), generate_random_int(bits_wanted)); return val; } template void test_convert_neg_val(From from, const boost::mpl::true_&) { from = -from; typename component_type::type answer = numerator(from) / denominator(from); To t3(from); To t4 = from.template convert_to(); BOOST_CHECK_EQUAL(answer.str(), t3.str()); BOOST_CHECK_EQUAL(answer.str(), t4.str()); } template void test_convert_neg_val(From const&, const boost::mpl::false_&) { } template void test_convert_imp(boost::mpl::int_ const&, boost::mpl::int_ const&) { int bits_wanted = (std::min)((std::min)(std::numeric_limits::digits, std::numeric_limits::digits), 2000); for (unsigned i = 0; i < 100; ++i) { From from = generate_random(bits_wanted); typename component_type::type answer = numerator(from) / denominator(from); To t1(from); To t2 = from.template convert_to(); BOOST_CHECK_EQUAL(answer.str(), t1.str()); BOOST_CHECK_EQUAL(answer.str(), t2.str()); test_convert_neg_val(from, boost::mpl::bool_ < std::numeric_limits::is_signed && std::numeric_limits::is_signed > ()); } } template void test_convert_neg_float_val(From from, To const& tol, const boost::mpl::true_&) { from = -from; To answer = To(numerator(from)) / To(denominator(from)); To t3(from); To t4 = from.template convert_to(); BOOST_CHECK_CLOSE_FRACTION(answer, t3, tol); BOOST_CHECK_CLOSE_FRACTION(answer, t4, tol); } template void test_convert_neg_float_val(From const&, To const&, const boost::mpl::false_&) { } template void test_convert_imp(boost::mpl::int_ const&, boost::mpl::int_ const&) { int bits_wanted = (std::min)((std::min)(std::numeric_limits::digits, std::numeric_limits::digits), 2000); for (unsigned i = 0; i < 100; ++i) { From from = generate_random(bits_wanted); To answer = To(numerator(from)) / To(denominator(from)); To t1(from); To t2 = from.template convert_to(); To tol = std::numeric_limits::is_specialized ? std::numeric_limits::epsilon() : ldexp(To(1), 1 - bits_wanted); tol *= 2; BOOST_CHECK_CLOSE_FRACTION(answer, t1, tol); BOOST_CHECK_CLOSE_FRACTION(answer, t2, tol); test_convert_neg_float_val(from, tol, boost::mpl::bool_ < std::numeric_limits::is_signed && std::numeric_limits::is_signed > ()); } } template void test_convert_neg_rat_val(From from, const boost::mpl::true_&) { from = -from; To t3(from); To t4 = from.template convert_to(); BOOST_CHECK_EQUAL(from.str(), t3.str()); BOOST_CHECK_EQUAL(from.str(), t4.str()); } template void test_convert_neg_rat_val(From const&, const boost::mpl::false_&) { } template void test_convert_imp(boost::mpl::int_ const&, boost::mpl::int_ const&) { int bits_wanted = (std::min)((std::min)(std::numeric_limits::digits, std::numeric_limits::digits), 2000); for (unsigned i = 0; i < 100; ++i) { From from = generate_random(bits_wanted); To t1(from); To t2 = from.template convert_to(); BOOST_CHECK_EQUAL(from.str(), t1.str()); BOOST_CHECK_EQUAL(from.str(), t2.str()); test_convert_neg_rat_val(from, boost::mpl::bool_ < std::numeric_limits::is_signed && std::numeric_limits::is_signed > ()); } } template void test_convert() { test_convert_imp(typename number_category::type(), typename number_category::type()); } int main() { test_convert(); test_convert(); test_convert(); test_convert(); test_convert(); test_convert(); #if defined(HAS_GMP) test_convert(); test_convert(); test_convert(); #endif #if defined(HAS_MPFR) test_convert(); #endif #if defined(HAS_MPFI) test_convert(); #endif test_convert(); return boost::report_errors(); } #else int main() { return 0; } #endif