summaryrefslogtreecommitdiff
path: root/boost/multiprecision/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/multiprecision/detail')
-rw-r--r--boost/multiprecision/detail/default_ops.hpp48
-rw-r--r--boost/multiprecision/detail/generic_interconvert.hpp7
-rw-r--r--boost/multiprecision/detail/no_et_ops.hpp56
-rw-r--r--boost/multiprecision/detail/rebind.hpp4
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