]> Savannah Git Hosting - gnulib.git/commitdiff
totalordermagl: New module.
authorBruno Haible <bruno@clisp.org>
Fri, 19 Apr 2024 00:22:16 +0000 (02:22 +0200)
committerBruno Haible <bruno@clisp.org>
Fri, 19 Apr 2024 00:22:16 +0000 (02:22 +0200)
* lib/math.in.h (totalordermagl): New declaration.
* lib/totalordermagl.c: New file, based on lib/totalorderl.c.
* m4/math_h.m4 (gl_MATH_H): Test whether totalordermagl is declared.
(gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_TOTALORDERMAGL.
(gl_MATH_H_DEFAULTS): Initialize HAVE_TOTALORDERMAGL,
REPLACE_TOTALORDERMAGL.
* modules/math (Makefile.am): Substitute GNULIB_TOTALORDERMAGL,
HAVE_TOTALORDERMAGL, REPLACE_TOTALORDERMAGL.
* modules/totalordermagl: New file, based on modules/totalorderl.
* doc/posix-functions/totalordermagl.texi: Mention the new module.

ChangeLog
doc/posix-functions/totalordermagl.texi
lib/math.in.h
lib/totalordermagl.c [new file with mode: 0644]
m4/math_h.m4
modules/math
modules/totalordermagl [new file with mode: 0644]

index 3257161de606d81fa77615261e107191d52797c0..7bd8b5072dc6ebe724ebefe8147423c76581e8e7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2024-04-18  Bruno Haible  <bruno@clisp.org>
+
+       totalordermagl: New module.
+       * lib/math.in.h (totalordermagl): New declaration.
+       * lib/totalordermagl.c: New file, based on lib/totalorderl.c.
+       * m4/math_h.m4 (gl_MATH_H): Test whether totalordermagl is declared.
+       (gl_MATH_H_REQUIRE_DEFAULTS): Initialize GNULIB_TOTALORDERMAGL.
+       (gl_MATH_H_DEFAULTS): Initialize HAVE_TOTALORDERMAGL,
+       REPLACE_TOTALORDERMAGL.
+       * modules/math (Makefile.am): Substitute GNULIB_TOTALORDERMAGL,
+       HAVE_TOTALORDERMAGL, REPLACE_TOTALORDERMAGL.
+       * modules/totalordermagl: New file, based on modules/totalorderl.
+       * doc/posix-functions/totalordermagl.texi: Mention the new module.
+
 2024-04-18  Bruno Haible  <bruno@clisp.org>
 
        totalordermagf: Add tests.
index 45895dd1b8d3f972b1c2dee98398944671500eab..09d36199f821837ed618b8d2535d915e3348ec90 100644 (file)
@@ -10,14 +10,10 @@ Documentation:@*
 @url{https://www.gnu.org/software/libc/manual/html_node/FP-Comparison-Functions.html}.
 @end ifnotinfo
 
-Gnulib module: ---
+Gnulib module: totalordermagl
 
 Portability problems fixed by Gnulib:
 @itemize
-@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.
@@ -25,3 +21,7 @@ glibc 2.24, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX
 This function has a different signature on some platforms:
 glibc 2.30.
 @end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
+@end itemize
index 43a9674fff47125aa12639a63eed23325764c434..96d0da44fdb441eb15dbbb419042e743397fdb73 100644 (file)
@@ -3056,6 +3056,36 @@ _GL_WARN_ON_USE (totalordermag, "totalordermag is unportable - "
 # endif
 #endif
 
+#if @GNULIB_TOTALORDERMAGL@
+# if @REPLACE_TOTALORDERMAGL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef totalordermagl
+#   define totalordermagl rpl_totalordermagl
+#  endif
+_GL_FUNCDECL_RPL (totalordermagl, int,
+                  (long double const *, long double const *));
+_GL_CXXALIAS_RPL (totalordermagl, int,
+                  (long double const *, long double const *));
+# else
+#  if !@HAVE_TOTALORDERMAGL@
+_GL_FUNCDECL_SYS (totalordermagl, int,
+                  (long double const *, long double const *));
+#  endif
+_GL_CXXALIAS_SYS (totalordermagl, int,
+                  (long double const *, long double const *));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN1 (totalordermagl, int,
+                   (long double const *, long double const *));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef totalordermagl
+# if HAVE_RAW_DECL_TOTALORDERMAGL
+_GL_WARN_ON_USE (totalordermagl, "totalordermagl is unportable - "
+                 "use gnulib module totalordermagl for portability");
+# endif
+#endif
+
 
 _GL_INLINE_HEADER_END
 
diff --git a/lib/totalordermagl.c b/lib/totalordermagl.c
new file mode 100644 (file)
index 0000000..85d492f
--- /dev/null
@@ -0,0 +1,149 @@
+/* Total order of absolute value for 'long double'.
+   Copyright 2023-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 Paul Eggert and Bruno Haible.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <math.h>
+
+#if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE
+
+int
+totalordermagl (long double const *x, long double const *y)
+{
+  return totalordermag ((double const *) x, (double const *) y);
+}
+
+#else
+
+# include <float.h>
+# include <stdint.h>
+# include <string.h>
+
+# include "verify.h"
+
+int
+totalordermagl (long double const *x, long double const *y)
+{
+  /* If one of *X, *Y is a NaN and the other isn't, the answer is easy:
+     the NaN is "greater" than the other argument.  */
+  int xn = isnanl (*x);
+  int yn = isnanl (*y);
+  if (!xn != !yn)
+    return yn;
+  /* If none of *X, *Y is a NaN, the '<=' operator on the absolute values
+     does the job, including for -Infinity and +Infinity.  */
+  if (!xn)
+    return (signbit (*x) ? - *x : *x) <= (signbit (*y) ? - *y : *y);
+
+  /* At this point, *X and *Y are NaNs.  */
+
+# if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT
+  /* The use of a union to extract the bits of the representation of a
+     'double' is safe in practice, despite of the "aliasing rules" of
+     C99, because the GCC docs say
+       "Even with '-fstrict-aliasing', type-punning is allowed, provided the
+        memory is accessed through the union type."
+     and similarly for other compilers.  */
+#  define NWORDS \
+    ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+#  if LDBL_MANT_DIG == 64 /* on i386, x86_64, ia64, m68k */
+  /* A single uint64_t is enough to hold the payload, since we ignore the sign
+     bit and the exponent has the maximum possible value.  */
+  verify (NWORDS >= 3);
+#   if LDBL_SIGNBIT_WORD == 2 && LDBL_SIGNBIT_BIT == 15 /* on i386, x86_64, ia64 */
+  /* Also, LDBL_EXPBIT0_WORD == 2 && LDBL_EXPBIT0_BIT == 0.  */
+  union { unsigned int word[NWORDS]; uint64_t i; long double value; } xu, yu;
+  xu.value = *x;
+  yu.value = *y;
+  return xu.i <= yu.i;
+#   elif LDBL_SIGNBIT_WORD == 0 && LDBL_SIGNBIT_BIT == 31 /* on m68k */
+  /* Also, LDBL_EXPBIT0_WORD == 0 && LDBL_EXPBIT0_BIT == 16.  */
+  union { unsigned int word[NWORDS]; long double value; } xu, yu;
+  xu.value = *x;
+  yu.value = *y;
+  /* The payload is in word[1] (high part) and word[2] (low part).  */
+  return (xu.word[1] < yu.word[1])
+         | ((xu.word[1] == yu.word[1]) & (xu.word[2] <= yu.word[2]));
+#   else
+#    error "Please port gnulib totalordermagl.c to your platform!"
+#   endif
+#  elif LDBL_MANT_DIG == 106 /* on powerpc, powerpc64, powerpc64le */
+  /* Two uint64_t are needed to hold the payload.
+     In the double-double representation, each of the two uint64_t holds
+     a sign bit.  */
+  verify (NWORDS == 4);
+  union { unsigned int word[NWORDS]; uint64_t i[2]; long double value; }
+    xu = {0}, yu = {0};
+  xu.value = *x;
+  yu.value = *y;
+  uint64_t xhi = xu.i[0] & ~((uint64_t) 1 << (LDBL_SIGNBIT_BIT + 32));
+  uint64_t xlo = xu.i[1] & ~((uint64_t) 1 << (LDBL_SIGNBIT_BIT + 32));
+  uint64_t yhi = yu.i[0] & ~((uint64_t) 1 << (LDBL_SIGNBIT_BIT + 32));
+  uint64_t ylo = yu.i[1] & ~((uint64_t) 1 << (LDBL_SIGNBIT_BIT + 32));
+  return (xhi < yhi) | ((xhi == yhi) & (xlo <= ylo));
+#  else
+  /* Here, LDBL_MANT_DIG == 113 (alpha, arm64, loongarch64, mips64, riscv64,
+                                 s390x, sparc64).  */
+  /* Two uint64_t are needed to hold the payload.  */
+  verify (NWORDS == 4);
+  union { unsigned int word[NWORDS]; uint64_t i[2]; long double value; }
+    xu = {0}, yu = {0};
+# if 0
+  xu.value = *x;
+  yu.value = *y;
+# else
+  /* On Linux/SPARC in 64-bit mode, gcc-6.4.0 -O2 miscompiles the simple
+     assignments above.  Use memcpy as a workaround.  */
+  memcpy (&xu.value, x, sizeof (long double));
+  memcpy (&yu.value, y, sizeof (long double));
+# endif
+  uint64_t xhi;
+  uint64_t xlo;
+  uint64_t yhi;
+  uint64_t ylo;
+#   if LDBL_SIGNBIT_WORD < 2 /* big-endian */
+  xhi = xu.i[0] & ~((uint64_t) 1 << (LDBL_SIGNBIT_BIT + 32 * (1 - LDBL_SIGNBIT_WORD)));
+  xlo = xu.i[1];
+  yhi = yu.i[0] & ~((uint64_t) 1 << (LDBL_SIGNBIT_BIT + 32 * (1 - LDBL_SIGNBIT_WORD)));
+  ylo = yu.i[1];
+#   else /* little-endian */
+  xhi = xu.i[1] & ~((uint64_t) 1 << (LDBL_SIGNBIT_BIT + 32 * (LDBL_SIGNBIT_WORD - 2)));
+  xlo = xu.i[0];
+  yhi = yu.i[1] & ~((uint64_t) 1 << (LDBL_SIGNBIT_BIT + 32 * (LDBL_SIGNBIT_WORD - 2)));
+  ylo = yu.i[0];
+#   endif
+#   if defined __hppa || (defined __mips__ && !MIPS_NAN2008_LONG_DOUBLE) || defined __sh__
+  /* Invert the most significant bit of the mantissa field.  Cf. snan.h.  */
+  xhi ^=
+    (1ULL << (LDBL_MANT_DIG == 106
+              ? 51                          /* double-double representation */
+              : (LDBL_MANT_DIG - 2) - 64)); /* quad precision representation */
+  yhi ^=
+    (1ULL << (LDBL_MANT_DIG == 106
+              ? 51                          /* double-double representation */
+              : (LDBL_MANT_DIG - 2) - 64)); /* quad precision representation */
+#   endif
+  return (xhi < yhi) | ((xhi == yhi) & (xlo <= ylo));
+#  endif
+# else
+#  error "Please port gnulib totalordermagl.c to your platform!"
+# endif
+}
+
+#endif
index d07813a0163c50c9239dbe7a8374dfbbb6d241a9..4b26c9e9dc433be75c1972226bae839055de0839 100644 (file)
@@ -1,5 +1,5 @@
 # math_h.m4
-# serial 137
+# serial 138
 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,
@@ -57,7 +57,7 @@ AC_DEFUN_ONCE([gl_MATH_H],
      setpayloadsig setpayloadsigf setpayloadsigl
      sinf sinl sinhf sqrtf sqrtl
      tanf tanl tanhf totalorder totalorderf totalorderl totalordermag
-     totalordermagf trunc truncf truncl])
+     totalordermagf totalordermagl trunc truncf truncl])
 ])
 
 # gl_MATH_MODULE_INDICATOR([modulename])
