1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //  This software is distributed WITHOUT ANY WARRANTY; without even
6 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
7 //  PURPOSE.  See the above copyright notice for more information.
8 //
9 //  Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 //  Copyright 2014 UT-Battelle, LLC.
11 //  Copyright 2014 Los Alamos National Security.
12 //
13 //  Under the terms of Contract DE-NA0003525 with NTESS,
14 //  the U.S. Government retains certain rights in this software.
15 //
16 //  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
17 //  Laboratory (LANL), the U.S. Government retains certain rights in
18 //  this software.
19 //============================================================================
20 #include <vtkm/cont/ArrayHandle.h>
21 #include <vtkm/cont/ArrayHandleCartesianProduct.h>
22 #include <vtkm/cont/ArrayHandleCast.h>
23 #include <vtkm/cont/ArrayHandleCompositeVector.h>
24 #include <vtkm/cont/ArrayHandleConcatenate.h>
25 #include <vtkm/cont/ArrayHandleConstant.h>
26 #include <vtkm/cont/ArrayHandleCounting.h>
27 #include <vtkm/cont/ArrayHandleExtractComponent.h>
28 #include <vtkm/cont/ArrayHandleGroupVec.h>
29 #include <vtkm/cont/ArrayHandleGroupVecVariable.h>
30 #include <vtkm/cont/ArrayHandleImplicit.h>
31 #include <vtkm/cont/ArrayHandleIndex.h>
32 #include <vtkm/cont/ArrayHandlePermutation.h>
33 #include <vtkm/cont/ArrayHandleReverse.h>
34 #include <vtkm/cont/ArrayHandleSwizzle.h>
35 #include <vtkm/cont/ArrayHandleTransform.h>
36 #include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
37 #include <vtkm/cont/ArrayHandleVirtualCoordinates.h>
38 #include <vtkm/cont/ArrayHandleZip.h>
39 #include <vtkm/cont/DynamicArrayHandle.h>
40 
41 #include <vtkm/cont/testing/TestingSerialization.h>
42 
43 #include <vtkm/VecTraits.h>
44 
45 #include <ctime>
46 #include <type_traits>
47 #include <vector>
48 
49 using namespace vtkm::cont::testing::serialization;
50 
51 namespace
52 {
53 
54 //-----------------------------------------------------------------------------
55 struct TestEqualArrayHandle
56 {
57 public:
58   template <typename ArrayHandle1, typename ArrayHandle2>
operator ()__anon257a451a0111::TestEqualArrayHandle59   VTKM_CONT void operator()(const ArrayHandle1& array1, const ArrayHandle2& array2) const
60   {
61     auto result = vtkm::cont::testing::test_equal_ArrayHandles(array1, array2);
62     VTKM_TEST_ASSERT(result, result.GetMergedMessage());
63   }
64 };
65 
66 //-----------------------------------------------------------------------------
67 template <typename T>
RunTest(const T & obj)68 inline void RunTest(const T& obj)
69 {
70   TestSerialization(obj, TestEqualArrayHandle{});
71 }
72 
73 //-----------------------------------------------------------------------------
74 constexpr vtkm::Id ArraySize = 10;
75 
76 using TestTypesList =
77   vtkm::ListTagBase<vtkm::Int8, vtkm::Id, vtkm::FloatDefault, vtkm::Vec<vtkm::FloatDefault, 3>>;
78 using TestStorageList = vtkm::ListTagBase<vtkm::cont::StorageTagBasic>;
79 
80 template <typename T, typename S>
81 inline vtkm::cont::DynamicArrayHandleBase<vtkm::ListTagAppendUnique<TestTypesList, T>,
82                                           vtkm::ListTagAppendUnique<TestStorageList, S>>
MakeTestDynamicArrayHandle(const vtkm::cont::ArrayHandle<T,S> & array)83 MakeTestDynamicArrayHandle(const vtkm::cont::ArrayHandle<T, S>& array)
84 {
85   return array;
86 }
87 
88 struct TestArrayHandleBasic
89 {
90   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleBasic91   void operator()(T) const
92   {
93     auto array = RandomArrayHandle<T>::Make(ArraySize);
94     RunTest(array);
95     RunTest(MakeTestDynamicArrayHandle(array));
96   }
97 };
98 
99 struct TestArrayHandleCartesianProduct
100 {
101   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleCartesianProduct102   void operator()(T) const
103   {
104     auto array =
105       vtkm::cont::make_ArrayHandleCartesianProduct(RandomArrayHandle<T>::Make(ArraySize),
106                                                    RandomArrayHandle<T>::Make(ArraySize),
107                                                    RandomArrayHandle<T>::Make(ArraySize));
108     RunTest(array);
109     RunTest(MakeTestDynamicArrayHandle(array));
110   }
111 };
112 
113 struct TestArrayHandleCast
114 {
115   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleCast116   void operator()(T) const
117   {
118     auto array =
119       vtkm::cont::make_ArrayHandleCast(RandomArrayHandle<vtkm::Int8>::Make(ArraySize), T{});
120     RunTest(array);
121     RunTest(MakeTestDynamicArrayHandle(array));
122   }
123 };
124 
125 struct TestArrayHandleCompositeVector
126 {
127   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleCompositeVector128   void operator()(T) const
129   {
130     auto array = vtkm::cont::make_ArrayHandleCompositeVector(RandomArrayHandle<T>::Make(ArraySize),
131                                                              RandomArrayHandle<T>::Make(ArraySize));
132     RunTest(array);
133     RunTest(MakeTestDynamicArrayHandle(array));
134   }
135 };
136 
137 struct TestArrayHandleConcatenate
138 {
139   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleConcatenate140   void operator()(T) const
141   {
142     auto array = vtkm::cont::make_ArrayHandleConcatenate(RandomArrayHandle<T>::Make(ArraySize),
143                                                          RandomArrayHandle<T>::Make(ArraySize));
144     RunTest(array);
145     RunTest(MakeTestDynamicArrayHandle(array));
146   }
147 };
148 
149 struct TestArrayHandleConstant
150 {
151   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleConstant152   void operator()(T) const
153   {
154     T cval = RandomValue<T>::Make();
155     auto array = vtkm::cont::make_ArrayHandleConstant(cval, ArraySize);
156     RunTest(array);
157     RunTest(MakeTestDynamicArrayHandle(array));
158   }
159 };
160 
161 struct TestArrayHandleCounting
162 {
163   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleCounting164   void operator()(T) const
165   {
166     T start = RandomValue<T>::Make();
167     T step = RandomValue<T>::Make(0, 5);
168     auto array = vtkm::cont::make_ArrayHandleCounting(start, step, ArraySize);
169     RunTest(array);
170     RunTest(MakeTestDynamicArrayHandle(array));
171   }
172 };
173 
174 struct TestArrayHandleExtractComponent
175 {
176   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleExtractComponent177   void operator()(T) const
178   {
179     auto numComps = vtkm::VecTraits<T>::NUM_COMPONENTS;
180     auto array = vtkm::cont::make_ArrayHandleExtractComponent(
181       RandomArrayHandle<T>::Make(ArraySize), RandomValue<vtkm::IdComponent>::Make(0, numComps - 1));
182     RunTest(array);
183     RunTest(MakeTestDynamicArrayHandle(array));
184   }
185 };
186 
187 struct TestArrayHandleGroupVec
188 {
189   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleGroupVec190   void operator()(T) const
191   {
192     auto numComps = RandomValue<vtkm::IdComponent>::Make(2, 4);
193     auto flat = RandomArrayHandle<T>::Make(ArraySize * numComps);
194     switch (numComps)
195     {
196       case 3:
197       {
198         auto array = vtkm::cont::make_ArrayHandleGroupVec<3>(flat);
199         RunTest(array);
200         RunTest(MakeTestDynamicArrayHandle(array));
201         break;
202       }
203       case 4:
204       {
205         auto array = vtkm::cont::make_ArrayHandleGroupVec<4>(flat);
206         RunTest(array);
207         RunTest(MakeTestDynamicArrayHandle(array));
208         break;
209       }
210       default:
211       {
212         auto array = vtkm::cont::make_ArrayHandleGroupVec<2>(flat);
213         RunTest(array);
214         RunTest(MakeTestDynamicArrayHandle(array));
215         break;
216       }
217     }
218   }
219 };
220 
221 struct TestArrayHandleGroupVecVariable
222 {
223   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleGroupVecVariable224   void operator()(T) const
225   {
226     auto rangen = UniformRandomValueGenerator<vtkm::IdComponent>(1, 4);
227     vtkm::Id size = 0;
228 
229     std::vector<vtkm::Id> comps(ArraySize);
230     std::generate(comps.begin(), comps.end(), [&size, &rangen]() {
231       auto offset = size;
232       size += rangen();
233       return offset;
234     });
235 
236     auto array = vtkm::cont::make_ArrayHandleGroupVecVariable(RandomArrayHandle<T>::Make(size),
237                                                               vtkm::cont::make_ArrayHandle(comps));
238     RunTest(array);
239 
240     // cannot make a DynamicArrayHandle containing ArrayHandleGroupVecVariable
241     // because of the variable number of components of its values.
242     // RunTest(MakeTestDynamicArrayHandle(array));
243   }
244 };
245 
246 struct TestArrayHandleImplicit
247 {
248   template <typename T>
249   struct ImplicitFunctor
250   {
251     ImplicitFunctor() = default;
252 
ImplicitFunctor__anon257a451a0111::TestArrayHandleImplicit::ImplicitFunctor253     explicit ImplicitFunctor(const T& factor)
254       : Factor(factor)
255     {
256     }
257 
operator ()__anon257a451a0111::TestArrayHandleImplicit::ImplicitFunctor258     VTKM_EXEC_CONT T operator()(vtkm::Id index) const
259     {
260       return static_cast<T>(this->Factor *
261                             static_cast<typename vtkm::VecTraits<T>::ComponentType>(index));
262     }
263 
264     T Factor;
265   };
266 
267   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleImplicit268   void operator()(T) const
269   {
270     ImplicitFunctor<T> functor(RandomValue<T>::Make(2, 9));
271     auto array = vtkm::cont::make_ArrayHandleImplicit(functor, ArraySize);
272     RunTest(array);
273     RunTest(MakeTestDynamicArrayHandle(array));
274   }
275 };
276 
TestArrayHandleIndex()277 void TestArrayHandleIndex()
278 {
279   auto size = RandomValue<vtkm::Id>::Make(2, 10);
280   auto array = vtkm::cont::ArrayHandleIndex(size);
281   RunTest(array);
282   RunTest(MakeTestDynamicArrayHandle(array));
283 }
284 
285 struct TestArrayHandlePermutation
286 {
287   template <typename T>
operator ()__anon257a451a0111::TestArrayHandlePermutation288   void operator()(T) const
289   {
290     std::uniform_int_distribution<vtkm::Id> distribution(0, ArraySize - 1);
291 
292     std::vector<vtkm::Id> inds(ArraySize);
293     std::generate(inds.begin(), inds.end(), [&distribution]() { return distribution(generator); });
294 
295     auto array = vtkm::cont::make_ArrayHandlePermutation(
296       RandomArrayHandle<vtkm::Id>::Make(ArraySize, 0, ArraySize - 1),
297       RandomArrayHandle<T>::Make(ArraySize));
298     RunTest(array);
299     RunTest(MakeTestDynamicArrayHandle(array));
300   }
301 };
302 
303 struct TestArrayHandleReverse
304 {
305   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleReverse306   void operator()(T) const
307   {
308     auto array = vtkm::cont::make_ArrayHandleReverse(RandomArrayHandle<T>::Make(ArraySize));
309     RunTest(array);
310     RunTest(MakeTestDynamicArrayHandle(array));
311   }
312 };
313 
314 struct TestArrayHandleSwizzle
315 {
316   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleSwizzle317   void operator()(T) const
318   {
319     static const vtkm::Vec<vtkm::IdComponent, 2> map2s[6] = { { 0, 1 }, { 0, 2 }, { 1, 0 },
320                                                               { 1, 2 }, { 2, 0 }, { 2, 1 } };
321     static const vtkm::Vec<vtkm::IdComponent, 3> map3s[6] = {
322       { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, { 1, 2, 0 }, { 2, 0, 1 }, { 2, 1, 0 }
323     };
324 
325     auto numOutComps = RandomValue<vtkm::IdComponent>::Make(2, 3);
326     switch (numOutComps)
327     {
328       case 2:
329       {
330         auto array = make_ArrayHandleSwizzle(RandomArrayHandle<vtkm::Vec<T, 3>>::Make(ArraySize),
331                                              map2s[RandomValue<int>::Make(0, 5)]);
332         RunTest(array);
333         RunTest(MakeTestDynamicArrayHandle(array));
334         break;
335       }
336       case 3:
337       default:
338       {
339         auto array = make_ArrayHandleSwizzle(RandomArrayHandle<vtkm::Vec<T, 3>>::Make(ArraySize),
340                                              map3s[RandomValue<int>::Make(0, 5)]);
341         RunTest(array);
342         RunTest(MakeTestDynamicArrayHandle(array));
343         break;
344       }
345     }
346   }
347 };
348 
349 struct TestArrayHandleTransform
350 {
351   struct TransformFunctor
352   {
353     template <typename T>
operator ()__anon257a451a0111::TestArrayHandleTransform::TransformFunctor354     VTKM_EXEC_CONT T operator()(const T& in) const
355     {
356       return static_cast<T>(in * T{ 2 });
357     }
358   };
359 
360   struct InverseTransformFunctor
361   {
362     template <typename T>
operator ()__anon257a451a0111::TestArrayHandleTransform::InverseTransformFunctor363     VTKM_EXEC_CONT T operator()(const T& in) const
364     {
365       return in / T{ 2 };
366     }
367   };
368 
369   template <typename T>
TestType1__anon257a451a0111::TestArrayHandleTransform370   void TestType1() const
371   {
372     auto array = vtkm::cont::make_ArrayHandleTransform(RandomArrayHandle<T>::Make(ArraySize),
373                                                        TransformFunctor{});
374     RunTest(array);
375     RunTest(MakeTestDynamicArrayHandle(array));
376   }
377 
378   template <typename T>
TestType2__anon257a451a0111::TestArrayHandleTransform379   void TestType2() const
380   {
381     auto array = vtkm::cont::make_ArrayHandleTransform(
382       RandomArrayHandle<T>::Make(ArraySize), TransformFunctor{}, InverseTransformFunctor{});
383     RunTest(array);
384     RunTest(MakeTestDynamicArrayHandle(array));
385   }
386 
387   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleTransform388   void operator()(T) const
389   {
390     this->TestType1<T>();
391     this->TestType2<T>();
392   }
393 };
394 
MakeRandomArrayHandleUniformPointCoordinates()395 vtkm::cont::ArrayHandleUniformPointCoordinates MakeRandomArrayHandleUniformPointCoordinates()
396 {
397   auto dimensions = RandomValue<vtkm::Id3>::Make(1, 3);
398   auto origin = RandomValue<vtkm::Vec<vtkm::FloatDefault, 3>>::Make();
399   auto spacing = RandomValue<vtkm::Vec<vtkm::FloatDefault, 3>>::Make(0.1f, 10.0f);
400   return vtkm::cont::ArrayHandleUniformPointCoordinates(dimensions, origin, spacing);
401 }
402 
TestArrayHandleUniformPointCoordinates()403 void TestArrayHandleUniformPointCoordinates()
404 {
405   auto array = MakeRandomArrayHandleUniformPointCoordinates();
406   RunTest(array);
407   RunTest(MakeTestDynamicArrayHandle(array));
408 }
409 
TestArrayHandleVirtualCoordinates()410 void TestArrayHandleVirtualCoordinates()
411 {
412   int type = RandomValue<int>::Make(0, 2);
413 
414   vtkm::cont::ArrayHandleVirtualCoordinates array;
415   switch (type)
416   {
417     case 0:
418       array =
419         vtkm::cont::ArrayHandleVirtualCoordinates(MakeRandomArrayHandleUniformPointCoordinates());
420       break;
421     case 1:
422       array =
423         vtkm::cont::ArrayHandleVirtualCoordinates(vtkm::cont::make_ArrayHandleCartesianProduct(
424           RandomArrayHandle<vtkm::FloatDefault>::Make(ArraySize),
425           RandomArrayHandle<vtkm::FloatDefault>::Make(ArraySize),
426           RandomArrayHandle<vtkm::FloatDefault>::Make(ArraySize)));
427       break;
428     default:
429       array = vtkm::cont::ArrayHandleVirtualCoordinates(
430         RandomArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>>::Make(ArraySize));
431       break;
432   }
433 
434   RunTest(array);
435   RunTest(MakeTestDynamicArrayHandle(array));
436 }
437 
438 struct TestArrayHandleZip
439 {
440   template <typename T>
operator ()__anon257a451a0111::TestArrayHandleZip441   void operator()(T) const
442   {
443     auto array = vtkm::cont::make_ArrayHandleZip(RandomArrayHandle<T>::Make(ArraySize),
444                                                  vtkm::cont::ArrayHandleIndex(ArraySize));
445     RunTest(array);
446     RunTest(MakeTestDynamicArrayHandle(array));
447   }
448 };
449 
450 //-----------------------------------------------------------------------------
TestArrayHandleSerialization()451 void TestArrayHandleSerialization()
452 {
453   std::cout << "Testing ArrayHandleBasic\n";
454   vtkm::testing::Testing::TryTypes(TestArrayHandleBasic(), TestTypesList());
455 
456   std::cout << "Testing ArrayHandleCartesianProduct\n";
457   vtkm::testing::Testing::TryTypes(TestArrayHandleCartesianProduct(), TestTypesList());
458 
459   std::cout << "Testing TestArrayHandleCast\n";
460   vtkm::testing::Testing::TryTypes(TestArrayHandleCast(), TestTypesList());
461 
462   std::cout << "Testing ArrayHandleCompositeVector\n";
463   vtkm::testing::Testing::TryTypes(TestArrayHandleCompositeVector(), TestTypesList());
464 
465   std::cout << "Testing ArrayHandleConcatenate\n";
466   vtkm::testing::Testing::TryTypes(TestArrayHandleConcatenate(), TestTypesList());
467 
468   std::cout << "Testing ArrayHandleConstant\n";
469   vtkm::testing::Testing::TryTypes(TestArrayHandleConstant(), TestTypesList());
470 
471   std::cout << "Testing ArrayHandleCounting\n";
472   vtkm::testing::Testing::TryTypes(TestArrayHandleCounting(), TestTypesList());
473 
474   std::cout << "Testing ArrayHandleExtractComponent\n";
475   vtkm::testing::Testing::TryTypes(TestArrayHandleExtractComponent(), TestTypesList());
476 
477   std::cout << "Testing ArrayHandleGroupVec\n";
478   vtkm::testing::Testing::TryTypes(TestArrayHandleGroupVec(), TestTypesList());
479 
480   std::cout << "Testing ArrayHandleGroupVecVariable\n";
481   vtkm::testing::Testing::TryTypes(TestArrayHandleGroupVecVariable(), TestTypesList());
482 
483   std::cout << "Testing ArrayHandleImplicit\n";
484   vtkm::testing::Testing::TryTypes(TestArrayHandleImplicit(), TestTypesList());
485 
486   std::cout << "Testing ArrayHandleIndex\n";
487   TestArrayHandleIndex();
488 
489   std::cout << "Testing ArrayHandlePermutation\n";
490   vtkm::testing::Testing::TryTypes(TestArrayHandlePermutation(), TestTypesList());
491 
492   std::cout << "Testing ArrayHandleReverse\n";
493   vtkm::testing::Testing::TryTypes(TestArrayHandleReverse(), TestTypesList());
494 
495   std::cout << "Testing ArrayHandleSwizzle\n";
496   vtkm::testing::Testing::TryTypes(TestArrayHandleSwizzle(), TestTypesList());
497 
498   std::cout << "Testing ArrayHandleTransform\n";
499   vtkm::testing::Testing::TryTypes(TestArrayHandleTransform(), TestTypesList());
500 
501   std::cout << "Testing ArrayHandleUniformPointCoordinates\n";
502   TestArrayHandleUniformPointCoordinates();
503 
504   std::cout << "Testing ArrayHandleVirtualCoordinates\n";
505   TestArrayHandleVirtualCoordinates();
506 
507   std::cout << "Testing ArrayHandleZip\n";
508   vtkm::testing::Testing::TryTypes(TestArrayHandleZip(), TestTypesList());
509 }
510 
511 } // anonymous namespace
512 
513 //-----------------------------------------------------------------------------
UnitTestSerializationArrayHandle(int,char * [])514 int UnitTestSerializationArrayHandle(int, char* [])
515 {
516   auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
517 
518   decltype(generator)::result_type seed = 0;
519   if (comm.rank() == 0)
520   {
521     seed = static_cast<decltype(seed)>(std::time(nullptr));
522     std::cout << "using seed: " << seed << "\n";
523   }
524   diy::mpi::broadcast(comm, seed, 0);
525   generator.seed(seed);
526 
527   return vtkm::cont::testing::Testing::Run(TestArrayHandleSerialization);
528 }
529 
530 //-----------------------------------------------------------------------------
531 namespace vtkm
532 {
533 namespace cont
534 {
535 
536 template <typename T>
537 struct TypeString<TestArrayHandleImplicit::ImplicitFunctor<T>>
538 {
Getvtkm::cont::TypeString539   static VTKM_CONT const std::string& Get()
540   {
541     static std::string name =
542       "TestArrayHandleImplicit::ImplicitFunctor<" + TypeString<T>::Get() + ">";
543     return name;
544   }
545 };
546 
547 template <>
548 struct TypeString<TestArrayHandleTransform::TransformFunctor>
549 {
Getvtkm::cont::TypeString550   static VTKM_CONT const std::string Get() { return "TestArrayHandleTransform::TransformFunctor"; }
551 };
552 
553 template <>
554 struct TypeString<TestArrayHandleTransform::InverseTransformFunctor>
555 {
Getvtkm::cont::TypeString556   static VTKM_CONT const std::string Get()
557   {
558     return "TestArrayHandleTransform::InverseTransformFunctor";
559   }
560 };
561 }
562 } // vtkm::cont
563