| /* Copyright (C) 1997-2014 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| Contributed by Andreas Jaeger <aj@suse.de> and |
| Ulrich Drepper <drepper@cygnus.com>, 1997. |
| |
| 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/>. */ |
| |
| /* Tests for ISO C99 7.6: Floating-point environment */ |
| |
| #ifndef _GNU_SOURCE |
| # define _GNU_SOURCE |
| #endif |
| |
| #include <complex.h> |
| #include <math.h> |
| #include <float.h> |
| #include <fenv.h> |
| |
| #include <errno.h> |
| #include <signal.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/wait.h> |
| #include <sys/resource.h> |
| |
| /* |
| Since not all architectures might define all exceptions, we define |
| a private set and map accordingly. |
| */ |
| #define NO_EXC 0 |
| #define INEXACT_EXC 0x1 |
| #define DIVBYZERO_EXC 0x2 |
| #define UNDERFLOW_EXC 0x04 |
| #define OVERFLOW_EXC 0x08 |
| #define INVALID_EXC 0x10 |
| #define ALL_EXC \ |
| (INEXACT_EXC | DIVBYZERO_EXC | UNDERFLOW_EXC | OVERFLOW_EXC | \ |
| INVALID_EXC) |
| |
| static int count_errors; |
| |
| /* Test whether a given exception was raised. */ |
| static void |
| test_single_exception (short int exception, |
| short int exc_flag, |
| fexcept_t fe_flag, |
| const char *flag_name) |
| { |
| if (exception & exc_flag) |
| { |
| if (fetestexcept (fe_flag)) |
| printf (" Pass: Exception \"%s\" is set\n", flag_name); |
| else |
| { |
| printf (" Fail: Exception \"%s\" is not set\n", flag_name); |
| ++count_errors; |
| } |
| } |
| else |
| { |
| if (fetestexcept (fe_flag)) |
| { |
| printf (" Fail: Exception \"%s\" is set\n", flag_name); |
| ++count_errors; |
| } |
| else |
| { |
| printf (" Pass: Exception \"%s\" is not set\n", flag_name); |
| } |
| } |
| } |
| |
| static void |
| test_exceptions (const char *test_name, short int exception, |
| int ignore_inexact) |
| { |
| printf ("Test: %s\n", test_name); |
| #ifdef FE_DIVBYZERO |
| test_single_exception (exception, DIVBYZERO_EXC, FE_DIVBYZERO, |
| "DIVBYZERO"); |
| #endif |
| #ifdef FE_INVALID |
| test_single_exception (exception, INVALID_EXC, FE_INVALID, |
| "INVALID"); |
| #endif |
| #ifdef FE_INEXACT |
| if (!ignore_inexact) |
| test_single_exception (exception, INEXACT_EXC, FE_INEXACT, |
| "INEXACT"); |
| #endif |
| #ifdef FE_UNDERFLOW |
| test_single_exception (exception, UNDERFLOW_EXC, FE_UNDERFLOW, |
| "UNDERFLOW"); |
| #endif |
| #ifdef FE_OVERFLOW |
| test_single_exception (exception, OVERFLOW_EXC, FE_OVERFLOW, |
| "OVERFLOW"); |
| #endif |
| } |
| |
| static void |
| print_rounding (int rounding) |
| { |
| |
| switch (rounding) |
| { |
| #ifdef FE_TONEAREST |
| case FE_TONEAREST: |
| printf ("TONEAREST"); |
| break; |
| #endif |
| #ifdef FE_UPWARD |
| case FE_UPWARD: |
| printf ("UPWARD"); |
| break; |
| #endif |
| #ifdef FE_DOWNWARD |
| case FE_DOWNWARD: |
| printf ("DOWNWARD"); |
| break; |
| #endif |
| #ifdef FE_TOWARDZERO |
| case FE_TOWARDZERO: |
| printf ("TOWARDZERO"); |
| break; |
| #endif |
| } |
| printf (".\n"); |
| } |
| |
| |
| static void |
| test_rounding (const char *test_name, int rounding_mode) |
| { |
| int curr_rounding = fegetround (); |
| |
| printf ("Test: %s\n", test_name); |
| if (curr_rounding == rounding_mode) |
| { |
| printf (" Pass: Rounding mode is "); |
| print_rounding (curr_rounding); |
| } |
| else |
| { |
| ++count_errors; |
| printf (" Fail: Rounding mode is "); |
| print_rounding (curr_rounding); |
| } |
| } |
| |
| |
| static void |
| set_single_exc (const char *test_name, int fe_exc, fexcept_t exception) |
| { |
| char str[200]; |
| /* The standard allows the inexact exception to be set together with the |
| underflow and overflow exceptions. So ignore the inexact flag if the |
| others are raised. */ |
| int ignore_inexact = (fe_exc & (UNDERFLOW_EXC | OVERFLOW_EXC)) != 0; |
| |
| strcpy (str, test_name); |
| strcat (str, ": set flag, with rest not set"); |
| feclearexcept (FE_ALL_EXCEPT); |
| feraiseexcept (exception); |
| test_exceptions (str, fe_exc, ignore_inexact); |
| |
| strcpy (str, test_name); |
| strcat (str, ": clear flag, rest also unset"); |
| feclearexcept (exception); |
| test_exceptions (str, NO_EXC, ignore_inexact); |
| |
| strcpy (str, test_name); |
| strcat (str, ": set flag, with rest set"); |
| feraiseexcept (FE_ALL_EXCEPT ^ exception); |
| feraiseexcept (exception); |
| test_exceptions (str, ALL_EXC, 0); |
| |
| strcpy (str, test_name); |
| strcat (str, ": clear flag, leave rest set"); |
| feclearexcept (exception); |
| test_exceptions (str, ALL_EXC ^ fe_exc, 0); |
| } |
| |
| static void |
| fe_tests (void) |
| { |
| /* clear all exceptions and test if all are cleared */ |
| feclearexcept (FE_ALL_EXCEPT); |
| test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions", |
| NO_EXC, 0); |
| |
| /* raise all exceptions and test if all are raised */ |
| feraiseexcept (FE_ALL_EXCEPT); |
| test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions", |
| ALL_EXC, 0); |
| feclearexcept (FE_ALL_EXCEPT); |
| |
| #ifdef FE_DIVBYZERO |
| set_single_exc ("Set/Clear FE_DIVBYZERO", DIVBYZERO_EXC, FE_DIVBYZERO); |
| #endif |
| #ifdef FE_INVALID |
| set_single_exc ("Set/Clear FE_INVALID", INVALID_EXC, FE_INVALID); |
| #endif |
| #ifdef FE_INEXACT |
| set_single_exc ("Set/Clear FE_INEXACT", INEXACT_EXC, FE_INEXACT); |
| #endif |
| #ifdef FE_UNDERFLOW |
| set_single_exc ("Set/Clear FE_UNDERFLOW", UNDERFLOW_EXC, FE_UNDERFLOW); |
| #endif |
| #ifdef FE_OVERFLOW |
| set_single_exc ("Set/Clear FE_OVERFLOW", OVERFLOW_EXC, FE_OVERFLOW); |
| #endif |
| } |
| |
| /* Test that program aborts with no masked interrupts */ |
| static void |
| feenv_nomask_test (const char *flag_name, int fe_exc) |
| { |
| #if defined FE_NOMASK_ENV |
| int status; |
| pid_t pid; |
| fenv_t saved; |
| |
| fegetenv (&saved); |
| errno = 0; |
| fesetenv (FE_NOMASK_ENV); |
| status = errno; |
| fesetenv (&saved); |
| if (status == ENOSYS) |
| { |
| printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n"); |
| return; |
| } |
| |
| printf ("Test: after fesetenv (FE_NOMASK_ENV) processes will abort\n"); |
| printf (" when feraiseexcept (%s) is called.\n", flag_name); |
| pid = fork (); |
| if (pid == 0) |
| { |
| #ifdef RLIMIT_CORE |
| /* Try to avoid dumping core. */ |
| struct rlimit core_limit; |
| core_limit.rlim_cur = 0; |
| core_limit.rlim_max = 0; |
| setrlimit (RLIMIT_CORE, &core_limit); |
| #endif |
| |
| fesetenv (FE_NOMASK_ENV); |
| feraiseexcept (fe_exc); |
| exit (2); |
| } |
| else if (pid < 0) |
| { |
| if (errno != ENOSYS) |
| { |
| printf (" Fail: Could not fork.\n"); |
| ++count_errors; |
| } |
| else |
| printf (" `fork' not implemented, test ignored.\n"); |
| } |
| else { |
| if (waitpid (pid, &status, 0) != pid) |
| { |
| printf (" Fail: waitpid call failed.\n"); |
| ++count_errors; |
| } |
| else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE) |
| printf (" Pass: Process received SIGFPE.\n"); |
| else |
| { |
| printf (" Fail: Process didn't receive signal and exited with status %d.\n", |
| status); |
| ++count_errors; |
| } |
| } |
| #endif |
| } |
| |
| /* Test that program doesn't abort with default environment */ |
| static void |
| feenv_mask_test (const char *flag_name, int fe_exc) |
| { |
| int status; |
| pid_t pid; |
| |
| printf ("Test: after fesetenv (FE_DFL_ENV) processes will not abort\n"); |
| printf (" when feraiseexcept (%s) is called.\n", flag_name); |
| pid = fork (); |
| if (pid == 0) |
| { |
| #ifdef RLIMIT_CORE |
| /* Try to avoid dumping core. */ |
| struct rlimit core_limit; |
| core_limit.rlim_cur = 0; |
| core_limit.rlim_max = 0; |
| setrlimit (RLIMIT_CORE, &core_limit); |
| #endif |
| |
| fesetenv (FE_DFL_ENV); |
| feraiseexcept (fe_exc); |
| exit (2); |
| } |
| else if (pid < 0) |
| { |
| if (errno != ENOSYS) |
| { |
| printf (" Fail: Could not fork.\n"); |
| ++count_errors; |
| } |
| else |
| printf (" `fork' not implemented, test ignored.\n"); |
| } |
| else { |
| if (waitpid (pid, &status, 0) != pid) |
| { |
| printf (" Fail: waitpid call failed.\n"); |
| ++count_errors; |
| } |
| else if (WIFEXITED (status) && WEXITSTATUS (status) == 2) |
| printf (" Pass: Process exited normally.\n"); |
| else |
| { |
| printf (" Fail: Process exited abnormally with status %d.\n", |
| status); |
| ++count_errors; |
| } |
| } |
| } |
| |
| /* Test that program aborts with no masked interrupts */ |
| static void |
| feexcp_nomask_test (const char *flag_name, int fe_exc) |
| { |
| int status; |
| pid_t pid; |
| |
| printf ("Test: after fedisableexcept (%s) processes will abort\n", |
| flag_name); |
| printf (" when feraiseexcept (%s) is called.\n", flag_name); |
| pid = fork (); |
| if (pid == 0) |
| { |
| #ifdef RLIMIT_CORE |
| /* Try to avoid dumping core. */ |
| struct rlimit core_limit; |
| core_limit.rlim_cur = 0; |
| core_limit.rlim_max = 0; |
| setrlimit (RLIMIT_CORE, &core_limit); |
| #endif |
| |
| fedisableexcept (FE_ALL_EXCEPT); |
| feenableexcept (fe_exc); |
| feraiseexcept (fe_exc); |
| exit (2); |
| } |
| else if (pid < 0) |
| { |
| if (errno != ENOSYS) |
| { |
| printf (" Fail: Could not fork.\n"); |
| ++count_errors; |
| } |
| else |
| printf (" `fork' not implemented, test ignored.\n"); |
| } |
| else { |
| if (waitpid (pid, &status, 0) != pid) |
| { |
| printf (" Fail: waitpid call failed.\n"); |
| ++count_errors; |
| } |
| else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGFPE) |
| printf (" Pass: Process received SIGFPE.\n"); |
| else |
| { |
| printf (" Fail: Process didn't receive signal and exited with status %d.\n", |
| status); |
| ++count_errors; |
| } |
| } |
| } |
| |
| /* Test that program doesn't abort with exception. */ |
| static void |
| feexcp_mask_test (const char *flag_name, int fe_exc) |
| { |
| int status; |
| int exception; |
| pid_t pid; |
| |
| printf ("Test: after fedisableexcept (%s) processes will not abort\n", |
| flag_name); |
| printf (" when feraiseexcept (%s) is called.\n", flag_name); |
| pid = fork (); |
| if (pid == 0) |
| { |
| #ifdef RLIMIT_CORE |
| /* Try to avoid dumping core. */ |
| struct rlimit core_limit; |
| core_limit.rlim_cur = 0; |
| core_limit.rlim_max = 0; |
| setrlimit (RLIMIT_CORE, &core_limit); |
| #endif |
| feenableexcept (FE_ALL_EXCEPT); |
| exception = fe_exc; |
| #ifdef FE_INEXACT |
| /* The standard allows the inexact exception to be set together with the |
| underflow and overflow exceptions. So add FE_INEXACT to the set of |
| exceptions to be disabled if we will be raising underflow or |
| overflow. */ |
| # ifdef FE_OVERFLOW |
| if (fe_exc & FE_OVERFLOW) |
| exception |= FE_INEXACT; |
| # endif |
| # ifdef FE_UNDERFLOW |
| if (fe_exc & FE_UNDERFLOW) |
| exception |= FE_INEXACT; |
| # endif |
| #endif |
| fedisableexcept (exception); |
| feraiseexcept (fe_exc); |
| exit (2); |
| } |
| else if (pid < 0) |
| { |
| if (errno != ENOSYS) |
| { |
| printf (" Fail: Could not fork.\n"); |
| ++count_errors; |
| } |
| else |
| printf (" `fork' not implemented, test ignored.\n"); |
| } |
| else { |
| if (waitpid (pid, &status, 0) != pid) |
| { |
| printf (" Fail: waitpid call failed.\n"); |
| ++count_errors; |
| } |
| else if (WIFEXITED (status) && WEXITSTATUS (status) == 2) |
| printf (" Pass: Process exited normally.\n"); |
| else |
| { |
| printf (" Fail: Process exited abnormally with status %d.\n", |
| status); |
| ++count_errors; |
| } |
| } |
| } |
| |
| |
| /* Tests for feenableexcept/fedisableexcept/fegetexcept. */ |
| static void |
| feenable_test (const char *flag_name, int fe_exc) |
| { |
| int excepts; |
| |
| |
| printf ("Tests for feenableexcepts etc. with flag %s\n", flag_name); |
| |
| /* First disable all exceptions. */ |
| if (fedisableexcept (FE_ALL_EXCEPT) == -1) |
| { |
| printf ("Test: fedisableexcept (FE_ALL_EXCEPT) failed\n"); |
| ++count_errors; |
| /* If this fails, the other tests don't make sense. */ |
| return; |
| } |
| excepts = fegetexcept (); |
| if (excepts != 0) |
| { |
| printf ("Test: fegetexcept (%s) failed, return should be 0, is %d\n", |
| flag_name, excepts); |
| ++count_errors; |
| } |
| |
| excepts = feenableexcept (fe_exc); |
| if (excepts == -1) |
| { |
| printf ("Test: feenableexcept (%s) failed\n", flag_name); |
| ++count_errors; |
| return; |
| } |
| if (excepts != 0) |
| { |
| printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n", |
| flag_name, excepts); |
| ++count_errors; |
| } |
| |
| excepts = fegetexcept (); |
| if (excepts != fe_exc) |
| { |
| printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n", |
| flag_name, fe_exc, excepts); |
| ++count_errors; |
| } |
| |
| /* And now disable the exception again. */ |
| excepts = fedisableexcept (fe_exc); |
| if (excepts == -1) |
| { |
| printf ("Test: fedisableexcept (%s) failed\n", flag_name); |
| ++count_errors; |
| return; |
| } |
| if (excepts != fe_exc) |
| { |
| printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n", |
| flag_name, fe_exc, excepts); |
| ++count_errors; |
| } |
| |
| excepts = fegetexcept (); |
| if (excepts != 0) |
| { |
| printf ("Test: fegetexcept (%s) failed, return should be 0, is 0x%x\n", |
| flag_name, excepts); |
| ++count_errors; |
| } |
| |
| /* Now the other way round: Enable all exceptions and disable just this one. */ |
| if (feenableexcept (FE_ALL_EXCEPT) == -1) |
| { |
| printf ("Test: feenableexcept (FE_ALL_EXCEPT) failed\n"); |
| ++count_errors; |
| /* If this fails, the other tests don't make sense. */ |
| return; |
| } |
| |
| excepts = fegetexcept (); |
| if (excepts != FE_ALL_EXCEPT) |
| { |
| printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n", |
| flag_name, FE_ALL_EXCEPT, excepts); |
| ++count_errors; |
| } |
| |
| excepts = fedisableexcept (fe_exc); |
| if (excepts == -1) |
| { |
| printf ("Test: fedisableexcept (%s) failed\n", flag_name); |
| ++count_errors; |
| return; |
| } |
| if (excepts != FE_ALL_EXCEPT) |
| { |
| printf ("Test: fedisableexcept (%s) failed, return should be 0, is 0x%x\n", |
| flag_name, excepts); |
| ++count_errors; |
| } |
| |
| excepts = fegetexcept (); |
| if (excepts != (FE_ALL_EXCEPT & ~fe_exc)) |
| { |
| printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n", |
| flag_name, (FE_ALL_EXCEPT & ~fe_exc), excepts); |
| ++count_errors; |
| } |
| |
| /* And now enable the exception again. */ |
| excepts = feenableexcept (fe_exc); |
| if (excepts == -1) |
| { |
| printf ("Test: feenableexcept (%s) failed\n", flag_name); |
| ++count_errors; |
| return; |
| } |
| if (excepts != (FE_ALL_EXCEPT & ~fe_exc)) |
| { |
| printf ("Test: feenableexcept (%s) failed, return should be 0, is 0x%x\n", |
| flag_name, excepts); |
| ++count_errors; |
| } |
| |
| excepts = fegetexcept (); |
| if (excepts != FE_ALL_EXCEPT) |
| { |
| printf ("Test: fegetexcept (%s) failed, return should be 0x%x, is 0x%x\n", |
| flag_name, FE_ALL_EXCEPT, excepts); |
| ++count_errors; |
| } |
| feexcp_nomask_test (flag_name, fe_exc); |
| feexcp_mask_test (flag_name, fe_exc); |
| |
| } |
| |
| |
| static void |
| fe_single_test (const char *flag_name, int fe_exc) |
| { |
| feenv_nomask_test (flag_name, fe_exc); |
| feenv_mask_test (flag_name, fe_exc); |
| feenable_test (flag_name, fe_exc); |
| } |
| |
| |
| static void |
| feenv_tests (void) |
| { |
| /* We might have some exceptions still set. */ |
| feclearexcept (FE_ALL_EXCEPT); |
| |
| #ifdef FE_DIVBYZERO |
| fe_single_test ("FE_DIVBYZERO", FE_DIVBYZERO); |
| #endif |
| #ifdef FE_INVALID |
| fe_single_test ("FE_INVALID", FE_INVALID); |
| #endif |
| #ifdef FE_INEXACT |
| fe_single_test ("FE_INEXACT", FE_INEXACT); |
| #endif |
| #ifdef FE_UNDERFLOW |
| fe_single_test ("FE_UNDERFLOW", FE_UNDERFLOW); |
| #endif |
| #ifdef FE_OVERFLOW |
| fe_single_test ("FE_OVERFLOW", FE_OVERFLOW); |
| #endif |
| fesetenv (FE_DFL_ENV); |
| } |
| |
| |
| static void |
| feholdexcept_tests (void) |
| { |
| fenv_t saved, saved2; |
| int res; |
| |
| feclearexcept (FE_ALL_EXCEPT); |
| fedisableexcept (FE_ALL_EXCEPT); |
| #ifdef FE_DIVBYZERO |
| feraiseexcept (FE_DIVBYZERO); |
| #endif |
| test_exceptions ("feholdexcept_tests FE_DIVBYZERO test", |
| DIVBYZERO_EXC, 0); |
| res = feholdexcept (&saved); |
| if (res != 0) |
| { |
| printf ("feholdexcept failed: %d\n", res); |
| ++count_errors; |
| } |
| #if defined FE_TONEAREST && defined FE_TOWARDZERO |
| res = fesetround (FE_TOWARDZERO); |
| if (res != 0) |
| { |
| printf ("fesetround failed: %d\n", res); |
| ++count_errors; |
| } |
| #endif |
| test_exceptions ("feholdexcept_tests 0 test", NO_EXC, 0); |
| #ifdef FE_INVALID |
| feraiseexcept (FE_INVALID); |
| test_exceptions ("feholdexcept_tests FE_INVALID test", |
| INVALID_EXC, 0); |
| #endif |
| res = feupdateenv (&saved); |
| if (res != 0) |
| { |
| printf ("feupdateenv failed: %d\n", res); |
| ++count_errors; |
| } |
| #if defined FE_TONEAREST && defined FE_TOWARDZERO |
| res = fegetround (); |
| if (res != FE_TONEAREST) |
| { |
| printf ("feupdateenv didn't restore rounding mode: %d\n", res); |
| ++count_errors; |
| } |
| #endif |
| test_exceptions ("feholdexcept_tests FE_DIVBYZERO|FE_INVALID test", |
| DIVBYZERO_EXC | INVALID_EXC, 0); |
| feclearexcept (FE_ALL_EXCEPT); |
| #ifdef FE_INVALID |
| feraiseexcept (FE_INVALID); |
| #endif |
| #if defined FE_TONEAREST && defined FE_UPWARD |
| res = fesetround (FE_UPWARD); |
| if (res != 0) |
| { |
| printf ("fesetround failed: %d\n", res); |
| ++count_errors; |
| } |
| #endif |
| res = feholdexcept (&saved2); |
| if (res != 0) |
| { |
| printf ("feholdexcept failed: %d\n", res); |
| ++count_errors; |
| } |
| #if defined FE_TONEAREST && defined FE_UPWARD |
| res = fesetround (FE_TONEAREST); |
| if (res != 0) |
| { |
| printf ("fesetround failed: %d\n", res); |
| ++count_errors; |
| } |
| #endif |
| test_exceptions ("feholdexcept_tests 0 2nd test", NO_EXC, 0); |
| #ifdef FE_INEXACT |
| feraiseexcept (FE_INEXACT); |
| test_exceptions ("feholdexcept_tests FE_INEXACT test", |
| INEXACT_EXC, 0); |
| #endif |
| res = feupdateenv (&saved2); |
| if (res != 0) |
| { |
| printf ("feupdateenv failed: %d\n", res); |
| ++count_errors; |
| } |
| #if defined FE_TONEAREST && defined FE_UPWARD |
| res = fegetround (); |
| if (res != FE_UPWARD) |
| { |
| printf ("feupdateenv didn't restore rounding mode: %d\n", res); |
| ++count_errors; |
| } |
| fesetround (FE_TONEAREST); |
| #endif |
| test_exceptions ("feholdexcept_tests FE_INEXACT|FE_INVALID test", |
| INVALID_EXC | INEXACT_EXC, 0); |
| feclearexcept (FE_ALL_EXCEPT); |
| } |
| |
| |
| /* IEC 559 and ISO C99 define a default startup environment */ |
| static void |
| initial_tests (void) |
| { |
| test_exceptions ("Initially all exceptions should be cleared", |
| NO_EXC, 0); |
| #ifdef FE_TONEAREST |
| test_rounding ("Rounding direction should be initalized to nearest", |
| FE_TONEAREST); |
| #endif |
| } |
| |
| int |
| main (void) |
| { |
| initial_tests (); |
| fe_tests (); |
| feenv_tests (); |
| feholdexcept_tests (); |
| |
| if (count_errors) |
| { |
| printf ("\n%d errors occurred.\n", count_errors); |
| exit (1); |
| } |
| printf ("\n All tests passed successfully.\n"); |
| return 0; |
| } |