* lib/math.in.h: Declare totalorderf, totalorder, totalorderl.
* lib/totalorder.c, lib/totalorderf.c, lib/totalorderl.c:
* m4/totalorder.m4, modules/totalorder, modules/totalorder-tests:
* modules/totalorderf, modules/totalorderf-tests:
* modules/totalorderl, modules/totalorderl-tests:
* tests/test-totalorder.c, tests/test-totalorderf.c:
* tests/test-totalorderl.c: New files.
* m4/math_h.m4 (gl_MATH_H, gl_MATH_H_REQUIRE_DEFAULTS)
(gl_MATH_H_DEFAULTS):
* modules/math (math.h): Set up totalorder, totalorderf, totalorderl.
* m4/mathfunc.m4 (gl_MATHFUNC): Also support pointer-to-const.
---
 ChangeLog                            | 15 +++++
 doc/posix-functions/totalorder.texi  | 12 ++--
 doc/posix-functions/totalorderf.texi | 12 ++--
 doc/posix-functions/totalorderl.texi | 12 ++--
 lib/math.in.h                        | 76 ++++++++++++++++++++++++
 lib/totalorder.c                     | 45 +++++++++++++++
 lib/totalorderf.c                    | 45 +++++++++++++++
 lib/totalorderl.c                    | 63 ++++++++++++++++++++
 m4/math_h.m4                         | 11 +++-
 m4/mathfunc.m4                       | 11 ++--
 m4/totalorder.m4                     | 86 ++++++++++++++++++++++++++++
 modules/math                         |  9 +++
 modules/totalorder                   | 36 ++++++++++++
 modules/totalorder-tests             | 15 +++++
 modules/totalorderf                  | 36 ++++++++++++
 modules/totalorderf-tests            | 16 ++++++
 modules/totalorderl                  | 37 ++++++++++++
 modules/totalorderl-tests            | 16 ++++++
 tests/test-totalorder.c              | 57 ++++++++++++++++++
 tests/test-totalorderf.c             |  6 ++
 tests/test-totalorderl.c             |  6 ++
 21 files changed, 598 insertions(+), 24 deletions(-)
 create mode 100644 lib/totalorder.c
 create mode 100644 lib/totalorderf.c
 create mode 100644 lib/totalorderl.c
 create mode 100644 m4/totalorder.m4
 create mode 100644 modules/totalorder
 create mode 100644 modules/totalorder-tests
 create mode 100644 modules/totalorderf
 create mode 100644 modules/totalorderf-tests
 create mode 100644 modules/totalorderl
 create mode 100644 modules/totalorderl-tests
 create mode 100644 tests/test-totalorder.c
 create mode 100644 tests/test-totalorderf.c
 create mode 100644 tests/test-totalorderl.c

diff --git a/ChangeLog b/ChangeLog
index 463a44ffbb..19e1a21d72 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2023-10-01  Paul Eggert  <egg...@cs.ucla.edu>
+
+       totalorder, totalorderf, totalorderl: new modules
+       * lib/math.in.h: Declare totalorderf, totalorder, totalorderl.
+       * lib/totalorder.c, lib/totalorderf.c, lib/totalorderl.c:
+       * m4/totalorder.m4, modules/totalorder, modules/totalorder-tests:
+       * modules/totalorderf, modules/totalorderf-tests:
+       * modules/totalorderl, modules/totalorderl-tests:
+       * tests/test-totalorder.c, tests/test-totalorderf.c:
+       * tests/test-totalorderl.c: New files.
+       * m4/math_h.m4 (gl_MATH_H, gl_MATH_H_REQUIRE_DEFAULTS)
+       (gl_MATH_H_DEFAULTS):
+       * modules/math (math.h): Set up totalorder, totalorderf, totalorderl.
+       * m4/mathfunc.m4 (gl_MATHFUNC): Also support pointer-to-const.
+
 2023-09-30  Paul Eggert  <egg...@cs.ucla.edu>
 
        regex-quote: fix recently-introduced typo
