Added C++ Utilities

This commit is contained in:
Arron David Nelson 2023-10-26 23:28:06 -07:00
parent d23e3d99e3
commit 3c993d7d69
39 changed files with 9539 additions and 2 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13.4)
project(ClassicOS VERSION 0.0.1 LANGUAGES C ASM_NASM)
project(ClassicOS VERSION 0.0.1 LANGUAGES C CXX ASM_NASM)
set(IS_OS_WINDOWS FALSE)
set(IS_OS_LINUX FALSE)
@ -38,7 +38,7 @@ set(DRIVERS_SOURCE_FILES
src/drivers/bus/isa.h
src/drivers/bus/mca.c
src/drivers/bus/mca.h
src/drivers/bus/pci.asm
#src/drivers/bus/pci.asm
src/drivers/bus/pci.c
src/drivers/bus/pci.h
src/drivers/bus/vesa.c
@ -71,6 +71,33 @@ set(KERNEL_SOURCE_FILES
src/kernel/print.c
)
set(UTIL_SOURCE_FILES
src/EHS.h
src/sys/cpu.h src/sys/cpu.cpp src/sys/CPU_GCC_AMD64.asm
src/Util.h src/Util.cpp
src/Version.h src/Version.cpp
src/Serializer.h
src/Array.h
src/Vector.h
src/SArray.h
src/Str.h
src/PRNG.h
src/HRNG.h src/HRNG_GCC.s
src/Math.h src/Math.cpp src/Math_GCC_AMD64.s
src/Rect.h
src/Range.h src/Range.cpp
src/Color4.h src/Color4.cpp
src/Color3.h src/Color3.cpp
src/Quat.h
src/Vec4.h
src/Vec3.h
src/Vec2.h
src/Mat4.h
src/Mat3.h
src/Mat2.h
)
add_executable(ClassicOS
${GRUB_SOURCE_FILES}
${DRIVERS_SOURCE_FILES}

375
src/Array.h Normal file
View File

@ -0,0 +1,375 @@
#pragma once
#include "EHS.h"
#include <initializer_list>
#include <algorithm>
/// A helper class for C-style arrays.
/// @tparam T Array data type to use.
/// @tparam N Number data type to use.
template<typename T, typename N = USize>
class Array
{
protected:
T* data;
N size;
public:
/// Frees any data created on the heap.
~Array()
{
delete[] data;
}
/// Default members initialization.
Array()
: data(nullptr), size(0)
{
}
/// Initializes an empty array with the given size.
/// @note Data must be assigned manually using an index.
explicit Array(const N size)
: data(new T[size]), size(size)
{
}
/// Initializes this array with an initializer list object.
/// @param [in] list The given initializer list.
Array(std::initializer_list<T> list)
: data(new T[list.size()]), size(list.size())
{
N i = 0;
for (auto v = list.begin(); v != list.end(); ++v)
data[i++] = std::move(*v);
}
/// Initializes members with given C-style array.
/// @param [in] data The C-style array.
/// @param [in] size The size of the given C-style array.
Array(const T* const data, const N size)
: data(new T[size]), size(size)
{
for (N i = 0; i < size; ++i)
this->data[i] = data[i];
}
/// Copies all members from the given array object.
/// @param [in] array The array object to copy from.
Array(const Array& array)
: data(new T[array.size]), size(array.size)
{
for (N i = 0; i < size; ++i)
data[i] = array.data[i];
}
Array(Array&& array) noexcept
: data(array.data), size(array.size)
{
array.data = nullptr;
array.size = 0;
}
/// Copies all members from the given array object.
/// @param [in] array The array object to copy from.
/// @returns The array that has been assigned to.
Array<T, N>& operator=(const Array& array)
{
if (this == &array)
return *this;
delete[] data;
data = new T[array.size];
for (N i = 0; i < array.size; ++i)
data[i] = array.data[i];
size = array.size;
return *this;
}
Array<T, N>& operator=(Array&& array) noexcept
{
if (this == &array)
return *this;
delete[] data;
data = array.data;
size = array.size;
array.data = nullptr;
array.size = 0;
return *this;
}
/// Copies all members from the given initializer list object.
/// @param [in] list The initializer list object to copy from.
/// @returns The array that has been assigned to.
Array& operator=(std::initializer_list<T> list)
{
delete[] data;
data = new T[list.size];
N i = 0;
for (auto v = list.begin(); v != list.end(); ++v)
data[i++] = std::move(*v);
size = list.size();
return *this;
}
/// Adds a given array object at the end of the array.
/// @param [in] value The given array object to push to the end of the array.
Array& operator+=(Array value)
{
T* result = new T[size + value.size];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
for (N i = 0; i < value.size; ++i)
result[size + i] = std::move(value[i]);
delete[] data;
data = result;
size += value.size;
return *this;
}
bool operator==(const Array<T, N>& array) const
{
if (size != array.size)
return false;
for (N i = 0; i < size; ++i)
if (data[i] != array[i])
return false;
return true;
}
bool operator!=(const Array<T, N>& array) const
{
if (size == array.size)
return false;
for (N i = 0; i < size; ++i)
if (data[i] != array[i])
return true;
return false;
}
/// Adds a given array object at the end of the array.
/// @param [in] value The given initializer list to push to the end of the array.
Array& operator+=(std::initializer_list<T> value)
{
T* result = new T[size + value.size()];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
N i = 0;
for (auto v = value.begin(); v != value.end(); ++v)
result[size + i++] = std::move(*v);
delete[] data;
data = result;
size += value.size();
return *this;
}
/// Adds a given value at the end of the array.
/// @param [in] value The given value to push to the end of the array.
Array& operator+=(const T value)
{
T* result = new T[size + 1];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
result[size] = std::move(value);
delete[] data;
data = result;
++size;
return *this;
}
/// Retrieves the raw C-style array from casting an array object.
operator T* () const
{
return data;
}
/// Swaps two values in the array.
/// @param a The first index to swap with.
/// @param b The second index to swap with.
void Swap(N a, N b) const
{
T tmp = std::move(data[a]);
data[a] = std::move(data[b]);
data[b] = std::move(tmp);
}
/// Adds a given C-style array at the end of the array.
/// @param [in] value The given C-style array to push to the end of the array.
/// @param [in] size The size of the given C-style array.
void Push(const T* const value, const N size)
{
T* result = new T[this->size + size];
for (N i = 0; i < this->size; ++i)
result[i] = std::move(this->data[i]);
for (N i = 0; i < size; ++i)
result[this->size + i] = value[i];
delete[] data;
this->data = result;
this->size += size;
}
/// Adds a given array object at the end of the array.
/// @param [in] value The given array object to push to the end of the array.
void Push(Array value)
{
T* result = new T[size + value.size];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
for (N i = 0; i < value.size; ++i)
result[size + i] = std::move(value[i]);
delete[] data;
data = result;
size += value.size;
}
/// Adds a given array object at the end of the array.
/// @param [in] value The given initializer list to push to the end of the array.
void Push(std::initializer_list<T> value)
{
T* result = new T[size + value.size()];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
N i = 0;
for (auto v = value.begin(); v != value.end(); ++v)
result[size + i++] = std::move(*v);
delete[] data;
data = result;
size += value.size();
}
/// Adds a given value at the end of the array.
/// @param [in] value The given value to push to the end of the array.
void Push(T value)
{
T* result = new T[size + 1];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
result[size] = std::move(value);
delete[] data;
data = result;
++size;
}
/// Removes a value at the end of the array.
/// @returns The value that was popped.
T Pop()
{
T* result = new T[--size];
T value = std::move(data[size]);
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
return value;
}
/// Removes a value at a provided index.
/// @param [in] index The index of the value to remove.
/// @returns The value that was removed.
T Remove(const N index)
{
T* result = new T[--size];
T value = std::move(data[index]);
for (N i = 0, c = 0; i < size; ++i)
if (i != index)
result[c++] = std::move(data[i]);
delete[] data;
data = result;
return value;
}
void Clear()
{
if (!data)
return;
delete[] data;
data = nullptr;
size = 0;
}
/// Resizes the array.
/// @param [in] newSize The size to change to.
void Resize(const N newSize)
{
if (size == newSize)
return;
T* result = new T[newSize];
for (N i = 0; i < newSize && i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
size = newSize;
}
/// Retrieves the size of the array.
/// @returns The resulting size.
N Size() const
{
return size;
}
N End() const
{
return size - 1;
}
};

89
src/Color3.cpp Normal file
View File

@ -0,0 +1,89 @@
#include "Color3.h"
#include "Math.h"
Color3::Color3()
: r(0.0f), g(0.0f), b(0.0f)
{
}
Color3::Color3(const float scalar)
: r(Math::Clamp(scalar, 0.0f, 1.0f)), g(Math::Clamp(scalar, 0.0f, 1.0f)), b(Math::Clamp(scalar, 0.0f, 1.0f))
{
}
Color3::Color3(const float r, const float g, const float b)
: r(Math::Clamp(r, 0.0f, 1.0f)), g(Math::Clamp(g, 0.0f, 1.0f)), b(Math::Clamp(b, 0.0f, 1.0f))
{
}
Color3::Color3(const Color3& color)
: r(color.r), g(color.g), b(color.b)
{
}
Color3& Color3::operator=(const Color3& color)
{
if (this == &color)
return *this;
r = color.r;
g = color.g;
b = color.b;
return *this;
}
bool Color3::operator==(const Color3& color) const
{
return r == color.r && g == color.g && b == color.b;
}
bool Color3::operator!=(const Color3& color) const
{
return r != color.r || g != color.g || b != color.b;
}
float Color3::operator[](const UInt_64 i) const
{
switch (i)
{
case 0:
return r;
case 1:
return g;
case 2:
return b;
default:
return r;
}
}
float& Color3::operator[](const UInt_64 i)
{
switch (i)
{
case 0:
return r;
case 1:
return g;
case 2:
return b;
default:
return r;
}
}
Color3& Color3::operator*=(const Color3& color)
{
r *= color.r;
g *= color.g;
b *= color.b;
return *this;
}
Color3 Color3::operator*(const Color3& color) const
{
return {r * color.r, g * color.g, b * color.b};
}

33
src/Color3.h Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include "EHS.h"
class Color3
{
public:
float r;
float g;
float b;
Color3();
Color3(const float scalar);
Color3(const float r, const float g, const float b);
Color3(const Color3& color);
Color3& operator=(const Color3& color);
bool operator==(const Color3& color) const;
bool operator!=(const Color3& color) const;
float operator[](const UInt_64 i) const;
float& operator[](const UInt_64 i);
Color3& operator*=(const Color3& color);
Color3 operator*(const Color3& color) const;
};

97
src/Color4.cpp Normal file
View File

@ -0,0 +1,97 @@
#include "Color4.h"
#include "Math.h"
{
Color4::Color4()
: r(0.0f), g(0.0f), b(0.0f), a(1.0f)
{
}
Color4::Color4(const float scalar, const float a)
: r(Math::Clamp(scalar, 0.0f, 1.0f)), g(Math::Clamp(scalar, 0.0f, 1.0f)), b(Math::Clamp(scalar, 0.0f, 1.0f)), a(a)
{
}
Color4::Color4(const float r, const float g, const float b, const float a)
: r(Math::Clamp(r, 0.0f, 1.0f)), g(Math::Clamp(g, 0.0f, 1.0f)), b(Math::Clamp(b, 0.0f, 1.0f)), a(Math::Clamp(a, 0.0f, 1.0f))
{
}
Color4::Color4(const Color4& color)
: r(color.r), g(color.g), b(color.b), a(color.a)
{
}
Color4& Color4::operator=(const Color4& color)
{
if (this == &color)
return *this;
r = color.r;
g = color.g;
b = color.b;
a = color.a;
return *this;
}
bool Color4::operator==(const Color4& color) const
{
return r == color.r && g == color.g && b == color.b && a == color.a;
}
bool Color4::operator!=(const Color4& color) const
{
return r != color.r || g != color.g || b != color.b || a != color.a;
}
float Color4::operator[](const UInt_64 i) const
{
switch (i)
{
case 0:
return r;
case 1:
return g;
case 2:
return b;
case 3:
return a;
default:
return r;
}
}
float& Color4::operator[](const UInt_64 i)
{
switch (i)
{
case 0:
return r;
case 1:
return g;
case 2:
return b;
case 3:
return a;
default:
return r;
}
}
Color4& Color4::operator*=(const Color4& color)
{
r *= color.r;
g *= color.g;
b *= color.b;
return *this;
}
Color4 Color4::operator*(const Color4& color) const
{
return {r * color.r, g * color.g, b * color.b, a};
}
}

34
src/Color4.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include "EHS.h"
class Color4
{
public:
float r;
float g;
float b;
float a;
Color4();
Color4(const float scalar, const float a = 1.0f);
Color4(const float r, const float g, const float b, const float a = 1.0f);
Color4(const Color4& color);
Color4& operator=(const Color4& color);
bool operator==(const Color4& color) const;
bool operator!=(const Color4& color) const;
float operator[](const UInt_64 i) const;
float& operator[](const UInt_64 i);
Color4& operator*=(const Color4& color);
Color4 operator*(const Color4& color) const;
};

72
src/EHS.h Normal file
View File

@ -0,0 +1,72 @@
#if defined(_M_AMD64) || defined(_M_X64) || defined(__x86_64__)
#define LITTLE_ENDIAN
#define ARCH_X64
#elif defined(__i386__)
#define LITTLE_ENDIAN
#define ARCH_X86
#elif defined(_M_ARM64) || defined(__aarch64__)
#define LITTLE_ENDIAN
#define ARCH_ARM64
#else
#error Unsupported architecture.
#endif
typedef unsigned char UInt_8;
typedef signed char SInt_8;
typedef char Int_8;
typedef unsigned short UInt_16;
typedef signed short SInt_16;
typedef short Int_16;
typedef unsigned int UInt_32;
typedef signed int SInt_32;
typedef int Int_32;
typedef UInt_8 Byte;
typedef Int_8 Char_8;
typedef Int_16 Char_16;
typedef Int_32 Char_32;
#if defined(__GNUC__)
typedef unsigned long long UInt_64;
typedef signed long long SInt_64;
typedef long long Int_64;
#elif defined(_WIN32)
typedef unsigned long UInt_64;
typedef signed long SInt_64;
typedef long Int_64;
#endif
#if defined(ARCH_X64)
typedef UInt_64 USize;
typedef SInt_64 SSize;
typedef Int_64 Size;
#elif defined(ARCH_X86)
typedef UInt_32 USize;
typedef SInt_32 SSize;
typedef Int_32 Size;
#endif
#define MAX_PATH 0x104
#define UINT_8_MAX 0xFF
#define SINT_8_MAX 0x7F
#define SINT_8_MIN 0x80
#define UINT_16_MAX 0xFFFF
#define SINT_16_MAX 0x7FFF
#define SINT_16_MIN 0x8000
#define UINT_24_MAX 0xFFFFFF
#define SINT_24_MAX 0x7FFFFF
#define SINT_24_MIN 0x800000
#define UINT_32_MAX 0xFFFFFFFF
#define SINT_32_MAX 0x7FFFFFFF
#define SINT_32_MIN 0x80000000
#define UINT_64_MAX 0xFFFFFFFFFFFFFFFF
#define SINT_64_MAX 0x7FFFFFFFFFFFFFFF
#define SINT_64_MIN 0x8000000000000000
#define FLOAT_MAX 3.40282e+038f
#define FLOAT_MIN 1.17549e-038f
#define DOUBLE_MAX 1.79769e+308
#define DOUBLE_MIN 2.22507e-308
#define LDOUBLE_MAX 1.79769e+308
#define LDOUBLE_MIN 2.22507e-308
#define INFINITE UINT_32_MAX

55
src/HRNG.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include "EHS.h"
class HRNG
{
public:
static UInt_64 GenerateSeed_u64();
static UInt_64 Generate_u64(const UInt_64 min, const UInt_64 max);
static UInt_64 Generate_u64();
static SInt_64 GenerateSeed_s64();
static SInt_64 Generate_s64(const SInt_64 min, const SInt_64 max);
static SInt_64 Generate_s64();
static UInt_32 GenerateSeed_u32();
static UInt_32 Generate_u32(const UInt_32 min, const UInt_32 max);
static UInt_32 Generate_u32();
static SInt_32 GenerateSeed_s32();
static SInt_32 Generate_s32(const SInt_32 min, const SInt_32 max);
static SInt_32 Generate_s32();
static UInt_32 GenerateSeed_u16();
static UInt_16 Generate_u16(const UInt_16 min, const UInt_16 max);
static UInt_16 Generate_u16();
static SInt_16 GenerateSeed_s16();
static SInt_16 Generate_s16(const SInt_16 min, const SInt_16 max);
static SInt_16 Generate_s16();
static UInt_8 GenerateSeed_u8();
static UInt_8 Generate_u8(const UInt_8 min, const UInt_8 max);
static UInt_8 Generate_u8();
static SInt_8 GenerateSeed_s8();
static SInt_8 Generate_s8(const SInt_8 min, const SInt_8 max);
static SInt_8 Generate_s8();
};

161
src/HRNG_GCC.s Normal file
View File

@ -0,0 +1,161 @@
global _ZN3lwe4HRNG16GenerateSeed_u64Ev
global _ZN3lwe4HRNG12Generate_u64Emm
global _ZN3lwe4HRNG12Generate_u64Ev
global _ZN3lwe4HRNG16GenerateSeed_s64Ev
global _ZN3lwe4HRNG12Generate_s64Ell
global _ZN3lwe4HRNG12Generate_s64Ev
global _ZN3lwe4HRNG16GenerateSeed_u32Ev
global _ZN3lwe4HRNG12Generate_u32Ejj
global _ZN3lwe4HRNG12Generate_u32Ev
global _ZN3lwe4HRNG16GenerateSeed_s32Ev
global _ZN3lwe4HRNG12Generate_s32Eii
global _ZN3lwe4HRNG12Generate_s32Ev
global _ZN3lwe4HRNG16GenerateSeed_u16Ev
global _ZN3lwe4HRNG12Generate_u16Ett
global _ZN3lwe4HRNG12Generate_u16Ev
global _ZN3lwe4HRNG16GenerateSeed_s16Ev
global _ZN3lwe4HRNG12Generate_s16Ess
global _ZN3lwe4HRNG12Generate_s16Ev
global _ZN3lwe4HRNG15GenerateSeed_u8Ev
global _ZN3lwe4HRNG11Generate_u8Ehh
global _ZN3lwe4HRNG11Generate_u8Ev
global _ZN3lwe4HRNG15GenerateSeed_s8Ev
global _ZN3lwe4HRNG11Generate_s8Eaa
global _ZN3lwe4HRNG11Generate_s8Ev
section .text
_ZN3lwe4HRNG16GenerateSeed_u64Ev:
RDSEED RAX
RET
_ZN3lwe4HRNG12Generate_u64Emm:
RDRAND RAX
SUB RDI, RCX
XOR RDX, RDX
DIV RDI
MOV RAX, RDX
ADD RAX, RCX
RET
_ZN3lwe4HRNG12Generate_u64Ev:
RDRAND RAX
RET
_ZN3lwe4HRNG16GenerateSeed_s64Ev:
RDSEED RAX
RET
_ZN3lwe4HRNG12Generate_s64Ell:
RDRAND RAX
SUB RDI, RCX
XOR RDX, RDX
DIV RDI
MOV RAX, RDX
ADD RAX, RCX
RET
_ZN3lwe4HRNG12Generate_s64Ev:
RDRAND RAX
RET
_ZN3lwe4HRNG16GenerateSeed_u32Ev:
RDSEED EAX
RET
_ZN3lwe4HRNG12Generate_u32Ejj:
RDRAND EAX
SUB EDI, ECX
XOR EDX, EDX
DIV EDI
MOV EAX, EDX
ADD EAX, ECX
RET
_ZN3lwe4HRNG12Generate_u32Ev:
RDRAND EAX
RET
_ZN3lwe4HRNG16GenerateSeed_s32Ev:
RDSEED EAX
RET
_ZN3lwe4HRNG12Generate_s32Eii:
RDRAND EAX
SUB EDI, ECX
XOR EDX, EDX
DIV EDI
MOV EAX, EDX
ADD EAX, ECX
RET
_ZN3lwe4HRNG12Generate_s32Ev:
RDRAND EAX
RET
_ZN3lwe4HRNG16GenerateSeed_u16Ev:
RDSEED AX
RET
_ZN3lwe4HRNG12Generate_u16Ett:
RDRAND AX
SUB DI, CX
XOR DX, DX
DIV DI
MOV AX, DX
ADD AX, CX
RET
_ZN3lwe4HRNG12Generate_u16Ev:
RDRAND AX
RET
_ZN3lwe4HRNG16GenerateSeed_s16Ev:
RDSEED AX
RET
_ZN3lwe4HRNG12Generate_s16Ess:
RDRAND AX
SUB DI, CX
XOR DX, DX
DIV DI
MOV AX, DX
ADD AX, CX
RET
_ZN3lwe4HRNG12Generate_s16Ev:
RDRAND AX
RET
_ZN3lwe4HRNG15GenerateSeed_u8Ev:
RDSEED AX
RET
_ZN3lwe4HRNG11Generate_u8Ehh:
RDRAND AX
SUB DI, CX
XOR DX, DX
DIV DI
MOV AX, DX
ADD AX, CX
RET
_ZN3lwe4HRNG11Generate_u8Ev:
RDRAND AX
RET
_ZN3lwe4HRNG15GenerateSeed_s8Ev:
RDSEED AX
RET
_ZN3lwe4HRNG11Generate_s8Eaa:
RDRAND AX
SUB DI, CX
XOR DX, DX
DIV DI
MOV AX, DX
ADD AX, CX
RET
_ZN3lwe4HRNG11Generate_s8Ev:
RDRAND AX
RET

169
src/HRNG_MSVC.s Normal file
View File

@ -0,0 +1,169 @@
global ?GenerateSeed_u64@HRNG@lwe@@SA_KXZ
global ?Generate_u64@HRNG@lwe@@SA_K_K0@Z
global ?Generate_u64@HRNG@lwe@@SA_KXZ
global ?GenerateSeed_s64@HRNG@lwe@@SA_JXZ
global ?Generate_s64@HRNG@lwe@@SA_J_J0@Z
global ?Generate_s64@HRNG@lwe@@SA_JXZ
global ?GenerateSeed_u32@HRNG@lwe@@SAIXZ
global ?Generate_u32@HRNG@lwe@@SAIII@Z
global ?Generate_u32@HRNG@lwe@@SAIXZ
global ?GenerateSeed_s32@HRNG@lwe@@SAHXZ
global ?Generate_s32@HRNG@lwe@@SAHHH@Z
global ?Generate_s32@HRNG@lwe@@SAHXZ
global ?GenerateSeed_u16@HRNG@lwe@@SAIXZ
global ?Generate_u16@HRNG@lwe@@SAGGG@Z
global ?Generate_u16@HRNG@lwe@@SAGXZ
global ?GenerateSeed_s16@HRNG@lwe@@SAFXZ
global ?Generate_s16@HRNG@lwe@@SAFFF@Z
global ?Generate_s16@HRNG@lwe@@SAFXZ
global ?GenerateSeed_u8@HRNG@lwe@@SAEXZ
global ?Generate_u8@HRNG@lwe@@SAEEE@Z
global ?Generate_u8@HRNG@lwe@@SAEXZ
global ?GenerateSeed_s8@HRNG@lwe@@SACXZ
global ?Generate_s8@HRNG@lwe@@SACCC@Z
global ?Generate_s8@HRNG@lwe@@SACXZ
section .text
?GenerateSeed_u64@HRNG@lwe@@SA_KXZ:
RDSEED RAX
RET
?Generate_u64@HRNG@lwe@@SA_K_K0@Z:
RDRAND RAX
MOV R8, RDX
SUB R8, RCX
XOR RDX, RDX
DIV R8
MOV RAX, RDX
ADD RAX, RCX
RET
?Generate_u64@HRNG@lwe@@SA_KXZ:
RDRAND RAX
RET
?GenerateSeed_s64@HRNG@lwe@@SA_JXZ:
RDSEED RAX
RET
?Generate_s64@HRNG@lwe@@SA_J_J0@Z:
RDRAND RAX
MOV R8, RDX
SUB R8, RCX
XOR RDX, RDX
DIV R8
MOV RAX, RDX
ADD RAX, RCX
RET
?Generate_s64@HRNG@lwe@@SA_JXZ:
RDRAND RAX
RET
?GenerateSeed_u32@HRNG@lwe@@SAIXZ:
RDSEED EAX
RET
?Generate_u32@HRNG@lwe@@SAIII@Z:
RDRAND EAX
MOV R8D, EDX
SUB R8D, ECX
XOR EDX, EDX
DIV R8D
MOV EAX, EDX
ADD EAX, ECX
RET
?Generate_u32@HRNG@lwe@@SAIXZ:
RDRAND EAX
RET
?GenerateSeed_s32@HRNG@lwe@@SAHXZ:
RDSEED EAX
RET
?Generate_s32@HRNG@lwe@@SAHHH@Z:
RDRAND EAX
MOV R8D, EDX
SUB R8D, ECX
XOR EDX, EDX
DIV R8D
MOV EAX, EDX
ADD EAX, ECX
RET
?Generate_s32@HRNG@lwe@@SAHXZ:
RDRAND EAX
RET
?GenerateSeed_u16@HRNG@lwe@@SAIXZ:
RDSEED AX
RET
?Generate_u16@HRNG@lwe@@SAGGG@Z:
RDRAND AX
MOV R8W, DX
SUB R8W, CX
XOR DX, DX
DIV R8W
MOV AX, DX
ADD AX, CX
RET
?Generate_u16@HRNG@lwe@@SAGXZ:
RDRAND AX
RET
?GenerateSeed_s16@HRNG@lwe@@SAFXZ:
RDSEED AX
RET
?Generate_s16@HRNG@lwe@@SAFFF@Z:
RDRAND AX
MOV R8W, DX
SUB R8W, CX
XOR DX, DX
DIV R8W
MOV AX, DX
ADD AX, CX
RET
?Generate_s16@HRNG@lwe@@SAFXZ:
RDRAND AX
RET
?GenerateSeed_u8@HRNG@lwe@@SAEXZ:
RDSEED AX
RET
?Generate_u8@HRNG@lwe@@SAEEE@Z:
RDRAND AX
MOV R8W, DX
SUB R8W, CX
XOR DX, DX
DIV R8W
MOV AX, DX
ADD AX, CX
RET
?Generate_u8@HRNG@lwe@@SAEXZ:
RDRAND AX
RET
?GenerateSeed_s8@HRNG@lwe@@SACXZ:
RDSEED AX
RET
?Generate_s8@HRNG@lwe@@SACCC@Z:
RDRAND AX
MOV R8W, DX
SUB R8W, CX
XOR DX, DX
DIV R8W
MOV AX, DX
ADD AX, CX
RET
?Generate_s8@HRNG@lwe@@SACXZ:
RDRAND AX
RET

66
src/Link.h Normal file
View File

@ -0,0 +1,66 @@
#pragma once
template<typename T>
class Link
{
public:
T value;
Link<T> *child;
~Link()
{
delete child;
}
Link()
: value(), child(nullptr)
{
}
Link(const T value, Link* child)
: value(value), child(child)
{
}
Link(const T value)
: value(value), child(nullptr)
{
}
Link(const Link& link)
: value(link.value), child(nullptr)
{
}
Link(Link&& link) noexcept
: value(link.value), child(link.child)
{
link.value = 0;
link.child = nullptr;
}
Link& operator=(const Link& link)
{
if (this == &link)
return *this;
value = link.value;
child = nullptr;
return *this;
}
Link& operator=(Link&& link) noexcept
{
if (this == &link)
return *this;
value = link.value;
child = link.child;
link.value = 0;
link.child = nullptr;
return *this;
}
};

236
src/LinkedList.h Normal file
View File

@ -0,0 +1,236 @@
#pragma once
#include "EHS.h"
#include "Link.h"
template<typename T, typename N = USize>
class LinkedList
{
private:
Link<T>* start;
Link<T>* end;
N size;
public:
~LinkedList()
{
delete start;
}
LinkedList()
: size(0), start(nullptr), end(nullptr)
{
}
LinkedList(const LinkedList& list)
: start(nullptr), end(nullptr), size(list.size)
{
const Link<T>* rLast = list.start;
Link<T>* last = new Link<T>(rLast->value);
start = last;
while (rLast->child)
{
last->child = new Link<T>(rLast->child->value);
last = last->child;
rLast = rLast->child;
}
end = last;
}
LinkedList(LinkedList&& list) noexcept
: start(list.start), end(list.end), size(list.size)
{
list.start = nullptr;
list.end = nullptr;
list.size = {};
}
LinkedList& operator=(const LinkedList& list)
{
if (this == &list)
return *this;
const Link<T>* rLast = list.start;
Link<T>* last = new Link<T>(rLast->value);
start = last;
while (rLast->child)
{
last->child = new Link<T>(rLast->child->value);
last = last->child;
rLast = rLast->child;
}
end = last;
size = list.size;
return *this;
}
LinkedList& operator=(LinkedList&& list) noexcept
{
if (this == &list)
return *this;
start = list.start;
end = list.end;
size = list.size;
list.start = nullptr;
list.end = nullptr;
list.size = {};
return *this;
}
const Link<T>* operator[](const N index) const
{
const Link<T>* result = start;
for (N i = 0; i != index; ++i)
result = result->child;
return result;
}
Link<T>* operator[](const N index)
{
Link<T>* result = start;
for (N i = 0; i != index; ++i)
result = result->child;
return result;
}
T& Insert(const N index, const T value)
{
if (index && index == size - 1)
{
end->child = new Link<T>(value);
end = end->child;
++size;
return end->value;
}
else if (index)
{
Link<T>* hierarchy = start;
for (N i = 0; i != index - 1; ++i)
hierarchy = hierarchy->child;
hierarchy->child = new Link<T>(value, hierarchy->child);
++size;
return hierarchy->child->value;
}
else
{
start = new Link<T>(value, start);
++size;
return start->value;
}
}
T Remove(const N index)
{
if (index && index == size - 1)
{
Link<T>* hierarchy = start;
while (hierarchy->child->child)
hierarchy = hierarchy->child;
T result = end->value;
delete end;
end = hierarchy;
--size;
return result;
}
else if (index)
{
Link<T>* hierarchy = start;
for (N i = 0; i != index - 1; ++i)
hierarchy = hierarchy->child;
Link<T>* tmp = hierarchy->child;
T result = tmp->value;
hierarchy->child = hierarchy->child->child;
tmp->child = nullptr;
delete tmp;
return result;
}
else
{
Link<T>* tmp = start;
T result = tmp->value;
start = start->child;
if (--size)
tmp->child = nullptr;
else
end = nullptr;
delete tmp;
return result;
}
}
T& Push(const T value)
{
if (size)
{
end->child = new Link<T>(value);
end = end->child;
++size;
return end->value;
}
else
{
start = new Link<T>(value);
end = start;
size = 1;
return start->value;
}
}
T Pop()
{
if (size == 1)
{
T result = start->value;
delete start;
start = nullptr;
end = nullptr;
size = 0;
return result;
}
if (size > 1)
{
Link<T>* hierarchy = start;
while (hierarchy->child->child)
hierarchy = hierarchy->child;
T result = hierarchy->child->value;
delete hierarchy->child;
hierarchy->child = nullptr;
end = hierarchy;
return result;
}
else
return {};
}
void Clear()
{
delete start;
start = nullptr;
end = nullptr;
size = 0;
}
N Size() const
{
return size;
}
};

214
src/Mat2.h Normal file
View File

@ -0,0 +1,214 @@
#pragma once
#include "EHS.h"
#include "Vec2.h"
template<typename T = float>
class Mat2
{
private:
T data[4];
public:
Mat2()
{
for (UInt_8 i = 0; i < 4; ++i)
data[i] = 0;
}
template<typename C>
Mat2(const Mat2<C>& mat)
{
for (UInt_8 i = 0; i < 4; ++i)
data[i] = mat.data[i];
}
template<typename C>
Mat2<T>& operator=(const Mat2<C>& mat)
{
if (this == &mat)
return *this;
for (UInt_8 i = 0; i < 4; ++i)
data[i] = mat.data[i];
return *this;
}
operator const T*() const
{
return data;
}
operator T*()
{
return data;
}
Vec2<T> operator*(Vec2<T> vec) const
{
Vec2<T> result;
result.x = vec.x * data[0] + vec.y * data[2];
result.y = vec.x * data[1] + vec.y * data[3];
return result;
}
Mat2<T>& operator*=(const T scalar)
{
for (UInt_8 i = 0; i < 4; ++i)
data[i] *= scalar;
return *this;
}
Mat2<T> operator*(const T scalar) const
{
Mat2<T> result;
for (UInt_8 i = 0; i < 4; ++i)
result.data[i] = data[i] * scalar;
return result;
}
Mat2<T>& operator*=(const Mat2<T>& mat)
{
Mat2<T> old = *this;
for (UInt_8 i = 0; i < 4; ++i)
{
UInt_8 row = i / 2;
UInt_8 column = i % 2;
data[i] = 0;
data[i] += old.data[0 * 2 + column] * mat.data[row * 2 + 0];
data[i] += old.data[1 * 2 + column] * mat.data[row * 2 + 1];
}
return *this;
}
Mat2<T> operator*(const Mat2<T>& mat) const
{
Mat2<T> result;
for (UInt_8 i = 0; i < 4; ++i)
{
UInt_8 row = i / 2;
UInt_8 column = i % 2;
result.data[i] += data[0 * 2 + column] * mat.data[row * 2 + 0];
result.data[i] += data[1 * 2 + column] * mat.data[row * 2 + 1];
}
return result;
}
Mat2<T> GetTranspose() const
{
Mat2<T> result;
for (UInt_8 i = 0; i < 4; ++i)
result.data[i] = data[2 * (i % 2) + i / 2];
return result;
}
void Transpose()
{
Mat2<T> old = *this;
for (UInt_8 i = 0; i < 4; ++i)
data[i] = old.data[2 * (i % 2) + i / 2];
}
Mat2<T> GetMinor() const
{
Mat2<T> result(0);
result.data[0] = data[3];
result.data[1] = data[2];
result.data[2] = data[1];
result.data[3] = data[0];
return result;
}
void Minor()
{
Mat2<T> old = *this;
data[0] = old.data[3];
data[1] = old.data[2];
data[2] = old.data[1];
data[3] = old.data[0];
}
T GetDeterminant() const
{
return data[0] * data[3] - data[1] * data[2];
}
Mat2<T> GetCofactor() const
{
Mat2<T> minor = GetMinor();
Mat2<T> result;
for (UInt_8 r = 0; r < 2; ++r)
{
for (UInt_8 c = 0; c < 2; ++c)
{
UInt_8 i = 2 * c + r;
result.data[i] = minor.data[i] * Math::Pow<T>(-1, r + c);
}
}
return result;
}
void Cofactor()
{
Mat2<T> minor = GetMinor();
for (UInt_8 r = 0; r < 2; ++r)
{
for (UInt_8 c = 0; c < 2; ++c)
{
UInt_8 i = 2 * c + r;
data[i] = minor.data[i] * Math::Pow<T>(-1, r + c);
}
}
}
Mat2<T> GetAdjugate() const
{
return GetCofactor().GetTranspose();
}
void Adjugate()
{
Cofactor();
Transpose();
}
Mat2<T> GetInverse() const
{
T det = GetDeterminant();
if (Math::ComCmp(det, 0.0f))
return {};
return GetAdjugate() * (1 / det);
}
void Inverse()
{
T det = GetDeterminant();
if (Math::ComCmp(det, 0.0f))
return;
Adjugate();
operator*=(1 / det);
}
static Mat2<T> Identity()
{
Mat2<T> result;
result[0] = 1;
result[3] = 1;
return result;
}
};
typedef Mat2<float> Mat2_f;
typedef Mat2<double> Mat2_d;

319
src/Mat3.h Normal file
View File

@ -0,0 +1,319 @@
#pragma once
#include "EHS.h"
#include "Vec3.h"
#include "Mat2.h"
template<typename T = float>
class Mat3
{
private:
T data[9];
public:
Mat3()
{
for (UInt_8 i = 0; i < 9; ++i)
data[i] = 0;
}
template<typename C>
Mat3(const Mat2<C>& mat)
{
for (UInt_8 i = 0; i < 4; ++i)
data[i / 2 * 4 + i % 2] = mat.data[i];
}
template<typename C>
Mat3(const Mat3<C>& mat)
{
for (UInt_8 i = 0; i < 9; ++i)
data[i] = mat.data[i];
}
template<typename C>
Mat3<T>& operator=(const Mat3<C>& mat)
{
if (this == &mat)
return *this;
for (UInt_8 i = 0; i < 9; ++i)
data[i] = mat.data[i];
return *this;
}
operator Mat2<T>() const
{
Mat2<T> result;
for (UInt_8 i = 0; i < 4; ++i)
result.data[i] = data[i / 2 * 4 + i % 2];
return result;
}
operator const T*() const
{
return data;
}
operator T*()
{
return data;
}
Vec3<T> operator*(Vec3<T> vec) const
{
Vec3<T> result;
result.x = vec.x * data[0] + vec.y * data[3] + vec.z * data[6];
result.y = vec.x * data[1] + vec.y * data[4] + vec.z * data[7];
result.z = vec.x * data[2] + vec.y * data[5] + vec.z * data[8];
return result;
}
Mat3<T>& operator*=(const T scalar)
{
for (UInt_8 i = 0; i < 9; ++i)
data[i] *= scalar;
return *this;
}
Mat3<T> operator*(const T scalar) const
{
Mat3<T> result;
for (UInt_8 i = 0; i < 9; ++i)
result.data[i] = data[i] * scalar;
return result;
}
Mat3<T>& operator*=(const Mat3<T>& mat)
{
Mat3<T> old = *this;
for (UInt_8 i = 0; i < 9; ++i)
{
UInt_8 row = i / 3;
UInt_8 column = i % 3;
data[i] = 0;
data[i] += old.data[0 * 3 + column] * mat.data[row * 3 + 0];
data[i] += old.data[1 * 3 + column] * mat.data[row * 3 + 1];
data[i] += old.data[2 * 3 + column] * mat.data[row * 3 + 2];
}
return *this;
}
Mat3<T> operator*(const Mat3<T>& mat) const
{
Mat3<T> result;
for (UInt_8 i = 0; i < 9; ++i)
{
UInt_8 row = i / 3;
UInt_8 column = i % 3;
result.data[i] += data[0 * 3 + column] * mat.data[row * 3 + 0];
result.data[i] += data[1 * 3 + column] * mat.data[row * 3 + 1];
result.data[i] += data[2 * 3 + column] * mat.data[row * 3 + 2];
}
return result;
}
Mat3<T> GetTranspose() const
{
Mat3<T> result;
for (UInt_8 i = 0; i < 9; ++i)
result.data[i] = data[3 * (i % 3) + i / 3];
return result;
}
void Transpose()
{
Mat3<T> old = *this;
for (UInt_8 i = 0; i < 9; ++i)
data[i] = old.data[3 * (i % 3) + i / 3];
}
Mat3<T> GetMinor() const
{
Mat3<T> result;
for (UInt_8 r = 0; r < 3; ++r)
for (UInt_8 c = 0; c < 3; ++c)
result[3 * r + c] = Cut(r, c).GetDeterminant();
return result;
}
void Minor()
{
Mat3<T> old = *this;
for (UInt_8 r = 0; r < 3; ++r)
for (UInt_8 c = 0; c < 3; ++c)
data[3 * r + c] = old.Cut(r, c).GetDeterminant();
}
Mat2<T> Cut(const UInt_8 row, const UInt_8 column) const
{
Mat2<T> result;
UInt_8 index = 0;
for (UInt_8 r = 0; r < 3; ++r)
{
for (UInt_8 c = 0; c < 3; ++c)
{
if (r == row || c == column)
continue;
result[index++] = data[3 * r + c];
}
}
return result;
}
T GetDeterminant() const
{
Mat3<T> cofactor = GetCofactor();
T result = 0;
for (UInt_8 c = 0; c < 3; ++c)
result += data[c] * cofactor[c];
return result;
}
Mat3<T> GetCofactor() const
{
Mat3<T> minor = GetMinor();
Mat3<T> result;
for (UInt_8 r = 0; r < 3; ++r)
{
for (UInt_8 c = 0; c < 3; ++c)
{
UInt_8 i = 3 * c + r;
result.data[i] = minor.data[i] * Math::Pow<T>(-1, r + c);
}
}
return result;
}
void Cofactor()
{
Mat3<T> minor = GetMinor();
for (UInt_8 r = 0; r < 3; ++r)
{
for (UInt_8 c = 0; c < 3; ++c)
{
UInt_8 i = 3 * c + r;
data[i] = minor.data[i] * Math::Pow<T>(-1, r + c);
}
}
}
Mat3<T> GetAdjugate() const
{
return GetCofactor().GetTranspose();
}
void Adjugate()
{
Cofactor();
Transpose();
}
Mat3<T> GetInverse() const
{
T det = GetDeterminant();
if (Math::ComCmp(det, 0.0f))
return {};
return GetAdjugate() * (1 / det);
}
void Inverse()
{
T det = GetDeterminant();
if (Math::ComCmp(det, 0.0f))
return;
Adjugate();
operator*=(1 / det);
}
static Mat3<T> Identity()
{
Mat3<T> result;
result.data[0] = 1;
result.data[4] = 1;
result.data[8] = 1;
return result;
}
static Mat3<T> Scale(const Vec3<T>& scale)
{
Mat3<T> result;
result.data[0] = scale.x;
result.data[4] = scale.y;
result.data[8] = scale.z;
return result;
}
static Mat3<T> PitchRotate(const T angle)
{
T radians = Math::Rads(angle);
Mat3<T> result;
result.data[0] = 1;
result.data[4] = Math::Cos(radians);
result.data[5] = Math::Sin(radians);
result.data[7] = -Math::Sin(radians);
result.data[8] = Math::Cos(radians);
return result;
}
static Mat3<T> YawRotate(const T angle)
{
T radians = Math::Rads(angle);
Mat3<T> result;
result.data[0] = Math::Cos(radians);
result.data[2] = -Math::Sin(radians);
result.data[4] = 1;
result.data[6] = Math::Sin(radians);
result.data[8] = Math::Cos(radians);
return result;
}
static Mat3<T> RollRotate(const T angle)
{
T radians = Math::Rads(angle);
Mat3<T> result;
result.data[0] = Math::Cos(radians);
result.data[1] = Math::Sin(radians);
result.data[3] = -Math::Sin(radians);
result.data[4] = Math::Cos(radians);
result.data[8] = 1;
return result;
}
static Mat3<T> Rotate(const Vec3<T>& vec)
{
return YawRotate(vec.y) * RollRotate(vec.z) * PitchRotate(vec.x);
}
};
typedef Mat3<float> Mat3_f;
typedef Mat3<double> Mat3_d;

420
src/Mat4.h Normal file
View File

@ -0,0 +1,420 @@
#pragma once
#include "EHS.h"
#include "Math.h"
#include "Mat3.h"
#include "Vec4.h"
#include "Vec3.h"
template <typename T = float>
class Mat4
{
private:
friend class Uniform;
T data[16];
public:
Mat4()
{
for (UInt_8 i = 0; i < 16; ++i)
data[i] = 0;
}
explicit Mat4(const T* data)
{
for (UInt_8 i = 0; i < 16; ++i)
this->data[i] = data[i];
}
template<typename C>
Mat4(const Mat3<C>& mat)
{
for (UInt_8 i = 0; i < 9; ++i)
{
UInt_8 row = i / 3;
UInt_8 column = i % 3;
UInt_8 dst = row * 4 + column;
data[dst] = (T)mat[i];
}
data[3] = 0;
data[7] = 0;
data[11] = 0;
data[12] = 0;
data[13] = 0;
data[14] = 0;
data[15] = 1;
}
template<typename C>
Mat4(const Mat4<C>& mat)
{
for (UInt_8 i = 0; i < 16; ++i)
data[i] = (T)mat.data[i];
}
template<typename C>
Mat4<T>& operator=(const Mat4<C>& mat)
{
if (this == &mat)
return *this;
for (UInt_8 i = 0; i < 16; ++i)
data[i] = (T)mat.data[i];
return *this;
}
Vec4<T> operator*(Vec4<T> vec) const
{
Vec4<T> result;
result.x = vec.x * data[0] + vec.y * data[4] + vec.z * data[8] + vec.w * data[12];
result.y = vec.x * data[1] + vec.y * data[5] + vec.z * data[9] + vec.w * data[13];
result.z = vec.x * data[2] + vec.y * data[6] + vec.z * data[10] + vec.w * data[14];
result.w = vec.x * data[3] + vec.y * data[7] + vec.z * data[11] + vec.w * data[15];
return result;
}
Mat4<T>& operator*=(const T scalar)
{
for (UInt_8 i = 0; i < 16; ++i)
data[i] *= scalar;
return *this;
}
Mat4<T> operator*(const T scalar) const
{
Mat4<T> result;
for (UInt_8 i = 0; i < 16; ++i)
result.data[i] = data[i] * scalar;
return result;
}
Mat4<T>& operator*=(const Mat4<T>& mat)
{
Mat4<T> old = *this;
for (UInt_8 i = 0; i < 16; ++i)
{
UInt_8 row = i / 4;
UInt_8 column = i % 4;
data[i] += old.data[0 * 4 + column] * mat.data[row * 4 + 0];
data[i] += old.data[1 * 4 + column] * mat.data[row * 4 + 1];
data[i] += old.data[2 * 4 + column] * mat.data[row * 4 + 2];
data[i] += old.data[3 * 4 + column] * mat.data[row * 4 + 3];
}
return *this;
}
Mat4<T> operator*(const Mat4<T>& mat) const
{
Mat4<T> result;
for (UInt_8 i = 0; i < 16; ++i)
{
UInt_8 row = i / 4;
UInt_8 column = i % 4;
result.data[i] += data[0 * 4 + column] * mat.data[row * 4 + 0];
result.data[i] += data[1 * 4 + column] * mat.data[row * 4 + 1];
result.data[i] += data[2 * 4 + column] * mat.data[row * 4 + 2];
result.data[i] += data[3 * 4 + column] * mat.data[row * 4 + 3];
}
return result;
}
operator const T*() const
{
return data;
}
operator T*()
{
return data;
}
Vec3<T> GetRight() const
{
return Vec3<T>(data[0], data[4], data[8]);
}
Vec3<T> GetUp() const
{
return Vec3<T>(data[1], data[5], data[9]);
}
Vec3<T> GetForward() const
{
return Vec3<T>(data[2], data[6], data[10]);
}
Mat4<T> GetTranspose() const
{
Mat4<T> result;
for (UInt_8 i = 0; i < 16; ++i)
result.data[i] = data[4 * (i % 4) + i / 4];
return result;
}
void Transpose()
{
Mat4<T> old = *this;
for (UInt_8 i = 0; i < 16; ++i)
data[i] = old.data[4 * (i % 4) + i / 4];
}
Mat3<T> Cut(const UInt_8 row, const UInt_8 column) const
{
Mat3<T> result;
UInt_8 index = 0;
for (UInt_8 r = 0; r < 4; ++r)
{
for (UInt_8 c = 0; c < 4; ++c)
{
if (r == row || c == column)
continue;
result[index++] = data[4 * r + c];
}
}
return result;
}
Mat4<T> GetMinor() const
{
Mat4<T> result;
for (UInt_8 r = 0; r < 4; ++r)
for (UInt_8 c = 0; c < 4; ++c)
result.data[4 * r + c] = Cut(r, c).GetDeterminant();
return result;
}
void Minor()
{
Mat4<T> old = *this;
for (UInt_8 r = 0; r < 4; ++r)
for (UInt_8 c = 0; c < 4; ++c)
data[4 * r + c] = old.Cut(r, c).GetDeterminant();
}
Mat4<T> GetCofactor() const
{
Mat4<T> minor = GetMinor();
Mat4<T> result;
for (UInt_8 r = 0; r < 4; ++r)
{
for (UInt_8 c = 0; c < 4; ++c)
{
UInt_8 i = 4 * c + r;
result.data[i] = minor.data[i] * Math::Pow<T>(-1, r + c);
}
}
return result;
}
void Cofactor()
{
Mat4<T> minor = GetMinor();
for (UInt_8 r = 0; r < 4; ++r)
{
for (UInt_8 c = 0; c < 4; ++c)
{
UInt_8 i = 4 * c + r;
data[i] = minor.data[i] * Math::Pow<T>(-1, r + c);
}
}
}
T GetDeterminant() const
{
Mat4<T> cofactor = GetCofactor();
T result = 0;
for (UInt_8 c = 0; c < 4; ++c)
result += data[c] * cofactor[c];
return result;
}
Mat4<T> GetAdjugate() const
{
return GetCofactor().GetTranspose();
}
void Adjugate()
{
Cofactor();
Transpose();
}
Mat4<T> GetInverse() const
{
T det = GetDeterminant();
if (Math::ComCmp(det, 0.0f))
return {};
return GetAdjugate() * (1 / det);
}
void Inverse()
{
T det = GetDeterminant();
if (Math::ComCmp(det, 0.0f))
return;
Adjugate();
operator*=(1 / det);
}
static Mat4<T> Identity()
{
Mat4<T> result;
result.data[0] = 1;
result.data[5] = 1;
result.data[10] = 1;
result.data[15] = 1;
return result;
}
static Mat4<T> Scale(const Vec3<T>& scale)
{
Mat4<T> result;
result.data[0] = scale.x;
result.data[5] = scale.y;
result.data[10] = scale.z;
result.data[15] = 1;
return result;
}
static Mat4<T> Translate(const Vec3<T>& pos)
{
Mat4<T> result = Identity();
result.data[12] = pos.x;
result.data[13] = pos.y;
result.data[14] = pos.z;
return result;
}
static Mat4<T> PitchRotate(const T angle)
{
T radians = Math::Rads(angle);
Mat4<T> result;
result.data[0] = 1;
result.data[5] = Math::Cos(radians);
result.data[6] = Math::Sin(radians);
result.data[9] = -Math::Sin(radians);
result.data[10] = Math::Cos(radians);
result.data[15] = 1;
return result;
}
static Mat4<T> YawRotate(const T angle)
{
T radians = Math::Rads(angle);
Mat4<T> result;
result.data[0] = Math::Cos(radians);
result.data[2] = -Math::Sin(radians);
result.data[5] = 1;
result.data[8] = Math::Sin(radians);
result.data[10] = Math::Cos(radians);
result.data[15] = 1;
return result;
}
static Mat4<T> RollRotate(const T angle)
{
T radians = Math::Rads(angle);
Mat4<T> result;
result.data[0] = Math::Cos(radians);
result.data[1] = Math::Sin(radians);
result.data[4] = -Math::Sin(radians);
result.data[5] = Math::Cos(radians);
result.data[10] = 1;
result.data[15] = 1;
return result;
}
static Mat4<T> Rotate(const Vec3<T>& vec)
{
return YawRotate(vec.y) * RollRotate(vec.z) * PitchRotate(vec.x);
}
static Mat4<T> RH_Perspective(const T fov, const T aspect, const T zNear, const T zFar)
{
const float tanHalfFovy = tan(Math::Rads(fov) / 2.0f);
Mat4<T> result;
result[0] = 1.0f / (aspect * tanHalfFovy);
result[5] = -1.0f / tanHalfFovy;
result[10] = zFar / (zFar - zNear);
result[14] = -(zFar * zNear) / (zFar - zNear);
return result;
}
static Mat4<T> LH_Perspective(const T fov, const T aspect, const T zNear, const T zFar)
{
const float tanHalfFovy = Math::Tan(Math::Rads(fov) / 2.0f);
Mat4<T> result;
result[0] = 1.0f / (aspect * tanHalfFovy);
result[5] = -1.0f / tanHalfFovy;
result[10] = zFar / (zFar - zNear);
result[11] = 1.0f;
result[14] = -(zFar * zNear) / (zFar - zNear);
result[15] = 0.0f;
return result;
}
static Mat4<T> LH_Orthographic(const T left, const T right, const T top, const T bottom, const T zNear, const T zFar)
{
Mat4<T> result;
result[0] = 2.0f / (right - left); // 0,0 entry
result[5] = 2.0f / (bottom - top); // 1,1 entry
result[10] = 1.0f / (zFar - zNear); // 2,2 entry
result[12] = -(right + left) / (right - left); // 3,0 entry
result[13] = -(bottom + top) / (bottom - top); // 3,1 entry
result[14] = -zNear / (zFar - zNear); // 3,2 entry
result[15] = 1.0f; // 3,3 entry
return result;
/*
Mat4<T> result;
result.data[0] = 2 / (right - left);
result.data[5] = 2 / (top - bottom);
result.data[10] = 1 / (zFar - zNear);
result.data[12] = (left + right) / (left - right);
result.data[13] = (top + bottom) / (bottom - top);
result.data[14] = zNear / (zNear - zFar);
result.data[15] = 1;
return result;
*/
}
};
typedef Mat4<float> Mat4_f;
typedef Mat4<double> Mat4_d;

87
src/Math.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "Math.h"
bool Math::AbsCmp(const float a, const float b)
{
return Abs(a - b) <= fltEpsilon;
}
bool Math::AbsCmp(const double a, const double b)
{
return Abs(a - b) <= fltEpsilon;
}
bool Math::RelCmp(const float a, const float b)
{
return Abs(a - b) <= fltEpsilon * Max(Abs(a), Abs(b));
}
bool Math::RelCmp(const double a, const double b)
{
return Abs(a - b) <= fltEpsilon * Max(Abs(a), Abs(b));
}
bool Math::ComCmp(const float a, const float b)
{
return Abs(a - b) <= fltEpsilon * Max(1.0f, Max(Abs(a), Abs(b)));
}
bool Math::ComCmp(const double a, const double b)
{
return Abs(a - b) <= dblEpsilon * Max(1.0, Max(Abs(a), Abs(b)));
}
double Math::Sqrt(const double from)
{
#if defined(ARCH_X64)
if (CPU::HasAVX())
return Sqrt_AVX(from);
else if (CPU::HasSSE())
return Sqrt_SSE2(from);
double temp = 0.0;
double result = from / 2.0;
while (result != temp)
{
temp = result;
result = (from / temp + temp) / 2.0;
}
return result;
#elif defined(ARCH_ARM64)
return Sqrt_VFP4(from);
#endif
}
float Math::Sqrt(const float from)
{
#if defined(ARCH_X64)
if (CPU::HasAVX())
return Sqrt_AVX(from);
else if (CPU::HasSSE())
return Sqrt_SSE(from);
float temp = 0.0f;
float result = from / 2.0f;
while (result != temp)
{
temp = result;
result = (from / temp + temp) / 2.0f;
}
return result;
#elif defined(ARCH_ARM64)
return Sqrt_VFP4(from);
#endif
}
float Math::Mod(const float from, const float divisor)
{
return from - Trunc(from / divisor) * divisor;
}
double Math::Mod(const double from, const double divisor)
{
return from - Trunc(from / divisor) * divisor;
}

313
src/Math.h Normal file
View File

@ -0,0 +1,313 @@
#pragma once
#include "sys/cpu.h"
#define LOW_WORD(x) *((int*)&x) + 1
class Math
{
private:
static float Sqrt_AVX(const float from);
static double Sqrt_AVX(const double from);
static float Sqrt_SSE(const float from);
static double Sqrt_SSE2(const double from);
static float Sqrt_VFP4(const float from);
static double Sqrt_VFP4(const double from);
public:
constexpr static float fltEpsilon = 1e-7f;
constexpr static double dblEpsilon = 1e-16;
/// Absolute tolerance comparison for single precision floats.
static bool AbsCmp(const float a, const float b);
/// Absolute tolerance comparison for double precision floats.
static bool AbsCmp(const double a, const double b);
/// Relative tolerance comparison for single precision floats.
static bool RelCmp(const float a, const float b);
/// Relative tolerance comparison for double precision floats.
static bool RelCmp(const double a, const double b);
/// Combined absolute and relative tolerance comparison for single precision floats.
static bool ComCmp(const float a, const float b);
/// Combined absolute and relative tolerance comparison for double precision floats.
static bool ComCmp(const double a, const double b);
template<typename T = float>
static T Max(const T a, const T b)
{
return a > b ? a : b;
}
template<typename T = float>
static T Min(const T a, const T b)
{
return a < b ? a : b;
}
template<typename T = float>
static T Clamp(const T value, const T min, const T max)
{
if (value < min)
return min;
else if (value > max)
return max;
return value;
}
template<typename T = float>
static T Abs(const T from)
{
return from < 0 ? -from : from;
}
/// Retrieves a very accurate version of Pi as a long double and converts it.
/// @tparam T The data type to return Pi as.
/// @returns The result.
template<typename T = float>
static constexpr T Pi()
{
return (T)3.141592653589793238462643383279502884L;
}
/// Converts degrees into radians.
/// @tparam T The data type to return;
/// @param [in] from The value to convert to radians.
/// @returns The value in radians.
template<typename T = float>
static T Rads(const T from)
{
return from * 0.01745329251994329576923690768489;
}
/// Converts radians into degrees.
/// @tparam T The data type to return;
/// @param [in] from The value to convert to degrees.
/// @returns The value in degrees.
template<typename T = float>
static T Degr(const T from)
{
return from * 57.295779513082320876798154814105;
}
/// A method for use of exponents.
/// @tparam T The data type to return;
/// @tparam I The data type to use as the exponent.
/// @param [in] from The value to use the exponent on.
/// @param [in] of The exponent.
/// @returns The result.
template<typename T = float, typename I = UInt_64>
static T Pow(const T from, const I of)
{
if (of < 0)
{
if (from == 0)
return -0;
return 1 / (from * Pow<T>(from, (-of) - 1));
}
if (of == 0)
return 1;
else if (of == 1)
return from;
return from * Pow<T>(from, of - 1);
}
static float Near(const float from);
static double Near(const double from);
static float Floor(const float from);
static double Floor(const double from);
static float Ceil(const float from);
static double Ceil(const double from);
static float Trunc(const float from);
static double Trunc(const double from);
static float Mod(const float from, const float divisor);
static double Mod(const double from, const double divisor);
/// A method for retrieving the square root of a value.
/// @tparam T The data type to use.
/// @param [in] from The value to retrieve to square root of.
/// @returns The result.
template<typename T = float>
static T Sqrt(const T from)
{
T temp = 0;
T result = from / 2;
while (result != temp)
{
temp = result;
result = (from / temp + temp) / 2;
}
return result;
}
static double Sqrt(const double from);
static float Sqrt(const float from);
template<typename R = float>
static R Sin(const R angle, const R precision = 0.001)
{
R sum = angle;
R term = angle;
for (UInt_64 i = 1; Abs<R>(term) >= precision; ++i)
{
term *= -angle * angle / (R)((2 * i + 1) * (2 * i));
sum += term;
}
return sum;
/*
R sum = 0;
for (USize n = 0; n < precision; ++n)
sum += Pow<R>(-1, n) / (R)Fact<T>(2 * n + 1) * Pow<R>(angle, 2 * n + 1);
return sum;
*/
}
template<typename R = float, typename T = UInt_64>
static R ASin(const R yPos, const T precision = 10)
{
R sum = 0;
for (T n = 0; n < precision; ++n)
sum += (R)Fact<T>(2 * n) / (Pow<R>(4, n) * Pow<R>((R)Fact<T>(n), 2) * (2 * n + 1)) * Pow<R>(yPos, 2 * n + 1);
return sum;
}
/// A trigonometry Cosine function for finding the X-Axis position from the Z-Axis angle.
/// @tparam R Input and result data type.
/// @tparam T Precision data type.
/// @param[in] angle The angle in radians from the Z-Axis.
/// @param [in] precision Sigma max.
/// @returns The X-Axis position.
template<typename R = float>
static R Cos(const R angle, const R precision = 0.001)
{
R sum = 1.0;
R term = 1.0;
for (UInt_64 i = 2; Abs<R>(term) >= precision; i += 2)
{
term *= -angle * angle / (R)(i * (i - 1));
sum += term;
}
return sum;
/*
R sum = 0;
for (T n = 0; n < precision; ++n)
sum += Pow<R>(-1, n) / (R)Fact<T>(2 * n) * Pow<R>(angle, 2 * n);
return sum;
*/
}
/// A trigonometry Arc Cosine function for finding the Z-Axis angle form the X-Axis position.
/// @tparam R Input and result data type.
/// @tparam T Precision data type.
/// @param [in] xPos The position from the X-Axis.
/// @param [in] precision Sigma max.
/// @returns The Z-Axis angle.
template<typename R = float, typename T = UInt_64>
static R ACos(const R xPos, const T precision = 10)
{
return Pi<R>() / 2 - ASin<R, T>(xPos, precision);
}
template<typename R = float>
static R Tan(const R angle, const R precision = 0.001)
{
/*
R sum = 0;
for (T n = 1; n < precision + 1; ++n)
sum += B<R>(2 * n) * Pow<R>(-4, n) * (1 - Pow<R>(4, n)) / (R)Fact<T>(2 * n) * Pow<R>(angle, 2 * n - 1);
return sum;
*/
return Sin<R>(angle) / Cos<R>(angle);
}
template<typename R = float, typename T = UInt_64>
static R ATan(const R x, const T precision = 1)
{
R sum = 0;
for (T n = 0; n < precision; ++n)
sum += Pow<R>(-1, n) / (2 * n + 1) * Pow<R>(x, 2 * n + 1);
return sum;
}
template<typename R = float>
static R Cot(const R x, const R precision = 0.001)
{
return 1 / Tan<R>(x, precision);
}
template<typename T = UInt_64>
static T Fact(const T n)
{
if (n <= 1)
return 1;
return n * Fact<T>(n - 1);
}
template<typename R = float, typename T = UInt_64>
static R Combination(const T n, const T k)
{
if (k <= n)
return (R)Fact<T>(n) / (R)(Fact<T>(n - k) * Fact<T>(k));
return 0;
}
template<typename R = float, typename T = UInt_64>
static R B(const T n)
{
R innerSum = 0;
R outerSum = 0;
for (T k = 0; k <= n; ++k)
{
for (T r = 0; r <= k; ++r)
innerSum += Pow<R, T>(-1, r) * Combination<R, T>(k, r) * Pow<R, T>(r, n);
outerSum += 1 / ((R)k + 1) * innerSum;
innerSum = 0;
}
return outerSum;
}
};

61
src/Math_GCC_AMD64.s Normal file
View File

@ -0,0 +1,61 @@
global _ZN3lwe4Math8Sqrt_AVXEf
global _ZN3lwe4Math8Sqrt_AVXEd
global _ZN3lwe4Math8Sqrt_SSEEf
global _ZN3lwe4Math9Sqrt_SSE2Ed
global _ZN3lwe4Math4NearEf
global _ZN3lwe4Math4NearEd
global _ZN3lwe4Math5FloorEf
global _ZN3lwe4Math5FloorEd
global _ZN3lwe4Math4CeilEf
global _ZN3lwe4Math4CeilEd
global _ZN3lwe4Math5TruncEf
global _ZN3lwe4Math5TruncEd
section .text
_ZN3lwe4Math8Sqrt_AVXEf:
VSQRTPS XMM0, XMM0
RET
_ZN3lwe4Math8Sqrt_AVXEd:
VSQRTPD XMM0, XMM0
RET
_ZN3lwe4Math8Sqrt_SSEEf:
SQRTPS XMM0, XMM0
RET
_ZN3lwe4Math9Sqrt_SSE2Ed:
SQRTPD XMM0, XMM0
RET
_ZN3lwe4Math4NearEf:
ROUNDPS XMM0, XMM0, 0
RET
_ZN3lwe4Math4NearEd:
ROUNDPD XMM0, XMM0, 0
RET
_ZN3lwe4Math5FloorEf:
ROUNDPS XMM0, XMM0, 1
RET
_ZN3lwe4Math5FloorEd:
ROUNDPD XMM0, XMM0, 1
RET
_ZN3lwe4Math4CeilEf:
ROUNDPS XMM0, XMM0, 2
RET
_ZN3lwe4Math4CeilEd:
ROUNDPD XMM0, XMM0, 2
RET
_ZN3lwe4Math5TruncEf:
ROUNDPS XMM0, XMM0, 3
RET
_ZN3lwe4Math5TruncEd:
ROUNDPD XMM0, XMM0, 3
RET

61
src/Math_MSVC_AMD64.s Normal file
View File

@ -0,0 +1,61 @@
global ?Sqrt_AVX@Math@lwe@@CAMM@Z
global ?Sqrt_AVX@Math@lwe@@CANN@Z
global ?Sqrt_SSE@Math@lwe@@CAMM@Z
global ?Sqrt_SSE2@Math@lwe@@CANN@Z
global ?Near@Math@lwe@@SAMM@Z
global ?Near@Math@lwe@@SANN@Z
global ?Floor@Math@lwe@@SAMM@Z
global ?Floor@Math@lwe@@SANN@Z
global ?Ceil@Math@lwe@@SAMM@Z
global ?Ceil@Math@lwe@@SANN@Z
global ?Trunc@Math@lwe@@SAMM@Z
global ?Trunc@Math@lwe@@SANN@Z
section .text
?Sqrt_AVX@Math@lwe@@CAMM@Z:
VSQRTPS XMM0, XMM0
RET
?Sqrt_AVX@Math@lwe@@CANN@Z:
VSQRTPD XMM0, XMM0
RET
?Sqrt_SSE@Math@lwe@@CAMM@Z:
SQRTPS XMM0, XMM0
RET
?Sqrt_SSE2@Math@lwe@@CANN@Z:
SQRTPD XMM0, XMM0
RET
?Near@Math@lwe@@SAMM@Z:
ROUNDPS XMM0, XMM0, 0
RET
?Near@Math@lwe@@SANN@Z:
ROUNDPD XMM0, XMM0, 0
RET
?Floor@Math@lwe@@SAMM@Z:
ROUNDPS XMM0, XMM0, 1
RET
?Floor@Math@lwe@@SANN@Z:
ROUNDPD XMM0, XMM0, 1
RET
?Ceil@Math@lwe@@SAMM@Z:
ROUNDPS XMM0, XMM0, 2
RET
?Ceil@Math@lwe@@SANN@Z:
ROUNDPD XMM0, XMM0, 2
RET
?Trunc@Math@lwe@@SAMM@Z:
ROUNDPS XMM0, XMM0, 3
RET
?Trunc@Math@lwe@@SANN@Z:
ROUNDPD XMM0, XMM0, 3
RET

55
src/PRNG.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include "EHS.h"
template<typename T>
class PRNG
{
private:
T seed;
T last;
public:
PRNG()
: seed(0), last(0)
{
}
PRNG(const T seed)
: seed(seed), last(seed)
{
}
PRNG(const PRNG& prng)
: seed(prng.seed), last(prng.last)
{
}
PRNG& operator=(const PRNG& prng)
{
if (this == &prng)
return *this;
seed = prng.seec;
last = prng.last;
}
T Generate(const T min, const T max)
{
return Generate() % (max - min) + min;
}
T Generate()
{
return ((last = last * 214013 + 2531011) >> 16) & 0x7fff;
}
};
typedef PRNG<SInt_64> PRNG_s64;
typedef PRNG<UInt_64> PRNG_u64;
typedef PRNG<SInt_32> PRNG_s32;
typedef PRNG<UInt_32> PRNG_u32;
typedef PRNG<SInt_16> PRNG_s16;
typedef PRNG<UInt_16> PRNG_u16;
typedef PRNG<SInt_8> PRNG_s8;
typedef PRNG<UInt_8> PRNG_u8;

393
src/Quat.h Normal file
View File

@ -0,0 +1,393 @@
#pragma once
#include "EHS.h"
#include "Math.h"
#include "Mat4.h"
#include "Vec3.h"
template<typename T>
class Quat
{
public:
T w;
T x;
T y;
T z;
Quat()
: w(0), x(0), y(0), z(0)
{
}
Quat(const T w, const T x, const T y, const T z)
: w(w), x(x), y(y), z(z)
{
}
Quat(const T yaw, const T pitch, const T roll)
: w(0), x(0), y(0), z(0)
{
T c1 = cos(yaw / 2);
T c2 = cos(pitch / 2);
T c3 = cos(roll / 2);
T s1 = sin(yaw / 2);
T s2 = sin(pitch / 2);
T s3 = sin(roll / 2);
w = c1 * c2 * c3 - s1 * s2 * s3;
x = s1 * s2 * c3 + c1 * c2 * s3;
y = s1 * c2 * c3 + c1 * s2 * s3;
z = c1 * s2 * c3 - s1 * c2 * s3;
}
explicit Quat(const Vec3<T>& euler)
: w(0), x(0), y(0), z(0)
{
T c1 = cos(euler.x / 2);
T c2 = cos(euler.y / 2);
T c3 = cos(euler.z / 2);
T s1 = sin(euler.x / 2);
T s2 = sin(euler.y / 2);
T s3 = sin(euler.z / 2);
w = c1 * c2 * c3 - s1 * s2 * s3;
x = s1 * s2 * c3 + c1 * c2 * s3;
y = s1 * c2 * c3 + c1 * s2 * s3;
z = c1 * s2 * c3 - s1 * c2 * s3;
}
Quat(const Vec3<T>& n, const T a)
: w(cosf(a / 2)), x(n.x * sinf(a / 2)), y(n.y * sinf(a / 2)), z(n.z * sinf(a / 2))
{
}
explicit Quat(const Mat4<T>& rotMatrix)
: w(0), x(0), y(0), z(0)
{
ToQuaternion(rotMatrix);
}
Quat(const Quat& quat)
: w(quat.w), x(quat.x), y(quat.y), z(quat.z)
{
}
explicit Quat(const T scalar)
: w(scalar), x(scalar), y(scalar), z(scalar)
{
}
Quat& operator=(const Quat& quat)
{
if (this == &quat)
return *this;
w = quat.w;
x = quat.x;
y = quat.y;
z = quat.z;
return *this;
}
Quat& operator=(const Mat4<T>& rotMatrix)
{
ToQuaternion(rotMatrix);
return *this;
}
Quat operator+(const Quat& other) const
{
return {w + other.w, x + other.x, y + other.y, z + other.z};
}
Quat operator-() const
{
return {-w, -x, -y, -z};
}
Quat operator-(const Quat& other) const
{
return {w - other.w, x - other.x, y - other.y, z - other.z};
}
Quat operator*(const T scalar)
{
return {w * scalar, x * scalar, x * scalar, x * scalar};
}
Quat operator*(const Quat& other)
{
return Quat
(
w * other.w - x * other.x - y * other.y - z * other.z,
w * other.x + x * other.w + y * other.z - z * other.y,
w * other.y - x * other.z + y * other.w + z * other.x,
w * other.z + x * other.y - y * other.x + z * other.w
);
}
Vec3<T> operator*(const Vec3<T>& vect)
{
Quat tmp(0, vect[0], vect[1], vect[2]);
Vec3<T> tmpVect(x, y, z);
Vec3<T> vcV = tmpVect.CrossProduct(vect);
return vect + vcV * (2 * w) + tmpVect.CrossProduct(vcV) * 2;
}
Quat operator^(const T t)
{
Vec3<T> n;
T a;
ToAxisAngle(&n, &a);
float at = a * t;
return Quat<T>(n, at);
}
bool operator==(const Quat& quat) const
{
return w == quat.w && x == quat.x && y == quat.y && z == quat.z;
}
bool operator!=(const Quat& quat) const
{
return w != quat.w || x != quat.x || y != quat.y || z == quat.z;
}
T operator[](const UInt_64 index) const
{
switch (index)
{
case 0:
return w;
case 1:
return x;
case 2:
return y;
case 3:
return z;
default:
return w;
}
}
T& operator[](const UInt_64 index)
{
switch (index)
{
case 0:
return w;
case 1:
return x;
case 2:
return y;
case 3:
return z;
default:
return w;
}
}
void ToAxisAngle(Vec3<T>* vectAxis, T* flAngle)
{
Vec3<T> tmp(x, y, z);
if (tmp.GetDis2() < 0.0001f)
*vectAxis = Vec3<T>(1, 0, 0);
else
*vectAxis = tmp.GetNorm();
*flAngle = acosf(w) * 2;
*flAngle = Math::Degr<T>(*flAngle);
}
void ToQuaternion(const Mat4<T>& rotMatrix)
{
T trace = rotMatrix[0][0] + rotMatrix[1][1] + rotMatrix[2][2];
if (trace > 0)
{
T s = 0.5f / Math::Sqrt<T>(trace + 1.0f);
w = 0.25f / s;
x = (rotMatrix[2][1] - rotMatrix[1][2]) * s;
y = (rotMatrix[0][2] - rotMatrix[2][0]) * s;
z = (rotMatrix[1][0] - rotMatrix[0][1]) * s;
} else
{
if ((rotMatrix[0][0] > rotMatrix[1][1]) && (rotMatrix[0][0] > rotMatrix[2][2]))
{
T s = 2.0f * Math::Sqrt(1.0f + rotMatrix[0][0] - rotMatrix[1][1] - rotMatrix[2][2]);
w = (rotMatrix[2][1] - rotMatrix[1][2]) / s;
x = 0.25f * s;
y = (rotMatrix[0][1] + rotMatrix[1][0]) / s;
z = (rotMatrix[0][2] + rotMatrix[2][0]) / s;
} else if (rotMatrix[1][1] > rotMatrix[2][2])
{
T s = 2.0f * sqrtf(1.0f + rotMatrix[1][1] - rotMatrix[0][0] - rotMatrix[2][2]);
w = (rotMatrix[0][2] - rotMatrix[2][0]) / s;
x = (rotMatrix[0][1] + rotMatrix[1][0]) / s;
y = 0.25f * s;
z = (rotMatrix[1][2] + rotMatrix[2][1]) / s;
} else
{
T s = 2.0f * sqrtf(1.0f + rotMatrix[2][2] - rotMatrix[0][0] - rotMatrix[1][1]);
w = (rotMatrix[1][0] - rotMatrix[0][1]) / s;
x = (rotMatrix[0][2] + rotMatrix[2][0]) / s;
y = (rotMatrix[1][2] + rotMatrix[2][1]) / s;
z = 0.25f * s;
}
}
}
/*
Vec3<T> ToEulerAngle() const
{
Vec3<T> euler;
float ysqr = y * y;
float t0 = 2 * (w * x + y * z);
float t1 = 1 - 2 * (x * x + ysqr);
euler.z = std::atan2(t0, t1);
float t2 = 2 * (w * y - z * x);
t2 = t2 > 1 ? 1 : t2;
t2 = t2 < -1 ? -1 : t2;
euler.y = std::asin(t2);
float t3 = 2 * (w * z + x * y);
float t4 = 1 - 2 * (ysqr + z * z);
euler.x = std::atan2(t3, t4);
return euler;
}
*/
Mat4<T> ToMatrix() const
{
Mat4<T> result;
T x2 = x + x;
T y2 = y + y;
T z2 = z + z;
T x2w = x2 * w;
T y2w = y2 * w;
T z2w = z2 * w;
T x2x = x2 * x;
T y2x = y2 * x;
T z2x = z2 * x;
T y2y = y2 * y;
T z2y = z2 * y;
T z2z = z2 * y;
result[0] = T(1) - (y2y + z2z);
result[1] = y2x - z2w;
result[2] = z2x + y2w;
result[3] = T(0);
result[4] = y2x + z2w;
result[5] = T(1) - (x2x + z2z);
result[6] = z2y - x2w;
result[7] = T(0);
result[8] = z2x - y2w;
result[9] = z2y + x2w;
result[10] = T(1) - (x2x + y2y);
result[11] = T(0);
result[12] = T(0);
result[13] = T(0);
result[14] = T(0);
result[15] = T(1);
return result;
}
float GetMagnitude()
{
return Math::Sqrt<T>(Math::Pow<T>(w, 2) + Math::Pow<T>(x, 2) + Math::Pow<T>(y, 2) + Math::Pow<T>(z, 2));
}
Quat<T> GetNormalized()
{
T mag = GetMagnitude();
return Quat<T>(w / mag, x / mag, y / mag, z / mag);
}
void Normalize()
{
T mag = GetMagnitude();
w = w / mag;
x = x / mag;
y = y / mag;
z = z / mag;
}
T Dot(const Quat& other) const
{
return w * other.w + x * other.x + y * other.y + z * other.z;
}
Quat<T> GetConjugate()
{
return Quat<T>(w, -x, -y, -z);
}
void Conjugate()
{
x = -x;
y = -y;
z = -z;
}
Quat<T> GetInverse()
{
return Quat<T>(w, -x, -y, -z);
}
void Inverse()
{
x = -x;
y = -y;
z = -z;
}
static Quat<T> Slerp(Quat<T> start, Quat<T> finish, const T t)
{
T cosHalfTheta = start.Dot(finish);
if (Math::Abs(cosHalfTheta) >= 1.0f)
return start;
float halfTheta = Math::ACos(cosHalfTheta);
float sinHalfTheta = Math::Sqrt(1.0f - cosHalfTheta * cosHalfTheta);
if (Math::Abs(sinHalfTheta) < 0.001f)
{
return {
start.w * 0.5f + finish.w * 0.5f,
start.x * 0.5f + finish.x * 0.5f,
start.y * 0.5f + finish.y * 0.5f,
start.z * 0.5f + finish.z * 0.5f
};
}
float ratioA = Math::Sin((1 - t) * halfTheta) / sinHalfTheta;
float ratioB = Math::Sin(t * halfTheta) / sinHalfTheta;
return {
start.w * ratioA + finish.w * ratioB,
start.x * ratioA + finish.x * ratioB,
start.y * ratioA + finish.y * ratioB,
start.z * ratioA + finish.z * ratioB
};
}
};
typedef Quat<float> Quat_f;

5
src/Range.cpp Normal file
View File

@ -0,0 +1,5 @@
//
// Created by Nelso on 3/29/2022.
//
#include "Range.h"

25
src/Range.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
template<typename N>
class Range
{
public:
N min;
N max;
Range()
: min(0), max(0)
{
}
Range(const N min, const N max)
: min(min), max(max)
{
}
Range(const Range& range)
: min(range.min), max(range.max)
{
}
};

181
src/Rect.h Normal file
View File

@ -0,0 +1,181 @@
#pragma once
#include "EHS.h"
#include "Vec2.h"
#include "Vec3.h"
#include "Vec4.h"
template<typename T>
class Rect
{
public:
T x;
T y;
T w;
T h;
Rect(const T scalar = 0)
: x(scalar), y(scalar), w(scalar), h(scalar)
{
}
Rect(const T x, const T y, const T w, const T h)
: x(x), y(y), w(w), h(h)
{
}
template<typename C>
Rect(const Vec2<C>& vec, const T w = 0, const T h = 0)
: x((T)vec.x), y((T)vec.y), w(w), h(h)
{
}
template<typename C>
Rect(const Vec3<C>& vec, const T h = 0)
: x((T)vec.x), y((T)vec.y), w((T)vec.z), h(h)
{
}
template<typename C>
Rect(const Vec4<C>& vec)
: x((T)vec.x), y((T)vec.y), w((T)vec.z), h((T)vec.w)
{
}
template<typename C>
Rect(const Rect<C>& rect)
: x((T)rect.x), y((T)rect.y), w((T)rect.w), h((T)rect.h)
{
}
template<typename C>
Rect<T>& operator=(const Vec2<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
w = 0;
h = 0;
return *this;
}
template<typename C>
Rect<T>& operator=(const Vec3<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
w = (T)vec.z;
h = 0;
return *this;
}
template<typename C>
Rect<T>& operator=(const Vec4<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
w = (T)vec.z;
h = (T)vec.w;
return *this;
}
template<typename C>
Rect<T>& operator=(const Rect<C>& rect)
{
if (this == &rect)
return *this;
x = (T)rect.x;
y = (T)rect.y;
w = (T)rect.w;
h = (T)rect.h;
return *this;
}
bool operator==(const Vec4<T>& vec)
{
return x == vec.x && y == vec.y && w == vec.z && h == vec.w;
}
bool operator!=(const Vec4<T>& vec)
{
return x != vec.x || y != vec.y || w != vec.z || h != vec.w;
}
bool operator==(const Rect<T>& rect)
{
return x == rect.x && y == rect.y && w == rect.w && h == rect.h;
}
bool operator!=(const Rect<T>& rect)
{
return x != rect.x || y != rect.y || w != rect.w || h != rect.h;
}
T operator[](const UInt_64 index) const
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return w;
case 3:
return h;
default:
return x;
}
}
T& operator[](const UInt_64 index)
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return w;
case 3:
return h;
default:
return x;
}
}
operator Vec4<T>()
{
return Vec4<T>(x, y, w, h);
}
Vec2<T> GetPos() const
{
return {x, y};
}
Vec2<T> GetScale() const
{
return {w, h};
}
};
typedef Rect<UInt_64> Rect_u64;
typedef Rect<SInt_64> Rect_s64;
typedef Rect<Int_64> Rect_64;
typedef Rect<UInt_32> Rect_u32;
typedef Rect<SInt_32> Rect_s32;
typedef Rect<Int_32> Rect_32;
typedef Rect<UInt_16> Rect_u16;
typedef Rect<SInt_16> Rect_s16;
typedef Rect<Int_16> Rect_16;
typedef Rect<UInt_8> Rect_u8;
typedef Rect<SInt_8> Rect_s8;
typedef Rect<Int_8> Rect_8;
typedef Rect<float> Rect_f;
typedef Rect<double> Rect_d;

