OpenKalman
layout_left.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 #pragma once
17 
18 #include "macros.hpp"
19 #include "trait_backports.hpp"
20 #include "extents.hpp"
21 
22 namespace std {
23 namespace experimental {
24 
25 //==============================================================================
26 
27 template <class Extents>
29  public:
30  using extents_type = Extents;
31  using index_type = typename extents_type::index_type;
32  using size_type = typename extents_type::size_type;
33  using rank_type = typename extents_type::rank_type;
34  using layout_type = layout_left;
35  private:
36 
37  static_assert(detail::__is_extents_v<extents_type>, "std::experimental::layout_left::mapping must be instantiated with a specialization of std::experimental::extents.");
38 
39  template <class>
40  friend class mapping;
41 
42  // i0+(i1 + E(1)*(i2 + E(2)*i3))
43  template <size_t r, size_t Rank>
44  struct __rank_count {};
45 
46  template <size_t r, size_t Rank, class I, class... Indices>
47  _MDSPAN_HOST_DEVICE
48  constexpr index_type __compute_offset(
49  __rank_count<r,Rank>, const I& i, Indices... idx) const {
50  return __compute_offset(__rank_count<r+1,Rank>(), idx...) *
51  __extents.extent(r) + i;
52  }
53 
54  template<class I>
55  _MDSPAN_HOST_DEVICE
56  constexpr index_type __compute_offset(
57  __rank_count<extents_type::rank()-1,extents_type::rank()>, const I& i) const {
58  return i;
59  }
60 
61  _MDSPAN_HOST_DEVICE
62  constexpr index_type __compute_offset(__rank_count<0,0>) const { return 0; }
63 
64  public:
65 
66  //--------------------------------------------------------------------------------
67 
68  MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() noexcept = default;
69  MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping const&) noexcept = default;
70 
71  _MDSPAN_HOST_DEVICE
72  constexpr mapping(extents_type const& __exts) noexcept
73  :__extents(__exts)
74  { }
75 
76  MDSPAN_TEMPLATE_REQUIRES(
77  class OtherExtents,
78  /* requires */ (
79  _MDSPAN_TRAIT(is_constructible, extents_type, OtherExtents)
80  )
81  )
82  MDSPAN_CONDITIONAL_EXPLICIT((!is_convertible<OtherExtents, extents_type>::value)) // needs two () due to comma
83  MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
84  mapping(mapping<OtherExtents> const& other) noexcept // NOLINT(google-explicit-constructor)
85  :__extents(other.extents())
86  {
87  /*
88  * TODO: check precondition
89  * other.required_span_size() is a representable value of type index_type
90  */
91  }
92 
93  MDSPAN_TEMPLATE_REQUIRES(
94  class OtherExtents,
95  /* requires */ (
96  _MDSPAN_TRAIT(is_constructible, extents_type, OtherExtents) &&
97  (extents_type::rank() <= 1)
98  )
99  )
100  MDSPAN_CONDITIONAL_EXPLICIT((!is_convertible<OtherExtents, extents_type>::value)) // needs two () due to comma
101  MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
102  mapping(layout_right::mapping<OtherExtents> const& other) noexcept // NOLINT(google-explicit-constructor)
103  :__extents(other.extents())
104  {
105  /*
106  * TODO: check precondition
107  * other.required_span_size() is a representable value of type index_type
108  */
109  }
110 
111  MDSPAN_TEMPLATE_REQUIRES(
112  class OtherExtents,
113  /* requires */ (
114  _MDSPAN_TRAIT(is_constructible, extents_type, OtherExtents)
115  )
116  )
117  MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0))
118  MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
119  mapping(layout_stride::mapping<OtherExtents> const& other) noexcept // NOLINT(google-explicit-constructor)
120  :__extents(other.extents())
121  {
122  /*
123  * TODO: check precondition
124  * other.required_span_size() is a representable value of type index_type
125  */
126  #if !defined(_MDSPAN_HAS_CUDA) && !defined(_MDSPAN_HAS_HIP) && !defined(NDEBUG)
127  index_type stride = 1;
128  for(rank_type r=0; r<__extents.rank(); r++) {
129  if(stride != static_cast<index_type>(other.stride(r))) {
130  // Note this throw will lead to a terminate if triggered since this function is marked noexcept
131  throw std::runtime_error("Assigning layout_stride to layout_left with invalid strides.");
132  }
133  stride *= __extents.extent(r);
134  }
135  #endif
136  }
137 
138  MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default;
139 
140  MDSPAN_INLINE_FUNCTION
141  constexpr const extents_type& extents() const noexcept {
142  return __extents;
143  }
144 
145  MDSPAN_INLINE_FUNCTION
146  constexpr index_type required_span_size() const noexcept {
147  index_type value = 1;
148  for(rank_type r=0; r<extents_type::rank(); r++) value*=__extents.extent(r);
149  return value;
150  }
151 
152  //--------------------------------------------------------------------------------
153 
154  MDSPAN_TEMPLATE_REQUIRES(
155  class... Indices,
156  /* requires */ (
157  (sizeof...(Indices) == extents_type::rank()) &&
158  _MDSPAN_FOLD_AND(
159  (_MDSPAN_TRAIT(is_convertible, Indices, index_type) &&
160  _MDSPAN_TRAIT(is_nothrow_constructible, index_type, Indices))
161  )
162  )
163  )
164  _MDSPAN_HOST_DEVICE
165  constexpr index_type operator()(Indices... idxs) const noexcept {
166  return __compute_offset(__rank_count<0, extents_type::rank()>(), static_cast<index_type>(idxs)...);
167  }
168 
169 
170 
171  MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; }
172  MDSPAN_INLINE_FUNCTION static constexpr bool is_always_exhaustive() noexcept { return true; }
173  MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; }
174 
175  MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { return true; }
176  MDSPAN_INLINE_FUNCTION constexpr bool is_exhaustive() const noexcept { return true; }
177  MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return true; }
178 
179  MDSPAN_INLINE_FUNCTION
180  constexpr index_type stride(rank_type i) const noexcept
181 #if MDSPAN_HAS_CXX_20
182  requires ( Extents::rank() > 0 )
183 #endif
184  {
185  index_type value = 1;
186  for(rank_type r=0; r<i; r++) value*=__extents.extent(r);
187  return value;
188  }
189 
190  template<class OtherExtents>
191  MDSPAN_INLINE_FUNCTION
192  friend constexpr bool operator==(mapping const& lhs, mapping<OtherExtents> const& rhs) noexcept {
193  return lhs.extents() == rhs.extents();
194  }
195 
196  // In C++ 20 the not equal exists if equal is found
197 #if !(MDSPAN_HAS_CXX_20)
198  template<class OtherExtents>
199  MDSPAN_INLINE_FUNCTION
200  friend constexpr bool operator!=(mapping const& lhs, mapping<OtherExtents> const& rhs) noexcept {
201  return lhs.extents() != rhs.extents();
202  }
203 #endif
204 
205  // Not really public, but currently needed to implement fully constexpr useable submdspan:
206  template<size_t N, class SizeType, size_t ... E, size_t ... Idx>
207  constexpr index_type __get_stride(std::experimental::extents<SizeType, E...>,integer_sequence<size_t, Idx...>) const {
208  return _MDSPAN_FOLD_TIMES_RIGHT((Idx<N? __extents.template __extent<Idx>():1),1);
209  }
210  template<size_t N>
211  constexpr index_type __stride() const noexcept {
212  return __get_stride<N>(__extents, make_index_sequence<extents_type::rank()>());
213  }
214 
215 private:
216  _MDSPAN_NO_UNIQUE_ADDRESS extents_type __extents{};
217 
218 };
219 
220 
221 } // end namespace experimental
222 } // end namespace std
223 
Definition: layout_right.hpp:29
Definition: layout_stride.hpp:70
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
Definition: layout_stride.hpp:40
Definition: trait_backports.hpp:64
Definition: layout_left.hpp:28
Definition: extents.hpp:372