diff --git a/Redcraft.Utility/Source/Public/Numerics/Limits.h b/Redcraft.Utility/Source/Public/Numerics/Limits.h new file mode 100644 index 0000000..d53c60c --- /dev/null +++ b/Redcraft.Utility/Source/Public/Numerics/Limits.h @@ -0,0 +1,91 @@ +#pragma once + +#include "CoreTypes.h" +#include "TypeTraits/TypeTraits.h" + +#include + +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 +struct TNumericLimits; + +template struct TNumericLimits : public TNumericLimits { }; +template struct TNumericLimits< volatile T> : public TNumericLimits { }; +template struct TNumericLimits : public TNumericLimits { }; + +template +struct TNumericLimits +{ + static_assert(!CFloatingPoint || NAMESPACE_STD::numeric_limits::has_infinity, "Floating point types must have infinity."); + static_assert(!CFloatingPoint || NAMESPACE_STD::numeric_limits::has_quiet_NaN, "Floating point types must have quiet NaN."); + static_assert(!CFloatingPoint || NAMESPACE_STD::numeric_limits::has_signaling_NaN, "Floating point types must have signaling NaN."); + + static constexpr bool bIsExact = NAMESPACE_STD::numeric_limits::is_exact; + + static constexpr EFloatRoundMode RoundMode = + NAMESPACE_STD::numeric_limits::round_style == NAMESPACE_STD::round_toward_zero ? EFloatRoundMode::TowardZero : + NAMESPACE_STD::numeric_limits::round_style == NAMESPACE_STD::round_to_nearest ? EFloatRoundMode::ToNearest : + NAMESPACE_STD::numeric_limits::round_style == NAMESPACE_STD::round_toward_infinity ? EFloatRoundMode::Upward : + NAMESPACE_STD::numeric_limits::round_style == NAMESPACE_STD::round_toward_neg_infinity ? EFloatRoundMode::Downward : + EFloatRoundMode::Unknown; + + static constexpr EFloatDenormMode DenormMode = + NAMESPACE_STD::numeric_limits::has_denorm == NAMESPACE_STD::denorm_absent ? EFloatDenormMode::Absent : + NAMESPACE_STD::numeric_limits::has_denorm == NAMESPACE_STD::denorm_present ? EFloatDenormMode::Present : + EFloatDenormMode::Unknown; + + static constexpr bool bHasDenormLoss = NAMESPACE_STD::numeric_limits::has_denorm_loss; + + static constexpr bool bIsIEEE754 = NAMESPACE_STD::numeric_limits::is_iec559 && sizeof(T) <= 8; + + static constexpr bool bIsModulo = NAMESPACE_STD::numeric_limits::is_modulo; + + static constexpr int Radix = NAMESPACE_STD::numeric_limits::radix; + + static constexpr int Digits = NAMESPACE_STD::numeric_limits::digits; + static constexpr int Digits10 = NAMESPACE_STD::numeric_limits::digits10; + + static constexpr int MaxExponent = NAMESPACE_STD::numeric_limits::max_exponent; + static constexpr int MaxExponent10 = NAMESPACE_STD::numeric_limits::max_exponent10; + static constexpr int MinExponent = NAMESPACE_STD::numeric_limits::min_exponent; + static constexpr int MinExponent10 = NAMESPACE_STD::numeric_limits::min_exponent10; + + static constexpr bool bInterrupt = NAMESPACE_STD::numeric_limits::traps; + + static constexpr T Min() { return NAMESPACE_STD::numeric_limits::lowest(); } + static constexpr T Max() { return NAMESPACE_STD::numeric_limits::max(); } + + static constexpr T Epsilon() { return NAMESPACE_STD::numeric_limits::epsilon(); } + + static constexpr T Infinity() { return NAMESPACE_STD::numeric_limits::infinity(); } + static constexpr T QuietNaN() { return NAMESPACE_STD::numeric_limits::quiet_NaN(); } + static constexpr T SignalingNaN() { return NAMESPACE_STD::numeric_limits::signaling_NaN(); } + + static constexpr T MinNormal() { return NAMESPACE_STD::numeric_limits::min(); } + static constexpr T MinDenorm() { return NAMESPACE_STD::numeric_limits::denorm_min(); } +}; + +NAMESPACE_MODULE_END(Utility) +NAMESPACE_MODULE_END(Redcraft) +NAMESPACE_REDCRAFT_END