diff --git a/libstdc++-v3/include/std/limits b/libstdc++-v3/include/std/limits index 898406f91ee..c27350c9ec4 100644 --- a/libstdc++-v3/include/std/limits +++ b/libstdc++-v3/include/std/limits @@ -1714,8 +1714,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX_CONSTEXPR float denorm_min() _GLIBCXX_USE_NOEXCEPT { return __FLT_DENORM_MIN__; } - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 - = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = __GCC_IEC_559 >= 2; static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; @@ -1789,8 +1788,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX_CONSTEXPR double denorm_min() _GLIBCXX_USE_NOEXCEPT { return __DBL_DENORM_MIN__; } - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 - = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = __GCC_IEC_559 >= 2; static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; @@ -1864,8 +1862,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX_CONSTEXPR long double denorm_min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_DENORM_MIN__; } - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 - = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = __GCC_IEC_559 >= 2; static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/denorm_min-1.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/denorm_min-1.cc new file mode 100644 index 00000000000..8ff2950d77e --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/numeric_limits/denorm_min-1.cc @@ -0,0 +1,2 @@ +// { dg-options "-ffast-math" } +#include "denorm_min.cc" diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/epsilon-1.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/epsilon-1.cc new file mode 100644 index 00000000000..34548976bea --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/numeric_limits/epsilon-1.cc @@ -0,0 +1,2 @@ +// { dg-options "-ffast-math" } +#include "epsilon.cc" diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/infinity-1.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/infinity-1.cc new file mode 100644 index 00000000000..7ff8ea81242 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/numeric_limits/infinity-1.cc @@ -0,0 +1,2 @@ +// { dg-options "-ffast-math" } +#include "infinity.cc" diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/infinity.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/infinity.cc index 3a5bce57c35..9585ab38216 100644 --- a/libstdc++-v3/testsuite/18_support/numeric_limits/infinity.cc +++ b/libstdc++-v3/testsuite/18_support/numeric_limits/infinity.cc @@ -33,10 +33,10 @@ test_infinity() { bool test; - if (std::numeric_limits::has_infinity) + if (std::numeric_limits::has_infinity && std::numeric_limits::is_iec559) { T inf = std::numeric_limits::infinity(); - test = (inf + inf == inf); + test = (inf + inf == inf); } else test = true; diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/is_iec559-1.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/is_iec559-1.cc new file mode 100644 index 00000000000..91dd8163126 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/numeric_limits/is_iec559-1.cc @@ -0,0 +1,2 @@ +// { dg-options "-ffast-math" } +#include "is_iec559.cc" diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/is_iec559.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/is_iec559.cc index d15ae5cae14..c71da192d1d 100644 --- a/libstdc++-v3/testsuite/18_support/numeric_limits/is_iec559.cc +++ b/libstdc++-v3/testsuite/18_support/numeric_limits/is_iec559.cc @@ -27,28 +27,50 @@ #include #include +// make these values "invisible" to the optimizer so that we really test the FPU +template +T min = std::numeric_limits::min(); +template +T denorm_min = std::numeric_limits::denorm_min(); +template +T inf = std::numeric_limits::infinity(); +template +T max = std::numeric_limits::max(); +template +T qnan = std::numeric_limits::quiet_NaN(); + template void test_is_iec559() { - bool test; - if (std::numeric_limits::is_iec559) { // IEC 559 requires all of the following. - test = (std::numeric_limits::has_infinity - && std::numeric_limits::has_quiet_NaN - && std::numeric_limits::has_signaling_NaN); + VERIFY(std::numeric_limits::has_infinity && + std::numeric_limits::has_quiet_NaN && + std::numeric_limits::has_signaling_NaN); + + // Test a few random IEC559 features + VERIFY(min / 2 > T()); // min/2 is denormal, but not 0 + VERIFY(denorm_min / 3 == T()); // calculation with denormals works + T x = denorm_min; + for (int i = 1; i < std::numeric_limits::digits; ++i) + x *= 2; + VERIFY(x == min); + VERIFY(inf * 2 == inf); // infinity saturates + VERIFY(max * 2 == inf); // max*2 saturates to infinity + T inf0 = inf * T(); // NaN + VERIFY(inf0 != inf); + VERIFY(inf0 != 0); + VERIFY((inf0 == inf0) == false); + VERIFY(qnan != qnan); } else { - // If we had all of the following, why didn't we set IEC 559? - test = (!std::numeric_limits::has_infinity - || !std::numeric_limits::has_quiet_NaN - || !std::numeric_limits::has_signaling_NaN); + // We could have representations for inf, NaN, and SNaN and still not be + // IEC559 compliant. At this point, the meaning of operations on NaNs and + // infinities is unspecified. } - - VERIFY (test); } // libstdc++/8949 diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/quiet_NaN-1.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/quiet_NaN-1.cc new file mode 100644 index 00000000000..45bef204a65 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/numeric_limits/quiet_NaN-1.cc @@ -0,0 +1,2 @@ +// { dg-options "-ffast-math" } +#include "quiet_NaN.cc" diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/quiet_NaN.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/quiet_NaN.cc index 97406aed2b3..b17df1cc3d7 100644 --- a/libstdc++-v3/testsuite/18_support/numeric_limits/quiet_NaN.cc +++ b/libstdc++-v3/testsuite/18_support/numeric_limits/quiet_NaN.cc @@ -33,10 +33,11 @@ test_qnan() { bool test; - if (std::numeric_limits::has_quiet_NaN) + if (std::numeric_limits::has_quiet_NaN && + std::numeric_limits::is_iec559) { T nan = std::numeric_limits::quiet_NaN(); - test = (nan != nan); + test = (nan != nan); } else test = true;