1 /* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word.
2 Copyright 2013-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Paul Eggert. */
19 #ifndef COUNT_TRAILING_ZEROS_H
20 #define COUNT_TRAILING_ZEROS_H 1
22 /* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE. */
23 #if !_GL_CONFIG_H_INCLUDED
24 #error "Please include config.h first."
30 _GL_INLINE_HEADER_BEGIN
31 #ifndef COUNT_TRAILING_ZEROS_INLINE
32 # define COUNT_TRAILING_ZEROS_INLINE _GL_INLINE
39 /* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
40 expand to code that computes the number of trailing zeros of the local
41 variable 'x' of type TYPE (an unsigned integer type) and return it
42 from the current function. */
43 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \
44 || (__clang_major__ >= 4)
45 # define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
46 return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
48 # pragma intrinsic (_BitScanForward)
50 # pragma intrinsic (_BitScanForward64)
52 # define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
55 unsigned long result; \
56 return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \
60 # define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
65 return CHAR_BIT * sizeof x; \
67 (count < CHAR_BIT * sizeof x - 32 \
68 && ! (x & 0xffffffffU)); \
71 return count + count_trailing_zeros_32 (x); \
75 /* Compute and return the number of trailing zeros in the least
76 significant 32 bits of X. One of these bits must be nonzero. */
77 COUNT_TRAILING_ZEROS_INLINE
int
78 count_trailing_zeros_32 (unsigned int x
)
80 /* <https://github.com/gibsjose/BitHacks>
81 <https://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
82 static const char de_Bruijn_lookup
[32] = {
83 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
84 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
86 return de_Bruijn_lookup
[(((x
& -x
) * 0x077cb531U
) & 0xffffffffU
) >> 27];
90 /* Compute and return the number of trailing zeros in X. */
91 COUNT_TRAILING_ZEROS_INLINE
int
92 count_trailing_zeros (unsigned int x
)
94 COUNT_TRAILING_ZEROS (__builtin_ctz
, _BitScanForward
, unsigned int);
97 /* Compute and return the number of trailing zeros in X. */
98 COUNT_TRAILING_ZEROS_INLINE
int
99 count_trailing_zeros_l (unsigned long int x
)
101 COUNT_TRAILING_ZEROS (__builtin_ctzl
, _BitScanForward
, unsigned long int);
104 /* Compute and return the number of trailing zeros in X. */
105 COUNT_TRAILING_ZEROS_INLINE
int
106 count_trailing_zeros_ll (unsigned long long int x
)
108 #if (defined _MSC_VER && !defined __clang__) && !defined _M_X64
109 /* 32-bit MSVC does not have _BitScanForward64, only _BitScanForward. */
110 unsigned long result
;
111 if (_BitScanForward (&result
, (unsigned long) x
))
113 if (_BitScanForward (&result
, (unsigned long) (x
>> 32)))
115 return CHAR_BIT
* sizeof x
;
117 COUNT_TRAILING_ZEROS (__builtin_ctzll
, _BitScanForward64
,
118 unsigned long long int);
126 _GL_INLINE_HEADER_END