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