Merge pull request 'Tests & fixes for various parts of Math module' (#137) from tests_math into master

Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/137
Reviewed-by: Georg Hagen <georg.hagen@madvoxel.com>
This commit is contained in:
Vladyslav_Baranovskyi_EXT
2024-10-09 10:31:16 +02:00
13 changed files with 794 additions and 64 deletions

View File

@@ -10,6 +10,7 @@
#include <string>
#include <set>
#include <algorithm>
#include <array>
#include <bit>
#include <cassert>
#include <cinttypes>

View File

@@ -98,12 +98,12 @@ namespace OpenVulkano::Math
[[nodiscard]] bool InBounds(const Math::Vector3f& position) const
{
return Math::Utils::all(Math::Utils::greaterThanEqual(min, position)) && Math::Utils::all(Math::Utils::lessThanEqual(position, max));
return Math::Utils::all(Math::Utils::lessThanEqual(min, position)) && Math::Utils::all(Math::Utils::lessThanEqual(position, max));
}
[[nodiscard]] bool Inside(const Math::Vector3f& position) const
{
return Math::Utils::all(Math::Utils::greaterThan(min, position)) && Math::Utils::all(Math::Utils::lessThan(position, max));
return Math::Utils::all(Math::Utils::lessThan(min, position)) && Math::Utils::all(Math::Utils::lessThan(position, max));
}
[[nodiscard]] bool IsEmpty() const

View File

@@ -134,9 +134,9 @@ namespace OpenVulkano
operator std::string() const { return Format(); }
ByteSize operator +(const ByteSize other) const { return bytes + other.bytes; }
ByteSize operator -(const ByteSize other) const { return bytes + other.bytes; }
ByteSize operator -(const ByteSize other) const { return bytes - other.bytes; }
ByteSize operator +(const size_t other) const { return bytes + other; }
ByteSize operator -(const size_t other) const { return bytes + other; }
ByteSize operator -(const size_t other) const { return bytes - other; }
ByteSize& operator =(const size_t other) { bytes = other; return *this; }
ByteSize& operator =(const ByteSize other) { bytes = other.bytes; return *this; }
ByteSize& operator +=(const size_t other) { bytes += other; return *this; }

View File

@@ -149,7 +149,7 @@ namespace OpenVulkano::Math
[[nodiscard]] constexpr bool operator !=(DenseVec3 rhs) const
{
return data == rhs.data;
return data != rhs.data;
}
[[nodiscard]] explicit constexpr operator Math::Vector3i() const

View File

@@ -30,21 +30,21 @@ namespace OpenVulkano::Math
RGB10A2(TYPE value = 0) : value(value) {}
template<typename T, typename = std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<TYPE>>>
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
void Set(Vector3<T> vec3)
{
vec3 &= VALUE_BITMASK;
SetUnchecked(vec3);
}
template<typename T, typename = std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<TYPE>>>
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
void Set(Vector3_SIMD<T> vec3)
{
vec3 &= VALUE_BITMASK;
SetUnchecked(vec3);
}
template<typename T, typename = std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<TYPE>>>
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
void Set(Vector4<T> vec4)
{
vec4 &= VALUE_BITMASK;
@@ -69,19 +69,19 @@ namespace OpenVulkano::Math
Set(Math::Vector4<TYPE>(vec4));
}
template<typename T, typename = std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<TYPE>>>
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
void const SetUnchecked(Vector3<T>& vec3)
{
value = vec3.r | vec3.g << 10 | vec3.b << 20 | MAX_ALPHA_VALUE << 30;
}
template<typename T, typename = std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<TYPE>>>
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
void SetUnchecked(const Vector3_SIMD<T>& vec3)
{
value = vec3.r | vec3.g << 10 | vec3.b << 20 | MAX_ALPHA_VALUE << 30;
}
template<typename T, typename = std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<TYPE>>>
template<typename T, typename = std::enable_if_t<std::is_integral_v<TYPE>>>
void SetUnchecked(const Vector4<T>& vec4)
{
value = vec4.r | vec4.g << 10 | vec4.b << 20 | vec4.a << 30;

View File

@@ -18,79 +18,61 @@ namespace OpenVulkano::Math
uint64_t timestamp;
public:
explicit Timestamp(uint64_t nanos = 0) : timestamp(nanos) {}
explicit Timestamp(double seconds) : timestamp(static_cast<uint64_t>(seconds * SECONDS_TO_NANOS)) {}
explicit constexpr Timestamp(uint64_t nanos = 0) : timestamp(nanos) {}
explicit constexpr Timestamp(double seconds) : timestamp(static_cast<uint64_t>(seconds * SECONDS_TO_NANOS)) {}
[[nodiscard]] uint64_t GetNanos() const { return timestamp; }
[[nodiscard]] double GetSeconds() const { return timestamp * NANOS_TO_SECONDS; }
[[nodiscard]] constexpr uint64_t GetNanos() const { return timestamp; }
[[nodiscard]] constexpr double GetSeconds() const { return timestamp * NANOS_TO_SECONDS; }
Timestamp& operator+=(const Timestamp& rhs)
constexpr Timestamp& operator+=(const Timestamp& rhs)
{
timestamp += rhs.timestamp;
return *this;
}
Timestamp& operator-=(const Timestamp& rhs)
constexpr Timestamp& operator-=(const Timestamp& rhs)
{
timestamp -= rhs.timestamp;
return *this;
}
Timestamp& operator =(double time)
constexpr Timestamp& operator =(double time)
{
timestamp = Timestamp(time).timestamp;
return *this;
}
Timestamp& operator =(uint64_t time)
constexpr Timestamp& operator =(uint64_t time)
{
timestamp = time;
return *this;
}
constexpr inline bool operator==(const Timestamp& rhs) const { return GetNanos() == rhs.GetNanos(); }
constexpr inline bool operator!=(const Timestamp& rhs) const { return !(*this == rhs); }
constexpr inline bool operator<(const Timestamp& rhs) const { return GetNanos() < rhs.GetNanos(); }
constexpr inline bool operator>(const Timestamp& rhs) const { return rhs < *this; }
constexpr inline bool operator>=(const Timestamp& rhs) const { return !(*this < rhs); }
constexpr inline bool operator<=(const Timestamp& rhs) const { return !(rhs < *this); }
constexpr inline Timestamp operator-(const Timestamp& rhs) const
{
return Timestamp(GetNanos() - rhs.GetNanos());
}
constexpr inline Timestamp operator+(const Timestamp& rhs) const
{
return Timestamp(GetNanos() + rhs.GetNanos());
}
constexpr inline double operator/(const Timestamp& rhs) const
{
return GetNanos() / static_cast<double>(rhs.GetNanos());
}
};
inline bool operator==(const Timestamp& lhs, const Timestamp& rhs)
{
return lhs.GetNanos() == rhs.GetNanos();
}
inline bool operator!=(const Timestamp& lhs, const Timestamp& rhs)
{
return !(lhs == rhs);
}
inline bool operator<(const Timestamp& lhs, const Timestamp& rhs)
{
return lhs.GetNanos() < rhs.GetNanos();
}
inline bool operator>(const Timestamp& lhs, const Timestamp& rhs)
{
return rhs < lhs;
}
inline bool operator>=(const Timestamp& lhs, const Timestamp& rhs)
{
return !(lhs < rhs);
}
inline bool operator<=(const Timestamp& lhs, const Timestamp& rhs)
{
return !(rhs < lhs);
}
inline Timestamp operator-(const Timestamp& lhs, const Timestamp& rhs)
{
return Timestamp(lhs.GetNanos() - rhs.GetNanos());
}
inline Timestamp operator+(const Timestamp& lhs, const Timestamp& rhs)
{
return Timestamp(lhs.GetNanos() + rhs.GetNanos());
}
inline double operator/(const Timestamp& lhs, const Timestamp& rhs)
{
return lhs.GetNanos() / static_cast<double>(rhs.GetNanos());
}
}

