]> git.eshelyaron.com Git - emacs.git/commitdiff
Prefer stdbit.h to count-one-bits.h etc
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 12 May 2024 21:22:58 +0000 (14:22 -0700)
committerEshel Yaron <me@eshelyaron.com>
Sat, 18 May 2024 19:12:38 +0000 (21:12 +0200)
C23's <stdbit.h> in the long run should be better supported than
Gnulib's count-one-bits.h and similar headers, so switch to the
C23 primitives, with a Gnulib fallback for platforms lacking C23.
* admin/merge-gnulib (GNULIB_MODULES): Remove count-leading-zeros,
count-one-bits, count-trailing-zeros.  Add stdc_bit_width,
stdc_count_ones, stdc_trailing_zeros.
* lib/count-leading-zeros.c, lib/count-leading-zeros.h:
* lib/count-one-bits.c, lib/count-one-bits.h:
* lib/count-trailing-zeros.c, lib/count-trailing-zeros.h: Remove.
* lib/stdbit.c, lib/stdbit.in.h, lib/stdc_bit_width.c:
* lib/stdc_count_ones.c, lib/stdc_leading_zeros.c:
* lib/stdc_trailing_zeros.c, m4/stdbit_h.m4:
New files, copied from Gnulib.
* lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate.
* src/data.c: Do not include count-one-bits.h, count-trailing-zeros.h.
Instead, rely on lisp.h including stdbit.h.
(Flogcount, Fbool_vector_count_population)
(Fbool_vector_count_consecutive): Use stdbit.h macros instead of
count-one-bits.h and count-trailing-zeros.h macros.
(shift_right_ull, count_one_bits_word, pre_value)
(count_trailing_zero_bits): Remove; no longer needed.
* src/lisp.h: Include stdbit.h instead of count-leading-zeros.h.
(elogb): Use stdbit.h macro instead of count-leading-zeros.h macro.

(cherry picked from commit 88b0bb4db9aaecff8b01e81726b911fa5d02b2fb)

19 files changed:
INSTALL.REPO
admin/merge-gnulib
lib/count-leading-zeros.c [deleted file]
lib/count-leading-zeros.h [deleted file]
lib/count-one-bits.c [deleted file]
lib/count-one-bits.h [deleted file]
lib/count-trailing-zeros.c [deleted file]
lib/count-trailing-zeros.h [deleted file]
lib/gnulib.mk.in
lib/stdbit.c [new file with mode: 0644]
lib/stdbit.in.h [new file with mode: 0644]
lib/stdc_bit_width.c [new file with mode: 0644]
lib/stdc_count_ones.c [new file with mode: 0644]
lib/stdc_leading_zeros.c [new file with mode: 0644]
lib/stdc_trailing_zeros.c [new file with mode: 0644]
m4/gnulib-comp.m4
m4/stdbit_h.m4 [new file with mode: 0644]
src/data.c
src/lisp.h

index 77d8153a5a8841be9ddc329e951361e0f18e9ab6..46ac4440aee690f33e644fceb47c7d50dc37d098 100644 (file)
@@ -80,7 +80,7 @@ handle.  The most thorough cleaning can be achieved by 'git clean -fdx'
 which will leave you with only files from the git repository.  Here
 are some faster methods for a couple of particular error cases:
 
-    /usr/bin/m4:aclocal.m4:9: cannot open `m4/count-leading-zeros.m4': No such file or directory
+    /usr/bin/m4:aclocal.m4:9: cannot open `m4/stdbit_h.m4': No such file or directory
 
 This can be fixed with 'rm aclocal.m4'.
 
index c4daaded0156ee7b74f5fcfe11cd74203ae971c7..65e098c712390ba17c8512f509a2a62c1434508a 100755 (executable)
@@ -29,7 +29,6 @@ GNULIB_MODULES='
   alignasof alloca-opt binary-io boot-time byteswap c-ctype c-strcase
   canonicalize-lgpl
   careadlinkat close-stream copy-file-range
-  count-leading-zeros count-one-bits count-trailing-zeros
   crypto/md5 crypto/md5-buffer
   crypto/sha1-buffer crypto/sha256-buffer crypto/sha512-buffer
   d-type diffseq double-slash-root dtoastr dtotimespec dup2
@@ -44,7 +43,9 @@ GNULIB_MODULES='
   nanosleep nproc nstrftime
   pathmax pipe2 pselect pthread_sigmask
   qcopy-acl readlink readlinkat regex
-  sig2str sigdescr_np socklen stat-time std-gnu11 stdbool stdckdint stddef stdio
+  sig2str sigdescr_np socklen stat-time std-gnu11 stdbool
+  stdc_bit_width stdc_count_ones stdc_trailing_zeros
+  stdckdint stddef stdio
   stpcpy strnlen strnlen strtoimax symlink sys_stat sys_time
   tempname time-h time_r time_rz timegm timer-time timespec-add timespec-sub
   update-copyright unlocked-io utimensat
