diff options
author | Thomas Schwinge <thomas@codesourcery.com> | 2013-02-28 22:38:23 +0100 |
---|---|---|
committer | Thomas Schwinge <thomas@codesourcery.com> | 2013-03-15 19:12:10 +0100 |
commit | 495ded2c8c1eb8c0ac4b54add2dd397852e19cba (patch) | |
tree | d1c635ce966b0b34936abe69b231e0e2e87ffcb4 /math | |
parent | 777b0332c0598ebba46685b41ea5846640751c19 (diff) | |
download | glibc-495ded2c8c1eb8c0ac4b54add2dd397852e19cba.zip glibc-495ded2c8c1eb8c0ac4b54add2dd397852e19cba.tar.gz glibc-495ded2c8c1eb8c0ac4b54add2dd397852e19cba.tar.bz2 |
Promote a math test for sNaN handling to the top-level.
Diffstat (limited to 'math')
-rw-r--r-- | math/Makefile | 2 | ||||
-rw-r--r-- | math/test-snan.c | 336 |
2 files changed, 337 insertions, 1 deletions
diff --git a/math/Makefile b/math/Makefile index 72cf338..e216dfb 100644 --- a/math/Makefile +++ b/math/Makefile @@ -88,7 +88,7 @@ long-c-yes = $(calls:=l) tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \ test-misc test-fpucw tst-definitions test-tgmath test-tgmath-ret \ bug-nextafter bug-nexttoward bug-tgmath1 test-tgmath-int \ - test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 + test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan # We do the `long double' tests only if this data type is available and # distinct from `double'. test-longdouble-yes = test-ldouble test-ildoubl diff --git a/math/test-snan.c b/math/test-snan.c new file mode 100644 index 0000000..6ec9414 --- /dev/null +++ b/math/test-snan.c @@ -0,0 +1,336 @@ +/* Test signaling NaNs in isnan, isinf, and similar functions. + Copyright (C) 2008-2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger <aj@suse.de>, 2005. + + 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/>. */ + +#define _GNU_SOURCE 1 +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <string.h> +#include <math.h> +#include <float.h> +#include <fenv.h> +#include <signal.h> +#include <setjmp.h> +#include <errno.h> + +int dest_offset; +char *dest_address; +double value = 123.456; +double zero = 0.0; + +static sigjmp_buf sigfpe_buf; + +typedef long double ldouble; + + +void +myFPsighandler(int signal, + siginfo_t *info, + void *context) +{ + siglongjmp(sigfpe_buf, 0); +} + +int +set_sigaction_FP(void) +{ + struct sigaction sa; + /* register RT signal handler via sigaction */ + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = &myFPsighandler; + sigemptyset(&sa.sa_mask); + sigaction(SIGFPE, &sa, NULL); + + return 0; +} + +int +remove_sigaction_FP(void) +{ + struct sigaction sa; + /* restore default RT signal handler via sigaction */ + sa.sa_flags = SA_SIGINFO; + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sigaction(SIGFPE, &sa, NULL); + + return 0; +} + +static int errors = 0; + +static void +check (const char *testname, int result) +{ + if (!result) { + printf ("Failure: %s\n", testname); + errors++; + } +} + +#define TEST_FUNC(NAME, FLOAT, SUFFIX) \ +static void \ +NAME (void) \ +{ \ + /* Variables are declared volatile to forbid some compiler \ + optimizations. */ \ + volatile FLOAT Inf_var, qNaN_var, zero_var, one_var; \ + /* A sNaN is only guaranteed to be representable in variables with */ \ + /* static (or thread-local) storage duration. */ \ + static volatile FLOAT sNaN_var = __builtin_nans ## SUFFIX (""); \ + fenv_t saved_fenv; \ + \ + zero_var = 0.0; \ + one_var = 1.0; \ + qNaN_var = __builtin_nan ## SUFFIX (""); \ + Inf_var = one_var / zero_var; \ + \ + (void) &zero_var; \ + (void) &one_var; \ + (void) &qNaN_var; \ + (void) &sNaN_var; \ + (void) &Inf_var; \ + \ + set_sigaction_FP (); \ + fegetenv(&saved_fenv); \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnan (qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnan (qNaN)", isnan (qNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnan (-qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnan (-qNaN)", isnan (-qNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnan (sNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnan (sNaN)", isnan (sNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnan (-sNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnan (-sNaN)", isnan (-sNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isinf (qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isinf (qNaN)", !isinf (qNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isinf (-qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isinf (-qNaN)", !isinf (-qNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isinf (sNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isinf (sNaN)", !isinf (sNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isinf (-sNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isinf (-sNaN)", !isinf (-sNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isfinite (qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isfinite (qNaN)", !isfinite (qNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isfinite (-qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isfinite (-qNaN)", !isfinite (-qNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isfinite (sNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isfinite (sNaN)", !isfinite (sNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isfinite (-sNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isfinite (-sNaN)", !isfinite (-sNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnormal (qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnormal (qNaN)", !isnormal (qNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnormal (-qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnormal (-qNaN)", !isnormal (-qNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnormal (sNaN) isnormal SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnormal (sNaN)", !isnormal (sNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnormal (-sNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnormal (-sNaN)", !isnormal (-sNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " fpclassify (qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " fpclassify (qNaN)", (fpclassify (qNaN_var)==FP_NAN)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " fpclassify (-qNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " fpclassify (-qNaN)", (fpclassify (-qNaN_var)==FP_NAN)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " fpclassify (sNaN) isnormal SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " fpclassify (sNaN)", (fpclassify (sNaN_var)==FP_NAN)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " fpclassify (-sNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " fpclassify (-sNaN)", (fpclassify (-sNaN_var)==FP_NAN)); \ + } \ + \ + fesetenv(&saved_fenv); /* restore saved fenv */ \ + remove_sigaction_FP(); \ +} + +TEST_FUNC (float_test, float, f) +TEST_FUNC (double_test, double, ) +#ifndef NO_LONG_DOUBLE +TEST_FUNC (ldouble_test, ldouble, l) +#endif + +static int +do_test (void) +{ + float_test(); + double_test(); +#ifndef NO_LONG_DOUBLE + ldouble_test(); +#endif + + return errors != 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |