From 92b1cdf6b76de75403b18fd144bf78318428e347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 24 Jan 2020 13:18:39 +0100 Subject: [PATCH] Math: pass strided array views by const&. It has the size of three pointers, which is more than a little. Unfortunately doing just that causes infinite recursion, so be a little more specific when delegating from the overloads. --- doc/changelog.dox | 22 ++++----- src/Magnum/Math/Functions.h | 10 ++--- src/Magnum/Math/FunctionsBatch.h | 76 ++++++++++++++++++++++---------- 3 files changed, 69 insertions(+), 39 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 8a1eca381..7d3637482 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -686,12 +686,12 @@ Released 2019-10-24, tagged as make them usable in more contexts - @ref Math::Vector::min(), @ref Math::Vector::max(), @ref Math::Vector::minmax() and batch - @ref Math::min(Containers::StridedArrayView1D), - @ref Math::max(Containers::StridedArrayView1D) and - @ref Math::minmax(Containers::StridedArrayView1D) functions now + @ref Math::min(const Containers::StridedArrayView1D&), + @ref Math::max(const Containers::StridedArrayView1D&) and + @ref Math::minmax(const Containers::StridedArrayView1D&) functions now ignore NaNs in the data, if possible. Use @ref Math::isNan(const Vector&) or the batch - @ref Math::isNan(Containers::StridedArrayView1D) to detect + @ref Math::isNan(const Containers::StridedArrayView1D&) to detect presence of NaN values if needed. - Changed the way @ref Math::operator<<(Corrade::Utility::Debug&, const BoolVector&) works --- the output now has the same bit order as when constructing it @@ -963,13 +963,13 @@ Released 2019-10-24, tagged as - @cpp Math::Frustum::planes() @ce are deprecated due to redundancy, use either @ref Math::Frustum::operator[](), @ref Math::Frustum::data() or range access using @ref Math::Frustum::begin() / @ref Math::Frustum::end() -- Batch @ref Math::min(Containers::StridedArrayView1D), - @ref Math::max(Containers::StridedArrayView1D) and - @ref Math::minmax(Containers::StridedArrayView1D) are moved to a - new @ref Magnum/Math/FunctionsBatch.h header in order to speed up compile - times. This header is included from @ref Magnum/Math/FunctionsBatch.h when - building with @ref MAGNUM_BUILD_DEPRECATED enabled, include it explicitly - to ensure forward compatibility +- Batch @ref Math::min(const Containers::StridedArrayView1D&), + @ref Math::max(const Containers::StridedArrayView1D&) and + @ref Math::minmax(const Containers::StridedArrayView1D&) are moved + to a new @ref Magnum/Math/FunctionsBatch.h header in order to speed up + compile times. This header is included from @ref Magnum/Math/FunctionsBatch.h + when building with @ref MAGNUM_BUILD_DEPRECATED enabled, include it + explicitly to ensure forward compatibility - @cpp Trade::ImporterFileCallbackPolicy @ce is deprecated as it was moved to @ref InputFileCallbackPolicy in the root namespace to be shared with APIs outside of the @ref Trade namespace. Moreover, diff --git a/src/Magnum/Math/Functions.h b/src/Magnum/Math/Functions.h index 6270876e9..d6d699c6d 100644 --- a/src/Magnum/Math/Functions.h +++ b/src/Magnum/Math/Functions.h @@ -189,7 +189,7 @@ the operations component-wise. @m_since{2019,10} @see @ref isNan(), @ref Constants::inf(), - @ref isInf(Corrade::Containers::StridedArrayView1D) + @ref isInf(const Corrade::Containers::StridedArrayView1D&) */ template inline typename std::enable_if::value, bool>::type isInf(T value) { return std::isinf(UnderlyingTypeOf(value)); @@ -212,7 +212,7 @@ template inline BoolVector isInf(const Vector) + @ref isNan(const Corrade::Containers::StridedArrayView1D&) */ /* defined in Vector.h */ template typename std::enable_if::value, bool>::type isNan(T value); @@ -233,7 +233,7 @@ template inline BoolVector isNan(const VectorNaNs passed in the @p value parameter are propagated. @see @ref max(), @ref minmax(), @ref clamp(), - @ref min(Corrade::Containers::StridedArrayView1D), + @ref min(const Corrade::Containers::StridedArrayView1D&), @ref Vector::min() */ /* defined in Vector.h */ @@ -260,7 +260,7 @@ template inline Vector min(const VectorNaNs passed in the @p value parameter are propagated. @see @ref min(), @ref minmax(), @ref clamp(), - @ref max(Corrade::Containers::StridedArrayView1D), + @ref max(const Corrade::Containers::StridedArrayView1D&), @ref Vector::max() */ /* defined in Vector.h */ @@ -286,7 +286,7 @@ template inline Vector max(const Vector), + @ref minmax(const Corrade::Containers::StridedArrayView1D&), @ref Vector::minmax(), @ref Range::Range(const std::pair&) */ diff --git a/src/Magnum/Math/FunctionsBatch.h b/src/Magnum/Math/FunctionsBatch.h index c6b42c593..c9990aa62 100644 --- a/src/Magnum/Math/FunctionsBatch.h +++ b/src/Magnum/Math/FunctionsBatch.h @@ -62,7 +62,7 @@ set to @cpp 1 @ce if any value has that component infinite. If the range is empty, returns @cpp false @ce or a @ref BoolVector with no bits set. @see @ref isInf(T), @ref Constants::inf() */ -template auto isInf(Corrade::Containers::StridedArrayView1D range) -> decltype(isInf(std::declval())) { +template auto isInf(const Corrade::Containers::StridedArrayView1D& range) -> decltype(isInf(std::declval())) { if(range.empty()) return {}; /* For scalars, this loop exits once any value is infinity. For vectors @@ -86,17 +86,23 @@ 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}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return isInf(Corrade::Containers::StridedArrayView1D{range}); } /** @overload */ template inline auto isInf(std::initializer_list list) -> decltype(isInf(std::declval())) { - return isInf(Corrade::Containers::stridedArrayView(list)); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return isInf(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline auto isInf(const T(&array)[size]) -> decltype(isInf(std::declval())) { - return isInf(Corrade::Containers::StridedArrayView1D{array}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return isInf(Corrade::Containers::StridedArrayView1D{array}); } /** @@ -108,7 +114,7 @@ set to @cpp 1 @ce if any value has that component NaN. If the range is empty, returns @cpp false @ce or a @ref BoolVector with no bits set. @see @ref isNan(T), @ref Constants::nan() */ -template inline auto isNan(Corrade::Containers::StridedArrayView1D range) -> decltype(isNan(std::declval())) { +template inline auto isNan(const Corrade::Containers::StridedArrayView1D& range) -> decltype(isNan(std::declval())) { if(range.empty()) return {}; /* For scalars, this loop exits once any value is infinity. For vectors @@ -133,17 +139,23 @@ above overload. Works with any type that's convertible to */ /* See isInf() for why arrayView() and not stridedArrayView() */ template()))> inline auto isNan(Iterable&& range) -> decltype(isNan(std::declval())) { - return isNan(Corrade::Containers::StridedArrayView1D{range}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return isNan(Corrade::Containers::StridedArrayView1D{range}); } /** @overload */ template inline auto isNan(std::initializer_list list) -> decltype(isNan(std::declval())) { - return isNan(Corrade::Containers::stridedArrayView(list)); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return isNan(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline auto isNan(const T(&array)[size]) -> decltype(isNan(std::declval())) { - return isNan(Corrade::Containers::StridedArrayView1D{array}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return isNan(Corrade::Containers::StridedArrayView1D{array}); } namespace Implementation { @@ -185,9 +197,9 @@ namespace Implementation { If the range is empty, returns default-constructed value. NaNs are ignored, unless the range is all NaNs. -@see @ref min(T, T), @ref isNan(Corrade::Containers::StridedArrayView1D) +@see @ref min(T, T), @ref isNan(const Corrade::Containers::StridedArrayView1D&) */ -template inline T min(Corrade::Containers::StridedArrayView1D range) { +template inline T min(const Corrade::Containers::StridedArrayView1D& range) { if(range.empty()) return {}; std::pair iOut = Implementation::firstNonNan(range, IsFloatingPoint{}, IsVector{}); @@ -206,17 +218,23 @@ 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}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return min(Corrade::Containers::StridedArrayView1D{range}); } /** @overload */ template inline T min(std::initializer_list list) { - return min(Corrade::Containers::stridedArrayView(list)); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return min(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline T min(const T(&array)[size]) { - return min(Corrade::Containers::StridedArrayView1D{array}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return min(Corrade::Containers::StridedArrayView1D{array}); } /** @@ -224,9 +242,9 @@ template inline T min(const T(&array)[size]) { If the range is empty, returns default-constructed value. NaNs are ignored, unless the range is all NaNs. -@see @ref max(T, T), @ref isNan(Corrade::Containers::StridedArrayView1D) +@see @ref max(T, T), @ref isNan(const Corrade::Containers::StridedArrayView1D&) */ -template inline T max(Corrade::Containers::StridedArrayView1D range) { +template inline T max(const Corrade::Containers::StridedArrayView1D& range) { if(range.empty()) return {}; std::pair iOut = Implementation::firstNonNan(range, IsFloatingPoint{}, IsVector{}); @@ -245,17 +263,23 @@ 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}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return max(Corrade::Containers::StridedArrayView1D{range}); } /** @overload */ template inline T max(std::initializer_list list) { - return max(Corrade::Containers::stridedArrayView(list)); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return max(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline T max(const T(&array)[size]) { - return max(Corrade::Containers::StridedArrayView1D{array}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return max(Corrade::Containers::StridedArrayView1D{array}); } namespace Implementation { @@ -278,9 +302,9 @@ If the range is empty, returns default-constructed values. NaNs are ignored, unless the range is all NaNs. @see @ref minmax(T, T), @ref Range::Range(const std::pair&), - @ref isNan(Corrade::Containers::StridedArrayView1D) + @ref isNan(const Corrade::Containers::StridedArrayView1D&) */ -template inline std::pair minmax(Corrade::Containers::StridedArrayView1D range) { +template inline std::pair minmax(const Corrade::Containers::StridedArrayView1D& range) { if(range.empty()) return {}; std::pair iOut = Implementation::firstNonNan(range, IsFloatingPoint{}, IsVector{}); @@ -300,17 +324,23 @@ 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}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return minmax(Corrade::Containers::StridedArrayView1D{range}); } /** @overload */ template inline std::pair minmax(std::initializer_list list) { - return minmax(Corrade::Containers::stridedArrayView(list)); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return minmax(Corrade::Containers::stridedArrayView(list)); } /** @overload */ template inline std::pair minmax(const T(&array)[size]) { - return minmax(Corrade::Containers::StridedArrayView1D{array}); + /* Specifying the template explicitly to avoid recursion into the generic + function again */ + return minmax(Corrade::Containers::StridedArrayView1D{array}); } /*@}*/