156
tests/Math/AABB.cpp Normal file
View File

@@ -0,0 +1,156 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <catch2/catch_all.hpp>
#include "Math/Math.hpp"
#include "Math/AABB.hpp"
using namespace OpenVulkano::Math;
TEST_CASE("Default Constructor", "[AABB]")
{
AABB aabb;
REQUIRE(aabb.GetMin() == Vector3f(INFINITY));
REQUIRE(aabb.GetMax() == Vector3f(-INFINITY));
}
TEST_CASE("Constructor with min and max", "[AABB]")
{
Vector3f min(1.0f, 2.0f, 3.0f);
Vector3f max(4.0f, 5.0f, 6.0f);
AABB aabb(min, max);
REQUIRE(aabb.GetMin() == min);
REQUIRE(aabb.GetMax() == max);
}
TEST_CASE("Constructor with single point", "[AABB]")
{
Vector3f point(1.0f, 2.0f, 3.0f);
AABB aabb(point);
REQUIRE(aabb.GetMin() == point);
REQUIRE(aabb.GetMax() == point);
}
TEST_CASE("Constructor with point and radius", "[AABB]")
{
Vector3f point(1.0f, 2.0f, 3.0f);
float radius = 1.0f;
AABB aabb(point, radius);
REQUIRE(aabb.GetMin() == (point - radius));
REQUIRE(aabb.GetMax() == (point + radius));
}
TEST_CASE("Init with single point", "[AABB]")
{
AABB aabb;
Vector3f point(1.0f, 2.0f, 3.0f);
aabb.Init(point);
REQUIRE(aabb.GetMin() == point);
REQUIRE(aabb.GetMax() == point);
}
TEST_CASE("Init with min and max", "[AABB]")
{
AABB aabb;
Vector3f min(1.0f, 2.0f, 3.0f);
Vector3f max(4.0f, 5.0f, 6.0f);
aabb.Init(min, max);
REQUIRE(aabb.GetMin() == min);
REQUIRE(aabb.GetMax() == max);
}
TEST_CASE("Init with point and radius", "[AABB]")
{
AABB aabb;
Vector3f point(1.0f, 2.0f, 3.0f);
float radius = 1.0f;
aabb.Init(point, radius);
REQUIRE(aabb.GetMin() == (point - radius));
REQUIRE(aabb.GetMax() == (point + radius));
}
TEST_CASE("Grow with point", "[AABB]")
{
AABB aabb(Vector3f(0.0f), Vector3f(1.0f));
Vector3f point(2.0f, 3.0f, 4.0f);
aabb.Grow(point);
REQUIRE(aabb.GetMin() == Vector3f(0.0f, 0.0f, 0.0f));
REQUIRE(aabb.GetMax() == point);
}
TEST_CASE("Grow with AABB", "[AABB]")
{
AABB aabb1(Vector3f(0.0f), Vector3f(1.0f));
AABB aabb2(Vector3f(-1.0f), Vector3f(2.0f));
aabb1.Grow(aabb2);
REQUIRE(aabb1.GetMin() == Vector3f(-1.0f));
REQUIRE(aabb1.GetMax() == Vector3f(2.0f));
}
TEST_CASE("GetDiagonal", "[AABB]")
{
AABB aabb(Vector3f(0.0f), Vector3f(1.0f));
REQUIRE(aabb.GetDiagonal() == Vector3f(1.0f));
}
TEST_CASE("GetCenter", "[AABB]")
{
AABB aabb(Vector3f(0.0f), Vector3f(2.0f));
REQUIRE(aabb.GetCenter() == Vector3f(1.0f));
}
TEST_CASE("IsOverlapping", "[AABB]")
{
AABB aabb1(Vector3f(0.0f), Vector3f(1.0f));
AABB aabb2(Vector3f(0.5f), Vector3f(1.5f));
REQUIRE(aabb1.IsOverlapping(aabb2));
AABB aabb3(Vector3f(2.0f), Vector3f(3.0f));
REQUIRE_FALSE(aabb1.IsOverlapping(aabb3));
}
TEST_CASE("InBounds", "[AABB]")
{
AABB aabb(Vector3f(0.0f), Vector3f(1.0f));
REQUIRE(aabb.InBounds(Vector3f(0.5f)));
REQUIRE(aabb.InBounds(Vector3f(0.0f)));
REQUIRE(aabb.InBounds(Vector3f(1.0f)));
REQUIRE_FALSE(aabb.InBounds(Vector3f(1.1f)));
REQUIRE_FALSE(aabb.InBounds(Vector3f(-0.1f)));
REQUIRE_FALSE(aabb.InBounds(Vector3f(2.0f)));
}
TEST_CASE("Inside", "[AABB]")
{
AABB aabb(Vector3f(0.0f), Vector3f(1.0f));
REQUIRE(aabb.Inside(Vector3f(0.5f)));
REQUIRE_FALSE(aabb.Inside(Vector3f(0.0f)));
REQUIRE_FALSE(aabb.Inside(Vector3f(1.0f)));
REQUIRE_FALSE(aabb.Inside(Vector3f(1.1f)));
REQUIRE_FALSE(aabb.Inside(Vector3f(-0.1f)));
REQUIRE_FALSE(aabb.Inside(Vector3f(1.0f)));
}
TEST_CASE("IsEmpty", "[AABB]")
{
AABB aabb;
REQUIRE(aabb.IsEmpty());
aabb.Init(Vector3f(0.0f), Vector3f(1.0f));
REQUIRE_FALSE(aabb.IsEmpty());
}
TEST_CASE("Reset", "[AABB]")
{
AABB aabb(Vector3f(0.0f), Vector3f(1.0f));
aabb.Reset();
REQUIRE(aabb.IsEmpty());
}