diff --git a/lib/count-leading-zeros.c b/lib/count-leading-zeros.c
deleted file mode 100644 (file)
index 2bbfd67..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Count the number of leading 0 bits in a word.
-
-   Copyright (C) 2012-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/>.  */
-
-#include <config.h>
-
-#define COUNT_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE
-#include "count-leading-zeros.h"
diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h
deleted file mode 100644 (file)
index a4b68c2..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/* count-leading-zeros.h -- counts the number of leading 0 bits in a word.
-   Copyright (C) 2012-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 Eric Blake.  */
-
-#ifndef COUNT_LEADING_ZEROS_H
-#define COUNT_LEADING_ZEROS_H 1
-
-/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE.  */
-#if !_GL_CONFIG_H_INCLUDED
- #error "Please include config.h first."
-#endif
-
-#include <limits.h>
-#include <stdlib.h>
-
-_GL_INLINE_HEADER_BEGIN
-#ifndef COUNT_LEADING_ZEROS_INLINE
-# define COUNT_LEADING_ZEROS_INLINE _GL_INLINE
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
-   expand to code that computes the number of leading zeros of the local
-   variable 'x' of type TYPE (an unsigned integer type) and return it
-   from the current function.  */
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \
-    || (__clang_major__ >= 4)
-# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)                \
-  return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
-#elif _MSC_VER
-extern unsigned char _BitScanReverse (unsigned long *, unsigned long);
-# pragma intrinsic (_BitScanReverse)
-# if defined _M_X64
-extern unsigned char _BitScanReverse64 (unsigned long *, unsigned long long);
-#  pragma intrinsic (_BitScanReverse64)
-# endif
-# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)                \
-    do                                                                  \
-      {                                                                 \
-        unsigned long result;                                           \
-        if (MSC_BUILTIN (&result, x))                                   \
-          return CHAR_BIT * sizeof x - 1 - result;                      \
-        return CHAR_BIT * sizeof x;                                     \
-      }                                                                 \
-    while (0)
-#else
-# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)                \
-    do                                                                  \
-      {                                                                 \
-        int count;                                                      \
-        unsigned int leading_32;                                        \
-        if (! x)                                                        \
-          return CHAR_BIT * sizeof x;                                   \
-        for (count = 0;                                                 \
-             (leading_32 = ((x >> (sizeof (TYPE) * CHAR_BIT - 32))      \
-                            & 0xffffffffU),                             \
-              count < CHAR_BIT * sizeof x - 32 && !leading_32);         \
-             count += 32)                                               \
-          x = x << 31 << 1;                                             \
-        return count + count_leading_zeros_32 (leading_32);             \
-      }                                                                 \
-    while (0)
-
-/* Compute and return the number of leading zeros in X,
-   where 0 < X < 2**32.  */
-COUNT_LEADING_ZEROS_INLINE int
-count_leading_zeros_32 (unsigned int x)
-{
-  /* <https://github.com/gibsjose/BitHacks>
-     <https://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
-  static const char de_Bruijn_lookup[32] = {
-    31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,
-    23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0
-  };
-
-  x |= x >> 1;
-  x |= x >> 2;
-  x |= x >> 4;
-  x |= x >> 8;
-  x |= x >> 16;
-  return de_Bruijn_lookup[((x * 0x07c4acddU) & 0xffffffffU) >> 27];
-}
-#endif
-
-/* Compute and return the number of leading zeros in X. */
-COUNT_LEADING_ZEROS_INLINE int
-count_leading_zeros (unsigned int x)
-{
-  COUNT_LEADING_ZEROS (__builtin_clz, _BitScanReverse, unsigned int);
-}
-
-/* Compute and return the number of leading zeros in X. */
-COUNT_LEADING_ZEROS_INLINE int
-count_leading_zeros_l (unsigned long int x)
-{
-  COUNT_LEADING_ZEROS (__builtin_clzl, _BitScanReverse, unsigned long int);
-}
-
-/* Compute and return the number of leading zeros in X. */
-COUNT_LEADING_ZEROS_INLINE int
-count_leading_zeros_ll (unsigned long long int x)
-{
-#if (defined _MSC_VER && !defined __clang__) && !defined _M_X64
-  /* 32-bit MSVC does not have _BitScanReverse64, only _BitScanReverse.  */
-  unsigned long result;
-  if (_BitScanReverse (&result, (unsigned long) (x >> 32)))
-    return CHAR_BIT * sizeof x - 1 - 32 - result;
-  if (_BitScanReverse (&result, (unsigned long) x))
-    return CHAR_BIT * sizeof x - 1 - result;
-  return CHAR_BIT * sizeof x;
-#else
-  COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64,
-                       unsigned long long int);
-#endif
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-_GL_INLINE_HEADER_END
-
-#endif /* COUNT_LEADING_ZEROS_H */
diff --git a/lib/count-one-bits.c b/lib/count-one-bits.c
deleted file mode 100644 (file)
index 54b8708..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Count the number of 1-bits in a word.
-
-   Copyright (C) 2012-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/>.  */
-
-#include <config.h>
-
-#define COUNT_ONE_BITS_INLINE _GL_EXTERN_INLINE
-#include "count-one-bits.h"
-
-#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
-int popcount_support = -1;
-#endif
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
deleted file mode 100644 (file)
index 24bf8cc..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/* count-one-bits.h -- counts the number of 1-bits in a word.
-   Copyright (C) 2007-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 Ben Pfaff.  */
-
-#ifndef COUNT_ONE_BITS_H
-#define COUNT_ONE_BITS_H 1
-
-/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE.  */
-#if !_GL_CONFIG_H_INCLUDED
- #error "Please include config.h first."
-#endif
-
-#include <limits.h>
-#include <stdlib.h>
-
-_GL_INLINE_HEADER_BEGIN
-#ifndef COUNT_ONE_BITS_INLINE
-# define COUNT_ONE_BITS_INLINE _GL_INLINE
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Assuming the GCC builtin is GCC_BUILTIN and the MSC builtin is MSC_BUILTIN,
-   expand to code that computes the number of 1-bits of the local
-   variable 'x' of type TYPE (an unsigned integer type) and return it
-   from the current function.  */
-#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
-    || (__clang_major__ >= 4)
-# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
-    return GCC_BUILTIN (x)
-#else
-
-/* Compute and return the number of 1-bits set in the least
-   significant 32 bits of X. */
-COUNT_ONE_BITS_INLINE int
-count_one_bits_32 (unsigned int x)
-{
-  x = ((x & 0xaaaaaaaaU) >> 1) + (x & 0x55555555U);
-  x = ((x & 0xccccccccU) >> 2) + (x & 0x33333333U);
-  x = (x >> 16) + (x & 0xffff);
-  x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f);
-  return (x >> 8) + (x & 0x00ff);
-}
-
-/* Expand to code that computes the number of 1-bits of the local
-   variable 'x' of type TYPE (an unsigned integer type) and return it
-   from the current function.  */
-# define COUNT_ONE_BITS_GENERIC(TYPE)                                   \
-    do                                                                  \
-      {                                                                 \
-        int count = 0;                                                  \
-        int bits;                                                       \
-        for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32)     \
-          {                                                             \
-            count += count_one_bits_32 (x);                             \
-            x = x >> 31 >> 1;                                           \
-          }                                                             \
-        return count;                                                   \
-      }                                                                 \
-    while (0)
-
-# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
-
-/* While gcc falls back to its own generic code if the machine
-   on which it's running doesn't support popcount, with Microsoft's
-   compiler we need to detect and fallback ourselves.  */
-
-#  if 0
-#   include <intrin.h>
-#  else
-    /* Don't pollute the namespace with too many MSVC intrinsics.  */
-extern void __cpuid (int[4], int);
-#   pragma intrinsic (__cpuid)
-extern unsigned int __popcnt (unsigned int);
-#   pragma intrinsic (__popcnt)
-#   if defined _M_X64
-extern unsigned long long __popcnt64 (unsigned long long);
-#    pragma intrinsic (__popcnt64)
-#   endif
-#  endif
-
-#  if !defined _M_X64
-static inline __popcnt64 (unsigned long long x)
-{
-  return __popcnt ((unsigned int) (x >> 32)) + __popcnt ((unsigned int) x);
-}
-#  endif
-
-/* Return nonzero if popcount is supported.  */
-
-/* 1 if supported, 0 if not supported, -1 if unknown.  */
-extern int popcount_support;
-
-COUNT_ONE_BITS_INLINE int
-popcount_supported (void)
-{
-  if (popcount_support < 0)
-    {
-      /* Do as described in
-         <https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64> */
-      int cpu_info[4];
-      __cpuid (cpu_info, 1);
-      popcount_support = (cpu_info[2] >> 23) & 1;
-    }
-  return popcount_support;
-}
-
-#  define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
-     do                                                  \
-       {                                                 \
-         if (popcount_supported ())                      \
-           return MSC_BUILTIN (x);                       \
-         else                                            \
-           COUNT_ONE_BITS_GENERIC (TYPE);                \
-       }                                                 \
-     while (0)
-
-# else
-
-#  define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
-     COUNT_ONE_BITS_GENERIC (TYPE)
-
-# endif
-#endif
-
-/* Compute and return the number of 1-bits set in X. */
-COUNT_ONE_BITS_INLINE int
-count_one_bits (unsigned int x)
-{
-  COUNT_ONE_BITS (__builtin_popcount, __popcnt, unsigned int);
-}
-
-/* Compute and return the number of 1-bits set in X. */
-COUNT_ONE_BITS_INLINE int
-count_one_bits_l (unsigned long int x)
-{
-  COUNT_ONE_BITS (__builtin_popcountl, __popcnt, unsigned long int);
-}
-
-/* Compute and return the number of 1-bits set in X. */
-COUNT_ONE_BITS_INLINE int
-count_one_bits_ll (unsigned long long int x)
-{
-  COUNT_ONE_BITS (__builtin_popcountll, __popcnt64, unsigned long long int);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-_GL_INLINE_HEADER_END
-
-#endif /* COUNT_ONE_BITS_H */
diff --git a/lib/count-trailing-zeros.c b/lib/count-trailing-zeros.c
deleted file mode 100644 (file)
index e13f777..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Count the number of trailing 0 bits in a word.
-
-   Copyright 2013-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/>.  */
-
-#include <config.h>
-
-#define COUNT_TRAILING_ZEROS_INLINE _GL_EXTERN_INLINE
-#include "count-trailing-zeros.h"
diff --git a/lib/count-trailing-zeros.h b/lib/count-trailing-zeros.h
deleted file mode 100644 (file)
index 82de873..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word.
-   Copyright 2013-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 COUNT_TRAILING_ZEROS_H
-#define COUNT_TRAILING_ZEROS_H 1
-
-/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE.  */
-#if !_GL_CONFIG_H_INCLUDED
- #error "Please include config.h first."
-#endif
-
-#include <limits.h>
-#include <stdlib.h>
-
-_GL_INLINE_HEADER_BEGIN
-#ifndef COUNT_TRAILING_ZEROS_INLINE
-# define COUNT_TRAILING_ZEROS_INLINE _GL_INLINE
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
-   expand to code that computes the number of trailing zeros of the local
-   variable 'x' of type TYPE (an unsigned integer type) and return it
-   from the current function.  */
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \
-    || (__clang_major__ >= 4)
-# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)               \
-  return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
-#elif _MSC_VER
-extern unsigned char _BitScanForward (unsigned long *, unsigned long);
-# pragma intrinsic (_BitScanForward)
-# if defined _M_X64
-extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long);
-#  pragma intrinsic (_BitScanForward64)
-# endif
-# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)               \
-    do                                                                  \
-      {                                                                 \
-        unsigned long result;                                           \
-        return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \
-      }                                                                 \
-    while (0)
-#else
-# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)               \
-    do                                                                  \
-      {                                                                 \
-        int count = 0;                                                  \
-        if (! x)                                                        \
-          return CHAR_BIT * sizeof x;                                   \
-        for (count = 0;                                                 \
-             (count < CHAR_BIT * sizeof x - 32                          \
-              && ! (x & 0xffffffffU));                                  \
-             count += 32)                                               \
-          x = x >> 31 >> 1;                                             \
-        return count + count_trailing_zeros_32 (x);                     \
-      }                                                                 \
-    while (0)
-
-/* Compute and return the number of trailing zeros in the least
-   significant 32 bits of X.  One of these bits must be nonzero.  */
-COUNT_TRAILING_ZEROS_INLINE int
-count_trailing_zeros_32 (unsigned int x)
-{
-  /* <https://github.com/gibsjose/BitHacks>
-     <https://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
-  static const char de_Bruijn_lookup[32] = {
-    0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
-    31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
-  };
-  return de_Bruijn_lookup[(((x & -x) * 0x077cb531U) & 0xffffffffU) >> 27];
-}
-#endif
-
-/* Compute and return the number of trailing zeros in X. */
-COUNT_TRAILING_ZEROS_INLINE int
-count_trailing_zeros (unsigned int x)
-{
-  COUNT_TRAILING_ZEROS (__builtin_ctz, _BitScanForward, unsigned int);
-}
-
-/* Compute and return the number of trailing zeros in X. */
-COUNT_TRAILING_ZEROS_INLINE int
-count_trailing_zeros_l (unsigned long int x)
-{
-  COUNT_TRAILING_ZEROS (__builtin_ctzl, _BitScanForward, unsigned long int);
-}
-
-/* Compute and return the number of trailing zeros in X. */
-COUNT_TRAILING_ZEROS_INLINE int
-count_trailing_zeros_ll (unsigned long long int x)
-{
-#if (defined _MSC_VER && !defined __clang__) && !defined _M_X64
-  /* 32-bit MSVC does not have _BitScanForward64, only _BitScanForward.  */
-  unsigned long result;
-  if (_BitScanForward (&result, (unsigned long) x))
-    return result;
-  if (_BitScanForward (&result, (unsigned long) (x >> 32)))
-    return result + 32;
-  return CHAR_BIT * sizeof x;
-#else
-  COUNT_TRAILING_ZEROS (__builtin_ctzll, _BitScanForward64,
-                        unsigned long long int);
-#endif
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-_GL_INLINE_HEADER_END
-
-#endif
index d03e193b63c10b166cbacdbca2c8cfebc4ed857d..358d58d5015a483d05b53d321dfddba698eb7464 100644 (file)
@@ -86,9 +86,6 @@
 #  careadlinkat \
 #  close-stream \
 #  copy-file-range \
-#  count-leading-zeros \
-#  count-one-bits \
-#  count-trailing-zeros \
 #  crypto/md5 \
 #  crypto/md5-buffer \
 #  crypto/sha1-buffer \
 #  stat-time \
 #  std-gnu11 \
 #  stdbool \
+#  stdc_bit_width \
+#  stdc_count_ones \
+#  stdc_trailing_zeros \
 #  stdckdint \
 #  stddef \
 #  stdio \
@@ -358,6 +358,7 @@ GL_GENERATE_GMP_H_CONDITION = @GL_GENERATE_GMP_H_CONDITION@
 GL_GENERATE_IEEE754_H_CONDITION = @GL_GENERATE_IEEE754_H_CONDITION@
 GL_GENERATE_LIMITS_H_CONDITION = @GL_GENERATE_LIMITS_H_CONDITION@
 GL_GENERATE_MINI_GMP_H_CONDITION = @GL_GENERATE_MINI_GMP_H_CONDITION@
+GL_GENERATE_STDBIT_H_CONDITION = @GL_GENERATE_STDBIT_H_CONDITION@
 GL_GENERATE_STDCKDINT_H_CONDITION = @GL_GENERATE_STDCKDINT_H_CONDITION@
 GL_GENERATE_STDDEF_H_CONDITION = @GL_GENERATE_STDDEF_H_CONDITION@
 GL_GENERATE_STDINT_H_CONDITION = @GL_GENERATE_STDINT_H_CONDITION@
@@ -664,6 +665,20 @@ GL_GNULIB_VSPRINTF_POSIX = @GL_GNULIB_VSPRINTF_POSIX@
 GL_GNULIB_WCTOMB = @GL_GNULIB_WCTOMB@
 GL_GNULIB_WRITE = @GL_GNULIB_WRITE@
 GL_GNULIB__EXIT = @GL_GNULIB__EXIT@
+GL_STDC_BIT_CEIL = @GL_STDC_BIT_CEIL@
+GL_STDC_BIT_FLOOR = @GL_STDC_BIT_FLOOR@
+GL_STDC_BIT_WIDTH = @GL_STDC_BIT_WIDTH@
+GL_STDC_COUNT_ONES = @GL_STDC_COUNT_ONES@
+GL_STDC_COUNT_ZEROS = @GL_STDC_COUNT_ZEROS@
+GL_STDC_FIRST_LEADING_ONE = @GL_STDC_FIRST_LEADING_ONE@
+GL_STDC_FIRST_LEADING_ZERO = @GL_STDC_FIRST_LEADING_ZERO@
+GL_STDC_FIRST_TRAILING_ONE = @GL_STDC_FIRST_TRAILING_ONE@
+GL_STDC_FIRST_TRAILING_ZERO = @GL_STDC_FIRST_TRAILING_ZERO@
+GL_STDC_HAS_SINGLE_BIT = @GL_STDC_HAS_SINGLE_BIT@
+GL_STDC_LEADING_ONES = @GL_STDC_LEADING_ONES@
+GL_STDC_LEADING_ZEROS = @GL_STDC_LEADING_ZEROS@
+GL_STDC_TRAILING_ONES = @GL_STDC_TRAILING_ONES@
+GL_STDC_TRAILING_ZEROS = @GL_STDC_TRAILING_ZEROS@
 GMALLOC_OBJ = @GMALLOC_OBJ@
 GMP_H = @GMP_H@
 GNULIBHEADERS_OVERRIDE_WINT_T = @GNULIBHEADERS_OVERRIDE_WINT_T@
@@ -1315,6 +1330,7 @@ SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
 SMALL_JA_DIC = @SMALL_JA_DIC@
 SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
 SQLITE3_LIBS = @SQLITE3_LIBS@
+STDBIT_H = @STDBIT_H@
 STDCKDINT_H = @STDCKDINT_H@
 STDDEF_H = @STDDEF_H@
 STDDEF_NOT_IDEMPOTENT = @STDDEF_NOT_IDEMPOTENT@
@@ -1444,6 +1460,7 @@ gl_GNULIB_ENABLED_open_CONDITION = @gl_GNULIB_ENABLED_open_CONDITION@
 gl_GNULIB_ENABLED_rawmemchr_CONDITION = @gl_GNULIB_ENABLED_rawmemchr_CONDITION@
 gl_GNULIB_ENABLED_strtoll_CONDITION = @gl_GNULIB_ENABLED_strtoll_CONDITION@
 gl_GNULIB_ENABLED_utimens_CONDITION = @gl_GNULIB_ENABLED_utimens_CONDITION@
+gl_GNULIB_ENABLED_verify_CONDITION = @gl_GNULIB_ENABLED_verify_CONDITION@
 gl_LIBOBJDEPS = @gl_LIBOBJDEPS@
 gl_LIBOBJS = @gl_LIBOBJS@
 gl_LTLIBOBJS = @gl_LTLIBOBJS@
@@ -1721,36 +1738,6 @@ endif
 endif
 ## end   gnulib module copy-file-range
 
-## begin gnulib module count-leading-zeros
-ifeq (,$(OMIT_GNULIB_MODULE_count-leading-zeros))
-
-libgnu_a_SOURCES += count-leading-zeros.c
-
-EXTRA_DIST += count-leading-zeros.h
-
-endif
-## end   gnulib module count-leading-zeros
-
-## begin gnulib module count-one-bits
-ifeq (,$(OMIT_GNULIB_MODULE_count-one-bits))
-
-libgnu_a_SOURCES += count-one-bits.c
-
-EXTRA_DIST += count-one-bits.h
-
-endif
-## end   gnulib module count-one-bits
-
-## begin gnulib module count-trailing-zeros
-ifeq (,$(OMIT_GNULIB_MODULE_count-trailing-zeros))
-
-libgnu_a_SOURCES += count-trailing-zeros.c
-
-EXTRA_DIST += count-trailing-zeros.h
-
-endif
-## end   gnulib module count-trailing-zeros
-
 ## begin gnulib module crypto/md5
 ifeq (,$(OMIT_GNULIB_MODULE_crypto/md5))
 
@@ -3052,6 +3039,84 @@ EXTRA_DIST += stat-time.h
 endif
 ## end   gnulib module stat-time
 
+## begin gnulib module stdbit-h
+ifeq (,$(OMIT_GNULIB_MODULE_stdbit-h))
+
+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.
+ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION))
+stdbit.h: stdbit.in.h $(top_builddir)/config.status
+       $(gl_V_at)$(SED_HEADER_STDOUT) \
+         -e 's/@''GL_STDC_LEADING_ZEROS''@/$(GL_STDC_LEADING_ZEROS)/g' \
+         -e 's/@''GL_STDC_LEADING_ONES''@/$(GL_STDC_LEADING_ONES)/g' \
+         -e 's/@''GL_STDC_TRAILING_ZEROS''@/$(GL_STDC_TRAILING_ZEROS)/g' \
+         -e 's/@''GL_STDC_TRAILING_ONES''@/$(GL_STDC_TRAILING_ONES)/g' \
+         -e 's/@''GL_STDC_FIRST_LEADING_ZERO''@/$(GL_STDC_FIRST_LEADING_ZERO)/g' \
+         -e 's/@''GL_STDC_FIRST_LEADING_ONE''@/$(GL_STDC_FIRST_LEADING_ONE)/g' \
+         -e 's/@''GL_STDC_FIRST_TRAILING_ZERO''@/$(GL_STDC_FIRST_TRAILING_ZERO)/g' \
+         -e 's/@''GL_STDC_FIRST_TRAILING_ONE''@/$(GL_STDC_FIRST_TRAILING_ONE)/g' \
+         -e 's/@''GL_STDC_COUNT_ZEROS''@/$(GL_STDC_COUNT_ZEROS)/g' \
+         -e 's/@''GL_STDC_COUNT_ONES''@/$(GL_STDC_COUNT_ONES)/g' \
+         -e 's/@''GL_STDC_HAS_SINGLE_BIT''@/$(GL_STDC_HAS_SINGLE_BIT)/g' \
+         -e 's/@''GL_STDC_BIT_WIDTH''@/$(GL_STDC_BIT_WIDTH)/g' \
+         -e 's/@''GL_STDC_BIT_FLOOR''@/$(GL_STDC_BIT_FLOOR)/g' \
+         -e 's/@''GL_STDC_BIT_CEIL''@/$(GL_STDC_BIT_CEIL)/g' \
+         $(srcdir)/stdbit.in.h > $@-t
+       $(AM_V_at)mv $@-t $@
+libgnu_a_SOURCES += stdbit.c
+else
+stdbit.h: $(top_builddir)/config.status
+       rm -f $@
+endif
+MOSTLYCLEANFILES += stdbit.h stdbit.h-t
+
+EXTRA_DIST += stdbit.in.h
+
+endif
+## end   gnulib module stdbit-h
+
+## begin gnulib module stdc_bit_width
+ifeq (,$(OMIT_GNULIB_MODULE_stdc_bit_width))
+
+ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION))
+libgnu_a_SOURCES += stdc_bit_width.c
+endif
+
+endif
+## end   gnulib module stdc_bit_width
+
+## begin gnulib module stdc_count_ones
+ifeq (,$(OMIT_GNULIB_MODULE_stdc_count_ones))
+
+ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION))
+libgnu_a_SOURCES += stdc_count_ones.c
+endif
+
+endif
+## end   gnulib module stdc_count_ones
+
+## begin gnulib module stdc_leading_zeros
+ifeq (,$(OMIT_GNULIB_MODULE_stdc_leading_zeros))
+
+ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION))
+libgnu_a_SOURCES += stdc_leading_zeros.c
+endif
+
+endif
+## end   gnulib module stdc_leading_zeros
+
+## begin gnulib module stdc_trailing_zeros
+ifeq (,$(OMIT_GNULIB_MODULE_stdc_trailing_zeros))
+
+ifneq (,$(GL_GENERATE_STDBIT_H_CONDITION))
+libgnu_a_SOURCES += stdc_trailing_zeros.c
+endif
+
+endif
+## end   gnulib module stdc_trailing_zeros
+
 ## begin gnulib module stdckdint
 ifeq (,$(OMIT_GNULIB_MODULE_stdckdint))
 
@@ -4274,7 +4339,9 @@ endif
 ## begin gnulib module verify
 ifeq (,$(OMIT_GNULIB_MODULE_verify))
 
+ifneq (,$(gl_GNULIB_ENABLED_verify_CONDITION))
 
+endif
 EXTRA_DIST += verify.h
 
 endif
diff --git a/lib/stdbit.c b/lib/stdbit.c
new file mode 100644 (file)
index 0000000..4801e74
--- /dev/null
@@ -0,0 +1,23 @@
+/* Support C23 bit and byte utilities on 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.  */
+
+#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 (file)
index 0000000..9f9e60a
--- /dev/null
@@ -0,0 +1,1077 @@
+/* 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
+
+_GL_INLINE_HEADER_BEGIN
+
+#ifndef _GL_STDBIT_INLINE
+# define _GL_STDBIT_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_LEADING_ZEROS_INLINE
+# define _GL_STDC_LEADING_ZEROS_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_LEADING_ONES_INLINE
+# define _GL_STDC_LEADING_ONES_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_TRAILING_ZEROS_INLINE
+# define _GL_STDC_TRAILING_ZEROS_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_TRAILING_ONES_INLINE
+# define _GL_STDC_TRAILING_ONES_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_FIRST_LEADING_ZERO_INLINE
+# define _GL_STDC_FIRST_LEADING_ZERO_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_FIRST_LEADING_ONE_INLINE
+# define _GL_STDC_FIRST_LEADING_ONE_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_FIRST_TRAILING_ZERO_INLINE
+# define _GL_STDC_FIRST_TRAILING_ZERO_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_FIRST_TRAILING_ONE_INLINE
+# define _GL_STDC_FIRST_TRAILING_ONE_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_COUNT_ZEROS_INLINE
+# define _GL_STDC_COUNT_ZEROS_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_COUNT_ONES_INLINE
+# define _GL_STDC_COUNT_ONES_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_HAS_SINGLE_BIT_INLINE
+# define _GL_STDC_HAS_SINGLE_BIT_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_BIT_WIDTH_INLINE
+# define _GL_STDC_BIT_WIDTH_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_BIT_FLOOR_INLINE
+# define _GL_STDC_BIT_FLOOR_INLINE _GL_INLINE
+#endif
+#ifndef _GL_STDC_BIT_CEIL_INLINE
+# define _GL_STDC_BIT_CEIL_INLINE _GL_INLINE
+#endif
+
+/* 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
+
+
+/* ISO C 23 § 7.18.1 General  */
+
+#define __STDC_VERSION_STDBIT_H__ 202311L
+
+
+/* ISO C 23 § 7.18.2 Endian  */
+
+#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
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) || 4 <= __clang_major__
+# define _GL_STDBIT_HAS_BUILTIN_CLZ true
+# define _GL_STDBIT_HAS_BUILTIN_CTZ true
+# define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true
+#elif defined __has_builtin
+# if (__has_builtin (__builtin_clz) \
+      && __has_builtin (__builtin_clzl) \
+      && __has_builtin (__builtin_clzll))
+#  define _GL_STDBIT_HAS_BUILTIN_CLZ true
+# endif
+# if (__has_builtin (__builtin_ctz) \
+      && __has_builtin (__builtin_ctzl) \
+      && __has_builtin (__builtin_ctzll))
+#  define _GL_STDBIT_HAS_BUILTIN_CTZ true
+# endif
+# if (__has_builtin (__builtin_popcount) \
+      && __has_builtin (__builtin_popcountl) \
+      && __has_builtin (__builtin_popcountll))
+#  define _GL_STDBIT_HAS_BUILTIN_POPCOUNT true
+# endif
+#endif
+
+/* Count leading 0 bits of N, even if N is 0.  */
+#ifdef _GL_STDBIT_HAS_BUILTIN_CLZ
+_GL_STDBIT_INLINE int
+__gl_stdbit_clz (unsigned int n)
+{
+  return n ? __builtin_clz (n) : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzl (unsigned long int n)
+{
+  return n ? __builtin_clzl (n) : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzll (unsigned long long int n)
+{
+  return n ? __builtin_clzll (n) : 8 * sizeof n;
+}
+#elif defined _MSC_VER
+
+/* Declare the few MSVC intrinsics that we need.  We prefer not to include
+   <intrin.h> because it would pollute the namespace.  */
+extern unsigned char _BitScanReverse (unsigned long *, unsigned long);
+# pragma intrinsic (_BitScanReverse)
+# ifdef _M_X64
+extern unsigned char _BitScanReverse64 (unsigned long *, unsigned long long);
+#  pragma intrinsic (_BitScanReverse64)
+# endif
+
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzl (unsigned long int n)
+{
+  unsigned long int r;
+  return 8 * sizeof n - (_BitScanReverse (&r, n) ? r + 1 : 0);
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_clz (unsigned int n)
+{
+  return __gl_stdbit_clzl (n) - 8 * (sizeof 0ul - sizeof n);
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzll (unsigned long long int n)
+{
+# ifdef _M_X64
+  unsigned long int r;
+  return 8 * sizeof n - (_BitScanReverse64 (&r, n) ? r + 1 : 0);
+# else
+  unsigned long int hi = n >> 32;
+  return __gl_stdbit_clzl (hi ? hi : n) + (hi ? 0 : 32);
+# endif
+}
+
+#else /* !_MSC_VER */
+
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzll (unsigned long long int n)
+{
+  int r = 0;
+  for (int i = 8 * sizeof n >> 1; 1 << 6 <= i; i >>= 1)
+    {
+      int a = (1ull << i <= n) * i; n >>= a; r += a;
+    }
+  int a5 = (0x00000000ffffffff < n) << 5; n >>= a5; r += a5;
+  int a4 = (0x000000000000ffff < n) << 4; n >>= a4; r += a4;
+  int a3 = (0x00000000000000ff < n) << 3; n >>= a3; r += a3;
+  int a2 = (0x000000000000000f < n) << 2; n >>= a2; r += a2;
+  return (8 * sizeof n - (1 << 2) - r) + ((0x11112234ull >> (n << 2)) & 0xf);
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_clz (unsigned int n)
+{
+  return __gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0u);
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzl (unsigned long int n)
+{
+  return __gl_stdbit_clzll (n) - 8 * (sizeof 0ull - sizeof 0ul);
+}
+#endif
+
+/* Count trailing 0 bits of N, even if N is 0.  */
+#ifdef _GL_STDBIT_HAS_BUILTIN_CTZ
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctz (unsigned int n)
+{
+  return n ? __builtin_ctz (n) : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzl (unsigned long int n)
+{
+  return n ? __builtin_ctzl (n) : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzll (unsigned long long int n)
+{
+  return n ? __builtin_ctzll (n) : 8 * sizeof n;
+}
+#elif defined _MSC_VER
+
+/* Declare the few MSVC intrinsics that we need.  We prefer not to include
+   <intrin.h> because it would pollute the namespace.  */
+extern unsigned char _BitScanForward (unsigned long *, unsigned long);
+# pragma intrinsic (_BitScanForward)
+# ifdef _M_X64
+extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long);
+#  pragma intrinsic (_BitScanForward64)
+# endif
+
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzl (unsigned long int n)
+{
+  unsigned long int r;
+  return _BitScanForward (&r, n) ? r : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctz (unsigned int n)
+{
+  return __gl_stdbit_ctzl (n | (1ul << (8 * sizeof n - 1) << 1));
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzll (unsigned long long int n)
+{
+# ifdef _M_X64
+  unsigned long int r;
+  return _BitScanForward64 (&r, n) ? r : 8 * sizeof n;
+# else
+  unsigned int lo = n;
+  return __gl_stdbit_ctzl (lo ? lo : n >> 32) + (lo ? 0 : 32);
+# endif
+}
+
+#else /* !_MSC_VER */
+
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctz (unsigned int n)
+{
+  return 8 * sizeof n - (n ? __gl_stdbit_clz (n & -n) + 1 : 0);
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzl (unsigned long int n)
+{
+  return 8 * sizeof n - (n ? __gl_stdbit_clzl (n & -n) + 1 : 0);
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzll (unsigned long long int n)
+{
+  return 8 * sizeof n - (n ? __gl_stdbit_clzll (n & -n) + 1 : 0);
+}
+#endif
+
+#if @GL_STDC_COUNT_ONES@
+/* Count 1 bits in N.  */
+# ifdef _GL_STDBIT_HAS_BUILTIN_POPCOUNT
+#  define __gl_stdbit_popcount __builtin_popcount
+#  define __gl_stdbit_popcountl __builtin_popcountl
+#  define __gl_stdbit_popcountll __builtin_popcountll
+# else
+_GL_STDC_COUNT_ONES_INLINE int
+__gl_stdbit_popcount_wide (unsigned long long int n)
+{
+  if (sizeof n & (sizeof n - 1))
+    {
+      /* Use a simple O(log N) loop on theoretical platforms where N's
+         width is not a power of 2.  */
+      int count = 0;
+      for (int i = 0; i < 8 * sizeof n; i++, n >>= 1)
+        count += n & 1;
+      return count;
+    }
+  else
+    {
+      /* N's width is a power of 2; count in parallel.  */
+      unsigned long long int
+        max = -1ull,
+        x555555 = max / (1 << 1 | 1),  /* 0x555555... */
+        x333333 = max / (1 << 2 | 1),  /* 0x333333... */
+        x0f0f0f = max / (1 << 4 | 1),  /* 0x0f0f0f... */
+        x010101 = max / ((1 << 8) - 1),        /* 0x010101... */
+        x000_7f = max / 0xffffffffffffffff * 0x7f; /* 0x000000000000007f... */
+      n -= (n >> 1) & x555555;
+      n = (n & x333333) + ((n >> 2) & x333333);
+      n = (n + (n >> 4)) & x0f0f0f;
+
+      /* If the popcount always fits in 8 bits, multiply so that the
+         popcount is in the leading 8 bits of the product; these days
+         this is typically faster than the alternative below.  */
+      if (8 * sizeof n < 1 << 8)
+        return n * x010101 >> 8 * (sizeof n - 1);
+
+      /* N is at least 256 bits wide!  Fall back on an O(log log N)
+         loop that a compiler could unroll.  Unroll the first three
+         iterations by hand, to skip some division and masking.  This
+         is the most we can easily do without hassling with constants
+         that a typical-platform compiler would reject.  */
+      n += n >> (1 << 3);
+      n += n >> (1 << 4);
+      n += n >> (1 << 5);
+      n &= x000_7f;
+      for (int i = 64; i < 8 * sizeof n; i <<= 1)
+        n = (n + (n >> i)) & max / (1ull << i | 1);
+      return n;
+    }
+}
+
+#  ifdef _MSC_VER
+#   if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
+/* Declare the few MSVC intrinsics that we need.  We prefer not to include
+   <intrin.h> because it would pollute the namespace.  */
+extern void __cpuid (int[4], int);
+#    pragma intrinsic (__cpuid)
+extern unsigned int __popcnt (unsigned int);
+#    pragma intrinsic (__popcnt)
+#    ifdef _M_X64
+extern unsigned long long __popcnt64 (unsigned long long);
+#     pragma intrinsic (__popcnt64)
+#    else
+_GL_STDC_COUNT_ONES_INLINE int
+__popcnt64 (unsigned long long int n)
+{
+  return __popcnt (n >> 32) + __popcnt (n);
+}
+#    endif
+#   endif
+
+/* 1 if supported, -1 if not, 0 if unknown.  */
+extern signed char __gl_stdbit_popcount_support;
+
+_GL_STDC_COUNT_ONES_INLINE bool
+__gl_stdbit_popcount_supported (void)
+{
+  if (!__gl_stdbit_popcount_support)
+    {
+      /* Do as described in
+         <https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64>
+         Although Microsoft started requiring POPCNT in MS-Windows 11 24H2,
+         we'll be more cautious.  */
+      int cpu_info[4];
+      __cpuid (cpu_info, 1);
+      __gl_stdbit_popcount_support = cpu_info[2] & 1 << 23 ? 1 : -1;
+    }
+  return 0 < __gl_stdbit_popcount_support;
+}
+_GL_STDC_COUNT_ONES_INLINE int
+__gl_stdbit_popcount (unsigned int n)
+{
+  return (__gl_stdbit_popcount_supported ()
+          ? __popcnt (n)
+          : __gl_stdbit_popcount_wide (n));
+}
+_GL_STDC_COUNT_ONES_INLINE int
+__gl_stdbit_popcountl (unsigned long int n)
+{
+  return (__gl_stdbit_popcount_supported ()
+          ? __popcnt (n)
+          : __gl_stdbit_popcount_wide (n));
+}
+_GL_STDC_COUNT_ONES_INLINE int
+__gl_stdbit_popcountll (unsigned long long int n)
+{
+  return (__gl_stdbit_popcount_supported ()
+          ? __popcnt64 (n)
+          : __gl_stdbit_popcount_wide (n));
+}
+#  else /* !_MSC_VER */
+#   define __gl_stdbit_popcount __gl_stdbit_popcount_wide
+#   define __gl_stdbit_popcountl __gl_stdbit_popcount_wide
+#   define __gl_stdbit_popcountll __gl_stdbit_popcount_wide
+#  endif
+# endif
+#endif
+
+
+/* ISO C 23 § 7.18.3 Count Leading Zeros  */
+
+#if @GL_STDC_LEADING_ZEROS@
+
+_GL_STDC_LEADING_ZEROS_INLINE unsigned int
+stdc_leading_zeros_ui (unsigned int n)
+{
+  return __gl_stdbit_clz (n);
+}
+
+_GL_STDC_LEADING_ZEROS_INLINE unsigned int
+stdc_leading_zeros_uc (unsigned char n)
+{
+  return stdc_leading_zeros_ui (n) - 8 * (sizeof 0u - sizeof n);
+}
+
+_GL_STDC_LEADING_ZEROS_INLINE unsigned int
+stdc_leading_zeros_us (unsigned short int n)
+{
+  return stdc_leading_zeros_ui (n) - 8 * (sizeof 0u - sizeof n);
+}
+
+_GL_STDC_LEADING_ZEROS_INLINE unsigned int
+stdc_leading_zeros_ul (unsigned long int n)
+{
+  return __gl_stdbit_clzl (n);
+}
+
+_GL_STDC_LEADING_ZEROS_INLINE unsigned int
+stdc_leading_zeros_ull (unsigned long long int n)
+{
+  return __gl_stdbit_clzll (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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.4 Count Leading Ones  */
+
+#if @GL_STDC_LEADING_ONES@
+
+_GL_STDC_LEADING_ONES_INLINE unsigned int
+stdc_leading_ones_uc (unsigned char n)
+{
+  return stdc_leading_zeros_uc (~n);
+}
+
+_GL_STDC_LEADING_ONES_INLINE unsigned int
+stdc_leading_ones_us (unsigned short int n)
+{
+  return stdc_leading_zeros_us (~n);
+}
+
+_GL_STDC_LEADING_ONES_INLINE unsigned int
+stdc_leading_ones_ui (unsigned int n)
+{
+  return stdc_leading_zeros_ui (~n);
+}
+
+_GL_STDC_LEADING_ONES_INLINE unsigned int
+stdc_leading_ones_ul (unsigned long int n)
+{
+  return stdc_leading_zeros_ul (~n);
+}
+
+_GL_STDC_LEADING_ONES_INLINE unsigned int
+stdc_leading_ones_ull (unsigned long long int n)
+{
+  return stdc_leading_zeros_ull (~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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.5 Count Trailing Zeros  */
+
+#if @GL_STDC_TRAILING_ZEROS@
+
+_GL_STDC_TRAILING_ZEROS_INLINE unsigned int
+stdc_trailing_zeros_ui (unsigned int n)
+{
+  return __gl_stdbit_ctz (n);
+}
+
+_GL_STDC_TRAILING_ZEROS_INLINE unsigned int
+stdc_trailing_zeros_uc (unsigned char n)
+{
+  return stdc_trailing_zeros_ui (n | (1 + (unsigned char) -1));
+}
+
+_GL_STDC_TRAILING_ZEROS_INLINE unsigned int
+stdc_trailing_zeros_us (unsigned short int n)
+{
+  return stdc_trailing_zeros_ui (n | (1 + (unsigned short int) -1));
+}
+
+_GL_STDC_TRAILING_ZEROS_INLINE unsigned int
+stdc_trailing_zeros_ul (unsigned long int n)
+{
+  return __gl_stdbit_ctzl (n);
+}
+
+_GL_STDC_TRAILING_ZEROS_INLINE unsigned int
+stdc_trailing_zeros_ull (unsigned long long int n)
+{
+  return __gl_stdbit_ctzll (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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.6 Count Trailing Ones  */
+
+#if @GL_STDC_TRAILING_ONES@
+
+_GL_STDC_TRAILING_ONES_INLINE unsigned int
+stdc_trailing_ones_uc (unsigned char n)
+{
+  return stdc_trailing_zeros_uc (~n);
+}
+
+_GL_STDC_TRAILING_ONES_INLINE unsigned int
+stdc_trailing_ones_us (unsigned short int n)
+{
+  return stdc_trailing_zeros_us (~n);
+}
+
+_GL_STDC_TRAILING_ONES_INLINE unsigned int
+stdc_trailing_ones_ui (unsigned int n)
+{
+  return stdc_trailing_zeros_ui (~n);
+}
+
+_GL_STDC_TRAILING_ONES_INLINE unsigned int
+stdc_trailing_ones_ul (unsigned long int n)
+{
+  return stdc_trailing_zeros_ul (~n);
+}
+
+_GL_STDC_TRAILING_ONES_INLINE unsigned int
+stdc_trailing_ones_ull (unsigned long long int n)
+{
+  return stdc_trailing_zeros_ull (~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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.7 First Leading Zero  */
+
+#if @GL_STDC_FIRST_LEADING_ZERO@
+
+_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int
+stdc_first_leading_zero_uc (unsigned char n)
+{
+  unsigned int count = stdc_leading_ones_uc (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int
+stdc_first_leading_zero_us (unsigned short int n)
+{
+  unsigned int count = stdc_leading_ones_us (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int
+stdc_first_leading_zero_ui (unsigned int n)
+{
+  unsigned int count = stdc_leading_ones_ui (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int
+stdc_first_leading_zero_ul (unsigned long int n)
+{
+  unsigned int count = stdc_leading_ones_ul (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_LEADING_ZERO_INLINE unsigned int
+stdc_first_leading_zero_ull (unsigned long long int n)
+{
+  unsigned int count = stdc_leading_ones_ull (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+# 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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.8 First Leading One  */
+
+#if @GL_STDC_FIRST_LEADING_ONE@
+
+_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int
+stdc_first_leading_one_uc (unsigned char n)
+{
+  unsigned int count = stdc_leading_zeros_uc (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int
+stdc_first_leading_one_us (unsigned short int n)
+{
+  unsigned int count = stdc_leading_zeros_us (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int
+stdc_first_leading_one_ui (unsigned int n)
+{
+  unsigned int count = stdc_leading_zeros_ui (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int
+stdc_first_leading_one_ul (unsigned long int n)
+{
+  unsigned int count = stdc_leading_zeros_ul (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_LEADING_ONE_INLINE unsigned int
+stdc_first_leading_one_ull (unsigned long long int n)
+{
+  unsigned int count = stdc_leading_zeros_ull (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+# 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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.9 First Trailing Zero  */
+
+#if @GL_STDC_FIRST_TRAILING_ZERO@
+
+_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int
+stdc_first_trailing_zero_uc (unsigned char n)
+{
+  unsigned int count = stdc_trailing_ones_uc (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int
+stdc_first_trailing_zero_us (unsigned short int n)
+{
+  unsigned int count = stdc_trailing_ones_us (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int
+stdc_first_trailing_zero_ui (unsigned int n)
+{
+  unsigned int count = stdc_trailing_ones_ui (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int
+stdc_first_trailing_zero_ul (unsigned long int n)
+{
+  unsigned int count = stdc_trailing_ones_ul (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_TRAILING_ZERO_INLINE unsigned int
+stdc_first_trailing_zero_ull (unsigned long long int n)
+{
+  unsigned int count = stdc_trailing_ones_ull (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+# 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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.10 First Trailing One  */
+
+#if @GL_STDC_FIRST_TRAILING_ONE@
+
+_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int
+stdc_first_trailing_one_uc (unsigned char n)
+{
+  unsigned int count = stdc_trailing_zeros_uc (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int
+stdc_first_trailing_one_us (unsigned short int n)
+{
+  unsigned int count = stdc_trailing_zeros_us (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int
+stdc_first_trailing_one_ui (unsigned int n)
+{
+  unsigned int count = stdc_trailing_zeros_ui (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int
+stdc_first_trailing_one_ul (unsigned long int n)
+{
+  unsigned int count = stdc_trailing_zeros_ul (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+_GL_STDC_FIRST_TRAILING_ONE_INLINE unsigned int
+stdc_first_trailing_one_ull (unsigned long long int n)
+{
+  unsigned int count = stdc_trailing_zeros_ull (n);
+  unsigned int bits = 8 * sizeof n;
+  return count % bits + (count < bits);
+}
+
+#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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.12 Count Ones  */
+
+#if @GL_STDC_COUNT_ONES@
+
+_GL_STDC_COUNT_ONES_INLINE unsigned int
+stdc_count_ones_ui (unsigned int n)
+{
+  return __gl_stdbit_popcount (n);
+}
+
+_GL_STDC_COUNT_ONES_INLINE unsigned int
+stdc_count_ones_uc (unsigned char n)
+{
+  return stdc_count_ones_ui (n);
+}
+
+_GL_STDC_COUNT_ONES_INLINE unsigned int
+stdc_count_ones_us (unsigned short int n)
+{
+  return stdc_count_ones_ui (n);
+}
+
+_GL_STDC_COUNT_ONES_INLINE unsigned int
+stdc_count_ones_ul (unsigned long int n)
+{
+  return __gl_stdbit_popcountl (n);
+}
+
+_GL_STDC_COUNT_ONES_INLINE unsigned int
+stdc_count_ones_ull (unsigned long long int n)
+{
+  return __gl_stdbit_popcountll (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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.11 Count Zeros  */
+
+#if @GL_STDC_COUNT_ZEROS@
+
+_GL_STDC_COUNT_ZEROS_INLINE unsigned int
+stdc_count_zeros_uc (unsigned char n)
+{
+  return stdc_count_ones_uc (~n);
+}
+
+_GL_STDC_COUNT_ZEROS_INLINE unsigned int
+stdc_count_zeros_us (unsigned short int n)
+{
+  return stdc_count_ones_us (~n);
+}
+
+_GL_STDC_COUNT_ZEROS_INLINE unsigned int
+stdc_count_zeros_ui (unsigned int n)
+{
+  return stdc_count_ones_ui (~n);
+}
+
+_GL_STDC_COUNT_ZEROS_INLINE unsigned int
+stdc_count_zeros_ul (unsigned long int n)
+{
+  return stdc_count_ones_ul (~n);
+}
+
+_GL_STDC_COUNT_ZEROS_INLINE unsigned int
+stdc_count_zeros_ull (unsigned long long int n)
+{
+  return stdc_count_ones_ull (~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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.13 Single-bit Check  */
+
+#if @GL_STDC_HAS_SINGLE_BIT@
+
+_GL_STDC_HAS_SINGLE_BIT_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_STDC_HAS_SINGLE_BIT_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_STDC_HAS_SINGLE_BIT_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_STDC_HAS_SINGLE_BIT_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_STDC_HAS_SINGLE_BIT_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)))
+
+#endif
+
+
+/* ISO C 23 § 7.18.14 Bit Width  */
+
+#if @GL_STDC_BIT_WIDTH@
+
+_GL_STDC_BIT_WIDTH_INLINE unsigned int
+stdc_bit_width_uc (unsigned char n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_uc (n);
+}
+
+_GL_STDC_BIT_WIDTH_INLINE unsigned int
+stdc_bit_width_us (unsigned short int n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_us (n);
+}
+
+_GL_STDC_BIT_WIDTH_INLINE unsigned int
+stdc_bit_width_ui (unsigned int n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_ui (n);
+}
+
+_GL_STDC_BIT_WIDTH_INLINE unsigned int
+stdc_bit_width_ul (unsigned long int n)
+{
+  return 8 * sizeof n - stdc_leading_zeros_ul (n);
+}
+
+_GL_STDC_BIT_WIDTH_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))
+
+#endif
+
+
+/* ISO C 23 § 7.18.15 Bit Floor  */
+
+#if @GL_STDC_BIT_FLOOR@
+
+_GL_STDC_BIT_FLOOR_INLINE unsigned char
+stdc_bit_floor_uc (unsigned char n)
+{
+  return n ? 1u << (stdc_bit_width_uc (n) - 1) : 0;
+}
+
+_GL_STDC_BIT_FLOOR_INLINE unsigned short int
+stdc_bit_floor_us (unsigned short int n)
+{
+  return n ? 1u << (stdc_bit_width_us (n) - 1) : 0;
+}
+
+_GL_STDC_BIT_FLOOR_INLINE unsigned int
+stdc_bit_floor_ui (unsigned int n)
+{
+  return n ? 1u << (stdc_bit_width_ui (n) - 1) : 0;
+}
+
+_GL_STDC_BIT_FLOOR_INLINE unsigned long int
+stdc_bit_floor_ul (unsigned long int n)
+{
+  return n ? 1ul << (stdc_bit_width_ul (n) - 1) : 0;
+}
+
+_GL_STDC_BIT_FLOOR_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))))
+
+#endif
+
+
+/* ISO C 23 § 7.18.16 Bit Ceiling  */
+
+#if @GL_STDC_BIT_CEIL@
+
+_GL_STDC_BIT_CEIL_INLINE unsigned char
+stdc_bit_ceil_uc (unsigned char n)
+{
+  return n <= 1 ? 1 : 2u << (stdc_bit_width_uc (n - 1) - 1);
+}
+
+_GL_STDC_BIT_CEIL_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_STDC_BIT_CEIL_INLINE unsigned int
+stdc_bit_ceil_ui (unsigned int n)
+{
+  return n <= 1 ? 1 : 2u << (stdc_bit_width_ui (n - 1) - 1);
+}
+
+_GL_STDC_BIT_CEIL_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_STDC_BIT_CEIL_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))))
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+_GL_INLINE_HEADER_END
+
+#endif /* STDBIT_H */
diff --git a/lib/stdc_bit_width.c b/lib/stdc_bit_width.c
new file mode 100644 (file)
index 0000000..a0dc8de
--- /dev/null
@@ -0,0 +1,20 @@
+/* stdc_bit_width_* functions.
+   Copyright (C) 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/>.  */
+
+#include <config.h>
+
+#define _GL_STDC_BIT_WIDTH_INLINE _GL_EXTERN_INLINE
+#include <stdbit.h>
diff --git a/lib/stdc_count_ones.c b/lib/stdc_count_ones.c
new file mode 100644 (file)
index 0000000..7421178
--- /dev/null
@@ -0,0 +1,24 @@
+/* stdc_count_ones_* functions.
+   Copyright (C) 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/>.  */
+
+#include <config.h>
+
+#define _GL_STDC_COUNT_ONES_INLINE _GL_EXTERN_INLINE
+#include <stdbit.h>
+
+#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
+signed char __gl_stdbit_popcount_support;
+#endif
diff --git a/lib/stdc_leading_zeros.c b/lib/stdc_leading_zeros.c
new file mode 100644 (file)
index 0000000..45695e5
--- /dev/null
@@ -0,0 +1,20 @@
+/* stdc_leading_zeros_* functions.
+   Copyright (C) 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/>.  */
+
+#include <config.h>
+
+#define _GL_STDC_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE
+#include <stdbit.h>
diff --git a/lib/stdc_trailing_zeros.c b/lib/stdc_trailing_zeros.c
new file mode 100644 (file)
index 0000000..f4bc43a
--- /dev/null
@@ -0,0 +1,20 @@
+/* stdc_trailing_zeros_* functions.
+   Copyright (C) 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/>.  */
+
+#include <config.h>
+
+#define _GL_STDC_TRAILING_ZEROS_INLINE _GL_EXTERN_INLINE
+#include <stdbit.h>
index 61040987b5766653c4b9ed59c97f87fad23a58b3..4dd1e68d15c1cbc618e8a5d4c6b794c17999127a 100644 (file)
@@ -63,9 +63,6 @@ AC_DEFUN([gl_EARLY],
   # Code from module cloexec:
   # Code from module close-stream:
   # Code from module copy-file-range:
-  # Code from module count-leading-zeros:
-  # Code from module count-one-bits:
-  # Code from module count-trailing-zeros:
   # Code from module crypto/md5:
   # Code from module crypto/md5-buffer:
   # Code from module crypto/sha1-buffer:
@@ -174,7 +171,12 @@ AC_DEFUN([gl_EARLY],
   # Code from module ssize_t:
   # Code from module stat-time:
   # Code from module std-gnu11:
+  # Code from module stdbit-h:
   # Code from module stdbool:
+  # Code from module stdc_bit_width:
+  # Code from module stdc_count_ones:
+  # Code from module stdc_leading_zeros:
+  # Code from module stdc_trailing_zeros:
   # Code from module stdckdint:
   # Code from module stddef:
   # Code from module stdint:
@@ -514,7 +516,18 @@ AC_DEFUN([gl_INIT],
   gt_TYPE_SSIZE_T
   gl_STAT_TIME
   gl_STAT_BIRTHTIME
+  gl_STDBIT_H
+  gl_CONDITIONAL_HEADER([stdbit.h])
+  AC_PROG_MKDIR_P
   gl_C_BOOL
+  AC_REQUIRE([gl_STDBIT_H])
+  GL_STDC_BIT_WIDTH=1
+  AC_REQUIRE([gl_STDBIT_H])
+  GL_STDC_COUNT_ONES=1
+  AC_REQUIRE([gl_STDBIT_H])
+  GL_STDC_LEADING_ZEROS=1
+  AC_REQUIRE([gl_STDBIT_H])
+  GL_STDC_TRAILING_ZEROS=1
   AC_CHECK_HEADERS_ONCE([stdckdint.h])
   if test $ac_cv_header_stdckdint_h = yes; then
     GL_GENERATE_STDCKDINT_H=false
@@ -673,6 +686,7 @@ AC_DEFUN([gl_INIT],
   gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false
   gl_gnulib_enabled_strtoll=false
   gl_gnulib_enabled_utimens=false
+  gl_gnulib_enabled_verify=false
   gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false
   func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b ()
   {
@@ -953,6 +967,12 @@ AC_DEFUN([gl_INIT],
       gl_gnulib_enabled_utimens=true
     fi
   }
+  func_gl_gnulib_m4code_verify ()
+  {
+    if $gl_gnulib_enabled_verify; then :; else
+      gl_gnulib_enabled_verify=true
+    fi
+  }
   func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec ()
   {
     if $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then :; else
@@ -1016,6 +1036,9 @@ AC_DEFUN([gl_INIT],
   if case $host_os in mingw* | windows*) false;; *) test $HAVE_GETRANDOM = 0 || test $REPLACE_GETRANDOM = 1;; esac; then
     func_gl_gnulib_m4code_open
   fi
+  if test $REPLACE_MKTIME = 1; then
+    func_gl_gnulib_m4code_verify
+  fi
   if test $HAVE_READLINKAT = 0 || test $REPLACE_READLINKAT = 1; then
     func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
   fi
@@ -1025,6 +1048,9 @@ AC_DEFUN([gl_INIT],
   if test $ac_use_included_regex = yes; then
     func_gl_gnulib_m4code_fd38c7e463b54744b77b98aeafb4fa7c
   fi
+  if test $ac_use_included_regex = yes; then
+    func_gl_gnulib_m4code_verify
+  fi
   if test $HAVE_DECL_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; then
     func_gl_gnulib_m4code_strtoll
   fi
@@ -1065,6 +1091,7 @@ AC_DEFUN([gl_INIT],
   AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_utimens], [$gl_gnulib_enabled_utimens])
+  AM_CONDITIONAL([gl_GNULIB_ENABLED_verify], [$gl_gnulib_enabled_verify])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec])
   # End of code from modules
   m4_ifval(gl_LIBSOURCES_LIST, [
@@ -1276,12 +1303,6 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/close-stream.c
   lib/close-stream.h
   lib/copy-file-range.c
-  lib/count-leading-zeros.c
-  lib/count-leading-zeros.h
-  lib/count-one-bits.c
-  lib/count-one-bits.h
-  lib/count-trailing-zeros.c
-  lib/count-trailing-zeros.h
   lib/diffseq.h
   lib/dirent-private.h
   lib/dirent.in.h
@@ -1414,6 +1435,12 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/signal.in.h
   lib/stat-time.c
   lib/stat-time.h
+  lib/stdbit.c
+  lib/stdbit.in.h
+  lib/stdc_bit_width.c
+  lib/stdc_count_ones.c
+  lib/stdc_leading_zeros.c
+  lib/stdc_trailing_zeros.c
   lib/stdckdint.in.h
   lib/stddef.in.h
   lib/stdint.in.h
@@ -1567,6 +1594,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/stat-time.m4
   m4/std-gnu11.m4
   m4/stdalign.m4
+  m4/stdbit_h.m4
   m4/stddef_h.m4
   m4/stdint.m4
   m4/stdio_h.m4
diff --git a/m4/stdbit_h.m4 b/m4/stdbit_h.m4
new file mode 100644 (file)
index 0000000..6af813f
--- /dev/null
@@ -0,0 +1,37 @@
+# stdbit_h.m4
+# serial 2
+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
+
+  dnl We don't use gl_MODULE_INDICATOR_INIT_VARIABLE here, because stdbit.in.h
+  dnl does not use #include_next.
+  GL_STDC_LEADING_ZEROS=0;       AC_SUBST([GL_STDC_LEADING_ZEROS])
+  GL_STDC_LEADING_ONES=0;        AC_SUBST([GL_STDC_LEADING_ONES])
+  GL_STDC_TRAILING_ZEROS=0;      AC_SUBST([GL_STDC_TRAILING_ZEROS])
+  GL_STDC_TRAILING_ONES=0;       AC_SUBST([GL_STDC_TRAILING_ONES])
+  GL_STDC_FIRST_LEADING_ZERO=0;  AC_SUBST([GL_STDC_FIRST_LEADING_ZERO])
+  GL_STDC_FIRST_LEADING_ONE=0;   AC_SUBST([GL_STDC_FIRST_LEADING_ONE])
+  GL_STDC_FIRST_TRAILING_ZERO=0; AC_SUBST([GL_STDC_FIRST_TRAILING_ZERO])
+  GL_STDC_FIRST_TRAILING_ONE=0;  AC_SUBST([GL_STDC_FIRST_TRAILING_ONE])
+  GL_STDC_COUNT_ZEROS=0;         AC_SUBST([GL_STDC_COUNT_ZEROS])
+  GL_STDC_COUNT_ONES=0;          AC_SUBST([GL_STDC_COUNT_ONES])
+  GL_STDC_HAS_SINGLE_BIT=0;      AC_SUBST([GL_STDC_HAS_SINGLE_BIT])
+  GL_STDC_BIT_WIDTH=0;           AC_SUBST([GL_STDC_BIT_WIDTH])
+  GL_STDC_BIT_FLOOR=0;           AC_SUBST([GL_STDC_BIT_FLOOR])
+  GL_STDC_BIT_CEIL=0;            AC_SUBST([GL_STDC_BIT_CEIL])
+])
index ea611ad1abf240017c64c2a5d18a734f25fa4e41..30d8eab7359591b98b3f9a6b56efdaffdaa61a6d 100644 (file)
@@ -23,8 +23,6 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <math.h>
 #include <stdio.h>
 
-#include <count-one-bits.h>
-#include <count-trailing-zeros.h>
 #include <intprops.h>
 
 #include "lisp.h"
@@ -3500,12 +3498,8 @@ representation.  */)
     }
 
   eassume (FIXNUMP (value));
-  EMACS_INT v = XFIXNUM (value) < 0 ? -1 - XFIXNUM (value) : XFIXNUM (value);
-  return make_fixnum (EMACS_UINT_WIDTH <= UINT_WIDTH
-                     ? count_one_bits (v)
-                     : EMACS_UINT_WIDTH <= ULONG_WIDTH
-                     ? count_one_bits_l (v)
-                     : count_one_bits_ll (v));
+  EMACS_UINT v = XFIXNUM (value) < 0 ? -1 - XFIXNUM (value) : XFIXNUM (value);
+  return make_fixnum (stdc_count_ones (v));
 }
 
 DEFUN ("ash", Fash, Sash, 2, 2, 0,
@@ -3662,36 +3656,6 @@ bool_vector_spare_mask (EMACS_INT nr_bits)
   return (((bits_word) 1) << (nr_bits % BITS_PER_BITS_WORD)) - 1;
 }
 
-/* Shift VAL right by the width of an unsigned long long.
-   ULLONG_WIDTH must be less than BITS_PER_BITS_WORD.  */
-
-static bits_word
-shift_right_ull (bits_word w)
-{
-  /* Pacify bogus GCC warning about shift count exceeding type width.  */
-  int shift = ULLONG_WIDTH - BITS_PER_BITS_WORD < 0 ? ULLONG_WIDTH : 0;
-  return w >> shift;
-}
-
-/* Return the number of 1 bits in W.  */
-
-static int
-count_one_bits_word (bits_word w)
-{
-  if (BITS_WORD_MAX <= UINT_MAX)
-    return count_one_bits (w);
-  else if (BITS_WORD_MAX <= ULONG_MAX)
-    return count_one_bits_l (w);
-  else
-    {
-      int i = 0, count = 0;
-      while (count += count_one_bits_ll (w),
-            (i += ULLONG_WIDTH) < BITS_PER_BITS_WORD)
-       w = shift_right_ull (w);
-      return count;
-    }
-}
-
 enum bool_vector_op { bool_vector_exclusive_or,
                       bool_vector_union,
                       bool_vector_intersection,
@@ -3798,55 +3762,6 @@ bool_vector_binop_driver (Lisp_Object a,
   return dest;
 }
 
-/* PRECONDITION must be true.  Return VALUE.  This odd construction
-   works around a bogus GCC diagnostic "shift count >= width of type".  */
-
-static int
-pre_value (bool precondition, int value)
-{
-  eassume (precondition);
-  return precondition ? value : 0;
-}
-
-/* Compute the number of trailing zero bits in val.  If val is zero,
-   return the number of bits in val.  */
-static int
-count_trailing_zero_bits (bits_word val)
-{
-  if (BITS_WORD_MAX == UINT_MAX)
-    return count_trailing_zeros (val);
-  if (BITS_WORD_MAX == ULONG_MAX)
-    return count_trailing_zeros_l (val);
-  if (BITS_WORD_MAX == ULLONG_MAX)
-    return count_trailing_zeros_ll (val);
-
-  /* The rest of this code is for the unlikely platform where bits_word differs
-     in width from unsigned int, unsigned long, and unsigned long long.  */
-  val |= ~ BITS_WORD_MAX;
-  if (BITS_WORD_MAX <= UINT_MAX)
-    return count_trailing_zeros (val);
-  if (BITS_WORD_MAX <= ULONG_MAX)
-    return count_trailing_zeros_l (val);
-  else
-    {
-      int count;
-      for (count = 0;
-          count < BITS_PER_BITS_WORD - ULLONG_WIDTH;
-          count += ULLONG_WIDTH)
-       {
-         if (val & ULLONG_MAX)
-           return count + count_trailing_zeros_ll (val);
-         val = shift_right_ull (val);
-       }
-
-      if (BITS_PER_BITS_WORD % ULLONG_WIDTH != 0
-         && BITS_WORD_MAX == (bits_word) -1)
-       val |= (bits_word) 1 << pre_value (ULONG_MAX < BITS_WORD_MAX,
-                                          BITS_PER_BITS_WORD % ULLONG_WIDTH);
-      return count + count_trailing_zeros_ll (val);
-    }
-}
-
 DEFUN ("bool-vector-exclusive-or", Fbool_vector_exclusive_or,
        Sbool_vector_exclusive_or, 2, 3, 0,
        doc: /* Return A ^ B, bitwise exclusive or.
@@ -3961,7 +3876,7 @@ value from A's length.  */)
   adata = bool_vector_data (a);
 
   for (i = 0; i < nwords; i++)
-    count += count_one_bits_word (adata[i]);
+    count += stdc_count_ones (adata[i]);
 
   return make_fixnum (count);
 }
@@ -4009,7 +3924,7 @@ A is a bool vector, B is t or nil, and I is an index into A.  */)
       /* Do not count the pad bits.  */
       mword |= (bits_word) 1 << (BITS_PER_BITS_WORD - offset);
 
-      count = count_trailing_zero_bits (mword);
+      count = stdc_trailing_zeros (mword);
       pos++;
       if (count + offset < BITS_PER_BITS_WORD)
         return make_fixnum (count);
@@ -4029,7 +3944,7 @@ A is a bool vector, B is t or nil, and I is an index into A.  */)
          in the current mword.  */
       mword = bits_word_to_host_endian (adata[pos]);
       mword ^= twiddle;
-      count += count_trailing_zero_bits (mword);
+      count += stdc_trailing_zeros (mword);
     }
   else if (nr_bits % BITS_PER_BITS_WORD != 0)
     {
index 8ee37f5298a664449e374101a3b5abea5c109439..d61a4d5c9829a65ca34bc2a21c5bc08d9468b781 100644 (file)
@@ -23,6 +23,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <alloca.h>
 #include <setjmp.h>
 #include <stdarg.h>
+#include <stdbit.h>
 #include <stdckdint.h>
 #include <stddef.h>
 #include <string.h>
@@ -37,7 +38,6 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 
 #include <attribute.h>
 #include <byteswap.h>
-#include <count-leading-zeros.h>
 #include <intprops.h>
 #include <verify.h>
 
@@ -4148,11 +4148,12 @@ integer_to_uintmax (Lisp_Object num, uintmax_t *n)
     }
 }
 
-/* Return floor (log2 (N)) as an int, where 0 < N <= ULLONG_MAX.  */
+/* Return floor (log2 (N)) as an int.  If N is zero, return -1.  */
 INLINE int
 elogb (unsigned long long int n)
 {
-  return ULLONG_WIDTH - 1 - count_leading_zeros_ll (n);
+  int width = stdc_bit_width (n);
+  return width - 1;
 }
 
 /* A modification count.  These are wide enough, and incremented