1 //=============================================================================
2 //
3 // Copyright (c) Kitware, Inc.
4 // All rights reserved.
5 // See LICENSE.txt for details.
6 //
7 // This software is distributed WITHOUT ANY WARRANTY; without even
8 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9 // PURPOSE. See the above copyright notice for more information.
10 //
11 // Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
12 // Copyright 2015 UT-Battelle, LLC.
13 // Copyright 2015 Los Alamos National Security.
14 //
15 // Under the terms of Contract DE-NA0003525 with NTESS,
16 // the U.S. Government retains certain rights in this software.
17 // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
18 // Laboratory (LANL), the U.S. Government retains certain rights in
19 // this software.
20 //
21 //=============================================================================
22
23 #ifndef vtk_m_cont_ArrayHandleReverse_h
24 #define vtk_m_cont_ArrayHandleReverse_h
25
26 #include <vtkm/cont/ArrayHandle.h>
27 #include <vtkm/cont/ErrorBadType.h>
28 #include <vtkm/cont/ErrorBadValue.h>
29
30 namespace vtkm
31 {
32 namespace cont
33 {
34
35 namespace internal
36 {
37
38 template <typename PortalType>
39 class VTKM_ALWAYS_EXPORT ArrayPortalReverse
40 {
41 public:
42 using ValueType = typename PortalType::ValueType;
43
44 VTKM_EXEC_CONT
ArrayPortalReverse()45 ArrayPortalReverse()
46 : portal()
47 {
48 }
49
50 VTKM_EXEC_CONT
ArrayPortalReverse(const PortalType & p)51 ArrayPortalReverse(const PortalType& p)
52 : portal(p)
53 {
54 }
55
56 template <typename OtherPortal>
ArrayPortalReverse(const ArrayPortalReverse<OtherPortal> & src)57 VTKM_EXEC_CONT ArrayPortalReverse(const ArrayPortalReverse<OtherPortal>& src)
58 : portal(src.GetPortal())
59 {
60 }
61
62 VTKM_EXEC_CONT
GetNumberOfValues()63 vtkm::Id GetNumberOfValues() const { return this->portal.GetNumberOfValues(); }
64
65 VTKM_EXEC_CONT
Get(vtkm::Id index)66 ValueType Get(vtkm::Id index) const
67 {
68 return this->portal.Get(portal.GetNumberOfValues() - index - 1);
69 }
70
71 VTKM_EXEC_CONT
Set(vtkm::Id index,const ValueType & value)72 void Set(vtkm::Id index, const ValueType& value) const
73 {
74 this->portal.Set(portal.GetNumberOfValues() - index - 1, value);
75 }
76
77 private:
78 PortalType portal;
79 };
80 }
81
82 template <typename ArrayHandleType>
83 class StorageTagReverse
84 {
85 };
86
87 namespace internal
88 {
89
90 template <typename ArrayHandleType>
91 class Storage<typename ArrayHandleType::ValueType, StorageTagReverse<ArrayHandleType>>
92 {
93 public:
94 using ValueType = typename ArrayHandleType::ValueType;
95 using PortalType = ArrayPortalReverse<typename ArrayHandleType::PortalControl>;
96 using PortalConstType = ArrayPortalReverse<typename ArrayHandleType::PortalConstControl>;
97
98 VTKM_CONT
Storage()99 Storage()
100 : Array()
101 {
102 }
103
104 VTKM_CONT
Storage(const ArrayHandleType & a)105 Storage(const ArrayHandleType& a)
106 : Array(a)
107 {
108 }
109
110
111 VTKM_CONT
GetPortalConst()112 PortalConstType GetPortalConst() const
113 {
114 return PortalConstType(this->Array.GetPortalConstControl());
115 }
116
117 VTKM_CONT
GetPortal()118 PortalType GetPortal() { return PortalType(this->Array.GetPortalControl()); }
119
120 VTKM_CONT
GetNumberOfValues()121 vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
122
123 VTKM_CONT
Allocate(vtkm::Id numberOfValues)124 void Allocate(vtkm::Id numberOfValues) { return this->Array.Allocate(numberOfValues); }
125
126 VTKM_CONT
Shrink(vtkm::Id numberOfValues)127 void Shrink(vtkm::Id numberOfValues) { return this->Array.Shrink(numberOfValues); }
128
129 VTKM_CONT
ReleaseResources()130 void ReleaseResources()
131 {
132 // This request is ignored since it is asking to release the resources
133 // of the delegate array, which may be used elsewhere. Should the behavior
134 // be different?
135 }
136
137 VTKM_CONT
GetArray()138 const ArrayHandleType& GetArray() const { return this->Array; }
139
140 private:
141 ArrayHandleType Array;
142 }; // class storage
143
144 template <typename ArrayHandleType, typename Device>
145 class ArrayTransfer<typename ArrayHandleType::ValueType, StorageTagReverse<ArrayHandleType>, Device>
146 {
147 public:
148 using ValueType = typename ArrayHandleType::ValueType;
149
150 private:
151 using StorageTag = StorageTagReverse<ArrayHandleType>;
152 using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
153
154 public:
155 using PortalControl = typename StorageType::PortalType;
156 using PortalConstControl = typename StorageType::PortalConstType;
157
158 using PortalExecution =
159 ArrayPortalReverse<typename ArrayHandleType::template ExecutionTypes<Device>::Portal>;
160 using PortalConstExecution =
161 ArrayPortalReverse<typename ArrayHandleType::template ExecutionTypes<Device>::PortalConst>;
162
163 VTKM_CONT
ArrayTransfer(StorageType * storage)164 ArrayTransfer(StorageType* storage)
165 : Array(storage->GetArray())
166 {
167 }
168
169 VTKM_CONT
GetNumberOfValues()170 vtkm::Id GetNumberOfValues() const { return this->Array.GetNumberOfValues(); }
171
172 VTKM_CONT
PrepareForInput(bool vtkmNotUsed (updateData))173 PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
174 {
175 return PortalConstExecution(this->Array.PrepareForInput(Device()));
176 }
177
178 VTKM_CONT
PrepareForInPlace(bool vtkmNotUsed (updateData))179 PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
180 {
181 return PortalExecution(this->Array.PrepareForInPlace(Device()));
182 }
183
184 VTKM_CONT
PrepareForOutput(vtkm::Id numberOfValues)185 PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
186 {
187 return PortalExecution(this->Array.PrepareForOutput(numberOfValues, Device()));
188 }
189
190 VTKM_CONT
RetrieveOutputData(StorageType * vtkmNotUsed (storage))191 void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
192 {
193 // not need to implement
194 }
195
196 VTKM_CONT
Shrink(vtkm::Id numberOfValues)197 void Shrink(vtkm::Id numberOfValues) { this->Array.Shrink(numberOfValues); }
198
199 VTKM_CONT
ReleaseResources()200 void ReleaseResources() { this->Array.ReleaseResourcesExecution(); }
201
202 private:
203 ArrayHandleType Array;
204 };
205
206 } // namespace internal
207
208 /// \brief Reverse the order of an array, on demand.
209 ///
210 /// ArrayHandleReverse is a specialization of ArrayHandle. Given an ArrayHandle,
211 /// it creates a new handle that returns the elements of the array in reverse
212 /// order (i.e. from end to beginning).
213 ///
214 template <typename ArrayHandleType>
215 class ArrayHandleReverse : public vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
216 StorageTagReverse<ArrayHandleType>>
217
218 {
219 public:
220 VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleReverse,
221 (ArrayHandleReverse<ArrayHandleType>),
222 (vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
223 StorageTagReverse<ArrayHandleType>>));
224
225 protected:
226 using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
227
228 public:
ArrayHandleReverse(const ArrayHandleType & handle)229 ArrayHandleReverse(const ArrayHandleType& handle)
230 : Superclass(handle)
231 {
232 }
233 };
234
235 /// make_ArrayHandleReverse is convenience function to generate an
236 /// ArrayHandleReverse.
237 ///
238 template <typename HandleType>
make_ArrayHandleReverse(const HandleType & handle)239 VTKM_CONT ArrayHandleReverse<HandleType> make_ArrayHandleReverse(const HandleType& handle)
240 {
241 return ArrayHandleReverse<HandleType>(handle);
242 }
243 }
244 } // namespace vtkm::cont
245
246 //=============================================================================
247 // Specializations of serialization related classes
248 namespace vtkm
249 {
250 namespace cont
251 {
252
253 template <typename AH>
254 struct TypeString<vtkm::cont::ArrayHandleReverse<AH>>
255 {
256 static VTKM_CONT const std::string& Get()
257 {
258 static std::string name = "AH_Reverse<" + TypeString<AH>::Get() + ">";
259 return name;
260 }
261 };
262
263 template <typename AH>
264 struct TypeString<
265 vtkm::cont::ArrayHandle<typename AH::ValueType, vtkm::cont::StorageTagReverse<AH>>>
266 : TypeString<vtkm::cont::ArrayHandleReverse<AH>>
267 {
268 };
269 }
270 } // vtkm::cont
271
272 namespace diy
273 {
274
275 template <typename AH>
276 struct Serialization<vtkm::cont::ArrayHandleReverse<AH>>
277 {
278 private:
279 using Type = vtkm::cont::ArrayHandleReverse<AH>;
280 using BaseType = vtkm::cont::ArrayHandle<typename Type::ValueType, typename Type::StorageTag>;
281
282 public:
283 static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
284 {
285 diy::save(bb, obj.GetStorage().GetArray());
286 }
287
288 static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
289 {
290 AH array;
291 diy::load(bb, array);
292 obj = vtkm::cont::make_ArrayHandleReverse(array);
293 }
294 };
295
296 template <typename AH>
297 struct Serialization<
298 vtkm::cont::ArrayHandle<typename AH::ValueType, vtkm::cont::StorageTagReverse<AH>>>
299 : Serialization<vtkm::cont::ArrayHandleReverse<AH>>
300 {
301 };
302
303 } // diy
304
305 #endif // vtk_m_cont_ArrayHandleReverse_h
306