diff --git a/applications/test/bitSet2/Test-bitSet2.C b/applications/test/bitSet2/Test-bitSet2.C index 9c62bd7e7a2536acd9c4533821644d5184388b97..b76048b01d508cc0c90c85b3898383b894ed15b2 100644 --- a/applications/test/bitSet2/Test-bitSet2.C +++ b/applications/test/bitSet2/Test-bitSet2.C @@ -40,12 +40,19 @@ Description using namespace Foam; -inline Ostream& report -( - const bitSet& bitset, - bool showBits = false, - bool debugOutput = false -) + +inline Ostream& extent(const bitSet& bitset) +{ + Info<< "first: " << bitset.find_first() + << " last: " << bitset.find_last() + << " first_not: " << bitset.find_first_not() + << endl; + + return Info; +} + + +inline Ostream& info(const bitSet& bitset) { Info<< "size=" << bitset.size() << "/" << bitset.capacity() << " count=" << bitset.count() @@ -54,17 +61,11 @@ inline Ostream& report << " any:" << bitset.any() << " none:" << bitset.none() << nl; - Info<< "values: " << flatOutput(bitset) << nl; - if (showBits) - { - bitset.printBits(Info, debugOutput) << nl; - } - return Info; } -inline Ostream& report(const UList<bool>& bools) +inline Ostream& info(const UList<bool>& bools) { Info<< "size=" << bools.size() << " count=" << BitOps::count(bools) @@ -77,6 +78,31 @@ inline Ostream& report(const UList<bool>& bools) } +inline Ostream& report +( + const bitSet& bitset, + bool showBits = false, + bool debugOutput = false +) +{ + info(bitset); + + Info<< "values: " << flatOutput(bitset) << nl; + if (showBits) + { + bitset.printBits(Info, debugOutput) << nl; + } + + return Info; +} + + +inline Ostream& report(const UList<bool>& bools) +{ + return info(bools); +} + + template<class UIntType> std::string toString(UIntType value, char off='.', char on='1') { @@ -153,10 +179,7 @@ int main(int argc, char *argv[]) compare(list1, "...................1..1..1..1..1"); report(list1, true); - - - Info<< "first: " << list1.find_first() - << " last: " << list1.find_last() << endl; + extent(list1); Info<< "iterate through:"; for (const label idx : list1) @@ -172,6 +195,21 @@ int main(int argc, char *argv[]) Info<< "\nflipped bit pattern\n"; report(list2, true); + extent(list2); + + Info<< "\nsparse set\n"; + { + bitSet sparse(1000); + sparse.set(300); + + info(sparse); + extent(sparse); + + sparse.set(0); + + info(sparse); + extent(sparse); + } // set every other on forAll(list2, i) diff --git a/src/OpenFOAM/containers/Bits/bitSet/bitSet.H b/src/OpenFOAM/containers/Bits/bitSet/bitSet.H index 32b104df2c4d7da178495968115d49e231ad77bb..8f2cfae00312ddf3ad86711b4eb18e20e06f8622 100644 --- a/src/OpenFOAM/containers/Bits/bitSet/bitSet.H +++ b/src/OpenFOAM/containers/Bits/bitSet/bitSet.H @@ -65,6 +65,15 @@ class bitSet : public PackedList<1> { +private: + + // Private Member Functions + + //- Find the first block with a '0' bit + // \return block number or -1 if the set is empty or all bits are on. + inline label first_not_block() const; + + protected: // Protected Member Functions @@ -203,12 +212,18 @@ public: // \note Method name compatibility with std::bitset inline bool test(const label pos) const; - //- Locate the first bit set. + //- Locate the first bit that is set. // \return the location or -1 if there are no bits set. // // \note Method name compatibility with boost::dynamic_bitset inline label find_first() const; + //- Locate the first bit that is unset. + // \return the location or -1 if the set is empty or all bits are on. + // + // \note Provided for symmetry with find_first() + inline label find_first_not() const; + //- Locate the last bit set. // \return the location or -1 if there are no bits set. // diff --git a/src/OpenFOAM/containers/Bits/bitSet/bitSetI.H b/src/OpenFOAM/containers/Bits/bitSet/bitSetI.H index 0ab1bb59abb7367c4be7394195775e5142ef5843..413aa87c3357418c04438e7042509f38555de0c9 100644 --- a/src/OpenFOAM/containers/Bits/bitSet/bitSetI.H +++ b/src/OpenFOAM/containers/Bits/bitSet/bitSetI.H @@ -23,6 +23,53 @@ License \*---------------------------------------------------------------------------*/ +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +inline Foam::label Foam::bitSet::first_not_block() const +{ + if (empty()) + { + return -1; + } + + // Use complement to change 0 <-> 1 and check if any 1's now appear + + const label nblocks = num_blocks(size()); + + // Extra bits in the final block? + const unsigned int off = size() % elem_per_block; + + if (!off) + { + for (label blocki=0; blocki < nblocks; ++blocki) + { + if (~(blocks_[blocki])) + { + return blocki; + } + } + } + else + { + for (label blocki=0; blocki < nblocks-1; ++blocki) + { + if (~(blocks_[blocki])) + { + return blocki; + } + } + + // The final block needs masking + if (~(blocks_[nblocks-1]) & mask_lower(off)) + { + return nblocks-1; + } + } + + return -1; +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // inline constexpr Foam::bitSet::bitSet() noexcept @@ -257,6 +304,38 @@ inline Foam::label Foam::bitSet::find_first() const } +inline Foam::label Foam::bitSet::find_first_not() const +{ + const label blocki = first_not_block(); + + if (blocki >= 0) + { + label pos = (blocki * elem_per_block); + + // Detect first '0' bit by checking the complement. + + // No special masking for the final block, that was already checked + // in the first_not_block() call. + + for + ( + unsigned int blockval = ~(blocks_[blocki]); + blockval; + blockval >>= 1u + ) + { + if (blockval & 1u) + { + return pos; + } + ++pos; + } + } + + return -1; +} + + inline Foam::label Foam::bitSet::find_last() const { // Process block-wise, detecting any '1' bits @@ -339,44 +418,7 @@ inline Foam::label Foam::bitSet::find_next(label pos) const inline bool Foam::bitSet::all() const { - if (empty()) - { - return true; - } - - // Use complement to change 0 <-> 1 and check if any 1's now appear - - const label nblocks = num_blocks(size()); - - // Extra bits in the final block? - const unsigned int off = size() % elem_per_block; - - if (!off) - { - for (label blocki=0; blocki < nblocks; ++blocki) - { - if (~(blocks_[blocki])) - { - return false; - } - } - } - else - { - for (label blocki=0; blocki < nblocks-1; ++blocki) - { - if (~(blocks_[blocki])) - { - return false; - } - } - - // Verify the final block, with masking - - return (!(~blocks_[nblocks-1] & mask_lower(off))); - } - - return true; + return -1 == first_not_block(); } @@ -388,7 +430,10 @@ inline bool Foam::bitSet::any() const for (label blocki=0; blocki < nblocks; ++blocki) { - if (blocks_[blocki]) return true; + if (blocks_[blocki]) + { + return true; + } } } @@ -421,7 +466,7 @@ inline unsigned int Foam::bitSet::count(const bool on) const if (!on) { - // Return the number of bits that are off. + // Return the number of bits that are OFF. return (unsigned(size()) - total); }