* bug#70898: switching to <stdbit.h> for Emacs bit ops
@ 2024-05-12 22:09 Paul Eggert
2024-05-13 14:34 ` Mattias Engdegård
0 siblings, 1 reply; 5+ messages in thread
From: Paul Eggert @ 2024-05-12 22:09 UTC (permalink / raw)
To: 70898
[-- Attachment #1: Type: text/plain, Size: 1016 bytes --]
Emacs currently uses the Gnulib headers count-trailing-zeros.h and
count-one-bits.h to do some low-level bit operations efficiently. C23
has standardized this in a new header <stdbit.h> and I've recently added
support for a Gnulib <stdbit.h> substitute, taking implementation ideas
from count-trailing-zeros.h, count-one-bits.h and elsewhere. So I'm
planning to switch Emacs to the C23 standard way of doing things, using
the Gnulib substitute on non-C23 platforms.
The first attached patch does this. I plan to test this somewhat more
before installing, but thought I'd give people a heads-up.
The second attached patch is a minor cleanup to the 32-bit Android code,
a cleanup made possible by the first attached patch. This cleanup patch
is optional of course. By the way, I'm surprised to see the code in
sfmt.c implementing 64-bit arithmetic from pairs of 32-bit words, as I
thought even ancient 32-bit Android has 64-bit 'unsigned long long', but
that's a matter for the Android experts I suppose.
[-- Attachment #2: 0001-Prefer-stdbit.h-to-count-one-bits.h-etc.patch --]
[-- Type: text/x-patch, Size: 64051 bytes --]
From 674e1adaa4335e9e9e628394a688d2e609071357 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 12 May 2024 14:22:58 -0700
Subject: [PATCH 1/2] Prefer stdbit.h to count-one-bits.h etc
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 stdbit.
* 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, 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.
---
INSTALL.REPO | 2 +-
admin/merge-gnulib | 4 +-
lib/count-leading-zeros.c | 21 -
lib/count-leading-zeros.h | 138 ------
lib/count-one-bits.c | 25 --
lib/count-one-bits.h | 166 -------
lib/count-trailing-zeros.c | 21 -
lib/count-trailing-zeros.h | 128 ------
lib/gnulib.mk.in | 62 ++-
lib/stdbit.c | 51 +++
lib/stdbit.in.h | 886 +++++++++++++++++++++++++++++++++++++
m4/gnulib-comp.m4 | 30 +-
m4/stdbit_h.m4 | 19 +
src/data.c | 95 +---
src/lisp.h | 7 +-
15 files changed, 1018 insertions(+), 637 deletions(-)
delete mode 100644 lib/count-leading-zeros.c
delete mode 100644 lib/count-leading-zeros.h
delete mode 100644 lib/count-one-bits.c
delete mode 100644 lib/count-one-bits.h
delete mode 100644 lib/count-trailing-zeros.c
delete mode 100644 lib/count-trailing-zeros.h
create mode 100644 lib/stdbit.c
create mode 100644 lib/stdbit.in.h
create mode 100644 m4/stdbit_h.m4
diff --git a/INSTALL.REPO b/INSTALL.REPO
index 77d8153a5a8..46ac4440aee 100644
--- a/INSTALL.REPO
+++ b/INSTALL.REPO
@@ -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'.
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index c4daaded015..526141d86ea 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -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,8 @@ 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
+ stdbit stdbool 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
index 2bbfd674849..00000000000
--- a/lib/count-leading-zeros.c
+++ /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
index 545749d6d27..00000000000
--- a/lib/count-leading-zeros.h
+++ /dev/null
@@ -1,138 +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
-# pragma intrinsic (_BitScanReverse)
-# if defined _M_X64
-# 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
index 54b87088028..00000000000
--- a/lib/count-one-bits.c
+++ /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
index 8d67f8718a4..00000000000
--- a/lib/count-one-bits.h
+++ /dev/null
@@ -1,166 +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. */
-# pragma intrinsic (__cpuid)
-# pragma intrinsic (__popcnt)
-# if defined _M_X64
-# 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
index e13f77788da..00000000000
--- a/lib/count-trailing-zeros.c
+++ /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
index ed1e0131147..00000000000
--- a/lib/count-trailing-zeros.h
+++ /dev/null
@@ -1,128 +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
-# pragma intrinsic (_BitScanForward)
-# if defined _M_X64
-# 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
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index a5c009cfb85..fecc3182456 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -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 \
@@ -155,6 +152,7 @@
# socklen \
# stat-time \
# std-gnu11 \
+# stdbit \
# stdbool \
# stdckdint \
# stddef \
@@ -358,6 +356,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@
@@ -1313,6 +1312,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@
@@ -1442,6 +1442,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@
@@ -1718,36 +1719,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))
@@ -3049,6 +3020,29 @@ EXTRA_DIST += stat-time.h
endif
## end gnulib module stat-time
+## begin gnulib module stdbit
+ifeq (,$(OMIT_GNULIB_MODULE_stdbit))
+
+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)cp $(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
+
## begin gnulib module stdckdint
ifeq (,$(OMIT_GNULIB_MODULE_stdckdint))
@@ -4269,7 +4263,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
index 00000000000..d369dc569d9
--- /dev/null
+++ b/lib/stdbit.c
@@ -0,0 +1,51 @@
+/* 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>
+
+#if !defined _GL_STDBIT_HAS_BUILTIN_CLZ && !_MSC_VER
+/* __gl_stdbit_clztab[B] is the number of leading zeros in
+ the 8-bit byte with value B. */
+unsigned char const __gl_stdbit_clztab[256] =
+ {
+ 8,
+ 7,
+ 6, 6,
+ 5, 5, 5, 5,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ /* The rest is zero. */
+ };
+#endif
+
+#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
+signed char __gl_stdbit_popcount_support;
+#endif
diff --git a/lib/stdbit.in.h b/lib/stdbit.in.h
new file mode 100644
index 00000000000..105cfd8c8b9
--- /dev/null
+++ b/lib/stdbit.in.h
@@ -0,0 +1,886 @@
+/* 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Bytes must be 8 bits, as POSIX requires. This implementation uses
+ 8 instead of CHAR_BIT to avoid namespace pollution. */
+static_assert ((unsigned char) -1 == (1 << 8) - 1);
+
+/* 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
+
+#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 zeros of nonzero N. */
+#ifdef _GL_STDBIT_HAS_BUILTIN_CLZ
+_GL_STDBIT_INLINE int
+__gl_stdbit_clz (unsigned int n)
+{
+ return n ? __builtin_clzl (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
+# pragma intrinsic (_BitScanReverse)
+# ifdef _M_X64
+# 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 - (_BitScanReverse (&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 */
+
+extern unsigned char const __gl_stdbit_clztab[256];
+
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzll (unsigned long long int n)
+{
+ static_assert (8 * sizeof n <= 1 << 7);
+ int r = 0;
+ int a6 = (0xffffffffffffffff < n) << 6; n >>= a6; r |= a6;
+ 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 clzbyte = __gl_stdbit_clztab[n];
+ return (8 * (sizeof n - 1) - r) + clzbyte;
+}
+_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
+
+#ifdef _GL_STDBIT_HAS_BUILTIN_CTZ
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctz (unsigned int n)
+{
+ return n ? __builtin_ctzl (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
+# pragma intrinsic (_BitScanForward)
+# ifdef _M_X64
+# 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
+_GL_STDBIT_INLINE int
+}
+
+#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
+
+#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
+/* Count the number of 1 bits in N. */
+_GL_STDBIT_INLINE int
+__gl_stdbit_popcount255 (unsigned long long int n)
+{
+ 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... */
+ n -= (n >> 1) & x555555;
+ n = (n & x333333) + ((n >> 2) & x333333);
+ n = (n + (n >> 4)) & x0f0f0f;
+
+ /* The multiplication means the popcount should fit in the leading 8
+ bits of the product, so N should be narrower than 256 bits. */
+ static_assert (8 * sizeof n < 1 << 8);
+ return n * x010101 >> 8 * (sizeof n - 1);
+}
+
+# ifdef _MSC_VER
+# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
+# pragma intrinsic (__cpuid)
+# pragma intrinsic (__popcnt)
+# ifdef _M_X64
+# pragma intrinsic (__popcnt64)
+# else
+_GL_STDBIT_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_stdint_popcount_support;
+
+_GL_STDBIT_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_STDBIT_INLINE int
+__gl_stdbit_popcount (unsigned int n)
+{
+ return (__gl_stdbit_popcount_supported ()
+ ? __popcnt (n)
+ : __gl_stdbit_popcount255 (n));
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_popcountl (unsigned long int n)
+{
+ return (__gl_stdbit_popcount_supported ()
+ ? __popcnt (n)
+ : __gl_stdbit_popcount255 (n));
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_popcountll (unsigned long long int n)
+{
+ return (__gl_stdbit_popcount_supported ()
+ ? __popcnt64 (n)
+ : __gl_stdbit_popcount255 (n));
+}
+# else /* !_MSC_VER */
+# define __gl_stdbit_popcount __gl_stdbit_popcount255
+# define __gl_stdbit_popcountl __gl_stdbit_popcount255
+# define __gl_stdbit_popcountll __gl_stdbit_popcount255
+# endif
+#endif
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_ui (unsigned int n)
+{
+ return __gl_stdbit_clz (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_uc (unsigned char n)
+{
+ return stdc_leading_zeros_ui (n) - 8 * (sizeof 0u - sizeof n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_us (unsigned short int n)
+{
+ return stdc_leading_zeros_ui (n) - 8 * (sizeof 0u - sizeof n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_zeros_ul (unsigned long int n)
+{
+ return __gl_stdbit_clzl (n);
+}
+
+_GL_STDBIT_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))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_uc (unsigned char n)
+{
+ return stdc_leading_zeros_uc (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_us (unsigned short int n)
+{
+ return stdc_leading_zeros_us (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_ui (unsigned int n)
+{
+ return stdc_leading_zeros_ui (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_leading_ones_ul (unsigned long int n)
+{
+ return stdc_leading_zeros_ul (~n);
+}
+
+_GL_STDBIT_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))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_ui (unsigned int n)
+{
+ return __gl_stdbit_ctz (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_uc (unsigned char n)
+{
+ return stdc_trailing_zeros_ui (n | (1 + (unsigned char) -1));
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_us (unsigned short int n)
+{
+ return stdc_trailing_zeros_ui (n | (1 + (unsigned short int) -1));
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_zeros_ul (unsigned long int n)
+{
+ return __gl_stdbit_ctzl (n);
+}
+
+_GL_STDBIT_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))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_uc (unsigned char n)
+{
+ return stdc_trailing_zeros_uc (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_us (unsigned short int n)
+{
+ return stdc_trailing_zeros_us (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_ui (unsigned int n)
+{
+ return stdc_trailing_zeros_ui (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_trailing_ones_ul (unsigned long int n)
+{
+ return stdc_trailing_zeros_ul (~n);
+}
+
+_GL_STDBIT_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))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_first_leading_zero_uc (unsigned char n)
+{
+ unsigned int count = stdc_leading_ones_uc (n);
+ bool big = count & 8 * sizeof 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_ones_ui (unsigned int n)
+{
+ return __gl_stdbit_popcount (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_ones_uc (unsigned char n)
+{
+ return stdc_count_ones_ui (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_ones_us (unsigned short int n)
+{
+ return stdc_count_ones_ui (n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_ones_ul (unsigned long int n)
+{
+ return __gl_stdbit_popcountl (n);
+}
+
+_GL_STDBIT_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))
+
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_uc (unsigned char n)
+{
+ return stdc_count_ones_uc (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_us (unsigned short int n)
+{
+ return stdc_count_ones_us (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_ui (unsigned int n)
+{
+ return stdc_count_ones_ui (~n);
+}
+
+_GL_STDBIT_INLINE unsigned int
+stdc_count_zeros_ul (unsigned long int n)
+{
+ return stdc_count_ones_ul (~n);
+}
+
+_GL_STDBIT_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))
+
+
+_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/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 37f180a8955..9fa5f458660 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -63,9 +63,6 @@ AC_DEFUN
# 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,6 +171,7 @@ AC_DEFUN
# Code from module ssize_t:
# Code from module stat-time:
# Code from module std-gnu11:
+ # Code from module stdbit:
# Code from module stdbool:
# Code from module stdckdint:
# Code from module stddef:
@@ -514,6 +512,9 @@ AC_DEFUN
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_CHECK_HEADERS_ONCE([stdckdint.h])
if test $ac_cv_header_stdckdint_h = yes; then
@@ -673,6 +674,7 @@ AC_DEFUN
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 +955,12 @@ AC_DEFUN
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 +1024,9 @@ AC_DEFUN
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 +1036,9 @@ AC_DEFUN
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 +1079,7 @@ AC_DEFUN
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, [
@@ -1275,12 +1290,6 @@ AC_DEFUN
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
@@ -1413,6 +1422,8 @@ AC_DEFUN
lib/signal.in.h
lib/stat-time.c
lib/stat-time.h
+ lib/stdbit.c
+ lib/stdbit.in.h
lib/stdckdint.in.h
lib/stddef.in.h
lib/stdint.in.h
@@ -1566,6 +1577,7 @@ AC_DEFUN
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
index 00000000000..3c07bdc6694
--- /dev/null
+++ b/m4/stdbit_h.m4
@@ -0,0 +1,19 @@
+# stdbit_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/src/data.c b/src/data.c
index ea611ad1abf..30d8eab7359 100644
--- a/src/data.c
+++ b/src/data.c
@@ -23,8 +23,6 @@
#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 @@ DEFUN ("logcount", Flogcount, Slogcount, 1, 1, 0,
}
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 @@ DEFUN ("bool-vector-count-population", Fbool_vector_count_population,
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 @@ DEFUN ("bool-vector-count-consecutive", Fbool_vector_count_consecutive,
/* 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 @@ DEFUN ("bool-vector-count-consecutive", Fbool_vector_count_consecutive,
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)
{
diff --git a/src/lisp.h b/src/lisp.h
index 41f8af35e8a..d33a760c37a 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -23,6 +23,7 @@ #define EMACS_LISP_H
#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 @@ #define EMACS_LISP_H
#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
--
2.44.0
[-- Attachment #3: 0002-Simplify-32-bit-Android-bit-fiddling.patch --]
[-- Type: text/x-patch, Size: 1918 bytes --]
From eee44e35c13356193a615f9cf21b5f417b421152 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 12 May 2024 14:26:32 -0700
Subject: [PATCH 2/2] Simplify 32-bit Android bit fiddling
* src/sfnt.c: Include stdbit.h.
(sfnt_count_leading_zero_bits) [!INT64_MAX]: Remove this function,
which was confusingly named as it actually returned 31 minus the
number of leading zero bits.
(sfnt_multiply_divide_2) [!INT64_MAX]: Use stdc_leading_zeros instead.
---
src/sfnt.c | 42 ++----------------------------------------
1 file changed, 2 insertions(+), 40 deletions(-)
diff --git a/src/sfnt.c b/src/sfnt.c
index d909fba7677..1832082e4f9 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -27,6 +27,7 @@ Copyright (C) 2023-2024 Free Software Foundation, Inc.
#include <fcntl.h>
#include <intprops.h>
#include <inttypes.h>
+#include <stdbit.h>
#include <stdckdint.h>
#include <stdint.h>
#include <stdio.h>
@@ -3678,45 +3679,6 @@ sfnt_multiply_divide_1 (unsigned int a, unsigned int b,
value->high = hi;
}
-/* Count the number of most significant zero bits in N. */
-
-static unsigned int
-sfnt_count_leading_zero_bits (unsigned int n)
-{
- int shift;
-
- shift = 0;
-
- if (n & 0xffff0000ul)
- {
- n >>= 16;
- shift += 16;
- }
-
- if (n & 0x0000ff00ul)
- {
- n >>= 8;
- shift += 8;
- }
-
- if (n & 0x000000f0ul)
- {
- n >>= 4;
- shift += 4;
- }
-
- if (n & 0x0000000cul)
- {
- n >>= 2;
- shift += 2;
- }
-
- if (n & 0x00000002ul)
- shift += 1;
-
- return shift;
-}
-
/* Calculate AB / C. Value is a 32 bit unsigned integer. */
static unsigned int
@@ -3730,7 +3692,7 @@ sfnt_multiply_divide_2 (struct sfnt_large_integer *ab,
hi = ab->high;
lo = ab->low;
- i = 31 - sfnt_count_leading_zero_bits (hi);
+ i = stdc_leading_zeros (hi);
r = (hi << i) | (lo >> (32 - i));
lo <<= i;
q = r / c;
--
2.44.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* bug#70898: switching to <stdbit.h> for Emacs bit ops
2024-05-12 22:09 bug#70898: switching to <stdbit.h> for Emacs bit ops Paul Eggert
@ 2024-05-13 14:34 ` Mattias Engdegård
2024-05-13 16:56 ` Paul Eggert
0 siblings, 1 reply; 5+ messages in thread
From: Mattias Engdegård @ 2024-05-13 14:34 UTC (permalink / raw)
To: Paul Eggert; +Cc: 70898
Has C23 been frozen yet? The most recent accessible draft I could find was N3096.
Overall happy with the changes but haven't read them in detail.
Minor things I stumbled upon:
> @@ -4269,7 +4263,9 @@ endif
> ## begin gnulib module verify
> ifeq (,$(OMIT_GNULIB_MODULE_verify))
>
> +ifneq (,$(gl_GNULIB_ENABLED_verify_CONDITION))
>
> +endif
Unfinished work?
> +/* 1 if supported, -1 if not, 0 if unknown. */
> +extern signed char __gl_stdint_popcount_support;
`__gl_stdbit_popcount_support`, maybe?
(By the way, in case you are on the WG: the N3096 draft has
> 7.18.8 First Leading One
...
> Returns the most significant index of the first 1 bit in value, plus 1.
Someone jumbled that sentence. Something like "the index of the most significant 1 bit" was probably intended.
^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#70898: switching to <stdbit.h> for Emacs bit ops
2024-05-13 14:34 ` Mattias Engdegård
@ 2024-05-13 16:56 ` Paul Eggert
2024-05-14 11:11 ` Mattias Engdegård
2024-05-18 17:32 ` Paul Eggert
0 siblings, 2 replies; 5+ messages in thread
From: Paul Eggert @ 2024-05-13 16:56 UTC (permalink / raw)
To: Mattias Engdegård; +Cc: 70898
On 2024-05-13 07:34, Mattias Engdegård wrote:
> Has C23 been frozen yet? The most recent accessible draft I could find was N3096.
It's not final, but it's pretty frozen. I doubt whether the stdbit spec
will change.
Yes, n3096 is the latest public draft.
> Overall happy with the changes but haven't read them in detail.
> Minor things I stumbled upon:
>
>> @@ -4269,7 +4263,9 @@ endif
>> ## begin gnulib module verify
>> ifeq (,$(OMIT_GNULIB_MODULE_verify))
>>
>> +ifneq (,$(gl_GNULIB_ENABLED_verify_CONDITION))
>>
>> +endif
>
> Unfinished work?
That was generated automatically by gnulib-tool and is harmless. That
being said, I installed a change to the Gnulib stdbit module for other
reasons (porting to theoretical platforms where C integers are wider
than 256 bits!) here:
https://git.savannah.gnu.org/cgit/gnulib.git/commit/?id=9768940fbd11558b8dab3453aa419a3433933d50
and I expect that will remove the harmless code by removing the
conditional dependency on Gnulib's assert-h module.
>> +/* 1 if supported, -1 if not, 0 if unknown. */
>> +extern signed char __gl_stdint_popcount_support;
>
> `__gl_stdbit_popcount_support`, maybe?
Thanks, fixed here:
https://git.savannah.gnu.org/cgit/gnulib.git/commit/?id=9deb8e8891e36968deeb93bd666670f7950d1095
> (By the way, in case you are on the WG: the N3096 draft has
Yes, that text is weird and I also didn't have a clue as to what it
meant. So I cloned latest glibc+gcc behavior and hoped for the best.
I have avoided dealing with that WG for decades as my political skills,
such as they are, are better deployed elsewhere. But you're welcome to
file a bug report.
^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#70898: switching to <stdbit.h> for Emacs bit ops
2024-05-13 16:56 ` Paul Eggert
@ 2024-05-14 11:11 ` Mattias Engdegård
2024-05-18 17:32 ` Paul Eggert
1 sibling, 0 replies; 5+ messages in thread
From: Mattias Engdegård @ 2024-05-14 11:11 UTC (permalink / raw)
To: Paul Eggert; +Cc: 70898
13 maj 2024 kl. 18.56 skrev Paul Eggert <eggert@cs.ucla.edu>:
> (porting to theoretical platforms where C integers are wider than 256 bits!)
Impressive! Now all we need is a run-time parametrisable C compiler that can use arbitrary integer sizes, so that your work can be tested.
(Actually that would be incredibly useful for portability work, if only.)
> Yes, that text is weird and I also didn't have a clue as to what it meant. So I cloned latest glibc+gcc behavior and hoped for the best.
Indeed I misunderstood the text and the stdc_find_{first,last} functions look pretty useless. Good to know.
^ permalink raw reply [flat|nested] 5+ messages in thread
* bug#70898: switching to <stdbit.h> for Emacs bit ops
2024-05-13 16:56 ` Paul Eggert
2024-05-14 11:11 ` Mattias Engdegård
@ 2024-05-18 17:32 ` Paul Eggert
1 sibling, 0 replies; 5+ messages in thread
From: Paul Eggert @ 2024-05-18 17:32 UTC (permalink / raw)
To: 70898
I installed an updated version of the patch (updated because Gnulib
mutated) and am closing the bug report.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-05-18 17:32 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-12 22:09 bug#70898: switching to <stdbit.h> for Emacs bit ops Paul Eggert
2024-05-13 14:34 ` Mattias Engdegård
2024-05-13 16:56 ` Paul Eggert
2024-05-14 11:11 ` Mattias Engdegård
2024-05-18 17:32 ` Paul Eggert
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.