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 getpayload, getpayloadf, getpayloadl
Date: Wed, 17 Apr 2024 15:56:32 +0200	[thread overview]
Message-ID: <13436243.RAW8MR3E7N@nimes> (raw)

[-- Attachment #1: Type: text/plain, Size: 2225 bytes --]

ISO C 23 specifies in the (optional, but normative) Annex F also functions
for extracting the payload of a quiet or signalling NaN. This patch series
implements them.


2024-04-17  Bruno Haible  <bruno@clisp.org>

	getpayloadl: Add tests.
	* tests/test-getpayloadl.c: New file.
	* modules/getpayloadl-tests: New file.

	getpayloadl: New module.
	* lib/math.in.h (getpayloadl): New declaration.
	* lib/getpayloadl.c: New file.
	* m4/math_h.m4 (gl_MATH_H): Test whether getpayloadl is declared.
	(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOADL.
	(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOADL, REPLACE_GETPAYLOADL.
	* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOADL,
	HAVE_GETPAYLOADL, REPLACE_GETPAYLOADL.
	* modules/getpayloadl: New file.
	* doc/posix-functions/getpayloadl.texi: Mention the new module and the
	glibc bug.

2024-04-17  Bruno Haible  <bruno@clisp.org>

	getpayloadf: Add tests.
	* tests/test-getpayloadf.c: New file.
	* modules/getpayloadf-tests: New file.

	getpayloadf: New module.
	* lib/math.in.h (getpayloadf): New declaration.
	* lib/getpayloadf.c: New file.
	* m4/math_h.m4 (gl_MATH_H): Test whether getpayloadf is declared.
	(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOADF.
	(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOADF, REPLACE_GETPAYLOADF.
	* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOADF,
	HAVE_GETPAYLOADF, REPLACE_GETPAYLOADF.
	* modules/getpayloadf: New file.
	* doc/posix-functions/getpayloadf.texi: Mention the new module and the
	glibc bug.

2024-04-17  Bruno Haible  <bruno@clisp.org>

	getpayload: Add tests.
	* tests/test-getpayload.c: New file.
	* modules/getpayload-tests: New file.

	getpayload: New module.
	* lib/math.in.h (getpayload): New declaration.
	* lib/getpayload.c: New file.
	* m4/getpayload.m4: New file.
	* m4/math_h.m4 (gl_MATH_H): Test whether getpayload is declared.
	(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOAD.
	(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOAD, REPLACE_GETPAYLOAD.
	* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOAD,
	HAVE_GETPAYLOAD, REPLACE_GETPAYLOAD.
	* modules/getpayload: New file.
	* doc/posix-functions/getpayload.texi: Mention the new module and the
	glibc bug.


[-- Attachment #2: 0001-getpayload-New-module.patch --]
[-- Type: text/x-patch, Size: 17003 bytes --]

From 20b8f23dca46e1383eb5e9f922c1ca93a3fac425 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Wed, 17 Apr 2024 10:57:05 +0200
Subject: [PATCH 1/6] getpayload: New module.

* lib/math.in.h (getpayload): New declaration.
* lib/getpayload.c: New file.
* m4/getpayload.m4: New file.
* m4/math_h.m4 (gl_MATH_H): Test whether getpayload is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOAD.
(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOAD, REPLACE_GETPAYLOAD.
* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOAD,
HAVE_GETPAYLOAD, REPLACE_GETPAYLOAD.
* modules/getpayload: New file.
* doc/posix-functions/getpayload.texi: Mention the new module and the
glibc bug.
---
 ChangeLog                           |  15 +++
 doc/posix-functions/getpayload.texi |  12 +-
 lib/getpayload.c                    |  54 ++++++++
 lib/math.in.h                       |  24 ++++
 m4/getpayload.m4                    | 183 ++++++++++++++++++++++++++++
 m4/math_h.m4                        |   9 +-
 modules/getpayload                  |  37 ++++++
 modules/math                        |   3 +
 8 files changed, 331 insertions(+), 6 deletions(-)
 create mode 100644 lib/getpayload.c
 create mode 100644 m4/getpayload.m4
 create mode 100644 modules/getpayload

diff --git a/ChangeLog b/ChangeLog
index ffe35d5d1d..6fbcff9835 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2024-04-17  Bruno Haible  <bruno@clisp.org>
+
+	getpayload: New module.
+	* lib/math.in.h (getpayload): New declaration.
+	* lib/getpayload.c: New file.
+	* m4/getpayload.m4: New file.
+	* m4/math_h.m4 (gl_MATH_H): Test whether getpayload is declared.
+	(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOAD.
+	(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOAD, REPLACE_GETPAYLOAD.
+	* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOAD,
+	HAVE_GETPAYLOAD, REPLACE_GETPAYLOAD.
+	* modules/getpayload: New file.
+	* doc/posix-functions/getpayload.texi: Mention the new module and the
+	glibc bug.
+
 2024-04-16  Sam James  <sam@gentoo.org>
 
 	wchar: Fix serial number.
diff --git a/doc/posix-functions/getpayload.texi b/doc/posix-functions/getpayload.texi
index da6154e61f..d5ea38d70c 100644
--- a/doc/posix-functions/getpayload.texi
+++ b/doc/posix-functions/getpayload.texi
@@ -10,15 +10,19 @@
 @url{https://www.gnu.org/software/libc/manual/html_node/FP-Bit-Twiddling.html}.
 @end ifnotinfo
 
-Gnulib module: ---
+Gnulib module: getpayload
 
 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.
+@item
+This function returns a wrong result for non-NaN arguments on some platforms:
+@c https://sourceware.org/bugzilla/show_bug.cgi?id=26073
+glibc 2.31.
 @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/getpayload.c b/lib/getpayload.c
new file mode 100644
index 0000000000..43979d595f
--- /dev/null
+++ b/lib/getpayload.c
@@ -0,0 +1,54 @@
+/* Extract the payload of a NaN 'double'.
+   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>
+
+double
+getpayload (const double *value)
+{
+  if (isnand (*value))
+    {
+#if DBL_MANT_DIG == 53
+      union { uint64_t i; double f; } x;
+# if 0
+      x.f = *value;
+# else
+      /* On 32-bit x86 processors, as well as on x86_64 processors with
+         CC="gcc -mfpmath=387", the evaluation of *value 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 (&x.f, value, sizeof (double));
+# endif
+      int64_t payload = x.i & (((uint64_t) 1 << (DBL_MANT_DIG - 2)) - 1);
+      return payload;
+#else
+# error "Please port gnulib getpayload.c to your platform!"
+#endif
+    }
+  else
+    return -1.0;
+}
diff --git a/lib/math.in.h b/lib/math.in.h
index 7bb7976b61..2e7dde2e07 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2774,6 +2774,30 @@ _GL_WARN_REAL_FLOATING_DECL (signbit);
 #endif
 
 
+#if @GNULIB_GETPAYLOAD@
+# if @REPLACE_GETPAYLOAD@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getpayload
+#   define getpayload rpl_getpayload
+#  endif
+_GL_FUNCDECL_RPL (getpayload, double, (const double *));
+_GL_CXXALIAS_RPL (getpayload, double, (const double *));
+# else
+#  if !@HAVE_GETPAYLOAD@
+_GL_FUNCDECL_SYS (getpayload, double, (const double *));
+#  endif
+_GL_CXXALIAS_SYS (getpayload, double, (const double *));
+# endif
+_GL_CXXALIASWARN (getpayload);
+#elif defined GNULIB_POSIXCHECK
+# undef getpayload
+# if HAVE_RAW_DECL_GETPAYLOAD
+_GL_WARN_ON_USE (getpayload, "getpayload is unportable - "
+                 "use gnulib module getpayload for portability");
+# endif
+#endif
+
+
 #if @GNULIB_SETPAYLOADF@
 # if !@HAVE_SETPAYLOADF@
 _GL_FUNCDECL_SYS (setpayloadf, int, (float *, float));
diff --git a/m4/getpayload.m4 b/m4/getpayload.m4
new file mode 100644
index 0000000000..c41f0c25d8
--- /dev/null
+++ b/m4/getpayload.m4
@@ -0,0 +1,183 @@
+# getpayload.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_GETPAYLOADF],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+  gl_MATHFUNC([getpayloadf], [float], [(float const *)])
+  if test $gl_cv_func_getpayloadf_no_libm != yes \
+     && test $gl_cv_func_getpayloadf_in_libm != yes; then
+    HAVE_GETPAYLOADF=0
+  else
+    dnl glibc versions < 2.32 return a wrong value,
+    dnl see <https://sourceware.org/bugzilla/show_bug.cgi?id=26073>.
+    AC_CACHE_CHECK([whether getpayloadf works],
+      [gl_cv_func_getpayloadf_works],
+      [AC_RUN_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[#include <math.h>
+            ]],
+            [[float x = 2.718281828459045f;
+              return getpayloadf (&x) != -1.0f;
+            ]])
+         ],
+         [gl_cv_func_getpayloadf_works=yes],
+         [gl_cv_func_getpayloadf_works=no],
+         [case "$host_os" in
+            # Guess no on glibc versions < 2.32.
+            *-gnu* | gnu*)
+              AC_EGREP_CPP([Unlucky],
+                [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 32)
+  Unlucky GNU user
+ #endif
+#endif
+                ],
+                [gl_cv_func_getpayloadf_works="guessing no"],
+                [gl_cv_func_getpayloadf_works="guessing yes"])
+              ;;
+            # Guess yes otherwise.
+            *) gl_cv_func_getpayloadf_works="guessing yes" ;;
+          esac
+         ])
+      ])
+    case "$gl_cv_func_getpayloadf_works" in
+      *yes) ;;
+      *) REPLACE_GETPAYLOADF=1 ;;
+    esac
+  fi
+  if test $HAVE_GETPAYLOADF = 0 || test $REPLACE_GETPAYLOADF = 1; then
+    GETPAYLOADF_LIBM='$(ISNANF_LIBM)'
+  fi
+  AC_SUBST([GETPAYLOADF_LIBM])
+])
+
+AC_DEFUN_ONCE([gl_FUNC_GETPAYLOAD],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+  gl_MATHFUNC([getpayload], [double], [(double const *)])
+  if test $gl_cv_func_getpayload_no_libm != yes \
+     && test $gl_cv_func_getpayload_in_libm != yes; then
+    HAVE_GETPAYLOAD=0
+  else
+    dnl glibc versions < 2.32 return a wrong value,
+    dnl see <https://sourceware.org/bugzilla/show_bug.cgi?id=26073>.
+    AC_CACHE_CHECK([whether getpayload works],
+      [gl_cv_func_getpayload_works],
+      [AC_RUN_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[#include <math.h>
+            ]],
+            [[double x = 2.718281828459045;
+              return getpayload (&x) != -1.0;
+            ]])
+         ],
+         [gl_cv_func_getpayload_works=yes],
+         [gl_cv_func_getpayload_works=no],
+         [case "$host_os" in
+            # Guess no on glibc versions < 2.32.
+            *-gnu* | gnu*)
+              AC_EGREP_CPP([Unlucky],
+                [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 32)
+  Unlucky GNU user
+ #endif
+#endif
+                ],
+                [gl_cv_func_getpayload_works="guessing no"],
+                [gl_cv_func_getpayload_works="guessing yes"])
+              ;;
+            # Guess yes otherwise.
+            *) gl_cv_func_getpayload_works="guessing yes" ;;
+          esac
+         ])
+      ])
+    case "$gl_cv_func_getpayload_works" in
+      *yes) ;;
+      *) REPLACE_GETPAYLOAD=1 ;;
+    esac
+  fi
+  if test $HAVE_GETPAYLOAD = 0 || test $REPLACE_GETPAYLOAD = 1; then
+    GETPAYLOAD_LIBM='$(ISNAND_LIBM)'
+  fi
+  AC_SUBST([GETPAYLOAD_LIBM])
+])
+
+AC_DEFUN([gl_FUNC_GETPAYLOADL],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE])
+
+  gl_MATHFUNC([getpayloadl], [long double], [(long double const *)])
+  if test $gl_cv_func_getpayloadl_no_libm != yes \
+     && test $gl_cv_func_getpayloadl_in_libm != yes; then
+    HAVE_GETPAYLOADL=0
+  else
+    dnl glibc versions < 2.32 return a wrong value,
+    dnl see <https://sourceware.org/bugzilla/show_bug.cgi?id=26073>.
+    AC_CACHE_CHECK([whether getpayloadl works],
+      [gl_cv_func_getpayloadl_works],
+      [AC_RUN_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[#include <math.h>
+            ]],
+            [[long double x = 2.718281828459045L;
+              return getpayloadl (&x) != -1.0L;
+            ]])
+         ],
+         [gl_cv_func_getpayloadl_works=yes],
+         [gl_cv_func_getpayloadl_works=no],
+         [case "$host_os" in
+            # Guess no on glibc versions < 2.32.
+            *-gnu* | gnu*)
+              AC_EGREP_CPP([Unlucky],
+                [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 32)
+  Unlucky GNU user
+ #endif
+#endif
+                ],
+                [gl_cv_func_getpayloadl_works="guessing no"],
+                [gl_cv_func_getpayloadl_works="guessing yes"])
+              ;;
+            # Guess yes otherwise.
+            *) gl_cv_func_getpayloadl_works="guessing yes" ;;
+          esac
+         ])
+      ])
+    case "$gl_cv_func_getpayloadl_works" in
+      *yes) ;;
+      *) REPLACE_GETPAYLOADL=1 ;;
+    esac
+  fi
+  if test $HAVE_GETPAYLOADL = 0 || test $REPLACE_GETPAYLOADL = 1; then
+    dnl Find libraries needed to link lib/getpayloadl.c.
+    if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then
+      AC_REQUIRE([gl_FUNC_GETPAYLOAD])
+      GETPAYLOADL_LIBM="$GETPAYLOAD_LIBM"
+    else
+      GETPAYLOADL_LIBM='$(ISNANL_LIBM)'
+    fi
+    dnl Prerequisite of lib/getpayloadl.c.
+    gl_LONG_DOUBLE_EXPONENT_LOCATION
+  fi
+  AC_SUBST([GETPAYLOADL_LIBM])
+])
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 7bcacf6959..370ea14051 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,5 +1,5 @@
 # math_h.m4
-# serial 132
+# serial 133
 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,
@@ -43,7 +43,9 @@ AC_DEFUN_ONCE([gl_MATH_H]
      cbrt cbrtf cbrtl ceilf ceill copysign copysignf copysignl cosf cosl coshf
      expf expl exp2 exp2f exp2l expm1 expm1f expm1l
      fabsf fabsl floorf floorl fma fmaf fmal
-     fmod fmodf fmodl frexpf frexpl hypotf hypotl
+     fmod fmodf fmodl frexpf frexpl
+     getpayload
+     hypotf hypotl
      ilogb ilogbf ilogbl
      ldexpf ldexpl
      log logf logl log10 log10f log10l log1p log1pf log1pl log2 log2f log2l
@@ -117,6 +119,7 @@ AC_DEFUN([gl_MATH_H_REQUIRE_DEFAULTS]
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FREXPF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FREXP])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FREXPL])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETPAYLOAD])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOT])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOTL])
@@ -223,6 +226,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
   HAVE_FMODF=1;                     AC_SUBST([HAVE_FMODF])
   HAVE_FMODL=1;                     AC_SUBST([HAVE_FMODL])
   HAVE_FREXPF=1;                    AC_SUBST([HAVE_FREXPF])
+  HAVE_GETPAYLOAD=1;                AC_SUBST([HAVE_GETPAYLOAD])
   HAVE_HYPOTF=1;                    AC_SUBST([HAVE_HYPOTF])
   HAVE_HYPOTL=1;                    AC_SUBST([HAVE_HYPOTL])
   HAVE_ILOGB=1;                     AC_SUBST([HAVE_ILOGB])
@@ -332,6 +336,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
   REPLACE_FREXPF=0;                 AC_SUBST([REPLACE_FREXPF])
   REPLACE_FREXP=0;                  AC_SUBST([REPLACE_FREXP])
   REPLACE_FREXPL=0;                 AC_SUBST([REPLACE_FREXPL])
+  REPLACE_GETPAYLOAD=0;             AC_SUBST([REPLACE_GETPAYLOAD])
   REPLACE_HUGE_VAL=0;               AC_SUBST([REPLACE_HUGE_VAL])
   REPLACE_HYPOT=0;                  AC_SUBST([REPLACE_HYPOT])
   REPLACE_HYPOTF=0;                 AC_SUBST([REPLACE_HYPOTF])
diff --git a/modules/getpayload b/modules/getpayload
new file mode 100644
index 0000000000..5721cb82a9
--- /dev/null
+++ b/modules/getpayload
@@ -0,0 +1,37 @@
+Description:
+getpayload function: extract the payload of a NaN
+
+Files:
+lib/getpayload.c
+m4/mathfunc.m4
+m4/getpayload.m4
+
+Depends-on:
+math
+extensions
+float           [test $HAVE_GETPAYLOAD = 0 || test $REPLACE_GETPAYLOAD = 1]
+stdint          [test $HAVE_GETPAYLOAD = 0 || test $REPLACE_GETPAYLOAD = 1]
+isnand          [test $HAVE_GETPAYLOAD = 0 || test $REPLACE_GETPAYLOAD = 1]
+
+configure.ac:
+gl_FUNC_GETPAYLOAD
+gl_CONDITIONAL([GL_COND_OBJ_GETPAYLOAD],
+               [test $HAVE_GETPAYLOAD = 0 || test $REPLACE_GETPAYLOAD = 1])
+gl_MATH_MODULE_INDICATOR([getpayload])
+
+Makefile.am:
+if GL_COND_OBJ_GETPAYLOAD
+lib_SOURCES += getpayload.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(GETPAYLOAD_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
diff --git a/modules/math b/modules/math
index 70baab7586..b6a15f6d68 100644
--- a/modules/math
+++ b/modules/math
@@ -75,6 +75,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's/@''GNULIB_FREXPF''@/$(GNULIB_FREXPF)/g' \
 	      -e 's/@''GNULIB_FREXP''@/$(GNULIB_FREXP)/g' \
 	      -e 's/@''GNULIB_FREXPL''@/$(GNULIB_FREXPL)/g' \
+	      -e 's/@''GNULIB_GETPAYLOAD''@/$(GNULIB_GETPAYLOAD)/g' \
 	      -e 's/@''GNULIB_HYPOT''@/$(GNULIB_HYPOT)/g' \
 	      -e 's/@''GNULIB_HYPOTF''@/$(GNULIB_HYPOTF)/g' \
 	      -e 's/@''GNULIB_HYPOTL''@/$(GNULIB_HYPOTL)/g' \
@@ -176,6 +177,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''HAVE_FMODF''@|$(HAVE_FMODF)|g' \
 	      -e 's|@''HAVE_FMODL''@|$(HAVE_FMODL)|g' \
 	      -e 's|@''HAVE_FREXPF''@|$(HAVE_FREXPF)|g' \
+	      -e 's|@''HAVE_GETPAYLOAD''@|$(HAVE_GETPAYLOAD)|g' \
 	      -e 's|@''HAVE_HYPOTF''@|$(HAVE_HYPOTF)|g' \
 	      -e 's|@''HAVE_HYPOTL''@|$(HAVE_HYPOTL)|g' \
 	      -e 's|@''HAVE_ILOGB''@|$(HAVE_ILOGB)|g' \
@@ -289,6 +291,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''REPLACE_FREXPF''@|$(REPLACE_FREXPF)|g' \
 	      -e 's|@''REPLACE_FREXP''@|$(REPLACE_FREXP)|g' \
 	      -e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \
+	      -e 's|@''REPLACE_GETPAYLOAD''@|$(REPLACE_GETPAYLOAD)|g' \
 	      -e 's|@''REPLACE_HUGE_VAL''@|$(REPLACE_HUGE_VAL)|g' \
 	      -e 's|@''REPLACE_HYPOT''@|$(REPLACE_HYPOT)|g' \
 	      -e 's|@''REPLACE_HYPOTF''@|$(REPLACE_HYPOTF)|g' \
-- 
2.34.1


[-- Attachment #3: 0002-getpayload-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4451 bytes --]

From 97313e9122e3f9780f6d259361f5e9e495b6d4eb Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Wed, 17 Apr 2024 10:58:47 +0200
Subject: [PATCH 2/6] getpayload: Add tests.

* tests/test-getpayload.c: New file.
* modules/getpayload-tests: New file.
---
 ChangeLog                |   4 ++
 modules/getpayload-tests |  18 +++++++
 tests/test-getpayload.c  | 112 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 modules/getpayload-tests
 create mode 100644 tests/test-getpayload.c

diff --git a/ChangeLog b/ChangeLog
index 6fbcff9835..495ea4d996 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2024-04-17  Bruno Haible  <bruno@clisp.org>
 
+	getpayload: Add tests.
+	* tests/test-getpayload.c: New file.
+	* modules/getpayload-tests: New file.
+
 	getpayload: New module.
 	* lib/math.in.h (getpayload): New declaration.
 	* lib/getpayload.c: New file.
diff --git a/modules/getpayload-tests b/modules/getpayload-tests
new file mode 100644
index 0000000000..d56192d63b
--- /dev/null
+++ b/modules/getpayload-tests
@@ -0,0 +1,18 @@
+Files:
+tests/test-getpayload.c
+tests/minus-zero.h
+tests/infinity.h
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+setpayload
+setpayloadsig
+signed-snan
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-getpayload
+check_PROGRAMS += test-getpayload
+test_getpayload_LDADD = $(LDADD) @GETPAYLOAD_LIBM@ $(SETPAYLOAD_LIBM) $(SETPAYLOADSIG_LIBM)
diff --git a/tests/test-getpayload.c b/tests/test-getpayload.c
new file mode 100644
index 0000000000..a6d9d940bd
--- /dev/null
+++ b/tests/test-getpayload.c
@@ -0,0 +1,112 @@
+/* Test getpayload.
+   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 (getpayload, double, (const double *));
+
+#include "minus-zero.h"
+#include "infinity.h"
+#include "signed-snan.h"
+#include "macros.h"
+
+#define PAYLOAD_BITS (53 - 2) /* = (DBL_MANT_DIG - 2) */
+
+int
+main ()
+{
+  double arg;
+  double ret;
+
+  /* Test non-NaN arguments.  */
+
+  arg = 2.718281828459045;
+  ret = getpayload (&arg);
+  ASSERT (ret == -1.0);
+
+  arg = -3.141592653589793;
+  ret = getpayload (&arg);
+  ASSERT (ret == -1.0);
+
+  arg = 0.0;
+  ret = getpayload (&arg);
+  ASSERT (ret == -1.0);
+
+  arg = minus_zerod;
+  ret = getpayload (&arg);
+  ASSERT (ret == -1.0);
+
+  arg = Infinityd ();
+  ret = getpayload (&arg);
+  ASSERT (ret == -1.0);
+
+  arg = - Infinityd ();
+  ret = getpayload (&arg);
+  ASSERT (ret == -1.0);
+
+  /* Test quiet NaNs.  */
+  {
+    int i;
+    double p;
+
+    for (i = 0, p = 1.0; i < PAYLOAD_BITS; i++, p *= 2.0)
+      {
+        ASSERT (setpayload (&arg, p) == 0);
+        ret = getpayload (&arg);
+        ASSERT (ret == p);
+        /* Test quiet NaNs with sign bit == 1.  */
+        arg = - arg;
+        ret = getpayload (&arg);
+        ASSERT (ret == p);
+      }
+
+    p = 1320699239819071.0;
+    ASSERT (setpayload (&arg, p) == 0);
+    ret = getpayload (&arg);
+    ASSERT (ret == p);
+  }
+
+  /* Test signalling NaNs.  */
+  {
+    int i;
+    double p;
+
+    for (i = 0, p = 1.0; i < PAYLOAD_BITS; i++, p *= 2.0)
+      {
+        ASSERT (setpayloadsig (&arg, p) == 0);
+        ret = getpayload (&arg);
+        ASSERT (ret == p);
+      }
+
+    p = 1320699239819071.0;
+    ASSERT (setpayloadsig (&arg, p) == 0);
+    ret = getpayload (&arg);
+    ASSERT (ret == p);
+
+    /* Test signalling NaNs with sign bit == 1.  */
+    memory_double pos_arg = memory_positive_SNaNd ();
+    memory_double neg_arg = memory_negative_SNaNd ();
+    double pos_ret = getpayload (&pos_arg.value);
+    double neg_ret = getpayload (&neg_arg.value);
+    ASSERT (neg_ret == pos_ret);
+  }
+
+  return 0;
+}
-- 
2.34.1


[-- Attachment #4: 0003-getpayloadf-New-module.patch --]
[-- Type: text/x-patch, Size: 10731 bytes --]

From 282b03a5af7553cd988b91e6380c228a66bfa6c1 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Wed, 17 Apr 2024 11:02:52 +0200
Subject: [PATCH 3/6] getpayloadf: New module.

* lib/math.in.h (getpayloadf): New declaration.
* lib/getpayloadf.c: New file.
* m4/math_h.m4 (gl_MATH_H): Test whether getpayloadf is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOADF.
(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOADF, REPLACE_GETPAYLOADF.
* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOADF,
HAVE_GETPAYLOADF, REPLACE_GETPAYLOADF.
* modules/getpayloadf: New file.
* doc/posix-functions/getpayloadf.texi: Mention the new module and the
glibc bug.
---
 ChangeLog                            | 14 ++++++++
 doc/posix-functions/getpayloadf.texi | 12 ++++---
 lib/getpayloadf.c                    | 54 ++++++++++++++++++++++++++++
 lib/math.in.h                        | 23 ++++++++++++
 m4/math_h.m4                         |  7 ++--
 modules/getpayloadf                  | 37 +++++++++++++++++++
 modules/math                         |  3 ++
 7 files changed, 144 insertions(+), 6 deletions(-)
 create mode 100644 lib/getpayloadf.c
 create mode 100644 modules/getpayloadf

diff --git a/ChangeLog b/ChangeLog
index 495ea4d996..6f97325216 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2024-04-17  Bruno Haible  <bruno@clisp.org>
+
+	getpayloadf: New module.
+	* lib/math.in.h (getpayloadf): New declaration.
+	* lib/getpayloadf.c: New file.
+	* m4/math_h.m4 (gl_MATH_H): Test whether getpayloadf is declared.
+	(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOADF.
+	(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOADF, REPLACE_GETPAYLOADF.
+	* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOADF,
+	HAVE_GETPAYLOADF, REPLACE_GETPAYLOADF.
+	* modules/getpayloadf: New file.
+	* doc/posix-functions/getpayloadf.texi: Mention the new module and the
+	glibc bug.
+
 2024-04-17  Bruno Haible  <bruno@clisp.org>
 
 	getpayload: Add tests.
diff --git a/doc/posix-functions/getpayloadf.texi b/doc/posix-functions/getpayloadf.texi
index 39bd40ead9..98eecf0109 100644
--- a/doc/posix-functions/getpayloadf.texi
+++ b/doc/posix-functions/getpayloadf.texi
@@ -10,15 +10,19 @@
 @url{https://www.gnu.org/software/libc/manual/html_node/FP-Bit-Twiddling.html}.
 @end ifnotinfo
 
-Gnulib module: ---
+Gnulib module: getpayloadf
 
 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.
+@item
+This function returns a wrong result for non-NaN arguments on some platforms:
+@c https://sourceware.org/bugzilla/show_bug.cgi?id=26073
+glibc 2.31.
 @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/getpayloadf.c b/lib/getpayloadf.c
new file mode 100644
index 0000000000..6e24c55407
--- /dev/null
+++ b/lib/getpayloadf.c
@@ -0,0 +1,54 @@
+/* Extract the payload of a NaN 'float'.
+   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>
+
+float
+getpayloadf (const float *value)
+{
+  if (isnanf (*value))
+    {
+#if FLT_MANT_DIG == 24
+      union { uint32_t i; float f; } x;
+# if 0
+      x.f = *value;
+# else
+      /* On 32-bit x86 processors, as well as on x86_64 processors with
+         CC="gcc -mfpmath=387", the evaluation of *value 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 (&x.f, value, sizeof (float));
+# endif
+      int32_t payload = x.i & (((uint32_t) 1 << (FLT_MANT_DIG - 2)) - 1);
+      return payload;
+#else
+# error "Please port gnulib getpayloadf.c to your platform!"
+#endif
+    }
+  else
+    return -1.0f;
+}
diff --git a/lib/math.in.h b/lib/math.in.h
index 2e7dde2e07..7a59c8cf35 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2774,6 +2774,29 @@ _GL_WARN_REAL_FLOATING_DECL (signbit);
 #endif
 
 
+#if @GNULIB_GETPAYLOADF@
+# if @REPLACE_GETPAYLOADF@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getpayloadf
+#   define getpayloadf rpl_getpayloadf
+#  endif
+_GL_FUNCDECL_RPL (getpayloadf, float, (const float *));
+_GL_CXXALIAS_RPL (getpayloadf, float, (const float *));
+# else
+#  if !@HAVE_GETPAYLOADF@
+_GL_FUNCDECL_SYS (getpayloadf, float, (const float *));
+#  endif
+_GL_CXXALIAS_SYS (getpayloadf, float, (const float *));
+# endif
+_GL_CXXALIASWARN (getpayloadf);
+#elif defined GNULIB_POSIXCHECK
+# undef getpayloadf
+# if HAVE_RAW_DECL_GETPAYLOADF
+_GL_WARN_ON_USE (getpayloadf, "getpayloadf is unportable - "
+                 "use gnulib module getpayloadf for portability");
+# endif
+#endif
+
 #if @GNULIB_GETPAYLOAD@
 # if @REPLACE_GETPAYLOAD@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 370ea14051..12aafb7fe9 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,5 +1,5 @@
 # math_h.m4
-# serial 133
+# serial 134
 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,
@@ -44,7 +44,7 @@ AC_DEFUN_ONCE([gl_MATH_H]
      expf expl exp2 exp2f exp2l expm1 expm1f expm1l
      fabsf fabsl floorf floorl fma fmaf fmal
      fmod fmodf fmodl frexpf frexpl
-     getpayload
+     getpayload getpayloadf
      hypotf hypotl
      ilogb ilogbf ilogbl
      ldexpf ldexpl
@@ -120,6 +120,7 @@ AC_DEFUN([gl_MATH_H_REQUIRE_DEFAULTS]
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FREXP])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FREXPL])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETPAYLOAD])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETPAYLOADF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOT])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOTL])
@@ -227,6 +228,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
   HAVE_FMODL=1;                     AC_SUBST([HAVE_FMODL])
   HAVE_FREXPF=1;                    AC_SUBST([HAVE_FREXPF])
   HAVE_GETPAYLOAD=1;                AC_SUBST([HAVE_GETPAYLOAD])
+  HAVE_GETPAYLOADF=1;               AC_SUBST([HAVE_GETPAYLOADF])
   HAVE_HYPOTF=1;                    AC_SUBST([HAVE_HYPOTF])
   HAVE_HYPOTL=1;                    AC_SUBST([HAVE_HYPOTL])
   HAVE_ILOGB=1;                     AC_SUBST([HAVE_ILOGB])
@@ -337,6 +339,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
   REPLACE_FREXP=0;                  AC_SUBST([REPLACE_FREXP])
   REPLACE_FREXPL=0;                 AC_SUBST([REPLACE_FREXPL])
   REPLACE_GETPAYLOAD=0;             AC_SUBST([REPLACE_GETPAYLOAD])
+  REPLACE_GETPAYLOADF=0;            AC_SUBST([REPLACE_GETPAYLOADF])
   REPLACE_HUGE_VAL=0;               AC_SUBST([REPLACE_HUGE_VAL])
   REPLACE_HYPOT=0;                  AC_SUBST([REPLACE_HYPOT])
   REPLACE_HYPOTF=0;                 AC_SUBST([REPLACE_HYPOTF])
diff --git a/modules/getpayloadf b/modules/getpayloadf
new file mode 100644
index 0000000000..a330b4f87a
--- /dev/null
+++ b/modules/getpayloadf
@@ -0,0 +1,37 @@
+Description:
+getpayloadf function: extract the payload of a NaN
+
+Files:
+lib/getpayloadf.c
+m4/mathfunc.m4
+m4/getpayload.m4
+
+Depends-on:
+math
+extensions
+float           [test $HAVE_GETPAYLOADF = 0 || test $REPLACE_GETPAYLOADF = 1]
+stdint          [test $HAVE_GETPAYLOADF = 0 || test $REPLACE_GETPAYLOADF = 1]
+isnanf          [test $HAVE_GETPAYLOADF = 0 || test $REPLACE_GETPAYLOADF = 1]
+
+configure.ac:
+gl_FUNC_GETPAYLOADF
+gl_CONDITIONAL([GL_COND_OBJ_GETPAYLOADF],
+               [test $HAVE_GETPAYLOADF = 0 || test $REPLACE_GETPAYLOADF = 1])
+gl_MATH_MODULE_INDICATOR([getpayloadf])
+
+Makefile.am:
+if GL_COND_OBJ_GETPAYLOADF
+lib_SOURCES += getpayloadf.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(GETPAYLOADF_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
diff --git a/modules/math b/modules/math
index b6a15f6d68..a8c9646124 100644
--- a/modules/math
+++ b/modules/math
@@ -76,6 +76,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's/@''GNULIB_FREXP''@/$(GNULIB_FREXP)/g' \
 	      -e 's/@''GNULIB_FREXPL''@/$(GNULIB_FREXPL)/g' \
 	      -e 's/@''GNULIB_GETPAYLOAD''@/$(GNULIB_GETPAYLOAD)/g' \
+	      -e 's/@''GNULIB_GETPAYLOADF''@/$(GNULIB_GETPAYLOADF)/g' \
 	      -e 's/@''GNULIB_HYPOT''@/$(GNULIB_HYPOT)/g' \
 	      -e 's/@''GNULIB_HYPOTF''@/$(GNULIB_HYPOTF)/g' \
 	      -e 's/@''GNULIB_HYPOTL''@/$(GNULIB_HYPOTL)/g' \
@@ -178,6 +179,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''HAVE_FMODL''@|$(HAVE_FMODL)|g' \
 	      -e 's|@''HAVE_FREXPF''@|$(HAVE_FREXPF)|g' \
 	      -e 's|@''HAVE_GETPAYLOAD''@|$(HAVE_GETPAYLOAD)|g' \
+	      -e 's|@''HAVE_GETPAYLOADF''@|$(HAVE_GETPAYLOADF)|g' \
 	      -e 's|@''HAVE_HYPOTF''@|$(HAVE_HYPOTF)|g' \
 	      -e 's|@''HAVE_HYPOTL''@|$(HAVE_HYPOTL)|g' \
 	      -e 's|@''HAVE_ILOGB''@|$(HAVE_ILOGB)|g' \
@@ -292,6 +294,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''REPLACE_FREXP''@|$(REPLACE_FREXP)|g' \
 	      -e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \
 	      -e 's|@''REPLACE_GETPAYLOAD''@|$(REPLACE_GETPAYLOAD)|g' \
+	      -e 's|@''REPLACE_GETPAYLOADF''@|$(REPLACE_GETPAYLOADF)|g' \
 	      -e 's|@''REPLACE_HUGE_VAL''@|$(REPLACE_HUGE_VAL)|g' \
 	      -e 's|@''REPLACE_HYPOT''@|$(REPLACE_HYPOT)|g' \
 	      -e 's|@''REPLACE_HYPOTF''@|$(REPLACE_HYPOTF)|g' \
-- 
2.34.1


[-- Attachment #5: 0004-getpayloadf-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4484 bytes --]

From e32e13caaef5f0cf9d6fc47a042251832746b7b7 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Wed, 17 Apr 2024 11:03:53 +0200
Subject: [PATCH 4/6] getpayloadf: Add tests.

* tests/test-getpayloadf.c: New file.
* modules/getpayloadf-tests: New file.
---
 ChangeLog                 |   4 ++
 modules/getpayloadf-tests |  18 ++++++
 tests/test-getpayloadf.c  | 112 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 modules/getpayloadf-tests
 create mode 100644 tests/test-getpayloadf.c

diff --git a/ChangeLog b/ChangeLog
index 6f97325216..863442a263 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2024-04-17  Bruno Haible  <bruno@clisp.org>
 
+	getpayloadf: Add tests.
+	* tests/test-getpayloadf.c: New file.
+	* modules/getpayloadf-tests: New file.
+
 	getpayloadf: New module.
 	* lib/math.in.h (getpayloadf): New declaration.
 	* lib/getpayloadf.c: New file.
diff --git a/modules/getpayloadf-tests b/modules/getpayloadf-tests
new file mode 100644
index 0000000000..1901fc43f9
--- /dev/null
+++ b/modules/getpayloadf-tests
@@ -0,0 +1,18 @@
+Files:
+tests/test-getpayloadf.c
+tests/minus-zero.h
+tests/infinity.h
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+setpayloadf
+setpayloadsigf
+signed-snan
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-getpayloadf
+check_PROGRAMS += test-getpayloadf
+test_getpayloadf_LDADD = $(LDADD) @GETPAYLOADF_LIBM@ $(SETPAYLOADF_LIBM) $(SETPAYLOADSIGF_LIBM)
diff --git a/tests/test-getpayloadf.c b/tests/test-getpayloadf.c
new file mode 100644
index 0000000000..f0ec047235
--- /dev/null
+++ b/tests/test-getpayloadf.c
@@ -0,0 +1,112 @@
+/* Test getpayloadf.
+   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 (getpayloadf, float, (const float *));
+
+#include "minus-zero.h"
+#include "infinity.h"
+#include "signed-snan.h"
+#include "macros.h"
+
+#define PAYLOAD_BITS (24 - 2) /* = (FLT_MANT_DIG - 2) */
+
+int
+main ()
+{
+  float arg;
+  float ret;
+
+  /* Test non-NaN arguments.  */
+
+  arg = 2.718281828459045f;
+  ret = getpayloadf (&arg);
+  ASSERT (ret == -1.0f);
+
+  arg = -3.141592653589793f;
+  ret = getpayloadf (&arg);
+  ASSERT (ret == -1.0f);
+
+  arg = 0.0f;
+  ret = getpayloadf (&arg);
+  ASSERT (ret == -1.0f);
+
+  arg = minus_zerof;
+  ret = getpayloadf (&arg);
+  ASSERT (ret == -1.0f);
+
+  arg = Infinityf ();
+  ret = getpayloadf (&arg);
+  ASSERT (ret == -1.0f);
+
+  arg = - Infinityf ();
+  ret = getpayloadf (&arg);
+  ASSERT (ret == -1.0f);
+
+  /* Test quiet NaNs.  */
+  {
+    int i;
+    float p;
+
+    for (i = 0, p = 1.0f; i < PAYLOAD_BITS; i++, p *= 2.0f)
+      {
+        ASSERT (setpayloadf (&arg, p) == 0);
+        ret = getpayloadf (&arg);
+        ASSERT (ret == p);
+        /* Test quiet NaNs with sign bit == 1.  */
+        arg = - arg;
+        ret = getpayloadf (&arg);
+        ASSERT (ret == p);
+      }
+
+    p = 2300902.0f;
+    ASSERT (setpayloadf (&arg, p) == 0);
+    ret = getpayloadf (&arg);
+    ASSERT (ret == p);
+  }
+
+  /* Test signalling NaNs.  */
+  {
+    int i;
+    float p;
+
+    for (i = 0, p = 1.0f; i < PAYLOAD_BITS; i++, p *= 2.0f)
+      {
+        ASSERT (setpayloadsigf (&arg, p) == 0);
+        ret = getpayloadf (&arg);
+        ASSERT (ret == p);
+      }
+
+    p = 2300902.0f;
+    ASSERT (setpayloadsigf (&arg, p) == 0);
+    ret = getpayloadf (&arg);
+    ASSERT (ret == p);
+
+    /* Test signalling NaNs with sign bit == 1.  */
+    memory_float pos_arg = memory_positive_SNaNf ();
+    memory_float neg_arg = memory_negative_SNaNf ();
+    float pos_ret = getpayloadf (&pos_arg.value);
+    float neg_ret = getpayloadf (&neg_arg.value);
+    ASSERT (neg_ret == pos_ret);
+  }
+
+  return 0;
+}
-- 
2.34.1


[-- Attachment #6: 0005-getpayloadl-New-module.patch --]
[-- Type: text/x-patch, Size: 13046 bytes --]

From 63f3bcdc9a42de17310dc636e031385a0feeaeff Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Wed, 17 Apr 2024 11:08:40 +0200
Subject: [PATCH 5/6] getpayloadl: New module.

* lib/math.in.h (getpayloadl): New declaration.
* lib/getpayloadl.c: New file.
* m4/math_h.m4 (gl_MATH_H): Test whether getpayloadl is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOADL.
(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOADL, REPLACE_GETPAYLOADL.
* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOADL,
HAVE_GETPAYLOADL, REPLACE_GETPAYLOADL.
* modules/getpayloadl: New file.
* doc/posix-functions/getpayloadl.texi: Mention the new module and the
glibc bug.
---
 ChangeLog                            |  14 ++++
 doc/posix-functions/getpayloadl.texi |  12 ++--
 lib/getpayloadl.c                    | 100 +++++++++++++++++++++++++++
 lib/math.in.h                        |  23 ++++++
 m4/math_h.m4                         |   7 +-
 modules/getpayloadl                  |  40 +++++++++++
 modules/math                         |   3 +
 7 files changed, 193 insertions(+), 6 deletions(-)
 create mode 100644 lib/getpayloadl.c
 create mode 100644 modules/getpayloadl

diff --git a/ChangeLog b/ChangeLog
index 863442a263..bcc40cb255 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2024-04-17  Bruno Haible  <bruno@clisp.org>
+
+	getpayloadl: New module.
+	* lib/math.in.h (getpayloadl): New declaration.
+	* lib/getpayloadl.c: New file.
+	* m4/math_h.m4 (gl_MATH_H): Test whether getpayloadl is declared.
+	(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_GETPAYLOADL.
+	(gl_MATH_H_DEFAULTS): Initialize HAVE_GETPAYLOADL, REPLACE_GETPAYLOADL.
+	* modules/math (Makefile.am): Substitute GNULIB_GETPAYLOADL,
+	HAVE_GETPAYLOADL, REPLACE_GETPAYLOADL.
+	* modules/getpayloadl: New file.
+	* doc/posix-functions/getpayloadl.texi: Mention the new module and the
+	glibc bug.
+
 2024-04-17  Bruno Haible  <bruno@clisp.org>
 
 	getpayloadf: Add tests.
diff --git a/doc/posix-functions/getpayloadl.texi b/doc/posix-functions/getpayloadl.texi
index b3f6471a67..8b1273b367 100644
--- a/doc/posix-functions/getpayloadl.texi
+++ b/doc/posix-functions/getpayloadl.texi
@@ -10,15 +10,19 @@
 @url{https://www.gnu.org/software/libc/manual/html_node/FP-Bit-Twiddling.html}.
 @end ifnotinfo
 
-Gnulib module: ---
+Gnulib module: getpayloadl
 
 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.
+@item
+This function returns a wrong result for non-NaN arguments on some platforms:
+@c https://sourceware.org/bugzilla/show_bug.cgi?id=26073
+glibc 2.31.
 @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/getpayloadl.c b/lib/getpayloadl.c
new file mode 100644
index 0000000000..6eefb56182
--- /dev/null
+++ b/lib/getpayloadl.c
@@ -0,0 +1,100 @@
+/* Extract the payload of a NaN 'long double'.
+   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
+
+long double
+getpayloadl (const long double *value)
+{
+  return getpayload ((const double *) value);
+}
+
+#else
+
+# include <float.h>
+# include <stdint.h>
+
+# include "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)))
+
+long double
+getpayloadl (const long double *value)
+{
+  if (isnanl (*value))
+    {
+# if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 106 || LDBL_MANT_DIG == 113) \
+     && defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
+      memory_long_double x;
+      x.value = *value;
+#  if LDBL_MANT_DIG == 64 /* on i386, x86_64, ia64, m68k */
+      int64_t payload;
+#   if LDBL_EXPBIT0_WORD == 2 && LDBL_EXPBIT0_BIT == 0 /* on i386, x86_64, ia64 */
+      payload = ((uint64_t) (x.word[1] & 0x3FFFFFFFU) << 32) | x.word[0];
+#   elif LDBL_EXPBIT0_WORD == 0 && LDBL_EXPBIT0_BIT == 16 /* on m68k */
+      payload = ((uint64_t) (x.word[1] & 0x3FFFFFFFU) << 32) | x.word[2];
+#   else
+#    error "Please port gnulib getpayloadl.c to your platform!"
+#   endif
+      return payload;
+#  endif
+#  if LDBL_MANT_DIG == 106 /* on powerpc, powerpc64, powerpc64le */
+      int64_t payload;
+#   if LDBL_EXPBIT0_BIT == 20
+      payload = ((uint64_t) (x.word[LDBL_EXPBIT0_WORD] & 0x0007FFFFU) << 32)
+                | x.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 1 : -1)];
+#   else
+#    error "Please port gnulib getpayloadl.c to your platform!"
+#   endif
+      return payload;
+#  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 = TWO_LDBL_MANT_DIG;
+      pl.word[LDBL_EXPBIT0_WORD] |= x.word[LDBL_EXPBIT0_WORD] & 0x00007FFFU;
+      pl.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 1 : -1)] =
+        x.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 1 : -1)];
+      pl.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 2 : -2)] =
+        x.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 2 : -2)];
+      pl.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 3 : -3)] =
+        x.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD == 0 ? 3 : -3)];
+      return pl.value - TWO_LDBL_MANT_DIG;
+#   else
+#    error "Please port gnulib getpayloadl.c to your platform!"
+#   endif
+#  endif
+# else
+#  error "Please port gnulib getpayloadl.c to your platform!"
+# endif
+    }
+  else
+    return -1.0L;
+}
+
+#endif
diff --git a/lib/math.in.h b/lib/math.in.h
index 7a59c8cf35..84b743e7ab 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2820,6 +2820,29 @@ _GL_WARN_ON_USE (getpayload, "getpayload is unportable - "
 # endif
 #endif
 
+#if @GNULIB_GETPAYLOADL@
+# if @REPLACE_GETPAYLOADL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getpayloadl
+#   define getpayloadl rpl_getpayloadl
+#  endif
+_GL_FUNCDECL_RPL (getpayloadl, long double, (const long double *));
+_GL_CXXALIAS_RPL (getpayloadl, long double, (const long double *));
+# else
+#  if !@HAVE_GETPAYLOADL@
+_GL_FUNCDECL_SYS (getpayloadl, long double, (const long double *));
+#  endif
+_GL_CXXALIAS_SYS (getpayloadl, long double, (const long double *));
+# endif
+_GL_CXXALIASWARN (getpayloadl);
+#elif defined GNULIB_POSIXCHECK
+# undef getpayloadl
+# if HAVE_RAW_DECL_GETPAYLOADL
+_GL_WARN_ON_USE (getpayloadl, "getpayloadl is unportable - "
+                 "use gnulib module getpayloadl for portability");
+# endif
+#endif
+
 
 #if @GNULIB_SETPAYLOADF@
 # if !@HAVE_SETPAYLOADF@
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 12aafb7fe9..217c4d225d 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,5 +1,5 @@
 # math_h.m4
-# serial 134
+# serial 135
 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,
@@ -44,7 +44,7 @@ AC_DEFUN_ONCE([gl_MATH_H]
      expf expl exp2 exp2f exp2l expm1 expm1f expm1l
      fabsf fabsl floorf floorl fma fmaf fmal
      fmod fmodf fmodl frexpf frexpl
-     getpayload getpayloadf
+     getpayload getpayloadf getpayloadl
      hypotf hypotl
      ilogb ilogbf ilogbl
      ldexpf ldexpl
@@ -121,6 +121,7 @@ AC_DEFUN([gl_MATH_H_REQUIRE_DEFAULTS]
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FREXPL])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETPAYLOAD])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETPAYLOADF])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETPAYLOADL])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOT])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOTF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HYPOTL])
@@ -229,6 +230,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
   HAVE_FREXPF=1;                    AC_SUBST([HAVE_FREXPF])
   HAVE_GETPAYLOAD=1;                AC_SUBST([HAVE_GETPAYLOAD])
   HAVE_GETPAYLOADF=1;               AC_SUBST([HAVE_GETPAYLOADF])
