diff --git a/doc/changelog.dox b/doc/changelog.dox index 4fba602ca..4c081cd31 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -523,6 +523,8 @@ See also: @subsubsection changelog-latest-changes-math Math library +- Added @ref Math::BitVector::set(std::size_t) and + @ref Math::BitVector::reset(std::size_t) for branchless bit setting - Added @ref Math::castInto() overloads for casting between @ref UnsignedByte and @ref UnsignedShort or @ref Byte and @ref Short, from and to @ref UnsignedLong / @ref Long, between integral types and @ref Double and diff --git a/src/Magnum/Math/BitVector.h b/src/Magnum/Math/BitVector.h index ef50a9e49..41f9fb388 100644 --- a/src/Magnum/Math/BitVector.h +++ b/src/Magnum/Math/BitVector.h @@ -153,7 +153,30 @@ template class BitVector { return (_data[i/8] >> i%8) & 0x01; } - /** @brief Set a bit at given position */ + /** + * @brief Set a bit at given position + * @m_since_latest + */ + BitVector& set(std::size_t i) { + _data[i/8] |= 1 << i%8; + return *this; + } + + /** + * @brief Reset a bit at given position + * @m_since_latest + */ + BitVector& reset(std::size_t i) { + _data[i/8] &= ~(1 << i%8); + return *this; + } + + /** + * @brief Set or reset a bit at given position + * + * Prefer to use @ref set(std::size_t) and @ref reset(std::size_t) + * where possible as that's a simpler operation. + */ BitVector& set(std::size_t i, bool value) { value ? _data[i/8] |= (1 << i%8) : _data[i/8] &= ~(1 << i%8); diff --git a/src/Magnum/Math/Test/BitVectorTest.cpp b/src/Magnum/Math/Test/BitVectorTest.cpp index cf83a50fe..27792ce66 100644 --- a/src/Magnum/Math/Test/BitVectorTest.cpp +++ b/src/Magnum/Math/Test/BitVectorTest.cpp @@ -220,23 +220,30 @@ void BitVectorTest::data() { constexpr bool b = ca[9]; CORRADE_COMPARE(b, true); - BitVector19 a(0x08, 0x03, 0x04); - a.set(15, true); - CORRADE_VERIFY(a[15]); - CORRADE_COMPARE(a, BitVector19(0x08, 0x83, 0x04)); - a.set(15, false); - CORRADE_VERIFY(!a[15]); - CORRADE_COMPARE(a, BitVector19(0x08, 0x03, 0x04)); + BitVector19 a1(0x08, 0x03, 0x04); + BitVector19 a2(0x08, 0x03, 0x04); + a1.set(15); + a2.set(15, true); + CORRADE_VERIFY(a1[15]); + CORRADE_VERIFY(a2[15]); + CORRADE_COMPARE(a1, BitVector19(0x08, 0x83, 0x04)); + CORRADE_COMPARE(a2, BitVector19(0x08, 0x83, 0x04)); + a1.reset(15); + a2.set(15, false); + CORRADE_VERIFY(!a1[15]); + CORRADE_VERIFY(!a2[15]); + CORRADE_COMPARE(a1, BitVector19(0x08, 0x03, 0x04)); + CORRADE_COMPARE(a2, BitVector19(0x08, 0x03, 0x04)); #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */ constexpr #endif UnsignedByte c = *ca.data(); - CORRADE_COMPARE(a.data()[1], 0x03); + CORRADE_COMPARE(a1.data()[1], 0x03); CORRADE_COMPARE(c, 0x08); /* It actually returns an array */ - CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3); + CORRADE_COMPARE(Corrade::Containers::arraySize(a1.data()), 3); CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3); } @@ -336,12 +343,12 @@ void BitVectorTest::booleanOperationEquivalents() { void BitVectorTest::strictWeakOrdering() { BitVector<11> a, b, c; - a.set(0, true); - a.set(1, true); + a.set(0); + a.set(1); - c.set(7, true); + c.set(7); - b.set(8, true); + b.set(8); StrictWeakOrdering o; CORRADE_VERIFY( o(b, a)); @@ -353,8 +360,8 @@ void BitVectorTest::strictWeakOrdering() { CORRADE_VERIFY(!o(a, a)); /* Check uninitialized padding reads */ - a.set(8, true); - a.set(10, true); + a.set(8); + a.set(10); b = a; a.data()[1] |= 0x08; b.data()[1] |= 0x20;