From 9e787eaf03e3c7ed1b4622eff5b20640523d35f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Kardos?= Date: Tue, 17 Sep 2024 18:00:23 +0200 Subject: [PATCH] completed changelog, small fixes and deprecations --- CHANGELOG.md | 133 ++++++++++++++++++------------ include/Mathter/Utility.hpp | 38 ++------- include/Mathter/Vector/Concat.hpp | 2 +- include/Mathter/Vector/Math.hpp | 15 ++++ test/TestUtility.cpp | 26 ------ test/Vector/TestMath.cpp | 26 ++++++ 6 files changed, 127 insertions(+), 113 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9f7592..dbadd28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,60 +1,83 @@ -### Version 2.0 (?) +# Changelog -Changes: -- Refactored utility folder structure and code (`Common/*`) -- Refactored vector folder structure and code (`Vector/*`) -- Refactored matrix folder structure and code (`Matrix/*`) -- Refactored quaternion folder structure and code (`Quaternion/*`) -- Refactored geometry header and code (`Geometry/*`) -- `Vector`s: - - Memory representation: - - Removed undefined behavior due to swizzle unions - - Named accessors (i.e. `.x`) are now `Swizzle`s instead of `T&` - - CTAD for `Vector` constructors - - Better support for heterogeneous types (i.e. adding vector of `double` plus vector of `float`) - - Better support and testing for `std::complex` - - Functions: - - `IsNullvector`: removed due to questionable meaning / use-cases - - `IsNormalized`: removed due to questionable meaning / use-cases - - `SafeNormalize`: renamed to `NormalizePrecise` - - Homogeneous downcast now performs perspective division - - Added several new functions -- `Matrix`es: - - Removed submatrices - - Added accessors for rows and columns - - Better support for heterogeneous types (i.e. adding matrix of `double` plus matrix of `float`) - - Better support and testing for `std::complex` - - Matrix casts: - - Constructors now handle more casts - - Casts are now utility functions mainly for internal use - - Functions: - - Added several new functions -- `Quaternion`s: - - Memory representation: - - New Layout template param to specify sijk or ijks - - Removed undefined behavior due to swizzle unions - - Named accessors (i.e. `.x`) are now `Swizzle`s instead of `T&` - - Better support for heterogeneous types (i.e. adding quaternion of `double` plus quaternion of `float`) - - Functions: - - Deprecated `ScalarPart` and `VectorPart`: - - Migrate to the new .scalar and .vector swizzlers instead - - Removed converion operator to Vector<3>: questionable meaning / use-cases (use q.vector instead) - - Renamed `Conjugate` to `Conj` (in line with STL) - - Fixed `Inverse` (q^-1) working only for unit quaternions +## 2.0.0 + +- Version 2.0.0 is a complete overhaul: + - The interfaces stayed mostly the same (especially the common ones) + - The internals have been completely rewriten and/or refactored + - Migrating from 1.x.x: + - Read this changelog + - Spam recompile until it works +- Folder structure and library organization: + - Changes to the top-level headers: + - `` no longer includes decompositions (include decompositions individually) + - `` no longer includes transforms (include ``) + - The internals (e.g. ``) have been completely refactored +- Vectors: + - New data structure: + - No more union abuse, `reinterpret_cast`, and UB + - Named accessors (e.g. `.x`) are no longer T&, but are implemented as swizzlers + - Homogeneous downcast now performs perspective division + - CTAD support added to some constructors + - Deprecated concatenation by the pipe (`|`) operator + - Use concatenating constructor with CTAD instead + - `IsNullvector`: removed due to questionable meaning / use-cases + - `IsNormalized`: removed due to questionable meaning / use-cases + - `SafeNormalize`: renamed to `NormalizePrecise` +- Matrices: + - Added additional converting constructors (switch order, layout, and scalar type) + - Removed casting utilities: + - Use the converting constructors instead + - Similar utilities in `Cast.hpp` (warning: not intended for end users) + - Removed submatrices / matrix views + - Added `Row` and `Column` accessors (these are layout-agnostic) + - Added `Extract` and `Insert` accessors (these replace sub-matrices) +- Quaternions: + - Added template parameter to select memory layout: + - Choose between SIJK and IJKS ordering + - New data structure: + - Deprecated `VectorPart` and `ScalarPart` + - Use the swizzlers `.scalar` and `.vector` + - Named accessors (e.g. `.s`) are no longer T&, but are implemented as swizzlers + - `Axis` and `Angle` are now free functions + - Renamed `Conjugate` to `Conj` (it's different from the quaternion inverse) + - `Inverse` does actual inverse (same as conjugation **only** for unit quaternions) + - Removed conversion to `Vector` (ambiguous semantics) + - Deprecated `operator*(Quaternion, Vector)`: + - Use `Quaternion::operator()(Vector)` to apply rotations to vectors - Transforms: - - Minimal changes to interface - New transforms: - - Random, general shear - - Now also applicable to vectors: zero, random + - Generalized shear + - Random (this is not really a transform though) + - Transforms applicable to more types (e.g. `Vector v = Zero()` is now valid) - Geometry: - - Complete overhaul of intersections - - All intersections now return `std::optional` for the intersection point - - Only small changes to objects + - The intersections have been completely reworked + - Use `Intersect(a, b)`: returns an `optional` of the intersection's coordinate - Decompositions: - - QR: - - Added LQ to support wide matrices - - SVD: unchanged - - LU/LUP: unchanged - - All decompositions have a uniform interface: - - Solve: solve system of equations / least squares if applicable - - Inverse: compute matrix inverse / pseudoinverse if applicable \ No newline at end of file + - Unified interface for the different decompositions: + - `Solve`: solve one/many equation systems & least squares problems + - `Inverse`: compute inverse and pseudoinverse + - Get factors via structured bindings + - QR: + - Added LQ decomposition + - SVD: + - Added 1-sided Jacobi algorithm (alongside existing 2-sided) +- IoStream: + - Complete rewrite (old implementation was mostly a quick and dirty utility) + - Changed formatting to Python's array syntax +- General: + - Mixed precision now widely permitted (e.g. adding vector or doubles to vector of complex floats returns a vector of complex doubles) + - Full support for complex numbers: + - Vectors and matrices now fully support complex numbers + - Methods (like `Dot`) have been adapted + - Algorithms (like decompositions) have been adapted + - Improved testing: + - More accurately (and conservatively) measuring coverage + - Raised coverage above 90%, with conservative estimates + - More template parameter combinations are tested (e.g. complex numbers, mixed matrix layouts) + - Many new mathematical functions: most on vectors and matrices, a few on quaternions +- Performance: + - Added many new benchmarks +- Documentation: + - Added an examples folder with a mini project + - Rewrote the guide \ No newline at end of file diff --git a/include/Mathter/Utility.hpp b/include/Mathter/Utility.hpp index bd8607a..246cc67 100644 --- a/include/Mathter/Utility.hpp +++ b/include/Mathter/Utility.hpp @@ -6,12 +6,8 @@ #pragma once #include "Common/TypeTraits.hpp" -#include "Common/Types.hpp" -#include "Vector/Math.hpp" -#include "Vector/Vector.hpp" #include -#include namespace mathter { @@ -26,12 +22,12 @@ namespace mathter { template class Constants { public: - static constexpr auto Pi = Scalar(3.1415926535897932384626433832795028841971693993751); - static constexpr auto PiHalf = Scalar(1.5707963267948966192313216916397514420985846996876); - static constexpr auto PiFourth = Scalar(0.78539816339744830961566084581987572104929234984378); - static constexpr auto E = Scalar(2.7182818284590452353602874713526624977572470937); - static constexpr auto Sqrt2 = Scalar(1.4142135623730950488016887242096980785696718753769); - static constexpr auto SqrtHalf = Scalar(0.70710678118654752440084436210484903928483593768847); + static constexpr auto Pi = Scalar(3.1415926535897932384626433832795028841971693993751L); + static constexpr auto PiHalf = Scalar(1.5707963267948966192313216916397514420985846996876L); + static constexpr auto PiFourth = Scalar(0.78539816339744830961566084581987572104929234984378L); + static constexpr auto E = Scalar(2.7182818284590452353602874713526624977572470937L); + static constexpr auto Sqrt2 = Scalar(1.4142135623730950488016887242096980785696718753769L); + static constexpr auto SqrtHalf = Scalar(0.70710678118654752440084436210484903928483593768847L); }; @@ -62,30 +58,10 @@ Scalar Clamp(Scalar arg, Scalar lower, Scalar upper) { return std::clamp(arg, lower, upper); } -/// Clamps all elements of the vector according to the scalar clamp. -template -Vector Clamp(const Vector& arg, T lower, T upper); - -/// Clamps argument into range [0,1]. +/// Clamps argument into range [0, 1]. template Scalar Saturate(Scalar arg) { return Clamp(arg, Scalar(0), Scalar(1)); } -/// Clamps all elements into range [0,1]. -template -Vector Saturate(const Vector& arg); - - -template -Vector Clamp(const Vector& arg, T lower, T upper) { - using Vec = Vector; - return Min(Max(arg, Vec(lower)), Vec(upper)); -} - -template -Vector Saturate(const Vector& arg) { - return Clamp(arg, T(0), T(1)); -} - } // namespace mathter \ No newline at end of file diff --git a/include/Mathter/Vector/Concat.hpp b/include/Mathter/Vector/Concat.hpp index 00024f2..0cac88a 100644 --- a/include/Mathter/Vector/Concat.hpp +++ b/include/Mathter/Vector/Concat.hpp @@ -13,7 +13,6 @@ namespace mathter { /// Concatenates the arguments, and returns the concatenated parts as a vector. - template > @@ -21,6 +20,7 @@ template > || is_swizzle_v>, int> = 0> +[[deprecated("use concatenating ctor with CTAD")]] auto operator|(Left&& lhs, Right&& rhs) { return Vector(std::forward(lhs), std::forward(rhs)); } diff --git a/include/Mathter/Vector/Math.hpp b/include/Mathter/Vector/Math.hpp index dccc20d..897d04e 100644 --- a/include/Mathter/Vector/Math.hpp +++ b/include/Mathter/Vector/Math.hpp @@ -70,6 +70,21 @@ T Max(const Vector& v) { } +/// Clamps all elements into range [lower, upper]. +template +Vector Clamp(const Vector& arg, T lower, T upper) { + using Vec = Vector; + return Min(Max(arg, Vec(lower)), Vec(upper)); +} + + +/// Clamps all elements into range [0, 1]. +template +Vector Saturate(const Vector& arg) { + return Clamp(arg, T(0), T(1)); +} + + /// Computes a divisor that scales the vector so that its largest element is close to 1. /// This is similar to dividing by the infinity norm, but it's much faster and /// less accurate for complex numbers. diff --git a/test/TestUtility.cpp b/test/TestUtility.cpp index 82e65e7..d23fa52 100644 --- a/test/TestUtility.cpp +++ b/test/TestUtility.cpp @@ -67,30 +67,4 @@ TEMPLATE_LIST_TEST_CASE("Utility: Saturate / scalar", "[Utility]", SECTION("Between") { REQUIRE(Saturate(Scalar(0.5)) == Scalar(0.5)); } -} - - -TEMPLATE_LIST_TEST_CASE("Utility: Clamp / vector", "[Utility]", - decltype(VectorCaseList{})) { - using Vec = typename TestType::template Vector<3>; - using Scalar = scalar_type_t; - const Scalar lower(-3); - const Scalar upper(3); - const Vec value = { -4, 4, 2 }; - const auto result = Clamp(value, lower, upper); - REQUIRE(result[0] == lower); - REQUIRE(result[1] == upper); - REQUIRE(result[2] == value[2]); -} - - -TEMPLATE_LIST_TEST_CASE("Utility: Saturate / vector", "[Utility]", - decltype(VectorCaseList{})) { - using Vec = typename TestType::template Vector<3>; - using Scalar = scalar_type_t; - const Vec value = { -1, 2, 0.5f }; - const auto result = Saturate(value); - REQUIRE(result[0] == Scalar(0)); - REQUIRE(result[1] == Scalar(1)); - REQUIRE(result[2] == value[2]); } \ No newline at end of file diff --git a/test/Vector/TestMath.cpp b/test/Vector/TestMath.cpp index dc7409e..95f3829 100644 --- a/test/Vector/TestMath.cpp +++ b/test/Vector/TestMath.cpp @@ -58,6 +58,32 @@ TEMPLATE_LIST_TEST_CASE("Vector - Min / Max (reduction)", "[Vector]", } +TEMPLATE_LIST_TEST_CASE("Vector - Clamp / vector", "[Vector]", + decltype(VectorCaseList{})) { + using Vec = typename TestType::template Vector<3>; + using Scalar = scalar_type_t; + const Scalar lower(-3); + const Scalar upper(3); + const Vec value = { -4, 4, 2 }; + const auto result = Clamp(value, lower, upper); + REQUIRE(result[0] == lower); + REQUIRE(result[1] == upper); + REQUIRE(result[2] == value[2]); +} + + +TEMPLATE_LIST_TEST_CASE("Vector - Saturate / vector", "[Vector]", + decltype(VectorCaseList{})) { + using Vec = typename TestType::template Vector<3>; + using Scalar = scalar_type_t; + const Vec value = { -1, 2, 0.5f }; + const auto result = Saturate(value); + REQUIRE(result[0] == Scalar(0)); + REQUIRE(result[1] == Scalar(1)); + REQUIRE(result[2] == value[2]); +} + + TEMPLATE_LIST_TEST_CASE("Vector - Abs (real)", "[Vector]", decltype(VectorCaseList{})) { using Vec = typename TestType::template Vector<3>;