105
src/SArray.h Normal file
View File

@ -0,0 +1,105 @@
#pragma once
#include "EHS.h"
/// This container is useful for sorting arrays efficiently.
template<typename T, typename N = UInt_64>
class SArray
{
private:
T* data;
N size;
public:
~SArray()
{
delete[] data;
}
SArray()
: data(nullptr), size(0)
{
}
SArray(const N size)
: data(new T[size]), size(size)
{
}
SArray(const SArray& sArray)
: data(new T[sArray.size]), size(sArray.size)
{
for (N i = 0; i < size; ++i)
data[i] = sArray.data[i];
}
SArray(SArray&& sArray) noexcept
: data(sArray.data), size(sArray.size)
{
sArray.data = nullptr;
sArray.size = 0;
}
SArray& operator=(const SArray& pArray)
{
if (this == &pArray)
return *this;
delete[] data;
data = new T[pArray.size];
for (N i = 0; i < pArray.size; ++i)
data[i] = pArray.data[i];
size = pArray.size;
return *this;
}
SArray& operator=(SArray&& pArray) noexcept
{
if (this == &pArray)
return *this;
delete[] data;
data = pArray.data;
size = pArray.size;
pArray.data = nullptr;
pArray.size = 0;
return *this;
}
operator const T* () const
{
return data;
}
operator T* ()
{
return data;
}
void Insert(const N index, T value)
{
if (index >= size)
{
return;
}
for (N i = size; i > index + 1; --i)
data[i - 1] = std::move(data[i - 2]);
data[index] = std::move(value);
}
void SetSize(const N newSize)
{
size = newSize;
}
N Size() const
{
return size;
}
};

