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 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.
This commit is contained in:
Paul Eggert 2024-05-12 14:22:58 -07:00
parent 08550d058f
commit 88b0bb4db9
16 changed files with 1320 additions and 593 deletions

View 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'.

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View 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 \
@ -156,6 +153,9 @@
# 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

23
lib/stdbit.c Normal file
View file

@ -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>

1077
lib/stdbit.in.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
/* Count the number of trailing 0 bits in a word.
Copyright 2013-2024 Free Software Foundation, Inc.
/* 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
@ -17,5 +16,5 @@
#include <config.h>
#define COUNT_TRAILING_ZEROS_INLINE _GL_EXTERN_INLINE
#include "count-trailing-zeros.h"
#define _GL_STDC_BIT_WIDTH_INLINE _GL_EXTERN_INLINE
#include <stdbit.h>

View file

@ -1,6 +1,5 @@
/* Count the number of 1-bits in a word.
Copyright (C) 2012-2024 Free Software Foundation, Inc.
/* 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
@ -17,9 +16,9 @@
#include <config.h>
#define COUNT_ONE_BITS_INLINE _GL_EXTERN_INLINE
#include "count-one-bits.h"
#define _GL_STDC_COUNT_ONES_INLINE _GL_EXTERN_INLINE
#include <stdbit.h>
#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
int popcount_support = -1;
signed char __gl_stdbit_popcount_support;
#endif

View file

@ -1,6 +1,5 @@
/* Count the number of leading 0 bits in a word.
Copyright (C) 2012-2024 Free Software Foundation, Inc.
/* 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
@ -17,5 +16,5 @@
#include <config.h>
#define COUNT_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE
#include "count-leading-zeros.h"
#define _GL_STDC_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE
#include <stdbit.h>

20
lib/stdc_trailing_zeros.c Normal file
View file

@ -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>

View 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

37
m4/stdbit_h.m4 Normal file
View file

@ -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])
])

View 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)
{

View 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