Commit 9149b357 authored by Mark Olesen's avatar Mark Olesen Committed by Andrew Heather
Browse files

ENH: PtrList and PtrListOps improvements

- PtrDynList support for move append list:
  can be used to concatenate pointer lists into a single one

- include resize in PtrDynList squeezeNull as being a natural
  combination

- support sorting operations for pointer lists (PtrListOps)
parent c2f59af0
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011 OpenFOAM Foundation
......@@ -36,6 +36,7 @@ Description
#include "SLPtrList.H"
#include "plane.H"
#include "DynamicList.H"
#include "PtrListOps.H"
using namespace Foam;
......@@ -598,6 +599,39 @@ int main(int argc, char *argv[])
Info<<"After pruning nullptr entries" << endl;
report(Info, dynPlanes, true);
{
PtrDynList<plane> dynPlanes2;
dynPlanes2.append(new plane(vector::one, vector::one));
dynPlanes2.append(new plane(vector(1,2,3), vector::one));
dynPlanes2.append(nullptr);
dynPlanes2.set(6, new plane(vector(2,2,1), vector::one));
dynPlanes2.set(10, new plane(Zero, vector::one));
labelList order;
sortedOrder(dynPlanes2, order);
Info<< "sorted order: " << flatOutput(order) << nl;
sortedOrder(dynPlanes2, order, PtrListOps::greater<plane>(dynPlanes2));
Info<< "sorted order: " << flatOutput(order) << nl;
sort(dynPlanes2);
// dynPlanes2.squeezeNull();
Info<<"Append" << endl;
report(Info, dynPlanes2, false);
dynPlanes.append(std::move(dynPlanes2));
Info<<"Result" << endl;
report(Info, dynPlanes, false);
Info<<"From" << endl;
report(Info, dynPlanes2, false);
}
Info<<"free()" << endl;
dynPlanes.free();
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2015 OpenFOAM Foundation
......@@ -26,6 +26,7 @@ License
\*---------------------------------------------------------------------------*/
#include "ListOps.H"
#include <numeric>
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
......@@ -159,4 +160,10 @@ void Foam::inplaceReorder
}
void Foam::ListOps::identity(labelList& map, label start)
{
std::iota(map.begin(), map.end(), start);
}
// ************************************************************************* //
......@@ -584,6 +584,11 @@ struct greater
};
//- Set identity map with (map[i] == i)
// Optionally with an alternative start index, so that (map[i] == i+start)
void identity(labelList& map, label start=0);
//- Find index of the first occurrence that satisfies the predicate.
// When start is specified, any occurrences before start are ignored.
// Linear search.
......
......@@ -349,10 +349,7 @@ void Foam::sortedOrder
order.resize(len);
}
for (label i=0; i < len; ++i)
{
order[i] = i; // identity
}
ListOps::identity(order);
Foam::stableSort(order, comp);
}
......
......@@ -137,15 +137,27 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink();
//- Squeeze out intermediate nullptr entries in the list of pointers
//- and adjust the addressable size accordingly.
// \return the number of non-null entries
inline label squeezeNull();
//- Append an element to the end of the list
inline void append(T* ptr);
//- Append an element to the end of the list
//- Move append an element to the end of the list
inline void append(const autoPtr<T>& aptr);
//- Append an element to the end of the list
//- Move or clone append a tmp to the end of the list
inline void append(const tmp<T>& tptr);
//- Move append another list to the end of this list.
inline void append(PtrList<T>&& other);
//- Move append another list to the end of this list.
template<int AnySizeMin>
inline void append(PtrDynList<T, AnySizeMin>&& other);
//- Remove and return the top element
inline autoPtr<T> remove();
......
......@@ -216,6 +216,15 @@ inline void Foam::PtrDynList<T, SizeMin>::shrink()
}
template<class T, int SizeMin>
inline Foam::label Foam::PtrDynList<T, SizeMin>::squeezeNull()
{
const label newLen = UPtrList<T>::squeezeNull();
resize(newLen);
return newLen;
}
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::append(T* ptr)
{
......@@ -228,14 +237,52 @@ inline void Foam::PtrDynList<T, SizeMin>::append(T* ptr)
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::append(const autoPtr<T>& aptr)
{
return this->append(const_cast<autoPtr<T>&>(aptr).release());
this->append(const_cast<autoPtr<T>&>(aptr).release());
}
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::append(const tmp<T>& tptr)
{
return this->append(tptr.ptr());
this->append(tptr.ptr());
}
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::append(PtrList<T>&& other)
{
const label idx = this->size();
const label len = other.size();
resize(idx + len);
for (label i=0; i < len; ++i)
{
set(idx + i, other.release(i)); // moves pointer
}
other.clear();
}
template<class T, int SizeMin>
template<int AnySizeMin>
inline void Foam::PtrDynList<T, SizeMin>::append
(
PtrDynList<T, AnySizeMin>&& other
)
{
const label idx = this->size();
const label len = other.size();
resize(idx + len);
for (label i=0; i < len; ++i)
{
set(idx + i, other.release(i)); // moves pointer
}
other.clearStorage(); // Ensure capacity=0
}
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -45,6 +45,25 @@ Foam::label Foam::Detail::PtrListDetail<T>::count() const
}
template<class T>
Foam::label Foam::Detail::PtrListDetail<T>::findNull() const
{
label idx = 0;
for (const T* ptr : *this)
{
if (!ptr)
{
return idx;
}
++idx;
}
return -1;
}
template<class T>
void Foam::Detail::PtrListDetail<T>::free()
{
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2018-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -86,6 +86,9 @@ public:
//- Return the count of non-nullptr entries
label count() const;
//- Locate the first null entry, -1 if there are not any
label findNull() const;
//- Delete the allocated entries, but retain the list size.
void free();
......
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
InNamespace
Foam
Description
Functions to operate on Pointer Lists.
Namespace
Foam::PtrListOps
Description
Various utility functions to operate on Pointer Lists.
SourceFiles
PtrListOpsTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef PtrListOps_H
#define PtrListOps_H
#include "PtrList.H"
#include "ListOps.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
//- Generate (stable) sort order for the list
template<class T>
void sortedOrder(const UPtrList<T>& input, 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,
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);
/*---------------------------------------------------------------------------*\
Namespace PtrListOps Declaration
\*---------------------------------------------------------------------------*/
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;
}
};
} // End namespace ListOps
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "PtrListOpsTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
\*---------------------------------------------------------------------------*/
#include "PtrListOps.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
template<class T>
void Foam::sortedOrder
(
const UPtrList<T>& input,
labelList& order
)
{
sortedOrder(input, order, typename PtrListOps::less<T>(input));
}
template<class T, class ListComparePredicate>
void Foam::sortedOrder
(
const UPtrList<T>& input,
labelList& order,
const ListComparePredicate& comp
)
{
const label len = input.size();
// List lengths must be identical
if (order.size() != len)
{
// Avoid copying elements, they are overwritten anyhow
order.clear();
order.resize(len);
}
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
}
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
}
template<class T>
void Foam::shuffle(UPtrList<T>& list)
{
labelList order = identity(list.size());
Foam::shuffle(order);
list.sortOrder(order, false); // false = allow nullptr
}
// ************************************************************************* //
......@@ -65,7 +65,11 @@ Foam::label Foam::UPtrList<T>::squeezeNull()
template<class T>
void Foam::UPtrList<T>::reorder(const labelUList& oldToNew)
void Foam::UPtrList<T>::reorder
(
const labelUList& oldToNew,
const bool testNull
)
{
const label len = this->size();
......@@ -97,19 +101,82 @@ void Foam::UPtrList<T>::reorder(const labelUList& oldToNew)
{
FatalErrorInFunction
<< "reorder map is not unique; element " << idx
<< " already set for type " << typeid(T).name()
<< " already used for type " << typeid(T).name()
<< abort(FatalError);
}
newList[idx] = ptrs_[i];
}
// Verify that all pointers were indeed set
if (testNull)
{
const label idx = newList.findNull();
if (idx >= 0)
{
FatalErrorInFunction
<< "Element " << idx << " not set after reordering." << nl
<< abort(FatalError);
}
}
ptrs_.transfer(newList);
}
template<class T>
void Foam::UPtrList<T>::sortOrder
(
const labelUList& order,
const bool testNull
)
{
const label len = this->size();
if (order.size() != len)
{
FatalErrorInFunction
<< "Size of map (" << order.size()
<< ") not equal to list size (" << len
<< ") for type " << typeid(T).name() << nl
<< abort(FatalError);
}
Detail::PtrListDetail<T> newList(len);
Detail::PtrListDetail<T> guard(len);
for (label i=0; i<len; ++i)
{
if (!newList[i])
const label idx = order[i];
if (idx < 0 || idx >= len)
{
FatalErrorInFunction
<< "Illegal index " << idx << nl
<< "Valid indices are [0," << len << ") for type "
<< typeid(T).name() << nl
<< abort(FatalError);
}
if (guard[idx])
{
FatalErrorInFunction
<< "order map is not unique; element " << idx
<< " already used for type " << typeid(T).name()
<< abort(FatalError);
}
guard[idx] = ptrs_[idx];
newList[i] = ptrs_[idx];
}
// Verify that all pointers were indeed set