ENH: add labelRange comparison operators and subset methods

- improve interface consistency.
This commit is contained in:
Mark Olesen
2017-04-30 21:29:24 +02:00
parent 7b427c382e
commit 75ef6f4e50
11 changed files with 252 additions and 192 deletions

View File

@ -54,6 +54,34 @@ int main(int argc, char *argv[])
labelRange::debug = 1; labelRange::debug = 1;
} }
{
Info<<"test sorting" << endl;
DynamicList<labelRange> list1(10);
list1.append(labelRange(25, 8));
list1.append(labelRange(0, 10));
list1.append(labelRange(15, 5));
list1.append(labelRange(50, -10));
sort(list1);
Info<<"sorted" << list1 << endl;
}
{
Info<<"test intersections" << endl;
labelRange range1(-15, 25);
labelRange range2(7, 8);
labelRange range3(-20, 8);
labelRange range4(50, 8);
Info<<range1 << " & " << range2
<< " = " << range1.subset(range2) << nl;
Info<< range1 << " & " << range3
<< " = " << range1.subset(range3) << nl;
Info<< range2 << " & " << range4
<< " = " << range2.subset(range4) << nl;
}
labelRange range; labelRange range;
labelRanges ranges; labelRanges ranges;

View File

@ -29,7 +29,10 @@ License
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::labelRange::debug(::Foam::debug::debugSwitch("labelRange", 0)); namespace Foam
{
int labelRange::debug(debug::debugSwitch("labelRange", 0));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -66,8 +69,7 @@ bool Foam::labelRange::overlaps(const labelRange& range, bool touches) const
return return
( (
this->size() this->size() && range.size()
&& range.size()
&& &&
( (
( (
@ -91,35 +93,59 @@ Foam::labelRange Foam::labelRange::join(const labelRange& range) const
{ {
return *this; return *this;
} }
else if (!range.size_) else if (!range.size())
{ {
return range; return range;
} }
const label lower = Foam::min(this->first(), range.first()); const label lower = Foam::min(this->first(), range.first());
const label upper = Foam::max(this->last(), range.last()); const label upper = Foam::max(this->last(), range.last());
const label sz = upper - lower + 1; const label total = upper+1 - lower;
// last = start+size-1
// size = last+1-start
return labelRange(lower, sz); return labelRange(lower, total);
} }
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // Foam::labelRange Foam::labelRange::subset(const labelRange& range) const
void Foam::labelRange::operator+=(const labelRange& rhs)
{ {
if (!size_) const label lower = Foam::max(this->first(), range.first());
{ const label upper = Foam::min(this->last(), range.last());
// trivial case const label total = upper+1 - lower;
operator=(rhs); // last = start+size-1
} // size = last+1-start
else if (rhs.size_)
{
const label lower = Foam::min(this->first(), rhs.first());
const label upper = Foam::max(this->last(), rhs.last());
start_ = lower; if (total > 0)
size_ = upper - lower + 1; {
return labelRange(lower, total);
}
else
{
return labelRange();
}
}
Foam::labelRange Foam::labelRange::subset
(
const label start,
const label size
) const
{
const label lower = Foam::max(this->start(), start);
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();
} }
} }
@ -148,7 +174,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const labelRange& range)
{ {
// Write ASCII only for now // Write ASCII only for now
os << token::BEGIN_LIST os << token::BEGIN_LIST
<< range.start_ << token::SPACE << range.size_ << range.start() << token::SPACE << range.size()
<< token::END_LIST; << token::END_LIST;
os.check("operator<<(Ostream&, const labelRange&)"); os.check("operator<<(Ostream&, const labelRange&)");

View File

@ -25,7 +25,7 @@ Class
Foam::labelRange Foam::labelRange
Description Description
A range of labels. A range of labels defined by a start and a size.
SourceFiles SourceFiles
labelRange.C labelRange.C
@ -66,28 +66,13 @@ public:
static int debug; static int debug;
// Public classes
//- Less function class for sorting labelRange
class less
{
public:
bool operator()(const labelRange& a, const labelRange& b)
{
return a.operator<(b);
}
};
// Constructors // Constructors
//- Construct an empty range with zero as start and size. //- An empty range with zero for start/size.
inline labelRange(); inline labelRange();
//- Construct a range from start and size. //- Construct a range from start and size, enforcing non-negative size.
// Optionally adjust the start to avoid any negative indices. // Optionally adjust the start to avoid any negative indices.
// Always reduce a negative size to zero.
inline labelRange inline labelRange
( (
const label start, const label start,
@ -116,21 +101,23 @@ public:
//- Adjust the start to avoid any negative indices //- Adjust the start to avoid any negative indices
void adjust(); void adjust();
//- Is the range valid (non-empty)? //- Is the range non-empty?
inline bool valid() const; inline bool valid() const;
//- Return the effective size of the range //- The (inclusive) lower value of the range
inline label start() const;
//- The effective size of the range
inline label size() const; inline label size() const;
//- The (inclusive) lower value of the range //- The (inclusive) lower value of the range - same as start
inline label first() const; inline label first() const;
//- The (inclusive) upper value of the range //- The (inclusive) upper value of the range
inline label last() const; inline label last() const;
//- Reset start and size. //- Reset start and size, enforcing non-negative size.
// Optionally adjust the start to avoid any negative indices. // Optionally adjust the start to avoid any negative indices.
// Always reduce a negative size to zero.
// Return true if the updated range valid (non-empty). // Return true if the updated range valid (non-empty).
inline bool reset inline bool reset
( (
@ -139,8 +126,8 @@ public:
const bool adjustStart = false const bool adjustStart = false
); );
//- Return true if the value is within the range //- Return true if the value is located the range
inline bool contains(const label value) const; inline bool found(const label value) const;
//- Return true if the ranges overlap. //- Return true if the ranges overlap.
// Optional test for ranges that also just touch each other // Optional test for ranges that also just touch each other
@ -150,22 +137,21 @@ public:
// A prior overlaps() check can be used to avoid squashing gaps. // A prior overlaps() check can be used to avoid squashing gaps.
labelRange join(const labelRange& range) const; labelRange join(const labelRange& range) const;
//- Calculate the intersection of the range with another.
// If there is no intersection, it returns an empty range with zero
// for start/size.
labelRange subset(const labelRange& range) const;
//- Calculate the intersection of the range with another.
// If there is no intersection, it returns an empty range with zero
// for start/size.
labelRange subset(const label start, const label size) const;
// Member Operators // Member Operators
//- Return element in range, no bounds checking //- Return element in the range, no bounds checking
inline label operator[](const label i) const; inline label operator[](const label localIndex) const;
//- Comparison function for sorting, compares the start.
// If the start values are equal, also compares the size.
inline bool operator<(const labelRange& rhs) const;
//- Join ranges, squashing any gaps in between
// A prior overlaps() check can be used to avoid squashing gaps.
void operator+=(const labelRange& rhs);
inline bool operator==(const labelRange& rhs) const;
inline bool operator!=(const labelRange& rhs) const;
// STL iterator // STL iterator
@ -175,36 +161,32 @@ public:
{ {
friend class labelRange; friend class labelRange;
// Private data // Private data
//- Reference to the range for which this is an iterator //- Reference to the range for which this is an iterator
const labelRange& range_; const labelRange* range_;
//- Current index //- Current index, relative to the start
label index_; label index_;
// Constructors
// Constructors //- Construct from range at given index.
// A negative index signals the 'end' position
//- Construct from range at 'begin' or 'end' position inline const_iterator(const labelRange* range, const label i);
inline const_iterator
(
const labelRange& range,
const bool endIter = false
);
public: public:
// Member operators // Member operators
inline bool operator==(const const_iterator& iter) const; inline bool operator==(const const_iterator& iter) const;
inline bool operator!=(const const_iterator& iter) const; inline bool operator!=(const const_iterator& iter) const;
inline label operator*() const; //- Return the current label
inline label operator()() const; inline label operator*() const;
inline const_iterator& operator++(); inline const_iterator& operator++();
inline const_iterator operator++(int); inline const_iterator operator++(int);
}; };
@ -229,6 +211,51 @@ public:
}; };
// Global Operators
inline bool operator==(const labelRange& a, const labelRange& b)
{
return (a.first() == b.first() && a.size() == b.size());
}
inline bool operator!=(const labelRange& a, const labelRange& b)
{
return !(a == b);
}
//- Comparison function for sorting, compares the start.
// If the start values are equal, also compares the size.
inline bool operator<(const labelRange& a, const labelRange& b)
{
return
(
a.first() < b.first()
||
(
!(b.first() < a.first())
&& a.size() < b.size()
)
);
}
inline bool operator<=(const labelRange& a, const labelRange& b)
{
return !(b < a);
}
inline bool operator>(const labelRange& a, const labelRange& b)
{
return (b < a);
}
inline bool operator>=(const labelRange& a, const labelRange& b)
{
return !(a < b);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam } // End namespace Foam

View File

@ -60,12 +60,12 @@ inline Foam::labelRange::labelRange
inline Foam::labelRange::const_iterator::const_iterator inline Foam::labelRange::const_iterator::const_iterator
( (
const labelRange& range, const labelRange* range,
const bool endIter const label i
) )
: :
range_(range), range_(range),
index_(endIter ? range_.size() : 0) index_(i < 0 ? range->size() : i)
{} {}
@ -89,13 +89,7 @@ inline bool Foam::labelRange::const_iterator::operator!=
inline Foam::label Foam::labelRange::const_iterator::operator*() const inline Foam::label Foam::labelRange::const_iterator::operator*() const
{ {
return range_[index_]; return range_->start_ + index_;
}
inline Foam::label Foam::labelRange::const_iterator::operator()() const
{
return range_[index_];
} }
@ -118,25 +112,25 @@ Foam::labelRange::const_iterator::operator++(int)
inline Foam::labelRange::const_iterator Foam::labelRange::cbegin() const inline Foam::labelRange::const_iterator Foam::labelRange::cbegin() const
{ {
return const_iterator(*this); return const_iterator(this, 0);
} }
inline const Foam::labelRange::const_iterator Foam::labelRange::cend() const inline const Foam::labelRange::const_iterator Foam::labelRange::cend() const
{ {
return const_iterator(*this, true); return const_iterator(this, -1);
} }
inline Foam::labelRange::const_iterator Foam::labelRange::begin() const inline Foam::labelRange::const_iterator Foam::labelRange::begin() const
{ {
return const_iterator(*this); return const_iterator(this, 0);
} }
inline const Foam::labelRange::const_iterator Foam::labelRange::end() const inline const Foam::labelRange::const_iterator Foam::labelRange::end() const
{ {
return const_iterator(*this, true); return const_iterator(this, -1);
} }
@ -183,6 +177,12 @@ inline Foam::label Foam::labelRange::size() const
} }
inline Foam::label Foam::labelRange::start() const
{
return start_;
}
inline Foam::label Foam::labelRange::first() const inline Foam::label Foam::labelRange::first() const
{ {
return start_; return start_;
@ -220,39 +220,17 @@ inline bool Foam::labelRange::reset
} }
inline bool Foam::labelRange::contains(const label value) const inline bool Foam::labelRange::found(const label value) const
{ {
return value >= this->first() && value <= this->last(); return (value >= this->first() && value <= this->last());
} }
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline Foam::label Foam::labelRange::operator[](const label i) const inline Foam::label Foam::labelRange::operator[](const label localIndex) const
{ {
return start_ + i; return start_ + localIndex;
}
inline bool Foam::labelRange::operator<(const labelRange& rhs) const
{
return
(
this->first() < rhs.first()
|| (this->first() == rhs.first() && this->size() < rhs.size())
);
}
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));
} }

