Skip to content

Add SimpleArray::as_span() and as_mdspan<N>()#777

Merged
yungyuc merged 3 commits into
solvcon:masterfrom
yungyuc:feat/mdspan
May 15, 2026
Merged

Add SimpleArray::as_span() and as_mdspan<N>()#777
yungyuc merged 3 commits into
solvcon:masterfrom
yungyuc:feat/mdspan

Conversation

@yungyuc
Copy link
Copy Markdown
Member

@yungyuc yungyuc commented May 13, 2026

Expose C++23 view types over the contiguous buffer:

  • as_span() returns std::span<value_type> over the contiguous body.
  • as_mdspan<N>() returns std::mdspan<value_type, std::dextents<size_t, N>> built from shape(). Ghost indices are not subtracted. The view spans the full underlying storage.

Add gtests/test_nopython_mdspan.cpp covering 1D-4D shapes, ghost arrays for each rank, and the as_span() linear view.

This is for issue #771 .

@yungyuc yungyuc self-assigned this May 13, 2026
@yungyuc yungyuc added the array Multi-dimensional array implementation label May 13, 2026
Comment thread cpp/modmesh/buffer/SimpleArray.hpp Outdated
template <typename... Args>
value_type * vptr(Args... args) { return m_body + buffer_offset(m_stride, args...); }

std::span<value_type> as_span() { return std::span<value_type>(data(), size()); }
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linear view.

std::span<value_type const> as_span() const { return std::span<value_type const>(data(), size()); }

template <size_t N>
std::mdspan<value_type, std::dextents<size_t, N>> as_mdspan()
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-dimensional view.

{
if (ndim() != N)
{
throw std::out_of_range(
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Runtime shape check.

}
std::array<size_t, N> exts;
for (size_t i = 0; i < N; ++i) { exts[i] = shape(i); }
return std::mdspan<value_type, std::dextents<size_t, N>>(data(), exts);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use data(). Disregard ghost information.

#error "Python.h should not be included."
#endif

TEST(SimpleArray, mdspan_1d)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1D test. Uninteresting.

EXPECT_EQ(sp[3], 99.0);
}

TEST(SimpleArray, mdspan_1d_const)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Const test

for (size_t i = 0; i < 6; ++i) { EXPECT_EQ(sp[i], 5.0); }
}

TEST(SimpleArray, mdspan_1d_ghost)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test with ghost.

{
for (size_t j = 0; j < 4; ++j)
{
arr(i, j) = static_cast<double>(i * 4 + j);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2D test. A little bit interesting.

}
}

// Linear view over the C-contiguous buffer; sp[i*4+j] == arr(i, j).
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linear view for 2D buffer.

for (size_t k = 0; k < sp.size(); ++k) { EXPECT_EQ(sp[k], arr.data(k)); }
}

TEST(SimpleArray, mdspan_3d)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So on and so forth for 3D and 4D.

sudo ln -fs "$(which clang-tidy-22)" "/usr/local/bin/clang-tidy"

- name: Install and configure gcc-14
- name: Install and configure gcc-16
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GCC 14 and 15 with the ubuntu package did not have mdspan.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although we may face CI error when ubuntu PPA dies again, it seems that GCC 16 is necessary.

@yungyuc yungyuc marked this pull request as ready for review May 14, 2026 14:36
@yungyuc
Copy link
Copy Markdown
Member Author

yungyuc commented May 14, 2026

@tigercosmos @ExplorerRay @ThreeMonth03 please help take a look.

@yungyuc yungyuc requested review from KHLee529 and tigercosmos May 14, 2026 14:37
Copy link
Copy Markdown
Collaborator

@ExplorerRay ExplorerRay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Comment on lines +1961 to +1964
std::format("SimpleArray::as_mdspan: rank {} does not match ndim() {}", N, ndim()));
}
std::array<size_t, N> exts;
for (size_t i = 0; i < N; ++i) { exts[i] = shape(i); }
Copy link
Copy Markdown
Collaborator

@ThreeMonth03 ThreeMonth03 May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be checked whether SimpleArray is contiguous. The size of shape may not equal to the size of data().

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Added above.

yungyuc added 3 commits May 15, 2026 07:25
Expose C++23 view types over the contiguous buffer:

- `as_span()` returns `std::span<value_type>` over the contiguous body.
- `as_mdspan<N>()` returns `std::mdspan<value_type, std::dextents<size_t, N>>`
  built from `shape()`. Ghost indices are not subtracted. The view spans the
  full underlying storage.

Add `gtests/test_nopython_mdspan.cpp` covering 1D-4D shapes, ghost
arrays for each rank, and the `as_span()` linear view.
gcc-14 and gcc-15 from ppa:ubuntu-toolchain-r/test does not ship <mdspan> in
libstdc++-15-dev.
Both views assume linear row-major storage of prod(shape) elements starting at
data(). Reject a non-C-contiguous array (e.g., padded or strided view) with
std::runtime_error.

Add `SimpleArray.mdspan_non_contiguous` to cover the new guard.
Comment on lines +1961 to +1964
std::format("SimpleArray::as_mdspan: rank {} does not match ndim() {}", N, ndim()));
}
std::array<size_t, N> exts;
for (size_t i = 0; i < N; ++i) { exts[i] = shape(i); }
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Added above.

throw std::out_of_range(
std::format("SimpleArray::as_mdspan: rank {} does not match ndim() {}", N, ndim()));
}
if (!is_c_contiguous())
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throw if the buffer is not C-contiguous.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks great now.

EXPECT_THROW(arr.as_mdspan<3>(), std::out_of_range);
}

TEST(SimpleArray, mdspan_non_contiguous)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test for non-C-contiguous.

@yungyuc
Copy link
Copy Markdown
Member Author

yungyuc commented May 14, 2026

Rebased to latest master.

Copy link
Copy Markdown
Collaborator

@ThreeMonth03 ThreeMonth03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We may consider the non cotiguous case by another pull request.

throw std::out_of_range(
std::format("SimpleArray::as_mdspan: rank {} does not match ndim() {}", N, ndim()));
}
if (!is_c_contiguous())
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks great now.

@yungyuc
Copy link
Copy Markdown
Member Author

yungyuc commented May 15, 2026

One of the linter runs keeps timeout. It should be false alarm and I'll merge.

@yungyuc yungyuc merged commit bf36b16 into solvcon:master May 15, 2026
22 of 26 checks passed
@yungyuc yungyuc deleted the feat/mdspan branch May 15, 2026 03:09
@yungyuc yungyuc linked an issue May 15, 2026 that may be closed by this pull request
@yungyuc
Copy link
Copy Markdown
Member Author

yungyuc commented May 15, 2026

LGTM. We may consider the non cotiguous case by another pull request.

Tracking noncontiguous support in issue #784 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

array Multi-dimensional array implementation

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

SimpleArray to support std::mdspan

3 participants