diff --git a/openVulkanoCpp/Base/Utils.hpp b/openVulkanoCpp/Base/Utils.hpp index 3b8f880..0999241 100644 --- a/openVulkanoCpp/Base/Utils.hpp +++ b/openVulkanoCpp/Base/Utils.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/openVulkanoCpp/Math/AABB.hpp b/openVulkanoCpp/Math/AABB.hpp index 88469df..9fddbdb 100644 --- a/openVulkanoCpp/Math/AABB.hpp +++ b/openVulkanoCpp/Math/AABB.hpp @@ -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 diff --git a/openVulkanoCpp/Math/ByteSize.hpp b/openVulkanoCpp/Math/ByteSize.hpp index 9ba1e59..1e3bfef 100644 --- a/openVulkanoCpp/Math/ByteSize.hpp +++ b/openVulkanoCpp/Math/ByteSize.hpp @@ -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; } diff --git a/openVulkanoCpp/Math/DenseVector3i.hpp b/openVulkanoCpp/Math/DenseVector3i.hpp index 3673596..2f2aa0c 100644 --- a/openVulkanoCpp/Math/DenseVector3i.hpp +++ b/openVulkanoCpp/Math/DenseVector3i.hpp @@ -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 diff --git a/openVulkanoCpp/Math/RGB10A2.hpp b/openVulkanoCpp/Math/RGB10A2.hpp index aac3434..b22aab0 100644 --- a/openVulkanoCpp/Math/RGB10A2.hpp +++ b/openVulkanoCpp/Math/RGB10A2.hpp @@ -30,21 +30,21 @@ namespace OpenVulkano::Math RGB10A2(TYPE value = 0) : value(value) {} - template || std::is_signed_v>> + template>> void Set(Vector3 vec3) { vec3 &= VALUE_BITMASK; SetUnchecked(vec3); } - template || std::is_signed_v>> + template>> void Set(Vector3_SIMD vec3) { vec3 &= VALUE_BITMASK; SetUnchecked(vec3); } - template || std::is_signed_v>> + template>> void Set(Vector4 vec4) { vec4 &= VALUE_BITMASK; @@ -69,19 +69,19 @@ namespace OpenVulkano::Math Set(Math::Vector4(vec4)); } - template || std::is_signed_v>> + template>> void const SetUnchecked(Vector3& vec3) { value = vec3.r | vec3.g << 10 | vec3.b << 20 | MAX_ALPHA_VALUE << 30; } - template || std::is_signed_v>> + template>> void SetUnchecked(const Vector3_SIMD& vec3) { value = vec3.r | vec3.g << 10 | vec3.b << 20 | MAX_ALPHA_VALUE << 30; } - template || std::is_signed_v>> + template>> void SetUnchecked(const Vector4& vec4) { value = vec4.r | vec4.g << 10 | vec4.b << 20 | vec4.a << 30; diff --git a/openVulkanoCpp/Math/Timestamp.hpp b/openVulkanoCpp/Math/Timestamp.hpp index b09b2f8..f848089 100644 --- a/openVulkanoCpp/Math/Timestamp.hpp +++ b/openVulkanoCpp/Math/Timestamp.hpp @@ -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(seconds * SECONDS_TO_NANOS)) {} + explicit constexpr Timestamp(uint64_t nanos = 0) : timestamp(nanos) {} + explicit constexpr Timestamp(double seconds) : timestamp(static_cast(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(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(rhs.GetNanos()); - } } \ No newline at end of file diff --git a/tests/Math/AABB.cpp b/tests/Math/AABB.cpp new file mode 100644 index 0000000..872da25 --- /dev/null +++ b/tests/Math/AABB.cpp @@ -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 + +#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()); +} \ No newline at end of file diff --git a/tests/Math/ByteSize.cpp b/tests/Math/ByteSize.cpp new file mode 100644 index 0000000..b2240b7 --- /dev/null +++ b/tests/Math/ByteSize.cpp @@ -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 +#include + +#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(size1) == 1'024 * (1uLL << 10)); + REQUIRE(almostEqual(static_cast(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(result) == (1'024 + 512) * (1uLL << 10)); + + result = size1 - size2; + REQUIRE(static_cast(result) == (1'024 - 512) * (1uLL << 10)); + + size1 += size2; + REQUIRE(static_cast(size1) == (1'024 + 512) * (1uLL << 10)); +} + +TEST_CASE("Literals", "[ByteSize]") +{ + REQUIRE(static_cast(1.0_kiB) == 1uLL << 10); + REQUIRE(static_cast(1.0_MiB) == 1uLL << 20); + REQUIRE(static_cast(1.0_GiB) == 1uLL << 30); + REQUIRE(static_cast(1.0_TiB) == 1uLL << 40); + REQUIRE(static_cast(1.0_PiB) == 1uLL << 50); + REQUIRE(static_cast(1.0_EiB) == 1uLL << 60); + + REQUIRE(static_cast(1.0_kB) == 1'000); + REQUIRE(static_cast(1.0_MB) == 1'000'000); + REQUIRE(static_cast(1.0_GB) == 1'000'000'000); + REQUIRE(static_cast(1.0_TB) == 1'000'000'000'000); + REQUIRE(static_cast(1.0_PB) == 1'000'000'000'000'000); + REQUIRE(static_cast(1.0_EB) == 1'000'000'000'000'000'000); + + REQUIRE(static_cast(1_kiB) == 1uLL << 10); + REQUIRE(static_cast(1_MiB) == 1uLL << 20); + REQUIRE(static_cast(1_GiB) == 1uLL << 30); + REQUIRE(static_cast(1_TiB) == 1uLL << 40); + REQUIRE(static_cast(1_PiB) == 1uLL << 50); + REQUIRE(static_cast(1_EiB) == 1uLL << 60); + + REQUIRE(static_cast(1_kB) == 1'000); + REQUIRE(static_cast(1_MB) == 1'000'000); + REQUIRE(static_cast(1_GB) == 1'000'000'000); + REQUIRE(static_cast(1_TB) == 1'000'000'000'000); + REQUIRE(static_cast(1_PB) == 1'000'000'000'000'000); + REQUIRE(static_cast(1_EB) == 1'000'000'000'000'000'000); +} \ No newline at end of file diff --git a/tests/Math/DenseVector3i.cpp b/tests/Math/DenseVector3i.cpp new file mode 100644 index 0000000..c9094c1 --- /dev/null +++ b/tests/Math/DenseVector3i.cpp @@ -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 + +#include "Math/DenseVector3i.hpp" + +using namespace OpenVulkano::Math; + +TEST_CASE("Constructor and Accessors", "[DenseVector3i]") +{ + Vector3i vec3 { 10, 20, 30 }; + DenseVector3i 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 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 denseVec1(10, 20, 30); + DenseVector3i denseVec2(10, 20, 30); + DenseVector3i 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 denseVec(10, 20, 30); + REQUIRE(denseVec.ToString() == fmt::format("{},{},{}", 10, 20, 30)); + REQUIRE(denseVec.ToString(" ") == "10 20 30"); +} + +TEST_CASE("Type Conversion", "[DenseVector3i]") +{ + DenseVector3i denseVec(10, 20, 30); + + Vector3i vec3 = static_cast(denseVec); + REQUIRE(vec3.x == 10); + REQUIRE(vec3.y == 20); + REQUIRE(vec3.z == 30); + + Vector3i_SIMD vec3_simd = static_cast(denseVec); + REQUIRE(vec3_simd.x == 10); + REQUIRE(vec3_simd.y == 20); + REQUIRE(vec3_simd.z == 30); +} \ No newline at end of file diff --git a/tests/Math/Int24.cpp b/tests/Math/Int24.cpp new file mode 100644 index 0000000..28da207 --- /dev/null +++ b/tests/Math/Int24.cpp @@ -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 + +#include "Math/Int24.hpp" + +using namespace OpenVulkano; + +TEST_CASE("Default constructor", "[Int24]") +{ + int24 a; + REQUIRE(static_cast(a) == 0); +} + +TEST_CASE("Integer constructor", "[Int24]") +{ + int24 a(0x123456); + REQUIRE(static_cast(a) == 0x123456); + + int24 b(-1); + REQUIRE(static_cast(b) == -1); +} + +TEST_CASE("Copy constructor", "[Int24]") +{ + int24 a(0x123456); + int24 b(a); + REQUIRE(static_cast(b) == 0x123456); +} + +TEST_CASE("Assignment operator", "[Int24]") +{ + int24 a; + a = 0x123456; + REQUIRE(static_cast(a) == 0x123456); + + int24 b; + b = a; + REQUIRE(static_cast(b) == 0x123456); +} + +TEST_CASE("Arithmetic operators", "[Int24]") +{ + int24 a(0x10); + int24 b(0x20); + + REQUIRE(static_cast(a + b) == 0x30); + REQUIRE(static_cast(b - a) == 0x10); + REQUIRE(static_cast(a * b) == 0x200); + REQUIRE(static_cast(b / a) == 2); +} + +TEST_CASE("Compound assignment operators", "[Int24]") +{ + int24 a(0x10); + int24 b(0x20); + + a += b; + REQUIRE(static_cast(a) == 0x30); + + a -= b; + REQUIRE(static_cast(a) == 0x10); + + a *= b; + REQUIRE(static_cast(a) == 0x200); + + a /= b; + REQUIRE(static_cast(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(a << 1) == 0x2468ac); + REQUIRE(static_cast(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(-a) == -0x123456); +} \ No newline at end of file diff --git a/tests/Math/RGB10A2.cpp b/tests/Math/RGB10A2.cpp new file mode 100644 index 0000000..8ba5f9e --- /dev/null +++ b/tests/Math/RGB10A2.cpp @@ -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 + +#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 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 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 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 { 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 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 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 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 { 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! +} \ No newline at end of file diff --git a/tests/Math/Range.cpp b/tests/Math/Range.cpp new file mode 100644 index 0000000..799022b --- /dev/null +++ b/tests/Math/Range.cpp @@ -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 + +#include "Math/Range.hpp" + +using namespace OpenVulkano::Math; +using RangeType = Range; + +// 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); +} \ No newline at end of file diff --git a/tests/Math/Timestamp.cpp b/tests/Math/Timestamp.cpp new file mode 100644 index 0000000..a41c1a5 --- /dev/null +++ b/tests/Math/Timestamp.cpp @@ -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 + +#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); +}