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