From: Bruno Haible <bruno@clisp.org>
To: bug-gnulib@gnu.org
Subject: new modules setpayloadsig, setpayloadsigf, setpayloadsigl
Date: Wed, 17 Apr 2024 00:49:51 +0200 [thread overview]
Message-ID: <6040641.QK70jAV3al@nimes> (raw)
[-- Attachment #1: Type: text/plain, Size: 2528 bytes --]
ISO C 23 specifies in the (optional, but normative) Annex F also functions
for creating signalling NaNs with a given payload. Here is a patch series that
implements them.
2024-04-16 Bruno Haible <bruno@clisp.org>
setpayloadsigl: Add tests.
* tests/test-setpayloadsigl.c: New file, based on
tests/test-setpayloadl.c.
* modules/setpayloadsigl-tests: New file.
setpayloadsigl: New module.
* lib/math.in.h (setpayloadsigl): New declaration.
* lib/setpayloadsigl.c: New file, based on lib/setpayloadl.c.
* m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsigl is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIGL.
(gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIGL.
* modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIGL,
HAVE_SETPAYLOADSIGL.
* modules/setpayloadsigl: New file.
* doc/posix-functions/setpayloadsigl.texi: Mention the new module.
2024-04-16 Bruno Haible <bruno@clisp.org>
setpayloadsigf: Add tests.
* tests/test-setpayloadf.c (PAYLOAD_BITS): New macro.
(main): Use it.
* tests/test-setpayloadsigf.c: New file, based on
tests/test-setpayloadf.c.
* modules/setpayloadsigf-tests: New file.
setpayloadsigf: New module.
* lib/math.in.h (setpayloadsigf): New declaration.
* lib/setpayloadsigf.c: New file, based on lib/setpayloadf.c.
* m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsigf is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIGF.
(gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIGF.
* modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIGF,
HAVE_SETPAYLOADSIGF.
* modules/setpayloadsigf: New file.
* doc/posix-functions/setpayloadsigf.texi: Mention the new module.
2024-04-16 Bruno Haible <bruno@clisp.org>
setpayloadsig: Add tests.
* tests/test-setpayload.c (PAYLOAD_BITS): New macro.
(main): Use it.
* tests/test-setpayloadsig.c: New file, based on
tests/test-setpayload.c.
* modules/setpayloadsig-tests: New file.
setpayloadsig: New module.
* lib/math.in.h (setpayloadsig): New declaration.
* lib/setpayloadsig.c: New file, based on lib/setpayload.c.
* m4/setpayloadsig.m4: New file, based on m4/setpayload.m4.
* m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsig is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIG.
(gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIG.
* modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIG,
HAVE_SETPAYLOADSIG.
* modules/setpayloadsig: New file.
* doc/posix-functions/setpayloadsig.texi: Mention the new module.
[-- Attachment #2: 0001-setpayloadsig-New-module.patch --]
[-- Type: text/x-patch, Size: 12355 bytes --]
From f9e62b06d50b24b727e2f9940d6c23848070c01c Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Tue, 16 Apr 2024 21:01:17 +0200
Subject: [PATCH 1/6] setpayloadsig: New module.
* lib/math.in.h (setpayloadsig): New declaration.
* lib/setpayloadsig.c: New file, based on lib/setpayload.c.
* m4/setpayloadsig.m4: New file, based on m4/setpayload.m4.
* m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsig is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIG.
(gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIG.
* modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIG,
HAVE_SETPAYLOADSIG.
* modules/setpayloadsig: New file.
* doc/posix-functions/setpayloadsig.texi: Mention the new module.
---
ChangeLog | 14 +++++
doc/posix-functions/setpayloadsig.texi | 8 +--
lib/math.in.h | 15 ++++++
lib/setpayloadsig.c | 74 ++++++++++++++++++++++++++
m4/math_h.m4 | 5 +-
m4/setpayloadsig.m4 | 63 ++++++++++++++++++++++
modules/math | 2 +
modules/setpayloadsig | 36 +++++++++++++
8 files changed, 212 insertions(+), 5 deletions(-)
create mode 100644 lib/setpayloadsig.c
create mode 100644 m4/setpayloadsig.m4
create mode 100644 modules/setpayloadsig
diff --git a/ChangeLog b/ChangeLog
index 7521411127..c4a23adb45 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2024-04-16 Bruno Haible <bruno@clisp.org>
+
+ setpayloadsig: New module.
+ * lib/math.in.h (setpayloadsig): New declaration.
+ * lib/setpayloadsig.c: New file, based on lib/setpayload.c.
+ * m4/setpayloadsig.m4: New file, based on m4/setpayload.m4.
+ * m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsig is declared.
+ (gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIG.
+ (gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIG.
+ * modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIG,
+ HAVE_SETPAYLOADSIG.
+ * modules/setpayloadsig: New file.
+ * doc/posix-functions/setpayloadsig.texi: Mention the new module.
+
2024-04-16 Bruno Haible <bruno@clisp.org>
setpayloadl: Fix platform-specific bugs.
diff --git a/doc/posix-functions/setpayloadsig.texi b/doc/posix-functions/setpayloadsig.texi
index 09ef9b86fc..6c40c6039e 100644
--- a/doc/posix-functions/setpayloadsig.texi
+++ b/doc/posix-functions/setpayloadsig.texi
@@ -10,15 +10,15 @@
@url{https://www.gnu.org/software/libc/manual/html_node/FP-Bit-Twiddling.html}.
@end ifnotinfo
-Gnulib module: ---
+Gnulib module: setpayloadsig
Portability problems fixed by Gnulib:
@itemize
+@item
+This function is missing on all non-glibc platforms:
+glibc 2.24, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
-@item
-This function is missing on all non-glibc platforms:
-glibc 2.24, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
@end itemize
diff --git a/lib/math.in.h b/lib/math.in.h
index 98da404780..c61e65c423 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2817,6 +2817,21 @@ _GL_WARN_ON_USE (setpayloadl, "setpayloadl is unportable - "
#endif
+#if @GNULIB_SETPAYLOADSIG@
+# if !@HAVE_SETPAYLOADSIG@
+_GL_FUNCDECL_SYS (setpayloadsig, int, (double *, double));
+# endif
+_GL_CXXALIAS_SYS (setpayloadsig, int, (double *, double));
+_GL_CXXALIASWARN (setpayloadsig);
+#elif defined GNULIB_POSIXCHECK
+# undef setpayloadsig
+# if HAVE_RAW_DECL_SETPAYLOADSIG
+_GL_WARN_ON_USE (setpayloadsig, "setpayloadsig is unportable - "
+ "use gnulib module setpayloadsig for portability");
+# endif
+#endif
+
+
#if @GNULIB_TOTALORDERF@
# if @REPLACE_TOTALORDERF@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
diff --git a/lib/setpayloadsig.c b/lib/setpayloadsig.c
new file mode 100644
index 0000000000..c336f08c80
--- /dev/null
+++ b/lib/setpayloadsig.c
@@ -0,0 +1,74 @@
+/* Construct a signalling NaN 'double' with a given payload.
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This file 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 3 of the
+ License, or (at your option) any later version.
+
+ This file 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible. */
+
+#include <config.h>
+
+/* Specification. */
+#include <math.h>
+
+#include <float.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "signed-snan.h"
+
+int
+setpayloadsig (double *result, double payload)
+{
+#if DBL_MANT_DIG == 53
+ if (
+# if defined __hppa || defined __mips__ || defined __sh__
+ payload >= 0.0
+# else
+ /* A zero payload is not allowed, because that would denote Infinity.
+ Cf. snan.h. */
+ payload > 0.0
+# endif
+ && payload < 2251799813685248.0 /* (double) (1ULL << (DBL_MANT_DIG - 2)) */
+ && payload == (double) (int64_t) payload)
+ {
+ memory_double x = memory_positive_SNaNd ();
+ uint64_t pl = (int64_t) payload;
+ uint32_t pl_hi = (uint32_t) (pl >> 32);
+ uint32_t pl_lo = (uint32_t) pl;
+ x.word[DBL_EXPBIT0_WORD] =
+ (x.word[DBL_EXPBIT0_WORD] & ~((1U << (DBL_MANT_DIG - 2 - 32)) - 1))
+ | pl_hi;
+ x.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD == 0 ? 1 : -1)] = pl_lo;
+# if 0
+ *result = x.value;
+# else
+ /* On 32-bit x86 processors, as well as on x86_64 processors with
+ CC="gcc -mfpmath=387", the evaluation of *x and *y above is done
+ through an 'fldl' instruction, which converts a signalling NaN to
+ a quiet NaN. See
+ <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
+ for details. Use memcpy to avoid this. */
+ memcpy (result, &x.value, sizeof (double));
+# endif
+ return 0;
+ }
+ else
+ {
+ *result = 0.0;
+ return -1;
+ }
+#else
+# error "Please port gnulib setpayloadsig.c to your platform!"
+#endif
+}
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 3dc779160c..0c5ce4f89c 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,5 +1,5 @@
# math_h.m4
-# serial 129
+# serial 130
dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -52,6 +52,7 @@ AC_DEFUN_ONCE([gl_MATH_H]
remainder remainderf remainderl
rint rintf rintl round roundf roundl
setpayload setpayloadf setpayloadl
+ setpayloadsig
sinf sinl sinhf sqrtf sqrtl
tanf tanl tanhf totalorder totalorderf totalorderl trunc truncf truncl])
])
@@ -162,6 +163,7 @@ AC_DEFUN([gl_MATH_H_REQUIRE_DEFAULTS]
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOAD])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADF])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADL])
+ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADSIG])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SIGNBIT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SINF])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SINL])
@@ -247,6 +249,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
HAVE_SETPAYLOAD=1; AC_SUBST([HAVE_SETPAYLOAD])
HAVE_SETPAYLOADF=1; AC_SUBST([HAVE_SETPAYLOADF])
HAVE_SETPAYLOADL=1; AC_SUBST([HAVE_SETPAYLOADL])
+ HAVE_SETPAYLOADSIG=1; AC_SUBST([HAVE_SETPAYLOADSIG])
HAVE_SINF=1; AC_SUBST([HAVE_SINF])
HAVE_SINL=1; AC_SUBST([HAVE_SINL])
HAVE_SINHF=1; AC_SUBST([HAVE_SINHF])
diff --git a/m4/setpayloadsig.m4 b/m4/setpayloadsig.m4
new file mode 100644
index 0000000000..a6ff790d4d
--- /dev/null
+++ b/m4/setpayloadsig.m4
@@ -0,0 +1,63 @@
+# setpayloadsig.m4
+# serial 1
+dnl Copyright 2024 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_SETPAYLOADSIGF],
+[
+ AC_REQUIRE([gl_MATH_H_DEFAULTS])
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+ gl_MATHFUNC([setpayloadsigf], [int], [(float *, float)])
+ if test $gl_cv_func_setpayloadsigf_no_libm != yes \
+ && test $gl_cv_func_setpayloadsigf_in_libm != yes; then
+ HAVE_SETPAYLOADSIGF=0
+ fi
+ if test $HAVE_SETPAYLOADSIGF = 0; then
+ SETPAYLOADSIGF_LIBM=
+ fi
+ AC_SUBST([SETPAYLOADSIGF_LIBM])
+])
+
+AC_DEFUN_ONCE([gl_FUNC_SETPAYLOADSIG],
+[
+ AC_REQUIRE([gl_MATH_H_DEFAULTS])
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+ gl_MATHFUNC([setpayloadsig], [int], [(double *, double)])
+ if test $gl_cv_func_setpayloadsig_no_libm != yes \
+ && test $gl_cv_func_setpayloadsig_in_libm != yes; then
+ HAVE_SETPAYLOADSIG=0
+ fi
+ if test $HAVE_SETPAYLOADSIG = 0; then
+ SETPAYLOADSIG_LIBM=
+ fi
+ AC_SUBST([SETPAYLOADSIG_LIBM])
+])
+
+AC_DEFUN([gl_FUNC_SETPAYLOADSIGL],
+[
+ AC_REQUIRE([gl_MATH_H_DEFAULTS])
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE])
+
+ gl_MATHFUNC([setpayloadsigl], [int], [(long double *, long double)])
+ if test $gl_cv_func_setpayloadsigl_no_libm != yes \
+ && test $gl_cv_func_setpayloadsigl_in_libm != yes; then
+ HAVE_SETPAYLOADSIGL=0
+ fi
+ if test $HAVE_SETPAYLOADSIGL = 0; then
+ dnl Find libraries needed to link lib/setpayloadsigl.c.
+ if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then
+ AC_REQUIRE([gl_FUNC_SETPAYLOADSIG])
+ SETPAYLOADSIGL_LIBM="$SETPAYLOADSIG_LIBM"
+ else
+ SETPAYLOADSIGL_LIBM=
+ fi
+ dnl Prerequisite of lib/setpayloadsigl.c.
+ gl_LONG_DOUBLE_EXPONENT_LOCATION
+ fi
+ AC_SUBST([SETPAYLOADSIGL_LIBM])
+])
diff --git a/modules/math b/modules/math
index 80de39a7f7..722aad91b9 100644
--- a/modules/math
+++ b/modules/math
@@ -123,6 +123,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
-e 's/@''GNULIB_SETPAYLOAD''@/$(GNULIB_SETPAYLOAD)/g' \
-e 's/@''GNULIB_SETPAYLOADF''@/$(GNULIB_SETPAYLOADF)/g' \
-e 's/@''GNULIB_SETPAYLOADL''@/$(GNULIB_SETPAYLOADL)/g' \
+ -e 's/@''GNULIB_SETPAYLOADSIG''@/$(GNULIB_SETPAYLOADSIG)/g' \
-e 's/@''GNULIB_SIGNBIT''@/$(GNULIB_SIGNBIT)/g' \
-e 's/@''GNULIB_SINF''@/$(GNULIB_SINF)/g' \
-e 's/@''GNULIB_SINL''@/$(GNULIB_SINL)/g' \
@@ -201,6 +202,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
-e 's|@''HAVE_SETPAYLOAD''@|$(HAVE_SETPAYLOAD)|g' \
-e 's|@''HAVE_SETPAYLOADF''@|$(HAVE_SETPAYLOADF)|g' \
-e 's|@''HAVE_SETPAYLOADL''@|$(HAVE_SETPAYLOADL)|g' \
+ -e 's|@''HAVE_SETPAYLOADSIG''@|$(HAVE_SETPAYLOADSIG)|g' \
-e 's|@''HAVE_SINF''@|$(HAVE_SINF)|g' \
-e 's|@''HAVE_SINL''@|$(HAVE_SINL)|g' \
-e 's|@''HAVE_SINHF''@|$(HAVE_SINHF)|g' \
diff --git a/modules/setpayloadsig b/modules/setpayloadsig
new file mode 100644
index 0000000000..27bb3a614e
--- /dev/null
+++ b/modules/setpayloadsig
@@ -0,0 +1,36 @@
+Description:
+setpayloadsig function: construct a signalling NaN with a given payload
+
+Files:
+lib/setpayloadsig.c
+m4/mathfunc.m4
+m4/setpayloadsig.m4
+
+Depends-on:
+math
+extensions
+float [test $HAVE_SETPAYLOADSIG = 0]
+stdint [test $HAVE_SETPAYLOADSIG = 0]
+signed-snan [test $HAVE_SETPAYLOADSIG = 0]
+
+configure.ac:
+gl_FUNC_SETPAYLOADSIG
+gl_CONDITIONAL([GL_COND_OBJ_SETPAYLOADSIG], [test $HAVE_SETPAYLOADSIG = 0])
+gl_MATH_MODULE_INDICATOR([setpayloadsig])
+
+Makefile.am:
+if GL_COND_OBJ_SETPAYLOADSIG
+lib_SOURCES += setpayloadsig.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(SETPAYLOADSIG_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
--
2.34.1
[-- Attachment #3: 0002-setpayloadsig-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4476 bytes --]
From 7daa10a173989f84cad5fe027d5ca61f31ff0ab2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Tue, 16 Apr 2024 21:06:20 +0200
Subject: [PATCH 2/6] setpayloadsig: Add tests.
* tests/test-setpayload.c (PAYLOAD_BITS): New macro.
(main): Use it.
* tests/test-setpayloadsig.c: New file, based on
tests/test-setpayload.c.
* modules/setpayloadsig-tests: New file.
---
ChangeLog | 7 +++
modules/setpayloadsig-tests | 15 +++++++
tests/test-setpayload.c | 4 +-
tests/test-setpayloadsig.c | 88 +++++++++++++++++++++++++++++++++++++
4 files changed, 113 insertions(+), 1 deletion(-)
create mode 100644 modules/setpayloadsig-tests
create mode 100644 tests/test-setpayloadsig.c
diff --git a/ChangeLog b/ChangeLog
index c4a23adb45..ed599bd255 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2024-04-16 Bruno Haible <bruno@clisp.org>
+ setpayloadsig: Add tests.
+ * tests/test-setpayload.c (PAYLOAD_BITS): New macro.
+ (main): Use it.
+ * tests/test-setpayloadsig.c: New file, based on
+ tests/test-setpayload.c.
+ * modules/setpayloadsig-tests: New file.
+
setpayloadsig: New module.
* lib/math.in.h (setpayloadsig): New declaration.
* lib/setpayloadsig.c: New file, based on lib/setpayload.c.
diff --git a/modules/setpayloadsig-tests b/modules/setpayloadsig-tests
new file mode 100644
index 0000000000..3c7845892d
--- /dev/null
+++ b/modules/setpayloadsig-tests
@@ -0,0 +1,15 @@
+Files:
+tests/test-setpayloadsig.c
+tests/infinity.h
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+isnand-nolibm
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-setpayloadsig
+check_PROGRAMS += test-setpayloadsig
+test_setpayloadsig_LDADD = $(LDADD) @SETPAYLOADSIG_LIBM@
diff --git a/tests/test-setpayload.c b/tests/test-setpayload.c
index d539b75ffc..a9976f2842 100644
--- a/tests/test-setpayload.c
+++ b/tests/test-setpayload.c
@@ -26,6 +26,8 @@ SIGNATURE_CHECK (setpayload, int, (double *, double));
#include "isnand-nolibm.h"
#include "macros.h"
+#define PAYLOAD_BITS (53 - 2) /* = (DBL_MANT_DIG - 2) */
+
int
main ()
{
@@ -34,7 +36,7 @@ main ()
{
/* Test valid payloads. */
- for (i = 0, p = 1.0; i < 53 - 2; i++, p *= 2.0)
+ for (i = 0, p = 1.0; i < PAYLOAD_BITS; i++, p *= 2.0)
{
int ret;
double x;
diff --git a/tests/test-setpayloadsig.c b/tests/test-setpayloadsig.c
new file mode 100644
index 0000000000..c8f9925841
--- /dev/null
+++ b/tests/test-setpayloadsig.c
@@ -0,0 +1,88 @@
+/* Test setpayloadsig.
+ Copyright 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <math.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (setpayloadsig, int, (double *, double));
+
+#include "infinity.h"
+#include "isnand-nolibm.h"
+#include "macros.h"
+
+#define PAYLOAD_BITS (53 - 2) /* = (DBL_MANT_DIG - 2) */
+
+int
+main ()
+{
+ int i;
+ double p;
+
+ {
+ /* Test valid payloads. */
+ for (i = 0, p = 1.0; i < PAYLOAD_BITS; i++, p *= 2.0)
+ {
+ int ret;
+ double x;
+
+ ret = setpayloadsig (&x, p);
+ ASSERT (ret == 0);
+ ASSERT (isnand (x));
+ }
+ /* Test out-of-range payload. */
+ int ret;
+ double x;
+
+ ret = setpayloadsig (&x, p);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0);
+ }
+
+ /* Test infinite payload. */
+ {
+ int ret;
+ double x;
+
+ ret = setpayloadsig (&x, Infinityd ());
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0);
+ }
+
+ /* Test negative payload. */
+ {
+ int ret;
+ double x;
+
+ ret = setpayloadsig (&x, -1.0);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0);
+ }
+
+ /* Test fractional payload. */
+ {
+ int ret;
+ double x;
+
+ ret = setpayloadsig (&x, 1.4);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0);
+ }
+
+ return 0;
+}
--
2.34.1
[-- Attachment #4: 0003-setpayloadsigf-New-module.patch --]
[-- Type: text/x-patch, Size: 9853 bytes --]
From 8cf6f8cdd3077e475cbe1e1b3252ac9bc90a4cf5 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Tue, 16 Apr 2024 21:12:39 +0200
Subject: [PATCH 3/6] setpayloadsigf: New module.
* lib/math.in.h (setpayloadsigf): New declaration.
* lib/setpayloadsigf.c: New file, based on lib/setpayloadf.c.
* m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsigf is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIGF.
(gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIGF.
* modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIGF,
HAVE_SETPAYLOADSIGF.
* modules/setpayloadsigf: New file.
* doc/posix-functions/setpayloadsigf.texi: Mention the new module.
---
ChangeLog | 13 +++++
doc/posix-functions/setpayloadsigf.texi | 8 +--
lib/math.in.h | 14 +++++
lib/setpayloadsigf.c | 69 +++++++++++++++++++++++++
m4/math_h.m4 | 6 ++-
modules/math | 2 +
modules/setpayloadsigf | 36 +++++++++++++
7 files changed, 142 insertions(+), 6 deletions(-)
create mode 100644 lib/setpayloadsigf.c
create mode 100644 modules/setpayloadsigf
diff --git a/ChangeLog b/ChangeLog
index ed599bd255..238b032d49 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2024-04-16 Bruno Haible <bruno@clisp.org>
+
+ setpayloadsigf: New module.
+ * lib/math.in.h (setpayloadsigf): New declaration.
+ * lib/setpayloadsigf.c: New file, based on lib/setpayloadf.c.
+ * m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsigf is declared.
+ (gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIGF.
+ (gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIGF.
+ * modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIGF,
+ HAVE_SETPAYLOADSIGF.
+ * modules/setpayloadsigf: New file.
+ * doc/posix-functions/setpayloadsigf.texi: Mention the new module.
+
2024-04-16 Bruno Haible <bruno@clisp.org>
setpayloadsig: Add tests.
diff --git a/doc/posix-functions/setpayloadsigf.texi b/doc/posix-functions/setpayloadsigf.texi
index 6bb4dc9aef..22f09ae268 100644
--- a/doc/posix-functions/setpayloadsigf.texi
+++ b/doc/posix-functions/setpayloadsigf.texi
@@ -10,15 +10,15 @@
@url{https://www.gnu.org/software/libc/manual/html_node/FP-Bit-Twiddling.html}.
@end ifnotinfo
-Gnulib module: ---
+Gnulib module: setpayloadsigf
Portability problems fixed by Gnulib:
@itemize
+@item
+This function is missing on all non-glibc platforms:
+glibc 2.24, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
-@item
-This function is missing on all non-glibc platforms:
-glibc 2.24, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
@end itemize
diff --git a/lib/math.in.h b/lib/math.in.h
index c61e65c423..416530e050 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2817,6 +2817,20 @@ _GL_WARN_ON_USE (setpayloadl, "setpayloadl is unportable - "
#endif
+#if @GNULIB_SETPAYLOADSIGF@
+# if !@HAVE_SETPAYLOADSIGF@
+_GL_FUNCDECL_SYS (setpayloadsigf, int, (float *, float));
+# endif
+_GL_CXXALIAS_SYS (setpayloadsigf, int, (float *, float));
+_GL_CXXALIASWARN (setpayloadsigf);
+#elif defined GNULIB_POSIXCHECK
+# undef setpayloadsigf
+# if HAVE_RAW_DECL_SETPAYLOADSIGF
+_GL_WARN_ON_USE (setpayloadsigf, "setpayloadsigf is unportable - "
+ "use gnulib module setpayloadsigf for portability");
+# endif
+#endif
+
#if @GNULIB_SETPAYLOADSIG@
# if !@HAVE_SETPAYLOADSIG@
_GL_FUNCDECL_SYS (setpayloadsig, int, (double *, double));
diff --git a/lib/setpayloadsigf.c b/lib/setpayloadsigf.c
new file mode 100644
index 0000000000..0f41f9f3df
--- /dev/null
+++ b/lib/setpayloadsigf.c
@@ -0,0 +1,69 @@
+/* Construct a signalling NaN 'float' with a given payload.
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This file 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 3 of the
+ License, or (at your option) any later version.
+
+ This file 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible. */
+
+#include <config.h>
+
+/* Specification. */
+#include <math.h>
+
+#include <float.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "signed-snan.h"
+
+int
+setpayloadsigf (float *result, float payload)
+{
+#if FLT_MANT_DIG == 24
+ if (
+# if defined __hppa || defined __mips__ || defined __sh__
+ payload >= 0.0f
+# else
+ /* A zero payload is not allowed, because that would denote Infinity.
+ Cf. snan.h. */
+ payload > 0.0f
+# endif
+ && payload < 4194304.0f /* (float) (1U << (FLT_MANT_DIG - 2)) */
+ && payload == (float) (int32_t) payload)
+ {
+ memory_float x = memory_positive_SNaNf ();
+ x.word[0] = (x.word[0] & ~((1U << (FLT_MANT_DIG - 2)) - 1))
+ | (int32_t) payload;
+# if 0
+ *result = x.value;
+# else
+ /* On 32-bit x86 processors, as well as on x86_64 processors with
+ CC="gcc -mfpmath=387", the evaluation of *x and *y above is done
+ through an 'flds' instruction, which converts a signalling NaN to
+ a quiet NaN. See
+ <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
+ for details. Use memcpy to avoid this. */
+ memcpy (result, &x.value, sizeof (float));
+# endif
+ return 0;
+ }
+ else
+ {
+ *result = 0.0f;
+ return -1;
+ }
+#else
+# error "Please port gnulib setpayloadsigf.c to your platform!"
+#endif
+}
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 0c5ce4f89c..f458464a2e 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,5 +1,5 @@
# math_h.m4
-# serial 130
+# serial 131
dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -52,7 +52,7 @@ AC_DEFUN_ONCE([gl_MATH_H]
remainder remainderf remainderl
rint rintf rintl round roundf roundl
setpayload setpayloadf setpayloadl
- setpayloadsig
+ setpayloadsig setpayloadsigf
sinf sinl sinhf sqrtf sqrtl
tanf tanl tanhf totalorder totalorderf totalorderl trunc truncf truncl])
])
@@ -164,6 +164,7 @@ AC_DEFUN([gl_MATH_H_REQUIRE_DEFAULTS]
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADF])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADL])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADSIG])
+ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADSIGF])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SIGNBIT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SINF])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SINL])
@@ -250,6 +251,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
HAVE_SETPAYLOADF=1; AC_SUBST([HAVE_SETPAYLOADF])
HAVE_SETPAYLOADL=1; AC_SUBST([HAVE_SETPAYLOADL])
HAVE_SETPAYLOADSIG=1; AC_SUBST([HAVE_SETPAYLOADSIG])
+ HAVE_SETPAYLOADSIGF=1; AC_SUBST([HAVE_SETPAYLOADSIGF])
HAVE_SINF=1; AC_SUBST([HAVE_SINF])
HAVE_SINL=1; AC_SUBST([HAVE_SINL])
HAVE_SINHF=1; AC_SUBST([HAVE_SINHF])
diff --git a/modules/math b/modules/math
index 722aad91b9..b1a2a94e4c 100644
--- a/modules/math
+++ b/modules/math
@@ -124,6 +124,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
-e 's/@''GNULIB_SETPAYLOADF''@/$(GNULIB_SETPAYLOADF)/g' \
-e 's/@''GNULIB_SETPAYLOADL''@/$(GNULIB_SETPAYLOADL)/g' \
-e 's/@''GNULIB_SETPAYLOADSIG''@/$(GNULIB_SETPAYLOADSIG)/g' \
+ -e 's/@''GNULIB_SETPAYLOADSIGF''@/$(GNULIB_SETPAYLOADSIGF)/g' \
-e 's/@''GNULIB_SIGNBIT''@/$(GNULIB_SIGNBIT)/g' \
-e 's/@''GNULIB_SINF''@/$(GNULIB_SINF)/g' \
-e 's/@''GNULIB_SINL''@/$(GNULIB_SINL)/g' \
@@ -203,6 +204,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
-e 's|@''HAVE_SETPAYLOADF''@|$(HAVE_SETPAYLOADF)|g' \
-e 's|@''HAVE_SETPAYLOADL''@|$(HAVE_SETPAYLOADL)|g' \
-e 's|@''HAVE_SETPAYLOADSIG''@|$(HAVE_SETPAYLOADSIG)|g' \
+ -e 's|@''HAVE_SETPAYLOADSIGF''@|$(HAVE_SETPAYLOADSIGF)|g' \
-e 's|@''HAVE_SINF''@|$(HAVE_SINF)|g' \
-e 's|@''HAVE_SINL''@|$(HAVE_SINL)|g' \
-e 's|@''HAVE_SINHF''@|$(HAVE_SINHF)|g' \
diff --git a/modules/setpayloadsigf b/modules/setpayloadsigf
new file mode 100644
index 0000000000..1807e9ada3
--- /dev/null
+++ b/modules/setpayloadsigf
@@ -0,0 +1,36 @@
+Description:
+setpayloadsigf function: construct a signalling NaN with a given payload
+
+Files:
+lib/setpayloadsigf.c
+m4/mathfunc.m4
+m4/setpayloadsig.m4
+
+Depends-on:
+math
+extensions
+float [test $HAVE_SETPAYLOADSIGF = 0]
+stdint [test $HAVE_SETPAYLOADSIGF = 0]
+signed-snan [test $HAVE_SETPAYLOADSIGF = 0]
+
+configure.ac:
+gl_FUNC_SETPAYLOADSIGF
+gl_CONDITIONAL([GL_COND_OBJ_SETPAYLOADSIGF], [test $HAVE_SETPAYLOADSIGF = 0])
+gl_MATH_MODULE_INDICATOR([setpayloadsigf])
+
+Makefile.am:
+if GL_COND_OBJ_SETPAYLOADSIGF
+lib_SOURCES += setpayloadsigf.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(SETPAYLOADSIGF_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
--
2.34.1
[-- Attachment #5: 0004-setpayloadsigf-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4518 bytes --]
From 86ddf2e74f8c097382dff72b99e6a71e5425f51e Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Tue, 16 Apr 2024 21:15:16 +0200
Subject: [PATCH 4/6] setpayloadsigf: Add tests.
* tests/test-setpayloadf.c (PAYLOAD_BITS): New macro.
(main): Use it.
* tests/test-setpayloadsigf.c: New file, based on
tests/test-setpayloadf.c.
* modules/setpayloadsigf-tests: New file.
---
ChangeLog | 7 +++
modules/setpayloadsigf-tests | 15 ++++++
tests/test-setpayloadf.c | 4 +-
tests/test-setpayloadsigf.c | 88 ++++++++++++++++++++++++++++++++++++
4 files changed, 113 insertions(+), 1 deletion(-)
create mode 100644 modules/setpayloadsigf-tests
create mode 100644 tests/test-setpayloadsigf.c
diff --git a/ChangeLog b/ChangeLog
index 238b032d49..ff58ee26b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2024-04-16 Bruno Haible <bruno@clisp.org>
+ setpayloadsigf: Add tests.
+ * tests/test-setpayloadf.c (PAYLOAD_BITS): New macro.
+ (main): Use it.
+ * tests/test-setpayloadsigf.c: New file, based on
+ tests/test-setpayloadf.c.
+ * modules/setpayloadsigf-tests: New file.
+
setpayloadsigf: New module.
* lib/math.in.h (setpayloadsigf): New declaration.
* lib/setpayloadsigf.c: New file, based on lib/setpayloadf.c.
diff --git a/modules/setpayloadsigf-tests b/modules/setpayloadsigf-tests
new file mode 100644
index 0000000000..7f9baefea1
--- /dev/null
+++ b/modules/setpayloadsigf-tests
@@ -0,0 +1,15 @@
+Files:
+tests/test-setpayloadsigf.c
+tests/infinity.h
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+isnanf-nolibm
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-setpayloadsigf
+check_PROGRAMS += test-setpayloadsigf
+test_setpayloadsigf_LDADD = $(LDADD) @SETPAYLOADSIGF_LIBM@
diff --git a/tests/test-setpayloadf.c b/tests/test-setpayloadf.c
index aa790343ae..af8af962ef 100644
--- a/tests/test-setpayloadf.c
+++ b/tests/test-setpayloadf.c
@@ -26,6 +26,8 @@ SIGNATURE_CHECK (setpayloadf, int, (float *, float));
#include "isnanf-nolibm.h"
#include "macros.h"
+#define PAYLOAD_BITS (24 - 2) /* = (FLT_MANT_DIG - 2) */
+
int
main ()
{
@@ -34,7 +36,7 @@ main ()
{
/* Test valid payloads. */
- for (i = 0, p = 1.0f; i < 24 - 2; i++, p *= 2.0f)
+ for (i = 0, p = 1.0f; i < PAYLOAD_BITS; i++, p *= 2.0f)
{
int ret;
float x;
diff --git a/tests/test-setpayloadsigf.c b/tests/test-setpayloadsigf.c
new file mode 100644
index 0000000000..d95d497e5f
--- /dev/null
+++ b/tests/test-setpayloadsigf.c
@@ -0,0 +1,88 @@
+/* Test setpayloadsigf.
+ Copyright 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <math.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (setpayloadsigf, int, (float *, float));
+
+#include "infinity.h"
+#include "isnanf-nolibm.h"
+#include "macros.h"
+
+#define PAYLOAD_BITS (24 - 2) /* = (FLT_MANT_DIG - 2) */
+
+int
+main ()
+{
+ int i;
+ float p;
+
+ {
+ /* Test valid payloads. */
+ for (i = 0, p = 1.0f; i < PAYLOAD_BITS; i++, p *= 2.0f)
+ {
+ int ret;
+ float x;
+
+ ret = setpayloadsigf (&x, p);
+ ASSERT (ret == 0);
+ ASSERT (isnanf (x));
+ }
+ /* Test out-of-range payload. */
+ int ret;
+ float x;
+
+ ret = setpayloadsigf (&x, p);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0f);
+ }
+
+ /* Test infinite payload. */
+ {
+ int ret;
+ float x;
+
+ ret = setpayloadsigf (&x, Infinityf ());
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0f);
+ }
+
+ /* Test negative payload. */
+ {
+ int ret;
+ float x;
+
+ ret = setpayloadsigf (&x, -1.0f);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0f);
+ }
+
+ /* Test fractional payload. */
+ {
+ int ret;
+ float x;
+
+ ret = setpayloadsigf (&x, 1.4f);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0f);
+ }
+
+ return 0;
+}
--
2.34.1
[-- Attachment #6: 0005-setpayloadsigl-New-module.patch --]
[-- Type: text/x-patch, Size: 12713 bytes --]
From 7a4a7fd18d3bfdc997ec8ac4d17b4064e04bde61 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Tue, 16 Apr 2024 21:28:42 +0200
Subject: [PATCH 5/6] setpayloadsigl: New module.
* lib/math.in.h (setpayloadsigl): New declaration.
* lib/setpayloadsigl.c: New file, based on lib/setpayloadl.c.
* m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsigl is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIGL.
(gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIGL.
* modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIGL,
HAVE_SETPAYLOADSIGL.
* modules/setpayloadsigl: New file.
* doc/posix-functions/setpayloadsigl.texi: Mention the new module.
---
ChangeLog | 13 +++
doc/posix-functions/setpayloadsigl.texi | 8 +-
lib/math.in.h | 14 +++
lib/setpayloadsigl.c | 129 ++++++++++++++++++++++++
m4/math_h.m4 | 6 +-
modules/math | 2 +
modules/setpayloadsigl | 38 +++++++
7 files changed, 204 insertions(+), 6 deletions(-)
create mode 100644 lib/setpayloadsigl.c
create mode 100644 modules/setpayloadsigl
diff --git a/ChangeLog b/ChangeLog
index ff58ee26b3..e862623d6c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2024-04-16 Bruno Haible <bruno@clisp.org>
+
+ setpayloadsigl: New module.
+ * lib/math.in.h (setpayloadsigl): New declaration.
+ * lib/setpayloadsigl.c: New file, based on lib/setpayloadl.c.
+ * m4/math_h.m4 (gl_MATH_H): Test whether setpayloadsigl is declared.
+ (gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_SETPAYLOADSIGL.
+ (gl_MATH_H_DEFAULTS): Initialize HAVE_SETPAYLOADSIGL.
+ * modules/math (Makefile.am): Substitute GNULIB_SETPAYLOADSIGL,
+ HAVE_SETPAYLOADSIGL.
+ * modules/setpayloadsigl: New file.
+ * doc/posix-functions/setpayloadsigl.texi: Mention the new module.
+
2024-04-16 Bruno Haible <bruno@clisp.org>
setpayloadsigf: Add tests.
diff --git a/doc/posix-functions/setpayloadsigl.texi b/doc/posix-functions/setpayloadsigl.texi
index f170f7090f..9d8dee189b 100644
--- a/doc/posix-functions/setpayloadsigl.texi
+++ b/doc/posix-functions/setpayloadsigl.texi
@@ -10,15 +10,15 @@
@url{https://www.gnu.org/software/libc/manual/html_node/FP-Bit-Twiddling.html}.
@end ifnotinfo
-Gnulib module: ---
+Gnulib module: setpayloadsigl
Portability problems fixed by Gnulib:
@itemize
+@item
+This function is missing on all non-glibc platforms:
+glibc 2.24, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
-@item
-This function is missing on all non-glibc platforms:
-glibc 2.24, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
@end itemize
diff --git a/lib/math.in.h b/lib/math.in.h
index 416530e050..7bb7976b61 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2845,6 +2845,20 @@ _GL_WARN_ON_USE (setpayloadsig, "setpayloadsig is unportable - "
# endif
#endif
+#if @GNULIB_SETPAYLOADSIGL@
+# if !@HAVE_SETPAYLOADSIGL@
+_GL_FUNCDECL_SYS (setpayloadsigl, int, (long double *, long double));
+# endif
+_GL_CXXALIAS_SYS (setpayloadsigl, int, (long double *, long double));
+_GL_CXXALIASWARN (setpayloadsigl);
+#elif defined GNULIB_POSIXCHECK
+# undef setpayloadsigl
+# if HAVE_RAW_DECL_SETPAYLOADSIGL
+_GL_WARN_ON_USE (setpayloadsigl, "setpayloadsigl is unportable - "
+ "use gnulib module setpayloadsigl for portability");
+# endif
+#endif
+
#if @GNULIB_TOTALORDERF@
# if @REPLACE_TOTALORDERF@
diff --git a/lib/setpayloadsigl.c b/lib/setpayloadsigl.c
new file mode 100644
index 0000000000..5cfe3cb783
--- /dev/null
+++ b/lib/setpayloadsigl.c
@@ -0,0 +1,129 @@
+/* Construct a signalling NaN 'long double' with a given payload.
+ Copyright 2024 Free Software Foundation, Inc.
+
+ This file 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 3 of the
+ License, or (at your option) any later version.
+
+ This file 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 this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible. */
+
+#include <config.h>
+
+/* Specification. */
+#include <math.h>
+
+#if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE
+
+int
+setpayloadsigl (long double *result, long double payload)
+{
+ return setpayloadsig ((double *) result, payload);
+}
+
+#else
+
+# include <float.h>
+# include <stdint.h>
+
+# include "signed-snan.h"
+
+/* 2^(LDBL_MANT_DIG-1). */
+# define TWO_LDBL_MANT_DIG \
+ ((long double) (1U << ((LDBL_MANT_DIG - 1) / 4)) \
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 1) / 4)) \
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 2) / 4)) \
+ * (long double) (1U << ((LDBL_MANT_DIG - 1 + 3) / 4)))
+
+int
+setpayloadsigl (long double *result, long double payload)
+{
+# if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 106 || LDBL_MANT_DIG == 113) \
+ && defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
+ if (
+# if defined __hppa || defined __mips__ || defined __sh__
+ payload >= 0.0L
+# else
+ /* A zero payload is not allowed, because that would denote Infinity.
+ Cf. snan.h. */
+ payload > 0.0L
+# endif
+# if LDBL_MANT_DIG == 64 /* on i386, x86_64, ia64, m68k */
+ && payload < 4611686018427387904.0L /* exp2l (LDBL_MANT_DIG - 2) */
+ && payload == (long double) (int64_t) payload
+# endif
+# if LDBL_MANT_DIG == 106 /* on powerpc, powerpc64, powerpc64le */
+ && payload < 2251799813685248.0L /* exp2l (DBL_MANT_DIG - 2) */
+ && payload == (long double) (int64_t) payload
+# endif
+# if LDBL_MANT_DIG == 113 /* on alpha, arm64, loongarch64, mips64, riscv64, s390x, sparc64 */
+ && payload < 2596148429267413814265248164610048.0L /* exp2l (LDBL_MANT_DIG - 2) */
+ && payload == +(+(payload + TWO_LDBL_MANT_DIG) - TWO_LDBL_MANT_DIG)
+# endif
+ )
+ {
+ memory_long_double x = memory_positive_SNaNl ();
+
+# if LDBL_MANT_DIG == 64 /* on i386, x86_64, ia64, m68k */
+ uint64_t pl = (int64_t) payload;
+# if LDBL_EXPBIT0_WORD == 2 && LDBL_EXPBIT0_BIT == 0 /* on i386, x86_64, ia64 */
+ x.word[1] = (x.word[1] & 0xC0000000U) | (uint32_t) (pl >> 32);
+ x.word[0] = (uint32_t) pl;
+# elif LDBL_EXPBIT0_WORD == 0 && LDBL_EXPBIT0_BIT == 16 /* on m68k */
+ x.word[1] = (x.word[1] & 0xC0000000U) | (uint32_t) (pl >> 32);
+ x.word[2] = (uint32_t) pl;
+# else
+# error "Please port gnulib setpayloadsigl.c to your platform!"
+# endif
+# endif
+# if LDBL_MANT_DIG == 106 /* on powerpc, powerpc64, powerpc64le */
+ uint64_t pl = (int64_t) payload;
+# if LDBL_EXPBIT0_BIT == 20
+ uint32_t pl_hi = (uint32_t) (pl >> 32);
+ uint32_t pl_lo = (uint32_t) pl;
+ x.word[LDBL_EXPBIT0_WORD] = (x.word[LDBL_EXPBIT0_WORD] & 0xFFF80000U)
+ | pl_hi;
+ x.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 1 : -1)] = pl_lo;
+# else
+# error "Please port gnulib setpayloadsigl.c to your platform!"
+# endif
+# endif
+# if LDBL_MANT_DIG == 113 /* on alpha, arm64, loongarch64, mips64, riscv64, s390x, sparc64 */
+# if LDBL_EXPBIT0_BIT == 16
+ memory_long_double pl;
+ pl.value = payload + TWO_LDBL_MANT_DIG;
+ x.word[LDBL_EXPBIT0_WORD] = (x.word[LDBL_EXPBIT0_WORD] & 0xFFFF8000U)
+ | (pl.word[LDBL_EXPBIT0_WORD] & 0x00007FFFU);
+ x.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 1 : -1)] =
+ pl.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 1 : -1)];
+ x.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 2 : -2)] =
+ pl.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 2 : -2)];
+ x.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 3 : -3)] =
+ pl.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 3 : -3)];
+# else
+# error "Please port gnulib setpayloadsigl.c to your platform!"
+# endif
+# endif
+
+ *result = x.value;
+ return 0;
+ }
+ else
+ {
+ *result = 0.0L;
+ return -1;
+ }
+# else
+# error "Please port gnulib setpayloadsigl.c to your platform!"
+# endif
+}
+
+#endif
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index f458464a2e..7bcacf6959 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,5 +1,5 @@
# math_h.m4
-# serial 131
+# serial 132
dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -52,7 +52,7 @@ AC_DEFUN_ONCE([gl_MATH_H]
remainder remainderf remainderl
rint rintf rintl round roundf roundl
setpayload setpayloadf setpayloadl
- setpayloadsig setpayloadsigf
+ setpayloadsig setpayloadsigf setpayloadsigl
sinf sinl sinhf sqrtf sqrtl
tanf tanl tanhf totalorder totalorderf totalorderl trunc truncf truncl])
])
@@ -165,6 +165,7 @@ AC_DEFUN([gl_MATH_H_REQUIRE_DEFAULTS]
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADL])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADSIG])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADSIGF])
+ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SETPAYLOADSIGL])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SIGNBIT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SINF])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_SINL])
@@ -252,6 +253,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
HAVE_SETPAYLOADL=1; AC_SUBST([HAVE_SETPAYLOADL])
HAVE_SETPAYLOADSIG=1; AC_SUBST([HAVE_SETPAYLOADSIG])
HAVE_SETPAYLOADSIGF=1; AC_SUBST([HAVE_SETPAYLOADSIGF])
+ HAVE_SETPAYLOADSIGL=1; AC_SUBST([HAVE_SETPAYLOADSIGL])
HAVE_SINF=1; AC_SUBST([HAVE_SINF])
HAVE_SINL=1; AC_SUBST([HAVE_SINL])
HAVE_SINHF=1; AC_SUBST([HAVE_SINHF])
diff --git a/modules/math b/modules/math
index b1a2a94e4c..70baab7586 100644
--- a/modules/math
+++ b/modules/math
@@ -125,6 +125,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
-e 's/@''GNULIB_SETPAYLOADL''@/$(GNULIB_SETPAYLOADL)/g' \
-e 's/@''GNULIB_SETPAYLOADSIG''@/$(GNULIB_SETPAYLOADSIG)/g' \
-e 's/@''GNULIB_SETPAYLOADSIGF''@/$(GNULIB_SETPAYLOADSIGF)/g' \
+ -e 's/@''GNULIB_SETPAYLOADSIGL''@/$(GNULIB_SETPAYLOADSIGL)/g' \
-e 's/@''GNULIB_SIGNBIT''@/$(GNULIB_SIGNBIT)/g' \
-e 's/@''GNULIB_SINF''@/$(GNULIB_SINF)/g' \
-e 's/@''GNULIB_SINL''@/$(GNULIB_SINL)/g' \
@@ -205,6 +206,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
-e 's|@''HAVE_SETPAYLOADL''@|$(HAVE_SETPAYLOADL)|g' \
-e 's|@''HAVE_SETPAYLOADSIG''@|$(HAVE_SETPAYLOADSIG)|g' \
-e 's|@''HAVE_SETPAYLOADSIGF''@|$(HAVE_SETPAYLOADSIGF)|g' \
+ -e 's|@''HAVE_SETPAYLOADSIGL''@|$(HAVE_SETPAYLOADSIGL)|g' \
-e 's|@''HAVE_SINF''@|$(HAVE_SINF)|g' \
-e 's|@''HAVE_SINL''@|$(HAVE_SINL)|g' \
-e 's|@''HAVE_SINHF''@|$(HAVE_SINHF)|g' \
diff --git a/modules/setpayloadsigl b/modules/setpayloadsigl
new file mode 100644
index 0000000000..deadba06af
--- /dev/null
+++ b/modules/setpayloadsigl
@@ -0,0 +1,38 @@
+Description:
+setpayloadsigl function: construct a signalling NaN with a given payload
+
+Files:
+lib/setpayloadsigl.c
+m4/mathfunc.m4
+m4/setpayloadsig.m4
+m4/exponentl.m4
+
+Depends-on:
+math
+extensions
+setpayloadsig [test $HAVE_SETPAYLOADSIGL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
+float [test $HAVE_SETPAYLOADSIGL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+stdint [test $HAVE_SETPAYLOADSIGL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+signed-snan [test $HAVE_SETPAYLOADSIGL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+
+configure.ac:
+gl_FUNC_SETPAYLOADSIGL
+gl_CONDITIONAL([GL_COND_OBJ_SETPAYLOADSIGL], [test $HAVE_SETPAYLOADSIGL = 0])
+gl_MATH_MODULE_INDICATOR([setpayloadsigl])
+
+Makefile.am:
+if GL_COND_OBJ_SETPAYLOADSIGL
+lib_SOURCES += setpayloadsigl.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(SETPAYLOADSIGL_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
--
2.34.1
[-- Attachment #7: 0006-setpayloadsigl-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4116 bytes --]
From e135884192c6ab4eb3cc1de853a571291aa9ae22 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Tue, 16 Apr 2024 21:29:16 +0200
Subject: [PATCH 6/6] setpayloadsigl: Add tests.
* tests/test-setpayloadsigl.c: New file, based on
tests/test-setpayloadl.c.
* modules/setpayloadsigl-tests: New file.
---
ChangeLog | 5 ++
modules/setpayloadsigl-tests | 15 ++++++
tests/test-setpayloadsigl.c | 97 ++++++++++++++++++++++++++++++++++++
3 files changed, 117 insertions(+)
create mode 100644 modules/setpayloadsigl-tests
create mode 100644 tests/test-setpayloadsigl.c
diff --git a/ChangeLog b/ChangeLog
index e862623d6c..6d4d37cca8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2024-04-16 Bruno Haible <bruno@clisp.org>
+ setpayloadsigl: Add tests.
+ * tests/test-setpayloadsigl.c: New file, based on
+ tests/test-setpayloadl.c.
+ * modules/setpayloadsigl-tests: New file.
+
setpayloadsigl: New module.
* lib/math.in.h (setpayloadsigl): New declaration.
* lib/setpayloadsigl.c: New file, based on lib/setpayloadl.c.
diff --git a/modules/setpayloadsigl-tests b/modules/setpayloadsigl-tests
new file mode 100644
index 0000000000..84073f96ad
--- /dev/null
+++ b/modules/setpayloadsigl-tests
@@ -0,0 +1,15 @@
+Files:
+tests/test-setpayloadsigl.c
+tests/infinity.h
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+isnanl-nolibm
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-setpayloadsigl
+check_PROGRAMS += test-setpayloadsigl
+test_setpayloadsigl_LDADD = $(LDADD) @SETPAYLOADSIGL_LIBM@
diff --git a/tests/test-setpayloadsigl.c b/tests/test-setpayloadsigl.c
new file mode 100644
index 0000000000..13f1eba393
--- /dev/null
+++ b/tests/test-setpayloadsigl.c
@@ -0,0 +1,97 @@
+/* Test setpayloadsigl.
+ Copyright 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <math.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (setpayloadsigl, int, (long double *, long double));
+
+#include <float.h>
+
+#include "infinity.h"
+#include "isnanl-nolibm.h"
+#include "macros.h"
+
+#if defined __powerpc__ && LDBL_MANT_DIG == 106
+ /* This is PowerPC "double double", a pair of two doubles. NaN is represented
+ as the corresponding 64-bit IEEE value in the first double; the second is
+ irrelevant and therefore does not contain a payload. */
+# define PAYLOAD_BITS (DBL_MANT_DIG - 2)
+#else
+# define PAYLOAD_BITS (LDBL_MANT_DIG - 2)
+#endif
+
+int
+main ()
+{
+ int i;
+ long double p;
+
+ {
+ /* Test valid payloads. */
+ for (i = 0, p = 1.0L; i < PAYLOAD_BITS; i++, p *= 2.0L)
+ {
+ int ret;
+ long double x;
+
+ ret = setpayloadsigl (&x, p);
+ ASSERT (ret == 0);
+ ASSERT (isnanl (x));
+ }
+ /* Test out-of-range payload. */
+ int ret;
+ long double x;
+
+ ret = setpayloadsigl (&x, p);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0L);
+ }
+
+ /* Test infinite payload. */
+ {
+ int ret;
+ long double x;
+
+ ret = setpayloadsigl (&x, Infinityl ());
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0L);
+ }
+
+ /* Test negative payload. */
+ {
+ int ret;
+ long double x;
+
+ ret = setpayloadsigl (&x, -1.0L);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0L);
+ }
+
+ /* Test fractional payload. */
+ {
+ int ret;
+ long double x;
+
+ ret = setpayloadsigl (&x, 1.4L);
+ ASSERT (ret != 0);
+ ASSERT (x == 0.0L);
+ }
+
+ return 0;
+}
--
2.34.1
reply other threads:[~2024-04-16 22:50 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6040641.QK70jAV3al@nimes \
--to=bruno@clisp.org \
--cc=bug-gnulib@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).