@@ -186,6 +186,7 @@ AC_DEFUN([gl_MATH_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TOTALORDERL])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TOTALORDERMAG])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TOTALORDERMAGF])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TOTALORDERMAGL])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TRUNC])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TRUNCF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TRUNCL])
@@ -278,6 +279,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   HAVE_TOTALORDERL=1;               AC_SUBST([HAVE_TOTALORDERL])
   HAVE_TOTALORDERMAG=1;             AC_SUBST([HAVE_TOTALORDERMAG])
   HAVE_TOTALORDERMAGF=1;            AC_SUBST([HAVE_TOTALORDERMAGF])
+  HAVE_TOTALORDERMAGL=1;            AC_SUBST([HAVE_TOTALORDERMAGL])
   HAVE_DECL_ACOSL=1;                AC_SUBST([HAVE_DECL_ACOSL])
   HAVE_DECL_ASINL=1;                AC_SUBST([HAVE_DECL_ASINL])
   HAVE_DECL_ATANL=1;                AC_SUBST([HAVE_DECL_ATANL])
@@ -399,6 +401,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   REPLACE_TOTALORDERL=0;            AC_SUBST([REPLACE_TOTALORDERL])
   REPLACE_TOTALORDERMAG=0;          AC_SUBST([REPLACE_TOTALORDERMAG])
   REPLACE_TOTALORDERMAGF=0;         AC_SUBST([REPLACE_TOTALORDERMAGF])
