vtk-m/vtkm/cont/testing/TestingDeviceAdapter.h

3098 lines
110 KiB
C
Raw Normal View History

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
2019-04-15 23:24:21 +00:00
//
// 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.
//============================================================================
#ifndef vtk_m_cont_testing_TestingDeviceAdapter_h
#define vtk_m_cont_testing_TestingDeviceAdapter_h
#include <vtkm/BinaryOperators.h>
2017-05-18 14:51:24 +00:00
#include <vtkm/BinaryPredicates.h>
#include <vtkm/TypeTraits.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCast.h>
2015-06-10 20:37:52 +00:00
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/ArrayHandleView.h>
2015-06-10 20:37:52 +00:00
#include <vtkm/cont/ArrayHandleZip.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
2017-05-18 14:51:24 +00:00
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/ErrorExecution.h>
#include <vtkm/cont/RuntimeDeviceInformation.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/internal/ArrayPortalFromIterators.h>
2017-03-29 14:48:43 +00:00
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/cont/AtomicArray.h>
2016-02-10 15:51:31 +00:00
#include <algorithm>
#include <chrono>
#include <cmath>
#include <ctime>
#include <random>
#include <thread>
#include <utility>
#include <vector>
#include <vtkm/internal/Windows.h>
2017-05-18 14:29:41 +00:00
namespace vtkm
{
namespace cont
{
namespace testing
{
#define ERROR_MESSAGE "Got an error."
2021-04-10 12:27:31 +00:00
#define ARRAY_SIZE 100
#define OFFSET 10
#define DIM_SIZE 8
/// This class has a single static member, Run, that tests the templated
/// DeviceAdapter for conformance.
///
2017-05-18 14:29:41 +00:00
template <class DeviceAdapterTag>
struct TestingDeviceAdapter
{
private:
using StorageTag = vtkm::cont::StorageTagBasic;
using IdArrayHandle = vtkm::cont::ArrayHandle<vtkm::Id, StorageTag>;
using IdComponentArrayHandle = vtkm::cont::ArrayHandle<vtkm::IdComponent, StorageTag>;
using ScalarArrayHandle = vtkm::cont::ArrayHandle<vtkm::FloatDefault, StorageTag>;
using FloatCastHandle = vtkm::cont::ArrayHandleCast<vtkm::FloatDefault, IdArrayHandle>;
using IdPortalType = typename IdArrayHandle::WritePortalType;
using IdPortalConstType = typename IdArrayHandle::ReadPortalType;
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapterTag>;
public:
// Cuda kernels have to be public (in Cuda 4.0).
template <typename PortalType>
struct GenericClearArrayKernel
{
using ValueType = typename PortalType::ValueType;
VTKM_CONT
GenericClearArrayKernel(const PortalType& array,
const ValueType& fillValue = static_cast<ValueType>(OFFSET))
2017-05-18 14:29:41 +00:00
: Array(array)
, Dims()
, FillValue(fillValue)
2017-05-18 14:29:41 +00:00
{
}
VTKM_CONT
GenericClearArrayKernel(const PortalType& array,
const vtkm::Id3& dims,
const ValueType& fillValue = static_cast<ValueType>(OFFSET))
2017-05-18 14:29:41 +00:00
: Array(array)
, Dims(dims)
, FillValue(fillValue)
{
}
VTKM_EXEC void operator()(vtkm::Id index) const { this->Array.Set(index, this->FillValue); }
2017-05-18 14:29:41 +00:00
VTKM_EXEC void operator()(vtkm::Id3 index) const
{
//convert from id3 to id
2017-05-18 14:29:41 +00:00
vtkm::Id flatIndex = index[0] + this->Dims[0] * (index[1] + this->Dims[1] * index[2]);
this->operator()(flatIndex);
}
2017-05-18 14:29:41 +00:00
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
PortalType Array;
vtkm::Id3 Dims;
ValueType FillValue;
};
using ClearArrayKernel = GenericClearArrayKernel<IdPortalType>;
template <typename PortalType>
struct AddArrayKernel
{
VTKM_CONT
AddArrayKernel(const PortalType& array)
2017-05-18 14:29:41 +00:00
: Array(array)
, Dims()
{
}
VTKM_CONT
AddArrayKernel(const PortalType& array, const vtkm::Id3& dims)
2017-05-18 14:29:41 +00:00
: Array(array)
, Dims(dims)
{
}
VTKM_EXEC void operator()(vtkm::Id index) const
{
this->Array.Set(index, this->Array.Get(index) + index);
}
VTKM_EXEC void operator()(vtkm::Id3 index) const
{
//convert from id3 to id
2017-05-18 14:29:41 +00:00
vtkm::Id flatIndex = index[0] + this->Dims[0] * (index[1] + this->Dims[1] * index[2]);
this->operator()(flatIndex);
}
2017-05-18 14:29:41 +00:00
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
PortalType Array;
vtkm::Id3 Dims;
};
template <typename PortalType>
static VTKM_CONT AddArrayKernel<PortalType> MakeAddArrayKernel(
PortalType portal,
const vtkm::Id3& dims = vtkm::Id3{})
{
return AddArrayKernel<PortalType>(portal, dims);
}
// Checks that each instance is only visited once:
struct OverlapKernel
{
using ArrayType = ArrayHandle<bool>;
using PortalType = typename ArrayType::WritePortalType;
PortalType TrackerPortal;
PortalType ValidPortal;
vtkm::Id3 Dims;
VTKM_CONT
OverlapKernel(const PortalType& trackerPortal,
const PortalType& validPortal,
const vtkm::Id3& dims)
: TrackerPortal(trackerPortal)
, ValidPortal(validPortal)
, Dims(dims)
{
}
VTKM_CONT
OverlapKernel(const PortalType& trackerPortal, const PortalType& validPortal)
: TrackerPortal(trackerPortal)
, ValidPortal(validPortal)
, Dims()
{
}
VTKM_EXEC void operator()(vtkm::Id index) const
{
if (this->TrackerPortal.Get(index))
{ // this index has already been visited, that's an error
this->ValidPortal.Set(index, false);
}
else
{
this->TrackerPortal.Set(index, true);
this->ValidPortal.Set(index, true);
}
}
VTKM_EXEC void operator()(vtkm::Id3 index) const
{
//convert from id3 to id
vtkm::Id flatIndex = index[0] + this->Dims[0] * (index[1] + this->Dims[1] * index[2]);
this->operator()(flatIndex);
}
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
};
struct OneErrorKernel
{
VTKM_EXEC void operator()(vtkm::Id index) const
{
2017-05-18 14:29:41 +00:00
if (index == ARRAY_SIZE / 2)
{
this->ErrorMessage.RaiseError(ERROR_MESSAGE);
}
}
VTKM_CONT void SetErrorMessageBuffer(
2017-05-18 14:29:41 +00:00
const vtkm::exec::internal::ErrorMessageBuffer& errorMessage)
{
this->ErrorMessage = errorMessage;
}
vtkm::exec::internal::ErrorMessageBuffer ErrorMessage;
};
struct AllErrorKernel
{
VTKM_EXEC void operator()(vtkm::Id vtkmNotUsed(index)) const
{
this->ErrorMessage.RaiseError(ERROR_MESSAGE);
}
VTKM_CONT void SetErrorMessageBuffer(
2017-05-18 14:29:41 +00:00
const vtkm::exec::internal::ErrorMessageBuffer& errorMessage)
{
this->ErrorMessage = errorMessage;
}
vtkm::exec::internal::ErrorMessageBuffer ErrorMessage;
};
struct OffsetPlusIndexKernel
{
VTKM_CONT
2017-05-18 14:29:41 +00:00
OffsetPlusIndexKernel(const IdPortalType& array)
: Array(array)
{
}
2017-05-18 14:29:41 +00:00
VTKM_EXEC void operator()(vtkm::Id index) const { this->Array.Set(index, OFFSET + index); }
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
IdPortalType Array;
};
struct MarkOddNumbersKernel
{
VTKM_CONT
2017-05-18 14:29:41 +00:00
MarkOddNumbersKernel(const IdPortalType& array)
: Array(array)
{
}
2017-05-18 14:29:41 +00:00
VTKM_EXEC void operator()(vtkm::Id index) const { this->Array.Set(index, index % 2); }
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
IdPortalType Array;
};
struct FuseAll
{
2017-05-18 14:29:41 +00:00
template <typename T>
VTKM_EXEC bool operator()(const T&, const T&) const
{
//binary predicates for unique return true if they are the same
return true;
}
};
2017-05-18 14:29:41 +00:00
template <typename T>
struct AtomicKernel
2016-02-10 15:51:31 +00:00
{
VTKM_CONT
AtomicKernel(const vtkm::cont::AtomicArray<T>& array, vtkm::cont::Token& token)
: AArray(array.PrepareForExecution(DeviceAdapterTag(), token))
2017-05-18 14:29:41 +00:00
{
}
2016-02-10 15:51:31 +00:00
VTKM_EXEC void operator()(vtkm::Id index) const
2016-02-10 15:51:31 +00:00
{
2017-05-18 14:29:41 +00:00
T value = (T)index;
this->AArray.Add(0, value);
2016-02-10 15:51:31 +00:00
}
2017-05-18 14:29:41 +00:00
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
2016-02-10 15:51:31 +00:00
vtkm::exec::AtomicArrayExecutionObject<T> AArray;
2016-02-10 15:51:31 +00:00
};
2017-05-18 14:29:41 +00:00
template <typename T>
struct AtomicCASKernel
{
VTKM_CONT
AtomicCASKernel(const vtkm::cont::AtomicArray<T>& array, vtkm::cont::Token& token)
: AArray(array.PrepareForExecution(DeviceAdapterTag(), token))
2017-05-18 14:29:41 +00:00
{
}
VTKM_EXEC void operator()(vtkm::Id index) const
{
2017-05-18 14:29:41 +00:00
T value = (T)index;
//Get the old value from the array
T oldValue = this->AArray.Get(0);
Change interface of atomic compare and swap The old atomic compare and swap operations (`vtkm::AtomicCompareAndSwap` and `vtkm::exec::AtomicArrayExecutionObject::CompareAndSwap`) had an order of arguments that was confusing. The order of the arguments was shared pointer (or index), desired value, expected value. Most people probably assume expected value comes before desired value. And this order conflicts with the order in the `std` methods, GCC atomics, and Kokkos. Change the interface of atomic operations to be patterned off the `std::atomic_compare_exchange` and `std::atomic<T>::compare_exchange` methods. First, these methods have a more intuitive order of parameters (shared pointer, expected, desired). Second, rather than take a value for the expected and return the actual old value, they take a pointer to the expected value (or reference in `AtomicArrayExecutionObject`) and modify this value in the case that it does not match the actual value. This makes it harder to mix up the expected and desired parameters. Also, because the methods return a bool indicating whether the value was changed, there is an additional benefit that compare-exchange loops are implemented easier. For example, consider you want to apply the function `MyOp` on a `sharedValue` atomically. With the old interface, you would have to do something like this. ```cpp T oldValue; T newValue; do { oldValue = *sharedValue; newValue = MyOp(oldValue); } while (vtkm::AtomicCompareAndSwap(sharedValue, newValue, oldValue) != oldValue); ``` With the new interface, this is simplfied to this. ```cpp T oldValue = *sharedValue; while (!vtkm::AtomicCompareExchange(sharedValue, &oldValue, MyOp(oldValue)); ```
2020-09-25 00:02:59 +00:00
//Use atomic compare-exchange to atomically add value
while (!this->AArray.CompareExchange(0, &oldValue, oldValue + value))
;
}
2017-05-18 14:29:41 +00:00
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
vtkm::exec::AtomicArrayExecutionObject<T> AArray;
};
2017-03-29 14:48:43 +00:00
class VirtualObjectTransferKernel
{
public:
2017-10-23 13:38:33 +00:00
struct Interface : public vtkm::VirtualObjectBase
2017-03-29 14:48:43 +00:00
{
2017-10-23 13:38:33 +00:00
VTKM_EXEC virtual vtkm::Id Foo() const = 0;
2017-03-29 14:48:43 +00:00
};
2017-10-23 13:38:33 +00:00
struct Concrete : public Interface
2017-03-29 14:48:43 +00:00
{
2017-10-23 13:38:33 +00:00
VTKM_EXEC vtkm::Id Foo() const override { return this->Value; }
2017-03-29 14:48:43 +00:00
vtkm::Id Value = 0;
};
VirtualObjectTransferKernel(const Interface* vo,
IdArrayHandle& result,
vtkm::cont::Token& token)
2017-05-18 14:29:41 +00:00
: Virtual(vo)
, Result(result.PrepareForInPlace(DeviceAdapterTag(), token))
2017-03-29 14:48:43 +00:00
{
}
2017-05-18 14:29:41 +00:00
VTKM_EXEC
2017-10-23 13:38:33 +00:00
void operator()(vtkm::Id) const { this->Result.Set(0, this->Virtual->Foo()); }
2017-05-18 14:29:41 +00:00
VTKM_CONT void SetErrorMessageBuffer(const vtkm::exec::internal::ErrorMessageBuffer&) {}
2017-03-29 14:48:43 +00:00
private:
2017-10-23 13:38:33 +00:00
const Interface* Virtual;
2017-03-29 14:48:43 +00:00
IdPortalType Result;
};
struct CustomPairOp
{
using ValueType = vtkm::Pair<vtkm::Id, vtkm::Float32>;
VTKM_EXEC
ValueType operator()(const vtkm::Id& a) const { return ValueType(a, 0.0f); }
VTKM_EXEC
ValueType operator()(const vtkm::Id& a, const vtkm::Id& b) const
{
return ValueType(vtkm::Max(a, b), 0.0f);
}
VTKM_EXEC
ValueType operator()(const ValueType& a, const ValueType& b) const
{
return ValueType(vtkm::Max(a.first, b.first), 0.0f);
}
VTKM_EXEC
ValueType operator()(const vtkm::Id& a, const ValueType& b) const
{
return ValueType(vtkm::Max(a, b.first), 0.0f);
}
VTKM_EXEC
ValueType operator()(const ValueType& a, const vtkm::Id& b) const
{
return ValueType(vtkm::Max(a.first, b), 0.0f);
}
};
struct CustomTForReduce
{
constexpr CustomTForReduce()
: Value(0.0f)
{
}
constexpr CustomTForReduce(float f)
: Value(f)
{
}
VTKM_EXEC_CONT
constexpr float value() const { return this->Value; }
float Value;
};
template <typename T>
struct CustomMinAndMax
{
VTKM_EXEC_CONT
vtkm::Vec<float, 2> operator()(const T& a) const
{
return vtkm::make_Vec(a.value(), a.value());
}
VTKM_EXEC_CONT
vtkm::Vec<float, 2> operator()(const T& a, const T& b) const
{
return vtkm::make_Vec(vtkm::Min(a.value(), b.value()), vtkm::Max(a.value(), b.value()));
}
VTKM_EXEC_CONT
vtkm::Vec<float, 2> operator()(const vtkm::Vec<float, 2>& a, const vtkm::Vec<float, 2>& b) const
{
return vtkm::make_Vec(vtkm::Min(a[0], b[0]), vtkm::Max(a[1], b[1]));
}
VTKM_EXEC_CONT
vtkm::Vec<float, 2> operator()(const T& a, const vtkm::Vec<float, 2>& b) const
{
return vtkm::make_Vec(vtkm::Min(a.value(), b[0]), vtkm::Max(a.value(), b[1]));
}
VTKM_EXEC_CONT
vtkm::Vec<float, 2> operator()(const vtkm::Vec<float, 2>& a, const T& b) const
{
return vtkm::make_Vec(vtkm::Min(a[0], b.value()), vtkm::Max(a[1], b.value()));
}
};
private:
static VTKM_CONT void TestDeviceAdapterTag()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing device adapter tag" << std::endl;
constexpr DeviceAdapterTag deviceTag;
constexpr vtkm::cont::DeviceAdapterTagUndefined undefinedTag;
VTKM_TEST_ASSERT(deviceTag.GetValue() == deviceTag.GetValue(),
"Device adapter Id does not equal itself.");
VTKM_TEST_ASSERT(deviceTag.GetValue() != undefinedTag.GetValue(),
"Device adapter Id not distinguishable from others.");
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
VTKM_TEST_ASSERT(Traits::GetName() == Traits::GetName(),
"Device adapter Name does not equal itself.");
}
static VTKM_CONT void TestMemoryTransfer()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Memory Transfer" << std::endl;
using T = vtkm::Id;
using PortalType = vtkm::cont::internal::ArrayPortalFromIterators<T*>;
auto makePortal = [](const vtkm::cont::internal::BufferInfo& buffer) {
return PortalType(static_cast<T*>(buffer.GetPointer()),
static_cast<T*>(buffer.GetPointer()) +
static_cast<std::size_t>(buffer.GetSize()) / sizeof(T));
};
constexpr vtkm::BufferSizeType BUFFER_SIZE =
ARRAY_SIZE * static_cast<vtkm::BufferSizeType>(sizeof(T));
// Set up buffer on host.
vtkm::cont::internal::BufferInfo hostBufferSrc =
vtkm::cont::internal::AllocateOnHost(BUFFER_SIZE);
VTKM_TEST_ASSERT(hostBufferSrc.GetSize() == BUFFER_SIZE);
SetPortal(makePortal(hostBufferSrc));
vtkm::cont::internal::DeviceAdapterMemoryManager<DeviceAdapterTag> memoryManager;
2021-04-10 15:44:12 +00:00
// Allocate a buffer.
vtkm::cont::internal::BufferInfo allocatedMemory = memoryManager.Allocate(BUFFER_SIZE);
VTKM_TEST_ASSERT(allocatedMemory.GetSize() == BUFFER_SIZE);
2021-04-10 15:44:12 +00:00
// Copy data from host to device.
allocatedMemory = memoryManager.CopyHostToDevice(hostBufferSrc);
2021-04-10 15:44:12 +00:00
// Copy data within device.
vtkm::cont::internal::BufferInfo workingMemory =
memoryManager.CopyDeviceToDevice(allocatedMemory);
VTKM_TEST_ASSERT(workingMemory.GetSize() == BUFFER_SIZE);
2021-04-10 15:44:12 +00:00
// Copy data back to host.
vtkm::cont::internal::BufferInfo hostBufferDest = memoryManager.CopyDeviceToHost(workingMemory);
VTKM_TEST_ASSERT(hostBufferDest.GetSize() == BUFFER_SIZE);
CheckPortal(makePortal(hostBufferDest));
2021-04-10 15:44:12 +00:00
// Shrink a buffer (and preserve memory)
memoryManager.Reallocate(workingMemory, BUFFER_SIZE / 2);
hostBufferDest = memoryManager.CopyDeviceToHost(workingMemory);
VTKM_TEST_ASSERT(hostBufferDest.GetSize() == BUFFER_SIZE / 2);
CheckPortal(makePortal(hostBufferDest));
2021-04-10 15:44:12 +00:00
// Grow a buffer (and preserve memory)
memoryManager.Reallocate(workingMemory, BUFFER_SIZE * 2);
hostBufferDest = memoryManager.CopyDeviceToHost(workingMemory);
VTKM_TEST_ASSERT(hostBufferDest.GetSize() == BUFFER_SIZE * 2);
hostBufferDest.Reallocate(BUFFER_SIZE / 2);
CheckPortal(makePortal(hostBufferDest));
2021-04-10 15:44:12 +00:00
// Make sure data is actually available on the device.
// This actually requires running schedule.
workingMemory = memoryManager.CopyDeviceToDevice(allocatedMemory);
Algorithm::Schedule(MakeAddArrayKernel(makePortal(workingMemory)), ARRAY_SIZE);
hostBufferDest = memoryManager.CopyDeviceToHost(workingMemory);
PortalType portal = makePortal(hostBufferDest);
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == ARRAY_SIZE);
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
{
T expected = TestValue(index, T()) + T(index);
T computed = portal.Get(index);
VTKM_TEST_ASSERT(test_equal(expected, computed), expected, " != ", computed);
}
}
static VTKM_CONT void TestOutOfMemory()
{
2017-05-18 14:29:41 +00:00
// Only test out of memory with 64 bit ids. If there are 32 bit ids on
// a 64 bit OS (common), it is simply too hard to get a reliable allocation
// that is too much memory.
#ifdef VTKM_USE_64BIT_IDS
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Out of Memory" << std::endl;
bool caughtBadAlloc = false;
try
{
2021-04-10 15:44:12 +00:00
std::cout << "Do array allocation that should fail." << std::endl;
vtkm::cont::Token token;
vtkm::cont::ArrayHandle<vtkm::Vec4f_32, StorageTagBasic> bigArray;
2020-06-16 12:54:01 +00:00
const vtkm::Id bigSize = 0x7FFFFFFFFFFFFFFELL;
bigArray.PrepareForOutput(bigSize, DeviceAdapterTag{}, token);
// It does not seem reasonable to get here. The previous call should fail.
VTKM_TEST_FAIL("A ridiculously sized allocation succeeded. Either there "
"was a failure that was not reported but should have been "
"or the width of vtkm::Id is not large enough to express all "
"array sizes.");
}
2021-04-10 13:11:27 +00:00
catch (vtkm::cont::ErrorBadAllocation&)
{
2021-04-10 15:44:12 +00:00
caughtBadAlloc = true;
}
2021-04-10 15:44:12 +00:00
VTKM_TEST_ASSERT(caughtBadAlloc);
#endif
}
VTKM_CONT
static void TestTimer()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Timer" << std::endl;
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
if (tracker.CanRunOn(DeviceAdapterTag()))
{
vtkm::cont::Timer timer{ DeviceAdapterTag() };
timer.Start();
Algorithm::Synchronize();
2021-04-10 15:44:12 +00:00
std::cout << "Timer started. Sleeping..." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
2021-04-10 15:44:12 +00:00
std::cout << "Woke up. Check time." << std::endl;
timer.Stop();
vtkm::Float64 elapsedTime = timer.GetElapsedTime();
2021-04-10 15:44:12 +00:00
std::cout << "Elapsed time: " << elapsedTime << std::endl;
VTKM_TEST_ASSERT(elapsedTime > 0.499, "Timer did not capture full second wait.");
VTKM_TEST_ASSERT(elapsedTime < 1.0, "Timer counted too far or system really busy.");
}
}
2017-03-29 14:48:43 +00:00
VTKM_CONT
static void TestVirtualObjectTransfer()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing VirtualObjectTransfer" << std::endl;
2017-10-23 13:38:33 +00:00
using BaseType = typename VirtualObjectTransferKernel::Interface;
2017-03-29 14:48:43 +00:00
using TargetType = typename VirtualObjectTransferKernel::Concrete;
2017-10-23 13:38:33 +00:00
using Transfer = vtkm::cont::internal::VirtualObjectTransfer<TargetType, DeviceAdapterTag>;
2017-03-29 14:48:43 +00:00
IdArrayHandle result;
result.Allocate(1);
result.WritePortal().Set(0, 0);
2017-03-29 14:48:43 +00:00
TargetType target;
target.Value = 5;
2017-10-23 13:38:33 +00:00
Transfer transfer(&target);
const BaseType* base = static_cast<const BaseType*>(transfer.PrepareForExecution(false));
2017-03-29 14:48:43 +00:00
{
vtkm::cont::Token token;
Algorithm::Schedule(VirtualObjectTransferKernel(base, result, token), 1);
}
VTKM_TEST_ASSERT(result.ReadPortal().Get(0) == 5, "Did not get expected result");
2017-03-29 14:48:43 +00:00
{
vtkm::cont::Token token;
target.Value = 10;
base = static_cast<const BaseType*>(transfer.PrepareForExecution(true));
Algorithm::Schedule(VirtualObjectTransferKernel(base, result, token), 1);
}
VTKM_TEST_ASSERT(result.ReadPortal().Get(0) == 10, "Did not get expected result");
2017-03-29 14:48:43 +00:00
2017-10-23 13:38:33 +00:00
transfer.ReleaseResources();
2017-03-29 14:48:43 +00:00
}
static VTKM_CONT void TestAlgorithmSchedule()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing single value Scheduling with vtkm::Id" << std::endl;
{
2021-04-10 15:44:12 +00:00
// Allocating execution array
vtkm::cont::ArrayHandle<vtkm::Id> handle;
{
vtkm::cont::Token token;
Algorithm::Schedule(ClearArrayKernel(handle.PrepareForOutput(1, DeviceAdapterTag{}, token)),
1);
}
{
vtkm::cont::Token token;
Algorithm::Schedule(MakeAddArrayKernel(handle.PrepareForInPlace(DeviceAdapterTag{}, token)),
1);
}
auto portal = handle.ReadPortal();
for (vtkm::Id index = 0; index < 1; index++)
{
vtkm::Id value = portal.Get(index);
VTKM_TEST_ASSERT(value == index + OFFSET,
"Got bad value for single value scheduled kernel.");
}
} //release memory
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Schedule with vtkm::Id" << std::endl;
{
vtkm::cont::ArrayHandle<vtkm::Id> handle;
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(handle.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag{}, token)),
ARRAY_SIZE);
}
{
vtkm::cont::Token token;
Algorithm::Schedule(MakeAddArrayKernel(handle.PrepareForInPlace(DeviceAdapterTag{}, token)),
ARRAY_SIZE);
}
auto portal = handle.ReadPortal();
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
vtkm::Id value = portal.Get(index);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == index + OFFSET, "Got bad value for scheduled kernels.");
}
} //release memory
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Schedule with a vary large Id value" << std::endl;
{
2021-04-10 15:44:12 +00:00
// Allocating execution array.
vtkm::cont::ArrayHandle<vtkm::Id> handle;
//size is selected to be larger than the CUDA backend can launch in a
//single invocation when compiled for SM_2 support
const vtkm::Id size = 8400000;
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(handle.PrepareForOutput(size, DeviceAdapterTag{}, token)), size);
}
{
vtkm::cont::Token token;
Algorithm::Schedule(MakeAddArrayKernel(handle.PrepareForInPlace(DeviceAdapterTag{}, token)),
size);
}
//Rather than testing for correctness every value of a large array,
// we randomly test a subset of that array.
std::default_random_engine generator(static_cast<unsigned int>(std::time(nullptr)));
std::uniform_int_distribution<vtkm::Id> distribution(0, size - 1);
vtkm::Id numberOfSamples = size / 100;
auto portal = handle.ReadPortal();
for (vtkm::Id i = 0; i < numberOfSamples; ++i)
{
vtkm::Id randomIndex = distribution(generator);
vtkm::Id value = portal.Get(randomIndex);
VTKM_TEST_ASSERT(value == randomIndex + OFFSET, "Got bad value for scheduled kernels.");
}
} //release memory
//verify that the schedule call works with id3
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Schedule with vtkm::Id3" << std::endl;
{
2021-04-10 15:44:12 +00:00
std::cout << "Allocating execution array" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Id> handle;
vtkm::Id3 maxRange(DIM_SIZE);
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(
handle.PrepareForOutput(DIM_SIZE * DIM_SIZE * DIM_SIZE, DeviceAdapterTag{}, token),
maxRange),
maxRange);
}
{
vtkm::cont::Token token;
Algorithm::Schedule(
MakeAddArrayKernel(handle.PrepareForInPlace(DeviceAdapterTag{}, token), maxRange),
maxRange);
}
const vtkm::Id maxId = DIM_SIZE * DIM_SIZE * DIM_SIZE;
auto portal = handle.ReadPortal();
for (vtkm::Id index = 0; index < maxId; index++)
{
vtkm::Id value = portal.Get(index);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == index + OFFSET, "Got bad value for scheduled vtkm::Id3 kernels.");
}
} //release memory
// Ensure that each element is only visited once:
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Schedule for overlap" << std::endl;
{
using BoolArray = ArrayHandle<bool>;
using BoolPortal = typename BoolArray::WritePortalType;
BoolArray tracker;
BoolArray valid;
// Initialize tracker with 'false' values
2021-04-10 15:44:12 +00:00
std::cout << "Allocating and initializing memory" << std::endl;
{
vtkm::cont::Token token;
Algorithm::Schedule(
GenericClearArrayKernel<BoolPortal>(
tracker.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token), false),
ARRAY_SIZE);
Algorithm::Schedule(GenericClearArrayKernel<BoolPortal>(
valid.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token), false),
ARRAY_SIZE);
}
2021-04-10 15:44:12 +00:00
std::cout << "Running Overlap kernel." << std::endl;
{
vtkm::cont::Token token;
Algorithm::Schedule(OverlapKernel(tracker.PrepareForInPlace(DeviceAdapterTag(), token),
valid.PrepareForInPlace(DeviceAdapterTag(), token)),
ARRAY_SIZE);
}
auto vPortal = valid.ReadPortal();
for (vtkm::Id i = 0; i < ARRAY_SIZE; i++)
{
bool isValid = vPortal.Get(i);
VTKM_TEST_ASSERT(isValid, "Schedule executed some elements more than once.");
}
} // release memory
// Ensure that each element is only visited once:
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Schedule for overlap with vtkm::Id3" << std::endl;
{
static constexpr vtkm::Id numElems{ DIM_SIZE * DIM_SIZE * DIM_SIZE };
static const vtkm::Id3 dims{ DIM_SIZE, DIM_SIZE, DIM_SIZE };
using BoolArray = ArrayHandle<bool>;
using BoolPortal = typename BoolArray::WritePortalType;
BoolArray tracker;
BoolArray valid;
// Initialize tracker with 'false' values
2021-04-10 15:44:12 +00:00
std::cout << "Allocating and initializing memory" << std::endl;
{
vtkm::cont::Token token;
Algorithm::Schedule(
GenericClearArrayKernel<BoolPortal>(
tracker.PrepareForOutput(numElems, DeviceAdapterTag(), token), dims, false),
numElems);
Algorithm::Schedule(
GenericClearArrayKernel<BoolPortal>(
valid.PrepareForOutput(numElems, DeviceAdapterTag(), token), dims, false),
numElems);
}
2021-04-10 15:44:12 +00:00
std::cout << "Running Overlap kernel." << std::endl;
{
vtkm::cont::Token token;
Algorithm::Schedule(OverlapKernel(tracker.PrepareForInPlace(DeviceAdapterTag(), token),
valid.PrepareForInPlace(DeviceAdapterTag(), token),
dims),
dims);
}
auto vPortal = valid.ReadPortal();
for (vtkm::Id i = 0; i < numElems; i++)
{
bool isValid = vPortal.Get(i);
VTKM_TEST_ASSERT(isValid, "Id3 Schedule executed some elements more than once.");
}
} // release memory
}
static VTKM_CONT void TestCopyIf()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing CopyIf" << std::endl;
IdArrayHandle array;
IdArrayHandle stencil;
IdArrayHandle result;
//construct the index array
{
vtkm::cont::Token token;
Algorithm::Schedule(
OffsetPlusIndexKernel(array.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
Algorithm::Schedule(
MarkOddNumbersKernel(stencil.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
}
2017-05-18 14:29:41 +00:00
Algorithm::CopyIf(array, stencil, result);
VTKM_TEST_ASSERT(result.GetNumberOfValues() == array.GetNumberOfValues() / 2,
"result of CopyIf has an incorrect size");
auto portal = result.ReadPortal();
for (vtkm::Id index = 0; index < result.GetNumberOfValues(); index++)
{
const vtkm::Id value = portal.Get(index);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == (OFFSET + (index * 2) + 1), "Incorrect value in CopyIf result.");
}
2021-04-10 15:44:12 +00:00
std::cout << " CopyIf on fancy arrays." << std::endl;
result.Allocate(0);
FloatCastHandle arrayCast(array);
FloatCastHandle resultCast(result);
Algorithm::CopyIf(arrayCast, stencil, resultCast);
VTKM_TEST_ASSERT(result.GetNumberOfValues() == array.GetNumberOfValues() / 2,
"result of CopyIf has an incorrect size");
portal = result.ReadPortal();
for (vtkm::Id index = 0; index < result.GetNumberOfValues(); index++)
{
const vtkm::Id value = portal.Get(index);
VTKM_TEST_ASSERT(value == (OFFSET + (index * 2) + 1), "Incorrect value in CopyIf result.");
}
2021-04-10 15:44:12 +00:00
std::cout << " CopyIf on zero size arrays." << std::endl;
array.ReleaseResources();
stencil.ReleaseResources();
Algorithm::CopyIf(array, stencil, result);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(result.GetNumberOfValues() == 0, "result of CopyIf has an incorrect size");
}
static VTKM_CONT void TestOrderedUniqueValues()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Testing Sort, Unique, LowerBounds and UpperBounds" << std::endl;
std::vector<vtkm::Id> testData(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
2017-05-18 14:29:41 +00:00
testData[i] = static_cast<vtkm::Id>(OFFSET + (i % 50));
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle input = vtkm::cont::make_ArrayHandle(testData, vtkm::CopyFlag::Off);
//make a deep copy of input and place it into temp
IdArrayHandle temp;
2017-05-18 14:29:41 +00:00
Algorithm::Copy(input, temp);
Algorithm::Sort(temp);
Algorithm::Unique(temp);
IdArrayHandle handle;
IdArrayHandle handle1;
//verify lower and upper bounds work
2017-05-18 14:29:41 +00:00
Algorithm::LowerBounds(temp, input, handle);
Algorithm::UpperBounds(temp, input, handle1);
// Check to make sure that temp was resized correctly during Unique.
// (This was a discovered bug at one point.)
temp.ReadPortal(); // Forces copy back to control.
temp.ReleaseResourcesExecution(); // Make sure not counting on execution.
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(temp.GetNumberOfValues() == 50,
"Unique did not resize array (or size did not copy to control).");
auto portal = handle.ReadPortal();
auto portal1 = handle1.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Id value = portal.Get(i);
vtkm::Id value1 = portal1.Get(i);
VTKM_TEST_ASSERT(value == i % 50, "Got bad value (LowerBounds)");
VTKM_TEST_ASSERT(value1 >= i % 50, "Got bad value (UpperBounds)");
}
2021-04-10 15:44:12 +00:00
std::cout << "Testing Sort/Unique/LowerBounds/UpperBounds with random values and fancy array"
<< std::endl;
//now test it works when the id are not incrementing
const vtkm::Id RANDOMDATA_SIZE = 6;
vtkm::Id randomData[RANDOMDATA_SIZE];
2017-05-18 14:29:41 +00:00
randomData[0] = 500; // 2 (lower), 3 (upper)
randomData[1] = 955; // 3 (lower), 4 (upper)
randomData[2] = 955; // 3 (lower), 4 (upper)
randomData[3] = 120; // 0 (lower), 1 (upper)
randomData[4] = 320; // 1 (lower), 2 (upper)
randomData[5] = 955; // 3 (lower), 4 (upper)
//change the control structure under the handle
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
input = vtkm::cont::make_ArrayHandle(randomData, RANDOMDATA_SIZE, vtkm::CopyFlag::Off);
FloatCastHandle tempCast(temp);
Algorithm::Copy(input, tempCast);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(temp.GetNumberOfValues() == RANDOMDATA_SIZE, "Copy failed");
Algorithm::Sort(tempCast);
Algorithm::Unique(tempCast);
Algorithm::LowerBounds(tempCast, FloatCastHandle(input), handle);
Algorithm::UpperBounds(tempCast, FloatCastHandle(input), handle1);
VTKM_TEST_ASSERT(handle.GetNumberOfValues() == RANDOMDATA_SIZE,
"LowerBounds returned incorrect size");
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(handle.ReadPortal()),
vtkm::cont::ArrayPortalToIteratorEnd(handle.ReadPortal()),
randomData);
VTKM_TEST_ASSERT(randomData[0] == 2, "Got bad value - LowerBounds");
VTKM_TEST_ASSERT(randomData[1] == 3, "Got bad value - LowerBounds");
VTKM_TEST_ASSERT(randomData[2] == 3, "Got bad value - LowerBounds");
VTKM_TEST_ASSERT(randomData[3] == 0, "Got bad value - LowerBounds");
VTKM_TEST_ASSERT(randomData[4] == 1, "Got bad value - LowerBounds");
VTKM_TEST_ASSERT(randomData[5] == 3, "Got bad value - LowerBounds");
VTKM_TEST_ASSERT(handle1.GetNumberOfValues() == RANDOMDATA_SIZE,
"UppererBounds returned incorrect size");
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(handle1.ReadPortal()),
vtkm::cont::ArrayPortalToIteratorEnd(handle1.ReadPortal()),
randomData);
VTKM_TEST_ASSERT(randomData[0] == 3, "Got bad value - UpperBound");
VTKM_TEST_ASSERT(randomData[1] == 4, "Got bad value - UpperBound");
VTKM_TEST_ASSERT(randomData[2] == 4, "Got bad value - UpperBound");
VTKM_TEST_ASSERT(randomData[3] == 1, "Got bad value - UpperBound");
VTKM_TEST_ASSERT(randomData[4] == 2, "Got bad value - UpperBound");
VTKM_TEST_ASSERT(randomData[5] == 4, "Got bad value - UpperBound");
}
static VTKM_CONT void TestSort()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Sort" << std::endl;
std::vector<vtkm::Id> testData(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
2017-05-18 14:29:41 +00:00
testData[i] = static_cast<vtkm::Id>(OFFSET + ((ARRAY_SIZE - i) % 50));
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle unsorted = vtkm::cont::make_ArrayHandle(testData, vtkm::CopyFlag::Off);
IdArrayHandle sorted;
Algorithm::Copy(unsorted, sorted);
//Validate the standard inplace sort is correct
Algorithm::Sort(sorted);
auto portal = sorted.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE - 1; ++i)
{
vtkm::Id sorted1 = portal.Get(i);
vtkm::Id sorted2 = portal.Get(i + 1);
VTKM_TEST_ASSERT(sorted1 <= sorted2, "Values not properly sorted.");
}
//Try zero sized array
sorted.Allocate(0);
Algorithm::Sort(sorted);
}
static VTKM_CONT void TestSortWithComparisonObject()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Sort with comparison object" << std::endl;
std::vector<vtkm::Id> testData(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
2017-05-18 14:29:41 +00:00
testData[i] = static_cast<vtkm::Id>(OFFSET + ((ARRAY_SIZE - i) % 50));
}
//sort the users memory in-place
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle sorted = vtkm::cont::make_ArrayHandle(testData, vtkm::CopyFlag::Off);
Algorithm::Sort(sorted);
//copy the sorted array into our own memory, if use the same user ptr
//we would also sort the 'sorted' handle
IdArrayHandle comp_sorted;
Algorithm::Copy(sorted, comp_sorted);
2017-05-18 14:29:41 +00:00
Algorithm::Sort(comp_sorted, vtkm::SortGreater());
//Validate that sorted and comp_sorted are sorted in the opposite directions
auto sorted_portal = sorted.ReadPortal();
auto comp_sorted_portal = comp_sorted.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Id sorted1 = sorted_portal.Get(i);
vtkm::Id sorted2 = comp_sorted_portal.Get(ARRAY_SIZE - (i + 1));
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(sorted1 == sorted2, "Got bad sort values when using SortGreater");
}
//validate that sorted and comp_sorted are now equal
2017-05-18 14:29:41 +00:00
Algorithm::Sort(comp_sorted, vtkm::SortLess());
comp_sorted_portal = comp_sorted.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Id sorted1 = sorted_portal.Get(i);
vtkm::Id sorted2 = comp_sorted_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(sorted1 == sorted2, "Got bad sort values when using SortLess");
}
}
static VTKM_CONT void TestSortWithFancyArrays()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Sort of a ArrayHandleZip" << std::endl;
std::vector<vtkm::Id> testData(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
2017-05-18 14:29:41 +00:00
testData[i] = static_cast<vtkm::Id>(OFFSET + ((ARRAY_SIZE - i) % 50));
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle unsorted = vtkm::cont::make_ArrayHandle(testData, vtkm::CopyFlag::Off);
IdArrayHandle sorted;
Algorithm::Copy(unsorted, sorted);
//verify that we can use ArrayHandleZip inplace
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandleZip<IdArrayHandle, IdArrayHandle> zipped(unsorted, sorted);
//verify we can use sort with zip handle
Algorithm::Sort(zipped, vtkm::SortGreater());
Algorithm::Sort(zipped);
auto portal = zipped.ReadPortal();
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Pair<vtkm::Id, vtkm::Id> kv_sorted = portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT((OFFSET + (i / (ARRAY_SIZE / 50))) == kv_sorted.first,
"ArrayZipHandle improperly sorted");
}
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Sort of a ArrayHandlePermutation" << std::endl;
//verify that we can use ArrayHandlePermutation inplace
vtkm::cont::ArrayHandleIndex index(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandlePermutation<vtkm::cont::ArrayHandleIndex, IdArrayHandle> perm(index,
sorted);
//verify we can use a custom operator sort with permutation handle
Algorithm::Sort(perm, vtkm::SortGreater());
auto perm_portal = perm.ReadPortal();
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Id sorted_value = perm_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT((OFFSET + ((ARRAY_SIZE - (i + 1)) / (ARRAY_SIZE / 50))) == sorted_value,
"ArrayZipPermutation improperly sorted");
}
//verify we can use the default sort with permutation handle
Algorithm::Sort(perm);
perm_portal = perm.ReadPortal();
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Id sorted_value = perm_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT((OFFSET + (i / (ARRAY_SIZE / 50))) == sorted_value,
"ArrayZipPermutation improperly sorted");
}
}
static VTKM_CONT void TestSortByKey()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Sort by keys" << std::endl;
using Vec3 = vtkm::Vec<FloatDefault, 3>;
using Vec3ArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec3f, StorageTag>;
std::vector<vtkm::Id> testKeys(ARRAY_SIZE);
std::vector<Vec3> testValues(testKeys.size());
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
std::size_t index = static_cast<size_t>(i);
testKeys[index] = ARRAY_SIZE - i;
testValues[index] = TestValue(i, Vec3());
2017-05-18 14:29:41 +00:00
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle keys = vtkm::cont::make_ArrayHandle(testKeys, vtkm::CopyFlag::Off);
Vec3ArrayHandle values = vtkm::cont::make_ArrayHandle(testValues, vtkm::CopyFlag::Off);
2017-05-18 14:29:41 +00:00
Algorithm::SortByKey(keys, values);
auto values_portal = values.ReadPortal();
auto keys_portal = keys.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
//keys should be sorted from 1 to ARRAY_SIZE
//values should be sorted from (ARRAY_SIZE-1) to 0
Vec3 sorted_value = values_portal.Get(i);
vtkm::Id sorted_key = keys_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT((sorted_key == (i + 1)), "Got bad SortByKeys key");
VTKM_TEST_ASSERT(test_equal(sorted_value, TestValue(ARRAY_SIZE - 1 - i, Vec3())),
"Got bad SortByKeys value");
}
// this will return everything back to what it was before sorting
2017-05-18 14:29:41 +00:00
Algorithm::SortByKey(keys, values, vtkm::SortGreater());
values_portal = values.ReadPortal();
keys_portal = keys.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
//keys should be sorted from ARRAY_SIZE to 1
//values should be sorted from 0 to (ARRAY_SIZE-1)
Vec3 sorted_value = values_portal.Get(i);
vtkm::Id sorted_key = keys_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT((sorted_key == (ARRAY_SIZE - i)), "Got bad SortByKeys key");
VTKM_TEST_ASSERT(test_equal(sorted_value, TestValue(i, Vec3())), "Got bad SortByKeys value");
}
//this is here to verify we can sort by vtkm::Vec
2017-05-18 14:29:41 +00:00
Algorithm::SortByKey(values, keys);
values_portal = values.ReadPortal();
keys_portal = keys.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
//keys should be sorted from ARRAY_SIZE to 1
//values should be sorted from 0 to (ARRAY_SIZE-1)
Vec3 sorted_value = values_portal.Get(i);
vtkm::Id sorted_key = keys_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT((sorted_key == (ARRAY_SIZE - i)), "Got bad SortByKeys key");
VTKM_TEST_ASSERT(test_equal(sorted_value, TestValue(i, Vec3())), "Got bad SortByKeys value");
}
}
static VTKM_CONT void TestLowerBoundsWithComparisonObject()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Testing LowerBounds with comparison object" << std::endl;
std::vector<vtkm::Id> testData(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
2017-05-18 14:29:41 +00:00
testData[i] = static_cast<vtkm::Id>(OFFSET + (i % 50));
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle input = vtkm::cont::make_ArrayHandle(testData, vtkm::CopyFlag::Off);
//make a deep copy of input and place it into temp
IdArrayHandle temp;
2017-05-18 14:29:41 +00:00
Algorithm::Copy(input, temp);
Algorithm::Sort(temp);
Algorithm::Unique(temp);
IdArrayHandle handle;
//verify lower bounds work
2017-05-18 14:29:41 +00:00
Algorithm::LowerBounds(temp, input, handle, vtkm::SortLess());
// Check to make sure that temp was resized correctly during Unique.
// (This was a discovered bug at one point.)
temp.ReadPortal(); // Forces copy back to control.
temp.ReleaseResourcesExecution(); // Make sure not counting on execution.
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(temp.GetNumberOfValues() == 50,
"Unique did not resize array (or size did not copy to control).");
auto portal = handle.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Id value = portal.Get(i);
VTKM_TEST_ASSERT(value == i % 50, "Got bad LowerBounds value with SortLess");
}
}
static VTKM_CONT void TestUpperBoundsWithComparisonObject()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Testing UpperBounds with comparison object" << std::endl;
std::vector<vtkm::Id> testData(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
2017-05-18 14:29:41 +00:00
testData[i] = static_cast<vtkm::Id>(OFFSET + (i % 50));
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle input = vtkm::cont::make_ArrayHandle(testData, vtkm::CopyFlag::Off);
//make a deep copy of input and place it into temp
IdArrayHandle temp;
2017-05-18 14:29:41 +00:00
Algorithm::Copy(input, temp);
Algorithm::Sort(temp);
Algorithm::Unique(temp);
IdArrayHandle handle;
//verify upper bounds work
2017-05-18 14:29:41 +00:00
Algorithm::UpperBounds(temp, input, handle, vtkm::SortLess());
// Check to make sure that temp was resized correctly during Unique.
// (This was a discovered bug at one point.)
temp.ReadPortal(); // Forces copy back to control.
temp.ReleaseResourcesExecution(); // Make sure not counting on execution.
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(temp.GetNumberOfValues() == 50,
"Unique did not resize array (or size did not copy to control).");
auto portal = handle.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Id value = portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == (i % 50) + 1, "Got bad UpperBounds value with SortLess");
}
}
static VTKM_CONT void TestUniqueWithComparisonObject()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Testing Unique with comparison object" << std::endl;
IdArrayHandle input;
input.Allocate(ARRAY_SIZE);
{
auto portal = input.WritePortal();
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
{
portal.Set(index, OFFSET + (index % 50));
}
}
Algorithm::Sort(input);
Algorithm::Unique(input, FuseAll());
// Check to make sure that input was resized correctly during Unique.
// (This was a discovered bug at one point.)
input.SyncControlArray(); // Forces copy back to control.
input.ReleaseResourcesExecution(); // Make sure not counting on execution.
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(input.GetNumberOfValues() == 1,
"Unique did not resize array (or size did not copy to control).");
vtkm::Id value = input.ReadPortal().Get(0);
VTKM_TEST_ASSERT(value == OFFSET, "Got bad unique value");
}
static VTKM_CONT void TestReduce()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Reduce" << std::endl;
//construct the index array
IdArrayHandle array;
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(array.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
}
//the output of reduce and scan inclusive should be the same
2021-04-10 15:44:12 +00:00
std::cout << " Reduce with initial value of 0." << std::endl;
vtkm::Id reduce_sum = Algorithm::Reduce(array, 0);
2021-04-10 15:44:12 +00:00
std::cout << " Reduce with initial value." << std::endl;
2017-05-18 14:29:41 +00:00
vtkm::Id reduce_sum_with_intial_value = Algorithm::Reduce(array, vtkm::Id(ARRAY_SIZE));
2021-04-10 15:44:12 +00:00
std::cout << " Inclusive scan to check" << std::endl;
vtkm::Id inclusive_sum = Algorithm::ScanInclusive(array, array);
2021-04-10 15:44:12 +00:00
std::cout << " Reduce with 1 value." << std::endl;
array.Allocate(1, vtkm::CopyFlag::On);
vtkm::Id reduce_sum_one_value = Algorithm::Reduce(array, 0);
2021-04-10 15:44:12 +00:00
std::cout << " Reduce with 0 values." << std::endl;
array.Allocate(0);
vtkm::Id reduce_sum_no_values = Algorithm::Reduce(array, 0);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(reduce_sum == OFFSET * ARRAY_SIZE, "Got bad sum from Reduce");
VTKM_TEST_ASSERT(reduce_sum_with_intial_value == reduce_sum + ARRAY_SIZE,
"Got bad sum from Reduce with initial value");
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(reduce_sum_one_value == OFFSET, "Got bad single sum from Reduce");
VTKM_TEST_ASSERT(reduce_sum_no_values == 0, "Got bad empty sum from Reduce");
VTKM_TEST_ASSERT(reduce_sum == inclusive_sum,
"Got different sums from Reduce and ScanInclusive");
}
static VTKM_CONT void TestReduceWithComparisonObject()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Reduce with comparison object " << std::endl;
std::cout << " Reduce vtkm::Id array with vtkm::MinAndMax to compute range." << std::endl;
//construct the index array. Assign an abnormally large value
//to the middle of the array, that should be what we see as our sum.
std::vector<vtkm::Id> testData(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
const vtkm::Id maxValue = ARRAY_SIZE * 2;
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
vtkm::Id index = static_cast<vtkm::Id>(i);
2017-05-18 14:29:41 +00:00
testData[i] = index;
}
2017-05-18 14:29:41 +00:00
testData[ARRAY_SIZE / 2] = maxValue;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle input = vtkm::cont::make_ArrayHandle(testData, vtkm::CopyFlag::Off);
vtkm::Id2 range = Algorithm::Reduce(input, vtkm::Id2(0, 0), vtkm::MinAndMax<vtkm::Id>());
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(maxValue == range[1], "Got bad value from Reduce with comparison object");
VTKM_TEST_ASSERT(0 == range[0], "Got bad value from Reduce with comparison object");
2021-04-10 15:44:12 +00:00
std::cout << " Reduce vtkm::Id array with custom functor that returns vtkm::Pair<>."
<< std::endl;
auto pairInit = vtkm::Pair<vtkm::Id, vtkm::Float32>(0, 0.0f);
vtkm::Pair<vtkm::Id, vtkm::Float32> pairRange =
Algorithm::Reduce(input, pairInit, CustomPairOp());
VTKM_TEST_ASSERT(maxValue == pairRange.first,
"Got bad value from Reduce with pair comparison object");
VTKM_TEST_ASSERT(0.0f == pairRange.second,
"Got bad value from Reduce with pair comparison object");
2021-04-10 15:44:12 +00:00
std::cout << " Reduce bool array with vtkm::LogicalAnd to see if all values are true."
<< std::endl;
//construct an array of bools and verify that they aren't all true
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
auto barray =
vtkm::cont::make_ArrayHandle({ true, true, true, true, true, true, false, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true });
bool all_true = Algorithm::Reduce(barray, true, vtkm::LogicalAnd());
VTKM_TEST_ASSERT(all_true == false, "reduction with vtkm::LogicalAnd should return false");
2021-04-10 15:44:12 +00:00
std::cout << " Reduce with custom value type and custom comparison operator." << std::endl;
//test with a custom value type with the reduction value being a vtkm::Vec<float,2>
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
auto farray = vtkm::cont::make_ArrayHandle<CustomTForReduce>(
{ 13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f, 413.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f,
13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f,
13.1f, -2.1f, -11.0f, 13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f,
13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f, 13.1f, -211.1f, -1.0f,
13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f, 13.1f, -2.1f, -1.0f, 113.1f, -2.1f, -1.0f });
vtkm::Vec2f_32 frange =
Algorithm::Reduce(farray, vtkm::Vec2f_32(0.0f, 0.0f), CustomMinAndMax<CustomTForReduce>());
VTKM_TEST_ASSERT(-211.1f == frange[0],
"Got bad float value from Reduce with comparison object");
VTKM_TEST_ASSERT(413.1f == frange[1], "Got bad float value from Reduce with comparison object");
}
static VTKM_CONT void TestReduceWithFancyArrays()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Reduce with ArrayHandleZip" << std::endl;
{
2017-05-18 14:29:41 +00:00
IdArrayHandle keys, values;
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(keys.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
Algorithm::Schedule(
ClearArrayKernel(values.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
}
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandleZip<IdArrayHandle, IdArrayHandle> zipped(keys, values);
2017-05-18 14:29:41 +00:00
//the output of reduce and scan inclusive should be the same
using ResultType = vtkm::Pair<vtkm::Id, vtkm::Id>;
2017-05-18 14:29:41 +00:00
ResultType reduce_sum_with_intial_value =
Algorithm::Reduce(vtkm::cont::make_ArrayHandleView(zipped, 0, ARRAY_SIZE),
ResultType(ARRAY_SIZE, ARRAY_SIZE));
2017-05-18 14:29:41 +00:00
ResultType expectedResult(OFFSET * ARRAY_SIZE + ARRAY_SIZE, OFFSET * ARRAY_SIZE + ARRAY_SIZE);
VTKM_TEST_ASSERT((reduce_sum_with_intial_value == expectedResult),
"Got bad sum from Reduce with initial value");
}
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Reduce with ArrayHandlePermutation" << std::endl;
{
2017-05-18 14:29:41 +00:00
//lastly test with heterogeneous zip values ( vec3, and constant array handle),
//and a custom reduce binary functor
using ValueType = vtkm::Float32;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle indexHandle =
vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4,
5, 5, 5, 1, 4, 9, 7, 7, 7, 8, 8, 8, 0, 1, 2 });
vtkm::cont::ArrayHandle<ValueType> valueHandle = vtkm::cont::make_ArrayHandle(
{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, -2.0f });
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
const ValueType expectedSum = 125;
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandlePermutation<IdArrayHandle, vtkm::cont::ArrayHandle<ValueType>> perm;
perm = vtkm::cont::make_ArrayHandlePermutation(indexHandle, valueHandle);
2017-05-18 14:29:41 +00:00
const ValueType sum = Algorithm::Reduce(perm, ValueType(0.0f));
2021-04-10 15:44:12 +00:00
std::cout << "sum: " << sum << std::endl;
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT((sum == expectedSum), "Got bad sum from Reduce with permutation handle");
}
}
static VTKM_CONT void TestReduceByKey()
2015-05-04 19:53:35 +00:00
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Reduce By Key" << std::endl;
2015-05-04 19:53:35 +00:00
//first test with very basic integer key / values
{
2017-05-18 14:29:41 +00:00
const vtkm::Id expectedLength = 6;
vtkm::IdComponent expectedKeys[expectedLength] = { 0, 1, 4, 0, 2, -1 };
2017-05-18 14:29:41 +00:00
vtkm::Id expectedValues[expectedLength] = { 10, 2, 0, 3, 10, -42 };
2015-05-04 19:53:35 +00:00
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdComponentArrayHandle keys =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 0, 0, 0, 1, 1, 4, 0, 2, 2, 2, 2, -1 });
IdArrayHandle values =
vtkm::cont::make_ArrayHandle<vtkm::Id>({ 13, -2, -1, 1, 1, 0, 3, 1, 2, 3, 4, -42 });
2015-05-04 19:53:35 +00:00
IdComponentArrayHandle keysOut;
IdArrayHandle valuesOut;
2017-05-18 14:29:41 +00:00
Algorithm::ReduceByKey(keys, values, keysOut, valuesOut, vtkm::Add());
2015-05-04 19:53:35 +00:00
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(keysOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output keys");
2015-05-04 19:53:35 +00:00
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
2015-05-04 19:53:35 +00:00
auto keys_portal = keysOut.ReadPortal();
auto values_portal = valuesOut.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < expectedLength; ++i)
2015-05-04 19:53:35 +00:00
{
const vtkm::Id k = keys_portal.Get(i);
const vtkm::Id v = values_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(expectedKeys[i] == k, "Incorrect reduced key");
VTKM_TEST_ASSERT(expectedValues[i] == v, "Incorrect reduced value");
2015-05-04 19:53:35 +00:00
}
}
//next test with a single key across the entire set, using vec3 as the
//value, using a custom reduce binary functor
2015-06-01 16:19:17 +00:00
{
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle keys = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0, 0, 0 });
vtkm::cont::ArrayHandle<vtkm::Vec3f_64, StorageTag> values =
vtkm::cont::make_ArrayHandle({ vtkm::Vec3f_64(13.1, 13.3, 13.5),
vtkm::Vec3f_64(-2.1, -2.3, -2.5),
vtkm::Vec3f_64(-1.0, -1.0, 1.0) });
2017-05-18 14:29:41 +00:00
const vtkm::Id expectedLength = 1;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
2017-05-18 14:29:41 +00:00
vtkm::Id expectedKeys[expectedLength] = { 0 };
vtkm::Vec3f_64 expectedValues[expectedLength];
2017-05-18 14:29:41 +00:00
expectedValues[0] = vtkm::make_Vec(27.51, 30.59, -33.75);
2015-06-01 16:19:17 +00:00
2017-05-18 14:29:41 +00:00
IdArrayHandle keysOut;
vtkm::cont::ArrayHandle<vtkm::Vec3f_64, StorageTag> valuesOut;
2017-05-18 14:29:41 +00:00
Algorithm::ReduceByKey(keys, values, keysOut, valuesOut, vtkm::Multiply());
2015-06-01 16:19:17 +00:00
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(keysOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output keys");
2015-06-01 16:19:17 +00:00
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
2015-06-01 16:19:17 +00:00
auto keys_portal = keysOut.ReadPortal();
auto values_portal = valuesOut.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < expectedLength; ++i)
2015-06-01 16:19:17 +00:00
{
const vtkm::Id k = keys_portal.Get(i);
const vtkm::Vec3f_64 v = values_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(expectedKeys[i] == k, "Incorrect reduced key");
VTKM_TEST_ASSERT(expectedValues[i] == v, "Incorrect reduced vale");
}
2015-06-01 16:19:17 +00:00
}
2017-05-18 14:29:41 +00:00
}
2017-05-18 14:29:41 +00:00
static VTKM_CONT void TestReduceByKeyWithFancyArrays()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Reduce By Key with Fancy Arrays" << std::endl;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdComponentArrayHandle keys =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 0, 0, 0, 1, 1, 4, 0, 2, 2, 2, 2, -1 });
IdArrayHandle values =
vtkm::cont::make_ArrayHandle<vtkm::Id>({ 13, -2, -1, 1, 1, 0, 3, 1, 2, 3, 4, -42 });
FloatCastHandle castValues(values);
const vtkm::Id expectedLength = 6;
vtkm::IdComponent expectedKeys[expectedLength] = { 0, 1, 4, 0, 2, -1 };
vtkm::Id expectedValues[expectedLength] = { 10, 2, 0, 3, 10, -42 };
2015-06-10 20:37:52 +00:00
IdComponentArrayHandle keysOut;
IdArrayHandle valuesOut;
FloatCastHandle castValuesOut(valuesOut);
Algorithm::ReduceByKey(keys, castValues, keysOut, castValuesOut, vtkm::Add());
2015-06-10 20:37:52 +00:00
VTKM_TEST_ASSERT(keysOut.GetNumberOfValues() == expectedLength,
2017-05-18 14:29:41 +00:00
"Got wrong number of output keys");
2015-06-10 20:37:52 +00:00
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == expectedLength,
2017-05-18 14:29:41 +00:00
"Got wrong number of output values");
auto keys_portal = keysOut.ReadPortal();
auto values_portal = valuesOut.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < expectedLength; ++i)
2015-06-10 20:37:52 +00:00
{
const vtkm::Id k = keys_portal.Get(i);
const vtkm::Id v = values_portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(expectedKeys[i] == k, "Incorrect reduced key");
VTKM_TEST_ASSERT(expectedValues[i] == v, "Incorrect reduced value");
}
2015-05-04 19:53:35 +00:00
}
static VTKM_CONT void TestScanInclusiveByKeyOne()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Inclusive By Key with 1 elements" << std::endl;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle keys = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 5 });
IdArrayHandle valuesOut;
Algorithm::ScanInclusiveByKey(keys, values, valuesOut, vtkm::Add());
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == 1, "Got wrong number of output values");
const vtkm::Id v = valuesOut.ReadPortal().Get(0);
VTKM_TEST_ASSERT(5 == v, "Incorrect scanned value");
}
static VTKM_CONT void TestScanInclusiveByKeyTwo()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Exclusive By Key with 2 elements" << std::endl;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle keys = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0, 1 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 1, 1 });
const vtkm::Id expectedLength = 2;
2017-05-18 14:29:41 +00:00
vtkm::Id expectedValues[expectedLength] = { 1, 1 };
IdArrayHandle valuesOut;
Algorithm::ScanInclusiveByKey(keys, values, valuesOut, vtkm::Add());
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
auto values_portal = valuesOut.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < expectedLength; i++)
{
const vtkm::Id v = values_portal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
static VTKM_CONT void TestScanInclusiveByKeyLarge()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Inclusive By Key with " << ARRAY_SIZE << " elements" << std::endl;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
std::vector<vtkm::Id> inputKeys(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; i++)
{
if (i % 100 < 98)
inputKeys[static_cast<std::size_t>(i)] = static_cast<vtkm::Id>(i / 100);
else
inputKeys[static_cast<std::size_t>(i)] = static_cast<vtkm::Id>(i);
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
std::vector<vtkm::Id> inputValues(ARRAY_SIZE, 1);
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
std::vector<vtkm::Id> expectedValues(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; i++)
{
if (i % 100 < 98)
expectedValues[i] = static_cast<vtkm::Id>(1 + i % 100);
else
expectedValues[i] = static_cast<vtkm::Id>(1);
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle keys = vtkm::cont::make_ArrayHandle(inputKeys, vtkm::CopyFlag::Off);
IdArrayHandle values = vtkm::cont::make_ArrayHandle(inputValues, vtkm::CopyFlag::Off);
IdArrayHandle valuesOut;
Algorithm::ScanInclusiveByKey(keys, values, valuesOut, vtkm::Add());
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == ARRAY_SIZE,
"Got wrong number of output values");
auto values_portal = valuesOut.ReadPortal();
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
for (auto i = 0; i < ARRAY_SIZE; i++)
2017-05-18 14:29:41 +00:00
{
const vtkm::Id v = values_portal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
static VTKM_CONT void TestScanInclusiveByKey()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Inclusive By Key" << std::endl;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdComponentArrayHandle keys =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 0, 0, 0, 1, 1, 2, 3, 3, 3, 3 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
const vtkm::Id expectedLength = 10;
2017-05-18 14:29:41 +00:00
vtkm::Id expectedValues[expectedLength] = { 1, 2, 3, 1, 2, 1, 1, 2, 3, 4 };
IdArrayHandle valuesOut;
Algorithm::ScanInclusiveByKey(keys, values, valuesOut);
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
auto valuesPortal = valuesOut.ReadPortal();
2017-05-18 14:29:41 +00:00
for (auto i = 0; i < expectedLength; i++)
{
const vtkm::Id v = valuesPortal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
static VTKM_CONT void TestScanInclusiveByKeyInPlace()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Inclusive By Key In Place" << std::endl;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdComponentArrayHandle keys =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 0, 0, 0, 1, 1, 2, 3, 3, 3, 3 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
const vtkm::Id expectedLength = 10;
vtkm::Id expectedValues[expectedLength] = { 1, 2, 3, 1, 2, 1, 1, 2, 3, 4 };
Algorithm::ScanInclusiveByKey(keys, values, values);
VTKM_TEST_ASSERT(values.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
auto valuesPortal = values.ReadPortal();
for (auto i = 0; i < expectedLength; i++)
{
const vtkm::Id v = valuesPortal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
static VTKM_CONT void TestScanInclusiveByKeyInPlaceWithFancyArray()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Inclusive By Key In Place with a Fancy Array" << std::endl;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdComponentArrayHandle keys =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 0, 0, 0, 1, 1, 2, 3, 3, 3, 3 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
FloatCastHandle castValues(values);
const vtkm::Id expectedLength = 10;
vtkm::Id expectedValues[expectedLength] = { 1, 2, 3, 1, 2, 1, 1, 2, 3, 4 };
Algorithm::ScanInclusiveByKey(keys, castValues, castValues);
VTKM_TEST_ASSERT(values.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
auto valuesPortal = values.ReadPortal();
for (auto i = 0; i < expectedLength; i++)
{
const vtkm::Id v = valuesPortal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
2017-04-13 17:50:56 +00:00
static VTKM_CONT void TestScanExclusiveByKeyOne()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Exclusive By Key with 1 elements" << std::endl;
vtkm::Id init = 5;
const vtkm::Id expectedLength = 1;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle keys = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0 });
IdArrayHandle valuesOut;
Algorithm::ScanExclusiveByKey(keys, values, valuesOut, init, vtkm::Add());
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
const vtkm::Id v = valuesOut.ReadPortal().Get(0);
VTKM_TEST_ASSERT(init == v, "Incorrect scanned value");
}
static VTKM_CONT void TestScanExclusiveByKeyTwo()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Exclusive By Key with 2 elements" << std::endl;
vtkm::Id init = 5;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle keys = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 0, 1 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 1, 1 });
const vtkm::Id expectedLength = 2;
2017-05-18 14:29:41 +00:00
vtkm::Id expectedValues[expectedLength] = { 5, 5 };
IdArrayHandle valuesOut;
Algorithm::ScanExclusiveByKey(keys, values, valuesOut, init, vtkm::Add());
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
auto valuesPortal = valuesOut.ReadPortal();
2017-05-18 14:29:41 +00:00
for (auto i = 0; i < expectedLength; i++)
{
const vtkm::Id v = valuesPortal.Get(i);
VTKM_TEST_ASSERT(expectedValues[i] == v, "Incorrect scanned value");
}
}
static VTKM_CONT void TestScanExclusiveByKeyLarge()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Exclusive By Key with " << ARRAY_SIZE << " elements" << std::endl;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
std::vector<vtkm::Id> inputKeys(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; i++)
{
if (i % 100 < 98)
inputKeys[i] = static_cast<vtkm::Id>(i / 100);
else
inputKeys[i] = static_cast<vtkm::Id>(i);
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
std::vector<vtkm::Id> inputValues(ARRAY_SIZE, 1);
vtkm::Id init = 5;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
std::vector<vtkm::Id> expectedValues(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; i++)
{
if (i % 100 < 98)
expectedValues[static_cast<std::size_t>(i)] = static_cast<vtkm::Id>(init + i % 100);
else
expectedValues[static_cast<std::size_t>(i)] = init;
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle keys = vtkm::cont::make_ArrayHandle(inputKeys, vtkm::CopyFlag::Off);
IdArrayHandle values = vtkm::cont::make_ArrayHandle(inputValues, vtkm::CopyFlag::Off);
IdArrayHandle valuesOut;
Algorithm::ScanExclusiveByKey(keys, values, valuesOut, init, vtkm::Add());
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == ARRAY_SIZE,
"Got wrong number of output values");
auto valuesPortal = valuesOut.ReadPortal();
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; i++)
2017-05-18 14:29:41 +00:00
{
const vtkm::Id v = valuesPortal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
static VTKM_CONT void TestScanExclusiveByKey()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Exclusive By Key" << std::endl;
vtkm::Id init = 5;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdComponentArrayHandle keys =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 0, 0, 0, 1, 1, 2, 3, 3, 3, 3 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
const vtkm::Id expectedLength = 10;
2017-05-18 14:29:41 +00:00
vtkm::Id expectedValues[expectedLength] = { 5, 6, 7, 5, 6, 5, 5, 6, 7, 8 };
IdArrayHandle valuesOut;
Algorithm::ScanExclusiveByKey(keys, values, valuesOut, init, vtkm::Add());
VTKM_TEST_ASSERT(valuesOut.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
auto valuesPortal = valuesOut.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < expectedLength; i++)
{
const vtkm::Id v = valuesPortal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
static VTKM_CONT void TestScanExclusiveByKeyInPlace()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Inclusive By Key In Place" << std::endl;
vtkm::Id init = 5;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdComponentArrayHandle keys =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 0, 0, 0, 1, 1, 2, 3, 3, 3, 3 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
const vtkm::Id expectedLength = 10;
vtkm::Id expectedValues[expectedLength] = { 5, 6, 7, 5, 6, 5, 5, 6, 7, 8 };
Algorithm::ScanExclusiveByKey(keys, values, values, init, vtkm::Add());
VTKM_TEST_ASSERT(values.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
auto valuesPortal = values.ReadPortal();
for (auto i = 0; i < expectedLength; i++)
{
const vtkm::Id v = valuesPortal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
static VTKM_CONT void TestScanExclusiveByKeyInPlaceWithFancyArray()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Scan Inclusive By Key In Place with a Fancy Array" << std::endl;
vtkm::FloatDefault init = 5;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdComponentArrayHandle keys =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 0, 0, 0, 1, 1, 2, 3, 3, 3, 3 });
IdArrayHandle values = vtkm::cont::make_ArrayHandle<vtkm::Id>({ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 });
FloatCastHandle castValues(values);
const vtkm::Id expectedLength = 10;
vtkm::Id expectedValues[expectedLength] = { 5, 6, 7, 5, 6, 5, 5, 6, 7, 8 };
Algorithm::ScanExclusiveByKey(keys, castValues, castValues, init, vtkm::Add());
VTKM_TEST_ASSERT(values.GetNumberOfValues() == expectedLength,
"Got wrong number of output values");
auto valuesPortal = values.ReadPortal();
for (auto i = 0; i < expectedLength; i++)
{
const vtkm::Id v = valuesPortal.Get(i);
VTKM_TEST_ASSERT(expectedValues[static_cast<std::size_t>(i)] == v, "Incorrect scanned value");
}
}
2017-04-13 17:50:56 +00:00
static VTKM_CONT void TestScanInclusive()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Inclusive Scan" << std::endl;
{
2021-04-10 15:44:12 +00:00
std::cout << " size " << ARRAY_SIZE << std::endl;
2017-05-18 14:29:41 +00:00
//construct the index array
IdArrayHandle array;
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(array.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
}
2017-05-18 14:29:41 +00:00
//we know have an array whose sum is equal to OFFSET * ARRAY_SIZE,
//let's validate that
vtkm::Id sum = Algorithm::ScanInclusive(array, array);
VTKM_TEST_ASSERT(sum == OFFSET * ARRAY_SIZE, "Got bad sum from Inclusive Scan");
auto portal = array.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
const vtkm::Id value = portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == (i + 1) * OFFSET, "Incorrect partial sum");
}
2021-04-10 15:44:12 +00:00
std::cout << " size 1" << std::endl;
array.Allocate(1, vtkm::CopyFlag::On);
2017-05-18 14:29:41 +00:00
sum = Algorithm::ScanInclusive(array, array);
VTKM_TEST_ASSERT(sum == OFFSET, "Incorrect partial sum");
const vtkm::Id value = array.ReadPortal().Get(0);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == OFFSET, "Incorrect partial sum");
2021-04-10 15:44:12 +00:00
std::cout << " size 0" << std::endl;
array.Allocate(0);
2017-05-18 14:29:41 +00:00
sum = Algorithm::ScanInclusive(array, array);
VTKM_TEST_ASSERT(sum == 0, "Incorrect partial sum");
}
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Inclusive Scan with multiplication operator" << std::endl;
{
2017-05-18 14:29:41 +00:00
std::vector<vtkm::Float64> inputValues(ARRAY_SIZE);
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
inputValues[i] = 1.01;
}
2017-05-18 14:29:41 +00:00
std::size_t mid = ARRAY_SIZE / 2;
inputValues[mid] = 0.0;
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<vtkm::Float64> array =
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
vtkm::cont::make_ArrayHandle(inputValues, vtkm::CopyFlag::Off);
2017-05-18 14:29:41 +00:00
vtkm::Float64 product = Algorithm::ScanInclusive(array, array, vtkm::Multiply());
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(product == 0.0f, "ScanInclusive product result not 0.0");
auto portal = array.ReadPortal();
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < mid; ++i)
{
vtkm::Id index = static_cast<vtkm::Id>(i);
vtkm::Float64 expected = pow(1.01, static_cast<vtkm::Float64>(i + 1));
vtkm::Float64 got = portal.Get(index);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(test_equal(got, expected), "Incorrect results for ScanInclusive");
}
for (std::size_t i = mid; i < ARRAY_SIZE; ++i)
{
vtkm::Id index = static_cast<vtkm::Id>(i);
VTKM_TEST_ASSERT(portal.Get(index) == 0.0f, "Incorrect results for ScanInclusive");
2017-05-18 14:29:41 +00:00
}
}
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Inclusive Scan with a vtkm::Vec" << std::endl;
{
using Vec3 = vtkm::Vec<Float64, 3>;
using Vec3ArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec3f_64, StorageTag>;
2017-05-18 14:29:41 +00:00
std::vector<Vec3> testValues(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
testValues[i] = TestValue(1, Vec3());
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
Vec3ArrayHandle values = vtkm::cont::make_ArrayHandle(testValues, vtkm::CopyFlag::Off);
2017-05-18 14:29:41 +00:00
Vec3 sum = Algorithm::ScanInclusive(values, values);
2021-04-10 15:44:12 +00:00
std::cout << "Sum that was returned " << sum << std::endl;
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(test_equal(sum, TestValue(1, Vec3()) * ARRAY_SIZE),
"Got bad sum from Inclusive Scan");
}
}
static VTKM_CONT void TestScanInclusiveWithComparisonObject()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Inclusive Scan with comparison object " << std::endl;
//construct the index array
IdArrayHandle array;
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(array.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
Algorithm::Schedule(
MakeAddArrayKernel(array.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
}
//we know have an array whose sum is equal to OFFSET * ARRAY_SIZE,
//let's validate that
IdArrayHandle result;
2017-05-18 14:29:41 +00:00
vtkm::Id sum = Algorithm::ScanInclusive(array, result, vtkm::Maximum());
VTKM_TEST_ASSERT(sum == OFFSET + (ARRAY_SIZE - 1),
"Got bad sum from Inclusive Scan with comparison object");
auto array_portal = array.ReadPortal();
auto result_portal = result.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
const vtkm::Id input_value = array_portal.Get(i);
const vtkm::Id result_value = result_portal.Get(i);
VTKM_TEST_ASSERT(input_value == result_value, "Incorrect partial sum");
}
//now try it inline
2017-05-18 14:29:41 +00:00
sum = Algorithm::ScanInclusive(array, array, vtkm::Maximum());
VTKM_TEST_ASSERT(sum == OFFSET + (ARRAY_SIZE - 1),
"Got bad sum from Inclusive Scan with comparison object");
array_portal = array.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
const vtkm::Id input_value = array_portal.Get(i);
const vtkm::Id result_value = result_portal.Get(i);
VTKM_TEST_ASSERT(input_value == result_value, "Incorrect partial sum");
}
}
static VTKM_CONT void TestScanExclusive()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Exclusive Scan" << std::endl;
{
2017-05-18 14:29:41 +00:00
//construct the index array
IdArrayHandle array;
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(array.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
}
2017-05-18 14:29:41 +00:00
// we know have an array whose sum = (OFFSET * ARRAY_SIZE),
// let's validate that
vtkm::Id sum = Algorithm::ScanExclusive(array, array);
VTKM_TEST_ASSERT(sum == (OFFSET * ARRAY_SIZE), "Got bad sum from Exclusive Scan");
auto portal = array.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
const vtkm::Id value = portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == i * OFFSET, "Incorrect partial sum");
}
2021-04-10 15:44:12 +00:00
std::cout << " size 1" << std::endl;
array.Allocate(1, vtkm::CopyFlag::On);
array.WritePortal().Set(0, OFFSET);
2017-05-18 14:29:41 +00:00
sum = Algorithm::ScanExclusive(array, array);
VTKM_TEST_ASSERT(sum == OFFSET, "Incorrect partial sum");
const vtkm::Id value = array.ReadPortal().Get(0);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == 0, "Incorrect partial sum");
array.Allocate(0);
2017-05-18 14:29:41 +00:00
sum = Algorithm::ScanExclusive(array, array);
VTKM_TEST_ASSERT(sum == 0, "Incorrect partial sum");
}
// Enable when Exclusive Scan with custom operator is implemented for all
// device adaptors
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Exclusive Scan with multiplication operator" << std::endl;
{
2017-05-18 14:29:41 +00:00
std::vector<vtkm::Float64> inputValues(ARRAY_SIZE);
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
inputValues[i] = 1.01;
}
2017-05-18 14:29:41 +00:00
std::size_t mid = ARRAY_SIZE / 2;
inputValues[mid] = 0.0;
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
vtkm::cont::ArrayHandle<vtkm::Float64> array =
vtkm::cont::make_ArrayHandle(inputValues, vtkm::CopyFlag::Off);
2017-05-18 14:29:41 +00:00
vtkm::Float64 initialValue = 2.00;
vtkm::Float64 product =
Algorithm::ScanExclusive(array, array, vtkm::Multiply(), initialValue);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(product == 0.0f, "ScanExclusive product result not 0.0");
VTKM_TEST_ASSERT(array.ReadPortal().Get(0) == initialValue,
2017-05-18 14:29:41 +00:00
"ScanExclusive result's first value != initialValue");
auto portal = array.ReadPortal();
2017-05-18 14:29:41 +00:00
for (std::size_t i = 1; i <= mid; ++i)
{
vtkm::Id index = static_cast<vtkm::Id>(i);
vtkm::Float64 expected = pow(1.01, static_cast<vtkm::Float64>(i)) * initialValue;
vtkm::Float64 got = portal.Get(index);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(test_equal(got, expected), "Incorrect results for ScanExclusive");
}
for (std::size_t i = mid + 1; i < ARRAY_SIZE; ++i)
{
vtkm::Id index = static_cast<vtkm::Id>(i);
VTKM_TEST_ASSERT(portal.Get(index) == 0.0f, "Incorrect results for ScanExclusive");
2017-05-18 14:29:41 +00:00
}
}
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Exclusive Scan with a vtkm::Vec" << std::endl;
{
using Vec3 = vtkm::Vec<Float64, 3>;
using Vec3ArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec3f_64, StorageTag>;
2017-05-18 14:29:41 +00:00
std::vector<Vec3> testValues(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
testValues[i] = TestValue(1, Vec3());
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
Vec3ArrayHandle values = vtkm::cont::make_ArrayHandle(testValues, vtkm::CopyFlag::Off);
2017-05-18 14:29:41 +00:00
Vec3 sum = Algorithm::ScanExclusive(values, values);
VTKM_TEST_ASSERT(test_equal(sum, (TestValue(1, Vec3()) * ARRAY_SIZE)),
"Got bad sum from Exclusive Scan");
}
}
static VTKM_CONT void TestScanExtended()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Extended Scan" << std::endl;
{
//construct the index array
IdArrayHandle array;
{
vtkm::cont::Token token;
Algorithm::Schedule(
ClearArrayKernel(array.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag(), token)),
ARRAY_SIZE);
}
// we now have an array whose sum = (OFFSET * ARRAY_SIZE),
// let's validate that
Algorithm::ScanExtended(array, array);
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE + 1, "Output size incorrect.");
{
auto portal = array.ReadPortal();
for (vtkm::Id i = 0; i < ARRAY_SIZE + 1; ++i)
{
const vtkm::Id value = portal.Get(i);
VTKM_TEST_ASSERT(value == i * OFFSET, "Incorrect partial sum");
}
}
array.Allocate(1, vtkm::CopyFlag::On);
array.WritePortal().Set(0, OFFSET);
Algorithm::ScanExtended(array, array);
VTKM_TEST_ASSERT(array.GetNumberOfValues() == 2);
{
auto portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.Get(0) == 0, "Incorrect initial value");
VTKM_TEST_ASSERT(portal.Get(1) == OFFSET, "Incorrect total sum");
}
2021-04-10 15:44:12 +00:00
std::cout << " size 0" << std::endl;
array.Allocate(0);
Algorithm::ScanExtended(array, array);
VTKM_TEST_ASSERT(array.GetNumberOfValues() == 1);
{
auto portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.Get(0) == 0, "Incorrect initial value");
}
}
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Extended Scan with multiplication operator" << std::endl;
{
std::vector<vtkm::Float64> inputValues(ARRAY_SIZE);
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
inputValues[i] = 1.01;
}
std::size_t mid = ARRAY_SIZE / 2;
inputValues[mid] = 0.0;
vtkm::cont::ArrayHandle<vtkm::Float64> array =
vtkm::cont::make_ArrayHandle(inputValues, vtkm::CopyFlag::On);
vtkm::Float64 initialValue = 2.00;
Algorithm::ScanExtended(array, array, vtkm::Multiply(), initialValue);
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE + 1,
"ScanExtended output size incorrect.");
auto portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.Get(0) == initialValue,
"ScanExtended result's first value != initialValue");
for (std::size_t i = 1; i <= mid; ++i)
{
vtkm::Id index = static_cast<vtkm::Id>(i);
vtkm::Float64 expected = pow(1.01, static_cast<vtkm::Float64>(i)) * initialValue;
vtkm::Float64 got = portal.Get(index);
VTKM_TEST_ASSERT(test_equal(got, expected), "Incorrect results for ScanExtended");
}
for (std::size_t i = mid + 1; i < ARRAY_SIZE + 1; ++i)
{
vtkm::Id index = static_cast<vtkm::Id>(i);
VTKM_TEST_ASSERT(portal.Get(index) == 0.0f, "Incorrect results for ScanExtended");
}
}
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Extended Scan with a vtkm::Vec" << std::endl;
{
using Vec3 = vtkm::Vec3f_64;
using Vec3ArrayHandle = vtkm::cont::ArrayHandle<Vec3, StorageTag>;
std::vector<Vec3> testValues(ARRAY_SIZE);
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
testValues[i] = TestValue(1, Vec3());
}
Vec3ArrayHandle values = vtkm::cont::make_ArrayHandle(testValues, vtkm::CopyFlag::On);
Algorithm::ScanExtended(values, values);
VTKM_TEST_ASSERT(test_equal(vtkm::cont::ArrayGetValue(ARRAY_SIZE, values),
(TestValue(1, Vec3()) * ARRAY_SIZE)),
"Got bad sum from ScanExtended");
}
}
static VTKM_CONT void TestErrorExecution()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing Exceptions in Execution Environment" << std::endl;
std::cout << "Generating one error." << std::endl;
std::string message;
try
{
Algorithm::Schedule(OneErrorKernel(), ARRAY_SIZE);
Algorithm::Synchronize();
}
2017-05-18 14:29:41 +00:00
catch (vtkm::cont::ErrorExecution& error)
{
2021-04-10 15:44:12 +00:00
std::cout << "Got expected error: " << error.GetMessage() << std::endl;
message = error.GetMessage();
}
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(message == ERROR_MESSAGE, "Did not get expected error message.");
2021-04-10 15:44:12 +00:00
std::cout << "Generating lots of errors." << std::endl;
message = "";
try
{
Algorithm::Schedule(AllErrorKernel(), ARRAY_SIZE);
Algorithm::Synchronize();
}
2017-05-18 14:29:41 +00:00
catch (vtkm::cont::ErrorExecution& error)
{
2021-04-10 15:44:12 +00:00
std::cout << "Got expected error: " << error.GetMessage() << std::endl;
message = error.GetMessage();
}
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(message == ERROR_MESSAGE, "Did not get expected error message.");
2021-04-10 15:44:12 +00:00
// This is spcifically to test the cuda-backend but should pass for all backends
std::cout << "Testing if execution errors are eventually propagated to the host "
<< "without explicit synchronization\n";
message = "";
int nkernels = 0;
try
{
vtkm::cont::Token token;
IdArrayHandle idArray;
auto portal = idArray.PrepareForOutput(ARRAY_SIZE, DeviceAdapterTag{}, token);
Algorithm::Schedule(OneErrorKernel(), ARRAY_SIZE);
for (; nkernels < 100; ++nkernels)
{
Algorithm::Schedule(MakeAddArrayKernel(portal), ARRAY_SIZE);
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
Algorithm::Synchronize();
}
catch (vtkm::cont::ErrorExecution& error)
{
2021-04-10 15:44:12 +00:00
std::cout << "Got expected error: \"" << error.GetMessage() << "\" ";
if (nkernels < 100)
{
std::cout << "after " << nkernels << " invocations of other kernel" << std::endl;
}
else
{
std::cout << "only after explicit synchronization" << std::endl;
}
message = error.GetMessage();
}
2021-04-10 15:44:12 +00:00
std::cout << "\n";
VTKM_TEST_ASSERT(message == ERROR_MESSAGE, "Did not get expected error message.");
}
2017-05-18 14:29:41 +00:00
template <typename T, int N = 0>
struct TestCopy
{
};
2016-05-12 09:59:54 +00:00
template <typename T>
2017-05-18 14:29:41 +00:00
struct TestCopy<T>
{
static T get(vtkm::Id i) { return static_cast<T>(i); }
2016-05-12 09:59:54 +00:00
};
template <typename T, int N>
2017-05-18 14:29:41 +00:00
struct TestCopy<vtkm::Vec<T, N>>
{
static vtkm::Vec<T, N> get(vtkm::Id i)
{
vtkm::Vec<T, N> temp;
for (int j = 0; j < N; ++j)
{
temp[j] = static_cast<T>(OFFSET + (i % 50));
2016-05-12 09:59:54 +00:00
}
2017-05-18 14:29:41 +00:00
return temp;
}
2016-05-12 09:59:54 +00:00
};
template <typename T, typename U>
struct TestCopy<vtkm::Pair<T, U>>
{
static vtkm::Pair<T, U> get(vtkm::Id i)
{
return vtkm::make_Pair(TestCopy<T>::get(i), TestCopy<U>::get(i));
}
};
2016-05-12 09:59:54 +00:00
template <typename T>
static VTKM_CONT void TestCopyArrays()
2016-05-12 09:59:54 +00:00
{
#define COPY_ARRAY_SIZE 10000
std::vector<T> testData(COPY_ARRAY_SIZE);
std::default_random_engine generator(static_cast<unsigned int>(std::time(nullptr)));
vtkm::Id index = 0;
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < COPY_ARRAY_SIZE; ++i, ++index)
2016-05-12 09:59:54 +00:00
{
2017-05-18 14:29:41 +00:00
testData[i] = TestCopy<T>::get(index);
2016-05-12 09:59:54 +00:00
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
vtkm::cont::ArrayHandle<T> input = vtkm::cont::make_ArrayHandle(testData, vtkm::CopyFlag::Off);
2016-05-12 09:59:54 +00:00
//make a deep copy of input and place it into temp
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> temp;
temp.Allocate(COPY_ARRAY_SIZE * 2);
Algorithm::Copy(input, temp);
VTKM_TEST_ASSERT(temp.GetNumberOfValues() == COPY_ARRAY_SIZE, "Copy Needs to Resize Array");
2016-05-12 09:59:54 +00:00
const auto& portal = temp.ReadPortal();
std::uniform_int_distribution<vtkm::Id> distribution(0, COPY_ARRAY_SIZE - 1);
vtkm::Id numberOfSamples = COPY_ARRAY_SIZE / 50;
for (vtkm::Id i = 0; i < numberOfSamples; ++i)
2017-05-18 14:29:41 +00:00
{
vtkm::Id randomIndex = distribution(generator);
T value = portal.Get(randomIndex);
VTKM_TEST_ASSERT(value == testData[static_cast<size_t>(randomIndex)],
"Got bad value (Copy)");
2017-05-18 14:29:41 +00:00
}
}
//Verify copy of empty array works
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> tempIn;
vtkm::cont::ArrayHandle<T> tempOut;
2017-05-18 14:29:41 +00:00
tempOut.Allocate(COPY_ARRAY_SIZE);
Algorithm::Copy(tempIn, tempOut);
VTKM_TEST_ASSERT(tempIn.GetNumberOfValues() == tempOut.GetNumberOfValues(),
"Copy sized wrong");
2017-05-18 14:29:41 +00:00
// Actually allocate input array to 0 in case that makes a difference.
tempIn.Allocate(0);
tempOut.Allocate(COPY_ARRAY_SIZE);
Algorithm::Copy(tempIn, tempOut);
VTKM_TEST_ASSERT(tempIn.GetNumberOfValues() == tempOut.GetNumberOfValues(),
"Copy sized wrong");
}
//CopySubRange tests:
//1. Verify invalid input start position fails
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> output;
bool result = Algorithm::CopySubRange(input, COPY_ARRAY_SIZE * 4, 1, output);
VTKM_TEST_ASSERT(result == false, "CopySubRange when given bad input offset");
}
//2. Verify unallocated output gets allocated
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> output;
bool result = Algorithm::CopySubRange(input, 0, COPY_ARRAY_SIZE, output);
VTKM_TEST_ASSERT(result == true, "CopySubRange should succeed");
VTKM_TEST_ASSERT(output.GetNumberOfValues() == COPY_ARRAY_SIZE,
"CopySubRange needs to allocate output");
}
//3. Verify under allocated output gets resized properly
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> output;
output.Allocate(2);
bool result = Algorithm::CopySubRange(input, 0, COPY_ARRAY_SIZE, output);
VTKM_TEST_ASSERT(result == true, "CopySubRange should succeed");
VTKM_TEST_ASSERT(output.GetNumberOfValues() == COPY_ARRAY_SIZE,
"CopySubRange needs to re-allocate output");
}
//4. Verify invalid input length gets shortened
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> output;
bool result = Algorithm::CopySubRange(input, 100, COPY_ARRAY_SIZE, output);
VTKM_TEST_ASSERT(result == true, "CopySubRange needs to shorten input range");
VTKM_TEST_ASSERT(output.GetNumberOfValues() == (COPY_ARRAY_SIZE - 100),
"CopySubRange needs to shorten input range");
std::uniform_int_distribution<vtkm::Id> distribution(0, COPY_ARRAY_SIZE - 100 - 1);
vtkm::Id numberOfSamples = (COPY_ARRAY_SIZE - 100) / 100;
auto outputPortal = output.ReadPortal();
for (vtkm::Id i = 0; i < numberOfSamples; ++i)
2017-05-18 14:29:41 +00:00
{
vtkm::Id randomIndex = distribution(generator);
T value = outputPortal.Get(randomIndex);
VTKM_TEST_ASSERT(value == testData[static_cast<size_t>(randomIndex) + 100],
"Got bad value (CopySubRange 2)");
2017-05-18 14:29:41 +00:00
}
}
//5. Verify sub range copy works when copying into a larger output
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> output;
output.Allocate(COPY_ARRAY_SIZE * 2);
Algorithm::CopySubRange(input, 0, COPY_ARRAY_SIZE, output);
Algorithm::CopySubRange(input, 0, COPY_ARRAY_SIZE, output, COPY_ARRAY_SIZE);
VTKM_TEST_ASSERT(output.GetNumberOfValues() == (COPY_ARRAY_SIZE * 2),
"CopySubRange needs to not resize array");
std::uniform_int_distribution<vtkm::Id> distribution(0, COPY_ARRAY_SIZE - 1);
vtkm::Id numberOfSamples = COPY_ARRAY_SIZE / 50;
auto portal = output.ReadPortal();
for (vtkm::Id i = 0; i < numberOfSamples; ++i)
2017-05-18 14:29:41 +00:00
{
vtkm::Id randomIndex = distribution(generator);
T value = portal.Get(randomIndex);
VTKM_TEST_ASSERT(value == testData[static_cast<size_t>(randomIndex)],
"Got bad value (CopySubRange 5)");
value = portal.Get(COPY_ARRAY_SIZE + randomIndex);
VTKM_TEST_ASSERT(value == testData[static_cast<size_t>(randomIndex)],
"Got bad value (CopySubRange 5)");
2017-05-18 14:29:41 +00:00
}
}
//6. Verify that whey sub range needs to reallocate the output it
// properly copies the original data instead of clearing it
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> output;
output.Allocate(COPY_ARRAY_SIZE);
Algorithm::CopySubRange(input, 0, COPY_ARRAY_SIZE, output);
Algorithm::CopySubRange(input, 0, COPY_ARRAY_SIZE, output, COPY_ARRAY_SIZE);
VTKM_TEST_ASSERT(output.GetNumberOfValues() == (COPY_ARRAY_SIZE * 2),
"CopySubRange needs too resize Array");
std::uniform_int_distribution<vtkm::Id> distribution(0, COPY_ARRAY_SIZE - 1);
vtkm::Id numberOfSamples = COPY_ARRAY_SIZE / 50;
auto portal = output.ReadPortal();
for (vtkm::Id i = 0; i < numberOfSamples; ++i)
2017-05-18 14:29:41 +00:00
{
vtkm::Id randomIndex = distribution(generator);
T value = portal.Get(randomIndex);
VTKM_TEST_ASSERT(value == testData[static_cast<size_t>(randomIndex)],
"Got bad value (CopySubRange 6)");
value = portal.Get(COPY_ARRAY_SIZE + randomIndex);
VTKM_TEST_ASSERT(value == testData[static_cast<size_t>(randomIndex)],
"Got bad value (CopySubRange 6)");
2017-05-18 14:29:41 +00:00
}
}
// 7. Test that overlapping ranges trigger a failure:
// 7.1 output starts inside input range:
{
const vtkm::Id inBegin = 100;
const vtkm::Id inEnd = 200;
const vtkm::Id outBegin = 150;
const vtkm::Id numVals = inEnd - inBegin;
bool result = Algorithm::CopySubRange(input, inBegin, numVals, input, outBegin);
VTKM_TEST_ASSERT(result == false, "Overlapping subrange did not fail.");
}
// 7.2 input starts inside output range
{
const vtkm::Id inBegin = 100;
const vtkm::Id inEnd = 200;
const vtkm::Id outBegin = 50;
const vtkm::Id numVals = inEnd - inBegin;
bool result = Algorithm::CopySubRange(input, inBegin, numVals, input, outBegin);
VTKM_TEST_ASSERT(result == false, "Overlapping subrange did not fail.");
}
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<T> output;
2017-05-18 14:29:41 +00:00
//7. Verify negative input index returns false
bool result = Algorithm::CopySubRange(input, -1, COPY_ARRAY_SIZE, output);
VTKM_TEST_ASSERT(result == false, "CopySubRange negative index should fail");
2017-05-18 14:29:41 +00:00
//8. Verify negative input numberOfElementsToCopy returns false
result = Algorithm::CopySubRange(input, 0, -COPY_ARRAY_SIZE, output);
VTKM_TEST_ASSERT(result == false, "CopySubRange negative number elements should fail");
2017-05-18 14:29:41 +00:00
//9. Verify negative output index return false
result = Algorithm::CopySubRange(input, 0, COPY_ARRAY_SIZE, output, -2);
VTKM_TEST_ASSERT(result == false, "CopySubRange negative output index should fail");
}
#undef COPY_ARRAY_SIZE
2016-05-12 09:59:54 +00:00
}
static VTKM_CONT void TestCopyArraysMany()
2016-05-12 09:59:54 +00:00
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Testing Copy to same array type" << std::endl;
TestCopyArrays<vtkm::Vec3f_32>();
TestCopyArrays<vtkm::Vec4ui_8>();
2017-05-18 14:29:41 +00:00
//
TestCopyArrays<vtkm::Pair<vtkm::Id, vtkm::Float32>>();
TestCopyArrays<vtkm::Pair<vtkm::Id, vtkm::Vec3f_32>>();
2017-05-18 14:29:41 +00:00
//
TestCopyArrays<vtkm::Float32>();
TestCopyArrays<vtkm::Float64>();
//
TestCopyArrays<vtkm::Int32>();
TestCopyArrays<vtkm::Int64>();
//
TestCopyArrays<vtkm::UInt8>();
TestCopyArrays<vtkm::UInt16>();
TestCopyArrays<vtkm::UInt32>();
TestCopyArrays<vtkm::UInt64>();
2016-05-12 09:59:54 +00:00
}
static VTKM_CONT void TestCopyArraysInDiffTypes()
{
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------------" << std::endl;
std::cout << "Testing Copy to a different array type" << std::endl;
std::vector<vtkm::Id> testData(ARRAY_SIZE);
2017-05-18 14:29:41 +00:00
for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
{
2017-05-18 14:29:41 +00:00
testData[i] = static_cast<vtkm::Id>(OFFSET + (i % 50));
}
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
IdArrayHandle input = vtkm::cont::make_ArrayHandle<vtkm::Id>(testData, vtkm::CopyFlag::Off);
//make a deep copy of input and place it into temp
vtkm::cont::ArrayHandle<vtkm::Float64> temp;
2017-05-18 14:29:41 +00:00
Algorithm::Copy(input, temp);
std::vector<vtkm::Id>::const_iterator c = testData.begin();
auto portal = temp.ReadPortal();
2017-05-18 14:29:41 +00:00
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i, ++c)
{
vtkm::Float64 value = portal.Get(i);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(value == static_cast<vtkm::Float64>(*c), "Got bad value (Copy)");
}
}
static VTKM_CONT void TestAtomicArray()
2016-02-10 15:51:31 +00:00
{
//we can't use ARRAY_SIZE as that would cause a overflow
vtkm::Int32 SHORT_ARRAY_SIZE = 10000;
vtkm::Int32 atomicCount = 0;
2017-05-18 14:29:41 +00:00
for (vtkm::Int32 i = 0; i < SHORT_ARRAY_SIZE; i++)
{
2017-05-18 14:29:41 +00:00
atomicCount += i;
}
2021-04-10 15:44:12 +00:00
std::cout << "-------------------------------------------" << std::endl;
// To test the atomics, SHORT_ARRAY_SIZE number of threads will all increment
2016-02-10 15:51:31 +00:00
// a single atomic value.
2021-04-10 15:44:12 +00:00
std::cout << "Testing Atomic Add with vtkm::Int32" << std::endl;
2016-02-10 15:51:31 +00:00
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<vtkm::Int32> atomicElement =
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
vtkm::cont::make_ArrayHandle<vtkm::Int32>({ 0 });
2016-02-10 15:51:31 +00:00
vtkm::cont::AtomicArray<vtkm::Int32> atomic(atomicElement);
{
vtkm::cont::Token token;
Algorithm::Schedule(AtomicKernel<vtkm::Int32>(atomic, token), SHORT_ARRAY_SIZE);
}
2017-05-18 14:29:41 +00:00
vtkm::Int32 expected = vtkm::Int32(atomicCount);
vtkm::Int32 actual = atomicElement.WritePortal().Get(0);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(expected == actual, "Did not get expected value: Atomic add Int32");
2016-02-10 15:51:31 +00:00
}
2021-04-10 15:44:12 +00:00
std::cout << "Testing Atomic Add with vtkm::Int64" << std::endl;
2016-02-10 15:51:31 +00:00
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<vtkm::Int64> atomicElement =
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
vtkm::cont::make_ArrayHandle<vtkm::Int64>({ 0 });
2016-02-10 15:51:31 +00:00
vtkm::cont::AtomicArray<vtkm::Int64> atomic(atomicElement);
{
vtkm::cont::Token token;
Algorithm::Schedule(AtomicKernel<vtkm::Int64>(atomic, token), SHORT_ARRAY_SIZE);
}
2017-05-18 14:29:41 +00:00
vtkm::Int64 expected = vtkm::Int64(atomicCount);
vtkm::Int64 actual = atomicElement.WritePortal().Get(0);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(expected == actual, "Did not get expected value: Atomic add Int64");
2016-02-10 15:51:31 +00:00
}
2021-04-10 15:44:12 +00:00
std::cout << "Testing Atomic CAS with vtkm::Int32" << std::endl;
2016-02-10 15:51:31 +00:00
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<vtkm::Int32> atomicElement =
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
vtkm::cont::make_ArrayHandle<vtkm::Int32>({ 0 });
2016-02-10 15:51:31 +00:00
vtkm::cont::AtomicArray<vtkm::Int32> atomic(atomicElement);
{
vtkm::cont::Token token;
Algorithm::Schedule(AtomicCASKernel<vtkm::Int32>(atomic, token), SHORT_ARRAY_SIZE);
}
2017-05-18 14:29:41 +00:00
vtkm::Int32 expected = vtkm::Int32(atomicCount);
vtkm::Int32 actual = atomicElement.WritePortal().Get(0);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(expected == actual, "Did not get expected value: Atomic CAS Int32");
2016-02-10 15:51:31 +00:00
}
2021-04-10 15:44:12 +00:00
std::cout << "Testing Atomic CAS with vtkm::Int64" << std::endl;
2016-02-10 15:51:31 +00:00
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandle<vtkm::Int64> atomicElement =
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
vtkm::cont::make_ArrayHandle<vtkm::Int64>({ 0 });
2016-02-10 15:51:31 +00:00
vtkm::cont::AtomicArray<vtkm::Int64> atomic(atomicElement);
{
vtkm::cont::Token token;
Algorithm::Schedule(AtomicCASKernel<vtkm::Int64>(atomic, token), SHORT_ARRAY_SIZE);
}
2017-05-18 14:29:41 +00:00
vtkm::Int64 expected = vtkm::Int64(atomicCount);
vtkm::Int64 actual = atomicElement.WritePortal().Get(0);
2017-05-18 14:29:41 +00:00
VTKM_TEST_ASSERT(expected == actual, "Did not get expected value: Atomic CAS Int64");
2016-02-10 15:51:31 +00:00
}
}
static VTKM_CONT void TestBitFieldToUnorderedSet()
{
using IndexArray = vtkm::cont::ArrayHandle<vtkm::Id>;
using WordType = WordTypeDefault;
// Test that everything works correctly with a partial word at the end.
static constexpr vtkm::Id BitsPerWord = static_cast<vtkm::Id>(sizeof(WordType) * CHAR_BIT);
// +5 to get a partial word:
static constexpr vtkm::Id NumBits = 1024 * BitsPerWord + 5;
static constexpr vtkm::Id NumWords = (NumBits + BitsPerWord - 1) / BitsPerWord;
auto testIndexArray = [](const BitField& bits) {
const vtkm::Id numBits = bits.GetNumberOfBits();
IndexArray indices;
Algorithm::BitFieldToUnorderedSet(bits, indices);
Algorithm::Sort(indices);
auto bitPortal = bits.ReadPortal();
auto indexPortal = indices.ReadPortal();
const vtkm::Id numIndices = indices.GetNumberOfValues();
vtkm::Id curIndex = 0;
for (vtkm::Id curBit = 0; curBit < numBits; ++curBit)
{
const bool markedSet = curIndex < numIndices ? indexPortal.Get(curIndex) == curBit : false;
const bool isSet = bitPortal.GetBit(curBit);
// std::cout << "curBit: " << curBit
// << " activeIndex: "
// << (curIndex < numIndices ? indexPortal.Get(curIndex) : -1)
// << " isSet: " << isSet << " markedSet: " << markedSet << "\n";
VTKM_TEST_ASSERT(
markedSet == isSet, "Bit ", curBit, " is set? ", isSet, " Marked set? ", markedSet);
if (markedSet)
{
curIndex++;
}
}
VTKM_TEST_ASSERT(curIndex == indices.GetNumberOfValues(), "Index array has extra values.");
};
auto testRepeatedMask = [&](WordType mask) {
2021-04-10 15:44:12 +00:00
std::cout << "Testing BitFieldToUnorderedSet with repeated 32-bit word 0x" << std::hex << mask
<< std::dec << std::endl;
BitField bits;
{
bits.Allocate(NumBits);
auto fillPortal = bits.WritePortal();
for (vtkm::Id i = 0; i < NumWords; ++i)
{
fillPortal.SetWord(i, mask);
}
}
testIndexArray(bits);
};
auto testRandomMask = [&](WordType seed) {
2021-04-10 15:44:12 +00:00
std::cout << "Testing BitFieldToUnorderedSet with random sequence seeded with 0x" << std::hex
<< seed << std::dec << std::endl;
std::mt19937 mt{ seed };
std::uniform_int_distribution<std::mt19937::result_type> rng;
BitField bits;
{
bits.Allocate(NumBits);
auto fillPortal = bits.WritePortal();
for (vtkm::Id i = 0; i < NumWords; ++i)
{
fillPortal.SetWord(i, static_cast<WordType>(rng(mt)));
}
}
testIndexArray(bits);
};
testRepeatedMask(0x00000000);
testRepeatedMask(0xeeeeeeee);
testRepeatedMask(0xffffffff);
testRepeatedMask(0x1c0fd395);
testRepeatedMask(0xdeadbeef);
testRandomMask(0x00000000);
testRandomMask(0xeeeeeeee);
testRandomMask(0xffffffff);
testRandomMask(0x1c0fd395);
testRandomMask(0xdeadbeef);
// This case was causing issues on CUDA:
{
BitField bits;
Algorithm::Fill(bits, false, 32 * 32);
auto portal = bits.WritePortal();
portal.SetWord(2, 0x00100000ul);
portal.SetWord(8, 0x00100010ul);
portal.SetWord(11, 0x10000000ul);
testIndexArray(bits);
}
}
static VTKM_CONT void TestCountSetBits()
{
using WordType = WordTypeDefault;
// Test that everything works correctly with a partial word at the end.
static constexpr vtkm::Id BitsPerWord = static_cast<vtkm::Id>(sizeof(WordType) * CHAR_BIT);
// +5 to get a partial word:
static constexpr vtkm::Id NumFullWords = 1024;
static constexpr vtkm::Id NumBits = NumFullWords * BitsPerWord + 5;
static constexpr vtkm::Id NumWords = (NumBits + BitsPerWord - 1) / BitsPerWord;
auto verifyPopCount = [](const BitField& bits) {
vtkm::Id refPopCount = 0;
const vtkm::Id numBits = bits.GetNumberOfBits();
auto portal = bits.ReadPortal();
for (vtkm::Id idx = 0; idx < numBits; ++idx)
{
if (portal.GetBit(idx))
{
++refPopCount;
}
}
const vtkm::Id popCount = Algorithm::CountSetBits(bits);
VTKM_TEST_ASSERT(
refPopCount == popCount, "CountSetBits returned ", popCount, ", expected ", refPopCount);
};
auto testRepeatedMask = [&](WordType mask) {
2021-04-10 15:44:12 +00:00
std::cout << "Testing CountSetBits with repeated word 0x" << std::hex << mask << std::dec
<< std::endl;
BitField bits;
{
bits.Allocate(NumBits);
auto fillPortal = bits.WritePortal();
for (vtkm::Id i = 0; i < NumWords; ++i)
{
fillPortal.SetWord(i, mask);
}
}
verifyPopCount(bits);
};
auto testRandomMask = [&](WordType seed) {
2021-04-10 15:44:12 +00:00
std::cout << "Testing CountSetBits with random sequence seeded with 0x" << std::hex << seed
<< std::dec << std::endl;
std::mt19937 mt{ seed };
std::uniform_int_distribution<std::mt19937::result_type> rng;
BitField bits;
{
bits.Allocate(NumBits);
auto fillPortal = bits.WritePortal();
for (vtkm::Id i = 0; i < NumWords; ++i)
{
fillPortal.SetWord(i, static_cast<WordType>(rng(mt)));
}
}
verifyPopCount(bits);
};
testRepeatedMask(0x00000000);
testRepeatedMask(0xeeeeeeee);
testRepeatedMask(0xffffffff);
testRepeatedMask(0x1c0fd395);
testRepeatedMask(0xdeadbeef);
testRandomMask(0x00000000);
testRandomMask(0xeeeeeeee);
testRandomMask(0xffffffff);
testRandomMask(0x1c0fd395);
testRandomMask(0xdeadbeef);
// This case was causing issues on CUDA:
{
BitField bits;
Algorithm::Fill(bits, false, 32 * 32);
auto portal = bits.WritePortal();
portal.SetWord(2, 0x00100000ul);
portal.SetWord(8, 0x00100010ul);
portal.SetWord(11, 0x10000000ul);
verifyPopCount(bits);
}
}
template <typename WordType>
static VTKM_CONT void TestFillBitFieldMask(WordType mask)
{
2021-04-10 15:44:12 +00:00
std::cout << "Testing Fill with " << (sizeof(WordType) * CHAR_BIT) << " bit mask: " << std::hex
<< vtkm::UInt64{ mask } << std::dec << std::endl;
// Test that everything works correctly with a partial word at the end.
static constexpr vtkm::Id BitsPerWord = static_cast<vtkm::Id>(sizeof(WordType) * CHAR_BIT);
// +5 to get a partial word:
static constexpr vtkm::Id NumFullWords = 1024;
static constexpr vtkm::Id NumBits = NumFullWords * BitsPerWord + 5;
static constexpr vtkm::Id NumWords = (NumBits + BitsPerWord - 1) / BitsPerWord;
vtkm::cont::BitField bits;
{
Algorithm::Fill(bits, mask, NumBits);
vtkm::Id numBits = bits.GetNumberOfBits();
VTKM_TEST_ASSERT(numBits == NumBits, "Unexpected number of bits.");
vtkm::Id numWords = bits.GetNumberOfWords<WordType>();
VTKM_TEST_ASSERT(numWords == NumWords, "Unexpected number of words.");
auto portal = bits.ReadPortal();
for (vtkm::Id wordIdx = 0; wordIdx < NumWords; ++wordIdx)
{
VTKM_TEST_ASSERT(portal.GetWord<WordType>(wordIdx) == mask,
"Incorrect word in result BitField; expected 0x",
std::hex,
vtkm::UInt64{ mask },
", got 0x",
vtkm::UInt64{ portal.GetWord<WordType>(wordIdx) },
std::dec,
" for word ",
wordIdx,
"/",
NumWords);
}
}
// Now fill the BitField with the reversed mask to test the no-alloc
// overload:
{
WordType invWord = static_cast<WordType>(~mask);
Algorithm::Fill(bits, invWord);
vtkm::Id numBits = bits.GetNumberOfBits();
VTKM_TEST_ASSERT(numBits == NumBits, "Unexpected number of bits.");
vtkm::Id numWords = bits.GetNumberOfWords<WordType>();
VTKM_TEST_ASSERT(numWords == NumWords, "Unexpected number of words.");
auto portal = bits.ReadPortal();
for (vtkm::Id wordIdx = 0; wordIdx < NumWords; ++wordIdx)
{
VTKM_TEST_ASSERT(portal.GetWord<WordType>(wordIdx) == invWord,
"Incorrect word in result BitField; expected 0x",
std::hex,
vtkm::UInt64{ invWord },
", got 0x",
vtkm::UInt64{ portal.GetWord<WordType>(wordIdx) },
std::dec,
" for word ",
wordIdx,
"/",
NumWords);
}
}
}
static VTKM_CONT void TestFillBitFieldBool(bool value)
{
2021-04-10 15:44:12 +00:00
std::cout << "Testing Fill with bool: " << value << std::endl;
// Test that everything works correctly with a partial word at the end.
// +5 to get a partial word:
static constexpr vtkm::Id NumBits = 1024 * 32 + 5;
vtkm::cont::BitField bits;
{
Algorithm::Fill(bits, value, NumBits);
vtkm::Id numBits = bits.GetNumberOfBits();
VTKM_TEST_ASSERT(numBits == NumBits, "Unexpected number of bits.");
auto portal = bits.ReadPortal();
for (vtkm::Id bitIdx = 0; bitIdx < NumBits; ++bitIdx)
{
VTKM_TEST_ASSERT(portal.GetBit(bitIdx) == value, "Incorrect bit in result BitField.");
}
}
// Now fill the BitField with the reversed mask to test the no-alloc
// overload:
{
Algorithm::Fill(bits, !value);
vtkm::Id numBits = bits.GetNumberOfBits();
VTKM_TEST_ASSERT(numBits == NumBits, "Unexpected number of bits.");
auto portal = bits.ReadPortal();
for (vtkm::Id bitIdx = 0; bitIdx < NumBits; ++bitIdx)
{
VTKM_TEST_ASSERT(portal.GetBit(bitIdx) == !value, "Incorrect bit in result BitField.");
}
}
}
static VTKM_CONT void TestFillBitField()
{
TestFillBitFieldBool(true);
TestFillBitFieldBool(false);
TestFillBitFieldMask<vtkm::UInt8>(vtkm::UInt8{ 0 });
TestFillBitFieldMask<vtkm::UInt8>(static_cast<vtkm::UInt8>(~vtkm::UInt8{ 0 }));
TestFillBitFieldMask<vtkm::UInt8>(vtkm::UInt8{ 0xab });
TestFillBitFieldMask<vtkm::UInt8>(vtkm::UInt8{ 0x4f });
TestFillBitFieldMask<vtkm::UInt16>(vtkm::UInt16{ 0 });
TestFillBitFieldMask<vtkm::UInt16>(static_cast<vtkm::UInt16>(~vtkm::UInt16{ 0 }));
TestFillBitFieldMask<vtkm::UInt16>(vtkm::UInt16{ 0xfade });
TestFillBitFieldMask<vtkm::UInt16>(vtkm::UInt16{ 0xbeef });
TestFillBitFieldMask<vtkm::UInt32>(vtkm::UInt32{ 0 });
TestFillBitFieldMask<vtkm::UInt32>(static_cast<vtkm::UInt32>(~vtkm::UInt32{ 0 }));
TestFillBitFieldMask<vtkm::UInt32>(vtkm::UInt32{ 0xfacecafe });
TestFillBitFieldMask<vtkm::UInt32>(vtkm::UInt32{ 0xbaddecaf });
TestFillBitFieldMask<vtkm::UInt64>(vtkm::UInt64{ 0 });
TestFillBitFieldMask<vtkm::UInt64>(static_cast<vtkm::UInt64>(~vtkm::UInt64{ 0 }));
TestFillBitFieldMask<vtkm::UInt64>(vtkm::UInt64{ 0xbaddefacedfacade });
TestFillBitFieldMask<vtkm::UInt64>(vtkm::UInt64{ 0xfeeddeadbeef2dad });
}
static VTKM_CONT void TestFillArrayHandle()
{
vtkm::cont::ArrayHandle<vtkm::Int32> handle;
Algorithm::Fill(handle, 867, ARRAY_SIZE);
{
auto portal = handle.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == ARRAY_SIZE);
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
VTKM_TEST_ASSERT(portal.Get(i) == 867);
}
}
Algorithm::Fill(handle, 5309);
{
auto portal = handle.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == ARRAY_SIZE);
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
VTKM_TEST_ASSERT(portal.Get(i) == 5309);
}
}
}
struct TestAll
{
VTKM_CONT void operator()() const
{
2021-04-10 15:44:12 +00:00
std::cout << "Doing DeviceAdapter tests" << std::endl;
TestMemoryTransfer();
TestOutOfMemory();
TestTimer();
2017-03-29 14:48:43 +00:00
TestVirtualObjectTransfer();
TestAlgorithmSchedule();
TestErrorExecution();
TestReduce();
TestReduceWithComparisonObject();
TestReduceWithFancyArrays();
2015-05-04 19:53:35 +00:00
TestReduceByKey();
TestReduceByKeyWithFancyArrays();
2015-05-04 19:53:35 +00:00
TestScanExclusive();
TestScanExtended();
TestScanInclusive();
TestScanInclusiveWithComparisonObject();
TestScanInclusiveByKeyOne();
TestScanInclusiveByKeyTwo();
TestScanInclusiveByKeyLarge();
TestScanInclusiveByKey();
TestScanInclusiveByKeyInPlace();
TestScanInclusiveByKeyInPlaceWithFancyArray();
TestScanExclusiveByKeyOne();
TestScanExclusiveByKeyTwo();
TestScanExclusiveByKeyLarge();
TestScanExclusiveByKey();
TestScanExclusiveByKeyInPlace();
TestScanExclusiveByKeyInPlaceWithFancyArray();
2017-04-13 17:50:56 +00:00
TestSort();
TestSortWithComparisonObject();
TestSortWithFancyArrays();
TestSortByKey();
TestLowerBoundsWithComparisonObject();
TestUpperBoundsWithComparisonObject();
TestUniqueWithComparisonObject();
TestOrderedUniqueValues(); //tests Copy, LowerBounds, Sort, Unique
TestCopyIf();
2016-05-12 09:59:54 +00:00
TestCopyArraysMany();
TestCopyArraysInDiffTypes();
2016-02-10 15:51:31 +00:00
TestAtomicArray();
TestBitFieldToUnorderedSet();
TestCountSetBits();
TestFillBitField();
TestFillArrayHandle();
}
};
public:
/// Run a suite of tests to check to see if a DeviceAdapter properly supports
/// all members and classes required for driving vtkm algorithms. Returns an
/// error code that can be returned from the main function of a test.
///
static VTKM_CONT int Run(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestAll(), argc, argv);
}
};
#undef ERROR_MESSAGE
#undef ARRAY_SIZE
#undef OFFSET
#undef DIM
}
}
} // namespace vtkm::cont::testing
#endif //vtk_m_cont_testing_TestingDeviceAdapter_h