//============================================================================ // 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 { const vtkm::Id ARRAY_SIZE = 10; struct MySquare { template VTKM_EXEC auto operator()(U u) const -> decltype(vtkm::Dot(u, u)) { return vtkm::Dot(u, u); } }; template struct CheckTransformFunctor : vtkm::exec::FunctorBase { OriginalPortalType OriginalPortal; TransformedPortalType TransformedPortal; VTKM_EXEC void operator()(vtkm::Id index) const { using T = typename TransformedPortalType::ValueType; typename OriginalPortalType::ValueType original = this->OriginalPortal.Get(index); T transformed = this->TransformedPortal.Get(index); if (!test_equal(transformed, MySquare{}(original))) { this->RaiseError("Encountered bad transformed value."); } } }; template VTKM_CONT CheckTransformFunctor make_CheckTransformFunctor(const OriginalArrayHandleType& originalArray, const TransformedArrayHandleType& transformedArray, Device, vtkm::cont::Token& token) { using OriginalPortalType = typename OriginalArrayHandleType::ReadPortalType; using TransformedPortalType = typename TransformedArrayHandleType::ReadPortalType; CheckTransformFunctor functor; functor.OriginalPortal = originalArray.PrepareForInput(Device(), token); functor.TransformedPortal = transformedArray.PrepareForInput(Device(), token); return functor; } template VTKM_CONT void CheckControlPortals(const OriginalArrayHandleType& originalArray, const TransformedArrayHandleType& transformedArray) { std::cout << " Verify that the control portal works" << std::endl; using OriginalPortalType = typename OriginalArrayHandleType::ReadPortalType; using TransformedPortalType = typename TransformedArrayHandleType::ReadPortalType; VTKM_TEST_ASSERT(originalArray.GetNumberOfValues() == transformedArray.GetNumberOfValues(), "Number of values in transformed array incorrect."); OriginalPortalType originalPortal = originalArray.ReadPortal(); TransformedPortalType transformedPortal = transformedArray.ReadPortal(); VTKM_TEST_ASSERT(originalPortal.GetNumberOfValues() == transformedPortal.GetNumberOfValues(), "Number of values in transformed portal incorrect."); for (vtkm::Id index = 0; index < originalArray.GetNumberOfValues(); index++) { using T = typename TransformedPortalType::ValueType; typename OriginalPortalType::ValueType original = originalPortal.Get(index); T transformed = transformedPortal.Get(index); VTKM_TEST_ASSERT(test_equal(transformed, MySquare{}(original)), "Bad transform value."); } } template struct TransformTests { using OutputValueType = typename vtkm::VecTraits::ComponentType; using TransformHandle = vtkm::cont::ArrayHandleTransform, MySquare>; using CountingTransformHandle = vtkm::cont::ArrayHandleTransform, MySquare>; using Device = vtkm::cont::DeviceAdapterTagSerial; using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; void operator()() const { MySquare functor; std::cout << "Test a transform handle with a counting handle as the values" << std::endl; { vtkm::cont::Token token; vtkm::cont::ArrayHandleCounting counting = vtkm::cont::make_ArrayHandleCounting( InputValueType(OutputValueType(0)), InputValueType(1), ARRAY_SIZE); CountingTransformHandle countingTransformed = vtkm::cont::make_ArrayHandleTransform(counting, functor); CheckControlPortals(counting, countingTransformed); std::cout << " Verify that the execution portal works" << std::endl; Algorithm::Schedule( make_CheckTransformFunctor(counting, countingTransformed, Device(), token), ARRAY_SIZE); } std::cout << "Test a transform handle with a normal handle as the values" << std::endl; //we are going to connect the two handles up, and than fill //the values and make the transform sees the new values in the handle vtkm::cont::ArrayHandle input; TransformHandle thandle(input, functor); using Portal = typename vtkm::cont::ArrayHandle::WritePortalType; input.Allocate(ARRAY_SIZE); { Portal portal = input.WritePortal(); for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index) { portal.Set(index, TestValue(index, InputValueType())); } } CheckControlPortals(input, thandle); std::cout << " Verify that the execution portal works" << std::endl; { vtkm::cont::Token token; Algorithm::Schedule(make_CheckTransformFunctor(input, thandle, Device(), token), ARRAY_SIZE); } std::cout << "Modify array handle values to ensure transform gets updated" << std::endl; { Portal portal = input.WritePortal(); for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index) { portal.Set(index, TestValue(index * index, InputValueType())); } } CheckControlPortals(input, thandle); std::cout << " Verify that the execution portal works" << std::endl; { vtkm::cont::Token token; Algorithm::Schedule(make_CheckTransformFunctor(input, thandle, Device(), token), ARRAY_SIZE); } } }; struct TryInputType { template void operator()(InputType) const { TransformTests()(); } }; void TestArrayHandleTransform() { vtkm::testing::Testing::TryTypes(TryInputType()); } } // anonymous namespace int UnitTestArrayHandleTransform(int argc, char* argv[]) { return vtkm::cont::testing::Testing::Run(TestArrayHandleTransform, argc, argv); }