Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement StridedArrayView #15972

Merged
merged 2 commits into from
Sep 17, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
137 changes: 137 additions & 0 deletions include/deal.II/base/array_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,143 @@ ArrayView<ElementType, MemorySpaceType>::operator[](const std::size_t i) const



/**
* A variation 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 <typename ElementType, std::size_t stride = 1>
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.
*/
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
* <em>view object</em>. 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 ElementType, std::size_t stride>
typename StridedArrayView<ElementType, stride>::value_type &
StridedArrayView<ElementType, stride>::operator[](const std::size_t i) const
{
AssertIndexRange(i, this->n_elements);

return *(this->starting_element + stride * i);
}



template <typename ElementType, std::size_t stride>
typename StridedArrayView<ElementType, stride>::value_type *
StridedArrayView<ElementType, stride>::data() const noexcept
{
if (this->n_elements == 0)
return nullptr;
else
return this->starting_element;
}



template <typename ElementType, std::size_t stride>
bool
StridedArrayView<ElementType, stride>::empty() const
{
return this->n_elements == 0;
}



template <typename ElementType, std::size_t stride>
std::size_t
StridedArrayView<ElementType, stride>::size() const
{
return this->n_elements;
}



template <typename ElementType, std::size_t stride>
StridedArrayView<ElementType, stride>::StridedArrayView(
value_type *starting_element,
const std::size_t n_elements)
: starting_element(starting_element)
, n_elements(n_elements)
{}



#ifndef DOXYGEN
namespace internal
{
Expand Down