Browse Source

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.
mousecapture
Vladimír Vondruš 6 years ago
parent
commit
92b1cdf6b7
  1. 22
      doc/changelog.dox
  2. 10
      src/Magnum/Math/Functions.h
  3. 76
      src/Magnum/Math/FunctionsBatch.h

22
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<const T>),
@ref Math::max(Containers::StridedArrayView1D<const T>) and
@ref Math::minmax(Containers::StridedArrayView1D<const T>) functions now
@ref Math::min(const Containers::StridedArrayView1D<const T>&),
@ref Math::max(const Containers::StridedArrayView1D<const T>&) and
@ref Math::minmax(const Containers::StridedArrayView1D<const T>&) functions now
ignore NaNs in the data, if possible. Use
@ref Math::isNan(const Vector<size, T>&) or the batch
@ref Math::isNan(Containers::StridedArrayView1D<const T>) to detect
@ref Math::isNan(const Containers::StridedArrayView1D<const T>&) to detect
presence of NaN values if needed.
- Changed the way @ref Math::operator<<(Corrade::Utility::Debug&, const BoolVector<size>&)
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<const T>),
@ref Math::max(Containers::StridedArrayView1D<const T>) and
@ref Math::minmax(Containers::StridedArrayView1D<const T>) 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<const T>&),
@ref Math::max(const Containers::StridedArrayView1D<const T>&) and
@ref Math::minmax(const Containers::StridedArrayView1D<const T>&) 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,

