From: Wolfgang Bangerth Date: Sat, 13 Jan 2024 04:02:22 +0000 (-0700) Subject: Simplify Tensor::unroll(). X-Git-Tag: relicensing~165^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F16467%2Fhead;p=dealii.git Simplify Tensor::unroll(). --- diff --git a/include/deal.II/base/tensor.h b/include/deal.II/base/tensor.h index 54a3cbce01..9ee2ba425f 100644 --- a/include/deal.II/base/tensor.h +++ b/include/deal.II/base/tensor.h @@ -424,13 +424,6 @@ private: */ Number value; - /** - * Internal helper function for unroll. - */ - template - Iterator - unroll_recursion(const Iterator current, const Iterator end) const; - // Allow an arbitrary Tensor to access the underlying values. template friend class Tensor; @@ -885,13 +878,6 @@ private: // ... avoid a compiler warning in case of dim == 0 and ensure that the // array always has positive size. - /** - * Internal helper function for unroll. - */ - template - Iterator - unroll_recursion(const Iterator current, const Iterator end) const; - /** * This constructor is for internal use. It provides a way * to create constexpr constructors for Tensor @@ -1255,24 +1241,6 @@ constexpr DEAL_II_HOST_DEVICE inline DEAL_II_ALWAYS_INLINE -template -template -Iterator -Tensor<0, dim, Number>::unroll_recursion(const Iterator current, - const Iterator end) const -{ - (void)end; - Assert(dim != 0, - ExcMessage("Cannot unroll an object of type Tensor<0,0,Number>")); - Assert(std::distance(current, end) >= 1, - ExcMessage("The provided iterator range must contain at least one " - "element.")); - *current = value; - return std::next(current); -} - - - template constexpr inline void Tensor<0, dim, Number>::clear() @@ -1289,8 +1257,14 @@ template inline void Tensor<0, dim, Number>::unroll(const Iterator begin, const Iterator end) const { + (void)end; AssertDimension(std::distance(begin, end), n_independent_components); - unroll_recursion(begin, end); + Assert(dim != 0, + ExcMessage("Cannot unroll an object of type Tensor<0,0,Number>")); + Assert(std::distance(begin, end) >= 1, + ExcMessage("The provided iterator range must contain at least one " + "element.")); + *begin = value; } @@ -1775,25 +1749,32 @@ inline void Tensor::unroll(const Iterator begin, const Iterator end) const { - AssertDimension(std::distance(begin, end), n_independent_components); - unroll_recursion(begin, end); + if constexpr (rank_ > 1) + { + // For higher-rank tensors, we recurse to the sub-tensors: + Iterator next = begin; + for (unsigned int i = 0; i < dim; ++i) + { + values[i].unroll(next, end); + std::advance( + next, Tensor::n_independent_components); + } + } + else + { + // For rank-1 tensors, we can simply copy the current elements from + // our linear array into the output range, and then return the + // iterator moved forward by 'dim' elements: + Assert(std::distance(begin, end) >= dim, + ExcMessage( + "The provided iterator range must contain at least 'dim' " + "elements.")); + std::copy(&values[0], &values[dim], begin); + } } -template -template -Iterator -Tensor::unroll_recursion(const Iterator current, - const Iterator end) const -{ - Iterator next = current; - for (unsigned int i = 0; i < dim; ++i) - next = values[i].unroll_recursion(next, end); - return next; -} - - template constexpr inline unsigned int Tensor::component_to_unrolled_index(