bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
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).