(root)/
glibc-2.38/
math/
test-snan.c
       1  /* Test signaling NaNs in issignaling, isnan, isinf, and similar functions.
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #define _GNU_SOURCE 1
      20  #include <stdio.h>
      21  #include <math.h>
      22  #include <float.h>
      23  #include <fenv.h>
      24  #include <signal.h>
      25  #include <setjmp.h>
      26  
      27  #include <math-tests.h>
      28  #include <support/check.h>
      29  
      30  
      31  #ifdef __SUPPORT_SNAN__
      32  static sigjmp_buf sigfpe_buf;
      33  
      34  static void
      35  myFPsighandler (int signal)
      36  {
      37    siglongjmp (sigfpe_buf, 1);
      38  }
      39  
      40  static int errors = 0;
      41  
      42  #define CHECK(testname, expr)						      \
      43    do {									      \
      44      feclearexcept (FE_ALL_EXCEPT);					      \
      45      feenableexcept (FE_ALL_EXCEPT);					      \
      46      if (sigsetjmp (sigfpe_buf, 0))					      \
      47        {									      \
      48  	printf ("%s raised SIGFPE\n", testname);			      \
      49  	++errors;							      \
      50        }									      \
      51      else if (!(expr))							      \
      52        {									      \
      53          printf ("Failure: %s\n", testname);				      \
      54          ++errors;							      \
      55        }									      \
      56    } while (0)
      57  
      58  #define TEST_FUNC(NAME, FLOAT, SUFFIX)					      \
      59  static void								      \
      60  NAME (void)								      \
      61  {									      \
      62    /* Variables are declared volatile to forbid some compiler		      \
      63       optimizations.  */							      \
      64    volatile FLOAT Inf_var, qNaN_var, zero_var, one_var;			      \
      65    /* A sNaN is only guaranteed to be representable in variables with */	      \
      66    /* static (or thread-local) storage duration.  */			      \
      67    static volatile FLOAT sNaN_var = __builtin_nans ## SUFFIX ("");	      \
      68    static volatile FLOAT minus_sNaN_var = -__builtin_nans ## SUFFIX ("");      \
      69    fenv_t saved_fenv;							      \
      70  									      \
      71    zero_var = 0.0;							      \
      72    one_var = 1.0;							      \
      73    qNaN_var = __builtin_nan ## SUFFIX ("");				      \
      74    Inf_var = one_var / zero_var;						      \
      75  									      \
      76    (void) &zero_var;							      \
      77    (void) &one_var;							      \
      78    (void) &qNaN_var;							      \
      79    (void) &sNaN_var;							      \
      80    (void) &minus_sNaN_var;						      \
      81    (void) &Inf_var;							      \
      82  									      \
      83    fegetenv (&saved_fenv);						      \
      84  									      \
      85    CHECK (#FLOAT " issignaling (qNaN)", !issignaling (qNaN_var));	      \
      86    CHECK (#FLOAT " issignaling (-qNaN)", !issignaling (-qNaN_var));	      \
      87    CHECK (#FLOAT " issignaling (sNaN)",					      \
      88           SNAN_TESTS (FLOAT) ? issignaling (sNaN_var) : 1);		      \
      89    CHECK (#FLOAT " issignaling (-sNaN)",					      \
      90           SNAN_TESTS (FLOAT) ? issignaling (minus_sNaN_var) : 1);	      \
      91    CHECK (#FLOAT " isnan (qNaN)", isnan (qNaN_var));			      \
      92    CHECK (#FLOAT " isnan (-qNaN)", isnan (-qNaN_var));			      \
      93    CHECK (#FLOAT " isnan (sNaN)",					      \
      94           SNAN_TESTS (FLOAT) ? isnan (sNaN_var) : 1);			      \
      95    CHECK (#FLOAT " isnan (-sNaN)",					      \
      96           SNAN_TESTS (FLOAT) ? isnan (minus_sNaN_var) : 1);		      \
      97    CHECK (#FLOAT " isinf (qNaN)", !isinf (qNaN_var));			      \
      98    CHECK (#FLOAT " isinf (-qNaN)", !isinf (-qNaN_var));			      \
      99    CHECK (#FLOAT " isinf (sNaN)",					      \
     100           SNAN_TESTS (FLOAT) ? !isinf (sNaN_var) : 1);			      \
     101    CHECK (#FLOAT " isinf (-sNaN)",					      \
     102           SNAN_TESTS (FLOAT) ? !isinf (minus_sNaN_var) : 1);		      \
     103    CHECK (#FLOAT " isfinite (qNaN)", !isfinite (qNaN_var));		      \
     104    CHECK (#FLOAT " isfinite (-qNaN)", !isfinite (-qNaN_var));		      \
     105    CHECK (#FLOAT " isfinite (sNaN)",					      \
     106           SNAN_TESTS (FLOAT) ? !isfinite (sNaN_var) : 1);		      \
     107    CHECK (#FLOAT " isfinite (-sNaN)",					      \
     108           SNAN_TESTS (FLOAT) ? !isfinite (minus_sNaN_var) : 1);		      \
     109    CHECK (#FLOAT " isnormal (qNaN)", !isnormal (qNaN_var));		      \
     110    CHECK (#FLOAT " isnormal (-qNaN)", !isnormal (-qNaN_var));		      \
     111    CHECK (#FLOAT " isnormal (sNaN)",					      \
     112           SNAN_TESTS (FLOAT) ? !isnormal (sNaN_var) : 1);		      \
     113    CHECK (#FLOAT " isnormal (-sNaN)",					      \
     114           SNAN_TESTS (FLOAT) ? !isnormal (minus_sNaN_var) : 1);		      \
     115    CHECK (#FLOAT " fpclassify (qNaN)", (fpclassify (qNaN_var)==FP_NAN));	      \
     116    CHECK (#FLOAT " fpclassify (-qNaN)", (fpclassify (-qNaN_var)==FP_NAN));     \
     117    CHECK (#FLOAT " fpclassify (sNaN)",					      \
     118           SNAN_TESTS (FLOAT) ? fpclassify (sNaN_var) == FP_NAN : 1);	      \
     119    CHECK (#FLOAT " fpclassify (-sNaN)",					      \
     120           SNAN_TESTS (FLOAT) ? fpclassify (minus_sNaN_var) == FP_NAN : 1);     \
     121  									      \
     122    fesetenv (&saved_fenv); /* restore saved fenv */			      \
     123  }									      \
     124  
     125  TEST_FUNC (float_test, float, f)
     126  TEST_FUNC (double_test, double, )
     127  TEST_FUNC (ldouble_test, long double, l)
     128  #endif
     129  
     130  static int
     131  do_test (void)
     132  {
     133  #ifdef __SUPPORT_SNAN__
     134    signal (SIGFPE, &myFPsighandler);
     135  
     136    float_test ();
     137    double_test ();
     138    ldouble_test ();
     139  
     140    return errors != 0;
     141  #else
     142    FAIL_UNSUPPORTED ("compiler does not support -fsignaling-nans");
     143  #endif
     144  }
     145  
     146  #include <support/test-driver.c>