ENH: use std algorithms for copy/move/compare within List containers

ENH: add List resize_fill variant. Fuses resize_nocopy + uniform fill

COMP: avoid cast ambiguity when assigning Foam::zero to UList<char>
This commit is contained in:
Mark Olesen
2023-08-04 16:46:12 +02:00
parent eeb9d144e3
commit 2422e6f061
23 changed files with 397 additions and 466 deletions

View File

@ -79,6 +79,13 @@ int main(int argc, char *argv[])
List<char> alphabet(istr);
Info<< "re-read: " << alphabet << nl;
// Can assign zero?
//Fails: alphabet = char(Zero);
alphabet = Foam::zero{};
// alphabet = '@';
Info<< "blanked: " << alphabet << nl;
}
return 0;

View File

@ -457,10 +457,10 @@ public:
inline reference operator[](const label i);
//- Copy assignment.
inline void operator=(const PackedList<Width>& lst);
inline void operator=(const PackedList<Width>& list);
//- Move assignment.
inline void operator=(PackedList<Width>&& lst);
inline void operator=(PackedList<Width>&& list);
//- Assign all entries to the given value. fill()
inline void operator=(const unsigned int val);

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,27 +36,28 @@ Foam::label Foam::DynamicList<T, SizeMin>::removeElements
const labelRange& slice
)
{
if (!slice.size())
if (!slice.good())
{
// No-op
return 0;
}
else if (slice.end_value() >= this->size())
// Note: already checked for valid begin_value before
if (slice.end_value() >= this->size())
{
// Remove entire tail
this->resize(slice.begin_value());
}
else
{
// Copy (swap) down, from range rbegin() -> rend()
// followed by truncation
label j = slice.begin_value();
const label len = this->size();
for (label i = slice.end_value(); i < len; ++i, ++j)
{
Foam::Swap(this->operator[](i), this->operator[](j));
}
// Move all trailing elements down into space previously
// occupied by the slice. Truncate after
std::move
(
this->begin(slice.end_value()),
this->end(),
this->begin(slice.begin_value())
);
this->resize(this->size() - slice.size());
}
@ -73,14 +74,14 @@ Foam::label Foam::DynamicList<T, SizeMin>::subsetElements
{
if (slice.begin_value() > 0)
{
// Copy (swap) down
label j = slice.begin_value();
const label len = slice.size();
for (label i = 0; i < len; ++i, ++j)
{
Foam::Swap(this->operator[](i), this->operator[](j));
}
// Move elements down.
// Since begin_value > 0, the initial destination is non-overlapping
std::move
(
this->begin(slice.begin_value()),
this->begin(slice.end_value()),
this->begin()
);
}
// Don't need min size, since slice size was already checked before

View File

@ -216,9 +216,12 @@ public:
// setting values (as per List usage).
inline void resize(const label len);
//- Alter addressable size and fill new entries with constant value
//- Alter addressable size and fill \em new entries with constant value
inline void resize(const label len, const T& val);
//- Alter addressable size and set val for \em all addressed entries
inline void resize_fill(const label len, const T& val);
//- Alter addressable list size, allocating new space if required
//- \em without necessarily recovering old content.
// If no reallocation is required, the contents remain untouched.
@ -328,7 +331,6 @@ public:
//- Retain a (start,size) subset from the list.
// The range is subsetted with the list size itself to ensure
// result always addresses a valid section of the list.
// Remaining elements are moved down.
inline label subset(const labelRange& range);
//- Retain a (start,size) subset from List.

View File

@ -363,6 +363,18 @@ inline void Foam::DynamicList<T, SizeMin>::resize
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::resize_fill
(
const label len,
const T& val
)
{
this->doResize(true, len); // nocopy = true
UList<T>::operator=(val);
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::resize_nocopy
(
@ -373,18 +385,6 @@ inline void Foam::DynamicList<T, SizeMin>::resize_nocopy
}
// template<class T, int SizeMin>
// inline void Foam::DynamicList<T, SizeMin>::resize_fill
// (
// const label len,
// const T& val
// )
// {
// this->doResize(true, len); // nocopy = true
// this->fill_uniform(val);
// }
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::resize
(
@ -392,14 +392,16 @@ inline void Foam::DynamicList<T, SizeMin>::resize
const T& val
)
{
label idx = List<T>::size();
const label oldLen = List<T>::size();
resize(len);
// Fill newly exposed with constant value
while (idx < len)
if (oldLen < List<T>::size())
{
this->operator[](idx) = val;
++idx;
std::fill
(
this->begin(oldLen), this->end(), val
);
}
}
@ -527,8 +529,8 @@ inline T& Foam::DynamicList<T, SizeMin>::emplace_back(Args&&... args)
resize(idx + 1);
// move assign element
this->operator[](idx) = T(std::forward<Args>(args)...);
return this->back();
UList<T>::operator[](idx) = T(std::forward<Args>(args)...);
return UList<T>::operator[](idx);
}
@ -541,7 +543,7 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
const label idx = List<T>::size();
resize(idx + 1);
this->operator[](idx) = val; // copy element
UList<T>::operator[](idx) = val; // copy element
}
@ -554,30 +556,27 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
const label idx = List<T>::size();
resize(idx + 1);
this->operator[](idx) = std::move(val); // move assign element
UList<T>::operator[](idx) = std::move(val); // move assign element
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::push_back
(
const UList<T>& lst
const UList<T>& list
)
{
if (this == &lst)
if (this == &list)
{
FatalErrorInFunction
<< "Attempted push_back to self"
<< abort(FatalError);
}
label idx = List<T>::size();
resize(idx + lst.size());
const label idx = List<T>::size();
resize(idx + list.size());
for (const T& val : lst)
{
this->operator[](idx++) = val; // copy element
}
std::copy(list.begin(), list.end(), this->begin(idx));
}
@ -585,32 +584,26 @@ template<class T, int SizeMin>
template<unsigned N>
inline void Foam::DynamicList<T, SizeMin>::push_back
(
const FixedList<T, N>& lst
const FixedList<T, N>& list
)
{
label idx = List<T>::size();
resize(idx + lst.size());
const label idx = List<T>::size();
resize(idx + list.size());
for (const T& val : lst)
{
this->operator[](idx++) = val; // copy element
}
std::copy(list.begin(), list.end(), this->begin(idx));
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::push_back
(
std::initializer_list<T> lst
std::initializer_list<T> list
)
{
label idx = List<T>::size();
resize(idx + lst.size());
const label idx = List<T>::size();
resize(idx + list.size());
for (const T& val : lst)
{
this->operator[](idx++) = val; // copy element
}
std::copy(list.begin(), list.end(), this->begin(idx));
}
@ -618,17 +611,23 @@ template<class T, int SizeMin>
template<class Addr>
inline void Foam::DynamicList<T, SizeMin>::push_back
(
const IndirectListBase<T, Addr>& lst
const IndirectListBase<T, Addr>& list
)
{
label idx = List<T>::size();
const label n = lst.size();
// Note: push_back will still work even if the indirect list
// actually references *this, since its source elements will not
// overlap the new destinations.
resize(idx + n);
const label idx = this->size();
const label n = list.size();
for (label i=0; i<n; ++i)
resize(list + n);
auto iter = this->begin(idx);
for (label i = 0; i < n; (void)++i, (void)++iter)
{
this->operator[](idx++) = lst[i]; // copy element
*iter = list[i]; // copy element
}
}
@ -646,13 +645,10 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
<< abort(FatalError);
}
label idx = List<T>::size();
const label idx = List<T>::size();
resize(idx + list.size());
for (T& val : list)
{
Foam::Swap(this->operator[](idx++), val); // moved content
}
std::move(list.begin(), list.end(), this->begin(idx));
list.clear();
}
@ -795,7 +791,7 @@ inline T& Foam::DynamicList<T, SizeMin>::operator()
resize(i + 1);
}
return this->operator[](i);
return UList<T>::operator[](i);
}