131
tests/Math/ByteSize.cpp Normal file
View File

@@ -0,0 +1,131 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <catch2/catch_all.hpp>
#include <cmath>
#include "Math/ByteSize.hpp"
using namespace OpenVulkano;
namespace
{
bool almostEqual(float a, float b, float epsilon = 0.001f) { return std::fabs(a - b) < epsilon; }
}
TEST_CASE("BuildFactors and BuildDivisors", "[ByteSize]")
{
constexpr auto factors = ByteSizeUnitHelper::BuildFactors();
constexpr auto divisors = ByteSizeUnitHelper::BuildDivisors();
REQUIRE(factors.size() == 13);
REQUIRE(factors[0] == 1);
REQUIRE(factors[1] == (1uLL << 10)); // KiB
REQUIRE(factors[6] == (1uLL << 60)); // EiB
REQUIRE(factors[7] == 1000); // kB
REQUIRE(factors[12] == 1'000'000'000'000'000'000); // EB
REQUIRE(divisors.size() == 13);
REQUIRE(almostEqual(divisors[0], 1.0));
REQUIRE(almostEqual(divisors[1], 1.0 / (1uLL << 10))); // KiB
REQUIRE(almostEqual(divisors[12], 1.0 / 1'000'000'000'000'000'000)); // EB
}
TEST_CASE("GetFactor, GetDivisor, and GetName", "[ByteSize]")
{
ByteSizeUnit kib(ByteSizeUnit::kiB);
ByteSizeUnit gb(ByteSizeUnit::GB);
REQUIRE(kib.GetFactor() == (1uLL << 10)); // KiB
REQUIRE(almostEqual(kib.GetDivisor(), 1.0 / (1uLL << 10)));
REQUIRE(kib.GetName() == "kiB");
REQUIRE(gb.GetFactor() == 1'000'000'000); // GB
REQUIRE(almostEqual(gb.GetDivisor(), 1.0 / 1'000'000'000));
REQUIRE(gb.GetName() == "GB");
}
TEST_CASE("FromName and GetClosestUnit", "[ByteSize]")
{
auto kib = ByteSizeUnit::FromName("kiB");
auto tb = ByteSizeUnit::FromName("TB");
REQUIRE(kib.GetFactor() == (1uLL << 10));
REQUIRE(tb.GetFactor() == 1'000'000'000'000);
uint64_t size1 = 2 * 1'000'000'000;
uint64_t size2 = 3 * (1uLL << 40);
ByteSizeUnit unit1 = ByteSizeUnit::GetClosestUnit(size1, true); // SI
ByteSizeUnit unit2 = ByteSizeUnit::GetClosestUnit(size2, false); // Binary
REQUIRE(unit1.GetName() == "GB");
REQUIRE(unit2.GetName() == "TiB");
}
TEST_CASE("Constructors and parsing from string", "[ByteSize]")
{
ByteSize size1(1'024, ByteSizeUnit(ByteSizeUnit::kiB));
ByteSize size2("1.5 MiB");
REQUIRE(static_cast<uint64_t>(size1) == 1'024 * (1uLL << 10));
REQUIRE(almostEqual(static_cast<uint64_t>(size2), 1.5 * (1uLL << 20)));
REQUIRE_THROWS_AS(ByteSize("invalid size"), std::runtime_error);
}
TEST_CASE("Formatting", "[ByteSize]")
{
ByteSize size2(1'024 + 512, ByteSizeUnit(ByteSizeUnit::kiB)); // This is 1.5 MiB
REQUIRE(size2.Format(true) == "1.57 MB");
REQUIRE(size2.Format(false) == "1.5 MiB");
}
TEST_CASE("Operator overloads", "[ByteSize]")
{
ByteSize size1(1'024, ByteSizeUnit(ByteSizeUnit::kiB));
ByteSize size2(512, ByteSizeUnit(ByteSizeUnit::kiB));
ByteSize result = size1 + size2;
REQUIRE(static_cast<uint64_t>(result) == (1'024 + 512) * (1uLL << 10));
result = size1 - size2;
REQUIRE(static_cast<uint64_t>(result) == (1'024 - 512) * (1uLL << 10));
size1 += size2;
REQUIRE(static_cast<uint64_t>(size1) == (1'024 + 512) * (1uLL << 10));
}
TEST_CASE("Literals", "[ByteSize]")
{
REQUIRE(static_cast<uint64_t>(1.0_kiB) == 1uLL << 10);
REQUIRE(static_cast<uint64_t>(1.0_MiB) == 1uLL << 20);
REQUIRE(static_cast<uint64_t>(1.0_GiB) == 1uLL << 30);
REQUIRE(static_cast<uint64_t>(1.0_TiB) == 1uLL << 40);
REQUIRE(static_cast<uint64_t>(1.0_PiB) == 1uLL << 50);
REQUIRE(static_cast<uint64_t>(1.0_EiB) == 1uLL << 60);
REQUIRE(static_cast<uint64_t>(1.0_kB) == 1'000);
REQUIRE(static_cast<uint64_t>(1.0_MB) == 1'000'000);
REQUIRE(static_cast<uint64_t>(1.0_GB) == 1'000'000'000);
REQUIRE(static_cast<uint64_t>(1.0_TB) == 1'000'000'000'000);
REQUIRE(static_cast<uint64_t>(1.0_PB) == 1'000'000'000'000'000);
REQUIRE(static_cast<uint64_t>(1.0_EB) == 1'000'000'000'000'000'000);
REQUIRE(static_cast<uint64_t>(1_kiB) == 1uLL << 10);
REQUIRE(static_cast<uint64_t>(1_MiB) == 1uLL << 20);
REQUIRE(static_cast<uint64_t>(1_GiB) == 1uLL << 30);
REQUIRE(static_cast<uint64_t>(1_TiB) == 1uLL << 40);
REQUIRE(static_cast<uint64_t>(1_PiB) == 1uLL << 50);
REQUIRE(static_cast<uint64_t>(1_EiB) == 1uLL << 60);
REQUIRE(static_cast<uint64_t>(1_kB) == 1'000);
REQUIRE(static_cast<uint64_t>(1_MB) == 1'000'000);
REQUIRE(static_cast<uint64_t>(1_GB) == 1'000'000'000);
REQUIRE(static_cast<uint64_t>(1_TB) == 1'000'000'000'000);
REQUIRE(static_cast<uint64_t>(1_PB) == 1'000'000'000'000'000);
REQUIRE(static_cast<uint64_t>(1_EB) == 1'000'000'000'000'000'000);
}

View File

@@ -0,0 +1,80 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <catch2/catch_all.hpp>
#include "Math/DenseVector3i.hpp"
using namespace OpenVulkano::Math;
TEST_CASE("Constructor and Accessors", "[DenseVector3i]")
{
Vector3i vec3 { 10, 20, 30 };
DenseVector3i<int32_t> denseVec(vec3);
REQUIRE(denseVec.X() == 10);
REQUIRE(denseVec.Y() == 20);
REQUIRE(denseVec.Z() == 30);
auto data = denseVec.Data();
REQUIRE(data != 0);
}
TEST_CASE("Setters", "[DenseVector3i]")
{
DenseVector3i<int32_t> denseVec(10, 20, 30);
denseVec.SetX(40);
REQUIRE(denseVec.X() == 40);
denseVec.SetY(50);
REQUIRE(denseVec.Y() == 50);
denseVec.SetZ(60);
REQUIRE(denseVec.Z() == 60);
}
TEST_CASE("Comparison Operators", "[DenseVector3i]")
{
DenseVector3i<int32_t> denseVec1(10, 20, 30);
DenseVector3i<int32_t> denseVec2(10, 20, 30);
DenseVector3i<int32_t> denseVec3(40, 50, 60);
REQUIRE(denseVec1 == denseVec2);
REQUIRE(denseVec1 != denseVec3);
REQUIRE(denseVec1 < denseVec3);
REQUIRE(denseVec3 > denseVec1);
REQUIRE(denseVec1 <= denseVec2);
REQUIRE(denseVec1 <= denseVec3);
REQUIRE(denseVec1 >= denseVec2);
REQUIRE(denseVec3 >= denseVec1);
}
TEST_CASE("ToString method", "[DenseVector3i]")
{
DenseVector3i<int32_t> denseVec(10, 20, 30);
REQUIRE(denseVec.ToString() == fmt::format("{},{},{}", 10, 20, 30));
REQUIRE(denseVec.ToString(" ") == "10 20 30");
}
TEST_CASE("Type Conversion", "[DenseVector3i]")
{
DenseVector3i<int32_t> denseVec(10, 20, 30);
Vector3i vec3 = static_cast<Vector3i>(denseVec);
REQUIRE(vec3.x == 10);
REQUIRE(vec3.y == 20);
REQUIRE(vec3.z == 30);
Vector3i_SIMD vec3_simd = static_cast<Vector3i_SIMD>(denseVec);
REQUIRE(vec3_simd.x == 10);
REQUIRE(vec3_simd.y == 20);
REQUIRE(vec3_simd.z == 30);
}

110
tests/Math/Int24.cpp Normal file
View File

@@ -0,0 +1,110 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <catch2/catch_all.hpp>
#include "Math/Int24.hpp"
using namespace OpenVulkano;
TEST_CASE("Default constructor", "[Int24]")
{
int24 a;
REQUIRE(static_cast<int>(a) == 0);
}
TEST_CASE("Integer constructor", "[Int24]")
{
int24 a(0x123456);
REQUIRE(static_cast<int>(a) == 0x123456);
int24 b(-1);
REQUIRE(static_cast<int>(b) == -1);
}
TEST_CASE("Copy constructor", "[Int24]")
{
int24 a(0x123456);
int24 b(a);
REQUIRE(static_cast<int>(b) == 0x123456);
}
TEST_CASE("Assignment operator", "[Int24]")
{
int24 a;
a = 0x123456;
REQUIRE(static_cast<int>(a) == 0x123456);
int24 b;
b = a;
REQUIRE(static_cast<int>(b) == 0x123456);
}
TEST_CASE("Arithmetic operators", "[Int24]")
{
int24 a(0x10);
int24 b(0x20);
REQUIRE(static_cast<int>(a + b) == 0x30);
REQUIRE(static_cast<int>(b - a) == 0x10);
REQUIRE(static_cast<int>(a * b) == 0x200);
REQUIRE(static_cast<int>(b / a) == 2);
}
TEST_CASE("Compound assignment operators", "[Int24]")
{
int24 a(0x10);
int24 b(0x20);
a += b;
REQUIRE(static_cast<int>(a) == 0x30);
a -= b;
REQUIRE(static_cast<int>(a) == 0x10);
a *= b;
REQUIRE(static_cast<int>(a) == 0x200);
a /= b;
REQUIRE(static_cast<int>(a) == 0x10);
}
TEST_CASE("Comparison operators", "[Int24]")
{
int24 a(0x100000);
int24 b(0x200000);
REQUIRE(a < b);
REQUIRE(b > a);
REQUIRE(a <= b);
REQUIRE(b >= a);
REQUIRE(a != b);
int24 c(0x100000);
REQUIRE(a == c);
}
TEST_CASE("Shift operators", "[Int24]")
{
int24 a(0x123456);
REQUIRE(static_cast<int>(a << 1) == 0x2468ac);
REQUIRE(static_cast<int>(a >> 1) == 0x91a2b);
}
TEST_CASE("Boolean operators", "[Int24]")
{
int24 a(0);
int24 b(1);
REQUIRE(!a);
REQUIRE(b);
}
TEST_CASE("Negation", "[Int24]")
{
int24 a(0x123456);
REQUIRE(static_cast<int>(-a) == -0x123456);
}

134
tests/Math/RGB10A2.cpp Normal file
View File

@@ -0,0 +1,134 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <catch2/catch_all.hpp>
#include "Math/RGB10A2.hpp"
using namespace OpenVulkano::Math;
namespace
{
bool almostEqual(float a, float b, float epsilon = 0.001f) { return std::fabs(a - b) < epsilon; }
}
TEST_CASE("Default Constructor", "[RGB10A2U]")
{
RGB10A2U color;
REQUIRE(color.value == 0);
}
TEST_CASE("Set Method with Vector3", "[RGB10A2U]")
{
RGB10A2U color;
Vector3<uint32_t> vec3 { 1000, 500, 250 };
color.Set(vec3);
REQUIRE(color.r == 1000);
REQUIRE(color.g == 500);
REQUIRE(color.b == 250);
REQUIRE(color.a == 3);
}
TEST_CASE("Set Method with Vector4", "[RGB10A2U]")
{
RGB10A2U color;
Vector4<uint32_t> vec4 { 1000, 500, 250, 1 };
color.Set(vec4);
REQUIRE(color.r == 1000);
REQUIRE(color.g == 500);
REQUIRE(color.b == 250);
REQUIRE(color.a == 1);
}
TEST_CASE("SetNormalized Method with Vector3", "[RGB10A2U]")
{
RGB10A2U color;
Vector3<float> vec3 { 0.5f, 0.25f, 0.125f };
color.SetNormalized(vec3);
REQUIRE(color.r == int(0.5 * 1023));
REQUIRE(color.g == int(0.25 * 1023));
REQUIRE(color.b == int(0.125 * 1023));
REQUIRE(color.a == 3);
}
TEST_CASE("Equality Operators", "[RGB10A2U]")
{
RGB10A2U color;
RGB10A2U color2 { color };
REQUIRE(color == color2);
color2.r = 1;
REQUIRE(color != color2);
}
TEST_CASE("Conversion to Vector4", "[RGB10A2U]")
{
RGB10A2U color;
color.Set(Vector4<uint32_t> { 1000, 500, 250, 2 });
Vector4f vec4 = color;
REQUIRE(almostEqual(vec4.x, 1000.0f / 1023.0f));
REQUIRE(almostEqual(vec4.y, 500.0f / 1023.0f));
REQUIRE(almostEqual(vec4.z, 250.0f / 1023.0f));
REQUIRE(almostEqual(vec4.w, 2.0f / 3.0f));
}
TEST_CASE("Default Constructor", "[RGB10A2S]")
{
RGB10A2S color;
REQUIRE(color.value == 0);
}
TEST_CASE("Set Method with Vector3", "[RGB10A2S]")
{
RGB10A2S color;
Vector3<int32_t> vec3 { 1000, 500, 250 };
color.Set(vec3);
REQUIRE(color.r == -24);
REQUIRE(color.g == 500);
REQUIRE(color.b == 250);
REQUIRE(color.a == 1);
}
TEST_CASE("Set Method with Vector4", "[RGB10A2S]")
{
RGB10A2S color;
Vector4<int32_t> vec4 { 1000, 500, 250, 1 };
color.Set(vec4);
REQUIRE(color.r == -24); // because it is RGB10A2S
REQUIRE(color.g == 500);
REQUIRE(color.b == 250);
REQUIRE(color.a == 1);
}
TEST_CASE("SetNormalized Method with Vector3", "[RGB10A2S]")
{
RGB10A2S color;
Vector3<float> vec3 { 0.5f, 0.25f, 0.125f };
color.SetNormalized(vec3);
REQUIRE(color.r == 255); // because it is RGB10A2S
REQUIRE(color.g == 127); // because it is RGB10A2S
REQUIRE(color.b == 63); // because it is RGB10A2S
REQUIRE(color.a == 1); // because it is RGB10A2S
}
TEST_CASE("Equality Operators", "[RGB10A2S]")
{
RGB10A2S color;
RGB10A2S color2 { color };
REQUIRE(color == color2);
color2.r = 1;
REQUIRE(color != color2);
}
TEST_CASE("Conversion to Vector4", "[RGB10A2S]")
{
RGB10A2S color;
color.Set(Vector4<int32_t> { 1000, 500, 250, 2 });
Vector4f vec4 = color;
REQUIRE(almostEqual(vec4.x, -0.0469667315)); // because the type is Signed. Ugh!
REQUIRE(almostEqual(vec4.y, 0.978474)); // because the type is Signed. Ugh!
REQUIRE(almostEqual(vec4.z, 0.489237)); // because the type is Signed. Ugh!
REQUIRE(almostEqual(vec4.w, -2.0f)); // because the type is Signed. Ugh!
}

57
tests/Math/Range.cpp Normal file
View File

@@ -0,0 +1,57 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <catch2/catch_all.hpp>
#include "Math/Range.hpp"
using namespace OpenVulkano::Math;
using RangeType = Range<int>;
// The class does not have a default constructor... So rely on warnings about unitialized members
TEST_CASE("Parameterized constructor", "[Range]")
{
int min = 10;
int max = 20;
RangeType range(min, max);
REQUIRE(range.GetMin() == min);
REQUIRE(range.GetMax() == max);
}
TEST_CASE("GetMin and GetMax", "[Range]")
{
int min = 10;
int max = 20;
RangeType range(min, max);
// Test const-qualified access
const RangeType& constRange = range;
REQUIRE(constRange.GetMin() == min);
REQUIRE(constRange.GetMax() == max);
// Test non-const access
range.GetMin() = 30;
range.GetMax() = 40;
REQUIRE(range.GetMin() == 30);
REQUIRE(range.GetMax() == 40);
}
TEST_CASE("GetSize", "[Range]")
{
int min = 10;
int max = 20;
RangeType range(min, max);
REQUIRE(range.GetSize() == 10);
}
TEST_CASE("GetSize with negative", "[Range]")
{
int min = -10;
int max = 10;
RangeType range(min, max);
REQUIRE(range.GetSize() == 20);
}

79
tests/Math/Timestamp.cpp Normal file
View File

@@ -0,0 +1,79 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <catch2/catch_all.hpp>
#include "Math/Timestamp.hpp"
using namespace OpenVulkano::Math;
TEST_CASE("Constructors", "[Timestamp]")
{
Timestamp ts;
REQUIRE(ts.GetNanos() == 0);
REQUIRE(ts.GetSeconds() == 0.0);
ts = Timestamp((uint64_t)1'000'000'000ull); // 1 second
REQUIRE(ts.GetNanos() == 1'000'000'000ull);
REQUIRE(ts.GetSeconds() == 1.0);
ts = Timestamp(2.5); // 2.5 seconds
REQUIRE(ts.GetNanos() == 2'500'000'000ull);
REQUIRE(ts.GetSeconds() == 2.5);
}
TEST_CASE("Arithmetic operations", "[Timestamp]")
{
Timestamp ts1((uint64_t)1'000'000'000ull); // 1 second
Timestamp ts2((uint64_t)2'000'000'000ull); // 2 seconds
Timestamp result;
result = ts1 + ts2;
REQUIRE(result.GetNanos() == 3'000'000'000ull);
result = ts2 - ts1;
REQUIRE(result.GetNanos() == 1'000'000'000ull);
ts1 += ts2;
REQUIRE(ts1.GetNanos() == 3'000'000'000ull);
ts1 -= ts2;
ts1 -= ts2; // Wraps around
REQUIRE(ts1.GetNanos() > 0);
}
TEST_CASE("Comparison operators", "[Timestamp]")
{
Timestamp ts1((uint64_t)1'000'000'000ull); // 1 second
Timestamp ts2((uint64_t)2'000'000'000ull); // 2 seconds
Timestamp ts3((uint64_t)1'000'000'000ull);
REQUIRE(ts1 == ts3);
REQUIRE(ts1 != ts2);
REQUIRE(ts1 < ts2);
REQUIRE(ts2 > ts1);
REQUIRE(ts1 <= ts3);
REQUIRE(ts2 >= ts1);
}
TEST_CASE("Assignment operators", "[Timestamp]")
{
Timestamp ts;
ts = (uint64_t)1'000'000'000ull;
REQUIRE(ts.GetNanos() == 1'000'000'000ull);
ts = 2.0;
REQUIRE(ts.GetNanos() == 2'000'000'000ull);
}
TEST_CASE("Division operator", "[Timestamp]")
{
Timestamp ts1(2.0);
Timestamp ts2(1.0);
double result = ts1 / ts2;
REQUIRE(result == 2.0);
}