From 8f513b1001ddabd3af943aac985b5efab11f0699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 2 Sep 2013 22:32:53 +0200 Subject: [PATCH] Math: added bitwise operations for integer Vector. --- src/Math/Test/VectorTest.cpp | 41 +++++- src/Math/Vector.h | 242 +++++++++++++++++++++++++++++++++++ 2 files changed, 282 insertions(+), 1 deletion(-) diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index b6484e5e6..b12a6a4da 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/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::value)); CORRADE_VERIFY((std::is_same::value)); - /* Integer multiplication/division */ + /* Bitwise operations */ const Vec2i ci; Vec2i i; + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same> 1), Vec2i>::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY((std::is_same>= 1), Vec2i&>::value)); + + /* Integer multiplication/division */ CORRADE_VERIFY((std::is_same::value)); CORRADE_VERIFY((std::is_same::value)); CORRADE_VERIFY((std::is_same::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)); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 28dc4daf8..dc5980e0f 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -563,6 +563,210 @@ template inline Vector operator/( return out; } +/** @relates Vector +@brief Bitwise NOT of integral vector +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value, Vector>::type +#endif +operator~(const Vector& vector) { + Vector 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 inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value, Vector&>::type +#endif +operator&=(Vector& a, const Vector& 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 inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value, Vector>::type +#endif +operator&(const Vector& a, const Vector& b) { + Vector copy(a); + return copy &= b; +} + +/** @relates Vector +@brief Do bitwise OR of two integral vectors and assign + +The computation is done in-place. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value, Vector&>::type +#endif +operator|=(Vector& a, const Vector& 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 inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value, Vector>::type +#endif +operator|(const Vector& a, const Vector& b) { + Vector copy(a); + return copy |= b; +} + +/** @relates Vector +@brief Do bitwise XOR of two integral vectors and assign + +The computation is done in-place. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value, Vector&>::type +#endif +operator^=(Vector& a, const Vector& 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 inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value, Vector>::type +#endif +operator^(const Vector& a, const Vector& b) { + Vector copy(a); + return copy ^= b; +} + +/** @relates Vector +@brief Do bitwise left shift of integral vector and assign + +The computation is done in-place. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value, Vector&>::type +#endif +operator<<=(Vector& vector, + #ifdef DOXYGEN_GENERATING_OUTPUT + Integral + #else + typename std::common_type::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 inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value, Vector>::type +#endif +operator<<(const Vector& vector, + #ifdef DOXYGEN_GENERATING_OUTPUT + Integral + #else + typename std::common_type::type + #endif + shift) +{ + Vector copy(vector); + return copy <<= shift; +} + +/** @relates Vector +@brief Do bitwise right shift of integral vector and assign + +The computation is done in-place. +*/ +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector& +#else +typename std::enable_if::value, Vector&>::type +#endif +operator>>=(Vector& vector, + #ifdef DOXYGEN_GENERATING_OUTPUT + Integral + #else + typename std::common_type::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 inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Vector +#else +typename std::enable_if::value, Vector>::type +#endif +operator>>(const Vector& vector, + #ifdef DOXYGEN_GENERATING_OUTPUT + Integral + #else + typename std::common_type::type + #endif + shift) { + Vector 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&>(vector); \ } \ \ + template inline typename std::enable_if::value, Type>::type operator~(const Type& vector) { \ + return ~static_cast&>(vector); \ + } \ + template inline typename std::enable_if::value, Type&>::type operator&=(Type& a, const Math::Vector& b) { \ + static_cast&>(a) &= b; \ + return a; \ + } \ + template inline typename std::enable_if::value, Type>::type operator&(const Type& a, const Math::Vector& b) { \ + return static_cast&>(a) & b; \ + } \ + template inline typename std::enable_if::value, Type&>::type operator|=(Type& a, const Math::Vector& b) { \ + static_cast&>(a) |= b; \ + return a; \ + } \ + template inline typename std::enable_if::value, Type>::type operator|(const Type& a, const Math::Vector& b) { \ + return static_cast&>(a) | b; \ + } \ + template inline typename std::enable_if::value, Type&>::type operator^=(Type& a, const Math::Vector& b) { \ + static_cast&>(a) ^= b; \ + return a; \ + } \ + template inline typename std::enable_if::value, Type>::type operator^(const Type& a, const Math::Vector& b) { \ + return static_cast&>(a) ^ b; \ + } \ + template inline typename std::enable_if::value, Type&>::type operator<<=(Type& vector, typename std::common_type::type shift) { \ + static_cast&>(vector) <<= shift; \ + return vector; \ + } \ + template inline typename std::enable_if::value, Type>::type operator<<(const Type& vector, typename std::common_type::type shift) { \ + return static_cast&>(vector) << shift; \ + } \ + template inline typename std::enable_if::value, Type&>::type operator>>=(Type& vector, typename std::common_type::type shift) { \ + static_cast&>(vector) >>= shift; \ + return vector; \ + } \ + template inline typename std::enable_if::value, Type>::type operator>>(const Type& vector, typename std::common_type::type shift) { \ + return static_cast&>(vector) >> shift; \ + } \ template inline typename std::enable_if::value && std::is_floating_point::value, Type&>::type operator*=(Type& vector, FloatingPoint number) { \ static_cast&>(vector) *= number; \ return vector; \