View File

@ -259,7 +259,7 @@ Foam::Istream& Foam::DynamicList<T, SizeMin>::readList(Istream& is)
);
// Fill with the value
this->fill_uniform(elem);
UList<T>::operator=(elem);
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +27,6 @@ License
\*---------------------------------------------------------------------------*/
#include "FixedList.H"
#include "ListLoopM.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
@ -51,11 +50,15 @@ Foam::label Foam::FixedList<T, N>::find(const T& val, label pos) const
{
if (pos >= 0)
{
List_CONST_ACCESS(T, *this, list);
// auto iter = std::find(this->begin(pos), this->end(), val);
// if (iter != this->end())
// {
// return label(iter - this->begin());
// }
while (pos < label(N))
{
if (list[pos] == val)
if (this->v_[pos] == val)
{
return pos;
}
@ -77,11 +80,9 @@ Foam::label Foam::FixedList<T, N>::rfind(const T& val, label pos) const
pos = label(N)-1;
}
List_CONST_ACCESS(T, *this, list);
while (pos >= 0)
{
if (list[pos] == val)
if (this->v_[pos] == val)
{
return pos;
}
@ -148,44 +149,30 @@ void Foam::FixedList<T, N>::swapLast(const label i)
template<class T, unsigned N>
bool Foam::FixedList<T, N>::operator==(const FixedList<T, N>& list) const
{
List_CONST_ACCESS(T, *this, lhs);
List_CONST_ACCESS(T, (list), rhs);
// List sizes are identical by definition (template parameter)
for (unsigned i = 0; i < N; ++i)
{
if (!(lhs[i] == rhs[i]))
{
return false;
}
}
// Contents appear to be identical.
return true;
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
return
(
// List sizes are identical by definition (template parameter)
std::equal(this->cbegin(), this->cend(), list.cbegin())
);
}
template<class T, unsigned N>
bool Foam::FixedList<T, N>::operator<(const FixedList<T, N>& list) const
{
List_CONST_ACCESS(T, *this, lhs);
List_CONST_ACCESS(T, (list), rhs);
// List sizes are identical by definition (template parameter)
for (unsigned i=0; i<N; ++i)
{
if (lhs[i] < rhs[i])
{
return true;
}
else if (rhs[i] < lhs[i])
{
return false;
}
}
// Contents appear to be identical.
return false;
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
return std::lexicographical_compare
(
this->cbegin(), this->cend(),
list.cbegin(), list.cend()
);
}

View File

@ -239,7 +239,7 @@ public:
//- Return the forward circular index, i.e. next index
//- which returns to the first at the end of the list
inline label fcIndex(const label i) const;
inline label fcIndex(const label i) const noexcept;
//- Return forward circular value (ie, next value in the list)
inline const T& fcValue(const label i) const;
@ -249,7 +249,7 @@ public:
//- Return the reverse circular index, i.e. previous index
//- which returns to the last at the beginning of the list
inline label rcIndex(const label i) const;
inline label rcIndex(const label i) const noexcept;
//- Return reverse circular value (ie, previous value in the list)
inline const T& rcValue(const label i) const;
@ -297,9 +297,15 @@ public:
// Edit
//- Dummy function, to make FixedList consistent with List
//- Any resizing is ignored (Fatal with bad sizing in full debug).
inline void resize(const label n);
//- Set val for \em all elements.
//- Any resizing is ignored (Fatal with bad sizing in full debug).
inline void resize_fill(const label n, const T& val);
//- Dummy function, to make FixedList consistent with List
//- Any resizing is ignored (Fatal with bad sizing in full debug).
inline void resize_nocopy(const label n);
//- Dummy function, to make FixedList consistent with List

View File

@ -56,20 +56,16 @@ inline Foam::FixedList<T, N>::FixedList(const Foam::zero)
template<class T, unsigned N>
inline Foam::FixedList<T, N>::FixedList(const FixedList<T, N>& list)
{
for (unsigned i=0; i<N; ++i)
{
v_[i] = list.v_[i];
}
// std::execution::unsequenced_policy
std::copy(list.begin(), list.end(), v_);
}
template<class T, unsigned N>
inline Foam::FixedList<T, N>::FixedList(FixedList<T, N>&& list)
{
for (unsigned i=0; i<N; ++i)
{
v_[i] = std::move(list.v_[i]);
}
// std::execution::unsequenced_policy
std::move(list.begin(), list.end(), v_);
}
@ -77,13 +73,7 @@ template<class T, unsigned N>
inline Foam::FixedList<T, N>::FixedList(std::initializer_list<T> list)
{
checkSize(list.size());
auto iter = list.begin();
for (unsigned i=0; i<N; ++i)
{
v_[i] = *iter;
++iter;
}
std::copy_n(list.begin(), N, v_);
}
@ -91,11 +81,7 @@ template<class T, unsigned N>
inline Foam::FixedList<T, N>::FixedList(const UList<T>& list)
{
checkSize(list.size());
for (unsigned i=0; i<N; ++i)
{
v_[i] = list[i];
}
std::copy_n(list.begin(), N, v_);
}
@ -107,7 +93,7 @@ inline Foam::FixedList<T, N>::FixedList
const FixedList<label, N>& indices
)
{
for (unsigned i=0; i<N; ++i)
for (unsigned i = 0; i < N; ++i)
{
v_[i] = list[indices[i]];
}
@ -121,7 +107,7 @@ inline Foam::FixedList<T, N>::FixedList
const FixedList<label, N>& indices
)
{
for (unsigned i=0; i<N; ++i)
for (unsigned i = 0; i < N; ++i)
{
v_[i] = list[indices[i]];
}
@ -224,7 +210,7 @@ inline const T& Foam::FixedList<T, N>::back() const noexcept
template<class T, unsigned N>
inline Foam::label Foam::FixedList<T, N>::fcIndex(const label i) const
inline Foam::label Foam::FixedList<T, N>::fcIndex(const label i) const noexcept
{
return (i == N-1 ? 0 : i+1);
}
@ -245,7 +231,7 @@ inline T& Foam::FixedList<T, N>::fcValue(const label i)
template<class T, unsigned N>
inline Foam::label Foam::FixedList<T, N>::rcIndex(const label i) const
inline Foam::label Foam::FixedList<T, N>::rcIndex(const label i) const noexcept
{
return (i ? i-1 : N-1);
}
@ -307,6 +293,7 @@ inline bool Foam::FixedList<T, N>::uniform() const
{
if (empty()) return false; // <- Compile-time disabled anyhow
// std::all_of()
for (unsigned i=1; i<N; ++i)
{
if (v_[0] != v_[i])
@ -335,6 +322,16 @@ inline void Foam::FixedList<T, N>::resize(const label n)
}
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::resize_fill(const label n, const T& val)
{
#ifdef FULLDEBUG
checkSize(n);
#endif
this->fill(val);
}
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::resize_nocopy(const label n)
{
@ -348,10 +345,7 @@ template<class T, unsigned N>
inline void Foam::FixedList<T, N>::fill(const T& val)
{
// Usually small enough that parallel execution is pointless...
for (unsigned i=0; i<N; ++i)
{
v_[i] = val;
}
std::fill_n(v_, N, val);
}
@ -359,7 +353,9 @@ template<class T, unsigned N>
inline void Foam::FixedList<T, N>::fill(const Foam::zero)
{
// Usually small enough that parallel execution is pointless...
for (unsigned i=0; i<N; ++i)
// Cannot use std::fill (ambiguous conversions for bool, char, etc)
for (unsigned i = 0; i < N; ++i)
{
v_[i] = Zero;
}
@ -390,10 +386,8 @@ inline void Foam::FixedList<T, N>::transfer(FixedList<T, N>& list)
return; // Self-assignment is a no-op
}
for (unsigned i=0; i<N; ++i)
{
v_[i] = std::move(list[i]);
}
// std::execution::unsequenced_policy
std::move(list.begin(), list.end(), v_);
}
@ -423,11 +417,7 @@ template<class T, unsigned N>
inline void Foam::FixedList<T, N>::operator=(const UList<T>& list)
{
checkSize(list.size());
for (unsigned i=0; i<N; ++i)
{
v_[i] = list[i];
}
std::copy_n(list.begin(), N, v_);
}
@ -435,15 +425,10 @@ template<class T, unsigned N>
inline void Foam::FixedList<T, N>::operator=(std::initializer_list<T> list)
{
checkSize(list.size());
auto iter = list.begin();
for (unsigned i=0; i<N; ++i)
{
v_[i] = *iter;
++iter;
}
std::copy_n(list.begin(), N, v_);
}
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::operator=(const T& val)
{
@ -466,12 +451,11 @@ inline void Foam::FixedList<T, N>::operator=(const FixedList<T, N>& list)
return; // Self-assignment is a no-op
}
for (unsigned i=0; i<N; ++i)
{
v_[i] = list.v_[i];
}
// std::execution::unsequenced_policy
std::copy(list.begin(), list.end(), v_);
}
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::operator=(FixedList<T, N>&& list)
{
@ -480,10 +464,8 @@ inline void Foam::FixedList<T, N>::operator=(FixedList<T, N>&& list)
return; // Self-assignment is a no-op
}
for (unsigned i=0; i<N; ++i)
{
v_[i] = std::move(list.v_[i]);
}
// std::execution::unsequenced_policy
std::move(list.begin(), list.end(), v_);
}

View File

@ -27,7 +27,6 @@ License
\*---------------------------------------------------------------------------*/
#include "List.H"
#include "ListLoopM.H"
#include "FixedList.H"
#include "PtrList.H"
#include "contiguous.H"
@ -47,46 +46,26 @@ void Foam::List<T>::doResize(const label len)
// With sign-check to avoid spurious -Walloc-size-larger-than
const label overlap = min(this->size_, len);
if (!overlap)
if (overlap > 0)
{
// Can discard old content before allocating new storage.
// - when used as storage for DynamicList, it is possible to have
// a zero-sized List with a non-null data pointer.
delete[] this->v_;
// Recover overlapping content when resizing
T* old = this->v_;
this->size_ = len;
this->v_ = new T[len];
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::move(old, (old + overlap), this->v_);
delete[] old;
}
else
{
// Recover old (overlapping) content when resizing
T* nv = new T[len];
// Like std::copy(this->v_, this->v_ + overlap, nv);
// but with move semantics!
#ifdef USEMEMCPY
if (is_contiguous<T>::value)
{
std::memcpy
(
static_cast<void*>(nv), this->v_, overlap*sizeof(T)
);
}
else
#endif
{
List_ACCESS(T, *this, vp);
for (label i = 0; i < overlap; ++i)
{
nv[i] = std::move(vp[i]);
}
}
// No overlapping content
delete[] this->v_;
this->size_ = len;
this->v_ = nv;
this->v_ = new T[len];
}
}
else
@ -138,7 +117,7 @@ Foam::List<T>::List(const label len, const T& val)
if (len)
{
doAlloc();
this->fill_uniform(val);
UList<T>::operator=(val);
}
}
@ -158,13 +137,7 @@ Foam::List<T>::List(const label len, const Foam::zero)
if (len)
{
doAlloc();
// fill_uniform()
List_ACCESS(T, (*this), vp);
for (label i = 0; i < len; ++i)
{
vp[i] = Zero;
}
UList<T>::operator=(Foam::zero{});
}
}
@ -249,20 +222,8 @@ Foam::List<T>::List(const UList<T>& list, const labelUList& indices)
:
UList<T>(nullptr, indices.size())
{
const label len = indices.size();
if (len)
{
doAlloc();
// Copy indirect
List_ACCESS(T, (*this), vp);
for (label i=0; i < len; ++i)
{
vp[i] = list[indices[i]];
}
}
doAlloc();
copyList(list, indices); // <- deepCopy()
}
@ -274,21 +235,10 @@ Foam::List<T>::List
const FixedList<label,N>& indices
)
:
UList<T>(nullptr, label(N))
UList<T>(nullptr, indices.size())
{
const label len = label(N);
{
doAlloc();
// Copy indirect
List_ACCESS(T, (*this), vp);
for (label i = 0; i < len; ++i)
{
vp[i] = list[indices[i]];
}
}
doAlloc();
copyList(list, indices); // <- deepCopy()
}
@ -296,11 +246,8 @@ template<class T>
template<unsigned N>
Foam::List<T>::List(const FixedList<T, N>& list)
:
UList<T>(nullptr, label(N))
{
doAlloc();
copyList(list);
}
List<T>(list.begin(), list.end(), list.size())
{}
template<class T>
@ -319,8 +266,11 @@ Foam::List<T>::List(const IndirectListBase<T, Addr>& list)
:
UList<T>(nullptr, list.size())
{
doAlloc();
copyList(list);
if (this->size_ > 0)
{
doAlloc();
UList<T>::deepCopy(list);
}
}
@ -450,15 +400,9 @@ template<class T>
template<unsigned N>
void Foam::List<T>::operator=(const FixedList<T, N>& list)
{
reAlloc(static_cast<label>(N));
reAlloc(list.size());
T* iter = this->begin();
for (const T& val : list)
{
*iter = val;
++iter;
}
std::copy(list.begin(), list.end(), this->v_);
}
@ -466,40 +410,17 @@ template<class T>
template<class Addr>
void Foam::List<T>::operator=(const IndirectListBase<T, Addr>& list)
{
const label len = list.size();
reAlloc(len);
if (len)
{
// copyList ...
List_ACCESS(T, (*this), vp);
for (label i=0; i < len; ++i)
{
vp[i] = list[i];
}
}
reAlloc(list.size());
UList<T>::deepCopy(list);
}
template<class T>
void Foam::List<T>::operator=(std::initializer_list<T> list)
{
const label len = list.size();
reAlloc(list.size());
reAlloc(len);
if (len)
{
T* iter = this->begin();
for (const T& val : list)
{
*iter = val;
++iter;
}
}
std::copy(list.begin(), list.end(), this->v_);
}
@ -571,7 +492,6 @@ void Foam::sortedOrder
}
// * * * * * * * * * * * * * * * Housekeeping * * * * * * * * * * * * * * * //
#include "SLList.H"

