diff options
Diffstat (limited to 'boost/multiprecision/detail')
-rw-r--r-- | boost/multiprecision/detail/default_ops.hpp | 48 | ||||
-rw-r--r-- | boost/multiprecision/detail/generic_interconvert.hpp | 7 | ||||
-rw-r--r-- | boost/multiprecision/detail/no_et_ops.hpp | 56 | ||||
-rw-r--r-- | boost/multiprecision/detail/rebind.hpp | 4 |
4 files changed, 77 insertions, 38 deletions
diff --git a/boost/multiprecision/detail/default_ops.hpp b/boost/multiprecision/detail/default_ops.hpp index bfdb8bd368..c45eec447f 100644 --- a/boost/multiprecision/detail/default_ops.hpp +++ b/boost/multiprecision/detail/default_ops.hpp @@ -50,8 +50,9 @@ namespace default_ops{ #ifdef BOOST_MSVC // warning C4127: conditional expression is constant +// warning C4146: unary minus operator applied to unsigned type, result still unsigned #pragma warning(push) -#pragma warning(disable:4127) +#pragma warning(disable:4127 4146) #endif // // Default versions of mixed arithmetic, these just construct a temporary @@ -889,29 +890,42 @@ struct calculate_next_larger_type }; template <class R, class T> -inline bool check_in_range(const T& t) +inline typename boost::enable_if_c<boost::is_integral<R>::value, bool>::type check_in_range(const T& t) { // Can t fit in an R? - if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)())) + if((t > 0) && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)())) return true; + else return false; } -template <class R, class T> -inline bool check_in_range(const terminal<T>&) +template <class R, class B> +inline typename boost::enable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend) { - return false; + typedef typename calculate_next_larger_type<R, B>::type next_type; + next_type n; + eval_convert_to(&n, backend); + if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (n > (next_type)(std::numeric_limits<R>::max)())) + { + *result = (std::numeric_limits<R>::max)(); + } + else if (std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (n < (next_type)(std::numeric_limits<R>::min)())) + { + *result = (std::numeric_limits<R>::min)(); + } + else + *result = static_cast<R>(n); } template <class R, class B> -inline void eval_convert_to(R* result, const B& backend) +inline typename boost::disable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend) { typedef typename calculate_next_larger_type<R, B>::type next_type; next_type n; eval_convert_to(&n, backend); - if(check_in_range<R>(n)) + if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && ((n > (next_type)(std::numeric_limits<R>::max)() || (n < (next_type)-(std::numeric_limits<R>::max)()) ))) { - *result = (std::numeric_limits<R>::max)(); + *result = n > 0 ? (std::numeric_limits<R>::max)() : -(std::numeric_limits<R>::max)(); } else *result = static_cast<R>(n); @@ -924,7 +938,21 @@ inline void eval_convert_to(terminal<R>* result, const B& backend) // We ran out of types to try for the conversion, try // a lexical_cast and hope for the best: // - result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0))); + if (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed && (eval_get_sign(backend) < 0)) + BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour")); + try + { + result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0))); + } + catch (const bad_lexical_cast&) + { + if (eval_get_sign(backend) < 0) + { + *result = std::numeric_limits<R>::is_integer && std::numeric_limits<R>::is_signed ? (std::numeric_limits<R>::min)() : -(std::numeric_limits<R>::max)(); + } + else + *result = (std::numeric_limits<R>::max)(); + } } template <class B1, class B2, expression_template_option et> diff --git a/boost/multiprecision/detail/generic_interconvert.hpp b/boost/multiprecision/detail/generic_interconvert.hpp index e2d8487c87..ac3fe6640b 100644 --- a/boost/multiprecision/detail/generic_interconvert.hpp +++ b/boost/multiprecision/detail/generic_interconvert.hpp @@ -429,6 +429,13 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in typename From::exponent_type e; typename component_type<number<To> >::type num, denom; number<From> val(from); + + if (!val) + { + to = ui_type(0u); + return; + } + e = ilogb(val); val = scalbn(val, -e); while(val) diff --git a/boost/multiprecision/detail/no_et_ops.hpp b/boost/multiprecision/detail/no_et_ops.hpp index dce7593852..2faee69d03 100644 --- a/boost/multiprecision/detail/no_et_ops.hpp +++ b/boost/multiprecision/detail/no_et_ops.hpp @@ -25,14 +25,14 @@ BOOST_MP_FORCEINLINE number<B, et_off> operator - (const number<B, et_off>& v) BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior."); number<B, et_off> result(v); result.backend().negate(); - return BOOST_MP_MOVE(result); + return result; } template <class B> BOOST_MP_FORCEINLINE number<B, et_off> operator ~ (const number<B, et_off>& v) { number<B, et_off> result; eval_complement(result.backend(), v.backend()); - return BOOST_MP_MOVE(result); + return result; } // // Addition: @@ -43,7 +43,7 @@ BOOST_MP_FORCEINLINE number<B, et_off> operator + (const number<B, et_off>& a, c number<B, et_off> result; using default_ops::eval_add; eval_add(result.backend(), a.backend(), b.backend()); - return BOOST_MP_MOVE(result); + return result; } template <class B, class V> BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type @@ -52,7 +52,7 @@ BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number< number<B, et_off> result; using default_ops::eval_add; eval_add(result.backend(), a.backend(), number<B, et_off>::canonical_value(b)); - return BOOST_MP_MOVE(result); + return result; } template <class V, class B> BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type @@ -61,7 +61,7 @@ BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number< number<B, et_off> result; using default_ops::eval_add; eval_add(result.backend(), b.backend(), number<B, et_off>::canonical_value(a)); - return BOOST_MP_MOVE(result); + return result; } // // Subtraction: @@ -72,7 +72,7 @@ BOOST_MP_FORCEINLINE number<B, et_off> operator - (const number<B, et_off>& a, c number<B, et_off> result; using default_ops::eval_subtract; eval_subtract(result.backend(), a.backend(), b.backend()); - return BOOST_MP_MOVE(result); + return result; } template <class B, class V> BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type @@ -81,7 +81,7 @@ BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number< number<B, et_off> result; using default_ops::eval_subtract; eval_subtract(result.backend(), a.backend(), number<B, et_off>::canonical_value(b)); - return BOOST_MP_MOVE(result); + return result; } template <class V, class B> BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type @@ -90,7 +90,7 @@ BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number< number<B, et_off> result; using default_ops::eval_subtract; eval_subtract(result.backend(), number<B, et_off>::canonical_value(a), b.backend()); - return BOOST_MP_MOVE(result); + return result; } // // Multiply: @@ -101,7 +101,7 @@ BOOST_MP_FORCEINLINE number<B, et_off> operator * (const number<B, et_off>& a, c number<B, et_off> result; using default_ops::eval_multiply; eval_multiply(result.backend(), a.backend(), b.backend()); - return BOOST_MP_MOVE(result); + return result; } template <class B, class V> BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type @@ -110,7 +110,7 @@ BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number< number<B, et_off> result; using default_ops::eval_multiply; eval_multiply(result.backend(), a.backend(), number<B, et_off>::canonical_value(b)); - return BOOST_MP_MOVE(result); + return result; } template <class V, class B> BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type @@ -119,7 +119,7 @@ BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number< number<B, et_off> result; using default_ops::eval_multiply; eval_multiply(result.backend(), b.backend(), number<B, et_off>::canonical_value(a)); - return BOOST_MP_MOVE(result); + return result; } // // divide: @@ -130,7 +130,7 @@ BOOST_MP_FORCEINLINE number<B, et_off> operator / (const number<B, et_off>& a, c number<B, et_off> result; using default_ops::eval_divide; eval_divide(result.backend(), a.backend(), b.backend()); - return BOOST_MP_MOVE(result); + return result; } template <class B, class V> BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type @@ -139,7 +139,7 @@ BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number< number<B, et_off> result; using default_ops::eval_divide; eval_divide(result.backend(), a.backend(), number<B, et_off>::canonical_value(b)); - return BOOST_MP_MOVE(result); + return result; } template <class V, class B> BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type @@ -148,7 +148,7 @@ BOOST_MP_FORCEINLINE typename enable_if<is_compatible_arithmetic_type<V, number< number<B, et_off> result; using default_ops::eval_divide; eval_divide(result.backend(), number<B, et_off>::canonical_value(a), b.backend()); - return BOOST_MP_MOVE(result); + return result; } // // modulus: @@ -159,7 +159,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_ki number<B, et_off> result; using default_ops::eval_modulus; eval_modulus(result.backend(), a.backend(), b.backend()); - return BOOST_MP_MOVE(result); + return result; } template <class B, class V> BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -168,7 +168,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, numbe number<B, et_off> result; using default_ops::eval_modulus; eval_modulus(result.backend(), a.backend(), number<B, et_off>::canonical_value(b)); - return BOOST_MP_MOVE(result); + return result; } template <class V, class B> BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -177,7 +177,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, numbe number<B, et_off> result; using default_ops::eval_modulus; eval_modulus(result.backend(), number<B, et_off>::canonical_value(a), b.backend()); - return BOOST_MP_MOVE(result); + return result; } // // Bitwise or: @@ -188,7 +188,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_ki number<B, et_off> result; using default_ops::eval_bitwise_or; eval_bitwise_or(result.backend(), a.backend(), b.backend()); - return BOOST_MP_MOVE(result); + return result; } template <class B, class V> BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -197,7 +197,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, numbe number<B, et_off> result; using default_ops::eval_bitwise_or; eval_bitwise_or(result.backend(), a.backend(), number<B, et_off>::canonical_value(b)); - return BOOST_MP_MOVE(result); + return result; } template <class V, class B> BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -206,7 +206,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, numbe number<B, et_off> result; using default_ops::eval_bitwise_or; eval_bitwise_or(result.backend(), b.backend(), number<B, et_off>::canonical_value(a)); - return BOOST_MP_MOVE(result); + return result; } // // Bitwise xor: @@ -217,7 +217,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_ki number<B, et_off> result; using default_ops::eval_bitwise_xor; eval_bitwise_xor(result.backend(), a.backend(), b.backend()); - return BOOST_MP_MOVE(result); + return result; } template <class B, class V> BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -226,7 +226,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, numbe number<B, et_off> result; using default_ops::eval_bitwise_xor; eval_bitwise_xor(result.backend(), a.backend(), number<B, et_off>::canonical_value(b)); - return BOOST_MP_MOVE(result); + return result; } template <class V, class B> BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -235,7 +235,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, numbe number<B, et_off> result; using default_ops::eval_bitwise_xor; eval_bitwise_xor(result.backend(), b.backend(), number<B, et_off>::canonical_value(a)); - return BOOST_MP_MOVE(result); + return result; } // // Bitwise and: @@ -246,7 +246,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<number_category<B>::value == number_ki number<B, et_off> result; using default_ops::eval_bitwise_and; eval_bitwise_and(result.backend(), a.backend(), b.backend()); - return BOOST_MP_MOVE(result); + return result; } template <class B, class V> BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -255,7 +255,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, numbe number<B, et_off> result; using default_ops::eval_bitwise_and; eval_bitwise_and(result.backend(), a.backend(), number<B, et_off>::canonical_value(b)); - return BOOST_MP_MOVE(result); + return result; } template <class V, class B> BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -264,7 +264,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_compatible_arithmetic_type<V, numbe number<B, et_off> result; using default_ops::eval_bitwise_and; eval_bitwise_and(result.backend(), b.backend(), number<B, et_off>::canonical_value(a)); - return BOOST_MP_MOVE(result); + return result; } // // shifts: @@ -277,7 +277,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_categ using default_ops::eval_left_shift; detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), is_signed<I>()); eval_left_shift(result.backend(), b); - return BOOST_MP_MOVE(result); + return result; } template <class B, class I> BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type @@ -287,7 +287,7 @@ BOOST_MP_FORCEINLINE typename enable_if_c<is_integral<I>::value && (number_categ using default_ops::eval_right_shift; detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), is_signed<I>()); eval_right_shift(result.backend(), b); - return BOOST_MP_MOVE(result); + return result; } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ < 5))) diff --git a/boost/multiprecision/detail/rebind.hpp b/boost/multiprecision/detail/rebind.hpp index 9aadf7ba41..1ad0f7dec0 100644 --- a/boost/multiprecision/detail/rebind.hpp +++ b/boost/multiprecision/detail/rebind.hpp @@ -13,7 +13,11 @@ template <class value_type, class my_allocator> struct rebind { +#ifndef BOOST_NO_CXX11_ALLOCATOR + typedef typename std::allocator_traits<my_allocator>::template rebind_alloc<value_type> type; +#else typedef typename my_allocator::template rebind<value_type>::other type; +#endif }; } } } } // namespace boost::multiprecision::backends::detail |