tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

bitops.h (3407B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 #ifndef AOM_AOM_PORTS_BITOPS_H_
     13 #define AOM_AOM_PORTS_BITOPS_H_
     14 
     15 #include <assert.h>
     16 #include <stdint.h>
     17 
     18 #include "config/aom_config.h"
     19 
     20 #ifdef _MSC_VER
     21 #if defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_ARM)
     22 #include <intrin.h>
     23 #define USE_MSC_INTRINSICS
     24 #endif
     25 #endif
     26 
     27 #ifdef __cplusplus
     28 extern "C" {
     29 #endif
     30 
     31 // get_msb:
     32 // Returns (int)floor(log2(n)). n must be > 0.
     33 // These versions of get_msb() are only valid when n != 0 because all
     34 // of the optimized versions are undefined when n == 0:
     35 
     36 // GCC compiler: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
     37 // MSVC: https://learn.microsoft.com/en-us/cpp/intrinsics/compiler-intrinsics
     38 
     39 // use GNU builtins where available.
     40 #if defined(__GNUC__) && \
     41    ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
     42 static inline int get_msb(unsigned int n) {
     43  assert(n != 0);
     44  return 31 ^ __builtin_clz(n);
     45 }
     46 #elif defined(USE_MSC_INTRINSICS)
     47 #pragma intrinsic(_BitScanReverse)
     48 
     49 static inline int get_msb(unsigned int n) {
     50  unsigned long first_set_bit;
     51  assert(n != 0);
     52  _BitScanReverse(&first_set_bit, n);
     53  return first_set_bit;
     54 }
     55 #else
     56 static inline int get_msb(unsigned int n) {
     57  int log = 0;
     58  unsigned int value = n;
     59 
     60  assert(n != 0);
     61 
     62  for (int shift = 16; shift != 0; shift >>= 1) {
     63    const unsigned int x = value >> shift;
     64    if (x != 0) {
     65      value = x;
     66      log += shift;
     67    }
     68  }
     69  return log;
     70 }
     71 #endif
     72 
     73 // Returns (int)ceil(log2(n)).
     74 static inline int aom_ceil_log2(int n) {
     75  if (n < 2) return 0;
     76  return get_msb(n - 1) + 1;
     77 }
     78 
     79 #if defined(__GNUC__) && \
     80    ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
     81 static inline int aom_clzll(uint64_t n) { return __builtin_clzll(n); }
     82 #elif defined(USE_MSC_INTRINSICS)
     83 #if defined(_M_X64) || defined(_M_ARM64)
     84 #pragma intrinsic(_BitScanReverse64)
     85 #endif
     86 
     87 static inline int aom_clzll(uint64_t n) {
     88  assert(n != 0);
     89  unsigned long first_set_bit;  // NOLINT(runtime/int)
     90 #if defined(_M_X64) || defined(_M_ARM64)
     91  const unsigned char bit_set =
     92      _BitScanReverse64(&first_set_bit, (unsigned __int64)n);
     93 #else  // !(defined(_M_X64) || defined(_M_ARM64))
     94  const unsigned long n_hi = (unsigned long)(n >> 32);  // NOLINT(runtime/int)
     95  if (n_hi != 0) {
     96    const unsigned char bit_set = _BitScanReverse(&first_set_bit, n_hi);
     97    assert(bit_set != 0);
     98    (void)bit_set;
     99    return 31 ^ (int)first_set_bit;
    100  }
    101  const unsigned char bit_set =
    102      _BitScanReverse(&first_set_bit, (unsigned long)n);  // NOLINT(runtime/int)
    103 #endif
    104  assert(bit_set != 0);
    105  (void)bit_set;
    106  return 63 ^ (int)first_set_bit;
    107 }
    108 #undef USE_MSC_INTRINSICS
    109 #else
    110 static inline int aom_clzll(uint64_t n) {
    111  assert(n != 0);
    112 
    113  int res = 0;
    114  uint64_t high_bit = 1ULL << 63;
    115  while (!(n & high_bit)) {
    116    res++;
    117    n <<= 1;
    118  }
    119  return res;
    120 }
    121 #endif
    122 
    123 #ifdef __cplusplus
    124 }  // extern "C"
    125 #endif
    126 
    127 #endif  // AOM_AOM_PORTS_BITOPS_H_