View File

@ -139,7 +139,7 @@ bool Foam::labelRanges::add(const labelRange& range)
if (currRange.overlaps(range, true)) if (currRange.overlaps(range, true))
{ {
// absorb into the existing (adjacent/overlapping) range // absorb into the existing (adjacent/overlapping) range
currRange += range; currRange.join(range);
// might connect with the next following range(s) // might connect with the next following range(s)
for (; elemI < this->size()-1; ++elemI) for (; elemI < this->size()-1; ++elemI)
@ -147,7 +147,7 @@ bool Foam::labelRanges::add(const labelRange& range)
labelRange& nextRange = ParentType::operator[](elemI+1); labelRange& nextRange = ParentType::operator[](elemI+1);
if (currRange.overlaps(nextRange, true)) if (currRange.overlaps(nextRange, true))
{ {
currRange += nextRange; currRange.join(nextRange);
nextRange.clear(); nextRange.clear();
} }
else else

View File

@ -99,8 +99,8 @@ public:
//- Return true if the list is empty //- Return true if the list is empty
using DynamicList<labelRange>::empty; using DynamicList<labelRange>::empty;
//- Return true if the value is within any of the ranges //- Return true if the value is found any of the sub-ranges
inline bool contains(const label value) const; inline bool found(const label value) const;
//- Add the range to the list //- Add the range to the list
bool add(const labelRange& range); bool add(const labelRange& range);
@ -116,38 +116,35 @@ public:
{ {
friend class labelRanges; friend class labelRanges;
// Private data // Private data
//- Reference to the list for which this is an iterator //- Reference to the list for which this is an iterator
const labelRanges& list_; const labelRanges* list_;
//- Current list index //- Current list-index
label index_; label index_;
//- Index of current element at listIndex //- Index of current element at list-index
label subIndex_; label subIndex_;
// Constructors // Constructors
//- Construct from ranges at 'begin' or 'end' position //- Construct from ranges at given index.
inline const_iterator // A negative index signals the 'end' position
( inline const_iterator(const labelRanges* lst, const label i);
const labelRanges& lst,
const bool endIter = false
);
public: public:
// Member operators // Member operators
inline bool operator==(const const_iterator& iter) const; inline bool operator==(const const_iterator& iter) const;
inline bool operator!=(const const_iterator& iter) const; inline bool operator!=(const const_iterator& iter) const;
inline label operator*(); //- Return the current label
inline label operator()(); inline label operator*();
inline const_iterator& operator++(); inline const_iterator& operator++();
inline const_iterator operator++(int); inline const_iterator operator++(int);
}; };

View File

@ -42,12 +42,12 @@ inline Foam::labelRanges::labelRanges(const label nElem)
inline Foam::labelRanges::const_iterator::const_iterator inline Foam::labelRanges::const_iterator::const_iterator
( (
const labelRanges& lst, const labelRanges* lst,
const bool endIter const label i
) )
: :
list_(lst), list_(lst),
index_(endIter ? lst.size() : 0), index_(i < 0 ? lst->size() : i),
subIndex_(0) subIndex_(0)
{} {}
@ -76,20 +76,14 @@ inline bool Foam::labelRanges::const_iterator::operator!=
inline Foam::label Foam::labelRanges::const_iterator::operator*() inline Foam::label Foam::labelRanges::const_iterator::operator*()
{ {
return list_[index_][subIndex_]; return list_->operator[](index_)[subIndex_];
}
inline Foam::label Foam::labelRanges::const_iterator::operator()()
{
return list_[index_][subIndex_];
} }
inline Foam::labelRanges::const_iterator& inline Foam::labelRanges::const_iterator&
Foam::labelRanges::const_iterator::operator++() Foam::labelRanges::const_iterator::operator++()
{ {
if (++subIndex_ >= list_[index_].size()) if (++subIndex_ >= list_->operator[](index_).size())
{ {
// Next sub-list // Next sub-list
++index_; ++index_;
@ -111,35 +105,35 @@ Foam::labelRanges::const_iterator::operator++(int)
inline Foam::labelRanges::const_iterator Foam::labelRanges::cbegin() const inline Foam::labelRanges::const_iterator Foam::labelRanges::cbegin() const
{ {
return const_iterator(*this); return const_iterator(this, 0);
} }
inline const Foam::labelRanges::const_iterator Foam::labelRanges::cend() const inline const Foam::labelRanges::const_iterator Foam::labelRanges::cend() const
{ {
return const_iterator(*this, true); return const_iterator(this, -1);
} }
inline Foam::labelRanges::const_iterator Foam::labelRanges::begin() const inline Foam::labelRanges::const_iterator Foam::labelRanges::begin() const
{ {
return const_iterator(*this); return const_iterator(this, 0);
} }
inline const Foam::labelRanges::const_iterator Foam::labelRanges::end() const inline const Foam::labelRanges::const_iterator Foam::labelRanges::end() const
{ {
return const_iterator(*this, true); return const_iterator(this, -1);
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::labelRanges::contains(const label value) const inline bool Foam::labelRanges::found(const label value) const
{ {
forAll(*this, i) forAll(*this, i)
{ {
if (this->ParentType::operator[](i).contains(value)) if (ParentType::operator[](i).found(value))
{ {
return true; return true;
} }

View File

@ -28,7 +28,10 @@ License
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::scalarRange::debug(::Foam::debug::debugSwitch("scalarRange", 0)); namespace Foam
{
int scalarRange::debug(debug::debugSwitch("scalarRange", 0));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -47,11 +50,9 @@ Foam::scalarRange::scalarRange(const scalar lower, const scalar upper)
value_(lower), value_(lower),
value2_(upper) value2_(upper)
{ {
// mark invalid range as empty
if (lower > upper) if (lower > upper)
{ {
type_ = EMPTY; clear(); // Mark invalid range as empty
value_ = value2_ = 0;
} }
} }
@ -73,6 +74,14 @@ Foam::scalarRange::scalarRange(Istream& is)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::scalarRange::clear()
{
type_ = scalarRange::EMPTY;
value_ = 0;
value2_ = 0;
}
bool Foam::scalarRange::empty() const bool Foam::scalarRange::empty() const
{ {
return type_ == EMPTY; return type_ == EMPTY;
@ -210,15 +219,14 @@ Foam::Istream& Foam::operator>>(Istream& is, scalarRange& range)
// a number is now required // a number is now required
if (!toks[nTok-1].isNumber()) if (!toks[nTok-1].isNumber())
{ {
is.setBad(); range.clear(); // Mark invalid range as empty
range.type_ = scalarRange::EMPTY;
range.value_ = range.value2_ = 0;
Info<< "rejected ill-formed or empty range:"; Info<< "rejected ill-formed or empty range:";
for (label i=0; i<nTok; ++i) for (label i=0; i<nTok; ++i)
{ {
Info<< " " << toks[i]; Info<< " " << toks[i];
} }
Info<< endl; Info<< endl;
is.setBad();
return is; return is;
} }
@ -245,15 +253,14 @@ Foam::Istream& Foam::operator>>(Istream& is, scalarRange& range)
{ {
if (range.type_ == scalarRange::UPPER) if (range.type_ == scalarRange::UPPER)
{ {
is.setBad(); range.clear(); // Mark invalid range as empty
range.type_ = scalarRange::EMPTY;
range.value_ = range.value2_ = 0;
Info<< "rejected ill-formed range:"; Info<< "rejected ill-formed range:";
for (label i=0; i<nTok; ++i) for (label i=0; i<nTok; ++i)
{ {
Info<< " " << toks[i]; Info<< " " << toks[i];
} }
Info<< endl; Info<< endl;
is.setBad();
return is; return is;
} }
@ -308,16 +315,15 @@ Foam::Istream& Foam::operator>>(Istream& is, scalarRange& range)
) )
) )
{ {
is.setBad(); range.clear(); // Mark invalid range as empty
range.type_ = scalarRange::EMPTY;
range.value_ = range.value2_ = 0;
Info<< "rejected ill-formed range:"; Info<< "rejected ill-formed range:";
for (label i=0; i<nTok; ++i) for (label i=0; i<nTok; ++i)
{ {
Info<< " " << toks[i]; Info<< " " << toks[i];
} }
Info<< endl; Info<< endl;
is.setBad();
return is;
} }
return is; return is;

View File

@ -52,8 +52,8 @@ class Ostream;
// Forward declaration of friend functions and operators // Forward declaration of friend functions and operators
class scalarRange; class scalarRange;
Istream& operator>>(Istream&, scalarRange&); Istream& operator>>(Istream& is, scalarRange& range);
Ostream& operator<<(Ostream&, const scalarRange&); Ostream& operator<<(Ostream& os, const scalarRange& range);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
@ -73,7 +73,7 @@ class scalarRange
}; };
// Private data // Private Member Data
enum rangeType type_; enum rangeType type_;
scalar value_; scalar value_;
@ -96,11 +96,14 @@ public:
//- Construct from Istream. //- Construct from Istream.
// Since commas can be used as list delimiters, // Since commas can be used as list delimiters,
// leading and trailing commas are ignored. // leading and trailing commas are ignored.
scalarRange(Istream&); scalarRange(Istream& is);
// Member Functions // Member Functions
//- Reset to an empty range.
void clear();
//- Is the range empty? //- Is the range empty?
bool empty() const; bool empty() const;
@ -121,19 +124,19 @@ public:
scalar upper() const; scalar upper() const;
//- Return true if the value is within the range //- Return true if the value is within the range
bool selected(const scalar) const; bool selected(const scalar value) const;
// Member Operators // Member Operators
bool operator==(const scalarRange&) const; bool operator==(const scalarRange& range) const;
bool operator!=(const scalarRange&) const; bool operator!=(const scalarRange& range) const;
// IOstream Operators // IOstream Operators
friend Istream& operator>>(Istream&, scalarRange&); friend Istream& operator>>(Istream& is, scalarRange& range);
friend Ostream& operator<<(Ostream&, const scalarRange&); friend Ostream& operator<<(Ostream& os, const scalarRange& range);
}; };

View File

@ -72,7 +72,7 @@ bool Foam::scalarRanges::selected(const scalar value) const
Foam::List<bool> Foam::scalarRanges::selected Foam::List<bool> Foam::scalarRanges::selected
( (
const List<scalar>& values const UList<scalar>& values
) const ) const
{ {
List<bool> lst(values.size(), false); List<bool> lst(values.size(), false);

View File

@ -55,27 +55,28 @@ public:
// Constructors // Constructors
//- Construct Null //- Construct null
scalarRanges(); scalarRanges();
//- Construct from Istream. //- Construct from Istream.
// The list items are comma-delimited. // The list items are comma-delimited.
scalarRanges(Istream&); scalarRanges(Istream& is);
// Member Functions // Member Functions
//- Return true if the given value is within the ranges //- Return true if the given value is within the ranges
bool selected(const scalar) const; bool selected(const scalar value) const;
//- Return the set of selected entries in the given list //- Return the set of selected entries in the given list
// that are within the ranges // that are within the ranges
List<bool> selected(const List<scalar>&) const; List<bool> selected(const UList<scalar>& values) const;
//- Select a list of values that are within the ranges //- Select a list of values that are within the ranges
List<scalar> select(const List<scalar>&) const; List<scalar> select(const List<scalar>& values) const;
//- Select a list of values that are within the ranges //- Select a list of values that are within the ranges
void inplaceSelect(List<scalar>&) const; void inplaceSelect(List<scalar>& values) const;
}; };