diff --git a/doc/posix-functions/totalorder.texi 
b/doc/posix-functions/totalorder.texi
index 4687d9ba90..a7f8524718 100644
--- a/doc/posix-functions/totalorder.texi
+++ b/doc/posix-functions/totalorder.texi
@@ -10,18 +10,18 @@ Documentation:@*
 
@url{https://www.gnu.org/software/libc/manual/html_node/FP-Comparison-Functions.html}.
 @end ifnotinfo
 
-Gnulib module: ---
+Gnulib module: totalorder
 
 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:
+This function is missing on many platforms:
 glibc 2.24, macOS 11.1, FreeBSD 13.0, NetBSD 9.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 has a different signature on some platforms:
 glibc 2.30.
 @end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
+@end itemize
diff --git a/doc/posix-functions/totalorderf.texi 
b/doc/posix-functions/totalorderf.texi
index 4e3928c1d8..115fbfdf5b 100644
--- a/doc/posix-functions/totalorderf.texi
+++ b/doc/posix-functions/totalorderf.texi
@@ -10,18 +10,18 @@ Documentation:@*
 
@url{https://www.gnu.org/software/libc/manual/html_node/FP-Comparison-Functions.html}.
 @end ifnotinfo
 
-Gnulib module: ---
+Gnulib module: totalorderf
 
 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:
+This function is missing on many platforms:
 glibc 2.24, macOS 11.1, FreeBSD 13.0, NetBSD 9.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 has a different signature on some platforms:
 glibc 2.30.
 @end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
+@end itemize
diff --git a/doc/posix-functions/totalorderl.texi 
b/doc/posix-functions/totalorderl.texi
index 927597882e..cc07d0e080 100644
--- a/doc/posix-functions/totalorderl.texi
+++ b/doc/posix-functions/totalorderl.texi
@@ -10,18 +10,18 @@ Documentation:@*
 
@url{https://www.gnu.org/software/libc/manual/html_node/FP-Comparison-Functions.html}.
 @end ifnotinfo
 
-Gnulib module: ---
+Gnulib module: totalorderl
 
 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:
+This function is missing on many platforms:
 glibc 2.24, macOS 11.1, FreeBSD 13.0, NetBSD 9.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 has a different signature on some platforms:
 glibc 2.30.
 @end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
+@end itemize
diff --git a/lib/math.in.h b/lib/math.in.h
index 75d5013cf1..b18627ae0a 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2761,6 +2761,82 @@ _GL_WARN_REAL_FLOATING_DECL (signbit);
 # endif
 #endif
 
+
+#if @GNULIB_TOTALORDERF@
+# if @REPLACE_TOTALORDERF@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef totalorderf
+#   define totalorderf rpl_totalorderf
+#  endif
+_GL_FUNCDECL_RPL (totalorderf, int, (float const *, float const *));
+_GL_CXXALIAS_RPL (totalorderf, int, (float const *, float const *));
+# else
+#  if !@HAVE_TOTALORDERF@
+_GL_FUNCDECL_SYS (totalorderf, int, (float const *, float const *));
+#  endif
+_GL_CXXALIAS_SYS (totalorderf, int, (float const *, float const *));
+# endif
+_GL_CXXALIASWARN (totalorderf);
+#elif defined GNULIB_POSIXCHECK
+# undef totalorderf
+# if HAVE_RAW_DECL_TOTALORDERF
+_GL_WARN_ON_USE (totalorderf, "totalorderf is unportable - "
+                 "use gnulib module totalorderf for portability");
+# endif
+#endif
+
+#if @GNULIB_TOTALORDER@
+# if @REPLACE_TOTALORDER@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef totalorder
+#   define totalorder rpl_totalorder
+#  endif
+_GL_FUNCDECL_RPL (totalorder, int, (double const *, double const *));
+_GL_CXXALIAS_RPL (totalorder, int, (double const *, double const *));
+# else
+#  if !@HAVE_TOTALORDER@
+_GL_FUNCDECL_SYS (totalorder, int, (double const *, double const *));
+#  endif
+_GL_CXXALIAS_SYS (totalorder, int, (double const *, double const *));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN1 (totalorder, int, (double const *, double const *));
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef totalorder
+# if HAVE_RAW_DECL_TOTALORDER
+_GL_WARN_ON_USE (totalorder, "totalorder is unportable - "
+                 "use gnulib module totalorder for portability");
+# endif
+#endif
+
+#if @GNULIB_TOTALORDERL@
+# if @REPLACE_TOTALORDERL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef totalorderl
+#   define totalorderl rpl_totalorderl
+#  endif
+_GL_FUNCDECL_RPL (totalorderl, int,
+                  (long double const *, long double const *));
+_GL_CXXALIAS_RPL (totalorderl, int,
+                  (long double const *, long double const *));
+# else
+#  if !@HAVE_TOTALORDERL@
+_GL_FUNCDECL_SYS (totalorderl, int,
+                  (long double const *, long double const *));
+#  endif
+_GL_CXXALIAS_SYS (totalorderl, int,
+                  (long double const *, long double const *));
+# endif
+_GL_CXXALIASWARN (totalorderl);
+#elif defined GNULIB_POSIXCHECK
+# undef totalorderl
+# if HAVE_RAW_DECL_TOTALORDERL
+_GL_WARN_ON_USE (totalorderl, "totalorderl is unportable - "
+                 "use gnulib module totalorderl for portability");
+# endif
+#endif
+
 _GL_INLINE_HEADER_END
 
 #endif /* _@GUARD_PREFIX@_MATH_H */
diff --git a/lib/totalorder.c b/lib/totalorder.c
new file mode 100644
index 0000000000..4c861f971c
--- /dev/null
+++ b/lib/totalorder.c
@@ -0,0 +1,45 @@
+/* Total order for 'double'
+   Copyright 2023 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.  */
+
+#include <config.h>
+
+#include <math.h>
+
+int
+totalorder (double const *x, double const *y)
+{
+  /* Although the following is not strictly portable, and won't work
+     on some obsolete platforms (e.g., PA-RISC, MIPS before alignment
+     to IEEE 754-2008), it should be good enough nowadays.  */
+  int xs = signbit (*x);
+  int ys = signbit (*y);
+  if (!xs != !ys)
+    return xs;
+  int xn = isnand (*x);
+  int yn = isnand (*y);
+  if (!xn != !yn)
+    return !xn == !xs;
+  if (!xn)
+    return *x <= *y;
+
+  unsigned long long extended_sign = -!!xs;
+  union { unsigned long long i; double f; } volatile xu = {0}, yu = {0};
+  xu.f = *x;
+  yu.f = *y;
+  return (xu.i ^ extended_sign) <= (yu.i ^ extended_sign);
+}
diff --git a/lib/totalorderf.c b/lib/totalorderf.c
new file mode 100644
index 0000000000..d86299ff09
--- /dev/null
+++ b/lib/totalorderf.c
@@ -0,0 +1,45 @@
+/* Total order for 'float'
+   Copyright 2023 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.  */
+
+#include <config.h>
+
+#include <math.h>
+
+int
+totalorderf (float const *x, float const *y)
+{
+  /* Although the following is not strictly portable, and won't work
+     on some obsolete platforms (e.g., PA-RISC, MIPS before alignment
+     to IEEE 754-2008), it should be good enough nowadays.  */
+  int xs = signbit (*x);
+  int ys = signbit (*y);
+  if (!xs != !ys)
+    return xs;
+  int xn = isnanf (*x);
+  int yn = isnanf (*y);
+  if (!xn != !yn)
+    return !xn == !xs;
+  if (!xn)
+    return *x <= *y;
+
+  unsigned long extended_sign = -!!xs;
+  union { unsigned long i; float f; } volatile xu = {0}, yu = {0};
+  xu.f = *x;
+  yu.f = *y;
+  return (xu.i ^ extended_sign) <= (yu.i ^ extended_sign);
+}
diff --git a/lib/totalorderl.c b/lib/totalorderl.c
new file mode 100644
index 0000000000..03aba3adf7
--- /dev/null
+++ b/lib/totalorderl.c
@@ -0,0 +1,63 @@
+/* Total order for 'long double'
+   Copyright 2023 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.  */
+
+#include <config.h>
+
+#include <math.h>
+
+int
+totalorderl (long double const *x, long double const *y)
+{
+  /* Although the following is not strictly portable, and won't work
+     on some obsolete platforms (e.g., PA-RISC, MIPS before alignment
+     to IEEE 754-2008), it should be good enough nowadays.  */
+  int xs = signbit (*x);
+  int ys = signbit (*y);
+  if (!xs != !ys)
+    return xs;
+  int xn = isnanl (*x);
+  int yn = isnanl (*y);
+  if (!xn != !yn)
+    return !xn == !xs;
+  if (!xn)
+    return *x <= *y;
+
+  unsigned long long extended_sign = -!!xs;
+
+  if (sizeof (long double) <= sizeof (unsigned long long))
+    {
+      union { unsigned long long i; long double f; } volatile
+        xu = {0}, yu = {0};
+      xu.f = *x;
+      yu.f = *y;
+      return (xu.i ^ extended_sign) <= (yu.i ^ extended_sign);
+    }
+
+  union { unsigned long long i[2]; long double f; } volatile
+    xu = {0}, yu = {0}, zu = {0};
+  xu.f = *x;
+  yu.f = *y;
+  zu.f = -zu.f;
+  bool bigendian = !!zu.i[0];
+  unsigned long long
+    xhi = xu.i[!bigendian] ^ extended_sign,
+    yhi = yu.i[!bigendian] ^ extended_sign,
+    xlo = xu.i[ bigendian] ^ extended_sign,
+    ylo = yu.i[ bigendian] ^ extended_sign;
+  return (xhi < yhi) | ((xhi == yhi) & (xlo <= ylo));
+}
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index c214f8efa8..008dd6fa3b 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -50,7 +50,7 @@ AC_DEFUN_ONCE([gl_MATH_H],
      modf modff modfl powf
      remainder remainderf remainderl
      rint rintf rintl round roundf roundl sinf sinl sinhf sqrtf sqrtl
-     tanf tanl tanhf trunc truncf truncl])
+     tanf tanl tanhf totalorder totalorderf totalorderl trunc truncf truncl])
 ])
 
 # gl_MATH_MODULE_INDICATOR([modulename])
