refactor(*): refactor the tool library's parent folder to plural form
This commit is contained in:
244
Redcraft.Utility/Source/Public/Numerics/Bit.h
Normal file
244
Redcraft.Utility/Source/Public/Numerics/Bit.h
Normal file
@ -0,0 +1,244 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Numerics/Limits.h"
|
||||
#include "Numerics/Literal.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
#include <bit>
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
NAMESPACE_BEGIN(Math)
|
||||
|
||||
/** @return The reinterpreted value of the given value. */
|
||||
template <CTriviallyCopyable T, CTriviallyCopyable U> requires (sizeof(T) == sizeof(U))
|
||||
FORCEINLINE constexpr T BitCast(const U& Value)
|
||||
{
|
||||
return __builtin_bit_cast(T, Value);
|
||||
}
|
||||
|
||||
/** @return The value of reversed byte order of the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr T ByteSwap(T Value)
|
||||
{
|
||||
static_assert(sizeof(T) <= 16, "ByteSwap only works with T up to 128 bits");
|
||||
|
||||
if constexpr (sizeof(T) == 1) return Value;
|
||||
|
||||
# if PLATFORM_COMPILER_MSVC
|
||||
{
|
||||
if constexpr (sizeof(T) == 2) return _byteswap_ushort(Value);
|
||||
if constexpr (sizeof(T) == 4) return _byteswap_ulong(Value);
|
||||
if constexpr (sizeof(T) == 8) return _byteswap_uint64(Value);
|
||||
}
|
||||
# elif PLATFORM_COMPILER_CLANG || PLATFORM_COMPILER_GCC
|
||||
{
|
||||
if constexpr (sizeof(T) == 2) return __builtin_bswap16(Value);
|
||||
if constexpr (sizeof(T) == 4) return __builtin_bswap32(Value);
|
||||
if constexpr (sizeof(T) == 8) return __builtin_bswap64(Value);
|
||||
}
|
||||
# else
|
||||
{
|
||||
if constexpr (sizeof(T) == 2) return (Value << 8) | (Value >> 8); // AB -> BA
|
||||
|
||||
if constexpr (sizeof(T) == 4)
|
||||
{
|
||||
T Result = 0;
|
||||
|
||||
Result = ((Result << 8) & 0xFF00FF00u32) | ((Result >> 8) & 0x00FF00FFu32); // ABCD -> BADC
|
||||
|
||||
return (Result << 16) | (Result >> 16);
|
||||
}
|
||||
|
||||
if constexpr (sizeof(T) == 8)
|
||||
{
|
||||
T Result = Value;
|
||||
|
||||
Result = ((Result << 8) & 0xFF00FF00FF00FF00u64) | ((Result >> 8) & 0x00FF00FF00FF00FFu64); // ABCDEFGH -> BADCFEHG
|
||||
Result = ((Result << 16) & 0xFFFF0000FFFF0000u64) | ((Result >> 16) & 0x0000FFFF0000FFFFu64); // BADCFEHG -> DCBAHGFE
|
||||
|
||||
return (Result << 32) | (Result >> 32);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
# if PLATFORM_HAS_INT128
|
||||
{
|
||||
if constexpr (sizeof(T) == 16)
|
||||
{
|
||||
T Result = Value;
|
||||
|
||||
Result = ((Result << 8) & 0xFF00FF00FF00FF00FF00FF00FF00FF00u128) | ((Result >> 8) & 0x00FF00FF00FF00FF00FF00FF00FF00FFu128); // ABCDEFGHIJKLMNOP -> BADCFEHGJILKMONP
|
||||
Result = ((Result << 16) & 0xFFFF0000FFFF0000FFFF0000FFFF0000u128) | ((Result >> 16) & 0x0000FFFF0000FFFF0000FFFF0000FFFFu128); // BADCFEHGJILKMONP -> DCBAHGFEJIKLNOPM
|
||||
Result = ((Result << 32) & 0xFFFFFFFF00000000FFFFFFFF00000000u128) | ((Result >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFFu128); // DCBAHGFEJIKLNOPM -> HGFEDCBAKJILMOPN
|
||||
|
||||
return (Result << 64) | (Result >> 64);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @return true if the given value is power of two, false otherwise. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr bool IsSingleBit(T Value)
|
||||
{
|
||||
if constexpr (CSameAs<T, bool>) return Value;
|
||||
|
||||
else return Value && !(Value & (Value - 1));
|
||||
}
|
||||
|
||||
/** @return The number of all zeros in the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr uint CountAllZero(T Value)
|
||||
{
|
||||
if constexpr (CSameAs<T, bool>) return Value ? 0 : 1;
|
||||
|
||||
else return static_cast<uint>(TNumericLimits<T>::Digits - NAMESPACE_STD::popcount(Value));
|
||||
}
|
||||
|
||||
/** @return The number of all ones in the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr uint CountAllOne(T Value)
|
||||
{
|
||||
if constexpr (CSameAs<T, bool>) return Value ? 1 : 0;
|
||||
|
||||
else return static_cast<uint>(NAMESPACE_STD::popcount(Value));
|
||||
}
|
||||
|
||||
/** @return The number of leading zeros in the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr uint CountLeftZero(T Value)
|
||||
{
|
||||
if constexpr (CSameAs<T, bool>) return Value ? 0 : 1;
|
||||
|
||||
else return static_cast<uint>(NAMESPACE_STD::countl_zero(Value));
|
||||
}
|
||||
|
||||
/** @return The number of leading ones in the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr uint CountLeftOne(T Value)
|
||||
{
|
||||
return Math::CountLeftZero<T>(~Value);
|
||||
}
|
||||
|
||||
/** @return The number of trailing zeros in the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr uint CountRightZero(T Value)
|
||||
{
|
||||
if constexpr (CSameAs<T, bool>) return Value ? 0 : 1;
|
||||
|
||||
else return static_cast<uint>(NAMESPACE_STD::countr_zero(Value));
|
||||
}
|
||||
|
||||
/** @return The number of trailing ones in the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr uint CountRightOne(T Value)
|
||||
{
|
||||
return Math::CountRightZero<T>(~Value);
|
||||
}
|
||||
|
||||
/** @return The smallest number of bits that can represent the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr T BitWidth(T Value)
|
||||
{
|
||||
return TNumericLimits<T>::Digits - Math::CountLeftZero(Value);
|
||||
}
|
||||
|
||||
/** @return The smallest integral power of two not less than the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr T BitCeil(T Value)
|
||||
{
|
||||
if (Value <= 1u) return static_cast<T>(1);
|
||||
|
||||
return static_cast<T>(1) << Math::BitWidth(static_cast<T>(Value - 1));
|
||||
}
|
||||
|
||||
/** @return The largest integral power of two not greater than the given value. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr T BitFloor(T Value)
|
||||
{
|
||||
if (Value == 0u) return static_cast<T>(0);
|
||||
|
||||
return static_cast<T>(1) << (Math::BitWidth(static_cast<T>(Value)) - 1);
|
||||
}
|
||||
|
||||
template <CUnsignedIntegral T> FORCEINLINE constexpr T RotateLeft (T Value, int Offset);
|
||||
template <CUnsignedIntegral T> FORCEINLINE constexpr T RotateRight(T Value, int Offset);
|
||||
|
||||
/** @return The value bitwise left-rotation by the given offset. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr T RotateLeft(T Value, int Offset)
|
||||
{
|
||||
if constexpr (CSameAs<T, bool>) return Value;
|
||||
|
||||
else
|
||||
{
|
||||
if (Offset >= 0)
|
||||
{
|
||||
const auto Remainder = Offset % TNumericLimits<T>::Digits;
|
||||
|
||||
return static_cast<T>((Value << Remainder) | (Value >> (TNumericLimits<T>::Digits - Remainder)));
|
||||
}
|
||||
|
||||
return Math::RotateRight(Value, -Offset);
|
||||
}
|
||||
}
|
||||
|
||||
/** @return The value bitwise right-rotation by the given offset. */
|
||||
template <CUnsignedIntegral T>
|
||||
FORCEINLINE constexpr T RotateRight(T Value, int Offset)
|
||||
{
|
||||
if constexpr (CSameAs<T, bool>) return Value;
|
||||
|
||||
else
|
||||
{
|
||||
if (Offset >= 0)
|
||||
{
|
||||
const auto Remainder = Offset % TNumericLimits<T>::Digits;
|
||||
|
||||
return static_cast<T>((Value >> Remainder) | (Value << (TNumericLimits<T>::Digits - Remainder)));
|
||||
}
|
||||
return Math::RotateLeft(Value, -Offset);
|
||||
}
|
||||
}
|
||||
|
||||
/** The enum indicates the endianness of scalar types. */
|
||||
enum class EEndian
|
||||
{
|
||||
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__)
|
||||
|
||||
Little = __ORDER_LITTLE_ENDIAN__,
|
||||
Big = __ORDER_BIG_ENDIAN__,
|
||||
Native = __BYTE_ORDER__,
|
||||
|
||||
#elif PLATFORM_LITTLE_ENDIAN
|
||||
|
||||
Little,
|
||||
Big,
|
||||
Native = Little,
|
||||
|
||||
#elif PLATFORM_BIG_ENDIAN
|
||||
|
||||
Little,
|
||||
Big,
|
||||
Native = Big,
|
||||
|
||||
#else
|
||||
|
||||
Little,
|
||||
Big,
|
||||
Native,
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
NAMESPACE_END(Math)
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
92
Redcraft.Utility/Source/Public/Numerics/Limits.h
Normal file
92
Redcraft.Utility/Source/Public/Numerics/Limits.h
Normal file
@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
#include <climits>
|
||||
#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
|
133
Redcraft.Utility/Source/Public/Numerics/Literal.h
Normal file
133
Redcraft.Utility/Source/Public/Numerics/Literal.h
Normal file
@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
#if PLATFORM_COMPILER_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4455)
|
||||
#elif PLATFORM_COMPILER_GCC || PLATFORM_COMPILER_CLANG
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wliteral-suffix"
|
||||
#endif
|
||||
|
||||
FORCEINLINE constexpr int8 operator""i8 (unsigned long long int Value) { return static_cast<int8 >(Value); }
|
||||
FORCEINLINE constexpr int16 operator""i16(unsigned long long int Value) { return static_cast<int16>(Value); }
|
||||
FORCEINLINE constexpr int32 operator""i32(unsigned long long int Value) { return static_cast<int32>(Value); }
|
||||
FORCEINLINE constexpr int64 operator""i64(unsigned long long int Value) { return static_cast<int64>(Value); }
|
||||
|
||||
FORCEINLINE constexpr int8 operator""I8 (unsigned long long int Value) { return static_cast<int8 >(Value); }
|
||||
FORCEINLINE constexpr int16 operator""I16(unsigned long long int Value) { return static_cast<int16>(Value); }
|
||||
FORCEINLINE constexpr int32 operator""I32(unsigned long long int Value) { return static_cast<int32>(Value); }
|
||||
FORCEINLINE constexpr int64 operator""I64(unsigned long long int Value) { return static_cast<int64>(Value); }
|
||||
|
||||
FORCEINLINE constexpr uint8 operator""u8 (unsigned long long int Value) { return static_cast<uint8 >(Value); }
|
||||
FORCEINLINE constexpr uint16 operator""u16(unsigned long long int Value) { return static_cast<uint16>(Value); }
|
||||
FORCEINLINE constexpr uint32 operator""u32(unsigned long long int Value) { return static_cast<uint32>(Value); }
|
||||
FORCEINLINE constexpr uint64 operator""u64(unsigned long long int Value) { return static_cast<uint64>(Value); }
|
||||
|
||||
FORCEINLINE constexpr uint8 operator""U8 (unsigned long long int Value) { return static_cast<uint8 >(Value); }
|
||||
FORCEINLINE constexpr uint16 operator""U16(unsigned long long int Value) { return static_cast<uint16>(Value); }
|
||||
FORCEINLINE constexpr uint32 operator""U32(unsigned long long int Value) { return static_cast<uint32>(Value); }
|
||||
FORCEINLINE constexpr uint64 operator""U64(unsigned long long int Value) { return static_cast<uint64>(Value); }
|
||||
|
||||
#if PLATFORM_HAS_INT128
|
||||
|
||||
FORCEINLINE constexpr int128 operator""i128(const char* Str);
|
||||
FORCEINLINE constexpr uint128 operator""u128(const char* Str);
|
||||
|
||||
FORCEINLINE constexpr int128 operator""I128(const char* Str) { return operator""i128(Str); }
|
||||
FORCEINLINE constexpr uint128 operator""U128(const char* Str) { return operator""u128(Str); }
|
||||
|
||||
FORCEINLINE constexpr int128 operator""i128(const char* Str)
|
||||
{
|
||||
return static_cast<int128>(operator""u128(Str));
|
||||
}
|
||||
|
||||
FORCEINLINE constexpr uint128 operator""u128(const char* Str)
|
||||
{
|
||||
constexpr uint8 DigitFromChar[] =
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
|
||||
uint128 Result = 0;
|
||||
|
||||
uint Base = 10;
|
||||
|
||||
size_t BeginIndex = 0;
|
||||
|
||||
if (Str[0] == '0')
|
||||
{
|
||||
if (Str[1] == 'x' || Str[1] == 'X')
|
||||
{
|
||||
Base = 16;
|
||||
BeginIndex += 2;
|
||||
}
|
||||
else if (Str[1] == 'b' || Str[1] == 'B')
|
||||
{
|
||||
Base = 2;
|
||||
BeginIndex += 2;
|
||||
}
|
||||
else Base = 8;
|
||||
}
|
||||
|
||||
for (size_t I = BeginIndex; Str[I]; ++I)
|
||||
{
|
||||
Result = Result * Base + DigitFromChar[Str[I]];
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if PLATFORM_HAS_INT128
|
||||
FORCEINLINE constexpr intmax operator""imax(const char* Str) { return operator""i128(Str); }
|
||||
FORCEINLINE constexpr intmax operator""IMAX(const char* Str) { return operator""I128(Str); }
|
||||
FORCEINLINE constexpr uintmax operator""umax(const char* Str) { return operator""u128(Str); }
|
||||
FORCEINLINE constexpr uintmax operator""UMAX(const char* Str) { return operator""U128(Str); }
|
||||
#else
|
||||
FORCEINLINE constexpr intmax operator""imax(unsigned long long int Value) { return operator""i64(Value); }
|
||||
FORCEINLINE constexpr intmax operator""IMAX(unsigned long long int Value) { return operator""I64(Value); }
|
||||
FORCEINLINE constexpr uintmax operator""umax(unsigned long long int Value) { return operator""u64(Value); }
|
||||
FORCEINLINE constexpr uintmax operator""UMAX(unsigned long long int Value) { return operator""U64(Value); }
|
||||
#endif
|
||||
|
||||
#ifndef __STDCPP_FLOAT32_T__
|
||||
FORCEINLINE constexpr float32 operator""f32(long double Value) { return static_cast<float32>(Value); }
|
||||
FORCEINLINE constexpr float32 operator""F32(long double Value) { return static_cast<float32>(Value); }
|
||||
#endif
|
||||
|
||||
#ifndef __STDCPP_FLOAT64_T__
|
||||
FORCEINLINE constexpr float64 operator""f64(long double Value) { return static_cast<float64>(Value); }
|
||||
FORCEINLINE constexpr float64 operator""F64(long double Value) { return static_cast<float64>(Value); }
|
||||
#endif
|
||||
|
||||
#if PLATFORM_COMPILER_MSVC
|
||||
# pragma warning(pop)
|
||||
#elif PLATFORM_COMPILER_GCC || PLATFORM_COMPILER_CLANG
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
1081
Redcraft.Utility/Source/Public/Numerics/Math.h
Normal file
1081
Redcraft.Utility/Source/Public/Numerics/Math.h
Normal file
File diff suppressed because it is too large
Load Diff
40
Redcraft.Utility/Source/Public/Numerics/Numbers.h
Normal file
40
Redcraft.Utility/Source/Public/Numerics/Numbers.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
NAMESPACE_BEGIN(Math)
|
||||
|
||||
template <CFloatingPoint T>
|
||||
struct TNumbers
|
||||
{
|
||||
static constexpr T E = static_cast<T>(2.71828182845904523536028747135266249775724709369995);
|
||||
static constexpr T Log2E = static_cast<T>(1.44269504088896340735992468100189213742664595415299);
|
||||
static constexpr T Log10E = static_cast<T>(0.43429448190325182765112891891660508229439700580367);
|
||||
static constexpr T Pi = static_cast<T>(3.14159265358979323846264338327950288419716939937511);
|
||||
static constexpr T HalfPi = static_cast<T>(1.57079632679489661923132169163975144209858469968756);
|
||||
static constexpr T TwoPi = static_cast<T>(6.28318530717958647692528676655900576839433879875022);
|
||||
static constexpr T SquaredPi = static_cast<T>(9.86960440108935861883449099987615113531369940724079);
|
||||
static constexpr T InvPi = static_cast<T>(0.31830988618379067153776752674502872406891929148091);
|
||||
static constexpr T InvSqrtPi = static_cast<T>(0.56418958354775628694807945156077258584405062932900);
|
||||
static constexpr T Ln2 = static_cast<T>(0.69314718055994530941723212145817656807550013436026);
|
||||
static constexpr T Ln10 = static_cast<T>(2.30258509299404568401799145468436420760110148862877);
|
||||
static constexpr T Sqrt2 = static_cast<T>(1.41421356237309504880168872420969807856967187537694);
|
||||
static constexpr T Sqrt3 = static_cast<T>(1.73205080756887729352744634150587236694280525381038);
|
||||
static constexpr T InvSqrt2 = static_cast<T>(0.70710678118654752440084436210484903928483593768847);
|
||||
static constexpr T InvSqrt3 = static_cast<T>(0.57735026918962576450914878050195745564760175127013);
|
||||
static constexpr T HalfSqrt2 = static_cast<T>(0.70710678118654752440084436210484903928483593768847);
|
||||
static constexpr T HalfSqrt3 = static_cast<T>(0.86602540378443864676372317075293618347140262690519);
|
||||
static constexpr T EGamma = static_cast<T>(0.57721566490153286060651209008240243104215933593992);
|
||||
static constexpr T GoldenRatio = static_cast<T>(1.61803398874989484820458683436563811772030917980576);
|
||||
};
|
||||
|
||||
NAMESPACE_END(Math)
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
9
Redcraft.Utility/Source/Public/Numerics/Numerics.h
Normal file
9
Redcraft.Utility/Source/Public/Numerics/Numerics.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Numerics/Literal.h"
|
||||
#include "Numerics/Limits.h"
|
||||
#include "Numerics/Numbers.h"
|
||||
#include "Numerics/Bit.h"
|
||||
#include "Numerics/Math.h"
|
||||
#include "Numerics/Random.h"
|
88
Redcraft.Utility/Source/Public/Numerics/Random.h
Normal file
88
Redcraft.Utility/Source/Public/Numerics/Random.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Numerics/Bit.h"
|
||||
#include "Numerics/Math.h"
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
NAMESPACE_BEGIN(Math)
|
||||
|
||||
/** Seeds the random number generator. Return the previous seed. */
|
||||
NODISCARD REDCRAFTUTILITY_API uint32 Seed(uint32 InSeed = 0);
|
||||
|
||||
/** @return The generated random number within the range of [0, 0x7FFFFFFF). */
|
||||
NODISCARD REDCRAFTUTILITY_API uint32 Rand();
|
||||
|
||||
/** @return The generated random number within the range of [0, A). */
|
||||
template <CIntegral T>
|
||||
NODISCARD FORCEINLINE T Rand(T A)
|
||||
{
|
||||
constexpr uint32 RandStateNum = 0x7FFFFFFF;
|
||||
|
||||
if (A <= 0) return 0;
|
||||
|
||||
if (A <= RandStateNum) return Rand() % A;
|
||||
|
||||
constexpr uint32 BlockSize = Math::BitFloor(RandStateNum);
|
||||
constexpr uint BlockWidth = Math::CountRightZero(BlockSize);
|
||||
|
||||
const T BlockNum = Math::DivAndCeil(A, BlockSize);
|
||||
|
||||
T Result = 0;
|
||||
|
||||
for (T I = 0; I < BlockNum; ++I)
|
||||
{
|
||||
Result ^= Rand();
|
||||
|
||||
Result <<= BlockWidth;
|
||||
}
|
||||
|
||||
return Math::Abs(Result) % A;
|
||||
}
|
||||
|
||||
/** @return The generated random number within the range of [0, A). */
|
||||
template <CFloatingPoint T>
|
||||
NODISCARD FORCEINLINE T Rand(T A)
|
||||
{
|
||||
constexpr uint32 RandStateNum = 0x7FFFFFFF;
|
||||
|
||||
if (Math::IsNegative(A)) return TNumericLimits<T>::QuietNaN();
|
||||
|
||||
constexpr size_t BlockNum = Math::DivAndCeil(sizeof(T), 4);
|
||||
|
||||
T Multiplier = A;
|
||||
|
||||
Multiplier /= BlockNum;
|
||||
Multiplier /= RandStateNum;
|
||||
|
||||
T Result = 0;
|
||||
|
||||
for (size_t I = 0; I < BlockNum; ++I)
|
||||
{
|
||||
Result += Rand() * Multiplier;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/** @return The generated random number within the range of [A, B). */
|
||||
template <CArithmetic T, CArithmetic U> requires (CCommonType<T, U>)
|
||||
NODISCARD FORCEINLINE auto RandWithin(T A, U B)
|
||||
{
|
||||
using FCommonT = TCommonType<T, U>;
|
||||
|
||||
if (A == B) return static_cast<FCommonT>(A);
|
||||
|
||||
if (A > B) return Math::RandWithin(B, A);
|
||||
|
||||
return static_cast<FCommonT>(A + Math::Rand(B - A));
|
||||
}
|
||||
|
||||
NAMESPACE_END(Math)
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
Reference in New Issue
Block a user