View File

@ -86,8 +86,13 @@ class List
inline void reAlloc(const label len);
//- Copy all list contents. Uses operator[] on the input list
template<class List2>
inline void copyList(const List2& list);
template<class ListType>
inline void copyList(const ListType& list);
//- Copy list contents via indirect indices.
// Uses operator[] on the values and indices lists
template<class ListType, class ListIndices>
inline void copyList(const ListType& list, const ListIndices& indices);
//- Change allocation size of List, retaining old contents.
// Backend for resize
@ -98,8 +103,8 @@ class List
template<class InputIterator>
inline List
(
InputIterator begIter,
InputIterator endIter,
InputIterator firstIter,
InputIterator lastIter, // (unused)
const label len
);
@ -213,9 +218,12 @@ public:
// The boolList version fills new memory with false.
inline void resize(const label len);
//- Adjust allocated size of list and set val for new elements
//- Adjust allocated size of list and set val for \em new elements
void resize(const label len, const T& val);
//- Adjust allocated size of list and set val for \em all elements
inline void resize_fill(const label len, const T& val);
//- Adjust allocated size of list \b without necessarily
// retaining old content.
// If no reallocation is required, the contents remain untouched.

View File

@ -52,17 +52,41 @@ inline void Foam::List<T>::reAlloc(const label len)
template<class T>
template<class List2>
inline void Foam::List<T>::copyList(const List2& list)
template<class ListType>
inline void Foam::List<T>::copyList(const ListType& list)
{
// NB: operator[] for list read access (eg, an indirect list)
// cannot necessarily replace with std::copy
const label len = this->size_;
for (label i = 0; i < len; ++i)
auto iter = this->v_;
for (label i = 0; i < len; (void)++i, (void)++iter)
{
this->v_[i] = list[i];
*iter = list[i];
}
}
template<class T>
template<class ListType, class ListIndices>
inline void Foam::List<T>::copyList
(
const ListType& list,
const ListIndices& indices
)
{
// NB: operator[] for list read access (eg, an indirect list)
// cannot necessarily replace with std::copy
const label len = this->size_;
auto iter = this->v_;
for (label i = 0; i < len; (void)++i, (void)++iter)
{
*iter = list[indices[i]];
}
}
@ -71,8 +95,8 @@ template<class T>
template<class InputIterator>
inline Foam::List<T>::List
(
InputIterator begIter,
InputIterator endIter,
InputIterator firstIter,
InputIterator lastIter, // (unused)
const label len
)
:
@ -85,11 +109,9 @@ inline Foam::List<T>::List
// Like std::copy() or std::copy_n()
// but without any requirements on the iterator category
InputIterator iter = begIter;
for (label i = 0; i < len; ++i)
for (label i = 0; i < len; (void)++i, (void)++firstIter)
{
this->v_[i] = *iter;
++iter;
this->v_[i] = *firstIter;
}
}
}
@ -148,6 +170,14 @@ inline void Foam::List<T>::resize(const label len)
}
template<class T>
inline void Foam::List<T>::resize_fill(const label len, const T& val)
{
this->reAlloc(len);
UList<T>::operator=(val);
}
template<class T>
inline void Foam::List<T>::resize_nocopy(const label len)
{
@ -155,14 +185,6 @@ inline void Foam::List<T>::resize_nocopy(const label len)
}
// template<class T>
// inline void Foam::List<T>::resize_fill(const label len, const T& val)
// {
// this->reAlloc(len);
// this->fill_uniform(val);
// }
template<class T>
inline T& Foam::List<T>::newElmt(const label i)
{
@ -196,9 +218,8 @@ inline T& Foam::List<T>::emplace_back(Args&&... args)
const label idx = this->size();
resize(idx + 1);
// move assign element
this->operator[](idx) = T(std::forward<Args>(args)...);
return this->back();
UList<T>::operator[](idx) = T(std::forward<Args>(args)...);
return UList<T>::operator[](idx);
}
@ -208,7 +229,7 @@ inline void Foam::List<T>::push_back(const T& val)
const label idx = this->size();
resize(idx + 1);
this->operator[](idx) = val; // copy element
UList<T>::operator[](idx) = val; // copy element
}
@ -218,7 +239,7 @@ inline void Foam::List<T>::push_back(T&& val)
const label idx = this->size();
resize(idx + 1);
this->operator[](idx) = std::move(val); // move assign element
UList<T>::operator[](idx) = std::move(val); // move assign element
}
@ -231,15 +252,10 @@ inline void Foam::List<T>::push_back(const UList<T>& list)
<< "Attempted push_back to self" << abort(FatalError);
}
label idx = this->size();
const label n = list.size();
const label idx = this->size();
resize(idx + list.size());
resize(idx + n);
for (label i=0; i<n; ++i)
{
this->operator[](idx++) = list[i]; // copy element
}
std::copy(list.begin(), list.end(), this->begin(idx));
}
@ -247,14 +263,20 @@ template<class T>
template<class Addr>
inline void Foam::List<T>::push_back(const IndirectListBase<T, Addr>& list)
{
label idx = this->size();
// Note: push_back will still work even if the indirect list
// actually references *this, since its source elements will not
// overlap the new destinations.
const label idx = this->size();
const label n = list.size();
resize(idx + n);
for (label i=0; i<n; ++i)
auto iter = this->begin(idx);
for (label i = 0; i < n; (void)++i, (void)++iter)
{
this->operator[](idx++) = list[i]; // copy element
*iter = list[i]; // copy element
}
}

