Browse Source

Math: added batch isInf() and isNan().

pull/342/head
Vladimír Vondruš 7 years ago
parent
commit
d38303505d
  1. 1
      doc/changelog.dox
  2. 6
      src/Magnum/Math/Functions.h
  3. 68
      src/Magnum/Math/FunctionsBatch.h
  4. 52
      src/Magnum/Math/Test/FunctionsBatchTest.cpp

1
doc/changelog.dox

@ -126,6 +126,7 @@ See also:
- New @ref Math::IsScalar, @ref Math::IsVector, @ref Math::IsIntegral,
@ref Math::IsFloatingPoint and @ref Math::IsUnitless type traits and a
@ref Math::UnderlyingTypeOf utility
- Added batch versions of @ref Math::isInf() and @ref Math::isNan()
@subsubsection changelog-latest-new-platform Platform libraries

6
src/Magnum/Math/Functions.h

@ -160,7 +160,8 @@ the operations component-wise.
/**
@brief If given number is a positive or negative infinity
@see @ref isNan(), @ref Constants::inf()
@see @ref isNan(), @ref Constants::inf(),
@ref isInf(Corrade::Containers::ArrayView<const T>)
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isInf(T value) {
return std::isinf(UnderlyingTypeOf<T>(value));
@ -178,7 +179,8 @@ template<std::size_t size, class T> inline BoolVector<size> isInf(const Vector<s
@brief If given number is a NaN
Equivalent to @cpp value != value @ce.
@see @ref isInf(), @ref Constants::nan()
@see @ref isInf(), @ref Constants::nan(),
@ref isNan(Corrade::Containers::ArrayView<const T>)
*/
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isNan(T value) {
return std::isnan(UnderlyingTypeOf<T>(value));

68
src/Magnum/Math/FunctionsBatch.h

@ -43,6 +43,74 @@ These functions process an ubounded range of values, as opposed to single
vectors or scalars.
*/
/**
@brief If any number in the range is a positive or negative infinity
For scalar types returns @cpp true @ce as soon as it finds an infinite value,
@cpp false @ce otherwise. For vector types, returns @ref BoolVector with bits
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::ArrayView<const T> range) -> decltype(isInf(std::declval<T>())) {
if(range.empty()) return {};
/* For scalars, this loop exits once any value is infinity. For vectors
the loop accumulates the bits and exits as soon as all bits are set
or the input is exhausted */
auto out = isInf(range[0]); /* bool or BoolVector */
for(std::size_t i = 1; i != range.size(); ++i) {
if(out) break;
out = out || isInf(range[i]);
}
return out;
}
/** @overload */
template<class T> inline auto isInf(std::initializer_list<T> list) -> decltype(isInf(std::declval<T>())) {
return isInf(Corrade::Containers::arrayView(list.begin(), list.size()));
}
/** @overload */
template<class T, std::size_t size> inline auto isInf(const T(&array)[size]) -> decltype(isInf(std::declval<T>())) {
return isInf(Corrade::Containers::arrayView(array));
}
/**
@brief If any number in the range is a NaN
For scalar types returns @cpp true @ce as soon as it finds a NaN value,
@cpp false @ce otherwise. For vector types, returns @ref BoolVector with bits
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::ArrayView<const T> range) -> decltype(isNan(std::declval<T>())) {
if(range.empty()) return {};
/* For scalars, this loop exits once any value is infinity. For vectors
the loop accumulates the bits and exits as soon as all bits are set
or the input is exhausted */
auto out = isNan(range[0]); /* bool or BoolVector */
for(std::size_t i = 1; i != range.size(); ++i) {
if(out) break;
out = out || isNan(range[i]);
}
return out;
}
/** @overload */
template<class T> inline auto isNan(std::initializer_list<T> list) -> decltype(isInf(std::declval<T>())) {
return isNan(Corrade::Containers::arrayView(list.begin(), list.size()));
}
/** @overload */
template<class T, std::size_t size> inline bool isNan(const T(&array)[size]) {
return isNan(Corrade::Containers::arrayView(array));
}
/**
@brief Minimum of a range

52
src/Magnum/Math/Test/FunctionsBatchTest.cpp

@ -33,6 +33,9 @@ namespace Magnum { namespace Math { namespace Test { namespace {
struct FunctionsBatchTest: Corrade::TestSuite::Tester {
explicit FunctionsBatchTest();
void isInf();
void isNan();
void min();
void max();
void minmax();
@ -40,15 +43,62 @@ struct FunctionsBatchTest: Corrade::TestSuite::Tester {
using namespace Literals;
typedef Math::Constants<Float> Constants;
typedef Math::Vector2<Float> Vector2;
typedef Math::Vector3<Int> Vector3i;
typedef Math::Vector3<Float> Vector3;
FunctionsBatchTest::FunctionsBatchTest() {
addTests({&FunctionsBatchTest::min,
addTests({&FunctionsBatchTest::isInf,
&FunctionsBatchTest::isNan,
&FunctionsBatchTest::min,
&FunctionsBatchTest::max,
&FunctionsBatchTest::minmax});
}
void FunctionsBatchTest::isInf() {
CORRADE_VERIFY(!Math::isInf({5.0f, -2.0f, 9.0f}));
CORRADE_VERIFY(Math::isInf({5.0f, Constants::inf(), 9.0f}));
CORRADE_COMPARE(Math::isInf({Vector2{5.0f, -3.0f},
Vector2{-2.0f, 14.0f},
Vector2{9.0f, -5.0f}}), BoolVector<2>{0});
CORRADE_COMPARE(Math::isInf({Vector2{5.0f, -3.0f},
Vector2{-2.0f, 14.0f},
Vector2{Constants::inf(), -5.0f}}), BoolVector<2>{1});
CORRADE_VERIFY(!Math::isInf(std::initializer_list<Float>{}));
CORRADE_COMPARE(Math::isInf(std::initializer_list<Vector3>{}), BoolVector<3>{0});
const Float a[]{5.0f, -2.0f, -Constants::inf()};
CORRADE_VERIFY(Math::isInf(a));
const Float b[]{5.0f, -2.0f, -1.0};
CORRADE_VERIFY(!Math::isInf(b));
}
void FunctionsBatchTest::isNan() {
CORRADE_VERIFY(!Math::isNan({5.0f, -2.0f, 9.0f}));
CORRADE_VERIFY(Math::isNan({5.0f, 9.0f, Constants::nan()}));
CORRADE_COMPARE(Math::isNan({Vector2{5.0f, -3.0f},
Vector2{-2.0f, 14.0f},
Vector2{9.0f, -5.0f}}), BoolVector<2>{0});
CORRADE_COMPARE(Math::isNan({Vector2{5.0f, -3.0f},
Vector2{14.0f, Constants::nan()},
Vector2{-2.0f, -5.0f}}), BoolVector<2>{2});
CORRADE_VERIFY(!Math::isNan(std::initializer_list<Double>{}));
CORRADE_COMPARE(Math::isNan(std::initializer_list<Vector3>{}), BoolVector<3>{0});
const Float a[]{5.0f, -Constants::nan(), -2.0f};
CORRADE_VERIFY(Math::isNan(a));
const Float b[]{5.0f, -2.0f, -1.0};
CORRADE_VERIFY(!Math::isNan(b));
}
void FunctionsBatchTest::min() {
CORRADE_COMPARE(Math::min({5, -2, 9}), -2);
CORRADE_COMPARE(Math::min({Vector3i(5, -3, 2),

Loading…
Cancel
Save