mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-02-20 02:42:26 +00:00
Fix NaN comparisons.
Add tests to verify comparisons of NaN's are unordered. Fix operators to check for unordered comparisons. Fixes: https://svn.boost.org/trac/boost/ticket/11159
This commit is contained in:
@@ -91,12 +91,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 +134,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 +142,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 +152,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 +162,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 +172,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 +180,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 +188,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 +196,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 +206,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 +216,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 +226,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 +234,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 +242,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 +250,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 +260,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 +270,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 +280,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 +288,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 +296,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 +304,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 +314,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 +324,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 +334,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 +350,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 +358,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 +367,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 +380,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 +390,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 +398,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 +406,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 +414,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 +424,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 +434,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 +444,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());
|
||||
}
|
||||
|
||||
|
||||
@@ -757,6 +757,44 @@ void test_float_funcs(const boost::mpl::true_&)
|
||||
BOOST_CHECK_CLOSE_FRACTION(b, Real(atan2(Real(4), Real(2))), tol);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
void compare_NaNs(const T& a, const U& b)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(a == b, false);
|
||||
BOOST_CHECK_EQUAL(a != b, true);
|
||||
BOOST_CHECK_EQUAL(a <= b, false);
|
||||
BOOST_CHECK_EQUAL(a >= b, false);
|
||||
BOOST_CHECK_EQUAL(a > b, false);
|
||||
BOOST_CHECK_EQUAL(a < b, false);
|
||||
//
|
||||
// Again where LHS may be an expression template:
|
||||
//
|
||||
BOOST_CHECK_EQUAL(1 * a == b, false);
|
||||
BOOST_CHECK_EQUAL(1 * a != b, true);
|
||||
BOOST_CHECK_EQUAL(1 * a <= b, false);
|
||||
BOOST_CHECK_EQUAL(1 * a >= b, false);
|
||||
BOOST_CHECK_EQUAL(1 * a > b, false);
|
||||
BOOST_CHECK_EQUAL(1 * a < b, false);
|
||||
//
|
||||
// Again where RHS may be an expression template:
|
||||
//
|
||||
BOOST_CHECK_EQUAL(a == b * 1, false);
|
||||
BOOST_CHECK_EQUAL(a != b * 1, true);
|
||||
BOOST_CHECK_EQUAL(a <= b * 1, false);
|
||||
BOOST_CHECK_EQUAL(a >= b * 1, false);
|
||||
BOOST_CHECK_EQUAL(a > b * 1, false);
|
||||
BOOST_CHECK_EQUAL(a < b * 1, false);
|
||||
//
|
||||
// Again where LHS and RHS may be an expression templates:
|
||||
//
|
||||
BOOST_CHECK_EQUAL(1 * a == b * 1, false);
|
||||
BOOST_CHECK_EQUAL(1 * a != b * 1, true);
|
||||
BOOST_CHECK_EQUAL(1 * a <= b * 1, false);
|
||||
BOOST_CHECK_EQUAL(1 * a >= b * 1, false);
|
||||
BOOST_CHECK_EQUAL(1 * a > b * 1, false);
|
||||
BOOST_CHECK_EQUAL(1 * a < b * 1, false);
|
||||
}
|
||||
|
||||
template <class Real, class T>
|
||||
void test_float_ops(const T&){}
|
||||
|
||||
@@ -861,6 +899,33 @@ void test_float_ops(const boost::mpl::int_<boost::multiprecision::number_kind_fl
|
||||
BOOST_CHECK_THROW(Real(Real(20) / 0u), std::overflow_error);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Comparisons of NaN's should always fail:
|
||||
//
|
||||
if(std::numeric_limits<Real>::has_quiet_NaN)
|
||||
{
|
||||
r = v = std::numeric_limits<Real>::quiet_NaN();
|
||||
compare_NaNs(r, v);
|
||||
v = 0;
|
||||
compare_NaNs(r, v);
|
||||
r.swap(v);
|
||||
compare_NaNs(r, v);
|
||||
//
|
||||
// Conmpare NaN to int:
|
||||
//
|
||||
compare_NaNs(v, 0);
|
||||
compare_NaNs(0, v);
|
||||
//
|
||||
// Compare to floats:
|
||||
//
|
||||
compare_NaNs(v, 0.5);
|
||||
compare_NaNs(0.5, v);
|
||||
if(std::numeric_limits<double>::has_quiet_NaN)
|
||||
{
|
||||
compare_NaNs(r, std::numeric_limits<double>::quiet_NaN());
|
||||
compare_NaNs(std::numeric_limits<double>::quiet_NaN(), r);
|
||||
}
|
||||
}
|
||||
|
||||
test_float_funcs<Real>(boost::mpl::bool_<std::numeric_limits<Real>::is_specialized>());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user