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