root/lib/count-trailing-zeros.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. count_trailing_zeros_32
  2. count_trailing_zeros
  3. count_trailing_zeros_l
  4. count_trailing_zeros_ll

     1 /* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word.
     2    Copyright 2013-2023 Free Software Foundation, Inc.
     3 
     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.
     8 
     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.
    13 
    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/>.  */
    16 
    17 /* Written by Paul Eggert.  */
    18 
    19 #ifndef COUNT_TRAILING_ZEROS_H
    20 #define COUNT_TRAILING_ZEROS_H 1
    21 
    22 #include <limits.h>
    23 #include <stdlib.h>
    24 
    25 #ifndef _GL_INLINE_HEADER_BEGIN
    26  #error "Please include config.h first."
    27 #endif
    28 _GL_INLINE_HEADER_BEGIN
    29 #ifndef COUNT_TRAILING_ZEROS_INLINE
    30 # define COUNT_TRAILING_ZEROS_INLINE _GL_INLINE
    31 #endif
    32 
    33 #ifdef __cplusplus
    34 extern "C" {
    35 #endif
    36 
    37 /* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
    38    expand to code that computes the number of trailing zeros of the local
    39    variable 'x' of type TYPE (an unsigned integer type) and return it
    40    from the current function.  */
    41 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \
    42     || (__clang_major__ >= 4)
    43 # define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)               \
    44   return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
    45 #elif _MSC_VER
    46 # pragma intrinsic (_BitScanForward)
    47 # if defined _M_X64
    48 #  pragma intrinsic (_BitScanForward64)
    49 # endif
    50 # define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)               \
    51     do                                                                  \
    52       {                                                                 \
    53         unsigned long result;                                           \
    54         return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \
    55       }                                                                 \
    56     while (0)
    57 #else
    58 # define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)               \
    59     do                                                                  \
    60       {                                                                 \
    61         int count = 0;                                                  \
    62         if (! x)                                                        \
    63           return CHAR_BIT * sizeof x;                                   \
    64         for (count = 0;                                                 \
    65              (count < CHAR_BIT * sizeof x - 32                          \
    66               && ! (x & 0xffffffffU));                                  \
    67              count += 32)                                               \
    68           x = x >> 31 >> 1;                                             \
    69         return count + count_trailing_zeros_32 (x);                     \
    70       }                                                                 \
    71     while (0)
    72 
    73 /* Compute and return the number of trailing zeros in the least
    74    significant 32 bits of X.  One of these bits must be nonzero.  */
    75 COUNT_TRAILING_ZEROS_INLINE int
    76 count_trailing_zeros_32 (unsigned int x)
    77 {
    78   /* <https://github.com/gibsjose/BitHacks>
    79      <https://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
    80   static const char de_Bruijn_lookup[32] = {
    81     0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
    82     31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
    83   };
    84   return de_Bruijn_lookup[(((x & -x) * 0x077cb531U) & 0xffffffffU) >> 27];
    85 }
    86 #endif
    87 
    88 /* Compute and return the number of trailing zeros in X. */
    89 COUNT_TRAILING_ZEROS_INLINE int
    90 count_trailing_zeros (unsigned int x)
    91 {
    92   COUNT_TRAILING_ZEROS (__builtin_ctz, _BitScanForward, unsigned int);
    93 }
    94 
    95 /* Compute and return the number of trailing zeros in X. */
    96 COUNT_TRAILING_ZEROS_INLINE int
    97 count_trailing_zeros_l (unsigned long int x)
    98 {
    99   COUNT_TRAILING_ZEROS (__builtin_ctzl, _BitScanForward, unsigned long int);
   100 }
   101 
   102 /* Compute and return the number of trailing zeros in X. */
   103 COUNT_TRAILING_ZEROS_INLINE int
   104 count_trailing_zeros_ll (unsigned long long int x)
   105 {
   106 #if (defined _MSC_VER && !defined __clang__) && !defined _M_X64
   107   /* 32-bit MSVC does not have _BitScanForward64, only _BitScanForward.  */
   108   unsigned long result;
   109   if (_BitScanForward (&result, (unsigned long) x))
   110     return result;
   111   if (_BitScanForward (&result, (unsigned long) (x >> 32)))
   112     return result + 32;
   113   return CHAR_BIT * sizeof x;
   114 #else
   115   COUNT_TRAILING_ZEROS (__builtin_ctzll, _BitScanForward64,
   116                         unsigned long long int);
   117 #endif
   118 }
   119 
   120 #ifdef __cplusplus
   121 }
   122 #endif
   123 
   124 _GL_INLINE_HEADER_END
   125 
   126 #endif

/* [<][>][^][v][top][bottom][index][help] */