(root)/
glibc-2.38/
math/
basic-test.c
       1  /* Copyright (C) 1999-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <math.h>
      19  #include <float.h>
      20  #include <stdio.h>
      21  
      22  #include <math-tests.h>
      23  
      24  
      25  static int errors = 0;
      26  
      27  
      28  static void
      29  check (const char *testname, int result)
      30  {
      31    if (!result) {
      32      printf ("Failure: %s\n", testname);
      33      errors++;
      34    }
      35  }
      36  
      37  #define TEST_FUNC(NAME, FLOAT, SUFFIX, EPSILON, HUGEVAL)		      \
      38  static void								      \
      39  NAME (void)								      \
      40  {									      \
      41    /* Variables are declared volatile to forbid some compiler		      \
      42       optimizations.  */							      \
      43    volatile FLOAT Inf_var, qNaN_var, zero_var, one_var;			      \
      44    /* A sNaN is only guaranteed to be representable in variables with */	      \
      45    /* static (or thread-local) storage duration.  */			      \
      46    static volatile FLOAT sNaN_var = __builtin_nans ## SUFFIX ("");	      \
      47    static volatile FLOAT minus_sNaN_var = -__builtin_nans ## SUFFIX ("");      \
      48    FLOAT x1, x2;								      \
      49  									      \
      50    zero_var = 0.0;							      \
      51    one_var = 1.0;							      \
      52    qNaN_var = __builtin_nan ## SUFFIX ("");				      \
      53    Inf_var = one_var / zero_var;						      \
      54  									      \
      55    (void) &zero_var;							      \
      56    (void) &one_var;							      \
      57    (void) &qNaN_var;							      \
      58    (void) &sNaN_var;							      \
      59    (void) &minus_sNaN_var;						      \
      60    (void) &Inf_var;							      \
      61  									      \
      62  									      \
      63    check (#FLOAT " isinf (inf) == 1", isinf (Inf_var) == 1);		      \
      64    check (#FLOAT " isinf (-inf) == -1", isinf (-Inf_var) == -1);		      \
      65    check (#FLOAT " !isinf (1)", !(isinf (one_var)));			      \
      66    check (#FLOAT " !isinf (qNaN)", !(isinf (qNaN_var)));			      \
      67    if (SNAN_TESTS (FLOAT))						      \
      68      check (#FLOAT " !isinf (sNaN)", !(isinf (sNaN_var)));		      \
      69  									      \
      70    check (#FLOAT " isnan (qNaN)", isnan (qNaN_var));			      \
      71    if (SNAN_TESTS (FLOAT))						      \
      72      check (#FLOAT " isnan (sNaN)", isnan (sNaN_var));			      \
      73    check (#FLOAT " isnan (-qNaN)", isnan (-qNaN_var));			      \
      74    if (SNAN_TESTS (FLOAT))						      \
      75      check (#FLOAT " isnan (-sNaN)", isnan (minus_sNaN_var));		      \
      76    check (#FLOAT " !isnan (1)", !(isnan (one_var)));			      \
      77    check (#FLOAT " !isnan (inf)", !(isnan (Inf_var)));			      \
      78  									      \
      79    check (#FLOAT " !issignaling (qNaN)", !(issignaling (qNaN_var)));	      \
      80    if (SNAN_TESTS (FLOAT))						      \
      81      check (#FLOAT " issignaling (sNaN)", issignaling (sNaN_var));	      \
      82    check (#FLOAT " !issignaling (-qNaN)", !(issignaling (-qNaN_var)));	      \
      83    if (SNAN_TESTS (FLOAT))						      \
      84      check (#FLOAT " issignaling (-sNaN)", issignaling (minus_sNaN_var));      \
      85    check (#FLOAT " !issignaling (1)", !(issignaling (one_var)));		      \
      86    check (#FLOAT " !issignaling (inf)", !(issignaling (Inf_var)));	      \
      87  									      \
      88    check (#FLOAT " inf == inf", Inf_var == Inf_var);			      \
      89    check (#FLOAT " -inf == -inf", -Inf_var == -Inf_var);			      \
      90    check (#FLOAT " inf != -inf", Inf_var != -Inf_var);			      \
      91    check (#FLOAT " qNaN != qNaN", qNaN_var != qNaN_var);			      \
      92    if (SNAN_TESTS (FLOAT))						      \
      93      check (#FLOAT " sNaN != sNaN", sNaN_var != sNaN_var);		      \
      94    if (SNAN_TESTS (FLOAT))						      \
      95      check (#FLOAT " qNaN != sNaN", qNaN_var != sNaN_var);		      \
      96    if (SNAN_TESTS (FLOAT))						      \
      97      check (#FLOAT " -sNaN != -sNaN", minus_sNaN_var != minus_sNaN_var);	      \
      98    if (SNAN_TESTS (FLOAT))						      \
      99      check (#FLOAT " sNaN != -sNaN", sNaN_var != minus_sNaN_var);	      \
     100    if (SNAN_TESTS (FLOAT))						      \
     101      check (#FLOAT " qNaN != -sNaN", qNaN_var != minus_sNaN_var);	      \
     102  									      \
     103    /*									      \
     104       the same tests but this time with NAN from <bits/nan.h>		      \
     105       NAN is a double const						      \
     106     */									      \
     107    check (#FLOAT " isnan (NAN)", isnan (NAN));				      \
     108    check (#FLOAT " isnan (-NAN)", isnan (-NAN));				      \
     109    check (#FLOAT " !isinf (NAN)", !(isinf (NAN)));			      \
     110    check (#FLOAT " !isinf (-NAN)", !(isinf (-NAN)));			      \
     111    check (#FLOAT " NAN != NAN", NAN != NAN);				      \
     112    check (#FLOAT " NAN != qNaN", NAN != qNaN_var);			      \
     113    if (SNAN_TESTS (FLOAT))						      \
     114      check (#FLOAT " NAN != sNaN", NAN != sNaN_var);			      \
     115    if (SNAN_TESTS (FLOAT))						      \
     116      check (#FLOAT " NAN != -sNaN", NAN != minus_sNaN_var);		      \
     117  									      \
     118    /*									      \
     119       And again with the value returned by the `nan' function.		      \
     120     */									      \
     121    check (#FLOAT " isnan (nan (\"\"))", isnan (nan ## SUFFIX ("")));	      \
     122    check (#FLOAT " isnan (-nan (\"\"))", isnan (-nan ## SUFFIX ("")));	      \
     123    check (#FLOAT " !isinf (nan (\"\"))", !(isinf (nan ## SUFFIX (""))));	      \
     124    check (#FLOAT " !isinf (-nan (\"\"))", !(isinf (-nan ## SUFFIX (""))));     \
     125    check (#FLOAT " nan (\"\") != nan (\"\")",				      \
     126  	 nan ## SUFFIX ("") != nan ## SUFFIX (""));			      \
     127    check (#FLOAT " nan (\"\") != qNaN", nan ## SUFFIX ("") != qNaN_var);	      \
     128    if (SNAN_TESTS (FLOAT))						      \
     129      check (#FLOAT " nan (\"\") != sNaN", nan ## SUFFIX ("") != sNaN_var);     \
     130    if (SNAN_TESTS (FLOAT))						      \
     131      check (#FLOAT " nan (\"\") != -sNaN",				      \
     132  	   nan ## SUFFIX ("") != minus_sNaN_var);			      \
     133  									      \
     134    /* test if EPSILON is ok */						      \
     135    x1 = 1.0;								      \
     136    x2 = x1 + EPSILON;							      \
     137    check (#FLOAT " 1 != 1+EPSILON", x1 != x2);				      \
     138  									      \
     139    x1 = 1.0;								      \
     140    x2 = x1 - EPSILON;							      \
     141    check (#FLOAT " 1 != 1-EPSILON", x1 != x2);				      \
     142  									      \
     143    /* test if HUGE_VALx is ok */						      \
     144    x1 = HUGEVAL;								      \
     145    check (#FLOAT " isinf (HUGE_VALx) == +1", isinf (x1) == +1);		      \
     146    x1 = - HUGEVAL;							      \
     147    check (#FLOAT " isinf (-HUGE_VALx) == -1", isinf (x1) == -1);		      \
     148  }
     149  
     150  #define TEST_CONVERT(NAME, FLOAT, DOUBLE, SUFFIX)			      \
     151  void									      \
     152  NAME (void)								      \
     153  {									      \
     154    volatile DOUBLE Inf_var, qNaN_var, zero_var, one_var;			      \
     155    /* A sNaN is only guaranteed to be representable in variables with */	      \
     156    /* static (or thread-local) storage duration.  */			      \
     157    static volatile DOUBLE sNaN_var = __builtin_nans ## SUFFIX ("");	      \
     158    FLOAT x1, x2;								      \
     159  									      \
     160    zero_var = 0.0;							      \
     161    one_var = 1.0;							      \
     162    qNaN_var = __builtin_nan ## SUFFIX ("");				      \
     163    Inf_var = one_var / zero_var;						      \
     164  									      \
     165    (void) &qNaN_var;							      \
     166    (void) &sNaN_var;							      \
     167    (void) &Inf_var;							      \
     168  									      \
     169    x1 = (FLOAT) qNaN_var;						      \
     170    check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") qNaN, isnan", isnan (x1));     \
     171    check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") qNaN, !issignaling",	      \
     172  	 !issignaling (x1));						      \
     173    if (SNAN_TESTS (FLOAT))						      \
     174      {									      \
     175        x1 = (FLOAT) sNaN_var;						      \
     176        check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") sNaN, isnan", isnan (x1)); \
     177        if (SNAN_TESTS_TYPE_CAST)						      \
     178  	{								      \
     179  	  /* Upon type conversion, a sNaN is converted into a qNaN plus an */ \
     180  	  /* INVALID exception (not checked here).  */			      \
     181  	  check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") sNaN, !issignaling",   \
     182  		 !issignaling (x1));					      \
     183  	}								      \
     184        }									      \
     185    x2 = (FLOAT) Inf_var;							      \
     186    check (" "#FLOAT" x = ("#FLOAT") ("#DOUBLE") Inf", isinf (x2) != 0);	      \
     187  }
     188  
     189  TEST_FUNC (float_test, float, f, FLT_EPSILON, HUGE_VALF)
     190  TEST_FUNC (double_test, double, , DBL_EPSILON, HUGE_VAL)
     191  TEST_CONVERT (convert_dfsf_test, float, double, )
     192  TEST_CONVERT (convert_sfdf_test, double, float, f)
     193  #if LDBL_MANT_DIG > DBL_MANT_DIG
     194  TEST_FUNC (ldouble_test, long double, l, LDBL_EPSILON, HUGE_VALL)
     195  TEST_CONVERT (convert_tfsf_test, float, long double, l)
     196  TEST_CONVERT (convert_sftf_test, long double, float, f)
     197  TEST_CONVERT (convert_tfdf_test, double, long double, l)
     198  TEST_CONVERT (convert_dftf_test, long double, double, )
     199  #endif
     200  
     201  int
     202  do_test (void)
     203  {
     204    float_test ();
     205    double_test ();
     206    convert_dfsf_test();
     207    convert_sfdf_test();
     208  
     209  #if LDBL_MANT_DIG > DBL_MANT_DIG
     210    ldouble_test ();
     211    convert_tfsf_test();
     212    convert_sftf_test();
     213    convert_tfdf_test();
     214    convert_dftf_test();
     215  #endif
     216  
     217    return errors != 0;
     218  }
     219  
     220  #define TEST_FUNCTION do_test ()
     221  #include "../test-skeleton.c"