View File

@ -259,7 +259,7 @@ Foam::Istream& Foam::List<T>::readList(Istream& is)
);
// Fill with the value
this->fill_uniform(elem);
UList<T>::operator=(elem);
}
}

View File

@ -27,7 +27,6 @@ License
\*---------------------------------------------------------------------------*/
#include "UList.H"
#include "ListLoopM.H"
#include "contiguous.H"
#include "labelRange.H"
@ -114,10 +113,9 @@ void Foam::UList<T>::deepCopy(const UList<T>& list)
}
else if (this->size_ > 0)
{
// Can also dispatch with
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::copy(list.cbegin(), list.cend(), this->v_);
}
}
@ -136,14 +134,18 @@ void Foam::UList<T>::deepCopy(const IndirectListBase<T, Addr>& list)
}
else if (this->size_)
{
// copyList()
// Copy the indirect list contents
// NB: operator[] for list read access (eg, an indirect list)
// cannot replace with std::copy
const label len = this->size_;
List_ACCESS(T, (*this), lhs);
for (label i = 0; i < len; ++i)
auto iter = this->v_;
for (label i = 0; i < len; (void)++i, (void)++iter)
{
lhs[i] = list[i];
*iter = list[i];
}
}
}
@ -151,18 +153,11 @@ void Foam::UList<T>::deepCopy(const IndirectListBase<T, Addr>& list)
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// This is non-inlined to allow template specializations
template<class T>
void Foam::UList<T>::operator=(const Foam::zero)
{
// fill_uniform()
const label len = this->size();
List_ACCESS(T, (*this), vp);
for (label i = 0; i < len; ++i)
{
vp[i] = Zero;
}
this->fill_uniform(Foam::zero{});
}
@ -186,13 +181,17 @@ Foam::label Foam::UList<T>::find(const T& val, label pos) const
{
const label len = this->size();
if (pos >= 0 && len)
if (pos >= 0)
{
List_CONST_ACCESS(T, (*this), list);
// auto iter = std::find(this->begin(pos), this->end(), val);
// if (iter != this->end())
// {
// return label(iter - this->begin());
// }
while (pos < len)
{
if (list[pos] == val)
if (this->v_[pos] == val)
{
return pos;
}
@ -214,11 +213,9 @@ Foam::label Foam::UList<T>::rfind(const T& val, label pos) const
pos = this->size()-1;
}
List_CONST_ACCESS(T, (*this), list);
while (pos >= 0)
{
if (list[pos] == val)
if (this->v_[pos] == val)
{
return pos;
}
@ -235,28 +232,14 @@ Foam::label Foam::UList<T>::rfind(const T& val, label pos) const
template<class T>
bool Foam::UList<T>::operator==(const UList<T>& list) const
{
/// OR:
/// return
/// (
/// (this->size_ == list.size_)
// && std::equal(cbegin(), cend(), list.cbegin())
/// );
const label len = this->size_;
if (len != list.size_)
{
return false;
}
List_CONST_ACCESS(T, (*this), lhs);
List_CONST_ACCESS(T, (list), rhs);
for (label i = 0; i < len; ++i)
{
if (!(lhs[i] == rhs[i])) return false;
}
return true;
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
return
(
(this->size_ == list.size_)
&& std::equal(this->cbegin(), this->cend(), list.cbegin())
);
}
@ -270,35 +253,14 @@ bool Foam::UList<T>::operator!=(const UList<T>& list) const
template<class T>
bool Foam::UList<T>::operator<(const UList<T>& list) const
{
/// OR:
/// return std::lexicographical_compare
/// (
/// cbegin(), cend(),
/// list.cbegin(), list.cend()
/// );
const const_iterator last1 = cend();
const const_iterator last2 = list.cend();
for
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
return std::lexicographical_compare
(
const_iterator lhs = cbegin(), rhs = list.cbegin();
(lhs != last1) && (rhs != last2);
++lhs, (void) ++rhs
)
{
if (*lhs < *rhs)
{
return true;
}
else if (*rhs < *lhs)
{
return false;
}
}
// Contents look to be identical, or lists have different sizes
return (this->size_ < list.size_);
this->cbegin(), this->cend(),
list.cbegin(), list.cend()
);
}
@ -328,6 +290,7 @@ bool Foam::UList<T>::operator>=(const UList<T>& list) const
template<class T>
void Foam::sort(UList<T>& list)
{
// With which std::execution:: ?
std::sort(list.begin(), list.end());
}
@ -335,6 +298,7 @@ void Foam::sort(UList<T>& list)
template<class T, class Compare>
void Foam::sort(UList<T>& list, const Compare& comp)
{
// With which std::execution:: ?
std::sort(list.begin(), list.end(), comp);
}
@ -342,6 +306,7 @@ void Foam::sort(UList<T>& list, const Compare& comp)
template<class T>
void Foam::stableSort(UList<T>& list)
{
// With which std::execution:: ?
std::stable_sort(list.begin(), list.end());
}
@ -349,6 +314,7 @@ void Foam::stableSort(UList<T>& list)
template<class T, class Compare>
void Foam::stableSort(UList<T>& list, const Compare& comp)
{
// With which std::execution:: ?
std::stable_sort(list.begin(), list.end(), comp);
}

View File

@ -122,6 +122,10 @@ protected:
// Caution: method name subject to change
inline void fill_uniform(const T& val);
//- Assign all entries to zero
// Caution: method name subject to change
inline void fill_uniform(const Foam::zero);
//- No copy assignment (default: shallow copy)
//
// Assignment may need to be shallow (copy pointer)
@ -628,16 +632,18 @@ public:
template<>
Istream& UList<char>::readList(Istream& is);
//- Specialized writeEntry for character lists which always uses
//- binary format.
//- Character list writeEntry - always uses binary format.
template<>
void UList<char>::writeEntry(Ostream& os) const;
//- Specialized writeList for character lists which always uses
//- binary format.
//- Character list writeList - always uses binary format.
template<>
Ostream& UList<char>::writeList(Ostream& os, const label /*unused*/) const;
//- Character list assign zero - avoids Foam::zero casting ambiguities
template<>
void UList<char>::operator=(const Foam::zero);
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //

View File

@ -52,17 +52,42 @@ inline Foam::UList<T>::UList(T* __restrict__ v, const label len) noexcept
template<class T>
inline void Foam::UList<T>::fill_uniform(const T& val)
{
// Can also dispatch with
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
this->v_, this->size_, val
);
}
if (this->size_ > 0)
template<class T>
inline void Foam::UList<T>::fill_uniform(const Foam::zero)
{
// Note: ambiguous conversions for char can still cause compilation
// issues.
// May also have special triggers when assigning non-contiguous from zero...
if (is_contiguous<T>::value)
{
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
this->v_, this->size_, val
this->data_bytes(), this->size_bytes(), char(0)
);
}
else
{
const auto last = (this->v_ + this->size_);
for (auto first = this->v_; (first != last); (void)++first)
{
*first = Foam::zero{};
}
}
}
@ -196,18 +221,16 @@ inline void Foam::UList<T>::checkIndex(const label i) const
template<class T>
inline bool Foam::UList<T>::uniform() const
{
const label len = size();
if (!len)
if (!size_)
{
return false;
}
const T& val = (*this)[0]; // first
// std::all_of()
for (label i = 1; i < len; ++i)
for (label i = 1; i < size_; ++i)
{
if (val != (*this)[i])
if (this->v_[0] != this->v_[i])
{
return false;
}
@ -318,7 +341,7 @@ namespace Foam
return Foam::pTraits<bool>::zero;
}
}
} // End namespace Foam
template<class T>

