From b59a5b11886ee43bf28abf510214b3969f7bfb50 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 12 Apr 2022 17:36:00 +0200 Subject: [PATCH] ENH: additional BitOps::toc, BitOps::sortedToc - for obtaining set entries from a boolList - BitOps::select to mirror bitSet constructor but returning a boolList - BitOps::set/unset for boolList ENH: construct bitSet from a labelRange - useful, for example, when marking up patch slices ENH: ListOps methods - ListOps::count_if to mirror std::count_if but with list indexing. - ListOps::find_if to mirror std::find_if but with list indexing. ENH: UPtrList::test() method. - includes bounds checks, which means it can be used in more places (eg, even if the storage is empty). --- applications/test/ListOps/Test-ListOps.C | 10 +- src/OpenFOAM/containers/Bits/BitOps/BitOps.C | 133 +++++++++++++++--- src/OpenFOAM/containers/Bits/BitOps/BitOps.H | 61 ++++++-- src/OpenFOAM/containers/Bits/bitSet/bitSet.C | 17 ++- src/OpenFOAM/containers/Bits/bitSet/bitSet.H | 62 +++++--- .../containers/Lists/ListOps/ListOps.H | 49 ++++++- .../Lists/ListOps/ListOpsTemplates.C | 37 ++++- .../PtrLists/PtrDynList/PtrDynList.H | 15 +- .../PtrLists/PtrDynList/PtrDynListI.H | 7 - .../containers/PtrLists/PtrList/PtrList.H | 8 +- .../containers/PtrLists/UPtrList/UPtrList.H | 22 +-- .../containers/PtrLists/UPtrList/UPtrListI.H | 9 +- 12 files changed, 332 insertions(+), 98 deletions(-) diff --git a/applications/test/ListOps/Test-ListOps.C b/applications/test/ListOps/Test-ListOps.C index 926d6e90f8..ea034e57b5 100644 --- a/applications/test/ListOps/Test-ListOps.C +++ b/applications/test/ListOps/Test-ListOps.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2012-2013 OpenFOAM Foundation - Copyright (C) 2019-2021 OpenCFD Ltd. + Copyright (C) 2019-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -131,20 +131,20 @@ int main(int argc, char *argv[]) const auto evenNonZero = [](const label& x){ return x && !(x % 2); }; Info<< "location of first even/non-zero: " - << ListOps::find(test6, evenNonZero) << nl; + << ListOps::find_if(test6, evenNonZero) << nl; Info<< "find > 12 && divisible by 5 : " - << ListOps::find + << ListOps::find_if ( test6, [](const label& x) { return x > 12 && !(x % 5); } ) << nl; Info<< "Found >= 8 : " - << ListOps::found(test6, labelMinMax(8, labelMax)) << nl; + << ListOps::found_if(test6, labelMinMax(8, labelMax)) << nl; Info<< "Found >= 25 : " - << ListOps::found(test6, labelMinMax(25, labelMax)) << nl; + << ListOps::found_if(test6, labelMinMax(25, labelMax)) << nl; Info<< "Subset of non-zero, even values: " diff --git a/src/OpenFOAM/containers/Bits/BitOps/BitOps.C b/src/OpenFOAM/containers/Bits/BitOps/BitOps.C index 8d840513d9..3f39bafdef 100644 --- a/src/OpenFOAM/containers/Bits/BitOps/BitOps.C +++ b/src/OpenFOAM/containers/Bits/BitOps/BitOps.C @@ -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. @@ -30,9 +30,32 @@ License #include "HashSet.H" #include "List.H" #include "labelRange.H" +#include // * * * * * * * * * * * * * * * * * BitOps * * * * * * * * * * * * * * * * // +// See bitSet::setMany for original implementation +void Foam::BitOps::set(List& bools, const labelUList& locations) +{ + // Check the max expected value first + const auto max = std::max_element(locations.begin(), locations.end()); + const label len = (max != locations.end() ? (1 + *max) : 0); + + if (len > bools.size()) + { + bools.resize(len, false); + } + + for (label i : locations) + { + if (i >= 0) + { + bools[i] = true; + } + } +} + + // See bitSet::set(labelRange) for original implementation void Foam::BitOps::set(List& bools, const labelRange& range) { @@ -45,28 +68,17 @@ void Foam::BitOps::set(List& bools, const labelRange& range) return; } - // Range finishes at or beyond the right side. - // - zero fill any gaps that we might create. - // - flood-fill the rest, which now corresponds to the full range. - // - // NB: use labelRange after() for the exclusive end-value, which - // corresponds to our new set size. + // Check maximum extent of the range. + // The after() method is the exclusive end-value, + // which corresponds to our potential new length. + // - resize now to avoid allocations within the loop + if (slice.after() >= bools.size()) { - label i = bools.size(); - - bools.resize(slice.after(), true); - - // Backfill with false - while (i < slice.start()) - { - bools.unset(i); - ++i; - } - return; + bools.resize(slice.after(), false); } - for (label i = slice.first(); i <= slice.last(); ++i) + for (const label i : slice) { bools.set(i); } @@ -79,7 +91,7 @@ void Foam::BitOps::set(labelHashSet& hashset, const labelRange& range) labelRange slice(range); slice.adjust(); // No negative start, size adjusted accordingly - for (label i = slice.first(); i <= slice.last(); ++i) + for (const label i : slice) { hashset.set(i); } @@ -92,10 +104,19 @@ void Foam::BitOps::set(bitSet& bitset, const labelRange& range) } +void Foam::BitOps::unset(List& bools, const labelUList& locations) +{ + for (const label i : locations) + { + bools.unset(i); + } +} + + // See bitSet::unset(labelRange) for original implementation void Foam::BitOps::unset(List& bools, const labelRange& range) { - for (label i = range.first(); i <= range.last(); ++i) + for (const label i : range) { bools.unset(i); } @@ -104,7 +125,7 @@ void Foam::BitOps::unset(List& bools, const labelRange& range) void Foam::BitOps::unset(labelHashSet& hashset, const labelRange& range) { - for (label i = range.first(); i <= range.last(); ++i) + for (const label i : range) { hashset.unset(i); } @@ -117,6 +138,74 @@ void Foam::BitOps::unset(bitSet& bitset, const labelRange& range) } +Foam::List Foam::BitOps::select +( + const label n, + const labelUList& locations +) +{ + List bools(n, false); + + BitOps::set(bools, locations); + + return bools; +} + + +Foam::List Foam::BitOps::select(const labelUList& locations) +{ + List bools; + + BitOps::set(bools, locations); + + return bools; +} + + +// Note: code is like ListOps findIndices() and/or bitSet toc() +Foam::List Foam::BitOps::toc(const UList& bools) +{ + const label len = bools.size(); + + // Pass 1: count occurrences + label count = 0; + + for (const bool b : bools) + { + if (b) ++count; + } + + labelList indices(count); + + // Pass 2: fill content + if (count) + { + const label total(count); + count = 0; + + for (label i = 0; i < len; ++i) + { + if (bools[i]) + { + indices[count] = i; + if (++count == total) // Terminate early + { + break; + } + } + } + } + + return indices; +} + + +Foam::List Foam::BitOps::sortedToc(const UList& bools) +{ + return BitOps::toc(bools); +} + + // * * * * * * * * * * * * * * * * BitSetOps * * * * * * * * * * * * * * * * // Foam::bitSet Foam::BitSetOps::create diff --git a/src/OpenFOAM/containers/Bits/BitOps/BitOps.H b/src/OpenFOAM/containers/Bits/BitOps/BitOps.H index 0301a03972..5262a89f9a 100644 --- a/src/OpenFOAM/containers/Bits/BitOps/BitOps.H +++ b/src/OpenFOAM/containers/Bits/BitOps/BitOps.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. @@ -27,7 +27,8 @@ Namespace Foam::BitOps Description - Various bit-wise operations, etc. + Various bit-wise operations and adaptor methods for containers + that are somewhat similar to bitSet (eg, boolList, labelHashSet). The population count uses the Hamming weight (http://en.wikipedia.org/wiki/Hamming_weight). @@ -42,8 +43,8 @@ Description \*---------------------------------------------------------------------------*/ -#ifndef BitOps_H -#define BitOps_H +#ifndef Foam_BitOps_H +#define Foam_BitOps_H #include "label.H" #include "UList.H" @@ -83,24 +84,30 @@ inline unsigned int count(const UList& bools, const bool val=true) // For compatibility with bitSet::all() inline bool all(const UList& bools) { - return std::all_of(bools.begin(), bools.end(), [](bool b){return b;}); + return std::all_of(bools.begin(), bools.end(), identityOp()); } //- True if any entries are 'true'. // For compatibility with bitSet::any() inline bool any(const UList& bools) { - return std::any_of(bools.begin(), bools.end(), [](bool b){return b;}); + return std::any_of(bools.begin(), bools.end(), identityOp()); } //- True if no entries are 'true'. // For compatibility with bitSet::none() inline bool none(const UList& bools) { - return std::none_of(bools.begin(), bools.end(), [](bool b){return b;}); + return std::none_of(bools.begin(), bools.end(), identityOp()); } +//- Set the listed locations (assign 'true'). +// Does auto-vivify for non-existent entries. +// +// For compatibility with bitSet::set(labelUList) +void set(List& bools, const labelUList& locations); + //- Set the specified range 'on' in a boolList. // For compatibility with bitSet::set(labelRange) void set(List& bools, const labelRange& range); @@ -113,6 +120,12 @@ void set(labelHashSet& hashset, const labelRange& range); void set(bitSet& bitset, const labelRange& range); +//- Unset the listed locations (assign 'false'). +// No auto-vivify non-existent entries. +// +// For compatibility with bitSet::set(labelUList) +void unset(List& bools, const labelUList& locations); + //- Unset the specified range 'on' in a boolList. // For compatibility with bitSet::unset(labelRange) void unset(List& bools, const labelRange& range); @@ -125,6 +138,34 @@ void unset(labelHashSet& hashset, const labelRange& range); void unset(bitSet& bitset, const labelRange& range); +//- Construct a selection list of bools (all false) with the given pre-size, +//- subsequently add specified locations as true, +//- auto-vivify entries if needed. +// Similar to bitSet construction from locations +// +// \return a List of bools +List select(const label n, const labelUList& locations); + +//- Construct an auto-sized selection list of bools (all false), +//- and populate the specified locations as true. +// Similar to bitSet construction from locations +// +// \return a List of bools +List select(const labelUList& locations); + +//- Return the (sorted) values corresponding to 'true' entries. +// Similar to bitSet::toc() +// +// \return a List of labels +List