1122
src/Serializer.h Normal file

File diff suppressed because it is too large Load Diff

1765
src/Str.h Normal file

File diff suppressed because it is too large Load Diff

109
src/Util.cpp Normal file
View File

@ -0,0 +1,109 @@
#include "Util.h"
bool Util::IsEqual(const void* const a, const void* const b, const UInt_64 size)
{
Byte* aBytes = (Byte*)a;
Byte* bBytes = (Byte*)b;
UInt_64 remainder = size;
UInt_64 i = 0;
while (i < size)
{
if (remainder >= sizeof(UInt_64))
{
if (*(UInt_64*)&aBytes[i] != *(UInt_64*)&bBytes[i])
return false;
i += sizeof(UInt_64);
}
else if (remainder >= sizeof(UInt_32))
{
if (*(UInt_32*)&aBytes[i] != *(UInt_32*)&bBytes[i])
return false;
i += sizeof(UInt_32);
}
else if (remainder >= sizeof(UInt_16))
{
if (*(UInt_16*)&aBytes[i] != *(UInt_16*)&bBytes[i])
return false;
i += sizeof(UInt_16);
}
else
{
if (aBytes[i] != bBytes[i])
return false;
i += sizeof(Byte);
}
remainder = size - i;
}
return true;
}
void Util::Copy(void* const out, const void* const in, const UInt_64 size)
{
Byte* outB = (Byte*)out;
Byte* inB = (Byte*)in;
UInt_64 remainder = size;
UInt_64 i = 0;
while (i < size)
{
if (remainder >= sizeof(UInt_64))
{
*(UInt_64*)&outB[i] = *(UInt_64*)&inB[i];
i += sizeof(UInt_64);
}
else if (remainder >= sizeof(UInt_32))
{
*(UInt_32*)&outB[i] = *(UInt_32*)&inB[i];
i += sizeof(UInt_32);
}
else if (remainder >= sizeof(UInt_16))
{
*(UInt_16*)&outB[i] = *(UInt_16*)&inB[i];
i += sizeof(UInt_16);
}
else
{
outB[i++] = inB[i];
}
remainder = size - i;
}
}
void Util::Zero(void* const in, const UInt_64 size)
{
Byte* inB = (Byte*)in;
UInt_64 remainder = size;
UInt_64 i = 0;
while (i < size)
{
if (remainder >= sizeof(UInt_64))
{
*(UInt_64*)&inB[i] = 0;
i += sizeof(UInt_64);
}
else if (remainder >= sizeof(UInt_32))
{
*(UInt_32*)&inB[i] = 0;
i += sizeof(UInt_32);
}
else if (remainder >= sizeof(UInt_16))
{
*(UInt_16*)&inB[i] = 0;
i += sizeof(UInt_16);
}
else
{
inB[i++] = 0;
}
remainder = size - i;
}
}

