xref: /freebsd/contrib/llvm-project/libcxx/include/mdspan (revision 357378bbdedf24ce2b90e9bd831af4a9db3ec70a)
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;
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// layout_stride synopsis
194
195namespace std {
196  template<class Extents>
197  class layout_stride::mapping {
198  public:
199    using extents_type = Extents;
200    using index_type = typename extents_type::index_type;
201    using size_type = typename extents_type::size_type;
202    using rank_type = typename extents_type::rank_type;
203    using layout_type = layout_stride;
204
205  private:
206    static constexpr rank_type rank_ = extents_type::rank();    // exposition only
207
208  public:
209    // [mdspan.layout.stride.cons], constructors
210    constexpr mapping() noexcept;
211    constexpr mapping(const mapping&) noexcept = default;
212    template<class OtherIndexType>
213      constexpr mapping(const extents_type&, span<OtherIndexType, rank_>) noexcept;
214    template<class OtherIndexType>
215      constexpr mapping(const extents_type&, const array<OtherIndexType, rank_>&) noexcept;
216
217    template<class StridedLayoutMapping>
218      constexpr explicit(see below) mapping(const StridedLayoutMapping&) noexcept;
219
220    constexpr mapping& operator=(const mapping&) noexcept = default;
221
222    // [mdspan.layout.stride.obs], observers
223    constexpr const extents_type& extents() const noexcept { return extents_; }
224    constexpr array<index_type, rank_> strides() const noexcept { return strides_; }
225
226    constexpr index_type required_span_size() const noexcept;
227
228    template<class... Indices>
229      constexpr index_type operator()(Indices...) const noexcept;
230
231    static constexpr bool is_always_unique() noexcept { return true; }
232    static constexpr bool is_always_exhaustive() noexcept { return false; }
233    static constexpr bool is_always_strided() noexcept { return true; }
234
235    static constexpr bool is_unique() noexcept { return true; }
236    constexpr bool is_exhaustive() const noexcept;
237    static constexpr bool is_strided() noexcept { return true; }
238
239    constexpr index_type stride(rank_type i) const noexcept { return strides_[i]; }
240
241    template<class OtherMapping>
242      friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
243
244  private:
245    extents_type extents_{};                    // exposition only
246    array<index_type, rank_> strides_{};        // exposition only
247  };
248}
249
250// default_accessor synopsis
251
252namespace std {
253  template<class ElementType>
254  struct default_accessor {
255    using offset_policy = default_accessor;
256    using element_type = ElementType;
257    using reference = ElementType&;
258    using data_handle_type = ElementType*;
259
260    constexpr default_accessor() noexcept = default;
261    template<class OtherElementType>
262      constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
263    constexpr reference access(data_handle_type p, size_t i) const noexcept;
264    constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
265  };
266}
267
268// mdspan synopsis
269
270namespace std {
271  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
272           class AccessorPolicy = default_accessor<ElementType>>
273  class mdspan {
274  public:
275    using extents_type = Extents;
276    using layout_type = LayoutPolicy;
277    using accessor_type = AccessorPolicy;
278    using mapping_type = typename layout_type::template mapping<extents_type>;
279    using element_type = ElementType;
280    using value_type = remove_cv_t<element_type>;
281    using index_type = typename extents_type::index_type;
282    using size_type = typename extents_type::size_type;
283    using rank_type = typename extents_type::rank_type;
284    using data_handle_type = typename accessor_type::data_handle_type;
285    using reference = typename accessor_type::reference;
286
287    static constexpr rank_type rank() noexcept { return extents_type::rank(); }
288    static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
289    static constexpr size_t static_extent(rank_type r) noexcept
290      { return extents_type::static_extent(r); }
291    constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); }
292
293    // [mdspan.mdspan.cons], constructors
294    constexpr mdspan();
295    constexpr mdspan(const mdspan& rhs) = default;
296    constexpr mdspan(mdspan&& rhs) = default;
297
298    template<class... OtherIndexTypes>
299      constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts);
300    template<class OtherIndexType, size_t N>
301      constexpr explicit(N != rank_dynamic())
302        mdspan(data_handle_type p, span<OtherIndexType, N> exts);
303    template<class OtherIndexType, size_t N>
304      constexpr explicit(N != rank_dynamic())
305        mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
306    constexpr mdspan(data_handle_type p, const extents_type& ext);
307    constexpr mdspan(data_handle_type p, const mapping_type& m);
308    constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
309
310    template<class OtherElementType, class OtherExtents,
311             class OtherLayoutPolicy, class OtherAccessorPolicy>
312      constexpr explicit(see below)
313        mdspan(const mdspan<OtherElementType, OtherExtents,
314                            OtherLayoutPolicy, OtherAccessorPolicy>& other);
315
316    constexpr mdspan& operator=(const mdspan& rhs) = default;
317    constexpr mdspan& operator=(mdspan&& rhs) = default;
318
319    // [mdspan.mdspan.members], members
320    template<class... OtherIndexTypes>
321      constexpr reference operator[](OtherIndexTypes... indices) const;
322    template<class OtherIndexType>
323      constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
324    template<class OtherIndexType>
325      constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
326
327    constexpr size_type size() const noexcept;
328    [[nodiscard]] constexpr bool empty() const noexcept;
329
330    friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
331
332    constexpr const extents_type& extents() const noexcept { return map_.extents(); }
333    constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
334    constexpr const mapping_type& mapping() const noexcept { return map_; }
335    constexpr const accessor_type& accessor() const noexcept { return acc_; }
336
337    // per LWG-4021 "mdspan::is_always_meow() should be noexcept"
338    static constexpr bool is_always_unique() noexcept
339      { return mapping_type::is_always_unique(); }
340    static constexpr bool is_always_exhaustive() noexcept
341      { return mapping_type::is_always_exhaustive(); }
342    static constexpr bool is_always_strided() noexcept
343      { return mapping_type::is_always_strided(); }
344
345    constexpr bool is_unique() const
346      { return map_.is_unique(); }
347    constexpr bool is_exhaustive() const
348      { return map_.is_exhaustive(); }
349    constexpr bool is_strided() const
350      { return map_.is_strided(); }
351    constexpr index_type stride(rank_type r) const
352      { return map_.stride(r); }
353
354  private:
355    accessor_type acc_;         // exposition only
356    mapping_type map_;          // exposition only
357    data_handle_type ptr_;      // exposition only
358  };
359
360  template<class CArray>
361    requires(is_array_v<CArray> && rank_v<CArray> == 1)
362    mdspan(CArray&)
363      -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;
364
365  template<class Pointer>
366    requires(is_pointer_v<remove_reference_t<Pointer>>)
367    mdspan(Pointer&&)
368      -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
369
370  template<class ElementType, class... Integrals>
371    requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
372    explicit mdspan(ElementType*, Integrals...)
373      -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;
374
375  template<class ElementType, class OtherIndexType, size_t N>
376    mdspan(ElementType*, span<OtherIndexType, N>)
377      -> mdspan<ElementType, dextents<size_t, N>>;
378
379  template<class ElementType, class OtherIndexType, size_t N>
380    mdspan(ElementType*, const array<OtherIndexType, N>&)
381      -> mdspan<ElementType, dextents<size_t, N>>;
382
383  template<class ElementType, class IndexType, size_t... ExtentsPack>
384    mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)
385      -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;
386
387  template<class ElementType, class MappingType>
388    mdspan(ElementType*, const MappingType&)
389      -> mdspan<ElementType, typename MappingType::extents_type,
390                typename MappingType::layout_type>;
391
392  template<class MappingType, class AccessorType>
393    mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
394           const AccessorType&)
395      -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
396                typename MappingType::layout_type, AccessorType>;
397}
398*/
399
400#ifndef _LIBCPP_MDSPAN
401#define _LIBCPP_MDSPAN
402
403#include <__config>
404#include <__fwd/mdspan.h>
405#include <__mdspan/default_accessor.h>
406#include <__mdspan/extents.h>
407#include <__mdspan/layout_left.h>
408#include <__mdspan/layout_right.h>
409#include <__mdspan/layout_stride.h>
410#include <__mdspan/mdspan.h>
411#include <version>
412
413#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
414#  pragma GCC system_header
415#endif
416
417#endif // _LIBCPP_MDSPAN
418