475 lines · plain
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-exception7//8//===---------------------------------------------------------------------===//9 10/*11 12// Overall mdspan synopsis13 14namespace std {15 // [mdspan.extents], class template extents16 template<class IndexType, size_t... Extents>17 class extents;18 19 // [mdspan.extents.dextents], alias template dextents20 template<class IndexType, size_t Rank>21 using dextents = see below;22 23 // [mdspan.extents.dims], alias template dims24 template<size_t Rank, class IndexType = size_t>25 using dims = see below; // since C++2626 27 // [mdspan.layout], layout mapping28 struct layout_left;29 struct layout_right;30 struct layout_stride;31 32 // [mdspan.accessor.default], class template default_accessor33 template<class ElementType>34 class default_accessor;35 36 // [mdspan.accessor.aligned], class template aligned_accessor37 template<class ElementType, size_t ByteAlignment>38 class aligned_accessor; // since C++2639 40 // [mdspan.mdspan], class template mdspan41 template<class ElementType, class Extents, class LayoutPolicy = layout_right,42 class AccessorPolicy = default_accessor<ElementType>>43 class mdspan;44}45 46// extents synopsis47 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 space57 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], constructors63 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 operators78 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 behavior84 // for example the default constructor must zero initialize dynamic extents85 array<index_type, rank_dynamic()> dynamic-extents{}; // exposition only86 };87 88 template<class... Integrals>89 explicit extents(Integrals...)90 -> see below;91}92 93// layout_left synopsis94 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], constructors106 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], observers122 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 only144 };145}146 147// layout_right synopsis148 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], constructors160 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], observers176 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 only198 };199}200 201// layout_stride synopsis202 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 only215 216 public:217 // [mdspan.layout.stride.cons], constructors218 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], observers231 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 only254 array<index_type, rank_> strides_{}; // exposition only255 };256}257 258// default_accessor synopsis259 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 synopsis277 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_type304 offset(data_handle_type p, size_t i) const noexcept;305 };306}307 308// mdspan synopsis309 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) noexcept330 { 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], constructors334 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], members360 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() noexcept379 { return mapping_type::is_always_unique(); }380 static constexpr bool is_always_exhaustive() noexcept381 { return mapping_type::is_always_exhaustive(); }382 static constexpr bool is_always_strided() noexcept383 { return mapping_type::is_always_strided(); }384 385 constexpr bool is_unique() const386 { return map_.is_unique(); }387 constexpr bool is_exhaustive() const388 { return map_.is_exhaustive(); }389 constexpr bool is_strided() const390 { return map_.is_strided(); }391 constexpr index_type stride(rank_type r) const392 { return map_.stride(r); }393 394 private:395 accessor_type acc_; // exposition only396 mapping_type map_; // exposition only397 data_handle_type ptr_; // exposition only398 };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++26414 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++26418 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_MDSPAN445#define _LIBCPP_MDSPAN446 447#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)448# include <__cxx03/__config>449#else450# include <__config>451 452# if _LIBCPP_STD_VER >= 23453# include <__fwd/mdspan.h> // TODO(boomanaiden154): This is currently a454 // non-standard extension to include455 // std::dynamic_extent tracked by LWG issue 4275.456 // This comment should be deleted or the include457 // 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# endif466 467# include <version>468 469# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)470# pragma GCC system_header471# endif472#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)473 474#endif // _LIBCPP_MDSPAN475