// -*- C++ -*- // Copyright (C) 2018-2019 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file include/bit * This is a Standard C++ Library header. */ #ifndef _GLIBCXX_BIT #define _GLIBCXX_BIT 1 #pragma GCC system_header #if __cplusplus >= 201402L #include #include namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION template constexpr _Tp __rotl(_Tp __x, int __s) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; const int __r = __s % _Nd; if (__r == 0) return __x; else if (__r > 0) return (__x << __r) | (__x >> ((_Nd - __r) % _Nd)); else return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r) } template constexpr _Tp __rotr(_Tp __x, int __s) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; const int __r = __s % _Nd; if (__r == 0) return __x; else if (__r > 0) return (__x >> __r) | (__x << ((_Nd - __r) % _Nd)); else return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r) } template constexpr int __countl_zero(_Tp __x) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; if (__x == 0) return _Nd; constexpr auto _Nd_ull = numeric_limits::digits; constexpr auto _Nd_ul = numeric_limits::digits; constexpr auto _Nd_u = numeric_limits::digits; if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) { constexpr int __diff = _Nd_u - _Nd; return __builtin_clz(__x) - __diff; } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) { constexpr int __diff = _Nd_ul - _Nd; return __builtin_clzl(__x) - __diff; } else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) { constexpr int __diff = _Nd_ull - _Nd; return __builtin_clzll(__x) - __diff; } else // (_Nd > _Nd_ull) { static_assert(_Nd <= (2 * _Nd_ull), "Maximum supported integer size is 128-bit"); unsigned long long __high = __x >> _Nd_ull; if (__high != 0) { constexpr int __diff = (2 * _Nd_ull) - _Nd; return __builtin_clzll(__high) - __diff; } constexpr auto __max_ull = numeric_limits::max(); unsigned long long __low = __x & __max_ull; return (_Nd - _Nd_ull) + __builtin_clzll(__low); } } template constexpr int __countl_one(_Tp __x) noexcept { if (__x == numeric_limits<_Tp>::max()) return numeric_limits<_Tp>::digits; return std::__countl_zero<_Tp>((_Tp)~__x); } template constexpr int __countr_zero(_Tp __x) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; if (__x == 0) return _Nd; constexpr auto _Nd_ull = numeric_limits::digits; constexpr auto _Nd_ul = numeric_limits::digits; constexpr auto _Nd_u = numeric_limits::digits; if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) return __builtin_ctz(__x); else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) return __builtin_ctzl(__x); else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) return __builtin_ctzll(__x); else // (_Nd > _Nd_ull) { static_assert(_Nd <= (2 * _Nd_ull), "Maximum supported integer size is 128-bit"); constexpr auto __max_ull = numeric_limits::max(); unsigned long long __low = __x & __max_ull; if (__low != 0) return __builtin_ctzll(__low); unsigned long long __high = __x >> _Nd_ull; return __builtin_ctzll(__high) + _Nd_ull; } } template constexpr int __countr_one(_Tp __x) noexcept { if (__x == numeric_limits<_Tp>::max()) return numeric_limits<_Tp>::digits; return std::__countr_zero((_Tp)~__x); } template constexpr int __popcount(_Tp __x) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; if (__x == 0) return 0; constexpr auto _Nd_ull = numeric_limits::digits; constexpr auto _Nd_ul = numeric_limits::digits; constexpr auto _Nd_u = numeric_limits::digits; if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) return __builtin_popcount(__x); else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) return __builtin_popcountl(__x); else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) return __builtin_popcountll(__x); else // (_Nd > _Nd_ull) { static_assert(_Nd <= (2 * _Nd_ull), "Maximum supported integer size is 128-bit"); constexpr auto __max_ull = numeric_limits::max(); unsigned long long __low = __x & __max_ull; unsigned long long __high = __x >> _Nd_ull; return __builtin_popcountll(__low) + __builtin_popcountll(__high); } } template constexpr bool __ispow2(_Tp __x) noexcept { return std::__popcount(__x) == 1; } template constexpr _Tp __ceil2(_Tp __x) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; if (__x == 0 || __x == 1) return 1; auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u)); // If the shift exponent equals _Nd then the correct result is not // representable as a value of _Tp, and so the result is undefined. // Want that undefined behaviour to be detected in constant expressions, // by UBSan, and by debug assertions. #ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED if (!__builtin_is_constant_evaluated()) __glibcxx_assert( __shift_exponent != numeric_limits<_Tp>::digits ); #endif using __promoted_type = decltype(__x << 1); if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) { // If __x undergoes integral promotion then shifting by _Nd is // not undefined. In order to make the shift undefined, so that // it is diagnosed in constant expressions and by UBsan, we also // need to "promote" the shift exponent to be too large for the // promoted type. const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2; __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp; } return (_Tp)1u << __shift_exponent; } template constexpr _Tp __floor2(_Tp __x) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; if (__x == 0) return 0; return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x >> 1))); } template constexpr _Tp __log2p1(_Tp __x) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; return _Nd - std::__countl_zero(__x); } #if __cplusplus > 201703L template> struct _If_is_unsigned_integer_type { }; template struct _If_is_unsigned_integer_type { }; template struct _If_is_unsigned_integer_type<_Tp, _Up, true> : enable_if>, _Up> { }; template using _If_is_unsigned_integer = typename _If_is_unsigned_integer_type, _Up>::type; // [bit.rot], rotating template [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> rotl(_Tp __x, int __s) noexcept { return std::__rotl(__x, __s); } template [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> rotr(_Tp __x, int __s) noexcept { return std::__rotr(__x, __s); } // [bit.count], counting template constexpr _If_is_unsigned_integer<_Tp, int> countl_zero(_Tp __x) noexcept { return std::__countl_zero(__x); } template constexpr _If_is_unsigned_integer<_Tp, int> countl_one(_Tp __x) noexcept { return std::__countl_one(__x); } template constexpr _If_is_unsigned_integer<_Tp, int> countr_zero(_Tp __x) noexcept { return std::__countr_zero(__x); } template constexpr _If_is_unsigned_integer<_Tp, int> countr_one(_Tp __x) noexcept { return std::__countr_one(__x); } template constexpr _If_is_unsigned_integer<_Tp, int> popcount(_Tp __x) noexcept { return std::__popcount(__x); } // [bit.pow.two], integral powers of 2 template constexpr _If_is_unsigned_integer<_Tp, bool> ispow2(_Tp __x) noexcept { return std::__ispow2(__x); } template constexpr _If_is_unsigned_integer<_Tp> ceil2(_Tp __x) noexcept { return std::__ceil2(__x); } template constexpr _If_is_unsigned_integer<_Tp> floor2(_Tp __x) noexcept { return std::__floor2(__x); } template constexpr _If_is_unsigned_integer<_Tp> log2p1(_Tp __x) noexcept { return std::__log2p1(__x); } #define __cpp_lib_endian 201907L /// Byte order enum class endian { little = __ORDER_LITTLE_ENDIAN__, big = __ORDER_BIG_ENDIAN__, native = __BYTE_ORDER__ }; #endif // C++2a _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // C++14 #endif // _GLIBCXX_BIT