// FCP guest_std (rexglue/UPSTREAM.md, change 140): freestanding replacement, see README.md.
#pragma once
#include <float.h>
#include <limits.h>
namespace std {
enum float_round_style { round_indeterminate = -1, round_toward_zero = 0, round_to_nearest = 1 };
template <class T>
struct numeric_limits {
  static constexpr bool is_specialized = false;
};
template <class T>
struct numeric_limits<const T> : numeric_limits<T> {};
template <class T>
struct numeric_limits<volatile T> : numeric_limits<T> {};
template <class T>
struct numeric_limits<const volatile T> : numeric_limits<T> {};

template <class T, T Min, T Max, int Digits>
struct fcp_int_limits {
  static constexpr bool is_specialized = true;
  static constexpr bool is_signed = Min != 0;
  static constexpr bool is_integer = true;
  static constexpr bool is_exact = true;
  static constexpr bool has_infinity = false;
  static constexpr bool has_quiet_NaN = false;
  static constexpr int digits = Digits;
  static constexpr int radix = 2;
  static constexpr T min() noexcept { return Min; }
  static constexpr T max() noexcept { return Max; }
  static constexpr T lowest() noexcept { return Min; }
};
template <>
struct numeric_limits<bool> : fcp_int_limits<bool, false, true, 1> {};
template <>
struct numeric_limits<char> : fcp_int_limits<char, CHAR_MIN, CHAR_MAX, 7> {};
template <>
struct numeric_limits<signed char> : fcp_int_limits<signed char, SCHAR_MIN, SCHAR_MAX, 7> {};
template <>
struct numeric_limits<unsigned char> : fcp_int_limits<unsigned char, 0, UCHAR_MAX, 8> {};
template <>
struct numeric_limits<short> : fcp_int_limits<short, SHRT_MIN, SHRT_MAX, 15> {};
template <>
struct numeric_limits<unsigned short> : fcp_int_limits<unsigned short, 0, USHRT_MAX, 16> {};
template <>
struct numeric_limits<int> : fcp_int_limits<int, INT_MIN, INT_MAX, 31> {};
template <>
struct numeric_limits<unsigned int> : fcp_int_limits<unsigned int, 0, UINT_MAX, 32> {};
template <>
struct numeric_limits<long> : fcp_int_limits<long, LONG_MIN, LONG_MAX, 31> {};
template <>
struct numeric_limits<unsigned long> : fcp_int_limits<unsigned long, 0, ULONG_MAX, 32> {};
template <>
struct numeric_limits<long long> : fcp_int_limits<long long, LLONG_MIN, LLONG_MAX, 63> {};
template <>
struct numeric_limits<unsigned long long> : fcp_int_limits<unsigned long long, 0, ULLONG_MAX, 64> {};

template <>
struct numeric_limits<float> {
  static constexpr bool is_specialized = true;
  static constexpr bool is_signed = true;
  static constexpr bool is_integer = false;
  static constexpr bool is_exact = false;
  static constexpr bool has_infinity = true;
  static constexpr bool has_quiet_NaN = true;
  static constexpr bool has_signaling_NaN = true;
  static constexpr bool is_iec559 = true;
  static constexpr float_round_style round_style = round_to_nearest;
  static constexpr int digits = FLT_MANT_DIG;
  static constexpr int digits10 = FLT_DIG;
  static constexpr int max_digits10 = 9;
  static constexpr int radix = 2;
  static constexpr int min_exponent = FLT_MIN_EXP;
  static constexpr int max_exponent = FLT_MAX_EXP;
  static constexpr float min() noexcept { return FLT_MIN; }
  static constexpr float max() noexcept { return FLT_MAX; }
  static constexpr float lowest() noexcept { return -FLT_MAX; }
  static constexpr float epsilon() noexcept { return FLT_EPSILON; }
  static constexpr float round_error() noexcept { return 0.5f; }
  static constexpr float infinity() noexcept { return __builtin_huge_valf(); }
  static constexpr float quiet_NaN() noexcept { return __builtin_nanf("0"); }
  static constexpr float signaling_NaN() noexcept { return __builtin_nansf("1"); }
  static constexpr float denorm_min() noexcept { return FLT_TRUE_MIN; }
};
template <>
struct numeric_limits<double> {
  static constexpr bool is_specialized = true;
  static constexpr bool is_signed = true;
  static constexpr bool is_integer = false;
  static constexpr bool is_exact = false;
  static constexpr bool has_infinity = true;
  static constexpr bool has_quiet_NaN = true;
  static constexpr bool has_signaling_NaN = true;
  static constexpr bool is_iec559 = true;
  static constexpr float_round_style round_style = round_to_nearest;
  static constexpr int digits = DBL_MANT_DIG;
  static constexpr int digits10 = DBL_DIG;
  static constexpr int max_digits10 = 17;
  static constexpr int radix = 2;
  static constexpr int min_exponent = DBL_MIN_EXP;
  static constexpr int max_exponent = DBL_MAX_EXP;
  static constexpr double min() noexcept { return DBL_MIN; }
  static constexpr double max() noexcept { return DBL_MAX; }
  static constexpr double lowest() noexcept { return -DBL_MAX; }
  static constexpr double epsilon() noexcept { return DBL_EPSILON; }
  static constexpr double round_error() noexcept { return 0.5; }
  static constexpr double infinity() noexcept { return __builtin_huge_val(); }
  static constexpr double quiet_NaN() noexcept { return __builtin_nan("0"); }
  static constexpr double signaling_NaN() noexcept { return __builtin_nans("1"); }
  static constexpr double denorm_min() noexcept { return DBL_TRUE_MIN; }
};
}  // namespace std
