Skip to content
Snippets Groups Projects
Commit 4b529f85 authored by Julien Michel's avatar Julien Michel
Browse files

ENH: A more efficient implementation of VariadicConcatenate (from code review)

parent f0d1424c
No related branches found
No related tags found
No related merge requests found
...@@ -35,40 +35,44 @@ namespace Functor ...@@ -35,40 +35,44 @@ namespace Functor
namespace variadic_concatenate_details namespace variadic_concatenate_details
{ {
// helper function to implement next functor (convert a scalar value
// to a VariableLengthVector) template <typename T> size_t NumberOfElements(const T &)
template <typename T> itk::VariableLengthVector<T> toVector(const T & in) {
static_assert(std::is_scalar<T>::value,"variadic_concatenate_details::NumberOfElements<T> only works for T and itk::VariableLengthVector<T> where T is a scalar type.");
return 1;
}
template <typename T> size_t NumberOfElements(const itk::VariableLengthVector<T> & v)
{ {
itk::VariableLengthVector<T> out; static_assert(std::is_scalar<T>::value,"variadic_concatenate_details::NumberOfElements<T> only works for T and itk::VariableLengthVector<T> where T is a scalar type.");
out.SetSize(1); return v.GetSize();
out[0] = in;
return out;
} }
// helper function to implement next functor, VariableLengthVectorVersion (returns in) template <typename ...T> size_t NumberOfElements(const T&...t)
template <typename T> const itk::VariableLengthVector<T> & toVector(const itk::VariableLengthVector<T> & in)
{ {
return in; std::array<size_t,sizeof...(T)> sizes = {{NumberOfElements(t)...}};
return std::accumulate(sizes.begin(),sizes.end(),0);
} }
// helper function to implement next functor, Merge two VariableLengthVector in-place template <typename Out, typename T> size_t fillVector(itk::VariableLengthVector<Out> & out, size_t idx, const T & t)
template <typename v1, typename v2> void concatenateVectors(v1 & a, const v2 & b)
{ {
const size_t previousSizeOfA = a.GetSize(); assert(idx<out.GetSize());
out[idx] = static_cast<Out>(t);
a.SetSize(previousSizeOfA+b.GetSize()); return idx+1;
for(size_t it = 0; it<b.Size();++it)
{
a[previousSizeOfA+it] = static_cast<typename v1::ValueType>(b[it]);
}
} }
// helper function to implement next functor, Merge N VariableLengthVector in-place template <typename Out, typename T> size_t fillVector(itk::VariableLengthVector<Out> & out, size_t idx, const itk::VariableLengthVector<T> & t)
template <typename v1, typename v2, typename ...vn> void concatenateVectors(v1 & a, const v2 & b, const vn&... z)
{ {
concatenateVectors(a,b); assert(idx+t.GetSize()<=out.GetSize());
concatenateVectors(a,z...); for(auto it = 0UL; it<t.GetSize(); ++it)
out[idx+it] = static_cast<Out>(t[it]);
return idx+t.GetSize();
}
template <typename Out, typename Current, typename ...T> size_t fillVector(itk::VariableLengthVector<Out> & out, size_t idx, const Current& current, const T&...t)
{
size_t newIdx = fillVector(out,idx,current);
return fillVector(out,newIdx,t...);
} }
} // end namespace variadic_concatenate_details } // end namespace variadic_concatenate_details
...@@ -86,8 +90,10 @@ template<typename TOut, typename ...TIns> struct VariadicConcatenate ...@@ -86,8 +90,10 @@ template<typename TOut, typename ...TIns> struct VariadicConcatenate
{ {
auto operator()(const TIns &... ins) const auto operator()(const TIns &... ins) const
{ {
itk::VariableLengthVector<TOut> out; const size_t numberOfElements = variadic_concatenate_details::NumberOfElements(ins...);
variadic_concatenate_details::concatenateVectors(out, variadic_concatenate_details::toVector(ins)...); itk::VariableLengthVector<TOut> out(numberOfElements);
variadic_concatenate_details::fillVector(out,0,ins...);
return out; return out;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment