|  | /* count-one-bits.h -- counts the number of 1-bits in a word. | 
|  | Copyright (C) 2007-2022 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 | 
|  |  | 
|  | #include <limits.h> | 
|  | #include <stdlib.h> | 
|  |  | 
|  | #ifndef _GL_INLINE_HEADER_BEGIN | 
|  | #error "Please include config.h first." | 
|  | #endif | 
|  | _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 */ |