>From 282b03a5af7553cd988b91e6380c228a66bfa6c1 Mon Sep 17 00:00:00 2001 From: Bruno Haible 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 + + 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 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 . */ + +/* Written by Bruno Haible. */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +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 + + 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: + + +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