#pragma once #include "CoreTypes.h" #include "TypeTraits/TypeTraits.h" #include <limits> NAMESPACE_REDCRAFT_BEGIN NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Utility) static_assert(CHAR_BIT == 8, "CHAR_BIT must be 8"); enum class EFloatRoundMode : uint8 { TowardZero, ToNearest, Upward, Downward, Unknown, }; enum class EFloatDenormMode : uint8 { Absent, Present, Unknown, }; template <CArithmetic T> struct TNumericLimits; template <typename T> struct TNumericLimits<const T> : public TNumericLimits<T> { }; template <typename T> struct TNumericLimits< volatile T> : public TNumericLimits<T> { }; template <typename T> struct TNumericLimits<const volatile T> : public TNumericLimits<T> { }; template <CArithmetic T> struct TNumericLimits { static_assert(!CFloatingPoint<T> || NAMESPACE_STD::numeric_limits<T>::has_infinity, "Floating point types must have infinity."); static_assert(!CFloatingPoint<T> || NAMESPACE_STD::numeric_limits<T>::has_quiet_NaN, "Floating point types must have quiet NaN."); static_assert(!CFloatingPoint<T> || NAMESPACE_STD::numeric_limits<T>::has_signaling_NaN, "Floating point types must have signaling NaN."); static constexpr bool bIsExact = NAMESPACE_STD::numeric_limits<T>::is_exact; static constexpr EFloatRoundMode RoundMode = NAMESPACE_STD::numeric_limits<T>::round_style == NAMESPACE_STD::round_toward_zero ? EFloatRoundMode::TowardZero : NAMESPACE_STD::numeric_limits<T>::round_style == NAMESPACE_STD::round_to_nearest ? EFloatRoundMode::ToNearest : NAMESPACE_STD::numeric_limits<T>::round_style == NAMESPACE_STD::round_toward_infinity ? EFloatRoundMode::Upward : NAMESPACE_STD::numeric_limits<T>::round_style == NAMESPACE_STD::round_toward_neg_infinity ? EFloatRoundMode::Downward : EFloatRoundMode::Unknown; static constexpr EFloatDenormMode DenormMode = NAMESPACE_STD::numeric_limits<T>::has_denorm == NAMESPACE_STD::denorm_absent ? EFloatDenormMode::Absent : NAMESPACE_STD::numeric_limits<T>::has_denorm == NAMESPACE_STD::denorm_present ? EFloatDenormMode::Present : EFloatDenormMode::Unknown; static constexpr bool bHasDenormLoss = NAMESPACE_STD::numeric_limits<T>::has_denorm_loss; static constexpr bool bIsIEEE754 = NAMESPACE_STD::numeric_limits<T>::is_iec559 && sizeof(T) <= 8; static constexpr bool bIsModulo = NAMESPACE_STD::numeric_limits<T>::is_modulo; static constexpr int Radix = NAMESPACE_STD::numeric_limits<T>::radix; static constexpr int Digits = NAMESPACE_STD::numeric_limits<T>::digits; static constexpr int Digits10 = NAMESPACE_STD::numeric_limits<T>::digits10; static constexpr int MaxExponent = NAMESPACE_STD::numeric_limits<T>::max_exponent; static constexpr int MaxExponent10 = NAMESPACE_STD::numeric_limits<T>::max_exponent10; static constexpr int MinExponent = NAMESPACE_STD::numeric_limits<T>::min_exponent; static constexpr int MinExponent10 = NAMESPACE_STD::numeric_limits<T>::min_exponent10; static constexpr bool bInterrupt = NAMESPACE_STD::numeric_limits<T>::traps; static constexpr T Min() { return NAMESPACE_STD::numeric_limits<T>::lowest(); } static constexpr T Max() { return NAMESPACE_STD::numeric_limits<T>::max(); } static constexpr T Epsilon() { return NAMESPACE_STD::numeric_limits<T>::epsilon(); } static constexpr T Infinity() { return NAMESPACE_STD::numeric_limits<T>::infinity(); } static constexpr T QuietNaN() { return NAMESPACE_STD::numeric_limits<T>::quiet_NaN(); } static constexpr T SignalingNaN() { return NAMESPACE_STD::numeric_limits<T>::signaling_NaN(); } static constexpr T MinNormal() { return NAMESPACE_STD::numeric_limits<T>::min(); } static constexpr T MinDenorm() { return NAMESPACE_STD::numeric_limits<T>::denorm_min(); } }; NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END