//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
///
 
/// \file
 
/// This file implements the C++20 <bit> header.
 
///
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_ADT_BIT_H
 
#define LLVM_ADT_BIT_H
 
 
 
#include "llvm/Support/Compiler.h"
 
#include <cstdint>
 
#include <limits>
 
#include <type_traits>
 
 
 
#if !__has_builtin(__builtin_bit_cast)
 
#include <cstring>
 
#endif
 
 
 
#if defined(_MSC_VER) && !defined(_DEBUG)
 
#include <cstdlib>  // for _byteswap_{ushort,ulong,uint64}
 
#endif
 
 
 
#ifdef _MSC_VER
 
// Declare these intrinsics manually rather including intrin.h. It's very
 
// expensive, and bit.h is popular via MathExtras.h.
 
// #include <intrin.h>
 
extern "C" {
 
unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
 
unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
 
unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
 
unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
 
}
 
#endif
 
 
 
namespace llvm {
 
 
 
// This implementation of bit_cast is different from the C++20 one in two ways:
 
//  - It isn't constexpr because that requires compiler support.
 
//  - It requires trivially-constructible To, to avoid UB in the implementation.
 
template <
 
    typename To, typename From,
 
    typename = std::enable_if_t<sizeof(To) == sizeof(From)>,
 
    typename = std::enable_if_t<std::is_trivially_constructible<To>::value>,
 
    typename = std::enable_if_t<std::is_trivially_copyable<To>::value>,
 
    typename = std::enable_if_t<std::is_trivially_copyable<From>::value>>
 
[[nodiscard]] inline To bit_cast(const From &from) noexcept {
 
#if __has_builtin(__builtin_bit_cast)
 
  return __builtin_bit_cast(To, from);
 
#else
 
  To to;
 
  std::memcpy(&to, &from, sizeof(To));
 
  return to;
 
#endif
 
}
 
 
 
/// Reverses the bytes in the given integer value V.
 
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
 
[[nodiscard]] constexpr T byteswap(T V) noexcept {
 
  if constexpr (sizeof(T) == 1) {
 
    return V;
 
  } else if constexpr (sizeof(T) == 2) {
 
    uint16_t UV = V;
 
#if defined(_MSC_VER) && !defined(_DEBUG)
 
    // The DLL version of the runtime lacks these functions (bug!?), but in a
 
    // release build they're replaced with BSWAP instructions anyway.
 
    return _byteswap_ushort(UV);
 
#else
 
    uint16_t Hi = UV << 8;
 
    uint16_t Lo = UV >> 8;
 
    return Hi | Lo;
 
#endif
 
  } else if constexpr (sizeof(T) == 4) {
 
    uint32_t UV = V;
 
#if __has_builtin(__builtin_bswap32)
 
    return __builtin_bswap32(UV);
 
#elif defined(_MSC_VER) && !defined(_DEBUG)
 
    return _byteswap_ulong(UV);
 
#else
 
    uint32_t Byte0 = UV & 0x000000FF;
 
    uint32_t Byte1 = UV & 0x0000FF00;
 
    uint32_t Byte2 = UV & 0x00FF0000;
 
    uint32_t Byte3 = UV & 0xFF000000;
 
    return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
 
#endif
 
  } else if constexpr (sizeof(T) == 8) {
 
    uint64_t UV = V;
 
#if __has_builtin(__builtin_bswap64)
 
    return __builtin_bswap64(UV);
 
#elif defined(_MSC_VER) && !defined(_DEBUG)
 
    return _byteswap_uint64(UV);
 
#else
 
    uint64_t Hi = llvm::byteswap<uint32_t>(UV);
 
    uint32_t Lo = llvm::byteswap<uint32_t>(UV >> 32);
 
    return (Hi << 32) | Lo;
 
#endif
 
  } else {
 
    static_assert(!sizeof(T *), "Don't know how to handle the given type.");
 
    return 0;
 
  }
 
}
 
 
 
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
 
[[nodiscard]] constexpr inline bool has_single_bit(T Value) noexcept {
 
  return (Value != 0) && ((Value & (Value - 1)) == 0);
 
}
 
 
 
namespace detail {
 
template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
 
