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:
parent
6defeddbff
commit
750d9084d4
@ -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);
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
Loading…
Reference in New Issue
Block a user