From f2ff863b3a90427692c8df8923a38691e67932a6 Mon Sep 17 00:00:00 2001 From: Medusa Slockbower Date: Sat, 28 Jun 2025 18:01:08 -0400 Subject: [PATCH] - Started unit tests for the common math functions --- include/fennec/math/common.h | 16 ++-- test/CMakeLists.txt | 1 + test/test.h | 5 +- test/tests/math/test_common.h | 157 ++++++++++++++++++++++++++++++++++ test/tests/test_math.h | 5 ++ 5 files changed, 175 insertions(+), 9 deletions(-) create mode 100644 test/tests/math/test_common.h diff --git a/include/fennec/math/common.h b/include/fennec/math/common.h index b4d0760..3fb7ab0 100644 --- a/include/fennec/math/common.h +++ b/include/fennec/math/common.h @@ -301,7 +301,7 @@ namespace fennec /// \param x input value template constexpr genType abs(genType x) - { return std::abs(x); } + { return ::abs(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -324,7 +324,7 @@ constexpr vector abs(const vector& x) /// \param x input value template constexpr genType sign(genType x) - { return (x < 0 ? -1 : (x > 0 ? +1 : 0)); } + { return (x < 0 ? -1 : 1) * static_cast(x != 0); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -427,7 +427,7 @@ constexpr vector round(const vector& x) /// \param x input value template constexpr genType roundEven(genType x) - { return x - floor(x) == 0.5f ? floor(x) + (static_cast(floor(x)) % 2) : round(x); } + { return ::roundeven(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -505,18 +505,18 @@ constexpr vector fract(const vector& x) /// \param y divisor template constexpr genType mod(genType x, genType y) - { return x - y * fennec::floor(x); } + { return x - y * fennec::floor(x / y); } // Vector Specializations ---------------------------------------------------------------------------------------------- template constexpr vector mod(const vector& x, genType y) - { return x - y * fennec::floor(x); } + { return x - y * fennec::floor(x / y); } template constexpr vector mod(const vector& x, const vector& y) - { return x - y * fennec::floor(x); } + { return x - y * fennec::floor(x / y); } @@ -533,7 +533,7 @@ constexpr vector mod(const vector& x, const vector /// \param i integral out template constexpr genType modf(genType x, genType& i) - { return ::modf(x, &i); } + { i = fennec::floor(x); return fennec::fract(x); } // Vector Specializations ---------------------------------------------------------------------------------------------- @@ -600,7 +600,7 @@ constexpr vector isinf(const vector& x) /// /// \copydetails fennec::floatBitsToUint(fennec::genFType) template requires(is_floating_point_v and is_integral_v and is_signed_v and sizeof(genType) == sizeof(genIType)) -constexpr genIType floatBitsToInt(genIType x) +constexpr genIType floatBitsToInt(genType x) { return fennec::bit_cast(x); } /// diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 701e41e..cc79542 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,6 +15,7 @@ add_executable(fennec-test main.cpp tests/lang/test_conditional_types.h tests/lang/test_bits.h tests/lang/test_sequences.h + tests/math/test_common.h ) target_link_libraries(fennec-test PRIVATE diff --git a/test/test.h b/test/test.h index ee478f1..baaa609 100644 --- a/test/test.h +++ b/test/test.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace fennec { @@ -76,7 +77,9 @@ inline void __fennec_test_run(const std::string& expression, const ResultT resul std::cout << std::boolalpha; std::cout << '\t' << expression << " = " << result; bool passed = false; - if constexpr(is_arithmetic_v or is_vector_v) + if constexpr(is_arithmetic_v) + passed = fennec::abs(expected - result) <= numeric_limits::epsilon(); + else if constexpr(is_vector_v && not(is_bool_v)) passed = fennec::abs(expected - result) <= numeric_limits::epsilon(); else passed = result == expected; diff --git a/test/tests/math/test_common.h b/test/tests/math/test_common.h new file mode 100644 index 0000000..8fea32b --- /dev/null +++ b/test/tests/math/test_common.h @@ -0,0 +1,157 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_TEST_MATH_COMMON_H +#define FENNEC_TEST_MATH_COMMON_H + +#include "../../test.h" + +namespace fennec +{ + +namespace test +{ + +inline void fennec_test_math_common() +{ + fennec_test_section("Sign Functions"); + + fennec_test_spacer(1); + + fennec_test_run(fennec::abs( 1), 1); + fennec_test_run(fennec::abs(-1), 1); + fennec_test_run(fennec::abs( 1.0f), 1.0f); + fennec_test_run(fennec::abs(-1.0f), 1.0f); + fennec_test_run(fennec::abs( 1.0), 1.0); + fennec_test_run(fennec::abs(-1.0), 1.0); + + fennec_test_spacer(1); + + fennec_test_run(fennec::sign(vec2( 1, -2)), vec2( 1, -1)); + fennec_test_run(fennec::sign(vec3(-1, 2, -3)), vec3(-1, 1, -1)); + fennec_test_run(fennec::sign(vec4( 1, -2, 3, -4)), vec4( 1, -1, 1, -1)); + + fennec_test_spacer(2); + + + + fennec_test_section("Rounding Functions"); + + fennec_test_spacer(1); + + fennec_test_run(fennec::ceil(2.4f), 3.0f); + fennec_test_run(fennec::ceil(2.5f), 3.0f); + fennec_test_run(fennec::ceil(2.6f), 3.0f); + + fennec_test_run(fennec::ceil(-2.4f), -2.0f); + fennec_test_run(fennec::ceil(-2.5f), -2.0f); + fennec_test_run(fennec::ceil(-2.6f), -2.0f); + + fennec_test_spacer(1); + + fennec_test_run(fennec::floor(2.4f), 2.0f); + fennec_test_run(fennec::floor(2.5f), 2.0f); + fennec_test_run(fennec::floor(2.6f), 2.0f); + + fennec_test_run(fennec::floor(-2.4f), -3.0f); + fennec_test_run(fennec::floor(-2.5f), -3.0f); + fennec_test_run(fennec::floor(-2.6f), -3.0f); + + fennec_test_spacer(1); + + fennec_test_run(fennec::round(2.4f), 2.0f); + fennec_test_run(fennec::round(2.5f), 3.0f); + fennec_test_run(fennec::round(2.6f), 3.0f); + + fennec_test_spacer(1); + + fennec_test_run(fennec::roundEven(2.4f), 2.0f); + fennec_test_run(fennec::roundEven(2.5f), 2.0f); + fennec_test_run(fennec::roundEven(2.6f), 3.0f); + + fennec_test_spacer(1); + + fennec_test_run(fennec::trunc(2.4f), 2.0f); + fennec_test_run(fennec::trunc(2.5f), 2.0f); + fennec_test_run(fennec::trunc(2.6f), 2.0f); + + fennec_test_run(fennec::trunc(-2.4f), -2.0f); + fennec_test_run(fennec::trunc(-2.5f), -2.0f); + fennec_test_run(fennec::trunc(-2.6f), -2.0f); + + fennec_test_spacer(2); + + + + fennec_test_section("Floating Point Functions"); + + fennec_test_spacer(1); + + fennec_test_run(fennec::fract(2.4f), 0.4f); + fennec_test_run(fennec::fract(2.5f), 0.5f); + fennec_test_run(fennec::fract(2.6f), 0.6f); + + fennec_test_spacer(1); + + fennec_test_run(fennec::mod(2.4f, 2.0f), 0.4f); + fennec_test_run(fennec::mod(2.5f, 2.0f), 0.5f); + fennec_test_run(fennec::mod(2.6f, 2.0f), 0.6f); + + fennec_test_spacer(1); + + fennec_test_run([]() -> float { float i; return fennec::modf(2.4f, i) + i; }(), 2.4f); + fennec_test_run([]() -> float { float i; return fennec::modf(2.5f, i) + i; }(), 2.5f); + fennec_test_run([]() -> float { float i; return fennec::modf(2.6f, i) + i; }(), 2.6f); + + fennec_test_spacer(1); + + fennec_test_run(fennec::isnan(0.0f), false); + fennec_test_run(fennec::isnan(fennec::numeric_limits::quiet_NaN()), true); + fennec_test_run(fennec::isnan(fennec::numeric_limits::signaling_NaN()), true); + + fennec_test_spacer(1); + + fennec_test_run(fennec::isinf( 0.0f), false); + fennec_test_run(fennec::isinf( fennec::numeric_limits::infinity()), true); + fennec_test_run(fennec::isinf(-fennec::numeric_limits::infinity()), true); + + fennec_test_spacer(1); + + fennec_test_run(fennec::floatBitsToInt( 1.0f), static_cast(0x3f800000u)); + fennec_test_run(fennec::floatBitsToInt(-1.0f), static_cast(0xbf800000u)); + fennec_test_run(fennec::floatBitsToUint( 1.0f), 0x3f800000u); + fennec_test_run(fennec::floatBitsToUint(-1.0f), 0xbf800000u); + + fennec_test_spacer(1); + + fennec_test_run(fennec::intBitsToFloat(static_cast(0x3f800000u)), 1.0f); + fennec_test_run(fennec::intBitsToFloat(static_cast(0xbf800000u)), -1.0f); + fennec_test_run(fennec::uintBitsToFloat(0x3f800000u), 1.0f); + fennec_test_run(fennec::uintBitsToFloat(0xbf800000u), -1.0f); + + fennec_test_spacer(2); + + + +} + +} + +} + +#endif // FENNEC_TEST_MATH_COMMON_H diff --git a/test/tests/test_math.h b/test/tests/test_math.h index 1312bfc..506172a 100644 --- a/test/tests/test_math.h +++ b/test/tests/test_math.h @@ -19,6 +19,7 @@ #ifndef FENNEC_TEST_MATH_H #define FENNEC_TEST_MATH_H +#include "math/test_common.h" #include "math/test_scalar.h" #include "math/test_vector.h" #include "math/test_matrix.h" @@ -47,6 +48,10 @@ inline void fennec_test_math() fennec_test_math_matrix(); fennec_test_spacer(3); + fennec_test_subheader("common tests"); + fennec_test_spacer(2); + fennec_test_math_common(); + fennec_test_spacer(3); fennec_test_subheader("geometric tests"); fennec_test_spacer(2);