@@ -165,6 +165,9 @@ AC_DEFUN([gl_MATH_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TANF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TANL])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TANHF])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TOTALORDER])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TOTALORDERF])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TOTALORDERL])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TRUNC])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TRUNCF])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TRUNCL])
@@ -243,6 +246,9 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   HAVE_TANF=1;                      AC_SUBST([HAVE_TANF])
   HAVE_TANL=1;                      AC_SUBST([HAVE_TANL])
   HAVE_TANHF=1;                     AC_SUBST([HAVE_TANHF])
+  HAVE_TOTALORDER=1;                AC_SUBST([HAVE_TOTALORDER])
+  HAVE_TOTALORDERF=1;               AC_SUBST([HAVE_TOTALORDERF])
+  HAVE_TOTALORDERL=1;               AC_SUBST([HAVE_TOTALORDERL])
   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])
@@ -356,6 +362,9 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   REPLACE_SQRTL=0;                  AC_SUBST([REPLACE_SQRTL])
   REPLACE_TANF=0;                   AC_SUBST([REPLACE_TANF])
   REPLACE_TANHF=0;                  AC_SUBST([REPLACE_TANHF])
+  REPLACE_TOTALORDER=0;             AC_SUBST([REPLACE_TOTALORDER])
+  REPLACE_TOTALORDERF=0;            AC_SUBST([REPLACE_TOTALORDERF])
+  REPLACE_TOTALORDERL=0;            AC_SUBST([REPLACE_TOTALORDERL])
   REPLACE_TRUNC=0;                  AC_SUBST([REPLACE_TRUNC])
   REPLACE_TRUNCF=0;                 AC_SUBST([REPLACE_TRUNCF])
   REPLACE_TRUNCL=0;                 AC_SUBST([REPLACE_TRUNCL])
