ENH: support UList[labelRange] and SubList construction with labelRange

This uses a concept similar to what std::valarray and std::slice do.
A labelRange provides a convenient container for holding start/size
and lends itself to addressing 'sliced' views of lists.
For safety, the operations and constructors restricts the given input range
to a valid addressible region of the underlying list, while the labelRange
itself precludes negative sizes.

The SubList version is useful for patches or other things that have a
SubList as its parameter. Otherwise the UList [] operator will be the
more natural solution. The slices can be done with a labelRange, or
a {start,size} pair.

Examples,
     labelList list1 = identity(20);

     list1[labelRange(18,10)]  = -1;
     list1[{-20,25}] = -2;
     list1[{1000,5}] = -3;

     const labelList list2 = identity(20);
     list2[{5,10}] = -3;  // ERROR: cannot assign to const!
This commit is contained in:
Mark Olesen
2017-05-01 14:01:09 +02:00
parent 75ef6f4e50
commit 805b76d4b9
6 changed files with 229 additions and 20 deletions

View File

@ -76,7 +76,6 @@ int main(int argc, char *argv[])
Info<<"is >>: " << intlist << endl; Info<<"is >>: " << intlist << endl;
} }
List<vector> list1(IStringStream("1 ((0 1 2))")()); List<vector> list1(IStringStream("1 ((0 1 2))")());
Info<< "list1: " << list1 << endl; Info<< "list1: " << list1 << endl;
@ -150,7 +149,6 @@ int main(int argc, char *argv[])
Info<< "normal: " << longLabelList << nl; Info<< "normal: " << longLabelList << nl;
Info<< "flatOutput: " << flatOutput(longLabelList) << nl; Info<< "flatOutput: " << flatOutput(longLabelList) << nl;
// Info<< "flatOutput(14): " << flatOutput(longLabelList, 14) << nl; // Info<< "flatOutput(14): " << flatOutput(longLabelList, 14) << nl;
// Info<< "flatOutput(15): " << flatOutput(longLabelList, 15) << nl;
stringList longStringList(12); stringList longStringList(12);
forAll(longStringList, i) forAll(longStringList, i)
@ -165,6 +163,66 @@ int main(int argc, char *argv[])
// contiguous longStringList[i].resize(3, 'a' + i); // contiguous longStringList[i].resize(3, 'a' + i);
} }
// test SubList and labelRange
{
Info<< nl;
labelList longLabelList = identity(25);
reverse(longLabelList);
FixedList<label, 6> fixedLabelList{0,1,2,3,4,5};
const labelList constLabelList = identity(25);
Info<< "full-list: " << flatOutput(longLabelList) << nl;
labelRange range1(-15, 25);
Info<<"sub range:" << range1 << "=";
Info<< SubList<label>(longLabelList, range1) << nl;
labelRange range2(7, 8);
Info<<"sub range:" << range2 << "=";
Info<< SubList<label>(longLabelList, range2) << nl;
// labelRange range2(7, 8);
Info<<"use range " << range2 << " to set value";
SubList<label>(longLabelList, range2) = -15;
Info<< "=> " << flatOutput(longLabelList) << nl;
// This syntax looks even nicer:
// GOOD: does not compile
// > constLabelList[labelRange(23,5)] = 5;
// Check correct overlaps
longLabelList[labelRange(-10, 12)] = 200;
longLabelList[{18,3}] = 100;
longLabelList[{23,3}] = 400;
// and complete misses
longLabelList[{500,50}] = 100;
// labelRange automatically suppresses -ve size -> nop
longLabelList[{5,-5}] = 42;
longLabelList[{21,100}] = 42;
//Good: does not compile
//> longLabelList[labelRange(20,50)] = constLabelList;
//Good: does not compile
// longLabelList[labelRange(20,50)] = fixedLabelList;
Info<< "updated: " << constLabelList[labelRange(23,5)] << nl;
Info<< "updated: " << flatOutput(longLabelList) << nl;
//Nope: sort(longLabelList[labelRange(18,5)]);
{
// Instead
UList<label> sub = longLabelList[labelRange(0, 8)];
sort(sub);
}
Info<< "sub-sorted: " << flatOutput(longLabelList) << nl;
// Info<<"Slice=" << longLabelList[labelRange(23,5)] << nl;
}
wordReList reLst; wordReList reLst;
wordList wLst; wordList wLst;
stringList sLst; stringList sLst;

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -40,6 +40,7 @@ SourceFiles
#define SubList_H #define SubList_H
#include "List.H" #include "List.H"
#include "labelRange.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -55,7 +56,6 @@ class SubList
: :
public UList<T> public UList<T>
{ {
public: public:
// Static Member Functions // Static Member Functions
@ -81,6 +81,23 @@ public:
const label startIndex const label startIndex
); );
//- Construct from UList and a (start,size) range.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
inline SubList
(
const UList<T>& list,
const labelRange& range
);
//- Construct from UList and a (start,size) range, but bypassing
// run-time range checking.
inline SubList
(
const labelRange& range,
const UList<T>& list
);
// Member operators // Member operators
@ -88,13 +105,13 @@ public:
inline operator const Foam::List<T>&() const; inline operator const Foam::List<T>&() const;
//- Assignment of all entries to the given sub-list //- Assignment of all entries to the given sub-list
inline void operator=(const SubList<T>&); inline void operator=(const SubList<T>& list);
//- Assignment of all entries to the given list //- Assignment of all entries to the given list
inline void operator=(const UList<T>&); inline void operator=(const UList<T>& list);
//- Assignment of all entries to the given value //- Assignment of all entries to the given value
inline void operator=(const T&); inline void operator=(const T& t);
}; };

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -51,7 +51,6 @@ inline Foam::SubList<T>::SubList
UList<T>(&(list.v_[startIndex]), subSize) UList<T>(&(list.v_[startIndex]), subSize)
{ {
#ifdef FULLDEBUG #ifdef FULLDEBUG
// Artificially allow the start of a zero-sized subList to be // Artificially allow the start of a zero-sized subList to be
// one past the end of the original list. // one past the end of the original list.
if (subSize) if (subSize)
@ -69,6 +68,28 @@ inline Foam::SubList<T>::SubList
} }
template<class T>
inline Foam::SubList<T>::SubList
(
const UList<T>& list,
const labelRange& range
)
:
SubList<T>(list.validateRange(range), list)
{}
template<class T>
inline Foam::SubList<T>::SubList
(
const labelRange& range,
const UList<T>& list
)
:
SubList<T>(list, range.size(), range.start())
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T> template<class T>
@ -88,16 +109,16 @@ inline Foam::SubList<T>::operator const Foam::List<T>&() const
template<class T> template<class T>
inline void Foam::SubList<T>::operator=(const SubList<T>& sl) inline void Foam::SubList<T>::operator=(const SubList<T>& list)
{ {
UList<T>::deepCopy(sl); UList<T>::deepCopy(list);
} }
template<class T> template<class T>
inline void Foam::SubList<T>::operator=(const UList<T>& l) inline void Foam::SubList<T>::operator=(const UList<T>& list)
{ {
UList<T>::deepCopy(l); UList<T>::deepCopy(list);
} }

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -26,9 +26,49 @@ License
#include "UList.H" #include "UList.H"
#include "ListLoopM.H" #include "ListLoopM.H"
#include "contiguous.H" #include "contiguous.H"
#include "labelRange.H"
#include <algorithm> #include <algorithm>
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class T>
Foam::labelRange Foam::UList<T>::validateRange(const labelRange& range) const
{
const labelRange slice = range.subset(0, this->size());
#ifdef FULLDEBUG
this->checkStart(slice.start());
this->checkSize(slice.start() + slice.size());
#endif
return slice;
}
template<class T>
Foam::labelRange Foam::UList<T>::validateRange
(
std::initializer_list<label> start_size_pair
) const
{
if (start_size_pair.size() != 2)
{
FatalErrorInFunction
<< "range specified with " << start_size_pair.size()
<< " elements instead of 2"
<< abort(FatalError);
}
auto iter = start_size_pair.begin();
const label beg = *(iter++);
const label sz = *iter;
return this->validateRange(labelRange(beg, sz));
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T> template<class T>
@ -64,6 +104,47 @@ void Foam::UList<T>::deepCopy(const UList<T>& a)
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T>
Foam::UList<T> Foam::UList<T>::operator[](const labelRange& range)
{
const labelRange slice = validateRange(range);
return UList<T>(&(this->v_[slice.start()]), slice.size()); // SubList
}
template<class T>
const Foam::UList<T> Foam::UList<T>::operator[](const labelRange& range) const
{
const labelRange slice = validateRange(range);
return UList<T>(&(this->v_[slice.start()]), slice.size()); // SubList
}
template<class T>
Foam::UList<T> Foam::UList<T>::operator[]
(
std::initializer_list<label> start_size_pair
)
{
const labelRange slice = validateRange(start_size_pair);
return UList<T>(&(this->v_[slice.start()]), slice.size()); // SubList
}
template<class T>
const Foam::UList<T> Foam::UList<T>::operator[]
(
std::initializer_list<label> start_size_range
) const
{
// Restricted range
const labelRange slice = validateRange(start_size_range);
return UList<T>(&(this->v_[slice.start()]), slice.size()); // SubList
}
template<class T> template<class T>
void Foam::UList<T>::operator=(const T& t) void Foam::UList<T>::operator=(const T& t)
{ {

View File

@ -48,13 +48,15 @@ SourceFiles
#include "nullObject.H" #include "nullObject.H"
#include "zero.H" #include "zero.H"
#include "stdFoam.H" #include "stdFoam.H"
#include <initializer_list>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// Forward declaration of friend classes // Forward declarations
class labelRange;
template<class T> class List; template<class T> class List;
template<class T> class SubList; template<class T> class SubList;
@ -101,6 +103,16 @@ protected:
//- Write the UList with its compound type //- Write the UList with its compound type
void writeEntry(Ostream& os) const; void writeEntry(Ostream& os) const;
//- Return a validated (start,size) subset range, which means that it
// always addresses a valid section of the list.
labelRange validateRange(const labelRange& range) const;
//- Return a validated (start,size) subset range, which means that it
// always addresses a valid section of the list.
labelRange validateRange
(
std::initializer_list<label> start_size_pair
) const;
public: public:
@ -239,6 +251,29 @@ public:
// an out-of-range element returns false without any ill-effects // an out-of-range element returns false without any ill-effects
inline const T& operator[](const label i) const; inline const T& operator[](const label i) const;
//- Return (start,size) subset from UList with non-const access.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
UList<T> operator[](const labelRange& range);
//- Return (start,size) subset from UList with const access.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
const UList<T> operator[](const labelRange& range) const;
//- Return (start,size) subset from UList with non-const access.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
UList<T> operator[](std::initializer_list<label> start_size_range);
//- Return (start,size) subset from UList with const access.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
const UList<T> operator[]
(
std::initializer_list<label> start_size_range
) const;
//- Allow cast to a const List<T>& //- Allow cast to a const List<T>&
inline operator const Foam::List<T>&() const; inline operator const Foam::List<T>&() const;

View File

@ -71,7 +71,7 @@ inline Foam::label Foam::UList<T>::rcIndex(const label i) const
template<class T> template<class T>
inline void Foam::UList<T>::checkStart(const label start) const inline void Foam::UList<T>::checkStart(const label start) const
{ {
if (start<0 || (start && start>=size_)) if (start < 0 || (start && start >= size_))
{ {
FatalErrorInFunction FatalErrorInFunction
<< "start " << start << " out of range 0 ... " << max(size_-1, 0) << "start " << start << " out of range 0 ... " << max(size_-1, 0)
@ -83,7 +83,7 @@ inline void Foam::UList<T>::checkStart(const label start) const
template<class T> template<class T>
inline void Foam::UList<T>::checkSize(const label size) const inline void Foam::UList<T>::checkSize(const label size) const
{ {
if (size<0 || size>size_) if (size < 0 || size > size_)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "size " << size << " out of range 0 ... " << size_ << "size " << size << " out of range 0 ... " << size_
@ -162,7 +162,6 @@ inline void Foam::UList<T>::shallowCopy(const UList<T>& a)
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T> template<class T>
inline T& Foam::UList<T>::operator[](const label i) inline T& Foam::UList<T>::operator[](const label i)
{ {
@ -172,7 +171,6 @@ inline T& Foam::UList<T>::operator[](const label i)
return v_[i]; return v_[i];
} }
namespace Foam namespace Foam
{ {
// Template specialization for bool // Template specialization for bool
@ -191,7 +189,6 @@ namespace Foam
} }
} }
template<class T> template<class T>
inline const T& Foam::UList<T>::operator[](const label i) const inline const T& Foam::UList<T>::operator[](const label i) const
{ {