diff --git a/doc/changelog.dox b/doc/changelog.dox index 4a046f16d..8a1eca381 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -132,6 +132,9 @@ See also: - @ref Math::Matrix3::scaling() const and @ref Math::Matrix4::scaling() const now return a signed scaling vector, taking into account negative scaling as well +- Functions in @ref Magnum/Math/FunctionsBatch.h now accept any type that's + convertible to a @ref Corrade::Containers::StridedArrayView without having + to add explicit casts or template parameters @subsubsection changelog-latest-changes-meshtools MeshTools library diff --git a/src/Magnum/Math/FunctionsBatch.h b/src/Magnum/Math/FunctionsBatch.h index 44ea59ce4..c6b42c593 100644 --- a/src/Magnum/Math/FunctionsBatch.h +++ b/src/Magnum/Math/FunctionsBatch.h @@ -36,6 +36,16 @@ namespace Magnum { namespace Math { +namespace Implementation { + +/** @todo Utility/Algorithms.h has a similar (but different) variant of this, + maybe turn that into some public utility once we have one more use case? */ +template::type>::from(std::declval()))> static auto stridedArrayViewTypeFor(T&&) -> typename View::Type; +template static T stridedArrayViewTypeFor(const Corrade::Containers::ArrayView&); +template static T stridedArrayViewTypeFor(const Corrade::Containers::StridedArrayView1D&); + +} + /** @{ @name Batch functions @@ -67,14 +77,26 @@ template auto isInf(Corrade::Containers::StridedArrayView1D ra return out; } +/** +@overload +@m_since_latest + +Converts @p range to @ref Corrade::Containers::StridedArrayView1D and calls the +above overload. Works with any type that's convertible to +@ref Corrade::Containers::StridedArrayView. +*/ +template()))> inline auto isInf(Iterable&& range) -> decltype(isInf(std::declval())) { + return isInf(Corrade::Containers::StridedArrayView1D{range}); +} + /** @overload */ template inline auto isInf(std::initializer_list list) -> decltype(isInf(std::declval())) { - return isInf(Corrade::Containers::arrayView(list.begin(), list.size())); + return isInf(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline auto isInf(const T(&array)[size]) -> decltype(isInf(std::declval())) { - return isInf(Corrade::Containers::arrayView(array)); + return isInf(Corrade::Containers::StridedArrayView1D{array}); } /** @@ -101,14 +123,27 @@ template inline auto isNan(Corrade::Containers::StridedArrayView1D()))> inline auto isNan(Iterable&& range) -> decltype(isNan(std::declval())) { + return isNan(Corrade::Containers::StridedArrayView1D{range}); +} + /** @overload */ template inline auto isNan(std::initializer_list list) -> decltype(isNan(std::declval())) { - return isNan(Corrade::Containers::arrayView(list.begin(), list.size())); + return isNan(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline auto isNan(const T(&array)[size]) -> decltype(isNan(std::declval())) { - return isNan(Corrade::Containers::arrayView(array)); + return isNan(Corrade::Containers::StridedArrayView1D{array}); } namespace Implementation { @@ -162,14 +197,26 @@ template inline T min(Corrade::Containers::StridedArrayView1D return iOut.second; } +/** +@overload +@m_since_latest + +Converts @p range to @ref Corrade::Containers::StridedArrayView1D and calls the +above overload. Works with any type that's convertible to +@ref Corrade::Containers::StridedArrayView. +*/ +template()))> inline T min(Iterable&& range) { + return min(Corrade::Containers::StridedArrayView1D{range}); +} + /** @overload */ template inline T min(std::initializer_list list) { - return min(Corrade::Containers::arrayView(list.begin(), list.size())); + return min(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline T min(const T(&array)[size]) { - return min(Corrade::Containers::arrayView(array)); + return min(Corrade::Containers::StridedArrayView1D{array}); } /** @@ -189,14 +236,26 @@ template inline T max(Corrade::Containers::StridedArrayView1D return iOut.second; } +/** +@overload +@m_since_latest + +Converts @p range to @ref Corrade::Containers::StridedArrayView1D and calls the +above overload. Works with any type that's convertible to +@ref Corrade::Containers::StridedArrayView. +*/ +template()))> inline T max(Iterable&& range) { + return max(Corrade::Containers::StridedArrayView1D{range}); +} + /** @overload */ template inline T max(std::initializer_list list) { - return max(Corrade::Containers::arrayView(list.begin(), list.size())); + return max(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline T max(const T(&array)[size]) { - return max(Corrade::Containers::arrayView(array)); + return max(Corrade::Containers::StridedArrayView1D{array}); } namespace Implementation { @@ -232,14 +291,26 @@ template inline std::pair minmax(Corrade::Containers::StridedArra return {min, max}; } +/** +@overload +@m_since_latest + +Converts @p range to @ref Corrade::Containers::StridedArrayView1D and calls the +above overload. Works with any type that's convertible to +@ref Corrade::Containers::StridedArrayView. +*/ +template()))> inline std::pair minmax(Iterable&& range) { + return minmax(Corrade::Containers::StridedArrayView1D{range}); +} + /** @overload */ template inline std::pair minmax(std::initializer_list list) { - return minmax(Corrade::Containers::arrayView(list.begin(), list.size())); + return minmax(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline std::pair minmax(const T(&array)[size]) { - return minmax(Corrade::Containers::arrayView(array)); + return minmax(Corrade::Containers::StridedArrayView1D{array}); } /*@}*/ diff --git a/src/Magnum/Math/Test/FunctionsBatchTest.cpp b/src/Magnum/Math/Test/FunctionsBatchTest.cpp index f97067c94..dd47f6f01 100644 --- a/src/Magnum/Math/Test/FunctionsBatchTest.cpp +++ b/src/Magnum/Math/Test/FunctionsBatchTest.cpp @@ -23,6 +23,8 @@ DEALINGS IN THE SOFTWARE. */ +#include +#include #include #include "Magnum/Math/FunctionsBatch.h" @@ -85,6 +87,14 @@ void FunctionsBatchTest::isInf() { Vector2 c[]{{5.0f, -3.0f}, {-2.0f, 14.0f}, {Constants::inf(), -5.0f}}; CORRADE_COMPARE(Math::isInf(c), BoolVector<2>{1}); + /* Mutable view */ + CORRADE_COMPARE(Math::isInf(Corrade::Containers::StridedArrayView1D{c}), BoolVector<2>{1}); + + /* This should work without explicit casts or types */ + CORRADE_VERIFY(!Math::isInf(std::vector{5.0f, -2.0f, -1.0f})); + CORRADE_COMPARE(Math::isInf(std::vector{ + {5.0f, -3.0f}, {-2.0f, 14.0f}, {Constants::inf(), -5.0f} + }), BoolVector<2>{1}); } void FunctionsBatchTest::isNan() { @@ -109,6 +119,14 @@ void FunctionsBatchTest::isNan() { Vector2 c[]{{5.0f, -3.0f}, {14.0f, Constants::nan()}, {-2.0f, -5.0f}}; CORRADE_COMPARE(Math::isNan(c), BoolVector<2>{2}); + /* Mutable view */ + CORRADE_COMPARE(Math::isNan(Corrade::Containers::StridedArrayView1D{c}), BoolVector<2>{2}); + + /* This should work without explicit casts or types */ + CORRADE_VERIFY(!Math::isNan(std::vector{5.0f, -2.0f, -1.0f})); + CORRADE_COMPARE(Math::isNan(std::vector{ + {5.0f, -3.0f}, {14.0f, Constants::nan()}, {-2.0f, -5.0f} + }), BoolVector<2>{2}); } void FunctionsBatchTest::min() { @@ -121,6 +139,12 @@ void FunctionsBatchTest::min() { const Int array[]{5, -2, 9}; CORRADE_COMPARE(Math::min(array), -2); + /* Mutable view */ + Int marray[]{5, -2, 9}; + CORRADE_COMPARE(Math::min(Corrade::Containers::StridedArrayView1D{marray}), -2); + + /* This should work without explicit casts or types */ + CORRADE_COMPARE(Math::min(std::vector{5, -2, 9}), -2); /* Wrapped types */ CORRADE_COMPARE(Math::min({5.0_degf, 2.0_degf, 9.0_degf}), 2.0_degf); @@ -136,6 +160,12 @@ void FunctionsBatchTest::max() { const Int array[]{5, -2, 9}; CORRADE_COMPARE(Math::max(array), 9); + /* Mutable view */ + Int marray[]{5, -2, 9}; + CORRADE_COMPARE(Math::max(Corrade::Containers::StridedArrayView1D{marray}), 9); + + /* This should work without explicit casts or types */ + CORRADE_COMPARE(Math::max(std::vector{5, -2, 9}), 9); /* Wrapped types */ CORRADE_COMPARE(Math::max({5.0_degf, 2.0_degf, 9.0_degf}), 9.0_degf); @@ -160,6 +190,12 @@ void FunctionsBatchTest::minmax() { const Float array[]{-1.0f, 2.0f, -3.0f}; CORRADE_COMPARE(Math::minmax(array), expected); + /* Mutable view */ + Float marray[]{-1.0f, 2.0f, -3.0f}; + CORRADE_COMPARE(Math::minmax(Corrade::Containers::StridedArrayView1D{marray}), expected); + + /* This should work without explicit casts or types */ + CORRADE_COMPARE(Math::minmax(std::vector{-1.0f, 2.0f, -3.0f}), expected); /* Wrapped types */ CORRADE_COMPARE(Math::minmax({1.0_radf, 2.0_radf, 3.0_radf}), std::make_pair(1.0_radf, 3.0_radf)); diff --git a/src/Magnum/MeshTools/CompressIndices.cpp b/src/Magnum/MeshTools/CompressIndices.cpp index 1cef1e651..c3b56d32e 100644 --- a/src/Magnum/MeshTools/CompressIndices.cpp +++ b/src/Magnum/MeshTools/CompressIndices.cpp @@ -49,7 +49,7 @@ template inline Containers::Array compress(const std::vector, MeshIndexType, UnsignedInt, UnsignedInt> compressIndices(const std::vector& indices) { /** @todo Performance hint when range can be represented by smaller value? */ - const auto minmax = Math::minmax(indices); + const auto minmax = Math::minmax(indices); Containers::Array data; MeshIndexType type; switch(Math::log(256, minmax.second)) { @@ -76,7 +76,7 @@ std::tuple, MeshIndexType, UnsignedInt, UnsignedInt> com template Containers::Array compressIndicesAs(const std::vector& indices) { #if !defined(CORRADE_NO_ASSERT) || defined(CORRADE_GRACEFUL_ASSERT) - const auto max = Math::max(indices); + const auto max = Math::max(indices); CORRADE_ASSERT(Math::log(256, max) < sizeof(T), "MeshTools::compressIndicesAs(): type too small to represent value" << max, {}); #endif diff --git a/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp b/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp index 915da8a93..872e532e1 100644 --- a/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp +++ b/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp @@ -406,7 +406,7 @@ void GenerateNormalsTest::benchmarkFlat() { generateFlatNormalsInto(positions, normals); } - CORRADE_COMPARE(Math::min(normals), (Vector3{-1.0f, -1.0f, -1.0f})); + CORRADE_COMPARE(Math::min(normals), (Vector3{-1.0f, -1.0f, -1.0f})); } void GenerateNormalsTest::benchmarkSmooth() { @@ -417,7 +417,7 @@ void GenerateNormalsTest::benchmarkSmooth() { BeveledCubePositions, normals); } - CORRADE_COMPARE(Math::min(normals), (Vector3{-0.996072f, -0.997808f, -0.996072f})); + CORRADE_COMPARE(Math::min(normals), (Vector3{-0.996072f, -0.997808f, -0.996072f})); } }}}}