13
src/Util.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "EHS.h"
class Util
{
public:
static bool IsEqual(const void* const a, const void* const b, const UInt_64 size);
static void Copy(void* const out, const void* const in, const UInt_64 size);
static void Zero(void* const in, const UInt_64 size);
};

375
src/Vec2.h Normal file
View File

@ -0,0 +1,375 @@
#pragma once
#include "EHS.h"
#include "UTF.h"
#include "Str.h"
#include "Math.h"
template<typename T = float>
class Vec2
{
public:
T x;
T y;
Vec2(const T x, const T y)
: x(x), y(y)
{
}
template<typename C>
Vec2(const Vec2<C>& vec)
: x((T)vec.x), y((T)vec.y)
{
}
Vec2(const T scalar = 0)
: x(scalar), y(scalar)
{
}
template<typename C>
Vec2<T>& operator=(const Vec2<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
return *this;
}
bool operator==(const Vec2<T>& vec) const
{
return Math::ComCmp(x, vec.x) && Math::ComCmp(x, vec.y);
}
bool operator!=(const Vec2<T>& vec) const
{
return !Math::ComCmp(x, vec.x) || !Math::ComCmp(x, vec.y);
}
Vec2<T>& operator+=(const Vec2<T>& vec)
{
x += vec.x;
y += vec.y;
return *this;
}
Vec2<T> operator+(const Vec2<T>& vec) const
{
Vec2<T> tmp;
tmp.x = x + vec.x;
tmp.y = y + vec.y;
return tmp;
}
Vec2<T>& operator+=(const T scalar)
{
x += scalar;
y += scalar;
return *this;
}
Vec2<T> operator+(const T scalar) const
{
Vec2<T> tmp;
tmp.x = x + scalar;
tmp.y = y + scalar;
return tmp;
}
Vec2<T>& operator-=(const Vec2<T>& vec)
{
x -= vec.x;
y -= vec.y;
return *this;
}
Vec2<T> operator-(const Vec2<T>& vec) const
{
Vec2<T> tmp;
tmp.x = x - vec.x;
tmp.y = y - vec.y;
return tmp;
}
Vec2<T>& operator-=(const T scalar)
{
x -= scalar;
y -= scalar;
return *this;
}
Vec2<T> operator-(const T scalar) const
{
Vec2<T> tmp;
tmp.x = x - scalar;
tmp.y = y - scalar;
return tmp;
}
Vec2<T>& operator/=(const Vec2<T>& vec)
{
x /= vec.x;
y /= vec.y;
return *this;
}
Vec2<T> operator/(const Vec2<T>& vec) const
{
Vec2<T> tmp;
tmp.x = x / vec.x;
tmp.y = y / vec.y;
return tmp;
}
Vec2<T>& operator/=(const T scalar)
{
x /= scalar;
y /= scalar;
return *this;
}
Vec2<T> operator/(const T scalar) const
{
Vec2<T> tmp;
tmp.x = x / scalar;
tmp.y = y / scalar;
return tmp;
}
Vec2<T>& operator*=(const Vec2<T>& vec)
{
x *= vec.x;
y *= vec.y;
return *this;
}
Vec2<T> operator*(const Vec2<T>& vec) const
{
Vec2<T> tmp;
tmp.x = x * vec.x;
tmp.y = y * vec.y;
return tmp;
}
Vec2<T>& operator*=(const T scalar)
{
x *= scalar;
y *= scalar;
return *this;
}
Vec2<T> operator*(const T scalar) const
{
Vec2<T> tmp;
tmp.x = x * scalar;
tmp.y = y * scalar;
return tmp;
}
bool operator<=(const Vec2<T>& other) const
{
return x <= other.x && y <= other.y;
}
bool operator<(const Vec2<T>& other) const
{
return x < other.x && y < other.y;
}
bool operator>=(const Vec2<T>& other) const
{
return x >= other.x && y >= other.y;
}
bool operator>(const Vec2<T>& other) const
{
return x > other.x && y > other.y;
}
T operator[](const UInt_64 index) const
{
switch (index)
{
case 0:
return x;
case 1:
return y;
default:
return x;
}
}
T& operator[](const UInt_64 index)
{
switch (index)
{
case 0:
return x;
case 1:
return y;
default:
return x;
}
}
Vec2<T> GetAbs() const
{
Vec2<T> tmp;
tmp.x = Math::Abs(x);
tmp.y = Math::Abs(y);
return tmp;
}
void Abs()
{
x = Math::Abs(x);
y = Math::Abs(y);
}
/// If positive, the vectors are pointing in the same direction. If negative, the vectors are pointing in opposing directions.
/// If zero, the vectors are perpendicular.
T GetDot(const Vec2<T>& vec) const
{
return x * vec.x + y * vec.y;
}
T GetAngle(const Vec2<T>& vec) const
{
return Math::ACos(GetDot(vec) / Math::Sqrt(GetMagnitude2() * vec.GetMagnitude2()));
}
Vec2<T> GetProjection(const Vec2<T>& length) const
{
return operator*(length.GetDot(*this) / GetMagnitude2());
}
Vec2<T> GetPerpendicular(const Vec2<T>& length) const
{
return length - GetProjection(length);
}
Vec2<T> GetReflection(const Vec2<T>& normal) const
{
return operator-(normal * (GetDot(normal) * 2));
}
T GetMagnitude() const
{
return Math::Sqrt(x * x + y * y);
}
T GetMagnitude2() const
{
return x * x + y * y;
}
T GetDistance(const Vec2<T>& vec) const
{
return Math::Sqrt(Math::Pow(vec.x - x, 2) + Math::Pow(vec.y - y, 2));
}
T GetDistance2(const Vec2<T>& vec) const
{
return Math::Pow(vec.x - x, 2) + Math::Pow(vec.y - y, 2);
}
Vec2<T> GetNorm() const
{
Vec2<T> norm;
T dis = GetMagnitude();
norm.x = x / dis;
norm.y = y / dis;
return norm;
}
void Norm()
{
T dis = GetMagnitude();
x /= dis;
y /= dis;
}
Vec2<T> GetRads() const
{
Vec2<T> tmp;
tmp.x = Math::Rads(x);
tmp.y = Math::Rads(y);
return tmp;
}
void ToRads()
{
x = Math::Rads(x);
y = Math::Rads(y);
}
Vec2<T> GetDegr() const
{
Vec2<T> tmp;
tmp.x = Math::Degr(x);
tmp.y = Math::Degr(y);
return tmp;
}
void ToDegr()
{
x = Math::Degr(x);
y = Math::Degr(y);
}
static Vec2 Lerp(const Vec2& start, const Vec2& finish, const T t)
{
return start + (finish - start) * t;
}
};
typedef Vec2<UInt_64> Vec2_u64;
typedef Vec2<SInt_64> Vec2_s64;
typedef Vec2<Int_64> Vec2_64;
typedef Vec2<UInt_32> Vec2_u32;
typedef Vec2<SInt_32> Vec2_s32;
typedef Vec2<Int_32> Vec2_32;
typedef Vec2<UInt_16> Vec2_u16;
typedef Vec2<SInt_16> Vec2_s16;
typedef Vec2<Int_16> Vec2_16;
typedef Vec2<UInt_8> Vec2_u8;
typedef Vec2<SInt_8> Vec2_s8;
typedef Vec2<Int_8> Vec2_8;
typedef Vec2<float> Vec2_f;
typedef Vec2<double> Vec2_d;

