mdspan 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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; // not implemented yet
  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. // default_accessor synopsis
  154. namespace std {
  155. template<class ElementType>
  156. struct default_accessor {
  157. using offset_policy = default_accessor;
  158. using element_type = ElementType;
  159. using reference = ElementType&;
  160. using data_handle_type = ElementType*;
  161. constexpr default_accessor() noexcept = default;
  162. template<class OtherElementType>
  163. constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
  164. constexpr reference access(data_handle_type p, size_t i) const noexcept;
  165. constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
  166. };
  167. }
  168. // mdspan synopsis
  169. namespace std {
  170. template<class ElementType, class Extents, class LayoutPolicy = layout_right,
  171. class AccessorPolicy = default_accessor<ElementType>>
  172. class mdspan {
  173. public:
  174. using extents_type = Extents;
  175. using layout_type = LayoutPolicy;
  176. using accessor_type = AccessorPolicy;
  177. using mapping_type = typename layout_type::template mapping<extents_type>;
  178. using element_type = ElementType;
  179. using value_type = remove_cv_t<element_type>;
  180. using index_type = typename extents_type::index_type;
  181. using size_type = typename extents_type::size_type;
  182. using rank_type = typename extents_type::rank_type;
  183. using data_handle_type = typename accessor_type::data_handle_type;
  184. using reference = typename accessor_type::reference;
  185. static constexpr rank_type rank() noexcept { return extents_type::rank(); }
  186. static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
  187. static constexpr size_t static_extent(rank_type r) noexcept
  188. { return extents_type::static_extent(r); }
  189. constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); }
  190. // [mdspan.mdspan.cons], constructors
  191. constexpr mdspan();
  192. constexpr mdspan(const mdspan& rhs) = default;
  193. constexpr mdspan(mdspan&& rhs) = default;
  194. template<class... OtherIndexTypes>
  195. constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts);
  196. template<class OtherIndexType, size_t N>
  197. constexpr explicit(N != rank_dynamic())
  198. mdspan(data_handle_type p, span<OtherIndexType, N> exts);
  199. template<class OtherIndexType, size_t N>
  200. constexpr explicit(N != rank_dynamic())
  201. mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
  202. constexpr mdspan(data_handle_type p, const extents_type& ext);
  203. constexpr mdspan(data_handle_type p, const mapping_type& m);
  204. constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
  205. template<class OtherElementType, class OtherExtents,
  206. class OtherLayoutPolicy, class OtherAccessorPolicy>
  207. constexpr explicit(see below)
  208. mdspan(const mdspan<OtherElementType, OtherExtents,
  209. OtherLayoutPolicy, OtherAccessorPolicy>& other);
  210. constexpr mdspan& operator=(const mdspan& rhs) = default;
  211. constexpr mdspan& operator=(mdspan&& rhs) = default;
  212. // [mdspan.mdspan.members], members
  213. template<class... OtherIndexTypes>
  214. constexpr reference operator[](OtherIndexTypes... indices) const;
  215. template<class OtherIndexType>
  216. constexpr reference operator[](span<OtherIndexType, rank()> indices) const;
  217. template<class OtherIndexType>
  218. constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
  219. constexpr size_type size() const noexcept;
  220. [[nodiscard]] constexpr bool empty() const noexcept;
  221. friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
  222. constexpr const extents_type& extents() const noexcept { return map_.extents(); }
  223. constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
  224. constexpr const mapping_type& mapping() const noexcept { return map_; }
  225. constexpr const accessor_type& accessor() const noexcept { return acc_; }
  226. static constexpr bool is_always_unique()
  227. { return mapping_type::is_always_unique(); }
  228. static constexpr bool is_always_exhaustive()
  229. { return mapping_type::is_always_exhaustive(); }
  230. static constexpr bool is_always_strided()
  231. { return mapping_type::is_always_strided(); }
  232. constexpr bool is_unique() const
  233. { return map_.is_unique(); }
  234. constexpr bool is_exhaustive() const
  235. { return map_.is_exhaustive(); }
  236. constexpr bool is_strided() const
  237. { return map_.is_strided(); }
  238. constexpr index_type stride(rank_type r) const
  239. { return map_.stride(r); }
  240. private:
  241. accessor_type acc_; // exposition only
  242. mapping_type map_; // exposition only
  243. data_handle_type ptr_; // exposition only
  244. };
  245. template<class CArray>
  246. requires(is_array_v<CArray> && rank_v<CArray> == 1)
  247. mdspan(CArray&)
  248. -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>;
  249. template<class Pointer>
  250. requires(is_pointer_v<remove_reference_t<Pointer>>)
  251. mdspan(Pointer&&)
  252. -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>;
  253. template<class ElementType, class... Integrals>
  254. requires((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0)
  255. explicit mdspan(ElementType*, Integrals...)
  256. -> mdspan<ElementType, dextents<size_t, sizeof...(Integrals)>>;
  257. template<class ElementType, class OtherIndexType, size_t N>
  258. mdspan(ElementType*, span<OtherIndexType, N>)
  259. -> mdspan<ElementType, dextents<size_t, N>>;
  260. template<class ElementType, class OtherIndexType, size_t N>
  261. mdspan(ElementType*, const array<OtherIndexType, N>&)
  262. -> mdspan<ElementType, dextents<size_t, N>>;
  263. template<class ElementType, class IndexType, size_t... ExtentsPack>
  264. mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&)
  265. -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>;
  266. template<class ElementType, class MappingType>
  267. mdspan(ElementType*, const MappingType&)
  268. -> mdspan<ElementType, typename MappingType::extents_type,
  269. typename MappingType::layout_type>;
  270. template<class MappingType, class AccessorType>
  271. mdspan(const typename AccessorType::data_handle_type&, const MappingType&,
  272. const AccessorType&)
  273. -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type,
  274. typename MappingType::layout_type, AccessorType>;
  275. }
  276. */
  277. #ifndef _LIBCPP_MDSPAN
  278. #define _LIBCPP_MDSPAN
  279. #include <__config>
  280. #include <__fwd/mdspan.h>
  281. #include <__mdspan/default_accessor.h>
  282. #include <__mdspan/extents.h>
  283. #include <__mdspan/layout_left.h>
  284. #include <__mdspan/layout_right.h>
  285. #include <__mdspan/mdspan.h>
  286. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  287. # pragma GCC system_header
  288. #endif
  289. #endif // _LIBCPP_MDSPAN