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