Browse Source

Math: new class BoolVector.

Will handle output from various comparison operators in Vector.
pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
dcb4595e6e
  1. 232
      src/Math/BoolVector.h
  2. 1
      src/Math/CMakeLists.txt
  3. 166
      src/Math/Test/BoolVectorTest.cpp
  4. 1
      src/Math/Test/CMakeLists.txt

232
src/Math/BoolVector.h

@ -0,0 +1,232 @@
#ifndef Magnum_Math_BoolVector_h
#define Magnum_Math_BoolVector_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::Math::BoolVector
*/
#include <cstdint>
#include <Utility/Debug.h>
namespace Magnum { namespace Math {
/**
@brief %Vector storing boolean values
@tparam size Bit count
Result of component-wise comparison from Vector. The boolean values are stored
as bits in array of unsigned bytes, unused bits have undefined value which
doesn't affect comparison or all() / none() / any() functions. See also
@ref matrix-vector for brief introduction.
*/
template<std::size_t size> class BoolVector {
static_assert(size != 0, "BoolVector cannot have zero elements");
public:
static const std::size_t Size = size; /**< @brief %Vector size */
static const std::size_t DataSize = (size-1)/8+1; /**< @brief %Vector storage size */
/** @brief Construct boolean with one value for all elements */
inline static BoolVector<size> from(bool value) {
BoolVector<size> out;
for(std::size_t i = 0; i != size; ++i)
out._data[i] = (value ? FullSegmentMask : 0);
return out;
}
/** @brief Construct zero-filled boolean vector */
inline constexpr BoolVector(): _data() {}
/** @brief Construct boolean vector from given values */
template<class ...U> inline constexpr BoolVector(std::uint8_t first, U... next): _data{first, std::uint8_t(next)...} {
static_assert(sizeof...(next)+1 == DataSize, "Improper number of arguments passed to BoolVector constructor");
}
/** @brief Copy constructor */
inline constexpr BoolVector(const BoolVector<size>&) = default;
/** @brief Copy assignment */
inline BoolVector<size>& operator=(const BoolVector<size>&) = default;
/**
* @brief Raw data
* @return %Array of DataSize length
*
* @see operator[](), set()
*/
inline std::uint8_t* data() { return _data; }
inline constexpr const std::uint8_t* data() const { return _data; } /**< @overload */
/** @brief Bit at given position */
inline constexpr bool operator[](std::size_t i) const {
return (_data[i/8] >> i%8) & 0x01;
}
/** @brief Set bit at given position */
inline BoolVector<size>& set(std::size_t i, bool value) {
_data[i/8] |= ((value & 0x01) << i%8);
return *this;
}
/** @brief Equality comparison */
inline bool operator==(const BoolVector<size>& other) const {
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i] != other._data[i]) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask) != (other._data[DataSize-1] & LastSegmentMask))
return false;
return true;
}
/** @brief Non-equality comparison */
inline bool operator!=(const BoolVector<size>& other) const {
return !operator==(other);
}
/** @brief Whether all bits are set */
bool all() const {
/* Check all full segments */
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i] != FullSegmentMask) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask) != LastSegmentMask)
return false;
return true;
}
/** @brief Whether no bits are set */
bool none() const {
/* Check all full segments */
for(std::size_t i = 0; i != size/8; ++i)
if(_data[i]) return false;
/* Check last segment */
if(size%8 && (_data[DataSize-1] & LastSegmentMask))
return false;
return true;
}
/** @brief Whether any bit is set */
inline bool any() const {
return !none();
}
/** @brief Bitwise inversion */
inline BoolVector<size> operator~() const {
BoolVector<size> out;
for(std::size_t i = 0; i != DataSize; ++i)
out._data[i] = ~_data[i];
return out;
}
/**
* @brief Bitwise AND and assign
*
* The computation is done in-place.
*/
inline BoolVector<size>& operator&=(const BoolVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] &= other._data[i];
return *this;
}
/**
* @brief Bitwise AND
*
* @see operator&=()
*/
inline BoolVector<size> operator&(const BoolVector<size>& other) const {
return BoolVector<size>(*this) &= other;
}
/**
* @brief Bitwise OR and assign
*
* The computation is done in-place.
*/
inline BoolVector<size>& operator|=(const BoolVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] |= other._data[i];
return *this;
}
/**
* @brief Bitwise OR
*
* @see operator|=()
*/
inline BoolVector<size> operator|(const BoolVector<size>& other) const {
return BoolVector<size>(*this) |= other;
}
/**
* @brief Bitwise XOR and assign
*
* The computation is done in-place.
*/
inline BoolVector<size>& operator^=(const BoolVector<size>& other) {
for(std::size_t i = 0; i != DataSize; ++i)
_data[i] ^= other._data[i];
return *this;
}
/**
* @brief Bitwise XOR
*
* @see operator^=()
*/
inline BoolVector<size> operator^(const BoolVector<size>& other) const {
return BoolVector<size>(*this) ^= other;
}
private:
enum: std::uint8_t {
FullSegmentMask = 0xFF,
LastSegmentMask = (1 << size%8) - 1
};
std::uint8_t _data[(size-1)/8+1];
};
/** @debugoperator{Magnum::Math::BoolVector} */
template<std::size_t size> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const BoolVector<size>& value) {
debug << "BoolVector(";
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false);
for(std::size_t i = 0; i != size; ++i) {
if(i && !(i%8)) debug << " ";
debug << (value[i] ? "1" : "0");
}
debug << ")";
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, true);
return debug;
}
}}
#endif

1
src/Math/CMakeLists.txt

