// FCP guest_std (rexglue/UPSTREAM.md, change 140): freestanding replacement, see README.md.
#pragma once
#include <cstdint>
#include <type_traits>
#if defined(_MSC_VER)
#include <intrin.h>
#endif
namespace std {
enum class endian { little = 0, big = 1, native = little };
template <class To, class From>
constexpr To bit_cast(const From& from) noexcept {
  return __builtin_bit_cast(To, from);
}
template <class T>
constexpr T byteswap(T v) noexcept {
  if constexpr (sizeof(T) == 1) {
    return v;
  } else if constexpr (sizeof(T) == 2) {
    return static_cast<T>(__builtin_bswap16(static_cast<uint16_t>(v)));
  } else if constexpr (sizeof(T) == 4) {
    return static_cast<T>(__builtin_bswap32(static_cast<uint32_t>(v)));
  } else {
    return static_cast<T>(__builtin_bswap64(static_cast<uint64_t>(v)));
  }
}
// With AVX2 the MSVC STL counts with the lzcnt intrinsics; the same here, so the code matches the hosted build.
template <class T>
constexpr int countl_zero(T v) noexcept {
#if defined(__AVX2__) && defined(_MSC_VER)
  if (!__builtin_is_constant_evaluated()) {
    if constexpr (sizeof(T) <= 2) {
      return static_cast<int>(__lzcnt16(static_cast<unsigned short>(v)) - (16 - sizeof(T) * 8));
    } else if constexpr (sizeof(T) == 4) {
      return static_cast<int>(__lzcnt(static_cast<unsigned int>(v)));
    } else {
      return static_cast<int>(__lzcnt64(static_cast<unsigned long long>(v)));
    }
  }
#endif
  return __builtin_clzg(v, static_cast<int>(sizeof(T) * 8));
}
template <class T>
constexpr int countr_zero(T v) noexcept {
  return __builtin_ctzg(v, static_cast<int>(sizeof(T) * 8));
}
template <class T>
constexpr int countl_one(T v) noexcept {
  return countl_zero(static_cast<T>(~v));
}
template <class T>
constexpr int countr_one(T v) noexcept {
  return countr_zero(static_cast<T>(~v));
}
template <class T>
constexpr int popcount(T v) noexcept {
  return __builtin_popcountg(v);
}
template <class T>
constexpr int bit_width(T v) noexcept {
  return static_cast<int>(sizeof(T) * 8) - countl_zero(v);
}
template <class T>
constexpr bool has_single_bit(T v) noexcept {
  return v != 0 && (v & (v - 1)) == 0;
}
template <class T>
constexpr T bit_floor(T v) noexcept {
  return v == 0 ? 0 : static_cast<T>(T(1) << (bit_width(v) - 1));
}
template <class T>
constexpr T bit_ceil(T v) noexcept {
  return v <= 1 ? T(1) : static_cast<T>(T(1) << bit_width(static_cast<T>(v - 1)));
}
template <class T>
constexpr T rotl(T v, int s) noexcept {
  constexpr int n = sizeof(T) * 8;
  const int r = s % n;
  if (r == 0) return v;
  if (r > 0) return static_cast<T>((v << r) | (v >> (n - r)));
  return static_cast<T>((v >> -r) | (v << (n + r)));
}
template <class T>
constexpr T rotr(T v, int s) noexcept {
  return rotl(v, -s);
}
}  // namespace std
