about summary refs log tree commit diff
path: root/math/test-fesetexcept.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2016-08-16 16:16:10 +0000
committerJoseph Myers <joseph@codesourcery.com>2016-08-16 16:16:10 +0000
commit5146356f5a72c3c660cd782c9eaafbe767817050 (patch)
tree34c9a3639d3a116a20c61a6d1d5bedcb7643b762 /math/test-fesetexcept.c
parent056dd72af83f5459ce6d545a49dea6dba7d635dc (diff)
downloadglibc-5146356f5a72c3c660cd782c9eaafbe767817050.tar.gz
glibc-5146356f5a72c3c660cd782c9eaafbe767817050.tar.xz
glibc-5146356f5a72c3c660cd782c9eaafbe767817050.zip
Add fesetexcept.
TS 18661-1 defines an fesetexcept function for setting floating-point
exception flags without the side-effect of causing enabled traps to be
taken.

This patch series implements this function for glibc.  The present
patch adds the fallback stub implementation, x86 and x86_64
implementations, documentation, tests and ABI baseline updates.  The
remaining patches, some of them untested, add implementations for
other architectures.  The implementations generally follow those of
the fesetexceptflag function.

As for fesetexceptflag, the approach taken for architectures where
setting flags causes enabled traps to be taken is to set the flags
(and potentially cause traps) rather than refusing to set the flags
and returning an error.  Since ISO C and TS 18661 provide no way to
enable traps, this is formally in accordance with the standards.

The NEWS entry should be considered a placeholder, since this patch
series is intended to be followed by further such series adding other
TS 18661-1 features, so that the NEWS entry would end up looking more
like

* New <fenv.h> features from TS 18661-1:2014 are added to libm: the
  fesetexcept, fetestexceptflag, fegetmode and fesetmode functions,
  the femode_t type and the FE_DFL_MODE macro.

with hopefully more such entries for other features, rather than
having an entry for a single function in the end.

I believe we have consensus for adding TS 18661-1 interfaces as per
<https://sourceware.org/ml/libc-alpha/2016-06/msg00421.html>.

Tested for x86_64, x86, mips64 (hard float, and soft float to test the
fallback version), arm (hard float) and powerpc (hard float, soft
float and e500).

	* math/fesetexcept.c: New file.
	* sysdeps/i386/fpu/fesetexcept.c: Likewise.
	* sysdeps/x86_64/fpu/fesetexcept.c: Likewise.
	* math/fenv.h: Define
	__GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION and include
	<bits/libc-header-start.h> instead of including <features.h>.
	[__GLIBC_USE (IEC_60559_BFP_EXT)] (fesetexcept): New function
	declaration.
	* manual/arith.texi (fesetexcept): Document function.
	* math/Versions (fesetexcept): New libm symbol at version
	GLIBC_2.25.
	* math/Makefile (libm-support): Add fesetexcept.
	(tests): Add test-fesetexcept and test-fesetexcept-traps.
	* math/test-fesetexcept.c: New file.
	* math/test-fesetexcept-traps.c: Likewise.
	* sysdeps/nacl/libm.abilist: Update.
	* sysdeps/unix/sysv/linux/aarch64/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libm.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libm.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libm.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libm.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libm.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/tile/tilepro/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libm.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libm.abilist: Likewise.
Diffstat (limited to 'math/test-fesetexcept.c')
-rw-r--r--math/test-fesetexcept.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/math/test-fesetexcept.c b/math/test-fesetexcept.c
new file mode 100644
index 0000000000..912a9a6bad
--- /dev/null
+++ b/math/test-fesetexcept.c
@@ -0,0 +1,129 @@
+/* Test fesetexcept.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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/>.  */
+
+#include <fenv.h>
+#include <stdio.h>
+#include <math-tests.h>
+
+static int
+test_fesetexcept (int exc, const char *exc_name)
+{
+  int result = 0;
+
+  printf ("Testing %s\n", exc_name);
+  feclearexcept (FE_ALL_EXCEPT);
+  int ret = fesetexcept (exc);
+  if (ret == 0)
+    printf ("fesetexcept (%s) succeeded\n", exc_name);
+  else
+    {
+      printf ("fesetexcept (%s) failed\n", exc_name);
+      if (exc == 0 || EXCEPTION_TESTS (float))
+	{
+	  puts ("failure of fesetexcept was unexpected");
+	  result = 1;
+	}
+      else
+	puts ("failure of fesetexcept OK, skipping further tests");
+      return result;
+    }
+  ret = fetestexcept (FE_ALL_EXCEPT);
+  if (ret != exc)
+    {
+      printf ("raised exceptions %x, expected %x\n",
+	      (unsigned int) ret, (unsigned int) exc);
+      result = 1;
+    }
+
+  ret = feraiseexcept (FE_ALL_EXCEPT);
+  if (ret != 0)
+    {
+      if (exc == 0 && !EXCEPTION_TESTS (float))
+	{
+	  puts ("feraiseexcept (FE_ALL_EXCEPT) failed, skipping further tests");
+	  return result;
+	}
+      puts ("feraiseexcept (FE_ALL_EXCEPT) unexpectedly failed");
+      result = 1;
+    }
+  ret = fesetexcept (exc);
+  if (ret != 0)
+    {
+      puts ("fesetexcept (second test) unexpectedly failed");
+      result = 1;
+    }
+  ret = fetestexcept (FE_ALL_EXCEPT);
+  if (ret != FE_ALL_EXCEPT)
+    {
+      printf ("raised exceptions (second test) %x, expected %x\n",
+	      (unsigned int) ret, (unsigned int) FE_ALL_EXCEPT);
+      result = 1;
+    }
+
+  feclearexcept (FE_ALL_EXCEPT);
+  ret = feraiseexcept (FE_ALL_EXCEPT & ~exc);
+  if (ret != 0)
+    {
+      puts ("feraiseexcept (third test) unexpectedly failed");
+      result = 1;
+    }
+  ret = fesetexcept (exc);
+  if (ret != 0)
+    {
+      puts ("fesetexcept (third test) unexpectedly failed");
+      result = 1;
+    }
+  ret = fetestexcept (FE_ALL_EXCEPT);
+  if (ret != FE_ALL_EXCEPT)
+    {
+      printf ("raised exceptions (third test) %x, expected %x\n",
+	      (unsigned int) ret, (unsigned int) FE_ALL_EXCEPT);
+      result = 1;
+    }
+
+  return result;
+}
+
+static int
+do_test (void)
+{
+  int result = 0;
+
+  result |= test_fesetexcept (0, "0");
+  result |= test_fesetexcept (FE_ALL_EXCEPT, "FE_ALL_EXCEPT");
+#ifdef FE_DIVBYZERO
+  result |= test_fesetexcept (FE_DIVBYZERO, "FE_DIVBYZERO");
+#endif
+#ifdef FE_INEXACT
+  result |= test_fesetexcept (FE_INEXACT, "FE_INEXACT");
+#endif
+#ifdef FE_INVALID
+  result |= test_fesetexcept (FE_INVALID, "FE_INVALID");
+#endif
+#ifdef FE_OVERFLOW
+  result |= test_fesetexcept (FE_OVERFLOW, "FE_OVERFLOW");
+#endif
+#ifdef FE_UNDERFLOW
+  result |= test_fesetexcept (FE_UNDERFLOW, "FE_UNDERFLOW");
+#endif
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"