Skip to content

Commit ea3d054

Browse files
committed
Add conversion from contiguous range to ndview
1 parent 7616af3 commit ea3d054

4 files changed

Lines changed: 122 additions & 2 deletions

File tree

doc/vt/ndarray/view/constructor.md

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,22 @@ vt::ndview::ndview
22
==================
33

44
```c++
5+
// (1)
56
constexpr ndview(const std::array<std::size_t, N>& shape, T* data) noexcept;
7+
// (2)
8+
template<ndview_compatible_range<T> R>
9+
constexpr ndview(R&& r) noexcept requires(N == 1);
10+
// (3)
11+
constexpr ndview(
12+
std::initializer_list<std::remove_cv_t<T>> il
13+
) noexcept requires(std::is_const_v<T> && N == 1);
614
```
715
8-
Constructs the view for the given shape over the given data.
16+
Constructs a view from given data, a range or initializer list.
917
10-
The behavior is undefined if the array pointed to by `data` contains less than `shape[0] * ... * shape[N-1]` elements.
18+
1. Constructs the view for the given shape over the given data. The behavior is undefined if the array pointed to by `data` contains less than `shape[0] * ... * shape[N-1]` elements.
19+
2. Constructs the 1D view from the given contiguous range.
20+
3. Constructs the 1D view from the given initializer list.
1121
1222
Parameters
1323
----------
@@ -16,3 +26,32 @@ Parameters
1626
--------- | --------------------------------------------------------------------
1727
**shape** | an array containing the size of the data in each dimension
1828
**data** | a pointer to the array containing the data that is to be viewed into
29+
**r** | a contiguous range to view into
30+
**il** | an initializer list to view into
31+
32+
Example
33+
-------
34+
35+
```c++
36+
#include <vt/ndarray/view.hpp>
37+
#include <iostream>
38+
39+
int sum(vt::ndview<const int, 1> x) {
40+
int sum_x = 0;
41+
for (int x_i : x) sum_x += x_i;
42+
return sum_x;
43+
}
44+
45+
int main() {
46+
const std::array<int, 4> x = { 1, 2, 3, 4 };
47+
// A contiguous range, like std::array, can implicitly convert to a 1D
48+
// vt::ndview:
49+
std::cout << sum(x) << '\n';
50+
}
51+
```
52+
53+
Output:
54+
55+
```
56+
10
57+
```

include/vt/ndarray/impl/view.ipp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ constexpr ndview<T, N>::ndview(
4242
}
4343

4444

45+
template<typename T, std::size_t N>
46+
template<ndview_compatible_range<T> R>
47+
constexpr ndview<T, N>::ndview(R&& r) noexcept requires(N == 1) :
48+
ndview{{ std::ranges::size(r) }, std::ranges::data(r)}
49+
{
50+
}
51+
52+
53+
template<typename T, std::size_t N>
54+
constexpr ndview<T, N>::ndview(
55+
std::initializer_list<std::remove_cv_t<T>> il
56+
) noexcept requires(std::is_const_v<T> && N == 1) :
57+
ndview{{ il.size() }, il.begin()}
58+
{
59+
}
60+
61+
4562
template<typename T, std::size_t N>
4663
template<indexer... Index>
4764
constexpr decltype(auto) ndview<T, N>::operator[](

include/vt/ndarray/view.hpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,35 @@
2727
#include <cstddef>
2828
#include <iterator>
2929
#include <ostream>
30+
#include <ranges>
3031
#include <type_traits>
3132

3233

3334
namespace vt {
3435

36+
template<typename T, std::size_t N>
37+
class ndview;
38+
39+
template<typename>
40+
struct is_ndview : std::false_type {};
41+
42+
template<typename T, std::size_t N>
43+
struct is_ndview<ndview<T, N>> : std::true_type {};
44+
45+
template<typename T>
46+
inline constexpr bool is_ndview_v = is_ndview<T>::value;
47+
48+
template<typename R, typename T>
49+
concept ndview_compatible_range =
50+
std::is_convertible_v<
51+
std::remove_reference_t<std::ranges::range_reference_t<R>>(*)[],
52+
T(*)[]
53+
>
54+
&& std::ranges::contiguous_range<R>
55+
&& std::ranges::sized_range<R>
56+
&& (std::ranges::borrowed_range<R> || std::is_const_v<T>)
57+
&& !is_ndview_v<R>;
58+
3559
template<typename T, std::size_t N>
3660
class ndview {
3761
static_assert(N > 0);
@@ -54,6 +78,13 @@ class ndview {
5478
T* data_
5579
) noexcept;
5680

81+
template<ndview_compatible_range<T> R>
82+
constexpr ndview(R&& r) noexcept requires(N == 1);
83+
84+
constexpr ndview(
85+
std::initializer_list<std::remove_cv_t<T>> il
86+
) noexcept requires(std::is_const_v<T> && N == 1);
87+
5788
template<indexer... Index>
5889
constexpr decltype(auto) operator[](
5990
Index... idx

test/vt/ndarray/view_test.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,39 @@ TEST_CASE(
4040
}
4141

4242

43+
TEST_CASE(
44+
"A 1D vt::ndview can be implicitly constructed from a contiguous range",
45+
"[ndarray][view]"
46+
) {
47+
const std::array<int, 4> data = { 3, 1, 4, 1 };
48+
const vt::ndview<const int, 1> view = data;
49+
50+
REQUIRE(view.shape(0) == 4);
51+
CHECK(std::equal(data.begin(), data.end(), view.data()));
52+
}
53+
54+
55+
TEST_CASE(
56+
"A 1D vt::ndview can be implicitly constructed from an initializer list",
57+
"[ndarray][view]"
58+
) {
59+
const vt::ndview<const int, 1> view = { 3, 1, 4, 1 };
60+
61+
REQUIRE(view.shape(0) == 4);
62+
63+
const std::array<int, 4> expected = { 3, 1, 4, 1 };
64+
CHECK(std::equal(expected.begin(), expected.end(), view.data()));
65+
}
66+
67+
68+
TEST_CASE(
69+
"A vt::ndview is a contiguous range",
70+
"[ndarray][view]"
71+
) {
72+
STATIC_REQUIRE(std::ranges::contiguous_range<vt::ndview<int, 3>>);
73+
}
74+
75+
4376
TEST_CASE(
4477
"A vt::ndview can index into 1-dimensional data",
4578
"[ndarray][view]"

0 commit comments

Comments
 (0)