+  REPLACE_TOTALORDERMAGL=0;         AC_SUBST([REPLACE_TOTALORDERMAGL])
   REPLACE_TRUNC=0;                  AC_SUBST([REPLACE_TRUNC])
   REPLACE_TRUNCF=0;                 AC_SUBST([REPLACE_TRUNCF])
   REPLACE_TRUNCL=0;                 AC_SUBST([REPLACE_TRUNCL])
index 04fa28720950d7c31c0f5448d71a9e1aadf298b2..983c7bf91e1cf4d2843b8ea9b482e7b2a6c9983f 100644 (file)
@@ -146,6 +146,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's/@''GNULIB_TOTALORDERL''@/$(GNULIB_TOTALORDERL)/g' \
              -e 's/@''GNULIB_TOTALORDERMAG''@/$(GNULIB_TOTALORDERMAG)/g' \
              -e 's/@''GNULIB_TOTALORDERMAGF''@/$(GNULIB_TOTALORDERMAGF)/g' \
+             -e 's/@''GNULIB_TOTALORDERMAGL''@/$(GNULIB_TOTALORDERMAGL)/g' \
              -e 's/@''GNULIB_MDA_J0''@/$(GNULIB_MDA_J0)/g' \
              -e 's/@''GNULIB_MDA_J1''@/$(GNULIB_MDA_J1)/g' \
              -e 's/@''GNULIB_MDA_JN''@/$(GNULIB_MDA_JN)/g' \
