| /* count-one-bits.h -- counts the number of 1-bits in a word. | |
| Copyright (C) 2007-2026 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; \ | |
| for (int 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 */ |