@ -1,4 +1,5 @@
set(MagnumMath_HEADERS
BoolVector.h
Constants.h
Functions.h
Math.h

166
src/Math/Test/BoolVectorTest.cpp

@ -0,0 +1,166 @@
/*
Copyright © 1910, 1911, 1912 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include <sstream>
#include <TestSuite/Tester.h>
#include "Math/BoolVector.h"
namespace Magnum { namespace Math { namespace Test {
class BoolVectorTest: public Corrade::TestSuite::Tester {
public:
explicit BoolVectorTest();
void constructDefault();
void constructOneValue();
void data();
void compare();
void compareUndefined();
void all();
void none();
void any();
void bitInverse();
void bitAndOrXor();
void debug();
};
static_assert(BoolVector<15>::DataSize == 2, "Improper DataSize");
static_assert(BoolVector<16>::DataSize == 2, "Improper DataSize");
static_assert(BoolVector<17>::DataSize == 3, "Improper DataSize");
typedef Math::BoolVector<19> BoolVector19;
BoolVectorTest::BoolVectorTest() {
addTests(&BoolVectorTest::constructDefault,
&BoolVectorTest::constructOneValue,
&BoolVectorTest::data,
&BoolVectorTest::compare,
&BoolVectorTest::compareUndefined,
&BoolVectorTest::all,
&BoolVectorTest::none,
&BoolVectorTest::any,
&BoolVectorTest::bitInverse,
&BoolVectorTest::bitAndOrXor,
&BoolVectorTest::debug);
}
void BoolVectorTest::constructDefault() {
CORRADE_COMPARE(BoolVector19(), BoolVector19(0x00, 0x00, 0x00));
}
void BoolVectorTest::constructOneValue() {
CORRADE_COMPARE(BoolVector19::from(false), BoolVector19(0x00, 0x00, 0x00));
CORRADE_COMPARE(BoolVector19::from(true), BoolVector19(0xff, 0xff, 0x07));
}
void BoolVectorTest::data() {
BoolVector19 a(0x08, 0x03, 0x04);
CORRADE_VERIFY(!a[0] && !a[1] && !a[2]);
CORRADE_VERIFY(a[3]);
CORRADE_VERIFY(!a[4] && !a[5] && !a[6] && !a[7]);
CORRADE_VERIFY(a[8]);
CORRADE_VERIFY(a[9]);
CORRADE_VERIFY(!a[10] && !a[11] && !a[12] && !a[13] && !a[14] && !a[15] && !a[16] && !a[17]);
CORRADE_VERIFY(a[18]);
a.set(15, true);
CORRADE_VERIFY(a[15]);
CORRADE_COMPARE(a, BoolVector19(0x08, 0x83, 0x04));
}
void BoolVectorTest::compare() {
BoolVector19 a(0xa5, 0x5f, 0x07);
CORRADE_VERIFY(a == a);
/* Change in full segments */
BoolVector19 b(0xa3, 0x5f, 0x07);
BoolVector19 c(0xa5, 0x98, 0x07);
CORRADE_VERIFY(a != b);
CORRADE_VERIFY(a != c);
/* Change in last bit */
BoolVector19 d(0xa5, 0x5f, 0x06);
CORRADE_VERIFY(a != d);
}
void BoolVectorTest::compareUndefined() {
BoolVector19 a(0xa5, 0x5f, 0x07);
/* Change in unused part of last segment */
BoolVector19 b(0xa5, 0x5f, 0x0f);
CORRADE_VERIFY(a == b);
/* Change in used part of last segment */
BoolVector19 c(0xa5, 0x5f, 0x03);
CORRADE_VERIFY(a != c);
}
void BoolVectorTest::all() {
CORRADE_VERIFY(BoolVector19(0xff, 0xff, 0x07).all());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BoolVector19(0xff, 0xff, 0x0f).all());
CORRADE_VERIFY(!BoolVector19(0xff, 0xff, 0x04).all());
}
void BoolVectorTest::none() {
CORRADE_VERIFY(BoolVector19(0x00, 0x00, 0x00).none());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BoolVector19(0x00, 0x00, 0x08).none());
CORRADE_VERIFY(!BoolVector19(0x00, 0x00, 0x04).none());
}
void BoolVectorTest::any() {
CORRADE_VERIFY(BoolVector19(0x00, 0x01, 0x00).any());
/* Last segment - bit in used and unused part */
CORRADE_VERIFY(BoolVector19(0x00, 0x00, 0x04).any());
CORRADE_VERIFY(!BoolVector19(0x00, 0x00, 0x08).any());
}
void BoolVectorTest::bitInverse() {
CORRADE_COMPARE(~BoolVector19(0xa5, 0x5f, 0x03), BoolVector19(0x5a, 0xa0, 0x04));
}
void BoolVectorTest::bitAndOrXor() {
BoolVector19 a(0xa5, 0x5f, 0x03);
BoolVector19 b(0x37, 0xf3, 0x06);
CORRADE_COMPARE(a & b, BoolVector19(0x25, 0x53, 0x02));
CORRADE_COMPARE(a | b, BoolVector19(0xb7, 0xff, 0x07));
CORRADE_COMPARE(a ^ b, BoolVector19(0x92, 0xac, 0x05));
}
void BoolVectorTest::debug() {
std::ostringstream o;
Corrade::Utility::Debug(&o) << BoolVector19(0x25, 0x53, 0x02);
CORRADE_COMPARE(o.str(), "BoolVector(10100100 11001010 010)\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::Math::Test::BoolVectorTest)

1
src/Math/Test/CMakeLists.txt

@ -1,3 +1,4 @@
corrade_add_test(MathBoolVectorTest BoolVectorTest.cpp)
corrade_add_test(MathConstantsTest ConstantsTest.cpp)
corrade_add_test(MathFunctionsTest FunctionsTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathMathTypeTraitsTest MathTypeTraitsTest.cpp)

Loading…
Cancel
Save