/////////////////////////////////////////////////////////////// // 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 #include #include #include "test.hpp" #include #include #include #include #ifdef TEST_GMP #include #endif #ifdef TEST_TOMMATH #include #endif #ifdef TEST_MPFR #include #endif int main() { using namespace boost::multiprecision; using namespace boost::random; independent_bits_engine gen; mt11213b small_gen; for (unsigned i = 0; i < 100; ++i) { cpp_int c = gen(); // // Integer to integer conversions first: // #ifdef TEST_GMP mpz_int z(c); cpp_int t(z); BOOST_CHECK_EQUAL(t, c); z.assign(-c); t.assign(-z); BOOST_CHECK_EQUAL(t, c); #endif #ifdef TEST_TOMMATH tom_int tom(c); cpp_int t2(tom); BOOST_CHECK_EQUAL(t2, c); tom.assign(-c); t2.assign(-tom); BOOST_CHECK_EQUAL(t2, c); #endif // // Now integer to float: // typedef number > dec_float_500; dec_float_500 df(c); dec_float_500 df2(c.str()); BOOST_CHECK_EQUAL(df, df2); df.assign(-c); df2 = -df2; BOOST_CHECK_EQUAL(df, df2); #ifdef TEST_GMP typedef number > mpf_type; mpf_type mpf(c); mpf_type mpf2(c.str()); BOOST_CHECK_EQUAL(mpf, mpf2); mpf.assign(-c); mpf2 = -mpf2; BOOST_CHECK_EQUAL(mpf, mpf2); #endif #ifdef TEST_MPFR typedef number > mpfr_type; mpfr_type mpfr(c); mpfr_type mpfr2(c.str()); BOOST_CHECK_EQUAL(mpfr, mpfr2); mpfr.assign(-c); mpfr2 = -mpfr2; BOOST_CHECK_EQUAL(mpfr, mpfr2); #endif // // Now float to float: // df.assign(c); df /= dec_float_500(gen()); dec_float_500 tol("1e-500"); #ifdef TEST_GMP mpf.assign(df); mpf2 = static_cast(df.str()); BOOST_CHECK_EQUAL(mpf, mpf2); df.assign(mpf); df2 = static_cast(mpf.str()); BOOST_CHECK(fabs((df - df2) / df) < tol); #endif #ifdef TEST_MPFR mpfr.assign(df); mpfr2 = static_cast(df.str()); BOOST_CHECK_EQUAL(mpfr, mpfr2); df.assign(mpfr); df2 = static_cast(mpfr.str()); BOOST_CHECK(fabs((df - df2) / df) < tol); #endif // // Rational to rational conversions: // cpp_rational cppr(c, gen()), cppr2, cppr3; #ifdef TEST_GMP mpq_rational mpq(cppr); cppr2.assign(mpq); BOOST_CHECK_EQUAL(cppr, cppr2); #endif #ifdef TEST_TOMMATH tom_rational tr(cppr); cppr3.assign(tr); BOOST_CHECK_EQUAL(cppr, cppr3); #endif // // Integer to rational conversions: // #ifdef TEST_GMP mpq.assign(c); mpq_rational mpq2 = static_cast(c.str()); BOOST_CHECK_EQUAL(mpq, mpq2); #endif #ifdef TEST_TOMMATH tr.assign(c); tom_rational tr2 = static_cast(c.str()); BOOST_CHECK_EQUAL(tr, tr2); #endif // // Rational to float: // df.assign(cppr); df2.assign(numerator(cppr)); df2 /= dec_float_500(denominator(cppr)); BOOST_CHECK(fabs(df - df2) / df2 < tol); // // Float to rational: // static const int max_range = std::numeric_limits::digits >= std::numeric_limits::digits ? (std::numeric_limits::max)() : (1 << (std::numeric_limits::digits - 1)) - 1; static const int min_range = std::numeric_limits::digits >= std::numeric_limits::digits ? (std::numeric_limits::min)() : -(1 << (std::numeric_limits::digits - 1)) + 1; static const boost::random::uniform_int_distribution<> i_val_dist(min_range, max_range); static const boost::random::uniform_int_distribution<> i_exp_dist(std::numeric_limits::min_exponent, std::numeric_limits::max_exponent - 2 - std::numeric_limits::digits); int iv = i_val_dist(small_gen); int eval = i_exp_dist(small_gen); double dv = iv; dv = ldexp(dv, eval); cppr = dv; cppr2 = iv; cpp_int cppi = 1; cppi <<= abs(eval); if (eval < 0) cppr2 /= cppi; else cppr2 *= cppi; BOOST_CHECK_EQUAL(cppr, cppr2); // // Again but with bigger numbers: // cpp_int cppi2 = gen(); number > cppbf(cppi2); cppbf = ldexp(cppbf, eval); cppr.assign(cppbf); cppr2 = cppi2; if (eval < 0) cppr2 /= cppi; else cppr2 *= cppi; BOOST_CHECK_EQUAL(cppr, cppr2); // // MSVC will compile either the code above, or // the code below, but not both in the same file. // Other compilers including Intel in msvc-compatibity // mode have no such difficulty. Indeed the fact that // the presence of the code below causes the code above to // fail to compile strongly suggests a compiler bug. // #if !defined(BOOST_MSVC) // // Again but with bigger base 10 numbers: // number::digits10 + 3> > cppdec2(cppi2); cppdec2 = scalbn(cppdec2, eval); cppr.assign(cppdec2); cppr2 = cppi2; cppi = 10; cppi = pow(cppi, abs(eval)); if (eval < 0) cppr2 /= cppi; else cppr2 *= cppi; BOOST_CHECK_EQUAL(cppr, cppr2); #endif } return boost::report_errors(); }