Browse Source

Math: added component-wise equal()/notEqual() for vectors.

pull/364/head
Vladimír Vondruš 7 years ago
parent
commit
3cf9dbf409
  1. 3
      doc/changelog.dox
  2. 10
      src/Magnum/Math/Test/VectorTest.cpp
  3. 59
      src/Magnum/Math/Vector.h

3
doc/changelog.dox

@ -160,6 +160,9 @@ See also:
@ref Math::IsFloatingPoint and @ref Math::IsUnitless type traits and a @ref Math::IsFloatingPoint and @ref Math::IsUnitless type traits and a
@ref Math::UnderlyingTypeOf utility @ref Math::UnderlyingTypeOf utility
- Added batch versions of @ref Math::isInf() and @ref Math::isNan() - Added batch versions of @ref Math::isInf() and @ref Math::isNan()
- @ref Math::equal() and @ref Math::notEqual() for component-wise comparison
of @ref Math::Vector, as the equality/non-equality operators return a
single @cpp bool @ce
@subsubsection changelog-latest-new-meshtools MeshTools library @subsubsection changelog-latest-new-meshtools MeshTools library

10
src/Magnum/Math/Test/VectorTest.cpp

@ -343,6 +343,16 @@ void VectorTest::compare() {
void VectorTest::compareComponentWise() { void VectorTest::compareComponentWise() {
typedef BoolVector<3> BoolVector3; typedef BoolVector<3> BoolVector3;
typedef BoolVector<4> BoolVector4;
Vector4 a{1.0f, -3.5f, 5.0f, -10.0f};
Vector4 b{1.0f + TypeTraits<Float>::epsilon()/2, -3.5f, 5.0f - TypeTraits<Float>::epsilon()*2, -10.0f};
Vector4 c{1.0f + TypeTraits<Float>::epsilon()*2, -3.5f, 5.0f - TypeTraits<Float>::epsilon()*10, -10.0f};
CORRADE_COMPARE(equal(a, b), BoolVector4{0xf});
CORRADE_COMPARE(equal(a, c), BoolVector4{0xa});
CORRADE_COMPARE(notEqual(a, b), BoolVector4{0x0});
CORRADE_COMPARE(notEqual(a, c), BoolVector4{0x5});
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) < Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x1)); CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) < Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x1));
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) <= Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x3)); CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) <= Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x3));
CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) >= Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x6)); CORRADE_COMPARE(Vector3(1.0f, -1.0f, 5.0f) >= Vector3(1.1f, -1.0f, 3.0f), BoolVector3(0x6));

59
src/Magnum/Math/Vector.h

@ -48,13 +48,13 @@ namespace Magnum { namespace Math {
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isNan(T value) { template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isNan(T value) {
return std::isnan(UnderlyingTypeOf<T>(value)); return std::isnan(UnderlyingTypeOf<T>(value));
} }
/* Keeping the same parameter names as in Functions.h so the note about
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type min(T a, T b) { NaN propagation works here too */
return b < a ? b : a; template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type min(T value, T min) {
return min < value ? min : value;
} }
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type max(T value, T max) {
template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type max(T a, T b) { return value < max ? max : value;
return a < b ? b : a;
} }
#endif #endif
@ -237,7 +237,11 @@ template<std::size_t size, class T> class Vector {
T& operator[](std::size_t pos) { return _data[pos]; } T& operator[](std::size_t pos) { return _data[pos]; }
constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */ constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */
/** @brief Equality comparison */ /**
* @brief Equality comparison
*
* @see @ref Math::equal()
*/
bool operator==(const Vector<size, T>& other) const { bool operator==(const Vector<size, T>& other) const {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
if(!TypeTraits<T>::equals(_data[i], other._data[i])) return false; if(!TypeTraits<T>::equals(_data[i], other._data[i])) return false;
@ -245,7 +249,11 @@ template<std::size_t size, class T> class Vector {
return true; return true;
} }
/** @brief Non-equality comparison */ /**
* @brief Non-equality comparison
*
* @see @ref Math::notEqual()
*/
bool operator!=(const Vector<size, T>& other) const { bool operator!=(const Vector<size, T>& other) const {
return !operator==(other); return !operator==(other);
} }
@ -640,6 +648,11 @@ template<std::size_t size, class T> class Vector {
template<std::size_t, class> friend class Matrix; template<std::size_t, class> friend class Matrix;
template<std::size_t, class> friend struct Implementation::MatrixDeterminant; template<std::size_t, class> friend struct Implementation::MatrixDeterminant;
/* So the out-of-class comparators can access data directly to avoid
function call overhead */
template<std::size_t size_, class T_> friend BoolVector<size_> equal(const Vector<size_, T_>&, const Vector<size_, T_>&);
template<std::size_t size_, class T_> friend BoolVector<size_> notEqual(const Vector<size_, T_>&, const Vector<size_, T_>&);
/* Implementation for Vector<size, T>::Vector(const Vector<size, U>&) */ /* Implementation for Vector<size, T>::Vector(const Vector<size, U>&) */
template<class U, std::size_t ...sequence> constexpr explicit Vector(Implementation::Sequence<sequence...>, const Vector<size, U>& vector) noexcept: _data{T(vector._data[sequence])...} {} template<class U, std::size_t ...sequence> constexpr explicit Vector(Implementation::Sequence<sequence...>, const Vector<size, U>& vector) noexcept: _data{T(vector._data[sequence])...} {}
@ -655,6 +668,36 @@ template<std::size_t size, class T> class Vector {
} }
}; };
/** @relatesalso Vector
@brief Component-wise equality comparison
Unlike @ref Vector::operator==() returns a @ref BoolVector instead of a single
value.
*/
template<std::size_t size, class T> inline BoolVector<size> equal(const Vector<size, T>& a, const Vector<size, T>& b) {
BoolVector<size> out;
for(std::size_t i = 0; i != size; ++i)
out.set(i, TypeTraits<T>::equals(a._data[i], b._data[i]));
return out;
}
/** @relatesalso Vector
@brief Component-wise non-equality comparison
Unlike @ref Vector::operator!=() returns a @ref BoolVector instead of a single
value.
*/
template<std::size_t size, class T> inline BoolVector<size> notEqual(const Vector<size, T>& a, const Vector<size, T>& b) {
BoolVector<size> out;
for(std::size_t i = 0; i != size; ++i)
out.set(i, !TypeTraits<T>::equals(a._data[i], b._data[i]));
return out;
}
/** @relates Vector /** @relates Vector
@brief Multiply a scalar with a vector @brief Multiply a scalar with a vector

Loading…
Cancel
Save