* doc/gnulib-tool.texi, doc/gnulib.texi: Mention it.
* doc/posix-headers/stdbit.texi, lib/stdbit.c, lib/stdbit.in.h:
* m4/stdbit_h.m4, modules/stdbit:
New files.
---
 ChangeLog                     |   8 +
 doc/gnulib-tool.texi          |   1 +
 doc/gnulib.texi               |   2 +
 doc/posix-headers/stdbit.texi |  25 ++
 lib/stdbit.c                  |   3 +
 lib/stdbit.in.h               | 640 ++++++++++++++++++++++++++++++++++
 m4/stdbit_h.m4                |  19 +
 modules/stdbit                |  44 +++
 8 files changed, 742 insertions(+)
 create mode 100644 doc/posix-headers/stdbit.texi
 create mode 100644 lib/stdbit.c
 create mode 100644 lib/stdbit.in.h
 create mode 100644 m4/stdbit_h.m4
 create mode 100644 modules/stdbit

diff --git a/ChangeLog b/ChangeLog
index da40ff41de..1019917f36 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2024-05-11  Paul Eggert  <egg...@cs.ucla.edu>
+
+       stdbit: new module
+       * doc/gnulib-tool.texi, doc/gnulib.texi: Mention it.
+       * doc/posix-headers/stdbit.texi, lib/stdbit.c, lib/stdbit.in.h:
+       * m4/stdbit_h.m4, modules/stdbit:
+       New files.
+
 2024-05-11  Bruno Haible  <br...@clisp.org>
 
        doc: Mention module execinfo.
diff --git a/doc/gnulib-tool.texi b/doc/gnulib-tool.texi
index 9ed30c2055..5a2fd19cac 100644
--- a/doc/gnulib-tool.texi
+++ b/doc/gnulib-tool.texi
@@ -585,6 +585,7 @@ This is true for the following POSIX or ISO C standardized 
header files:
 @item @code{spawn.h}
 @item @code{stdalign.h}
 @item @code{stdarg.h}
+@item @code{stdbit.h}
 @item @code{stddef.h}
 @item @code{stdint.h}
 @item @code{stdio.h}
diff --git a/doc/gnulib.texi b/doc/gnulib.texi
index 55cf6ebcc9..6cbd10619e 100644
--- a/doc/gnulib.texi
+++ b/doc/gnulib.texi
@@ -1082,6 +1082,7 @@ which (known) portability problems are not worked around 
by Gnulib.
 * stdalign.h::
 * stdarg.h::
 * stdatomic.h::
+* stdbit.h::
 * stdbool.h::
 * stdckdint.h::
 * stddef.h::
@@ -1174,6 +1175,7 @@ which (known) portability problems are not worked around 
by Gnulib.
 @include posix-headers/stdalign.texi
 @include posix-headers/stdarg.texi
 @include posix-headers/stdatomic.texi
+@include posix-headers/stdbit.texi
 @include posix-headers/stdbool.texi
 @include posix-headers/stdckdint.texi
 @include posix-headers/stddef.texi
