summaryrefslogtreecommitdiff
path: root/boost/multiprecision/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/multiprecision/detail')
-rw-r--r--boost/multiprecision/detail/bitscan.hpp10
-rw-r--r--boost/multiprecision/detail/default_ops.hpp44
-rw-r--r--boost/multiprecision/detail/functions/pow.hpp10
-rw-r--r--boost/multiprecision/detail/functions/trig.hpp20
-rw-r--r--boost/multiprecision/detail/generic_interconvert.hpp10
-rw-r--r--boost/multiprecision/detail/number_base.hpp24
-rw-r--r--boost/multiprecision/detail/number_compare.hpp156
7 files changed, 198 insertions, 76 deletions
diff --git a/boost/multiprecision/detail/bitscan.hpp b/boost/multiprecision/detail/bitscan.hpp
index 40602a939b..ce1cdc8d18 100644
--- a/boost/multiprecision/detail/bitscan.hpp
+++ b/boost/multiprecision/detail/bitscan.hpp
@@ -124,7 +124,7 @@ BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, mpl::int_<2> const&)
{
return __builtin_ctzl(mask);
}
-BOOST_FORCEINLINE unsigned find_lsb(unsigned long long mask, mpl::int_<3> const&)
+BOOST_FORCEINLINE unsigned find_lsb(boost::ulong_long_type mask, mpl::int_<3> const&)
{
return __builtin_ctzll(mask);
}
@@ -136,9 +136,9 @@ BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, mpl::int_<2> const&)
{
return sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(mask);
}
-BOOST_FORCEINLINE unsigned find_msb(unsigned long long mask, mpl::int_<3> const&)
+BOOST_FORCEINLINE unsigned find_msb(boost::ulong_long_type mask, mpl::int_<3> const&)
{
- return sizeof(unsigned long long) * CHAR_BIT - 1 - __builtin_clzll(mask);
+ return sizeof(boost::ulong_long_type) * CHAR_BIT - 1 - __builtin_clzll(mask);
}
template <class Unsigned>
@@ -152,7 +152,7 @@ BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
sizeof(Unsigned) <= sizeof(unsigned long),
mpl::int_<2>,
typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned long long),
+ sizeof(Unsigned) <= sizeof(boost::ulong_long_type),
mpl::int_<3>,
mpl::int_<0>
>::type
@@ -171,7 +171,7 @@ BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
sizeof(Unsigned) <= sizeof(unsigned long),
mpl::int_<2>,
typename mpl::if_c<
- sizeof(Unsigned) <= sizeof(unsigned long long),
+ sizeof(Unsigned) <= sizeof(boost::ulong_long_type),
mpl::int_<3>,
mpl::int_<0>
>::type
diff --git a/boost/multiprecision/detail/default_ops.hpp b/boost/multiprecision/detail/default_ops.hpp
index bf51a58295..01fbe181df 100644
--- a/boost/multiprecision/detail/default_ops.hpp
+++ b/boost/multiprecision/detail/default_ops.hpp
@@ -1219,7 +1219,7 @@ inline typename B::exponent_type eval_ilogb(const B& val)
template <class B>
inline void eval_logb(B& result, const B& val)
{
- typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, long long, boost::intmax_t>::type max_t;
+ typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, boost::long_long_type, boost::intmax_t>::type max_t;
result = static_cast<max_t>(eval_ilogb(val));
}
template <class B, class A>
@@ -1436,29 +1436,29 @@ inline long ltrunc(const number<T, ExpressionTemplates>& v)
}
#ifndef BOOST_NO_LONG_LONG
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
number_type r = trunc(v, pol);
- if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
+ if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol);
- return r.template convert_to<long long>();
+ return r.template convert_to<boost::long_long_type>();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
+inline boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
{
return lltrunc(v, boost::math::policies::policy<>());
}
template <class T, expression_template_option ExpressionTemplates, class Policy>
-inline long long lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
+inline boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
{
number<T, ExpressionTemplates> r = trunc(v, pol);
- if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
+ if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
- return r.template convert_to<long long>();
+ return r.template convert_to<boost::long_long_type>();
}
template <class T, expression_template_option ExpressionTemplates>
-inline long long lltrunc(const number<T, ExpressionTemplates>& v)
+inline boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v)
{
return lltrunc(v, boost::math::policies::policy<>());
}
@@ -1534,29 +1534,29 @@ inline long lround(const number<T, ExpressionTemplates>& v)
}
#ifndef BOOST_NO_LONG_LONG
template <class tag, class A1, class A2, class A3, class A4, class Policy>
-inline long long llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
+inline boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
{
typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
number_type r = round(v, pol);
- if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
+ if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol);
- return r.template convert_to<long long>();
+ return r.template convert_to<boost::long_long_type>();
}
template <class tag, class A1, class A2, class A3, class A4>
-inline long long llround(const detail::expression<tag, A1, A2, A3, A4>& v)
+inline boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v)
{
return llround(v, boost::math::policies::policy<>());
}
template <class T, expression_template_option ExpressionTemplates, class Policy>
-inline long long llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
+inline boost::long_long_type llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
{
number<T, ExpressionTemplates> r = round(v, pol);
- if((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !(boost::math::isfinite)(v))
+ if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
- return r.template convert_to<long long>();
+ return r.template convert_to<boost::long_long_type>();
}
template <class T, expression_template_option ExpressionTemplates>
-inline long long llround(const number<T, ExpressionTemplates>& v)
+inline boost::long_long_type llround(const number<T, ExpressionTemplates>& v)
{
return llround(v, boost::math::policies::policy<>());
}
@@ -1612,7 +1612,7 @@ frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
}
template <class T, expression_template_option ExpressionTemplates>
-inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long long* pint)
+inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, boost::long_long_type* pint)
{
using default_ops::eval_frexp;
number<T, ExpressionTemplates> result;
@@ -1621,7 +1621,7 @@ inline typename enable_if_c<number_category<T>::value == number_kind_floating_po
}
template <class tag, class A1, class A2, class A3, class A4>
inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
-frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long long* pint)
+frexp(const detail::expression<tag, A1, A2, A3, A4>& v, boost::long_long_type* pint)
{
typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
@@ -2104,8 +2104,8 @@ HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
//HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
//HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
-HETERO_BINARY_OP_FUNCTOR_B(ldexp, long long, number_kind_floating_point)
-//HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, number_kind_floating_point)
+HETERO_BINARY_OP_FUNCTOR_B(ldexp, boost::long_long_type, number_kind_floating_point)
+//HETERO_BINARY_OP_FUNCTOR_B(frexp, boost::long_long_type*, number_kind_floating_point)
BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
@@ -2114,7 +2114,7 @@ UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
-HETERO_BINARY_OP_FUNCTOR_B(scalbn, long long, number_kind_floating_point)
+HETERO_BINARY_OP_FUNCTOR_B(scalbn, boost::long_long_type, number_kind_floating_point)
//
// Integer functions:
diff --git a/boost/multiprecision/detail/functions/pow.hpp b/boost/multiprecision/detail/functions/pow.hpp
index 5b54a1a9a8..b58d6b07be 100644
--- a/boost/multiprecision/detail/functions/pow.hpp
+++ b/boost/multiprecision/detail/functions/pow.hpp
@@ -12,6 +12,11 @@
// This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp
//
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:6326) // comparison of two constants
+#endif
+
namespace detail{
template<typename T, typename U>
@@ -160,7 +165,7 @@ void hyp1F0(T& H1F0, const T& a, const T& x)
si_type n;
T term, part;
- static const unsigned series_limit =
+ static const si_type series_limit =
boost::multiprecision::detail::digits2<number<T, et_on> >::value < 100
? 100 : boost::multiprecision::detail::digits2<number<T, et_on> >::value;
// Series expansion of hyperg_1f0(a; ; x).
@@ -692,3 +697,6 @@ inline void eval_tanh(T& result, const T& x)
eval_divide(result, c);
}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
diff --git a/boost/multiprecision/detail/functions/trig.hpp b/boost/multiprecision/detail/functions/trig.hpp
index baa42be38c..5d4e2639c2 100644
--- a/boost/multiprecision/detail/functions/trig.hpp
+++ b/boost/multiprecision/detail/functions/trig.hpp
@@ -12,6 +12,11 @@
// This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp
//
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:6326) // comparison of two constants
+#endif
+
template <class T>
void hyp0F1(T& result, const T& b, const T& x)
{
@@ -494,12 +499,12 @@ void eval_asin(T& result, const T& x)
// Newton-Raphson iteration
while(current_digits < target_precision)
{
- T s, c;
- eval_sin(s, result);
- eval_cos(c, result);
- eval_subtract(s, xx);
- eval_divide(s, c);
- eval_subtract(result, s);
+ T sine, cosine;
+ eval_sin(sine, result);
+ eval_cos(cosine, result);
+ eval_subtract(sine, xx);
+ eval_divide(sine, cosine);
+ eval_subtract(result, sine);
current_digits *= 2;
/*
@@ -770,3 +775,6 @@ inline typename enable_if<is_arithmetic<A>, void>::type eval_atan2(T& result, co
eval_atan2(result, c, a);
}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
diff --git a/boost/multiprecision/detail/generic_interconvert.hpp b/boost/multiprecision/detail/generic_interconvert.hpp
index 690723be8b..d1fa028d30 100644
--- a/boost/multiprecision/detail/generic_interconvert.hpp
+++ b/boost/multiprecision/detail/generic_interconvert.hpp
@@ -10,7 +10,7 @@
#ifdef BOOST_MSVC
#pragma warning(push)
-#pragma warning(disable:4127)
+#pragma warning(disable:4127 6326)
#endif
namespace boost{ namespace multiprecision{ namespace detail{
@@ -314,7 +314,7 @@ typename enable_if_c<is_number<To>::value || is_floating_point<To>::value>::type
if(shift > 0)
num <<= shift;
else if(shift < 0)
- denom <<= std::abs(shift);
+ denom <<= boost::multiprecision::detail::unsigned_abs(shift);
Integer q, r;
divide_qr(num, denom, q, r);
int q_bits = msb(q);
@@ -392,7 +392,7 @@ template <class To, class From>
void generic_interconvert_float2rational(To& to, const From& from, const mpl::int_<2>& /*radix*/)
{
typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
- static const int shift = std::numeric_limits<long long>::digits;
+ static const int shift = std::numeric_limits<boost::long_long_type>::digits;
typename From::exponent_type e;
typename component_type<number<To> >::type num, denom;
number<From> val(from);
@@ -401,7 +401,7 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
{
val = ldexp(val, shift);
e -= shift;
- long long ll = boost::math::lltrunc(val);
+ boost::long_long_type ll = boost::math::lltrunc(val);
val -= ll;
num <<= shift;
num += ll;
@@ -430,7 +430,7 @@ void generic_interconvert_float2rational(To& to, const From& from, const mpl::in
val = scalbn(val, -e);
while(val)
{
- long long ll = boost::math::lltrunc(val);
+ boost::long_long_type ll = boost::math::lltrunc(val);
val -= ll;
val = scalbn(val, 1);
num *= Radix;
diff --git a/boost/multiprecision/detail/number_base.hpp b/boost/multiprecision/detail/number_base.hpp
index 09c86e6ce0..d725779091 100644
--- a/boost/multiprecision/detail/number_base.hpp
+++ b/boost/multiprecision/detail/number_base.hpp
@@ -25,7 +25,19 @@
# define BOOST_MP_FORCEINLINE inline
#endif
-namespace boost{ namespace multiprecision{
+#if defined(BOOST_GCC) && (BOOST_GCC <= 40700)
+# define BOOST_MP_NOEXCEPT_IF(x)
+#else
+# define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
+#endif
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable:6326)
+#endif
+
+namespace boost{
+ namespace multiprecision{
enum expression_template_option
{
@@ -72,13 +84,13 @@ struct is_compatible_arithmetic_type
namespace detail{
//
-// Workaround for missing abs(long long) and abs(__int128) on some compilers:
+// Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
//
template <class T>
BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
{
// This strange expression avoids a hardware trap in the corner case
- // that val is the most negative value permitted in long long.
+ // that val is the most negative value permitted in boost::long_long_type.
// See https://svn.boost.org/trac/boost/ticket/9740.
return t < 0 ? T(1u) + T(-(t + 1)) : t;
}
@@ -94,7 +106,7 @@ template <class T>
BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), typename make_unsigned<T>::type>::type unsigned_abs(T t) BOOST_NOEXCEPT
{
// This strange expression avoids a hardware trap in the corner case
- // that val is the most negative value permitted in long long.
+ // that val is the most negative value permitted in boost::long_long_type.
// See https://svn.boost.org/trac/boost/ticket/9740.
return t < 0 ? static_cast<typename make_unsigned<T>::type>(1u) + static_cast<typename make_unsigned<T>::type>(-(t + 1)) : static_cast<typename make_unsigned<T>::type>(t);
}
@@ -814,6 +826,10 @@ namespace constants{
}}
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
#endif // BOOST_MATH_BIG_NUM_BASE_HPP
diff --git a/boost/multiprecision/detail/number_compare.hpp b/boost/multiprecision/detail/number_compare.hpp
index d1606ad73d..e9e510d302 100644
--- a/boost/multiprecision/detail/number_compare.hpp
+++ b/boost/multiprecision/detail/number_compare.hpp
@@ -6,6 +6,8 @@
#ifndef BOOST_MP_COMPARE_HPP
#define BOOST_MP_COMPARE_HPP
+#include <boost/multiprecision/traits/is_backend.hpp>
+
//
// Comparison operators for number.
//
@@ -14,61 +16,82 @@ namespace boost{ namespace multiprecision{
namespace default_ops{
+//
+// The dispatching mechanism used here to deal with differently typed arguments
+// could be better replaced with enable_if overloads, but that breaks MSVC-12
+// under strange and hard to reproduce circumstances.
+//
template <class B>
inline bool eval_eq(const B& a, const B& b)
{
return a.compare(b) == 0;
}
-//
-// For the default version which compares to some arbitrary type convertible to
-// our number type, we don't know what value the ExpressionTemplates parameter to
-// class number should be. We generally prefer ExpressionTemplates to be enabled
-// in case type A is itself an expression template, but we need to test both options
-// with is_convertible in case A has an implicit conversion operator to number<B,something>.
-// This is the case with many uBlas types for example.
-//
-template <class B, class A>
-inline bool eval_eq(const B& a, const A& b)
-{
- typedef typename mpl::if_c<
- is_convertible<A, number<B, et_on> >::value,
- number<B, et_on>,
- number<B, et_off> >::type mp_type;
- mp_type t(b);
+template <class T, class U>
+inline bool eval_eq_imp(const T& a, const U& b, const mpl::true_&)
+{
+ typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
return eval_eq(a, t.backend());
}
+template <class T, class U>
+inline bool eval_eq_imp(const T& a, const U& b, const mpl::false_&)
+{
+ typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
+ return eval_eq(t.backend(), b);
+}
+template <class T, class U>
+inline bool eval_eq(const T& a, const U& b)
+{
+ typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
+ return eval_eq_imp(a, b, tag_type());
+}
template <class B>
inline bool eval_lt(const B& a, const B& b)
{
return a.compare(b) < 0;
}
-template <class B, class A>
-inline bool eval_lt(const B& a, const A& b)
+template <class T, class U>
+inline bool eval_lt_imp(const T& a, const U& b, const mpl::true_&)
{
- typedef typename mpl::if_c<
- is_convertible<A, number<B, et_on> >::value,
- number<B, et_on>,
- number<B, et_off> >::type mp_type;
- mp_type t(b);
+ typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
return eval_lt(a, t.backend());
}
+template <class T, class U>
+inline bool eval_lt_imp(const T& a, const U& b, const mpl::false_&)
+{
+ typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
+ return eval_lt(t.backend(), b);
+}
+template <class T, class U>
+inline bool eval_lt(const T& a, const U& b)
+{
+ typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
+ return eval_lt_imp(a, b, tag_type());
+}
template <class B>
inline bool eval_gt(const B& a, const B& b)
{
return a.compare(b) > 0;
}
-template <class B, class A>
-inline bool eval_gt(const B& a, const A& b)
+template <class T, class U>
+inline bool eval_gt_imp(const T& a, const U& b, const mpl::true_&)
{
- typedef typename mpl::if_c<
- is_convertible<A, number<B, et_on> >::value,
- number<B, et_on>,
- number<B, et_off> >::type mp_type;
- mp_type t(b);
+ typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
return eval_gt(a, t.backend());
}
+template <class T, class U>
+inline bool eval_gt_imp(const T& a, const U& b, const mpl::false_&)
+{
+ typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
+ return eval_gt(t.backend(), b);
+}
+template <class T, class U>
+inline bool eval_gt(const T& a, const U& b)
+{
+ typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
+ return eval_gt_imp(a, b, tag_type());
+}
} // namespace default_ops
@@ -91,12 +114,42 @@ template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, ex
struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
: public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
+template <class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>&)
+{
+ return false;
+}
+template <class Backend, expression_template_option ExpressionTemplates>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a)
+{
+ using default_ops::eval_fpclassify;
+ return eval_fpclassify(a.backend()) == FP_NAN;
+}
+
+template <class Arithmetic>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value != number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic&)
+{
+ return false;
+}
+template <class Arithmetic>
+inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value == number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic& a)
+{
+ return (boost::math::isnan)(a);
+}
+
+template <class T, class U>
+inline BOOST_CONSTEXPR bool is_unordered_comparison(const T& a, const U& b)
+{
+ return is_unordered_value(a) || is_unordered_value(b);
+}
+
}
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
inline bool operator == (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_eq;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_eq(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
@@ -104,6 +157,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_eq;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
@@ -111,6 +165,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_eq;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
@@ -120,6 +175,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_eq;
result_type t(b);
+ if(detail::is_unordered_comparison(a, t)) return false;
return eval_eq(t.backend(), result_type::canonical_value(a));
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
@@ -129,6 +185,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_eq;
result_type t(a);
+ if(detail::is_unordered_comparison(t, b)) return false;
return eval_eq(t.backend(), result_type::canonical_value(b));
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
@@ -138,6 +195,7 @@ inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A
using default_ops::eval_eq;
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+ if(detail::is_unordered_comparison(t, t2)) return false;
return eval_eq(t.backend(), t2.backend());
}
@@ -145,6 +203,7 @@ template <class Backend, expression_template_option ExpressionTemplates, class B
inline bool operator != (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_eq;
+ if(detail::is_unordered_comparison(a, b)) return true;
return !eval_eq(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
@@ -152,6 +211,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_eq;
+ if(detail::is_unordered_comparison(a, b)) return true;
return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
@@ -159,6 +219,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_eq;
+ if(detail::is_unordered_comparison(a, b)) return true;
return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
@@ -168,6 +229,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_eq;
result_type t(b);
+ if(detail::is_unordered_comparison(a, t)) return true;
return !eval_eq(t.backend(), result_type::canonical_value(a));
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
@@ -177,6 +239,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_eq;
result_type t(a);
+ if(detail::is_unordered_comparison(t, b)) return true;
return !eval_eq(t.backend(), result_type::canonical_value(b));
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
@@ -186,6 +249,7 @@ inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A
using default_ops::eval_eq;
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+ if(detail::is_unordered_comparison(t, t2)) return true;
return !eval_eq(t.backend(), t2.backend());
}
@@ -193,6 +257,7 @@ template <class Backend, expression_template_option ExpressionTemplates, class B
inline bool operator < (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_lt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_lt(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
@@ -200,6 +265,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_lt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
@@ -207,6 +273,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_gt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
@@ -216,6 +283,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_gt;
result_type t(b);
+ if(detail::is_unordered_comparison(a, t)) return false;
return eval_gt(t.backend(), result_type::canonical_value(a));
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
@@ -225,6 +293,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_lt;
result_type t(a);
+ if(detail::is_unordered_comparison(t, b)) return false;
return eval_lt(t.backend(), result_type::canonical_value(b));
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
@@ -234,6 +303,7 @@ inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A
using default_ops::eval_lt;
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+ if(detail::is_unordered_comparison(t, t2)) return false;
return eval_lt(t.backend(), t2.backend());
}
@@ -241,6 +311,7 @@ template <class Backend, expression_template_option ExpressionTemplates, class B
inline bool operator > (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_gt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_gt(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
@@ -248,6 +319,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_gt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
@@ -255,6 +327,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_lt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
@@ -264,7 +337,8 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_lt;
result_type t(b);
- return eval_lt(t.backend(), result_type::canonical_value(a));
+ if(detail::is_unordered_comparison(a, t)) return false;
+ return a > t;
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
@@ -273,7 +347,8 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_gt;
result_type t(a);
- return eval_gt(t.backend(), result_type::canonical_value(b));
+ if(detail::is_unordered_comparison(t, b)) return false;
+ return t > b;
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
@@ -282,13 +357,15 @@ inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A
using default_ops::eval_gt;
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
- return eval_gt(t.backend(), t2.backend());
+ if(detail::is_unordered_comparison(t, t2)) return false;
+ return t > t2;
}
template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
inline bool operator <= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_gt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return !eval_gt(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
@@ -296,6 +373,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_gt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
@@ -303,6 +381,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_lt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
@@ -311,7 +390,10 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
{
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_lt;
+ if(detail::is_unordered_value(a) || detail::is_unordered_value(b))
+ return false;
result_type t(b);
+ if(detail::is_unordered_comparison(a, t)) return false;
return !eval_lt(t.backend(), result_type::canonical_value(a));
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
@@ -321,6 +403,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_gt;
result_type t(a);
+ if(detail::is_unordered_comparison(t, b)) return false;
return !eval_gt(t.backend(), result_type::canonical_value(b));
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
@@ -330,6 +413,7 @@ inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A
using default_ops::eval_gt;
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+ if(detail::is_unordered_comparison(t, t2)) return false;
return !eval_gt(t.backend(), t2.backend());
}
@@ -337,6 +421,7 @@ template <class Backend, expression_template_option ExpressionTemplates, class B
inline bool operator >= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
{
using default_ops::eval_lt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return !eval_lt(a.backend(), b.backend());
}
template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
@@ -344,6 +429,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
{
using default_ops::eval_lt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
}
template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
@@ -351,6 +437,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre
operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
{
using default_ops::eval_gt;
+ if(detail::is_unordered_comparison(a, b)) return false;
return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
}
template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
@@ -360,6 +447,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_gt;
result_type t(b);
+ if(detail::is_unordered_comparison(a, t)) return false;
return !eval_gt(t.backend(), result_type::canonical_value(a));
}
template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
@@ -369,6 +457,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr
typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
using default_ops::eval_lt;
result_type t(a);
+ if(detail::is_unordered_comparison(t, b)) return false;
return !eval_lt(t.backend(), result_type::canonical_value(b));
}
template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
@@ -378,6 +467,7 @@ inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A
using default_ops::eval_lt;
typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
+ if(detail::is_unordered_comparison(t, t2)) return false;
return !eval_lt(t.backend(), t2.backend());
}