From 3aa49fef5e94cc71170d2b7ca7396221b7982ba7 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Mon, 13 Dec 2010 11:51:49 +0100 Subject: [PATCH] ENH: first version of labelRange, labelRanges - an opaque means of handling ranges of labels --- applications/test/labelRanges/Make/files | 3 + applications/test/labelRanges/Make/options | 0 .../test/labelRanges/Test-labelRanges.C | 121 +++++++ src/OpenFOAM/Make/files | 2 + .../primitives/ranges/labelRange/labelRange.C | 156 +++++++++ .../primitives/ranges/labelRange/labelRange.H | 215 ++++++++++++ .../ranges/labelRange/labelRangeI.H | 205 ++++++++++++ .../ranges/labelRange/labelRanges.C | 310 ++++++++++++++++++ .../ranges/labelRange/labelRanges.H | 191 +++++++++++ .../ranges/labelRange/labelRangesI.H | 166 ++++++++++ 10 files changed, 1369 insertions(+) create mode 100644 applications/test/labelRanges/Make/files create mode 100644 applications/test/labelRanges/Make/options create mode 100644 applications/test/labelRanges/Test-labelRanges.C create mode 100644 src/OpenFOAM/primitives/ranges/labelRange/labelRange.C create mode 100644 src/OpenFOAM/primitives/ranges/labelRange/labelRange.H create mode 100644 src/OpenFOAM/primitives/ranges/labelRange/labelRangeI.H create mode 100644 src/OpenFOAM/primitives/ranges/labelRange/labelRanges.C create mode 100644 src/OpenFOAM/primitives/ranges/labelRange/labelRanges.H create mode 100644 src/OpenFOAM/primitives/ranges/labelRange/labelRangesI.H diff --git a/applications/test/labelRanges/Make/files b/applications/test/labelRanges/Make/files new file mode 100644 index 0000000000..df0fcc4843 --- /dev/null +++ b/applications/test/labelRanges/Make/files @@ -0,0 +1,3 @@ +Test-labelRanges.C + +EXE = $(FOAM_USER_APPBIN)/Test-labelRanges diff --git a/applications/test/labelRanges/Make/options b/applications/test/labelRanges/Make/options new file mode 100644 index 0000000000..e69de29bb2 diff --git a/applications/test/labelRanges/Test-labelRanges.C b/applications/test/labelRanges/Test-labelRanges.C new file mode 100644 index 0000000000..d7ef91301d --- /dev/null +++ b/applications/test/labelRanges/Test-labelRanges.C @@ -0,0 +1,121 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Application + +Description + Test label ranges +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "IOobject.H" +#include "IOstreams.H" +#include "IFstream.H" +#include "IStringStream.H" +#include "labelRanges.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + argList::validArgs.insert("start size .. startN sizeN"); + argList::addOption("verbose"); + argList::addNote + ( + "The default is to add ranges, use 'add' and 'del' to toggle\n\n" + "Eg, 0 10 30 10 del 20 15" + ); + + argList args(argc, argv, false, true); + + if (args.optionFound("verbose")) + { + labelRange::debug = 1; + } + + + labelRanges ranges; + + bool removeMode = false; + for (label argI=1; argI < args.size()-1; ++argI) + { + if (args[argI] == "add") + { + removeMode = false; + continue; + } + else if (args[argI] == "del") + { + removeMode = true; + continue; + } + + label start = 0; + label size = 0; + + IStringStream(args[argI])() >> start; + ++argI; + IStringStream(args[argI])() >> size; + + labelRange range(start, size); + + Info<< "---------------" << nl; + if (removeMode) + { + Info<< "del " << range << " :"; + forAllConstIter(labelRange, range, iter) + { + Info<< " " << iter(); + } + Info<< nl; + + ranges.remove(range); + } + else + { + Info<< "add " << range << " :"; + forAllConstIter(labelRange, range, iter) + { + Info<< " " << iter(); + } + Info<< nl; + + ranges.add(range); + } + + Info<< "" << ranges << "" << nl; + forAllConstIter(labelRanges, ranges, iter) + { + Info<< " " << iter(); + } + Info<< nl; + } + + return 0; +} + +// ************************************************************************* // diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 6f0c12d89a..9cc3dd17b9 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -65,6 +65,8 @@ primitives/random/Random/Random.C primitives/random/cachedRandom/cachedRandom.H ranges = primitives/ranges +$(ranges)/labelRange/labelRange.C +$(ranges)/labelRange/labelRanges.C $(ranges)/scalarRange/scalarRange.C $(ranges)/scalarRange/scalarRanges.C diff --git a/src/OpenFOAM/primitives/ranges/labelRange/labelRange.C b/src/OpenFOAM/primitives/ranges/labelRange/labelRange.C new file mode 100644 index 0000000000..fa4ed366cf --- /dev/null +++ b/src/OpenFOAM/primitives/ranges/labelRange/labelRange.C @@ -0,0 +1,156 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "labelRange.H" +#include "token.H" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::labelRange::const_iterator Foam::labelRange::endIter_; + +int Foam::labelRange::debug(::Foam::debug::debugSwitch("labelRange", 0)); + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::labelRange::labelRange(Istream& is) +: + start_(0), + size_(0) +{ + is >> *this; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::labelRange::intersects +( + const labelRange& range, + const bool touches +) const +{ + label final = touches ? 1 : 0; + + return + ( + this->size() + && range.size() + && + ( + ( + range.first() >= this->first() + && range.first() <= this->last() + final + ) + || + ( + this->first() >= range.first() + && this->first() <= range.last() + final + ) + ) + ); +} + + +Foam::labelRange Foam::labelRange::join(const labelRange& range) const +{ + // trivial cases first + if (!size_) + { + return *this; + } + else if (!range.size_) + { + return range; + } + + const label lower = Foam::min(this->first(), range.first()); + const label upper = Foam::max(this->last(), range.last()); + const label sz = upper - lower + 1; + + return labelRange(lower, sz); +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +Foam::labelRange& Foam::labelRange::operator+=(const labelRange& rhs) +{ + if (!size_) + { + // trivial case + operator=(rhs); + } + else if (rhs.size_) + { + const label lower = Foam::min(this->first(), rhs.first()); + const label upper = Foam::max(this->last(), rhs.last()); + + start_ = lower; + size_ = upper - lower + 1; + } + + return *this; +} + + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>>(Istream& is, labelRange& range) +{ + is.readBegin("labelRange"); + is >> range.start_ >> range.size_; + is.readEnd("labelRange"); + + is.check("operator>>(Istream&, labelRange&)"); + + // disallow invalid sizes + if (range.size_ <= 0) + { + range.clear(); + } + + return is; +} + + +Foam::Ostream& Foam::operator<<(Ostream& os, const labelRange& range) +{ + // write ASCII only for now + os << token::BEGIN_LIST + << range.start_ << token::SPACE << range.size_ + << token::END_LIST; + +// os << token::BEGIN_BLOCK +// << range.start_ << "-" << range.last() +// << token::END_BLOCK; + + os.check("operator<<(Ostream&, const labelRange&)"); + return os; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ranges/labelRange/labelRange.H b/src/OpenFOAM/primitives/ranges/labelRange/labelRange.H new file mode 100644 index 0000000000..2d4fcc4f84 --- /dev/null +++ b/src/OpenFOAM/primitives/ranges/labelRange/labelRange.H @@ -0,0 +1,215 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::labelRange + +Description + A label range specifier. + +SourceFiles + labelRange.C + +\*---------------------------------------------------------------------------*/ +#ifndef labelRange_H +#define labelRange_H + +#include "label.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes +class Istream; +class Ostream; + +// Forward declaration of friend functions and operators +class labelRange; +Istream& operator>>(Istream&, labelRange&); +Ostream& operator<<(Ostream&, const labelRange&); + +/*---------------------------------------------------------------------------*\ + Class labelRange Declaration +\*---------------------------------------------------------------------------*/ + +class labelRange +{ + // Private data + + label start_; + label size_; + +public: + + static int debug; + + + // Public classes + + //- Less function class for sorting labelRange + class less + { + public: + + bool operator()(const labelRange& a, const labelRange& b) + { + return a.first() < b.first(); + } + }; + + // Constructors + + //- Construct an empty range + inline labelRange(); + + //- Construct a range + // A negative size is autmatically changed to zero. + inline labelRange(const label start, const label size); + + //- Construct from Istream. + labelRange(Istream&); + + + // Member Functions + + //- Reset to zero size + inline void clear(); + + //- Is the range empty? + inline bool empty() const; + + //- Return the effective size of the range + inline label size() const; + + //- The (inclusive) lower value of the range + inline label first() const; + + //- The (inclusive) upper value of the range + inline label last() const; + + //- Return true if the value is within the range + inline bool contains(const label) const; + + //- Return true if the ranges intersect + // Optional test for ranges that also just touch each other + bool intersects(const labelRange&, const bool touches = false) const; + + //- Return a joined range, squashing any gaps in between + // A prior intersects() check can be used to avoid squashing gaps. + labelRange join(const labelRange&) const; + + + // Member Operators + + //- Return element in range, no bounds checking + inline label operator[](const label) const; + + //- Comparison function for sorting, compares the start + inline bool operator<(const labelRange& rhs) const; + + //- Join ranges, squashing any gaps in between + // A prior intersects() check can be used to avoid squashing gaps. + labelRange& operator+=(const labelRange&); + + inline bool operator==(const labelRange&) const; + inline bool operator!=(const labelRange&) const; + + + // STL iterator + + //- An STL const_iterator + class const_iterator + { + // Private data + + //- Reference to the range for which this is an iterator + const labelRange& range_; + + //- Current index + label index_; + + public: + + // Constructors + + //- Construct null - equivalent to an 'end' position + inline const_iterator(); + + //- Construct from range, moving to its 'begin' position + inline explicit const_iterator(const labelRange&); + + + // Member operators + + inline bool operator==(const const_iterator&) const; + + inline bool operator!=(const const_iterator&) const; + + inline label operator*(); + inline label operator()(); + + inline const_iterator& operator++(); + inline const_iterator operator++(int); + }; + + + //- const_iterator set to the beginning of the range + inline const_iterator cbegin() const; + + //- const_iterator set to beyond the end of the range + inline const const_iterator& cend() const; + + //- const_iterator set to the beginning of the range + inline const_iterator begin() const; + + //- const_iterator set to beyond the end of the range + inline const const_iterator& end() const; + + + // IOstream Operators + + friend Istream& operator>>(Istream&, labelRange&); + friend Ostream& operator<<(Ostream&, const labelRange&); + + +private: + + //- const_iterator returned by end(), cend() + static const const_iterator endIter_; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "labelRangeI.H" + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ranges/labelRange/labelRangeI.H b/src/OpenFOAM/primitives/ranges/labelRange/labelRangeI.H new file mode 100644 index 0000000000..3070657cca --- /dev/null +++ b/src/OpenFOAM/primitives/ranges/labelRange/labelRangeI.H @@ -0,0 +1,205 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +inline Foam::labelRange::labelRange() +: + start_(0), + size_(0) +{} + + +inline Foam::labelRange::labelRange(const label start, const label size) +: + start_(start), + size_(size) +{ + // disallow invalid sizes + if (size_ <= 0) + { + this->clear(); + } +} + + +// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * // + +inline Foam::labelRange::const_iterator::const_iterator() +: + range_(*reinterpret_cast< Foam::labelRange* >(0)), + index_(-1) +{} + + +inline Foam::labelRange::const_iterator::const_iterator(const labelRange& range) +: + range_(range), + index_(range_.empty() ? -1 : 0) +{} + + +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->operator==(iter)); +} + + +inline Foam::label Foam::labelRange::const_iterator::operator*() +{ + return range_[index_]; +} + + +inline Foam::label Foam::labelRange::const_iterator::operator()() +{ + return range_[index_]; +} + + +inline Foam::labelRange::const_iterator& +Foam::labelRange::const_iterator::operator++() +{ + if (++index_ >= range_.size()) + { + // equivalent to end iterator + index_ = -1; + } + + return *this; +} + + +inline Foam::labelRange::const_iterator +Foam::labelRange::const_iterator::operator++(int) +{ + const_iterator old = *this; + this->operator++(); + return old; +} + + +inline Foam::labelRange::const_iterator Foam::labelRange::cbegin() const +{ + return const_iterator(*this); +} + + +inline const Foam::labelRange::const_iterator& Foam::labelRange::cend() const +{ + return endIter_; +} + + +inline Foam::labelRange::const_iterator Foam::labelRange::begin() const +{ + return const_iterator(*this); +} + + +inline const Foam::labelRange::const_iterator& Foam::labelRange::end() const +{ + return endIter_; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline void Foam::labelRange::clear() +{ + start_ = size_ = 0; +} + + +inline bool Foam::labelRange::empty() const +{ + return !size_; +} + + +inline Foam::label Foam::labelRange::size() const +{ + return size_; +} + + +inline Foam::label Foam::labelRange::first() const +{ + return start_; +} + + +inline Foam::label Foam::labelRange::last() const +{ + return start_ + size_ - 1; +} + + +inline bool Foam::labelRange::contains(const label value) const +{ + return value >= this->first() && value <= this->last(); +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +inline Foam::label Foam::labelRange::operator[](const label i) const +{ + return start_ + i; +} + + +inline bool Foam::labelRange::operator<(const labelRange& rhs) const +{ + return this->first() < rhs.first(); +} + + +inline bool Foam::labelRange::operator==(const labelRange& rhs) const +{ + return start_ == rhs.start_ && size_ == rhs.size_; +} + + +inline bool Foam::labelRange::operator!=(const labelRange& rhs) const +{ + return !(operator==(rhs)); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ranges/labelRange/labelRanges.C b/src/OpenFOAM/primitives/ranges/labelRange/labelRanges.C new file mode 100644 index 0000000000..188e63e5f0 --- /dev/null +++ b/src/OpenFOAM/primitives/ranges/labelRange/labelRanges.C @@ -0,0 +1,310 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "labelRanges.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::labelRanges::const_iterator Foam::labelRanges::endIter_; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::labelRanges::insertBefore +( + const label insert, + const labelRange& range +) +{ + // insert via copying up + label nElem = this->size(); + + if (labelRange::debug) + { + Info<<"before insert " + << nElem << " elements, insert at " << insert << nl + << *this << endl; + } + + ParentType::setSize(nElem+1); + + if (labelRange::debug) + { + Info<<"copy between " << nElem << " and " << insert << nl; + } + + for (label i = nElem-1; i >= insert; --i) + { + if (labelRange::debug) + { + Info<<"copy from " << (i) << " to " << (i+1) << nl; + } + + ParentType::operator[](i+1) = ParentType::operator[](i); + } + + // finally insert the range + if (labelRange::debug) + { + Info<< "finally insert the range at " << insert << nl; + } + ParentType::operator[](insert) = range; +} + + +void Foam::labelRanges::purgeEmpty() +{ + // purge empty ranges by copying down + label nElem = 0; + forAll(*this, elemI) + { + if (!ParentType::operator[](elemI).empty()) + { + if (nElem != elemI) + { + ParentType::operator[](nElem) = ParentType::operator[](elemI); + } + ++nElem; + } + } + + // truncate + this->ParentType::setSize(nElem); +} + + +Foam::Ostream& Foam::labelRanges::printRange +( + Ostream& os, + const labelRange& range +) const +{ + if (range.empty()) + { + os << "empty"; + } + else + { + os << range << " = " << range.first() << ":" << range.last(); + } + return os; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::labelRanges::labelRanges(Istream& is) +{ + is >> *this; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::labelRanges::add(const labelRange& range) +{ + if (range.empty()) + { + return false; + } + else if (this->empty()) + { + this->append(range); + return true; + } + + // find the correct place for insertion + forAll(*this, elemI) + { + labelRange& currRange = ParentType::operator[](elemI); + + if (currRange.intersects(range, true)) + { + // absorb into the existing (adjacent/overlapping) range + currRange += range; + + // might connect with the next following range(s) + for (; elemI < this->size()-1; ++elemI) + { + labelRange& nextRange = ParentType::operator[](elemI+1); + if (currRange.intersects(nextRange, true)) + { + currRange += nextRange; + nextRange.clear(); + } + else + { + break; + } + } + + // done - remove any empty ranges that might have been created + purgeEmpty(); + return true; + break; + } + else if (range < currRange) + { + insertBefore(elemI, range); + return true; + break; + } + } + + + // not found: simply append + this->append(range); + + return true; +} + + +bool Foam::labelRanges::remove(const labelRange& range) +{ + bool status = false; + if (range.empty() || this->empty()) + { + return status; + } + + forAll(*this, elemI) + { + labelRange& currRange = ParentType::operator[](elemI); + + if (range.first() > currRange.first()) + { + if (range.last() < currRange.last()) + { + // removal of range fragments of currRange + + if (labelRange::debug) + { + Info<<"Fragment removal "; + printRange(Info, range) << " from "; + printRange(Info, currRange) << endl; + } + + // left-hand-side fragment: insert before current range + label lower = currRange.first(); + label upper = range.first() - 1; + + labelRange fragment(lower, upper - lower + 1); + + // right-hand-side fragment + lower = range.last() + 1; + upper = currRange.last(); + + currRange = labelRange(lower, upper - lower + 1); + status = true; + insertBefore(elemI, fragment); + + if (labelRange::debug) + { + Info<<"fragment "; + printRange(Info, fragment) << endl; + Info<<"yields "; + printRange(Info, currRange) << endl; + } + + // fragmentation can only affect a single range + // thus we are done + break; + } + else if (range.first() <= currRange.last()) + { + // keep left-hand-side, remove right-hand-side + + if (labelRange::debug) + { + Info<<"RHS removal "; + printRange(Info, range) << " from "; + printRange(Info, currRange) << endl; + } + + const label lower = currRange.first(); + const label upper = range.first() - 1; + + currRange = labelRange(lower, upper - lower + 1); + status = true; + + if (labelRange::debug) + { + Info<<"yields "; + printRange(Info, currRange) << endl; + } + } + } + else if (range.first() <= currRange.first()) + { + if (range.last() >= currRange.first()) + { + // remove left-hand-side, keep right-hand-side + + if (labelRange::debug) + { + Info<<"LHS removal "; + printRange(Info, range) << " from "; + printRange(Info, currRange) << endl; + } + + const label lower = range.last() + 1; + const label upper = currRange.last(); + + currRange = labelRange(lower, upper - lower + 1); + status = true; + + if (labelRange::debug) + { + Info<<"yields "; + printRange(Info, currRange) << endl; + } + } + } + } + + purgeEmpty(); + + return status; +} + + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>>(Istream& is, labelRanges& ranges) +{ + is >> static_cast(ranges); + return is; +} + + +Foam::Ostream& Foam::operator<<(Ostream& os, const labelRanges& ranges) +{ + os << static_cast(ranges); + return os; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ranges/labelRange/labelRanges.H b/src/OpenFOAM/primitives/ranges/labelRange/labelRanges.H new file mode 100644 index 0000000000..d8b00970d0 --- /dev/null +++ b/src/OpenFOAM/primitives/ranges/labelRange/labelRanges.H @@ -0,0 +1,191 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::labelRanges + +Description + A list of labelRange. + +SourceFiles + labelRanges.C + +\*---------------------------------------------------------------------------*/ + +#ifndef labelRanges_H +#define labelRanges_H + +#include "labelRange.H" +#include "DynamicList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes +class Istream; +class Ostream; + +// Forward declaration of friend functions and operators +class labelRanges; +Istream& operator>>(Istream&, labelRanges&); +Ostream& operator<<(Ostream&, const labelRanges&); + +/*---------------------------------------------------------------------------*\ + Class labelRanges Declaration +\*---------------------------------------------------------------------------*/ + +class labelRanges +: + private DynamicList +{ + // Private typedefs for convenience + + typedef DynamicList ParentType; + + + // Private Member Functions + + //- Insert range before specified insertion index, by copying up + void insertBefore(const label, const labelRange&); + + //- Purge empty ranges, by copying down + void purgeEmpty(); + + //- Print the range for debugging purposes + Ostream& printRange(Ostream&, const labelRange&) const; + + +public: + + // Constructors + + //- Construct null + inline labelRanges(); + + //- Construct given size + inline explicit labelRanges(const label); + + //- Construct from Istream. + labelRanges(Istream&); + + + // Member Functions + + //- Clear the addressed list + using DynamicList::clear; + + //- Return true if the list is empty + using DynamicList::empty; + + //- Return true if the value is within any of the ranges + inline bool contains(const label) const; + + //- Add the range to the list + bool add(const labelRange&); + + //- Remove the range from the list + bool remove(const labelRange&); + + // STL iterator + + //- An STL const_iterator + class const_iterator + { + // Private data + + //- Reference to the list for which this is an iterator + const labelRanges& list_; + + //- Current list index + label index_; + + //- Index of current element at listIndex + label subIndex_; + + public: + + // Constructors + + //- Construct null - equivalent to an 'end' position + inline const_iterator(); + + //- Construct from list, moving to its 'begin' position + inline explicit const_iterator(const labelRanges&); + + + // Member operators + + inline bool operator==(const const_iterator&) const; + + inline bool operator!=(const const_iterator&) const; + + inline label operator*(); + inline label operator()(); + + inline const_iterator& operator++(); + inline const_iterator operator++(int); + }; + + + //- const_iterator set to the beginning of the list + inline const_iterator cbegin() const; + + //- const_iterator set to beyond the end of the list + inline const const_iterator& cend() const; + + //- const_iterator set to the beginning of the list + inline const_iterator begin() const; + + //- const_iterator set to beyond the end of the list + inline const const_iterator& end() const; + + + // IOstream Operators + + friend Istream& operator>>(Istream&, labelRanges&); + friend Ostream& operator<<(Ostream&, const labelRanges&); + + +private: + + //- const_iterator returned by end(), cend() + static const const_iterator endIter_; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "labelRangesI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/ranges/labelRange/labelRangesI.H b/src/OpenFOAM/primitives/ranges/labelRange/labelRangesI.H new file mode 100644 index 0000000000..d4b34ace9f --- /dev/null +++ b/src/OpenFOAM/primitives/ranges/labelRange/labelRangesI.H @@ -0,0 +1,166 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +inline Foam::labelRanges::labelRanges() +: + ParentType() +{} + + +inline Foam::labelRanges::labelRanges(const label nElem) +: + ParentType(nElem) +{} + + +// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * // + +inline Foam::labelRanges::const_iterator::const_iterator() +: + list_(*reinterpret_cast< Foam::labelRanges* >(0)), + index_(-1), + subIndex_(-1) +{} + + +inline Foam::labelRanges::const_iterator::const_iterator(const labelRanges& lst) +: + list_(lst), + index_(0), + subIndex_(0) +{ + if (list_.empty()) + { + // equivalent to end iterator + index_ = subIndex_ = -1; + } +} + + +inline bool Foam::labelRanges::const_iterator::operator== +( + const const_iterator& iter +) const +{ + return + ( + this->index_ == iter.index_ + && this->subIndex_ == iter.subIndex_ + ); +} + + +inline bool Foam::labelRanges::const_iterator::operator!= +( + const const_iterator& iter +) const +{ + return !(this->operator==(iter)); +} + + +inline Foam::label Foam::labelRanges::const_iterator::operator*() +{ + return list_[index_][subIndex_]; +} + + +inline Foam::label Foam::labelRanges::const_iterator::operator()() +{ + return list_[index_][subIndex_]; +} + + +inline Foam::labelRanges::const_iterator& +Foam::labelRanges::const_iterator::operator++() +{ + if (++subIndex_ >= list_[index_].size()) + { + // go to next list entry + subIndex_ = 0; + if (++index_ >= list_.size()) + { + // equivalent to end iterator + index_ = subIndex_ = -1; + } + } + + return *this; +} + + +inline Foam::labelRanges::const_iterator +Foam::labelRanges::const_iterator::operator++(int) +{ + const_iterator old = *this; + this->operator++(); + return old; +} + + +inline Foam::labelRanges::const_iterator Foam::labelRanges::cbegin() const +{ + return const_iterator(*this); +} + + +inline const Foam::labelRanges::const_iterator& Foam::labelRanges::cend() const +{ + return endIter_; +} + + +inline Foam::labelRanges::const_iterator Foam::labelRanges::begin() const +{ + return const_iterator(*this); +} + + +inline const Foam::labelRanges::const_iterator& Foam::labelRanges::end() const +{ + return endIter_; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline bool Foam::labelRanges::contains(const label value) const +{ + forAll(*this, i) + { + if (this->ParentType::operator[](i).contains(value)) + { + return true; + } + } + + return false; +} + + +// ************************************************************************* //