diff options
Diffstat (limited to 'math')
-rw-r--r-- | math/math.h | 33 | ||||
-rw-r--r-- | math/test-math-iszero.cc | 79 |
2 files changed, 108 insertions, 4 deletions
diff --git a/math/math.h b/math/math.h index 9162bee50c..f3eb677a40 100644 --- a/math/math.h +++ b/math/math.h @@ -513,15 +513,40 @@ inline int issignaling (_Float128 __val) { return __issignalingf128 (__val); } # endif # else /* __cplusplus */ extern "C++" { +# ifdef __SUPPORT_SNAN__ +inline int +iszero (float __val) +{ + return __fpclassifyf (__val) == FP_ZERO; +} +inline int +iszero (double __val) +{ + return __fpclassify (__val) == FP_ZERO; +} +inline int +iszero (long double __val) +{ +# ifdef __NO_LONG_DOUBLE_MATH + return __fpclassify (__val) == FP_ZERO; +# else + return __fpclassifyl (__val) == FP_ZERO; +# endif +} +# if __HAVE_DISTINCT_FLOAT128 +inline int +iszero (_Float128 __val) +{ + return __fpclassifyf128 (__val) == FP_ZERO; +} +# endif +# else template <class __T> inline bool iszero (__T __val) { -# ifdef __SUPPORT_SNAN__ - return fpclassify (__val) == FP_ZERO; -# else return __val == 0; -# endif } +# endif } /* extern C++ */ # endif /* __cplusplus */ #endif /* Use IEC_60559_BFP_EXT. */ diff --git a/math/test-math-iszero.cc b/math/test-math-iszero.cc index 027e972654..5c07261626 100644 --- a/math/test-math-iszero.cc +++ b/math/test-math-iszero.cc @@ -22,6 +22,13 @@ #include <limits> +/* Support for _Float128 in std::numeric_limits is limited. + Include ieee754_float128.h and use the bitfields in the union + ieee854_float128.ieee_nan to build corner-case inputs. */ +#if __HAVE_DISTINCT_FLOAT128 +# include <ieee754_float128.h> +#endif + static bool errors; static void @@ -72,12 +79,84 @@ check_type () std::numeric_limits<T>::has_denorm == std::denorm_absent); } +#if __HAVE_DISTINCT_FLOAT128 +static void +check_float128 () +{ + ieee854_float128 q; + + q.d = 0.0Q; + CHECK (iszero (q.d), 1); + q.d = -0.0Q; + CHECK (iszero (q.d), 1); + q.d = 1.0Q; + CHECK (iszero (q.d), 0); + q.d = -1.0Q; + CHECK (iszero (q.d), 0); + + /* Normal min. */ + q.ieee.negative = 0; + q.ieee.exponent = 0x0001; + q.ieee.mantissa0 = 0x0000; + q.ieee.mantissa1 = 0x00000000; + q.ieee.mantissa2 = 0x00000000; + q.ieee.mantissa3 = 0x00000000; + CHECK (iszero (q.d), 0); + q.ieee.negative = 1; + CHECK (iszero (q.d), 0); + + /* Normal max. */ + q.ieee.negative = 0; + q.ieee.exponent = 0x7FFE; + q.ieee.mantissa0 = 0xFFFF; + q.ieee.mantissa1 = 0xFFFFFFFF; + q.ieee.mantissa2 = 0xFFFFFFFF; + q.ieee.mantissa3 = 0xFFFFFFFF; + CHECK (iszero (q.d), 0); + q.ieee.negative = 1; + CHECK (iszero (q.d), 0); + + /* Infinity. */ + q.ieee.negative = 0; + q.ieee.exponent = 0x7FFF; + q.ieee.mantissa0 = 0x0000; + q.ieee.mantissa1 = 0x00000000; + q.ieee.mantissa2 = 0x00000000; + q.ieee.mantissa3 = 0x00000000; + CHECK (iszero (q.d), 0); + + /* Quiet NaN. */ + q.ieee_nan.quiet_nan = 1; + q.ieee_nan.mantissa0 = 0x0000; + CHECK (iszero (q.d), 0); + + /* Signaling NaN. */ + q.ieee_nan.quiet_nan = 0; + q.ieee_nan.mantissa0 = 0x4000; + CHECK (iszero (q.d), 0); + + /* Denormal min. */ + q.ieee.negative = 0; + q.ieee.exponent = 0x0000; + q.ieee.mantissa0 = 0x0000; + q.ieee.mantissa1 = 0x00000000; + q.ieee.mantissa2 = 0x00000000; + q.ieee.mantissa3 = 0x00000001; + CHECK (iszero (q.d), 0); + q.ieee.negative = 1; + CHECK (iszero (q.d), 0); +} +#endif + static int do_test (void) { check_type<float> (); check_type<double> (); check_type<long double> (); +#if __HAVE_DISTINCT_FLOAT128 + check_float128 (); +#endif return errors; } |