103 lines
2.8 KiB
C++
103 lines
2.8 KiB
C++
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==============================================================================*/
|
|
#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_BITS_H_
|
|
#define TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_BITS_H_
|
|
|
|
#ifdef __cplusplus
|
|
#include <cstdint>
|
|
|
|
extern "C" {
|
|
#endif
|
|
|
|
static inline int CountLeadingZeros32Slow(uint64_t n) {
|
|
int zeroes = 28;
|
|
if (n >> 16) zeroes -= 16, n >>= 16;
|
|
if (n >> 8) zeroes -= 8, n >>= 8;
|
|
if (n >> 4) zeroes -= 4, n >>= 4;
|
|
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
|
|
}
|
|
|
|
static inline int CountLeadingZeros32(uint32_t n) {
|
|
#if defined(_MSC_VER)
|
|
unsigned long result = 0; // NOLINT(runtime/int)
|
|
if (_BitScanReverse(&result, n)) {
|
|
return 31 - result;
|
|
}
|
|
return 32;
|
|
#elif defined(__GNUC__)
|
|
|
|
// Handle 0 as a special case because __builtin_clz(0) is undefined.
|
|
if (n == 0) {
|
|
return 32;
|
|
}
|
|
return __builtin_clz(n);
|
|
#else
|
|
return CountLeadingZeros32Slow(n);
|
|
#endif
|
|
}
|
|
|
|
static inline int MostSignificantBit32(uint32_t n) {
|
|
return 32 - CountLeadingZeros32(n);
|
|
}
|
|
|
|
static inline int CountLeadingZeros64Slow(uint64_t n) {
|
|
int zeroes = 60;
|
|
if (n >> 32) zeroes -= 32, n >>= 32;
|
|
if (n >> 16) zeroes -= 16, n >>= 16;
|
|
if (n >> 8) zeroes -= 8, n >>= 8;
|
|
if (n >> 4) zeroes -= 4, n >>= 4;
|
|
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
|
|
}
|
|
|
|
static inline int CountLeadingZeros64(uint64_t n) {
|
|
#if defined(_MSC_VER) && defined(_M_X64)
|
|
// MSVC does not have __builtin_clzll. Use _BitScanReverse64.
|
|
unsigned long result = 0; // NOLINT(runtime/int)
|
|
if (_BitScanReverse64(&result, n)) {
|
|
return 63 - result;
|
|
}
|
|
return 64;
|
|
#elif defined(_MSC_VER)
|
|
// MSVC does not have __builtin_clzll. Compose two calls to _BitScanReverse
|
|
unsigned long result = 0; // NOLINT(runtime/int)
|
|
if ((n >> 32) && _BitScanReverse(&result, n >> 32)) {
|
|
return 31 - result;
|
|
}
|
|
if (_BitScanReverse(&result, n)) {
|
|
return 63 - result;
|
|
}
|
|
return 64;
|
|
#elif defined(__GNUC__)
|
|
|
|
// Handle 0 as a special case because __builtin_clzll(0) is undefined.
|
|
if (n == 0) {
|
|
return 64;
|
|
}
|
|
return __builtin_clzll(n);
|
|
#else
|
|
return CountLeadingZeros64Slow(n);
|
|
#endif
|
|
}
|
|
|
|
static inline int MostSignificantBit64(uint64_t n) {
|
|
return 64 - CountLeadingZeros64(n);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
} // extern "C"
|
|
#endif
|
|
|
|
#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICROFRONTEND_LIB_BITS_H_
|