diff --git a/doc/posix-headers/stdbit.texi b/doc/posix-headers/stdbit.texi
new file mode 100644
index 0000000000..8870668a59
--- /dev/null
+++ b/doc/posix-headers/stdbit.texi
@@ -0,0 +1,25 @@
+@node stdbit.h
+@section @file{stdbit.h}
+
+Gnulib module: stdbit
+
+Portability problems fixed by Gnulib:
+@itemize
+@item
+This header file is missing on many non-C23 platforms:
+glibc 2.38, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5,
+AIX 7.3, HP-UX 11.31, Solaris 11.4, mingw, MSVC 17, Android 15.
+@end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
+@item
+On older non-C23 platforms lacking @code{typeof} or equivalent, a call
+to @code{stdc_bit_floor} and @code{stdc_bit_ceil} may yield a type
+that is wider than its argument.  Although C23 seems to allow this,
+it differs from GNU behavior.
+
+@item
+On non-C23 platforms, type-generic functions apply portably only to
+the standard unsigned integer types specified by C17 or earlier.
+@end itemize
diff --git a/lib/stdbit.c b/lib/stdbit.c
new file mode 100644
index 0000000000..0346ec095c
--- /dev/null
+++ b/lib/stdbit.c
@@ -0,0 +1,3 @@
+#include <config.h>
+#define _GL_STDBIT_INLINE _GL_EXTERN_INLINE
+#include <stdbit.h>
diff --git a/lib/stdbit.in.h b/lib/stdbit.in.h
new file mode 100644
index 0000000000..a2fff04772
--- /dev/null
+++ b/lib/stdbit.in.h
@@ -0,0 +1,640 @@
+/* stdbit.h - C23 bit and byte utilities for non-C23 platforms
+
+   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 2.1 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.  */
+
+#ifndef STDBIT_H
+#define STDBIT_H 1
+
+/* This file uses _GL_INLINE, WORDS_BIGENDIAN.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
+#include <count-leading-zeros.h>
+#include <count-trailing-zeros.h>
+#include <count-one-bits.h>
+
+/* An expression, preferably with the type of A, that has the value of B.  */
+#if ((defined __GNUC__ && 2 <= __GNUC__) \
+     || (defined __clang_major__ && 4 <= __clang_major__) \
+     || (defined __IBMC__ && 1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
+     || (defined __SUNPRO_C && 0x5110 <= __SUNPRO_C && !__STDC__))
+# define _GL_STDBIT_TYPEOF_CAST(a, b) ((__typeof__ (a)) (b))
+#elif 202311 <= __STDC_VERSION__
+# define _GL_STDBIT_TYPEOF_CAST(a, b) ((typeof (a)) (b))
+#else
+/* This platform is so old that it lacks typeof, so _Generic is likely
+   missing or unreliable.  The C23 standard seems to allow yielding B
+   (which is always unsigned long long int), so do that.  */
+# define _GL_STDBIT_TYPEOF_CAST(a, b) (b)
+#endif
+
+#define __STDC_VERSION_STDBIT_H__ 202311L
+
+#define __STDC_ENDIAN_BIG__ 4321
+#define __STDC_ENDIAN_LITTLE__ 1234
+#ifdef WORDS_BIGENDIAN
+# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_BIG__
+#else
+# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_LITTLE__
+#endif
+
+_GL_INLINE_HEADER_BEGIN
+#ifndef _GL_STDBIT_INLINE
+# define _GL_STDBIT_INLINE _GL_INLINE
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_uc (unsigned char n)
+{
+  return count_leading_zeros (n) - 8 * (sizeof 0u - sizeof n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_us (unsigned short int n)
+{
+  return count_leading_zeros (n) - 8 * (sizeof 0u - sizeof n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_ui (unsigned int n)
+{
+  return count_leading_zeros (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_ul (unsigned long int n)
+{
+  return count_leading_zeros_l (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_ull (unsigned long long int n)
+{
+  return count_leading_zeros_ll (n);
+}
+
+#define stdc_leading_zeros(n) \
+  (sizeof (n) == 1 ? stdc_leading_zeros_uc (n) \
+   : sizeof (n) == sizeof (unsigned short int) ? stdc_leading_zeros_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_leading_zeros_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_leading_zeros_ul (n) \
+   : stdc_leading_zeros_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_uc (unsigned char n)
+{
+  unsigned int ui = n;
+  return count_leading_zeros (~(ui << 8 * (sizeof ui - sizeof n)));
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_us (unsigned short int n)
+{
+  unsigned int ui = n;
+  return count_leading_zeros (~(ui << 8 * (sizeof ui - sizeof n)));
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_ui (unsigned int n)
+{
+  return count_leading_zeros (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_ul (unsigned long int n)
+{
+  return count_leading_zeros_l (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_ull (unsigned long long int n)
+{
+  return count_leading_zeros_ll (~n);
+}
+
+#define stdc_leading_ones(n) \
+  (sizeof (n) == 1 ? stdc_leading_ones_uc (n)  \
+   : sizeof (n) == sizeof (unsigned short int) ? stdc_leading_ones_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_leading_ones_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_leading_ones_ul (n) \
+   : stdc_leading_ones_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_uc (unsigned char n)
+{
+  return count_trailing_zeros (n | (1 + (unsigned char) -1));
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_us (unsigned short int n)
+{
+  return count_trailing_zeros (n | (1 + (unsigned short int) -1));
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_ui (unsigned int n)
+{
+  return count_trailing_zeros (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_ul (unsigned long int n)
+{
+  return count_trailing_zeros_l (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_ull (unsigned long long int n)
+{
+  return count_trailing_zeros_ll (n);
+}
+
+#define stdc_trailing_zeros(n) \
+  (sizeof (n) == 1 ? stdc_trailing_zeros_uc (n)        \
+   : sizeof (n) == sizeof (unsigned short int) ? stdc_trailing_zeros_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_trailing_zeros_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_trailing_zeros_ul (n) \
+   : stdc_trailing_zeros_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_uc (unsigned char n)
+{
+  unsigned int ui = n;
+  return count_trailing_zeros (~ui);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_us (unsigned short int n)
+{
+  unsigned int ui = n;
+  return count_trailing_zeros (~ui);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_ui (unsigned int n)
+{
+  return count_trailing_zeros (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_ul (unsigned long int n)
+{
+  return count_trailing_zeros_l (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_ull (unsigned long long int n)
+{
+  return count_trailing_zeros_ll (~n);
+}
+
+#define stdc_trailing_ones(n) \
+  (sizeof (n) == 1 ? stdc_trailing_ones_uc (n) \
+   : sizeof (n) == sizeof (unsigned short int) ? stdc_trailing_ones_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_trailing_ones_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_trailing_ones_ul (n) \
+   : stdc_trailing_ones_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_zero_uc (unsigned char n)
+{
+  unsigned int count = stdc_leading_ones_uc (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_zero_us (unsigned short int n)
+{
+  unsigned int count = stdc_leading_ones_us (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_zero_ui (unsigned int n)
+{
+  unsigned int count = stdc_leading_ones_ui (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_zero_ul (unsigned long int n)
+{
+  unsigned int count = stdc_leading_ones_ul (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_zero_ull (unsigned long long int n)
+{
+  unsigned int count = stdc_leading_ones_ull (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+#define stdc_first_leading_zero(n) \
+  (sizeof (n) == 1 ? stdc_first_leading_zero_uc (n) \
+   : sizeof (n) == sizeof (unsigned short) ? stdc_first_leading_zero_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_first_leading_zero_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_first_leading_zero_ul (n) \
+   : stdc_first_leading_zero_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_one_uc (unsigned char n)
+{
+  unsigned int count = stdc_leading_zeros_uc (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_one_us (unsigned short int n)
+{
+  unsigned int count = stdc_leading_zeros_us (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_one_ui (unsigned int n)
+{
+  unsigned int count = stdc_leading_zeros_ui (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_one_ul (unsigned long int n)
+{
+  unsigned int count = stdc_leading_zeros_ul (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_one_ull (unsigned long long int n)
+{
+  unsigned int count = stdc_leading_zeros_ull (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+#define stdc_first_leading_one(n) \
+  (sizeof (n) == 1 ? stdc_first_leading_one_uc (n) \
+   : sizeof (n) == sizeof (unsigned short) ? stdc_first_leading_one_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_first_leading_one_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_first_leading_one_ul (n) \
+   : stdc_first_leading_one_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_zero_uc (unsigned char n)
+{
+  unsigned int count = stdc_trailing_ones_uc (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_zero_us (unsigned short int n)
+{
+  unsigned int count = stdc_trailing_ones_us (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_zero_ui (unsigned int n)
+{
+  unsigned int count = stdc_trailing_ones_ui (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_zero_ul (unsigned long int n)
+{
+  unsigned int count = stdc_trailing_ones_ul (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_zero_ull (unsigned long long int n)
+{
+  unsigned int count = stdc_trailing_ones_ull (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+#define stdc_first_trailing_zero(n) \
+  (sizeof (n) == 1 ? stdc_first_trailing_zero_uc (n) \
+   : sizeof (n) == sizeof (unsigned short) ? stdc_first_trailing_zero_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_first_trailing_zero_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_first_trailing_zero_ul (n) \
+   : stdc_first_trailing_zero_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_one_uc (unsigned char n)
+{
+  unsigned int count = stdc_trailing_zeros_uc (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_one_us (unsigned short int n)
+{
+  unsigned int count = stdc_trailing_zeros_us (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_one_ui (unsigned int n)
+{
+  unsigned int count = stdc_trailing_zeros_ui (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_one_ul (unsigned long int n)
+{
+  unsigned int count = stdc_trailing_zeros_ul (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_trailing_one_ull (unsigned long long int n)
+{
+  unsigned int count = stdc_trailing_zeros_ull (n);
+  return count == 8 * sizeof n ? 0 : count + 1;
+}
+
+#define stdc_first_trailing_one(n) \
+  (sizeof (n) == 1 ? stdc_first_trailing_one_uc (n) \
+   : sizeof (n) == sizeof (unsigned short) ? stdc_first_trailing_one_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_first_trailing_one_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_first_trailing_one_ul (n) \
+   : stdc_first_trailing_one_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_uc (unsigned char n)
+{
+  unsigned int ui = n;
+  return count_one_bits (~ui) - 8 * (sizeof ui - sizeof n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_us (unsigned short int n)
+{
+  unsigned int ui = n;
+  return count_one_bits (~ui) - 8 * (sizeof ui - sizeof n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_ui (unsigned int n)
+{
+  return count_one_bits (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_ul (unsigned long int n)
+{
+  return count_one_bits_l (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_ull (unsigned long long int n)
+{
+  return count_one_bits_ll (~n);
+}
+
+#define stdc_count_zeros(n) \
+  (sizeof (n) == 1 ? stdc_count_zeros_uc (n) \
+   : sizeof (n) == sizeof (unsigned short int) ? stdc_count_zeros_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_count_zeros_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_count_zeros_ul (n) \
+   : stdc_count_zeros_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_ones_uc (unsigned char n)
+{
+  return count_one_bits (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_ones_us (unsigned short int n)
+{
+  return count_one_bits (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_ones_ui (unsigned int n)
+{
+  return count_one_bits (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_ones_ul (unsigned long int n)
+{
+  return count_one_bits_l (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_ones_ull (unsigned long long int n)
+{
+  return count_one_bits_ll (n);
+}
+
+#define stdc_count_ones(n) \
+  (sizeof (n) == 1 ? stdc_count_ones_uc (n) \
+   : sizeof (n) == sizeof (unsigned short int) ? stdc_count_ones_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_count_ones_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_count_ones_ul (n) \
+   : stdc_count_ones_ull (n))
+
+
+_GL_STDBIT_INLINE bool
+stdc_has_single_bit_uc (unsigned char n)
+{
+  unsigned char n_1 = n - 1, nx = n_1 ^ n;
+  return n_1 < nx;
+}
+
+_GL_STDBIT_INLINE bool
+stdc_has_single_bit_us (unsigned short int n)
+{
+  unsigned short int n_1 = n - 1, nx = n_1 ^ n;
+  return n_1 < nx;
+}
+
+_GL_STDBIT_INLINE bool
+stdc_has_single_bit_ui (unsigned int n)
+{
+  unsigned int n_1 = n - 1, nx = n_1 ^ n;
+  return n_1 < nx;
+}
+
+_GL_STDBIT_INLINE bool
+stdc_has_single_bit_ul (unsigned long int n)
+{
+  unsigned long int n_1 = n - 1, nx = n_1 ^ n;
+  return n_1 < nx;
+}
+
+_GL_STDBIT_INLINE bool
+stdc_has_single_bit_ull (unsigned long long int n)
+{
+  unsigned long long int n_1 = n - 1, nx = n_1 ^ n;
+  return n_1 < nx;
+}
+
+#define stdc_has_single_bit(n) \
+  ((bool) \
+   (sizeof (n) == 1 ? stdc_has_single_bit_uc (n) \
+    : sizeof (n) == sizeof (unsigned short int) ? stdc_has_single_bit_us (n) \
+    : sizeof (n) == sizeof 0u ? stdc_has_single_bit_ui (n) \
+    : sizeof (n) == sizeof 0ul ? stdc_has_single_bit_ul (n) \
+    : stdc_has_single_bit_ull (n)))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_bit_width_uc (unsigned char n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_uc (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_bit_width_us (unsigned short int n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_us (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_bit_width_ui (unsigned int n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_ui (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_bit_width_ul (unsigned long int n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_ul (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_bit_width_ull (unsigned long long int n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_ull (n);
+}
+
+#define stdc_bit_width(n) \
+  (sizeof (n) == 1 ? stdc_bit_width_uc (n) \
+   : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_width_us (n) \
+   : sizeof (n) == sizeof 0u ? stdc_bit_width_ui (n) \
+   : sizeof (n) == sizeof 0ul ? stdc_bit_width_ul (n) \
+   : stdc_bit_width_ull (n))
+
+
+_GL_STDBIT_INLINE unsigned char
+stdc_bit_floor_uc (unsigned char n)
+{
+  return n ? 1u << (stdc_bit_width_uc (n) - 1) : 0;
+}
+
+_GL_STDBIT_INLINE unsigned short int
+stdc_bit_floor_us (unsigned short int n)
+{
+  return n ? 1u << (stdc_bit_width_us (n) - 1) : 0;
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_bit_floor_ui (unsigned int n)
+{
+  return n ? 1u << (stdc_bit_width_ui (n) - 1) : 0;
+}
+
+_GL_STDBIT_INLINE unsigned long int
+stdc_bit_floor_ul (unsigned long int n)
+{
+  return n ? 1ul << (stdc_bit_width_ul (n) - 1) : 0;
+}
+
+_GL_STDBIT_INLINE unsigned long long int
+stdc_bit_floor_ull (unsigned long long int n)
+{
+  return n ? 1ull << (stdc_bit_width_ull (n) - 1) : 0;
+}
+
+#define stdc_bit_floor(n) \
+  (_GL_STDBIT_TYPEOF_CAST \
+   (n, \
+    (sizeof (n) == 1 ? stdc_bit_floor_uc (n) \
+     : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_floor_us (n) \
+     : sizeof (n) == sizeof 0u ? stdc_bit_floor_ui (n) \
+     : sizeof (n) == sizeof 0ul ? stdc_bit_floor_ul (n) \
+     : stdc_bit_floor_ull (n))))
+
+
+_GL_STDBIT_INLINE unsigned char
+stdc_bit_ceil_uc (unsigned char n)
+{
+  return n <= 1 ? 1 : 2u << (stdc_bit_width_uc (n - 1) - 1);
+}
+
+_GL_STDBIT_INLINE unsigned short int
+stdc_bit_ceil_us (unsigned short int n)
+{
+  return n <= 1 ? 1 : 2u << (stdc_bit_width_us (n - 1) - 1);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_bit_ceil_ui (unsigned int n)
+{
+  return n <= 1 ? 1 : 2u << (stdc_bit_width_ui (n - 1) - 1);
+}
+
+_GL_STDBIT_INLINE unsigned long int
+stdc_bit_ceil_ul (unsigned long int n)
+{
+  return n <= 1 ? 1 : 2ul << (stdc_bit_width_ul (n - 1) - 1);
+}
+
+_GL_STDBIT_INLINE unsigned long long int
+stdc_bit_ceil_ull (unsigned long long int n)
+{
+  return n <= 1 ? 1 : 2ull << (stdc_bit_width_ull (n - 1) - 1);
+}
+
+#define stdc_bit_ceil(n) \
+  (_GL_STDBIT_TYPEOF_CAST \
+   (n, \
+    (sizeof (n) == 1 ? stdc_bit_ceil_uc (n) \
+     : sizeof (n) == sizeof (unsigned short int) ? stdc_bit_ceil_us (n) \
+     : sizeof (n) == sizeof 0u ? stdc_bit_ceil_ui (n) \
+     : sizeof (n) == sizeof 0ul ? stdc_bit_ceil_ul (n) \
+     : stdc_bit_ceil_ull (n))))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+_GL_INLINE_HEADER_END
+
+#endif /* STDBIT_H */
diff --git a/m4/stdbit_h.m4 b/m4/stdbit_h.m4
new file mode 100644
index 0000000000..9ce3cb3146
--- /dev/null
+++ b/m4/stdbit_h.m4
@@ -0,0 +1,19 @@
+# stddef_h.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.
+
+dnl A placeholder for <stdbit.h>, for platforms that have issues.
+
+AC_DEFUN_ONCE([gl_STDBIT_H],
+[
+  AC_REQUIRE([gl_BIGENDIAN])
+  AC_CHECK_HEADERS_ONCE([stdbit.h])
+  if test $ac_cv_header_stdbit_h = yes; then
+    GL_GENERATE_STDBIT_H=false
+  else
+    GL_GENERATE_STDBIT_H=true
+  fi
+])
diff --git a/modules/stdbit b/modules/stdbit
new file mode 100644
index 0000000000..6096869774
--- /dev/null
+++ b/modules/stdbit
@@ -0,0 +1,44 @@
+Description:
+A stdbit.h that is like C23.
+
+Files:
+lib/stdbit.c
+lib/stdbit.in.h
+m4/stdbit_h.m4
+
+Depends-on:
+count-leading-zeros    [$GL_GENERATE_STDBIT_H]
+count-trailing-zeros   [$GL_GENERATE_STDBIT_H]
+count-one-bits         [$GL_GENERATE_STDBIT_H]
+stdbool                 [$GL_GENERATE_STDBIT_H]
+
+configure.ac:
+gl_STDBIT_H
+gl_CONDITIONAL_HEADER([stdbit.h])
+AC_PROG_MKDIR_P
+
+Makefile.am:
+BUILT_SOURCES += $(STDBIT_H)
+
+# We need the following in order to create <stdbit.h> when the system
+# doesn't have one that works with the given compiler.
+if GL_GENERATE_STDBIT_H
+stdbit.h: stdbit.in.h $(top_builddir)/config.status
+@NMD@  $(AM_V_GEN)$(MKDIR_P) '%reldir%'
+       $(gl_V_at)cp $(srcdir)/stdbit.in.h $@-t
+       $(AM_V_at)mv $@-t $@
+lib_SOURCES += stdbit.c
+else
+stdbit.h: $(top_builddir)/config.status
+       rm -f $@
+endif
+MOSTLYCLEANFILES += stdbit.h stdbit.h-t
+
+Include:
+<stdbit.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
-- 
2.44.0


Reply via email to