123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- ///////////////////////////////////////////////////////////////
- // 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 <boost/detail/lightweight_test.hpp>
- #include <boost/array.hpp>
- #include "test.hpp"
- #include <boost/multiprecision/cpp_bin_float.hpp>
- #include <boost/multiprecision/cpp_dec_float.hpp>
- #include <boost/multiprecision/cpp_int.hpp>
- #include <boost/random.hpp>
- #ifdef TEST_GMP
- #include <boost/multiprecision/gmp.hpp>
- #endif
- #ifdef TEST_TOMMATH
- #include <boost/multiprecision/tommath.hpp>
- #endif
- #ifdef TEST_MPFR
- #include <boost/multiprecision/mpfr.hpp>
- #endif
- int main()
- {
- using namespace boost::multiprecision;
- using namespace boost::random;
- independent_bits_engine<mt11213b, 1024, cpp_int> 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<cpp_dec_float<500> > 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<gmp_float<500> > 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_float_backend<500> > 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<mpf_type>(df.str());
- BOOST_CHECK_EQUAL(mpf, mpf2);
- df.assign(mpf);
- df2 = static_cast<dec_float_500>(mpf.str());
- BOOST_CHECK(fabs((df - df2) / df) < tol);
- #endif
- #ifdef TEST_MPFR
- mpfr.assign(df);
- mpfr2 = static_cast<mpfr_type>(df.str());
- BOOST_CHECK_EQUAL(mpfr, mpfr2);
- df.assign(mpfr);
- df2 = static_cast<dec_float_500>(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<mpq_rational>(c.str());
- BOOST_CHECK_EQUAL(mpq, mpq2);
- #endif
- #ifdef TEST_TOMMATH
- tr.assign(c);
- tom_rational tr2 = static_cast<tom_rational>(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<double>::digits >= std::numeric_limits<int>::digits ? (std::numeric_limits<int>::max)() : (1 << (std::numeric_limits<double>::digits - 1)) - 1;
- static const int min_range = std::numeric_limits<double>::digits >= std::numeric_limits<int>::digits ? (std::numeric_limits<int>::min)() : -(1 << (std::numeric_limits<double>::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<double>::min_exponent, std::numeric_limits<double>::max_exponent - 2 - std::numeric_limits<int>::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<cpp_bin_float<1030> > 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<cpp_dec_float<std::numeric_limits<int1024_t>::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();
- }
|