  static unsigned count(T Val) {
 
    if (!Val)
 
      return std::numeric_limits<T>::digits;
 
    if (Val & 0x1)
 
      return 0;
 
 
 
    // Bisection method.
 
    unsigned ZeroBits = 0;
 
    T Shift = std::numeric_limits<T>::digits >> 1;
 
    T Mask = std::numeric_limits<T>::max() >> Shift;
 
    while (Shift) {
 
      if ((Val & Mask) == 0) {
 
        Val >>= Shift;
 
        ZeroBits |= Shift;
 
      }
 
      Shift >>= 1;
 
      Mask >>= Shift;
 
    }
 
    return ZeroBits;
 
  }
 
};
 
 
 
#if defined(__GNUC__) || defined(_MSC_VER)
 
template <typename T> struct TrailingZerosCounter<T, 4> {
 
  static unsigned count(T Val) {
 
    if (Val == 0)
 
      return 32;
 
 
 
#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
 
    return __builtin_ctz(Val);
 
#elif defined(_MSC_VER)
 
    unsigned long Index;
 
    _BitScanForward(&Index, Val);
 
    return Index;
 
#endif
 
  }
 
};
 
 
 
#if !defined(_MSC_VER) || defined(_M_X64)
 
template <typename T> struct TrailingZerosCounter<T, 8> {
 
  static unsigned count(T Val) {
 
    if (Val == 0)
 
      return 64;
 
 
 
#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
 
    return __builtin_ctzll(Val);
 
#elif defined(_MSC_VER)
 
    unsigned long Index;
 
    _BitScanForward64(&Index, Val);
 
    return Index;
 
#endif
 
  }
 
};
 
#endif
 
#endif
 
} // namespace detail
 
 
 
/// Count number of 0's from the least significant bit to the most
 
///   stopping at the first 1.
 
///
 
/// Only unsigned integral types are allowed.
 
///
 
/// Returns std::numeric_limits<T>::digits on an input of 0.
 
template <typename T> [[nodiscard]] int countr_zero(T Val) {
 
  static_assert(std::is_unsigned_v<T>,
 
                "Only unsigned integral types are allowed.");
 
  return llvm::detail::TrailingZerosCounter<T, sizeof(T)>::count(Val);
 
}
 
 
 
namespace detail {
 
template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
 
  static unsigned count(T Val) {
 
    if (!Val)
 
      return std::numeric_limits<T>::digits;
 
 
 
    // Bisection method.
 
    unsigned ZeroBits = 0;
 
    for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
 
      T Tmp = Val >> Shift;
 
      if (Tmp)
 
        Val = Tmp;
 
      else
 
        ZeroBits |= Shift;
 
    }
 
    return ZeroBits;
 
  }
 
};
 
 
 
#if defined(__GNUC__) || defined(_MSC_VER)
 
template <typename T> struct LeadingZerosCounter<T, 4> {
 
  static unsigned count(T Val) {
 
    if (Val == 0)
 
      return 32;
 
 
 
#if __has_builtin(__builtin_clz) || defined(__GNUC__)
 
    return __builtin_clz(Val);
 
#elif defined(_MSC_VER)
 
    unsigned long Index;
 
    _BitScanReverse(&Index, Val);
 
    return Index ^ 31;
 
#endif
 
  }
 
};
 
 
 
#if !defined(_MSC_VER) || defined(_M_X64)
 
template <typename T> struct LeadingZerosCounter<T, 8> {
 
  static unsigned count(T Val) {
 
    if (Val == 0)
 
      return 64;
 
 
 
#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
 
    return __builtin_clzll(Val);
 
#elif defined(_MSC_VER)
 
    unsigned long Index;
 
    _BitScanReverse64(&Index, Val);
 
    return Index ^ 63;
 
#endif
 
  }
 
};
 
#endif
 
#endif
 
} // namespace detail
 
 
 
/// Count number of 0's from the most significant bit to the least
 
///   stopping at the first 1.
 
///
 
/// Only unsigned integral types are allowed.
 
///
 
/// Returns std::numeric_limits<T>::digits on an input of 0.
 
template <typename T> [[nodiscard]] int countl_zero(T Val) {
 
  static_assert(std::is_unsigned_v<T>,
 
                "Only unsigned integral types are allowed.");
 
  return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val);
 
}
 
 
 
