mdspan 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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. // Overall mdspan synopsis
  11. namespace std {
  12. // [mdspan.extents], class template extents
  13. template<class IndexType, size_t... Extents>
  14. class extents;
  15. // [mdspan.extents.dextents], alias template dextents
  16. template<class IndexType, size_t Rank>
  17. using dextents = see below;
  18. // [mdspan.layout], layout mapping
  19. struct layout_left;
  20. struct layout_right;
  21. struct layout_stride;
  22. // [mdspan.accessor.default], class template default_accessor
  23. template<class ElementType>
  24. class default_accessor;
  25. // [mdspan.mdspan], class template mdspan
  26. template<class ElementType, class Extents, class LayoutPolicy = layout_right,
  27. class AccessorPolicy = default_accessor<ElementType>>
  28. class mdspan; // not implemented yet
  29. }
  30. // extents synopsis
  31. namespace std {
  32. template<class _IndexType, size_t... _Extents>
  33. class extents {
  34. public:
  35. using index_type = _IndexType;
  36. using size_type = make_unsigned_t<index_type>;
  37. using rank_type = size_t;
  38. // [mdspan.extents.obs], observers of the multidimensional index space
  39. static constexpr rank_type rank() noexcept { return sizeof...(_Extents); }
  40. static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); }
  41. static constexpr size_t static_extent(rank_type) noexcept;
  42. constexpr index_type extent(rank_type) const noexcept;
  43. // [mdspan.extents.cons], constructors
  44. constexpr extents() noexcept = default;
  45. template<class _OtherIndexType, size_t... _OtherExtents>
  46. constexpr explicit(see below)
  47. extents(const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
  48. template<class... _OtherIndexTypes>
  49. constexpr explicit extents(_OtherIndexTypes...) noexcept;
  50. template<class _OtherIndexType, size_t N>
  51. constexpr explicit(N != rank_dynamic())
  52. extents(span<_OtherIndexType, N>) noexcept;
  53. template<class _OtherIndexType, size_t N>
  54. constexpr explicit(N != rank_dynamic())
  55. extents(const array<_OtherIndexType, N>&) noexcept;
  56. // [mdspan.extents.cmp], comparison operators
  57. template<class _OtherIndexType, size_t... _OtherExtents>
  58. friend constexpr bool operator==(const extents&,
  59. const extents<_OtherIndexType, _OtherExtents...>&) noexcept;
  60. private:
  61. // libcxx note: we do not use an array here, but we need to preserve the as-if behavior
  62. // for example the default constructor must zero initialize dynamic extents
  63. array<index_type, rank_dynamic()> dynamic-extents{}; // exposition only
  64. };
  65. template<class... Integrals>
  66. explicit extents(Integrals...)
  67. -> see below;
  68. }
  69. // layout_left synopsis
  70. namespace std {
  71. template<class Extents>
  72. class layout_left::mapping {
  73. public:
  74. using extents_type = Extents;
  75. using index_type = typename extents_type::index_type;
  76. using size_type = typename extents_type::size_type;
  77. using rank_type = typename extents_type::rank_type;
  78. using layout_type = layout_left;
  79. // [mdspan.layout.right.cons], constructors
  80. constexpr mapping() noexcept = default;
  81. constexpr mapping(const mapping&) noexcept = default;
  82. constexpr mapping(const extents_type&) noexcept;
  83. template<class OtherExtents>
  84. constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
  85. mapping(const mapping<OtherExtents>&) noexcept;
  86. template<class OtherExtents>
  87. constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
  88. mapping(const layout_right::mapping<OtherExtents>&) noexcept;
  89. template<class OtherExtents>
  90. constexpr explicit(extents_type::rank() > 0)
  91. mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
  92. constexpr mapping& operator=(const mapping&) noexcept = default;
  93. // [mdspan.layout.right.obs], observers
  94. constexpr const extents_type& extents() const noexcept { return extents_; }
  95. constexpr index_type required_span_size() const noexcept;
  96. template<class... Indices>
  97. constexpr index_type operator()(Indices...) const noexcept;
  98. static constexpr bool is_always_unique() noexcept { return true; }
  99. static constexpr bool is_always_exhaustive() noexcept { return true; }
  100. static constexpr bool is_always_strided() noexcept { return true; }
  101. static constexpr bool is_unique() noexcept { return true; }
  102. static constexpr bool is_exhaustive() noexcept { return true; }
  103. static constexpr bool is_strided() noexcept { return true; }
  104. constexpr index_type stride(rank_type) const noexcept;
  105. template<class OtherExtents>
  106. friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
  107. private:
  108. extents_type extents_{}; // exposition only
  109. };
  110. }
  111. // layout_right synopsis
  112. namespace std {
  113. template<class Extents>
  114. class layout_right::mapping {
  115. public:
  116. using extents_type = Extents;
  117. using index_type = typename extents_type::index_type;
  118. using size_type = typename extents_type::size_type;
  119. using rank_type = typename extents_type::rank_type;
  120. using layout_type = layout_right;
  121. // [mdspan.layout.right.cons], constructors
  122. constexpr mapping() noexcept = default;
  123. constexpr mapping(const mapping&) noexcept = default;
  124. constexpr mapping(const extents_type&) noexcept;
  125. template<class OtherExtents>
  126. constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
  127. mapping(const mapping<OtherExtents>&) noexcept;
  128. template<class OtherExtents>
  129. constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
  130. mapping(const layout_left::mapping<OtherExtents>&) noexcept;
  131. template<class OtherExtents>
  132. constexpr explicit(extents_type::rank() > 0)
  133. mapping(const layout_stride::mapping<OtherExtents>&) noexcept;
  134. constexpr mapping& operator=(const mapping&) noexcept = default;
  135. // [mdspan.layout.right.obs], observers
  136. constexpr const extents_type& extents() const noexcept { return extents_; }
  137. constexpr index_type required_span_size() const noexcept;
  138. template<class... Indices>
  139. constexpr index_type operator()(Indices...) const noexcept;
  140. static constexpr bool is_always_unique() noexcept { return true; }
  141. static constexpr bool is_always_exhaustive() noexcept { return true; }
  142. static constexpr bool is_always_strided() noexcept { return true; }
  143. static constexpr bool is_unique() noexcept { return true; }
  144. static constexpr bool is_exhaustive() noexcept { return true; }
  145. static constexpr bool is_strided() noexcept { return true; }
  146. constexpr index_type stride(rank_type) const noexcept;
  147. template<class OtherExtents>
  148. friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
  149. private:
  150. extents_type extents_{}; // exposition only
  151. };
  152. }
  153. // layout_stride synopsis
  154. namespace std {
  155. template<class Extents>
  156. class layout_stride::mapping {
  157. public:
  158. using extents_type = Extents;
  159. using index_type = typename extents_type::index_type;
  160. using size_type = typename extents_type::size_type;
  161. using rank_type = typename extents_type::rank_type;
  162. using layout_type = layout_stride;
  163. private:
  164. static constexpr rank_type rank_ = extents_type::rank(); // exposition only
  165. public:
  166. // [mdspan.layout.stride.cons], constructors
  167. constexpr mapping() noexcept;
  168. constexpr mapping(const mapping&) noexcept = default;
  169. template<class OtherIndexType>
  170. constexpr mapping(const extents_type&, span<OtherIndexType, rank_>) noexcept;
  171. template<class OtherIndexType>
  172. constexpr mapping(const extents_type&, const array<OtherIndexType, rank_>&) noexcept;
  173. template<class StridedLayoutMapping>
  174. constexpr explicit(see below) mapping(const StridedLayoutMapping&) noexcept;
  175. constexpr mapping& operator=(const mapping&) noexcept = default;
  176. // [mdspan.layout.stride.obs], observers
  177. constexpr const extents_type& extents() const noexcept { return extents_; }
  178. constexpr array<index_type, rank_> strides() const noexcept { return strides_; }
  179. constexpr index_type required_span_size() const noexcept;
  180. template<class... Indices>
  181. constexpr index_type operator()(Indices...) const noexcept;
  182. static constexpr bool is_always_unique() noexcept { return true; }
  183. static constexpr bool is_always_exhaustive() noexcept { return false; }
  184. static constexpr bool is_always_strided() noexcept { return true; }
  185. static constexpr bool is_unique() noexcept { return true; }
  186. constexpr bool is_exhaustive() const noexcept;
  187. static constexpr bool is_strided() noexcept { return true; }
  188. constexpr index_type stride(rank_type i) const noexcept { return strides_[i]; }
  189. template<class OtherMapping>
  190. friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept;
  191. private:
  192. extents_type extents_{}; // exposition only
  193. array<index_type, rank_> strides_{}; // exposition only
  194. };
  195. }
  196. // default_accessor synopsis
  197. namespace std {
  198. template<class ElementType>
  199. struct default_accessor {
  200. using offset_policy = default_accessor;
  201. using element_type = ElementType;
  202. using reference = ElementType&;
  203. using data_handle_type = ElementType*;
  204. constexpr default_accessor() noexcept = default;
  205. template<class OtherElementType>
  206. constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
  207. constexpr reference access(data_handle_type p, size_t i) const noexcept;
  208. constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
  209. };
  210. }
  211. // mdspan synopsis
  212. namespace std {
  213. template<class ElementType, class Extents, class LayoutPolicy = layout_right,
  214. class AccessorPolicy = default_accessor<ElementType>>
  215. class mdspan {
  216. public:
  217. using extents_type = Extents;
  218. using layout_type = LayoutPolicy;
  219. using accessor_type = AccessorPolicy;
  220. using mapping_type = typename layout_type::template mapping<extents_type>;
  221. using element_type = ElementType;
  222. using value_type = remove_cv_t<element_type>;
  223. using index_type = typename extents_type::index_type;
  224. using size_type = typename extents_type::size_type;
  225. using rank_type = typename extents_type::rank_type;
  226. using data_handle_type = typename accessor_type::data_handle_type;
  227. using reference = typename accessor_type::reference;
  228. static constexpr rank_type rank() noexcept { return extents_type::rank(); }
  229. static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
  230. static constexpr size_t static_extent(rank_type r) noexcept
  231. { return extents_type::static_extent(r); }
  232. constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); }
  233. // [mdspan.mdspan.cons], constructors
  234. constexpr mdspan();
  235. constexpr mdspan(const mdspan& rhs) = default;
  236. constexpr mdspan(mdspan&& rhs) = default;
  237. template<class... OtherIndexTypes>
  238. constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts);
  239. template<class OtherIndexType, size_t N>
  240. constexpr explicit(N != rank_dynamic())
  241. mdspan(data_handle_type p, span<OtherIndexType, N> exts);
  242. template<class OtherIndexType, size_t N>
  243. constexpr explicit(N != rank_dynamic())
  244. mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
  245. constexpr mdspan(data_handle_type p, const extents_type& ext);
  246. constexpr mdspan(data_handle_type p, const mapping_type& m);
  247. constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
  248. template<class OtherElementType, class OtherExtents,
  249. class OtherLayoutPolicy, class OtherAccessorPolicy>
  250. constexpr explicit(see below)
  251. mdspan(const mdspan<OtherElementType, OtherExtents,
  252. OtherLayoutPolicy, OtherAccessorPolicy>& other);
  253. constexpr mdspan& operator=(const mdspan& rhs) = default;
  254. constexpr mdspan& operator=(mdspan&& rhs) = default;
  255. // [mdspan.mdspan.members], members
  256. template<class... OtherIndexTypes>
  257. constexpr reference operator[](OtherIndexTypes... indices) const;
  258. template<class OtherIndexType>
  259. constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
  260. template<class OtherIndexType>
  261. constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
  262. constexpr size_type size() const noexcept;
  263. [[nodiscard]] constexpr bool empty() const noexcept;
  264. friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
  265. constexpr const extents_type& extents() const noexcept { return map_.extents(); }
  266. constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
  267. constexpr const mapping_type& mapping() const noexcept { return map_; }
  268. constexpr const accessor_type& accessor() const noexcept { return acc_; }
  269. // per LWG-4021 "mdspan::is_always_meow() should be noexcept"
  270. static constexpr bool is_always_unique() noexcept
  271. { return mapping_type::is_always_unique(); }
  272. static constexpr bool is_always_exhaustive() noexcept
  273. { return mapping_type::is_always_exhaustive(); }
  274. static constexpr bool is_always_strided() noexcept
  275. { return mapping_type::is_always_strided(); }
  276. constexpr bool is_unique() const
  277. { return map_.is_unique(); }
  278. constexpr bool is_exhaustive() const
  279. { return map_.is_exhaustive(); }
  280. constexpr bool is_strided() const
  281. { return map_.is_strided(); }
  282. constexpr index_type stride(rank_type r) const
  283. { return map_.stride(r); }
  284. private:
  285. accessor_type acc_; // exposition only
  286. mapping_type map_; // exposition only
  287. data_handle_type ptr_; // exposition only
  288. };
  289. template<class CArray>
  290. requires(is_array_v<CArray> && rank_v<CArray> == 1)
  291. mdspan(CArray&)
  292. -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;
  293. template<class Pointer>
  294. requires(is_pointer_v<remove_reference_t<Pointer>>)
  295. mdspan(Pointer&&)
  296. -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
  297. template<class ElementType, class... Integrals>
  298. requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
  299. explicit mdspan(ElementType*, Integrals...)
  300. -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;
  301. template<class ElementType, class OtherIndexType, size_t N>
  302. mdspan(ElementType*, span<OtherIndexType, N>)
  303. -> mdspan<ElementType, dextents<size_t, N>>;
  304. template<class ElementType, class OtherIndexType, size_t N>
  305. mdspan(ElementType*, const array<OtherIndexType, N>&)
  306. -> mdspan<ElementType, dextents<size_t, N>>;
  307. template<class ElementType, class IndexType, size_t... ExtentsPack>
  308. mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)
  309. -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;
  310. template<class ElementType, class MappingType>
  311. mdspan(ElementType*, const MappingType&)
  312. -> mdspan<ElementType, typename MappingType::extents_type,
  313. typename MappingType::layout_type>;
  314. template<class MappingType, class AccessorType>
  315. mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
  316. const AccessorType&)
  317. -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
  318. typename MappingType::layout_type, AccessorType>;
  319. }
  320. */
  321. #ifndef _LIBCPP_MDSPAN
  322. #define _LIBCPP_MDSPAN
  323. #include <__config>
  324. #include <__fwd/mdspan.h>
  325. #include <__mdspan/default_accessor.h>
  326. #include <__mdspan/extents.h>
  327. #include <__mdspan/layout_left.h>
  328. #include <__mdspan/layout_right.h>
  329. #include <__mdspan/layout_stride.h>
  330. #include <__mdspan/mdspan.h>
  331. #include <version>
  332. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  333. # pragma GCC system_header
  334. #endif
  335. #endif // _LIBCPP_MDSPAN