From 9f39ecbe8073883f4717c0a8c15942055ebfd5b6 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Sun, 10 Nov 2024 19:46:32 +0200 Subject: [PATCH 1/2] UInt24 class --- openVulkanoCpp/Math/UInt24.hpp | 166 +++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 openVulkanoCpp/Math/UInt24.hpp diff --git a/openVulkanoCpp/Math/UInt24.hpp b/openVulkanoCpp/Math/UInt24.hpp new file mode 100644 index 0000000..7a8504e --- /dev/null +++ b/openVulkanoCpp/Math/UInt24.hpp @@ -0,0 +1,166 @@ +/* + * 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/. + */ + +#pragma once + +#include +#include + +namespace OpenVulkano +{ + class uint24 final + { + uint8_t m_internal[3]; + public: + constexpr uint24() : m_internal{ 0, 0, 0 } + {} + + constexpr uint24(const int val) + : m_internal{(uint8_t)(val & 0xff), (uint8_t)((val >> 8) & 0xff), (uint8_t)((val >> 16) & 0xff)} + {} + + constexpr uint24(const uint24& val) : m_internal{ val.m_internal[0], val.m_internal[1], val.m_internal[2] } + {} + + operator int() const { return (m_internal[2] << 16) | (m_internal[1] << 8) | (m_internal[0] << 0); } + + operator float() const + { + return (float)this->operator int(); + } + + uint24& operator =(const uint24& input) + { + m_internal[0] = input.m_internal[0]; + m_internal[1] = input.m_internal[1]; + m_internal[2] = input.m_internal[2]; + return *this; + } + + uint24& operator =(const int input) + { + m_internal[0] = ((unsigned char*)&input)[0]; + m_internal[1] = ((unsigned char*)&input)[1]; + m_internal[2] = ((unsigned char*)&input)[2]; + return *this; + } + +#define INT24_OPERATORS(op) \ + template, bool> = true> \ + uint24 operator op(const T& val) const { return uint24( (int)*this op static_cast(val) ); } \ + template, bool> = true> \ + uint24& operator op##=(const T& val ) { *this = *this op static_cast(val); return *this; } + + INT24_OPERATORS(+) + INT24_OPERATORS(-) + INT24_OPERATORS(*) + INT24_OPERATORS(/) +#undef INT24_OPERATORS + + uint24 operator >>(const int val) const + { + return uint24( (int)*this >> val ); + } + + uint24 operator <<(const int val) const + { + return uint24( (int)*this << val ); + } + + uint24& operator >>=(const int val ) + { + *this = *this >> val; + return *this; + } + + uint24& operator <<=(const int val ) + { + *this = *this << val; + return *this; + } + + operator bool() const + { + return (int)*this != 0; + } + + bool operator !() const + { + return !((int)*this); + } + + uint24 operator -() + { + return uint24( -(int)*this ); + } + + template, bool> = true> + [[nodiscard]] bool operator==(const T& val) const + { + return static_cast(*this) == static_cast(val); + } + + template, bool> = true> + [[nodiscard]] constexpr auto operator<=>(const T& other) const + { + return operator int() <=> static_cast(other); + } + + template friend + struct std::hash; + }; +} + +namespace std +{ + template<> + struct hash + { + std::size_t operator()(const OpenVulkano::uint24& value) const + { + return hash()(static_cast(value)); + } + }; + + template <> + class numeric_limits + { + public: + static const bool is_specialized = true; + static constexpr OpenVulkano::uint24 min() { return OpenVulkano::uint24(0); } + static constexpr OpenVulkano::uint24 max() { return OpenVulkano::uint24(0xFFFFFF); } + static const int radix = 2; + static const int digits = 24; + static const int digits10 = 7; + static const bool is_signed = false; + static const bool is_integer = true; + static const bool is_exact = true; + static const bool traps = false; + static const bool is_modulo = true; + static const bool is_bounded = true; + + static constexpr OpenVulkano::uint24 epsilon() { return OpenVulkano::uint24(1); } + static constexpr OpenVulkano::uint24 round_error() { return OpenVulkano::uint24(0); } + static const int min_exponent10 = 0; + static const int max_exponent10 = 0; + static const int min_exponent = 0; + static const int max_exponent = 0; + + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const bool is_iec559 = false; + static const bool has_denorm = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_toward_zero; + + // Not meaningful for uint24... + static constexpr OpenVulkano::uint24 denorm_min() { return OpenVulkano::uint24(0); } + static constexpr OpenVulkano::uint24 infinity() { return OpenVulkano::uint24(0); } + static constexpr OpenVulkano::uint24 quiet_NaN() { return OpenVulkano::uint24(0); } + static constexpr OpenVulkano::uint24 signaling_NaN() { return OpenVulkano::uint24(0); } + }; +} \ No newline at end of file From 373a6acd775d193989af99e81ac7919abdb86b9a Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Sun, 10 Nov 2024 19:46:44 +0200 Subject: [PATCH 2/2] Tests for UInt24 --- tests/Math/UInt24.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 tests/Math/UInt24.cpp diff --git a/tests/Math/UInt24.cpp b/tests/Math/UInt24.cpp new file mode 100644 index 0000000..804a9a1 --- /dev/null +++ b/tests/Math/UInt24.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/UInt24.hpp" + +using namespace OpenVulkano; + +TEST_CASE("Default constructor", "[UInt24]") +{ + uint24 a; + REQUIRE(static_cast(a) == 0); +} + +TEST_CASE("Integer constructor", "[UInt24]") +{ + uint24 a(0x123456); + REQUIRE(static_cast(a) == 0x123456); + + uint24 b(-1); + REQUIRE(static_cast(b) == 0xffffff); +} + +TEST_CASE("Copy constructor", "[UInt24]") +{ + uint24 a(0x123456); + uint24 b(a); + REQUIRE(static_cast(b) == 0x123456); +} + +TEST_CASE("Assignment operator", "[UInt24]") +{ + uint24 a; + a = 0x123456; + REQUIRE(static_cast(a) == 0x123456); + + uint24 b; + b = a; + REQUIRE(static_cast(b) == 0x123456); +} + +TEST_CASE("Arithmetic operators", "[UInt24]") +{ + uint24 a(0x10); + uint24 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", "[UInt24]") +{ + uint24 a(0x10); + uint24 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", "[UInt24]") +{ + uint24 a(0x100000); + uint24 b(0x200000); + + REQUIRE(a < b); + REQUIRE(b > a); + REQUIRE(a <= b); + REQUIRE(b >= a); + REQUIRE(a != b); + + uint24 c(0x100000); + REQUIRE(a == c); +} + +TEST_CASE("Shift operators", "[UInt24]") +{ + uint24 a(0x123456); + REQUIRE(static_cast(a << 1) == 0x2468ac); + REQUIRE(static_cast(a >> 1) == 0x91a2b); +} + +TEST_CASE("Boolean operators", "[UInt24]") +{ + uint24 a(0); + uint24 b(1); + + REQUIRE(!a); + REQUIRE(b); +} + +TEST_CASE("Negation", "[UInt24]") +{ + uint24 a(0x123456); + REQUIRE(static_cast(-a) == 0xedcbaa); +} \ No newline at end of file