434
src/Vec3.h Normal file
View File

@ -0,0 +1,434 @@
#pragma once
#include "EHS.h"
#include "UTF.h"
#include "Str.h"
#include "Math.h"
#include "Vec2.h"
template<typename T>
class Vec3
{
public:
T x;
T y;
T z;
Vec3(const T scalar = 0)
: x(scalar), y(scalar), z(scalar)
{
}
Vec3(const T x, const T y, const T z)
: x(x), y(y), z(z)
{
}
template<typename C>
Vec3(const Vec2<C>& vec, const T z = 0)
: x((T)vec.x), y((T)vec.y), z(z)
{
}
template<typename C>
Vec3(const Vec3<C>& vec)
: x((T)vec.x), y((T)vec.y), z((T)vec.z)
{
}
template<typename C>
Vec3<T>& operator=(const Vec2<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
z = 0;
return *this;
}
template<typename C>
Vec3<T>& operator=(const Vec3<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
z = (T)vec.z;
return *this;
}
bool operator==(const Vec3<T>& vec) const
{
return Math::ComCmp(x, vec.x) && Math::ComCmp(y, vec.y) && Math::ComCmp(z, vec.z);
}
bool operator!=(const Vec3<T>& vec) const
{
return !Math::ComCmp(z, vec.z) || !Math::ComCmp(y, vec.y) || !Math::ComCmp(z, vec.z);
}
Vec3<T> operator+(const Vec3<T>& vec) const
{
Vec3<T> tmp;
tmp.x = x + vec.x;
tmp.y = y + vec.y;
tmp.z = z + vec.z;
return tmp;
}
Vec3<T>& operator+=(const Vec3<T>& vec)
{
x += vec.x;
y += vec.y;
z += vec.z;
return *this;
}
Vec3<T> operator+(const T scalar) const
{
Vec3<T> tmp;
tmp.x = x + scalar;
tmp.y = y + scalar;
tmp.z = z + scalar;
return tmp;
}
Vec3<T>& operator+=(const T scalar)
{
x += scalar;
y += scalar;
z += scalar;
return *this;
}
Vec3<T> operator-(const Vec3<T>& vec) const
{
Vec3<T> tmp;
tmp.x = x - vec.x;
tmp.y = y - vec.y;
tmp.z = z - vec.z;
return tmp;
}
Vec3<T>& operator-=(const Vec3<T>& vec)
{
x -= vec.x;
y -= vec.y;
z -= vec.z;
return *this;
}
Vec3<T> operator-(const T scalar) const
{
Vec3<T> tmp;
tmp.x = x - scalar;
tmp.y = y - scalar;
tmp.z = z - scalar;
return tmp;
}
Vec3<T>& operator-=(const T scalar)
{
x -= scalar;
y -= scalar;
z -= scalar;
return *this;
}
Vec3<T> operator*(const Vec3<T>& vec) const
{
Vec3<T> tmp;
tmp.x = x * vec.x;
tmp.y = y * vec.y;
tmp.z = z * vec.z;
return tmp;
}
Vec3<T>& operator*=(const Vec3<T>& vec)
{
x *= vec.x;
y *= vec.y;
z *= vec.z;
return *this;
}
Vec3<T> operator*(const T scalar) const
{
Vec3<T> tmp;
tmp.x = x * scalar;
tmp.y = y * scalar;
tmp.z = z * scalar;
return tmp;
}
Vec3<T>& operator*=(const T scalar)
{
x *= scalar;
y *= scalar;
z *= scalar;
return *this;
}
Vec3<T> operator/(const Vec3<T>& vec) const
{
Vec3<T> tmp;
tmp.x = x / vec.x;
tmp.y = y / vec.y;
tmp.z = z / vec.z;
return tmp;
}
Vec3<T>& operator/=(const Vec3<T>& vec)
{
x /= vec.x;
y /= vec.y;
z /= vec.z;
return *this;
}
Vec3<T> operator/(const T scalar) const
{
Vec3<T> tmp;
tmp.x = x / scalar;
tmp.y = y / scalar;
tmp.z = z / scalar;
return tmp;
}
Vec3<T>& operator/=(const T scalar)
{
x /= scalar;
y /= scalar;
z /= scalar;
return *this;
}
bool operator<=(const Vec3<T>& other) const
{
return x <= other.x && y <= other.y && z <= other.z;
}
bool operator<(const Vec3<T>& other) const
{
return x < other.x && y < other.y && z < other.z;
}
bool operator>=(const Vec3<T>& other) const
{
return x >= other.x && y >= other.y && z >= other.z;
}
bool operator>(const Vec3<T>& other) const
{
return x > other.x && y > other.y && z > other.z;
}
T operator[](const UInt_64 index) const
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
return x;
}
}
T& operator[](const UInt_64 index)
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
return x;
}
}
operator Vec2<T>()
{
return Vec2<T>(x, y);
}
Vec3<T> GetAbs() const
{
Vec3<T> absolute;
absolute.x = Math::Abs(x);
absolute.y = Math::Abs(y);
absolute.z = Math::Abs(z);
return absolute;
}
void Abs()
{
x = Math::Abs(x);
y = Math::Abs(y);
z = Math::Abs(z);
}
Vec3<T> GetNorm() const
{
Vec3<T> norm;
T dis = GetMagnitude();
norm.x = x / dis;
norm.y = y / dis;
norm.z = z / dis;
return norm;
}
void Norm()
{
T dis = GetMagnitude();
x /= dis;
y /= dis;
z /= dis;
}
Vec3<T> GetCross(const Vec3<T>& vec) const
{
return Vec3<T>(
y * vec.z - z * vec.y,
z * vec.x - x * vec.z,
x * vec.y - y * vec.x
);
}
T GetDot(const Vec3<T>& vec) const
{
return x * vec.x + y * vec.y + z * vec.z;
}
T GetAngle(const Vec2<T>& vec) const
{
return Math::ACos(GetDot(vec) / Math::Sqrt(GetMagnitude2() * vec.GetMagnitude2()));
}
Vec2<T> GetProjection(const Vec2<T>& length) const
{
return operator*(length.GetDot(*this) / GetMagnitude2());
}
Vec2<T> GetPerpendicular(const Vec2<T>& length) const
{
return length - GetProjection(length);
}
Vec2<T> GetReflection(const Vec2<T>& normal) const
{
return operator-(normal * (GetDot(normal) * 2));
}
T GetMagnitude() const
{
return Math::Sqrt(x * x + y * y + z * z);
}
T GetMagnitude2() const
{
return x * x + y * y + z * z;
}
T GetDistance(const Vec3<T>& vec) const
{
return (T)Math::Sqrt(Math::Pow<T>(vec.x - x, 2) + Math::Pow<T>(vec.y - y, 2) + Math::Pow<T>(vec.z - z, 2));
}
T GetDistance2(const Vec3<T>& vec) const
{
return static_cast<T>(Math::Pow<T>(vec.x - x, 2) + Math::Pow<T>(vec.y - y, 2) + Math::Pow<T>(vec.z - z, 2));
}
Vec3<T> GetRads() const
{
Vec3<T> tmp;
tmp.x = Math::Rads(x);
tmp.y = Math::Rads(y);
tmp.z = Math::Rads(z);
return tmp;
}
void ToRads()
{
x = Math::Rads(x);
y = Math::Rads(y);
z = Math::Rads(z);
}
Vec3<T> GetDegr() const
{
Vec3<T> tmp;
tmp.x = Math::Degr(x);
tmp.y = Math::Degr(y);
tmp.z = Math::Degr(z);
return tmp;
}
void ToDegr()
{
x = Math::Degr(x);
y = Math::Degr(y);
z = Math::Degr(z);
}
static Vec3 Lerp(const Vec3& start, const Vec3& finish, const T t)
{
return start + (finish - start) * t;
}
};
typedef Vec3<UInt_64> Vec3_u64;
typedef Vec3<SInt_64> Vec3_s64;
typedef Vec3<Int_64> Vec3_64;
typedef Vec3<UInt_32> Vec3_u32;
typedef Vec3<SInt_32> Vec3_s32;
typedef Vec3<Int_32> Vec3_32;
typedef Vec3<UInt_16> Vec3_u16;
typedef Vec3<SInt_16> Vec3_s16;
typedef Vec3<Int_16> Vec3_16;
typedef Vec3<UInt_8> Vec3_u8;
typedef Vec3<SInt_8> Vec3_s8;
typedef Vec3<Int_8> Vec3_8;
typedef Vec3<float> Vec3_f;
typedef Vec3<double> Vec3_d;

