ENH: return UList range slice as a SubList

- previously returned the range slice as a UList,
  but this prevents convenient assignment.
  Apply similar handling for Field/SubField

  Allows the following

     labelRange range(...);
     fullList.slice(range) = identity(range.size());

  and

     fullList.slice(range) = UIndirectList<T>(other, addr);

ENH: create SubList from full FixedList (simplifies interface)

- allow default constructed SubList. Use shallowCopy to 'reset' later
This commit is contained in:
Mark Olesen
2021-10-21 17:35:03 +02:00
parent 3781f17eee
commit e2861cc200
14 changed files with 269 additions and 96 deletions

View File

@ -48,7 +48,9 @@ See also
#include "scalarList.H"
#include "HashOps.H"
#include "ListOps.H"
#include "IndirectList.H"
#include "SubList.H"
#include "SliceList.H"
#include "ListPolicy.H"
#include <list>
@ -344,7 +346,7 @@ int main(int argc, char *argv[])
labelList longLabelList = identity(25);
reverse(longLabelList);
FixedList<label, 6> fixedLabelList{0,1,2,3,4,5};
FixedList<label, 6> fixedLabelList({0,1,2,3,4,5});
const labelList constLabelList = identity(25);
Info<< "full-list: " << flatOutput(longLabelList) << nl;
@ -353,6 +355,36 @@ int main(int argc, char *argv[])
Info<<"sub range:" << range1 << "=";
Info<< SubList<label>(longLabelList, range1) << nl;
{
// A valid range
const labelRange subset(4, 5);
// Assign some values
longLabelList.slice(subset) = identity(subset.size());
Info<<"assigned identity in range:" << subset
<< "=> " << flatOutput(longLabelList) << nl;
labelList someList(identity(24));
longLabelList.slice(subset) =
SliceList<label>(someList, sliceRange(8, subset.size(), 2));
Info<<"assigned sliced/stride in range:" << subset
<< "=> " << flatOutput(longLabelList) << nl;
// Does not work - need a reference, not a temporary
// Foam::reverse(longLabelList[subset]);
{
auto sub(longLabelList.slice(subset));
Foam::reverse(sub);
}
Info<<"reversed range:" << subset
<< "=> " << flatOutput(longLabelList) << nl;
}
labelRange range2(7, 8);
Info<<"sub range:" << range2 << "=";
Info<< SubList<label>(longLabelList, range2) << nl;
@ -368,29 +400,29 @@ int main(int argc, char *argv[])
// > constLabelList[labelRange(23,5)] = 5;
// Check correct overlaps
longLabelList[labelRange(-10, 12)] = 200;
longLabelList[{18,3}] = 100;
longLabelList[{23,3}] = 400;
longLabelList.slice(labelRange(-10, 12)) = 200;
longLabelList.slice({18,3}) = 100;
longLabelList.slice({23,3}) = 400;
// and complete misses
longLabelList[{500,50}] = 100;
longLabelList.slice({500,50}) = 100;
// -ve size suppressed by internal 'validateRange' = no-op
longLabelList[{5,-5}] = 42;
longLabelList[{21,100}] = 42;
longLabelList.slice({5,-5}) = 42;
longLabelList.slice({21,100}) = 42;
//Good: does not compile
//> longLabelList[labelRange(20,50)] = constLabelList;
longLabelList.slice(labelRange(20,50)) = constLabelList;
//Good: does not compile
// longLabelList[labelRange(20,50)] = fixedLabelList;
Info<< "updated: " << constLabelList[labelRange(23,5)] << nl;
Info<< "updated: " << constLabelList.slice(labelRange(23,5)) << nl;
Info<< "updated: " << flatOutput(longLabelList) << nl;
//Nope: sort(longLabelList[labelRange(18,5)]);
//Nope: sort(longLabelList.slice(labelRange(18,5)));
{
// Instead
UList<label> sub = longLabelList[labelRange(8)];
auto sub = longLabelList.slice(labelRange(8));
sort(sub);
}
Info<< "sub-sorted: " << flatOutput(longLabelList) << nl;

View File

