mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Merge branch 'master' into new_connected_components
This commit is contained in:
commit
2540fb1b27
@ -324,6 +324,7 @@ if(VTKm_ENABLE_KOKKOS AND NOT TARGET vtkm::kokkos)
|
|||||||
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
|
||||||
enable_language(HIP)
|
enable_language(HIP)
|
||||||
add_library(vtkm::kokkos_hip INTERFACE IMPORTED GLOBAL)
|
add_library(vtkm::kokkos_hip INTERFACE IMPORTED GLOBAL)
|
||||||
|
set_property(TARGET Kokkos::kokkoscore PROPERTY INTERFACE_COMPILE_DEFINITIONS "")
|
||||||
set_property(TARGET Kokkos::kokkoscore PROPERTY INTERFACE_COMPILE_OPTIONS "")
|
set_property(TARGET Kokkos::kokkoscore PROPERTY INTERFACE_COMPILE_OPTIONS "")
|
||||||
set_property(TARGET Kokkos::kokkoscore PROPERTY INTERFACE_LINK_OPTIONS "")
|
set_property(TARGET Kokkos::kokkoscore PROPERTY INTERFACE_LINK_OPTIONS "")
|
||||||
endif()
|
endif()
|
||||||
|
11
docs/changelog/arraycopy-precompiled.md
Normal file
11
docs/changelog/arraycopy-precompiled.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Make ArrayCopy not depend on a device compiler
|
||||||
|
|
||||||
|
Rather than require `ArrayCopy` to create special versions of copy for
|
||||||
|
all arrays, use a precompiled versions. This should speed up compiles,
|
||||||
|
reduce the amount of code being generated, and require the device
|
||||||
|
compiler on fewer source files.
|
||||||
|
|
||||||
|
There are some cases where you still need to copy arrays that are not
|
||||||
|
well supported by the precompiled versions in `ArrayCopy`. (It will
|
||||||
|
always work, but the fallback is very slow.) In this case, you will want
|
||||||
|
to switch over to `ArrayCopyDevice`, which has the old behavior.
|
@ -9,178 +9,43 @@
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
#include <vtkm/cont/DeviceAdapterList.h>
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/Invoker.h>
|
|
||||||
|
|
||||||
#include <vtkm/cont/internal/ArrayCopyUnknown.h>
|
|
||||||
|
|
||||||
#include <vtkm/worklet/WorkletMapField.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
// Use a worklet because device adapter copies often have an issue with casting the values from the
|
|
||||||
// `ArrayHandleRecomineVec` that comes from `UnknownArrayHandle::CastAndCallWithExtractedArray`.
|
|
||||||
struct CopyWorklet : vtkm::worklet::WorkletMapField
|
|
||||||
{
|
|
||||||
using ControlSignature = void(FieldIn, FieldOut);
|
|
||||||
using ExecutionSignature = void(_1, _2);
|
|
||||||
using InputDomain = _1;
|
|
||||||
|
|
||||||
template <typename InType, typename OutType>
|
|
||||||
VTKM_EXEC void operator()(const InType& in, OutType& out) const
|
|
||||||
{
|
|
||||||
out = in;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct UnknownCopyOnDevice
|
|
||||||
{
|
|
||||||
bool Called = false;
|
|
||||||
|
|
||||||
template <typename InType, typename OutType>
|
|
||||||
void operator()(vtkm::cont::DeviceAdapterId device,
|
|
||||||
const vtkm::cont::ArrayHandleRecombineVec<InType>& in,
|
|
||||||
const vtkm::cont::ArrayHandleRecombineVec<OutType>& out)
|
|
||||||
{
|
|
||||||
// Note: ArrayHandleRecombineVec returns the wrong value for IsOnDevice (always true).
|
|
||||||
// This is one of the consequences of ArrayHandleRecombineVec breaking assumptions of
|
|
||||||
// ArrayHandle. It does this by stuffing Buffer objects in another Buffer's meta data
|
|
||||||
// rather than listing them explicitly (where they can be queried). We get around this
|
|
||||||
// by pulling out one of the component arrays and querying that.
|
|
||||||
if (!this->Called &&
|
|
||||||
((device == vtkm::cont::DeviceAdapterTagAny{}) ||
|
|
||||||
(in.GetComponentArray(0).IsOnDevice(device))))
|
|
||||||
{
|
|
||||||
vtkm::cont::Invoker invoke(device);
|
|
||||||
invoke(CopyWorklet{}, in, out);
|
|
||||||
this->Called = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct UnknownCopyFunctor2
|
|
||||||
{
|
|
||||||
template <typename OutType, typename InType>
|
|
||||||
void operator()(const vtkm::cont::ArrayHandleRecombineVec<OutType>& out,
|
|
||||||
const vtkm::cont::ArrayHandleRecombineVec<InType>& in) const
|
|
||||||
{
|
|
||||||
UnknownCopyOnDevice doCopy;
|
|
||||||
|
|
||||||
// Try to copy on a device that the data are already on.
|
|
||||||
vtkm::ListForEach(doCopy, VTKM_DEFAULT_DEVICE_ADAPTER_LIST{}, in, out);
|
|
||||||
|
|
||||||
// If it was not on any device, call one more time with any adapter to copy wherever.
|
|
||||||
doCopy(vtkm::cont::DeviceAdapterTagAny{}, in, out);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct UnknownCopyFunctor1
|
|
||||||
{
|
|
||||||
template <typename InType>
|
|
||||||
void operator()(const vtkm::cont::ArrayHandleRecombineVec<InType>& in,
|
|
||||||
const vtkm::cont::UnknownArrayHandle& out) const
|
|
||||||
{
|
|
||||||
out.Allocate(in.GetNumberOfValues());
|
|
||||||
|
|
||||||
this->DoIt(in, out, typename std::is_same<vtkm::FloatDefault, InType>::type{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename InType>
|
|
||||||
void DoIt(const vtkm::cont::ArrayHandleRecombineVec<InType>& in,
|
|
||||||
const vtkm::cont::UnknownArrayHandle& out,
|
|
||||||
std::false_type) const
|
|
||||||
{
|
|
||||||
// Source is not float.
|
|
||||||
if (out.IsBaseComponentType<InType>())
|
|
||||||
{
|
|
||||||
// Arrays have the same base component type. Copy directly.
|
|
||||||
UnknownCopyFunctor2{}(out.ExtractArrayFromComponents<InType>(), in);
|
|
||||||
}
|
|
||||||
else if (out.IsBaseComponentType<vtkm::FloatDefault>())
|
|
||||||
{
|
|
||||||
// Can copy anything to default float.
|
|
||||||
UnknownCopyFunctor2{}(out.ExtractArrayFromComponents<vtkm::FloatDefault>(), in);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Arrays have different base types. To reduce the number of template paths from nxn to 3n,
|
|
||||||
// copy first to a temp array of default float.
|
|
||||||
vtkm::cont::UnknownArrayHandle temp = out.NewInstanceFloatBasic();
|
|
||||||
(*this)(in, temp);
|
|
||||||
vtkm::cont::ArrayCopy(temp, out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename InType>
|
|
||||||
void DoIt(const vtkm::cont::ArrayHandleRecombineVec<InType>& in,
|
|
||||||
const vtkm::cont::UnknownArrayHandle& out,
|
|
||||||
std::true_type) const
|
|
||||||
{
|
|
||||||
// Source array is FloatDefault. That should be copiable to anything.
|
|
||||||
out.CastAndCallWithExtractedArray(UnknownCopyFunctor2{}, in);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void DoUnknownArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
|
||||||
const vtkm::cont::UnknownArrayHandle& destination)
|
|
||||||
{
|
|
||||||
if (source.GetNumberOfValues() > 0)
|
|
||||||
{
|
|
||||||
source.CastAndCallWithExtractedArray(UnknownCopyFunctor1{}, destination);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
destination.ReleaseResources();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
namespace cont
|
namespace cont
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
|
||||||
vtkm::cont::UnknownArrayHandle& destination)
|
|
||||||
{
|
{
|
||||||
if (!destination.IsValid())
|
|
||||||
|
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>())
|
||||||
{
|
{
|
||||||
destination = source.NewInstanceBasic();
|
auto outArray = result.ExtractComponent<vtkm::FloatDefault>(0);
|
||||||
|
vtkm::cont::ArrayCopyDevice(vtkm::cont::make_ArrayHandleCounting(start, step, size), outArray);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
DoUnknownArrayCopy(source, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
|
||||||
const vtkm::cont::UnknownArrayHandle& destination)
|
|
||||||
{
|
|
||||||
if (!destination.IsValid())
|
|
||||||
{
|
{
|
||||||
throw vtkm::cont::ErrorBadValue(
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray;
|
||||||
"Attempty to copy to a constant UnknownArrayHandle with no valid array.");
|
outArray.Allocate(size);
|
||||||
|
CopyCountingFloat(start, step, size, outArray);
|
||||||
|
result.DeepCopyFrom(outArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
DoUnknownArrayCopy(source, destination);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace internal
|
vtkm::cont::ArrayHandle<Id> ArrayCopyConcreteSrc<vtkm::cont::StorageTagCounting>::CopyCountingId(
|
||||||
|
const vtkm::cont::ArrayHandleCounting<vtkm::Id>& source) const
|
||||||
{
|
{
|
||||||
|
vtkm::cont::ArrayHandle<Id> destination;
|
||||||
void ArrayCopyUnknown(const vtkm::cont::UnknownArrayHandle& source,
|
vtkm::cont::ArrayCopyDevice(source, destination);
|
||||||
vtkm::cont::UnknownArrayHandle& destination)
|
return destination;
|
||||||
{
|
|
||||||
vtkm::cont::ArrayCopy(source, destination);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrayCopyUnknown(const vtkm::cont::UnknownArrayHandle& source,
|
|
||||||
const vtkm::cont::UnknownArrayHandle& destination)
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayCopy(source, destination);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} // namespace vtkm::cont::internal
|
} // namespace vtkm::cont::detail
|
||||||
|
|
||||||
} // namespace vtkm::cont
|
|
||||||
} // namespace vtkm
|
|
||||||
|
@ -10,19 +10,20 @@
|
|||||||
#ifndef vtk_m_cont_ArrayCopy_h
|
#ifndef vtk_m_cont_ArrayCopy_h
|
||||||
#define vtk_m_cont_ArrayCopy_h
|
#define vtk_m_cont_ArrayCopy_h
|
||||||
|
|
||||||
#include <vtkm/cont/Algorithm.h>
|
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||||
#include <vtkm/cont/DeviceAdapterTag.h>
|
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||||
#include <vtkm/cont/ErrorExecution.h>
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||||
#include <vtkm/cont/Logging.h>
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleView.h>
|
||||||
#include <vtkm/cont/UnknownArrayHandle.h>
|
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||||
|
|
||||||
#include <vtkm/cont/internal/ArrayHandleDeprecated.h>
|
|
||||||
|
|
||||||
#include <vtkm/cont/vtkm_cont_export.h>
|
#include <vtkm/cont/vtkm_cont_export.h>
|
||||||
|
|
||||||
// TODO: When virtual arrays are available, compile the implementation in a .cxx/.cu file. Common
|
#include <vtkm/cont/internal/MapArrayPermutation.h>
|
||||||
// arrays are copied directly but anything else would be copied through virtual methods.
|
|
||||||
|
#include <vtkm/StaticAssert.h>
|
||||||
|
#include <vtkm/VecTraits.h>
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
@ -32,72 +33,91 @@ namespace cont
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
// Element-wise copy.
|
// Compile-time check to make sure that an `ArrayHandle` passed to `ArrayCopy`
|
||||||
template <typename InArrayType, typename OutArrayType>
|
// can be passed to a `UnknownArrayHandle`. This function does nothing
|
||||||
void ArrayCopyWithAlgorithm(const InArrayType& source, OutArrayType& destination)
|
// except provide a compile error that is easier to understand than if you
|
||||||
|
// let it go and error in `UnknownArrayHandle`. (Huh? I'm not using that.)
|
||||||
|
template <typename T>
|
||||||
|
inline void ArrayCopyValueTypeCheck()
|
||||||
{
|
{
|
||||||
// Current implementation of Algorithm::Copy will first try to copy on devices where the
|
VTKM_STATIC_ASSERT_MSG(vtkm::HasVecTraits<T>::value,
|
||||||
// data is already available.
|
"An `ArrayHandle` that has a special value type that is not supported "
|
||||||
vtkm::cont::Algorithm::Copy(source, destination);
|
"by the precompiled version of `ArrayCopy` has been used. If this array "
|
||||||
|
"must be deep copied, consider using `ArrayCopyDevice`. Look at the "
|
||||||
|
"compile error for the type assigned to template parameter `T` to "
|
||||||
|
"see the offending type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove last argument once ArryHandleNewStyle becomes ArrayHandle
|
template <typename S>
|
||||||
template <typename InArrayType, typename OutArrayType>
|
struct ArrayCopyConcreteSrc;
|
||||||
void ArrayCopyOldImpl(const InArrayType& in, OutArrayType& out, std::false_type /* Copy storage */)
|
|
||||||
{
|
|
||||||
ArrayCopyWithAlgorithm(in, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy storage for implicit arrays, must be of same type:
|
template <typename SrcIsArrayHandle>
|
||||||
// TODO: This will go away once ArrayHandleNewStyle becomes ArrayHandle.
|
inline void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
|
||||||
template <typename ArrayType>
|
vtkm::cont::UnknownArrayHandle& destination,
|
||||||
void ArrayCopyOldImpl(const ArrayType& in, ArrayType& out, std::true_type /* Copy storage */)
|
SrcIsArrayHandle,
|
||||||
|
std::false_type)
|
||||||
{
|
{
|
||||||
// This is only called if in/out are the same type and the handle is not
|
destination.DeepCopyFrom(source);
|
||||||
// writable. This allows read-only implicit array handles to be copied.
|
|
||||||
auto newStorage = in.GetStorage();
|
|
||||||
out = ArrayType(newStorage);
|
|
||||||
}
|
}
|
||||||
|
template <typename SrcIsArrayHandle>
|
||||||
// TODO: This will go away once ArrayHandleNewStyle becomes ArrayHandle.
|
inline void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
|
||||||
template <typename InArrayType, typename OutArrayType>
|
const vtkm::cont::UnknownArrayHandle& destination,
|
||||||
VTKM_CONT void ArrayCopyImpl(const InArrayType& source,
|
SrcIsArrayHandle,
|
||||||
OutArrayType& destination,
|
std::false_type)
|
||||||
std::false_type /* New style */)
|
|
||||||
{
|
|
||||||
using SameTypes = std::is_same<InArrayType, OutArrayType>;
|
|
||||||
using IsWritable = vtkm::cont::internal::IsWritableArrayHandle<OutArrayType>;
|
|
||||||
using JustCopyStorage = std::integral_constant<bool, SameTypes::value && !IsWritable::value>;
|
|
||||||
ArrayCopyOldImpl(source, destination, JustCopyStorage{});
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: ArrayHandleNewStyle will eventually become ArrayHandle, in which case this
|
|
||||||
// will become ArrayCopyWithAlgorithm
|
|
||||||
template <typename T1, typename S1, typename T2, typename S2>
|
|
||||||
VTKM_CONT void ArrayCopyImpl(const vtkm::cont::ArrayHandle<T1, S1>& source,
|
|
||||||
vtkm::cont::ArrayHandle<T2, S2>& destination,
|
|
||||||
std::true_type /* New style */)
|
|
||||||
{
|
|
||||||
VTKM_STATIC_ASSERT((!std::is_same<T1, T2>::value || !std::is_same<S1, S2>::value));
|
|
||||||
ArrayCopyWithAlgorithm(source, destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: ArrayHandleNewStyle will eventually become ArrayHandle, in which case this
|
|
||||||
// will become the only version with the same array types.
|
|
||||||
template <typename T, typename S>
|
|
||||||
VTKM_CONT void ArrayCopyImpl(const vtkm::cont::ArrayHandle<T, S>& source,
|
|
||||||
vtkm::cont::ArrayHandle<T, S>& destination,
|
|
||||||
std::true_type /* New style */)
|
|
||||||
{
|
{
|
||||||
destination.DeepCopyFrom(source);
|
destination.DeepCopyFrom(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
template <typename T, typename S>
|
||||||
|
void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
|
||||||
|
vtkm::cont::ArrayHandle<T, S>& destination,
|
||||||
|
std::false_type,
|
||||||
|
std::true_type)
|
||||||
|
{
|
||||||
|
detail::ArrayCopyValueTypeCheck<T>();
|
||||||
|
|
||||||
|
using DestType = vtkm::cont::ArrayHandle<T, S>;
|
||||||
|
if (source.CanConvert<DestType>())
|
||||||
|
{
|
||||||
|
destination.DeepCopyFrom(source.AsArrayHandle<DestType>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vtkm::cont::UnknownArrayHandle destWrapper(destination);
|
||||||
|
vtkm::cont::detail::ArrayCopyImpl(source, destWrapper, std::false_type{}, std::false_type{});
|
||||||
|
// Destination array should not change, but just in case.
|
||||||
|
destWrapper.AsArrayHandle(destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TS, typename SS, typename TD, typename SD>
|
||||||
|
void ArrayCopyImpl(const vtkm::cont::ArrayHandle<TS, SS>& source,
|
||||||
|
vtkm::cont::ArrayHandle<TD, SD>& destination,
|
||||||
|
std::true_type,
|
||||||
|
std::true_type)
|
||||||
|
{
|
||||||
|
ArrayCopyValueTypeCheck<TS>();
|
||||||
|
ArrayCopyValueTypeCheck<TD>();
|
||||||
|
|
||||||
|
detail::ArrayCopyConcreteSrc<SS>{}(source, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case of copying data when type is the same.
|
||||||
|
template <typename T, typename S>
|
||||||
|
void ArrayCopyImpl(const vtkm::cont::ArrayHandle<T, S>& source,
|
||||||
|
vtkm::cont::ArrayHandle<T, S>& destination,
|
||||||
|
std::true_type,
|
||||||
|
std::true_type)
|
||||||
|
{
|
||||||
|
destination.DeepCopyFrom(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Does a deep copy from one array to another array.
|
/// \brief Does a deep copy from one array to another array.
|
||||||
///
|
///
|
||||||
/// Given a source \c ArrayHandle and a destination \c ArrayHandle, this
|
/// Given a source `ArrayHandle` and a destination `ArrayHandle`, this
|
||||||
/// function allocates the destination \c ArrayHandle to the correct size and
|
/// function allocates the destination `ArrayHandle` to the correct size and
|
||||||
/// deeply copies all the values from the source to the destination.
|
/// deeply copies all the values from the source to the destination.
|
||||||
///
|
///
|
||||||
/// This method will attempt to copy the data using the device that the input
|
/// This method will attempt to copy the data using the device that the input
|
||||||
@ -108,61 +128,41 @@ VTKM_CONT void ArrayCopyImpl(const vtkm::cont::ArrayHandle<T, S>& source,
|
|||||||
/// This should work on some non-writable array handles as well, as long as
|
/// This should work on some non-writable array handles as well, as long as
|
||||||
/// both \a source and \a destination are the same type.
|
/// both \a source and \a destination are the same type.
|
||||||
///
|
///
|
||||||
|
/// This version of array copy uses a precompiled version of copy that is
|
||||||
|
/// efficient for most standard memory layouts. However, there are some
|
||||||
|
/// types of fancy `ArrayHandle` that cannot be handled directly, and
|
||||||
|
/// the fallback for these arrays can be slow. If you see a warning in
|
||||||
|
/// the log about an inefficient memory copy when extracting a component,
|
||||||
|
/// pay heed and look for a different way to copy the data (perhaps
|
||||||
|
/// using `ArrayCopyDevice`).
|
||||||
|
///
|
||||||
/// @{
|
/// @{
|
||||||
///
|
///
|
||||||
template <typename InValueType, typename InStorage, typename OutValueType, typename OutStorage>
|
template <typename SourceArrayType, typename DestArrayType>
|
||||||
VTKM_CONT void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InStorage>& source,
|
inline void ArrayCopy(const SourceArrayType& source, DestArrayType& destination)
|
||||||
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination)
|
|
||||||
{
|
{
|
||||||
using InArrayType = vtkm::cont::ArrayHandle<InValueType, InStorage>;
|
detail::ArrayCopyImpl(source,
|
||||||
using OutArrayType = vtkm::cont::ArrayHandle<OutValueType, OutStorage>;
|
destination,
|
||||||
using SameTypes = std::is_same<InArrayType, OutArrayType>;
|
typename internal::ArrayHandleCheck<SourceArrayType>::type{},
|
||||||
using IsWritable = vtkm::cont::internal::IsWritableArrayHandle<OutArrayType>;
|
typename internal::ArrayHandleCheck<DestArrayType>::type{});
|
||||||
|
|
||||||
// There are three cases handled here:
|
|
||||||
// 1. The arrays are the same type:
|
|
||||||
// -> Deep copy the buffers and the Storage object
|
|
||||||
// 2. The arrays are different and the output is writable:
|
|
||||||
// -> Do element-wise copy
|
|
||||||
// 3. The arrays are different and the output is not writable:
|
|
||||||
// -> fail (cannot copy)
|
|
||||||
|
|
||||||
// Give a nice error message for case 3:
|
|
||||||
VTKM_STATIC_ASSERT_MSG(IsWritable::value || SameTypes::value,
|
|
||||||
"Cannot copy to a read-only array with a different "
|
|
||||||
"type than the source.");
|
|
||||||
|
|
||||||
using IsOldStyle =
|
|
||||||
std::is_base_of<vtkm::cont::internal::ArrayHandleDeprecated<InValueType, InStorage>,
|
|
||||||
InArrayType>;
|
|
||||||
|
|
||||||
// Static dispatch cases 1 & 2
|
|
||||||
detail::ArrayCopyImpl(source, destination, std::integral_constant<bool, !IsOldStyle::value>{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case where we allow a const UnknownArrayHandle as output.
|
||||||
VTKM_CONT_EXPORT void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
template <typename SourceArrayType>
|
||||||
vtkm::cont::UnknownArrayHandle& destination);
|
inline void ArrayCopy(const SourceArrayType& source, vtkm::cont::UnknownArrayHandle& destination)
|
||||||
|
|
||||||
VTKM_CONT_EXPORT void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
|
||||||
const vtkm::cont::UnknownArrayHandle& destination);
|
|
||||||
|
|
||||||
template <typename T, typename S>
|
|
||||||
VTKM_CONT void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
|
||||||
vtkm::cont::ArrayHandle<T, S>& destination)
|
|
||||||
{
|
{
|
||||||
using DestType = vtkm::cont::ArrayHandle<T, S>;
|
detail::ArrayCopyImpl(source,
|
||||||
if (source.CanConvert<DestType>())
|
destination,
|
||||||
{
|
typename internal::ArrayHandleCheck<SourceArrayType>::type{},
|
||||||
ArrayCopy(source.AsArrayHandle<DestType>(), destination);
|
std::false_type{});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
// Invalid const ArrayHandle in destination, which is not allowed because it will
|
||||||
vtkm::cont::UnknownArrayHandle destWrapper(destination);
|
// not work in all cases.
|
||||||
ArrayCopy(source, destWrapper);
|
template <typename T, typename S>
|
||||||
// Destination array should not change, but just in case.
|
void ArrayCopy(const vtkm::cont::UnknownArrayHandle&, const vtkm::cont::ArrayHandle<T, S>&)
|
||||||
destWrapper.AsArrayHandle(destination);
|
{
|
||||||
}
|
VTKM_STATIC_ASSERT_MSG(sizeof(T) == 0, "Copying to a constant ArrayHandle is not allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@ -190,13 +190,160 @@ VTKM_CONT void ArrayCopyShallowIfPossible(const vtkm::cont::UnknownArrayHandle s
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
vtkm::cont::UnknownArrayHandle destWrapper(destination);
|
vtkm::cont::UnknownArrayHandle destWrapper(destination);
|
||||||
ArrayCopy(source, destWrapper);
|
vtkm::cont::ArrayCopy(source, destWrapper);
|
||||||
// Destination array should not change, but just in case.
|
// Destination array should not change, but just in case.
|
||||||
destWrapper.AsArrayHandle(destination);
|
destWrapper.AsArrayHandle(destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
namespace detail
|
||||||
} // namespace vtkm::cont
|
{
|
||||||
|
|
||||||
|
template <typename S>
|
||||||
|
struct ArrayCopyConcreteSrc
|
||||||
|
{
|
||||||
|
template <typename T, typename DestArray>
|
||||||
|
void operator()(const vtkm::cont::ArrayHandle<T, S>& source, DestArray& destination) const
|
||||||
|
{
|
||||||
|
using ArrayType = vtkm::cont::ArrayHandle<T, S>;
|
||||||
|
this->DoIt(
|
||||||
|
source, destination, vtkm::cont::internal::ArrayExtractComponentIsInefficient<ArrayType>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename DestArray>
|
||||||
|
void DoIt(const vtkm::cont::ArrayHandle<T, S>& source,
|
||||||
|
DestArray& destination,
|
||||||
|
std::false_type vtkmNotUsed(isInefficient)) const
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayCopy(vtkm::cont::UnknownArrayHandle{ source }, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename DestArray>
|
||||||
|
void DoIt(const vtkm::cont::ArrayHandle<T, S>& source,
|
||||||
|
DestArray& destination,
|
||||||
|
std::true_type vtkmNotUsed(isInefficient)) const
|
||||||
|
{
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||||
|
"Attempting to copy from an array of type " +
|
||||||
|
vtkm::cont::TypeToString<vtkm::cont::ArrayHandle<T, S>>() +
|
||||||
|
" with ArrayCopy is inefficient. It is highly recommended you use another method "
|
||||||
|
"such as vtkm::cont::ArrayCopyDevice.");
|
||||||
|
// Still call the precompiled `ArrayCopy`. You will get another warning after this,
|
||||||
|
// but it will still technically work, albiet slowly.
|
||||||
|
vtkm::cont::ArrayCopy(vtkm::cont::UnknownArrayHandle{ source }, destination);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Special case for constant arrays to be efficient.
|
||||||
|
template <>
|
||||||
|
struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagConstant>
|
||||||
|
{
|
||||||
|
template <typename T1, typename T2, typename S2>
|
||||||
|
void operator()(const vtkm::cont::ArrayHandle<T1, vtkm::cont::StorageTagConstant>& source_,
|
||||||
|
vtkm::cont::ArrayHandle<T2, S2>& destination) const
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandleConstant<T1> source = source_;
|
||||||
|
destination.AllocateAndFill(source.GetNumberOfValues(), static_cast<T2>(source.GetValue()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Special case for ArrayHandleIndex to be efficient.
|
||||||
|
template <>
|
||||||
|
struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagIndex>
|
||||||
|
{
|
||||||
|
template <typename T, typename S>
|
||||||
|
void operator()(const vtkm::cont::ArrayHandleIndex& source,
|
||||||
|
vtkm::cont::ArrayHandle<T, S>& destination) const
|
||||||
|
{
|
||||||
|
// Skip warning about inefficient copy because there is a special case in ArrayCopyUnknown.cxx
|
||||||
|
// to copy ArrayHandleIndex efficiently.
|
||||||
|
vtkm::cont::ArrayCopy(vtkm::cont::UnknownArrayHandle{ source }, destination);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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>>
|
||||||
|
{
|
||||||
|
template <typename SourceArrayType, typename DestArrayType>
|
||||||
|
void operator()(const SourceArrayType& source, DestArrayType& destination) const
|
||||||
|
{
|
||||||
|
auto source1 = source.GetStorage().GetArray1(source.GetBuffers());
|
||||||
|
auto source2 = source.GetStorage().GetArray2(source.GetBuffers());
|
||||||
|
|
||||||
|
// Need to preallocate because view decorator will not be able to resize.
|
||||||
|
destination.Allocate(source.GetNumberOfValues());
|
||||||
|
auto dest1 = vtkm::cont::make_ArrayHandleView(destination, 0, source1.GetNumberOfValues());
|
||||||
|
auto dest2 = vtkm::cont::make_ArrayHandleView(
|
||||||
|
destination, source1.GetNumberOfValues(), source2.GetNumberOfValues());
|
||||||
|
|
||||||
|
vtkm::cont::ArrayCopy(source1, dest1);
|
||||||
|
vtkm::cont::ArrayCopy(source2, dest2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Special case for ArrayHandlePermutation to be efficient
|
||||||
|
template <typename SIndex, typename SValue>
|
||||||
|
struct ArrayCopyConcreteSrc<vtkm::cont::StorageTagPermutation<SIndex, SValue>>
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
auto indexArray = source.GetStorage().GetIndexArray(source.GetBuffers());
|
||||||
|
auto valueArray = source.GetStorage().GetValueArray(source.GetBuffers());
|
||||||
|
vtkm::cont::UnknownArrayHandle copy =
|
||||||
|
vtkm::cont::internal::MapArrayPermutation(valueArray, indexArray);
|
||||||
|
vtkm::cont::ArrayCopyShallowIfPossible(copy, destination);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace cont
|
||||||
|
} // namespace vtkm
|
||||||
|
|
||||||
#endif //vtk_m_cont_ArrayCopy_h
|
#endif //vtk_m_cont_ArrayCopy_h
|
||||||
|
153
vtkm/cont/ArrayCopyDevice.h
Normal file
153
vtkm/cont/ArrayCopyDevice.h
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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.
|
||||||
|
//============================================================================
|
||||||
|
#ifndef vtk_m_cont_ArrayCopyDevice_h
|
||||||
|
#define vtk_m_cont_ArrayCopyDevice_h
|
||||||
|
|
||||||
|
#include <vtkm/cont/Algorithm.h>
|
||||||
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
|
#include <vtkm/cont/DeviceAdapterTag.h>
|
||||||
|
#include <vtkm/cont/ErrorExecution.h>
|
||||||
|
#include <vtkm/cont/Logging.h>
|
||||||
|
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/internal/ArrayHandleDeprecated.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/vtkm_cont_export.h>
|
||||||
|
|
||||||
|
// TODO: When virtual arrays are available, compile the implementation in a .cxx/.cu file. Common
|
||||||
|
// arrays are copied directly but anything else would be copied through virtual methods.
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace cont
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// Element-wise copy.
|
||||||
|
template <typename InArrayType, typename OutArrayType>
|
||||||
|
void ArrayCopyWithAlgorithm(const InArrayType& source, OutArrayType& destination)
|
||||||
|
{
|
||||||
|
// Current implementation of Algorithm::Copy will first try to copy on devices where the
|
||||||
|
// data is already available.
|
||||||
|
vtkm::cont::Algorithm::Copy(source, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove last argument once ArryHandleNewStyle becomes ArrayHandle
|
||||||
|
template <typename InArrayType, typename OutArrayType>
|
||||||
|
void ArrayCopyOldImpl(const InArrayType& in, OutArrayType& out, std::false_type /* Copy storage */)
|
||||||
|
{
|
||||||
|
ArrayCopyWithAlgorithm(in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy storage for implicit arrays, must be of same type:
|
||||||
|
// TODO: This will go away once ArrayHandleNewStyle becomes ArrayHandle.
|
||||||
|
template <typename ArrayType>
|
||||||
|
void ArrayCopyOldImpl(const ArrayType& in, ArrayType& out, std::true_type /* Copy storage */)
|
||||||
|
{
|
||||||
|
// This is only called if in/out are the same type and the handle is not
|
||||||
|
// writable. This allows read-only implicit array handles to be copied.
|
||||||
|
auto newStorage = in.GetStorage();
|
||||||
|
out = ArrayType(newStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This will go away once ArrayHandleNewStyle becomes ArrayHandle.
|
||||||
|
template <typename InArrayType, typename OutArrayType>
|
||||||
|
VTKM_CONT void ArrayCopyImpl(const InArrayType& source,
|
||||||
|
OutArrayType& destination,
|
||||||
|
std::false_type /* New style */)
|
||||||
|
{
|
||||||
|
using SameTypes = std::is_same<InArrayType, OutArrayType>;
|
||||||
|
using IsWritable = vtkm::cont::internal::IsWritableArrayHandle<OutArrayType>;
|
||||||
|
using JustCopyStorage = std::integral_constant<bool, SameTypes::value && !IsWritable::value>;
|
||||||
|
ArrayCopyOldImpl(source, destination, JustCopyStorage{});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: ArrayHandleNewStyle will eventually become ArrayHandle, in which case this
|
||||||
|
// will become ArrayCopyWithAlgorithm
|
||||||
|
template <typename T1, typename S1, typename T2, typename S2>
|
||||||
|
VTKM_CONT void ArrayCopyImpl(const vtkm::cont::ArrayHandle<T1, S1>& source,
|
||||||
|
vtkm::cont::ArrayHandle<T2, S2>& destination,
|
||||||
|
std::true_type /* New style */)
|
||||||
|
{
|
||||||
|
VTKM_STATIC_ASSERT((!std::is_same<T1, T2>::value || !std::is_same<S1, S2>::value));
|
||||||
|
ArrayCopyWithAlgorithm(source, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: ArrayHandleNewStyle will eventually become ArrayHandle, in which case this
|
||||||
|
// will become the only version with the same array types.
|
||||||
|
template <typename T, typename S>
|
||||||
|
VTKM_CONT void ArrayCopyImpl(const vtkm::cont::ArrayHandle<T, S>& source,
|
||||||
|
vtkm::cont::ArrayHandle<T, S>& destination,
|
||||||
|
std::true_type /* New style */)
|
||||||
|
{
|
||||||
|
destination.DeepCopyFrom(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// \brief Does a deep copy from one array to another array.
|
||||||
|
///
|
||||||
|
/// Given a source `ArrayHandle` and a destination `ArrayHandle`, this
|
||||||
|
/// function allocates the destination `ArrayHandle` to the correct size and
|
||||||
|
/// deeply copies all the values from the source to the destination.
|
||||||
|
///
|
||||||
|
/// This method will attempt to copy the data using the device that the input
|
||||||
|
/// data is already valid on. If the input data is only valid in the control
|
||||||
|
/// environment, the runtime device tracker is used to try to find another
|
||||||
|
/// device.
|
||||||
|
///
|
||||||
|
/// This should work on some non-writable array handles as well, as long as
|
||||||
|
/// both \a source and \a destination are the same type.
|
||||||
|
///
|
||||||
|
/// This version of array copy is templated to create custom code for the
|
||||||
|
/// particular types of `ArrayHandle`s that you are copying. This will
|
||||||
|
/// ensure that you get the best possible copy, but requires a device
|
||||||
|
/// compiler and tends to bloat the code.
|
||||||
|
///
|
||||||
|
/// @{
|
||||||
|
///
|
||||||
|
template <typename InValueType, typename InStorage, typename OutValueType, typename OutStorage>
|
||||||
|
VTKM_CONT void ArrayCopyDevice(const vtkm::cont::ArrayHandle<InValueType, InStorage>& source,
|
||||||
|
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination)
|
||||||
|
{
|
||||||
|
using InArrayType = vtkm::cont::ArrayHandle<InValueType, InStorage>;
|
||||||
|
using OutArrayType = vtkm::cont::ArrayHandle<OutValueType, OutStorage>;
|
||||||
|
using SameTypes = std::is_same<InArrayType, OutArrayType>;
|
||||||
|
using IsWritable = vtkm::cont::internal::IsWritableArrayHandle<OutArrayType>;
|
||||||
|
|
||||||
|
// There are three cases handled here:
|
||||||
|
// 1. The arrays are the same type:
|
||||||
|
// -> Deep copy the buffers and the Storage object
|
||||||
|
// 2. The arrays are different and the output is writable:
|
||||||
|
// -> Do element-wise copy
|
||||||
|
// 3. The arrays are different and the output is not writable:
|
||||||
|
// -> fail (cannot copy)
|
||||||
|
|
||||||
|
// Give a nice error message for case 3:
|
||||||
|
VTKM_STATIC_ASSERT_MSG(IsWritable::value || SameTypes::value,
|
||||||
|
"Cannot copy to a read-only array with a different "
|
||||||
|
"type than the source.");
|
||||||
|
|
||||||
|
using IsOldStyle =
|
||||||
|
std::is_base_of<vtkm::cont::internal::ArrayHandleDeprecated<InValueType, InStorage>,
|
||||||
|
InArrayType>;
|
||||||
|
|
||||||
|
// Static dispatch cases 1 & 2
|
||||||
|
detail::ArrayCopyImpl(source, destination, std::integral_constant<bool, !IsOldStyle::value>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace vtkm::cont
|
||||||
|
|
||||||
|
#endif //vtk_m_cont_ArrayCopyDevice_h
|
@ -19,6 +19,8 @@
|
|||||||
#include <vtkm/VecFlat.h>
|
#include <vtkm/VecFlat.h>
|
||||||
#include <vtkm/VecTraits.h>
|
#include <vtkm/VecTraits.h>
|
||||||
|
|
||||||
|
#include <vtkmstd/integer_sequence.h>
|
||||||
|
|
||||||
#include <vtkm/cont/vtkm_cont_export.h>
|
#include <vtkm/cont/vtkm_cont_export.h>
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
@ -137,6 +139,39 @@ struct ArrayExtractComponentImpl<vtkm::cont::StorageTagBasic>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <std::size_t, typename Super>
|
||||||
|
struct ForwardSuper : Super
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename sequence, typename... Supers>
|
||||||
|
struct SharedSupersImpl;
|
||||||
|
|
||||||
|
template <std::size_t... Indices, typename... Supers>
|
||||||
|
struct SharedSupersImpl<vtkmstd::index_sequence<Indices...>, Supers...>
|
||||||
|
: ForwardSuper<Indices, Supers>...
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// `ArrayExtractComponentImpl`s that modify the behavior from other storage types might
|
||||||
|
// want to inherit from the `ArrayExtractComponentImpl`s of these storage types. However,
|
||||||
|
// if the template specifies multiple storage types, two of the same might be specified,
|
||||||
|
// and it is illegal in C++ to directly inherit from the same type twice. This special
|
||||||
|
// superclass accepts a variable amout of superclasses. Inheriting from this will inherit
|
||||||
|
// from all these superclasses, and duplicates are allowed.
|
||||||
|
template <typename... Supers>
|
||||||
|
using DuplicatedSuperclasses =
|
||||||
|
detail::SharedSupersImpl<vtkmstd::make_index_sequence<sizeof...(Supers)>, Supers...>;
|
||||||
|
|
||||||
|
template <typename... StorageTags>
|
||||||
|
using ArrayExtractComponentImplInherit =
|
||||||
|
DuplicatedSuperclasses<vtkm::cont::internal::ArrayExtractComponentImpl<StorageTags>...>;
|
||||||
|
|
||||||
/// \brief Resolves to true if ArrayHandleComponent of the array handle would be inefficient.
|
/// \brief Resolves to true if ArrayHandleComponent of the array handle would be inefficient.
|
||||||
///
|
///
|
||||||
template <typename ArrayHandleType>
|
template <typename ArrayHandleType>
|
||||||
|
@ -379,8 +379,11 @@ VTKM_CONT
|
|||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Superclass will inherit the ArrayExtractComponentImplInefficient property if any
|
||||||
|
// of the sub-storage are inefficient (thus making everything inefficient).
|
||||||
template <typename... STs>
|
template <typename... STs>
|
||||||
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagCartesianProduct<STs...>>
|
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagCartesianProduct<STs...>>
|
||||||
|
: vtkm::cont::internal::ArrayExtractComponentImplInherit<STs...>
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
vtkm::cont::ArrayHandleStride<T> AdjustStrideForComponent(
|
vtkm::cont::ArrayHandleStride<T> AdjustStrideForComponent(
|
||||||
|
@ -507,16 +507,19 @@ struct ExtractComponentCompositeVecFunctor
|
|||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
// Superclass will inherit the ArrayExtractComponentImplInefficient property if any
|
||||||
|
// of the sub-storage are inefficient (thus making everything inefficient).
|
||||||
template <typename... StorageTags>
|
template <typename... StorageTags>
|
||||||
struct ArrayExtractComponentImpl<StorageTagCompositeVec<StorageTags...>>
|
struct ArrayExtractComponentImpl<StorageTagCompositeVec<StorageTags...>>
|
||||||
|
: vtkm::cont::internal::ArrayExtractComponentImplInherit<StorageTags...>
|
||||||
{
|
{
|
||||||
template <typename T, vtkm::IdComponent NUM_COMPONENTS>
|
template <typename VecT>
|
||||||
typename detail::ExtractComponentCompositeVecFunctor<T>::ResultArray operator()(
|
auto operator()(
|
||||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, NUM_COMPONENTS>,
|
const vtkm::cont::ArrayHandle<VecT, vtkm::cont::StorageTagCompositeVec<StorageTags...>>& src,
|
||||||
vtkm::cont::StorageTagCompositeVec<StorageTags...>>& src,
|
|
||||||
vtkm::IdComponent componentIndex,
|
vtkm::IdComponent componentIndex,
|
||||||
vtkm::CopyFlag allowCopy) const
|
vtkm::CopyFlag allowCopy) const
|
||||||
{
|
{
|
||||||
|
using T = typename vtkm::VecTraits<VecT>::ComponentType;
|
||||||
vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, StorageTags>...> array(src);
|
vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, StorageTags>...> array(src);
|
||||||
constexpr vtkm::IdComponent NUM_SUB_COMPONENTS = vtkm::VecFlat<T>::NUM_COMPONENTS;
|
constexpr vtkm::IdComponent NUM_SUB_COMPONENTS = vtkm::VecFlat<T>::NUM_COMPONENTS;
|
||||||
|
|
||||||
|
@ -248,12 +248,12 @@ public:
|
|||||||
return vtkm::cont::internal::CreateBuffers(array1, array2);
|
return vtkm::cont::internal::CreateBuffers(array1, array2);
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT static const ArrayHandleType1& GetArray1(const vtkm::cont::internal::Buffer* buffers)
|
VTKM_CONT static const ArrayHandleType1 GetArray1(const vtkm::cont::internal::Buffer* buffers)
|
||||||
{
|
{
|
||||||
return ArrayHandleType1(Buffers1(buffers));
|
return ArrayHandleType1(Buffers1(buffers));
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT static const ArrayHandleType2& GetArray2(const vtkm::cont::internal::Buffer* buffers)
|
VTKM_CONT static const ArrayHandleType2 GetArray2(const vtkm::cont::internal::Buffer* buffers)
|
||||||
{
|
{
|
||||||
return ArrayHandleType2(Buffers2(buffers));
|
return ArrayHandleType2(Buffers2(buffers));
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,10 @@ public:
|
|||||||
internal::ArrayPortalCounting<CountingValueType>(start, step, length)))
|
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
|
/// A convenience function for creating an ArrayHandleCounting. It takes the
|
||||||
|
@ -249,9 +249,12 @@ VTKM_CONT vtkm::cont::ArrayHandleGroupVec<ArrayHandleType, NUM_COMPONENTS> make_
|
|||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Superclass will inherit the ArrayExtractComponentImplInefficient property if
|
||||||
|
// the sub-storage is inefficient (thus making everything inefficient).
|
||||||
template <typename ComponentsStorageTag, vtkm::IdComponent NUM_COMPONENTS>
|
template <typename ComponentsStorageTag, vtkm::IdComponent NUM_COMPONENTS>
|
||||||
struct ArrayExtractComponentImpl<
|
struct ArrayExtractComponentImpl<
|
||||||
vtkm::cont::StorageTagGroupVec<ComponentsStorageTag, NUM_COMPONENTS>>
|
vtkm::cont::StorageTagGroupVec<ComponentsStorageTag, NUM_COMPONENTS>>
|
||||||
|
: vtkm::cont::internal::ArrayExtractComponentImpl<ComponentsStorageTag>
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> operator()(
|
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> operator()(
|
||||||
|
@ -216,6 +216,10 @@ class ArrayHandlePermutation
|
|||||||
VTKM_IS_ARRAY_HANDLE(IndexArrayHandleType);
|
VTKM_IS_ARRAY_HANDLE(IndexArrayHandleType);
|
||||||
VTKM_IS_ARRAY_HANDLE(ValueArrayHandleType);
|
VTKM_IS_ARRAY_HANDLE(ValueArrayHandleType);
|
||||||
|
|
||||||
|
VTKM_STATIC_ASSERT_MSG(
|
||||||
|
(std::is_same<vtkm::Id, typename IndexArrayHandleType::ValueType>::value),
|
||||||
|
"Permutation array in ArrayHandlePermutation must have vtkm::Id value type.");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||||
ArrayHandlePermutation,
|
ArrayHandlePermutation,
|
||||||
|
@ -217,8 +217,11 @@ VTKM_CONT ArrayHandleReverse<HandleType> make_ArrayHandleReverse(const HandleTyp
|
|||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Superclass will inherit the ArrayExtractComponentImplInefficient property if
|
||||||
|
// the sub-storage is inefficient (thus making everything inefficient).
|
||||||
template <typename StorageTag>
|
template <typename StorageTag>
|
||||||
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagReverse<StorageTag>>
|
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagReverse<StorageTag>>
|
||||||
|
: vtkm::cont::internal::ArrayExtractComponentImpl<StorageTag>
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using StrideArrayType =
|
using StrideArrayType =
|
||||||
|
@ -179,7 +179,7 @@ public:
|
|||||||
vtkm::Id adjustedEndIndex = (endIndex < indices.NumberOfValues)
|
vtkm::Id adjustedEndIndex = (endIndex < indices.NumberOfValues)
|
||||||
? endIndex + indices.StartIndex
|
? endIndex + indices.StartIndex
|
||||||
: indices.NumberOfValues + indices.StartIndex;
|
: indices.NumberOfValues + indices.StartIndex;
|
||||||
SourceStorage::Fill(buffers, fillValue, adjustedStartIndex, adjustedEndIndex, token);
|
SourceStorage::Fill(buffers + 1, fillValue, adjustedStartIndex, adjustedEndIndex, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
|
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
|
||||||
@ -258,8 +258,11 @@ ArrayHandleView<ArrayHandleType> make_ArrayHandleView(const ArrayHandleType& arr
|
|||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Superclass will inherit the ArrayExtractComponentImplInefficient property if
|
||||||
|
// the sub-storage is inefficient (thus making everything inefficient).
|
||||||
template <typename StorageTag>
|
template <typename StorageTag>
|
||||||
struct ArrayExtractComponentImpl<StorageTagView<StorageTag>>
|
struct ArrayExtractComponentImpl<StorageTagView<StorageTag>>
|
||||||
|
: vtkm::cont::internal::ArrayExtractComponentImpl<StorageTag>
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using StrideArrayType =
|
using StrideArrayType =
|
||||||
|
@ -208,6 +208,15 @@ public:
|
|||||||
FirstStorage::CreateWritePortal(FirstArrayBuffers(buffers), device, token),
|
FirstStorage::CreateWritePortal(FirstArrayBuffers(buffers), device, token),
|
||||||
SecondStorage::CreateWritePortal(SecondArrayBuffers(buffers), device, token));
|
SecondStorage::CreateWritePortal(SecondArrayBuffers(buffers), device, token));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<T1, ST1> GetFirstArray(const vtkm::cont::internal::Buffer* buffers)
|
||||||
|
{
|
||||||
|
return { FirstArrayBuffers(buffers) };
|
||||||
|
}
|
||||||
|
vtkm::cont::ArrayHandle<T2, ST2> GetSecondArray(const vtkm::cont::internal::Buffer* buffers)
|
||||||
|
{
|
||||||
|
return { SecondArrayBuffers(buffers) };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
@ -238,6 +247,15 @@ public:
|
|||||||
: Superclass(vtkm::cont::internal::CreateBuffers(firstArray, secondArray))
|
: Superclass(vtkm::cont::internal::CreateBuffers(firstArray, secondArray))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FirstHandleType GetFirstArray() const
|
||||||
|
{
|
||||||
|
return this->GetStorage().GetFirstArray(this->GetBuffers());
|
||||||
|
}
|
||||||
|
SecondHandleType GetSecondArray() const
|
||||||
|
{
|
||||||
|
return this->GetStorage().GetSecondArray(this->GetBuffers());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A convenience function for creating an ArrayHandleZip. It takes the two
|
/// A convenience function for creating an ArrayHandleZip. It takes the two
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
set(headers
|
set(headers
|
||||||
Algorithm.h
|
Algorithm.h
|
||||||
ArrayCopy.h
|
ArrayCopy.h
|
||||||
|
ArrayCopyDevice.h
|
||||||
ArrayExtractComponent.h
|
ArrayExtractComponent.h
|
||||||
ArrayGetValues.h
|
ArrayGetValues.h
|
||||||
ArrayHandle.h
|
ArrayHandle.h
|
||||||
@ -192,7 +193,9 @@ set(device_sources
|
|||||||
ColorTable.cxx
|
ColorTable.cxx
|
||||||
ConvertNumComponentsToOffsets.cxx
|
ConvertNumComponentsToOffsets.cxx
|
||||||
Field.cxx
|
Field.cxx
|
||||||
|
internal/ArrayCopyUnknown.cxx
|
||||||
internal/Buffer.cxx
|
internal/Buffer.cxx
|
||||||
|
internal/MapArrayPermutation.cxx
|
||||||
MergePartitionedDataSet.cxx
|
MergePartitionedDataSet.cxx
|
||||||
PointLocatorSparseGrid.cxx
|
PointLocatorSparseGrid.cxx
|
||||||
RuntimeDeviceInformation.cxx
|
RuntimeDeviceInformation.cxx
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#ifndef vtk_m_cont_DataSetBuilderRectilinear_h
|
#ifndef vtk_m_cont_DataSetBuilderRectilinear_h
|
||||||
#define vtk_m_cont_DataSetBuilderRectilinear_h
|
#define vtk_m_cont_DataSetBuilderRectilinear_h
|
||||||
|
|
||||||
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||||
#include <vtkm/cont/CoordinateSystem.h>
|
#include <vtkm/cont/CoordinateSystem.h>
|
||||||
@ -34,7 +35,7 @@ class VTKM_CONT_EXPORT DataSetBuilderRectilinear
|
|||||||
VTKM_CONT static void CopyInto(const vtkm::cont::ArrayHandle<T>& input,
|
VTKM_CONT static void CopyInto(const vtkm::cont::ArrayHandle<T>& input,
|
||||||
vtkm::cont::ArrayHandle<U>& output)
|
vtkm::cont::ArrayHandle<U>& output)
|
||||||
{
|
{
|
||||||
vtkm::cont::UnknownArrayHandle(output).DeepCopyFrom(input);
|
vtkm::cont::ArrayCopy(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
#include <vtkm/cont/MergePartitionedDataSet.h>
|
#include <vtkm/cont/MergePartitionedDataSet.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/Algorithm.h>
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>
|
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>
|
||||||
#include <vtkm/cont/ArrayHandleView.h>
|
#include <vtkm/cont/ArrayHandleView.h>
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#define vtk_m_cont_ParticleArrayCopy_hxx
|
#define vtk_m_cont_ParticleArrayCopy_hxx
|
||||||
|
|
||||||
#include <vtkm/cont/Algorithm.h>
|
#include <vtkm/cont/Algorithm.h>
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
|
||||||
#include <vtkm/cont/ArrayHandleTransform.h>
|
#include <vtkm/cont/ArrayHandleTransform.h>
|
||||||
#include <vtkm/cont/Invoker.h>
|
#include <vtkm/cont/Invoker.h>
|
||||||
#include <vtkm/cont/ParticleArrayCopy.h>
|
#include <vtkm/cont/ParticleArrayCopy.h>
|
||||||
@ -84,7 +83,7 @@ VTKM_ALWAYS_EXPORT inline void ParticleArrayCopy(
|
|||||||
vtkm::cont::Algorithm::CopyIf(posTrn, termTrn, outPos);
|
vtkm::cont::Algorithm::CopyIf(posTrn, termTrn, outPos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vtkm::cont::ArrayCopy(posTrn, outPos);
|
vtkm::cont::Algorithm::Copy(posTrn, outPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include <vtkm/cont/Algorithm.h>
|
#include <vtkm/cont/Algorithm.h>
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||||
#include <vtkm/cont/Invoker.h>
|
#include <vtkm/cont/Invoker.h>
|
||||||
#include <vtkm/worklet/WorkletMapField.h>
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
@ -82,9 +82,8 @@ void PointLocatorSparseGrid::Build()
|
|||||||
static_cast<vtkm::FloatDefault>(this->Range[2].Max));
|
static_cast<vtkm::FloatDefault>(this->Range[2].Max));
|
||||||
|
|
||||||
// generate unique id for each input point
|
// generate unique id for each input point
|
||||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> pointCounting(
|
vtkm::cont::ArrayHandleIndex pointIndex(this->GetCoordinates().GetNumberOfValues());
|
||||||
0, 1, this->GetCoordinates().GetNumberOfValues());
|
vtkm::cont::ArrayCopy(pointIndex, this->PointIds);
|
||||||
vtkm::cont::ArrayCopy(pointCounting, this->PointIds);
|
|
||||||
|
|
||||||
using internal::BinPointsWorklet;
|
using internal::BinPointsWorklet;
|
||||||
|
|
||||||
|
@ -275,12 +275,32 @@ VTKM_CONT void UnknownArrayHandle::Allocate(vtkm::Id numValues, vtkm::CopyFlag p
|
|||||||
|
|
||||||
VTKM_CONT void UnknownArrayHandle::DeepCopyFrom(const vtkm::cont::UnknownArrayHandle& source)
|
VTKM_CONT void UnknownArrayHandle::DeepCopyFrom(const vtkm::cont::UnknownArrayHandle& source)
|
||||||
{
|
{
|
||||||
vtkm::cont::internal::ArrayCopyUnknown(source, *this);
|
if (!this->IsValid())
|
||||||
|
{
|
||||||
|
*this = source.NewInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_cast<const UnknownArrayHandle*>(this)->DeepCopyFrom(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT void UnknownArrayHandle::DeepCopyFrom(const vtkm::cont::UnknownArrayHandle& source) const
|
VTKM_CONT void UnknownArrayHandle::DeepCopyFrom(const vtkm::cont::UnknownArrayHandle& source) const
|
||||||
{
|
{
|
||||||
vtkm::cont::internal::ArrayCopyUnknown(source, *this);
|
if (!this->IsValid())
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorBadValue(
|
||||||
|
"Attempty to copy to a constant UnknownArrayHandle with no valid array.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.IsValueTypeImpl(this->Container->ValueType) &&
|
||||||
|
source.IsStorageTypeImpl(this->Container->StorageType))
|
||||||
|
{
|
||||||
|
this->Container->DeepCopy(source.Container->ArrayHandlePointer,
|
||||||
|
this->Container->ArrayHandlePointer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vtkm::cont::internal::ArrayCopyUnknown(source, *this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT
|
VTKM_CONT
|
||||||
@ -290,8 +310,10 @@ void UnknownArrayHandle::CopyShallowIfPossible(const vtkm::cont::UnknownArrayHan
|
|||||||
{
|
{
|
||||||
*this = source;
|
*this = source;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
const_cast<const UnknownArrayHandle*>(this)->CopyShallowIfPossible(source);
|
{
|
||||||
|
const_cast<const UnknownArrayHandle*>(this)->CopyShallowIfPossible(source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT
|
VTKM_CONT
|
||||||
@ -311,7 +333,7 @@ void UnknownArrayHandle::CopyShallowIfPossible(const vtkm::cont::UnknownArrayHan
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->DeepCopyFrom(source);
|
vtkm::cont::internal::ArrayCopyUnknown(source, *this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +113,15 @@ void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem)
|
|||||||
*destination = *source;
|
*destination = *source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
void UnknownAHDeepCopy(const void* sourceMem, void* destinationMem)
|
||||||
|
{
|
||||||
|
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||||
|
const AH* source = reinterpret_cast<const AH*>(sourceMem);
|
||||||
|
AH* destination = reinterpret_cast<AH*>(destinationMem);
|
||||||
|
destination->DeepCopyFrom(*source);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
std::vector<vtkm::cont::internal::Buffer>
|
std::vector<vtkm::cont::internal::Buffer>
|
||||||
UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy)
|
UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy)
|
||||||
@ -224,6 +233,9 @@ struct VTKM_CONT_EXPORT UnknownAHContainer
|
|||||||
using ShallowCopyType = void(const void*, void*);
|
using ShallowCopyType = void(const void*, void*);
|
||||||
ShallowCopyType* ShallowCopy;
|
ShallowCopyType* ShallowCopy;
|
||||||
|
|
||||||
|
using DeepCopyType = void(const void*, void*);
|
||||||
|
DeepCopyType* DeepCopy;
|
||||||
|
|
||||||
using ExtractComponentType = std::vector<vtkm::cont::internal::Buffer>(void*,
|
using ExtractComponentType = std::vector<vtkm::cont::internal::Buffer>(void*,
|
||||||
vtkm::IdComponent,
|
vtkm::IdComponent,
|
||||||
vtkm::CopyFlag);
|
vtkm::CopyFlag);
|
||||||
@ -331,6 +343,7 @@ inline UnknownAHContainer::UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S
|
|||||||
, NumberOfComponentsFlat(detail::UnknownAHNumberOfComponentsFlat<T>)
|
, NumberOfComponentsFlat(detail::UnknownAHNumberOfComponentsFlat<T>)
|
||||||
, Allocate(detail::UnknownAHAllocate<T, S>)
|
, Allocate(detail::UnknownAHAllocate<T, S>)
|
||||||
, ShallowCopy(detail::UnknownAHShallowCopy<T, S>)
|
, ShallowCopy(detail::UnknownAHShallowCopy<T, S>)
|
||||||
|
, DeepCopy(detail::UnknownAHDeepCopy<T, S>)
|
||||||
, ExtractComponent(detail::UnknownAHExtractComponent<T, S>)
|
, ExtractComponent(detail::UnknownAHExtractComponent<T, S>)
|
||||||
, ReleaseResources(detail::UnknownAHReleaseResources<T, S>)
|
, ReleaseResources(detail::UnknownAHReleaseResources<T, S>)
|
||||||
, ReleaseResourcesExecution(detail::UnknownAHReleaseResourcesExecution<T, S>)
|
, ReleaseResourcesExecution(detail::UnknownAHReleaseResourcesExecution<T, S>)
|
||||||
|
254
vtkm/cont/internal/ArrayCopyUnknown.cxx
Normal file
254
vtkm/cont/internal/ArrayCopyUnknown.cxx
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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>
|
||||||
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||||
|
#include <vtkm/cont/DeviceAdapterList.h>
|
||||||
|
#include <vtkm/cont/Invoker.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/internal/ArrayCopyUnknown.h>
|
||||||
|
|
||||||
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
// Use a worklet because device adapter copies often have an issue with casting the values from the
|
||||||
|
// `ArrayHandleRecomineVec` that comes from `UnknownArrayHandle::CastAndCallWithExtractedArray`.
|
||||||
|
struct CopyWorklet : vtkm::worklet::WorkletMapField
|
||||||
|
{
|
||||||
|
using ControlSignature = void(FieldIn, FieldOut);
|
||||||
|
using ExecutionSignature = void(_1, _2);
|
||||||
|
using InputDomain = _1;
|
||||||
|
|
||||||
|
template <typename InType, typename OutType>
|
||||||
|
VTKM_EXEC void operator()(const InType& in, OutType& out) const
|
||||||
|
{
|
||||||
|
out = in;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UnknownCopyOnDevice
|
||||||
|
{
|
||||||
|
bool Called = false;
|
||||||
|
|
||||||
|
template <typename InType, typename OutType>
|
||||||
|
void operator()(vtkm::cont::DeviceAdapterId device,
|
||||||
|
const vtkm::cont::ArrayHandleRecombineVec<InType>& in,
|
||||||
|
const vtkm::cont::ArrayHandleRecombineVec<OutType>& out)
|
||||||
|
{
|
||||||
|
// Note: ArrayHandleRecombineVec returns the wrong value for IsOnDevice (always true).
|
||||||
|
// This is one of the consequences of ArrayHandleRecombineVec breaking assumptions of
|
||||||
|
// ArrayHandle. It does this by stuffing Buffer objects in another Buffer's meta data
|
||||||
|
// rather than listing them explicitly (where they can be queried). We get around this
|
||||||
|
// by pulling out one of the component arrays and querying that.
|
||||||
|
if (!this->Called &&
|
||||||
|
((device == vtkm::cont::DeviceAdapterTagAny{}) ||
|
||||||
|
(in.GetComponentArray(0).IsOnDevice(device))))
|
||||||
|
{
|
||||||
|
vtkm::cont::Invoker invoke(device);
|
||||||
|
invoke(CopyWorklet{}, in, out);
|
||||||
|
this->Called = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UnknownCopyFunctor2
|
||||||
|
{
|
||||||
|
template <typename OutType, typename InType>
|
||||||
|
void operator()(const vtkm::cont::ArrayHandleRecombineVec<OutType>& out,
|
||||||
|
const vtkm::cont::ArrayHandleRecombineVec<InType>& in) const
|
||||||
|
{
|
||||||
|
UnknownCopyOnDevice doCopy;
|
||||||
|
|
||||||
|
// Try to copy on a device that the data are already on.
|
||||||
|
vtkm::ListForEach(doCopy, VTKM_DEFAULT_DEVICE_ADAPTER_LIST{}, in, out);
|
||||||
|
|
||||||
|
// If it was not on any device, call one more time with any adapter to copy wherever.
|
||||||
|
doCopy(vtkm::cont::DeviceAdapterTagAny{}, in, out);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UnknownCopyFunctor1
|
||||||
|
{
|
||||||
|
template <typename InType>
|
||||||
|
void operator()(const vtkm::cont::ArrayHandleRecombineVec<InType>& in,
|
||||||
|
const vtkm::cont::UnknownArrayHandle& out) const
|
||||||
|
{
|
||||||
|
out.Allocate(in.GetNumberOfValues());
|
||||||
|
|
||||||
|
this->DoIt(in, out, typename std::is_same<vtkm::FloatDefault, InType>::type{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InType>
|
||||||
|
void DoIt(const vtkm::cont::ArrayHandleRecombineVec<InType>& in,
|
||||||
|
const vtkm::cont::UnknownArrayHandle& out,
|
||||||
|
std::false_type) const
|
||||||
|
{
|
||||||
|
// Source is not float.
|
||||||
|
if (out.IsBaseComponentType<InType>())
|
||||||
|
{
|
||||||
|
// Arrays have the same base component type. Copy directly.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UnknownCopyFunctor2{}(out.ExtractArrayFromComponents<InType>(vtkm::CopyFlag::Off), in);
|
||||||
|
}
|
||||||
|
catch (vtkm::cont::Error& error)
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorBadType(
|
||||||
|
"Unable to copy to an array of type " + out.GetArrayTypeName() +
|
||||||
|
" using anonymous methods. Try using vtkm::cont::ArrayCopyDevice. "
|
||||||
|
"(Original error: `" +
|
||||||
|
error.GetMessage() + "')");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (out.IsBaseComponentType<vtkm::FloatDefault>())
|
||||||
|
{
|
||||||
|
// Can copy anything to default float.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UnknownCopyFunctor2{}(
|
||||||
|
out.ExtractArrayFromComponents<vtkm::FloatDefault>(vtkm::CopyFlag::Off), in);
|
||||||
|
}
|
||||||
|
catch (vtkm::cont::Error& error)
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorBadType(
|
||||||
|
"Unable to copy to an array of type " + out.GetArrayTypeName() +
|
||||||
|
" using anonymous methods. Try using vtkm::cont::ArrayCopyDevice. "
|
||||||
|
"(Original error: `" +
|
||||||
|
error.GetMessage() + "')");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Arrays have different base types. To reduce the number of template paths from nxn to 3n,
|
||||||
|
// copy first to a temp array of default float.
|
||||||
|
vtkm::cont::UnknownArrayHandle temp = out.NewInstanceFloatBasic();
|
||||||
|
(*this)(in, temp);
|
||||||
|
vtkm::cont::ArrayCopy(temp, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename InType>
|
||||||
|
void DoIt(const vtkm::cont::ArrayHandleRecombineVec<InType>& in,
|
||||||
|
const vtkm::cont::UnknownArrayHandle& out,
|
||||||
|
std::true_type) const
|
||||||
|
{
|
||||||
|
// Source array is FloatDefault. That should be copiable to anything.
|
||||||
|
out.CastAndCallWithExtractedArray(UnknownCopyFunctor2{}, in);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void ArrayCopySpecialCase(const vtkm::cont::ArrayHandleIndex& source,
|
||||||
|
const vtkm::cont::UnknownArrayHandle& destination)
|
||||||
|
{
|
||||||
|
if (destination.CanConvert<vtkm::cont::ArrayHandleIndex>())
|
||||||
|
{
|
||||||
|
// Unlikely, but we'll check.
|
||||||
|
destination.AsArrayHandle<vtkm::cont::ArrayHandleIndex>().DeepCopyFrom(source);
|
||||||
|
}
|
||||||
|
else if (destination.IsBaseComponentType<vtkm::Id>())
|
||||||
|
{
|
||||||
|
destination.Allocate(source.GetNumberOfValues());
|
||||||
|
auto dest = destination.ExtractComponent<vtkm::Id>(0, vtkm::CopyFlag::Off);
|
||||||
|
vtkm::cont::ArrayCopyDevice(source, dest);
|
||||||
|
}
|
||||||
|
else if (destination.IsBaseComponentType<vtkm::IdComponent>())
|
||||||
|
{
|
||||||
|
destination.Allocate(source.GetNumberOfValues());
|
||||||
|
auto dest = destination.ExtractComponent<vtkm::IdComponent>(0, vtkm::CopyFlag::Off);
|
||||||
|
vtkm::cont::ArrayCopyDevice(source, dest);
|
||||||
|
}
|
||||||
|
else if (destination.CanConvert<vtkm::cont::ArrayHandle<vtkm::FloatDefault>>())
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> dest;
|
||||||
|
destination.AsArrayHandle(dest);
|
||||||
|
vtkm::cont::ArrayCopyDevice(source, dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Initializing something that is probably not really an index. Rather than trace down every
|
||||||
|
// unlikely possibility, just copy to float and then to the final array.
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> dest;
|
||||||
|
vtkm::cont::ArrayCopyDevice(source, dest);
|
||||||
|
vtkm::cont::ArrayCopy(dest, destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ArrayHandleType>
|
||||||
|
bool TryArrayCopySpecialCase(const vtkm::cont::UnknownArrayHandle& source,
|
||||||
|
const vtkm::cont::UnknownArrayHandle& destination)
|
||||||
|
{
|
||||||
|
if (source.CanConvert<ArrayHandleType>())
|
||||||
|
{
|
||||||
|
ArrayCopySpecialCase(source.AsArrayHandle<ArrayHandleType>(), destination);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoUnknownArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
||||||
|
const vtkm::cont::UnknownArrayHandle& destination)
|
||||||
|
{
|
||||||
|
if (source.GetNumberOfValues() > 0)
|
||||||
|
{
|
||||||
|
// Try known special cases.
|
||||||
|
if (TryArrayCopySpecialCase<vtkm::cont::ArrayHandleIndex>(source, destination))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
source.CastAndCallWithExtractedArray(UnknownCopyFunctor1{}, destination);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
destination.ReleaseResources();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace cont
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
void ArrayCopyUnknown(const vtkm::cont::UnknownArrayHandle& source,
|
||||||
|
vtkm::cont::UnknownArrayHandle& destination)
|
||||||
|
{
|
||||||
|
if (!destination.IsValid())
|
||||||
|
{
|
||||||
|
destination = source.NewInstanceBasic();
|
||||||
|
}
|
||||||
|
|
||||||
|
DoUnknownArrayCopy(source, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayCopyUnknown(const vtkm::cont::UnknownArrayHandle& source,
|
||||||
|
const vtkm::cont::UnknownArrayHandle& destination)
|
||||||
|
{
|
||||||
|
if (!destination.IsValid())
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorBadValue(
|
||||||
|
"Attempty to copy to a constant UnknownArrayHandle with no valid array.");
|
||||||
|
}
|
||||||
|
|
||||||
|
DoUnknownArrayCopy(source, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vtkm::cont::internal
|
||||||
|
} // namespace vtkm::cont
|
||||||
|
} // namespace vtkm
|
@ -28,6 +28,7 @@ set(headers
|
|||||||
FunctorsGeneral.h
|
FunctorsGeneral.h
|
||||||
IteratorFromArrayPortal.h
|
IteratorFromArrayPortal.h
|
||||||
KXSort.h
|
KXSort.h
|
||||||
|
MapArrayPermutation.h
|
||||||
OptionParser.h
|
OptionParser.h
|
||||||
OptionParserArguments.h
|
OptionParserArguments.h
|
||||||
ParallelRadixSort.h
|
ParallelRadixSort.h
|
||||||
|
100
vtkm/cont/internal/MapArrayPermutation.cxx
Normal file
100
vtkm/cont/internal/MapArrayPermutation.cxx
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/internal/CastInvalidValue.h>
|
||||||
|
#include <vtkm/cont/internal/MapArrayPermutation.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/ErrorBadType.h>
|
||||||
|
|
||||||
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct MapPermutationWorklet : vtkm::worklet::WorkletMapField
|
||||||
|
{
|
||||||
|
T InvalidValue;
|
||||||
|
|
||||||
|
explicit MapPermutationWorklet(T invalidValue)
|
||||||
|
: InvalidValue(invalidValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
using ControlSignature = void(FieldIn permutationIndex, WholeArrayIn input, FieldOut output);
|
||||||
|
|
||||||
|
template <typename InputPortalType, typename OutputType>
|
||||||
|
VTKM_EXEC void operator()(vtkm::Id permutationIndex,
|
||||||
|
InputPortalType inputPortal,
|
||||||
|
OutputType& output) const
|
||||||
|
{
|
||||||
|
VTKM_STATIC_ASSERT(vtkm::HasVecTraits<OutputType>::value);
|
||||||
|
if ((permutationIndex >= 0) && (permutationIndex < inputPortal.GetNumberOfValues()))
|
||||||
|
{
|
||||||
|
output = inputPortal.Get(permutationIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output = this->InvalidValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DoMapFieldPermutation
|
||||||
|
{
|
||||||
|
template <typename InputArrayType, typename PermutationArrayType>
|
||||||
|
void operator()(const InputArrayType& input,
|
||||||
|
const PermutationArrayType& permutation,
|
||||||
|
vtkm::cont::UnknownArrayHandle& output,
|
||||||
|
vtkm::Float64 invalidValue) const
|
||||||
|
{
|
||||||
|
using BaseComponentType = typename InputArrayType::ValueType::ComponentType;
|
||||||
|
|
||||||
|
MapPermutationWorklet<BaseComponentType> worklet(
|
||||||
|
vtkm::cont::internal::CastInvalidValue<BaseComponentType>(invalidValue));
|
||||||
|
vtkm::cont::Invoker{}(
|
||||||
|
worklet,
|
||||||
|
permutation,
|
||||||
|
input,
|
||||||
|
output.ExtractArrayFromComponents<BaseComponentType>(vtkm::CopyFlag::Off));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace cont
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
vtkm::cont::UnknownArrayHandle MapArrayPermutation(
|
||||||
|
const vtkm::cont::UnknownArrayHandle& inputArray,
|
||||||
|
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.ExtractComponent<vtkm::Id>(0), outputArray, invalidValue);
|
||||||
|
return outputArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::cont::internal
|
51
vtkm/cont/internal/MapArrayPermutation.h
Normal file
51
vtkm/cont/internal/MapArrayPermutation.h
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.
|
||||||
|
//============================================================================
|
||||||
|
#ifndef vtk_m_cont_internal_MapArrayPermutation_h
|
||||||
|
#define vtk_m_cont_internal_MapArrayPermutation_h
|
||||||
|
|
||||||
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||||
|
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/vtkm_cont_export.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace cont
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Used to map a permutation like that found in an ArrayHandlePermutation.
|
||||||
|
///
|
||||||
|
VTKM_CONT_EXPORT vtkm::cont::UnknownArrayHandle MapArrayPermutation(
|
||||||
|
const vtkm::cont::UnknownArrayHandle& inputArray,
|
||||||
|
const vtkm::cont::UnknownArrayHandle& permutation,
|
||||||
|
vtkm::Float64 invalidValue = vtkm::Nan64());
|
||||||
|
|
||||||
|
/// Used to map a permutation array.
|
||||||
|
///
|
||||||
|
template <typename T, typename S>
|
||||||
|
vtkm::cont::UnknownArrayHandle MapArrayPermutation(
|
||||||
|
const vtkm::cont::ArrayHandle<T,
|
||||||
|
vtkm::cont::StorageTagPermutation<vtkm::cont::StorageTagBasic, S>>&
|
||||||
|
inputArray,
|
||||||
|
vtkm::Float64 invalidValue = vtkm::Nan64())
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandlePermutation<vtkm::cont::ArrayHandle<vtkm::Id>,
|
||||||
|
vtkm::cont::ArrayHandle<T, S>>
|
||||||
|
input = inputArray;
|
||||||
|
return MapArrayPermutation(input.GetValueArray(), input.GetIndexArray(), invalidValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::cont::internal
|
||||||
|
|
||||||
|
#endif //vtk_m_cont_internal_MapArrayPermutation_h
|
@ -426,7 +426,7 @@ private:
|
|||||||
SetPortal(basicArray.WritePortal());
|
SetPortal(basicArray.WritePortal());
|
||||||
|
|
||||||
vtkm::cont::ArrayHandleSOA<ValueType> soaArray;
|
vtkm::cont::ArrayHandleSOA<ValueType> soaArray;
|
||||||
vtkm::cont::ArrayCopy(basicArray, soaArray);
|
vtkm::cont::Invoker{}(PassThrough{}, basicArray, soaArray);
|
||||||
|
|
||||||
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
|
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
|
||||||
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
|
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
|
||||||
@ -1085,13 +1085,13 @@ private:
|
|||||||
VTKM_EXEC void operator()(const InputType& input, vtkm::Id workIndex, vtkm::Id& dummyOut) const
|
VTKM_EXEC void operator()(const InputType& input, vtkm::Id workIndex, vtkm::Id& dummyOut) const
|
||||||
{
|
{
|
||||||
using ComponentType = typename InputType::ComponentType;
|
using ComponentType = typename InputType::ComponentType;
|
||||||
vtkm::IdComponent expectedSize = static_cast<vtkm::IdComponent>(workIndex + 1);
|
vtkm::IdComponent expectedSize = static_cast<vtkm::IdComponent>(workIndex);
|
||||||
if (expectedSize != input.GetNumberOfComponents())
|
if (expectedSize != input.GetNumberOfComponents())
|
||||||
{
|
{
|
||||||
this->RaiseError("Got unexpected number of components.");
|
this->RaiseError("Got unexpected number of components.");
|
||||||
}
|
}
|
||||||
|
|
||||||
vtkm::Id valueIndex = workIndex * (workIndex + 1) / 2;
|
vtkm::Id valueIndex = workIndex * (workIndex - 1) / 2;
|
||||||
dummyOut = valueIndex;
|
dummyOut = valueIndex;
|
||||||
for (vtkm::IdComponent componentIndex = 0; componentIndex < expectedSize; componentIndex++)
|
for (vtkm::IdComponent componentIndex = 0; componentIndex < expectedSize; componentIndex++)
|
||||||
{
|
{
|
||||||
@ -1113,8 +1113,7 @@ private:
|
|||||||
vtkm::Id sourceArraySize;
|
vtkm::Id sourceArraySize;
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> numComponentsArray;
|
vtkm::cont::ArrayHandle<vtkm::Id> numComponentsArray;
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleCounting<vtkm::IdComponent>(1, 1, ARRAY_SIZE),
|
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(ARRAY_SIZE), numComponentsArray);
|
||||||
numComponentsArray);
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray =
|
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray =
|
||||||
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, sourceArraySize);
|
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, sourceArraySize);
|
||||||
|
|
||||||
@ -1147,13 +1146,13 @@ private:
|
|||||||
VTKM_EXEC void operator()(OutputType& output, vtkm::Id workIndex) const
|
VTKM_EXEC void operator()(OutputType& output, vtkm::Id workIndex) const
|
||||||
{
|
{
|
||||||
using ComponentType = typename OutputType::ComponentType;
|
using ComponentType = typename OutputType::ComponentType;
|
||||||
vtkm::IdComponent expectedSize = static_cast<vtkm::IdComponent>(workIndex + 1);
|
vtkm::IdComponent expectedSize = static_cast<vtkm::IdComponent>(workIndex);
|
||||||
if (expectedSize != output.GetNumberOfComponents())
|
if (expectedSize != output.GetNumberOfComponents())
|
||||||
{
|
{
|
||||||
this->RaiseError("Got unexpected number of components.");
|
this->RaiseError("Got unexpected number of components.");
|
||||||
}
|
}
|
||||||
|
|
||||||
vtkm::Id valueIndex = workIndex * (workIndex + 1) / 2;
|
vtkm::Id valueIndex = workIndex * (workIndex - 1) / 2;
|
||||||
for (vtkm::IdComponent componentIndex = 0; componentIndex < expectedSize; componentIndex++)
|
for (vtkm::IdComponent componentIndex = 0; componentIndex < expectedSize; componentIndex++)
|
||||||
{
|
{
|
||||||
output[componentIndex] = TestValue(valueIndex, ComponentType());
|
output[componentIndex] = TestValue(valueIndex, ComponentType());
|
||||||
@ -1170,8 +1169,7 @@ private:
|
|||||||
vtkm::Id sourceArraySize;
|
vtkm::Id sourceArraySize;
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> numComponentsArray;
|
vtkm::cont::ArrayHandle<vtkm::Id> numComponentsArray;
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleCounting<vtkm::IdComponent>(1, 1, ARRAY_SIZE),
|
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(ARRAY_SIZE), numComponentsArray);
|
||||||
numComponentsArray);
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray = vtkm::cont::ConvertNumComponentsToOffsets(
|
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray = vtkm::cont::ConvertNumComponentsToOffsets(
|
||||||
numComponentsArray, sourceArraySize, DeviceAdapterTag());
|
numComponentsArray, sourceArraySize, DeviceAdapterTag());
|
||||||
|
|
||||||
@ -1364,6 +1362,15 @@ private:
|
|||||||
|
|
||||||
//verify that the control portal works
|
//verify that the control portal works
|
||||||
CheckPortal(view.ReadPortal());
|
CheckPortal(view.ReadPortal());
|
||||||
|
|
||||||
|
//verify that filling works
|
||||||
|
const ValueType expected = TestValue(20, ValueType{});
|
||||||
|
view.Fill(expected);
|
||||||
|
auto valuesPortal = values.ReadPortal();
|
||||||
|
for (vtkm::Id index = length; index < 2 * length; ++index)
|
||||||
|
{
|
||||||
|
VTKM_TEST_ASSERT(valuesPortal.Get(index) == expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,12 +9,18 @@
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
||||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||||
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleView.h>
|
||||||
#include <vtkm/cont/UncertainArrayHandle.h>
|
#include <vtkm/cont/UncertainArrayHandle.h>
|
||||||
#include <vtkm/cont/UnknownArrayHandle.h>
|
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||||
|
|
||||||
#include <vtkm/TypeTraits.h>
|
#include <vtkm/TypeTraits.h>
|
||||||
|
#include <vtkm/VecTraits.h>
|
||||||
|
|
||||||
#include <vtkm/cont/testing/Testing.h>
|
#include <vtkm/cont/testing/Testing.h>
|
||||||
|
|
||||||
@ -23,13 +29,43 @@ namespace
|
|||||||
|
|
||||||
static constexpr vtkm::Id ARRAY_SIZE = 10;
|
static constexpr vtkm::Id ARRAY_SIZE = 10;
|
||||||
|
|
||||||
template <typename RefArrayType, typename TestArrayType>
|
vtkm::cont::UnknownArrayHandle MakeComparable(const vtkm::cont::UnknownArrayHandle& array,
|
||||||
void TestValues(const RefArrayType& refArray, const TestArrayType& testArray)
|
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);
|
auto result = test_equal_ArrayHandles(refArray, testArray);
|
||||||
VTKM_TEST_ASSERT(result, result.GetMergedMessage());
|
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>
|
template <typename ValueType>
|
||||||
vtkm::cont::ArrayHandle<ValueType> MakeInputArray()
|
vtkm::cont::ArrayHandle<ValueType> MakeInputArray()
|
||||||
{
|
{
|
||||||
@ -44,18 +80,20 @@ void TryCopy()
|
|||||||
{
|
{
|
||||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||||
"Trying type: " << vtkm::testing::TypeName<ValueType>::Name());
|
"Trying type: " << vtkm::testing::TypeName<ValueType>::Name());
|
||||||
|
using VTraits = vtkm::VecTraits<ValueType>;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::cout << "implicit -> basic" << std::endl;
|
std::cout << "implicit -> basic" << std::endl;
|
||||||
vtkm::cont::ArrayHandleIndex input(ARRAY_SIZE);
|
vtkm::cont::ArrayHandleIndex input(ARRAY_SIZE);
|
||||||
vtkm::cont::ArrayHandle<ValueType> output;
|
vtkm::cont::ArrayHandle<typename VTraits::BaseComponentType> output;
|
||||||
vtkm::cont::ArrayCopy(input, output);
|
vtkm::cont::ArrayCopy(input, output);
|
||||||
TestValues(input, output);
|
TestValues(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::cout << "basic -> basic" << std::endl;
|
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::ArrayHandle<ValueType> output;
|
||||||
vtkm::cont::ArrayCopy(input, output);
|
vtkm::cont::ArrayCopy(input, output);
|
||||||
TestValues(input, output);
|
TestValues(input, output);
|
||||||
@ -90,30 +128,72 @@ void TryCopy()
|
|||||||
TestValues(input, output);
|
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;
|
std::cout << "constant -> basic" << std::endl;
|
||||||
UnknownArray input = MakeInputArray<ValueType>();
|
vtkm::cont::ArrayHandleConstant<ValueType> input(TestValue(2, ValueType{}), ARRAY_SIZE);
|
||||||
UnknownArray output;
|
|
||||||
vtkm::cont::ArrayCopy(input, output);
|
|
||||||
TestValues(input, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::cout << "uncertain -> basic (same type)" << std::endl;
|
|
||||||
UncertainArray input = MakeInputArray<ValueType>();
|
|
||||||
vtkm::cont::ArrayHandle<ValueType> output;
|
vtkm::cont::ArrayHandle<ValueType> output;
|
||||||
vtkm::cont::ArrayCopy(input, output);
|
vtkm::cont::ArrayCopy(input, output);
|
||||||
TestValues(input, output);
|
TestValues(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::cout << "uncertain -> basic (different type)" << std::endl;
|
std::cout << "counting -> basic" << std::endl;
|
||||||
UncertainArray input = MakeInputArray<vtkm::UInt8>();
|
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 << "view -> basic" << std::endl;
|
||||||
|
vtkm::cont::ArrayHandle<ValueType> input = MakeInputArray<ValueType>();
|
||||||
|
auto viewInput = vtkm::cont::make_ArrayHandleView(input, 1, ARRAY_SIZE / 2);
|
||||||
|
vtkm::cont::ArrayHandle<ValueType> output;
|
||||||
|
vtkm::cont::ArrayCopy(input, output);
|
||||||
|
TestValues(input, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::cout << "concatinate -> basic" << std::endl;
|
||||||
|
vtkm::cont::ArrayHandle<ValueType> input1 = MakeInputArray<ValueType>();
|
||||||
|
vtkm::cont::ArrayHandleConstant<ValueType> input2(TestValue(6, ValueType{}), ARRAY_SIZE / 2);
|
||||||
|
auto concatInput = vtkm::cont::make_ArrayHandleConcatenate(input1, input2);
|
||||||
|
vtkm::cont::ArrayHandle<ValueType> output;
|
||||||
|
vtkm::cont::ArrayCopy(concatInput, output);
|
||||||
|
TestValues(concatInput, 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::ArrayHandle<ValueType> output;
|
||||||
vtkm::cont::ArrayCopy(input, output);
|
vtkm::cont::ArrayCopy(input, output);
|
||||||
TestValues(input, output);
|
TestValues(input, output);
|
||||||
@ -139,7 +219,8 @@ void TryCopy()
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::cout << "unknown.DeepCopyFrom(different type)" << std::endl;
|
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::ArrayHandle<ValueType> outputArray;
|
||||||
vtkm::cont::UnknownArrayHandle(outputArray).DeepCopyFrom(input);
|
vtkm::cont::UnknownArrayHandle(outputArray).DeepCopyFrom(input);
|
||||||
TestValues(input, outputArray);
|
TestValues(input, outputArray);
|
||||||
@ -166,7 +247,8 @@ void TryCopy()
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::cout << "unknown.CopyShallowIfPossible(different type)" << std::endl;
|
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::ArrayHandle<ValueType> outputArray;
|
||||||
vtkm::cont::UnknownArrayHandle(outputArray).CopyShallowIfPossible(input);
|
vtkm::cont::UnknownArrayHandle(outputArray).CopyShallowIfPossible(input);
|
||||||
TestValues(input, outputArray);
|
TestValues(input, outputArray);
|
||||||
@ -203,6 +285,8 @@ void TestArrayCopy()
|
|||||||
TryCopy<vtkm::Id>();
|
TryCopy<vtkm::Id>();
|
||||||
TryCopy<vtkm::IdComponent>();
|
TryCopy<vtkm::IdComponent>();
|
||||||
TryCopy<vtkm::Float32>();
|
TryCopy<vtkm::Float32>();
|
||||||
|
TryCopy<vtkm::Vec3f>();
|
||||||
|
TryCopy<vtkm::Vec4i_16>();
|
||||||
TryArrayCopyShallowIfPossible();
|
TryArrayCopyShallowIfPossible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <vtkm/cont/Algorithm.h>
|
#include <vtkm/cont/Algorithm.h>
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||||
@ -331,8 +332,8 @@ struct DecoratorTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy a constant array into the decorator. This should modify ah3Copy.
|
// Copy a constant array into the decorator. This should modify ah3Copy.
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant(ValueType{ 25 }, ARRAY_SIZE),
|
vtkm::cont::ArrayCopyDevice(vtkm::cont::make_ArrayHandleConstant(ValueType{ 25 }, ARRAY_SIZE),
|
||||||
ahDecor);
|
ahDecor);
|
||||||
|
|
||||||
{ // Accessing portal should give all 25s:
|
{ // Accessing portal should give all 25s:
|
||||||
auto portalDecor = ahDecor.ReadPortal();
|
auto portalDecor = ahDecor.ReadPortal();
|
||||||
@ -390,7 +391,7 @@ struct DecoratorTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<ValueType> copiedInExec;
|
vtkm::cont::ArrayHandle<ValueType> copiedInExec;
|
||||||
vtkm::cont::ArrayCopy(decorArray, copiedInExec);
|
vtkm::cont::ArrayCopyDevice(decorArray, copiedInExec);
|
||||||
{
|
{
|
||||||
auto copiedPortal = copiedInExec.ReadPortal();
|
auto copiedPortal = copiedInExec.ReadPortal();
|
||||||
auto countPortal = ahCount.ReadPortal();
|
auto countPortal = ahCount.ReadPortal();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// PURPOSE. See the above copyright notice for more information.
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/ArrayHandleBasic.h>
|
#include <vtkm/cont/ArrayHandleBasic.h>
|
||||||
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||||
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
||||||
@ -84,13 +84,13 @@ void FillArray(vtkm::cont::ArrayHandle<T, S>& array)
|
|||||||
using Traits = vtkm::VecTraits<T>;
|
using Traits = vtkm::VecTraits<T>;
|
||||||
vtkm::IdComponent numComponents = Traits::NUM_COMPONENTS;
|
vtkm::IdComponent numComponents = Traits::NUM_COMPONENTS;
|
||||||
|
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant(T{}, ARRAY_SIZE), array);
|
array.AllocateAndFill(ARRAY_SIZE, vtkm::TypeTraits<T>::ZeroInitialization());
|
||||||
|
|
||||||
for (vtkm::IdComponent component = 0; component < numComponents; ++component)
|
for (vtkm::IdComponent component = 0; component < numComponents; ++component)
|
||||||
{
|
{
|
||||||
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float64> randomArray(ARRAY_SIZE);
|
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float64> randomArray(ARRAY_SIZE);
|
||||||
auto dest = vtkm::cont::make_ArrayHandleExtractComponent(array, component);
|
auto dest = vtkm::cont::make_ArrayHandleExtractComponent(array, component);
|
||||||
vtkm::cont::ArrayCopy(randomArray, dest);
|
vtkm::cont::ArrayCopyDevice(randomArray, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
// PURPOSE. See the above copyright notice for more information.
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||||
@ -143,16 +143,13 @@ auto PermutationArray = vtkm::cont::ArrayHandleCounting<vtkm::Id>(0, 2, BaseLine
|
|||||||
vtkm::cont::CellSetExplicit<> MakeCellSetExplicit()
|
vtkm::cont::CellSetExplicit<> MakeCellSetExplicit()
|
||||||
{
|
{
|
||||||
vtkm::cont::ArrayHandle<vtkm::UInt8> shapes;
|
vtkm::cont::ArrayHandle<vtkm::UInt8> shapes;
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleConstant<vtkm::UInt8>{ vtkm::CELL_SHAPE_HEXAHEDRON,
|
shapes.AllocateAndFill(BaseLineNumberOfCells, vtkm::CELL_SHAPE_HEXAHEDRON);
|
||||||
BaseLineNumberOfCells },
|
|
||||||
shapes);
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
|
||||||
vtkm::cont::ArrayCopy(
|
numIndices.AllocateAndFill(BaseLineNumberOfCells, 8);
|
||||||
vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>{ 8, BaseLineNumberOfCells }, numIndices);
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||||
vtkm::cont::ArrayCopy(BaseLineConnectivity, connectivity);
|
vtkm::cont::ArrayCopyDevice(BaseLineConnectivity, connectivity);
|
||||||
|
|
||||||
auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numIndices);
|
auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numIndices);
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ vtkm_add_instantiations(ClipWithImplicitFunctionInstantiations
|
|||||||
set(deprecated_headers
|
set(deprecated_headers
|
||||||
CellSetConnectivity.h
|
CellSetConnectivity.h
|
||||||
CleanGrid.h
|
CleanGrid.h
|
||||||
|
CrossProduct.h
|
||||||
DotProduct.h
|
DotProduct.h
|
||||||
Entropy.h
|
Entropy.h
|
||||||
ExternalFaces.h
|
ExternalFaces.h
|
||||||
@ -88,7 +89,6 @@ set(extra_headers
|
|||||||
ComputeMoments.h
|
ComputeMoments.h
|
||||||
CoordinateSystemTransform.h
|
CoordinateSystemTransform.h
|
||||||
CreateResult.h
|
CreateResult.h
|
||||||
CrossProduct.h
|
|
||||||
FieldSelection.h
|
FieldSelection.h
|
||||||
FieldToColors.h
|
FieldToColors.h
|
||||||
GhostCellClassify.h
|
GhostCellClassify.h
|
||||||
@ -133,7 +133,6 @@ set(extra_header_template_sources
|
|||||||
ClipWithImplicitFunctionExternInstantiations.h
|
ClipWithImplicitFunctionExternInstantiations.h
|
||||||
ComputeMoments.hxx
|
ComputeMoments.hxx
|
||||||
CoordinateSystemTransform.hxx
|
CoordinateSystemTransform.hxx
|
||||||
CrossProduct.hxx
|
|
||||||
FieldToColors.hxx
|
FieldToColors.hxx
|
||||||
GhostCellClassify.hxx
|
GhostCellClassify.hxx
|
||||||
ImageDifference.hxx
|
ImageDifference.hxx
|
||||||
|
@ -11,133 +11,31 @@
|
|||||||
#ifndef vtk_m_filter_CrossProduct_h
|
#ifndef vtk_m_filter_CrossProduct_h
|
||||||
#define vtk_m_filter_CrossProduct_h
|
#define vtk_m_filter_CrossProduct_h
|
||||||
|
|
||||||
#include <vtkm/filter/FilterField.h>
|
#include <vtkm/Deprecated.h>
|
||||||
#include <vtkm/worklet/CrossProduct.h>
|
#include <vtkm/filter/vector_calculus/CrossProduct.h>
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
namespace filter
|
namespace filter
|
||||||
{
|
{
|
||||||
|
|
||||||
class CrossProduct : public vtkm::filter::FilterField<CrossProduct>
|
VTKM_DEPRECATED(
|
||||||
|
1.8,
|
||||||
|
"Use vtkm/filter/vector_calculus/CrossProduct.h instead of vtkm/filter/CrossProduct.h.")
|
||||||
|
inline void CrossProduct_deprecated() {}
|
||||||
|
|
||||||
|
inline void CrossProduct_deprecated_warning()
|
||||||
{
|
{
|
||||||
public:
|
CrossProduct_deprecated();
|
||||||
//CrossProduct filter only works on vec3 data.
|
}
|
||||||
using SupportedTypes = vtkm::TypeListFieldVec3;
|
|
||||||
|
|
||||||
VTKM_CONT
|
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::vector_calculus::CrossProduct.") CrossProduct
|
||||||
CrossProduct();
|
: public vtkm::filter::vector_calculus::CrossProduct
|
||||||
|
{
|
||||||
//@{
|
using vector_calculus::CrossProduct::CrossProduct;
|
||||||
/// Choose the primary field to operate on. In the cross product operation A x B, A is
|
|
||||||
/// the primary field.
|
|
||||||
VTKM_CONT
|
|
||||||
void SetPrimaryField(
|
|
||||||
const std::string& name,
|
|
||||||
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::ANY)
|
|
||||||
{
|
|
||||||
this->SetActiveField(name, association);
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT const std::string& GetPrimaryFieldName() const { return this->GetActiveFieldName(); }
|
|
||||||
VTKM_CONT vtkm::cont::Field::Association GetPrimaryFieldAssociation() const
|
|
||||||
{
|
|
||||||
return this->GetActiveFieldAssociation();
|
|
||||||
}
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//@{
|
|
||||||
/// When set to true, uses a coordinate system as the primary field instead of the one selected
|
|
||||||
/// by name. Use SetPrimaryCoordinateSystem to select which coordinate system.
|
|
||||||
VTKM_CONT
|
|
||||||
void SetUseCoordinateSystemAsPrimaryField(bool flag)
|
|
||||||
{
|
|
||||||
this->SetUseCoordinateSystemAsField(flag);
|
|
||||||
}
|
|
||||||
VTKM_CONT
|
|
||||||
bool GetUseCoordinateSystemAsPrimaryField() const
|
|
||||||
{
|
|
||||||
return this->GetUseCoordinateSystemAsField();
|
|
||||||
}
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//@{
|
|
||||||
/// Select the coordinate system index to use as the primary field. This only has an effect when
|
|
||||||
/// UseCoordinateSystemAsPrimaryField is true.
|
|
||||||
VTKM_CONT
|
|
||||||
void SetPrimaryCoordinateSystem(vtkm::Id index) { this->SetActiveCoordinateSystem(index); }
|
|
||||||
VTKM_CONT
|
|
||||||
vtkm::Id GetPrimaryCoordinateSystemIndex() const
|
|
||||||
{
|
|
||||||
return this->GetActiveCoordinateSystemIndex();
|
|
||||||
}
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//@{
|
|
||||||
/// Choose the secondary field to operate on. In the cross product operation A x B, B is
|
|
||||||
/// the secondary field.
|
|
||||||
VTKM_CONT
|
|
||||||
void SetSecondaryField(
|
|
||||||
const std::string& name,
|
|
||||||
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::ANY)
|
|
||||||
{
|
|
||||||
this->SecondaryFieldName = name;
|
|
||||||
this->SecondaryFieldAssociation = association;
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT const std::string& GetSecondaryFieldName() const { return this->SecondaryFieldName; }
|
|
||||||
VTKM_CONT vtkm::cont::Field::Association GetSecondaryFieldAssociation() const
|
|
||||||
{
|
|
||||||
return this->SecondaryFieldAssociation;
|
|
||||||
}
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//@{
|
|
||||||
/// When set to true, uses a coordinate system as the primary field instead of the one selected
|
|
||||||
/// by name. Use SetPrimaryCoordinateSystem to select which coordinate system.
|
|
||||||
VTKM_CONT
|
|
||||||
void SetUseCoordinateSystemAsSecondaryField(bool flag)
|
|
||||||
{
|
|
||||||
this->UseCoordinateSystemAsSecondaryField = flag;
|
|
||||||
}
|
|
||||||
VTKM_CONT
|
|
||||||
bool GetUseCoordinateSystemAsSecondaryField() const
|
|
||||||
{
|
|
||||||
return this->UseCoordinateSystemAsSecondaryField;
|
|
||||||
}
|
|
||||||
//@}
|
|
||||||
|
|
||||||
//@{
|
|
||||||
/// Select the coordinate system index to use as the primary field. This only has an effect when
|
|
||||||
/// UseCoordinateSystemAsPrimaryField is true.
|
|
||||||
VTKM_CONT
|
|
||||||
void SetSecondaryCoordinateSystem(vtkm::Id index)
|
|
||||||
{
|
|
||||||
this->SecondaryCoordinateSystemIndex = index;
|
|
||||||
}
|
|
||||||
VTKM_CONT
|
|
||||||
vtkm::Id GetSecondaryCoordinateSystemIndex() const
|
|
||||||
{
|
|
||||||
return this->SecondaryCoordinateSystemIndex;
|
|
||||||
}
|
|
||||||
//@}
|
|
||||||
|
|
||||||
template <typename T, typename StorageType, typename DerivedPolicy>
|
|
||||||
VTKM_CONT vtkm::cont::DataSet DoExecute(
|
|
||||||
const vtkm::cont::DataSet& input,
|
|
||||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& field,
|
|
||||||
const vtkm::filter::FieldMetadata& fieldMeta,
|
|
||||||
vtkm::filter::PolicyBase<DerivedPolicy> policy);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string SecondaryFieldName;
|
|
||||||
vtkm::cont::Field::Association SecondaryFieldAssociation;
|
|
||||||
bool UseCoordinateSystemAsSecondaryField;
|
|
||||||
vtkm::Id SecondaryCoordinateSystemIndex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
} // namespace vtkm::filter
|
} // namespace vtkm::filter
|
||||||
|
|
||||||
#include <vtkm/filter/CrossProduct.hxx>
|
|
||||||
|
|
||||||
#endif // vtk_m_filter_CrossProduct_h
|
#endif // vtk_m_filter_CrossProduct_h
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
// 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.
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#ifndef vtk_m_filter_CrossProduct_hxx
|
|
||||||
#define vtk_m_filter_CrossProduct_hxx
|
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayHandleCast.h>
|
|
||||||
|
|
||||||
#include <vtkm/worklet/DispatcherMapField.h>
|
|
||||||
|
|
||||||
namespace vtkm
|
|
||||||
{
|
|
||||||
namespace filter
|
|
||||||
{
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
inline VTKM_CONT CrossProduct::CrossProduct()
|
|
||||||
: vtkm::filter::FilterField<CrossProduct>()
|
|
||||||
, SecondaryFieldName()
|
|
||||||
, SecondaryFieldAssociation(vtkm::cont::Field::Association::ANY)
|
|
||||||
, UseCoordinateSystemAsSecondaryField(false)
|
|
||||||
, SecondaryCoordinateSystemIndex(0)
|
|
||||||
{
|
|
||||||
this->SetOutputFieldName("crossproduct");
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T, typename StorageType, typename DerivedPolicy>
|
|
||||||
inline VTKM_CONT vtkm::cont::DataSet CrossProduct::DoExecute(
|
|
||||||
const vtkm::cont::DataSet& inDataSet,
|
|
||||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& primary,
|
|
||||||
const vtkm::filter::FieldMetadata& fieldMetadata,
|
|
||||||
vtkm::filter::PolicyBase<DerivedPolicy> policy)
|
|
||||||
{
|
|
||||||
vtkm::cont::Field secondaryField;
|
|
||||||
if (this->UseCoordinateSystemAsSecondaryField)
|
|
||||||
{
|
|
||||||
secondaryField = inDataSet.GetCoordinateSystem(this->GetSecondaryCoordinateSystemIndex());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
secondaryField = inDataSet.GetField(this->SecondaryFieldName, this->SecondaryFieldAssociation);
|
|
||||||
}
|
|
||||||
auto secondary =
|
|
||||||
vtkm::filter::ApplyPolicyFieldOfType<vtkm::Vec<T, 3>>(secondaryField, policy, *this);
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>> output;
|
|
||||||
this->Invoke(vtkm::worklet::CrossProduct{}, primary, secondary, output);
|
|
||||||
|
|
||||||
return CreateResult(inDataSet, output, this->GetOutputFieldName(), fieldMetadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace vtkm::filter
|
|
||||||
|
|
||||||
#endif
|
|
@ -8,65 +8,11 @@
|
|||||||
// PURPOSE. See the above copyright notice for more information.
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <vtkm/VecTraits.h>
|
|
||||||
#include <vtkm/cont/Logging.h>
|
#include <vtkm/cont/Logging.h>
|
||||||
#include <vtkm/cont/internal/CastInvalidValue.h>
|
|
||||||
|
#include <vtkm/cont/internal/MapArrayPermutation.h>
|
||||||
|
|
||||||
#include <vtkm/filter/MapFieldPermutation.h>
|
#include <vtkm/filter/MapFieldPermutation.h>
|
||||||
#include <vtkm/worklet/WorkletMapField.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct MapPermutationWorklet : vtkm::worklet::WorkletMapField
|
|
||||||
{
|
|
||||||
T InvalidValue;
|
|
||||||
|
|
||||||
explicit MapPermutationWorklet(T invalidValue)
|
|
||||||
: InvalidValue(invalidValue)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
using ControlSignature = void(FieldIn permutationIndex, WholeArrayIn input, FieldOut output);
|
|
||||||
|
|
||||||
template <typename InputPortalType, typename OutputType>
|
|
||||||
VTKM_EXEC void operator()(vtkm::Id permutationIndex,
|
|
||||||
InputPortalType inputPortal,
|
|
||||||
OutputType& output) const
|
|
||||||
{
|
|
||||||
VTKM_STATIC_ASSERT(vtkm::HasVecTraits<OutputType>::value);
|
|
||||||
if ((permutationIndex >= 0) && (permutationIndex < inputPortal.GetNumberOfValues()))
|
|
||||||
{
|
|
||||||
output = inputPortal.Get(permutationIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
output = this->InvalidValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DoMapFieldPermutation
|
|
||||||
{
|
|
||||||
template <typename InputArrayType>
|
|
||||||
void operator()(const InputArrayType& input,
|
|
||||||
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
|
|
||||||
vtkm::cont::UnknownArrayHandle& output,
|
|
||||||
vtkm::Float64 invalidValue) const
|
|
||||||
{
|
|
||||||
using BaseComponentType = typename InputArrayType::ValueType::ComponentType;
|
|
||||||
|
|
||||||
MapPermutationWorklet<BaseComponentType> worklet(
|
|
||||||
vtkm::cont::internal::CastInvalidValue<BaseComponentType>(invalidValue));
|
|
||||||
vtkm::cont::Invoker{}(
|
|
||||||
worklet,
|
|
||||||
permutation,
|
|
||||||
input,
|
|
||||||
output.ExtractArrayFromComponents<BaseComponentType>(vtkm::CopyFlag::Off));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
VTKM_FILTER_CORE_EXPORT VTKM_CONT bool vtkm::filter::MapFieldPermutation(
|
VTKM_FILTER_CORE_EXPORT VTKM_CONT bool vtkm::filter::MapFieldPermutation(
|
||||||
const vtkm::cont::Field& inputField,
|
const vtkm::cont::Field& inputField,
|
||||||
@ -76,12 +22,10 @@ VTKM_FILTER_CORE_EXPORT VTKM_CONT bool vtkm::filter::MapFieldPermutation(
|
|||||||
{
|
{
|
||||||
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
|
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
|
||||||
|
|
||||||
vtkm::cont::UnknownArrayHandle outputArray = inputField.GetData().NewInstanceBasic();
|
|
||||||
outputArray.Allocate(permutation.GetNumberOfValues());
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
inputField.GetData().CastAndCallWithExtractedArray(
|
vtkm::cont::UnknownArrayHandle outputArray =
|
||||||
DoMapFieldPermutation{}, permutation, outputArray, invalidValue);
|
vtkm::cont::internal::MapArrayPermutation(inputField.GetData(), permutation, invalidValue);
|
||||||
outputField = vtkm::cont::Field(inputField.GetName(), inputField.GetAssociation(), outputArray);
|
outputField = vtkm::cont::Field(inputField.GetName(), inputField.GetAssociation(), outputArray);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,54 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Functor, typename... Args>
|
||||||
|
VTKM_CONT void CastAndCallScalarField(const vtkm::cont::UnknownArrayHandle& fieldArray,
|
||||||
|
Functor&& functor,
|
||||||
|
Args&&... args) const
|
||||||
|
{
|
||||||
|
fieldArray
|
||||||
|
.CastAndCallForTypesWithFloatFallback<vtkm::TypeListFieldScalar, VTKM_DEFAULT_STORAGE_LIST>(
|
||||||
|
std::forward<Functor>(functor), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Functor, typename... Args>
|
||||||
|
VTKM_CONT void CastAndCallScalarField(const vtkm::cont::Field& field,
|
||||||
|
Functor&& functor,
|
||||||
|
Args&&... args) const
|
||||||
|
{
|
||||||
|
this->CastAndCallScalarField(
|
||||||
|
field.GetData(), std::forward<Functor>(functor), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <vtkm::IdComponent VecSize>
|
||||||
|
struct ScalarToVec
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
using type = vtkm::Vec<T, VecSize>;
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
template <vtkm::IdComponent VecSize, typename Functor, typename... Args>
|
||||||
|
VTKM_CONT void CastAndCallVecField(const vtkm::cont::UnknownArrayHandle& fieldArray,
|
||||||
|
Functor&& functor,
|
||||||
|
Args&&... args) const
|
||||||
|
{
|
||||||
|
using VecList =
|
||||||
|
vtkm::ListTransform<vtkm::TypeListFieldScalar, ScalarToVec<VecSize>::template type>;
|
||||||
|
fieldArray.CastAndCallForTypesWithFloatFallback<VecList, VTKM_DEFAULT_STORAGE_LIST>(
|
||||||
|
std::forward<Functor>(functor), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <vtkm::IdComponent VecSize, typename Functor, typename... Args>
|
||||||
|
VTKM_CONT void CastAndCallVecField(const vtkm::cont::Field& field,
|
||||||
|
Functor&& functor,
|
||||||
|
Args&&... args) const
|
||||||
|
{
|
||||||
|
this->CastAndCallVecField<VecSize>(
|
||||||
|
field.GetData(), std::forward<Functor>(functor), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ResizeIfNeeded(size_t index_st);
|
void ResizeIfNeeded(size_t index_st);
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#ifndef vtk_m_worklet_RemoveUnusedPoints_h
|
#ifndef vtk_m_worklet_RemoveUnusedPoints_h
|
||||||
#define vtk_m_worklet_RemoveUnusedPoints_h
|
#define vtk_m_worklet_RemoveUnusedPoints_h
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||||
@ -102,9 +102,7 @@ public:
|
|||||||
if (this->MaskArray.GetNumberOfValues() < 1)
|
if (this->MaskArray.GetNumberOfValues() < 1)
|
||||||
{
|
{
|
||||||
// Initialize mask array to 0.
|
// Initialize mask array to 0.
|
||||||
vtkm::cont::ArrayCopy(
|
this->MaskArray.AllocateAndFill(inCellSet.GetNumberOfPoints(), 0);
|
||||||
vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>(0, inCellSet.GetNumberOfPoints()),
|
|
||||||
this->MaskArray);
|
|
||||||
}
|
}
|
||||||
VTKM_ASSERT(this->MaskArray.GetNumberOfValues() == inCellSet.GetNumberOfPoints());
|
VTKM_ASSERT(this->MaskArray.GetNumberOfValues() == inCellSet.GetNumberOfPoints());
|
||||||
|
|
||||||
@ -257,7 +255,7 @@ public:
|
|||||||
VTKM_CONT void MapPointFieldDeep(const vtkm::cont::ArrayHandle<InT, InS>& inArray,
|
VTKM_CONT void MapPointFieldDeep(const vtkm::cont::ArrayHandle<InT, InS>& inArray,
|
||||||
vtkm::cont::ArrayHandle<OutT, OutS>& outArray) const
|
vtkm::cont::ArrayHandle<OutT, OutS>& outArray) const
|
||||||
{
|
{
|
||||||
vtkm::cont::ArrayCopy(this->MapPointFieldShallow(inArray), outArray);
|
vtkm::cont::ArrayCopyDevice(this->MapPointFieldShallow(inArray), outArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#ifndef vtk_m_worklet_connectivity_InnerJoin_h
|
#ifndef vtk_m_worklet_connectivity_InnerJoin_h
|
||||||
#define vtk_m_worklet_connectivity_InnerJoin_h
|
#define vtk_m_worklet_connectivity_InnerJoin_h
|
||||||
|
|
||||||
|
#include <vtkm/cont/Algorithm.h>
|
||||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||||
#include <vtkm/worklet/DispatcherMapField.h>
|
#include <vtkm/worklet/DispatcherMapField.h>
|
||||||
#include <vtkm/worklet/ScatterCounting.h>
|
#include <vtkm/worklet/ScatterCounting.h>
|
||||||
|
@ -23,6 +23,6 @@ set(libraries
|
|||||||
vtkm_unit_tests(
|
vtkm_unit_tests(
|
||||||
SOURCES ${unit_tests}
|
SOURCES ${unit_tests}
|
||||||
LIBRARIES ${libraries}
|
LIBRARIES ${libraries}
|
||||||
ALL_BACKENDS # use ArrayCopy
|
ALL_BACKENDS # UnitTestParticleDensity.cxx uses DescriptiveStatistcs worklet
|
||||||
USE_VTKM_JOB_POOL
|
USE_VTKM_JOB_POOL
|
||||||
)
|
)
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
// PURPOSE. See the above copyright notice for more information.
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/ArrayHandleRandomUniformReal.h>
|
#include <vtkm/cont/ArrayHandleRandomUniformReal.h>
|
||||||
#include <vtkm/cont/DataSetBuilderExplicit.h>
|
#include <vtkm/cont/DataSetBuilderExplicit.h>
|
||||||
#include <vtkm/cont/testing/Testing.h>
|
#include <vtkm/cont/testing/Testing.h>
|
||||||
@ -27,7 +29,7 @@ void TestNGP()
|
|||||||
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xdeed),
|
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xdeed),
|
||||||
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xabba));
|
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xabba));
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> positions;
|
vtkm::cont::ArrayHandle<vtkm::Vec3f> positions;
|
||||||
vtkm::cont::ArrayCopy(composite, positions);
|
vtkm::cont::ArrayCopyDevice(composite, positions);
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleIndex(N), connectivity);
|
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleIndex(N), connectivity);
|
||||||
@ -36,8 +38,8 @@ void TestNGP()
|
|||||||
positions, vtkm::CellShapeTagVertex{}, 1, connectivity);
|
positions, vtkm::CellShapeTagVertex{}, 1, connectivity);
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> mass;
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> mass;
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleRandomUniformReal<vtkm::FloatDefault>(N, 0xd1ce),
|
vtkm::cont::ArrayCopyDevice(
|
||||||
mass);
|
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::FloatDefault>(N, 0xd1ce), mass);
|
||||||
dataSet.AddCellField("mass", mass);
|
dataSet.AddCellField("mass", mass);
|
||||||
|
|
||||||
auto cellDims = vtkm::Id3{ 3, 3, 3 };
|
auto cellDims = vtkm::Id3{ 3, 3, 3 };
|
||||||
@ -78,7 +80,7 @@ void TestCIC()
|
|||||||
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xdeed),
|
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xdeed),
|
||||||
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xabba));
|
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xabba));
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> positions;
|
vtkm::cont::ArrayHandle<vtkm::Vec3f> positions;
|
||||||
vtkm::cont::ArrayCopy(composite, positions);
|
vtkm::cont::ArrayCopyDevice(composite, positions);
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleIndex(N), connectivity);
|
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleIndex(N), connectivity);
|
||||||
@ -87,7 +89,8 @@ void TestCIC()
|
|||||||
positions, vtkm::CellShapeTagVertex{}, 1, connectivity);
|
positions, vtkm::CellShapeTagVertex{}, 1, connectivity);
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Float32> mass;
|
vtkm::cont::ArrayHandle<vtkm::Float32> mass;
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xd1ce), mass);
|
vtkm::cont::ArrayCopyDevice(vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float32>(N, 0xd1ce),
|
||||||
|
mass);
|
||||||
dataSet.AddCellField("mass", mass);
|
dataSet.AddCellField("mass", mass);
|
||||||
|
|
||||||
auto cellDims = vtkm::Id3{ 3, 3, 3 };
|
auto cellDims = vtkm::Id3{ 3, 3, 3 };
|
||||||
|
@ -147,7 +147,7 @@ VTKM_CONT vtkm::cont::DataSet ThresholdPoints::DoExecute(const vtkm::cont::DataS
|
|||||||
vtkm::cont::CellSetSingleType<> outCellSet;
|
vtkm::cont::CellSetSingleType<> outCellSet;
|
||||||
vtkm::worklet::ThresholdPoints worklet;
|
vtkm::worklet::ThresholdPoints worklet;
|
||||||
|
|
||||||
auto ResolveType = [&, this](const auto& concrete) {
|
auto resolveType = [&, this](const auto& concrete) {
|
||||||
switch (this->ThresholdType)
|
switch (this->ThresholdType)
|
||||||
{
|
{
|
||||||
case THRESHOLD_BELOW:
|
case THRESHOLD_BELOW:
|
||||||
@ -170,8 +170,7 @@ VTKM_CONT vtkm::cont::DataSet ThresholdPoints::DoExecute(const vtkm::cont::DataS
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto& fieldArray = field.GetData();
|
this->CastAndCallScalarField(field, resolveType);
|
||||||
fieldArray.CastAndCallForTypes<vtkm::TypeListScalarAll, VTKM_DEFAULT_STORAGE_LIST>(ResolveType);
|
|
||||||
|
|
||||||
// create the output dataset
|
// create the output dataset
|
||||||
vtkm::cont::DataSet output;
|
vtkm::cont::DataSet output;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <vtkm/cont/Algorithm.h>
|
#include <vtkm/cont/Algorithm.h>
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/ArrayGetValues.h>
|
#include <vtkm/cont/ArrayGetValues.h>
|
||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
||||||
@ -940,7 +941,9 @@ public:
|
|||||||
auto offsetsArray =
|
auto offsetsArray =
|
||||||
vtkm::cont::make_ArrayHandleConcatenate(faceOffsetsTrim, adjustedPolyDataOffsets);
|
vtkm::cont::make_ArrayHandleConcatenate(faceOffsetsTrim, adjustedPolyDataOffsets);
|
||||||
OffsetsArrayType joinedOffsets;
|
OffsetsArrayType joinedOffsets;
|
||||||
vtkm::cont::ArrayCopy(offsetsArray, joinedOffsets);
|
// Need to compile a special device copy because the precompiled ArrayCopy does not
|
||||||
|
// know how to copy the ArrayHandleTransform.
|
||||||
|
vtkm::cont::ArrayCopyDevice(offsetsArray, joinedOffsets);
|
||||||
|
|
||||||
vtkm::cont::ArrayHandleConcatenate<vtkm::cont::ArrayHandle<vtkm::Id>,
|
vtkm::cont::ArrayHandleConcatenate<vtkm::cont::ArrayHandle<vtkm::Id>,
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id>>
|
vtkm::cont::ArrayHandle<vtkm::Id>>
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
##============================================================================
|
##============================================================================
|
||||||
set(field_transform_headers
|
set(field_transform_headers
|
||||||
GenerateIds.h)
|
GenerateIds.h)
|
||||||
set(field_transform_sources_device
|
set(field_transform_sources
|
||||||
GenerateIds.cxx)
|
GenerateIds.cxx)
|
||||||
|
|
||||||
vtkm_library(
|
vtkm_library(
|
||||||
NAME vtkm_filter_field_transform
|
NAME vtkm_filter_field_transform
|
||||||
HEADERS ${field_transform_headers}
|
HEADERS ${field_transform_headers}
|
||||||
DEVICE_SOURCES ${field_transform_sources_device}
|
SOURCES ${field_transform_sources}
|
||||||
USE_VTKM_JOB_POOL
|
USE_VTKM_JOB_POOL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ set(unit_tests
|
|||||||
UnitTestContourTreeUniformAugmentedFilter.cxx
|
UnitTestContourTreeUniformAugmentedFilter.cxx
|
||||||
UnitTestContourTreeUniformDistributedFilter.cxx
|
UnitTestContourTreeUniformDistributedFilter.cxx
|
||||||
UnitTestCoordinateSystemTransform.cxx
|
UnitTestCoordinateSystemTransform.cxx
|
||||||
UnitTestCrossProductFilter.cxx
|
|
||||||
UnitTestFieldMetadata.cxx
|
UnitTestFieldMetadata.cxx
|
||||||
UnitTestFieldSelection.cxx
|
UnitTestFieldSelection.cxx
|
||||||
UnitTestFieldToColors.cxx
|
UnitTestFieldToColors.cxx
|
||||||
|
@ -8,9 +8,13 @@
|
|||||||
## PURPOSE. See the above copyright notice for more information.
|
## PURPOSE. See the above copyright notice for more information.
|
||||||
##============================================================================
|
##============================================================================
|
||||||
set(vector_calculus_headers
|
set(vector_calculus_headers
|
||||||
DotProduct.h)
|
CrossProduct.h
|
||||||
|
DotProduct.h
|
||||||
|
)
|
||||||
set(vector_calculus_sources_device
|
set(vector_calculus_sources_device
|
||||||
DotProduct.cxx)
|
CrossProduct.cxx
|
||||||
|
DotProduct.cxx
|
||||||
|
)
|
||||||
|
|
||||||
vtkm_library(
|
vtkm_library(
|
||||||
NAME vtkm_filter_vector_calculus
|
NAME vtkm_filter_vector_calculus
|
||||||
|
91
vtkm/filter/vector_calculus/CrossProduct.cxx
Normal file
91
vtkm/filter/vector_calculus/CrossProduct.cxx
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/filter/vector_calculus/CrossProduct.h>
|
||||||
|
|
||||||
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
|
|
||||||
|
#include <vtkm/VectorAnalysis.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
class CrossProductWorklet : public vtkm::worklet::WorkletMapField
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ControlSignature = void(FieldIn, FieldIn, FieldOut);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
VTKM_EXEC void operator()(const vtkm::Vec<T, 3>& vec1,
|
||||||
|
const vtkm::Vec<T, 3>& vec2,
|
||||||
|
vtkm::Vec<T, 3>& outVec) const
|
||||||
|
{
|
||||||
|
outVec = vtkm::Cross(vec1, vec2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace vector_calculus
|
||||||
|
{
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
VTKM_CONT CrossProduct::CrossProduct()
|
||||||
|
{
|
||||||
|
this->SetOutputFieldName("crossproduct");
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
VTKM_CONT vtkm::cont::DataSet CrossProduct::DoExecute(const vtkm::cont::DataSet& inDataSet)
|
||||||
|
{
|
||||||
|
vtkm::cont::Field primaryField = this->GetFieldFromDataSet(0, inDataSet);
|
||||||
|
vtkm::cont::UnknownArrayHandle primaryArray = primaryField.GetData();
|
||||||
|
|
||||||
|
vtkm::cont::UnknownArrayHandle outArray;
|
||||||
|
|
||||||
|
// We are using a C++14 auto lambda here. The advantage over a Functor is obvious, we don't
|
||||||
|
// need to explicitly pass filter, input/output DataSets etc. thus reduce the impact to
|
||||||
|
// the legacy code. The lambda can also access the private part of the filter thus reducing
|
||||||
|
// filter's public interface profile. CastAndCall tries to cast primaryArray of unknown value
|
||||||
|
// type and storage to a concrete ArrayHandle<T, S> with T from the `TypeList` and S from
|
||||||
|
// `StorageList`. It then passes the concrete array to the lambda as the first argument.
|
||||||
|
// We can later recover the concrete ValueType, T, from the concrete array.
|
||||||
|
auto resolveType = [&, this](const auto& concrete) {
|
||||||
|
// use std::decay to remove const ref from the decltype of concrete.
|
||||||
|
using T = typename std::decay_t<decltype(concrete)>::ValueType;
|
||||||
|
const auto& secondaryField = this->GetFieldFromDataSet(1, inDataSet);
|
||||||
|
vtkm::cont::ArrayHandle<T> secondaryArray;
|
||||||
|
vtkm::cont::ArrayCopyShallowIfPossible(secondaryField.GetData(), secondaryArray);
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<T> result;
|
||||||
|
this->Invoke(CrossProductWorklet{}, concrete, secondaryArray, result);
|
||||||
|
outArray = result;
|
||||||
|
};
|
||||||
|
|
||||||
|
this->CastAndCallVecField<3>(primaryArray, resolveType);
|
||||||
|
|
||||||
|
vtkm::cont::DataSet outDataSet;
|
||||||
|
outDataSet.CopyStructure(inDataSet);
|
||||||
|
outDataSet.AddField({ this->GetOutputFieldName(), primaryField.GetAssociation(), outArray });
|
||||||
|
|
||||||
|
this->MapFieldsOntoOutput(inDataSet, outDataSet);
|
||||||
|
|
||||||
|
return outDataSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::filter::vector_calculus
|
129
vtkm/filter/vector_calculus/CrossProduct.h
Normal file
129
vtkm/filter/vector_calculus/CrossProduct.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef vtk_m_filter_vector_calculus_CrossProduct_h
|
||||||
|
#define vtk_m_filter_vector_calculus_CrossProduct_h
|
||||||
|
|
||||||
|
#include <vtkm/filter/NewFilterField.h>
|
||||||
|
|
||||||
|
#include <vtkm/filter/vector_calculus/vtkm_filter_vector_calculus_export.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace vector_calculus
|
||||||
|
{
|
||||||
|
|
||||||
|
class VTKM_FILTER_VECTOR_CALCULUS_EXPORT CrossProduct : public vtkm::filter::NewFilterField
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VTKM_CONT
|
||||||
|
CrossProduct();
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// Choose the primary field to operate on. In the cross product operation A x B, A is
|
||||||
|
/// the primary field.
|
||||||
|
VTKM_CONT
|
||||||
|
void SetPrimaryField(
|
||||||
|
const std::string& name,
|
||||||
|
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::ANY)
|
||||||
|
{
|
||||||
|
this->SetActiveField(name, association);
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT const std::string& GetPrimaryFieldName() const { return this->GetActiveFieldName(); }
|
||||||
|
VTKM_CONT vtkm::cont::Field::Association GetPrimaryFieldAssociation() const
|
||||||
|
{
|
||||||
|
return this->GetActiveFieldAssociation();
|
||||||
|
}
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// When set to true, uses a coordinate system as the primary field instead of the one selected
|
||||||
|
/// by name. Use SetPrimaryCoordinateSystem to select which coordinate system.
|
||||||
|
VTKM_CONT
|
||||||
|
void SetUseCoordinateSystemAsPrimaryField(bool flag)
|
||||||
|
{
|
||||||
|
this->SetUseCoordinateSystemAsField(flag);
|
||||||
|
}
|
||||||
|
VTKM_CONT
|
||||||
|
bool GetUseCoordinateSystemAsPrimaryField() const
|
||||||
|
{
|
||||||
|
return this->GetUseCoordinateSystemAsField();
|
||||||
|
}
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// Select the coordinate system index to use as the primary field. This only has an effect when
|
||||||
|
/// UseCoordinateSystemAsPrimaryField is true.
|
||||||
|
VTKM_CONT
|
||||||
|
void SetPrimaryCoordinateSystem(vtkm::Id index) { this->SetActiveCoordinateSystem(index); }
|
||||||
|
VTKM_CONT
|
||||||
|
vtkm::Id GetPrimaryCoordinateSystemIndex() const
|
||||||
|
{
|
||||||
|
return this->GetActiveCoordinateSystemIndex();
|
||||||
|
}
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// Choose the secondary field to operate on. In the dot product operation A . B, B is
|
||||||
|
/// the secondary field.
|
||||||
|
VTKM_CONT
|
||||||
|
void SetSecondaryField(
|
||||||
|
const std::string& name,
|
||||||
|
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::ANY)
|
||||||
|
{
|
||||||
|
this->SetActiveField(1, name, association);
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT const std::string& GetSecondaryFieldName() const { return this->GetActiveFieldName(1); }
|
||||||
|
VTKM_CONT vtkm::cont::Field::Association GetSecondaryFieldAssociation() const
|
||||||
|
{
|
||||||
|
return this->GetActiveFieldAssociation(1);
|
||||||
|
}
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// When set to true, uses a coordinate system as the secondary field instead of the one selected
|
||||||
|
/// by name. Use SetSecondaryCoordinateSystem to select which coordinate system.
|
||||||
|
VTKM_CONT
|
||||||
|
void SetUseCoordinateSystemAsSecondaryField(bool flag)
|
||||||
|
{
|
||||||
|
this->SetUseCoordinateSystemAsField(1, flag);
|
||||||
|
}
|
||||||
|
VTKM_CONT
|
||||||
|
bool GetUseCoordinateSystemAsSecondaryField() const
|
||||||
|
{
|
||||||
|
return this->GetUseCoordinateSystemAsField(1);
|
||||||
|
}
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// Select the coordinate system index to use as the secondary field. This only has an effect when
|
||||||
|
/// UseCoordinateSystemAsSecondaryField is true.
|
||||||
|
VTKM_CONT
|
||||||
|
void SetSecondaryCoordinateSystem(vtkm::Id index) { this->SetActiveCoordinateSystem(1, index); }
|
||||||
|
VTKM_CONT
|
||||||
|
vtkm::Id GetSecondaryCoordinateSystemIndex() const
|
||||||
|
{
|
||||||
|
return this->GetActiveCoordinateSystemIndex(1);
|
||||||
|
}
|
||||||
|
//@}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::filter::vector_calculus
|
||||||
|
|
||||||
|
#endif // vtk_m_filter_vector_calculus_CrossProduct_h
|
@ -8,33 +8,59 @@
|
|||||||
// PURPOSE. See the above copyright notice for more information.
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
#include <vtkm/cont/ErrorFilterExecution.h>
|
||||||
#include <vtkm/filter/vector_calculus/DotProduct.h>
|
#include <vtkm/filter/vector_calculus/DotProduct.h>
|
||||||
#include <vtkm/worklet/WorkletMapField.h>
|
#include <vtkm/worklet/WorkletMapField.h>
|
||||||
|
|
||||||
namespace // anonymous namespace making worklet::DotProduct internal to this .cxx
|
namespace // anonymous namespace making worklet::DotProduct internal to this .cxx
|
||||||
{
|
{
|
||||||
namespace worklet
|
|
||||||
|
struct DotProductWorklet : vtkm::worklet::WorkletMapField
|
||||||
{
|
{
|
||||||
class DotProduct : public vtkm::worklet::WorkletMapField
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using ControlSignature = void(FieldIn, FieldIn, FieldOut);
|
using ControlSignature = void(FieldIn, FieldIn, FieldOut);
|
||||||
|
|
||||||
template <typename T, vtkm::IdComponent Size>
|
template <typename T1, typename T2, typename T3>
|
||||||
VTKM_EXEC void operator()(const vtkm::Vec<T, Size>& v1,
|
VTKM_EXEC void operator()(const T1& v1, const T2& v2, T3& outValue) const
|
||||||
const vtkm::Vec<T, Size>& v2,
|
|
||||||
T& outValue) const
|
|
||||||
{
|
{
|
||||||
outValue = static_cast<T>(vtkm::Dot(v1, v2));
|
VTKM_ASSERT(v1.GetNumberOfComponents() == v2.GetNumberOfComponents());
|
||||||
}
|
outValue = v1[0] * v2[0];
|
||||||
|
for (vtkm::IdComponent i = 1; i < v1.GetNumberOfComponents(); ++i)
|
||||||
template <typename T>
|
{
|
||||||
VTKM_EXEC void operator()(T s1, T s2, T& outValue) const
|
outValue += v1[i] * v2[i];
|
||||||
{
|
}
|
||||||
outValue = static_cast<T>(s1 * s2);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace worklet
|
|
||||||
|
template <typename PrimaryArrayType>
|
||||||
|
vtkm::cont::UnknownArrayHandle DoDotProduct(const PrimaryArrayType& primaryArray,
|
||||||
|
const vtkm::cont::Field& secondaryField)
|
||||||
|
{
|
||||||
|
using T = typename PrimaryArrayType::ValueType::ComponentType;
|
||||||
|
|
||||||
|
vtkm::cont::Invoker invoke;
|
||||||
|
vtkm::cont::ArrayHandle<T> outputArray;
|
||||||
|
|
||||||
|
if (secondaryField.GetData().IsBaseComponentType<T>())
|
||||||
|
{
|
||||||
|
invoke(DotProductWorklet{},
|
||||||
|
primaryArray,
|
||||||
|
secondaryField.GetData().ExtractArrayFromComponents<T>(),
|
||||||
|
outputArray);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Data types of primary and secondary array do not match. Rather than try to replicate every
|
||||||
|
// possibility, get the secondary array as a FloatDefault.
|
||||||
|
vtkm::cont::UnknownArrayHandle castSecondaryArray = secondaryField.GetDataAsDefaultFloat();
|
||||||
|
invoke(DotProductWorklet{},
|
||||||
|
primaryArray,
|
||||||
|
castSecondaryArray.ExtractArrayFromComponents<vtkm::FloatDefault>(),
|
||||||
|
outputArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputArray;
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
@ -51,37 +77,39 @@ VTKM_CONT DotProduct::DotProduct()
|
|||||||
|
|
||||||
VTKM_CONT vtkm::cont::DataSet DotProduct::DoExecute(const vtkm::cont::DataSet& inDataSet)
|
VTKM_CONT vtkm::cont::DataSet DotProduct::DoExecute(const vtkm::cont::DataSet& inDataSet)
|
||||||
{
|
{
|
||||||
const auto& primaryArray = this->GetFieldFromDataSet(inDataSet).GetData();
|
vtkm::cont::Field primaryField = this->GetFieldFromDataSet(0, inDataSet);
|
||||||
|
vtkm::cont::UnknownArrayHandle primaryArray = primaryField.GetData();
|
||||||
|
|
||||||
|
vtkm::cont::Field secondaryField = this->GetFieldFromDataSet(1, inDataSet);
|
||||||
|
|
||||||
|
if (primaryArray.GetNumberOfComponentsFlat() !=
|
||||||
|
secondaryField.GetData().GetNumberOfComponentsFlat())
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorFilterExecution(
|
||||||
|
"Primary and secondary arrays of DotProduct filter have different number of components.");
|
||||||
|
}
|
||||||
|
|
||||||
vtkm::cont::UnknownArrayHandle outArray;
|
vtkm::cont::UnknownArrayHandle outArray;
|
||||||
|
|
||||||
// We are using a C++14 auto lambda here. The advantage over a Functor is obvious, we don't
|
if (primaryArray.IsBaseComponentType<vtkm::Float32>())
|
||||||
// need to explicitly pass filter, input/output DataSets etc. thus reduce the impact to
|
{
|
||||||
// the legacy code. The lambda can also access the private part of the filter thus reducing
|
outArray =
|
||||||
// filter's public interface profile. CastAndCall tries to cast primaryArray of unknown value
|
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::Float32>(), secondaryField);
|
||||||
// type and storage to a concrete ArrayHandle<T, S> with T from the `TypeList` and S from
|
}
|
||||||
// `StorageList`. It then passes the concrete array to the lambda as the first argument.
|
else if (primaryArray.IsBaseComponentType<vtkm::Float64>())
|
||||||
// We can later recover the concrete ValueType, T, from the concrete array.
|
{
|
||||||
auto ResolveType = [&, this](const auto& concrete) {
|
outArray =
|
||||||
// use std::decay to remove const ref from the decltype of concrete.
|
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::Float64>(), secondaryField);
|
||||||
using T = typename std::decay_t<decltype(concrete)>::ValueType;
|
}
|
||||||
const auto& secondaryField = this->GetFieldFromDataSet(1, inDataSet);
|
else
|
||||||
vtkm::cont::UnknownArrayHandle secondary = vtkm::cont::ArrayHandle<T>{};
|
{
|
||||||
secondary.CopyShallowIfPossible(secondaryField.GetData());
|
primaryArray = primaryField.GetDataAsDefaultFloat();
|
||||||
|
outArray =
|
||||||
|
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::FloatDefault>(), secondaryField);
|
||||||
|
}
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<typename vtkm::VecTraits<T>::ComponentType> result;
|
vtkm::cont::DataSet outDataSet;
|
||||||
this->Invoke(::worklet::DotProduct{},
|
outDataSet.CopyStructure(inDataSet);
|
||||||
concrete,
|
|
||||||
secondary.template AsArrayHandle<vtkm::cont::ArrayHandle<T>>(),
|
|
||||||
result);
|
|
||||||
outArray = result;
|
|
||||||
};
|
|
||||||
|
|
||||||
primaryArray
|
|
||||||
.CastAndCallForTypesWithFloatFallback<VTKM_DEFAULT_TYPE_LIST, VTKM_DEFAULT_STORAGE_LIST>(
|
|
||||||
ResolveType);
|
|
||||||
|
|
||||||
vtkm::cont::DataSet outDataSet = inDataSet; // copy
|
|
||||||
outDataSet.AddField({ this->GetOutputFieldName(),
|
outDataSet.AddField({ this->GetOutputFieldName(),
|
||||||
this->GetFieldFromDataSet(inDataSet).GetAssociation(),
|
this->GetFieldFromDataSet(inDataSet).GetAssociation(),
|
||||||
outArray });
|
outArray });
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
##============================================================================
|
##============================================================================
|
||||||
|
|
||||||
set(unit_tests
|
set(unit_tests
|
||||||
|
UnitTestCrossProductFilter.cxx
|
||||||
UnitTestDotProductFilter.cxx
|
UnitTestDotProductFilter.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
|
|
||||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||||
#include <vtkm/cont/testing/Testing.h>
|
#include <vtkm/cont/testing/Testing.h>
|
||||||
#include <vtkm/filter/CrossProduct.h>
|
#include <vtkm/filter/vector_calculus/CrossProduct.h>
|
||||||
|
|
||||||
|
#include <vtkm/VectorAnalysis.h>
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -139,7 +141,7 @@ void TestCrossProduct()
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::cout << " Both vectors as normal fields" << std::endl;
|
std::cout << " Both vectors as normal fields" << std::endl;
|
||||||
vtkm::filter::CrossProduct filter;
|
vtkm::filter::vector_calculus::CrossProduct filter;
|
||||||
filter.SetPrimaryField("vec1");
|
filter.SetPrimaryField("vec1");
|
||||||
filter.SetSecondaryField("vec2", vtkm::cont::Field::Association::POINTS);
|
filter.SetSecondaryField("vec2", vtkm::cont::Field::Association::POINTS);
|
||||||
|
|
||||||
@ -163,7 +165,7 @@ void TestCrossProduct()
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::cout << " First field as coordinates" << std::endl;
|
std::cout << " First field as coordinates" << std::endl;
|
||||||
vtkm::filter::CrossProduct filter;
|
vtkm::filter::vector_calculus::CrossProduct filter;
|
||||||
filter.SetUseCoordinateSystemAsPrimaryField(true);
|
filter.SetUseCoordinateSystemAsPrimaryField(true);
|
||||||
filter.SetPrimaryCoordinateSystem(1);
|
filter.SetPrimaryCoordinateSystem(1);
|
||||||
filter.SetSecondaryField("vec2");
|
filter.SetSecondaryField("vec2");
|
||||||
@ -184,7 +186,7 @@ void TestCrossProduct()
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::cout << " Second field as coordinates" << std::endl;
|
std::cout << " Second field as coordinates" << std::endl;
|
||||||
vtkm::filter::CrossProduct filter;
|
vtkm::filter::vector_calculus::CrossProduct filter;
|
||||||
filter.SetPrimaryField("vec1");
|
filter.SetPrimaryField("vec1");
|
||||||
filter.SetUseCoordinateSystemAsSecondaryField(true);
|
filter.SetUseCoordinateSystemAsSecondaryField(true);
|
||||||
filter.SetSecondaryCoordinateSystem(2);
|
filter.SetSecondaryCoordinateSystem(2);
|
@ -49,19 +49,15 @@ set(sources
|
|||||||
ImageWriterPNG.cxx
|
ImageWriterPNG.cxx
|
||||||
ImageWriterPNM.cxx
|
ImageWriterPNM.cxx
|
||||||
VTKDataSetReader.cxx
|
VTKDataSetReader.cxx
|
||||||
|
VTKDataSetReaderBase.cxx
|
||||||
VTKDataSetWriter.cxx
|
VTKDataSetWriter.cxx
|
||||||
VTKPolyDataReader.cxx
|
VTKPolyDataReader.cxx
|
||||||
|
VTKRectilinearGridReader.cxx
|
||||||
VTKStructuredGridReader.cxx
|
VTKStructuredGridReader.cxx
|
||||||
VTKStructuredPointsReader.cxx
|
VTKStructuredPointsReader.cxx
|
||||||
VTKUnstructuredGridReader.cxx
|
VTKUnstructuredGridReader.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
# These files use ArrayCopy which uses a WorkletMapField thus are required to be device_sources
|
|
||||||
set(device_sources
|
|
||||||
VTKDataSetReaderBase.cxx
|
|
||||||
VTKRectilinearGridReader.cxx
|
|
||||||
)
|
|
||||||
|
|
||||||
if (VTKm_ENABLE_HDF5_IO)
|
if (VTKm_ENABLE_HDF5_IO)
|
||||||
set(headers
|
set(headers
|
||||||
${headers}
|
${headers}
|
||||||
|
@ -297,9 +297,16 @@ void VTKDataSetReaderBase::ReadCells(vtkm::cont::ArrayHandle<vtkm::Id>& connecti
|
|||||||
offsets.CastAndCallForTypes<vtkm::List<vtkm::Int64, vtkm::Int32>,
|
offsets.CastAndCallForTypes<vtkm::List<vtkm::Int64, vtkm::Int32>,
|
||||||
vtkm::List<vtkm::cont::StorageTagBasic>>(
|
vtkm::List<vtkm::cont::StorageTagBasic>>(
|
||||||
[&](const auto& offsetsAH) {
|
[&](const auto& offsetsAH) {
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleOffsetsToNumComponents(
|
// Convert on host. There will be several other passes of this array on the host anyway.
|
||||||
vtkm::cont::make_ArrayHandleCast(offsetsAH, vtkm::Id{})),
|
numIndices.Allocate(offsetsSize - 1);
|
||||||
numIndices);
|
auto offsetPortal = offsetsAH.ReadPortal();
|
||||||
|
auto numIndicesPortal = numIndices.WritePortal();
|
||||||
|
for (vtkm::Id cellIndex = 0; cellIndex < offsetsSize - 1; ++cellIndex)
|
||||||
|
{
|
||||||
|
numIndicesPortal.Set(cellIndex,
|
||||||
|
static_cast<vtkm::IdComponent>(offsetPortal.Get(cellIndex + 1) -
|
||||||
|
offsetPortal.Get(cellIndex)));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this->DataFile->Stream >> tag >> dataType >> std::ws;
|
this->DataFile->Stream >> tag >> dataType >> std::ws;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#define vtk_m_worklet_AverageByKey_h
|
#define vtk_m_worklet_AverageByKey_h
|
||||||
|
|
||||||
#include <vtkm/VecTraits.h>
|
#include <vtkm/VecTraits.h>
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
#include <vtkm/worklet/DescriptiveStatistics.h>
|
#include <vtkm/worklet/DescriptiveStatistics.h>
|
||||||
#include <vtkm/worklet/Keys.h>
|
#include <vtkm/worklet/Keys.h>
|
||||||
@ -86,23 +86,13 @@ struct AverageByKey
|
|||||||
return outAverages;
|
return outAverages;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExtractKey
|
|
||||||
{
|
|
||||||
template <typename First, typename Second>
|
|
||||||
VTKM_EXEC First operator()(const vtkm::Pair<First, Second>& pair) const
|
|
||||||
{
|
|
||||||
return pair.first;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ExtractMean
|
struct ExtractMean
|
||||||
{
|
{
|
||||||
template <typename KeyType, typename ValueType>
|
template <typename ValueType>
|
||||||
VTKM_EXEC ValueType operator()(
|
VTKM_EXEC ValueType
|
||||||
const vtkm::Pair<KeyType, vtkm::worklet::DescriptiveStatistics::StatState<ValueType>>& pair)
|
operator()(const vtkm::worklet::DescriptiveStatistics::StatState<ValueType>& state) const
|
||||||
const
|
|
||||||
{
|
{
|
||||||
return pair.second.Mean();
|
return state.Mean();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,13 +121,15 @@ struct AverageByKey
|
|||||||
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "AverageByKey::Run");
|
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "AverageByKey::Run");
|
||||||
|
|
||||||
auto results = vtkm::worklet::DescriptiveStatistics::Run(keyArray, valueArray);
|
auto results = vtkm::worklet::DescriptiveStatistics::Run(keyArray, valueArray);
|
||||||
|
// Extract results to outputKeyArray and outputValueArray
|
||||||
// Copy/TransformCopy from results to outputKeyArray and outputValueArray
|
outputKeyArray = results.GetFirstArray();
|
||||||
auto results_key = vtkm::cont::make_ArrayHandleTransform(results, ExtractKey{});
|
// TODO: DescriptiveStatistics should write its output to a SOA instead of an AOS.
|
||||||
auto results_mean = vtkm::cont::make_ArrayHandleTransform(results, ExtractMean{});
|
// An ArrayHandle of a weird struct by itself is not useful in any general algorithm.
|
||||||
|
// In fact, using DescriptiveStatistics at all seems like way overkill. It computes
|
||||||
vtkm::cont::ArrayCopy(results_key, outputKeyArray);
|
// all sorts of statistics, and we then throw them all away except for mean.
|
||||||
vtkm::cont::ArrayCopy(results_mean, outputValueArray);
|
auto resultsMean =
|
||||||
|
vtkm::cont::make_ArrayHandleTransform(results.GetSecondArray(), ExtractMean{});
|
||||||
|
vtkm::cont::ArrayCopyDevice(resultsMean, outputValueArray);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,11 @@ set(headers
|
|||||||
ContourTreeUniformAugmented.h
|
ContourTreeUniformAugmented.h
|
||||||
CoordinateSystemTransform.h
|
CoordinateSystemTransform.h
|
||||||
CosmoTools.h
|
CosmoTools.h
|
||||||
CrossProduct.h
|
|
||||||
DispatcherMapField.h
|
DispatcherMapField.h
|
||||||
DispatcherMapTopology.h
|
DispatcherMapTopology.h
|
||||||
DispatcherCellNeighborhood.h
|
DispatcherCellNeighborhood.h
|
||||||
DispatcherPointNeighborhood.h
|
DispatcherPointNeighborhood.h
|
||||||
DispatcherReduceByKey.h
|
DispatcherReduceByKey.h
|
||||||
DotProduct.h
|
|
||||||
FieldStatistics.h
|
FieldStatistics.h
|
||||||
Gradient.h
|
Gradient.h
|
||||||
ImageDifference.h
|
ImageDifference.h
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
// 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.
|
|
||||||
//============================================================================
|
|
||||||
#ifndef vtk_m_worklet_CrossProduct_h
|
|
||||||
#define vtk_m_worklet_CrossProduct_h
|
|
||||||
|
|
||||||
#include <vtkm/worklet/WorkletMapField.h>
|
|
||||||
|
|
||||||
#include <vtkm/VectorAnalysis.h>
|
|
||||||
|
|
||||||
namespace vtkm
|
|
||||||
{
|
|
||||||
namespace worklet
|
|
||||||
{
|
|
||||||
|
|
||||||
class CrossProduct : public vtkm::worklet::WorkletMapField
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using ControlSignature = void(FieldIn, FieldIn, FieldOut);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
VTKM_EXEC void operator()(const vtkm::Vec<T, 3>& vec1,
|
|
||||||
const vtkm::Vec<T, 3>& vec2,
|
|
||||||
vtkm::Vec<T, 3>& outVec) const
|
|
||||||
{
|
|
||||||
outVec = vtkm::Cross(vec1, vec2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} // namespace vtkm::worklet
|
|
||||||
|
|
||||||
#endif // vtk_m_worklet_CrossProduct_h
|
|
@ -1,45 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
// 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.
|
|
||||||
//============================================================================
|
|
||||||
#ifndef vtk_m_worklet_DotProduct_h
|
|
||||||
#define vtk_m_worklet_DotProduct_h
|
|
||||||
|
|
||||||
#include <vtkm/worklet/WorkletMapField.h>
|
|
||||||
|
|
||||||
#include <vtkm/Math.h>
|
|
||||||
#include <vtkm/VectorAnalysis.h>
|
|
||||||
|
|
||||||
namespace vtkm
|
|
||||||
{
|
|
||||||
namespace worklet
|
|
||||||
{
|
|
||||||
|
|
||||||
class DotProduct : public vtkm::worklet::WorkletMapField
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using ControlSignature = void(FieldIn, FieldIn, FieldOut);
|
|
||||||
|
|
||||||
template <typename T, vtkm::IdComponent Size>
|
|
||||||
VTKM_EXEC void operator()(const vtkm::Vec<T, Size>& v1,
|
|
||||||
const vtkm::Vec<T, Size>& v2,
|
|
||||||
T& outValue) const
|
|
||||||
{
|
|
||||||
outValue = static_cast<T>(vtkm::Dot(v1, v2));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
VTKM_EXEC void operator()(T s1, T s2, T& outValue) const
|
|
||||||
{
|
|
||||||
outValue = static_cast<T>(s1 * s2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} // namespace vtkm::worklet
|
|
||||||
|
|
||||||
#endif // vtk_m_worklet_Normalize_h
|
|
@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
// global libraries
|
// global libraries
|
||||||
#include <vtkm/cont/Algorithm.h>
|
#include <vtkm/cont/Algorithm.h>
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||||
#include <vtkm/cont/ArrayHandleTransform.h>
|
#include <vtkm/cont/ArrayHandleTransform.h>
|
||||||
@ -106,7 +106,7 @@ inline void PermuteArray(const ArrayType& input, IdArrayType& permute, ArrayType
|
|||||||
// fancy vtkm array so that we do not actually copy any data here
|
// fancy vtkm array so that we do not actually copy any data here
|
||||||
permute_type permutedInput(maskedPermuteIndex, input);
|
permute_type permutedInput(maskedPermuteIndex, input);
|
||||||
// Finally, copy the permuted values to the output array
|
// Finally, copy the permuted values to the output array
|
||||||
vtkm::cont::ArrayCopy(permutedInput, output);
|
vtkm::cont::ArrayCopyDevice(permutedInput, output);
|
||||||
} // permuteValues()
|
} // permuteValues()
|
||||||
|
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ public:
|
|||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> cellIndex;
|
vtkm::cont::ArrayHandle<vtkm::Id> cellIndex;
|
||||||
vtkm::Id connectivityLen = vtkm::cont::Algorithm::ScanExclusive(numPoints, cellIndex);
|
vtkm::Id connectivityLen = vtkm::cont::Algorithm::ScanExclusive(numPoints, cellIndex);
|
||||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> connCount(0, 1, connectivityLen);
|
vtkm::cont::ArrayHandleIndex connCount(connectivityLen);
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||||
vtkm::cont::ArrayCopy(connCount, connectivity);
|
vtkm::cont::ArrayCopy(connCount, connectivity);
|
||||||
|
|
||||||
|
@ -27,9 +27,7 @@ set(unit_tests
|
|||||||
UnitTestContourTreeUniformDistributed.cxx
|
UnitTestContourTreeUniformDistributed.cxx
|
||||||
UnitTestCoordinateSystemTransform.cxx
|
UnitTestCoordinateSystemTransform.cxx
|
||||||
UnitTestCosmoTools.cxx
|
UnitTestCosmoTools.cxx
|
||||||
UnitTestCrossProduct.cxx
|
|
||||||
UnitTestDescriptiveStatistics.cxx
|
UnitTestDescriptiveStatistics.cxx
|
||||||
UnitTestDotProduct.cxx
|
|
||||||
UnitTestFieldStatistics.cxx
|
UnitTestFieldStatistics.cxx
|
||||||
UnitTestKeys.cxx
|
UnitTestKeys.cxx
|
||||||
UnitTestMagnitude.cxx
|
UnitTestMagnitude.cxx
|
||||||
|
@ -70,7 +70,8 @@ void TryKeyType(KeyType)
|
|||||||
VTKM_TEST_ASSERT(keys.GetInputRange() == NUM_UNIQUE, "Keys has bad input range.");
|
VTKM_TEST_ASSERT(keys.GetInputRange() == NUM_UNIQUE, "Keys has bad input range.");
|
||||||
|
|
||||||
// Create values array
|
// Create values array
|
||||||
vtkm::cont::ArrayHandleCounting<vtkm::FloatDefault> valuesArray(0.0f, 1.0f, ARRAY_SIZE);
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> valuesArray;
|
||||||
|
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(ARRAY_SIZE), valuesArray);
|
||||||
|
|
||||||
std::cout << " Try average with Keys object" << std::endl;
|
std::cout << " Try average with Keys object" << std::endl;
|
||||||
CheckAverageByKey(keys.GetUniqueKeys(), vtkm::worklet::AverageByKey::Run(keys, valuesArray));
|
CheckAverageByKey(keys.GetUniqueKeys(), vtkm::worklet::AverageByKey::Run(keys, valuesArray));
|
||||||
|
@ -152,8 +152,7 @@ inline vtkm::cont::DataSet MakeRadiantDataSet::Make3DRadiantDataSet(vtkm::IdComp
|
|||||||
DataArrayHandle distanceToOther(coordinates, EuclideanNorm(CoordType(1., 1., 1.)));
|
DataArrayHandle distanceToOther(coordinates, EuclideanNorm(CoordType(1., 1., 1.)));
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArray;
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArray;
|
||||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, 1, nCells),
|
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleIndex(nCells), cellFieldArray);
|
||||||
cellFieldArray);
|
|
||||||
|
|
||||||
ConnectivityArrayHandle connectivity(
|
ConnectivityArrayHandle connectivity(
|
||||||
vtkm::cont::ArrayHandleCounting<vtkm::Id>(0, 1, nCells * HexTraits::NUM_POINTS),
|
vtkm::cont::ArrayHandleCounting<vtkm::Id>(0, 1, nCells * HexTraits::NUM_POINTS),
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
// 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/worklet/CrossProduct.h>
|
|
||||||
#include <vtkm/worklet/DispatcherMapField.h>
|
|
||||||
|
|
||||||
#include <random>
|
|
||||||
#include <vtkm/cont/testing/Testing.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
std::mt19937 randGenerator;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void createVectors(std::vector<vtkm::Vec<T, 3>>& vecs1, std::vector<vtkm::Vec<T, 3>>& vecs2)
|
|
||||||
{
|
|
||||||
// First, test the standard directions.
|
|
||||||
// X x Y
|
|
||||||
vecs1.push_back(vtkm::make_Vec(1, 0, 0));
|
|
||||||
vecs2.push_back(vtkm::make_Vec(0, 1, 0));
|
|
||||||
|
|
||||||
// Y x Z
|
|
||||||
vecs1.push_back(vtkm::make_Vec(0, 1, 0));
|
|
||||||
vecs2.push_back(vtkm::make_Vec(0, 0, 1));
|
|
||||||
|
|
||||||
// Z x X
|
|
||||||
vecs1.push_back(vtkm::make_Vec(0, 0, 1));
|
|
||||||
vecs2.push_back(vtkm::make_Vec(1, 0, 0));
|
|
||||||
|
|
||||||
// Y x X
|
|
||||||
vecs1.push_back(vtkm::make_Vec(0, 1, 0));
|
|
||||||
vecs2.push_back(vtkm::make_Vec(1, 0, 0));
|
|
||||||
|
|
||||||
// Z x Y
|
|
||||||
vecs1.push_back(vtkm::make_Vec(0, 0, 1));
|
|
||||||
vecs2.push_back(vtkm::make_Vec(0, 1, 0));
|
|
||||||
|
|
||||||
// X x Z
|
|
||||||
vecs1.push_back(vtkm::make_Vec(1, 0, 0));
|
|
||||||
vecs2.push_back(vtkm::make_Vec(0, 0, 1));
|
|
||||||
|
|
||||||
//Test some other vector combinations
|
|
||||||
std::uniform_real_distribution<vtkm::Float64> randomDist(-10.0, 10.0);
|
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++)
|
|
||||||
{
|
|
||||||
vecs1.push_back(vtkm::make_Vec(
|
|
||||||
randomDist(randGenerator), randomDist(randGenerator), randomDist(randGenerator)));
|
|
||||||
vecs2.push_back(vtkm::make_Vec(
|
|
||||||
randomDist(randGenerator), randomDist(randGenerator), randomDist(randGenerator)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void TestCrossProduct()
|
|
||||||
{
|
|
||||||
std::vector<vtkm::Vec<T, 3>> inputVecs1, inputVecs2;
|
|
||||||
createVectors(inputVecs1, inputVecs2);
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>> inputArray1, inputArray2;
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>> outputArray;
|
|
||||||
inputArray1 = vtkm::cont::make_ArrayHandle(inputVecs1, vtkm::CopyFlag::Off);
|
|
||||||
inputArray2 = vtkm::cont::make_ArrayHandle(inputVecs2, vtkm::CopyFlag::Off);
|
|
||||||
|
|
||||||
vtkm::worklet::CrossProduct crossProductWorklet;
|
|
||||||
vtkm::worklet::DispatcherMapField<vtkm::worklet::CrossProduct> dispatcherCrossProduct(
|
|
||||||
crossProductWorklet);
|
|
||||||
dispatcherCrossProduct.Invoke(inputArray1, inputArray2, outputArray);
|
|
||||||
|
|
||||||
VTKM_TEST_ASSERT(outputArray.GetNumberOfValues() == inputArray1.GetNumberOfValues(),
|
|
||||||
"Wrong number of results for CrossProduct worklet");
|
|
||||||
|
|
||||||
//Test the canonical cases.
|
|
||||||
VTKM_TEST_ASSERT(test_equal(outputArray.ReadPortal().Get(0), vtkm::make_Vec(0, 0, 1)) &&
|
|
||||||
test_equal(outputArray.ReadPortal().Get(1), vtkm::make_Vec(1, 0, 0)) &&
|
|
||||||
test_equal(outputArray.ReadPortal().Get(2), vtkm::make_Vec(0, 1, 0)) &&
|
|
||||||
test_equal(outputArray.ReadPortal().Get(3), vtkm::make_Vec(0, 0, -1)) &&
|
|
||||||
test_equal(outputArray.ReadPortal().Get(4), vtkm::make_Vec(-1, 0, 0)) &&
|
|
||||||
test_equal(outputArray.ReadPortal().Get(5), vtkm::make_Vec(0, -1, 0)),
|
|
||||||
"Wrong result for CrossProduct worklet");
|
|
||||||
|
|
||||||
for (vtkm::Id i = 0; i < inputArray1.GetNumberOfValues(); i++)
|
|
||||||
{
|
|
||||||
vtkm::Vec<T, 3> v1 = inputArray1.ReadPortal().Get(i);
|
|
||||||
vtkm::Vec<T, 3> v2 = inputArray2.ReadPortal().Get(i);
|
|
||||||
vtkm::Vec<T, 3> res = outputArray.ReadPortal().Get(i);
|
|
||||||
|
|
||||||
//Make sure result is orthogonal each input vector. Need to normalize to compare with zero.
|
|
||||||
vtkm::Vec<T, 3> v1N(vtkm::Normal(v1)), v2N(vtkm::Normal(v1)), resN(vtkm::Normal(res));
|
|
||||||
VTKM_TEST_ASSERT(test_equal(vtkm::Dot(resN, v1N), T(0.0)), "Wrong result for cross product");
|
|
||||||
VTKM_TEST_ASSERT(test_equal(vtkm::Dot(resN, v2N), T(0.0)), "Wrong result for cross product");
|
|
||||||
|
|
||||||
T sinAngle = vtkm::Magnitude(res) * vtkm::RMagnitude(v1) * vtkm::RMagnitude(v2);
|
|
||||||
T cosAngle = vtkm::Dot(v1, v2) * vtkm::RMagnitude(v1) * vtkm::RMagnitude(v2);
|
|
||||||
VTKM_TEST_ASSERT(test_equal(sinAngle * sinAngle + cosAngle * cosAngle, T(1.0)),
|
|
||||||
"Bad cross product length.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCrossProductWorklets()
|
|
||||||
{
|
|
||||||
std::cout << "Testing CrossProduct Worklet" << std::endl;
|
|
||||||
TestCrossProduct<vtkm::Float32>();
|
|
||||||
TestCrossProduct<vtkm::Float64>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int UnitTestCrossProduct(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
return vtkm::cont::testing::Testing::Run(TestCrossProductWorklets, argc, argv);
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
//============================================================================
|
|
||||||
// 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/worklet/DispatcherMapField.h>
|
|
||||||
#include <vtkm/worklet/DotProduct.h>
|
|
||||||
|
|
||||||
#include <vtkm/cont/testing/Testing.h>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T normalizedVector(T v)
|
|
||||||
{
|
|
||||||
T vN = vtkm::Normal(v);
|
|
||||||
return vN;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void createVectors(std::vector<vtkm::Vec<T, 3>>& vecs1,
|
|
||||||
std::vector<vtkm::Vec<T, 3>>& vecs2,
|
|
||||||
std::vector<T>& result)
|
|
||||||
{
|
|
||||||
vecs1.push_back(normalizedVector(vtkm::make_Vec(T(1), T(0), T(0))));
|
|
||||||
vecs2.push_back(normalizedVector(vtkm::make_Vec(T(1), T(0), T(0))));
|
|
||||||
result.push_back(1);
|
|
||||||
|
|
||||||
vecs1.push_back(normalizedVector(vtkm::make_Vec(T(1), T(0), T(0))));
|
|
||||||
vecs2.push_back(normalizedVector(vtkm::make_Vec(T(-1), T(0), T(0))));
|
|
||||||
result.push_back(-1);
|
|
||||||
|
|
||||||
vecs1.push_back(normalizedVector(vtkm::make_Vec(T(1), T(0), T(0))));
|
|
||||||
vecs2.push_back(normalizedVector(vtkm::make_Vec(T(0), T(1), T(0))));
|
|
||||||
result.push_back(0);
|
|
||||||
|
|
||||||
vecs1.push_back(normalizedVector(vtkm::make_Vec(T(1), T(0), T(0))));
|
|
||||||
vecs2.push_back(normalizedVector(vtkm::make_Vec(T(0), T(-1), T(0))));
|
|
||||||
result.push_back(0);
|
|
||||||
|
|
||||||
vecs1.push_back(normalizedVector(vtkm::make_Vec(T(1), T(0), T(0))));
|
|
||||||
vecs2.push_back(normalizedVector(vtkm::make_Vec(T(1), T(1), T(0))));
|
|
||||||
result.push_back(T(1.0 / vtkm::Sqrt(2.0)));
|
|
||||||
|
|
||||||
vecs1.push_back(normalizedVector(vtkm::make_Vec(T(1), T(1), T(0))));
|
|
||||||
vecs2.push_back(normalizedVector(vtkm::make_Vec(T(1), T(0), T(0))));
|
|
||||||
result.push_back(T(1.0 / vtkm::Sqrt(2.0)));
|
|
||||||
|
|
||||||
vecs1.push_back(normalizedVector(vtkm::make_Vec(T(-1), T(0), T(0))));
|
|
||||||
vecs2.push_back(normalizedVector(vtkm::make_Vec(T(1), T(1), T(0))));
|
|
||||||
result.push_back(-T(1.0 / vtkm::Sqrt(2.0)));
|
|
||||||
|
|
||||||
vecs1.push_back(normalizedVector(vtkm::make_Vec(T(0), T(1), T(0))));
|
|
||||||
vecs2.push_back(normalizedVector(vtkm::make_Vec(T(1), T(1), T(0))));
|
|
||||||
result.push_back(T(1.0 / vtkm::Sqrt(2.0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void TestDotProduct()
|
|
||||||
{
|
|
||||||
std::vector<vtkm::Vec<T, 3>> inputVecs1, inputVecs2;
|
|
||||||
std::vector<T> answer;
|
|
||||||
createVectors(inputVecs1, inputVecs2, answer);
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>> inputArray1, inputArray2;
|
|
||||||
vtkm::cont::ArrayHandle<T> outputArray;
|
|
||||||
inputArray1 = vtkm::cont::make_ArrayHandle(inputVecs1, vtkm::CopyFlag::Off);
|
|
||||||
inputArray2 = vtkm::cont::make_ArrayHandle(inputVecs2, vtkm::CopyFlag::Off);
|
|
||||||
|
|
||||||
vtkm::worklet::DotProduct dotProductWorklet;
|
|
||||||
vtkm::worklet::DispatcherMapField<vtkm::worklet::DotProduct> dispatcherDotProduct(
|
|
||||||
dotProductWorklet);
|
|
||||||
dispatcherDotProduct.Invoke(inputArray1, inputArray2, outputArray);
|
|
||||||
|
|
||||||
VTKM_TEST_ASSERT(outputArray.GetNumberOfValues() == inputArray1.GetNumberOfValues(),
|
|
||||||
"Wrong number of results for DotProduct worklet");
|
|
||||||
|
|
||||||
for (vtkm::Id i = 0; i < inputArray1.GetNumberOfValues(); i++)
|
|
||||||
{
|
|
||||||
vtkm::Vec<T, 3> v1 = inputArray1.ReadPortal().Get(i);
|
|
||||||
vtkm::Vec<T, 3> v2 = inputArray2.ReadPortal().Get(i);
|
|
||||||
T ans = answer[static_cast<std::size_t>(i)];
|
|
||||||
|
|
||||||
VTKM_TEST_ASSERT(test_equal(ans, vtkm::Dot(v1, v2)), "Wrong result for dot product");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestDotProductWorklets()
|
|
||||||
{
|
|
||||||
std::cout << "Testing DotProduct Worklet" << std::endl;
|
|
||||||
TestDotProduct<vtkm::Float32>();
|
|
||||||
// TestDotProduct<vtkm::Float64>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int UnitTestDotProduct(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
return vtkm::cont::testing::Testing::Run(TestDotProductWorklets, argc, argv);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user