1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //
6 //  This software is distributed WITHOUT ANY WARRANTY; without even
7 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 //  PURPOSE.  See the above copyright notice for more information.
9 //============================================================================
10 #include <vtkm/cont/ArrayCopy.h>
11 #include <vtkm/cont/ArrayHandle.h>
12 #include <vtkm/cont/ArrayHandleCartesianProduct.h>
13 #include <vtkm/cont/ArrayHandleCast.h>
14 #include <vtkm/cont/ArrayHandleCompositeVector.h>
15 #include <vtkm/cont/ArrayHandleConcatenate.h>
16 #include <vtkm/cont/ArrayHandleConstant.h>
17 #include <vtkm/cont/ArrayHandleCounting.h>
18 #include <vtkm/cont/ArrayHandleExtractComponent.h>
19 #include <vtkm/cont/ArrayHandleGroupVec.h>
20 #include <vtkm/cont/ArrayHandleGroupVecVariable.h>
21 #include <vtkm/cont/ArrayHandleImplicit.h>
22 #include <vtkm/cont/ArrayHandleIndex.h>
23 #include <vtkm/cont/ArrayHandlePermutation.h>
24 #include <vtkm/cont/ArrayHandleReverse.h>
25 #include <vtkm/cont/ArrayHandleSOA.h>
26 #include <vtkm/cont/ArrayHandleSwizzle.h>
27 #include <vtkm/cont/ArrayHandleTransform.h>
28 #include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
29 #include <vtkm/cont/ArrayHandleZip.h>
30 
31 #include <vtkm/cont/UncertainArrayHandle.h>
32 #include <vtkm/cont/UnknownArrayHandle.h>
33 
34 #include <vtkm/cont/testing/TestingSerialization.h>
35 
36 #include <vtkm/VecTraits.h>
37 
38 #include <ctime>
39 #include <type_traits>
40 #include <vector>
41 
42 using namespace vtkm::cont::testing::serialization;
43 
44 namespace
45 {
46 
47 using StorageList = vtkm::List<
48   vtkm::cont::StorageTagBasic,
49   vtkm::cont::StorageTagSOA,
50   vtkm::cont::StorageTagCartesianProduct<vtkm::cont::StorageTagBasic,
51                                          vtkm::cont::StorageTagBasic,
52                                          vtkm::cont::StorageTagBasic>,
53   vtkm::cont::StorageTagCast<vtkm::Int8, vtkm::cont::StorageTagBasic>,
54   vtkm::cont::StorageTagConstant,
55   vtkm::cont::StorageTagCounting,
56   vtkm::cont::StorageTagGroupVec<vtkm::cont::StorageTagBasic, 2>,
57   vtkm::cont::StorageTagGroupVec<vtkm::cont::StorageTagBasic, 3>,
58   vtkm::cont::StorageTagGroupVec<vtkm::cont::StorageTagBasic, 4>,
59   vtkm::cont::StorageTagIndex,
60   vtkm::cont::StorageTagPermutation<vtkm::cont::StorageTagBasic, vtkm::cont::StorageTagBasic>,
61   vtkm::cont::StorageTagReverse<vtkm::cont::StorageTagBasic>,
62   vtkm::cont::StorageTagUniformPoints>;
63 
64 //-----------------------------------------------------------------------------
65 struct TestEqualArrayHandle
66 {
67 public:
68   template <typename ArrayHandle1, typename ArrayHandle2>
operator ()__anon2c460e810111::TestEqualArrayHandle69   VTKM_CONT void operator()(const ArrayHandle1& array1, const ArrayHandle2& array2) const
70   {
71     VTKM_TEST_ASSERT(test_equal_ArrayHandles(array1, array2));
72   }
73 
operator ()__anon2c460e810111::TestEqualArrayHandle74   VTKM_CONT void operator()(const vtkm::cont::UnknownArrayHandle& array1,
75                             const vtkm::cont::UnknownArrayHandle& array2) const
76   {
77     VTKM_TEST_ASSERT(test_equal_ArrayHandles(array1.ResetTypes<vtkm::TypeListAll, StorageList>(),
78                                              array2.ResetTypes<vtkm::TypeListAll, StorageList>()));
79   }
80 };
81 
82 //-----------------------------------------------------------------------------
83 template <typename T>
RunTest(const T & obj)84 inline void RunTest(const T& obj)
85 {
86   TestSerialization(obj, TestEqualArrayHandle{});
87 }
88 
89 //-----------------------------------------------------------------------------
90 constexpr vtkm::Id ArraySize = 10;
91 
92 using TestTypesListScalar = vtkm::List<vtkm::Int8, vtkm::Id, vtkm::FloatDefault>;
93 using TestTypesListVec = vtkm::List<vtkm::Vec3f_32, vtkm::Vec3f_64>;
94 using TestTypesList = vtkm::ListAppend<TestTypesListScalar, TestTypesListVec>;
95 
96 template <typename T, typename S>
MakeTestUnknownArrayHandle(const vtkm::cont::ArrayHandle<T,S> & array)97 inline vtkm::cont::UnknownArrayHandle MakeTestUnknownArrayHandle(
98   const vtkm::cont::ArrayHandle<T, S>& array)
99 {
100   return array;
101 }
102 
103 template <typename T, typename S>
MakeTestUncertainArrayHandle(const vtkm::cont::ArrayHandle<T,S> & array)104 inline vtkm::cont::UncertainArrayHandle<vtkm::List<T>, vtkm::List<S>> MakeTestUncertainArrayHandle(
105   const vtkm::cont::ArrayHandle<T, S>& array)
106 {
107   return array;
108 }
109 
110 struct TestArrayHandleBasic
111 {
112   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleBasic113   void operator()(T) const
114   {
115     auto array = RandomArrayHandle<T>::Make(ArraySize);
116     RunTest(array);
117     RunTest(MakeTestUnknownArrayHandle(array));
118     RunTest(MakeTestUncertainArrayHandle(array));
119   }
120 };
121 
122 struct TestArrayHandleSOA
123 {
124   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleSOA125   void operator()(T) const
126   {
127     vtkm::cont::ArrayHandleSOA<T> array;
128     vtkm::cont::ArrayCopy(RandomArrayHandle<T>::Make(ArraySize), array);
129     RunTest(array);
130     RunTest(MakeTestUnknownArrayHandle(array));
131     RunTest(MakeTestUncertainArrayHandle(array));
132   }
133 };
134 
135 struct TestArrayHandleCartesianProduct
136 {
137   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleCartesianProduct138   void operator()(T) const
139   {
140     auto array =
141       vtkm::cont::make_ArrayHandleCartesianProduct(RandomArrayHandle<T>::Make(ArraySize),
142                                                    RandomArrayHandle<T>::Make(ArraySize),
143                                                    RandomArrayHandle<T>::Make(ArraySize));
144     RunTest(array);
145     RunTest(MakeTestUnknownArrayHandle(array));
146     RunTest(MakeTestUncertainArrayHandle(array));
147   }
148 };
149 
150 struct TestArrayHandleCast
151 {
152   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleCast153   void operator()(T) const
154   {
155     auto array =
156       vtkm::cont::make_ArrayHandleCast<T>(RandomArrayHandle<vtkm::Int8>::Make(ArraySize));
157     RunTest(array);
158     RunTest(MakeTestUnknownArrayHandle(array));
159     RunTest(MakeTestUncertainArrayHandle(array));
160   }
161 
162   template <typename T, vtkm::IdComponent N>
operator ()__anon2c460e810111::TestArrayHandleCast163   void operator()(vtkm::Vec<T, N>) const
164   {
165     auto array = vtkm::cont::make_ArrayHandleCast<vtkm::Vec<T, N>>(
166       RandomArrayHandle<vtkm::Vec<vtkm::Int8, N>>::Make(ArraySize));
167     RunTest(array);
168     RunTest(MakeTestUnknownArrayHandle(array));
169     RunTest(MakeTestUncertainArrayHandle(array));
170   }
171 };
172 
173 struct TestArrayHandleConstant
174 {
175   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleConstant176   void operator()(T) const
177   {
178     T cval = RandomValue<T>::Make();
179     auto array = vtkm::cont::make_ArrayHandleConstant(cval, ArraySize);
180     RunTest(array);
181     RunTest(MakeTestUnknownArrayHandle(array));
182     RunTest(MakeTestUncertainArrayHandle(array));
183   }
184 };
185 
186 struct TestArrayHandleCounting
187 {
188   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleCounting189   void operator()(T) const
190   {
191     T start = RandomValue<T>::Make();
192     T step = RandomValue<T>::Make(0, 5);
193     auto array = vtkm::cont::make_ArrayHandleCounting(start, step, ArraySize);
194     RunTest(array);
195     RunTest(MakeTestUnknownArrayHandle(array));
196     RunTest(MakeTestUncertainArrayHandle(array));
197   }
198 };
199 
200 struct TestArrayHandleGroupVec
201 {
202   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleGroupVec203   void operator()(T) const
204   {
205     auto numComps = RandomValue<vtkm::IdComponent>::Make(2, 4);
206     auto flat = RandomArrayHandle<T>::Make(ArraySize * numComps);
207     switch (numComps)
208     {
209       case 3:
210       {
211         auto array = vtkm::cont::make_ArrayHandleGroupVec<3>(flat);
212         RunTest(array);
213         RunTest(MakeTestUnknownArrayHandle(array));
214         RunTest(MakeTestUncertainArrayHandle(array));
215         break;
216       }
217       case 4:
218       {
219         auto array = vtkm::cont::make_ArrayHandleGroupVec<4>(flat);
220         RunTest(array);
221         RunTest(MakeTestUnknownArrayHandle(array));
222         RunTest(MakeTestUncertainArrayHandle(array));
223         break;
224       }
225       default:
226       {
227         auto array = vtkm::cont::make_ArrayHandleGroupVec<2>(flat);
228         RunTest(array);
229         RunTest(MakeTestUnknownArrayHandle(array));
230         RunTest(MakeTestUncertainArrayHandle(array));
231         break;
232       }
233     }
234   }
235 };
236 
237 struct TestArrayHandleGroupVecVariable
238 {
239   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleGroupVecVariable240   void operator()(T) const
241   {
242     auto rangen = UniformRandomValueGenerator<vtkm::IdComponent>(1, 4);
243     vtkm::Id size = 0;
244 
245     std::vector<vtkm::Id> comps(ArraySize);
246     std::generate(comps.begin(), comps.end(), [&size, &rangen]() {
247       auto offset = size;
248       size += rangen();
249       return offset;
250     });
251 
252     auto array = vtkm::cont::make_ArrayHandleGroupVecVariable(
253       RandomArrayHandle<T>::Make(size), vtkm::cont::make_ArrayHandle(comps, vtkm::CopyFlag::On));
254     RunTest(array);
255 
256     // cannot make a UnknownArrayHandle containing ArrayHandleGroupVecVariable
257     // because of the variable number of components of its values.
258     // RunTest(MakeTestUnknownArrayHandle(array));
259   }
260 };
261 
TestArrayHandleIndex()262 void TestArrayHandleIndex()
263 {
264   auto size = RandomValue<vtkm::Id>::Make(2, 10);
265   auto array = vtkm::cont::ArrayHandleIndex(size);
266   RunTest(array);
267   RunTest(MakeTestUnknownArrayHandle(array));
268   RunTest(MakeTestUncertainArrayHandle(array));
269 }
270 
271 struct TestArrayHandlePermutation
272 {
273   template <typename T>
operator ()__anon2c460e810111::TestArrayHandlePermutation274   void operator()(T) const
275   {
276     std::uniform_int_distribution<vtkm::Id> distribution(0, ArraySize - 1);
277 
278     std::vector<vtkm::Id> inds(ArraySize);
279     std::generate(inds.begin(), inds.end(), [&distribution]() { return distribution(generator); });
280 
281     auto array = vtkm::cont::make_ArrayHandlePermutation(
282       RandomArrayHandle<vtkm::Id>::Make(ArraySize, 0, ArraySize - 1),
283       RandomArrayHandle<T>::Make(ArraySize));
284     RunTest(array);
285     RunTest(MakeTestUnknownArrayHandle(array));
286     RunTest(MakeTestUncertainArrayHandle(array));
287   }
288 };
289 
290 struct TestArrayHandleReverse
291 {
292   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleReverse293   void operator()(T) const
294   {
295     auto array = vtkm::cont::make_ArrayHandleReverse(RandomArrayHandle<T>::Make(ArraySize));
296     RunTest(array);
297     RunTest(MakeTestUnknownArrayHandle(array));
298     RunTest(MakeTestUncertainArrayHandle(array));
299   }
300 };
301 
302 struct TestArrayHandleSwizzle
303 {
304   template <typename T>
operator ()__anon2c460e810111::TestArrayHandleSwizzle305   void operator()(T) const
306   {
307     constexpr vtkm::IdComponent NUM_COMPONENTS = vtkm::VecTraits<T>::NUM_COMPONENTS;
308     vtkm::Vec<vtkm::IdComponent, NUM_COMPONENTS> map;
309     for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; ++i)
310     {
311       map[i] = NUM_COMPONENTS - (i + 1);
312     }
313     auto array = vtkm::cont::make_ArrayHandleSwizzle(RandomArrayHandle<T>::Make(ArraySize), map);
314     RunTest(array);
315   }
316 };
317 
318 
MakeRandomArrayHandleUniformPointCoordinates()319 vtkm::cont::ArrayHandleUniformPointCoordinates MakeRandomArrayHandleUniformPointCoordinates()
320 {
321   auto dimensions = RandomValue<vtkm::Id3>::Make(1, 3);
322   auto origin = RandomValue<vtkm::Vec3f>::Make();
323   auto spacing = RandomValue<vtkm::Vec3f>::Make(0.1f, 10.0f);
324   return vtkm::cont::ArrayHandleUniformPointCoordinates(dimensions, origin, spacing);
325 }
326 
TestArrayHandleUniformPointCoordinates()327 void TestArrayHandleUniformPointCoordinates()
328 {
329   auto array = MakeRandomArrayHandleUniformPointCoordinates();
330   RunTest(array);
331   RunTest(MakeTestUnknownArrayHandle(array));
332   RunTest(MakeTestUncertainArrayHandle(array));
333 }
334 
335 
336 //-----------------------------------------------------------------------------
TestArrayHandleSerialization()337 void TestArrayHandleSerialization()
338 {
339   std::cout << "Testing ArrayHandleBasic\n";
340   vtkm::testing::Testing::TryTypes(TestArrayHandleBasic(), TestTypesList());
341   vtkm::testing::Testing::TryTypes(
342     TestArrayHandleBasic(), vtkm::List<char, long, long long, unsigned long, unsigned long long>());
343 
344   std::cout << "Testing ArrayHandleSOA\n";
345   vtkm::testing::Testing::TryTypes(TestArrayHandleSOA(), TestTypesListVec());
346 
347   std::cout << "Testing ArrayHandleCartesianProduct\n";
348   vtkm::testing::Testing::TryTypes(TestArrayHandleCartesianProduct(), TestTypesListScalar());
349 
350   std::cout << "Testing TestArrayHandleCast\n";
351   vtkm::testing::Testing::TryTypes(TestArrayHandleCast(), TestTypesList());
352 
353   std::cout << "Testing ArrayHandleConstant\n";
354   vtkm::testing::Testing::TryTypes(TestArrayHandleConstant(), TestTypesList());
355 
356   std::cout << "Testing ArrayHandleCounting\n";
357   vtkm::testing::Testing::TryTypes(TestArrayHandleCounting(), TestTypesList());
358 
359   std::cout << "Testing ArrayHandleGroupVec\n";
360   vtkm::testing::Testing::TryTypes(TestArrayHandleGroupVec(), TestTypesListScalar());
361 
362   std::cout << "Testing ArrayHandleGroupVecVariable\n";
363   vtkm::testing::Testing::TryTypes(TestArrayHandleGroupVecVariable(), TestTypesList());
364 
365   std::cout << "Testing ArrayHandleIndex\n";
366   TestArrayHandleIndex();
367 
368   std::cout << "Testing ArrayHandlePermutation\n";
369   vtkm::testing::Testing::TryTypes(TestArrayHandlePermutation(), TestTypesList());
370 
371   std::cout << "Testing ArrayHandleReverse\n";
372   vtkm::testing::Testing::TryTypes(TestArrayHandleReverse(), TestTypesList());
373 
374   std::cout << "Testing ArrayHandleSwizzle\n";
375   vtkm::testing::Testing::TryTypes(TestArrayHandleSwizzle(), TestTypesList());
376 
377   std::cout << "Testing ArrayHandleUniformPointCoordinates\n";
378   TestArrayHandleUniformPointCoordinates();
379 }
380 
381 } // anonymous namespace
382 
383 //-----------------------------------------------------------------------------
UnitTestSerializationArrayHandle(int argc,char * argv[])384 int UnitTestSerializationArrayHandle(int argc, char* argv[])
385 {
386   // Normally VTK-m `Testing::Run` would setup the diy MPI env,
387   // but since we need to access it before execution we have
388   // to manually set it  up
389   vtkmdiy::mpi::environment env(argc, argv);
390   auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
391 
392   decltype(generator)::result_type seed = 0;
393   if (comm.rank() == 0)
394   {
395     seed = static_cast<decltype(seed)>(std::time(nullptr));
396     std::cout << "using seed: " << seed << "\n";
397   }
398   vtkmdiy::mpi::broadcast(comm, seed, 0);
399   generator.seed(seed);
400 
401   return vtkm::cont::testing::Testing::Run(TestArrayHandleSerialization, argc, argv);
402 }
403