mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: additional 'nocopy' methods for List resize/reserve methods
- the size of a List often requires adjustment prior to an operation,
but old values (if any) are not of interest and will be overwritten.
In these cases can use the _nocopy versions to avoid additional memory
overhead of the intermediate list and the copy/move overhead of
retaining the old values (that we will subsequently discard anyhow).
No equivalent for PtrList/UPtrList - this would be too fragile.
- add swap DynamicField with DynamicList
BUG: fixed Dynamic{Field,List} setCapacity corner case
- for the case when the newly requested capacity coincides with the
current addressable size, the resize of the underlying list would have
been bypassed - ie, the real capacity was not actually changed.
- remove (unused) PtrDynList setCapacity method as too fragile
This commit is contained in:
3
applications/test/DynamicList2/Make/files
Normal file
3
applications/test/DynamicList2/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-DynamicList2.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-DynamicList2
|
||||
2
applications/test/DynamicList2/Make/options
Normal file
2
applications/test/DynamicList2/Make/options
Normal file
@ -0,0 +1,2 @@
|
||||
/* EXE_INC = */
|
||||
/* EXE_LIBS = */
|
||||
155
applications/test/DynamicList2/Test-DynamicList2.C
Normal file
155
applications/test/DynamicList2/Test-DynamicList2.C
Normal file
@ -0,0 +1,155 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Description
|
||||
Test allocation patterns when reading into an existing list.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "DynamicList.H"
|
||||
#include "DynamicField.H"
|
||||
#include "IOstreams.H"
|
||||
#include "ITstream.H"
|
||||
#include "OTstream.H"
|
||||
#include "StringStream.H"
|
||||
#include "FlatOutput.H"
|
||||
#include "ListOps.H"
|
||||
#include "labelRange.H"
|
||||
#include "labelIndList.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
template<class T, int SizeMin>
|
||||
void printInfo
|
||||
(
|
||||
const word& tag,
|
||||
const DynamicList<T, SizeMin>& list,
|
||||
const bool showSize = true
|
||||
)
|
||||
{
|
||||
Info<< '<' << tag;
|
||||
if (showSize)
|
||||
{
|
||||
Info<< " size=\"" << list.size()
|
||||
<< "\" capacity=\"" << list.capacity() << "\"";
|
||||
if (list.cdata())
|
||||
{
|
||||
Info<< " ptr=\"" << name(list.cdata()) << "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " ptr=\"nullptr\"";
|
||||
}
|
||||
}
|
||||
Info<< '>' << nl << flatOutput(list) << nl
|
||||
<< "</" << tag << ">\n" << endl;
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
void printInfo
|
||||
(
|
||||
const word& tag,
|
||||
const DynamicField<T, SizeMin>& list,
|
||||
const bool showSize = true
|
||||
)
|
||||
{
|
||||
Info<< '<' << tag;
|
||||
if (showSize)
|
||||
{
|
||||
Info<< " size=\"" << list.size()
|
||||
<< "\" capacity=\"" << list.capacity() << "\"";
|
||||
if (list.cdata())
|
||||
{
|
||||
Info<< " ptr=\"" << name(list.cdata()) << "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " ptr=\"nullptr\"";
|
||||
}
|
||||
}
|
||||
Info<< '>' << nl << flatOutput(list) << nl
|
||||
<< "</" << tag << ">\n" << endl;
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
void readList
|
||||
(
|
||||
DynamicList<T, SizeMin>& output,
|
||||
const UList<T>& input
|
||||
)
|
||||
{
|
||||
OTstream os;
|
||||
os << input;
|
||||
ITstream is("input", os.tokens());
|
||||
|
||||
is >> output;
|
||||
}
|
||||
|
||||
template<class T, int SizeMin>
|
||||
void readList
|
||||
(
|
||||
DynamicField<T, SizeMin>& output,
|
||||
const UList<T>& input
|
||||
)
|
||||
{
|
||||
OTstream os;
|
||||
os << input;
|
||||
ITstream is("input", os.tokens());
|
||||
|
||||
is >> output;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//
|
||||
{
|
||||
DynamicList<label, 64> list1;
|
||||
|
||||
list1.resize(4);
|
||||
ListOps::identity(list1);
|
||||
|
||||
list1.resize(3);
|
||||
printInfo("", list1);
|
||||
|
||||
// list1.clear();
|
||||
// printInfo("", list1);
|
||||
|
||||
list1.setCapacity(3);
|
||||
printInfo("", list1);
|
||||
}
|
||||
|
||||
Info<< "\nEnd\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -290,7 +290,7 @@ public:
|
||||
inline bool empty() const noexcept;
|
||||
|
||||
//- The number of elements that can be stored with reallocating
|
||||
inline label capacity() const;
|
||||
inline label capacity() const noexcept;
|
||||
|
||||
//- True if all entries have identical values, and list is non-empty
|
||||
bool uniform() const;
|
||||
@ -353,17 +353,20 @@ public:
|
||||
//- Alter the size of the underlying storage.
|
||||
// The addressed size will be truncated if needed to fit, but will
|
||||
// remain otherwise untouched.
|
||||
inline void setCapacity(const label nElem);
|
||||
inline void setCapacity(const label numElem);
|
||||
|
||||
//- Reset addressable list size, does not shrink the allocated size.
|
||||
// Optionally specify a value for new elements.
|
||||
inline void resize(const label nElem, const unsigned int val = 0u);
|
||||
inline void resize(const label numElem, const unsigned int val = 0u);
|
||||
|
||||
//- Currently identical to resize. Subject to future change (Oct-2021)
|
||||
inline void resize_nocopy(const label numElem);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
// Never shrinks the allocated size.
|
||||
// The list size is adjusted as per DynamicList with
|
||||
// SizeInc=0, SizeMult=2, SizeDiv=1
|
||||
inline void reserve(const label nElem);
|
||||
inline void reserve(const label numElem);
|
||||
|
||||
//- Clear the list, i.e. set addressable size to zero.
|
||||
// Does not adjust the underlying storage
|
||||
|
||||
@ -388,12 +388,22 @@ inline bool Foam::PackedList<Width>::empty() const noexcept
|
||||
|
||||
|
||||
template<unsigned Width>
|
||||
inline Foam::label Foam::PackedList<Width>::capacity() const
|
||||
inline Foam::label Foam::PackedList<Width>::capacity() const noexcept
|
||||
{
|
||||
return elem_per_block * blocks_.size();
|
||||
}
|
||||
|
||||
|
||||
template<unsigned Width>
|
||||
inline void Foam::PackedList<Width>::resize_nocopy
|
||||
(
|
||||
const label numElem
|
||||
)
|
||||
{
|
||||
this->resize(numElem);
|
||||
}
|
||||
|
||||
|
||||
template<unsigned Width>
|
||||
inline void Foam::PackedList<Width>::resize
|
||||
(
|
||||
@ -406,7 +416,7 @@ inline void Foam::PackedList<Width>::resize
|
||||
const label oldSize = size();
|
||||
size_ = newSize;
|
||||
|
||||
if (oldSize < size())
|
||||
if (oldSize < newSize)
|
||||
{
|
||||
// Fill new elements or newly exposed elements
|
||||
if (val)
|
||||
@ -438,7 +448,7 @@ inline void Foam::PackedList<Width>::resize
|
||||
clear_trailing_bits();
|
||||
}
|
||||
}
|
||||
else if (size() < oldSize)
|
||||
else if (newSize < oldSize)
|
||||
{
|
||||
// The list is now shorter than before, so we zero assign the unused
|
||||
// blocks and any trailing junk. This costs slightly here, but make
|
||||
|
||||
@ -46,7 +46,6 @@ SourceFiles
|
||||
#define DynamicList_H
|
||||
|
||||
#include "List.H"
|
||||
#include <type_traits>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -92,6 +91,21 @@ class DynamicList
|
||||
template<class ListType>
|
||||
inline void assignDynList(const ListType& list);
|
||||
|
||||
//- Alter the size of the underlying storage
|
||||
// The 'nocopy' option will not attempt to recover old content
|
||||
inline void doCapacity(const bool nocopy, const label len);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
// The 'nocopy' option will not attempt to recover old content
|
||||
inline void doReserve(const bool nocopy, const label len);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
// The 'nocopy' option will not attempt to recover old content
|
||||
inline void doResize(const bool nocopy, const label len);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
@ -121,7 +135,7 @@ public:
|
||||
|
||||
//- Construct from a FixedList
|
||||
template<unsigned N>
|
||||
inline DynamicList(const FixedList<T, N>& lst);
|
||||
inline explicit DynamicList(const FixedList<T, N>& lst);
|
||||
|
||||
//- Construct from an initializer list. Size set to list size.
|
||||
inline explicit DynamicList(std::initializer_list<T> lst);
|
||||
@ -168,23 +182,49 @@ public:
|
||||
// The addressed size will be truncated if needed to fit, but will
|
||||
// remain otherwise untouched.
|
||||
// Use this or reserve() in combination with append().
|
||||
inline void setCapacity(const label newCapacity);
|
||||
inline void setCapacity(const label len);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
//- Alter the size of the underlying storage,
|
||||
//- \em without retaining old content.
|
||||
// The addressed size will be truncated if needed to fit, but will
|
||||
// remain otherwise untouched.
|
||||
inline void setCapacity_nocopy(const label len);
|
||||
|
||||
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
|
||||
//- Does not perform any memory management or resizing.
|
||||
inline void setCapacity_unsafe(const label len) noexcept;
|
||||
|
||||
//- Reserve allocation space for at least this size, allocating new
|
||||
//- space if required and \em retaining old content.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
inline void reserve(const label len);
|
||||
|
||||
//- Alter addressable size.
|
||||
// New space will be allocated if required.
|
||||
inline void resize(const label newLen);
|
||||
//- Reserve allocation space for at least this size, allocating new
|
||||
//- space if required \em without retaining old content.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
inline void reserve_nocopy(const label len);
|
||||
|
||||
//- Alter addressable size and fill new space with constant value
|
||||
inline void resize(const label newLen, const T& val);
|
||||
//- Alter addressable list size, allocating new space if required
|
||||
//- while \em recovering old content.
|
||||
// If no reallocation is required, the contents remain untouched.
|
||||
// Otherwise new entries will be uninitialized.
|
||||
// Use this to resize the list prior to using the operator[] for
|
||||
// setting values (as per List usage).
|
||||
inline void resize(const label len);
|
||||
|
||||
//- Alias for resize()
|
||||
//- Alter addressable size and fill new entries with constant value
|
||||
inline void resize(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.
|
||||
// Otherwise all entries will be uninitialized.
|
||||
inline void resize_nocopy(const label len);
|
||||
|
||||
//- Same as resize()
|
||||
void setSize(const label n) { this->resize(n); }
|
||||
|
||||
//- Alias for resize()
|
||||
//- Same as resize()
|
||||
void setSize(const label n, const T& val) { this->resize(n, val); }
|
||||
|
||||
//- Clear the addressed list, i.e. set the size to zero.
|
||||
@ -198,6 +238,9 @@ public:
|
||||
// Returns the previous addressable size.
|
||||
inline label expandStorage() noexcept;
|
||||
|
||||
//- Shrink the allocated space to the number of elements used.
|
||||
inline void shrinkStorage();
|
||||
|
||||
//- Shrink the allocated space to the number of elements used.
|
||||
// Returns a reference to the DynamicList.
|
||||
inline DynamicList<T, SizeMin>& shrink();
|
||||
|
||||
@ -37,22 +37,98 @@ inline void Foam::DynamicList<T, SizeMin>::assignDynList
|
||||
const ListType& list
|
||||
)
|
||||
{
|
||||
const label newLen = list.size();
|
||||
const label len = list.size();
|
||||
|
||||
if (newLen <= capacity_)
|
||||
if (capacity_ < len)
|
||||
{
|
||||
// Can copy w/o reallocating - adjust addressable size accordingly.
|
||||
List<T>::setAddressableSize(newLen);
|
||||
List<T>::operator=(list);
|
||||
// Needs more space for the copy operation
|
||||
List<T>::setAddressableSize(capacity_); // Use entire space
|
||||
List<T>::resize_nocopy(len);
|
||||
capacity_ = List<T>::size();
|
||||
}
|
||||
|
||||
// Perform copy into addressable portion
|
||||
List<T>::setAddressableSize(len);
|
||||
List<T>::operator=(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::doCapacity
|
||||
(
|
||||
const bool nocopy,
|
||||
const label newCapacity
|
||||
)
|
||||
{
|
||||
if (newCapacity == capacity_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Addressable length, possibly truncated by new capacity
|
||||
const label currLen = min(List<T>::size(), newCapacity);
|
||||
|
||||
// Corner case...
|
||||
if (List<T>::size() == newCapacity)
|
||||
{
|
||||
// Adjust addressable size to trigger proper resizing.
|
||||
// Using (old size+1) is safe since it does not affect the 'overlap'
|
||||
// of old and new addressable regions, but incurs fewew copy
|
||||
// operations than extending to use the current capacity would.
|
||||
List<T>::setAddressableSize(currLen+1);
|
||||
}
|
||||
|
||||
if (nocopy)
|
||||
{
|
||||
List<T>::resize_nocopy(newCapacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure list size consistency prior to copying.
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
|
||||
List<T>::operator=(list);
|
||||
capacity_ = List<T>::size();
|
||||
List<T>::resize(newCapacity);
|
||||
}
|
||||
|
||||
capacity_ = List<T>::size();
|
||||
List<T>::setAddressableSize(currLen);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::doReserve
|
||||
(
|
||||
const bool nocopy,
|
||||
const label len
|
||||
)
|
||||
{
|
||||
if (capacity_ < len)
|
||||
{
|
||||
// Preserve addressed size
|
||||
const label currLen = List<T>::size();
|
||||
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(len, label(2*capacity_)));
|
||||
|
||||
if (nocopy)
|
||||
{
|
||||
List<T>::resize_nocopy(capacity_);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<T>::resize(capacity_);
|
||||
}
|
||||
List<T>::setAddressableSize(currLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::doResize
|
||||
(
|
||||
const bool nocopy,
|
||||
const label len
|
||||
)
|
||||
{
|
||||
this->doReserve(nocopy, len);
|
||||
List<T>::setAddressableSize(len);
|
||||
}
|
||||
|
||||
|
||||
@ -72,7 +148,7 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList(const label len)
|
||||
List<T>(),
|
||||
capacity_(0)
|
||||
{
|
||||
reserve(len);
|
||||
reserve_nocopy(len);
|
||||
}
|
||||
|
||||
|
||||
@ -141,10 +217,9 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList
|
||||
const FixedList<T, N>& list
|
||||
)
|
||||
:
|
||||
capacity_(0)
|
||||
{
|
||||
this->operator=(list);
|
||||
}
|
||||
List<T>(list),
|
||||
capacity_(List<T>::size())
|
||||
{}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
@ -201,10 +276,9 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList
|
||||
List<T>&& lst
|
||||
)
|
||||
:
|
||||
capacity_(0)
|
||||
{
|
||||
transfer(lst);
|
||||
}
|
||||
List<T>(std::move(lst)),
|
||||
capacity_(List<T>::size())
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
@ -227,20 +301,30 @@ Foam::DynamicList<T, SizeMin>::capacity_bytes() const noexcept
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::setCapacity
|
||||
(
|
||||
const label newCapacity
|
||||
const label len
|
||||
)
|
||||
{
|
||||
label currLen = List<T>::size();
|
||||
capacity_ = newCapacity;
|
||||
this->doCapacity(false, len); // nocopy = false
|
||||
}
|
||||
|
||||
if (currLen > capacity_)
|
||||
{
|
||||
// Truncate addressed sizes too
|
||||
currLen = capacity_;
|
||||
}
|
||||
|
||||
List<T>::resize(capacity_);
|
||||
List<T>::setAddressableSize(currLen);
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::setCapacity_nocopy
|
||||
(
|
||||
const label len
|
||||
)
|
||||
{
|
||||
this->doCapacity(true, len); // nocopy = true
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::setCapacity_unsafe
|
||||
(
|
||||
const label len
|
||||
) noexcept
|
||||
{
|
||||
capacity_ = len;
|
||||
}
|
||||
|
||||
|
||||
@ -250,52 +334,55 @@ inline void Foam::DynamicList<T, SizeMin>::reserve
|
||||
const label len
|
||||
)
|
||||
{
|
||||
if (capacity_ < len)
|
||||
{
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(len, label(2 * capacity_)));
|
||||
|
||||
// Adjust allocated size, leave addressed size untouched
|
||||
const label currLen = List<T>::size();
|
||||
List<T>::resize(capacity_);
|
||||
List<T>::setAddressableSize(currLen);
|
||||
}
|
||||
this->doReserve(false, len); // nocopy = false
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::resize
|
||||
inline void Foam::DynamicList<T, SizeMin>::reserve_nocopy
|
||||
(
|
||||
const label newLen
|
||||
const label len
|
||||
)
|
||||
{
|
||||
if (capacity_ < newLen)
|
||||
{
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(newLen, label(2 * capacity_)));
|
||||
|
||||
List<T>::resize(capacity_);
|
||||
}
|
||||
|
||||
// Adjust addressed size
|
||||
List<T>::setAddressableSize(newLen);
|
||||
this->doReserve(true, len); // nocopy = true
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::resize
|
||||
(
|
||||
const label newLen,
|
||||
const label len
|
||||
)
|
||||
{
|
||||
this->doResize(false, len); // nocopy = false
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::resize_nocopy
|
||||
(
|
||||
const label len
|
||||
)
|
||||
{
|
||||
this->doResize(true, len); // nocopy = true
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicList<T, SizeMin>::resize
|
||||
(
|
||||
const label len,
|
||||
const T& val
|
||||
)
|
||||
{
|
||||
label currLen = List<T>::size();
|
||||
resize(newLen);
|
||||
label idx = List<T>::size();
|
||||
resize(len);
|
||||
|
||||
// Fill newly exposed with constant value
|
||||
while (currLen < newLen)
|
||||
while (idx < len)
|
||||
{
|
||||
this->operator[](currLen++) = val;
|
||||
this->operator[](idx) = val;
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,7 +407,7 @@ inline Foam::label Foam::DynamicList<T, SizeMin>::expandStorage() noexcept
|
||||
{
|
||||
const label currLen = List<T>::size();
|
||||
|
||||
// Allow addressing into the entire list
|
||||
// Address into the entire list
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
|
||||
return currLen;
|
||||
@ -328,20 +415,25 @@ inline Foam::label Foam::DynamicList<T, SizeMin>::expandStorage() noexcept
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicList<T, SizeMin>&
|
||||
Foam::DynamicList<T, SizeMin>::shrink()
|
||||
inline void Foam::DynamicList<T, SizeMin>::shrinkStorage()
|
||||
{
|
||||
const label currLen = List<T>::size();
|
||||
if (currLen < capacity_)
|
||||
{
|
||||
// Use the full list when resizing
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
// Adjust addressable size to trigger proper resizing
|
||||
List<T>::setAddressableSize(currLen+1);
|
||||
|
||||
// Capacity and size are identical
|
||||
capacity_ = currLen;
|
||||
List<T>::resize(currLen);
|
||||
// Redundant: List<T>::setAddressableSize(currLen);
|
||||
capacity_ = List<T>::size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicList<T, SizeMin>&
|
||||
Foam::DynamicList<T, SizeMin>::shrink()
|
||||
{
|
||||
this->shrinkStorage();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -745,14 +837,7 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
|
||||
const FixedList<T, N>& lst
|
||||
)
|
||||
{
|
||||
const label n = lst.size();
|
||||
|
||||
resize(n);
|
||||
|
||||
for (label i=0; i<n; ++i)
|
||||
{
|
||||
this->operator[](i) = lst[i]; // copy element
|
||||
}
|
||||
assignDynList(lst);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -298,6 +298,9 @@ public:
|
||||
//- Dummy function, to make FixedList consistent with List
|
||||
inline void resize(const label n);
|
||||
|
||||
//- Dummy function, to make FixedList consistent with List
|
||||
inline void resize_nocopy(const label n);
|
||||
|
||||
//- Dummy function, to make FixedList consistent with List
|
||||
void setSize(const label n) { this->resize(n); }
|
||||
|
||||
|
||||
@ -346,6 +346,16 @@ inline void Foam::FixedList<T, N>::resize(const label n)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline void Foam::FixedList<T, N>::resize_nocopy(const label n)
|
||||
{
|
||||
#ifdef FULLDEBUG
|
||||
checkSize(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline void Foam::FixedList<T, N>::fill(const T& val)
|
||||
{
|
||||
|
||||
@ -37,54 +37,57 @@ License
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
void Foam::List<T>::doResize(const label newSize)
|
||||
void Foam::List<T>::doResize(const label len)
|
||||
{
|
||||
if (newSize < 0)
|
||||
if (len == this->size_)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "bad size " << newSize
|
||||
<< abort(FatalError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newSize != this->size_)
|
||||
if (len > 0)
|
||||
{
|
||||
if (newSize > 0)
|
||||
// With sign-check to avoid spurious -Walloc-size-larger-than
|
||||
T* nv = new T[len];
|
||||
|
||||
const label overlap = min(this->size_, len);
|
||||
|
||||
if (overlap)
|
||||
{
|
||||
// With sign-check to avoid spurious -Walloc-size-larger-than
|
||||
T* nv = new T[newSize];
|
||||
|
||||
const label overlap = min(this->size_, newSize);
|
||||
|
||||
if (overlap)
|
||||
#ifdef USEMEMCPY
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
#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)
|
||||
{
|
||||
std::memcpy
|
||||
(
|
||||
static_cast<void*>(nv), this->v_, overlap*sizeof(T)
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// No speedup observed for copy assignment on simple types
|
||||
List_ACCESS(T, *this, vp);
|
||||
for (label i = 0; i < overlap; ++i)
|
||||
{
|
||||
nv[i] = std::move(vp[i]);
|
||||
}
|
||||
nv[i] = std::move(vp[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clear();
|
||||
this->size_ = newSize;
|
||||
this->v_ = nv;
|
||||
}
|
||||
else
|
||||
clear();
|
||||
this->size_ = len;
|
||||
this->v_ = nv;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Or only #ifdef FULLDEBUG
|
||||
if (len < 0)
|
||||
{
|
||||
clear();
|
||||
FatalErrorInFunction
|
||||
<< "bad size " << len
|
||||
<< abort(FatalError);
|
||||
}
|
||||
// #endif
|
||||
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,7 +260,7 @@ Foam::List<T>::List(List<T>& a, bool reuse)
|
||||
{
|
||||
if (reuse)
|
||||
{
|
||||
// swap content
|
||||
// Steal content
|
||||
this->v_ = a.v_;
|
||||
a.v_ = nullptr;
|
||||
a.size_ = 0;
|
||||
@ -435,15 +438,16 @@ Foam::List<T>::~List()
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
void Foam::List<T>::resize(const label newSize, const T& val)
|
||||
void Foam::List<T>::resize(const label len, const T& val)
|
||||
{
|
||||
const label oldSize = this->size_;
|
||||
this->doResize(newSize);
|
||||
label idx = this->size_;
|
||||
this->doResize(len);
|
||||
|
||||
List_ACCESS(T, *this, vp);
|
||||
for (label i = oldSize; i < newSize; ++i)
|
||||
while (idx < len)
|
||||
{
|
||||
vp[i] = val;
|
||||
vp[idx] = val;
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,7 +566,7 @@ template<class T>
|
||||
template<unsigned N>
|
||||
void Foam::List<T>::operator=(const FixedList<T, N>& list)
|
||||
{
|
||||
reAlloc(label(N));
|
||||
reAlloc(static_cast<label>(N));
|
||||
|
||||
T* iter = this->begin();
|
||||
|
||||
|
||||
@ -43,8 +43,8 @@ SourceFiles
|
||||
#ifndef List_H
|
||||
#define List_H
|
||||
|
||||
#include "UList.H"
|
||||
#include "autoPtr.H"
|
||||
#include "UList.H"
|
||||
#include "SLListFwd.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -83,14 +83,16 @@ class List
|
||||
inline void doAlloc();
|
||||
|
||||
//- Reallocate list storage to the given size
|
||||
// Discards old storage (if any). Does not copy old contents
|
||||
inline void reAlloc(const label len);
|
||||
|
||||
//- Copy list of given type.
|
||||
//- Copy all list contents
|
||||
template<class List2>
|
||||
inline void copyList(const List2& list);
|
||||
|
||||
//- Change allocation size - backend for resize.
|
||||
void doResize(const label newSize);
|
||||
//- Change allocation size of List, retaining old contents.
|
||||
// Backend for resize
|
||||
void doResize(const label len);
|
||||
|
||||
//- Construct given begin/end iterators and number of elements
|
||||
// Since the size is provided, the end iterator is actually ignored.
|
||||
@ -206,10 +208,16 @@ public:
|
||||
|
||||
//- Adjust allocated size of list.
|
||||
// The boolList version fills new memory with false.
|
||||
inline void resize(const label newLen);
|
||||
inline void resize(const label len);
|
||||
|
||||
//- Adjust allocated size of list and set val for new elements
|
||||
void resize(const label newLen, const T& val);
|
||||
void resize(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.
|
||||
// Otherwise the contents will be uninitialized.
|
||||
inline void resize_nocopy(const label len);
|
||||
|
||||
//- Alias for resize()
|
||||
void setSize(const label n) { this->resize(n); }
|
||||
@ -221,15 +229,19 @@ public:
|
||||
// Edit
|
||||
|
||||
//- Append an element at the end of the list
|
||||
// If this is frequently required, consider a DynamicList
|
||||
inline void append(const T& val);
|
||||
|
||||
//- Move append an element at the end of the list
|
||||
// If this is frequently required, consider a DynamicList
|
||||
inline void append(T&& val);
|
||||
|
||||
//- Append a List to the end of this list
|
||||
// If this is frequently required, consider a DynamicList
|
||||
inline void append(const UList<T>& list);
|
||||
|
||||
//- Append IndirectList contents at the end of this list
|
||||
// If this is frequently required, consider a DynamicList
|
||||
template<class Addr>
|
||||
inline void append(const IndirectListBase<T, Addr>& list);
|
||||
|
||||
|
||||
@ -120,14 +120,13 @@ inline void Foam::List<T>::clear()
|
||||
delete[] this->v_;
|
||||
this->v_ = nullptr;
|
||||
}
|
||||
|
||||
this->size_ = 0;
|
||||
}
|
||||
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
// Template specialization for bool. Fills with false
|
||||
// Template specialization for bool. Fills new entries with false
|
||||
template<>
|
||||
inline void List<bool>::resize(const label newLen)
|
||||
{
|
||||
@ -137,9 +136,16 @@ namespace Foam
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::List<T>::resize(const label newLen)
|
||||
inline void Foam::List<T>::resize(const label len)
|
||||
{
|
||||
this->doResize(newLen);
|
||||
this->doResize(len);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::List<T>::resize_nocopy(const label len)
|
||||
{
|
||||
this->reAlloc(len);
|
||||
}
|
||||
|
||||
|
||||
@ -168,7 +174,10 @@ inline T& Foam::List<T>::newElmt(const label i)
|
||||
template<class T>
|
||||
inline void Foam::List<T>::append(const T& val)
|
||||
{
|
||||
resize(this->size() + 1, val); // copy element
|
||||
const label idx = this->size();
|
||||
resize(idx + 1);
|
||||
|
||||
this->operator[](idx) = val; // copy element
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -114,11 +114,7 @@ public:
|
||||
|
||||
// Sizing
|
||||
|
||||
//- Alter the size of the underlying storage.
|
||||
inline void setCapacity(const label newCapacity);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
inline void reserve(const label len);
|
||||
|
||||
//- Alter the addressed list size.
|
||||
|
||||
@ -97,33 +97,17 @@ inline const T* Foam::PtrDynList<T, SizeMin>::get(const label i) const
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::PtrDynList<T, SizeMin>::setCapacity(const label newCapacity)
|
||||
{
|
||||
label currLen = PtrList<T>::size();
|
||||
capacity_ = newCapacity;
|
||||
|
||||
if (currLen > capacity_)
|
||||
{
|
||||
// Truncate addressed sizes too
|
||||
currLen = capacity_;
|
||||
}
|
||||
|
||||
PtrList<T>::resize(capacity_);
|
||||
PtrList<T>::setAddressableSize(currLen);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::PtrDynList<T, SizeMin>::reserve(const label len)
|
||||
{
|
||||
if (capacity_ < len)
|
||||
{
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(len, label(2 * capacity_)));
|
||||
|
||||
// Adjust allocated size, leave addressed size untouched
|
||||
// Preserve addressed size
|
||||
const label currLen = PtrList<T>::size();
|
||||
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(len, label(2*capacity_)));
|
||||
|
||||
PtrList<T>::resize(capacity_);
|
||||
PtrList<T>::setAddressableSize(currLen);
|
||||
}
|
||||
@ -140,7 +124,7 @@ inline void Foam::PtrDynList<T, SizeMin>::resize(const label newLen)
|
||||
if (capacity_ < newLen)
|
||||
{
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(newLen, label(2 * capacity_)));
|
||||
capacity_ = max(SizeMin, max(newLen, label(2*capacity_)));
|
||||
|
||||
PtrList<T>::resize(capacity_);
|
||||
}
|
||||
@ -193,13 +177,11 @@ inline void Foam::PtrDynList<T, SizeMin>::shrink()
|
||||
const label currLen = PtrList<T>::size();
|
||||
if (currLen < capacity_)
|
||||
{
|
||||
// Use the full list when resizing
|
||||
PtrList<T>::setAddressableSize(capacity_);
|
||||
// Adjust addressable size to trigger proper resizing
|
||||
PtrList<T>::setAddressableSize(currLen+1);
|
||||
|
||||
// Capacity and size are identical
|
||||
capacity_ = currLen;
|
||||
PtrList<T>::resize(currLen);
|
||||
// Redundant: PtrList<T>::setAddressableSize(currLen);
|
||||
capacity_ = PtrList<T>::size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2019 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2021 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -66,6 +66,19 @@ Foam::label Foam::Detail::PtrListDetail<T>::findNull() const
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Detail::PtrListDetail<T>::setNull()
|
||||
{
|
||||
List<T*>& ptrs = *this;
|
||||
const label len = ptrs.size();
|
||||
|
||||
for (label i=0; i<len; ++i)
|
||||
{
|
||||
ptrs[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Detail::PtrListDetail<T>::free()
|
||||
{
|
||||
|
||||
@ -95,6 +95,9 @@ public:
|
||||
//- Locate the first null entry, -1 if there are not any
|
||||
label findNull() const;
|
||||
|
||||
//- Assign all pointers to nullptr, without deleting.
|
||||
void setNull();
|
||||
|
||||
//- Delete the allocated entries, but retain the list size.
|
||||
void free();
|
||||
|
||||
@ -129,6 +132,9 @@ public:
|
||||
void setSize(const label) = delete;
|
||||
void setSize(const label, const T&) = delete;
|
||||
void setSize(const label, const T*) = delete;
|
||||
|
||||
// Too fragile or dangerous
|
||||
void resize_nocopy(const label) = delete;
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -39,7 +39,7 @@ SourceFiles
|
||||
#define DynamicField_H
|
||||
|
||||
#include "Field.H"
|
||||
#include <type_traits>
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -78,6 +78,21 @@ class DynamicField
|
||||
template<class ListType>
|
||||
inline void assignDynList(const ListType& list);
|
||||
|
||||
//- Alter the size of the underlying storage
|
||||
// The 'nocopy' option will not attempt to recover old content
|
||||
inline void doCapacity(const bool nocopy, const label len);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
// The 'nocopy' option will not attempt to recover old content
|
||||
inline void doReserve(const bool nocopy, const label len);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
// The 'nocopy' option will not attempt to recover old content
|
||||
inline void doResize(const bool nocopy, const label len);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Static Member Functions
|
||||
@ -128,6 +143,10 @@ public:
|
||||
template<int AnySizeMin>
|
||||
inline DynamicField(DynamicField<T, AnySizeMin>&& content);
|
||||
|
||||
//- Move construct from DynamicList
|
||||
template<int AnySizeMin>
|
||||
inline DynamicField(DynamicList<T, AnySizeMin>&& list);
|
||||
|
||||
//- Construct by 1 to 1 mapping from the given field
|
||||
inline DynamicField
|
||||
(
|
||||
@ -178,18 +197,44 @@ public:
|
||||
// The addressed size will be truncated if needed to fit, but will
|
||||
// remain otherwise untouched.
|
||||
// Use this or reserve() in combination with append().
|
||||
inline void setCapacity(const label newCapacity);
|
||||
inline void setCapacity(const label len);
|
||||
|
||||
//- Reserve allocation space for at least this size.
|
||||
//- Alter the size of the underlying storage,
|
||||
//- \em without retaining old content.
|
||||
// The addressed size will be truncated if needed to fit, but will
|
||||
// remain otherwise untouched.
|
||||
inline void setCapacity_nocopy(const label len);
|
||||
|
||||
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
|
||||
//- Does not perform any memory management or resizing.
|
||||
inline void setCapacity_unsafe(const label len) noexcept;
|
||||
|
||||
//- Reserve allocation space for at least this size, allocating new
|
||||
//- space if required and \em retaining old content.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
inline void reserve(const label len);
|
||||
|
||||
//- Alter addressable size.
|
||||
// New space will be allocated if required.
|
||||
inline void resize(const label newLen);
|
||||
//- Reserve allocation space for at least this size, allocating new
|
||||
//- space if required \em without retaining old content.
|
||||
// Never shrinks the allocated size, use setCapacity() for that.
|
||||
inline void reserve_nocopy(const label len);
|
||||
|
||||
//- Alter addressable list size, allocating new space if required
|
||||
//- while \em recovering old content.
|
||||
// If no reallocation is required, the contents remain untouched.
|
||||
// Otherwise new entries will be uninitialized.
|
||||
// Use this to resize the list prior to using the operator[] for
|
||||
// setting values (as per List usage).
|
||||
inline void resize(const label len);
|
||||
|
||||
//- Alter addressable size and fill new space with constant value
|
||||
inline void resize(const label newLen, const T& val);
|
||||
inline void resize(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.
|
||||
// Otherwise all entries will be uninitialized.
|
||||
inline void resize_nocopy(const label len);
|
||||
|
||||
//- Alias for resize()
|
||||
void setSize(const label n) { this->resize(n); }
|
||||
@ -208,6 +253,9 @@ public:
|
||||
// Returns the previous addressable size.
|
||||
inline label expandStorage() noexcept;
|
||||
|
||||
//- Shrink the allocated space to the number of elements used.
|
||||
inline void shrinkStorage();
|
||||
|
||||
//- Shrink the allocated space to the number of elements used.
|
||||
// Returns a reference to the DynamicField.
|
||||
inline DynamicField<T, SizeMin>& shrink();
|
||||
@ -219,6 +267,10 @@ public:
|
||||
template<int AnySizeMin>
|
||||
inline void swap(DynamicField<T, AnySizeMin>& other);
|
||||
|
||||
//- Swap content with DynamicList, independent of sizing parameter
|
||||
template<int AnySizeMin>
|
||||
inline void swap(DynamicList<T, AnySizeMin>& other);
|
||||
|
||||
//- Transfer the parameter contents into this
|
||||
inline void transfer(List<T>& list);
|
||||
|
||||
@ -271,6 +323,10 @@ public:
|
||||
//- Move assignment
|
||||
inline void operator=(List<T>&& list);
|
||||
|
||||
//- Move assignment
|
||||
template<int AnySizeMin>
|
||||
inline void operator=(DynamicList<T, AnySizeMin>&& list);
|
||||
|
||||
//- Move assignment
|
||||
inline void operator=(DynamicField<T, SizeMin>&& list);
|
||||
|
||||
|
||||
@ -35,22 +35,94 @@ inline void Foam::DynamicField<T, SizeMin>::assignDynList
|
||||
const ListType& list
|
||||
)
|
||||
{
|
||||
const label newLen = list.size();
|
||||
const label len = list.size();
|
||||
|
||||
if (newLen <= capacity_)
|
||||
if (capacity_ < len)
|
||||
{
|
||||
// Can copy w/o reallocating - adjust addressable size accordingly.
|
||||
List<T>::setAddressableSize(newLen);
|
||||
List<T>::operator=(list);
|
||||
// Needs more space for the copy operation
|
||||
List<T>::setAddressableSize(capacity_); // Use entire space
|
||||
List<T>::resize_nocopy(len);
|
||||
capacity_ = List<T>::size();
|
||||
}
|
||||
|
||||
// Perform copy into addressable portion
|
||||
List<T>::setAddressableSize(len);
|
||||
List<T>::operator=(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::doCapacity
|
||||
(
|
||||
const bool nocopy,
|
||||
const label newCapacity
|
||||
)
|
||||
{
|
||||
if (newCapacity == capacity_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Addressable length, possibly truncated by new capacity
|
||||
const label currLen = min(List<T>::size(), newCapacity);
|
||||
|
||||
// Corner case - see comments in DynamicList doCapacity
|
||||
if (List<T>::size() == newCapacity)
|
||||
{
|
||||
List<T>::setAddressableSize(currLen+1);
|
||||
}
|
||||
|
||||
if (nocopy)
|
||||
{
|
||||
List<T>::resize_nocopy(newCapacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure list size consistency prior to copying.
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
|
||||
List<T>::operator=(list);
|
||||
capacity_ = List<T>::size();
|
||||
List<T>::resize(newCapacity);
|
||||
}
|
||||
|
||||
capacity_ = List<T>::size();
|
||||
List<T>::setAddressableSize(currLen);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::doReserve
|
||||
(
|
||||
const bool nocopy,
|
||||
const label len
|
||||
)
|
||||
{
|
||||
if (capacity_ < len)
|
||||
{
|
||||
// Preserve addressed size
|
||||
const label currLen = List<T>::size();
|
||||
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(len, label(2*capacity_)));
|
||||
|
||||
if (nocopy)
|
||||
{
|
||||
List<T>::resize_nocopy(capacity_);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<T>::resize(capacity_);
|
||||
}
|
||||
List<T>::setAddressableSize(currLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::doResize
|
||||
(
|
||||
const bool nocopy,
|
||||
const label len
|
||||
)
|
||||
{
|
||||
this->doReserve(nocopy, len);
|
||||
List<T>::setAddressableSize(len);
|
||||
}
|
||||
|
||||
|
||||
@ -70,7 +142,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField(const label len)
|
||||
Field<T>(),
|
||||
capacity_(0)
|
||||
{
|
||||
reserve(len);
|
||||
reserve_nocopy(len);
|
||||
}
|
||||
|
||||
|
||||
@ -155,6 +227,20 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
{}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
DynamicList<T, AnySizeMin>&& list
|
||||
)
|
||||
:
|
||||
Field<T>(),
|
||||
capacity_(0)
|
||||
{
|
||||
transfer(list);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>::DynamicField
|
||||
(
|
||||
@ -255,20 +341,30 @@ Foam::DynamicField<T, SizeMin>::capacity_bytes() const noexcept
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::setCapacity
|
||||
(
|
||||
const label newCapacity
|
||||
const label len
|
||||
)
|
||||
{
|
||||
label currLen = List<T>::size();
|
||||
capacity_ = newCapacity;
|
||||
this->doCapacity(false, len); // nocopy = false
|
||||
}
|
||||
|
||||
if (currLen > capacity_)
|
||||
{
|
||||
// Truncate addressed sizes too
|
||||
currLen = capacity_;
|
||||
}
|
||||
|
||||
List<T>::resize(capacity_);
|
||||
List<T>::setAddressableSize(currLen);
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::setCapacity_nocopy
|
||||
(
|
||||
const label len
|
||||
)
|
||||
{
|
||||
this->doCapacity(true, len); // nocopy = true
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::setCapacity_unsafe
|
||||
(
|
||||
const label len
|
||||
) noexcept
|
||||
{
|
||||
capacity_ = len;
|
||||
}
|
||||
|
||||
|
||||
@ -278,52 +374,55 @@ inline void Foam::DynamicField<T, SizeMin>::reserve
|
||||
const label len
|
||||
)
|
||||
{
|
||||
if (capacity_ < len)
|
||||
{
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(len, label(2 * capacity_)));
|
||||
|
||||
// Adjust allocated size, leave addressed size untouched
|
||||
const label currLen = List<T>::size();
|
||||
List<T>::resize(capacity_);
|
||||
List<T>::setAddressableSize(currLen);
|
||||
}
|
||||
this->doReserve(false, len); // nocopy = false
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::resize
|
||||
inline void Foam::DynamicField<T, SizeMin>::reserve_nocopy
|
||||
(
|
||||
const label newLen
|
||||
const label len
|
||||
)
|
||||
{
|
||||
if (capacity_ < newLen)
|
||||
{
|
||||
// Increase capacity (doubling)
|
||||
capacity_ = max(SizeMin, max(newLen, label(2 * capacity_)));
|
||||
|
||||
List<T>::resize(capacity_);
|
||||
}
|
||||
|
||||
// Adjust addressed size
|
||||
List<T>::setAddressableSize(newLen);
|
||||
this->doReserve(true, len); // nocopy = true
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::resize
|
||||
(
|
||||
const label newLen,
|
||||
const label len
|
||||
)
|
||||
{
|
||||
this->doResize(false, len); // nocopy = false
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::resize_nocopy
|
||||
(
|
||||
const label len
|
||||
)
|
||||
{
|
||||
this->doResize(true, len); // nocopy = true
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::resize
|
||||
(
|
||||
const label len,
|
||||
const T& val
|
||||
)
|
||||
{
|
||||
label currLen = List<T>::size();
|
||||
resize(newLen);
|
||||
label idx = List<T>::size();
|
||||
resize(len);
|
||||
|
||||
// Fill newly exposed with constant value
|
||||
while (currLen < newLen)
|
||||
while (idx < len)
|
||||
{
|
||||
this->operator[](currLen++) = val;
|
||||
this->operator[](idx) = val;
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,21 +454,27 @@ inline Foam::label Foam::DynamicField<T, SizeMin>::expandStorage() noexcept
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::shrinkStorage()
|
||||
{
|
||||
const label currLen = List<T>::size();
|
||||
|
||||
if (currLen < capacity_)
|
||||
{
|
||||
// Adjust addressable size to trigger proper resizing
|
||||
List<T>::setAddressableSize(currLen+1);
|
||||
|
||||
List<T>::resize(currLen);
|
||||
capacity_ = List<T>::size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline Foam::DynamicField<T, SizeMin>&
|
||||
Foam::DynamicField<T, SizeMin>::shrink()
|
||||
{
|
||||
const label currLen = Field<T>::size();
|
||||
if (currLen < capacity_)
|
||||
{
|
||||
// Use the full list when resizing
|
||||
List<T>::setAddressableSize(capacity_);
|
||||
|
||||
// Capacity and size are identical
|
||||
capacity_ = currLen;
|
||||
List<T>::resize(currLen);
|
||||
// Redundant: List<T>::setAddressableSize(currLen);
|
||||
}
|
||||
this->shrinkStorage();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -395,6 +500,34 @@ inline void Foam::DynamicField<T, SizeMin>::swap
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::swap
|
||||
(
|
||||
DynamicList<T, AnySizeMin>& other
|
||||
)
|
||||
{
|
||||
auto& self = (*this);
|
||||
|
||||
// ... not yet needed:
|
||||
// Cannot compare 'this' for different types, so use cdata()
|
||||
if (self.cdata() == other.cdata())
|
||||
{
|
||||
return; // Self-swap is a no-op
|
||||
}
|
||||
|
||||
// Swap storage and addressable size
|
||||
UList<T>::swap(other);
|
||||
|
||||
// Swap capacity
|
||||
const label oldCap = self.capacity();
|
||||
const label newCap = other.capacity();
|
||||
|
||||
self.setCapacity_unsafe(newCap);
|
||||
other.setCapacity_unsafe(oldCap);
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::transfer(List<T>& list)
|
||||
{
|
||||
@ -421,7 +554,7 @@ inline void Foam::DynamicField<T, SizeMin>::transfer
|
||||
// clear addressing and storage for old list.
|
||||
capacity_ = list.capacity();
|
||||
|
||||
Field<T>::transfer(static_cast<Field<T>&>(list));
|
||||
Field<T>::transfer(static_cast<List<T>&>(list));
|
||||
list.clearStorage(); // Ensure capacity=0
|
||||
}
|
||||
|
||||
@ -443,7 +576,7 @@ inline void Foam::DynamicField<T, SizeMin>::transfer
|
||||
// clear addressing and storage for old list.
|
||||
capacity_ = list.capacity();
|
||||
|
||||
Field<T>::transfer(static_cast<Field<T>&>(list));
|
||||
Field<T>::transfer(static_cast<List<T>&>(list));
|
||||
list.clearStorage(); // Ensure capacity=0
|
||||
}
|
||||
|
||||
@ -531,7 +664,7 @@ inline T& Foam::DynamicField<T, SizeMin>::operator()
|
||||
const label i
|
||||
)
|
||||
{
|
||||
if (i >= Field<T>::size())
|
||||
if (i >= List<T>::size())
|
||||
{
|
||||
resize(i + 1);
|
||||
}
|
||||
@ -616,6 +749,17 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
}
|
||||
|
||||
|
||||
template<class T, int SizeMin>
|
||||
template<int AnySizeMin>
|
||||
inline void Foam::DynamicField<T, SizeMin>::operator=
|
||||
(
|
||||
DynamicList<T, AnySizeMin>&& list
|
||||
)
|
||||
{
|
||||
transfer(list);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
template<class T, int SizeMin>
|
||||
@ -624,13 +768,14 @@ inline Foam::Istream& Foam::DynamicField<T, SizeMin>::readList
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
DynamicField<T, SizeMin>& rhs = *this;
|
||||
// Use DynamicList::readList for reading DynamicField.
|
||||
// The logic should be the same and this avoids duplicate code
|
||||
|
||||
// Use entire storage - ie, resize(capacity())
|
||||
(void) rhs.expandStorage();
|
||||
DynamicList<T, SizeMin> list;
|
||||
(*this).swap(list);
|
||||
|
||||
is >> static_cast<Field<T>&>(rhs);
|
||||
rhs.capacity_ = rhs.Field<T>::size();
|
||||
list.readList(is);
|
||||
(*this).swap(list);
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
@ -345,6 +345,36 @@ void Foam::Matrix<Form, Type>::resize(const label m, const label n)
|
||||
}
|
||||
|
||||
|
||||
template<class Form, class Type>
|
||||
void Foam::Matrix<Form, Type>::resize_nocopy(const label mrow, const label ncol)
|
||||
{
|
||||
if (mrow == mRows_ && ncol == nCols_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const label oldLen = (mRows_ * nCols_);
|
||||
|
||||
const label newLen = (mrow * ncol);
|
||||
|
||||
if (oldLen == newLen)
|
||||
{
|
||||
// Shallow resize is enough
|
||||
mRows_ = mrow;
|
||||
nCols_ = ncol;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->clear();
|
||||
|
||||
mRows_ = mrow;
|
||||
nCols_ = ncol;
|
||||
|
||||
this->doAlloc();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Form, class Type>
|
||||
void Foam::Matrix<Form, Type>::round(const scalar tol)
|
||||
{
|
||||
|
||||
@ -357,6 +357,9 @@ public:
|
||||
//- Change Matrix dimensions, preserving the elements
|
||||
void resize(const label m, const label n);
|
||||
|
||||
//- Change Matrix dimensions \em without preserving existing content
|
||||
void resize_nocopy(const label mrow, const label ncol);
|
||||
|
||||
//- Change Matrix dimensions, preserving the elements
|
||||
inline void setSize(const label m, const label n);
|
||||
|
||||
@ -366,6 +369,7 @@ public:
|
||||
//- Round elements with magnitude smaller than tol (SMALL) to zero
|
||||
void round(const scalar tol = SMALL);
|
||||
|
||||
|
||||
// Operations
|
||||
|
||||
//- Return (conjugate) transpose of Matrix
|
||||
|
||||
Reference in New Issue
Block a user