diff --git a/m4/mathfunc.m4 b/m4/mathfunc.m4
index 4cdd0a9001..00216ceae6 100644
--- a/m4/mathfunc.m4
+++ b/m4/mathfunc.m4
@@ -1,4 +1,4 @@
-# mathfunc.m4 serial 12
+# mathfunc.m4 serial 13
 dnl Copyright (C) 2010-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -40,10 +40,11 @@ AC_DEFUN([gl_MATHFUNC],
                                           [m4_bpatsubst(
                                              [m4_bpatsubst(
                                                 [$3],
-                                                [int \*], [&i_ret])],
-                                             [float \*], [&f_ret])],
-                                          [double \*], [&d_ret])],
-                                       [long double \*], [&l_ret])],
+                                                [int\( const\)? \*],
+                                                [&i_ret])],
+                                             [float\( const\)? \*], [&f_ret])],
+                                          [double\( const\)? \*], [&d_ret])],
+                                       [long double\( const\)? \*], [&l_ret])],
                                     [int], [2])],
                                  [float], [1.618034f])],
                               [long double], [1.618033988749894848L])],
diff --git a/m4/totalorder.m4 b/m4/totalorder.m4
new file mode 100644
index 0000000000..4d065dc0eb
--- /dev/null
+++ b/m4/totalorder.m4
@@ -0,0 +1,86 @@
+# totalorder.m4
+dnl Copyright 2023 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_TOTALORDERF],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+  gl_MATHFUNC([totalorderf], [int],
+    [(float const *, float const *)],
+    [extern
+     #ifdef __cplusplus
+     "C"
+     #endif
+     int totalorderf (float const *, float const *);
+    ])
+  AS_IF([test $gl_cv_func_totalorderf_no_libm != yes &&
+         test $gl_cv_func_totalorderf_in_libm != yes],
+    [gl_saved_LIBS=$LIBS
+     AC_SEARCH_LIBS([totalorderf], [m])
+     LIBS=$gl_saved_LIBS
+     if test "$ac_cv_search_totalorderf" = no; then
+       HAVE_TOTALORDERF=0
+     else
+       REPLACE_TOTALORDERF=1
+     fi
+     TOTALORDER_LIBM='$(ISNANF_LIBM)'])
+  AC_SUBST([TOTALORDERF_LIBM])
+])
+
+AC_DEFUN([gl_FUNC_TOTALORDER],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+  gl_MATHFUNC([totalorder], [int],
+    [(double const *, double const *)],
+    [extern
+     #ifdef __cplusplus
+     "C"
+     #endif
+     int totalorder (double const *, double const *);
+    ])
+  AS_IF([test $gl_cv_func_totalorder_no_libm != yes &&
+         test $gl_cv_func_totalorder_in_libm != yes],
+    [gl_saved_LIBS=$LIBS
+     AC_SEARCH_LIBS([totalorder], [m])
+     LIBS=$gl_saved_LIBS
+     if test "$ac_cv_search_totalorder" = no; then
+       HAVE_TOTALORDER=0
+     else
+       REPLACE_TOTALORDER=1
+     fi
+     TOTALORDER_LIBM='$(ISNAND_LIBM)'])
+  AC_SUBST([TOTALORDER_LIBM])
+])
+
+AC_DEFUN([gl_FUNC_TOTALORDERL],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+
+  gl_MATHFUNC([totalorderl], [int],
+    [(long double const *, long double const *)],
+    [extern
+     #ifdef __cplusplus
+     "C"
+     #endif
+     int totalorderl (long double const *, long double const *);
+    ])
+  AS_IF([test $gl_cv_func_totalorderl_no_libm != yes &&
+         test $gl_cv_func_totalorderl_in_libm != yes],
+    [gl_saved_LIBS=$LIBS
+     AC_SEARCH_LIBS([totalorderl], [m])
+     LIBS=$gl_saved_LIBS
+     if test "$ac_cv_search_totalorderl" = no; then
+       HAVE_TOTALORDERL=0
+     else
+       REPLACE_TOTALORDERL=1
+     fi
+     TOTALORDERL_LIBM='$(ISNANL_LIBM)'])
+  AC_SUBST([TOTALORDERL_LIBM])
+])
diff --git a/modules/math b/modules/math
index f107141533..f816d64cd2 100644
--- a/modules/math
+++ b/modules/math
@@ -132,6 +132,9 @@ math.h: math.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's/@''GNULIB_TRUNC''@/$(GNULIB_TRUNC)/g' \
              -e 's/@''GNULIB_TRUNCF''@/$(GNULIB_TRUNCF)/g' \
              -e 's/@''GNULIB_TRUNCL''@/$(GNULIB_TRUNCL)/g' \
+             -e 's/@''GNULIB_TOTALORDER''@/$(GNULIB_TOTALORDER)/g' \
+             -e 's/@''GNULIB_TOTALORDERF''@/$(GNULIB_TOTALORDERF)/g' \
+             -e 's/@''GNULIB_TOTALORDERL''@/$(GNULIB_TOTALORDERL)/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' \
@@ -200,6 +203,9 @@ math.h: math.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's|@''HAVE_TANF''@|$(HAVE_TANF)|g' \
              -e 's|@''HAVE_TANL''@|$(HAVE_TANL)|g' \
              -e 's|@''HAVE_TANHF''@|$(HAVE_TANHF)|g' \
+             -e 's|@''HAVE_TOTALORDER''@|$(HAVE_TOTALORDER)|g' \
+             -e 's|@''HAVE_TOTALORDERF''@|$(HAVE_TOTALORDERF)|g' \
+             -e 's|@''HAVE_TOTALORDERL''@|$(HAVE_TOTALORDERL)|g' \
              < $@-t2 > $@-t3
        $(AM_V_at)sed \
              -e 's|@''HAVE_DECL_ACOSL''@|$(HAVE_DECL_ACOSL)|g' \
@@ -320,6 +326,9 @@ math.h: math.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's|@''REPLACE_SQRTL''@|$(REPLACE_SQRTL)|g' \
              -e 's|@''REPLACE_TANF''@|$(REPLACE_TANF)|g' \
              -e 's|@''REPLACE_TANHF''@|$(REPLACE_TANHF)|g' \
