//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ #include #include #include #include #include #include #include namespace { template struct SwizzleTests { static constexpr vtkm::IdComponent InSize = 4; using SwizzleInputArrayType = vtkm::cont::ArrayHandle>; template using SwizzleArrayType = vtkm::cont::ArrayHandleSwizzle; using ReferenceComponentArrayType = vtkm::cont::ArrayHandleCounting; using ReferenceArrayType = vtkm::cont::ArrayHandleCompositeVector; template using MapType = vtkm::Vec; using Algo = vtkm::cont::Algorithm; // This is used to build a ArrayHandleSwizzle's internal array. ReferenceArrayType RefArray; void ConstructReferenceArray() { // Build the Ref array const vtkm::Id numValues = 32; ReferenceComponentArrayType c1 = vtkm::cont::make_ArrayHandleCounting(3, 2, numValues); ReferenceComponentArrayType c2 = vtkm::cont::make_ArrayHandleCounting(2, 3, numValues); ReferenceComponentArrayType c3 = vtkm::cont::make_ArrayHandleCounting(4, 4, numValues); ReferenceComponentArrayType c4 = vtkm::cont::make_ArrayHandleCounting(1, 3, numValues); this->RefArray = vtkm::cont::make_ArrayHandleCompositeVector(c1, c2, c3, c4); } SwizzleInputArrayType BuildSwizzleInputArray() const { SwizzleInputArrayType result; Algo::Copy(this->RefArray, result); return result; } template void SanityCheck(const MapType& map) const { SwizzleInputArrayType input = this->BuildSwizzleInputArray(); auto swizzle = vtkm::cont::make_ArrayHandleSwizzle(input, map); VTKM_TEST_ASSERT(input.GetNumberOfValues() == swizzle.GetNumberOfValues(), "Number of values in copied Swizzle array does not match input."); } template void ReadTest(const MapType& map) const { // Test that the expected values are read from an Swizzle array. SwizzleInputArrayType input = this->BuildSwizzleInputArray(); auto swizzle = vtkm::cont::make_ArrayHandleSwizzle(input, map); // Test reading the data back in the control env: this->ValidateReadTest(swizzle, map); // Copy the extracted array in the execution environment to test reading: vtkm::cont::ArrayHandle> execCopy; Algo::Copy(swizzle, execCopy); this->ValidateReadTest(execCopy, map); } template void ValidateReadTest(ArrayHandleType testArray, const MapType& map) const { using ReferenceVectorType = typename ReferenceArrayType::ValueType; using SwizzleVectorType = vtkm::Vec; VTKM_TEST_ASSERT(map.GetNumberOfComponents() == vtkm::VecTraits::NUM_COMPONENTS, "Unexpected runtime component map size."); VTKM_TEST_ASSERT(testArray.GetNumberOfValues() == this->RefArray.GetNumberOfValues(), "Number of values incorrect in Read test."); auto refPortal = this->RefArray.ReadPortal(); auto testPortal = testArray.ReadPortal(); SwizzleVectorType refVecSwizzle(vtkm::TypeTraits::ZeroInitialization()); for (vtkm::Id i = 0; i < testArray.GetNumberOfValues(); ++i) { ReferenceVectorType refVec = refPortal.Get(i); // Manually swizzle the reference vector using the runtime map information: for (vtkm::IdComponent j = 0; j < map.GetNumberOfComponents(); ++j) { refVecSwizzle[j] = refVec[map[j]]; } VTKM_TEST_ASSERT(test_equal(refVecSwizzle, testPortal.Get(i), 0.), "Invalid value encountered in Read test."); } } // Doubles everything in the input portal. template struct WriteTestFunctor : vtkm::exec::FunctorBase { PortalType Portal; VTKM_CONT WriteTestFunctor(const PortalType& portal) : Portal(portal) { } VTKM_EXEC_CONT void operator()(vtkm::Id index) const { this->Portal.Set(index, this->Portal.Get(index) * 2.); } }; struct WriteExec { template bool operator()(DeviceTag, SwizzleHandleType& swizzle) const { vtkm::cont::Token token; using Portal = typename SwizzleHandleType::WritePortalType; WriteTestFunctor functor(swizzle.PrepareForInPlace(DeviceTag(), token)); Algo::Schedule(functor, swizzle.GetNumberOfValues()); return true; } }; template void WriteTest(const MapType& map, std::true_type) const { // Control test: { SwizzleInputArrayType input = this->BuildSwizzleInputArray(); auto swizzle = vtkm::cont::make_ArrayHandleSwizzle(input, map); { WriteTestFunctor::WritePortalType> functor( swizzle.WritePortal()); for (vtkm::Id i = 0; i < swizzle.GetNumberOfValues(); ++i) { functor(i); } } this->ValidateWriteTestArray(input, map); } // Exec test: { SwizzleInputArrayType input = this->BuildSwizzleInputArray(); auto swizzle = vtkm::cont::make_ArrayHandleSwizzle(input, map); vtkm::cont::TryExecute(WriteExec{}, swizzle); this->ValidateWriteTestArray(input, map); } } template void WriteTest(const MapType&, std::false_type) const { // Array is not writable } template void WriteTest(const MapType& map) const { this->WriteTest(map, std::integral_constant{}); } // Check that the swizzled components are twice the reference value. template void ValidateWriteTestArray(SwizzleInputArrayType testArray, const MapType& map) const { auto refPortal = this->RefArray.ReadPortal(); auto portal = testArray.ReadPortal(); VTKM_TEST_ASSERT(portal.GetNumberOfValues() == refPortal.GetNumberOfValues(), "Number of values in write test output do not match input."); for (vtkm::Id i = 0; i < portal.GetNumberOfValues(); ++i) { auto value = portal.Get(i); auto refValue = refPortal.Get(i); // Double all of the components that appear in the map to replicate the // test result: for (vtkm::IdComponent j = 0; j < map.GetNumberOfComponents(); ++j) { refValue[map[j]] *= 2; } VTKM_TEST_ASSERT(test_equal(refValue, value, 0.), "Value mismatch in Write test."); } } template void TestSwizzle(const MapType& map) const { this->SanityCheck(map); this->ReadTest(map); this->WriteTest(map); } void operator()() { this->ConstructReferenceArray(); this->TestSwizzle(vtkm::make_Vec(0, 1)); this->TestSwizzle(vtkm::make_Vec(0, 2)); this->TestSwizzle(vtkm::make_Vec(0, 3)); this->TestSwizzle(vtkm::make_Vec(1, 0)); this->TestSwizzle(vtkm::make_Vec(1, 2)); this->TestSwizzle(vtkm::make_Vec(1, 3)); this->TestSwizzle(vtkm::make_Vec(2, 0)); this->TestSwizzle(vtkm::make_Vec(2, 1)); this->TestSwizzle(vtkm::make_Vec(2, 3)); this->TestSwizzle(vtkm::make_Vec(3, 0)); this->TestSwizzle(vtkm::make_Vec(3, 1)); this->TestSwizzle(vtkm::make_Vec(3, 2)); this->TestSwizzle(vtkm::make_Vec(0, 1, 2)); this->TestSwizzle(vtkm::make_Vec(0, 1, 3)); this->TestSwizzle(vtkm::make_Vec(0, 2, 1)); this->TestSwizzle(vtkm::make_Vec(0, 2, 3)); this->TestSwizzle(vtkm::make_Vec(0, 3, 1)); this->TestSwizzle(vtkm::make_Vec(0, 3, 2)); this->TestSwizzle(vtkm::make_Vec(1, 0, 2)); this->TestSwizzle(vtkm::make_Vec(1, 0, 3)); this->TestSwizzle(vtkm::make_Vec(1, 2, 0)); this->TestSwizzle(vtkm::make_Vec(1, 2, 3)); this->TestSwizzle(vtkm::make_Vec(1, 3, 0)); this->TestSwizzle(vtkm::make_Vec(1, 3, 2)); this->TestSwizzle(vtkm::make_Vec(2, 0, 1)); this->TestSwizzle(vtkm::make_Vec(2, 0, 3)); this->TestSwizzle(vtkm::make_Vec(2, 1, 0)); this->TestSwizzle(vtkm::make_Vec(2, 1, 3)); this->TestSwizzle(vtkm::make_Vec(2, 3, 0)); this->TestSwizzle(vtkm::make_Vec(2, 3, 1)); this->TestSwizzle(vtkm::make_Vec(3, 0, 1)); this->TestSwizzle(vtkm::make_Vec(3, 0, 2)); this->TestSwizzle(vtkm::make_Vec(3, 1, 0)); this->TestSwizzle(vtkm::make_Vec(3, 1, 2)); this->TestSwizzle(vtkm::make_Vec(3, 2, 0)); this->TestSwizzle(vtkm::make_Vec(3, 2, 1)); this->TestSwizzle(vtkm::make_Vec(0, 1, 2, 3)); this->TestSwizzle(vtkm::make_Vec(0, 1, 3, 2)); this->TestSwizzle(vtkm::make_Vec(0, 2, 1, 3)); this->TestSwizzle(vtkm::make_Vec(0, 2, 3, 1)); this->TestSwizzle(vtkm::make_Vec(0, 3, 1, 2)); this->TestSwizzle(vtkm::make_Vec(0, 3, 2, 1)); this->TestSwizzle(vtkm::make_Vec(1, 0, 2, 3)); this->TestSwizzle(vtkm::make_Vec(1, 0, 3, 2)); this->TestSwizzle(vtkm::make_Vec(1, 2, 0, 3)); this->TestSwizzle(vtkm::make_Vec(1, 2, 3, 0)); this->TestSwizzle(vtkm::make_Vec(1, 3, 0, 2)); this->TestSwizzle(vtkm::make_Vec(1, 3, 2, 0)); this->TestSwizzle(vtkm::make_Vec(2, 0, 1, 3)); this->TestSwizzle(vtkm::make_Vec(2, 0, 3, 1)); this->TestSwizzle(vtkm::make_Vec(2, 1, 0, 3)); this->TestSwizzle(vtkm::make_Vec(2, 1, 3, 0)); this->TestSwizzle(vtkm::make_Vec(2, 3, 0, 1)); this->TestSwizzle(vtkm::make_Vec(2, 3, 1, 0)); this->TestSwizzle(vtkm::make_Vec(3, 0, 1, 2)); this->TestSwizzle(vtkm::make_Vec(3, 0, 2, 1)); this->TestSwizzle(vtkm::make_Vec(3, 1, 0, 2)); this->TestSwizzle(vtkm::make_Vec(3, 1, 2, 0)); this->TestSwizzle(vtkm::make_Vec(3, 2, 0, 1)); this->TestSwizzle(vtkm::make_Vec(3, 2, 1, 0)); } }; struct ArgToTemplateType { template void operator()(ValueType) const { SwizzleTests()(); } }; void TestArrayHandleSwizzle() { using TestTypes = vtkm::List; vtkm::testing::Testing::TryTypes(ArgToTemplateType(), TestTypes()); } } // end anon namespace int UnitTestArrayHandleSwizzle(int argc, char* argv[]) { return vtkm::cont::testing::Testing::Run(TestArrayHandleSwizzle, argc, argv); }