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