+             -e 's|@''REPLACE_TOTALORDER''@|$(REPLACE_TOTALORDER)|g' \
+             -e 's|@''REPLACE_TOTALORDERF''@|$(REPLACE_TOTALORDERF)|g' \
+             -e 's|@''REPLACE_TOTALORDERL''@|$(REPLACE_TOTALORDERL)|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/totalorder b/modules/totalorder
new file mode 100644
index 0000000000..c74fa383b2
--- /dev/null
+++ b/modules/totalorder
@@ -0,0 +1,36 @@
+Description:
+totalorder function: total order on float
+
+Files:
+lib/totalorder.c
+m4/mathfunc.m4
+m4/totalorder.m4
+
+Depends-on:
+math
+extensions
+isnand          [test $HAVE_TOTALORDER = 0 || test $REPLACE_TOTALORDER = 0]
+signbit         [test $HAVE_TOTALORDER = 0 || test $REPLACE_TOTALORDER = 0]
+
+configure.ac:
+gl_FUNC_TOTALORDER
+gl_CONDITIONAL([GL_COND_OBJ_TOTALORDER],
+               [test $HAVE_TOTALORDER = 0 || test $REPLACE_TOTALORDER = 1])
+gl_MATH_MODULE_INDICATOR([totalorder])
+
+Makefile.am:
+if GL_COND_OBJ_TOTALORDER
+lib_SOURCES += totalorder.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(TOTALORDER_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
diff --git a/modules/totalorder-tests b/modules/totalorder-tests
new file mode 100644
index 0000000000..fbcfb11a99
--- /dev/null
+++ b/modules/totalorder-tests
@@ -0,0 +1,15 @@
+Files:
+tests/test-totalorder.c
+tests/minus-zero.h
+tests/infinity.h
+tests/nan.h
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-totalorder
+check_PROGRAMS += test-totalorder
+test_totalorder_LDADD = $(LDADD) @TOTALORDER_LIBM@
diff --git a/modules/totalorderf b/modules/totalorderf
new file mode 100644
index 0000000000..b3fb5d99e2
--- /dev/null
+++ b/modules/totalorderf
@@ -0,0 +1,36 @@
+Description:
+totalorderf function: total order on float
+
+Files:
+lib/totalorderf.c
+m4/mathfunc.m4
+m4/totalorder.m4
+
+Depends-on:
+math
+extensions
+isnanf          [test $HAVE_TOTALORDERF = 0 || test $REPLACE_TOTALORDERF = 0]
+signbit         [test $HAVE_TOTALORDERF = 0 || test $REPLACE_TOTALORDERF = 0]
+
+configure.ac:
+gl_FUNC_TOTALORDERF
+gl_CONDITIONAL([GL_COND_OBJ_TOTALORDERF],
+               [test $HAVE_TOTALORDERF = 0 || test $REPLACE_TOTALORDERF = 1])
+gl_MATH_MODULE_INDICATOR([totalorderf])
+
+Makefile.am:
+if GL_COND_OBJ_TOTALORDERF
+lib_SOURCES += totalorderf.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(TOTALORDERF_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
diff --git a/modules/totalorderf-tests b/modules/totalorderf-tests
new file mode 100644
index 0000000000..e76c9fda38
--- /dev/null
+++ b/modules/totalorderf-tests
@@ -0,0 +1,16 @@
+Files:
+tests/test-totalorderf.c
+tests/test-totalorder.c
+tests/minus-zero.h
+tests/infinity.h
+tests/nan.h
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-totalorderf
+check_PROGRAMS += test-totalorderf
+test_totalorderf_LDADD = $(LDADD) @TOTALORDERF_LIBM@
diff --git a/modules/totalorderl b/modules/totalorderl
new file mode 100644
index 0000000000..407b243bb3
--- /dev/null
+++ b/modules/totalorderl
@@ -0,0 +1,37 @@
+Description:
+totalorderl function: total order on long double
+
+Files:
+lib/totalorderl.c
+m4/mathfunc.m4
+m4/totalorder.m4
+
+Depends-on:
+math
+extensions
+stdbool         [test $HAVE_TOTALORDERL = 0 || test $REPLACE_TOTALORDERL = 0]
+isnanl          [test $HAVE_TOTALORDERL = 0 || test $REPLACE_TOTALORDERL = 0]
+signbit         [test $HAVE_TOTALORDERL = 0 || test $REPLACE_TOTALORDERL = 0]
+
+configure.ac:
+gl_FUNC_TOTALORDERL
+gl_CONDITIONAL([GL_COND_OBJ_TOTALORDERL],
+               [test $HAVE_TOTALORDERL = 0 || test $REPLACE_TOTALORDERL = 1])
+gl_MATH_MODULE_INDICATOR([totalorderl])
+
+Makefile.am:
+if GL_COND_OBJ_TOTALORDERL
+lib_SOURCES += totalorderl.c
+endif
+
+Include:
+<math.h>
+
+Link:
+$(TOTALORDERL_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+all
diff --git a/modules/totalorderl-tests b/modules/totalorderl-tests
new file mode 100644
index 0000000000..cfc50e21e9
--- /dev/null
+++ b/modules/totalorderl-tests
@@ -0,0 +1,16 @@
+Files:
+tests/test-totalorderl.c
+tests/test-totalorder.c
+tests/minus-zero.h
+tests/infinity.h
+tests/nan.h
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-totalorderl
+check_PROGRAMS += test-totalorderl
+test_totalorderl_LDADD = $(LDADD) @TOTALORDERL_LIBM@
diff --git a/tests/test-totalorder.c b/tests/test-totalorder.c
new file mode 100644
index 0000000000..1fc1b84568
--- /dev/null
+++ b/tests/test-totalorder.c
@@ -0,0 +1,57 @@
+/* Test totalorder.
+   Copyright 2023 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>
+
+#include <math.h>
+
+#include "infinity.h"
+#include "macros.h"
+#include "minus-zero.h"
+#include "nan.h"
+
+#ifndef TOTALORDER
+# define TOTALORDER totalorder
+# define TOTALORDER_INF Infinityd
+# define TOTALORDER_MINUS_ZERO minus_zerod
+# define TOTALORDER_NAN NaNd
+# define TOTALORDER_TYPE double
+#endif
+
+int
+main ()
+{
+  TOTALORDER_TYPE x[] =
+    {
+      -TOTALORDER_NAN (), -TOTALORDER_INF (), -1e37, -1, -1e-5,
+      TOTALORDER_MINUS_ZERO, 0,
+      1e-5, 1, 1e37, TOTALORDER_INF (), TOTALORDER_NAN ()
+    };
+  int n = sizeof x / sizeof *x;
+
+  /* TOTALORDER_NAN () yields a NaN of unknown sign, so fix the
+     first NaN to be negative and the last NaN to be nonnegative.
+     Do this via volatile accesses, to work around GCC bug 111655.  */
+  TOTALORDER_TYPE volatile a = x[0], z = x[n - 1];
+  if (! signbit (a)) a = -a;
+  if (  signbit (z)) z = -z;
+  x[0] = a, x[n - 1] = z;
+
+  for (int i = 0; i < n; i++)
+    for (int j = 0; j < n; j++)
+      ASSERT (!!TOTALORDER (&x[i], &x[j]) == (i <= j));
+  return 0;
+}
diff --git a/tests/test-totalorderf.c b/tests/test-totalorderf.c
new file mode 100644
index 0000000000..2dcb47aca4
--- /dev/null
+++ b/tests/test-totalorderf.c
@@ -0,0 +1,6 @@
+#define TOTALORDER totalorderf
+#define TOTALORDER_INF Infinityf
+#define TOTALORDER_MINUS_ZERO minus_zerof
+#define TOTALORDER_NAN NaNf
+#define TOTALORDER_TYPE float
+#include "test-totalorder.c"
diff --git a/tests/test-totalorderl.c b/tests/test-totalorderl.c
new file mode 100644
index 0000000000..ac454ad848
--- /dev/null
+++ b/tests/test-totalorderl.c
@@ -0,0 +1,6 @@
+#define TOTALORDER totalorderl
+#define TOTALORDER_INF Infinityl
+#define TOTALORDER_MINUS_ZERO minus_zerol
+#define TOTALORDER_NAN NaNl
+#define TOTALORDER_TYPE long double
+#include "test-totalorder.c"
-- 
2.41.0


Reply via email to