1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
///////////////////////////////////////////////////////////////
// Copyright 2012 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
//
#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/multiprecision/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();
}
|