Abseil Common Libraries (C++) (grcp 依赖)
https://abseil.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.6 KiB
177 lines
5.6 KiB
// Copyright 2020 The Abseil Authors |
|
// |
|
// 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 |
|
// |
|
// https://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. |
|
// |
|
// ----------------------------------------------------------------------------- |
|
// File: bits.h |
|
// ----------------------------------------------------------------------------- |
|
// |
|
// This file contains implementations of C++20's bitwise math functions, as |
|
// defined by: |
|
// |
|
// P0553R4: |
|
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html |
|
// P0556R3: |
|
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html |
|
// P1355R2: |
|
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html |
|
// P1956R1: |
|
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf |
|
// |
|
// When using a standard library that implements these functions, we use the |
|
// standard library's implementation. |
|
|
|
#ifndef ABSL_NUMERIC_BITS_H_ |
|
#define ABSL_NUMERIC_BITS_H_ |
|
|
|
#include <cstdint> |
|
#include <limits> |
|
#include <type_traits> |
|
|
|
#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) || \ |
|
(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) |
|
#include <bit> |
|
#endif |
|
|
|
#include "absl/base/attributes.h" |
|
#include "absl/base/config.h" |
|
#include "absl/numeric/internal/bits.h" |
|
|
|
namespace absl { |
|
ABSL_NAMESPACE_BEGIN |
|
|
|
#if !(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) |
|
// rotating |
|
template <class T> |
|
ABSL_MUST_USE_RESULT constexpr |
|
typename std::enable_if<std::is_unsigned<T>::value, T>::type |
|
rotl(T x, int s) noexcept { |
|
return numeric_internal::RotateLeft(x, s); |
|
} |
|
|
|
template <class T> |
|
ABSL_MUST_USE_RESULT constexpr |
|
typename std::enable_if<std::is_unsigned<T>::value, T>::type |
|
rotr(T x, int s) noexcept { |
|
return numeric_internal::RotateRight(x, s); |
|
} |
|
|
|
// Counting functions |
|
// |
|
// While these functions are typically constexpr, on some platforms, they may |
|
// not be marked as constexpr due to constraints of the compiler/available |
|
// intrinsics. |
|
template <class T> |
|
ABSL_INTERNAL_CONSTEXPR_CLZ inline |
|
typename std::enable_if<std::is_unsigned<T>::value, int>::type |
|
countl_zero(T x) noexcept { |
|
return numeric_internal::CountLeadingZeroes(x); |
|
} |
|
|
|
template <class T> |
|
ABSL_INTERNAL_CONSTEXPR_CLZ inline |
|
typename std::enable_if<std::is_unsigned<T>::value, int>::type |
|
countl_one(T x) noexcept { |
|
// Avoid integer promotion to a wider type |
|
return countl_zero(static_cast<T>(~x)); |
|
} |
|
|
|
template <class T> |
|
ABSL_INTERNAL_CONSTEXPR_CTZ inline |
|
typename std::enable_if<std::is_unsigned<T>::value, int>::type |
|
countr_zero(T x) noexcept { |
|
return numeric_internal::CountTrailingZeroes(x); |
|
} |
|
|
|
template <class T> |
|
ABSL_INTERNAL_CONSTEXPR_CTZ inline |
|
typename std::enable_if<std::is_unsigned<T>::value, int>::type |
|
countr_one(T x) noexcept { |
|
// Avoid integer promotion to a wider type |
|
return countr_zero(static_cast<T>(~x)); |
|
} |
|
|
|
template <class T> |
|
ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline |
|
typename std::enable_if<std::is_unsigned<T>::value, int>::type |
|
popcount(T x) noexcept { |
|
return numeric_internal::Popcount(x); |
|
} |
|
#else // defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L |
|
|
|
using std::countl_one; |
|
using std::countl_zero; |
|
using std::countr_one; |
|
using std::countr_zero; |
|
using std::popcount; |
|
using std::rotl; |
|
using std::rotr; |
|
|
|
#endif |
|
|
|
#if !(defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) |
|
// Returns: true if x is an integral power of two; false otherwise. |
|
template <class T> |
|
constexpr inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type |
|
has_single_bit(T x) noexcept { |
|
return x != 0 && (x & (x - 1)) == 0; |
|
} |
|
|
|
// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any |
|
// fractional part discarded. |
|
template <class T> |
|
ABSL_INTERNAL_CONSTEXPR_CLZ inline |
|
typename std::enable_if<std::is_unsigned<T>::value, T>::type |
|
bit_width(T x) noexcept { |
|
return std::numeric_limits<T>::digits - countl_zero(x); |
|
} |
|
|
|
// Returns: If x == 0, 0; otherwise the maximal value y such that |
|
// has_single_bit(y) is true and y <= x. |
|
template <class T> |
|
ABSL_INTERNAL_CONSTEXPR_CLZ inline |
|
typename std::enable_if<std::is_unsigned<T>::value, T>::type |
|
bit_floor(T x) noexcept { |
|
return x == 0 ? 0 : T{1} << (bit_width(x) - 1); |
|
} |
|
|
|
// Returns: N, where N is the smallest power of 2 greater than or equal to x. |
|
// |
|
// Preconditions: N is representable as a value of type T. |
|
template <class T> |
|
ABSL_INTERNAL_CONSTEXPR_CLZ inline |
|
typename std::enable_if<std::is_unsigned<T>::value, T>::type |
|
bit_ceil(T x) { |
|
// If T is narrower than unsigned, T{1} << bit_width will be promoted. We |
|
// want to force it to wraparound so that bit_ceil of an invalid value are not |
|
// core constant expressions. |
|
// |
|
// BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would |
|
// undergo promotion to unsigned but not fit the result into T without |
|
// truncation. |
|
return has_single_bit(x) ? T{1} << (bit_width(x) - 1) |
|
: numeric_internal::BitCeilNonPowerOf2(x); |
|
} |
|
#else // defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L |
|
|
|
using std::bit_ceil; |
|
using std::bit_floor; |
|
using std::bit_width; |
|
using std::has_single_bit; |
|
|
|
#endif |
|
|
|
ABSL_NAMESPACE_END |
|
} // namespace absl |
|
|
|
#endif // ABSL_NUMERIC_BITS_H_
|
|
|