diff options
Diffstat (limited to 'boost/multiprecision/detail')
-rw-r--r-- | boost/multiprecision/detail/bitscan.hpp | 10 | ||||
-rw-r--r-- | boost/multiprecision/detail/default_ops.hpp | 44 | ||||
-rw-r--r-- | boost/multiprecision/detail/functions/pow.hpp | 10 | ||||
-rw-r--r-- | boost/multiprecision/detail/functions/trig.hpp | 20 | ||||
-rw-r--r-- | boost/multiprecision/detail/generic_interconvert.hpp | 10 | ||||
-rw-r--r-- | boost/multiprecision/detail/number_base.hpp | 24 | ||||
-rw-r--r-- | boost/multiprecision/detail/number_compare.hpp | 156 |
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()); } |