From d68902f4a735417f9ee996835880aa00aafb93ad Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Mon, 9 May 2022 11:48:23 +0200 Subject: [PATCH] ENH: relocate Foam::sort from PtrListOps to UPtrList.H - can sort directly without ListOps or other intermediates (eg labelList order). - PtrListOps::less/greater wrappers -> UPtrList::less/greater --- applications/test/PtrList/Test-PtrList.C | 163 ++++++++++-------- .../PtrLists/PtrListDetail/PtrListDetail.C | 3 + .../PtrLists/PtrListDetail/PtrListDetail.H | 9 +- .../PtrLists/PtrListDetail/PtrListDetailI.H | 14 ++ .../PtrLists/PtrListOps/PtrListOps.H | 66 +------ .../PtrLists/PtrListOps/PtrListOpsTemplates.C | 48 ++---- .../containers/PtrLists/UPtrList/UPtrList.C | 84 ++++----- .../containers/PtrLists/UPtrList/UPtrList.H | 113 ++++++++++-- .../containers/PtrLists/UPtrList/UPtrListI.H | 7 + 9 files changed, 294 insertions(+), 213 deletions(-) diff --git a/applications/test/PtrList/Test-PtrList.C b/applications/test/PtrList/Test-PtrList.C index 488618e0b37..a8cf8686afb 100644 --- a/applications/test/PtrList/Test-PtrList.C +++ b/applications/test/PtrList/Test-PtrList.C @@ -59,7 +59,7 @@ public: ~Scalar() { - Info<<"delete Scalar: " << data_ << endl; + Info<< "delete Scalar: " << data_ << endl; } const scalar& value() const @@ -324,7 +324,7 @@ int main(int argc, char *argv[]) list1.set(i, new Scalar(1.3*i)); } - Info<<"Emplace set " << list2.size() << " values" << nl; + Info<< "Emplace set " << list2.size() << " values" << nl; forAll(list2, i) { list2.emplace(i, (10 + 1.3*i)); @@ -338,9 +338,9 @@ int main(int argc, char *argv[]) Info<< nl - <<"list1: " << list1 << nl - <<"list2: " << list2 << nl - <<"list-appended: " << listApp << endl; + << "list1: " << list1 << nl + << "list2: " << list2 << nl + << "list-appended: " << listApp << endl; // Release values @@ -357,27 +357,27 @@ int main(int argc, char *argv[]) } } - Info<<"Released pointers from"; + Info<< "Released pointers from"; print(Info, listApp) << nl; - Info<<"Into plain list of pointers"; + Info<< "Into plain list of pointers"; print(Info, ptrs) << nl; PtrDynList<Scalar> newlist1(ptrs); - Info<<"Constructed from plain list of pointers"; + Info<< "Constructed from plain list of pointers"; print(Info, ptrs) << nl; print(Info, newlist1) << nl; } - Info<<"indirectly delete some items via set(.., nullptr) :" << endl; + Info<< "indirectly delete some items via set(.., nullptr) :" << endl; for (label i = 2; i < 5; i++) { list1.set(i, nullptr); } - Info<<"release some items:" << endl; + Info<< "release some items:" << endl; for (label i = -2; i < 5; i++) { @@ -389,31 +389,31 @@ int main(int argc, char *argv[]) } } - Info<<"list1: "; + Info<< "list1: "; print(Info, list1) << nl; list1.resize(list1.squeezeNull()); - Info<<"squeezed null: "; + Info<< "squeezed null: "; print(Info, list1) << nl; - Info<<"transfer list2 -> list1:" << endl; + Info<< "transfer list2 -> list1:" << endl; list1.transfer(list2); - Info<<"list1: " << list1 << nl - <<"list2: " << list2 << endl; + Info<< "list1: " << list1 << nl + << "list2: " << list2 << endl; - Info<<"indirectly delete some items via setSize :" << endl; + Info<< "indirectly delete some items via setSize :" << endl; list1.setSize(4); - Info<<"list1: " << list1 << endl; + Info<< "list1: " << list1 << endl; { PtrList<Scalar> list1a(list1, false); - Info<<"Clone constructed" << endl; - Info<<"in: " << list1 << nl - <<"out: " << list1a << nl - <<"addresses:" << nl; + Info<< "Clone constructed" << endl; + Info<< "in: " << list1 << nl + << "out: " << list1a << nl + << "addresses:" << nl; printAddr(Info, list1); printAddr(Info, list1a); Info<<"values:" << nl; @@ -423,112 +423,112 @@ int main(int argc, char *argv[]) { auto* ptr = &(list1a.first()); list1a.set(0, ptr); - Info<<"values:" << nl; + Info<< "values:" << nl; print(Info, list1a); } PtrList<Scalar> list1b(list1a, true); - Info<<"Reuse constructed" << endl; - Info<<"in: " << list1a << nl - <<"out: " << list1b << nl - <<"addresses:" << nl; + Info<< "Reuse constructed" << endl; + Info<< "in: " << list1a << nl + << "out: " << list1b << nl + << "addresses:" << nl; printAddr(Info, list1a); printAddr(Info, list1b); PtrList<Scalar> list1c(list1b.clone()); - Info<<"Explicit clone()" << endl; - Info<<"in: " << list1b << nl - <<"out: " << list1c << nl - <<"addresses:" << nl; + Info<< "Explicit clone()" << endl; + Info<< "in: " << list1b << nl + << "out: " << list1c << nl + << "addresses:" << nl; printAddr(Info, list1b); printAddr(Info, list1c); } PtrList<Scalar> list3(std::move(list1)); - Info<<"Move constructed" << endl; + Info<< "Move constructed" << endl; - Info<<"list1: " << list1 << nl - <<"list2: " << list2 << nl - <<"list3: " << list3 << endl; + Info<< "list1: " << list1 << nl + << "list2: " << list2 << nl + << "list3: " << list3 << endl; - Info<<"Move construct:" << endl; + Info<< "Move construct:" << endl; PtrList<Scalar> list4(std::move(list3)); - Info<<"list3: " << list3 << nl - <<"list4: " << list4 << endl; + Info<< "list3: " << list3 << nl + << "list4: " << list4 << endl; - Info<<"Move assign:" << endl; + Info<< "Move assign:" << endl; list3 = std::move(list4); - Info<<"list3: " << list3 << nl - <<"list4: " << list4 << endl; + Info<< "list3: " << list3 << nl + << "list4: " << list4 << endl; - Info<<"UPtrList from PtrList" << nl; + Info<< "UPtrList from PtrList" << nl; UPtrList<Scalar> ulist1(list3); - Info<<"ulist1: " << ulist1 << nl; - Info<<"PtrList addresses:"; + Info<< "ulist1: " << ulist1 << nl; + Info<< "PtrList addresses:"; printAddr(Info, list3); - Info<<"UPtrList addresses:"; + Info<< "UPtrList addresses:"; printAddr(Info, ulist1); Info<< nl; { - Info<<"UPtrList(const UPtrList&)" << nl; + Info<< "UPtrList(const UPtrList&)" << nl; const UPtrList<Scalar>& cref = ulist1; UPtrList<Scalar> ulist1cp(cref); - Info<<"src addresses:"; + Info<< "src addresses:"; printAddr(Info, cref); - Info<<"dst addresses:"; + Info<< "dst addresses:"; printAddr(Info, ulist1cp); Info<< nl; } - Info<<"Move construct:" << endl; + Info<< "Move construct:" << endl; UPtrList<Scalar> ulist2(std::move(ulist1)); - Info<<"ulist1: " << ulist1 << nl - <<"ulist2: " << ulist2 << nl; + Info<< "ulist1: " << ulist1 << nl + << "ulist2: " << ulist2 << nl; - Info<<"Copy assign:" << endl; + Info<< "Copy assign:" << endl; ulist1 = ulist2; - Info<<"ulist1: " << ulist1 << nl - <<"ulist2: " << ulist2 << nl; + Info<< "ulist1: " << ulist1 << nl + << "ulist2: " << ulist2 << nl; - Info<<"Move assign:" << endl; + Info<< "Move assign:" << endl; ulist1 = std::move(ulist2); - Info<<"ulist1: " << ulist1 << nl - <<"ulist2: " << ulist2 << nl; + Info<< "ulist1: " << ulist1 << nl + << "ulist2: " << ulist2 << nl; // Test iterator random access { auto iter1 = ulist1.begin(); auto iter2 = iter1 + 3; - Info<<"begin:" << *iter1 << " (+3):" << *iter2 << nl; + Info<< "begin:" << *iter1 << " (+3):" << *iter2 << nl; Info<< "diff= " << (iter1 - iter2) << nl; Info<< "iter[2]=" << iter1[2] << nl; Info<< "iter1 < iter2 : " << (iter1 < iter2) << nl; Info<< "iter1 >= iter2 : " << (iter1 >= iter2) << nl; - Info<<"->" << iter1->value() << nl; - Info<<"*" << (*iter1).value() << nl; - Info<<"()" << iter1().value() << nl; + Info<< "->" << iter1->value() << nl; + Info<< "*" << (*iter1).value() << nl; + Info<< "()" << iter1().value() << nl; } PtrList<plane> planes; @@ -541,7 +541,7 @@ int main(int argc, char *argv[]) Info<< " plane " << p << endl; } - Info<<"Testing PtrDynList" << nl; + Info<< "Testing PtrDynList" << nl; PtrDynList<plane> dynPlanes; @@ -566,10 +566,10 @@ int main(int argc, char *argv[]) report(Info, dynPlanes, true); dynPlanes.clear(); - Info<<"clear()" << nl; + Info<< "clear()" << nl; report(Info, dynPlanes); - Info<<"now append again" << endl; + Info<< "now append again" << endl; { dynPlanes.append(new plane(vector::one, vector::one)); dynPlanes.append(new plane(vector(1,2,3), vector::one)); @@ -597,13 +597,13 @@ int main(int argc, char *argv[]) stdPlanes.resize(stdPlanes.squeezeNull()); - Info<<"After pruning nullptr entries" << endl; + Info<< "After pruning nullptr entries" << endl; printAddr(Info, stdPlanes); } dynPlanes.resize(dynPlanes.squeezeNull()); - Info<<"After pruning nullptr entries" << endl; + Info<< "After pruning nullptr entries" << endl; report(Info, dynPlanes, true); @@ -621,25 +621,48 @@ int main(int argc, char *argv[]) sortedOrder(dynPlanes2, order); Info<< "sorted order: " << flatOutput(order) << nl; - sortedOrder(dynPlanes2, order, PtrListOps::greater<plane>(dynPlanes2)); + sortedOrder(dynPlanes2, order, UPtrList<plane>::greater(dynPlanes2)); Info<< "sorted order: " << flatOutput(order) << nl; + // Shuffle + shuffle(dynPlanes2); + Info<< "Shuffled" << endl; + report(Info, dynPlanes2, false); + + // Reverse sort + sort + ( + dynPlanes2, + [](const plane& a, const plane& b) { return (b < a); } + ); + Info<< "Reverse sorted" << endl; + report(Info, dynPlanes2, false); + + // Forward sort sort(dynPlanes2); + Info<< "Sorted" << endl; + report(Info, dynPlanes2, false); + + // Reverse pointer list - not yet available or needed! + /// reverse(dynPlanes2); + /// Info<< "Reversed" << endl; + /// report(Info, dynPlanes2, false); + // dynPlanes2.squeezeNull(); - Info<<"Append" << endl; + Info<< "Append" << endl; report(Info, dynPlanes2, false); dynPlanes.append(std::move(dynPlanes2)); - Info<<"Result" << endl; + Info<< "Result" << endl; report(Info, dynPlanes, false); - Info<<"From" << endl; + Info<< "From" << endl; report(Info, dynPlanes2, false); } - Info<<"free()" << endl; + Info<< "free()" << endl; dynPlanes.free(); report(Info, dynPlanes, true); diff --git a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C index a72ec9461a6..a71e0f4a198 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C +++ b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.C @@ -50,6 +50,9 @@ Foam::label Foam::Detail::PtrListDetail<T>::count() const template<class T> Foam::label Foam::Detail::PtrListDetail<T>::findNull() const { + // Same as List<T*>::find(nullptr); + // except perhaps without pointer ambiguities... + label idx = 0; for (const T* ptr : *this) diff --git a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H index 8e7ccf43722..70b4637c3b1 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H +++ b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetail.H @@ -42,8 +42,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef PtrListDetail_H -#define PtrListDetail_H +#ifndef Foam_PtrListDetail_H +#define Foam_PtrListDetail_H #include "List.H" @@ -92,9 +92,12 @@ public: //- Return the count of non-nullptr entries label count() const; - //- Locate the first null entry, -1 if there are not any + //- Locate the first null entry, -1 if there are none (or empty list) label findNull() const; + //- FatalError if any null exists in the list + inline void checkNonNull() const; + //- Assign all pointers to nullptr, without deleting. void setNull(); diff --git a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetailI.H b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetailI.H index a8777f39ad9..7b5425c1f48 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetailI.H +++ b/src/OpenFOAM/containers/PtrLists/PtrListDetail/PtrListDetailI.H @@ -109,6 +109,20 @@ inline void Foam::Detail::PtrListDetail<T>::resize(const label newLen) } +template<class T> +inline void Foam::Detail::PtrListDetail<T>::checkNonNull() const +{ + const label idx = this->findNull(); + + if (idx >= 0) + { + FatalErrorInFunction + << "Element " << idx << " is null" << nl + << abort(FatalError); + } +} + + // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template<class T> diff --git a/src/OpenFOAM/containers/PtrLists/PtrListOps/PtrListOps.H b/src/OpenFOAM/containers/PtrLists/PtrListOps/PtrListOps.H index 8bd574602d3..bdc9df5f717 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListOps/PtrListOps.H +++ b/src/OpenFOAM/containers/PtrLists/PtrListOps/PtrListOps.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019-2021 OpenCFD Ltd. + Copyright (C) 2019-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,8 +40,8 @@ SourceFiles \*---------------------------------------------------------------------------*/ -#ifndef PtrListOps_H -#define PtrListOps_H +#ifndef Foam_PtrListOps_H +#define Foam_PtrListOps_H #include "predicates.H" #include "PtrList.H" @@ -54,31 +54,23 @@ namespace Foam //- Return (stable) sort order for the list template<class T> -labelList sortedOrder(const UPtrList<T>& input); +labelList sortedOrder(const UPtrList<T>& list); //- Generate (stable) sort order for the list template<class T> -void sortedOrder(const UPtrList<T>& input, labelList& order); +void sortedOrder(const UPtrList<T>& list, labelList& order); //- Generate (stable) sort order for the list, //- using the specified list compare predicate template<class T, class ListComparePredicate> void sortedOrder ( - const UPtrList<T>& input, + const UPtrList<T>& list, labelList& order, const ListComparePredicate& comp ); -//- Inplace (stable) sorting of pointer list. -template<class T> -void sort(UPtrList<T>& list); - -//- Inplace (stable) sorting of pointer list. -template<class T, class Compare> -void sort(UPtrList<T>& list, const Compare& comp); - //- Inplace shuffle of pointer list. template<class T> void shuffle(UPtrList<T>& list); @@ -91,52 +83,6 @@ void shuffle(UPtrList<T>& list); namespace PtrListOps { -// Public Classes - -//- A UPtrList compare binary predicate for normal sort. -// Null entries sort to the end -template<class T> -struct less -{ - const UPtrList<T>& values; - - less(const UPtrList<T>& list) - : - values(list) - {} - - bool operator()(const label a, const label b) const - { - const T* const ptr1 = values(a); - const T* const ptr2 = values(b); - - return (ptr1 && ptr2) ? (*ptr1 < *ptr2) : !ptr2; - } -}; - - -//- A UPtrList compare binary predicate for reverse sort. -// Null entries sort to the end -template<class T> -struct greater -{ - const UPtrList<T>& values; - - greater(const UPtrList<T>& list) - : - values(list) - {} - - bool operator()(const label a, const label b) const - { - const T* const ptr1 = values(a); - const T* const ptr2 = values(b); - - return (ptr1 && ptr2) ? (*ptr2 < *ptr1) : !ptr2; - } -}; - - //- List of values generated by applying the access operation //- to each list item. // diff --git a/src/OpenFOAM/containers/PtrLists/PtrListOps/PtrListOpsTemplates.C b/src/OpenFOAM/containers/PtrLists/PtrListOps/PtrListOpsTemplates.C index aec159d25f7..85d6fedf70f 100644 --- a/src/OpenFOAM/containers/PtrLists/PtrListOps/PtrListOpsTemplates.C +++ b/src/OpenFOAM/containers/PtrLists/PtrListOps/PtrListOpsTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019-2021 OpenCFD Ltd. + Copyright (C) 2019-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -32,11 +32,11 @@ License template<class T> Foam::labelList Foam::sortedOrder ( - const UPtrList<T>& input + const UPtrList<T>& list ) { labelList order; - sortedOrder(input, order, typename PtrListOps::less<T>(input)); + Foam::sortedOrder(list, order, typename UPtrList<T>::less(list)); return order; } @@ -44,59 +44,49 @@ Foam::labelList Foam::sortedOrder template<class T> void Foam::sortedOrder ( - const UPtrList<T>& input, + const UPtrList<T>& list, labelList& order ) { - sortedOrder(input, order, typename PtrListOps::less<T>(input)); + Foam::sortedOrder(list, order, typename UPtrList<T>::less(list)); } template<class T, class ListComparePredicate> void Foam::sortedOrder ( - const UPtrList<T>& input, + const UPtrList<T>& list, labelList& order, const ListComparePredicate& comp ) { // List lengths must be identical. Old content is overwritten - order.resize_nocopy(input.size()); - - ListOps::identity(order); - - Foam::stableSort(order, comp); -} - - -template<class T> -void Foam::sort(UPtrList<T>& list) -{ - labelList order; - sortedOrder(list, order); - list.sortOrder(order, false); // false = allow nullptr -} + order.resize_nocopy(list.size()); + // Same as std::iota and ListOps::identity + label value = 0; + for (label& item : order) + { + item = value; + ++value; + } -template<class T, class Compare> -void Foam::sort(UPtrList<T>& list, const Compare& comp) -{ - labelList order; - sortedOrder(list, order, comp); - list.sortOrder(order, false); // false = allow nullptr + std::stable_sort(order.begin(), order.end(), comp); } template<class T> void Foam::shuffle(UPtrList<T>& list) { + // Cannot use std::shuffle directly since that would dereference + // the list entries, which may contain null pointers. + // The alternative would be to expose the pointer details (a bit ugly). labelList order(identity(list.size())); Foam::shuffle(order); - list.sortOrder(order, false); // false = allow nullptr + list.sortOrder(order, false); // false = no nullptr check } - // Templated implementation for types(), names(), etc - file-scope template<class ReturnType, class T, class AccessOp> Foam::List<ReturnType> Foam::PtrListOps::get diff --git a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.C b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.C index 476054ef504..9ae4fcdec70 100644 --- a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.C +++ b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2015-2019 OpenCFD Ltd. + Copyright (C) 2015-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -66,11 +66,7 @@ Foam::label Foam::UPtrList<T>::squeezeNull() template<class T> -void Foam::UPtrList<T>::reorder -( - const labelUList& oldToNew, - const bool testNull -) +void Foam::UPtrList<T>::reorder(const labelUList& oldToNew, const bool check) { const label len = this->size(); @@ -87,37 +83,31 @@ void Foam::UPtrList<T>::reorder for (label i=0; i<len; ++i) { - const label idx = oldToNew[i]; + const label newIdx = oldToNew[i]; - if (idx < 0 || idx >= len) + if (newIdx < 0 || newIdx >= len) { FatalErrorInFunction - << "Illegal index " << idx << nl + << "Illegal index " << newIdx << nl << "Valid indices are [0," << len << ") for type " << typeid(T).name() << nl << abort(FatalError); } - if (newList[idx]) + if (newList[newIdx]) { FatalErrorInFunction - << "reorder map is not unique; element " << idx + << "reorder map is not unique; element " << newIdx << " already used for type " << typeid(T).name() << abort(FatalError); } - newList[idx] = ptrs_[i]; + newList[newIdx] = ptrs_[i]; } - // Verify that all pointers were indeed set - if (testNull) + // Verify all pointers were indeed set + if (check) { - const label idx = newList.findNull(); - if (idx >= 0) - { - FatalErrorInFunction - << "Element " << idx << " not set after reordering." << nl - << abort(FatalError); - } + newList.checkNonNull(); } ptrs_.transfer(newList); @@ -125,11 +115,7 @@ void Foam::UPtrList<T>::reorder template<class T> -void Foam::UPtrList<T>::sortOrder -( - const labelUList& order, - const bool testNull -) +void Foam::UPtrList<T>::sortOrder(const labelUList& order, const bool check) { const label len = this->size(); @@ -147,39 +133,33 @@ void Foam::UPtrList<T>::sortOrder for (label i=0; i<len; ++i) { - const label idx = order[i]; + const label oldIdx = order[i]; - if (idx < 0 || idx >= len) + if (oldIdx < 0 || oldIdx >= len) { FatalErrorInFunction - << "Illegal index " << idx << nl + << "Illegal index " << oldIdx << nl << "Valid indices are [0," << len << ") for type " << typeid(T).name() << nl << abort(FatalError); } - if (guard[idx]) + if (guard[oldIdx]) { FatalErrorInFunction - << "order map is not unique; element " << idx + << "order map is not unique; element " << oldIdx << " already used for type " << typeid(T).name() << abort(FatalError); } - guard[idx] = ptrs_[idx]; - newList[i] = ptrs_[idx]; + guard[oldIdx] = ptrs_[oldIdx]; + newList[i] = ptrs_[oldIdx]; } // Verify that all pointers were indeed set - if (testNull) + if (check) { - const label idx = newList.findNull(); - if (idx >= 0) - { - FatalErrorInFunction - << "Element " << idx << " not set after reordering." << nl - << abort(FatalError); - } + newList.checkNonNull(); } ptrs_.transfer(newList); @@ -195,4 +175,26 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const UPtrList<T>& list) } +// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // + +template<class T, class Compare> +void Foam::sort(UPtrList<T>& list, const Compare& comp) +{ + std::stable_sort + ( + list.begin_ptr(), + list.end_ptr(), + typename UPtrList<T>::template value_compare<Compare>(comp) + ); +} + + +template<class T> +void Foam::sort(UPtrList<T>& list) +{ + // ie, lessOp<T>() or std::less<T>() + Foam::sort(list, [](const T& a, const T& b) { return (a < b); }); +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H index 0cf86426268..4f88822e985 100644 --- a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H +++ b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrList.H @@ -110,6 +110,72 @@ public: class const_iterator; + // Public Classes + + //- A wrapper for a binary comparison of values that interjects + //- pointer dereferencing with null pointer guards. + // It will also sort any null pointers to the end + // (eg, rubbish that can be truncated) + template<class Compare> + struct value_compare + { + const Compare& comp; + + value_compare(const Compare& cmp) + : + comp(cmp) + {} + + //- Compare dereferenced pointers + bool operator()(const T* const a, const T* const b) const + { + return (a && b) ? comp(*a, *b) : bool(a); + } + }; + + //- A UPtrList compare binary predicate for normal sort order. + //- Null entries (if any) sort to the end. + struct less + { + const UPtrList<T>& values; + + less(const UPtrList<T>& list) + : + values(list) + {} + + //- Compare dereferenced pointer locations for normal sort. + bool operator()(const label ai, const label bi) const + { + const T* const a = values.get(ai); + const T* const b = values.get(bi); + + return (a && b) ? (*a < *b) : bool(a); + } + }; + + //- A UPtrList compare binary predicate for reverse sort order. + // Null entries (if any) sort to the end. + struct greater + { + const UPtrList<T>& values; + + greater(const UPtrList<T>& list) + : + values(list) + {} + + //- Compare dereferenced pointer locations for reverse sort + bool operator()(const label ai, const label bi) const + { + const T* const a = values.get(ai); + const T* const b = values.get(bi); + + return (a && b) ? (*b < *a) : bool(b); + } + }; + + // Constructors //- Default construct @@ -215,13 +281,19 @@ public: //- Reorder elements. //- Reordering must be unique (ie, shuffle). - // Optionally verify that all pointers have been set. - void reorder(const labelUList& oldToNew, const bool testNull = true); + // Optionally check that all pointers have been set. + void reorder(const labelUList& oldToNew, const bool check = false); //- Reorder elements according to new order mapping (newToOld). //- Reordering must be unique (ie, shuffle). - // Optionally verify that all pointers have been set. - void sortOrder(const labelUList& order, const bool testNull = true); + // Optionally check that all pointers have been set. + void sortOrder(const labelUList& order, const bool check = false); + + + // Checks + + //- Check and raise FatalError if any nullptr exists in the list + inline void checkNonNull() const; // Member Operators @@ -362,22 +434,29 @@ public: }; - //- Return an iterator to begin traversing the UPtrList + //- Iterator to begin of raw pointers traversal (use with caution) + T** begin_ptr() noexcept { return ptrs_.begin(); } + + //- Iterator beyond end of raw pointers traversal (use with caution) + T** end_ptr() noexcept { return ptrs_.end(); } + + + //- Return an iterator to begin of UPtrList traversal inline iterator begin() noexcept; - //- Return an iterator to end traversing the UPtrList + //- Return iterator beyond end of UPtrList traversal inline iterator end() noexcept; - //- Return an const_iterator to begin traversing the UPtrList + //- Return const_iterator to begin of UPtrList traversal inline const_iterator cbegin() const noexcept; - //- Return an const_iterator to end traversing the UPtrList + //- Return const_iterator beyond end of UPtrList traversal inline const_iterator cend() const noexcept; - //- Return an const_iterator to begin traversing the UPtrList + //- Return const_iterator to begin of UPtrList traversal inline const_iterator begin() const noexcept; - //- Return an const_iterator to end traversing the UPtrList + //- Return const_iterator beyond end of UPtrList traversal inline const_iterator end() const noexcept; @@ -392,6 +471,20 @@ public: }; +// * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * // + +//- Inplace (stable) sorting of pointer list. +template<class T> +void sort(UPtrList<T>& list); + +//- Inplace (stable) sorting of pointer list using given comparator, +//- which compares objects, not pointers. +// This sort function includes null pointer guards and will also sort +// any null pointers to the end (eg, rubbish that can be truncated) +template<class T, class Compare> +void sort(UPtrList<T>& list, const Compare& comp); + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H index 0bc1262089c..1716ddf253d 100644 --- a/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H +++ b/src/OpenFOAM/containers/PtrLists/UPtrList/UPtrListI.H @@ -215,6 +215,13 @@ inline T* Foam::UPtrList<T>::set(const label i, T* ptr) } +template<class T> +inline void Foam::UPtrList<T>::checkNonNull() const +{ + ptrs_.checkNonNull(); +} + + // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template<class T> -- GitLab