339
src/Vec4.h Normal file
View File

@ -0,0 +1,339 @@
#pragma once
#include "EHS.h"
#include "UTF.h"
#include "Str.h"
#include "Math.h"
#include "Vec2.h"
#include "Vec3.h"
template<typename T>
class Vec4
{
public:
T x;
T y;
T z;
T w;
Vec4(const T scalar = 0)
: x(scalar), y(scalar), z(scalar), w(scalar)
{
}
Vec4(const T x, const T y, const T z, const T w)
: x(x), y(y), z(z), w(w)
{
}
template<typename C>
Vec4(const Vec2<C>& vec, const T z = 0, const T w = 0)
: x((T)vec.x), y((T)vec.y), z(z), w(w)
{
}
template<typename C>
Vec4(const Vec3<C>& vec, const T w = 1)
: x((T)vec.x), y((T)vec.y), z((T)vec.z), w(w)
{
}
template<typename C>
Vec4(const Vec4<C>& vec)
: x((T)vec.x), y((T)vec.y), z((T)vec.z), w((T)vec.w)
{
}
template<typename C>
Vec4<T>& operator=(const Vec2<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
z = (T)0;
w = (T)0;
return*this;
}
template<typename C>
Vec4<T>& operator=(const Vec3<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
z = (T)vec.z;
w = (T)0;
return*this;
}
template<typename C>
Vec4<T>& operator=(const Vec4<C>& vec)
{
x = (T)vec.x;
y = (T)vec.y;
z = (T)vec.z;
w = (T)vec.w;
return*this;
}
bool operator==(const Vec4<T>& vec)
{
return Math::ComCmp(x, vec.x) && Math::ComCmp(y, vec.y) && Math::ComCmp(z, vec.z) && Math::ComCmp(w, vec.w);
}
bool operator!=(const Vec4<T>& vec)
{
return !Math::ComCmp(z, vec.z) || !Math::ComCmp(y, vec.y) || !Math::ComCmp(z, vec.z) || !Math::ComCmp(w, vec.w);
}
Vec4<T>& operator+=(const Vec4<T>& vec)
{
x += vec.x;
y += vec.y;
z += vec.z;
w += vec.w;
return *this;
}
Vec4<T> operator+(const Vec4<T>& vec)
{
Vec4<T> tmp;
tmp.x = x + vec.x;
tmp.y = y + vec.y;
tmp.z = z + vec.z;
tmp.w = w + vec.w;
return tmp;
}
Vec4<T>& operator+=(const T scalar)
{
x += scalar;
y += scalar;
z += scalar;
w += scalar;
return *this;
}
Vec4<T> operator+(const T scalar)
{
Vec4<T> tmp;
tmp.x = x + scalar;
tmp.y = y + scalar;
tmp.z = z + scalar;
tmp.w = w + scalar;
return tmp;
}
Vec4<T>& operator-=(const Vec4<T>& vec)
{
x -= vec.x;
y -= vec.y;
z -= vec.z;
w -= vec.w;
return *this;
}
Vec4<T> operator-(const Vec4<T>& vec)
{
Vec4<T> tmp;
tmp.x = x - vec.x;
tmp.y = y - vec.y;
tmp.z = z - vec.z;
tmp.w = w - vec.w;
return tmp;
}
Vec4<T>& operator-=(const T scalar)
{
x -= scalar;
y -= scalar;
z -= scalar;
w -= scalar;
return *this;
}
Vec4<T> operator-(const T scalar)
{
Vec4<T> tmp;
tmp.x = x - scalar;
tmp.y = y - scalar;
tmp.z = z - scalar;
tmp.w = w - scalar;
return tmp;
}
Vec4<T>& operator*=(const Vec4<T>& vec)
{
x *= vec.x;
y *= vec.y;
z *= vec.z;
w *= vec.w;
return *this;
}
Vec4<T> operator*(const Vec4<T>& vec)
{
Vec4<T> tmp;
tmp.x = x * vec.x;
tmp.y = y * vec.y;
tmp.z = z * vec.z;
tmp.w = w * vec.w;
return tmp;
}
Vec4<T>& operator*=(const T scalar)
{
x *= scalar;
y *= scalar;
z *= scalar;
w *= scalar;
return *this;
}
Vec4<T> operator*(const T scalar)
{
Vec4<T> tmp;
tmp.x = x * scalar;
tmp.y = y * scalar;
tmp.z = z * scalar;
tmp.w = w * scalar;
return tmp;
}
Vec4<T>& operator/=(const Vec4<T>& vec)
{
x /= vec.x;
y /= vec.y;
z /= vec.z;
w /= vec.w;
return *this;
}
Vec4<T> operator/(const Vec4<T>& vec)
{
Vec4<T> tmp;
tmp.x = x / vec.x;
tmp.y = y / vec.y;
tmp.z = z / vec.z;
tmp.w = w / vec.w;
return tmp;
}
Vec4<T>& operator/=(const T scalar)
{
x /= scalar;
y /= scalar;
z /= scalar;
w /= scalar;
return *this;
}
Vec4<T> operator/(const T scalar)
{
Vec4<T> tmp;
tmp.x = x / scalar;
tmp.y = y / scalar;
tmp.z = z / scalar;
tmp.w = w / scalar;
return tmp;
}
T operator[](const UInt_64 index) const
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
case 3:
return w;
default:
return x;
}
}
T& operator[](const UInt_64 index)
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
case 3:
return w;
default:
return x;
}
}
operator Vec3<T>()
{
return Vec3<T>(x, y, z);
}
operator Vec2<T>()
{
return Vec2<T>(x, y);
}
T GetDotProduct(const Vec4<T>& vec) const
{
return x * vec.x + y * vec.y + z * vec.z + w * vec.w;
}
T GetMagnitude() const
{
return Math::Sqrt(x * x + y * y + z * z + w * w);
}
T GetMagnitude2() const
{
return x * x + y * y + z * z + w * w;
}
};
typedef Vec4<UInt_64> Vec4_u64;
typedef Vec4<SInt_64> Vec4_s64;
typedef Vec4<Int_64> Vec4_64;
typedef Vec4<UInt_32> Vec4_u32;
typedef Vec4<SInt_32> Vec4_s32;
typedef Vec4<Int_32> Vec4_32;
typedef Vec4<UInt_16> Vec4_u16;
typedef Vec4<SInt_16> Vec4_s16;
typedef Vec4<Int_16> Vec4_16;
typedef Vec4<UInt_8> Vec4_u8;
typedef Vec4<SInt_8> Vec4_s8;
typedef Vec4<Int_8> Vec4_8;
typedef Vec4<float> Vec4_f;
typedef Vec4<double> Vec4_d;

587
src/Vector.h Normal file
View File

