Add ArrayCopy specialization for Counting and Permutation array

This required adding another source file.
This commit is contained in:
Kenneth Moreland 2022-01-14 14:04:18 -07:00
parent f3c82bfea7
commit 392d781359
7 changed files with 201 additions and 31 deletions

51
vtkm/cont/ArrayCopy.cxx Normal file

@ -0,0 +1,51 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayCopyDevice.h>
namespace vtkm
{
namespace cont
{
namespace detail
{
void ArrayCopyConcreteSrc<vtkm::cont::StorageTagCounting>::CopyCountingFloat(
vtkm::FloatDefault start,
vtkm::FloatDefault step,
vtkm::Id size,
const vtkm::cont::UnknownArrayHandle& result) const
{
if (result.IsBaseComponentType<vtkm::FloatDefault>())
{
auto outArray = result.ExtractComponent<vtkm::FloatDefault>(0);
vtkm::cont::ArrayCopyDevice(vtkm::cont::make_ArrayHandleCounting(start, step, size), outArray);
}
else
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray;
outArray.Allocate(size);
CopyCountingFloat(start, step, size, outArray);
result.DeepCopyFrom(outArray);
}
}
vtkm::cont::ArrayHandle<Id> ArrayCopyConcreteSrc<vtkm::cont::StorageTagCounting>::CopyCountingId(
const vtkm::cont::ArrayHandleCounting<vtkm::Id>& source) const
{
vtkm::cont::ArrayHandle<Id> destination;
vtkm::cont::ArrayCopyDevice(source, destination);
return destination;
}
}
}
} // namespace vtkm::cont::detail

@ -12,11 +12,14 @@
#include <vtkm/cont/ArrayHandleConcatenate.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/ArrayHandleView.h>
#include <vtkm/cont/UnknownArrayHandle.h>
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/cont/internal/MapArrayPermutation.h>
#include <vtkm/StaticAssert.h>
@ -258,6 +261,48 @@ struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagIndex>
}
};
// Special case for ArrayHandleCounting to be efficient.
template <>
struct VTKM_CONT_EXPORT ArrayCopyConcreteSrc<vtkm::cont::StorageTagCounting>
{
template <typename T1, typename T2, typename S2>
void operator()(const vtkm::cont::ArrayHandle<T1, vtkm::cont::StorageTagCounting>& source,
vtkm::cont::ArrayHandle<T2, S2>& destination) const
{
vtkm::cont::ArrayHandleCounting<T1> countingSource = source;
T1 start = countingSource.GetStart();
T1 step = countingSource.GetStep();
vtkm::Id size = countingSource.GetNumberOfValues();
destination.Allocate(size);
vtkm::cont::UnknownArrayHandle unknownDest = destination;
using VTraits1 = vtkm::VecTraits<T1>;
using VTraits2 = vtkm::VecTraits<T2>;
for (vtkm::IdComponent comp = 0; comp < VTraits1::GetNumberOfComponents(start); ++comp)
{
this->CopyCountingFloat(
static_cast<vtkm::FloatDefault>(VTraits1::GetComponent(start, comp)),
static_cast<vtkm::FloatDefault>(VTraits1::GetComponent(step, comp)),
size,
unknownDest.ExtractComponent<typename VTraits2::BaseComponentType>(comp));
}
}
void operator()(const vtkm::cont::ArrayHandle<vtkm::Id, vtkm::cont::StorageTagCounting>& source,
vtkm::cont::ArrayHandle<vtkm::Id>& destination) const
{
destination = this->CopyCountingId(source);
}
private:
void CopyCountingFloat(vtkm::FloatDefault start,
vtkm::FloatDefault step,
vtkm::Id size,
const vtkm::cont::UnknownArrayHandle& result) const;
vtkm::cont::ArrayHandle<Id> CopyCountingId(
const vtkm::cont::ArrayHandleCounting<vtkm::Id>& source) const;
};
// Special case for ArrayHandleConcatenate to be efficient
template <typename ST1, typename ST2>
struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagConcatenate<ST1, ST2>>
@ -280,10 +325,10 @@ struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagConcatenate<ST1, ST2>>
};
// Special case for ArrayHandlePermutation to be efficient
template <typename S>
struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagPermutation<vtkm::cont::StorageTagBasic, S>>
template <typename SIndex, typename SValue>
struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagPermutation<SIndex, SValue>>
{
using SourceStorageTag = vtkm::cont::StorageTagPermutation<vtkm::cont::StorageTagBasic, S>;
using SourceStorageTag = vtkm::cont::StorageTagPermutation<SIndex, SValue>;
template <typename T1, typename T2, typename S2>
void operator()(const vtkm::cont::ArrayHandle<T1, SourceStorageTag>& source,
vtkm::cont::ArrayHandle<T2, S2>& destination) const

@ -138,6 +138,10 @@ public:
internal::ArrayPortalCounting<CountingValueType>(start, step, length)))
{
}
VTKM_CONT CountingValueType GetStart() const { return this->ReadPortal().GetStart(); }
VTKM_CONT CountingValueType GetStep() const { return this->ReadPortal().GetStep(); }
};
/// A convenience function for creating an ArrayHandleCounting. It takes the

