Line data Source code
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 :
17 : #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
18 : static_assert(false,
19 : "Including non-public Kokkos header files is not allowed.");
20 : #endif
21 :
22 : #ifndef KOKKOS_VIEW_DATA_ANALYSIS_HPP
23 : #define KOKKOS_VIEW_DATA_ANALYSIS_HPP
24 :
25 : #include <Kokkos_Macros.hpp>
26 :
27 : namespace Kokkos::Impl {
28 :
29 : template <unsigned I, size_t... Args>
30 : struct variadic_size_t {
31 : enum : size_t { value = KOKKOS_INVALID_INDEX };
32 : };
33 :
34 : template <size_t Val, size_t... Args>
35 : struct variadic_size_t<0, Val, Args...> {
36 : enum : size_t { value = Val };
37 : };
38 :
39 : template <unsigned I, size_t Val, size_t... Args>
40 : struct variadic_size_t<I, Val, Args...> {
41 : enum : size_t { value = variadic_size_t<I - 1, Args...>::value };
42 : };
43 :
44 : template <size_t... Args>
45 : struct rank_dynamic;
46 :
47 : template <>
48 : struct rank_dynamic<> {
49 : enum : unsigned { value = 0 };
50 : };
51 :
52 : template <size_t Val, size_t... Args>
53 : struct rank_dynamic<Val, Args...> {
54 : enum : unsigned { value = (Val == 0 ? 1 : 0) + rank_dynamic<Args...>::value };
55 : };
56 :
57 : #define KOKKOS_IMPL_VIEW_DIMENSION(R) \
58 : template <size_t V, unsigned> \
59 : struct ViewDimension##R { \
60 : static constexpr size_t ArgN##R = (V != KOKKOS_INVALID_INDEX ? V : 1); \
61 : static constexpr size_t N##R = (V != KOKKOS_INVALID_INDEX ? V : 1); \
62 : KOKKOS_INLINE_FUNCTION explicit ViewDimension##R(size_t) {} \
63 : ViewDimension##R() = default; \
64 : ViewDimension##R(const ViewDimension##R&) = default; \
65 : ViewDimension##R& operator=(const ViewDimension##R&) = default; \
66 : }; \
67 : template <size_t V, unsigned RD> \
68 : constexpr size_t ViewDimension##R<V, RD>::ArgN##R; \
69 : template <size_t V, unsigned RD> \
70 : constexpr size_t ViewDimension##R<V, RD>::N##R; \
71 : template <unsigned RD> \
72 : struct ViewDimension##R<0u, RD> { \
73 : static constexpr size_t ArgN##R = 0; \
74 : std::conditional_t<(RD < 3), size_t, unsigned> N##R; \
75 : ViewDimension##R() = default; \
76 : ViewDimension##R(const ViewDimension##R&) = default; \
77 : ViewDimension##R& operator=(const ViewDimension##R&) = default; \
78 : KOKKOS_INLINE_FUNCTION explicit ViewDimension##R(size_t V) : N##R(V) {} \
79 : }; \
80 : template <unsigned RD> \
81 : constexpr size_t ViewDimension##R<0u, RD>::ArgN##R;
82 :
83 : KOKKOS_IMPL_VIEW_DIMENSION(0)
84 : KOKKOS_IMPL_VIEW_DIMENSION(1)
85 : KOKKOS_IMPL_VIEW_DIMENSION(2)
86 : KOKKOS_IMPL_VIEW_DIMENSION(3)
87 : KOKKOS_IMPL_VIEW_DIMENSION(4)
88 : KOKKOS_IMPL_VIEW_DIMENSION(5)
89 : KOKKOS_IMPL_VIEW_DIMENSION(6)
90 : KOKKOS_IMPL_VIEW_DIMENSION(7)
91 :
92 : #undef KOKKOS_IMPL_VIEW_DIMENSION
93 :
94 : // MSVC does not do empty base class optimization by default.
95 : // Per standard it is required for standard layout types
96 : template <size_t... Vals>
97 : struct KOKKOS_IMPL_ENFORCE_EMPTY_BASE_OPTIMIZATION ViewDimension
98 : : public ViewDimension0<variadic_size_t<0u, Vals...>::value,
99 : rank_dynamic<Vals...>::value>,
100 : public ViewDimension1<variadic_size_t<1u, Vals...>::value,
101 : rank_dynamic<Vals...>::value>,
102 : public ViewDimension2<variadic_size_t<2u, Vals...>::value,
103 : rank_dynamic<Vals...>::value>,
104 : public ViewDimension3<variadic_size_t<3u, Vals...>::value,
105 : rank_dynamic<Vals...>::value>,
106 : public ViewDimension4<variadic_size_t<4u, Vals...>::value,
107 : rank_dynamic<Vals...>::value>,
108 : public ViewDimension5<variadic_size_t<5u, Vals...>::value,
109 : rank_dynamic<Vals...>::value>,
110 : public ViewDimension6<variadic_size_t<6u, Vals...>::value,
111 : rank_dynamic<Vals...>::value>,
112 : public ViewDimension7<variadic_size_t<7u, Vals...>::value,
113 : rank_dynamic<Vals...>::value> {
114 : using D0 = ViewDimension0<variadic_size_t<0U, Vals...>::value,
115 : rank_dynamic<Vals...>::value>;
116 : using D1 = ViewDimension1<variadic_size_t<1U, Vals...>::value,
117 : rank_dynamic<Vals...>::value>;
118 : using D2 = ViewDimension2<variadic_size_t<2U, Vals...>::value,
119 : rank_dynamic<Vals...>::value>;
120 : using D3 = ViewDimension3<variadic_size_t<3U, Vals...>::value,
121 : rank_dynamic<Vals...>::value>;
122 : using D4 = ViewDimension4<variadic_size_t<4U, Vals...>::value,
123 : rank_dynamic<Vals...>::value>;
124 : using D5 = ViewDimension5<variadic_size_t<5U, Vals...>::value,
125 : rank_dynamic<Vals...>::value>;
126 : using D6 = ViewDimension6<variadic_size_t<6U, Vals...>::value,
127 : rank_dynamic<Vals...>::value>;
128 : using D7 = ViewDimension7<variadic_size_t<7U, Vals...>::value,
129 : rank_dynamic<Vals...>::value>;
130 :
131 : using D0::ArgN0;
132 : using D1::ArgN1;
133 : using D2::ArgN2;
134 : using D3::ArgN3;
135 : using D4::ArgN4;
136 : using D5::ArgN5;
137 : using D6::ArgN6;
138 : using D7::ArgN7;
139 :
140 : using D0::N0;
141 : using D1::N1;
142 : using D2::N2;
143 : using D3::N3;
144 : using D4::N4;
145 : using D5::N5;
146 : using D6::N6;
147 : using D7::N7;
148 :
149 : static constexpr unsigned rank = sizeof...(Vals);
150 : static constexpr unsigned rank_dynamic = Impl::rank_dynamic<Vals...>::value;
151 :
152 : ViewDimension() = default;
153 : ViewDimension(const ViewDimension&) = default;
154 : ViewDimension& operator=(const ViewDimension&) = default;
155 :
156 : KOKKOS_INLINE_FUNCTION
157 : constexpr ViewDimension(size_t n0, size_t n1, size_t n2, size_t n3, size_t n4,
158 : size_t n5, size_t n6, size_t n7)
159 : : D0(n0 == KOKKOS_INVALID_INDEX ? 1 : n0),
160 : D1(n1 == KOKKOS_INVALID_INDEX ? 1 : n1),
161 : D2(n2 == KOKKOS_INVALID_INDEX ? 1 : n2),
162 : D3(n3 == KOKKOS_INVALID_INDEX ? 1 : n3),
163 : D4(n4 == KOKKOS_INVALID_INDEX ? 1 : n4),
164 : D5(n5 == KOKKOS_INVALID_INDEX ? 1 : n5),
165 : D6(n6 == KOKKOS_INVALID_INDEX ? 1 : n6),
166 : D7(n7 == KOKKOS_INVALID_INDEX ? 1 : n7) {}
167 :
168 : KOKKOS_INLINE_FUNCTION
169 106864929 : constexpr size_t extent(const unsigned r) const noexcept {
170 : return r == 0
171 73224123 : ? N0
172 : : (r == 1
173 33640806 : ? N1
174 : : (r == 2
175 : ? N2
176 : : (r == 3
177 : ? N3
178 : : (r == 4
179 : ? N4
180 : : (r == 5
181 : ? N5
182 : : (r == 6
183 : ? N6
184 : : (r == 7 ? N7
185 106864929 : : 0)))))));
186 : }
187 :
188 : static KOKKOS_INLINE_FUNCTION constexpr size_t static_extent(
189 : const unsigned r) noexcept {
190 : return r == 0
191 : ? ArgN0
192 : : (r == 1
193 : ? ArgN1
194 : : (r == 2
195 : ? ArgN2
196 : : (r == 3
197 : ? ArgN3
198 : : (r == 4
199 : ? ArgN4
200 : : (r == 5
201 : ? ArgN5
202 : : (r == 6
203 : ? ArgN6
204 : : (r == 7 ? ArgN7
205 : : 0)))))));
206 : }
207 :
208 : template <size_t N>
209 : struct prepend {
210 : using type = ViewDimension<N, Vals...>;
211 : };
212 :
213 : template <size_t N>
214 : struct append {
215 : using type = ViewDimension<Vals..., N>;
216 : };
217 : };
218 :
219 : template <class A, class B>
220 : struct ViewDimensionJoin;
221 :
222 : template <size_t... A, size_t... B>
223 : struct ViewDimensionJoin<ViewDimension<A...>, ViewDimension<B...>> {
224 : using type = ViewDimension<A..., B...>;
225 : };
226 :
227 : //----------------------------------------------------------------------------
228 :
229 : template <class DstDim, class SrcDim>
230 : struct ViewDimensionAssignable;
231 :
232 : template <size_t... DstArgs, size_t... SrcArgs>
233 : struct ViewDimensionAssignable<ViewDimension<DstArgs...>,
234 : ViewDimension<SrcArgs...>> {
235 : using dst = ViewDimension<DstArgs...>;
236 : using src = ViewDimension<SrcArgs...>;
237 :
238 : enum {
239 : value = unsigned(dst::rank) == unsigned(src::rank) &&
240 : (
241 : // Compile time check that potential static dimensions match
242 : ((1 > dst::rank_dynamic && 1 > src::rank_dynamic)
243 : ? (size_t(dst::ArgN0) == size_t(src::ArgN0))
244 : : true) &&
245 : ((2 > dst::rank_dynamic && 2 > src::rank_dynamic)
246 : ? (size_t(dst::ArgN1) == size_t(src::ArgN1))
247 : : true) &&
248 : ((3 > dst::rank_dynamic && 3 > src::rank_dynamic)
249 : ? (size_t(dst::ArgN2) == size_t(src::ArgN2))
250 : : true) &&
251 : ((4 > dst::rank_dynamic && 4 > src::rank_dynamic)
252 : ? (size_t(dst::ArgN3) == size_t(src::ArgN3))
253 : : true) &&
254 : ((5 > dst::rank_dynamic && 5 > src::rank_dynamic)
255 : ? (size_t(dst::ArgN4) == size_t(src::ArgN4))
256 : : true) &&
257 : ((6 > dst::rank_dynamic && 6 > src::rank_dynamic)
258 : ? (size_t(dst::ArgN5) == size_t(src::ArgN5))
259 : : true) &&
260 : ((7 > dst::rank_dynamic && 7 > src::rank_dynamic)
261 : ? (size_t(dst::ArgN6) == size_t(src::ArgN6))
262 : : true) &&
263 : ((8 > dst::rank_dynamic && 8 > src::rank_dynamic)
264 : ? (size_t(dst::ArgN7) == size_t(src::ArgN7))
265 : : true))
266 : };
267 : };
268 :
269 : /** \brief Given a value type and dimension generate the View data type */
270 : template <class T, class Dim>
271 : struct ViewDataType;
272 :
273 : template <class T>
274 : struct ViewDataType<T, ViewDimension<>> {
275 : using type = T;
276 : };
277 :
278 : template <class T, size_t... Args>
279 : struct ViewDataType<T, ViewDimension<0, Args...>> {
280 : using type = typename ViewDataType<T*, ViewDimension<Args...>>::type;
281 : };
282 :
283 : template <class T, size_t N, size_t... Args>
284 : struct ViewDataType<T, ViewDimension<N, Args...>> {
285 : using type = typename ViewDataType<T, ViewDimension<Args...>>::type[N];
286 : };
287 :
288 : /**\brief Analysis of View data type.
289 : *
290 : * Data type conforms to one of the following patterns :
291 : * {const} value_type [][#][#][#]
292 : * {const} value_type ***[#][#][#]
293 : * Where the sum of counts of '*' and '[#]' is at most ten.
294 : *
295 : * Provide alias for ViewDimension<...> and value_type.
296 : */
297 : template <class T>
298 : struct ViewArrayAnalysis {
299 : using value_type = T;
300 : using const_value_type = std::add_const_t<T>;
301 : using non_const_value_type = std::remove_const_t<T>;
302 : using static_dimension = ViewDimension<>;
303 : using dynamic_dimension = ViewDimension<>;
304 : using dimension = ViewDimension<>;
305 : };
306 :
307 : template <class T, size_t N>
308 : struct ViewArrayAnalysis<T[N]> {
309 : private:
310 : using nested = ViewArrayAnalysis<T>;
311 :
312 : public:
313 : using value_type = typename nested::value_type;
314 : using const_value_type = typename nested::const_value_type;
315 : using non_const_value_type = typename nested::non_const_value_type;
316 :
317 : using static_dimension =
318 : typename nested::static_dimension::template prepend<N>::type;
319 :
320 : using dynamic_dimension = typename nested::dynamic_dimension;
321 :
322 : using dimension =
323 : typename ViewDimensionJoin<dynamic_dimension, static_dimension>::type;
324 : };
325 :
326 : template <class T>
327 : struct ViewArrayAnalysis<T[]> {
328 : private:
329 : using nested = ViewArrayAnalysis<T>;
330 : using nested_dimension = typename nested::dimension;
331 :
332 : public:
333 : using value_type = typename nested::value_type;
334 : using const_value_type = typename nested::const_value_type;
335 : using non_const_value_type = typename nested::non_const_value_type;
336 :
337 : using dynamic_dimension =
338 : typename nested::dynamic_dimension::template prepend<0>::type;
339 :
340 : using static_dimension = typename nested::static_dimension;
341 :
342 : using dimension =
343 : typename ViewDimensionJoin<dynamic_dimension, static_dimension>::type;
344 : };
345 :
346 : template <class T>
347 : struct ViewArrayAnalysis<T*> {
348 : private:
349 : using nested = ViewArrayAnalysis<T>;
350 :
351 : public:
352 : using value_type = typename nested::value_type;
353 : using const_value_type = typename nested::const_value_type;
354 : using non_const_value_type = typename nested::non_const_value_type;
355 :
356 : using dynamic_dimension =
357 : typename nested::dynamic_dimension::template prepend<0>::type;
358 :
359 : using static_dimension = typename nested::static_dimension;
360 :
361 : using dimension =
362 : typename ViewDimensionJoin<dynamic_dimension, static_dimension>::type;
363 : };
364 :
365 : template <class DataType, class ArrayLayout, class ValueType>
366 : struct ViewDataAnalysis {
367 : private:
368 : using array_analysis = ViewArrayAnalysis<DataType>;
369 :
370 : // ValueType is opportunity for partial specialization.
371 : // Must match array analysis when this default template is used.
372 : static_assert(
373 : std::is_same_v<ValueType, typename array_analysis::non_const_value_type>);
374 :
375 : public:
376 : using specialize = void; // No specialization
377 :
378 : using dimension = typename array_analysis::dimension;
379 : using value_type = typename array_analysis::value_type;
380 : using const_value_type = typename array_analysis::const_value_type;
381 : using non_const_value_type = typename array_analysis::non_const_value_type;
382 :
383 : // Generate analogous multidimensional array specification type.
384 : using type = typename ViewDataType<value_type, dimension>::type;
385 : using const_type = typename ViewDataType<const_value_type, dimension>::type;
386 : using non_const_type =
387 : typename ViewDataType<non_const_value_type, dimension>::type;
388 :
389 : // Generate "flattened" multidimensional array specification type.
390 : using scalar_array_type = type;
391 : using const_scalar_array_type = const_type;
392 : using non_const_scalar_array_type = non_const_type;
393 : };
394 :
395 : template <class Dimension, class Layout, class Enable = void>
396 : struct ViewOffset {
397 : using is_mapping_plugin = std::false_type;
398 : };
399 : } // namespace Kokkos::Impl
400 :
401 : #endif // KOKKOS_VIEW_DATA_ANALYSIS_HPP
|