root/lib/count-leading-zeros.h

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. count_leading_zeros_32
  2. count_leading_zeros
  3. count_leading_zeros_l
  4. count_leading_zeros_ll

     1 /* count-leading-zeros.h -- counts the number of leading 0 bits in a word.
     2    Copyright (C) 2012-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 Eric Blake.  */
    18 
    19 #ifndef COUNT_LEADING_ZEROS_H
    20 #define COUNT_LEADING_ZEROS_H 1
    21 
    22 /* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE.  */
    23 #if !_GL_CONFIG_H_INCLUDED
    24  #error "Please include config.h first."
    25 #endif
    26 
    27 #include <limits.h>
    28 #include <stdlib.h>
    29 
    30 _GL_INLINE_HEADER_BEGIN
    31 #ifndef COUNT_LEADING_ZEROS_INLINE
    32 # define COUNT_LEADING_ZEROS_INLINE _GL_INLINE
    33 #endif
    34 
    35 #ifdef __cplusplus
    36 extern "C" {
    37 #endif
    38 
    39 /* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
    40    expand to code that computes the number of leading 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_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)                \
    46   return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
    47 #elif _MSC_VER
    48 # pragma intrinsic (_BitScanReverse)
    49 # if defined _M_X64
    50 #  pragma intrinsic (_BitScanReverse64)
    51 # endif
    52 # define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)                \
    53     do                                                                  \
    54       {                                                                 \
    55         unsigned long result;                                           \
    56         if (MSC_BUILTIN (&result, x))                                   \
    57           return CHAR_BIT * sizeof x - 1 - result;                      \
    58         return CHAR_BIT * sizeof x;                                     \
    59       }                                                                 \
    60     while (0)
    61 #else
    62 # define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)                \
    63     do                                                                  \
    64       {                                                                 \
    65         int count;                                                      \
    66         unsigned int leading_32;                                        \
    67         if (! x)                                                        \
    68           return CHAR_BIT * sizeof x;                                   \
    69         for (count = 0;                                                 \
    70              (leading_32 = ((x >> (sizeof (TYPE) * CHAR_BIT - 32))      \
    71                             & 0xffffffffU),                             \
    72               count < CHAR_BIT * sizeof x - 32 && !leading_32);         \
    73              count += 32)                                               \
    74           x = x << 31 << 1;                                             \
    75         return count + count_leading_zeros_32 (leading_32);             \
    76       }                                                                 \
    77     while (0)
    78 
    79 /* Compute and return the number of leading zeros in X,
    80    where 0 < X < 2**32.  */
    81 COUNT_LEADING_ZEROS_INLINE int
    82 count_leading_zeros_32 (unsigned int x)
    83 {
    84   /* <https://github.com/gibsjose/BitHacks>
    85      <https://www.fit.vutbr.cz/~ibarina/pub/bithacks.pdf> */
    86   static const char de_Bruijn_lookup[32] = {
    87     31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,
    88     23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0
    89   };
    90 
    91   x |= x >> 1;
    92   x |= x >> 2;
    93   x |= x >> 4;
    94   x |= x >> 8;
    95   x |= x >> 16;
    96   return de_Bruijn_lookup[((x * 0x07c4acddU) & 0xffffffffU) >> 27];
    97 }
    98 #endif
    99 
   100 /* Compute and return the number of leading zeros in X. */
   101 COUNT_LEADING_ZEROS_INLINE int
   102 count_leading_zeros (unsigned int x)
   103 {
   104   COUNT_LEADING_ZEROS (__builtin_clz, _BitScanReverse, unsigned int);
   105 }
   106 
   107 /* Compute and return the number of leading zeros in X. */
   108 COUNT_LEADING_ZEROS_INLINE int
   109 count_leading_zeros_l (unsigned long int x)
   110 {
   111   COUNT_LEADING_ZEROS (__builtin_clzl, _BitScanReverse, unsigned long int);
   112 }
   113 
   114 /* Compute and return the number of leading zeros in X. */
   115 COUNT_LEADING_ZEROS_INLINE int
   116 count_leading_zeros_ll (unsigned long long int x)
   117 {
   118 #if (defined _MSC_VER && !defined __clang__) && !defined _M_X64
   119   /* 32-bit MSVC does not have _BitScanReverse64, only _BitScanReverse.  */
   120   unsigned long result;
   121   if (_BitScanReverse (&result, (unsigned long) (x >> 32)))
   122     return CHAR_BIT * sizeof x - 1 - 32 - result;
   123   if (_BitScanReverse (&result, (unsigned long) x))
   124     return CHAR_BIT * sizeof x - 1 - result;
   125   return CHAR_BIT * sizeof x;
   126 #else
   127   COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64,
   128                        unsigned long long int);
   129 #endif
   130 }
   131 
   132 #ifdef __cplusplus
   133 }
   134 #endif
   135 
   136 _GL_INLINE_HEADER_END
   137 
   138 #endif /* COUNT_LEADING_ZEROS_H */

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