Commit 5d541def authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: simplify and extend labelRange

- add increment/decrement, repositioning. Simplify const_iterator.

- this makes is much easier to use labelRange for constructing ranges of
  sub-lists. For symmetry with setSize() it has a setStart() instead of
  simply assigning to start() directly. This would also provide the
  future possibility to imbue the labelRange with a particular policy
  (eg, no negative starts, max size etc) and ensure that they are
  enforced.

  A simple use case:

    // initialize each to zero...
    List<labelRange> subListRanges = ...;

    // scan and categorize
    if (condition)
       subListRanges[categoryI]++;  // increment size for that category

    // finally, set the starting points
    start = 0;
    for (labelRange& range : subListRanges)
    {
        range.setStart(start);
        start += range.size();
    }
parent 45c29be3
......@@ -35,7 +35,7 @@ License
template<class T>
Foam::labelRange Foam::UList<T>::validateRange(const labelRange& range) const
{
const labelRange slice = range.subset(0, this->size());
const labelRange slice = range.subset0(this->size());
#ifdef FULLDEBUG
this->checkStart(slice.start());
......
......@@ -289,12 +289,10 @@ public:
//- Type of values the UList contains
typedef T value_type;
//- Type that can be used for storing into
// UList::value_type objects
//- The type used for storing into value_type objects
typedef T& reference;
//- Type that can be used for storing into
// constant UList::value_type objects
//- The type used for reading from constant value_type objects.
typedef const T& const_reference;
//- The type that can represent the difference between any two
......
......@@ -52,11 +52,17 @@ void Foam::labelRange::adjust()
{
if (start_ < 0)
{
size_ += start_;
if (size_ <= 0)
{
size_ = 0;
}
else
{
size_ += start_;
}
start_ = 0;
}
if (size_ < 0)
else if (size_ < 0)
{
size_ = 0;
}
......@@ -65,7 +71,7 @@ void Foam::labelRange::adjust()
bool Foam::labelRange::overlaps(const labelRange& range, bool touches) const
{
const label final = touches ? 1 : 0;
const label extra = touches ? 1 : 0;
return
(
......@@ -74,12 +80,12 @@ bool Foam::labelRange::overlaps(const labelRange& range, bool touches) const
(
(
range.first() >= this->first()
&& range.first() <= this->last() + final
&& range.first() <= this->last() + extra
)
||
(
this->first() >= range.first()
&& this->first() <= range.last() + final
&& this->first() <= range.last() + extra
)
)
);
......@@ -134,7 +140,26 @@ Foam::labelRange Foam::labelRange::subset
) const
{
const label lower = Foam::max(this->start(), start);
const label upper = Foam::min(this->last(), start+Foam::max(0,size)-1);
const label upper = Foam::min(this->last(), start+Foam::max(0,size-1));
const label total = upper+1 - lower;
// last = start+size-1
// size = last+1-start
if (total > 0)
{
return labelRange(lower, total);
}
else
{
return labelRange();
}
}
Foam::labelRange Foam::labelRange::subset0(const label size) const
{
const label lower = Foam::max(this->start(), 0);
const label upper = Foam::min(this->last(), Foam::max(0,size-1));
const label total = upper+1 - lower;
// last = start+size-1
// size = last+1-start
......
......@@ -65,6 +65,17 @@ public:
static int debug;
// STL type definitions similar to what UList has
//- Type of values the range contains
typedef label value_type;
//- The type that can represent the difference between two iterators
typedef label difference_type;
//- The type that can represent the size of the range
typedef label size_type;
// Constructors
......@@ -86,12 +97,21 @@ public:
// Member Functions
//- Alias for setSize(const label)
inline void resize(const label n);
//- Adjust start position
inline void setStart(const label i);
//- Adjust size
inline void setSize(const label n);
//- Alias for setSize()
inline void resize(const label n);
//- Decrease the size by 1, but never below 0.
inline void decrement();
//- Increase the size by 1.
inline void increment();
//- Reset to zero start and zero size
inline void clear();
......@@ -116,6 +136,12 @@ public:
//- The (inclusive) upper value of the range
inline label last() const;
//- The value before the start of the range
inline label before() const;
//- The value after the last element in the range
inline label after() const;
//- Reset start and size, enforcing non-negative size.
// Optionally adjust the start to avoid any negative indices.
// Return true if the updated range valid (non-empty).
......@@ -142,63 +168,71 @@ public:
// for start/size.
labelRange subset(const labelRange& range) const;
//- Calculate the intersection of the range with another.
//- Calculate the intersection with the given start/size range.
// If there is no intersection, it returns an empty range with zero
// for start/size.
labelRange subset(const label start, const label size) const;
//- Calculate the intersection with the given 0/size range.
// If there is no intersection, it returns an empty range with zero
// for start/size.
labelRange subset0(const label size) const;
// Member Operators
//- Return element in the range, no bounds checking
inline label operator[](const label localIndex) const;
//- Increase the size by 1.
inline label operator++();
inline label operator++(int);
//- Decrease the size by 1, but never below 0.
inline label operator--();
inline label operator--(int);
// STL iterator
//- An STL const_iterator
//- Forward iterator with const access
class const_iterator
{
friend class labelRange;
// Private data
//- Reference to the range for which this is an iterator
const labelRange* range_;
//- Current index, relative to the start
//- The current label (not the local index)
label index_;
public:
// Constructors
//- Construct from range at given index.
//- Construct from range at given local index.
// A negative index signals the 'end' position
inline const_iterator(const labelRange* range, const label i);
public:
inline const_iterator(const labelRange* range, const label i = 0);
// Member operators
inline bool operator==(const const_iterator& iter) const;
inline bool operator!=(const const_iterator& iter) const;
//- Return the current label
inline label operator*() const;
inline const_iterator& operator++();
inline const_iterator operator++(int);
inline bool operator==(const const_iterator& iter) const;
inline bool operator!=(const const_iterator& iter) const;
};
//- A const_iterator set to the beginning of the range
// The value returned is guaranteed to be the same as start()
inline const_iterator begin() const;
//- A const_iterator set to the beginning of the range
// The value returned is guaranteed to be the same as start()
inline const_iterator cbegin() const;
//- A const_iterator set to beyond the end of the range
inline const const_iterator cend() const;
//- A const_iterator set to the beginning of the range
inline const_iterator begin() const;
//- A const_iterator set to beyond the end of the range
inline const const_iterator end() const;
......
......@@ -64,32 +64,17 @@ inline Foam::labelRange::const_iterator::const_iterator
const label i
)
:
range_(range),
index_(i < 0 ? range->size() : i)
index_
(
range->start()
+ ((i < 0 || i > range->size()) ? range->size() : i)
)
{}
inline bool Foam::labelRange::const_iterator::operator==
(
const const_iterator& iter
) const
{
return (this->index_ == iter.index_);
}
inline bool Foam::labelRange::const_iterator::operator!=
(
const const_iterator& iter
) const
{
return (this->index_ != iter.index_);
}
inline Foam::label Foam::labelRange::const_iterator::operator*() const
{
return range_->start_ + index_;
return index_;
}
......@@ -110,15 +95,21 @@ Foam::labelRange::const_iterator::operator++(int)
}
inline Foam::labelRange::const_iterator Foam::labelRange::cbegin() const
inline bool Foam::labelRange::const_iterator::operator==
(
const const_iterator& iter
) const
{
return const_iterator(this, 0);
return (this->index_ == iter.index_);
}
inline const Foam::labelRange::const_iterator Foam::labelRange::cend() const
inline bool Foam::labelRange::const_iterator::operator!=
(
const const_iterator& iter
) const
{
return const_iterator(this, -1);
return (this->index_ != iter.index_);
}
......@@ -128,28 +119,55 @@ inline Foam::labelRange::const_iterator Foam::labelRange::begin() const
}
inline Foam::labelRange::const_iterator Foam::labelRange::cbegin() const
{
return const_iterator(this, 0);
}
inline const Foam::labelRange::const_iterator Foam::labelRange::end() const
{
return const_iterator(this, -1);
}
inline const Foam::labelRange::const_iterator Foam::labelRange::cend() const
{
return const_iterator(this, -1);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline void Foam::labelRange::resize(const label n)
inline void Foam::labelRange::setStart(const label i)
{
setSize(n);
start_ = i;
}
inline void Foam::labelRange::setSize(const label n)
{
size_ = n;
if (size_ < 0) size_ = 0;
}
if (size_ < 0)
{
size_ = 0;
}
inline void Foam::labelRange::resize(const label n)
{
setSize(n);
}
inline void Foam::labelRange::decrement()
{
--size_;
if (size_ < 0) size_ = 0;
}
inline void Foam::labelRange::increment()
{
++size_;
}
......@@ -195,6 +213,18 @@ inline Foam::label Foam::labelRange::last() const
}
inline Foam::label Foam::labelRange::before() const
{
return start_ - 1;
}
inline Foam::label Foam::labelRange::after() const
{
return start_ + size_;
}
inline bool Foam::labelRange::reset
(
const label start,
......@@ -234,4 +264,31 @@ inline Foam::label Foam::labelRange::operator[](const label localIndex) const
}
inline Foam::label Foam::labelRange::operator++()
{
return ++size_;
}
inline Foam::label Foam::labelRange::operator++(int)
{
return size_++;
}
inline Foam::label Foam::labelRange::operator--()
{
decrement();
return size_;
}
inline Foam::label Foam::labelRange::operator--(int)
{
const label old = size_;
decrement();
return old;
}
// ************************************************************************* //
......@@ -44,7 +44,7 @@ void Foam::labelRanges::insertBefore
<< *this << endl;
}
ParentType::setSize(nElem+1);
StorageContainer::setSize(nElem+1);
if (labelRange::debug)
{
......@@ -58,7 +58,7 @@ void Foam::labelRanges::insertBefore
Info<<"copy from " << (i) << " to " << (i+1) << nl;
}
ParentType::operator[](i+1) = ParentType::operator[](i);
StorageContainer::operator[](i+1) = StorageContainer::operator[](i);
}
// finally insert the range
......@@ -66,7 +66,7 @@ void Foam::labelRanges::insertBefore
{
Info<< "finally insert the range at " << insert << nl;
}
ParentType::operator[](insert) = range;
StorageContainer::operator[](insert) = range;
}
......@@ -76,18 +76,19 @@ void Foam::labelRanges::purgeEmpty()
label nElem = 0;
forAll(*this, elemI)
{
if (!ParentType::operator[](elemI).empty())
if (!StorageContainer::operator[](elemI).empty())
{
if (nElem != elemI)
{
ParentType::operator[](nElem) = ParentType::operator[](elemI);
StorageContainer::operator[](nElem) =
StorageContainer::operator[](elemI);
}
++nElem;
}
}
// truncate
this->ParentType::setSize(nElem);
this->StorageContainer::setSize(nElem);
}
......@@ -134,7 +135,7 @@ bool Foam::labelRanges::add(const labelRange& range)
// find the correct place for insertion
forAll(*this, elemI)
{
labelRange& currRange = ParentType::operator[](elemI);
labelRange& currRange = StorageContainer::operator[](elemI);
if (currRange.overlaps(range, true))
{
......@@ -144,7 +145,7 @@ bool Foam::labelRanges::add(const labelRange& range)
// might connect with the next following range(s)
for (; elemI < this->size()-1; ++elemI)
{
labelRange& nextRange = ParentType::operator[](elemI+1);
labelRange& nextRange = StorageContainer::operator[](elemI+1);
if (currRange.overlaps(nextRange, true))
{
currRange.join(nextRange);
......@@ -187,7 +188,7 @@ bool Foam::labelRanges::remove(const labelRange& range)
forAll(*this, elemI)
{
labelRange& currRange = ParentType::operator[](elemI);
labelRange& currRange = StorageContainer::operator[](elemI);
if (range.first() > currRange.first())
{
......@@ -290,14 +291,14 @@ bool Foam::labelRanges::remove(const labelRange& range)
Foam::Istream& Foam::operator>>(Istream& is, labelRanges& ranges)
{
is >> static_cast<labelRanges::ParentType&>(ranges);
is >> static_cast<labelRanges::StorageContainer&>(ranges);
return is;
}
Foam::Ostream& Foam::operator<<(Ostream& os, const labelRanges& ranges)
{
os << static_cast<const labelRanges::ParentType&>(ranges);
os << static_cast<const labelRanges::StorageContainer&>(ranges);
return os;
}
......
......@@ -62,7 +62,7 @@ class labelRanges
{
// Private typedefs for convenience
typedef DynamicList<labelRange> ParentType;
typedef DynamicList<labelRange> StorageContainer;
// Private Member Functions
......
......@@ -28,13 +28,13 @@ License
inline Foam::labelRanges::labelRanges()
:
ParentType()
StorageContainer()
{}
inline Foam::labelRanges::labelRanges(const label nElem)
:
ParentType(nElem)
StorageContainer(nElem)
{}
......@@ -133,7 +133,7 @@ inline bool Foam::labelRanges::found(const label value) const
{
forAll(*this, i)
{
if (ParentType::operator[](i).found(value))
if (StorageContainer::operator[](i).found(value))
{
return true;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment