diff --git a/applications/test/DynamicList2/Make/files b/applications/test/DynamicList2/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..78b8198c6a0a2af68afbb94d319ad5ba3501664c --- /dev/null +++ b/applications/test/DynamicList2/Make/files @@ -0,0 +1,3 @@ +Test-DynamicList2.C + +EXE = $(FOAM_USER_APPBIN)/Test-DynamicList2 diff --git a/applications/test/DynamicList2/Make/options b/applications/test/DynamicList2/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..18e6fe47afacb902cddccf82632772447704fd88 --- /dev/null +++ b/applications/test/DynamicList2/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = */ +/* EXE_LIBS = */ diff --git a/applications/test/DynamicList2/Test-DynamicList2.C b/applications/test/DynamicList2/Test-DynamicList2.C new file mode 100644 index 0000000000000000000000000000000000000000..b199e67579479386f50b1e98436ed12d7f20f95c --- /dev/null +++ b/applications/test/DynamicList2/Test-DynamicList2.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/containers/Bits/PackedList/PackedList.H b/src/OpenFOAM/containers/Bits/PackedList/PackedList.H index 1ae6f228f2592f4d38ad8ded51768520411f096f..23401256b65cc8af325b11d857d8478ae3f44371 100644 --- a/src/OpenFOAM/containers/Bits/PackedList/PackedList.H +++ b/src/OpenFOAM/containers/Bits/PackedList/PackedList.H @@ -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 diff --git a/src/OpenFOAM/containers/Bits/PackedList/PackedListI.H b/src/OpenFOAM/containers/Bits/PackedList/PackedListI.H index a525746d39bdb76884982894c57a3137ec3e0567..5d3dbe1dd596aa25841543e26041dfa17fb11dd0 100644 --- a/src/OpenFOAM/containers/Bits/PackedList/PackedListI.H +++ b/src/OpenFOAM/containers/Bits/PackedList/PackedListI.H @@ -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 diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H index d45d836afdcb47f312590d363efbcda5a553ce23..c97645e21fd7427ca840031f2eec26116a8e359a 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H @@ -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. - // Never shrinks the allocated size, use setCapacity() for that. - inline void reserve(const label len); + //- 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); - //- Alter addressable size. - // New space will be allocated if required. - inline void resize(const label newLen); + //- 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; - //- Alter addressable size and fill new space with constant value - inline void resize(const label newLen, const T& val); + //- 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); - //- Alias for resize() + //- 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 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(); diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H index 047aa3423aecc51003b7b668c97e9eeb49d31598..972317b73540fa1e9d02a185319acf19011b88bc 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H @@ -37,25 +37,101 @@ 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) + { + // 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) { - // Can copy w/o reallocating - adjust addressable size accordingly. - List<T>::setAddressableSize(newLen); - List<T>::operator=(list); + List<T>::resize_nocopy(newCapacity); } else { - // Ensure list size consistency prior to copying. - List<T>::setAddressableSize(capacity_); + List<T>::resize(newCapacity); + } - List<T>::operator=(list); - capacity_ = List<T>::size(); + 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); +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template<class T, int SizeMin> @@ -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_))); + this->doReserve(false, len); // nocopy = false +} - // Adjust allocated size, leave addressed size untouched - const label currLen = List<T>::size(); - List<T>::resize(capacity_); - List<T>::setAddressableSize(currLen); - } + +template<class T, int SizeMin> +inline void Foam::DynamicList<T, SizeMin>::reserve_nocopy +( + const label len +) +{ + this->doReserve(true, len); // nocopy = true } template<class T, int SizeMin> inline void Foam::DynamicList<T, SizeMin>::resize ( - const label newLen + const label len ) { - if (capacity_ < newLen) - { - // Increase capacity (doubling) - capacity_ = max(SizeMin, max(newLen, label(2 * capacity_))); + this->doResize(false, len); // nocopy = false +} - List<T>::resize(capacity_); - } - // Adjust addressed size - List<T>::setAddressableSize(newLen); +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 newLen, + 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); } diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedList.H b/src/OpenFOAM/containers/Lists/FixedList/FixedList.H index 3a3a6c63ef8146d858eb07cf04f3183e44cf28ae..2120e2ce062fe14abac81d9990ddfc69dad92fd0 100644 --- a/src/OpenFOAM/containers/Lists/FixedList/FixedList.H +++ b/src/OpenFOAM/containers/Lists/FixedList/FixedList.H @@ -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); } diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H b/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H index d72b3fb94440dc76dd4e441dea1a16ad4c6af65b..b23bd86ba8aceb7bd4fbf477e5f183d3117407fe 100644 --- a/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H +++ b/src/OpenFOAM/containers/Lists/FixedList/FixedListI.H @@ -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) { diff --git a/src/OpenFOAM/containers/Lists/List/List.C b/src/OpenFOAM/containers/Lists/List/List.C index 1a7186cace438ac7491b200c9e533832f9ce902e..858b046e839cbcaa3359ac09e30b77ca25b150de 100644 --- a/src/OpenFOAM/containers/Lists/List/List.C +++ b/src/OpenFOAM/containers/Lists/List/List.C @@ -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[newSize]; + // With sign-check to avoid spurious -Walloc-size-larger-than + T* nv = new T[len]; - const label overlap = min(this->size_, newSize); + const label overlap = min(this->size_, len); - if (overlap) + 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 + 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) { - // 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(); diff --git a/src/OpenFOAM/containers/Lists/List/List.H b/src/OpenFOAM/containers/Lists/List/List.H index 4cb9815a42fb2120f2950ac152c6783a26c1d113..c300941d482da9fd46a58dbeec7b48a8a8ca083d 100644 --- a/src/OpenFOAM/containers/Lists/List/List.H +++ b/src/OpenFOAM/containers/Lists/List/List.H @@ -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); diff --git a/src/OpenFOAM/containers/Lists/List/ListI.H b/src/OpenFOAM/containers/Lists/List/ListI.H index 7249511c1001f9cefc725f3264736e94360b6e6b..4063c27bcffb965c63d5299f865af0d83711aa92 100644 --- a/src/OpenFOAM/containers/Lists/List/ListI.H +++ b/src/OpenFOAM/containers/Lists/List/ListI.H @@ -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 } diff --git a/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynList.H b/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynList.H index 3c0131a62379d472759696f505c9b3951d86abb5..13fee326f20f1b164201b4ead3014a2ce2f229e5 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynList.H +++ b/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynList.H @@ -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. diff --git a/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynListI.H b/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynListI.H index 950b5ad6278591bced8a80ce93695b607299e78a..b8973ff4b6f3c405b496aab8f6e3dfb5553867f6 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynListI.H +++ b/src/OpenFOAM/containers/PtrLists/PtrDynList/PtrDynListI.H @@ -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) { + // Preserve addressed size + const label currLen = PtrList<T>::size(); + // Increase capacity (doubling) - capacity_ = max(SizeMin, max(len, label(2 * capacity_))); + capacity_ = max(SizeMin, max(len, label(2*capacity_))); - // Adjust allocated size, leave addressed size untouched - const label currLen = PtrList<T>::size(); 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(); } } diff --git a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C index 64af6c6b6de9c48c3b2458b8e31ddddb65212359..a72ec9461a619e6df4ef4a9b714fb3e2fdc4a7d3 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C +++ b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C @@ -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() { diff --git a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H index 811ae9d18f4d4723e5e33d3ef8064086fb921224..8e7ccf43722fa133197e754e2050fd52544f7b4f 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H +++ b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H @@ -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; }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H b/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H index 517d292afd5550a0a183d6f9846dbd375f91df84..1293335420b3536a16f98611446a3da154848e91 100644 --- a/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H +++ b/src/OpenFOAM/fields/Fields/DynamicField/DynamicField.H @@ -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); diff --git a/src/OpenFOAM/fields/Fields/DynamicField/DynamicFieldI.H b/src/OpenFOAM/fields/Fields/DynamicField/DynamicFieldI.H index 8d41f1e36351aba021296231e6fe6b48ea3e8f68..7a3da8641650194e761d84a20921a2c5a29cb13e 100644 --- a/src/OpenFOAM/fields/Fields/DynamicField/DynamicFieldI.H +++ b/src/OpenFOAM/fields/Fields/DynamicField/DynamicFieldI.H @@ -35,25 +35,97 @@ 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) + { + // 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) { - // Can copy w/o reallocating - adjust addressable size accordingly. - List<T>::setAddressableSize(newLen); - List<T>::operator=(list); + List<T>::resize_nocopy(newCapacity); } else { - // Ensure list size consistency prior to copying. - List<T>::setAddressableSize(capacity_); + List<T>::resize(newCapacity); + } - List<T>::operator=(list); - capacity_ = List<T>::size(); + 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); +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template<class T, int SizeMin> @@ -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_))); + this->doReserve(false, len); // nocopy = false +} - // Adjust allocated size, leave addressed size untouched - const label currLen = List<T>::size(); - List<T>::resize(capacity_); - List<T>::setAddressableSize(currLen); - } + +template<class T, int SizeMin> +inline void Foam::DynamicField<T, SizeMin>::reserve_nocopy +( + const label len +) +{ + this->doReserve(true, len); // nocopy = true } template<class T, int SizeMin> inline void Foam::DynamicField<T, SizeMin>::resize ( - const label newLen + const label len ) { - if (capacity_ < newLen) - { - // Increase capacity (doubling) - capacity_ = max(SizeMin, max(newLen, label(2 * capacity_))); + this->doResize(false, len); // nocopy = false +} - List<T>::resize(capacity_); - } - // Adjust addressed size - List<T>::setAddressableSize(newLen); +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 newLen, + 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; } } @@ -356,20 +455,26 @@ inline Foam::label Foam::DynamicField<T, SizeMin>::expandStorage() noexcept template<class T, int SizeMin> -inline Foam::DynamicField<T, SizeMin>& -Foam::DynamicField<T, SizeMin>::shrink() +inline void Foam::DynamicField<T, SizeMin>::shrinkStorage() { - const label currLen = Field<T>::size(); + 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::DynamicField<T, SizeMin>& +Foam::DynamicField<T, SizeMin>::shrink() +{ + 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; } diff --git a/src/OpenFOAM/matrices/Matrix/Matrix.C b/src/OpenFOAM/matrices/Matrix/Matrix.C index 7de050fc9e7a045faa213120de553582998f1030..d27013e8aeca8d6d7d9113112bfb00630a804fc0 100644 --- a/src/OpenFOAM/matrices/Matrix/Matrix.C +++ b/src/OpenFOAM/matrices/Matrix/Matrix.C @@ -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) { diff --git a/src/OpenFOAM/matrices/Matrix/Matrix.H b/src/OpenFOAM/matrices/Matrix/Matrix.H index 24eb0bd7e6bbee218223ecece66ec813086416bc..c11d7a27ec0f544a4abe26526f2ea608dab4f53c 100644 --- a/src/OpenFOAM/matrices/Matrix/Matrix.H +++ b/src/OpenFOAM/matrices/Matrix/Matrix.H @@ -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