master
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===---------------------------------------------------------------------===//
9
10/*
11
12// Overall mdspan synopsis
13
14namespace std {
15 // [mdspan.extents], class template extents
16 template<class IndexType, size_t... Extents>
17 class extents;
18
19 // [mdspan.extents.dextents], alias template dextents
20 template<class IndexType, size_t Rank>
21 using dextents = see below;
22
23 // [mdspan.extents.dims], alias template dims
24 template<size_t Rank, class IndexType = size_t>
25 using dims = see below; // since C++26
26
27 // [mdspan.layout], layout mapping
28 struct layout_left;
29 struct layout_right;
30 struct layout_stride;
31
32 // [mdspan.accessor.default], class template default_accessor
33 template<class ElementType>
34 class default_accessor;
35
36 // [mdspan.accessor.aligned], class template aligned_accessor
37 template<class ElementType, size_t ByteAlignment>
38 class aligned_accessor; // since C++26
39
40 // [mdspan.mdspan], class template mdspan
41 template<class ElementType, class Extents, class LayoutPolicy = layout_right,
42 class AccessorPolicy = default_accessor<ElementType>>
43 class mdspan;
44}
45
46// extents synopsis
47
48namespace std {
49 template<class _IndexType, size_t... _Extents>
50 class extents {
51 public:
52 using index_type = _IndexType;
53 using size_type = make_unsigned_t<index_type>;
54 using rank_type = size_t;
55
56 // [mdspan.extents.obs], observers of the multidimensional index space
57 static constexpr rank_type rank() noexcept { return sizeof...(_Extents); }
58 static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); }
59 static constexpr size_t static_extent(rank_type) noexcept;
60 constexpr index_type extent(rank_type) const noexcept;
61
62 // [mdspan.extents.cons], constructors
63 constexpr extents() noexcept = default;
64
65 template<class _OtherIndexType, size_t... _OtherExtents>
66 constexpr explicit(see below)
67 extents(const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
68 template<class... _OtherIndexTypes>
69 constexpr explicit extents(_OtherIndexTypes...) noexcept;
70 template<class _OtherIndexType, size_t N>
71 constexpr explicit(N != rank_dynamic())
72 extents(span<_OtherIndexType, N>) noexcept;
73 template<class _OtherIndexType, size_t N>
74 constexpr explicit(N != rank_dynamic())
75 extents(const array<_OtherIndexType, N>&) noexcept;
76
77 // [mdspan.extents.cmp], comparison operators
78 template<class _OtherIndexType, size_t... _OtherExtents>
79 friend constexpr bool operator==(const extents&,
80 const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
81
82 private:
83 // libcxx note: we do not use an array here, but we need to preserve the as-if behavior
84 // for example the default constructor must zero initialize dynamic extents
85 array<index_type, rank_dynamic()> dynamic-extents{}; // exposition only
86 };
87
88 template<class... Integrals>
89 explicit extents(Integrals...)
90 -> see below;
91}
92
93// layout_left synopsis
94
95namespace std {
96 template<class Extents>
97 class layout_left::mapping {
98 public:
99 using extents_type = Extents;
100 using index_type = typename extents_type::index_type;
101 using size_type = typename extents_type::size_type;
102 using rank_type = typename extents_type::rank_type;
103 using layout_type = layout_left;
104
105 // [mdspan.layout.right.cons], constructors
106 constexpr mapping() noexcept = default;
107 constexpr mapping(const mapping&) noexcept = default;
108 constexpr mapping(const extents_type&) noexcept;
109 template<class OtherExtents>
110 constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
111 mapping(const mapping<OtherExtents>&) noexcept;
112 template<class OtherExtents>
113 constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
114 mapping(const layout_right::mapping<OtherExtents>&) noexcept;
115 template<class OtherExtents>
116 constexpr explicit(extents_type::rank() > 0)
117 mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
118
119 constexpr mapping& operator=(const mapping&) noexcept = default;
120
121 // [mdspan.layout.right.obs], observers
122 constexpr const extents_type& extents() const noexcept { return extents_; }
123
124 constexpr index_type required_span_size() const noexcept;
125
126 template<class... Indices>
127 constexpr index_type operator()(Indices...) const noexcept;
128
129 static constexpr bool is_always_unique() noexcept { return true; }
130 static constexpr bool is_always_exhaustive() noexcept { return true; }
131 static constexpr bool is_always_strided() noexcept { return true; }
132
133 static constexpr bool is_unique() noexcept { return true; }
134 static constexpr bool is_exhaustive() noexcept { return true; }
135 static constexpr bool is_strided() noexcept { return true; }
136
137 constexpr index_type stride(rank_type) const noexcept;
138
139 template<class OtherExtents>
140 friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
141
142 private:
143 extents_type extents_{}; // exposition only
144 };
145}
146
147// layout_right synopsis
148
149namespace std {
150 template<class Extents>
151 class layout_right::mapping {
152 public:
153 using extents_type = Extents;
154 using index_type = typename extents_type::index_type;
155 using size_type = typename extents_type::size_type;
156 using rank_type = typename extents_type::rank_type;
157 using layout_type = layout_right;
158
159 // [mdspan.layout.right.cons], constructors
160 constexpr mapping() noexcept = default;
161 constexpr mapping(const mapping&) noexcept = default;
162 constexpr mapping(const extents_type&) noexcept;
163 template<class OtherExtents>
164 constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
165 mapping(const mapping<OtherExtents>&) noexcept;
166 template<class OtherExtents>
167 constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
168 mapping(const layout_left::mapping<OtherExtents>&) noexcept;
169 template<class OtherExtents>
170 constexpr explicit(extents_type::rank() > 0)
171 mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
172
173 constexpr mapping& operator=(const mapping&) noexcept = default;
174
175 // [mdspan.layout.right.obs], observers
176 constexpr const extents_type& extents() const noexcept { return extents_; }
177
178 constexpr index_type required_span_size() const noexcept;
179
180 template<class... Indices>
181 constexpr index_type operator()(Indices...) const noexcept;
182
183 static constexpr bool is_always_unique() noexcept { return true; }
184 static constexpr bool is_always_exhaustive() noexcept { return true; }
185 static constexpr bool is_always_strided() noexcept { return true; }
186
187 static constexpr bool is_unique() noexcept { return true; }
188 static constexpr bool is_exhaustive() noexcept { return true; }
189 static constexpr bool is_strided() noexcept { return true; }
190
191 constexpr index_type stride(rank_type) const noexcept;
192
193 template<class OtherExtents>
194 friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
195
196 private:
197 extents_type extents_{}; // exposition only
198 };
199}
200
201// layout_stride synopsis
202
203namespace std {
204 template<class Extents>
205 class layout_stride::mapping {
206 public:
207 using extents_type = Extents;
208 using index_type = typename extents_type::index_type;
209 using size_type = typename extents_type::size_type;
210 using rank_type = typename extents_type::rank_type;
211 using layout_type = layout_stride;
212
213 private:
214 static constexpr rank_type rank_ = extents_type::rank(); // exposition only
215
216 public:
217 // [mdspan.layout.stride.cons], constructors
218 constexpr mapping() noexcept;
219 constexpr mapping(const mapping&) noexcept = default;
220 template<class OtherIndexType>
221 constexpr mapping(const extents_type&, span<OtherIndexType, rank_>) noexcept;
222 template<class OtherIndexType>
223 constexpr mapping(const extents_type&, const array<OtherIndexType, rank_>&) noexcept;
224
225 template<class StridedLayoutMapping>
226 constexpr explicit(see below) mapping(const StridedLayoutMapping&) noexcept;
227
228 constexpr mapping& operator=(const mapping&) noexcept = default;
229
230 // [mdspan.layout.stride.obs], observers
231 constexpr const extents_type& extents() const noexcept { return extents_; }
232 constexpr array<index_type, rank_> strides() const noexcept { return strides_; }
233
234 constexpr index_type required_span_size() const noexcept;
235
236 template<class... Indices>
237 constexpr index_type operator()(Indices...) const noexcept;
238
239 static constexpr bool is_always_unique() noexcept { return true; }
240 static constexpr bool is_always_exhaustive() noexcept { return false; }
241 static constexpr bool is_always_strided() noexcept { return true; }
242
243 static constexpr bool is_unique() noexcept { return true; }
244 constexpr bool is_exhaustive() const noexcept;
245 static constexpr bool is_strided() noexcept { return true; }
246
247 constexpr index_type stride(rank_type i) const noexcept { return strides_[i]; }
248
249 template<class OtherMapping>
250 friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
251
252 private:
253 extents_type extents_{}; // exposition only
254 array<index_type, rank_> strides_{}; // exposition only
255 };
256}
257
258// default_accessor synopsis
259
260namespace std {
261 template<class ElementType>
262 struct default_accessor {
263 using offset_policy = default_accessor;
264 using element_type = ElementType;
265 using reference = ElementType&;
266 using data_handle_type = ElementType*;
267
268 constexpr default_accessor() noexcept = default;
269 template<class OtherElementType>
270 constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
271 constexpr reference access(data_handle_type p, size_t i) const noexcept;
272 constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
273 };
274}
275
276// aligned_accessor synopsis
277
278namespace std {
279 template<class ElementType, size_t ByteAlignment>
280 struct aligned_accessor {
281 using offset_policy = default_accessor<ElementType>;
282 using element_type = ElementType;
283 using reference = ElementType&;
284 using data_handle_type = ElementType*;
285
286 static constexpr size_t byte_alignment = ByteAlignment;
287
288 constexpr aligned_accessor() noexcept = default;
289
290 template<class OtherElementType, size_t OtherByteAlignment>
291 constexpr aligned_accessor(
292 aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
293
294 template<class OtherElementType>
295 explicit constexpr aligned_accessor(
296 default_accessor<OtherElementType>) noexcept;
297
298 template<class OtherElementType>
299 constexpr operator default_accessor<OtherElementType>() const noexcept;
300
301 constexpr reference access(data_handle_type p, size_t i) const noexcept;
302
303 constexpr typename offset_policy::data_handle_type
304 offset(data_handle_type p, size_t i) const noexcept;
305 };
306}
307
308// mdspan synopsis
309
310namespace std {
311 template<class ElementType, class Extents, class LayoutPolicy = layout_right,
312 class AccessorPolicy = default_accessor<ElementType>>
313 class mdspan {
314 public:
315 using extents_type = Extents;
316 using layout_type = LayoutPolicy;
317 using accessor_type = AccessorPolicy;
318 using mapping_type = typename layout_type::template mapping<extents_type>;
319 using element_type = ElementType;
320 using value_type = remove_cv_t<element_type>;
321 using index_type = typename extents_type::index_type;
322 using size_type = typename extents_type::size_type;
323 using rank_type = typename extents_type::rank_type;
324 using data_handle_type = typename accessor_type::data_handle_type;
325 using reference = typename accessor_type::reference;
326
327 static constexpr rank_type rank() noexcept { return extents_type::rank(); }
328 static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
329 static constexpr size_t static_extent(rank_type r) noexcept
330 { return extents_type::static_extent(r); }
331 constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); }
332
333 // [mdspan.mdspan.cons], constructors
334 constexpr mdspan();
335 constexpr mdspan(const mdspan& rhs) = default;
336 constexpr mdspan(mdspan&& rhs) = default;
337
338 template<class... OtherIndexTypes>
339 constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts);
340 template<class OtherIndexType, size_t N>
341 constexpr explicit(N != rank_dynamic())
342 mdspan(data_handle_type p, span<OtherIndexType, N> exts);
343 template<class OtherIndexType, size_t N>
344 constexpr explicit(N != rank_dynamic())
345 mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
346 constexpr mdspan(data_handle_type p, const extents_type& ext);
347 constexpr mdspan(data_handle_type p, const mapping_type& m);
348 constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
349
350 template<class OtherElementType, class OtherExtents,
351 class OtherLayoutPolicy, class OtherAccessorPolicy>
352 constexpr explicit(see below)
353 mdspan(const mdspan<OtherElementType, OtherExtents,
354 OtherLayoutPolicy, OtherAccessorPolicy>& other);
355
356 constexpr mdspan& operator=(const mdspan& rhs) = default;
357 constexpr mdspan& operator=(mdspan&& rhs) = default;
358
359 // [mdspan.mdspan.members], members
360 template<class... OtherIndexTypes>
361 constexpr reference operator[](OtherIndexTypes... indices) const;
362 template<class OtherIndexType>
363 constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
364 template<class OtherIndexType>
365 constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
366
367 constexpr size_type size() const noexcept;
368 [[nodiscard]] constexpr bool empty() const noexcept;
369
370 friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
371
372 constexpr const extents_type& extents() const noexcept { return map_.extents(); }
373 constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
374 constexpr const mapping_type& mapping() const noexcept { return map_; }
375 constexpr const accessor_type& accessor() const noexcept { return acc_; }
376
377 // per LWG-4021 "mdspan::is_always_meow() should be noexcept"
378 static constexpr bool is_always_unique() noexcept
379 { return mapping_type::is_always_unique(); }
380 static constexpr bool is_always_exhaustive() noexcept
381 { return mapping_type::is_always_exhaustive(); }
382 static constexpr bool is_always_strided() noexcept
383 { return mapping_type::is_always_strided(); }
384
385 constexpr bool is_unique() const
386 { return map_.is_unique(); }
387 constexpr bool is_exhaustive() const
388 { return map_.is_exhaustive(); }
389 constexpr bool is_strided() const
390 { return map_.is_strided(); }
391 constexpr index_type stride(rank_type r) const
392 { return map_.stride(r); }
393
394 private:
395 accessor_type acc_; // exposition only
396 mapping_type map_; // exposition only
397 data_handle_type ptr_; // exposition only
398 };
399
400 template<class CArray>
401 requires(is_array_v<CArray> && rank_v<CArray> == 1)
402 mdspan(CArray&)
403 -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;
404
405 template<class Pointer>
406 requires(is_pointer_v<remove_reference_t<Pointer>>)
407 mdspan(Pointer&&)
408 -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
409
410 template<class ElementType, class... Integrals>
411 requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
412 explicit mdspan(ElementType*, Integrals...)
413 -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>; // until C++26
414 template<class ElementType, class... Integrals>
415 requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
416 explicit mdspan(ElementType*, Integrals...)
417 -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>; // since C++26
418
419 template<class ElementType, class OtherIndexType, size_t N>
420 mdspan(ElementType*, span<OtherIndexType, N>)
421 -> mdspan<ElementType, dextents<size_t, N>>;
422
423 template<class ElementType, class OtherIndexType, size_t N>
424 mdspan(ElementType*, const array<OtherIndexType, N>&)
425 -> mdspan<ElementType, dextents<size_t, N>>;
426
427 template<class ElementType, class IndexType, size_t... ExtentsPack>
428 mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)
429 -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;
430
431 template<class ElementType, class MappingType>
432 mdspan(ElementType*, const MappingType&)
433 -> mdspan<ElementType, typename MappingType::extents_type,
434 typename MappingType::layout_type>;
435
436 template<class MappingType, class AccessorType>
437 mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
438 const AccessorType&)
439 -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
440 typename MappingType::layout_type, AccessorType>;
441}
442*/
443
444#ifndef _LIBCPP_MDSPAN
445#define _LIBCPP_MDSPAN
446
447#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
448# include <__cxx03/__config>
449#else
450# include <__config>
451
452# if _LIBCPP_STD_VER >= 23
453# include <__fwd/mdspan.h> // TODO(boomanaiden154): This is currently a
454 // non-standard extension to include
455 // std::dynamic_extent tracked by LWG issue 4275.
456 // This comment should be deleted or the include
457 // deleted upon resolution.
458# include <__fwd/span.h>
459# include <__mdspan/default_accessor.h>
460# include <__mdspan/extents.h>
461# include <__mdspan/layout_left.h>
462# include <__mdspan/layout_right.h>
463# include <__mdspan/layout_stride.h>
464# include <__mdspan/mdspan.h>
465# endif
466
467# include <version>
468
469# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
470# pragma GCC system_header
471# endif
472#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
473
474#endif // _LIBCPP_MDSPAN