Commit 15f72608 authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: cleanup of ListOps, ListListOps. Adjustments to List, PackedList.

- relocated ListAppendEqOp and ListUniqueEqOp to ListOps::appendEqOp
  and ListOps::UniqueEqOp, respectively for better code isolation and
  documentation of purpose.

- relocated setValues to ListOps::setValue() with many more
  alternative selectors possible

- relocated createWithValues to ListOps::createWithValue
  for better code isolation. The default initialization value is itself
  now a default parameter, which allow for less typing.

  Negative indices in the locations to set are now silently ignored,
  which makes it possible to use an oldToNew mapping that includes
  negative indices.

- additional ListOps::createWithValue taking a single position to set,
  available both in copy assign and move assign versions.
  Since a negative index is ignored, it is possible to combine with
  the output of List::find() etc.

STYLE: changes for PackedList

- code simplication in the PackedList iterators, including dropping
  the unused operator() on iterators, which is not available in plain
  list versions either.

- improved sizing for PackedBoolList creation from a labelUList.

ENH: additional List constructors, for handling single element list.

- can assist in reducing constructor ambiguity, but can also helps
  memory optimization when creating a single element list.
  For example,

    labelListList labels(one(), identity(mesh.nFaces()));
parent ffd7b00a
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -97,11 +97,14 @@ void printMyString(const UList<string>& lst)
int main(int argc, char *argv[])
{
argList::noParallel();
argList::noFunctionObjects();
argList::addOption("reList", "reList");
argList::addOption("wordList", "wordList");
argList::addOption("stringList", "stringList");
argList::addOption("float", "xx");
argList::addBoolOption("transform", "Test List::createList functionality");
argList::addBoolOption("create", "Test ListOps::create functionality");
argList::addBoolOption("ListList", "Test list of list functionality");
argList::addBoolOption("flag");
#include "setRootCase.H"
......@@ -332,11 +335,11 @@ int main(int argc, char *argv[])
List<scalar> sident(range.begin(), range.end());
Info<<"range-list (scalar)=" << sident << nl;
// Sub-ranges also work
List<scalar> sident2(range(3), range(10));
Info<<"range-list (scalar)=" << sident2 << nl;
// // Sub-ranges also work
// List<scalar> sident2(range.at(3), range.at(10));
// Info<<"subrange-list (scalar)=" << sident2 << nl;
// VERY BAD IDEA: List<scalar> sident3(range(10), range(3));
// VERY BAD IDEA: List<scalar> sident3(range.at(10), range.at(3));
// This doesn't work, and don't know what it should do anyhow
// List<vector> vident(range.begin(), range.end());
......@@ -362,15 +365,15 @@ int main(int argc, char *argv[])
Info<<"-flag:" << args["flag"] << endl;
}
if (args.found("transform"))
if (args.found("create"))
{
Info<< nl << "Test List::createList functionality" << nl;
Info<< nl << "Test ListOps::create functionality" << nl;
const auto labels = identity(15);
Info<< "labels: " << flatOutput(labels) << endl;
{
auto scalars = List<scalar>::createList
auto scalars = ListOps::create<scalar>
(
labels,
[](const label& val){ return scalar(1.5*val); }
......@@ -379,7 +382,7 @@ int main(int argc, char *argv[])
}
{
auto vectors = List<vector>::createList
auto vectors = ListOps::create<vector>
(
labels,
[](const label& val){ return vector(1.2*val, -1.2*val, 0); }
......@@ -388,7 +391,7 @@ int main(int argc, char *argv[])
}
{
auto longs = List<long>::createList
auto longs = ListOps::create<long>
(
labels,
[](const label& val){ return val; }
......@@ -396,7 +399,7 @@ int main(int argc, char *argv[])
Info<< "longs: " << flatOutput(longs) << endl;
}
{
auto negs = List<label>::createList
auto negs = ListOps::create<label>
(
labels,
std::negate<label>()
......@@ -405,7 +408,7 @@ int main(int argc, char *argv[])
}
{
auto scalars = List<scalar>::createList
auto scalars = ListOps::create<scalar>
(
labelRange::null.cbegin(),
labelRange::identity(15).cend(),
......@@ -417,9 +420,9 @@ int main(int argc, char *argv[])
#if WM_LABEL_SIZE == 32
{
List<int64_t> input(10);
std::iota(input.begin(), input.end(), 0);
std::iota(input.begin(), input.end(), 50);
auto output = List<label>::createList
auto output = ListOps::create<label>
(
input,
toLabel<int64_t>()
......@@ -429,9 +432,9 @@ int main(int argc, char *argv[])
#elif WM_LABEL_SIZE == 64
{
List<int32_t> input(10);
std::iota(input.begin(), input.end(), 0);
std::iota(input.begin(), input.end(), 50);
auto output = List<label>::createList
auto output = ListOps::create<label>
(
input,
toLabel<int32_t>()
......@@ -439,6 +442,157 @@ int main(int argc, char *argv[])
Info<< "label (from int32): " << flatOutput(output) << endl;
}
#endif
labelHashSet locations{ -15, 5, 10, 15, 25, 35 };
Info<< nl << "Test for createWithValue with locations :"
<< flatOutput(locations.sortedToc()) << nl;
{
auto output = ListOps::createWithValue<label>
(
30,
locations.toc(), // Any order
100,
-1 // default value
);
Info<< "with labelUList: " << flatOutput(output)
<< " selector: " << flatOutput(locations.sortedToc()) << nl;
}
{
auto output = ListOps::createWithValue<label>
(
30,
locations,
100,
-1 // default value
);
Info<< "with labelHashSet: " << flatOutput(output)
<< " selector: " << flatOutput(locations) << nl;
}
{
PackedBoolList select(locations.toc());
auto output = ListOps::createWithValue<label>
(
30,
select,
100,
-1 // default value
);
Info<< "with PackedBoolList: " << flatOutput(output)
<< " selector: " << flatOutput(select.used()) << nl;
}
{
// Fairly really inconvenient way to set true/false
labelList toc(locations.sortedToc());
List<bool> select = ListOps::createWithValue<bool>
(
toc.last() + 1,
toc,
true,
false // default value
);
auto output = ListOps::createWithValue<label>
(
30,
select,
100,
-1 // default value
);
Info<< "with boolList: " << flatOutput(output)
<< " selector: " << flatOutput(select) << nl;
}
// Repeat with a shorter selector
locations = { -15, 5, 10 };
{
auto output = ListOps::createWithValue<label>
(
30,
locations,
100,
-1 // default value
);
Info<< "with labelHashSet: " << flatOutput(output)
<< " selector: " << flatOutput(locations) << nl;
}
{
PackedBoolList select(locations.toc());
auto output = ListOps::createWithValue<label>
(
30,
select,
100,
-1 // default value
);
Info<< "with PackedBoolList: " << flatOutput(output)
<< " selector: " << flatOutput(select.used()) << nl;
}
{
// Fairly really inconvenient way to set true/false
labelList toc(locations.sortedToc());
List<bool> select = ListOps::createWithValue<bool>
(
toc.last() + 1,
toc,
true,
false // default value
);
auto output = ListOps::createWithValue<label>
(
30,
select,
100,
-1 // default value
);
Info<< "with boolList: " << flatOutput(output)
<< " selector: " << flatOutput(select) << nl;
}
}
if (args.found("ListList"))
{
{
labelListList listlist(5, identity(5));
Info<<"list-list with length/val:" << listlist << nl;
}
{
labelListList listlist(one(), identity(5));
Info<<"list-list 1/val:" << listlist << nl;
}
{
labelList content = identity(5);
labelListList listlist(one(), content);
Info<<"list-list 1/copy val:" << listlist
<<" - from " << content << nl;
}
{
labelList content = identity(5);
labelListList listlist(one(), std::move(content));
Info<<"list-list 1/move val:" << listlist
<<" - from " << content << nl;
}
{
labelListList listlist(one(), Zero);
Info<<"list-list 1/move val:" << listlist
<< nl;
}
}
if (args.readIfPresent<scalar>("float", xxx))
......
......@@ -251,13 +251,13 @@ int main(int argc, char *argv[])
Info<< "begin():";
iter.printInfo(Info) << "\n";
Info<< "iterator:" << iter() << "\n";
iter() = 5;
Info<< "iterator:" << *iter << "\n";
*iter = 5;
iter.printInfo(Info);
list1.printInfo(Info, true);
iter = list1[31];
Info<< "iterator:" << iter() << "\n";
Info<< "iterator:" << *iter << "\n";
iter.printInfo(Info);
......
......@@ -229,7 +229,7 @@ int main(int argc, char *argv[])
sum = 0;
for (label iter = 0; iter < nIters; ++iter)
{
forAllIter(PackedBoolList, packed, it)
forAllIters(packed, it)
{
sum += it;
}
......@@ -244,9 +244,9 @@ int main(int argc, char *argv[])
sum = 0;
for (label iter = 0; iter < nIters; ++iter)
{
forAllConstIter(PackedBoolList, packed, cit)
forAllConstIters(packed, cit)
{
sum += cit();
sum += *cit;
}
}
std::cout
......@@ -370,9 +370,9 @@ int main(int argc, char *argv[])
// Write packed
for (label iter = 0; iter < nIters; ++iter)
{
forAllIter(PackedBoolList, packed, it)
forAllIters(packed, it)
{
it() = 1;
*it = 1;
}
}
Info<< "Writing packed using iterator:" << timer.cpuTimeIncrement()
......
......@@ -29,9 +29,12 @@ Description
#include "uLabel.H"
#include "boolList.H"
#include "DynamicList.H"
#include "IOstreams.H"
#include "PackedBoolList.H"
#include "ITstream.H"
#include "StringStream.H"
#include "FlatOutput.H"
using namespace Foam;
......@@ -135,8 +138,9 @@ int main(int argc, char *argv[])
PackedBoolList list4
(
IStringStream
ITstream
(
"input",
"(1 n 1 n 1 n 1 1 off 0 0 f f 0 y yes y true y false on t)"
)()
);
......@@ -199,6 +203,18 @@ int main(int argc, char *argv[])
list4.writeEntry("PackedBoolList", Info);
// Construct from labelUList, labelUIndList
{
DynamicList<label> indices({10, 50, 300});
Info<< "set: " << flatOutput(indices) << endl;
PackedBoolList bools1(indices);
Info<< "used: " << bools1.size() << " "
<< flatOutput(bools1.used()) << endl;
}
return 0;
}
......
......@@ -1007,7 +1007,7 @@ Foam::label Foam::checkGeometry
globalFaces().gather
(
UPstream::worldComm,
labelList::createList
ListOps::create<label>
(
UPstream::procID(UPstream::worldComm),
toLabel<int>() // int -> label
......@@ -1061,7 +1061,7 @@ Foam::label Foam::checkGeometry
globalFaces().gather
(
UPstream::worldComm,
labelList::createList
ListOps::create<label>
(
UPstream::procID(UPstream::worldComm),
toLabel<int>() // int -> label
......
......@@ -84,7 +84,7 @@ void writeWeights
globalFaces().gather
(
UPstream::worldComm,
labelList::createList
ListOps::create<label>
(
UPstream::procID(UPstream::worldComm),
toLabel<int>() // int -> label
......
......@@ -81,7 +81,7 @@ void Foam::parLagrangianRedistributor::findClouds
}
// Synchronise cloud names
Pstream::combineGather(cloudNames, ListUniqueEqOp<word>());
Pstream::combineGather(cloudNames, ListOps::uniqueEqOp<word>());
Pstream::combineScatter(cloudNames);
objectNames.setSize(cloudNames.size());
......@@ -117,10 +117,10 @@ void Foam::parLagrangianRedistributor::findClouds
}
// Synchronise objectNames
forAll(objectNames, cloudI)
forAll(objectNames, i)
{
Pstream::combineGather(objectNames[cloudI], ListUniqueEqOp<word>());
Pstream::combineScatter(objectNames[cloudI]);
Pstream::combineGather(objectNames[i], ListOps::uniqueEqOp<word>());
Pstream::combineScatter(objectNames[i]);
}
}
......
......@@ -44,7 +44,7 @@ Foam::wordList Foam::parLagrangianRedistributor::filterObjects
// Parallel synchronise
wordList fieldNames(objects.names(fieldClassName));
Pstream::combineGather(fieldNames, ListUniqueEqOp<word>());
Pstream::combineGather(fieldNames, ListOps::uniqueEqOp<word>());
Pstream::combineScatter(fieldNames);
if (!selectedFields.empty())
......
......@@ -2357,7 +2357,7 @@ int main(int argc, char *argv[])
bool nfs = true;
{
List<fileName> roots(1, args.rootPath());
combineReduce(roots, ListUniqueEqOp<fileName>());
combineReduce(roots, ListOps::uniqueEqOp<fileName>());
nfs = (roots.size() == 1);
}
......
......@@ -35,65 +35,6 @@ License
#include <utility>
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class T>
template<class T2, class UnaryOperation>
Foam::List<T> Foam::List<T>::createList
(
const UList<T2>& input,
const UnaryOperation& op
)
{
const label len = input.size();
List<T> output(len);
if (len)
{
List_ACCESS(T, output, out);
List_CONST_ACCESS(T2, input, in);
for (label i = 0; i < len; ++i)
{
out[i] = op(in[i]);
}
}
return output;
}
template<class T>
template<class InputIterator, class UnaryOperation>
Foam::List<T> Foam::List<T>::createList
(
InputIterator begIter,
InputIterator endIter,
const UnaryOperation& op
)
{
const label len = std::distance(begIter, endIter);
List<T> output(len);
if (len)
{
List_ACCESS(T, output, out);
InputIterator iter = begIter;
for (label i = 0; i < len; ++i)
{
out[i] = op(*iter);
++iter;
}
}
return output;
}
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
template<class T>
......@@ -162,6 +103,33 @@ Foam::List<T>::List(const label len, const zero)
}
template<class T>
Foam::List<T>::List(const one, const T& val)
:
UList<T>(new T[1], 1)
{
this->v_[0] = val;
}
template<class T>
Foam::List<T>::List(const one, T&& val)
:
UList<T>(new T[1], 1)
{
this->v_[0] = std::move(val);
}
template<class T>
Foam::List<T>::List(const one, const zero)
:
UList<T>(new T[1], 1)
{
this->v_[0] = Zero;
}
template<class T>
Foam::List<T>::List(const UList<T>& a)
:
......
......@@ -42,6 +42,7 @@ SourceFiles
#include "UList.H"
#include "autoPtr.H"
#include "one.H"
#include "Xfer.H"
#include "SLListFwd.H"
......@@ -112,49 +113,11 @@ public:
//- Return a null List
inline static const List<T>& null();
//- Create from a list of a dissimilar type.
// Eg, convert a list of ints to floats, vectors etc.
// For example,
// \code
// auto vectors = List<vector>::createList
// (
// ints,
// [](const int& val){ return vector(1.5*val, 0, 0); }
// );
//
// auto neg = labelList::createList
// (
// ints,
// std::negate<label>()
// );
// auto labels = labelList::createList
// (
// ints,
// toLabel<int>()
// );
// \endcode
template<class T2, class UnaryOperation>
static List<T> createList
(
const UList<T2>& input,
const UnaryOperation& op
);
//- Create from an iterator range (uses std::distance for the size).
// The unary operation can be used to convert to other types.
template<class InputIterator, class UnaryOperation>
static List<T> createList
(
InputIterator begIter,
InputIterator endIter,
const UnaryOperation& op
);
// Constructors
//- Null constructor
inline List();
inline constexpr List() noexcept;
//- Construct with given size
explicit List(const label len);
......@@ -165,6 +128,15 @@ public:
//- Construct with given size initializing all elements to zero
List(const label len, const zero);
//- Construct with length=1, copying the value as the only content
List(const one, const T& val);
//- Construct with length=1, moving the value as the only content
List(const one, T&& val);