@@ -228,6 +229,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's|@''HAVE_TOTALORDERL''@|$(HAVE_TOTALORDERL)|g' \
              -e 's|@''HAVE_TOTALORDERMAG''@|$(HAVE_TOTALORDERMAG)|g' \
              -e 's|@''HAVE_TOTALORDERMAGF''@|$(HAVE_TOTALORDERMAGF)|g' \
+             -e 's|@''HAVE_TOTALORDERMAGL''@|$(HAVE_TOTALORDERMAGL)|g' \
              < $@-t2 > $@-t3
        $(AM_V_at)sed \
              -e 's|@''HAVE_DECL_ACOSL''@|$(HAVE_DECL_ACOSL)|g' \
@@ -356,6 +358,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's|@''REPLACE_TOTALORDERL''@|$(REPLACE_TOTALORDERL)|g' \
              -e 's|@''REPLACE_TOTALORDERMAG''@|$(REPLACE_TOTALORDERMAG)|g' \
              -e 's|@''REPLACE_TOTALORDERMAGF''@|$(REPLACE_TOTALORDERMAGF)|g' \
+             -e 's|@''REPLACE_TOTALORDERMAGL''@|$(REPLACE_TOTALORDERMAGL)|g' \
              -e 's|@''REPLACE_TRUNC''@|$(REPLACE_TRUNC)|g' \
              -e 's|@''REPLACE_TRUNCF''@|$(REPLACE_TRUNCF)|g' \
              -e 's|@''REPLACE_TRUNCL''@|$(REPLACE_TRUNCL)|g' \
diff --git a/modules/totalordermagl b/modules/totalordermagl
new file mode 100644 (file)
index 0000000..ca51cd0
--- /dev/null
@@ -0,0 +1,43 @@
+Description:
+totalordermagl function: total order of absolute value on long double
+
+Files:
+lib/totalordermagl.c
+m4/mathfunc.m4
+m4/totalordermag.m4
+m4/nan-mips.m4
+m4/signbit.m4
+
+Depends-on:
+math
+extensions
+totalordermag   [{ test $HAVE_TOTALORDERMAGL = 0 || test $REPLACE_TOTALORDERMAGL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
+float           [{ test $HAVE_TOTALORDERMAGL = 0 || test $REPLACE_TOTALORDERMAGL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+stdbool         [{ test $HAVE_TOTALORDERMAGL = 0 || test $REPLACE_TOTALORDERMAGL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+stdint          [{ test $HAVE_TOTALORDERMAGL = 0 || test $REPLACE_TOTALORDERMAGL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+verify          [{ test $HAVE_TOTALORDERMAGL = 0 || test $REPLACE_TOTALORDERMAGL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+isnanl          [{ test $HAVE_TOTALORDERMAGL = 0 || test $REPLACE_TOTALORDERMAGL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+signbit         [{ test $HAVE_TOTALORDERMAGL = 0 || test $REPLACE_TOTALORDERMAGL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+
+configure.ac:
+gl_FUNC_TOTALORDERMAGL
+gl_CONDITIONAL([GL_COND_OBJ_TOTALORDERMAGL],
+               [test $HAVE_TOTALORDERMAGL = 0 || test $REPLACE_TOTALORDERMAGL = 1])
+gl_MATH_MODULE_INDICATOR([totalordermagl])
+
+Makefile.am:
+if GL_COND_OBJ_TOTALORDERMAGL
+lib_SOURCES += totalordermagl.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(TOTALORDERMAGL_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all