View File

@ -293,6 +293,9 @@ public:
//- Copy append another list to the end of this list
inline void push_back(const UList<T>& list);
//- Move append another list to the end of this list
inline void push_back(List<T>&& list);
//- Reduce size by 1 or more elements. Can be called on an empty list.
inline void pop_back(label n = 1);

View File

@ -408,14 +408,16 @@ inline void Foam::DynamicField<T, SizeMin>::resize
const T& val
)
{
label idx = List<T>::size();
const label oldLen = List<T>::size();
resize(len);
// Fill newly exposed with constant value
while (idx < len)
if (oldLen < List<T>::size())
{
this->operator[](idx) = val;
++idx;
std::fill
(
this->begin(oldLen), this->end(), val
);
}
}
@ -596,7 +598,7 @@ inline T& Foam::DynamicField<T, SizeMin>::emplace_back(Args&&... args)
// move assign element
this->operator[](idx) = T(std::forward<Args>(args)...);
return this->back();
return this->operator[](idx);
}
@ -639,13 +641,32 @@ inline void Foam::DynamicField<T, SizeMin>::push_back
<< abort(FatalError);
}
label idx = List<T>::size();
const label idx = List<T>::size();
resize(idx + list.size());
for (const T& val : list)
std::copy(list.begin(), list.end(), this->begin(idx));
}
template<class T, int SizeMin>
inline void Foam::DynamicField<T, SizeMin>::push_back
(
List<T>&& list
)
{
if (this == &list)
{
this->operator[](idx++) = val; // copy element
FatalErrorInFunction
<< "Attempted push_back to self"
<< abort(FatalError);
}
const label idx = List<T>::size();
resize(idx + list.size());
std::move(list.begin(), list.end(), this->begin(idx));
list.clear();
}

