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.layout], layout mapping
24  struct layout_left;
25  struct layout_right;
26  struct layout_stride; // not implemented yet
27
28  // [mdspan.accessor.default], class template default_accessor
29  template<class ElementType>
30    class default_accessor;
31
32  // [mdspan.mdspan], class template mdspan
33  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
34           class AccessorPolicy = default_accessor<ElementType>>
35    class mdspan; // not implemented yet
36}
37
38// extents synopsis
39
40namespace std {
41  template<class _IndexType, size_t... _Extents>
42  class extents {
43  public:
44    using index_type = _IndexType;
45    using size_type = make_unsigned_t<index_type>;
46    using rank_type = size_t;
47
48    // [mdspan.extents.obs], observers of the multidimensional index space
49    static constexpr rank_type rank() noexcept { return sizeof...(_Extents); }
50    static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); }
51    static constexpr size_t static_extent(rank_type) noexcept;
52    constexpr index_type extent(rank_type) const noexcept;
53
54    // [mdspan.extents.cons], constructors
55    constexpr extents() noexcept = default;
56
57    template<class _OtherIndexType, size_t... _OtherExtents>
58      constexpr explicit(see below)
59        extents(const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
60    template<class... _OtherIndexTypes>
61      constexpr explicit extents(_OtherIndexTypes...) noexcept;
62    template<class _OtherIndexType, size_t N>
63      constexpr explicit(N != rank_dynamic())
64        extents(span<_OtherIndexType, N>) noexcept;
65    template<class _OtherIndexType, size_t N>
66      constexpr explicit(N != rank_dynamic())
67        extents(const array<_OtherIndexType, N>&) noexcept;
68
69    // [mdspan.extents.cmp], comparison operators
70    template<class _OtherIndexType, size_t... _OtherExtents>
71      friend constexpr bool operator==(const extents&,
72                                       const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
73
74  private:
75    // libcxx note: we do not use an array here, but we need to preserve the as-if behavior
76    // for example the default constructor must zero initialize dynamic extents
77    array<index_type, rank_dynamic()> dynamic-extents{};                // exposition only
78  };
79
80  template<class... Integrals>
81    explicit extents(Integrals...)
82      -> see below;
83}
84
85// layout_left synopsis
86
87namespace std {
88  template<class Extents>
89  class layout_left::mapping {
90  public:
91    using extents_type = Extents;
92    using index_type = typename extents_type::index_type;
93    using size_type = typename extents_type::size_type;
94    using rank_type = typename extents_type::rank_type;
95    using layout_type = layout_left;
96
97    // [mdspan.layout.right.cons], constructors
98    constexpr mapping() noexcept = default;
99    constexpr mapping(const mapping&) noexcept = default;
100    constexpr mapping(const extents_type&) noexcept;
101    template<class OtherExtents>
102      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
103        mapping(const mapping<OtherExtents>&) noexcept;
104    template<class OtherExtents>
105      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
106        mapping(const layout_right::mapping<OtherExtents>&) noexcept;
107    template<class OtherExtents>
108      constexpr explicit(extents_type::rank() > 0)
109        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
110
111    constexpr mapping& operator=(const mapping&) noexcept = default;
112
113    // [mdspan.layout.right.obs], observers
114    constexpr const extents_type& extents() const noexcept { return extents_; }
115
116    constexpr index_type required_span_size() const noexcept;
117
118    template<class... Indices>
119      constexpr index_type operator()(Indices...) const noexcept;
120
121    static constexpr bool is_always_unique() noexcept { return true; }
122    static constexpr bool is_always_exhaustive() noexcept { return true; }
123    static constexpr bool is_always_strided() noexcept { return true; }
124
125    static constexpr bool is_unique() noexcept { return true; }
126    static constexpr bool is_exhaustive() noexcept { return true; }
127    static constexpr bool is_strided() noexcept { return true; }
128
129    constexpr index_type stride(rank_type) const noexcept;
130
131    template<class OtherExtents>
132      friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
133
134  private:
135    extents_type extents_{};    // exposition only
136  };
137}
138
139// layout_right synopsis
140
141namespace std {
142  template<class Extents>
143  class layout_right::mapping {
144  public:
145    using extents_type = Extents;
146    using index_type = typename extents_type::index_type;
147    using size_type = typename extents_type::size_type;
148    using rank_type = typename extents_type::rank_type;
149    using layout_type = layout_right;
150
151    // [mdspan.layout.right.cons], constructors
152    constexpr mapping() noexcept = default;
153    constexpr mapping(const mapping&) noexcept = default;
154    constexpr mapping(const extents_type&) noexcept;
155    template<class OtherExtents>
156      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
157        mapping(const mapping<OtherExtents>&) noexcept;
158    template<class OtherExtents>
159      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
160        mapping(const layout_left::mapping<OtherExtents>&) noexcept;
161    template<class OtherExtents>
162      constexpr explicit(extents_type::rank() > 0)
163        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
164
165    constexpr mapping& operator=(const mapping&) noexcept = default;
166
167    // [mdspan.layout.right.obs], observers
168    constexpr const extents_type& extents() const noexcept { return extents_; }
169
170    constexpr index_type required_span_size() const noexcept;
171
172    template<class... Indices>
173      constexpr index_type operator()(Indices...) const noexcept;
174
175    static constexpr bool is_always_unique() noexcept { return true; }
176    static constexpr bool is_always_exhaustive() noexcept { return true; }
177    static constexpr bool is_always_strided() noexcept { return true; }
178
179    static constexpr bool is_unique() noexcept { return true; }
180    static constexpr bool is_exhaustive() noexcept { return true; }
181    static constexpr bool is_strided() noexcept { return true; }
182
183    constexpr index_type stride(rank_type) const noexcept;
184
185    template<class OtherExtents>
186      friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
187
188  private:
189    extents_type extents_{};    // exposition only
190  };
191}
192
193// default_accessor synopsis
194
195namespace std {
196  template<class ElementType>
197  struct default_accessor {
198    using offset_policy = default_accessor;
199    using element_type = ElementType;
200    using reference = ElementType&;
201    using data_handle_type = ElementType*;
202
203    constexpr default_accessor() noexcept = default;
204    template<class OtherElementType>
205      constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
206    constexpr reference access(data_handle_type p, size_t i) const noexcept;
207    constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
208  };
209}
210
211// mdspan synopsis
212
213namespace std {
214  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
215           class AccessorPolicy = default_accessor<ElementType>>
216  class mdspan {
217  public:
218    using extents_type = Extents;
219    using layout_type = LayoutPolicy;
220    using accessor_type = AccessorPolicy;
221    using mapping_type = typename layout_type::template mapping<extents_type>;
222    using element_type = ElementType;
223    using value_type = remove_cv_t<element_type>;
224    using index_type = typename extents_type::index_type;
225    using size_type = typename extents_type::size_type;
226    using rank_type = typename extents_type::rank_type;
227    using data_handle_type = typename accessor_type::data_handle_type;
228    using reference = typename accessor_type::reference;
229
230    static constexpr rank_type rank() noexcept { return extents_type::rank(); }
231    static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
232    static constexpr size_t static_extent(rank_type r) noexcept
233      { return extents_type::static_extent(r); }
234    constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); }
235
236    // [mdspan.mdspan.cons], constructors
237    constexpr mdspan();
238    constexpr mdspan(const mdspan& rhs) = default;
239    constexpr mdspan(mdspan&& rhs) = default;
240
241    template<class... OtherIndexTypes>
242      constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts);
243    template<class OtherIndexType, size_t N>
244      constexpr explicit(N != rank_dynamic())
245        mdspan(data_handle_type p, span<OtherIndexType, N> exts);
246    template<class OtherIndexType, size_t N>
247      constexpr explicit(N != rank_dynamic())
248        mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
249    constexpr mdspan(data_handle_type p, const extents_type& ext);
250    constexpr mdspan(data_handle_type p, const mapping_type& m);
251    constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
252
253    template<class OtherElementType, class OtherExtents,
254             class OtherLayoutPolicy, class OtherAccessorPolicy>
255      constexpr explicit(see below)
256        mdspan(const mdspan<OtherElementType, OtherExtents,
257                            OtherLayoutPolicy, OtherAccessorPolicy>& other);
258
259    constexpr mdspan& operator=(const mdspan& rhs) = default;
260    constexpr mdspan& operator=(mdspan&& rhs) = default;
261
262    // [mdspan.mdspan.members], members
263    template<class... OtherIndexTypes>
264      constexpr reference operator[](OtherIndexTypes... indices) const;
265    template<class OtherIndexType>
266      constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
267    template<class OtherIndexType>
268      constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
269
270    constexpr size_type size() const noexcept;
271    [[nodiscard]] constexpr bool empty() const noexcept;
272
273    friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
274
275    constexpr const extents_type& extents() const noexcept { return map_.extents(); }
276    constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
277    constexpr const mapping_type& mapping() const noexcept { return map_; }
278    constexpr const accessor_type& accessor() const noexcept { return acc_; }
279
280    static constexpr bool is_always_unique()
281      { return mapping_type::is_always_unique(); }
282    static constexpr bool is_always_exhaustive()
283      { return mapping_type::is_always_exhaustive(); }
284    static constexpr bool is_always_strided()
285      { return mapping_type::is_always_strided(); }
286
287    constexpr bool is_unique() const
288      { return map_.is_unique(); }
289    constexpr bool is_exhaustive() const
290      { return map_.is_exhaustive(); }
291    constexpr bool is_strided() const
292      { return map_.is_strided(); }
293    constexpr index_type stride(rank_type r) const
294      { return map_.stride(r); }
295
296  private:
297    accessor_type acc_;         // exposition only
298    mapping_type map_;          // exposition only
299    data_handle_type ptr_;      // exposition only
300  };
301
302  template<class CArray>
303    requires(is_array_v<CArray> && rank_v<CArray> == 1)
304    mdspan(CArray&)
305      -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;
306
307  template<class Pointer>
308    requires(is_pointer_v<remove_reference_t<Pointer>>)
309    mdspan(Pointer&&)
310      -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
311
312  template<class ElementType, class... Integrals>
313    requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
314    explicit mdspan(ElementType*, Integrals...)
315      -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;
316
317  template<class ElementType, class OtherIndexType, size_t N>
318    mdspan(ElementType*, span<OtherIndexType, N>)
319      -> mdspan<ElementType, dextents<size_t, N>>;
320
321  template<class ElementType, class OtherIndexType, size_t N>
322    mdspan(ElementType*, const array<OtherIndexType, N>&)
323      -> mdspan<ElementType, dextents<size_t, N>>;
324
325  template<class ElementType, class IndexType, size_t... ExtentsPack>
326    mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)
327      -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;
328
329  template<class ElementType, class MappingType>
330    mdspan(ElementType*, const MappingType&)
331      -> mdspan<ElementType, typename MappingType::extents_type,
332                typename MappingType::layout_type>;
333
334  template<class MappingType, class AccessorType>
335    mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
336           const AccessorType&)
337      -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
338                typename MappingType::layout_type, AccessorType>;
339}
340*/
341
342#ifndef _LIBCPP_MDSPAN
343#define _LIBCPP_MDSPAN
344
345#include <__config>
346#include <__fwd/mdspan.h>
347#include <__mdspan/default_accessor.h>
348#include <__mdspan/extents.h>
349#include <__mdspan/layout_left.h>
350#include <__mdspan/layout_right.h>
351#include <__mdspan/mdspan.h>
352
353#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
354#  pragma GCC system_header
355#endif
356
357#endif // _LIBCPP_MDSPAN
358