/// Count the number of ones from the most significant bit to the first
 
/// zero bit.
 
///
 
/// Ex. countl_one(0xFF0FFF00) == 8.
 
/// Only unsigned integral types are allowed.
 
///
 
/// Returns std::numeric_limits<T>::digits on an input of all ones.
 
template <typename T> [[nodiscard]] int countl_one(T Value) {
 
  static_assert(std::is_unsigned_v<T>,
 
                "Only unsigned integral types are allowed.");
 
  return llvm::countl_zero<T>(~Value);
 
}
 
 
 
/// Count the number of ones from the least significant bit to the first
 
/// zero bit.
 
///
 
/// Ex. countr_one(0x00FF00FF) == 8.
 
/// Only unsigned integral types are allowed.
 
///
 
/// Returns std::numeric_limits<T>::digits on an input of all ones.
 
template <typename T> [[nodiscard]] int countr_one(T Value) {
 
  static_assert(std::is_unsigned_v<T>,
 
                "Only unsigned integral types are allowed.");
 
  return llvm::countr_zero<T>(~Value);
 
}
 
 
 
/// Returns the number of bits needed to represent Value if Value is nonzero.
 
/// Returns 0 otherwise.
 
///
 
/// Ex. bit_width(5) == 3.
 
template <typename T> [[nodiscard]] int bit_width(T Value) {
 
  static_assert(std::is_unsigned_v<T>,
 
                "Only unsigned integral types are allowed.");
 
  return std::numeric_limits<T>::digits - llvm::countl_zero(Value);
 
}
 
 
 
/// Returns the largest integral power of two no greater than Value if Value is
 
/// nonzero.  Returns 0 otherwise.
 
///
 
/// Ex. bit_floor(5) == 4.
 
template <typename T> [[nodiscard]] T bit_floor(T Value) {
 
  static_assert(std::is_unsigned_v<T>,
 
                "Only unsigned integral types are allowed.");
 
  if (!Value)
 
    return 0;
 
  return T(1) << (llvm::bit_width(Value) - 1);
 
}
 
 
 
/// Returns the smallest integral power of two no smaller than Value if Value is
 
/// nonzero.  Returns 0 otherwise.
 
///
 
/// Ex. bit_ceil(5) == 8.
 
///
 
/// The return value is undefined if the input is larger than the largest power
 
/// of two representable in T.
 
template <typename T> [[nodiscard]] T bit_ceil(T Value) {
 
  static_assert(std::is_unsigned_v<T>,
 
                "Only unsigned integral types are allowed.");
 
  if (Value < 2)
 
    return 1;
 
  return T(1) << llvm::bit_width<T>(Value - 1u);
 
}
 
 
 
namespace detail {
 
template <typename T, std::size_t SizeOfT> struct PopulationCounter {
 
  static int count(T Value) {
 
    // Generic version, forward to 32 bits.
 
    static_assert(SizeOfT <= 4, "Not implemented!");
 
#if defined(__GNUC__)
 
    return (int)__builtin_popcount(Value);
 
#else
 
    uint32_t v = Value;
 
    v = v - ((v >> 1) & 0x55555555);
 
    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
 
    return int(((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
 
#endif
 
  }
 
};
 
 
 
template <typename T> struct PopulationCounter<T, 8> {
 
  static int count(T Value) {
 
#if defined(__GNUC__)
 
    return (int)__builtin_popcountll(Value);
 
#else
 
    uint64_t v = Value;
 
    v = v - ((v >> 1) & 0x5555555555555555ULL);
 
    v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
 
    v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
 
    return int((uint64_t)(v * 0x0101010101010101ULL) >> 56);
 
#endif
 
  }
 
};
 
} // namespace detail
 
 
 
/// Count the number of set bits in a value.
 
/// Ex. popcount(0xF000F000) = 8
 
/// Returns 0 if the word is zero.
 
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
 
[[nodiscard]] inline int popcount(T Value) noexcept {
 
  return detail::PopulationCounter<T, sizeof(T)>::count(Value);
 
}
 
 
 
} // namespace llvm
 
 
 
#endif