Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_Extents.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 2.0
6 // Copyright (2019) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 */
43 
44 #ifndef KOKKOS_KOKKOS_EXTENTS_HPP
45 #define KOKKOS_KOKKOS_EXTENTS_HPP
46 
47 #include <cstddef>
48 
49 namespace Kokkos {
50 namespace Experimental {
51 
52 constexpr ptrdiff_t dynamic_extent = -1;
53 
54 template <ptrdiff_t... ExtentSpecs>
55 struct Extents {
56  /* TODO @enhancement flesh this out more */
57 };
58 
59 template <class Exts, ptrdiff_t NewExtent>
60 struct PrependExtent;
61 
62 template <ptrdiff_t... Exts, ptrdiff_t NewExtent>
63 struct PrependExtent<
64  Extents<Exts...>, NewExtent
65 > {
66  using type = Extents<NewExtent, Exts...>;
67 };
68 
69 template <class Exts, ptrdiff_t NewExtent>
70 struct AppendExtent;
71 
72 template <ptrdiff_t... Exts, ptrdiff_t NewExtent>
73 struct AppendExtent<
74  Extents<Exts...>, NewExtent
75 > {
76  using type = Extents<Exts..., NewExtent>;
77 };
78 
79 } // end namespace Experimental
80 
81 namespace Impl {
82 
83 namespace _parse_view_extents_impl {
84 
85 template <class T>
86 struct _all_remaining_extents_dynamic : std::true_type { };
87 
88 template <class T>
89 struct _all_remaining_extents_dynamic<T*>
90  : _all_remaining_extents_dynamic<T>
91 { };
92 
93 template <class T, unsigned N>
94 struct _all_remaining_extents_dynamic<T[N]>
95  : std::false_type
96 { };
97 
98 template <class T, class Result, class=void>
99 struct _parse_impl {
100  using type = Result;
101 };
102 
103 // We have to treat the case of int**[x] specially, since it *doesn't* go backwards
104 template <class T, ptrdiff_t... ExtentSpec>
105 struct _parse_impl<
106  T*, Experimental::Extents<ExtentSpec...>,
107  typename std::enable_if<_all_remaining_extents_dynamic<T>::value>::type
108 >
109  : _parse_impl<
110  T, Experimental::Extents<Experimental::dynamic_extent, ExtentSpec...>
111  >
112 { };
113 
114 // int*(*[x])[y] should still work also (meaning int[][x][][y])
115 template <class T, ptrdiff_t... ExtentSpec>
116 struct _parse_impl<
117  T*, Experimental::Extents<ExtentSpec...>,
118  typename std::enable_if<not _all_remaining_extents_dynamic<T>::value>::type
119 >
120 {
121  using _next = Kokkos::Experimental::AppendExtent<
122  typename _parse_impl<T, Experimental::Extents<ExtentSpec...>, void>::type,
123  Experimental::dynamic_extent
124  >;
125  using type = typename _next::type;
126 };
127 
128 template <class T, ptrdiff_t... ExtentSpec, unsigned N>
129 struct _parse_impl<
130  T[N], Experimental::Extents<ExtentSpec...>, void
131 >
132  : _parse_impl<
133  T, Experimental::Extents<ExtentSpec..., ptrdiff_t(N)> // TODO @pedantic this could be a narrowing cast
134  >
135 { };
136 
137 } // end namespace _parse_view_extents_impl
138 
139 template <class DataType>
140 struct ParseViewExtents {
141  using type =
142  typename _parse_view_extents_impl
143  ::_parse_impl<DataType, Experimental::Extents<>>::type;
144 };
145 
146 template <class ValueType, ptrdiff_t Ext>
147 struct ApplyExtent
148 {
149  using type = ValueType[Ext];
150 };
151 
152 template <class ValueType>
153 struct ApplyExtent<ValueType, Experimental::dynamic_extent>
154 {
155  using type = ValueType*;
156 };
157 
158 template <class ValueType, unsigned N, ptrdiff_t Ext>
159 struct ApplyExtent<ValueType[N], Ext>
160 {
161  using type = typename ApplyExtent<ValueType, Ext>::type[N];
162 };
163 
164 template <class ValueType, ptrdiff_t Ext>
165 struct ApplyExtent<ValueType*, Ext>
166 {
167  using type = ValueType*[Ext];
168 };
169 
170 template <class ValueType>
171 struct ApplyExtent<ValueType*, Experimental::dynamic_extent>
172 {
173  using type = typename ApplyExtent<ValueType, Experimental::dynamic_extent>::type*;
174 };
175 
176 template <class ValueType, unsigned N>
177 struct ApplyExtent<ValueType[N], Experimental::dynamic_extent>
178 {
179  using type = typename ApplyExtent<ValueType, Experimental::dynamic_extent>::type[N];
180 };
181 
182 } // end namespace Impl
183 
184 } // end namespace Kokkos
185 
186 #endif //KOKKOS_KOKKOS_EXTENTS_HPP