View File

@ -128,7 +128,7 @@ Foam::Matrix<Form, Type>::Matrix(const label m, const label n, const Foam::zero)
doAlloc();
std::fill(begin(), end(), Zero);
std::fill_n(begin(), size(), Zero);
}
@ -143,7 +143,7 @@ Foam::Matrix<Form, Type>::Matrix(const label m, const label n, const Type& val)
doAlloc();
std::fill(begin(), end(), val);
std::fill_n(begin(), size(), val);
}
@ -244,10 +244,7 @@ inline Foam::Matrix<Form, Type>::Matrix
template<class Form, class Type>
Foam::Matrix<Form, Type>::~Matrix()
{
if (v_)
{
delete[] v_;
}
delete[] v_;
}
@ -594,14 +591,14 @@ void Foam::Matrix<Form, Type>::operator=
template<class Form, class Type>
void Foam::Matrix<Form, Type>::operator=(const Type& val)
{
std::fill(begin(), end(), val);
std::fill_n(begin(), size(), val);
}
template<class Form, class Type>
void Foam::Matrix<Form, Type>::operator=(const Foam::zero)
{
std::fill(begin(), end(), Zero);
std::fill_n(begin(), size(), Zero);
}

View File

@ -188,10 +188,22 @@ public:
// Access
//- The number of rows
inline label m() const noexcept;
label mRows() const noexcept { return mRows_; }
//- The number of rows
label nRows() const noexcept { return mRows_; }
//- The number of rows
label m() const noexcept { return mRows_; }
//- The number of columns
inline label n() const noexcept;
label nCols() const noexcept { return nCols_; }
//- The number of columns
label n() const noexcept { return nCols_; }
//- Return true if Matrix is empty (i.e., size() is zero)
inline bool empty() const noexcept;
//- The number of elements in Matrix (m*n)
inline label size() const;
@ -199,9 +211,6 @@ public:
//- Return row/column sizes
inline labelPair sizes() const;
//- Return true if Matrix is empty (i.e., size() is zero)
inline bool empty() const noexcept;
//- Return const pointer to the first data element, which can also
//- be used to address into Matrix contents
inline const Type* cdata() const noexcept;
@ -510,25 +519,6 @@ public:
// Housekeeping
//- The number of rows - same as m()
inline label mRows() const noexcept
{
return mRows_;
}
//- The number of rows - same as m()
inline label nRows() const noexcept
{
return mRows_;
}
//- The number of columns - same as n()
inline label nCols() const noexcept
{
return nCols_;
}
//- Deprecated(2019-04) raw data pointer, const access
// \deprecated(2019-04) - use cdata() method
FOAM_DEPRECATED_FOR(2019-04, "cdata() method")

