ENH: new/revised emplace_back() [for DynamicList/List/PtrDynList/PtrList]

- returns reference as per C++17 std::vector

STYLE: drop unused, redundant DynamicField remove() method
This commit is contained in:
Mark Olesen 2023-01-26 11:24:25 +01:00
parent c1cdacc0b4
commit 7c60c80edd
28 changed files with 179 additions and 135 deletions

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -52,28 +53,29 @@ int main(int argc, char *argv[])
Info << "testField:" << testField << endl;
testField.append(vector(0.5, 4.8, 6.2));
testField.emplace_back(0.5, 4.8, 6.2);
Info << "testField after appending:" << testField << endl;
testField.append(vector(2.7, 2.3, 6.1));
testField.emplace_back(2.7, 2.3, 6.1);
Info << "testField after appending:" << testField << endl;
vector elem = testField.remove();
vector elem = testField.back();
testField.pop_back();
Info << "removed element:" << elem << endl;
Info << "testField:" << testField << endl;
testField.append(vector(3.0, 1.3, 9.2));
testField.emplace_back(3.0, 1.3, 9.2);
Info << "testField:" << testField << endl;
testField.setSize(10, vector(1.5, 0.6, -1.0));
testField.resize(10, vector(1.5, 0.6, -1.0));
Info << "testField after setSize:" << testField << endl;
testField.append(testField2);
testField.push_back(testField2);
Info << "testField after appending testField2:" << testField << endl;
@ -87,7 +89,7 @@ int main(int argc, char *argv[])
testField.clear();
testField.append(vector(3.0, 1.3, 9.2));
testField.emplace_back(3.0, 1.3, 9.2);
Info << "testField after clear and append:" << testField << endl;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -140,7 +140,7 @@ int main(int argc, char *argv[])
{
0, 1, 2, 3, 4
};
dlA.append({ 5, 6 });
dlA.push_back({ 5, 6 });
dlA = { 1, 2, 4 };
DynamicList<label> dlB;
@ -172,7 +172,7 @@ int main(int argc, char *argv[])
// Copy back and append a few time
for (label i=0; i < 3; i++)
{
dlB.append(lstA);
dlB.push_back(lstA);
}
Info<< "appended list a few times" << endl;
@ -186,7 +186,7 @@ int main(int argc, char *argv[])
// Copy back and append a few time
for (label i=0; i < 3; i++)
{
dlB.append(lstA);
dlB.push_back(lstA);
}
@ -220,8 +220,8 @@ int main(int argc, char *argv[])
for (label elemI=0; elemI < 5; ++elemI)
{
dlE1.append(4 - elemI);
dlE2.append(elemI);
dlE1.push_back(4 - elemI);
dlE2.push_back(elemI);
}
printInfo("dlE2", dlE2, true);
@ -243,9 +243,12 @@ int main(int argc, char *argv[])
{
DynamicList<label> addr(10);
addr.append(3);
addr.append(1);
addr.append(2);
addr.emplace_back(3);
addr.emplace_back(1);
addr.emplace_back(2);
// Can also use the return value
Info<< "adding " << addr.emplace_back(4) << endl;
forAll(dlE2, i)
{
@ -297,9 +300,9 @@ int main(int argc, char *argv[])
Info<< "test move-append with "
<< flatOutput(input1) << " and " << flatOutput(input2) << endl;
list2.append(std::move(list1));
list2.append(std::move(input1));
list2.append(std::move(input2));
list2.push_back(std::move(list1));
list2.push_back(std::move(input1));
list2.push_back(std::move(input2));
Info<< "result: " << flatOutput(list2) << nl
<< "inputs: " << flatOutput(list1) << " / "

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -132,7 +132,7 @@ int main(int argc, char *argv[])
{
if (nameFilter(f))
{
functionNames.append(f);
functionNames.push_back(f);
}
}
}
@ -140,7 +140,7 @@ int main(int argc, char *argv[])
{
for (label argi=1; argi < args.size(); ++argi)
{
functionNames.append(args[argi]);
functionNames.push_back(args[argi]);
}
}

View File

@ -155,7 +155,7 @@ int main(int argc, char *argv[])
<< IndirectList<label>::subset_if(test6, evenNonZero) << nl
<< endl;
test6.append(identity(13, 12));
test6.push_back(identity(13, 12));
Info<< "Randomized: " << flatOutput(test6) << endl;
inplaceUniqueSort(test6);

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -71,16 +72,9 @@ int main(int argc, char *argv[])
label edgeI = 0;
Info<< "Starting walk on edge " << edgeI << endl;
initialEdges.append(edgeI);
initialEdges.push_back(edgeI);
const edge& e = patch.edges()[edgeI];
initialEdgesInfo.append
(
patchEdgeFaceInfo
(
e.centre(patch.localPoints()),
0.0
)
);
initialEdgesInfo.emplace_back(e.centre(patch.localPoints()), 0);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2022 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -332,10 +332,8 @@ int main(int argc, char *argv[])
for (label i = 0; i < 5; ++i)
{
listApp.append(new Scalar(1.3*i));
listApp.emplace_back(1.3*i);
}
listApp.emplace_back(100);
Info<< nl
<< "list1: " << list1 << nl
@ -353,7 +351,7 @@ int main(int argc, char *argv[])
if (old)
{
ptrs.append(old.release());
ptrs.push_back(old.release());
}
}
@ -459,8 +457,8 @@ int main(int argc, char *argv[])
printAddr(Info, dynlist1b);
printAddr(Info, dynlist1c);
dynlist1d.append(std::move(dynlist1b));
dynlist1d.append(std::move(dynlist1c));
dynlist1d.push_back(std::move(dynlist1b));
dynlist1d.push_back(std::move(dynlist1c));
Info<< "result:" << nl;
print(Info, dynlist1d);
@ -477,8 +475,8 @@ int main(int argc, char *argv[])
printAddr(Info, list1b);
printAddr(Info, list1c);
list1d.append(std::move(list1b));
list1d.append(std::move(list1c));
list1d.push_back(std::move(list1b));
list1d.push_back(std::move(list1c));
Info<< "result:" << nl;
print(Info, list1d);
@ -523,7 +521,7 @@ int main(int argc, char *argv[])
printAddr(Info, ulist1);
Info<< nl;
ulist1c.append(std::move(ulist1b));
ulist1c.push_back(std::move(ulist1b));
Info<< "UPtrList append/append:";
printAddr(Info, ulist1c);
@ -596,7 +594,7 @@ int main(int argc, char *argv[])
{
dynPlanes.emplace_back(vector::one, vector::one);
dynPlanes.emplace_back(vector(1,2,3), vector::one);
dynPlanes.append(nullptr);
dynPlanes.push_back(nullptr);
dynPlanes.set(6, new plane(vector(2,2,1), vector::one));
dynPlanes.set(10, new plane(vector(4,5,6), vector::one));
@ -619,10 +617,10 @@ int main(int argc, char *argv[])
Info<< "now append again" << endl;
{
dynPlanes.append(new plane(vector::one, vector::one));
dynPlanes.append(new plane(vector(1,2,3), vector::one));
dynPlanes.emplace_back(vector::one, vector::one);
dynPlanes.emplace_back(vector(1,2,3), vector::one);
dynPlanes.set(5, new plane(vector(2,2,1), vector::one));
dynPlanes.emplace(5, vector(2,2,1), vector::one);
}
report(Info, dynPlanes, true);
@ -658,12 +656,12 @@ int main(int argc, char *argv[])
{
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.emplace_back(vector::one, vector::one);
dynPlanes2.emplace_back(vector(1,2,3), vector::one);
dynPlanes2.push_back(nullptr);
dynPlanes2.set(6, new plane(vector(2,2,1), vector::one));
dynPlanes2.set(10, new plane(Zero, vector::one));
dynPlanes2.emplace(6, vector(2,2,1), vector::one);
dynPlanes2.emplace(10, Zero, vector::one);
labelList order;
sortedOrder(dynPlanes2, order);
@ -701,7 +699,7 @@ int main(int argc, char *argv[])
Info<< "Append" << endl;
report(Info, dynPlanes2, false);
dynPlanes.append(std::move(dynPlanes2));
dynPlanes.push_back(std::move(dynPlanes2));
Info<< "Result" << endl;
report(Info, dynPlanes, false);

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -130,7 +131,7 @@ int main(int argc, char *argv[])
flatList = labelUIndList(completeList, addresses);
Info<< "List assign from UIndirectList: " << flatOutput(flatList) << nl;
flatList.append(labelUIndList(completeList, addresses));
flatList.push_back(labelUIndList(completeList, addresses));
Info<< "List::append(UIndirectList): " << flatOutput(flatList) << nl;
@ -138,7 +139,7 @@ int main(int argc, char *argv[])
Info<< "DynamicList construct from UIndirectList: " << flatOutput(dynList)
<< nl;
dynList.append(labelUIndList(completeList, addresses));
flatList.push_back(labelUIndList(completeList, addresses));
Info<< "DynamicList::append(UIndirectList): " << flatOutput(dynList) << nl;
Info<< "\nEnd\n" << endl;

View File

@ -84,10 +84,10 @@ int main(int argc, char *argv[])
DynamicList<string> dynlst;
dynlst.reserve(16);
dynlst.append("string1 with content");
dynlst.append("string2 other content");
dynlst.append("string3 more");
dynlst.append("string4 done");
dynlst.push_back("string1 with content");
dynlst.push_back("string2 other content");
dynlst.push_back("string3 more");
dynlst.push_back("string4 done");
{
CStringList inC(dynlst);
@ -133,7 +133,7 @@ int main(int argc, char *argv[])
dynlst.clear();
for (int i=0; i<argc; ++i)
{
dynlst.append(argv[i]);
dynlst.push_back(argv[i]);
}
Info<< "input: " << dynlst << endl;

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012 OpenFOAM Foundation
Copyright (C) 2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -67,14 +68,14 @@ int main(int argc, char *argv[])
{
scalar factor = pI/scalar(size);
pointList.append(0.99*point(factor, factor, factor));
pointFieldList[pI] = 0.99*point(factor, factor, factor);
pointList.push_back(0.99*point::uniform(factor));
pointFieldList[pI] = 0.99*point::uniform(factor);
}
for (label i=0; i<5; ++i)
{
pointList.append(point(0.95, 0.95,0.95));
pointFieldList.append(point(0.95, 0.95,0.95));
pointList.emplace_back(0.95, 0.95, 0.95);
pointFieldList.emplace_back(0.95, 0.95, 0.95);
}
Info<< "Time to construct lists of points: "
@ -148,7 +149,7 @@ int main(int argc, char *argv[])
// Test point insertion
label index = pointList.size();
pointList.append(p);
pointList.push_back(p);
Info<< nl << "Inserting point " << p << " with index " << index << endl;
@ -159,7 +160,7 @@ int main(int argc, char *argv[])
<< tree.findNearest(p, 0.4) << endl;
index = pointList.size();
pointList.append(p);
pointList.push_back(p);
Info<< "Inserting same point " << p << " with index " << index << endl;

View File

@ -85,8 +85,8 @@ int main(int argc, char *argv[])
}
else
{
libPtrs_.append(ptr);
libNames_.append(libName);
libPtrs_.push_back(ptr);
libNames_.push_back(libName);
if (verbose)
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021-2022 OpenCFD Ltd.
Copyright (C) 2021-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -181,7 +181,7 @@ int main(int argc, char *argv[])
DynamicList<label> globalIDs;
for (label i = 0; i < 100; i++)
{
globalIDs.append(rndGen.position(label(0), nTotalCells-1));
globalIDs.push_back(rndGen.position(label(0), nTotalCells-1));
}
// Get the cell centres at those cell indices

View File

@ -62,20 +62,20 @@ int main(int argc, char *argv[])
{
DynamicList<instant> times;
times.append(instant{});
times.append({12, "abc"});
times.append(instant{3.14159});
times.append({300.456, "def"});
times.append({454.456, "xyz"});
times.append({10, "ten"});
times.append({15, "fifteen"});
times.emplace_back();
times.emplace_back(12, "abc");
times.emplace_back(3.14159);
times.emplace_back(300.456, "def");
times.emplace_back(454.456, "xyz");
times.emplace_back(10, "ten");
times.push_back({15, "fifteen"});
{
word timeName("twenty");
Info<<"move append: " << timeName << nl;
times.append({20, std::move(timeName)});
Info<<"after append: " << timeName << nl;
Info<<"move append: <" << timeName << '>' << nl;
times.emplace_back(20, std::move(timeName));
Info<<"after append: <" << timeName << '>' << nl;
}
Info<< nl << "times:" << times << nl;
@ -97,12 +97,12 @@ int main(int argc, char *argv[])
}
DynamicList<fileNameInstant> files;
files.append(fileNameInstant{});
files.append({12, "twelve"});
files.append({3.14, "/path/almost-pi"});
files.append({300, "/dev/value"});
files.append({454, "/tmp/xyz"});
files.append({10, "ten"});
files.emplace_back();
files.emplace_back(12, "twelve");
files.emplace_back(3.14, "/path/almost-pi");
files.emplace_back(300, "/dev/value");
files.emplace_back(454, "/tmp/xyz");
files.emplace_back(10, "ten");
Info<< nl << "files:" << files << nl;
sort(files);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -78,10 +78,10 @@ int main(int argc, char *argv[])
{
Info<<"test sorting" << endl;
DynamicList<labelRange> list1(10);
list1.append(labelRange(25, 8));
list1.append(labelRange(8));
list1.append(labelRange(15, 5));
list1.append(labelRange(50, -10, true));
list1.emplace_back(25, 8);
list1.emplace_back(8);
list1.emplace_back(15, 5);
list1.emplace_back(50, -10, true);
sort(list1);
Info<<"sorted" << list1 << endl;

View File

@ -86,11 +86,8 @@ int main(int argc, char *argv[])
forAll(fEdges, i)
{
changedEdges.append(fEdges[i]);
changedInfo.append
(
patchEdgeFaceRegions(labelPair(globalFacei, globalFacei))
);
changedEdges.push_back(fEdges[i]);
changedInfo.emplace_back(labelPair(globalFacei, globalFacei));
}
}

View File

@ -108,8 +108,8 @@ int main(int argc, char *argv[])
{
if (surf->interfaceCell()[celli])
{
centres.append(surf->centre()[celli]);
normals.append(surf->normal()[celli]);
centres.push_back(surf->centre()[celli]);
normals.push_back(surf->normal()[celli]);
}
}

View File

@ -249,7 +249,7 @@ void Foam::router::storeRoute
{
if (weights_[nodeI] == pathValue)
{
route.append(nodeI);
route.push_back(nodeI);
storeRoute
(
@ -386,7 +386,7 @@ Foam::labelList Foam::router::getRoute(const label pathValue) const
DynamicList<label> route(weights_.size());
route.append(startNodeI);
route.push_back(startNodeI);
storeRoute(startNodeI, -1, pathValue, route);

View File

@ -90,7 +90,7 @@ int main(int argc, char *argv[])
if (tok.good())
{
tokens.append(std::move(tok));
tokens.push_back(std::move(tok));
if (verbose)
{
Info<< "after append: " << tok.info() << endl;

View File

@ -227,7 +227,7 @@ int main(int argc, char *argv[])
wordRe wre(wres1[rnd.position<label>(0,last)]);
// Append
wres1.append(wre);
wres1.push_back(wre);
}
// Add some entropy

View File

@ -259,6 +259,11 @@ public:
template<int AnySizeMin>
inline void transfer(DynamicList<T, AnySizeMin>& list);
//- Construct an element at the end of the list,
//- return reference to the new list element
template<class... Args>
inline T& emplace_back(Args&&... args);
//- Copy append an element to the end of this list.
inline void push_back(const T& val);

View File

@ -503,6 +503,23 @@ Foam::DynamicList<T, SizeMin>::transfer
}
template<class T, int SizeMin>
template<class... Args>
inline T& Foam::DynamicList<T, SizeMin>::emplace_back(Args&&... args)
{
// This could/should be better with inplace construction
// (as per std::vector), but currently lacking the methods for that
// so resize and move assign
const label idx = List<T>::size();
resize(idx + 1);
// move assign element
this->operator[](idx) = T(std::forward<Args>(args)...);
return this->back();
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::push_back
(

View File

@ -240,6 +240,12 @@ public:
// Edit
//- Construct an element at the end of the list,
//- return reference to the new list element.
// If this is frequently required, consider a DynamicList instead.
template<class... Args>
inline T& emplace_back(Args&&... args);
//- Append an element at the end of the list
// If this is frequently required, consider a DynamicList
inline void push_back(const T& val);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -171,6 +171,23 @@ inline T& Foam::List<T>::newElmt(const label i)
}
template<class T>
template<class... Args>
inline T& Foam::List<T>::emplace_back(Args&&... args)
{
// This could/should be better with inplace construction
// (as per std::vector), but currently lacking the methods for that
// so resize and move assign
const label idx = this->size();
resize(idx + 1);
// move assign element
this->operator[](idx) = T(std::forward<Args>(args)...);
return this->back();
}
template<class T>
inline void Foam::List<T>::push_back(const T& val)
{

View File

@ -141,9 +141,10 @@ public:
template<int AnySizeMin>
inline void swap(PtrDynList<T, AnySizeMin>& other);
//- Construct an element at the end of the list
//- Construct an element at the end of the list,
//- return reference to the new list element
template<class... Args>
inline void emplace_back(Args&&... args);
inline T& emplace_back(Args&&... args);
//- Append an element to the end of the list
inline void push_back(T* ptr);

View File

@ -218,9 +218,10 @@ inline void Foam::PtrDynList<T, SizeMin>::swap
template<class T, int SizeMin>
template<class... Args>
inline void Foam::PtrDynList<T, SizeMin>::emplace_back(Args&&... args)
inline T& Foam::PtrDynList<T, SizeMin>::emplace_back(Args&&... args)
{
this->push_back(new T(std::forward<Args>(args)...));
return this->back();
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2022 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -149,9 +149,10 @@ public:
//- Same as resize()
void setSize(const label newLen) { this->resize(newLen); }
//- Construct and append an element to the end of the list
//- Construct and append an element to the end of the list,
//- return reference to the new list element
template<class... Args>
inline void emplace_back(Args&&... args);
inline T& emplace_back(Args&&... args);
//- Append an element to the end of the list
inline void push_back(T* ptr);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2022 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -103,9 +103,10 @@ inline void Foam::PtrList<T>::clear()
template<class T>
template<class... Args>
inline void Foam::PtrList<T>::emplace_back(Args&&... args)
inline T& Foam::PtrList<T>::emplace_back(Args&&... args)
{
UPtrList<T>::push_back(new T(std::forward<Args>(args)...));
return this->back();
}

View File

@ -279,21 +279,23 @@ public:
template<int AnySizeMin>
inline void transfer(DynamicField<T, AnySizeMin>& list);
//- Append an element at the end of the list
//- Construct an element at the end of the list,
//- return reference to the new list element
template<class... Args>
inline T& emplace_back(Args&&... args);
//- Copy append an element at the end of the list
inline void push_back(const T& val);
//- Move append an element
inline void push_back(T&& val);
//- Append a List at the end of this list
//- Copy append another list to the end of this list
inline void push_back(const UList<T>& list);
//- Reduce size by 1 or more elements. Can be called on an empty list.
inline void pop_back(label n = 1);
//- Remove and return the last element. Fatal on an empty list.
inline T remove();
// Reading/writing

View File

@ -583,6 +583,23 @@ inline void Foam::DynamicField<T, SizeMin>::transfer
}
template<class T, int SizeMin>
template<class... Args>
inline T& Foam::DynamicField<T, SizeMin>::emplace_back(Args&&... args)
{
// This could/should be better with inplace construction
// (as per std::vector), but currently lacking the methods for that
// so resize and move assign
const label idx = List<T>::size();
resize(idx + 1);
// move assign element
this->operator[](idx) = T(std::forward<Args>(args)...);
return this->back();
}
template<class T, int SizeMin>
inline void Foam::DynamicField<T, SizeMin>::push_back
(
@ -646,26 +663,6 @@ inline void Foam::DynamicField<T, SizeMin>::pop_back(label n)
}
template<class T, int SizeMin>
inline T Foam::DynamicField<T, SizeMin>::remove()
{
// Location of last element and simultaneously the new size
const label idx = List<T>::size() - 1;
if (idx < 0)
{
FatalErrorInFunction
<< "List is empty" << abort(FatalError);
}
const T& val = List<T>::operator[](idx);
List<T>::setAddressableSize(idx);
return val;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, int SizeMin>