Fix conversions from long long to take long sized chunks.

Also fixed some bitmasks, and added feature-detection checks.
This commit is contained in:
jzmaddock
2015-03-29 11:34:20 +01:00
parent b5c1d0965d
commit 3719752df5
3 changed files with 94 additions and 42 deletions

View File

@@ -59,10 +59,15 @@ namespace detail{
template <unsigned digits10>
struct gmp_float_imp
{
typedef mpl::list<long, long long> signed_types;
#ifdef BOOST_HAS_LONG_LONG
typedef mpl::list<long, long long> signed_types;
typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
typedef mpl::list<double, long double> float_types;
typedef long exponent_type;
#else
typedef mpl::list<long> signed_types;
typedef mpl::list<unsigned long> unsigned_types;
#endif
typedef mpl::list<double, long double> float_types;
typedef long exponent_type;
gmp_float_imp() BOOST_NOEXCEPT {}
@@ -100,27 +105,36 @@ struct gmp_float_imp
return *this;
}
#endif
#ifdef BOOST_HAS_LONG_LONG
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
gmp_float_imp& operator = (unsigned long long i)
{
*this = static_cast<unsigned long>(i);
}
#else
gmp_float_imp& operator = (unsigned long long i)
{
if(m_data[0]._mp_d == 0)
mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
unsigned long long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
unsigned shift = 0;
mpf_t t;
mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
mpf_set_ui(m_data, 0);
while(i)
{
mpf_set_ui(t, static_cast<unsigned>(i & mask));
mpf_set_ui(t, static_cast<unsigned long>(i & mask));
if(shift)
mpf_mul_2exp(t, t, shift);
mpf_add(m_data, m_data, t);
shift += std::numeric_limits<unsigned>::digits;
i >>= std::numeric_limits<unsigned>::digits;
shift += std::numeric_limits<unsigned long>::digits;
i >>= std::numeric_limits<unsigned long>::digits;
}
mpf_clear(t);
return *this;
}
#endif
gmp_float_imp& operator = (long long i)
{
if(m_data[0]._mp_d == 0)
@@ -131,6 +145,7 @@ struct gmp_float_imp
mpf_neg(m_data, m_data);
return *this;
}
#endif
gmp_float_imp& operator = (unsigned long i)
{
if(m_data[0]._mp_d == 0)
@@ -969,8 +984,13 @@ inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& v
struct gmp_int
{
#ifdef BOOST_HAS_LONG_LONG
typedef mpl::list<long, long long> signed_types;
typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
#else
typedef mpl::list<long> signed_types;
typedef mpl::list<unsigned long> unsigned_types;
#endif
typedef mpl::list<double, long double> float_types;
gmp_int()
@@ -1026,27 +1046,35 @@ struct gmp_int
return *this;
}
#endif
#ifdef BOOST_HAS_LONG_LONG
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
gmp_int& operator = (unsigned long long i)
{
*this = static_cast<unsigned long>(i);
}
#else
gmp_int& operator = (unsigned long long i)
{
if(m_data[0]._mp_d == 0)
mpz_init(this->m_data);
unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
unsigned long long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
unsigned shift = 0;
mpz_t t;
mpz_set_ui(m_data, 0);
mpz_init_set_ui(t, 0);
while(i)
{
mpz_set_ui(t, static_cast<unsigned>(i & mask));
mpz_set_ui(t, static_cast<unsigned long>(i & mask));
if(shift)
mpz_mul_2exp(t, t, shift);
mpz_add(m_data, m_data, t);
shift += std::numeric_limits<unsigned>::digits;
i >>= std::numeric_limits<unsigned>::digits;
shift += std::numeric_limits<unsigned long>::digits;
i >>= std::numeric_limits<unsigned long>::digits;
}
mpz_clear(t);
return *this;
}
#endif
gmp_int& operator = (long long i)
{
if(m_data[0]._mp_d == 0)
@@ -1057,6 +1085,7 @@ struct gmp_int
mpz_neg(m_data, m_data);
return *this;
}
#endif
gmp_int& operator = (unsigned long i)
{
if(m_data[0]._mp_d == 0)
@@ -1706,9 +1735,14 @@ void eval_add(gmp_rational& t, const gmp_rational& o);
struct gmp_rational
{
typedef mpl::list<long, long long> signed_types;
#ifdef BOOST_HAS_LONG_LONG
typedef mpl::list<long, long long> signed_types;
typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
typedef mpl::list<double, long double> float_types;
#else
typedef mpl::list<long> signed_types;
typedef mpl::list<unsigned long> unsigned_types;
#endif
typedef mpl::list<double, long double> float_types;
gmp_rational()
{
@@ -1757,25 +1791,20 @@ struct gmp_rational
return *this;
}
#endif
#ifdef BOOST_HAS_LONG_LONG
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
gmp_rational& operator = (unsigned long long i)
{
*this = static_cast<unsigned long>(i);
}
#else
gmp_rational& operator = (unsigned long long i)
{
if(m_data[0]._mp_den._mp_d == 0)
mpq_init(m_data);
unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
unsigned shift = 0;
mpq_t t;
mpq_set_ui(m_data, 0, 1);
mpq_init(t);
while(i)
{
mpq_set_ui(t, static_cast<unsigned>(i & mask), 1);
if(shift)
mpq_mul_2exp(t, t, shift);
mpq_add(m_data, m_data, t);
shift += std::numeric_limits<unsigned>::digits;
i >>= std::numeric_limits<unsigned>::digits;
}
mpq_clear(t);
gmp_int zi;
zi = i;
mpq_set_z(m_data, zi.data());
return *this;
}
gmp_rational& operator = (long long i)
@@ -1788,6 +1817,8 @@ struct gmp_rational
mpq_neg(m_data, m_data);
return *this;
}
#endif
#endif
gmp_rational& operator = (unsigned long i)
{
if(m_data[0]._mp_den._mp_d == 0)

View File

@@ -55,8 +55,13 @@ struct mpfi_float_imp;
template <unsigned digits10>
struct mpfi_float_imp
{
#ifdef BOOST_HAS_LONG_LONG
typedef mpl::list<long, long long> signed_types;
typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
#else
typedef mpl::list<long> signed_types;
typedef mpl::list<unsigned long> unsigned_types;
#endif
typedef mpl::list<double, long double> float_types;
typedef long exponent_type;
@@ -97,6 +102,7 @@ struct mpfi_float_imp
return *this;
}
#endif
#ifdef BOOST_HAS_LONG_LONG
#ifdef _MPFR_H_HAVE_INTMAX_T
mpfi_float_imp& operator = (unsigned long long i)
{
@@ -119,19 +125,19 @@ struct mpfi_float_imp
{
if(m_data[0].left._mpfr_d == 0)
mpfi_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
unsigned long long mask = (((1uLL << (std::numeric_limits<unsigned long>::digits - 1) - 1) << 1) | 1u);
unsigned shift = 0;
mpfi_t t;
mpfi_init2(t, (std::max)(static_cast<unsigned>(std::numeric_limits<unsigned long long>::digits), static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10))));
mpfi_init2(t, (std::max)(static_cast<unsigned>(std::numeric_limits<unsigned long long>::digits), static_cast<unsigned long>(multiprecision::detail::digits10_2_2(digits10))));
mpfi_set_ui(m_data, 0);
while(i)
{
mpfi_set_ui(t, static_cast<unsigned>(i & mask));
mpfi_set_ui(t, static_cast<unsigned long>(i & mask));
if(shift)
mpfi_mul_2exp(t, t, shift);
mpfi_add(m_data, m_data, t);
shift += std::numeric_limits<unsigned>::digits;
i >>= std::numeric_limits<unsigned>::digits;
shift += std::numeric_limits<unsigned long>::digits;
i >>= std::numeric_limits<unsigned long>::digits;
}
mpfi_clear(t);
return *this;
@@ -146,6 +152,7 @@ struct mpfi_float_imp
mpfi_neg(m_data, m_data);
return *this;
}
#endif
#endif
mpfi_float_imp& operator = (unsigned long i)
{

View File

@@ -63,8 +63,13 @@ struct mpfr_float_imp;
template <unsigned digits10>
struct mpfr_float_imp<digits10, allocate_dynamic>
{
#ifdef BOOST_HAS_LONG_LONG
typedef mpl::list<long, long long> signed_types;
typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
#else
typedef mpl::list<long> signed_types;
typedef mpl::list<unsigned long> unsigned_types;
#endif
typedef mpl::list<double, long double> float_types;
typedef long exponent_type;
@@ -105,6 +110,7 @@ struct mpfr_float_imp<digits10, allocate_dynamic>
return *this;
}
#endif
#ifdef BOOST_HAS_LONG_LONG
#ifdef _MPFR_H_HAVE_INTMAX_T
mpfr_float_imp& operator = (unsigned long long i)
{
@@ -125,19 +131,19 @@ struct mpfr_float_imp<digits10, allocate_dynamic>
{
if(m_data[0]._mpfr_d == 0)
mpfr_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : get_default_precision()));
unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
unsigned long long mask = (((1uLL << (std::numeric_limits<unsigned long>::digits - 1) - 1) << 1) | 1uLL);
unsigned shift = 0;
mpfr_t t;
mpfr_init2(t, (std::max)(static_cast<unsigned>(std::numeric_limits<unsigned long long>::digits), static_cast<unsigned>(multiprecision::detail::digits10_2_2(digits10))));
mpfr_init2(t, (std::max)(static_cast<unsigned>(std::numeric_limits<unsigned long long>::digits), static_cast<unsigned long>(multiprecision::detail::digits10_2_2(digits10))));
mpfr_set_ui(m_data, 0, GMP_RNDN);
while(i)
{
mpfr_set_ui(t, static_cast<unsigned>(i & mask), GMP_RNDN);
mpfr_set_ui(t, static_cast<unsigned long>(i & mask), GMP_RNDN);
if(shift)
mpfr_mul_2exp(t, t, shift, GMP_RNDN);
mpfr_add(m_data, m_data, t, GMP_RNDN);
shift += std::numeric_limits<unsigned>::digits;
i >>= std::numeric_limits<unsigned>::digits;
shift += std::numeric_limits<unsigned long>::digits;
i >>= std::numeric_limits<unsigned long>::digits;
}
mpfr_clear(t);
return *this;
@@ -152,6 +158,7 @@ struct mpfr_float_imp<digits10, allocate_dynamic>
mpfr_neg(m_data, m_data, GMP_RNDN);
return *this;
}
#endif
#endif
mpfr_float_imp& operator = (unsigned long i)
{
@@ -363,8 +370,13 @@ protected:
template <unsigned digits10>
struct mpfr_float_imp<digits10, allocate_stack>
{
#ifdef BOOST_HAS_LONG_LONG
typedef mpl::list<long, long long> signed_types;
typedef mpl::list<unsigned long, unsigned long long> unsigned_types;
#else
typedef mpl::list<long> signed_types;
typedef mpl::list<unsigned long> unsigned_types;
#endif
typedef mpl::list<double, long double> float_types;
typedef long exponent_type;
@@ -392,6 +404,7 @@ struct mpfr_float_imp<digits10, allocate_stack>
mpfr_set(m_data, o.m_data, GMP_RNDN);
return *this;
}
#ifdef BOOST_HAS_LONG_LONG
#ifdef _MPFR_H_HAVE_INTMAX_T
mpfr_float_imp& operator = (unsigned long long i)
{
@@ -406,7 +419,7 @@ struct mpfr_float_imp<digits10, allocate_stack>
#else
mpfr_float_imp& operator = (unsigned long long i)
{
unsigned long long mask = ((1uLL << std::numeric_limits<unsigned>::digits) - 1);
unsigned long long mask = (((1uLL << (std::numeric_limits<unsigned long>::digits - 1) - 1) << 1) | 1uL);
unsigned shift = 0;
mpfr_t t;
mp_limb_t t_limbs[limb_count];
@@ -415,12 +428,12 @@ struct mpfr_float_imp<digits10, allocate_stack>
mpfr_set_ui(m_data, 0, GMP_RNDN);
while(i)
{
mpfr_set_ui(t, static_cast<unsigned>(i & mask), GMP_RNDN);
mpfr_set_ui(t, static_cast<unsigned long>(i & mask), GMP_RNDN);
if(shift)
mpfr_mul_2exp(t, t, shift, GMP_RNDN);
mpfr_add(m_data, m_data, t, GMP_RNDN);
shift += std::numeric_limits<unsigned>::digits;
i >>= std::numeric_limits<unsigned>::digits;
shift += std::numeric_limits<unsigned long>::digits;
i >>= std::numeric_limits<unsigned long>::digits;
}
return *this;
}
@@ -432,6 +445,7 @@ struct mpfr_float_imp<digits10, allocate_stack>
mpfr_neg(m_data, m_data, GMP_RNDN);
return *this;
}
#endif
#endif
mpfr_float_imp& operator = (unsigned long i)
{