+  HAVE_GETPAYLOADL=1;               AC_SUBST([HAVE_GETPAYLOADL])
   HAVE_HYPOTF=1;                    AC_SUBST([HAVE_HYPOTF])
   HAVE_HYPOTL=1;                    AC_SUBST([HAVE_HYPOTL])
   HAVE_ILOGB=1;                     AC_SUBST([HAVE_ILOGB])
@@ -340,6 +342,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
   REPLACE_FREXPL=0;                 AC_SUBST([REPLACE_FREXPL])
   REPLACE_GETPAYLOAD=0;             AC_SUBST([REPLACE_GETPAYLOAD])
   REPLACE_GETPAYLOADF=0;            AC_SUBST([REPLACE_GETPAYLOADF])
+  REPLACE_GETPAYLOADL=0;            AC_SUBST([REPLACE_GETPAYLOADL])
   REPLACE_HUGE_VAL=0;               AC_SUBST([REPLACE_HUGE_VAL])
   REPLACE_HYPOT=0;                  AC_SUBST([REPLACE_HYPOT])
   REPLACE_HYPOTF=0;                 AC_SUBST([REPLACE_HYPOTF])
diff --git a/modules/getpayloadl b/modules/getpayloadl
new file mode 100644
index 0000000000..3ddd0a57ef
--- /dev/null
+++ b/modules/getpayloadl
@@ -0,0 +1,40 @@
+Description:
+getpayloadl function: extract the payload of a NaN
+
+Files:
+lib/getpayloadl.c
+m4/mathfunc.m4
+m4/getpayload.m4
+m4/exponentl.m4
+
+Depends-on:
+math
+extensions
+getpayload      [{ test $HAVE_GETPAYLOADL = 0 || test $REPLACE_GETPAYLOADL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
+float           [{ test $HAVE_GETPAYLOADL = 0 || test $REPLACE_GETPAYLOADL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+stdint          [{ test $HAVE_GETPAYLOADL = 0 || test $REPLACE_GETPAYLOADL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+isnanl          [{ test $HAVE_GETPAYLOADL = 0 || test $REPLACE_GETPAYLOADL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+snan            [{ test $HAVE_GETPAYLOADL = 0 || test $REPLACE_GETPAYLOADL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+
+configure.ac:
+gl_FUNC_GETPAYLOADL
+gl_CONDITIONAL([GL_COND_OBJ_GETPAYLOADL],
+               [test $HAVE_GETPAYLOADL = 0 || test $REPLACE_GETPAYLOADL = 1])
+gl_MATH_MODULE_INDICATOR([getpayloadl])
+
+Makefile.am:
+if GL_COND_OBJ_GETPAYLOADL
+lib_SOURCES += getpayloadl.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(GETPAYLOADL_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
diff --git a/modules/math b/modules/math
index a8c9646124..8c853f0979 100644
--- a/modules/math
+++ b/modules/math
@@ -77,6 +77,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's/@''GNULIB_FREXPL''@/$(GNULIB_FREXPL)/g' \
 	      -e 's/@''GNULIB_GETPAYLOAD''@/$(GNULIB_GETPAYLOAD)/g' \
 	      -e 's/@''GNULIB_GETPAYLOADF''@/$(GNULIB_GETPAYLOADF)/g' \
+	      -e 's/@''GNULIB_GETPAYLOADL''@/$(GNULIB_GETPAYLOADL)/g' \
 	      -e 's/@''GNULIB_HYPOT''@/$(GNULIB_HYPOT)/g' \
 	      -e 's/@''GNULIB_HYPOTF''@/$(GNULIB_HYPOTF)/g' \
 	      -e 's/@''GNULIB_HYPOTL''@/$(GNULIB_HYPOTL)/g' \
@@ -180,6 +181,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''HAVE_FREXPF''@|$(HAVE_FREXPF)|g' \
 	      -e 's|@''HAVE_GETPAYLOAD''@|$(HAVE_GETPAYLOAD)|g' \
 	      -e 's|@''HAVE_GETPAYLOADF''@|$(HAVE_GETPAYLOADF)|g' \
+	      -e 's|@''HAVE_GETPAYLOADL''@|$(HAVE_GETPAYLOADL)|g' \
 	      -e 's|@''HAVE_HYPOTF''@|$(HAVE_HYPOTF)|g' \
 	      -e 's|@''HAVE_HYPOTL''@|$(HAVE_HYPOTL)|g' \
 	      -e 's|@''HAVE_ILOGB''@|$(HAVE_ILOGB)|g' \
@@ -295,6 +297,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \
 	      -e 's|@''REPLACE_GETPAYLOAD''@|$(REPLACE_GETPAYLOAD)|g' \
 	      -e 's|@''REPLACE_GETPAYLOADF''@|$(REPLACE_GETPAYLOADF)|g' \
+	      -e 's|@''REPLACE_GETPAYLOADL''@|$(REPLACE_GETPAYLOADL)|g' \
 	      -e 's|@''REPLACE_HUGE_VAL''@|$(REPLACE_HUGE_VAL)|g' \
 	      -e 's|@''REPLACE_HYPOT''@|$(REPLACE_HYPOT)|g' \
 	      -e 's|@''REPLACE_HYPOTF''@|$(REPLACE_HYPOTF)|g' \
-- 
2.34.1


[-- Attachment #7: 0006-getpayloadl-Add-tests.patch --]
[-- Type: text/x-patch, Size: 4923 bytes --]

From 507b790ed13750b4c81afff56f403d2aeac4ca72 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Wed, 17 Apr 2024 11:09:13 +0200
Subject: [PATCH 6/6] getpayloadl: Add tests.

* tests/test-getpayloadl.c: New file.
* modules/getpayloadl-tests: New file.
---
 ChangeLog                 |   4 ++
 modules/getpayloadl-tests |  18 ++++++
 tests/test-getpayloadl.c  | 119 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 141 insertions(+)
 create mode 100644 modules/getpayloadl-tests
 create mode 100644 tests/test-getpayloadl.c

diff --git a/ChangeLog b/ChangeLog
index bcc40cb255..e6b4eff89b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2024-04-17  Bruno Haible  <bruno@clisp.org>
 
+	getpayloadl: Add tests.
+	* tests/test-getpayloadl.c: New file.
+	* modules/getpayloadl-tests: New file.
+
 	getpayloadl: New module.
 	* lib/math.in.h (getpayloadl): New declaration.
 	* lib/getpayloadl.c: New file.
diff --git a/modules/getpayloadl-tests b/modules/getpayloadl-tests
new file mode 100644
index 0000000000..02433a206d
--- /dev/null
+++ b/modules/getpayloadl-tests
@@ -0,0 +1,18 @@
+Files:
+tests/test-getpayloadl.c
+tests/minus-zero.h
+tests/infinity.h
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+setpayloadl
+setpayloadsigl
+signed-snan
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-getpayloadl
+check_PROGRAMS += test-getpayloadl
+test_getpayloadl_LDADD = $(LDADD) @GETPAYLOADL_LIBM@ $(SETPAYLOADL_LIBM) $(SETPAYLOADSIGL_LIBM)
diff --git a/tests/test-getpayloadl.c b/tests/test-getpayloadl.c
new file mode 100644
index 0000000000..4aaa7c5c0c
--- /dev/null
+++ b/tests/test-getpayloadl.c
@@ -0,0 +1,119 @@
+/* Test getpayloadl.
+   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 (getpayloadl, long double, (const long double *));
+
+#include "minus-zero.h"
+#include "infinity.h"
+#include "signed-snan.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 ()
+{
+  long double arg;
+  long double ret;
+
+  /* Test non-NaN arguments.  */
+
+  arg = 2.71828182845904523536028747135266249776L;
+  ret = getpayloadl (&arg);
+  ASSERT (ret == -1.0L);
+
+  arg = -3.1415926535897932384626433832795028842L;
+  ret = getpayloadl (&arg);
+  ASSERT (ret == -1.0L);
+
+  arg = 0.0L;
+  ret = getpayloadl (&arg);
+  ASSERT (ret == -1.0L);
+
+  arg = minus_zerol;
+  ret = getpayloadl (&arg);
+  ASSERT (ret == -1.0L);
+
+  arg = Infinityl ();
+  ret = getpayloadl (&arg);
+  ASSERT (ret == -1.0L);
+
+  arg = - Infinityl ();
+  ret = getpayloadl (&arg);
+  ASSERT (ret == -1.0L);
+
+  /* Test quiet NaNs.  */
+  {
+    int i;
+    long double p;
+
+    for (i = 0, p = 1.0L; i < PAYLOAD_BITS; i++, p *= 2.0L)
+      {
+        ASSERT (setpayloadl (&arg, p) == 0);
+        ret = getpayloadl (&arg);
+        ASSERT (ret == p);
+        /* Test quiet NaNs with sign bit == 1.  */
+        arg = - arg;
+        ret = getpayloadl (&arg);
+        ASSERT (ret == p);
+      }
+
+    p = 1320699239819071.0L;
+    ASSERT (setpayloadl (&arg, p) == 0);
+    ret = getpayloadl (&arg);
+    ASSERT (ret == p);
+  }
+
+  /* Test signalling NaNs.  */
+  {
+    int i;
+    long double p;
+
+    for (i = 0, p = 1.0L; i < PAYLOAD_BITS; i++, p *= 2.0L)
+      {
+        ASSERT (setpayloadsigl (&arg, p) == 0);
+        ret = getpayloadl (&arg);
+        ASSERT (ret == p);
+      }
+
+    p = 1320699239819071.0L;
+    ASSERT (setpayloadsigl (&arg, p) == 0);
+    ret = getpayloadl (&arg);
+    ASSERT (ret == p);
+
+    /* Test signalling NaNs with sign bit == 1.  */
+    memory_long_double pos_arg = memory_positive_SNaNl ();
+    memory_long_double neg_arg = memory_negative_SNaNl ();
+    long double pos_ret = getpayloadl (&pos_arg.value);
+    long double neg_ret = getpayloadl (&neg_arg.value);
+    ASSERT (neg_ret == pos_ret);
+  }
+
+  return 0;
+}
-- 
2.34.1


                 reply	other threads:[~2024-04-17 13:57 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=13436243.RAW8MR3E7N@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).