/* Test of floating-point rounding direction. Copyright (C) 2023-2024 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Written by Bruno Haible , 2023. */ #include /* Specification. */ #include #include "macros.h" /* Check the FE_TOWARDZERO rounding direction. */ _GL_UNUSED static void test_towardzero () { { float volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p < a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p > a); } { double volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p < a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p > a); } #if !(((defined __FreeBSD__ || defined __OpenBSD__) && defined __aarch64__) || (defined __NetBSD__ && defined __sparcv9 /* sparc64 */) || (defined __OpenBSD__ && defined __mips64)) { long double volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p < a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p > a); } #endif } /* Check the FE_UPWARD rounding direction. */ _GL_UNUSED static void test_upward () { { float volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p > a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p > a); } { double volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p > a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p > a); } #if !(((defined __FreeBSD__ || defined __OpenBSD__) && defined __aarch64__) || (defined __NetBSD__ && defined __sparcv9 /* sparc64 */) || (defined __OpenBSD__ && defined __mips64)) { long double volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p > a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p > a); } #endif } /* Check the FE_DOWNWARD rounding direction. */ _GL_UNUSED static void test_downward () { { float volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p < a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p < a); } { double volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p < a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p < a); } #if !(((defined __FreeBSD__ || defined __OpenBSD__) && defined __aarch64__) || (defined __NetBSD__ && defined __sparcv9 /* sparc64 */) || (defined __OpenBSD__ && defined __mips64)) { long double volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p < a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p < a); } #endif } /* Check the FE_TONEAREST rounding direction. */ static void test_tonearest () { { float volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p == a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p == a); } { double volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p == a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p == a); } { long double volatile a, b, q, p; a = 1; b = 3; q = a / b; p = b * q; ASSERT (p == a); a = -1; b = 3; q = a / b; p = b * q; ASSERT (p == a); } } int main () { /* Check that the default rounding direction is FE_TONEAREST. */ test_tonearest (); /* On alpha, this test works only when compiled with the GCC option '-mfp-rounding-mode=d'. */ #if !((defined __arm__ && defined __SOFTFP__) || defined __alpha) # if defined FE_TOWARDZERO ASSERT (fesetround (FE_TOWARDZERO) == 0); test_towardzero (); ASSERT (fegetround () == FE_TOWARDZERO); # endif # if defined FE_UPWARD ASSERT (fesetround (FE_UPWARD) == 0); test_upward (); ASSERT (fegetround () == FE_UPWARD); # endif # if defined FE_DOWNWARD ASSERT (fesetround (FE_DOWNWARD) == 0); test_downward (); ASSERT (fegetround () == FE_DOWNWARD); # endif #endif ASSERT (fesetround (FE_TONEAREST) == 0); test_tonearest (); ASSERT (fegetround () == FE_TONEAREST); return 0; }