From 7e5a9472e408530c6630c74ab29d67941cd2cf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 31 Dec 2025 20:22:42 +0100 Subject: [PATCH] Math: add scatterInto(). Because doing `foo = Math::scatter<'y', 'w'>(foo, ...)` is just too long, especially when the expression is already too long to begin with. --- doc/changelog.dox | 4 ++ doc/snippets/Math.cpp | 8 +++ src/Magnum/Math/Swizzle.h | 24 ++++++++- src/Magnum/Math/Test/CMakeLists.txt | 2 + src/Magnum/Math/Test/SwizzleCpp14Test.cpp | 61 +++++++++++++++++++++++ src/Magnum/Math/Test/SwizzleTest.cpp | 14 +++++- 6 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/Magnum/Math/Test/SwizzleCpp14Test.cpp diff --git a/doc/changelog.dox b/doc/changelog.dox index 57535fd37..f6be7ab9d 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -317,6 +317,10 @@ See also: @link Literals::ColorLiterals::operator""_srgbh() _srgbh @endlink and @link Literals::ColorLiterals::operator""_srgbah() _srgbah @endlink literals for convenient @ref Color3h and @ref Color4h creation +- Added @ref Math::scatterInto() as an in-place variant of + @ref Math::scatter(), which is now marked with @ref CORRADE_NODISCARD to + better convey that it returns the modified value instead of mutating it + in-place @subsubsection changelog-latest-new-materialtools MaterialTools library diff --git a/doc/snippets/Math.cpp b/doc/snippets/Math.cpp index f82505f76..f7da9f787 100644 --- a/doc/snippets/Math.cpp +++ b/doc/snippets/Math.cpp @@ -1443,6 +1443,14 @@ vec2 = Math::scatter<'w', 'x', 'y'>(vec2, Math::gather<'x', 'w', 'y'>(vec)); /* [scatter] */ } +{ +/* [scatterInto] */ +Vector4 vec{1.5f, 3.0f, 0.1f, 1.1f}; +Vector2 coords{5.0f, -2.0f}; +Math::scatterInto<'z', 'w'>(vec, coords); // { 1.5, 3.0, 5.0, -2.0 } +/* [scatterInto] */ +} + { Float a{}, b{}; /* [TypeTraits-equalsZero] */ diff --git a/src/Magnum/Math/Swizzle.h b/src/Magnum/Math/Swizzle.h index f671c41bf..25a3a5025 100644 --- a/src/Magnum/Math/Swizzle.h +++ b/src/Magnum/Math/Swizzle.h @@ -27,7 +27,7 @@ */ /** @file - * @brief Function @ref Magnum::Math::gather(), @ref Magnum::Math::scatter() + * @brief Function @ref Magnum::Math::gather(), @ref Magnum::Math::scatter(), @ref Magnum::Math::scatterInto() */ #include "Magnum/Math/Vector.h" @@ -141,6 +141,7 @@ Inverse to @ref gather(), supporting the same component addressing except for @snippet Math.cpp scatter +Use @ref scatterInto() to update the vector in-place. @see @ref matrix-vector-component-access, @ref Vector4::xyz(), @ref Vector4::rgb(), @ref Vector4::xy(), @ref Vector3::xy() */ @@ -155,6 +156,27 @@ template CORRADE_NODISCARD constexpr T scatter(cons return Implementation::scatterRecursive(vector, values, 0); } +/** +@brief Scatter @ref Vector components in-place +@param[in,out] vector Vector to update +@param[in] values Values to update it with +@m_since_latest + +Like @ref scatter(), but updates the @p vector in-place. Example usage: + +@snippet Math.cpp scatterInto +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template CORRADE_CONSTEXPR14 void scatterInto(T& vector, const Vector& values) +#else +/* Using std::common_type otherwise GCC 4.8 fails to match the arguments + in SwizzleTest::scatterOneComponent() */ +template CORRADE_CONSTEXPR14 void scatterInto(T& vector, const typename std::common_type>::type& values) +#endif +{ + vector = Implementation::scatterRecursive(vector, values, 0); +} + }} #endif diff --git a/src/Magnum/Math/Test/CMakeLists.txt b/src/Magnum/Math/Test/CMakeLists.txt index 9b85da837..b348c0956 100644 --- a/src/Magnum/Math/Test/CMakeLists.txt +++ b/src/Magnum/Math/Test/CMakeLists.txt @@ -127,6 +127,7 @@ if(NOT CMAKE_CXX_FLAGS MATCHES "-std=") corrade_add_test(MathQuaternionCpp14Test QuaternionCpp14Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathRangeCpp14Test RangeCpp14Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathRectangularMatrixCpp14Test RectangularMatrixCpp14Test.cpp LIBRARIES MagnumMathTestLib) + corrade_add_test(MathSwizzleCpp14Test SwizzleCpp14Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathVectorCpp14Test VectorCpp14Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathVector2Cpp14Test Vector2Cpp14Test.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathVector3Cpp14Test Vector3Cpp14Test.cpp LIBRARIES MagnumMathTestLib) @@ -141,6 +142,7 @@ if(NOT CMAKE_CXX_FLAGS MATCHES "-std=") MathQuaternionCpp14Test MathRangeCpp14Test MathRectangularMatrixCpp14Test + MathSwizzleCpp14Test MathVectorCpp14Test MathVector2Cpp14Test MathVector3Cpp14Test diff --git a/src/Magnum/Math/Test/SwizzleCpp14Test.cpp b/src/Magnum/Math/Test/SwizzleCpp14Test.cpp new file mode 100644 index 000000000..5b35b1700 --- /dev/null +++ b/src/Magnum/Math/Test/SwizzleCpp14Test.cpp @@ -0,0 +1,61 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023, 2024, 2025 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Magnum/Math/Swizzle.h" + +namespace Magnum { namespace Math { namespace Test { namespace { + +struct SwizzleCpp14Test: TestSuite::Tester { + explicit SwizzleCpp14Test(); + + void scatterIntoConstexpr(); +}; + +/* What's a typedef and not a using differs from the typedefs in root Magnum + namespace, or is not present there at all */ +typedef Vector<2, Int> Vector2i; +typedef Vector<4, Int> Vector4i; + +SwizzleCpp14Test::SwizzleCpp14Test() { + addTests({&SwizzleCpp14Test::scatterIntoConstexpr}); +} + +constexpr Vector4i populate() { + Vector4i a{2, 4, 5, 7}; + Math::scatterInto<'w', 'y'>(a, Vector2i{1, 3}); + return a; +} + +void SwizzleCpp14Test::scatterIntoConstexpr() { + constexpr Vector4i a = populate(); + CORRADE_COMPARE(a, (Vector4i{2, 3, 5, 1})); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Math::Test::SwizzleCpp14Test) diff --git a/src/Magnum/Math/Test/SwizzleTest.cpp b/src/Magnum/Math/Test/SwizzleTest.cpp index 9a1e00b41..9cb616f6b 100644 --- a/src/Magnum/Math/Test/SwizzleTest.cpp +++ b/src/Magnum/Math/Test/SwizzleTest.cpp @@ -43,6 +43,8 @@ struct SwizzleTest: TestSuite::Tester { void scatterRepeatedComponents(); void scatterOverwriteAllComponents(); void scatterFarComponents(); + + void scatterInto(); }; /* These differ from the typedefs in root Magnum namespace */ @@ -60,7 +62,9 @@ SwizzleTest::SwizzleTest() { &SwizzleTest::scatterOneComponent, &SwizzleTest::scatterRepeatedComponents, &SwizzleTest::scatterOverwriteAllComponents, - &SwizzleTest::scatterFarComponents}); + &SwizzleTest::scatterFarComponents, + + &SwizzleTest::scatterInto}); } void SwizzleTest::gather() { @@ -138,6 +142,14 @@ void SwizzleTest::scatterFarComponents() { CORRADE_COMPARE(a, (Vector<7, Int>{2, 4, 5, 7, 6, 1, 9})); } +void SwizzleTest::scatterInto() { + /* It calls into scatter() internally so just verify it works at all, the + whole functionality is sufficiently tested above */ + Vector4i a{2, 4, 5, 7}; + Math::scatterInto<'w', 'y'>(a, Vector2i{1, 3}); + CORRADE_COMPARE(a, (Vector4i{2, 3, 5, 1})); +} + }}}} CORRADE_TEST_MAIN(Magnum::Math::Test::SwizzleTest)