@ -183,6 +183,7 @@ set(sources
# This list of sources has code that uses devices and so might need to be
# compiled with a device-specific compiler (like CUDA).
set(device_sources
ArrayCopy.cxx
ArrayGetValues.cxx
ArrayRangeCompute.cxx
CellLocatorBoundingIntervalHierarchy.cxx

@ -11,6 +11,8 @@
#include <vtkm/cont/internal/CastInvalidValue.h>
#include <vtkm/cont/internal/MapArrayPermutation.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/worklet/WorkletMapField.h>
@ -48,9 +50,9 @@ struct MapPermutationWorklet : vtkm::worklet::WorkletMapField
struct DoMapFieldPermutation
{
template <typename InputArrayType>
template <typename InputArrayType, typename PermutationArrayType>
void operator()(const InputArrayType& input,
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
const PermutationArrayType& permutation,
vtkm::cont::UnknownArrayHandle& output,
vtkm::Float64 invalidValue) const
{
@ -77,13 +79,19 @@ namespace internal
vtkm::cont::UnknownArrayHandle MapArrayPermutation(
const vtkm::cont::UnknownArrayHandle& inputArray,
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
const vtkm::cont::UnknownArrayHandle& permutation,
vtkm::Float64 invalidValue)
{
if (!permutation.IsBaseComponentType<vtkm::Id>())
{
throw vtkm::cont::ErrorBadType("Permutation array input to MapArrayPermutation must have "
"values of vtkm::Id. Reported type is " +
permutation.GetBaseComponentTypeName());
}
vtkm::cont::UnknownArrayHandle outputArray = inputArray.NewInstanceBasic();
outputArray.Allocate(permutation.GetNumberOfValues());
inputArray.CastAndCallWithExtractedArray(
DoMapFieldPermutation{}, permutation, outputArray, invalidValue);
DoMapFieldPermutation{}, permutation.ExtractComponent<vtkm::Id>(0), outputArray, invalidValue);
return outputArray;
}

@ -26,7 +26,7 @@ namespace internal
///
VTKM_CONT_EXPORT vtkm::cont::UnknownArrayHandle MapArrayPermutation(
const vtkm::cont::UnknownArrayHandle& inputArray,
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
const vtkm::cont::UnknownArrayHandle& permutation,
vtkm::Float64 invalidValue = vtkm::Nan64());
/// Used to map a permutation array.

@ -9,12 +9,14 @@
//============================================================================
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayCopyDevice.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/UncertainArrayHandle.h>
#include <vtkm/cont/UnknownArrayHandle.h>
#include <vtkm/TypeTraits.h>
#include <vtkm/VecTraits.h>
#include <vtkm/cont/testing/Testing.h>
@ -23,13 +25,43 @@ namespace
static constexpr vtkm::Id ARRAY_SIZE = 10;
template <typename RefArrayType, typename TestArrayType>
void TestValues(const RefArrayType& refArray, const TestArrayType& testArray)
vtkm::cont::UnknownArrayHandle MakeComparable(const vtkm::cont::UnknownArrayHandle& array,
std::false_type)
{
return array;
}
template <typename T>
vtkm::cont::UnknownArrayHandle MakeComparable(const vtkm::cont::ArrayHandle<T>& array,
std::true_type)
{
return array;
}
template <typename ArrayType>
vtkm::cont::UnknownArrayHandle MakeComparable(const ArrayType& array, std::true_type)
{
vtkm::cont::ArrayHandle<typename ArrayType::ValueType> simpleArray;
vtkm::cont::ArrayCopyDevice(array, simpleArray);
return simpleArray;
}
void TestValuesImpl(const vtkm::cont::UnknownArrayHandle& refArray,
const vtkm::cont::UnknownArrayHandle& testArray)
{
auto result = test_equal_ArrayHandles(refArray, testArray);
VTKM_TEST_ASSERT(result, result.GetMergedMessage());
}
template <typename RefArrayType, typename TestArrayType>
void TestValues(const RefArrayType& refArray, const TestArrayType& testArray)
{
TestValuesImpl(
MakeComparable(refArray, typename vtkm::cont::internal::ArrayHandleCheck<RefArrayType>::type{}),
MakeComparable(testArray,
typename vtkm::cont::internal::ArrayHandleCheck<TestArrayType>::type{}));
}
template <typename ValueType>
vtkm::cont::ArrayHandle<ValueType> MakeInputArray()
{
@ -44,18 +76,20 @@ void TryCopy()
{
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
"Trying type: " << vtkm::testing::TypeName<ValueType>::Name());
using VTraits = vtkm::VecTraits<ValueType>;
{
std::cout << "implicit -> basic" << std::endl;
vtkm::cont::ArrayHandleIndex input(ARRAY_SIZE);
vtkm::cont::ArrayHandle<ValueType> output;
vtkm::cont::ArrayHandle<typename VTraits::BaseComponentType> output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
}
{
std::cout << "basic -> basic" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Id> input = MakeInputArray<vtkm::Id>();
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::Id>;
vtkm::cont::ArrayHandle<SourceType> input = MakeInputArray<SourceType>();
vtkm::cont::ArrayHandle<ValueType> output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
@ -90,30 +124,53 @@ void TryCopy()
TestValues(input, output);
}
using TypeList = vtkm::ListAppend<vtkm::TypeListField, vtkm::List<ValueType, vtkm::UInt8>>;
using StorageList = VTKM_DEFAULT_STORAGE_LIST;
using UnknownArray = vtkm::cont::UnknownArrayHandle;
using UncertainArray = vtkm::cont::UncertainArrayHandle<TypeList, StorageList>;
{
std::cout << "unknown -> unknown" << std::endl;
UnknownArray input = MakeInputArray<ValueType>();
UnknownArray output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
}
{
std::cout << "uncertain -> basic (same type)" << std::endl;
UncertainArray input = MakeInputArray<ValueType>();
std::cout << "constant -> basic" << std::endl;
vtkm::cont::ArrayHandleConstant<ValueType> input(TestValue(2, ValueType{}), ARRAY_SIZE);
vtkm::cont::ArrayHandle<ValueType> output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
}
{
std::cout << "uncertain -> basic (different type)" << std::endl;
UncertainArray input = MakeInputArray<vtkm::UInt8>();
std::cout << "counting -> basic" << std::endl;
vtkm::cont::ArrayHandleCounting<ValueType> input(ValueType(-4), ValueType(3), ARRAY_SIZE);
vtkm::cont::ArrayHandle<ValueType> output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
}
{
std::cout << "permutation -> basic" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Id> indices;
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, 2, ARRAY_SIZE / 2),
indices);
auto input = vtkm::cont::make_ArrayHandlePermutation(indices, MakeInputArray<ValueType>());
vtkm::cont::ArrayHandle<ValueType> output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
}
{
std::cout << "unknown -> unknown" << std::endl;
vtkm::cont::UnknownArrayHandle input = MakeInputArray<ValueType>();
vtkm::cont::UnknownArrayHandle output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
}
{
std::cout << "unknown -> basic (same type)" << std::endl;
vtkm::cont::UnknownArrayHandle input = MakeInputArray<ValueType>();
vtkm::cont::ArrayHandle<ValueType> output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
}
{
std::cout << "unknown -> basic (different type)" << std::endl;
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::UInt8>;
vtkm::cont::UnknownArrayHandle input = MakeInputArray<SourceType>();
vtkm::cont::ArrayHandle<ValueType> output;
vtkm::cont::ArrayCopy(input, output);
TestValues(input, output);
@ -139,7 +196,8 @@ void TryCopy()
{
std::cout << "unknown.DeepCopyFrom(different type)" << std::endl;
vtkm::cont::ArrayHandle<vtkm::UInt8> input = MakeInputArray<vtkm::UInt8>();
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::UInt8>;
vtkm::cont::ArrayHandle<SourceType> input = MakeInputArray<SourceType>();
vtkm::cont::ArrayHandle<ValueType> outputArray;
vtkm::cont::UnknownArrayHandle(outputArray).DeepCopyFrom(input);
TestValues(input, outputArray);
@ -166,7 +224,8 @@ void TryCopy()
{
std::cout << "unknown.CopyShallowIfPossible(different type)" << std::endl;
vtkm::cont::ArrayHandle<vtkm::UInt8> input = MakeInputArray<vtkm::UInt8>();
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::UInt8>;
vtkm::cont::ArrayHandle<SourceType> input = MakeInputArray<SourceType>();
vtkm::cont::ArrayHandle<ValueType> outputArray;
vtkm::cont::UnknownArrayHandle(outputArray).CopyShallowIfPossible(input);
TestValues(input, outputArray);
@ -203,6 +262,8 @@ void TestArrayCopy()
TryCopy<vtkm::Id>();
TryCopy<vtkm::IdComponent>();
TryCopy<vtkm::Float32>();
TryCopy<vtkm::Vec3f>();
TryCopy<vtkm::Vec4i_16>();
TryArrayCopyShallowIfPossible();
}