xref: /llvm-project-15.0.7/libcxx/include/bit (revision a83004f4)
1e02ee4f0SMarshall Clow// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
3e02ee4f0SMarshall Clow//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e02ee4f0SMarshall Clow//
8e02ee4f0SMarshall Clow//===---------------------------------------------------------------------===//
9e02ee4f0SMarshall Clow
10e02ee4f0SMarshall Clow#ifndef _LIBCPP_BIT
11e02ee4f0SMarshall Clow#define _LIBCPP_BIT
12e02ee4f0SMarshall Clow
13e02ee4f0SMarshall Clow/*
14e02ee4f0SMarshall Clow    bit synopsis
15e02ee4f0SMarshall Clow
16e02ee4f0SMarshall Clownamespace std {
17b1fb3d75SLouis Dionne  // [bit.cast], bit_cast
18b1fb3d75SLouis Dionne  template<class To, class From>
19b1fb3d75SLouis Dionne    constexpr To bit_cast(const From& from) noexcept; // C++20
20e02ee4f0SMarshall Clow
211dc62f26SNikolas Klauser  // [bit.byteswap], byteswap
221dc62f26SNikolas Klauser  template<class T>
231dc62f26SNikolas Klauser    constexpr T byteswap(T value) noexcept;      // C++23
241dc62f26SNikolas Klauser
25ebddf90aSLouis Dionne  // [bit.pow.two], integral powers of 2
26a5c3485aSMarshall Clow  template <class T>
271a036e9cSMark de Wever    constexpr bool has_single_bit(T x) noexcept; // C++20
28a5c3485aSMarshall Clow  template <class T>
291a036e9cSMark de Wever    constexpr T bit_ceil(T x);                   // C++20
30a5c3485aSMarshall Clow  template <class T>
311a036e9cSMark de Wever    constexpr T bit_floor(T x) noexcept;         // C++20
32a5c3485aSMarshall Clow  template <class T>
333347e7d4SArthur O'Dwyer    constexpr int bit_width(T x) noexcept;       // C++20
34a5c3485aSMarshall Clow
35ebddf90aSLouis Dionne  // [bit.rotate], rotating
36a5c3485aSMarshall Clow  template<class T>
37a5c3485aSMarshall Clow    constexpr T rotl(T x, unsigned int s) noexcept; // C++20
38a5c3485aSMarshall Clow  template<class T>
39a5c3485aSMarshall Clow    constexpr T rotr(T x, unsigned int s) noexcept; // C++20
40a5c3485aSMarshall Clow
41ebddf90aSLouis Dionne  // [bit.count], counting
42a5c3485aSMarshall Clow  template<class T>
43a5c3485aSMarshall Clow    constexpr int countl_zero(T x) noexcept;  // C++20
44a5c3485aSMarshall Clow  template<class T>
45a5c3485aSMarshall Clow    constexpr int countl_one(T x) noexcept;   // C++20
46a5c3485aSMarshall Clow  template<class T>
47a5c3485aSMarshall Clow    constexpr int countr_zero(T x) noexcept;  // C++20
48a5c3485aSMarshall Clow  template<class T>
49a5c3485aSMarshall Clow    constexpr int countr_one(T x) noexcept;   // C++20
50a5c3485aSMarshall Clow  template<class T>
51a5c3485aSMarshall Clow    constexpr int popcount(T x) noexcept;     // C++20
52a5c3485aSMarshall Clow
53ebddf90aSLouis Dionne  // [bit.endian], endian
5430f12a42SMarshall Clow  enum class endian {
5530f12a42SMarshall Clow    little = see below,        // C++20
5630f12a42SMarshall Clow    big = see below,           // C++20
5730f12a42SMarshall Clow    native = see below         // C++20
5830f12a42SMarshall Clow  };
5930f12a42SMarshall Clow
60e02ee4f0SMarshall Clow} // namespace std
61e02ee4f0SMarshall Clow
62e02ee4f0SMarshall Clow*/
63e02ee4f0SMarshall Clow
64385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
65b1fb3d75SLouis Dionne#include <__bit/bit_cast.h>
661dc62f26SNikolas Klauser#include <__bit/byteswap.h>
67bfbd73f8SArthur O'Dwyer#include <__bits> // __libcpp_clz
6823b10a4aSMark de Wever#include <__concepts/arithmetic.h>
69b1fb3d75SLouis Dionne#include <__config>
70a5c3485aSMarshall Clow#include <limits>
71a5c3485aSMarshall Clow#include <type_traits>
72f56972e2SMarshall Clow#include <version>
73e02ee4f0SMarshall Clow
74*de4a57cbSLouis Dionne#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
75*de4a57cbSLouis Dionne#  include <iosfwd>
76*de4a57cbSLouis Dionne#endif
77*de4a57cbSLouis Dionne
78e02ee4f0SMarshall Clow#if defined(_LIBCPP_COMPILER_MSVC)
79e02ee4f0SMarshall Clow#  include <intrin.h>
80e02ee4f0SMarshall Clow#endif
81e02ee4f0SMarshall Clow
82e02ee4f0SMarshall Clow#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
83e02ee4f0SMarshall Clow#  pragma GCC system_header
84e02ee4f0SMarshall Clow#endif
85e02ee4f0SMarshall Clow
86a5c3485aSMarshall Clow_LIBCPP_PUSH_MACROS
87a5c3485aSMarshall Clow#include <__undef_macros>
88a5c3485aSMarshall Clow
89e02ee4f0SMarshall Clow_LIBCPP_BEGIN_NAMESPACE_STD
90e02ee4f0SMarshall Clow
91a5c3485aSMarshall Clowtemplate<class _Tp>
9223b10a4aSMark de Wever_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
93f3b851f0SMarshall Clow_Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT
94a5c3485aSMarshall Clow{
95e130fbe2SArthur O'Dwyer    static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type");
96a5c3485aSMarshall Clow    const unsigned int __dig = numeric_limits<_Tp>::digits;
97a5c3485aSMarshall Clow    if ((__cnt % __dig) == 0)
98a5c3485aSMarshall Clow        return __t;
99a5c3485aSMarshall Clow    return (__t >> (__cnt % __dig)) | (__t << (__dig - (__cnt % __dig)));
100a5c3485aSMarshall Clow}
101a5c3485aSMarshall Clow
102a5c3485aSMarshall Clowtemplate<class _Tp>
10323b10a4aSMark de Wever_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
104f3b851f0SMarshall Clowint __countl_zero(_Tp __t) _NOEXCEPT
105a5c3485aSMarshall Clow{
106e130fbe2SArthur O'Dwyer    static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type");
107f3b851f0SMarshall Clow    if (__t == 0)
108f3b851f0SMarshall Clow        return numeric_limits<_Tp>::digits;
109f3b851f0SMarshall Clow
110f3b851f0SMarshall Clow    if      (sizeof(_Tp) <= sizeof(unsigned int))
11121ba9d0bSMark de Wever        return std::__libcpp_clz(static_cast<unsigned int>(__t))
112f3b851f0SMarshall Clow              - (numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits);
113f3b851f0SMarshall Clow    else if (sizeof(_Tp) <= sizeof(unsigned long))
11421ba9d0bSMark de Wever        return std::__libcpp_clz(static_cast<unsigned long>(__t))
115f3b851f0SMarshall Clow              - (numeric_limits<unsigned long>::digits - numeric_limits<_Tp>::digits);
116f3b851f0SMarshall Clow    else if (sizeof(_Tp) <= sizeof(unsigned long long))
11721ba9d0bSMark de Wever        return std::__libcpp_clz(static_cast<unsigned long long>(__t))
118f3b851f0SMarshall Clow              - (numeric_limits<unsigned long long>::digits - numeric_limits<_Tp>::digits);
119f3b851f0SMarshall Clow    else
120f3b851f0SMarshall Clow    {
121f3b851f0SMarshall Clow        int __ret = 0;
122f3b851f0SMarshall Clow        int __iter = 0;
123f3b851f0SMarshall Clow        const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
124f3b851f0SMarshall Clow        while (true) {
12521ba9d0bSMark de Wever            __t = std::__rotr(__t, __ulldigits);
12621ba9d0bSMark de Wever            if ((__iter = std::__countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits)
127f3b851f0SMarshall Clow                break;
128f3b851f0SMarshall Clow            __ret += __iter;
129f3b851f0SMarshall Clow            }
130f3b851f0SMarshall Clow        return __ret + __iter;
131f3b851f0SMarshall Clow    }
132f3b851f0SMarshall Clow}
133f3b851f0SMarshall Clow
13421ba9d0bSMark de Wever#if _LIBCPP_STD_VER > 17
13521ba9d0bSMark de Wever
13621ba9d0bSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
13721ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept {
13821ba9d0bSMark de Wever  const unsigned int __dig = numeric_limits<_Tp>::digits;
13921ba9d0bSMark de Wever  if ((__cnt % __dig) == 0)
14021ba9d0bSMark de Wever    return __t;
14121ba9d0bSMark de Wever  return (__t << (__cnt % __dig)) | (__t >> (__dig - (__cnt % __dig)));
142a5c3485aSMarshall Clow}
143a5c3485aSMarshall Clow
14421ba9d0bSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
14521ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept {
14621ba9d0bSMark de Wever  return std::__rotr(__t, __cnt);
147f3b851f0SMarshall Clow}
148f3b851f0SMarshall Clow
14921ba9d0bSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
15021ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept {
15121ba9d0bSMark de Wever  return std::__countl_zero(__t);
15221ba9d0bSMark de Wever}
15321ba9d0bSMark de Wever
15421ba9d0bSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
15521ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept {
15621ba9d0bSMark de Wever  return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits;
15721ba9d0bSMark de Wever}
15821ba9d0bSMark de Wever
15921ba9d0bSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
16021ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept {
16121ba9d0bSMark de Wever  if (__t == 0)
16221ba9d0bSMark de Wever    return numeric_limits<_Tp>::digits;
16321ba9d0bSMark de Wever
164f3b851f0SMarshall Clow  if (sizeof(_Tp) <= sizeof(unsigned int))
16521ba9d0bSMark de Wever    return std::__libcpp_ctz(static_cast<unsigned int>(__t));
166f3b851f0SMarshall Clow  else if (sizeof(_Tp) <= sizeof(unsigned long))
16721ba9d0bSMark de Wever    return std::__libcpp_ctz(static_cast<unsigned long>(__t));
168f3b851f0SMarshall Clow  else if (sizeof(_Tp) <= sizeof(unsigned long long))
16921ba9d0bSMark de Wever    return std::__libcpp_ctz(static_cast<unsigned long long>(__t));
17021ba9d0bSMark de Wever  else {
171a5c3485aSMarshall Clow    int __ret = 0;
17221ba9d0bSMark de Wever    const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
17321ba9d0bSMark de Wever    while (static_cast<unsigned long long>(__t) == 0uLL) {
17421ba9d0bSMark de Wever      __ret += __ulldigits;
17521ba9d0bSMark de Wever      __t >>= __ulldigits;
17621ba9d0bSMark de Wever    }
17721ba9d0bSMark de Wever    return __ret + std::__libcpp_ctz(static_cast<unsigned long long>(__t));
17821ba9d0bSMark de Wever  }
17921ba9d0bSMark de Wever}
18021ba9d0bSMark de Wever
18121ba9d0bSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
18221ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept {
18321ba9d0bSMark de Wever  return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits;
18421ba9d0bSMark de Wever}
18521ba9d0bSMark de Wever
18621ba9d0bSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
18721ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept {
18821ba9d0bSMark de Wever  if (sizeof(_Tp) <= sizeof(unsigned int))
18921ba9d0bSMark de Wever    return std::__libcpp_popcount(static_cast<unsigned int>(__t));
19021ba9d0bSMark de Wever  else if (sizeof(_Tp) <= sizeof(unsigned long))
19121ba9d0bSMark de Wever    return std::__libcpp_popcount(static_cast<unsigned long>(__t));
19221ba9d0bSMark de Wever  else if (sizeof(_Tp) <= sizeof(unsigned long long))
19321ba9d0bSMark de Wever    return std::__libcpp_popcount(static_cast<unsigned long long>(__t));
19421ba9d0bSMark de Wever  else {
19521ba9d0bSMark de Wever    int __ret = 0;
19621ba9d0bSMark de Wever    while (__t != 0) {
19721ba9d0bSMark de Wever      __ret += std::__libcpp_popcount(static_cast<unsigned long long>(__t));
198a5c3485aSMarshall Clow      __t >>= numeric_limits<unsigned long long>::digits;
199a5c3485aSMarshall Clow    }
200a5c3485aSMarshall Clow    return __ret;
201a5c3485aSMarshall Clow  }
202a5c3485aSMarshall Clow}
203a5c3485aSMarshall Clow
20421ba9d0bSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
20521ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept {
206f3b851f0SMarshall Clow  return __t != 0 && (((__t & (__t - 1)) == 0));
207f3b851f0SMarshall Clow}
208f3b851f0SMarshall Clow
20921ba9d0bSMark de Wever// integral log base 2
21023b10a4aSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
21121ba9d0bSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept {
21221ba9d0bSMark de Wever  return numeric_limits<_Tp>::digits - 1 - std::countl_zero(__t);
213f3b851f0SMarshall Clow}
214a5c3485aSMarshall Clow
21523b10a4aSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
21623b10a4aSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept {
21721ba9d0bSMark de Wever  return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t);
218f3b851f0SMarshall Clow}
219a5c3485aSMarshall Clow
22023b10a4aSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
22123b10a4aSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept {
22223b10a4aSMark de Wever  if (__t < 2)
22323b10a4aSMark de Wever    return 1;
22421ba9d0bSMark de Wever  const unsigned __n = numeric_limits<_Tp>::digits - std::countl_zero((_Tp)(__t - 1u));
2255675b611SNikolas Klauser  _LIBCPP_ASSERT(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil");
226a5c3485aSMarshall Clow
227a5c3485aSMarshall Clow  if constexpr (sizeof(_Tp) >= sizeof(unsigned))
228a5c3485aSMarshall Clow    return _Tp{1} << __n;
22923b10a4aSMark de Wever  else {
230a5c3485aSMarshall Clow    const unsigned __extra = numeric_limits<unsigned>::digits - numeric_limits<_Tp>::digits;
231a5c3485aSMarshall Clow    const unsigned __retVal = 1u << (__n + __extra);
232a5c3485aSMarshall Clow    return (_Tp)(__retVal >> __extra);
233a5c3485aSMarshall Clow  }
234a5c3485aSMarshall Clow}
235a5c3485aSMarshall Clow
23623b10a4aSMark de Wevertemplate <__libcpp_unsigned_integer _Tp>
23723b10a4aSMark de Wever_LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept {
23821ba9d0bSMark de Wever  return __t == 0 ? 0 : std::__bit_log2(__t) + 1;
239f3b851f0SMarshall Clow}
240a5c3485aSMarshall Clow
24121ba9d0bSMark de Weverenum class endian {
24230f12a42SMarshall Clow  little = 0xDEAD,
24330f12a42SMarshall Clow  big = 0xFACE,
24430f12a42SMarshall Clow#  if defined(_LIBCPP_LITTLE_ENDIAN)
24530f12a42SMarshall Clow  native = little
24630f12a42SMarshall Clow#  elif defined(_LIBCPP_BIG_ENDIAN)
24730f12a42SMarshall Clow  native = big
24830f12a42SMarshall Clow#  else
24930f12a42SMarshall Clow  native = 0xCAFE
25030f12a42SMarshall Clow#  endif
25130f12a42SMarshall Clow};
25230f12a42SMarshall Clow
253a5c3485aSMarshall Clow#endif // _LIBCPP_STD_VER > 17
254a5c3485aSMarshall Clow
255e02ee4f0SMarshall Clow_LIBCPP_END_NAMESPACE_STD
256e02ee4f0SMarshall Clow
257a5c3485aSMarshall Clow_LIBCPP_POP_MACROS
258a5c3485aSMarshall Clow
259e02ee4f0SMarshall Clow#endif // _LIBCPP_BIT
260