@ -0,0 +1,587 @@
#pragma once
#include "EHS.h"
#include <initializer_list>
#include <utility>
/// An array with extra memory pre-allocated for fast pushes.
/// @tparam T Array data type to use.
/// @tparam N Number data type to use.
/// @note If extra memory is set to five then each time that memory is filled it will add five extra.
template<typename T, typename N = UInt_64>
class Vector
{
protected:
N rawSize;
N size;
N stride;
T* data;
public:
/// Frees any data created on the heap.
~Vector()
{
delete[] data;
}
/// Default members initialization.
Vector()
: rawSize(0), size(0), stride(5), data(nullptr)
{
}
/// Initializes members for pre-allocated memory to write to later.
/// @param [in] size The size of memory to pre-allocate.
/// @param [in] stride The stride size of memory to pre-allocate.
Vector(const N size, const N stride)
: rawSize(size + stride), size(size), stride(stride), data(new T[rawSize])
{
}
/// Initializes this vector with an initializer list object.
/// @param [in] list The given initializer list.
/// @param [in] stride The extra amount of memory to allocate.
Vector(std::initializer_list<T> list, const N stride = 5)
: rawSize(0), size(list.size()), stride(stride), data(nullptr)
{
if (stride)
{
rawSize = list.size() / stride * stride;
if (list.size() % stride)
rawSize += stride;
}
else
{
rawSize = list.size();
}
data = new T[rawSize];
N i = 0;
for (auto v = list.begin(); v != list.end(); ++v)
data[i++] = std::move(*v);
}
/// Initializes members with given C-style array.
/// @param [in] data The C-style array.
/// @param [in] size The size of the given C-style array.
/// @param [in] stride The size of the extra memory allocated.
Vector(const T* data, const N size, const N stride)
: rawSize(0), size(size), stride(stride), data(nullptr)
{
if (stride)
{
rawSize = size / stride * stride;
if (size % stride)
rawSize += stride;
}
else
{
rawSize = size;
}
data = new T[rawSize];
for (N i = 0; i < size; ++i)
this->data[i] = data[i];
}
/// Copies all members from the given vector object.
/// @param [in] vec The vector object to copy from.
Vector(const Vector& vec)
: rawSize(vec.rawSize), size(vec.size), stride(vec.stride), data(new T[rawSize])
{
for (N i = 0; i < size; ++i)
data[i] = vec.data[i];
}
Vector(Vector&& vec) noexcept
: rawSize(vec.rawSize), size(vec.size), stride(vec.stride), data(vec.data)
{
vec.rawSize = 0;
vec.size = 0;
vec.stride = 0;
vec.data = nullptr;
}
/// Copies all members from the given vector object.
/// @param [in] vec The vector object to copy from.
/// @returns The vector that has been assigned to.
Vector& operator=(const Vector& vec)
{
if (this == &vec)
return *this;
rawSize = vec.rawSize;
size = vec.size;
stride = vec.stride;
delete[] data;
data = new T[rawSize];
for (N i = 0; i < size; ++i)
data[i] = vec.data[i];
return *this;
}
Vector& operator=(Vector&& vec) noexcept
{
if (this == &vec)
return *this;
rawSize = vec.rawSize;
size = vec.size;
stride = vec.stride;
delete[] data;
data = vec.data;
vec.rawSize = 0;
vec.size = 0;
vec.stride = 0;
vec.data = nullptr;
return *this;
}
/// Adds a given initializer list at the end of the vector.
/// @param [in] value The given initializer list to push to the end of the vector.
Vector& operator+=(std::initializer_list<T> value)
{
if (size + value.size() >= rawSize)
{
if (stride)
{
rawSize = (size + value.size()) / stride * stride;
if ((size + value.size()) % stride)
rawSize += stride;
}
else
{
rawSize = size + value.size();
}
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(std::move(data[i]));
delete[] data;
data = result;
}
for (auto v = value.begin(); v != value.end(); ++v)
data[size++] = std::move(*v);
return *this;
}
/// Adds a given value at the end of the vector.
/// @param [in] value The given value to push to the end of the vector.
Vector& operator+=(const T value)
{
if (size + 1 >= rawSize)
{
if (stride)
rawSize = size + stride;
else
rawSize = size + 1;
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
}
data[size++] = std::move(value);
return *this;
}
/// Retrieves the raw C-style array from casting an array object.
operator T* () const
{
return data;
}
/// Retrieves the size of the vector object including the extra memory allocated.
/// @returns The raw size.
N RawSize() const
{
return rawSize;
}
/// Retrieves the size of the array not including the extra memory allocated.
/// @returns The size.
N Size() const
{
return size;
}
/// Retrieves the size of the extra memory allocated.
/// @returns The extra size.
N Stride() const
{
return stride;
}
N End() const
{
return size ? size - 1 : size;
}
/// Copies a vector object with offsets.
/// @param [in] dstOffset The offset index to copy the given vector object to.
/// @param [in] src The given vector object.
/// @param [in] srcOffset The offset index from the given vector object to copy from.
void Copy(const N dstOffset, Vector<T, N> src, const N srcOffset = 0)
{
for (N i = 0; i < src.Size() - srcOffset; ++i)
data[i + dstOffset] = std::move(src[i + srcOffset]);
}
/// Copies a C-style array with offsets.
/// @param [in] dstOffset The offset index to copy the given C-style array to.
/// @param [in] src The given C-style array.
/// @param [in] size The size from the given C-style array to copy.
void Copy(const N dstOffset, const T* src, const N size)
{
for (N i = 0; i < size; ++i)
data[i + dstOffset] = src[i];
}
/// Swaps two values in the vector.
/// @param [in] a The first index to swap with.
/// @param [in] b The second index to swap with.
void Swap(N a, N b)
{
T tmp = std::move(data[a]);
data[a] = std::move(data[b]);
data[b] = std::move(tmp);
}
/// Inserts a value at a specified index that is available.
/// @param [in] index The index to insert the value at.
/// @param [in] value The given value to insert.
void Insert(const N index, const T value)
{
N newSize = 0;
if (index > size - 1)
newSize = size + ((index + 1) - size);
else
newSize = size + 1;
if (newSize >= rawSize)
{
if (stride)
rawSize += newSize + stride;
else
rawSize = newSize;
T* result = new T[rawSize];
for (N i = 0; i < index; ++i)
result[i] = std::move(data[i]);
result[index] = std::move(value);
for (N i = index; i < size; ++i)
result[i + 1] = std::move(data[i]);
delete[] data;
data = result;
}
else
{
for (N i = index; i < size; ++i)
data[i + 1] = std::move(data[i]);
data[index] = std::move(value);
}
size += newSize;
}
/// Removes a value at a specified index.
/// @param [in] index The index to remove the value at.
/// @returns The removed data.
T Remove(const N index)
{
T popped = {};
if (!size || index >= size)
return popped;
popped = std::move(data[index]);
if (!stride)
{
rawSize = size - 1;
T* result = new T[rawSize];
for (N i = 0; i < index; ++i)
result[i] = std::move(data[i]);
for (N i = index + 1; i < size; ++i)
result[i - 1] = std::move(data[i]);
delete[] data;
data = result;
}
else if (rawSize - stride && size - 1 <= rawSize - stride)
{
rawSize -= stride;
T* result = new T[rawSize];
for (N i = 0; i < index; ++i)
result[i] = std::move(data[i]);
for (N i = index + 1; i < size; ++i)
result[i - 1] = std::move(data[i]);
delete[] data;
data = result;
}
else
{
for (N i = index + 1; i < size; ++i)
data[i - 1] = std::move(data[i]);
}
--size;
return popped;
}
/// Adds a given C-style array at the end of the vector.
/// @param [in] value The given C-style array to push to the end of the vector.
/// @param [in] size The size of the given C-style array.
void Push(const T* const value, const N size)
{
if (this->size + size >= rawSize)
{
if (stride)
{
rawSize = (this->size + size()) / stride * stride;
if ((this->size + size) % stride)
rawSize += stride;
}
else
{
rawSize = this->size + size;
}
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
}
for (N i = 0; i < size; ++i)
data[this->size + i] = value[i];
this->size += size;
}
/// Adds a given vector object at the end of the vector.
/// @param [in] value The given vector object to push to the end of the vector.
void Push(Vector<T> value)
{
if (size + value.size >= rawSize)
{
if (stride)
{
rawSize = (size + value.size) / stride * stride;
if ((size + value.size) % stride)
rawSize += stride;
}
else
{
rawSize = size + value.size;
}
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
}
for (N i = 0; i < value.size; ++i)
data[size + i] = std::move(value.data[i]);
size += value.size;
}
/// Adds a given initializer at the end of the vector.
/// @param [in] value The given initializer list to push to the end of the vector.
void Push(std::initializer_list<T> value)
{
if (size + value.size() >= rawSize)
{
if (stride)
{
rawSize = (size + value.size()) / stride * stride;
if ((size + value.size()) % stride)
rawSize += stride;
}
else
{
rawSize = size + value.size();
}
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
}
for (auto v = value.begin(); v != value.end(); ++v)
data[size++] = std::move(*v);
}
/// Adds a given value at the end of the vector.
/// @param [in] value The given value to push to the end of the vector.
void Push(T value)
{
if (size + 1 >= rawSize)
{
if (stride)
rawSize += stride;
else
rawSize = size + 1;
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
}
data[size++] = std::move(value);
}
/// Much like the stack it pops a value at the end of the vector.
/// @returns The removed data.
T Pop()
{
T popped = {};
if (!size)
return popped;
popped = std::move(data[--size]);
if (!stride)
{
rawSize = size;
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
}
else if (rawSize - stride && size < rawSize - stride)
{
rawSize -= stride;
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
}
return popped;
}
/// Resizes the vector while keeping its alignment.
/// @param [in] newSize The size to change to.
void Resize(const N newSize)
{
if (newSize == size)
return;
if (stride)
{
rawSize = newSize / stride * stride;
if (newSize % stride)
rawSize += stride;
}
else
{
rawSize = newSize;
}
T* result = new T[rawSize];
for (N i = 0; i < size && i < newSize; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
size = newSize;
}
/// Removes any extra allocated memory.
void ExactSize()
{
if (!stride)
return;
stride = 0;
if (size)
{
rawSize = size;
T* result = new T[rawSize];
for (N i = 0; i < size; ++i)
result[i] = std::move(data[i]);
delete[] data;
data = result;
}
else
{
rawSize = 0;
delete[] data;
data = nullptr;
}
}
/// Clears all values in the vector object.
void Clear()
{
if (!size)
return;
rawSize = stride;
size = 0;
delete[] data;
if (rawSize)
data = new T[rawSize];
else
data = nullptr;
}
};

68
src/Version.cpp Normal file
View File

@ -0,0 +1,68 @@
#include "Version.h"
Version::Version()
: major(0), minor(0), patch(0)
{
}
Version::Version(const unsigned int major, const unsigned int minor, const unsigned int patch)
: major(major), minor(minor), patch(patch)
{
}
Version::Version(const Version& version)
: major(version.major), minor(version.minor), patch(version.patch)
{
}
Version& Version::operator=(const Version& version)
{
if (this == &version)
return *this;
major = version.major;
minor = version.minor;
patch = version.patch;
return *this;
}
bool Version::operator==(const Version& version) const
{
return major == version.major && minor == version.minor && patch == version.patch;
}
bool Version::operator!=(const Version& version) const
{
return major != version.major || minor != version.minor || patch != version.patch;
}
unsigned int Version::operator[](const unsigned int i) const
{
switch (i)
{
case 0:
return major;
case 1:
return minor;
case 2:
return patch;
default:
return major;
}
}
unsigned int& Version::operator[](const unsigned int i)
{
switch (i)
{
case 0:
return major;
case 1:
return minor;
case 2:
return patch;
default:
return major;
}
}

36
src/Version.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
/// A helper class for storing version major, minor and patch.
class Version
{
public:
unsigned int major;
unsigned int minor;
unsigned int patch;
/// Default members initialization.
Version();
/// Initializes members with given major, minor and patch.
/// @param [in] major The major version.
/// @param [in] minor The minor version.
/// @param [in] patch The patch version.
Version(const unsigned int major, const unsigned int minor, const unsigned int patch);
/// Copies all members from the given version object.
/// @param [in] version The version object to copy from.
Version(const Version& version);
/// Copies all members from the given version object.
/// @param [in] version The version object to copy from.
/// @returns The version object that has been assigned to.
Version& operator=(const Version& version);
bool operator==(const Version& version) const;
bool operator!=(const Version& version) const;
unsigned int operator[](const unsigned int i) const;
unsigned int& operator[](const unsigned int i);
};

562
src/sys/CPU.cpp Normal file
View File

@ -0,0 +1,562 @@
#include "CPU.h"
#include "../Log.h"
#include "../IO/File.h"
#include "../Json/Json.h"
#include "Thread.h"
{
#ifdef OS_LINUX
UInt_64 CPU::TSC_Freq = 0;
#endif
Architecture CPU::GetArchitecture()
{
#if defined(ARCH_X64)
return Architecture::X64;
#elif defined(ARCH_ARM64)
return Architecture::ARM64;
#else
return Architecture::UNKNOWN;
#endif
}
UInt_8 CPU::PointerSize()
{
return sizeof(void*);
}
Endianness CPU::GetEndianness()
{
#if defined(LITTLE_ENDIAN)
return Endianness::LE;
#elif defined(BIG_ENDIAN)
return Endianness::BE;
#else
UInt_16 tmp = 1;
if (((Byte*)&tmp)[0] == 1)
return Endianness::LE;
return Endianness::BE;
#endif
}
UInt_64 CPU::GetTSC_Freq()
{
#if defined(OS_WINDOWS)
LARGE_INTEGER frequency = {};
QueryPerformanceFrequency(&frequency);
return frequency.QuadPart;
#elif defined(OS_LINUX)
if (!TSC_Freq)
TSC_Freq = RetrieveTSC_Freq();
return TSC_Freq;
#endif
return 0;
}
UInt_64 CPU::GetTSC()
{
#if defined(OS_WINDOWS)
LARGE_INTEGER count = {};
QueryPerformanceCounter(&count);
return count.QuadPart;
#elif defined(OS_LINUX)
TSC tsc;
RDTSCP(&tsc);
#if defined(ARCH_X64)
UInt_64 result = 0;
#if defined(LITTLE_ENDIAN)
((UInt_32*)&result)[0] = tsc.lowCount;
((UInt_32*)&result)[1] = tsc.highCount;
#elif defined(BIG_ENDIAN)
((UInt_32*)&result)[0] = tsc.highCount;
((UInt_32*)&result)[1] = tsc.lowCount;
#endif
return result;
#elif defined(ARCH_X86)
return tsc.lowPart;
#endif
#endif
return 0;
}
UInt_8 CPU::GetSteppingId()
{
return (UInt_8)GetInfoBits() & 0x00001111;
}
UInt_8 CPU::GetModelId()
{
return (UInt_8)GetInfoBits() & 0x11110000;
}
UInt_8 CPU::GetFamilyId()
{
return (UInt_8)(GetInfoBits() >> 8) & 0x00001111;
}
UInt_8 CPU::GetProcessorTypeId()
{
return (UInt_8)(GetInfoBits() >> 12) & 0x00000011;
}
UInt_8 CPU::GetExtModelId()
{
return (UInt_8)(GetInfoBits() >> 16) & 0x00001111;
}
UInt_8 CPU::GetExtFamilyId()
{
return (UInt_8)(GetInfoBits() >> 20);
}
bool CPU::HasFPU()
{
return GetFeatureBits_1() & 0b00000000000000000000000000000001;
}
bool CPU::HasVME()
{
return GetFeatureBits_1() & 0b00000000000000000000000000000010;
}
bool CPU::HasDE()
{
return GetFeatureBits_1() & 0b00000000000000000000000000000100;
}
bool CPU::HasPSE()
{
return GetFeatureBits_1() & 0b00000000000000000000000000001000;
}
bool CPU::HasTSC()
{
return GetFeatureBits_1() & 0b00000000000000000000000000010000;
}
bool CPU::HasMSR()
{
return GetFeatureBits_1() & 0b00000000000000000000000000100000;
}
bool CPU::HasPAE()
{
return GetFeatureBits_1() & 0b00000000000000000000000001000000;
}
bool CPU::HasMCE()
{
return GetFeatureBits_1() & 0b00000000000000000000000010000000;
}
bool CPU::HasCX8()
{
return GetFeatureBits_1() & 0b00000000000000000000000100000000;
}
bool CPU::HasAPIC()
{
return GetFeatureBits_1() & 0b00000000000000000000001000000000;
}
bool CPU::HasSEP()
{
return GetFeatureBits_1() & 0b00000000000000000000100000000000;
}
bool CPU::HasMTRR()
{
return GetFeatureBits_1() & 0b00000000000000000001000000000000;
}
bool CPU::HasPGE()
{
return GetFeatureBits_1() & 0b00000000000000000010000000000000;
}
bool CPU::HasMCA()
{
return GetFeatureBits_1() & 0b00000000000000000100000000000000;
}
bool CPU::HasCMOV()
{
return GetFeatureBits_1() & 0b00000000000000001000000000000000;
}
bool CPU::HasPAT()
{
return GetFeatureBits_1() & 0b00000000000000010000000000000000;
}
bool CPU::HasPSE_36()
{
return GetFeatureBits_1() & 0b00000000000000100000000000000000;
}
bool CPU::HasPSN()
{
return GetFeatureBits_1() & 0b00000000000001000000000000000000;
}
bool CPU::HasCLFSH()
{
return GetFeatureBits_1() & 0b00000000000010000000000000000000;
}
bool CPU::HasDS()
{
return GetFeatureBits_1() & 0b00000000001000000000000000000000;
}
bool CPU::HasACPI()
{
return GetFeatureBits_1() & 0b00000000010000000000000000000000;
}
bool CPU::HasMMX()
{
return GetFeatureBits_1() & 0b00000000100000000000000000000000;
}
bool CPU::HasFXSR()
{
return GetFeatureBits_1() & 0b00000001000000000000000000000000;
}
bool CPU::HasSSE()
{
return GetFeatureBits_1() & 0b00000010000000000000000000000000;
}
bool CPU::HasSSE2()
{
return GetFeatureBits_1() & 0b00000100000000000000000000000000;
}
bool CPU::HasSS()
{
return GetFeatureBits_1() & 0b00001000000000000000000000000000;
}
bool CPU::HasHTT()
{
return GetFeatureBits_1() & 0b00010000000000000000000000000000;
}
bool CPU::HasTM()
{
return GetFeatureBits_1() & 0b00100000000000000000000000000000;
}
bool CPU::HasIA64()
{
return GetFeatureBits_1() & 0b01000000000000000000000000000000;
}
bool CPU::HasPBE()
{
return GetFeatureBits_1() & 0b10000000000000000000000000000000;
}
bool CPU::HasSSE3()
{
return GetFeatureBits_2() & 0b00000000000000000000000000000001;
}
bool CPU::HasPCLMULQDQ()
{
return GetFeatureBits_2() & 0b00000000000000000000000000000010;
}
bool CPU::HasDTES64()
{
return GetFeatureBits_2() & 0b00000000000000000000000000000100;
}
bool CPU::HasMONITOR()
{
return GetFeatureBits_2() & 0b00000000000000000000000000001000;
}
bool CPU::HasDS_CPL()
{
return GetFeatureBits_2() & 0b00000000000000000000000000010000;
}
bool CPU::HasVMX()
{
return GetFeatureBits_2() & 0b00000000000000000000000000100000;
}
bool CPU::HasSMX()
{
return GetFeatureBits_2() & 0b00000000000000000000000001000000;
}
bool CPU::HasEST()
{
return GetFeatureBits_2() & 0b00000000000000000000000010000000;
}
bool CPU::HasTM2()
{
return GetFeatureBits_2() & 0b00000000000000000000000100000000;
}
bool CPU::HasSSSE3()
{
return GetFeatureBits_2() & 0b00000000000000000000001000000000;
}
bool CPU::HasCNXT_ID()
{
return GetFeatureBits_2() & 0b00000000000000000000010000000000;
}
bool CPU::HasSDBG()
{
return GetFeatureBits_2() & 0b00000000000000000000100000000000;
}
bool CPU::HasFMA()
{
return GetFeatureBits_2() & 0b00000000000000000001000000000000;
}
bool CPU::HasCX16()
{
return GetFeatureBits_2() & 0b00000000000000000010000000000000;
}
bool CPU::HasXTPR()
{
return GetFeatureBits_2() & 0b00000000000000000100000000000000;
}
bool CPU::HasPDCM()
{
return GetFeatureBits_2() & 0b00000000000000001000000000000000;
}
bool CPU::HasPCID()
{
return GetFeatureBits_2() & 0b00000000000000100000000000000000;
}
bool CPU::HasDCA()
{
return GetFeatureBits_2() & 0b00000000000001000000000000000000;
}
bool CPU::HasSSE4_1()
{
return GetFeatureBits_2() & 0b00000000000010000000000000000000;
}
bool CPU::HasSSE4_2()
{
return GetFeatureBits_2() & 0b00000000000100000000000000000000;
}
bool CPU::HasX2APIC()
{
return GetFeatureBits_2() & 0b00000000001000000000000000000000;
}
bool CPU::HasMOVBE()
{
return GetFeatureBits_2() & 0b00000000010000000000000000000000;
}
bool CPU::HasPOPCNT()
{
return GetFeatureBits_2() & 0b00000000100000000000000000000000;
}
bool CPU::HasTSC_DEADLINE()
{
return GetFeatureBits_2() & 0b00000001000000000000000000000000;
}
bool CPU::HasAES()
{
return GetFeatureBits_2() & 0b00000010000000000000000000000000;
}
bool CPU::HasXSAVE()
{
return GetFeatureBits_2() & 0b00000100000000000000000000000000;
}
bool CPU::HasOSXSAVE()
{
return GetFeatureBits_2() & 0b00001000000000000000000000000000;
}
bool CPU::HasAVX()
{
return GetFeatureBits_2() & 0b00010000000000000000000000000000;
}
bool CPU::HasF16C()
{
return GetFeatureBits_2() & 0b00100000000000000000000000000000;
}
bool CPU::HasRDRND()
{
return GetFeatureBits_2() & 0b01000000000000000000000000000000;
}
bool CPU::HasHYPERVISOR()
{
return GetFeatureBits_2() & 0b10000000000000000000000000000000;
}
bool CPU::HasAVX2()
{
return GetExtFeatureBits_1() & 0b00000000000000000000000000100000;
}
bool CPU::HasRDSEED()
{
return GetExtFeatureBits_1() & 0b00000000000001000000000000000000;
}
bool CPU::HasADX()
{
return GetExtFeatureBits_1() & 0b00000000000010000000000000000000;
}
/*
Str_8 CPU::ToStr()
{
return "Manufacturer: " + GetManufacturer() + "\r\n" +
"Brand: " + GetBrand() + "\r\n" +
"Stepping Id: " + Str_8::FromNum(GetSteppingId()) + "\r\n" +
"GpuModel Id: " + Str_8::FromNum(GetModelId()) + "\r\n" +
"Family Id: " + Str_8::FromNum(GetFamilyId()) + "\r\n" +
"Processor Type Id: " + Str_8::FromNum(GetProcessorTypeId()) + "\r\n" +
"Extended GpuModel Id: " + Str_8::FromNum(GetExtModelId()) + "\r\n" +
"Extended Family Id: " + Str_8::FromNum(GetExtFamilyId()) + "\r\n" +
"Has FPU: " + Str_8::FromNum((UInt_8)HasFPU()) + "\r\n" +
"Has SSE: " + Str_8::FromNum((UInt_8)HasSSE()) + "\r\n" +
"Has SSE 2: " + Str_8::FromNum((UInt_8)HasSSE2()) + "\r\n" +
"Has SSE 3: " + Str_8::FromNum((UInt_8)HasSSE3()) + "\r\n" +
"Has SSSE 3: " + Str_8::FromNum((UInt_8)HasSSSE3()) + "\r\n" +
"Has SSE 4.1: " + Str_8::FromNum((UInt_8)HasSSE4_1()) + "\r\n" +
"Has SSE 4.2: " + Str_8::FromNum((UInt_8)HasSSE4_2()) + "\r\n" +
"Has AVX: " + Str_8::FromNum((UInt_8)HasAVX()) + "\r\n" +
"Has RDRND: " + Str_8::FromNum((UInt_8)HasRDRND()) + "\r\n" +
"Has AVX 2: " + Str_8::FromNum((UInt_8)HasAVX2()) + "\r\n" +
"Has ADX: " + Str_8::FromNum((UInt_8)HasADX()) + "\r\n" +
"Has RDSEED: " + Str_8::FromNum((UInt_8)HasRDSEED());
}
*/
UInt_64 CPU::RetrieveTSC_Freq()
{
File tscDatabase("TSC_Frequencies.json", Mode::READ_WRITE, Disposition::CREATE_PERSISTENT);
if (tscDatabase.Size())
{
Json json(tscDatabase.ReadStr_8(tscDatabase.Size()), 5);
JsonObj* root = (JsonObj*)json.GetValue();
Char_8 manu[13];
manu[12] = 0;
GetManufacturer(manu);
JsonVar* jManu = root->GetVar(manu);
if (jManu)
{
JsonObj* joManu = (JsonObj*)jManu->GetValue();
Char_8 brand[49];
brand[48] = 0;
GetBrand(brand);
JsonVar* jBrand = joManu->GetVar(brand);
if (jBrand)
{
tscDatabase.Release();
return (UInt_64)*(JsonNum*)jBrand->GetValue();
}
else
{
UInt_64 tscFreq = CalculateTSC_Freq();
joManu->AddVar({brand, tscFreq});
tscDatabase.WriteStr_8(json.ToStr(false));
tscDatabase.Release();
return tscFreq;
}
}
else
{
UInt_64 tscFreq = CalculateTSC_Freq();
Char_8 brand[49];
brand[48] = 0;
GetBrand(brand);
JsonObj cpus(1, 0);
cpus[0] = JsonVar(brand, tscFreq);
JsonVar tmp({brand, cpus});
root->AddVar(tmp);
tscDatabase.WriteStr_8(json.ToStr(false));
tscDatabase.Release();
return tscFreq;
}
}
UInt_64 tscFreq = CalculateTSC_Freq();
Char_8 manu[13];
manu[12] = 0;
GetManufacturer(manu);
Char_8 brand[49];
brand[48] = 0;
GetBrand(brand);
JsonObj jManu(1, 0);
jManu[0] = JsonVar(brand, tscFreq);
JsonObj root(1, 0);
root[0] = JsonVar(manu, jManu);
Json json(root);
tscDatabase.WriteStr_8(json.ToStr(false));
tscDatabase.Release();
return tscFreq;
}
UInt_64 CPU::CalculateTSC_Freq()
{
UInt_64 result = GetTSC();
Thread::SleepFor(10000);
return (GetTSC() - result) / 10;
}
}

215
src/sys/CPU.h Normal file
View File

@ -0,0 +1,215 @@
#pragma once
#include "../EHS.h"
#include "../Str.h"
#include "../Array.h"
enum class Architecture : UInt_8
{
X64,
X86,
ARM64,
ARM,
UNKNOWN
};
enum class Endianness : UInt_8
{
LE,
BE
};
struct TSC
{
UInt_32 coreId = 0;
UInt_32 highCount = 0;
UInt_32 lowCount = 0;
};
class CPU
{
private:
#ifdef OS_LINUX
static UInt_64 TSC_Freq;
#endif
public:
static Architecture GetArchitecture();
static UInt_8 PointerSize();
static Endianness GetEndianness();
static void RDTSCP(TSC* tsc);
static UInt_64 GetTSC_Freq();
static UInt_64 GetTSC();
/// Retrieves the CPU manufacturer id as a null-terminated ASCII string.
/// @param[out] input A twelve byte character array representing the manufacturer id.
static void GetManufacturer(Char_8* input);
static UInt_32 GetInfoBits();
static UInt_8 GetSteppingId();
static UInt_8 GetModelId();
static UInt_8 GetFamilyId();
static UInt_8 GetProcessorTypeId();
static UInt_8 GetExtModelId();
static UInt_8 GetExtFamilyId();
static UInt_32 GetFeatureBits_1();
static bool HasFPU();
static bool HasVME();
static bool HasDE();
static bool HasPSE();
static bool HasTSC();
static bool HasMSR();
static bool HasPAE();
static bool HasMCE();
static bool HasCX8();
static bool HasAPIC();
static bool HasSEP();
static bool HasMTRR();
static bool HasPGE();
static bool HasMCA();
static bool HasCMOV();
static bool HasPAT();
static bool HasPSE_36();
static bool HasPSN();
static bool HasCLFSH();
static bool HasDS();
static bool HasACPI();
static bool HasMMX();
static bool HasFXSR();
static bool HasSSE();
static bool HasSSE2();
static bool HasSS();
static bool HasHTT();
static bool HasTM();
static bool HasIA64();
static bool HasPBE();
static UInt_32 GetFeatureBits_2();
static bool HasSSE3();
static bool HasPCLMULQDQ();
static bool HasDTES64();
static bool HasMONITOR();
static bool HasDS_CPL();
static bool HasVMX();
static bool HasSMX();
static bool HasEST();
static bool HasTM2();
static bool HasSSSE3();
static bool HasCNXT_ID();
static bool HasSDBG();
static bool HasFMA();
static bool HasCX16();
static bool HasXTPR();
static bool HasPDCM();
static bool HasPCID();
static bool HasDCA();
static bool HasSSE4_1();
static bool HasSSE4_2();
static bool HasX2APIC();
static bool HasMOVBE();
static bool HasPOPCNT();
static bool HasTSC_DEADLINE();
static bool HasAES();
static bool HasXSAVE();
static bool HasOSXSAVE();
static bool HasAVX();
static bool HasF16C();
static bool HasRDRND();
static bool HasHYPERVISOR();
static UInt_32 GetExtFeatureBits_1();
static bool HasAVX2();
static bool HasRDSEED();
static bool HasADX();
static UInt_32 GetExtFeatureBits_2();
static UInt_32 GetExtFeatureBits_3();
/// Retrieves the CPU brand as a null-terminated ASCII string.
/// @param[out] input A 48 byte character array representing the brand.
static void GetBrand(Char_8* input);
//static Str_8 ToStr();
private:
static UInt_64 RetrieveTSC_Freq();
static UInt_64 CalculateTSC_Freq();
};

132
src/sys/CPU_GCC_AMD64.asm Normal file
View File

@ -0,0 +1,132 @@
global _ZN3lwe3CPU6RDTSCPEPNS_3TSCE
global _ZN3lwe3CPU15GetManufacturerEPc
global _ZN3lwe3CPU11GetInfoBitsEv
global _ZN3lwe3CPU16GetFeatureBits_1Ev
global _ZN3lwe3CPU16GetFeatureBits_2Ev
global _ZN3lwe3CPU19GetExtFeatureBits_1Ev
global _ZN3lwe3CPU19GetExtFeatureBits_2Ev
global _ZN3lwe3CPU19GetExtFeatureBits_3Ev
global _ZN3lwe3CPU8GetBrandEPc
section .text
_ZN3lwe3CPU6RDTSCPEPNS_3TSCE:
RDTSCP
MOV DWORD [RDI], ECX
MOV DWORD [RDI + 4], EDX
MOV DWORD [RDI + 8], EAX
RET
_ZN3lwe3CPU15GetManufacturerEPc:
PUSH RBX
XOR EAX, EAX
CPUID
MOV DWORD [RDI], EBX
MOV DWORD [RDI + 4], EDX
MOV DWORD [RDI + 8], ECX
POP RBX
RET
_ZN3lwe3CPU11GetInfoBitsEv:
PUSH RBX
MOV EAX, 1
CPUID
POP RBX
RET
_ZN3lwe3CPU16GetFeatureBits_1Ev:
PUSH RBX
MOV EAX, 1
CPUID
MOV EAX, EDX
POP RBX
RET
_ZN3lwe3CPU16GetFeatureBits_2Ev:
PUSH RBX
MOV EAX, 1
CPUID
MOV EAX, ECX
POP RBX
RET
_ZN3lwe3CPU19GetExtFeatureBits_1Ev:
PUSH RBX
MOV EAX, 7
XOR ECX, ECX
CPUID
MOV EAX, EBX
POP RBX
RET
_ZN3lwe3CPU19GetExtFeatureBits_2Ev:
PUSH RBX
MOV EAX, 7
XOR ECX, ECX
CPUID
MOV EAX, ECX
POP RBX
RET
_ZN3lwe3CPU19GetExtFeatureBits_3Ev:
PUSH RBX
MOV EAX, 7
XOR ECX, ECX
CPUID
MOV EAX, EDX
POP RBX
RET
_ZN3lwe3CPU8GetBrandEPc:
PUSH RBX
MOV EAX, 80000002h
CPUID
MOV DWORD [RDI], EAX
MOV DWORD [RDI + 4], EBX
MOV DWORD [RDI + 8], ECX
MOV DWORD [RDI + 12], EDX
MOV EAX, 80000003h
CPUID
MOV DWORD [RDI + 16], EAX
MOV DWORD [RDI + 20], EBX
MOV DWORD [RDI + 24], ECX
MOV DWORD [RDI + 28], EDX
MOV EAX, 80000004h
CPUID
MOV DWORD [RDI + 32], EAX
MOV DWORD [RDI + 36], EBX
MOV DWORD [RDI + 40], ECX
MOV DWORD [RDI + 44], EDX
POP RBX
RET

127
src/sys/CPU_MSVC_AMD64.asm Normal file
View File

@ -0,0 +1,127 @@
global ?GetManufacturer@CPU@lwe@@SAXPEAD@Z
global ?GetInfoBits@CPU@lwe@@SAIXZ
global ?GetFeatureBits_1@CPU@lwe@@SAIXZ
global ?GetFeatureBits_2@CPU@lwe@@SAIXZ
global ?GetExtFeatureBits_1@CPU@lwe@@SAIXZ
global ?GetExtFeatureBits_2@CPU@lwe@@SAKXZ
global ?GetExtFeatureBits_3@CPU@lwe@@SAKXZ
global ?GetBrand@CPU@lwe@@SAXPEAD@Z
section .text
?GetManufacturer@CPU@lwe@@SAXPEAD@Z:
PUSH RBX
XOR EAX, EAX
MOV R8, RCX
CPUID
MOV DWORD [R8], EBX
MOV DWORD [R8 + 4], EDX
MOV DWORD [R8 + 8], ECX
POP RBX
RET
?GetInfoBits@CPU@lwe@@SAIXZ:
PUSH RBX
MOV EAX, 1
CPUID
POP RBX
RET
?GetFeatureBits_1@CPU@lwe@@SAIXZ:
PUSH RBX
MOV EAX, 1
CPUID
MOV EAX, EDX
POP RBX
RET
?GetFeatureBits_2@CPU@lwe@@SAIXZ:
PUSH RBX
MOV EAX, 1
CPUID
MOV EAX, ECX
POP RBX
RET
?GetExtFeatureBits_1@CPU@lwe@@SAIXZ:
PUSH RBX
MOV EAX, 7
XOR ECX, ECX
CPUID
MOV EAX, EBX
POP RBX
RET
?GetExtFeatureBits_2@CPU@lwe@@SAKXZ:
PUSH RBX
MOV EAX, 7
XOR ECX, ECX
CPUID
MOV EAX, ECX
POP RBX
RET
?GetExtFeatureBits_3@CPU@lwe@@SAKXZ:
PUSH RBX
MOV EAX, 7
XOR ECX, ECX
CPUID
MOV EAX, EDX
POP RBX
RET
?GetBrand@CPU@lwe@@SAXPEAD@Z:
PUSH RBX
MOV R8, RCX
MOV EAX, 80000002h
CPUID
MOV DWORD [R8], EAX
MOV DWORD [R8 + 4], EBX
MOV DWORD [R8 + 8], ECX
MOV DWORD [R8 + 12], EDX
MOV EAX, 80000003h
CPUID
MOV DWORD [R8 + 16], EAX
MOV DWORD [R8 + 20], EBX
MOV DWORD [R8 + 24], ECX
MOV DWORD [R8 + 28], EDX
MOV EAX, 80000004h
CPUID
MOV DWORD [R8 + 32], EAX
MOV DWORD [R8 + 36], EBX
MOV DWORD [R8 + 40], ECX
MOV DWORD [R8 + 44], EDX
POP RBX
RET