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 #ifndef vtk_m_cont_ArrayHandleConcatenate_h
23 #define vtk_m_cont_ArrayHandleConcatenate_h
24
25 #include <vtkm/cont/ArrayHandle.h>
26
27 namespace vtkm
28 {
29 namespace cont
30 {
31 namespace internal
32 {
33
34 template <typename PortalType1, typename PortalType2>
35 class VTKM_ALWAYS_EXPORT ArrayPortalConcatenate
36 {
37 public:
38 using ValueType = typename PortalType1::ValueType;
39
40 VTKM_SUPPRESS_EXEC_WARNINGS
41 VTKM_EXEC_CONT
ArrayPortalConcatenate()42 ArrayPortalConcatenate()
43 : portal1()
44 , portal2()
45 {
46 }
47
48 VTKM_EXEC_CONT
ArrayPortalConcatenate(const PortalType1 & p1,const PortalType2 & p2)49 ArrayPortalConcatenate(const PortalType1& p1, const PortalType2& p2)
50 : portal1(p1)
51 , portal2(p2)
52 {
53 }
54
55 // Copy constructor
56 template <typename OtherP1, typename OtherP2>
ArrayPortalConcatenate(const ArrayPortalConcatenate<OtherP1,OtherP2> & src)57 VTKM_EXEC_CONT ArrayPortalConcatenate(const ArrayPortalConcatenate<OtherP1, OtherP2>& src)
58 : portal1(src.GetPortal1())
59 , portal2(src.GetPortal2())
60 {
61 }
62
63 VTKM_EXEC_CONT
GetNumberOfValues()64 vtkm::Id GetNumberOfValues() const
65 {
66 return this->portal1.GetNumberOfValues() + this->portal2.GetNumberOfValues();
67 }
68
69 VTKM_EXEC_CONT
Get(vtkm::Id index)70 ValueType Get(vtkm::Id index) const
71 {
72 if (index < this->portal1.GetNumberOfValues())
73 return this->portal1.Get(index);
74 else
75 return this->portal2.Get(index - this->portal1.GetNumberOfValues());
76 }
77
78 VTKM_EXEC_CONT
Set(vtkm::Id index,const ValueType & value)79 void Set(vtkm::Id index, const ValueType& value) const
80 {
81 if (index < this->portal1.GetNumberOfValues())
82 this->portal1.Set(index, value);
83 else
84 this->portal2.Set(index - this->portal1.GetNumberOfValues(), value);
85 }
86
87 VTKM_EXEC_CONT
GetPortal1()88 const PortalType1& GetPortal1() const { return this->portal1; }
89
90 VTKM_EXEC_CONT
GetPortal2()91 const PortalType2& GetPortal2() const { return this->portal2; }
92
93 private:
94 PortalType1 portal1;
95 PortalType2 portal2;
96 }; // class ArrayPortalConcatenate
97
98 } // namespace internal
99
100 template <typename ArrayHandleType1, typename ArrayHandleType2>
101 class StorageTagConcatenate
102 {
103 };
104
105 namespace internal
106 {
107
108 template <typename ArrayHandleType1, typename ArrayHandleType2>
109 class Storage<typename ArrayHandleType1::ValueType,
110 StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>>
111 {
112 public:
113 using ValueType = typename ArrayHandleType1::ValueType;
114 using PortalType = ArrayPortalConcatenate<typename ArrayHandleType1::PortalControl,
115 typename ArrayHandleType2::PortalControl>;
116 using PortalConstType = ArrayPortalConcatenate<typename ArrayHandleType1::PortalConstControl,
117 typename ArrayHandleType2::PortalConstControl>;
118
119 VTKM_CONT
Storage()120 Storage()
121 : valid(false)
122 {
123 }
124
125 VTKM_CONT
Storage(const ArrayHandleType1 & a1,const ArrayHandleType2 & a2)126 Storage(const ArrayHandleType1& a1, const ArrayHandleType2& a2)
127 : array1(a1)
128 , array2(a2)
129 , valid(true){};
130
131 VTKM_CONT
GetPortalConst()132 PortalConstType GetPortalConst() const
133 {
134 VTKM_ASSERT(this->valid);
135 return PortalConstType(this->array1.GetPortalConstControl(),
136 this->array2.GetPortalConstControl());
137 }
138
139 VTKM_CONT
GetPortal()140 PortalType GetPortal()
141 {
142 VTKM_ASSERT(this->valid);
143 return PortalType(this->array1.GetPortalControl(), this->array2.GetPortalControl());
144 }
145
146 VTKM_CONT
GetNumberOfValues()147 vtkm::Id GetNumberOfValues() const
148 {
149 VTKM_ASSERT(this->valid);
150 return this->array1.GetNumberOfValues() + this->array2.GetNumberOfValues();
151 }
152
153 VTKM_CONT
Allocate(vtkm::Id vtkmNotUsed (numberOfValues))154 void Allocate(vtkm::Id vtkmNotUsed(numberOfValues))
155 {
156 throw vtkm::cont::ErrorInternal("ArrayHandleConcatenate should not be allocated explicitly. ");
157 }
158
159 VTKM_CONT
Shrink(vtkm::Id numberOfValues)160 void Shrink(vtkm::Id numberOfValues)
161 {
162 VTKM_ASSERT(this->valid);
163 if (numberOfValues < this->array1.GetNumberOfValues())
164 {
165 this->array1.Shrink(numberOfValues);
166 this->array2.Shrink(0);
167 }
168 else
169 this->array2.Shrink(numberOfValues - this->array1.GetNumberOfValues());
170 }
171
172 VTKM_CONT
ReleaseResources()173 void ReleaseResources()
174 {
175 VTKM_ASSERT(this->valid);
176 this->array1.ReleaseResources();
177 this->array2.ReleaseResources();
178 }
179
180 VTKM_CONT
GetArray1()181 const ArrayHandleType1& GetArray1() const
182 {
183 VTKM_ASSERT(this->valid);
184 return this->array1;
185 }
186
187 VTKM_CONT
GetArray2()188 const ArrayHandleType2& GetArray2() const
189 {
190 VTKM_ASSERT(this->valid);
191 return this->array2;
192 }
193
194 private:
195 ArrayHandleType1 array1;
196 ArrayHandleType2 array2;
197 bool valid;
198 }; // class Storage
199
200 template <typename ArrayHandleType1, typename ArrayHandleType2, typename Device>
201 class ArrayTransfer<typename ArrayHandleType1::ValueType,
202 StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>,
203 Device>
204 {
205 public:
206 using ValueType = typename ArrayHandleType1::ValueType;
207
208 private:
209 using StorageTag = StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>;
210 using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
211
212 public:
213 using PortalControl = typename StorageType::PortalType;
214 using PortalConstControl = typename StorageType::PortalConstType;
215
216 using PortalExecution =
217 ArrayPortalConcatenate<typename ArrayHandleType1::template ExecutionTypes<Device>::Portal,
218 typename ArrayHandleType2::template ExecutionTypes<Device>::Portal>;
219 using PortalConstExecution =
220 ArrayPortalConcatenate<typename ArrayHandleType1::template ExecutionTypes<Device>::PortalConst,
221 typename ArrayHandleType2::template ExecutionTypes<Device>::PortalConst>;
222
223 VTKM_CONT
ArrayTransfer(StorageType * storage)224 ArrayTransfer(StorageType* storage)
225 : array1(storage->GetArray1())
226 , array2(storage->GetArray2())
227 {
228 }
229
230 VTKM_CONT
GetNumberOfValues()231 vtkm::Id GetNumberOfValues() const
232 {
233 return this->array1.GetNumberOfValues() + this->array2.GetNumberOfValues();
234 }
235
236 VTKM_CONT
PrepareForInput(bool vtkmNotUsed (updateData))237 PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData))
238 {
239 return PortalConstExecution(this->array1.PrepareForInput(Device()),
240 this->array2.PrepareForInput(Device()));
241 }
242
243 VTKM_CONT
PrepareForInPlace(bool vtkmNotUsed (updateData))244 PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
245 {
246 return PortalExecution(this->array1.PrepareForInPlace(Device()),
247 this->array2.PrepareForInPlace(Device()));
248 }
249
250 VTKM_CONT
PrepareForOutput(vtkm::Id vtkmNotUsed (numberOfValues))251 PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
252 {
253 throw vtkm::cont::ErrorInternal("ArrayHandleConcatenate is derived and read-only. ");
254 }
255
256 VTKM_CONT
RetrieveOutputData(StorageType * vtkmNotUsed (storage))257 void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
258 {
259 // not need to implement
260 }
261
262 VTKM_CONT
Shrink(vtkm::Id numberOfValues)263 void Shrink(vtkm::Id numberOfValues)
264 {
265 if (numberOfValues < this->array1.GetNumberOfValues())
266 {
267 this->array1.Shrink(numberOfValues);
268 this->array2.Shrink(0);
269 }
270 else
271 this->array2.Shrink(numberOfValues - this->array1.GetNumberOfValues());
272 }
273
274 VTKM_CONT
ReleaseResources()275 void ReleaseResources()
276 {
277 this->array1.ReleaseResourcesExecution();
278 this->array2.ReleaseResourcesExecution();
279 }
280
281 private:
282 ArrayHandleType1 array1;
283 ArrayHandleType2 array2;
284 };
285 }
286 }
287 } // namespace vtkm::cont::internal
288
289 namespace vtkm
290 {
291 namespace cont
292 {
293
294 template <typename ArrayHandleType1, typename ArrayHandleType2>
295 class ArrayHandleConcatenate
296 : public vtkm::cont::ArrayHandle<typename ArrayHandleType1::ValueType,
297 StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>>
298 {
299 public:
300 VTKM_ARRAY_HANDLE_SUBCLASS(
301 ArrayHandleConcatenate,
302 (ArrayHandleConcatenate<ArrayHandleType1, ArrayHandleType2>),
303 (vtkm::cont::ArrayHandle<typename ArrayHandleType1::ValueType,
304 StorageTagConcatenate<ArrayHandleType1, ArrayHandleType2>>));
305
306 protected:
307 using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
308
309 public:
310 VTKM_CONT
ArrayHandleConcatenate(const ArrayHandleType1 & array1,const ArrayHandleType2 & array2)311 ArrayHandleConcatenate(const ArrayHandleType1& array1, const ArrayHandleType2& array2)
312 : Superclass(StorageType(array1, array2))
313 {
314 }
315 };
316
317 template <typename ArrayHandleType1, typename ArrayHandleType2>
make_ArrayHandleConcatenate(const ArrayHandleType1 & array1,const ArrayHandleType2 & array2)318 VTKM_CONT ArrayHandleConcatenate<ArrayHandleType1, ArrayHandleType2> make_ArrayHandleConcatenate(
319 const ArrayHandleType1& array1,
320 const ArrayHandleType2& array2)
321 {
322 return ArrayHandleConcatenate<ArrayHandleType1, ArrayHandleType2>(array1, array2);
323 }
324 }
325 } // namespace vtkm::cont
326
327 //=============================================================================
328 // Specializations of serialization related classes
329 namespace vtkm
330 {
331 namespace cont
332 {
333
334 template <typename AH1, typename AH2>
335 struct TypeString<vtkm::cont::ArrayHandleConcatenate<AH1, AH2>>
336 {
337 static VTKM_CONT const std::string& Get()
338 {
339 static std::string name =
340 "AH_Concatenate<" + TypeString<AH1>::Get() + "," + TypeString<AH2>::Get() + ">";
341 return name;
342 }
343 };
344
345 template <typename AH1, typename AH2>
346 struct TypeString<
347 vtkm::cont::ArrayHandle<typename AH1::ValueType, vtkm::cont::StorageTagConcatenate<AH1, AH2>>>
348 : TypeString<vtkm::cont::ArrayHandleConcatenate<AH1, AH2>>
349 {
350 };
351 }
352 } // vtkm::cont
353
354 namespace diy
355 {
356
357 template <typename AH1, typename AH2>
358 struct Serialization<vtkm::cont::ArrayHandleConcatenate<AH1, AH2>>
359 {
360 private:
361 using Type = vtkm::cont::ArrayHandleConcatenate<AH1, AH2>;
362 using BaseType = vtkm::cont::ArrayHandle<typename Type::ValueType, typename Type::StorageTag>;
363
364 public:
365 static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
366 {
367 auto storage = obj.GetStorage();
368 diy::save(bb, storage.GetArray1());
369 diy::save(bb, storage.GetArray2());
370 }
371
372 static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
373 {
374 AH1 array1;
375 AH2 array2;
376
377 diy::load(bb, array1);
378 diy::load(bb, array2);
379
380 obj = vtkm::cont::make_ArrayHandleConcatenate(array1, array2);
381 }
382 };
383
384 template <typename AH1, typename AH2>
385 struct Serialization<
386 vtkm::cont::ArrayHandle<typename AH1::ValueType, vtkm::cont::StorageTagConcatenate<AH1, AH2>>>
387 : Serialization<vtkm::cont::ArrayHandleConcatenate<AH1, AH2>>
388 {
389 };
390 } // diy
391
392 #endif //vtk_m_cont_ArrayHandleConcatenate_h
393