+/* 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
-#define COUNT_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE
-#define COUNT_TRAILING_ZEROS_INLINE _GL_EXTERN_INLINE
-#define COUNT_ONE_BITS_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. */
+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)
-int popcount_support = -1;
+signed char __gl_stdbit_popcount_support;
#endif
#error "Please include config.h first."
#endif
-/* Taken from count-leading-zeros.h. */
-#include <limits.h>
-#include <stdlib.h>
-
_GL_INLINE_HEADER_BEGIN
-#ifndef COUNT_LEADING_ZEROS_INLINE
-# define COUNT_LEADING_ZEROS_INLINE _GL_INLINE
+#ifndef _GL_STDBIT_INLINE
+# define _GL_STDBIT_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)
+/* 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
-# 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];
-}
+/* 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
-/* 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);
-}
+#define __STDC_VERSION_STDBIT_H__ 202311L
-/* 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;
+#define __STDC_ENDIAN_BIG__ 4321
+#define __STDC_ENDIAN_LITTLE__ 1234
+#ifdef WORDS_BIGENDIAN
+# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_BIG__
#else
- COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64,
- unsigned long long int);
+# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_LITTLE__
#endif
-}
#ifdef __cplusplus
-}
+extern "C" {
#endif
-_GL_INLINE_HEADER_END
+#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
-/* Taken from count-trailing-zeros.h. */
-#include <limits.h>
-#include <stdlib.h>
+/* Count leading zeros of nonzero N. */
+#ifdef _GL_STDBIT_HAS_BUILTIN_CLZ
+# define __gl_stdbit_clz __builtin_clz
+# define __gl_stdbit_clzl __builtin_clzl
+# define __gl_stdbit_clzll __builtin_clzll
+#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;
+ _BitScanReverse (&r, n);
+ return 8 * sizeof n - 1 - r;
+}
+_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;
+ _BitScanReverse64 (&r, n);
+ return 64 - 1 - r;
+# else
+ unsigned long int hi = n >> 32;
+ return __gl_stdbit_clzl (hi ? hi : n) + (hi ? 0 : 32);
+# endif
+}
-_GL_INLINE_HEADER_BEGIN
-#ifndef COUNT_TRAILING_ZEROS_INLINE
-# define COUNT_TRAILING_ZEROS_INLINE _GL_INLINE
-#endif
+#else /* !_MSC_VER */
-#ifdef __cplusplus
-extern "C" {
+extern 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;
+ return (8 * (sizeof n - 1) - r) | __gl_stdbit_clztab[n];
+}
+_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
-/* 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
+#ifdef _GL_STDBIT_HAS_BUILTIN_CTZ
+# define __gl_stdbit_ctz __builtin_ctz
+# define __gl_stdbit_ctzl __builtin_ctzl
+# define __gl_stdbit_ctzll __builtin_ctzll
+#elif defined _MSC_VER
# pragma intrinsic (_BitScanForward)
-# if defined _M_X64
+# ifdef _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];
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzl (unsigned long int n)
+{
+ unsigned long int r;
+ _BitScanForward (&r, n);
+ return r;
}
-#endif
-
-/* Compute and return the number of trailing zeros in X. */
-COUNT_TRAILING_ZEROS_INLINE int
-count_trailing_zeros (unsigned int x)
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctz (unsigned int n)
{
- COUNT_TRAILING_ZEROS (__builtin_ctz, _BitScanForward, unsigned int);
+ return __gl_stdbit_ctzl (n);
}
-
-/* Compute and return the number of trailing zeros in X. */
-COUNT_TRAILING_ZEROS_INLINE int
-count_trailing_zeros_l (unsigned long int x)
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzll (unsigned long long int n)
{
- COUNT_TRAILING_ZEROS (__builtin_ctzl, _BitScanForward, unsigned long int);
+# ifdef _M_X64
+ unsigned long int r;
+ _BitScanForward64 (&r, n);
+ return r;
+# else
+ unsigned int lo = n;
+ return __gl_stdbit_ctzl (lo ? lo : n >> 32) + (lo ? 0 : 32);
+# endif
+_GL_STDBIT_INLINE 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)
+#else /* !_MSC_VER */
+
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctz (unsigned int n)
{
-#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
+ return 8 * sizeof n - 1 - __gl_stdbit_clz (n & -n);
}
-
-#ifdef __cplusplus
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzl (unsigned long int n)
+{
+ return 8 * sizeof n - 1 - __gl_stdbit_clzl (n & -n);
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzll (unsigned long long int n)
+{
+ return 8 * sizeof n - 1 - __gl_stdbit_clzll (n & -n);
}
#endif
-_GL_INLINE_HEADER_END
-
-/* Taken from count-one-bits.h. */
-#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)
+#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
-
-/* 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. */
+/* 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)
-# if defined _M_X64
+# ifdef _M_X64
# pragma intrinsic (__popcnt64)
-# endif
-# endif
-
-# if !defined _M_X64
-static inline __popcnt64 (unsigned long long x)
+# else
+_GL_STDBIT_INLINE int
+__popcnt64 (unsigned long long int n)
{
- return __popcnt ((unsigned int) (x >> 32)) + __popcnt ((unsigned int) x);
+ return __popcnt (n >> 32) + __popcnt (n);
}
+# endif
# endif
-/* Return nonzero if popcount is supported. */
-
-/* 1 if supported, 0 if not supported, -1 if unknown. */
-extern int popcount_support;
+/* 1 if supported, -1 if not, 0 if unknown. */
+extern signed char __gl_stdint_popcount_support;
-COUNT_ONE_BITS_INLINE int
-popcount_supported (void)
+_GL_STDBIT_INLINE bool
+__gl_stdbit_popcount_supported (void)
{
- if (popcount_support < 0)
+ if (!__gl_stdbit_popcount_support)
{
/* Do as described in
- <https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64> */
+ <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);
- popcount_support = (cpu_info[2] >> 23) & 1;
+ __gl_stdbit_popcount_support = cpu_info[2] & 1 << 23 ? 1 : -1;
}
- return popcount_support;
+ return 0 < __gl_stdbit_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)
+_GL_STDBIT_INLINE int
+__gl_stdbit_popcount (unsigned int n)
{
- COUNT_ONE_BITS (__builtin_popcount, __popcnt, unsigned int);
+ return (__gl_stdbit_popcount_supported ()
+ ? __popcnt (n)
+ : __gl_stdbit_popcount255 (n));
}
-
-/* Compute and return the number of 1-bits set in X. */
-COUNT_ONE_BITS_INLINE int
-count_one_bits_l (unsigned long int x)
+_GL_STDBIT_INLINE int
+__gl_stdbit_popcountl (unsigned long int n)
{
- COUNT_ONE_BITS (__builtin_popcountl, __popcnt, unsigned long int);
+ return (__gl_stdbit_popcount_supported ()
+ ? __popcnt (n)
+ : __gl_stdbit_popcount255 (n));
}
-
-/* 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)
+_GL_STDBIT_INLINE int
+__gl_stdbit_popcountll (unsigned long long int n)
{
- COUNT_ONE_BITS (__builtin_popcountll, __popcnt64, unsigned long long int);
+ return (__gl_stdbit_popcount_supported ()
+ ? __popcnt64 (n)
+ : __gl_stdbit_popcount255 (n));
}
-
-#ifdef __cplusplus
-}
-#endif
-
-_GL_INLINE_HEADER_END
-
-
-/* An expression, preferably with the type of A, that has the value of B. */
-#if ((defined __GNUC__ && 2 <= __GNUC__) \
- || (defined __clang_major__ && 4 <= __clang_major__) \
- || (defined __IBMC__ && 1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
- || (defined __SUNPRO_C && 0x5110 <= __SUNPRO_C && !__STDC__))
-# define _GL_STDBIT_TYPEOF_CAST(a, b) ((__typeof__ (a)) (b))
-#elif 202311 <= __STDC_VERSION__
-# define _GL_STDBIT_TYPEOF_CAST(a, b) ((typeof (a)) (b))
-#else
-/* This platform is so old that it lacks typeof, so _Generic is likely
- missing or unreliable. The C23 standard seems to allow yielding B
- (which is always unsigned long long int), so do that. */
-# define _GL_STDBIT_TYPEOF_CAST(a, b) (b)
-#endif
-
-#define __STDC_VERSION_STDBIT_H__ 202311L
-
-#define __STDC_ENDIAN_BIG__ 4321
-#define __STDC_ENDIAN_LITTLE__ 1234
-#ifdef WORDS_BIGENDIAN
-# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_BIG__
-#else
-# define __STDC_ENDIAN_NATIVE__ __STDC_ENDIAN_LITTLE__
-#endif
-
-_GL_INLINE_HEADER_BEGIN
-#ifndef _GL_STDBIT_INLINE
-# define _GL_STDBIT_INLINE _GL_INLINE
-#endif
-
-#ifdef __cplusplus
-extern "C" {
+# 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 count_leading_zeros (n);
+ return n ? __gl_stdbit_clz (n) : 8 * sizeof n;
}
_GL_STDBIT_INLINE unsigned int
_GL_STDBIT_INLINE unsigned int
stdc_leading_zeros_ul (unsigned long int n)
{
- return count_leading_zeros_l (n);
+ return n ? __gl_stdbit_clzl (n) : 8 * sizeof n;
}
_GL_STDBIT_INLINE unsigned int
stdc_leading_zeros_ull (unsigned long long int n)
{
- return count_leading_zeros_ll (n);
+ return n ? __gl_stdbit_clzll (n) : 8 * sizeof n;
}
#define stdc_leading_zeros(n) \
_GL_STDBIT_INLINE unsigned int
stdc_trailing_zeros_ui (unsigned int n)
{
- return count_trailing_zeros (n);
+ return n ? __gl_stdbit_ctz (n) : 8 * sizeof n;
}
_GL_STDBIT_INLINE unsigned int
_GL_STDBIT_INLINE unsigned int
stdc_trailing_zeros_ul (unsigned long int n)
{
- return count_trailing_zeros_l (n);
+ return n ? __gl_stdbit_ctzl (n) : 8 * sizeof n;
}
_GL_STDBIT_INLINE unsigned int
stdc_trailing_zeros_ull (unsigned long long int n)
{
- return count_trailing_zeros_ll (n);
+ return n ? __gl_stdbit_ctzll (n) : 8 * sizeof n;
}
#define stdc_trailing_zeros(n) \
_GL_STDBIT_INLINE unsigned int
stdc_count_ones_ui (unsigned int n)
{
- return count_one_bits (n);
+ return __gl_stdbit_popcount (n);
}
_GL_STDBIT_INLINE unsigned int
_GL_STDBIT_INLINE unsigned int
stdc_count_ones_ul (unsigned long int n)
{
- return count_one_bits_l (n);
+ return __gl_stdbit_popcountl (n);
}
_GL_STDBIT_INLINE unsigned int
stdc_count_ones_ull (unsigned long long int n)
{
- return count_one_bits_ll (n);
+ return __gl_stdbit_popcountll (n);
}
#define stdc_count_ones(n) \