(root)/
glibc-2.38/
math/
test-femode.c
       1  /* Test femode_t functions.
       2     Copyright (C) 2016-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  #include <fenv.h>
      20  #include <stdio.h>
      21  #include <math-tests.h>
      22  
      23  static int
      24  test_mmee (int mode1, int mode2, int exc1, int exc2)
      25  {
      26    int result = 0;
      27    printf ("testing %x %x %x %x\n", (unsigned int) mode1, (unsigned int) mode2,
      28  	  (unsigned int) exc1, (unsigned int) exc2);
      29  
      30    feclearexcept (FE_ALL_EXCEPT);
      31    int ret = fesetround (mode1);
      32    if (ret != 0)
      33      {
      34        if (ROUNDING_TESTS (float, mode1))
      35  	{
      36  	  puts ("first fesetround failed unexpectedly");
      37  	  result = 1;
      38  	}
      39        else
      40  	puts ("first fesetround failed, cannot test");
      41        return result;
      42      }
      43    ret = fesetexcept (exc1);
      44    if (ret != 0)
      45      {
      46        if (EXCEPTION_TESTS (float) || exc1 == 0)
      47  	{
      48  	  puts ("first fesetexcept failed unexpectedly");
      49  	  result = 1;
      50  	}
      51        else
      52  	puts ("first fesetexcept failed, cannot test");
      53        return result;
      54      }
      55    femode_t saved;
      56    ret = fegetmode (&saved);
      57    if (ret != 0)
      58      {
      59        puts ("fegetmode failed");
      60        result = 1;
      61        return result;
      62      }
      63    feclearexcept (FE_ALL_EXCEPT);
      64    ret = fesetround (mode2);
      65    if (ret != 0)
      66      {
      67        if (ROUNDING_TESTS (float, mode2))
      68  	{
      69  	  puts ("second fesetround failed unexpectedly");
      70  	  result = 1;
      71  	}
      72        else
      73  	puts ("second fesetround failed, cannot test");
      74        return result;
      75      }
      76    ret = fesetexcept (exc2);
      77    if (ret != 0)
      78      {
      79        if (EXCEPTION_TESTS (float) || exc2 == 0)
      80  	{
      81  	  puts ("second fesetexcept failed unexpectedly");
      82  	  result = 1;
      83  	}
      84        else
      85  	puts ("second fesetexcept failed, cannot test");
      86        return result;
      87      }
      88    ret = fesetmode (&saved);
      89    if (ret != 0)
      90      {
      91        puts ("fesetmode failed");
      92        result = 1;
      93        return result;
      94      }
      95    /* Verify that the rounding mode was restored but the exception
      96       flags remain unchanged.  */
      97    ret = fegetround ();
      98    if (ret != mode1)
      99      {
     100        printf ("restored rounding mode %x not %x\n", (unsigned int) ret,
     101  	      (unsigned int) mode1);
     102        result = 1;
     103      }
     104    ret = fetestexcept (FE_ALL_EXCEPT);
     105    if (ret != exc2)
     106      {
     107        printf ("exceptions %x not %x\n", (unsigned int) ret,
     108  	      (unsigned int) exc2);
     109        result = 1;
     110      }
     111    /* Likewise, with default modes.  */
     112    ret = fesetmode (FE_DFL_MODE);
     113    if (ret != 0)
     114      {
     115        puts ("fesetmode (FE_DFL_MODE) failed");
     116        result = 1;
     117        return result;
     118      }
     119    ret = fegetround ();
     120    if (ret != FE_TONEAREST)
     121      {
     122        printf ("FE_DFL_MODE rounding mode %x not %x\n", (unsigned int) ret,
     123  	      (unsigned int) FE_TONEAREST);
     124        result = 1;
     125      }
     126    ret = fetestexcept (FE_ALL_EXCEPT);
     127    if (ret != exc2)
     128      {
     129        printf ("FE_DFL_MODE exceptions %x not %x\n", (unsigned int) ret,
     130  	      (unsigned int) exc2);
     131        result = 1;
     132      }
     133    return result;
     134  }
     135  
     136  static int
     137  test_mme (int mode1, int mode2, int exc1)
     138  {
     139    int result = 0;
     140  
     141    result |= test_mmee (mode1, mode2, exc1, 0);
     142    result |= test_mmee (mode1, mode2, exc1, FE_ALL_EXCEPT);
     143  #ifdef FE_DIVBYZERO
     144    result |= test_mmee (mode1, mode2, exc1, FE_DIVBYZERO);
     145  #endif
     146  #ifdef FE_INEXACT
     147    result |= test_mmee (mode1, mode2, exc1, FE_INEXACT);
     148  #endif
     149  #ifdef FE_INVALID
     150    result |= test_mmee (mode1, mode2, exc1, FE_INVALID);
     151  #endif
     152  #ifdef FE_OVERFLOW
     153    result |= test_mmee (mode1, mode2, exc1, FE_OVERFLOW);
     154  #endif
     155  #ifdef FE_UNDERFLOW
     156    result |= test_mmee (mode1, mode2, exc1, FE_UNDERFLOW);
     157  #endif
     158  
     159    return result;
     160  }
     161  
     162  static int
     163  test_mm (int mode1, int mode2)
     164  {
     165    int result = 0;
     166  
     167    result |= test_mme (mode1, mode2, 0);
     168    result |= test_mme (mode1, mode2, FE_ALL_EXCEPT);
     169  #ifdef FE_DIVBYZERO
     170    result |= test_mme (mode1, mode2, FE_DIVBYZERO);
     171  #endif
     172  #ifdef FE_INEXACT
     173    result |= test_mme (mode1, mode2, FE_INEXACT);
     174  #endif
     175  #ifdef FE_INVALID
     176    result |= test_mme (mode1, mode2, FE_INVALID);
     177  #endif
     178  #ifdef FE_OVERFLOW
     179    result |= test_mme (mode1, mode2, FE_OVERFLOW);
     180  #endif
     181  #ifdef FE_UNDERFLOW
     182    result |= test_mme (mode1, mode2, FE_UNDERFLOW);
     183  #endif
     184  
     185    return result;
     186  }
     187  
     188  static int
     189  test_m (int mode1)
     190  {
     191    int result = 0;
     192  
     193  #ifdef FE_DOWNWARD
     194    result |= test_mm (mode1, FE_DOWNWARD);
     195  #endif
     196  #ifdef FE_TONEAREST
     197    result |= test_mm (mode1, FE_TONEAREST);
     198  #endif
     199  #ifdef FE_TOWARDZERO
     200    result |= test_mm (mode1, FE_TOWARDZERO);
     201  #endif
     202  #ifdef FE_UPWARD
     203    result |= test_mm (mode1, FE_UPWARD);
     204  #endif
     205  
     206    return result;
     207  }
     208  
     209  static int
     210  do_test (void)
     211  {
     212    int result = 0;
     213  
     214  #ifdef FE_DOWNWARD
     215    result |= test_m (FE_DOWNWARD);
     216  #endif
     217  #ifdef FE_TONEAREST
     218    result |= test_m (FE_TONEAREST);
     219  #endif
     220  #ifdef FE_TOWARDZERO
     221    result |= test_m (FE_TOWARDZERO);
     222  #endif
     223  #ifdef FE_UPWARD
     224    result |= test_m (FE_UPWARD);
     225  #endif
     226  
     227    return result;
     228  }
     229  
     230  #define TEST_FUNCTION do_test ()
     231  #include "../test-skeleton.c"