//============================================================================ // 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 #include namespace UnitTestArrayHandleDiscardDetail { template struct Test { static constexpr vtkm::Id ARRAY_SIZE = 100; static constexpr vtkm::Id NUM_KEYS = 3; using DeviceTag = vtkm::cont::DeviceAdapterTagSerial; using Algorithm = vtkm::cont::DeviceAdapterAlgorithm; using Handle = vtkm::cont::ArrayHandle; using DiscardHandle = vtkm::cont::ArrayHandleDiscard; using OutputPortal = typename Handle::WritePortalType; using ReduceOp = vtkm::Add; // Test discard arrays by using the ReduceByKey algorithm. Two regular arrays // handles are provided as inputs, but the keys_output array is a discard // array handle. The values_output array should still be populated correctly. void TestReduceByKey() { // The reduction operator: ReduceOp op; // Prepare inputs / reference data: ValueType keyData[ARRAY_SIZE]; ValueType valueData[ARRAY_SIZE]; ValueType refData[NUM_KEYS]; std::fill(refData, refData + NUM_KEYS, ValueType(0)); for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i) { const vtkm::Id key = i % NUM_KEYS; keyData[i] = static_cast(key); valueData[i] = static_cast(i * 2); refData[key] = op(refData[key], valueData[i]); } // Prepare array handles: Handle keys = vtkm::cont::make_ArrayHandle(keyData, ARRAY_SIZE, vtkm::CopyFlag::Off); Handle values = vtkm::cont::make_ArrayHandle(valueData, ARRAY_SIZE, vtkm::CopyFlag::Off); DiscardHandle output_keys; Handle output_values; Algorithm::SortByKey(keys, values); Algorithm::ReduceByKey(keys, values, output_keys, output_values, op); OutputPortal outputs = output_values.WritePortal(); VTKM_TEST_ASSERT(outputs.GetNumberOfValues() == NUM_KEYS, "Unexpected number of output values from ReduceByKey."); for (vtkm::Id i = 0; i < NUM_KEYS; ++i) { VTKM_TEST_ASSERT(test_equal(outputs.Get(i), refData[i]), "Unexpected output value after ReduceByKey."); } } void TestPrepareExceptions() { vtkm::cont::Token token; DiscardHandle handle; handle.Allocate(50); try { handle.PrepareForInput(DeviceTag(), token); } catch (vtkm::cont::ErrorBadValue&) { // Expected failure. } try { handle.PrepareForInPlace(DeviceTag(), token); } catch (vtkm::cont::ErrorBadValue&) { // Expected failure. } // Shouldn't fail: handle.PrepareForOutput(ARRAY_SIZE, DeviceTag(), token); } void TestFill() { DiscardHandle array; array.AllocateAndFill(ARRAY_SIZE, ValueType{ 0 }); VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE); } void operator()() { TestReduceByKey(); TestPrepareExceptions(); TestFill(); } }; void TestArrayHandleDiscard() { Test()(); Test()(); Test()(); Test()(); Test()(); Test()(); } } // end namespace UnitTestArrayHandleDiscardDetail int UnitTestArrayHandleDiscard(int argc, char* argv[]) { using namespace UnitTestArrayHandleDiscardDetail; return vtkm::cont::testing::Testing::Run(TestArrayHandleDiscard, argc, argv); }