xref: /freebsd-src/contrib/llvm-project/libcxx/include/mdspan (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric// -*-C++ - *-
2*06c3fb27SDimitry Andric//===----------------------------------------------------------------------===//
3*06c3fb27SDimitry Andric//
4*06c3fb27SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*06c3fb27SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
6*06c3fb27SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*06c3fb27SDimitry Andric//
8*06c3fb27SDimitry Andric//===---------------------------------------------------------------------===//
9*06c3fb27SDimitry Andric
10*06c3fb27SDimitry Andric/*
11*06c3fb27SDimitry Andric
12*06c3fb27SDimitry Andric// Overall mdspan synopsis
13*06c3fb27SDimitry Andric
14*06c3fb27SDimitry Andricnamespace std {
15*06c3fb27SDimitry Andric  // [mdspan.extents], class template extents
16*06c3fb27SDimitry Andric  template<class IndexType, size_t... Extents>
17*06c3fb27SDimitry Andric    class extents;
18*06c3fb27SDimitry Andric
19*06c3fb27SDimitry Andric  // [mdspan.extents.dextents], alias template dextents
20*06c3fb27SDimitry Andric  template<class IndexType, size_t Rank>
21*06c3fb27SDimitry Andric    using dextents = see below;
22*06c3fb27SDimitry Andric
23*06c3fb27SDimitry Andric  // [mdspan.layout], layout mapping
24*06c3fb27SDimitry Andric  struct layout_left;
25*06c3fb27SDimitry Andric  struct layout_right;
26*06c3fb27SDimitry Andric  struct layout_stride; // not implemented yet
27*06c3fb27SDimitry Andric
28*06c3fb27SDimitry Andric  // [mdspan.accessor.default], class template default_accessor
29*06c3fb27SDimitry Andric  template<class ElementType>
30*06c3fb27SDimitry Andric    class default_accessor;
31*06c3fb27SDimitry Andric
32*06c3fb27SDimitry Andric  // [mdspan.mdspan], class template mdspan
33*06c3fb27SDimitry Andric  template<class ElementType, class Extents, class LayoutPolicy = layout_right,
34*06c3fb27SDimitry Andric           class AccessorPolicy = default_accessor<ElementType>>
35*06c3fb27SDimitry Andric    class mdspan; // not implemented yet
36*06c3fb27SDimitry Andric}
37*06c3fb27SDimitry Andric
38*06c3fb27SDimitry Andric// extents synopsis
39*06c3fb27SDimitry Andric
40*06c3fb27SDimitry Andricnamespace std {
41*06c3fb27SDimitry Andric  template<class _IndexType, size_t... _Extents>
42*06c3fb27SDimitry Andric  class extents {
43*06c3fb27SDimitry Andric  public:
44*06c3fb27SDimitry Andric    using index_type = _IndexType;
45*06c3fb27SDimitry Andric    using size_type = make_unsigned_t<index_type>;
46*06c3fb27SDimitry Andric    using rank_type = size_t;
47*06c3fb27SDimitry Andric
48*06c3fb27SDimitry Andric    // [mdspan.extents.obs], observers of the multidimensional index space
49*06c3fb27SDimitry Andric    static constexpr rank_type rank() noexcept { return sizeof...(_Extents); }
50*06c3fb27SDimitry Andric    static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); }
51*06c3fb27SDimitry Andric    static constexpr size_t static_extent(rank_type) noexcept;
52*06c3fb27SDimitry Andric    constexpr index_type extent(rank_type) const noexcept;
53*06c3fb27SDimitry Andric
54*06c3fb27SDimitry Andric    // [mdspan.extents.cons], constructors
55*06c3fb27SDimitry Andric    constexpr extents() noexcept = default;
56*06c3fb27SDimitry Andric
57*06c3fb27SDimitry Andric    template<class _OtherIndexType, size_t... _OtherExtents>
58*06c3fb27SDimitry Andric      constexpr explicit(see below)
59*06c3fb27SDimitry Andric        extents(const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
60*06c3fb27SDimitry Andric    template<class... _OtherIndexTypes>
61*06c3fb27SDimitry Andric      constexpr explicit extents(_OtherIndexTypes...) noexcept;
62*06c3fb27SDimitry Andric    template<class _OtherIndexType, size_t N>
63*06c3fb27SDimitry Andric      constexpr explicit(N != rank_dynamic())
64*06c3fb27SDimitry Andric        extents(span<_OtherIndexType, N>) noexcept;
65*06c3fb27SDimitry Andric    template<class _OtherIndexType, size_t N>
66*06c3fb27SDimitry Andric      constexpr explicit(N != rank_dynamic())
67*06c3fb27SDimitry Andric        extents(const array<_OtherIndexType, N>&) noexcept;
68*06c3fb27SDimitry Andric
69*06c3fb27SDimitry Andric    // [mdspan.extents.cmp], comparison operators
70*06c3fb27SDimitry Andric    template<class _OtherIndexType, size_t... _OtherExtents>
71*06c3fb27SDimitry Andric      friend constexpr bool operator==(const extents&,
72*06c3fb27SDimitry Andric                                       const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
73*06c3fb27SDimitry Andric
74*06c3fb27SDimitry Andric  private:
75*06c3fb27SDimitry Andric    // libcxx note: we do not use an array here, but we need to preserve the as-if behavior
76*06c3fb27SDimitry Andric    // for example the default constructor must zero initialize dynamic extents
77*06c3fb27SDimitry Andric    array<index_type, rank_dynamic()> dynamic-extents{};                // exposition only
78*06c3fb27SDimitry Andric  };
79*06c3fb27SDimitry Andric
80*06c3fb27SDimitry Andric  template<class... Integrals>
81*06c3fb27SDimitry Andric    explicit extents(Integrals...)
82*06c3fb27SDimitry Andric      -> see below;
83*06c3fb27SDimitry Andric}
84*06c3fb27SDimitry Andric
85*06c3fb27SDimitry Andric// layout_left synopsis
86*06c3fb27SDimitry Andric
87*06c3fb27SDimitry Andricnamespace std {
88*06c3fb27SDimitry Andric  template<class Extents>
89*06c3fb27SDimitry Andric  class layout_left::mapping {
90*06c3fb27SDimitry Andric  public:
91*06c3fb27SDimitry Andric    using extents_type = Extents;
92*06c3fb27SDimitry Andric    using index_type = typename extents_type::index_type;
93*06c3fb27SDimitry Andric    using size_type = typename extents_type::size_type;
94*06c3fb27SDimitry Andric    using rank_type = typename extents_type::rank_type;
95*06c3fb27SDimitry Andric    using layout_type = layout_left;
96*06c3fb27SDimitry Andric
97*06c3fb27SDimitry Andric    // [mdspan.layout.right.cons], constructors
98*06c3fb27SDimitry Andric    constexpr mapping() noexcept = default;
99*06c3fb27SDimitry Andric    constexpr mapping(const mapping&) noexcept = default;
100*06c3fb27SDimitry Andric    constexpr mapping(const extents_type&) noexcept;
101*06c3fb27SDimitry Andric    template<class OtherExtents>
102*06c3fb27SDimitry Andric      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
103*06c3fb27SDimitry Andric        mapping(const mapping<OtherExtents>&) noexcept;
104*06c3fb27SDimitry Andric    template<class OtherExtents>
105*06c3fb27SDimitry Andric      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
106*06c3fb27SDimitry Andric        mapping(const layout_right::mapping<OtherExtents>&) noexcept;
107*06c3fb27SDimitry Andric    template<class OtherExtents>
108*06c3fb27SDimitry Andric      constexpr explicit(extents_type::rank() > 0)
109*06c3fb27SDimitry Andric        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
110*06c3fb27SDimitry Andric
111*06c3fb27SDimitry Andric    constexpr mapping& operator=(const mapping&) noexcept = default;
112*06c3fb27SDimitry Andric
113*06c3fb27SDimitry Andric    // [mdspan.layout.right.obs], observers
114*06c3fb27SDimitry Andric    constexpr const extents_type& extents() const noexcept { return extents_; }
115*06c3fb27SDimitry Andric
116*06c3fb27SDimitry Andric    constexpr index_type required_span_size() const noexcept;
117*06c3fb27SDimitry Andric
118*06c3fb27SDimitry Andric    template<class... Indices>
119*06c3fb27SDimitry Andric      constexpr index_type operator()(Indices...) const noexcept;
120*06c3fb27SDimitry Andric
121*06c3fb27SDimitry Andric    static constexpr bool is_always_unique() noexcept { return true; }
122*06c3fb27SDimitry Andric    static constexpr bool is_always_exhaustive() noexcept { return true; }
123*06c3fb27SDimitry Andric    static constexpr bool is_always_strided() noexcept { return true; }
124*06c3fb27SDimitry Andric
125*06c3fb27SDimitry Andric    static constexpr bool is_unique() noexcept { return true; }
126*06c3fb27SDimitry Andric    static constexpr bool is_exhaustive() noexcept { return true; }
127*06c3fb27SDimitry Andric    static constexpr bool is_strided() noexcept { return true; }
128*06c3fb27SDimitry Andric
129*06c3fb27SDimitry Andric    constexpr index_type stride(rank_type) const noexcept;
130*06c3fb27SDimitry Andric
131*06c3fb27SDimitry Andric    template<class OtherExtents>
132*06c3fb27SDimitry Andric      friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
133*06c3fb27SDimitry Andric
134*06c3fb27SDimitry Andric  private:
135*06c3fb27SDimitry Andric    extents_type extents_{};    // exposition only
136*06c3fb27SDimitry Andric  };
137*06c3fb27SDimitry Andric}
138*06c3fb27SDimitry Andric
139*06c3fb27SDimitry Andric// layout_right synopsis
140*06c3fb27SDimitry Andric
141*06c3fb27SDimitry Andricnamespace std {
142*06c3fb27SDimitry Andric  template<class Extents>
143*06c3fb27SDimitry Andric  class layout_right::mapping {
144*06c3fb27SDimitry Andric  public:
145*06c3fb27SDimitry Andric    using extents_type = Extents;
146*06c3fb27SDimitry Andric    using index_type = typename extents_type::index_type;
147*06c3fb27SDimitry Andric    using size_type = typename extents_type::size_type;
148*06c3fb27SDimitry Andric    using rank_type = typename extents_type::rank_type;
149*06c3fb27SDimitry Andric    using layout_type = layout_right;
150*06c3fb27SDimitry Andric
151*06c3fb27SDimitry Andric    // [mdspan.layout.right.cons], constructors
152*06c3fb27SDimitry Andric    constexpr mapping() noexcept = default;
153*06c3fb27SDimitry Andric    constexpr mapping(const mapping&) noexcept = default;
154*06c3fb27SDimitry Andric    constexpr mapping(const extents_type&) noexcept;
155*06c3fb27SDimitry Andric    template<class OtherExtents>
156*06c3fb27SDimitry Andric      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
157*06c3fb27SDimitry Andric        mapping(const mapping<OtherExtents>&) noexcept;
158*06c3fb27SDimitry Andric    template<class OtherExtents>
159*06c3fb27SDimitry Andric      constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
160*06c3fb27SDimitry Andric        mapping(const layout_left::mapping<OtherExtents>&) noexcept;
161*06c3fb27SDimitry Andric    template<class OtherExtents>
162*06c3fb27SDimitry Andric      constexpr explicit(extents_type::rank() > 0)
163*06c3fb27SDimitry Andric        mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
164*06c3fb27SDimitry Andric
165*06c3fb27SDimitry Andric    constexpr mapping& operator=(const mapping&) noexcept = default;
166*06c3fb27SDimitry Andric
167*06c3fb27SDimitry Andric    // [mdspan.layout.right.obs], observers
168*06c3fb27SDimitry Andric    constexpr const extents_type& extents() const noexcept { return extents_; }
169*06c3fb27SDimitry Andric
170*06c3fb27SDimitry Andric    constexpr index_type required_span_size() const noexcept;
171*06c3fb27SDimitry Andric
172*06c3fb27SDimitry Andric    template<class... Indices>
173*06c3fb27SDimitry Andric      constexpr index_type operator()(Indices...) const noexcept;
174*06c3fb27SDimitry Andric
175*06c3fb27SDimitry Andric    static constexpr bool is_always_unique() noexcept { return true; }
176*06c3fb27SDimitry Andric    static constexpr bool is_always_exhaustive() noexcept { return true; }
177*06c3fb27SDimitry Andric    static constexpr bool is_always_strided() noexcept { return true; }
178*06c3fb27SDimitry Andric
179*06c3fb27SDimitry Andric    static constexpr bool is_unique() noexcept { return true; }
180*06c3fb27SDimitry Andric    static constexpr bool is_exhaustive() noexcept { return true; }
181*06c3fb27SDimitry Andric    static constexpr bool is_strided() noexcept { return true; }
182*06c3fb27SDimitry Andric
183*06c3fb27SDimitry Andric    constexpr index_type stride(rank_type) const noexcept;
184*06c3fb27SDimitry Andric
185*06c3fb27SDimitry Andric    template<class OtherExtents>
186*06c3fb27SDimitry Andric      friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
187*06c3fb27SDimitry Andric
188*06c3fb27SDimitry Andric  private:
189*06c3fb27SDimitry Andric    extents_type extents_{};    // exposition only
190*06c3fb27SDimitry Andric  };
191*06c3fb27SDimitry Andric}
192*06c3fb27SDimitry Andric
193*06c3fb27SDimitry Andric// default_accessor synopsis
194*06c3fb27SDimitry Andric
195*06c3fb27SDimitry Andricnamespace std {
196*06c3fb27SDimitry Andric  template<class ElementType>
197*06c3fb27SDimitry Andric  struct default_accessor {
198*06c3fb27SDimitry Andric    using offset_policy = default_accessor;
199*06c3fb27SDimitry Andric    using element_type = ElementType;
200*06c3fb27SDimitry Andric    using reference = ElementType&;
201*06c3fb27SDimitry Andric    using data_handle_type = ElementType*;
202*06c3fb27SDimitry Andric
203*06c3fb27SDimitry Andric    constexpr default_accessor() noexcept = default;
204*06c3fb27SDimitry Andric    template<class OtherElementType>
205*06c3fb27SDimitry Andric      constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
206*06c3fb27SDimitry Andric    constexpr reference access(data_handle_type p, size_t i) const noexcept;
207*06c3fb27SDimitry Andric    constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
208*06c3fb27SDimitry Andric  };
209*06c3fb27SDimitry Andric}
210*06c3fb27SDimitry Andric
211*06c3fb27SDimitry Andric*/
212*06c3fb27SDimitry Andric
213*06c3fb27SDimitry Andric#ifndef _LIBCPP_MDSPAN
214*06c3fb27SDimitry Andric#define _LIBCPP_MDSPAN
215*06c3fb27SDimitry Andric
216*06c3fb27SDimitry Andric#include <__config>
217*06c3fb27SDimitry Andric#include <__fwd/mdspan.h>
218*06c3fb27SDimitry Andric#include <__mdspan/default_accessor.h>
219*06c3fb27SDimitry Andric#include <__mdspan/extents.h>
220*06c3fb27SDimitry Andric#include <__mdspan/layout_left.h>
221*06c3fb27SDimitry Andric#include <__mdspan/layout_right.h>
222*06c3fb27SDimitry Andric
223*06c3fb27SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
224*06c3fb27SDimitry Andric#  pragma GCC system_header
225*06c3fb27SDimitry Andric#endif
226*06c3fb27SDimitry Andric
227*06c3fb27SDimitry Andric#endif // _LIBCPP_MDSPAN
228