From 41c67149b94676347b0068a902058f130e3e88e6 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Wed, 21 Dec 2016 01:48:27 +0000 Subject: Add roundeven, roundevenf, roundevenl. TS 18661-1 defines roundeven functions that round a floating-point number to the nearest integer, in that floating-point type, with ties rounding to even (whereas the round functions round ties away from zero). As with other such functions, they raise no exceptions apart from "invalid" for signaling NaNs. There was a previous user request for this functionality in glibc in . This patch implements these functions for glibc. The implementations use integer bit-manipulation (or roundeven on the high and low parts, in the IBM long double case). It's possible that there may be faster approaches on some architectures (in particular, on AArch64 the frintn instruction should do exactly what's required); I'll leave it to architecture maintainers or others interested to implement such architecture-specific versions if desired. (Where architectures have instructions to round to nearest integer in the current rounding mode, implementations saving and restoring the rounding mode - and dealing with exceptions if those instructions generate "inexact" - are also possible, though their performance depends on the cost of manipulating exceptions / rounding mode state.) Tested for x86_64, x86, mips64 and powerpc. * math/bits/mathcalls.h [__GLIBC_USE (IEC_60559_BFP_EXT)] (roundeven): New declaration. * math/tgmath.h [__GLIBC_USE (IEC_60559_BFP_EXT)] (roundeven): New macro. * math/Versions (roundeven): New libm symbol at version GLIBC_2.25. (roundevenf): Likewise. (roundevenl): Likewise. * math/Makefile (libm-calls): Add s_roundevenF. * math/libm-test.inc (roundeven_test_data): New array. (roundeven_test): New function. (main): Call roundeven_test. * math/test-tgmath.c (NCALLS): Increase to 134. (F(compile_test)): Call roundeven. (F(roundeven)): New function. * manual/arith.texi (Rounding Functions): Document roundeven, roundevenf and roundevenl. * manual/libm-err-tab.pl (@all_functions): Add roundeven. * include/math.h (roundeven): Use libm_hidden_proto. * sysdeps/ieee754/dbl-64/s_roundeven.c: New file. * sysdeps/ieee754/dbl-64/wordsize-64/s_roundeven.c: Likewise. * sysdeps/ieee754/flt-32/s_roundevenf.c: Likewise. * sysdeps/ieee754/ldbl-128/s_roundevenl.c: Likewise. * sysdeps/ieee754/ldbl-128ibm/s_roundevenl.c: Likewise. * sysdeps/ieee754/ldbl-96/s_roundevenl.c: Likewise. * sysdeps/ieee754/ldbl-opt/Makefile (libnldbl-calls): Add roundeven. (CFLAGS-nldbl-roundeven.c): New variable. * sysdeps/ieee754/ldbl-opt/nldbl-roundeven.c: New file. * 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. --- sysdeps/ieee754/ldbl-opt/Makefile | 4 +++- sysdeps/ieee754/ldbl-opt/nldbl-roundeven.c | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 sysdeps/ieee754/ldbl-opt/nldbl-roundeven.c (limited to 'sysdeps/ieee754/ldbl-opt') diff --git a/sysdeps/ieee754/ldbl-opt/Makefile b/sysdeps/ieee754/ldbl-opt/Makefile index 99aa6c6e0b..006d0d59ee 100644 --- a/sysdeps/ieee754/ldbl-opt/Makefile +++ b/sysdeps/ieee754/ldbl-opt/Makefile @@ -43,7 +43,8 @@ libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \ isoc99_wscanf isoc99_fwscanf isoc99_swscanf \ isoc99_vwscanf isoc99_vfwscanf isoc99_vswscanf \ nextup nextdown totalorder totalordermag getpayload \ - canonicalize setpayload setpayloadsig llogb fmaxmag fminmag + canonicalize setpayload setpayloadsig llogb fmaxmag fminmag \ + roundeven libnldbl-routines = $(libnldbl-calls:%=nldbl-%) libnldbl-inhibit-o = $(object-suffixes) libnldbl-static-only-routines = $(libnldbl-routines) @@ -138,6 +139,7 @@ CFLAGS-nldbl-remainder.c = -fno-builtin-remainderl -fno-builtin-dreml CFLAGS-nldbl-remquo.c = -fno-builtin-remquol CFLAGS-nldbl-rint.c = -fno-builtin-rintl CFLAGS-nldbl-round.c = -fno-builtin-roundl +CFLAGS-nldbl-roundeven.c = -fno-builtin-roundevenl CFLAGS-nldbl-scalb.c = -fno-builtin-scalbl CFLAGS-nldbl-scalbln.c = -fno-builtin-scalblnl CFLAGS-nldbl-scalbn.c = -fno-builtin-scalbnl diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-roundeven.c b/sysdeps/ieee754/ldbl-opt/nldbl-roundeven.c new file mode 100644 index 0000000000..cd52e7376f --- /dev/null +++ b/sysdeps/ieee754/ldbl-opt/nldbl-roundeven.c @@ -0,0 +1,26 @@ +/* Compatibility routine for IEEE double as long double for roundeven. + 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 + . */ + +#include "nldbl-compat.h" + +double +attribute_hidden +roundevenl (double x) +{ + return roundeven (x); +} -- cgit 1.4.1