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