View File

@ -92,20 +92,6 @@ inline const Foam::Matrix<Form, Type>& Foam::Matrix<Form, Type>::null()
}
template<class Form, class Type>
inline Foam::label Foam::Matrix<Form, Type>::m() const noexcept
{
return mRows_;
}
template<class Form, class Type>
inline Foam::label Foam::Matrix<Form, Type>::n() const noexcept
{
return nCols_;
}
template<class Form, class Type>
inline Foam::label Foam::Matrix<Form, Type>::size() const
{
@ -181,11 +167,12 @@ inline bool Foam::Matrix<Form, Type>::uniform() const
{
const label len = size();
if (len == 0)
if (!len)
{
return false;
}
// std::all_of()
for (label idx = 1; idx < len; ++idx)
{
if (v_[0] != v_[idx])

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2022 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -118,7 +118,7 @@ bool Foam::Matrix<Form, Type>::readMatrix(Istream& is)
is.fatalCheck("readMatrix : reading the single entry");
std::fill(begin(), end(), element);
std::fill_n(begin(), size(), element);
}
}

View File

@ -188,6 +188,13 @@ Istream& UList<char>::readList(Istream& is)
return is;
}
template<>
void UList<char>::operator=(const Foam::zero)
{
UList<char>::operator=(char(0));
}
} // End namespace Foam
// ************************************************************************* //