diff --git a/applications/test/bitSet2/Test-bitSet2.C b/applications/test/bitSet2/Test-bitSet2.C index df04f3ce0f..f53f3e831f 100644 --- a/applications/test/bitSet2/Test-bitSet2.C +++ b/applications/test/bitSet2/Test-bitSet2.C @@ -344,12 +344,35 @@ int main(int argc, char *argv[]) Info<< "\noperator|=\n"; { + bitSet a; a.set(labelRange(15, 8)); + bitSet b; b.set(labelRange(30, 8)); + + report(a, false); + report(b, false); + report((a |= b), true); + } + { + Info<< " other test\n"; + bitSet list3 = list1; report((list3 |= list2), true); } Info<< "\noperator&=\n"; { + bitSet a; a.set(labelRange(30, 8)); + bitSet b; b.set(labelRange(0, 8)); + + report(a, false); + report(b, false); + Info<< " (a & b)\n"; + report((a & b), true); + Info<< " (b & a)\n"; + report((b & a), true); + } + { + Info<< " other test\n"; + bitSet list3 = list1; report((list3 &= list2), true); } diff --git a/src/OpenFOAM/containers/Bits/PackedList/PackedList.H b/src/OpenFOAM/containers/Bits/PackedList/PackedList.H index 1cb1395ad2..9b281f158f 100644 --- a/src/OpenFOAM/containers/Bits/PackedList/PackedList.H +++ b/src/OpenFOAM/containers/Bits/PackedList/PackedList.H @@ -344,7 +344,7 @@ public: //- a minimum position, below which trimming will not occur. // // \return true if trimming changed the size. - inline bool trim(label minpos=-1); + inline bool trim(label minpos = -1); //- Clear all bits but do not adjust the addressable size. // \note Method name compatibility with boost::dynamic_bitset diff --git a/src/OpenFOAM/containers/Bits/bitSet/bitSet.C b/src/OpenFOAM/containers/Bits/bitSet/bitSet.C index 2a778de499..1e7ad6fcf5 100644 --- a/src/OpenFOAM/containers/Bits/bitSet/bitSet.C +++ b/src/OpenFOAM/containers/Bits/bitSet/bitSet.C @@ -43,7 +43,7 @@ Foam::bitSet& Foam::bitSet::minusEq(const bitSet& other) { if (&other == this) { - // Self '-=' : results in clearing all bits + // Self '-=' : clears all bits if (debug & 2) { InfoInFunction @@ -53,12 +53,12 @@ Foam::bitSet& Foam::bitSet::minusEq(const bitSet& other) reset(); return *this; } - else if (empty() || other.empty()) + else if (none() || other.none()) { + // no-op: nothing can change return *this; } - // The operation (on overlapping blocks) { const label nblocks = num_blocks(std::min(size(), other.size())); @@ -88,21 +88,32 @@ Foam::bitSet& Foam::bitSet::andEq(const bitSet& other) return *this; } - else if (empty()) + else if (none()) { - // empty set : no-op (no overlap possible) + // no-op: nothing is set - no intersection possible return *this; } - else if (other.empty()) + else if (other.none()) { - reset(); // Other is empty - no overlap possible + // no-op: other has nothing set - no intersection possible + reset(); return *this; } + const label origSize(size()); + const label otherSize(other.size()); + + if (origSize > otherSize) + { + // Clear bits (and blocks) that do not overlap at all + resize(otherSize); + resize(origSize); + } + // The operation (on overlapping blocks) { - const label nblocks = num_blocks(std::min(size(), other.size())); + const label nblocks = num_blocks(std::min(origSize, otherSize)); const auto& rhs = other.blocks_; for (label blocki = 0; blocki < nblocks; ++blocki) @@ -115,7 +126,7 @@ Foam::bitSet& Foam::bitSet::andEq(const bitSet& other) } -Foam::bitSet& Foam::bitSet::orEq(const bitSet& other, const bool strict) +Foam::bitSet& Foam::bitSet::orEq(const bitSet& other) { if (&other == this) { @@ -129,52 +140,21 @@ Foam::bitSet& Foam::bitSet::orEq(const bitSet& other, const bool strict) return *this; } - else if (other.empty()) + else if (other.none()) { - if ((debug & 2) && !empty()) - { - // OK if both are empty - InfoInFunction - << "Perform |= using empty operand: ignore" << nl; - } - - // No (normal) overlap: no-op + // no-op: nothing can change return *this; } - else if (empty()) + + + // Largest new bit that could be introduced + const label otherMax(other.find_last()); + + if (otherMax >= size()) { - if (debug & 2) - { - InfoInFunction - << "Perform |= on empty bitSet" << nl; - } - - if (strict) - { - // No (normal) overlap: no-op - return *this; - } + // Extend to accommodate bits from 'other' + resize(otherMax+1); } - else if ((debug & 2) && (size() != other.size())) - { - InfoInFunction - << "Perform |= on dissimilar sized bitSets: " - << size() << " vs. " << other.size() << nl; - } - - label minpos = -1; // Min trim point - - if ((size() < other.size()) && !strict) - { - // The size (B > A) and we are non-strict (greedy), which means we may - // acquire additional bits from B. However, we would like to avoid - // spurious changes in the size of A (ie, B is longer but the extra - // bits are unset and thus don't affect the logical result). - - minpos = size(); - resize(other.size()); // Blocks now overlap - } - // The operation (on overlapping blocks) { @@ -187,26 +167,15 @@ Foam::bitSet& Foam::bitSet::orEq(const bitSet& other, const bool strict) } } - - // Cleanup - minpos >= 0 means we need to check/adjust the trim point - if (minpos >= 0) - { - trim(minpos); // Adjust the trim point (size) - } - else - { - clear_trailing_bits(); - } - return *this; } -Foam::bitSet& Foam::bitSet::xorEq(const bitSet& other, const bool strict) +Foam::bitSet& Foam::bitSet::xorEq(const bitSet& other) { if (&other == this) { - // Self '^=' : results in clearing all bits + // Self '^=' : clears all bits if (debug & 2) { @@ -217,47 +186,21 @@ Foam::bitSet& Foam::bitSet::xorEq(const bitSet& other, const bool strict) reset(); return *this; } - else if (other.empty()) + else if (other.none()) { - if ((debug & 2) && !empty()) - { - // OK if both are empty - InfoInFunction - << "Perform ^= using empty operand: ignore" << nl; - } - - // No (normal) overlap: no-op + // no-op: nothing can change return *this; } - else if (empty()) + + + // Largest new bit that could be introduced + const label otherMax(other.find_last()); + + if (otherMax >= size()) { - if (debug & 2) - { - InfoInFunction - << "Perform ^= on empty bitSet" << nl; - } - - if (strict) - { - // No (normal) overlap: no-op - return *this; - } + // Extend to accommodate bits from 'other' + resize(otherMax+1); } - else if ((debug & 2) && (size() != other.size())) - { - InfoInFunction - << "Perform ^= on dissimilar sized bitSets: " - << size() << " vs. " << other.size() << nl; - } - - label minpos = -1; // Min trim point - - if ((size() < other.size()) && !strict) - { - minpos = size(); // This logic is explained in the orEq() method - resize(other.size()); // Blocks now overlap - } - // The operation (on overlapping blocks) { @@ -270,17 +213,6 @@ Foam::bitSet& Foam::bitSet::xorEq(const bitSet& other, const bool strict) } } - - // Cleanup - minpos >= 0 means we need to check/adjust the trim point - if (minpos >= 0) - { - trim(minpos); // Adjust the trim point (size) - } - else - { - clear_trailing_bits(); - } - return *this; } diff --git a/src/OpenFOAM/containers/Bits/bitSet/bitSet.H b/src/OpenFOAM/containers/Bits/bitSet/bitSet.H index 1bcafd563b..1ed379e172 100644 --- a/src/OpenFOAM/containers/Bits/bitSet/bitSet.H +++ b/src/OpenFOAM/containers/Bits/bitSet/bitSet.H @@ -83,7 +83,8 @@ protected: // A = (A & ~B) // \endcode // A and B can have different sizes. - // Does not change the original set size. + // Never changes the original set size. + // Non-overlapping parts are considered \em off. bitSet& minusEq(const bitSet& other); //- The set logical AND @@ -91,8 +92,9 @@ protected: // A = (A & B) // // \endcode - // A and B can have different sizes.. - // Does not change the original set size. + // A and B can have different sizes. + // Never changes the original set size. + // Non-overlapping parts are considered \em off. bitSet& andEq(const bitSet& other); //- The set logical OR @@ -101,18 +103,17 @@ protected: // \endcode // A and B can have different sizes // - // \note - // The default (strict=true) ignores additional length from B, - // whereas (strict=false) permits the set to automatically grow - // to accommodate additional elements arising from B. - bitSet& orEq(const bitSet& other, const bool strict=true); + // The size grows to accommodate new \em on bits. + bitSet& orEq(const bitSet& other); //- The set logical XOR // \code // A = (A ^ B) // \endcode - // A and B can have different sizes. Sizing behaviour as per orEq. - bitSet& xorEq(const bitSet& other, const bool strict=true); + // A and B can have different sizes. + // + // The size grows to accommodate new \em on bits. + bitSet& xorEq(const bitSet& other); public: @@ -123,6 +124,7 @@ public: class const_iterator; typedef unsigned int const_reference; + // Static Member Functions //- Return a null bitSet reference @@ -363,10 +365,14 @@ public: //- Invert all bits in the addressable region inline void flip(); - //- Invert bits at the specified position. + //- Invert bit at the specified position. // A no-op if the position is out-of-range inline void flip(const label pos); + //- Resize to include the last \em on bit only. + // Functionally identical to resize(find_last()+1) + inline void resize_last(); + //- Swap contents inline void swap(bitSet& bitset); @@ -573,23 +579,24 @@ public: inline bitSet& operator=(const bool val); //- Bitwise-AND all the bits in other with the bits in this bitset. - // The operands may have dissimilar sizes without affecting the size - // of the set. + // The operands may have dissimilar sizes, + // never changes the original set size. + // Non-overlapping elements are considered \em off. inline bitSet& operator&=(const bitSet& other); //- Bitwise-OR operator - similar to the set() method. - // The operands may have dissimilar sizes without affecting the size - // of the set. + // The operands may have dissimilar sizes, + // the set grows to accommodate new \em on bits. inline bitSet& operator|=(const bitSet& other); //- Bitwise-XOR operator - retains unique entries. - // The operands may have dissimilar sizes without affecting the size - // of the set. + // The operands may have dissimilar sizes, + // the set grows to accommodate new \em on bits. inline bitSet& operator^=(const bitSet& other); //- Remove entries from this list - identical to the unset() method. - // The operands may have dissimilar sizes without affecting the size - // of the set. + // The operands may have dissimilar sizes, + // never changes the original set size. inline bitSet& operator-=(const bitSet& other); diff --git a/src/OpenFOAM/containers/Bits/bitSet/bitSetI.H b/src/OpenFOAM/containers/Bits/bitSet/bitSetI.H index 1ad6e80a80..a32f68db8b 100644 --- a/src/OpenFOAM/containers/Bits/bitSet/bitSetI.H +++ b/src/OpenFOAM/containers/Bits/bitSet/bitSetI.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2020 OpenCFD Ltd. + Copyright (C) 2018-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -316,6 +316,7 @@ inline Foam::label Foam::bitSet::find_first() const // Process block-wise, detecting any '1' bits const label nblocks = num_blocks(size()); + for (label blocki = 0; blocki < nblocks; ++blocki) { label pos = (blocki * elem_per_block); @@ -535,6 +536,21 @@ inline Foam::labelList Foam::bitSet::sortedToc() const } +inline void Foam::bitSet::resize_last() +{ + const label pos = find_last(); + + if (pos >= 0) + { + resize(pos+1); + } + else + { + clear(); + } +} + + inline void Foam::bitSet::swap(bitSet& bitset) { PackedList<1>::swap(bitset); @@ -573,7 +589,7 @@ inline void Foam::bitSet::fill(const bool val) inline void Foam::bitSet::set(const bitSet& bitset) { - orEq(bitset, false); // Non-strict: Lets the set size grow. + orEq(bitset); } @@ -754,28 +770,40 @@ inline Foam::bitSet Foam::operator~(const bitSet& bitset) inline Foam::bitSet Foam::operator&(const bitSet& a, const bitSet& b) { bitSet result(a); - return (result &= b); + result &= b; + + result.resize_last(); + return result; } inline Foam::bitSet Foam::operator|(const bitSet& a, const bitSet& b) { bitSet result(a); - return (result |= b); + result |= b; + + result.resize_last(); + return result; } inline Foam::bitSet Foam::operator^(const bitSet& a, const bitSet& b) { bitSet result(a); - return (result ^= b); + result ^= b; + + result.resize_last(); + return result; } inline Foam::bitSet Foam::operator-(const bitSet& a, const bitSet& b) { bitSet result(a); - return (result -= b); + result |= b; + + result.resize_last(); + return result; }