Browse Source

Math: added bitwise operations for integer Vector.

pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
8f513b1001
  1. 41
      src/Math/Test/VectorTest.cpp
  2. 242
      src/Math/Vector.h

41
src/Math/Test/VectorTest.cpp

@ -74,6 +74,7 @@ class VectorTest: public Corrade::TestSuite::Tester {
void multiplyDivideIntegral();
void multiplyDivideComponentWise();
void multiplyDivideComponentWiseIntegral();
void bitwise();
void compare();
void compareComponentWise();
@ -127,6 +128,7 @@ VectorTest::VectorTest() {
&VectorTest::multiplyDivideIntegral,
&VectorTest::multiplyDivideComponentWise,
&VectorTest::multiplyDivideComponentWiseIntegral,
&VectorTest::bitwise,
&VectorTest::compare,
&VectorTest::compareComponentWise,
@ -335,6 +337,21 @@ void VectorTest::multiplyDivideComponentWiseIntegral() {
/* Using integer vector as divisor is not supported */
}
void VectorTest::bitwise() {
typedef Math::Vector<2, Int> Vector2i;
const Vector2i a(85, 240);
const Vector2i b(170, 85);
CORRADE_COMPARE(~a, Vector2i(-86, -241));
CORRADE_COMPARE(a & b, Vector2i(0, 80));
CORRADE_COMPARE(a | b, Vector2i(255, 245));
CORRADE_COMPARE(a ^ b, Vector2i(255, 165));
const Vector2i c(7, 32);
CORRADE_COMPARE(c << 2, Vector2i(28, 128));
CORRADE_COMPARE(c >> 2, Vector2i(1, 8));
}
void VectorTest::dot() {
CORRADE_COMPARE(Vector4::dot({1.0f, 0.5f, 0.75f, 1.5f}, {2.0f, 4.0f, 1.0f, 7.0f}), 15.25f);
}
@ -462,9 +479,22 @@ void VectorTest::subclassTypes() {
CORRADE_VERIFY((std::is_same<decltype(a *= c), Vec2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a /= c), Vec2&>::value));
/* Integer multiplication/division */
/* Bitwise operations */
const Vec2i ci;
Vec2i i;
CORRADE_VERIFY((std::is_same<decltype(~ci), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(ci & ci), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(ci | ci), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(ci ^ ci), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(ci << 1), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(ci >> 1), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(i &= ci), Vec2i&>::value));
CORRADE_VERIFY((std::is_same<decltype(i |= ci), Vec2i&>::value));
CORRADE_VERIFY((std::is_same<decltype(i ^= ci), Vec2i&>::value));
CORRADE_VERIFY((std::is_same<decltype(i <<= 1), Vec2i&>::value));
CORRADE_VERIFY((std::is_same<decltype(i >>= 1), Vec2i&>::value));
/* Integer multiplication/division */
CORRADE_VERIFY((std::is_same<decltype(ci*1.0f), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f*ci), Vec2i>::value));
CORRADE_VERIFY((std::is_same<decltype(c*ci), Vec2i>::value));
@ -498,6 +528,15 @@ void VectorTest::subclass() {
CORRADE_COMPARE(Vec2(-2.0f, 5.0f)*Vec2(1.5f, -2.0f), Vec2(-3.0f, -10.0f));
CORRADE_COMPARE(Vec2(-2.0f, 5.0f)/Vec2(2.0f/3.0f, -0.5f), Vec2(-3.0f, -10.0f));
/* Bitwise operations */
CORRADE_COMPARE(~Vec2i(85, 240), Vec2i(-86, -241));
CORRADE_COMPARE(Vec2i(85, 240) & Vec2i(170, 85), Vec2i(0, 80));
CORRADE_COMPARE(Vec2i(85, 240) | Vec2i(170, 85), Vec2i(255, 245));
CORRADE_COMPARE(Vec2i(85, 240) ^ Vec2i(170, 85), Vec2i(255, 165));
CORRADE_COMPARE(Vec2i(7, 32) << 2, Vec2i(28, 128));
CORRADE_COMPARE(Vec2i(7, 32) >> 2, Vec2i(1, 8));
/* Integral multiplication/division */
CORRADE_COMPARE(Vec2i(2, 4)*1.5f, Vec2i(3, 6));
CORRADE_COMPARE(1.5f*Vec2i(2, 4), Vec2i(3, 6));

242
src/Math/Vector.h

@ -563,6 +563,210 @@ template<std::size_t size, class T> inline Vector<size, T> operator/(
return out;
}
/** @relates Vector
@brief Bitwise NOT of integral vector
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>>::type
#endif
operator~(const Vector<size, Integral>& vector) {
Vector<size, Integral> out;
for(std::size_t i = 0; i != size; ++i)
out[i] = ~vector[i];
return out;
}
/** @relates Vector
@brief Do bitwise AND of two integral vectors and assign
The computation is done in-place.
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>&>::type
#endif
operator&=(Vector<size, Integral>& a, const Vector<size, Integral>& b) {
for(std::size_t i = 0; i != size; ++i)
a[i] &= b[i];
return a;
}
/** @relates Vector
@brief Bitwise AND of two integral vectors
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>>::type
#endif
operator&(const Vector<size, Integral>& a, const Vector<size, Integral>& b) {
Vector<size, Integral> copy(a);
return copy &= b;
}
/** @relates Vector
@brief Do bitwise OR of two integral vectors and assign
The computation is done in-place.
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>&>::type
#endif
operator|=(Vector<size, Integral>& a, const Vector<size, Integral>& b) {
for(std::size_t i = 0; i != size; ++i)
a[i] |= b[i];
return a;
}
/** @relates Vector
@brief Bitwise OR of two integral vectors
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>>::type
#endif
operator|(const Vector<size, Integral>& a, const Vector<size, Integral>& b) {
Vector<size, Integral> copy(a);
return copy |= b;
}
/** @relates Vector
@brief Do bitwise XOR of two integral vectors and assign
The computation is done in-place.
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>&>::type
#endif
operator^=(Vector<size, Integral>& a, const Vector<size, Integral>& b) {
for(std::size_t i = 0; i != size; ++i)
a[i] ^= b[i];
return a;
}
/** @relates Vector
@brief Bitwise XOR of two integral vectors
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>>::type
#endif
operator^(const Vector<size, Integral>& a, const Vector<size, Integral>& b) {
Vector<size, Integral> copy(a);
return copy ^= b;
}
/** @relates Vector
@brief Do bitwise left shift of integral vector and assign
The computation is done in-place.
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>&>::type
#endif
operator<<=(Vector<size, Integral>& vector,
#ifdef DOXYGEN_GENERATING_OUTPUT
Integral
#else
typename std::common_type<Integral>::type
#endif
shift)
{
for(std::size_t i = 0; i != size; ++i)
vector[i] <<= shift;
return vector;
}
/** @relates Vector
@brief Bitwise left shift of integral vector
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>>::type
#endif
operator<<(const Vector<size, Integral>& vector,
#ifdef DOXYGEN_GENERATING_OUTPUT
Integral
#else
typename std::common_type<Integral>::type
#endif
shift)
{
Vector<size, Integral> copy(vector);
return copy <<= shift;
}
/** @relates Vector
@brief Do bitwise right shift of integral vector and assign
The computation is done in-place.
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>&
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>&>::type
#endif
operator>>=(Vector<size, Integral>& vector,
#ifdef DOXYGEN_GENERATING_OUTPUT
Integral
#else
typename std::common_type<Integral>::type
#endif
shift) {
for(std::size_t i = 0; i != size; ++i)
vector[i] >>= shift;
return vector;
}
/** @relates Vector
@brief Bitwise left shift of integral vector
*/
template<std::size_t size, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT
Vector<size, Integral>
#else
typename std::enable_if<std::is_integral<Integral>::value, Vector<size, Integral>>::type
#endif
operator>>(const Vector<size, Integral>& vector,
#ifdef DOXYGEN_GENERATING_OUTPUT
Integral
#else
typename std::common_type<Integral>::type
#endif
shift) {
Vector<size, Integral> copy(vector);
return copy >>= shift;
}
/** @relates Vector
@brief Multiply integral vector with floating-point number and assign
@ -853,6 +1057,44 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
return number/static_cast<const Math::Vector<size, T>&>(vector); \
} \
\
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator~(const Type<Integral>& vector) { \
return ~static_cast<const Math::Vector<size, Integral>&>(vector); \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator&=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) &= b; \
return a; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator&(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a) & b; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator|=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) |= b; \
return a; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator|(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a) | b; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator^=(Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
static_cast<Math::Vector<size, Integral>&>(a) ^= b; \
return a; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator^(const Type<Integral>& a, const Math::Vector<size, Integral>& b) { \
return static_cast<const Math::Vector<size, Integral>&>(a) ^ b; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator<<=(Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \
static_cast<Math::Vector<size, Integral>&>(vector) <<= shift; \
return vector; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator<<(const Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \
return static_cast<const Math::Vector<size, Integral>&>(vector) << shift; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>&>::type operator>>=(Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \
static_cast<Math::Vector<size, Integral>&>(vector) >>= shift; \
return vector; \
} \
template<class Integral> inline typename std::enable_if<std::is_integral<Integral>::value, Type<Integral>>::type operator>>(const Type<Integral>& vector, typename std::common_type<Integral>::type shift) { \
return static_cast<const Math::Vector<size, Integral>&>(vector) >> shift; \
} \
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_integral<Integral>::value && std::is_floating_point<FloatingPoint>::value, Type<Integral>&>::type operator*=(Type<Integral>& vector, FloatingPoint number) { \
static_cast<Math::Vector<size, Integral>&>(vector) *= number; \
return vector; \

Loading…
Cancel
Save