ENH: improve addressing into labelRanges (#2933)

- totalSize() returns retrieve the linear (total) size
  (naming as per globalIndex)
- operator[] retrieves the referenced value (linear indexing)
- labels() returns a flattened labelList (as per labelRange itself)
This commit is contained in:
Mark Olesen 2023-08-21 11:10:19 +02:00 committed by Mark OLESEN
parent 6defeddbff
commit 750d9084d4
4 changed files with 356 additions and 88 deletions

View File

@ -68,25 +68,51 @@ int main(int argc, char *argv[])
labelRange::debug = 1;
}
Info<< nl;
{
labelRange range(5, 10);
Info<< "identity: " << identity(range) << nl;
}
{
Info<<"test sorting" << endl;
DynamicList<labelRange> list1(10);
Info<< "test sorting" << endl;
labelRanges list1(10);
list1.emplace_back(25, 8);
list1.emplace_back(8);
list1.emplace_back(15, 5);
list1.emplace_back(50, -10, true);
sort(list1);
Info<<"sorted" << list1 << endl;
// Move construct
labelRanges ranges(std::move(list1));
if (!list1.empty())
{
Info<< "Move construct failed? "
<< flatOutput(list1.ranges()) << nl;
}
Info<< "unsorted: ";
ranges.writeList(Info) << nl;
ranges.sort();
Info<< "sorted: ";
ranges.writeList(Info) << nl;
Info<< nl
<< "list linear length = " << ranges.totalSize() << nl;
Info<< "list labels = ";
ranges.labels().writeList(Info) << nl;
Info<< nl;
for (int i : { -1, 0, 5, 8, 10, 20, 26 })
{
Info<< "value at [" << i << "] = " << ranges[i] << nl;
}
}
{
Info<<"test intersections" << endl;
Info<< "test intersections" << endl;
labelRange range1(-15, 25);
labelRange range2(7, 8);
labelRange range3(-20, 8);

View File

@ -27,7 +27,7 @@ License
\*---------------------------------------------------------------------------*/
#include "labelRanges.H"
#include "ListOps.H"
#include <numeric>
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@ -51,7 +51,6 @@ static Ostream& printRange(Ostream& os, const labelRange& range)
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::labelRanges::insertBefore
@ -60,7 +59,7 @@ void Foam::labelRanges::insertBefore
const labelRange& range
)
{
auto& list = static_cast<StorageContainer&>(*this);
auto& list = ranges_;
// Insert via copying up
label nElem = list.size();
@ -101,7 +100,7 @@ void Foam::labelRanges::insertBefore
void Foam::labelRanges::purgeEmpty()
{
auto& list = static_cast<StorageContainer&>(*this);
auto& list = ranges_;
// Purge empty ranges by copying down
label nElem = 0;
@ -135,18 +134,18 @@ Foam::labelRanges::labelRanges(Istream& is)
bool Foam::labelRanges::add(const labelRange& range)
{
auto& list = ranges_;
if (range.empty())
{
return false;
}
else if (this->empty())
else if (list.empty())
{
this->push_back(range);
list.push_back(range);
return true;
}
auto& list = static_cast<StorageContainer&>(*this);
// Find the correct place for insertion
forAll(list, elemi)
{
@ -158,7 +157,7 @@ bool Foam::labelRanges::add(const labelRange& range)
currRange.join(range);
// Might connect with the next following range(s)
for (; elemi < this->size()-1; ++elemi)
for (; elemi < list.size()-1; ++elemi)
{
labelRange& nextRange = list[elemi+1];
if (currRange.overlaps(nextRange, true))
@ -187,7 +186,7 @@ bool Foam::labelRanges::add(const labelRange& range)
// not found: simply append
this->push_back(range);
list.push_back(range);
return true;
}
@ -195,14 +194,14 @@ bool Foam::labelRanges::add(const labelRange& range)
bool Foam::labelRanges::remove(const labelRange& range)
{
auto& list = ranges_;
bool status = false;
if (range.empty() || this->empty())
if (range.empty() || list.empty())
{
return status;
}
auto& list = static_cast<StorageContainer&>(*this);
forAll(list, elemi)
{
labelRange& currRange = list[elemi];
@ -307,19 +306,97 @@ bool Foam::labelRanges::remove(const labelRange& range)
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, labelRanges& ranges)
Foam::List<Foam::label> Foam::labelRanges::labels() const
{
is >> static_cast<labelRanges::StorageContainer&>(ranges);
return is;
label total = 0;
for (const labelRange& range : ranges_)
{
if (range.size() > 0) // Ignore negative size (paranoid)
{
total += range.size();
}
}
if (!total)
{
// Skip this check?
return List<label>();
}
List<label> result(total);
auto* iter = result.begin();
for (const labelRange& range : ranges_)
{
const label len = range.size();
if (len > 0) // Ignore negative size (paranoid)
{
std::iota(iter, (iter + len), range.start());
iter += len;
}
}
return result;
}
Foam::Ostream& Foam::operator<<(Ostream& os, const labelRanges& ranges)
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
Foam::label Foam::labelRanges::operator[](const label i) const
{
os << static_cast<const labelRanges::StorageContainer&>(ranges);
return os;
if (i < 0) return -1;
label subIdx = i;
for (const labelRange& range : ranges_)
{
if (subIdx < range.size())
{
return (range.start() + subIdx);
}
else
{
subIdx -= range.size();
}
}
return -1; // Not found
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Istream& Foam::labelRanges::readList(Istream& is)
{
return ranges_.readList(is);
}
Foam::Ostream& Foam::labelRanges::writeList
(
Ostream& os,
const label shortLen
) const
{
return ranges_.writeList(os, shortLen);
}
Foam::Istream& Foam::operator>>(Istream& is, labelRanges& list)
{
return list.readList(is);
}
Foam::Ostream& Foam::operator<<(Ostream& os, const labelRanges& list)
{
return list.writeList
(
os,
Detail::ListPolicy::short_length<labelRange>::value
);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,9 +28,10 @@ Class
Foam::labelRanges
Description
A list of labelRange.
A list of labelRange with constrained list capabilities.
SourceFiles
labelRangesI.H
labelRanges.C
\*---------------------------------------------------------------------------*/
@ -56,12 +57,11 @@ Ostream& operator<<(Ostream& is, const labelRanges& ranges);
\*---------------------------------------------------------------------------*/
class labelRanges
:
private Foam::DynamicList<Foam::labelRange>
{
// Private Typedefs
// Private Data
typedef Foam::DynamicList<Foam::labelRange> StorageContainer;
//- The list of ranges
DynamicList<labelRange> ranges_;
// Private Member Functions
@ -76,35 +76,69 @@ public:
// STL type definitions
//- The value type the list contains
typedef labelRange value_type;
//- Input iterator with const access
class const_iterator;
// Constructors
// Generated Methods
//- Default construct
labelRanges() = default;
//- Construct given size
inline explicit labelRanges(const label nElem);
//- Default copy construct
labelRanges(const labelRanges&) = default;
//- Default move construct
labelRanges(labelRanges&&) = default;
//- Default copy assignment
labelRanges& operator=(const labelRanges&) = default;
//- Default move assignment
labelRanges& operator=(labelRanges&&) = default;
// Constructors
//- Construct an empty list with given initial capacity
inline explicit labelRanges(const label initialCapacity);
//- Copy construct from list of ranges
inline explicit labelRanges(const UList<labelRange>& list);
//- Move construct from list of ranges
inline labelRanges(List<labelRange>&& list);
//- Move construct from list of ranges
template<int AnySizeMin>
inline labelRanges(DynamicList<labelRange, AnySizeMin>&& list);
//- Construct from Istream.
labelRanges(Istream& is);
explicit labelRanges(Istream& is);
// Member Functions
//- Clear the addressed list
using DynamicList<labelRange>::clear;
//- The list of ranges
const UList<labelRange>& ranges() const noexcept { return ranges_; }
//- Return true if the list is empty
using DynamicList<labelRange>::empty;
//- Clear the addressable list of ranges
void clear() noexcept { ranges_.clear(); }
//- True if list of ranges is empty
bool empty() const noexcept { return ranges_.empty(); }
//- Reserve space for at least this size
void reserve(const label len) { ranges_.reserve(len); }
//- The linear size (sum of all the element sizes)
inline label totalSize() const noexcept;
//- True if the value is contained within any of the sub-ranges
inline bool contains(const label value) const;
//- True if the value is contained within any of the sub-ranges
bool found(const label value) const { return contains(value); }
inline bool contains(const label value) const noexcept;
//- Add the range to the list
bool add(const labelRange& range);
@ -112,14 +146,31 @@ public:
//- Remove the range from the list
bool remove(const labelRange& range);
//- Construct a range element at the end of the list,
//- return reference to the new element.
template<class... Args>
inline labelRange& emplace_back(Args&&... args);
//- Inplace sort of the range elements
inline void sort();
//- Return flattened list of all range labels
List<label> labels() const;
// Member Operators
//- Return the value at linear index 'i', -1 for out-of-range
label operator[](const label i) const;
// STL iterator
//- Forward input iterator with const access
class const_iterator
{
//- The list for which this is an iterator
const labelRanges* list_;
//- The list of ranges for which this is an iterator
const UList<labelRange>* list_;
//- The index into the list
label index_;
@ -131,11 +182,12 @@ public:
// Constructors
//- Construct from range list at given index
//- Construct from range list at given index (and sub-index)
inline explicit constexpr const_iterator
(
const labelRanges* list,
const label i = 0
const UList<labelRange>* list,
const label idx = 0,
const label subIdx = 0
) noexcept;
@ -168,10 +220,39 @@ public:
inline const const_iterator end() const noexcept;
//- Return const_iterator at linear offset i from begin,
//- clamped to [0,size] range
inline const_iterator cbegin(const label i) const;
//- Return const_iterator at linear offset i from begin,
//- clamped to [0,size] range
inline const_iterator begin(const label i) const;
// Reading/writing
//- Read List of labelRange from Istream, discarding contents
Istream& readList(Istream& is);
//- Write List of labelRange, with line-breaks in ASCII
//- when length exceeds shortLen.
// Using '0' suppresses line-breaks entirely.
Ostream& writeList(Ostream& os, const label shortLen=0) const;
// IOstream Operators
friend Istream& operator>>(Istream& is, labelRanges& ranges);
friend Ostream& operator<<(Ostream& os, const labelRanges& ranges);
//- Use the readList() method to read contents from Istream.
friend Istream& operator>>(Istream& is, labelRanges& list);
//- Write to Ostream. Uses the writeList() method
friend Ostream& operator<<(Ostream& os, const labelRanges& list);
// Housekeeping
//- Same as contains()
bool found(const label value) const { return contains(value); }
};

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,9 +28,31 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::labelRanges::labelRanges(const label nElem)
inline Foam::labelRanges::labelRanges(const label initialCapacity)
:
DynamicList<labelRange>(nElem)
ranges_(initialCapacity)
{}
inline Foam::labelRanges::labelRanges(const UList<labelRange>& list)
:
ranges_(list)
{}
inline Foam::labelRanges::labelRanges(List<labelRange>&& list)
:
ranges_(std::move(list))
{}
template<int AnySizeMin>
inline Foam::labelRanges::labelRanges
(
DynamicList<labelRange, AnySizeMin>&& list
)
:
ranges_(std::move(list))
{}
@ -39,13 +61,14 @@ inline Foam::labelRanges::labelRanges(const label nElem)
inline constexpr Foam::labelRanges::const_iterator::
const_iterator
(
const labelRanges* list,
const label i
const UList<labelRange>* list,
const label idx,
const label subIdx
) noexcept
:
list_(list),
index_(i),
subIndex_(0)
index_(idx),
subIndex_(subIdx)
{}
@ -60,6 +83,7 @@ inline Foam::labelRanges::const_iterator&
Foam::labelRanges::const_iterator::
operator++()
{
// TBD: trap (index_ >= list_->size()) and make a no-op?
if (++subIndex_ >= (*list_)[index_].size())
{
// Move to the next range
@ -109,41 +133,23 @@ operator!=
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline Foam::labelRanges::const_iterator
Foam::labelRanges::cbegin() const noexcept
inline Foam::label Foam::labelRanges::totalSize() const noexcept
{
return const_iterator(this);
label total = 0;
for (const labelRange& range : ranges_)
{
if (range.size() > 0) // Ignore negative size (paranoid)
{
total += range.size();
}
}
return total;
}
inline const Foam::labelRanges::const_iterator
Foam::labelRanges::cend() const noexcept
inline bool Foam::labelRanges::contains(const label value) const noexcept
{
return const_iterator(this, this->size());
}
inline Foam::labelRanges::const_iterator
Foam::labelRanges::begin() const noexcept
{
return const_iterator(this);
}
inline const Foam::labelRanges::const_iterator
Foam::labelRanges::end() const noexcept
{
return const_iterator(this, this->size());
}
inline bool Foam::labelRanges::contains(const label value) const
{
for
(
const labelRange& range
: static_cast<const StorageContainer&>(*this)
)
for (const labelRange& range : ranges_)
{
if (range.contains(value))
{
@ -155,4 +161,82 @@ inline bool Foam::labelRanges::contains(const label value) const
}
template<class... Args>
inline Foam::labelRange& Foam::labelRanges::emplace_back(Args&&... args)
{
return ranges_.emplace_back(args...);
}
inline void Foam::labelRanges::sort()
{
Foam::sort(ranges_);
}
// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
inline Foam::labelRanges::const_iterator
Foam::labelRanges::cbegin() const noexcept
{
return const_iterator(&ranges_);
}
inline const Foam::labelRanges::const_iterator
Foam::labelRanges::cend() const noexcept
{
return const_iterator(&ranges_, ranges_.size());
}
inline Foam::labelRanges::const_iterator
Foam::labelRanges::begin() const noexcept
{
return const_iterator(&ranges_);
}
inline const Foam::labelRanges::const_iterator
Foam::labelRanges::end() const noexcept
{
return const_iterator(&ranges_, ranges_.size());
}
inline Foam::labelRanges::const_iterator
Foam::labelRanges::cbegin(const label i) const
{
if (i <= 0) return this->cbegin();
label idx = 0;
label subIdx = i;
for (const labelRange& range : ranges_)
{
if (subIdx < range.size())
{
return const_iterator(&ranges_, idx, subIdx);
}
else
{
++idx;
if (range.size() > 0) // Ignore negative size (paranoid)
{
subIdx -= range.size();
}
}
}
return this->cend();
}
inline Foam::labelRanges::const_iterator
Foam::labelRanges::begin(const label i) const
{
return this->cbegin(i);
}
// ************************************************************************* //