@ -49,7 +49,7 @@ void printInfo(const SortableList<T>& list)
int main(int argc, char *argv[])
{
const labelList orig{7, 9, 1, 2, 4, 7, 4, 0};
const labelList orig({7, 9, 1, 2, 4, 7, 4, 0});
labelList order;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016 Shell Research Ltd.
Copyright (C) 2019-2020 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -269,7 +269,7 @@ int main(int argc, char* argv[])
{
Info<< " negative blocks: " << origBlocks.size() << nl;
for (const PDRobstacle& obs : obstacles[origBlocks])
for (const PDRobstacle& obs : obstacles.slice(origBlocks))
{
arr.addBlockage(obs, patches, -1);
}
@ -282,7 +282,7 @@ int main(int argc, char* argv[])
{
Info<< " blocks " << interBlocks.size() << nl;
for (const PDRobstacle& obs : obstacles[interBlocks])
for (const PDRobstacle& obs : obstacles.slice(interBlocks))
{
arr.addBlockage(obs, patches, 0);
}
@ -293,7 +293,7 @@ int main(int argc, char* argv[])
{
Info<< " positive blocks: " << origBlocks.size() << nl;
for (const PDRobstacle& obs : obstacles[origBlocks])
for (const PDRobstacle& obs : obstacles.slice(origBlocks))
{
arr.addBlockage(obs, patches, 1);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016 Shell Research Ltd.
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -405,7 +405,7 @@ scalar block_overlap
// Sort blocks by their x-position (with sortBias)
labelList blkOrder;
sortedOrder(blocks[range], blkOrder);
sortedOrder(blocks.slice(range), blkOrder);
DynamicList<PDRobstacle> newBlocks;
@ -510,7 +510,7 @@ scalar block_cylinder_overlap
// Sort blocks and cylinders by their x-position (with sortBias)
labelList blkOrder;
sortedOrder(blocks[range], blkOrder);
sortedOrder(blocks.slice(range), blkOrder);
labelList cylOrder;
sortedOrder(cylinders, cylOrder);

View File

@ -43,6 +43,7 @@ SourceFiles
#define SubList_H
#include "List.H"
#include "FixedList.H"
#include "labelRange.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -78,8 +79,11 @@ public:
// Generated Methods
//- Copy construct
SubList(const SubList&) = default;
//- Default construct, zero-sized and nullptr
SubList() noexcept = default;
//- Copy construct, shallow copy
SubList(const SubList&) noexcept = default;
// Constructors
@ -87,6 +91,10 @@ public:
//- Construct from UList, the entire size
inline explicit SubList(const UList<T>& list);
//- Construct from FixedList, the entire size
template<unsigned N>
inline explicit SubList(const FixedList<T, N>& list);
//- Construct from UList and sub-list size, start at 0
inline SubList
(
@ -151,6 +159,48 @@ public:
#include "SubListI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Foam::SubList<Type>
Foam::UList<Type>::slice(const label pos, label len)
{
if (len < 0)
{
len = (this->size() - pos);
}
return SubList<Type>(*this, len, pos);
}
template<class Type>
const Foam::SubList<Type>
Foam::UList<Type>::slice(const label pos, label len) const
{
if (len < 0)
{
len = (this->size() - pos);
}
return SubList<Type>(*this, len, pos);
}
template<class Type>
Foam::SubList<Type>
Foam::UList<Type>::slice(const labelRange& range)
{
return SubList<Type>(*this, range); // with range checking
}
template<class Type>
const Foam::SubList<Type>
Foam::UList<Type>::slice(const labelRange& range) const
{
return SubList<Type>(*this, range); // with range checking
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif

View File

@ -34,7 +34,18 @@ inline Foam::SubList<T>::SubList
const UList<T>& list
)
:
UList<T>(list.v_, list.size())
UList<T>(const_cast<T*>(list.cdata()), list.size())
{}
template<class T>
template<unsigned N>
inline Foam::SubList<T>::SubList
(
const FixedList<T, N>& list
)
:
UList<T>(const_cast<T*>(list.cdata()), static_cast<label>(N))
{}
@ -45,7 +56,7 @@ inline Foam::SubList<T>::SubList
const label subSize
)
:
UList<T>(list.v_, subSize)
UList<T>(const_cast<T*>(list.cdata()), subSize)
{
#ifdef FULLDEBUG
list.checkSize(subSize);
@ -61,22 +72,10 @@ inline Foam::SubList<T>::SubList
const label startIndex
)
:
UList<T>(&(list.v_[startIndex]), subSize)
UList<T>(const_cast<T*>(list.cdata() + startIndex), subSize)
{
#ifdef FULLDEBUG
// Artificially allow the start of a zero-sized subList to be
// one past the end of the original list.
if (subSize)
{
list.checkStart(startIndex);
list.checkSize(startIndex + subSize);
}
else
{
// Start index needs to fall between 0 and size. One position
// behind the last element is allowed
list.checkSize(startIndex);
}
list.checkRange(startIndex, subSize);
#endif
}
@ -88,8 +87,14 @@ inline Foam::SubList<T>::SubList
const labelRange& range
)
:
SubList<T>(list.validateRange(range), list)
{}
SubList<T>(range.subset0(list.size()), list)
{
#ifdef FULLDEBUG
// The subset0() above always produces valid ranges but want to check
// that the input itself was valid
list.checkRange(range.start(), range.size());
#endif
}
template<class T>

View File

@ -37,16 +37,17 @@ License
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class T>
Foam::labelRange Foam::UList<T>::validateRange(const labelRange& range) const
Foam::labelRange
Foam::UList<T>::validateRange(const labelRange& requestedRange) const
{
const labelRange slice = range.subset0(this->size());
const labelRange range(requestedRange.subset0(this->size()));
#ifdef FULLDEBUG
this->checkStart(slice.start());
this->checkSize(slice.start() + slice.size());
this->checkStart(range.start());
this->checkSize(range.start() + range.size());
#endif
return slice;
return range;
}
@ -164,24 +165,6 @@ void Foam::UList<T>::deepCopy(const IndirectListBase<T, Addr>& list)
// * * * * * * * * * * * * * * * 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>
void Foam::UList<T>::operator=(const T& val)
{

View File

@ -119,8 +119,7 @@ protected:
//- 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;
labelRange validateRange(const labelRange& requestedRange) const;
//- No copy assignment (default: shallow copy)
//
@ -230,7 +229,7 @@ public:
inline constexpr UList() noexcept;
//- Construct from components
inline UList(T* __restrict__ v, label size) noexcept;
inline UList(T* __restrict__ v, const label len) noexcept;
// Member Functions
@ -302,6 +301,9 @@ public:
//- Check size is within valid range [0,size]
inline void checkSize(const label size) const;
//- Check that start and length define a valid range
inline void checkRange(const label start, const label len) const;
//- Check index is within valid range [0,size)
inline void checkIndex(const label i) const;
@ -347,37 +349,46 @@ public:
// Copy
//- Copy the pointer held by the given UList
//- Copy the pointer and size held by the given UList
inline void shallowCopy(const UList<T>& list);
//- Copy elements of the given UList
//- Copy elements of the given UList. Sizes must match!
void deepCopy(const UList<T>& list);
//- Copy elements of the given indirect list
//- Copy elements of the given indirect list. Sizes must match!
template<class Addr>
void deepCopy(const IndirectListBase<T, Addr>& list);
// Other Access
//- Return SubList slice (non-const access) - no range checking
SubList<T> slice(const label pos, label len = -1);
//- Return SubList slice (const access) - no range checking
const SubList<T> slice(const label pos, label len = -1) const;
//- Return SubList slice (non-const access) - with range checking.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
SubList<T> slice(const labelRange& range);
//- Return SubList slice (const access) - with range checking.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
const SubList<T> slice(const labelRange& range) const;
// Member Operators
//- Return element of UList
inline T& operator[](const label i);
//- Return element of constant UList
// Note that the bool specialization adds lazy evaluation so reading
// an out-of-range element returns false without any ill-effects
// \note bool specialization adds lazy evaluation so reading an
// out-of-range element returns false without ill-effects
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;
//- Allow cast to a const List<T>&
inline operator const Foam::List<T>&() const;
@ -659,7 +670,7 @@ struct accessOp
{
const T& operator()(const T& obj) const
{
return obj;
return obj; // Default is pass-through
}
};
@ -668,7 +679,7 @@ struct accessOp
template<class T>
struct emptyOp
{
inline bool operator()(const T& obj) const
bool operator()(const T& obj) const
{
return obj.empty();
}
@ -679,7 +690,7 @@ struct emptyOp
template<class T>
struct sizeOp
{
inline label operator()(const T& obj) const
label operator()(const T& obj) const
{
return obj.size();
}

View File

@ -40,9 +40,9 @@ inline constexpr Foam::UList<T>::UList() noexcept
template<class T>
inline Foam::UList<T>::UList(T* __restrict__ v, label size) noexcept
inline Foam::UList<T>::UList(T* __restrict__ v, const label len) noexcept
:
size_(size),
size_(len),
v_(v)
{}
@ -105,7 +105,8 @@ inline void Foam::UList<T>::checkStart(const label start) const
{
// Note: accept start=0 for zero-sized lists
FatalErrorInFunction
<< "start " << start << " out of range [0," << size_ << "]"
<< "start " << start << " out of range [0,"
<< size_ << "]\n"
<< abort(FatalError);
}
}
@ -117,12 +118,43 @@ inline void Foam::UList<T>::checkSize(const label size) const
if (size < 0 || size > size_)
{
FatalErrorInFunction
<< "size " << size << " out of range [0," << size_ << "]"
<< "size " << size << " out of range [0,"
<< size_ << "]\n"
<< abort(FatalError);
}
}
template<class T>
inline void Foam::UList<T>::checkRange
(
const label start,
const label len
) const
{
// Artificially allow the start of a zero-sized subList to be
// one past the end of the original list.
if (len)
{
if (len < 0)
{
FatalErrorInFunction
<< "size " << len << " is negative, out of range [0,"
<< size_ << "]\n"
<< abort(FatalError);
}
this->checkStart(start);
this->checkSize(start + len);
}
else
{
// Start index needs to fall between 0 and size. One position
// behind the last element is allowed
this->checkSize(start);
}
}
template<class T>
inline void Foam::UList<T>::checkIndex(const label i) const
{
@ -135,7 +167,8 @@ inline void Foam::UList<T>::checkIndex(const label i) const
else if (i < 0 || i >= size_)
{
FatalErrorInFunction
<< "index " << i << " out of range [0," << size_ << "]"
<< "index " << i << " out of range [0,"
<< size_ << "]\n"
<< abort(FatalError);
}
}

View File

@ -57,7 +57,7 @@ SourceFiles
namespace Foam
{
// Forward declarations
// Forward Declarations
class FieldMapper;
class dictionary;
@ -369,6 +369,21 @@ public:
void writeEntry(const word& keyword, Ostream& os) const;
// Other Access
//- Return SubField slice (non-const access) - no range checking
SubField<Type> slice(const label pos, label len = -1);
//- Return SubField slice (const access) - no range checking
const SubField<Type> slice(const label pos, label len = -1) const;
//- Return SubField slice (non-const access) - with range checking
SubField<Type> slice(const labelRange& range);
//- Return SubField slice (const access) - with range checking
const SubField<Type> slice(const labelRange& range) const;
// Member Operators
//- Copy assignment

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2020 OpenCFD Ltd.
Copyright (C) 2018-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -65,7 +65,6 @@ class SubField
public refCount,
public SubList<Type>
{
public:
//- Component type
@ -74,6 +73,9 @@ public:
// Constructors
//- Default construct, zero-sized and nullptr
SubField() noexcept = default;
//- Copy construct (shallow copy)
inline SubField(const SubField<Type>& sfield);
@ -171,6 +173,48 @@ public:
#include "SubFieldI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Foam::SubField<Type>
Foam::Field<Type>::slice(const label pos, label len)
{
if (len < 0)
{
len = (this->size() - pos);
}
return SubField<Type>(*this, len, pos);
}
template<class Type>
const Foam::SubField<Type>
Foam::Field<Type>::slice(const label pos, label len) const
{
if (len < 0)
{
len = (this->size() - pos);
}
return SubField<Type>(*this, len, pos);
}
template<class Type>
Foam::SubField<Type>
Foam::Field<Type>::slice(const labelRange& range)
{
return SubField<Type>(*this, range); // with range checking
}
template<class Type>
const Foam::SubField<Type>
Foam::Field<Type>::slice(const labelRange& range) const
{
return SubField<Type>(*this, range); // with range checking
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -54,7 +54,7 @@ inline Foam::SubField<Type>::SubField
const UList<Type>& list
)
:
SubList<Type>(list, list.size())
SubList<Type>(list)
{}

View File

@ -79,7 +79,7 @@ inline const Foam::labelList& Foam::ensightCells::cellIds() const
inline const Foam::labelUList
Foam::ensightCells::cellIds(const elemType etype) const
{
return addressing()[range(etype)];
return addressing().slice(range(etype));
}

View File

@ -85,7 +85,7 @@ inline const Foam::labelList& Foam::ensightFaces::faceIds() const noexcept
inline const Foam::labelUList
Foam::ensightFaces::faceIds(const elemType etype) const
{
return addressing()[range(etype)];
return addressing().slice(range(etype));
}
@ -111,7 +111,7 @@ Foam::ensightFaces::faceOrder() const noexcept
inline const Foam::labelUList
Foam::ensightFaces::faceOrder(const elemType etype) const
{
return faceOrder_[range(etype)];
return faceOrder_.slice(range(etype));
}