diff options
Diffstat (limited to 'stdlib/tst-strtod-underflow.c')
-rw-r--r-- | stdlib/tst-strtod-underflow.c | 225 |
1 files changed, 0 insertions, 225 deletions
diff --git a/stdlib/tst-strtod-underflow.c b/stdlib/tst-strtod-underflow.c deleted file mode 100644 index f623a6be90..0000000000 --- a/stdlib/tst-strtod-underflow.c +++ /dev/null @@ -1,225 +0,0 @@ -/* Test for strtod handling of arguments that may cause floating-point - underflow. - Copyright (C) 2012-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <fenv.h> -#include <float.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <tininess.h> - -enum underflow_case - { - /* Result is exact or outside the subnormal range. */ - UNDERFLOW_NONE, - /* Result has magnitude at most half way between the largest - subnormal value and the smallest positive normal value, and is - not exact, so underflows in all rounding modes and independent - of how tininess is detected. */ - UNDERFLOW_ALWAYS, - /* Result is positive, with magnitude larger than half way between - the largest subnormal value and the least positive normal - value, but would underflow when rounded to nearest to normal - precision, so underflows after rounding in all modes except - rounding upward. */ - UNDERFLOW_EXCEPT_UPWARD, - /* Likewise, for a negative result, underflowing after rounding - except when rounding downward. */ - UNDERFLOW_EXCEPT_DOWNWARD, - /* Result is positive, with magnitude at least three quarters of - the way from the largest subnormal value to the smallest - positive normal value, so underflows after rounding only when - rounding downward or toward zero. */ - UNDERFLOW_ONLY_DOWNWARD_ZERO, - /* Likewise, for a negative result, underflowing after rounding - only when rounding upward or toward zero. */ - UNDERFLOW_ONLY_UPWARD_ZERO, - }; - -struct test -{ - const char *s; - enum underflow_case c; -}; - -static const struct test tests[] = - { - { "0x1p-1022", UNDERFLOW_NONE }, - { "-0x1p-1022", UNDERFLOW_NONE }, - { "0x0p-10000000000000000000000000", UNDERFLOW_NONE }, - { "-0x0p-10000000000000000000000000", UNDERFLOW_NONE }, - { "0x1p-10000000000000000000000000", UNDERFLOW_ALWAYS }, - { "-0x1p-10000000000000000000000000", UNDERFLOW_ALWAYS }, - { "0x1.000000000000000000001p-1022", UNDERFLOW_NONE }, - { "-0x1.000000000000000000001p-1022", UNDERFLOW_NONE }, - { "0x1p-1075", UNDERFLOW_ALWAYS }, - { "-0x1p-1075", UNDERFLOW_ALWAYS }, - { "0x1p-1023", UNDERFLOW_NONE }, - { "-0x1p-1023", UNDERFLOW_NONE }, - { "0x1p-1074", UNDERFLOW_NONE }, - { "-0x1p-1074", UNDERFLOW_NONE }, - { "0x1.ffffffffffffep-1023", UNDERFLOW_NONE }, - { "-0x1.ffffffffffffep-1023", UNDERFLOW_NONE }, - { "0x1.fffffffffffffp-1023", UNDERFLOW_ALWAYS }, - { "-0x1.fffffffffffffp-1023", UNDERFLOW_ALWAYS }, - { "0x1.fffffffffffff0001p-1023", UNDERFLOW_EXCEPT_UPWARD }, - { "-0x1.fffffffffffff0001p-1023", UNDERFLOW_EXCEPT_DOWNWARD }, - { "0x1.fffffffffffff7fffp-1023", UNDERFLOW_EXCEPT_UPWARD }, - { "-0x1.fffffffffffff7fffp-1023", UNDERFLOW_EXCEPT_DOWNWARD }, - { "0x1.fffffffffffff8p-1023", UNDERFLOW_ONLY_DOWNWARD_ZERO }, - { "-0x1.fffffffffffff8p-1023", UNDERFLOW_ONLY_UPWARD_ZERO }, - { "0x1.fffffffffffffffffp-1023", UNDERFLOW_ONLY_DOWNWARD_ZERO }, - { "-0x1.fffffffffffffffffp-1023", UNDERFLOW_ONLY_UPWARD_ZERO }, - }; - -/* Return whether to expect underflow from a particular testcase, in a - given rounding mode. */ - -static bool -expect_underflow (enum underflow_case c, int rm) -{ - if (c == UNDERFLOW_NONE) - return false; - if (c == UNDERFLOW_ALWAYS) - return true; - if (TININESS_AFTER_ROUNDING) - { - switch (rm) - { -#ifdef FE_DOWNWARD - case FE_DOWNWARD: - return (c == UNDERFLOW_EXCEPT_UPWARD - || c == UNDERFLOW_ONLY_DOWNWARD_ZERO); -#endif - -#ifdef FE_TOWARDZERO - case FE_TOWARDZERO: - return true; -#endif - -#ifdef FE_UPWARD - case FE_UPWARD: - return (c == UNDERFLOW_EXCEPT_DOWNWARD - || c == UNDERFLOW_ONLY_UPWARD_ZERO); -#endif - - default: - return (c == UNDERFLOW_EXCEPT_UPWARD - || c == UNDERFLOW_EXCEPT_DOWNWARD); - } - } - else - return true; -} - -static bool support_underflow_exception = false; -volatile double d = DBL_MIN; -volatile double dd; - -static int -test_in_one_mode (const char *s, enum underflow_case c, int rm, - const char *mode_name) -{ - int result = 0; - feclearexcept (FE_ALL_EXCEPT); - errno = 0; - double d = strtod (s, NULL); - int got_errno = errno; -#ifdef FE_UNDERFLOW - bool got_fe_underflow = fetestexcept (FE_UNDERFLOW) != 0; -#else - bool got_fe_underflow = false; -#endif - printf ("strtod (%s) (%s) returned %a, errno = %d, %sunderflow exception\n", - s, mode_name, d, got_errno, got_fe_underflow ? "" : "no "); - bool this_expect_underflow = expect_underflow (c, rm); - if (got_errno != 0 && got_errno != ERANGE) - { - puts ("FAIL: errno neither 0 nor ERANGE"); - result = 1; - } - else if (this_expect_underflow != (errno == ERANGE)) - { - puts ("FAIL: underflow from errno differs from expectations"); - result = 1; - } - if (support_underflow_exception && got_fe_underflow != this_expect_underflow) - { - puts ("FAIL: underflow from exceptions differs from expectations"); - result = 1; - } - return result; -} - -static int -do_test (void) -{ - int save_round_mode __attribute__ ((unused)) = fegetround (); - int result = 0; -#ifdef FE_TONEAREST - const int fe_tonearest = FE_TONEAREST; -#else - const int fe_tonearest = 0; -# if defined FE_DOWNWARD || defined FE_TOWARDZERO || defined FE_UPWARD -# error "FE_TONEAREST not defined, but another rounding mode is" -# endif -#endif -#ifdef FE_UNDERFLOW - feclearexcept (FE_ALL_EXCEPT); - dd = d * d; - if (fetestexcept (FE_UNDERFLOW)) - support_underflow_exception = true; - else - puts ("underflow exception not supported at runtime, only testing errno"); -#endif - for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); i++) - { - result |= test_in_one_mode (tests[i].s, tests[i].c, fe_tonearest, - "default rounding mode"); -#ifdef FE_DOWNWARD - if (!fesetround (FE_DOWNWARD)) - { - result |= test_in_one_mode (tests[i].s, tests[i].c, FE_DOWNWARD, - "FE_DOWNWARD"); - fesetround (save_round_mode); - } -#endif -#ifdef FE_TOWARDZERO - if (!fesetround (FE_TOWARDZERO)) - { - result |= test_in_one_mode (tests[i].s, tests[i].c, FE_TOWARDZERO, - "FE_TOWARDZERO"); - fesetround (save_round_mode); - } -#endif -#ifdef FE_UPWARD - if (!fesetround (FE_UPWARD)) - { - result |= test_in_one_mode (tests[i].s, tests[i].c, FE_UPWARD, - "FE_UPWARD"); - fesetround (save_round_mode); - } -#endif - } - return result; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" |