Commit c3403761 authored by Mark Olesen's avatar Mark Olesen

ENH: generalize indirect lists and support new types

- use an IndirectListBase class for various indirect list types.

- new SortList type

  In some places the SortList can be used as a lightweight alternative
  to SortableList to have the convenience of bundling data and sort
  indices together, but while operating on existing data lists.
  In other situations, it can be useful as an alternative to
  sortedOrder.  For example,

        pointField points = ...;

        labelList order;
        sortedOrder(points, order);

        forAll(order, i)
        {
            points[order[i]] = ...;
        }

   Can be replaced with the following (with the same memory overhead)

        pointField points = ...;

        SortList<point> sortedPoints(points);

        for (point& pt : sortedPoints)
        {
            pt = ...;
        }

- new SliceList type (#1220), which can be used for stride-based
  addressing into existing lists
parent 853c5503
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010, 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2010-2010, 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011 OpenFOAM Foundation
......@@ -27,19 +27,21 @@ Description
\*---------------------------------------------------------------------------*/
#include "IndirectList.H"
#include "IOstreams.H"
#include "argList.H"
#include "Fstream.H"
#include "ListOps.H"
#include "IndirectList.H"
#include "labelIndList.H"
#include "argList.H"
#include "SortList.H"
#include "Random.H"
#include <functional>
using namespace Foam;
template<class ListType>
void printInfo(const ListType& lst)
{
Info<< "full: " << flatOutput(lst.completeList()) << nl
Info<< "full: " << flatOutput(lst.values()) << nl
<< "addr: " << flatOutput(lst.addressing()) << nl
<< "list: " << flatOutput(lst) << nl
<< endl;
......@@ -103,7 +105,7 @@ int main(int argc, char *argv[])
inplaceReverseList(addresses);
idl1.resetAddressing(std::move(addresses));
idl1.addressing() = std::move(addresses);
printInfo(idl1);
......@@ -114,10 +116,10 @@ int main(int argc, char *argv[])
printInfo(uidl1);
idl1.resetAddressing(List<label>());
// idl2.resetAddressing(List<label>());
idl1.addressing().clear();
// idl2.addressing().clear();
Info<<"after resetAddressing:" << nl << endl;
Info<<"after reset addressing:" << nl << endl;
printInfo(uidl1);
printInfo(idl1);
......@@ -140,7 +142,7 @@ int main(int argc, char *argv[])
{
if (Pstream::master())
{
Pout<< "full: " << flatOutput(idl3.completeList()) << nl
Pout<< "full: " << flatOutput(idl3.values()) << nl
<< "send: " << flatOutput(idl3) << endl;
for
......@@ -173,6 +175,61 @@ int main(int argc, char *argv[])
Pstream::scatter(barrier);
}
// SortList
{
List<scalar> list1(20);
Random rnd(1234);
for (scalar& val : list1)
{
val = 100 * rnd.sample01<scalar>();
}
// Pick out 1/2 the values and make the negative
for (label i=0; i < list1.size()/2; ++i)
{
label pos = rnd.position(0, list1.size()-1);
list1[pos] = -list1[pos];
}
Info<< nl << "Random list: " << flatOutput(list1) << nl;
SortList<scalar> sorter1(list1);
Info<< nl << "Sort indices: " << flatOutput(sorter1.indices()) << nl;
Info<< nl << "Reverse indices: " << flatOutput(sorter1.indices()) << nl;
sorter1.reverse();
Info<< nl << "Again indices: " << flatOutput(sorter1.indices()) << nl;
sorter1.reverseSort();
Info<< nl << "Reverse indices: " << flatOutput(sorter1.indices()) << nl;
Info<< nl << "Sorted : " << flatOutput(sorter1) << nl;
sorter1.sort(std::greater<scalar>());
SortList<scalar> sorter2(list1, std::greater<scalar>());
sorter2.reverse();
Info<< "sorted: ";
for (const auto& val : sorter2)
{
Info<< ' ' << val;
}
Info<< nl;
sorter2.sort([](scalar a, scalar b) { return mag(a) < mag(b); });
Info<< nl << "Mag sorted: " << flatOutput(sorter2) << nl;
}
Info<< "End\n" << endl;
return 0;
......
......@@ -29,6 +29,9 @@ Description
#include "labelList.H"
#include "FixedList.H"
#include "sliceRange.H"
#include "SliceList.H"
#include "IndirectList.H"
#include "Random.H"
using namespace Foam;
......@@ -128,9 +131,60 @@ int main(int argc, char *argv[])
}
}
// Sliced lists
{
List<scalar> list1(100);
Random rnd(1234);
for (scalar& val : list1)
{
val = 100 * rnd.sample01<scalar>();
}
Info<< nl << "Random list: " << flatOutput(list1) << nl;
SliceList<scalar> slice1(list1, sliceRange(0, 15, 3));
Info<< nl << "slicing with: " << slice1.addressing() << nl;
Info<< nl << "Sliced list: " << flatOutput(slice1) << nl;
for (scalar& val : slice1)
{
val = -val;
}
// Changed list via slice:
Info<< nl << "Changed via slice: " << flatOutput(list1) << nl;
// Some indirect list
IndirectList<scalar> indlist
(
list1,
identity(slice1.size(), list1.size()-slice1.size())
);
Info<< nl << "Indirect slice: " << flatOutput(indlist) << nl;
indlist = 1000;
Info<< nl << "zeroed slice: " << flatOutput(indlist) << nl;
slice1 = indlist;
Info<< nl << "self-copy: " << flatOutput(list1) << nl;
slice1 = 100000;
Info<< nl << "set values: " << flatOutput(slice1) << nl
<< " = " << flatOutput(list1) << nl;
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //
......@@ -47,10 +47,11 @@ Foam::PackedList<Width>::PackedList
template<unsigned Width>
template<class Addr>
Foam::PackedList<Width>::PackedList
(
const PackedList<Width>& list,
const labelUIndList& addr
const IndirectListBase<label, Addr>& addr
)
:
PackedList<Width>(addr.size())
......
......@@ -93,7 +93,7 @@ SourceFiles
#include "BitOps.H"
#include "labelList.H"
#include "UIndirectList.H"
#include "IndirectListBase.H"
#include "InfoProxy.H"
#include "PackedListCore.H"
......@@ -252,7 +252,12 @@ public:
PackedList(const PackedList<Width>& list, const labelUList& addr);
//- Copy construct a subset
PackedList(const PackedList<Width>& list, const labelUIndList& addr);
template<class Addr>
PackedList
(
const PackedList<Width>& list,
const IndirectListBase<label, Addr>& addr
);
//- Copy construct a subset range
PackedList(const PackedList<Width>& list, const labelRange& range);
......@@ -260,8 +265,9 @@ public:
//- Construct from a list of values
inline explicit PackedList(const labelUList& values);
//- Construct from a list of values
inline explicit PackedList(const labelUIndList& values);
//- Construct from a indirect list of values
template<class Addr>
inline explicit PackedList(const IndirectListBase<label, Addr>& values);
//- Clone
inline autoPtr<PackedList<Width>> clone() const;
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010, 2017-2018 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2010, 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
......@@ -242,7 +242,11 @@ inline Foam::PackedList<Width>::PackedList(const labelUList& values)
template<unsigned Width>
inline Foam::PackedList<Width>::PackedList(const labelUIndList& values)
template<class Addr>
inline Foam::PackedList<Width>::PackedList
(
const IndirectListBase<label, Addr>& values
)
:
blocks_(num_blocks(values.size()), 0u),
size_(values.size())
......
......@@ -306,19 +306,6 @@ Foam::bitSet::bitSet(const bitSet& bitset, const labelUList& addr)
}
Foam::bitSet::bitSet(const bitSet& bitset, const labelUIndList& addr)
:
bitSet(addr.size())
{
const label len = addr.size();
for (label i = 0; i < len; ++i)
{
set(i, bitset.get(addr[i]));
}
}
Foam::bitSet::bitSet(const bitSet& bitset, const labelRange& range)
:
bitSet(range.size())
......
......@@ -156,7 +156,12 @@ public:
bitSet(const bitSet& bitset, const labelUList& addr);
//- Copy construct a subset
bitSet(const bitSet& bitset, const labelUIndList& addr);
template<class Addr>
bitSet
(
const bitSet& bitset,
const IndirectListBase<label, Addr>& addr
);
//- Copy construct a subset range
bitSet(const bitSet& bitset, const labelRange& range);
......@@ -170,7 +175,12 @@ public:
//- Construct with given size with all bits set to 0,
//- subsequently add specified locations as 1.
inline bitSet(const label n, const labelUIndList& locations);
template<class Addr>
bitSet
(
const label n,
const IndirectListBase<label, Addr>& locations
);
//- Construct with given size with all bits set to 0,
//- subsequently add specified locations as 1.
......@@ -187,7 +197,8 @@ public:
//- Construct with automatic sizing (filled with 0),
//- and populate with specified locations as 1.
inline explicit bitSet(const labelUIndList& locations);
template<class Addr>
inline explicit bitSet(const IndirectListBase<label, Addr>& locations);
//- Construct with automatic sizing (filled with 0),
//- and populate with specified locations as 1.
......@@ -381,7 +392,8 @@ public:
// Does auto-vivify for non-existent entries.
//
// \return number of locations changed
inline label set(const labelUIndList& locations);
template<class Addr>
inline label set(const IndirectListBase<label, Addr>& locations);
//- Set the listed locations to true.
// Does auto-vivify for non-existent entries.
......@@ -405,7 +417,8 @@ public:
//- Unset the listed locations, never auto-vivifies.
//
// \return number of locations changed
inline label unset(const labelUIndList& locations);
template<class Addr>
inline label unset(const IndirectListBase<label, Addr>& locations);
//- Unset the listed locations, never auto-vivifies.
//
......
......@@ -120,7 +120,12 @@ inline Foam::bitSet::bitSet(const label n, const labelUList& locations)
}
inline Foam::bitSet::bitSet(const label n, const labelUIndList& locations)
template<class Addr>
inline Foam::bitSet::bitSet
(
const label n,
const IndirectListBase<label, Addr>& locations
)
:
bitSet(n)
{
......@@ -148,7 +153,11 @@ inline Foam::bitSet::bitSet(const labelUList& locations)
}
inline Foam::bitSet::bitSet(const labelUIndList& locations)
template<class Addr>
inline Foam::bitSet::bitSet
(
const IndirectListBase<label, Addr>& locations
)
:
bitSet()
{
......@@ -537,7 +546,11 @@ inline Foam::label Foam::bitSet::set(const labelUList& locations)
}
inline Foam::label Foam::bitSet::set(const labelUIndList& locations)
template<class Addr>
inline Foam::label Foam::bitSet::set
(
const IndirectListBase<label, Addr>& locations
)
{
return setMany(locations.begin(), locations.end());
}
......@@ -549,7 +562,11 @@ inline Foam::label Foam::bitSet::unset(const labelUList& locations)
}
inline Foam::label Foam::bitSet::unset(const labelUIndList& locations)
template<class Addr>
inline Foam::label Foam::bitSet::unset
(
const IndirectListBase<label, Addr>& locations
)
{
return unset(locations.begin(), locations.end());
}
......
......@@ -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
......@@ -48,6 +48,25 @@ Foam::bitSet::bitSet(const FixedList<label, N>& locations)
}
template<class Addr>
Foam::bitSet::bitSet
(
const bitSet& bitset,
const IndirectListBase<label, Addr>& addr
)
:
bitSet(addr.size())
{
const label len = addr.size();
for (label i = 0; i < len; ++i)
{
set(i, bitset.get(addr[i]));
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class InputIter>
......
......@@ -84,7 +84,8 @@ Foam::HashSet<Key, Hash>::HashSet(const UList<Key>& list)
template<class Key, class Hash>
Foam::HashSet<Key, Hash>::HashSet(const UIndirectList<Key>& list)
template<class Addr>
Foam::HashSet<Key, Hash>::HashSet(const IndirectListBase<Key, Addr>& list)
:
parent_type(2*list.size())
{
......@@ -177,9 +178,10 @@ inline Foam::label Foam::HashSet<Key, Hash>::insert
template<class Key, class Hash>
template<class Addr>
inline Foam::label Foam::HashSet<Key, Hash>::insert
(
const UIndirectList<Key>& list
const IndirectListBase<Key, Addr>& list
)
{
return insert(list.begin(), list.end());
......@@ -230,9 +232,10 @@ inline Foam::label Foam::HashSet<Key, Hash>::unset
template<class Key, class Hash>
template<class Addr>
inline Foam::label Foam::HashSet<Key, Hash>::unset
(
const UIndirectList<Key>& list
const IndirectListBase<Key, Addr>& list
)
{
return unset(list.begin(), list.end());
......
......@@ -65,7 +65,7 @@ Description
#define HashSet_H
#include "HashTable.H"
#include "UIndirectList.H"
#include "IndirectList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -143,7 +143,8 @@ public:
explicit HashSet(const UList<Key>& list);
//- Construct from an indirect list
explicit HashSet(const UIndirectList<Key>& list);
template<class Addr>
explicit HashSet(const IndirectListBase<Key, Addr>& list);
//- Construct from an initializer list of Key
HashSet(std::initializer_list<Key> list);
......@@ -222,7 +223,8 @@ public:
//- Insert keys from the list of Key
// \return The number of new elements inserted
inline label insert(const UIndirectList<Key>& list);
template<class Addr>
inline label insert(const IndirectListBase<Key, Addr>& list);
//- Same as insert (no value to overwrite)
template<class InputIter>
......@@ -251,7 +253,8 @@ public:
}
//- Same as insert (no value to overwrite)
inline label set(const UIndirectList<Key>& list)
template<class Addr>
inline label set(const IndirectListBase<Key, Addr>& list)
{
return insert(list);
}
......@@ -284,7 +287,8 @@ public:
//- Unset the listed keys - same as erase
// \return The number of items removed
inline label unset(const UIndirectList<Key>& list);
template<class Addr>
inline label unset(const IndirectListBase<Key, Addr>& list);
// STL iterators
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010, 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2010, 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011-2016 OpenFOAM Foundation
......@@ -30,8 +30,7 @@ Description
A List with indirect addressing.
See also
Foam::UIndirectList for a version without any allocation for the
addressing.
Foam::UIndirectList for a version without any addressing allocation.
SourceFiles
IndirectListI.H
......@@ -41,6 +40,7 @@ SourceFiles
#ifndef IndirectList_H
#define IndirectList_H
#include "IndirectListAddressing.H"
#include "UIndirectList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -48,53 +48,6 @@ SourceFiles
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class IndirectListAddressing Declaration
\*---------------------------------------------------------------------------*/
//- A helper class for storing addresses.
class IndirectListAddressing
{
// Private data
//- Storage for the list addressing
List<label> addressing_;
// Private Member Functions
//- No copy construct
IndirectListAddressing(const IndirectListAddressing&) = delete;
//- No copy assignment
void operator=(const IndirectListAddressing&) = delete;
protected:
// Constructors
//- Copy construct from addressing array
inline explicit IndirectListAddressing(const labelUList& addr);
//- Move construct from addressing array
inline explicit IndirectListAddressing(List<label>&& addr);
// Member Functions
//- Return the list addressing
inline const List<label>& addressing() const;
//- Copy reset addressing
inline void resetAddressing(const labelUList& addr);
//- Move reset addressing
inline void resetAddressing(List<label>&& addr);
};
/*---------------------------------------------------------------------------*\
Class IndirectList Declaration
\*---------------------------------------------------------------------------*/
......@@ -102,43 +55,30 @@ protected:
template<class T>
class IndirectList
:
private IndirectListAddressing,
public UIndirectList<T>
private IndirectListAddressing<labelList>,
public UIndirectList<T>
{
// Private Member Functions
//- No copy assignment
void operator=(const IndirectList<T>&) = delete;
//- No copy assignment from UIndirectList
void operator=(const UIndirectList<T>&) = delete;
public:
// Constructors
//- Copy construct addressing, shallow copy values list reference.
//- Copy construct addressing, shallow copy values list reference
inline IndirectList(const UList<T>& values, const labelUList& addr);
//- Move construct addressing, shallow copy values list reference.
inline IndirectList(const UList<T>& values, List<label>&& addr);
//- Move construct addressing, shallow copy values list reference