From 3f315340fa2edd733deb9ff7cf41c9ac0d61f015 Mon Sep 17 00:00:00 2001 From: Maximilian Bergbauer Date: Fri, 8 Sep 2023 13:23:10 +0200 Subject: [PATCH] Implement StridedArrayView --- include/deal.II/base/array_view.h | 255 +++++++++++++++++------------- 1 file changed, 149 insertions(+), 106 deletions(-) diff --git a/include/deal.II/base/array_view.h b/include/deal.II/base/array_view.h index fe34a066ad..729c64430b 100644 --- a/include/deal.II/base/array_view.h +++ b/include/deal.II/base/array_view.h @@ -39,6 +39,142 @@ class Table; template class LAPACKFullMatrix; +/** + * Base class of @p ArrayView which allows strided access into the view. + * This is particularly useful when you want to access only one lane of a + * VectorizedArray. + */ +template +class StridedArrayView +{ +public: + /** + * An alias that denotes the "value_type" of this container-like class, + * i.e., the type of the element it "stores" or points to. + */ + using value_type = ElementType; + + /** + * Constructor. + * + * @param[in] starting_element A pointer to the first element of the array + * this object should represent. + * @param[in] n_elements The length (in elements) of the chunk of memory + * this object should represent. + * + * @note The object that is constructed from these arguments has no + * knowledge how large the object into which it points really is. As a + * consequence, whenever you call ArrayView::operator[], the array view can + * check that the given index is within the range of the view, but it can't + * check that the view is indeed a subset of the valid range of elements of + * the underlying object that allocated that range. In other words, you need + * to ensure that the range of the view specified by the two arguments to + * this constructor is in fact a subset of the elements of the array into + * which it points. The appropriate way to do this is to use the + * make_array_view() functions. + */ + StridedArrayView(value_type *starting_element, const std::size_t n_elements); + + /** + * Return the size (in elements) of the view of memory this object + * represents. + */ + std::size_t + size() const; + + /** + * Return a bool whether the array view is empty. + */ + bool + empty() const; + + /** + * Return a pointer to the underlying array serving as element storage. + * In case the container is empty a nullptr is returned. + */ + DEAL_II_HOST_DEVICE value_type * + data() const noexcept; + + /** + * Return a reference to the $i$th element of the range represented by the + * current object. + * + * This function is marked as @p const because it does not change the + * view object. It may however return a reference to a non-@p const + * memory location depending on whether the template type of the class is @p + * const or not. + * + * This function is only allowed to be called if the underlying data is indeed + * stored in CPU memory. + */ + value_type & + operator[](const std::size_t i) const; + +protected: + /** + * A pointer to the first element of the range of locations in memory that + * this object represents. + */ + value_type *starting_element; + + /** + * The length of the array this object represents. + */ + std::size_t n_elements; +}; + + + +template +typename StridedArrayView::value_type & +StridedArrayView::operator[](const std::size_t i) const +{ + AssertIndexRange(i, this->n_elements); + + return *(this->starting_element + stride * i); +} + + + +template +DEAL_II_HOST_DEVICE typename StridedArrayView::value_type * +StridedArrayView::data() const noexcept +{ + if (this->n_elements == 0) + return nullptr; + else + return this->starting_element; +} + + + +template +bool +StridedArrayView::empty() const +{ + return this->n_elements == 0; +} + + + +template +std::size_t +StridedArrayView::size() const +{ + return this->n_elements; +} + + + +template +StridedArrayView::StridedArrayView( + value_type *starting_element, + const std::size_t n_elements) + : starting_element(starting_element) + , n_elements(n_elements) +{} + + /** * A class that represents a window of memory locations of type @p ElementType @@ -82,7 +218,7 @@ class LAPACKFullMatrix; * @ingroup data */ template -class ArrayView +class ArrayView : public StridedArrayView { public: /** @@ -309,26 +445,6 @@ public: operator!=(const ArrayView, MemorySpaceType> &other_view) const; - /** - * Return the size (in elements) of the view of memory this object - * represents. - */ - std::size_t - size() const; - - /** - * Return a bool whether the array view is empty. - */ - bool - empty() const; - - /** - * Return a pointer to the underlying array serving as element storage. - * In case the container is empty a nullptr is returned. - */ - DEAL_II_HOST_DEVICE value_type * - data() const noexcept; - /** * Return an iterator pointing to the beginning of the array view. */ @@ -353,33 +469,6 @@ public: const_iterator cend() const; - /** - * Return a reference to the $i$th element of the range represented by the - * current object. - * - * This function is marked as @p const because it does not change the - * view object. It may however return a reference to a non-@p const - * memory location depending on whether the template type of the class is @p - * const or not. - * - * This function is only allowed to be called if the underlying data is indeed - * stored in CPU memory. - */ - value_type & - operator[](const std::size_t i) const; - -private: - /** - * A pointer to the first element of the range of locations in memory that - * this object represents. - */ - value_type *starting_element; - - /** - * The length of the array this object represents. - */ - std::size_t n_elements; - friend class ArrayView; }; @@ -390,8 +479,7 @@ private: template inline ArrayView::ArrayView() - : starting_element(nullptr) - , n_elements(0) + : StridedArrayView(nullptr, 0) {} @@ -400,8 +488,7 @@ template inline ArrayView::ArrayView( value_type *starting_element, const std::size_t n_elements) - : starting_element(starting_element) - , n_elements(n_elements) + : StridedArrayView(starting_element, n_elements) {} @@ -419,8 +506,7 @@ ArrayView::reinit(value_type *starting_element, template inline ArrayView::ArrayView(ElementType &element) - : starting_element(&element) - , n_elements(1) + : StridedArrayView(&element, 1) {} @@ -428,8 +514,7 @@ inline ArrayView::ArrayView(ElementType &element) template inline ArrayView::ArrayView( const ArrayView, MemorySpaceType> &view) - : starting_element(view.starting_element) - , n_elements(view.n_elements) + : StridedArrayView(view.starting_element, view.n_elements) {} @@ -516,8 +601,8 @@ inline bool ArrayView::operator==( const ArrayView &other_view) const { - return (other_view.data() == starting_element) && - (other_view.size() == n_elements); + return (other_view.data() == this->starting_element) && + (other_view.size() == this->n_elements); } @@ -528,8 +613,8 @@ ArrayView::operator==( const ArrayView, MemorySpaceType> &other_view) const { - return (other_view.data() == starting_element) && - (other_view.size() == n_elements); + return (other_view.data() == this->starting_element) && + (other_view.size() == this->n_elements); } @@ -544,19 +629,6 @@ ArrayView::operator!=( -template -inline DEAL_II_HOST_DEVICE - typename ArrayView::value_type * - ArrayView::data() const noexcept -{ - if (n_elements == 0) - return nullptr; - else - return starting_element; -} - - - template inline bool ArrayView::operator!=( @@ -568,29 +640,11 @@ ArrayView::operator!=( -template -inline std::size_t -ArrayView::size() const -{ - return n_elements; -} - - - -template -inline bool -ArrayView::empty() const -{ - return n_elements == 0; -} - - - template inline typename ArrayView::iterator ArrayView::begin() const { - return starting_element; + return this->starting_element; } @@ -599,7 +653,7 @@ template inline typename ArrayView::iterator ArrayView::end() const { - return starting_element + n_elements; + return this->starting_element + this->n_elements; } @@ -608,7 +662,7 @@ template inline typename ArrayView::const_iterator ArrayView::cbegin() const { - return starting_element; + return this->starting_element; } @@ -617,18 +671,7 @@ template inline typename ArrayView::const_iterator ArrayView::cend() const { - return starting_element + n_elements; -} - - - -template -inline typename ArrayView::value_type & -ArrayView::operator[](const std::size_t i) const -{ - AssertIndexRange(i, n_elements); - - return *(starting_element + i); + return this->starting_element + this->n_elements; } -- 2.39.5