10
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<const T>)
@ref isInf(const Corrade::Containers::StridedArrayView1D<const T>&)
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isInf(T value) {
return std::isinf(UnderlyingTypeOf<T>(value));
@ -212,7 +212,7 @@ template<std::size_t size, class T> inline BoolVector<size> isInf(const Vector<s
Equivalent to @cpp value != value @ce.
@see @ref isInf(), @ref Constants::nan(),
@ref isNan(Corrade::Containers::StridedArrayView1D<const T>)
@ref isNan(const Corrade::Containers::StridedArrayView1D<const T>&)
*/
/* defined in Vector.h */
template<class T> typename std::enable_if<IsScalar<T>::value, bool>::type isNan(T value);
@ -233,7 +233,7 @@ template<std::size_t size, class T> inline BoolVector<size> isNan(const Vector<s
<em>NaN</em>s passed in the @p value parameter are propagated.
@see @ref max(), @ref minmax(), @ref clamp(),
@ref min(Corrade::Containers::StridedArrayView1D<const T>),
@ref min(const Corrade::Containers::StridedArrayView1D<const T>&),
@ref Vector::min()
*/
/* defined in Vector.h */
@ -260,7 +260,7 @@ template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size
<em>NaN</em>s passed in the @p value parameter are propagated.
@see @ref min(), @ref minmax(), @ref clamp(),
@ref max(Corrade::Containers::StridedArrayView1D<const T>),
@ref max(const Corrade::Containers::StridedArrayView1D<const T>&),
@ref Vector::max()
*/
/* defined in Vector.h */
@ -286,7 +286,7 @@ template<std::size_t size, class T> inline Vector<size, T> max(const Vector<size
@brief Minimum and maximum of two values
@see @ref min(), @ref max(), @ref clamp(),
@ref minmax(Corrade::Containers::StridedArrayView1D<const T>),
@ref minmax(const Corrade::Containers::StridedArrayView1D<const T>&),
@ref Vector::minmax(),
@ref Range::Range(const std::pair<VectorType, VectorType>&)
*/

76
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<class T> auto isInf(Corrade::Containers::StridedArrayView1D<const T> range) -> decltype(isInf(std::declval<T>())) {
template<class T> auto isInf(const Corrade::Containers::StridedArrayView1D<const T>& range) -> decltype(isInf(std::declval<T>())) {
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<class Iterable, class T = decltype(Implementation::stridedArrayViewTypeFor(std::declval<Iterable&&>()))> inline auto isInf(Iterable&& range) -> decltype(isInf(std::declval<T>())) {
return isInf(Corrade::Containers::StridedArrayView1D<const T>{range});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return isInf<T>(Corrade::Containers::StridedArrayView1D<const T>{range});
}
/** @overload */
template<class T> inline auto isInf(std::initializer_list<T> list) -> decltype(isInf(std::declval<T>())) {
return isInf(Corrade::Containers::stridedArrayView(list));
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return isInf<T>(Corrade::Containers::stridedArrayView(list));
}
/** @overload */
template<class T, std::size_t size> inline auto isInf(const T(&array)[size]) -> decltype(isInf(std::declval<T>())) {
return isInf(Corrade::Containers::StridedArrayView1D<const T>{array});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return isInf<T>(Corrade::Containers::StridedArrayView1D<const T>{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<class T> inline auto isNan(Corrade::Containers::StridedArrayView1D<const T> range) -> decltype(isNan(std::declval<T>())) {
template<class T> inline auto isNan(const Corrade::Containers::StridedArrayView1D<const T>& range) -> decltype(isNan(std::declval<T>())) {
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<class Iterable, class T = decltype(Implementation::stridedArrayViewTypeFor(std::declval<Iterable&&>()))> inline auto isNan(Iterable&& range) -> decltype(isNan(std::declval<T>())) {
return isNan(Corrade::Containers::StridedArrayView1D<const T>{range});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return isNan<T>(Corrade::Containers::StridedArrayView1D<const T>{range});
}
/** @overload */
template<class T> inline auto isNan(std::initializer_list<T> list) -> decltype(isNan(std::declval<T>())) {
return isNan(Corrade::Containers::stridedArrayView(list));
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return isNan<T>(Corrade::Containers::stridedArrayView(list));
}
/** @overload */
template<class T, std::size_t size> inline auto isNan(const T(&array)[size]) -> decltype(isNan(std::declval<T>())) {
return isNan(Corrade::Containers::StridedArrayView1D<const T>{array});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return isNan<T>(Corrade::Containers::StridedArrayView1D<const T>{array});
}
namespace Implementation {
@ -185,9 +197,9 @@ namespace Implementation {
If the range is empty, returns default-constructed value. <em>NaN</em>s are
ignored, unless the range is all <em>NaN</em>s.
@see @ref min(T, T), @ref isNan(Corrade::Containers::StridedArrayView1D<const T>)
@see @ref min(T, T), @ref isNan(const Corrade::Containers::StridedArrayView1D<const T>&)
*/
template<class T> inline T min(Corrade::Containers::StridedArrayView1D<const T> range) {
template<class T> inline T min(const Corrade::Containers::StridedArrayView1D<const T>& range) {
if(range.empty()) return {};
std::pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{});
@ -206,17 +218,23 @@ above overload. Works with any type that's convertible to
@ref Corrade::Containers::StridedArrayView.
*/
template<class Iterable, class T = decltype(Implementation::stridedArrayViewTypeFor(std::declval<Iterable&&>()))> inline T min(Iterable&& range) {
return min(Corrade::Containers::StridedArrayView1D<const T>{range});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return min<T>(Corrade::Containers::StridedArrayView1D<const T>{range});
}
/** @overload */
template<class T> inline T min(std::initializer_list<T> list) {
return min(Corrade::Containers::stridedArrayView(list));
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return min<T>(Corrade::Containers::stridedArrayView(list));
}
/** @overload */
template<class T, std::size_t size> inline T min(const T(&array)[size]) {
return min(Corrade::Containers::StridedArrayView1D<const T>{array});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return min<T>(Corrade::Containers::StridedArrayView1D<const T>{array});
}
/**
@ -224,9 +242,9 @@ template<class T, std::size_t size> inline T min(const T(&array)[size]) {
If the range is empty, returns default-constructed value. <em>NaN</em>s are
ignored, unless the range is all <em>NaN</em>s.
@see @ref max(T, T), @ref isNan(Corrade::Containers::StridedArrayView1D<const T>)
@see @ref max(T, T), @ref isNan(const Corrade::Containers::StridedArrayView1D<const T>&)
*/
template<class T> inline T max(Corrade::Containers::StridedArrayView1D<const T> range) {
template<class T> inline T max(const Corrade::Containers::StridedArrayView1D<const T>& range) {
if(range.empty()) return {};
std::pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{});
@ -245,17 +263,23 @@ above overload. Works with any type that's convertible to
@ref Corrade::Containers::StridedArrayView.
*/
template<class Iterable, class T = decltype(Implementation::stridedArrayViewTypeFor(std::declval<Iterable&&>()))> inline T max(Iterable&& range) {
return max(Corrade::Containers::StridedArrayView1D<const T>{range});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return max<T>(Corrade::Containers::StridedArrayView1D<const T>{range});
}
/** @overload */
template<class T> inline T max(std::initializer_list<T> list) {
return max(Corrade::Containers::stridedArrayView(list));
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return max<T>(Corrade::Containers::stridedArrayView(list));
}
/** @overload */
template<class T, std::size_t size> inline T max(const T(&array)[size]) {
return max(Corrade::Containers::StridedArrayView1D<const T>{array});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return max<T>(Corrade::Containers::StridedArrayView1D<const T>{array});
}
namespace Implementation {
@ -278,9 +302,9 @@ If the range is empty, returns default-constructed values. <em>NaN</em>s are
ignored, unless the range is all <em>NaN</em>s.
@see @ref minmax(T, T),
@ref Range::Range(const std::pair<VectorType, VectorType>&),
@ref isNan(Corrade::Containers::StridedArrayView1D<const T>)
@ref isNan(const Corrade::Containers::StridedArrayView1D<const T>&)
*/
template<class T> inline std::pair<T, T> minmax(Corrade::Containers::StridedArrayView1D<const T> range) {
template<class T> inline std::pair<T, T> minmax(const Corrade::Containers::StridedArrayView1D<const T>& range) {
if(range.empty()) return {};
std::pair<std::size_t, T> iOut = Implementation::firstNonNan(range, IsFloatingPoint<T>{}, IsVector<T>{});
@ -300,17 +324,23 @@ above overload. Works with any type that's convertible to
@ref Corrade::Containers::StridedArrayView.
*/
template<class Iterable, class T = decltype(Implementation::stridedArrayViewTypeFor(std::declval<Iterable&&>()))> inline std::pair<T, T> minmax(Iterable&& range) {
return minmax(Corrade::Containers::StridedArrayView1D<const T>{range});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return minmax<T>(Corrade::Containers::StridedArrayView1D<const T>{range});
}
/** @overload */
template<class T> inline std::pair<T, T> minmax(std::initializer_list<T> list) {
return minmax(Corrade::Containers::stridedArrayView(list));
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return minmax<T>(Corrade::Containers::stridedArrayView(list));
}
/** @overload */
template<class T, std::size_t size> inline std::pair<T, T> minmax(const T(&array)[size]) {
return minmax(Corrade::Containers::StridedArrayView1D<const T>{array});
/* Specifying the template explicitly to avoid recursion into the generic
function again */
return minmax<T>(Corrade::Containers::StridedArrayView1D<const T>{array});
}
/*@}*/

Loading…
Cancel
Save