mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 21:33: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)
|
||||
enable_language(HIP)
|
||||
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_LINK_OPTIONS "")
|
||||
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/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.
|
||||
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
|
||||
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
||||
vtkm::cont::UnknownArrayHandle& destination)
|
||||
namespace detail
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
DoUnknownArrayCopy(source, destination);
|
||||
}
|
||||
|
||||
void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
||||
const vtkm::cont::UnknownArrayHandle& destination)
|
||||
{
|
||||
if (!destination.IsValid())
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue(
|
||||
"Attempty to copy to a constant UnknownArrayHandle with no valid array.");
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray;
|
||||
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
|
||||
{
|
||||
|
||||
void ArrayCopyUnknown(const vtkm::cont::UnknownArrayHandle& source,
|
||||
vtkm::cont::UnknownArrayHandle& destination)
|
||||
{
|
||||
vtkm::cont::ArrayCopy(source, destination);
|
||||
vtkm::cont::ArrayHandle<Id> destination;
|
||||
vtkm::cont::ArrayCopyDevice(source, destination);
|
||||
return 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
|
||||
} // namespace vtkm
|
||||
}
|
||||
} // namespace vtkm::cont::detail
|
||||
|
@ -10,19 +10,20 @@
|
||||
#ifndef vtk_m_cont_ArrayCopy_h
|
||||
#define vtk_m_cont_ArrayCopy_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/ArrayHandleConcatenate.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/ArrayHandleView.h>
|
||||
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||
|
||||
#include <vtkm/cont/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.
|
||||
#include <vtkm/cont/internal/MapArrayPermutation.h>
|
||||
|
||||
#include <vtkm/StaticAssert.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -32,72 +33,91 @@ namespace cont
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Element-wise copy.
|
||||
template <typename InArrayType, typename OutArrayType>
|
||||
void ArrayCopyWithAlgorithm(const InArrayType& source, OutArrayType& destination)
|
||||
// Compile-time check to make sure that an `ArrayHandle` passed to `ArrayCopy`
|
||||
// can be passed to a `UnknownArrayHandle`. This function does nothing
|
||||
// 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
|
||||
// data is already available.
|
||||
vtkm::cont::Algorithm::Copy(source, destination);
|
||||
VTKM_STATIC_ASSERT_MSG(vtkm::HasVecTraits<T>::value,
|
||||
"An `ArrayHandle` that has a special value type that is not supported "
|
||||
"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 InArrayType, typename OutArrayType>
|
||||
void ArrayCopyOldImpl(const InArrayType& in, OutArrayType& out, std::false_type /* Copy storage */)
|
||||
{
|
||||
ArrayCopyWithAlgorithm(in, out);
|
||||
}
|
||||
template <typename S>
|
||||
struct ArrayCopyConcreteSrc;
|
||||
|
||||
// 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 */)
|
||||
template <typename SrcIsArrayHandle>
|
||||
inline void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
|
||||
vtkm::cont::UnknownArrayHandle& destination,
|
||||
SrcIsArrayHandle,
|
||||
std::false_type)
|
||||
{
|
||||
// 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);
|
||||
destination.DeepCopyFrom(source);
|
||||
}
|
||||
|
||||
// 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 */)
|
||||
template <typename SrcIsArrayHandle>
|
||||
inline void ArrayCopyImpl(const vtkm::cont::UnknownArrayHandle& source,
|
||||
const vtkm::cont::UnknownArrayHandle& destination,
|
||||
SrcIsArrayHandle,
|
||||
std::false_type)
|
||||
{
|
||||
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.
|
||||
///
|
||||
/// Given a source \c ArrayHandle and a destination \c ArrayHandle, this
|
||||
/// function allocates the destination \c ArrayHandle to the correct size and
|
||||
/// 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
|
||||
@ -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
|
||||
/// 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>
|
||||
VTKM_CONT void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InStorage>& source,
|
||||
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination)
|
||||
template <typename SourceArrayType, typename DestArrayType>
|
||||
inline void ArrayCopy(const SourceArrayType& source, DestArrayType& 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>{});
|
||||
detail::ArrayCopyImpl(source,
|
||||
destination,
|
||||
typename internal::ArrayHandleCheck<SourceArrayType>::type{},
|
||||
typename internal::ArrayHandleCheck<DestArrayType>::type{});
|
||||
}
|
||||
|
||||
|
||||
VTKM_CONT_EXPORT void ArrayCopy(const vtkm::cont::UnknownArrayHandle& 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)
|
||||
// Special case where we allow a const UnknownArrayHandle as output.
|
||||
template <typename SourceArrayType>
|
||||
inline void ArrayCopy(const SourceArrayType& source, vtkm::cont::UnknownArrayHandle& destination)
|
||||
{
|
||||
using DestType = vtkm::cont::ArrayHandle<T, S>;
|
||||
if (source.CanConvert<DestType>())
|
||||
{
|
||||
ArrayCopy(source.AsArrayHandle<DestType>(), destination);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::cont::UnknownArrayHandle destWrapper(destination);
|
||||
ArrayCopy(source, destWrapper);
|
||||
// Destination array should not change, but just in case.
|
||||
destWrapper.AsArrayHandle(destination);
|
||||
}
|
||||
detail::ArrayCopyImpl(source,
|
||||
destination,
|
||||
typename internal::ArrayHandleCheck<SourceArrayType>::type{},
|
||||
std::false_type{});
|
||||
}
|
||||
|
||||
// Invalid const ArrayHandle in destination, which is not allowed because it will
|
||||
// not work in all cases.
|
||||
template <typename T, typename S>
|
||||
void ArrayCopy(const vtkm::cont::UnknownArrayHandle&, const vtkm::cont::ArrayHandle<T, S>&)
|
||||
{
|
||||
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
|
||||
{
|
||||
vtkm::cont::UnknownArrayHandle destWrapper(destination);
|
||||
ArrayCopy(source, destWrapper);
|
||||
vtkm::cont::ArrayCopy(source, destWrapper);
|
||||
// Destination array should not change, but just in case.
|
||||
destWrapper.AsArrayHandle(destination);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
namespace detail
|
||||
{
|
||||
|
||||
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
|
||||
|
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/VecTraits.h>
|
||||
|
||||
#include <vtkmstd/integer_sequence.h>
|
||||
|
||||
#include <vtkm/cont/vtkm_cont_export.h>
|
||||
|
||||
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.
|
||||
///
|
||||
template <typename ArrayHandleType>
|
||||
|
@ -379,8 +379,11 @@ VTKM_CONT
|
||||
namespace internal
|
||||
{
|
||||
|
||||
// Superclass will inherit the ArrayExtractComponentImplInefficient property if any
|
||||
// of the sub-storage are inefficient (thus making everything inefficient).
|
||||
template <typename... STs>
|
||||
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagCartesianProduct<STs...>>
|
||||
: vtkm::cont::internal::ArrayExtractComponentImplInherit<STs...>
|
||||
{
|
||||
template <typename T>
|
||||
vtkm::cont::ArrayHandleStride<T> AdjustStrideForComponent(
|
||||
|
@ -507,16 +507,19 @@ struct ExtractComponentCompositeVecFunctor
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Superclass will inherit the ArrayExtractComponentImplInefficient property if any
|
||||
// of the sub-storage are inefficient (thus making everything inefficient).
|
||||
template <typename... StorageTags>
|
||||
struct ArrayExtractComponentImpl<StorageTagCompositeVec<StorageTags...>>
|
||||
: vtkm::cont::internal::ArrayExtractComponentImplInherit<StorageTags...>
|
||||
{
|
||||
template <typename T, vtkm::IdComponent NUM_COMPONENTS>
|
||||
typename detail::ExtractComponentCompositeVecFunctor<T>::ResultArray operator()(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<T, NUM_COMPONENTS>,
|
||||
vtkm::cont::StorageTagCompositeVec<StorageTags...>>& src,
|
||||
template <typename VecT>
|
||||
auto operator()(
|
||||
const vtkm::cont::ArrayHandle<VecT, vtkm::cont::StorageTagCompositeVec<StorageTags...>>& src,
|
||||
vtkm::IdComponent componentIndex,
|
||||
vtkm::CopyFlag allowCopy) const
|
||||
{
|
||||
using T = typename vtkm::VecTraits<VecT>::ComponentType;
|
||||
vtkm::cont::ArrayHandleCompositeVector<vtkm::cont::ArrayHandle<T, StorageTags>...> array(src);
|
||||
constexpr vtkm::IdComponent NUM_SUB_COMPONENTS = vtkm::VecFlat<T>::NUM_COMPONENTS;
|
||||
|
||||
|
@ -248,12 +248,12 @@ public:
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
@ -138,6 +138,10 @@ public:
|
||||
internal::ArrayPortalCounting<CountingValueType>(start, step, length)))
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT CountingValueType GetStart() const { return this->ReadPortal().GetStart(); }
|
||||
|
||||
VTKM_CONT CountingValueType GetStep() const { return this->ReadPortal().GetStep(); }
|
||||
};
|
||||
|
||||
/// A convenience function for creating an ArrayHandleCounting. It takes the
|
||||
|
@ -249,9 +249,12 @@ VTKM_CONT vtkm::cont::ArrayHandleGroupVec<ArrayHandleType, NUM_COMPONENTS> make_
|
||||
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>
|
||||
struct ArrayExtractComponentImpl<
|
||||
vtkm::cont::StorageTagGroupVec<ComponentsStorageTag, NUM_COMPONENTS>>
|
||||
: vtkm::cont::internal::ArrayExtractComponentImpl<ComponentsStorageTag>
|
||||
{
|
||||
template <typename T>
|
||||
vtkm::cont::ArrayHandleStride<typename vtkm::VecTraits<T>::BaseComponentType> operator()(
|
||||
|
@ -216,6 +216,10 @@ class ArrayHandlePermutation
|
||||
VTKM_IS_ARRAY_HANDLE(IndexArrayHandleType);
|
||||
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:
|
||||
VTKM_ARRAY_HANDLE_SUBCLASS(
|
||||
ArrayHandlePermutation,
|
||||
|
@ -217,8 +217,11 @@ VTKM_CONT ArrayHandleReverse<HandleType> make_ArrayHandleReverse(const HandleTyp
|
||||
namespace internal
|
||||
{
|
||||
|
||||
// Superclass will inherit the ArrayExtractComponentImplInefficient property if
|
||||
// the sub-storage is inefficient (thus making everything inefficient).
|
||||
template <typename StorageTag>
|
||||
struct ArrayExtractComponentImpl<vtkm::cont::StorageTagReverse<StorageTag>>
|
||||
: vtkm::cont::internal::ArrayExtractComponentImpl<StorageTag>
|
||||
{
|
||||
template <typename T>
|
||||
using StrideArrayType =
|
||||
|
@ -179,7 +179,7 @@ public:
|
||||
vtkm::Id adjustedEndIndex = (endIndex < indices.NumberOfValues)
|
||||
? endIndex + 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,
|
||||
@ -258,8 +258,11 @@ ArrayHandleView<ArrayHandleType> make_ArrayHandleView(const ArrayHandleType& arr
|
||||
namespace internal
|
||||
{
|
||||
|
||||
// Superclass will inherit the ArrayExtractComponentImplInefficient property if
|
||||
// the sub-storage is inefficient (thus making everything inefficient).
|
||||
template <typename StorageTag>
|
||||
struct ArrayExtractComponentImpl<StorageTagView<StorageTag>>
|
||||
: vtkm::cont::internal::ArrayExtractComponentImpl<StorageTag>
|
||||
{
|
||||
template <typename T>
|
||||
using StrideArrayType =
|
||||
|
@ -208,6 +208,15 @@ public:
|
||||
FirstStorage::CreateWritePortal(FirstArrayBuffers(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
|
||||
|
||||
@ -238,6 +247,15 @@ public:
|
||||
: 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
|
||||
|
@ -11,6 +11,7 @@
|
||||
set(headers
|
||||
Algorithm.h
|
||||
ArrayCopy.h
|
||||
ArrayCopyDevice.h
|
||||
ArrayExtractComponent.h
|
||||
ArrayGetValues.h
|
||||
ArrayHandle.h
|
||||
@ -192,7 +193,9 @@ set(device_sources
|
||||
ColorTable.cxx
|
||||
ConvertNumComponentsToOffsets.cxx
|
||||
Field.cxx
|
||||
internal/ArrayCopyUnknown.cxx
|
||||
internal/Buffer.cxx
|
||||
internal/MapArrayPermutation.cxx
|
||||
MergePartitionedDataSet.cxx
|
||||
PointLocatorSparseGrid.cxx
|
||||
RuntimeDeviceInformation.cxx
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef vtk_m_cont_DataSetBuilderRectilinear_h
|
||||
#define vtk_m_cont_DataSetBuilderRectilinear_h
|
||||
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||
#include <vtkm/cont/ArrayPortalToIterators.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::ArrayHandle<U>& output)
|
||||
{
|
||||
vtkm::cont::UnknownArrayHandle(output).DeepCopyFrom(input);
|
||||
vtkm::cont::ArrayCopy(input, output);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
|
@ -9,6 +9,7 @@
|
||||
//============================================================================
|
||||
#include <vtkm/cont/MergePartitionedDataSet.h>
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>
|
||||
#include <vtkm/cont/ArrayHandleView.h>
|
||||
|
@ -12,7 +12,6 @@
|
||||
#define vtk_m_cont_ParticleArrayCopy_hxx
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleTransform.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
#include <vtkm/cont/ParticleArrayCopy.h>
|
||||
@ -84,7 +83,7 @@ VTKM_ALWAYS_EXPORT inline void ParticleArrayCopy(
|
||||
vtkm::cont::Algorithm::CopyIf(posTrn, termTrn, outPos);
|
||||
}
|
||||
else
|
||||
vtkm::cont::ArrayCopy(posTrn, outPos);
|
||||
vtkm::cont::Algorithm::Copy(posTrn, outPos);
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
@ -82,9 +82,8 @@ void PointLocatorSparseGrid::Build()
|
||||
static_cast<vtkm::FloatDefault>(this->Range[2].Max));
|
||||
|
||||
// generate unique id for each input point
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> pointCounting(
|
||||
0, 1, this->GetCoordinates().GetNumberOfValues());
|
||||
vtkm::cont::ArrayCopy(pointCounting, this->PointIds);
|
||||
vtkm::cont::ArrayHandleIndex pointIndex(this->GetCoordinates().GetNumberOfValues());
|
||||
vtkm::cont::ArrayCopy(pointIndex, this->PointIds);
|
||||
|
||||
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::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::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
|
||||
@ -290,8 +310,10 @@ void UnknownArrayHandle::CopyShallowIfPossible(const vtkm::cont::UnknownArrayHan
|
||||
{
|
||||
*this = source;
|
||||
}
|
||||
|
||||
const_cast<const UnknownArrayHandle*>(this)->CopyShallowIfPossible(source);
|
||||
else
|
||||
{
|
||||
const_cast<const UnknownArrayHandle*>(this)->CopyShallowIfPossible(source);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
@ -311,7 +333,7 @@ void UnknownArrayHandle::CopyShallowIfPossible(const vtkm::cont::UnknownArrayHan
|
||||
}
|
||||
else
|
||||
{
|
||||
this->DeepCopyFrom(source);
|
||||
vtkm::cont::internal::ArrayCopyUnknown(source, *this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,15 @@ void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem)
|
||||
*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>
|
||||
std::vector<vtkm::cont::internal::Buffer>
|
||||
UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy)
|
||||
@ -224,6 +233,9 @@ struct VTKM_CONT_EXPORT UnknownAHContainer
|
||||
using ShallowCopyType = void(const void*, void*);
|
||||
ShallowCopyType* ShallowCopy;
|
||||
|
||||
using DeepCopyType = void(const void*, void*);
|
||||
DeepCopyType* DeepCopy;
|
||||
|
||||
using ExtractComponentType = std::vector<vtkm::cont::internal::Buffer>(void*,
|
||||
vtkm::IdComponent,
|
||||
vtkm::CopyFlag);
|
||||
@ -331,6 +343,7 @@ inline UnknownAHContainer::UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S
|
||||
, NumberOfComponentsFlat(detail::UnknownAHNumberOfComponentsFlat<T>)
|
||||
, Allocate(detail::UnknownAHAllocate<T, S>)
|
||||
, ShallowCopy(detail::UnknownAHShallowCopy<T, S>)
|
||||
, DeepCopy(detail::UnknownAHDeepCopy<T, S>)
|
||||
, ExtractComponent(detail::UnknownAHExtractComponent<T, S>)
|
||||
, ReleaseResources(detail::UnknownAHReleaseResources<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
|
||||
IteratorFromArrayPortal.h
|
||||
KXSort.h
|
||||
MapArrayPermutation.h
|
||||
OptionParser.h
|
||||
OptionParserArguments.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());
|
||||
|
||||
vtkm::cont::ArrayHandleSOA<ValueType> soaArray;
|
||||
vtkm::cont::ArrayCopy(basicArray, soaArray);
|
||||
vtkm::cont::Invoker{}(PassThrough{}, basicArray, soaArray);
|
||||
|
||||
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
|
||||
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
|
||||
{
|
||||
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())
|
||||
{
|
||||
this->RaiseError("Got unexpected number of components.");
|
||||
}
|
||||
|
||||
vtkm::Id valueIndex = workIndex * (workIndex + 1) / 2;
|
||||
vtkm::Id valueIndex = workIndex * (workIndex - 1) / 2;
|
||||
dummyOut = valueIndex;
|
||||
for (vtkm::IdComponent componentIndex = 0; componentIndex < expectedSize; componentIndex++)
|
||||
{
|
||||
@ -1113,8 +1113,7 @@ private:
|
||||
vtkm::Id sourceArraySize;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> numComponentsArray;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleCounting<vtkm::IdComponent>(1, 1, ARRAY_SIZE),
|
||||
numComponentsArray);
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(ARRAY_SIZE), numComponentsArray);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray =
|
||||
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, sourceArraySize);
|
||||
|
||||
@ -1147,13 +1146,13 @@ private:
|
||||
VTKM_EXEC void operator()(OutputType& output, vtkm::Id workIndex) const
|
||||
{
|
||||
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())
|
||||
{
|
||||
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++)
|
||||
{
|
||||
output[componentIndex] = TestValue(valueIndex, ComponentType());
|
||||
@ -1170,8 +1169,7 @@ private:
|
||||
vtkm::Id sourceArraySize;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> numComponentsArray;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleCounting<vtkm::IdComponent>(1, 1, ARRAY_SIZE),
|
||||
numComponentsArray);
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(ARRAY_SIZE), numComponentsArray);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray = vtkm::cont::ConvertNumComponentsToOffsets(
|
||||
numComponentsArray, sourceArraySize, DeviceAdapterTag());
|
||||
|
||||
@ -1364,6 +1362,15 @@ private:
|
||||
|
||||
//verify that the control portal works
|
||||
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/ArrayCopyDevice.h>
|
||||
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/ArrayHandleView.h>
|
||||
#include <vtkm/cont/UncertainArrayHandle.h>
|
||||
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||
|
||||
#include <vtkm/TypeTraits.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
@ -23,13 +29,43 @@ namespace
|
||||
|
||||
static constexpr vtkm::Id ARRAY_SIZE = 10;
|
||||
|
||||
template <typename RefArrayType, typename TestArrayType>
|
||||
void TestValues(const RefArrayType& refArray, const TestArrayType& testArray)
|
||||
vtkm::cont::UnknownArrayHandle MakeComparable(const vtkm::cont::UnknownArrayHandle& array,
|
||||
std::false_type)
|
||||
{
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
vtkm::cont::UnknownArrayHandle MakeComparable(const vtkm::cont::ArrayHandle<T>& array,
|
||||
std::true_type)
|
||||
{
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename ArrayType>
|
||||
vtkm::cont::UnknownArrayHandle MakeComparable(const ArrayType& array, std::true_type)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<typename ArrayType::ValueType> simpleArray;
|
||||
vtkm::cont::ArrayCopyDevice(array, simpleArray);
|
||||
return simpleArray;
|
||||
}
|
||||
|
||||
void TestValuesImpl(const vtkm::cont::UnknownArrayHandle& refArray,
|
||||
const vtkm::cont::UnknownArrayHandle& testArray)
|
||||
{
|
||||
auto result = test_equal_ArrayHandles(refArray, testArray);
|
||||
VTKM_TEST_ASSERT(result, result.GetMergedMessage());
|
||||
}
|
||||
|
||||
template <typename RefArrayType, typename TestArrayType>
|
||||
void TestValues(const RefArrayType& refArray, const TestArrayType& testArray)
|
||||
{
|
||||
TestValuesImpl(
|
||||
MakeComparable(refArray, typename vtkm::cont::internal::ArrayHandleCheck<RefArrayType>::type{}),
|
||||
MakeComparable(testArray,
|
||||
typename vtkm::cont::internal::ArrayHandleCheck<TestArrayType>::type{}));
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
vtkm::cont::ArrayHandle<ValueType> MakeInputArray()
|
||||
{
|
||||
@ -44,18 +80,20 @@ void TryCopy()
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Trying type: " << vtkm::testing::TypeName<ValueType>::Name());
|
||||
using VTraits = vtkm::VecTraits<ValueType>;
|
||||
|
||||
{
|
||||
std::cout << "implicit -> basic" << std::endl;
|
||||
vtkm::cont::ArrayHandleIndex input(ARRAY_SIZE);
|
||||
vtkm::cont::ArrayHandle<ValueType> output;
|
||||
vtkm::cont::ArrayHandle<typename VTraits::BaseComponentType> output;
|
||||
vtkm::cont::ArrayCopy(input, output);
|
||||
TestValues(input, output);
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "basic -> basic" << std::endl;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> input = MakeInputArray<vtkm::Id>();
|
||||
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::Id>;
|
||||
vtkm::cont::ArrayHandle<SourceType> input = MakeInputArray<SourceType>();
|
||||
vtkm::cont::ArrayHandle<ValueType> output;
|
||||
vtkm::cont::ArrayCopy(input, output);
|
||||
TestValues(input, output);
|
||||
@ -90,30 +128,72 @@ void TryCopy()
|
||||
TestValues(input, output);
|
||||
}
|
||||
|
||||
using TypeList = vtkm::ListAppend<vtkm::TypeListField, vtkm::List<ValueType, vtkm::UInt8>>;
|
||||
using StorageList = VTKM_DEFAULT_STORAGE_LIST;
|
||||
using UnknownArray = vtkm::cont::UnknownArrayHandle;
|
||||
using UncertainArray = vtkm::cont::UncertainArrayHandle<TypeList, StorageList>;
|
||||
|
||||
{
|
||||
std::cout << "unknown -> unknown" << std::endl;
|
||||
UnknownArray input = MakeInputArray<ValueType>();
|
||||
UnknownArray output;
|
||||
vtkm::cont::ArrayCopy(input, output);
|
||||
TestValues(input, output);
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "uncertain -> basic (same type)" << std::endl;
|
||||
UncertainArray input = MakeInputArray<ValueType>();
|
||||
std::cout << "constant -> basic" << std::endl;
|
||||
vtkm::cont::ArrayHandleConstant<ValueType> input(TestValue(2, ValueType{}), ARRAY_SIZE);
|
||||
vtkm::cont::ArrayHandle<ValueType> output;
|
||||
vtkm::cont::ArrayCopy(input, output);
|
||||
TestValues(input, output);
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "uncertain -> basic (different type)" << std::endl;
|
||||
UncertainArray input = MakeInputArray<vtkm::UInt8>();
|
||||
std::cout << "counting -> basic" << std::endl;
|
||||
vtkm::cont::ArrayHandleCounting<ValueType> input(ValueType(-4), ValueType(3), ARRAY_SIZE);
|
||||
vtkm::cont::ArrayHandle<ValueType> output;
|
||||
vtkm::cont::ArrayCopy(input, output);
|
||||
TestValues(input, output);
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "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::ArrayCopy(input, output);
|
||||
TestValues(input, output);
|
||||
@ -139,7 +219,8 @@ void TryCopy()
|
||||
|
||||
{
|
||||
std::cout << "unknown.DeepCopyFrom(different type)" << std::endl;
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> input = MakeInputArray<vtkm::UInt8>();
|
||||
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::UInt8>;
|
||||
vtkm::cont::ArrayHandle<SourceType> input = MakeInputArray<SourceType>();
|
||||
vtkm::cont::ArrayHandle<ValueType> outputArray;
|
||||
vtkm::cont::UnknownArrayHandle(outputArray).DeepCopyFrom(input);
|
||||
TestValues(input, outputArray);
|
||||
@ -166,7 +247,8 @@ void TryCopy()
|
||||
|
||||
{
|
||||
std::cout << "unknown.CopyShallowIfPossible(different type)" << std::endl;
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> input = MakeInputArray<vtkm::UInt8>();
|
||||
using SourceType = typename VTraits::template ReplaceComponentType<vtkm::UInt8>;
|
||||
vtkm::cont::ArrayHandle<SourceType> input = MakeInputArray<SourceType>();
|
||||
vtkm::cont::ArrayHandle<ValueType> outputArray;
|
||||
vtkm::cont::UnknownArrayHandle(outputArray).CopyShallowIfPossible(input);
|
||||
TestValues(input, outputArray);
|
||||
@ -203,6 +285,8 @@ void TestArrayCopy()
|
||||
TryCopy<vtkm::Id>();
|
||||
TryCopy<vtkm::IdComponent>();
|
||||
TryCopy<vtkm::Float32>();
|
||||
TryCopy<vtkm::Vec3f>();
|
||||
TryCopy<vtkm::Vec4i_16>();
|
||||
TryArrayCopyShallowIfPossible();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
@ -331,8 +332,8 @@ struct DecoratorTests
|
||||
}
|
||||
|
||||
// Copy a constant array into the decorator. This should modify ah3Copy.
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant(ValueType{ 25 }, ARRAY_SIZE),
|
||||
ahDecor);
|
||||
vtkm::cont::ArrayCopyDevice(vtkm::cont::make_ArrayHandleConstant(ValueType{ 25 }, ARRAY_SIZE),
|
||||
ahDecor);
|
||||
|
||||
{ // Accessing portal should give all 25s:
|
||||
auto portalDecor = ahDecor.ReadPortal();
|
||||
@ -390,7 +391,7 @@ struct DecoratorTests
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<ValueType> copiedInExec;
|
||||
vtkm::cont::ArrayCopy(decorArray, copiedInExec);
|
||||
vtkm::cont::ArrayCopyDevice(decorArray, copiedInExec);
|
||||
{
|
||||
auto copiedPortal = copiedInExec.ReadPortal();
|
||||
auto countPortal = ahCount.ReadPortal();
|
||||
|
@ -8,7 +8,7 @@
|
||||
// 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/ArrayHandleCartesianProduct.h>
|
||||
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
||||
@ -84,13 +84,13 @@ void FillArray(vtkm::cont::ArrayHandle<T, S>& array)
|
||||
using Traits = vtkm::VecTraits<T>;
|
||||
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)
|
||||
{
|
||||
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::Float64> randomArray(ARRAY_SIZE);
|
||||
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
|
||||
// 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/ArrayHandleConstant.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::ArrayHandle<vtkm::UInt8> shapes;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleConstant<vtkm::UInt8>{ vtkm::CELL_SHAPE_HEXAHEDRON,
|
||||
BaseLineNumberOfCells },
|
||||
shapes);
|
||||
shapes.AllocateAndFill(BaseLineNumberOfCells, vtkm::CELL_SHAPE_HEXAHEDRON);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
|
||||
vtkm::cont::ArrayCopy(
|
||||
vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>{ 8, BaseLineNumberOfCells }, numIndices);
|
||||
numIndices.AllocateAndFill(BaseLineNumberOfCells, 8);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||
vtkm::cont::ArrayCopy(BaseLineConnectivity, connectivity);
|
||||
vtkm::cont::ArrayCopyDevice(BaseLineConnectivity, connectivity);
|
||||
|
||||
auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numIndices);
|
||||
|
||||
|
@ -24,6 +24,7 @@ vtkm_add_instantiations(ClipWithImplicitFunctionInstantiations
|
||||
set(deprecated_headers
|
||||
CellSetConnectivity.h
|
||||
CleanGrid.h
|
||||
CrossProduct.h
|
||||
DotProduct.h
|
||||
Entropy.h
|
||||
ExternalFaces.h
|
||||
@ -88,7 +89,6 @@ set(extra_headers
|
||||
ComputeMoments.h
|
||||
CoordinateSystemTransform.h
|
||||
CreateResult.h
|
||||
CrossProduct.h
|
||||
FieldSelection.h
|
||||
FieldToColors.h
|
||||
GhostCellClassify.h
|
||||
@ -133,7 +133,6 @@ set(extra_header_template_sources
|
||||
ClipWithImplicitFunctionExternInstantiations.h
|
||||
ComputeMoments.hxx
|
||||
CoordinateSystemTransform.hxx
|
||||
CrossProduct.hxx
|
||||
FieldToColors.hxx
|
||||
GhostCellClassify.hxx
|
||||
ImageDifference.hxx
|
||||
|
@ -11,133 +11,31 @@
|
||||
#ifndef vtk_m_filter_CrossProduct_h
|
||||
#define vtk_m_filter_CrossProduct_h
|
||||
|
||||
#include <vtkm/filter/FilterField.h>
|
||||
#include <vtkm/worklet/CrossProduct.h>
|
||||
#include <vtkm/Deprecated.h>
|
||||
#include <vtkm/filter/vector_calculus/CrossProduct.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
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 filter only works on vec3 data.
|
||||
using SupportedTypes = vtkm::TypeListFieldVec3;
|
||||
CrossProduct_deprecated();
|
||||
}
|
||||
|
||||
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 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;
|
||||
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::vector_calculus::CrossProduct.") CrossProduct
|
||||
: public vtkm::filter::vector_calculus::CrossProduct
|
||||
{
|
||||
using vector_calculus::CrossProduct::CrossProduct;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace vtkm::filter
|
||||
|
||||
#include <vtkm/filter/CrossProduct.hxx>
|
||||
|
||||
#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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/VecTraits.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/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(
|
||||
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::cont::UnknownArrayHandle outputArray = inputField.GetData().NewInstanceBasic();
|
||||
outputArray.Allocate(permutation.GetNumberOfValues());
|
||||
try
|
||||
{
|
||||
inputField.GetData().CastAndCallWithExtractedArray(
|
||||
DoMapFieldPermutation{}, permutation, outputArray, invalidValue);
|
||||
vtkm::cont::UnknownArrayHandle outputArray =
|
||||
vtkm::cont::internal::MapArrayPermutation(inputField.GetData(), permutation, invalidValue);
|
||||
outputField = vtkm::cont::Field(inputField.GetName(), inputField.GetAssociation(), outputArray);
|
||||
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:
|
||||
void ResizeIfNeeded(size_t index_st);
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#ifndef 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/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
@ -102,9 +102,7 @@ public:
|
||||
if (this->MaskArray.GetNumberOfValues() < 1)
|
||||
{
|
||||
// Initialize mask array to 0.
|
||||
vtkm::cont::ArrayCopy(
|
||||
vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>(0, inCellSet.GetNumberOfPoints()),
|
||||
this->MaskArray);
|
||||
this->MaskArray.AllocateAndFill(inCellSet.GetNumberOfPoints(), 0);
|
||||
}
|
||||
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::ArrayHandle<OutT, OutS>& outArray) const
|
||||
{
|
||||
vtkm::cont::ArrayCopy(this->MapPointFieldShallow(inArray), outArray);
|
||||
vtkm::cont::ArrayCopyDevice(this->MapPointFieldShallow(inArray), outArray);
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifndef 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/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/ScatterCounting.h>
|
||||
|
@ -23,6 +23,6 @@ set(libraries
|
||||
vtkm_unit_tests(
|
||||
SOURCES ${unit_tests}
|
||||
LIBRARIES ${libraries}
|
||||
ALL_BACKENDS # use ArrayCopy
|
||||
ALL_BACKENDS # UnitTestParticleDensity.cxx uses DescriptiveStatistcs worklet
|
||||
USE_VTKM_JOB_POOL
|
||||
)
|
||||
|
@ -8,6 +8,8 @@
|
||||
// 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/DataSetBuilderExplicit.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, 0xabba));
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> positions;
|
||||
vtkm::cont::ArrayCopy(composite, positions);
|
||||
vtkm::cont::ArrayCopyDevice(composite, positions);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleIndex(N), connectivity);
|
||||
@ -36,8 +38,8 @@ void TestNGP()
|
||||
positions, vtkm::CellShapeTagVertex{}, 1, connectivity);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> mass;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleRandomUniformReal<vtkm::FloatDefault>(N, 0xd1ce),
|
||||
mass);
|
||||
vtkm::cont::ArrayCopyDevice(
|
||||
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::FloatDefault>(N, 0xd1ce), mass);
|
||||
dataSet.AddCellField("mass", mass);
|
||||
|
||||
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, 0xabba));
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> positions;
|
||||
vtkm::cont::ArrayCopy(composite, positions);
|
||||
vtkm::cont::ArrayCopyDevice(composite, positions);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleIndex(N), connectivity);
|
||||
@ -87,7 +89,8 @@ void TestCIC()
|
||||
positions, vtkm::CellShapeTagVertex{}, 1, connectivity);
|
||||
|
||||
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);
|
||||
|
||||
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::worklet::ThresholdPoints worklet;
|
||||
|
||||
auto ResolveType = [&, this](const auto& concrete) {
|
||||
auto resolveType = [&, this](const auto& concrete) {
|
||||
switch (this->ThresholdType)
|
||||
{
|
||||
case THRESHOLD_BELOW:
|
||||
@ -170,8 +170,7 @@ VTKM_CONT vtkm::cont::DataSet ThresholdPoints::DoExecute(const vtkm::cont::DataS
|
||||
}
|
||||
};
|
||||
|
||||
const auto& fieldArray = field.GetData();
|
||||
fieldArray.CastAndCallForTypes<vtkm::TypeListScalarAll, VTKM_DEFAULT_STORAGE_LIST>(ResolveType);
|
||||
this->CastAndCallScalarField(field, resolveType);
|
||||
|
||||
// create the output dataset
|
||||
vtkm::cont::DataSet output;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||
#include <vtkm/cont/ArrayGetValues.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
||||
@ -940,7 +941,9 @@ public:
|
||||
auto offsetsArray =
|
||||
vtkm::cont::make_ArrayHandleConcatenate(faceOffsetsTrim, adjustedPolyDataOffsets);
|
||||
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::ArrayHandle<vtkm::Id>>
|
||||
|
@ -9,13 +9,13 @@
|
||||
##============================================================================
|
||||
set(field_transform_headers
|
||||
GenerateIds.h)
|
||||
set(field_transform_sources_device
|
||||
set(field_transform_sources
|
||||
GenerateIds.cxx)
|
||||
|
||||
vtkm_library(
|
||||
NAME vtkm_filter_field_transform
|
||||
HEADERS ${field_transform_headers}
|
||||
DEVICE_SOURCES ${field_transform_sources_device}
|
||||
SOURCES ${field_transform_sources}
|
||||
USE_VTKM_JOB_POOL
|
||||
)
|
||||
|
||||
|
@ -23,7 +23,6 @@ set(unit_tests
|
||||
UnitTestContourTreeUniformAugmentedFilter.cxx
|
||||
UnitTestContourTreeUniformDistributedFilter.cxx
|
||||
UnitTestCoordinateSystemTransform.cxx
|
||||
UnitTestCrossProductFilter.cxx
|
||||
UnitTestFieldMetadata.cxx
|
||||
UnitTestFieldSelection.cxx
|
||||
UnitTestFieldToColors.cxx
|
||||
|
@ -8,9 +8,13 @@
|
||||
## PURPOSE. See the above copyright notice for more information.
|
||||
##============================================================================
|
||||
set(vector_calculus_headers
|
||||
DotProduct.h)
|
||||
CrossProduct.h
|
||||
DotProduct.h
|
||||
)
|
||||
set(vector_calculus_sources_device
|
||||
DotProduct.cxx)
|
||||
CrossProduct.cxx
|
||||
DotProduct.cxx
|
||||
)
|
||||
|
||||
vtkm_library(
|
||||
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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/cont/ErrorFilterExecution.h>
|
||||
#include <vtkm/filter/vector_calculus/DotProduct.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
template <typename T1, typename T2, typename T3>
|
||||
VTKM_EXEC void operator()(const T1& v1, const T2& v2, T3& 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);
|
||||
VTKM_ASSERT(v1.GetNumberOfComponents() == v2.GetNumberOfComponents());
|
||||
outValue = v1[0] * v2[0];
|
||||
for (vtkm::IdComponent i = 1; i < v1.GetNumberOfComponents(); ++i)
|
||||
{
|
||||
outValue += v1[i] * v2[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
} // 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
|
||||
|
||||
namespace vtkm
|
||||
@ -51,37 +77,39 @@ VTKM_CONT DotProduct::DotProduct()
|
||||
|
||||
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;
|
||||
|
||||
// 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::UnknownArrayHandle secondary = vtkm::cont::ArrayHandle<T>{};
|
||||
secondary.CopyShallowIfPossible(secondaryField.GetData());
|
||||
if (primaryArray.IsBaseComponentType<vtkm::Float32>())
|
||||
{
|
||||
outArray =
|
||||
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::Float32>(), secondaryField);
|
||||
}
|
||||
else if (primaryArray.IsBaseComponentType<vtkm::Float64>())
|
||||
{
|
||||
outArray =
|
||||
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::Float64>(), secondaryField);
|
||||
}
|
||||
else
|
||||
{
|
||||
primaryArray = primaryField.GetDataAsDefaultFloat();
|
||||
outArray =
|
||||
DoDotProduct(primaryArray.ExtractArrayFromComponents<vtkm::FloatDefault>(), secondaryField);
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<typename vtkm::VecTraits<T>::ComponentType> result;
|
||||
this->Invoke(::worklet::DotProduct{},
|
||||
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
|
||||
vtkm::cont::DataSet outDataSet;
|
||||
outDataSet.CopyStructure(inDataSet);
|
||||
outDataSet.AddField({ this->GetOutputFieldName(),
|
||||
this->GetFieldFromDataSet(inDataSet).GetAssociation(),
|
||||
outArray });
|
||||
|
@ -9,6 +9,7 @@
|
||||
##============================================================================
|
||||
|
||||
set(unit_tests
|
||||
UnitTestCrossProductFilter.cxx
|
||||
UnitTestDotProductFilter.cxx
|
||||
)
|
||||
|
||||
|
@ -10,7 +10,9 @@
|
||||
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.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 <vector>
|
||||
@ -139,7 +141,7 @@ void TestCrossProduct()
|
||||
|
||||
{
|
||||
std::cout << " Both vectors as normal fields" << std::endl;
|
||||
vtkm::filter::CrossProduct filter;
|
||||
vtkm::filter::vector_calculus::CrossProduct filter;
|
||||
filter.SetPrimaryField("vec1");
|
||||
filter.SetSecondaryField("vec2", vtkm::cont::Field::Association::POINTS);
|
||||
|
||||
@ -163,7 +165,7 @@ void TestCrossProduct()
|
||||
|
||||
{
|
||||
std::cout << " First field as coordinates" << std::endl;
|
||||
vtkm::filter::CrossProduct filter;
|
||||
vtkm::filter::vector_calculus::CrossProduct filter;
|
||||
filter.SetUseCoordinateSystemAsPrimaryField(true);
|
||||
filter.SetPrimaryCoordinateSystem(1);
|
||||
filter.SetSecondaryField("vec2");
|
||||
@ -184,7 +186,7 @@ void TestCrossProduct()
|
||||
|
||||
{
|
||||
std::cout << " Second field as coordinates" << std::endl;
|
||||
vtkm::filter::CrossProduct filter;
|
||||
vtkm::filter::vector_calculus::CrossProduct filter;
|
||||
filter.SetPrimaryField("vec1");
|
||||
filter.SetUseCoordinateSystemAsSecondaryField(true);
|
||||
filter.SetSecondaryCoordinateSystem(2);
|
@ -49,19 +49,15 @@ set(sources
|
||||
ImageWriterPNG.cxx
|
||||
ImageWriterPNM.cxx
|
||||
VTKDataSetReader.cxx
|
||||
VTKDataSetReaderBase.cxx
|
||||
VTKDataSetWriter.cxx
|
||||
VTKPolyDataReader.cxx
|
||||
VTKRectilinearGridReader.cxx
|
||||
VTKStructuredGridReader.cxx
|
||||
VTKStructuredPointsReader.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)
|
||||
set(headers
|
||||
${headers}
|
||||
|
@ -297,9 +297,16 @@ void VTKDataSetReaderBase::ReadCells(vtkm::cont::ArrayHandle<vtkm::Id>& connecti
|
||||
offsets.CastAndCallForTypes<vtkm::List<vtkm::Int64, vtkm::Int32>,
|
||||
vtkm::List<vtkm::cont::StorageTagBasic>>(
|
||||
[&](const auto& offsetsAH) {
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleOffsetsToNumComponents(
|
||||
vtkm::cont::make_ArrayHandleCast(offsetsAH, vtkm::Id{})),
|
||||
numIndices);
|
||||
// Convert on host. There will be several other passes of this array on the host anyway.
|
||||
numIndices.Allocate(offsetsSize - 1);
|
||||
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;
|
||||
|
@ -11,7 +11,7 @@
|
||||
#define vtk_m_worklet_AverageByKey_h
|
||||
|
||||
#include <vtkm/VecTraits.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/worklet/DescriptiveStatistics.h>
|
||||
#include <vtkm/worklet/Keys.h>
|
||||
@ -86,23 +86,13 @@ struct AverageByKey
|
||||
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
|
||||
{
|
||||
template <typename KeyType, typename ValueType>
|
||||
VTKM_EXEC ValueType operator()(
|
||||
const vtkm::Pair<KeyType, vtkm::worklet::DescriptiveStatistics::StatState<ValueType>>& pair)
|
||||
const
|
||||
template <typename ValueType>
|
||||
VTKM_EXEC ValueType
|
||||
operator()(const vtkm::worklet::DescriptiveStatistics::StatState<ValueType>& state) const
|
||||
{
|
||||
return pair.second.Mean();
|
||||
return state.Mean();
|
||||
}
|
||||
};
|
||||
|
||||
@ -131,13 +121,15 @@ struct AverageByKey
|
||||
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "AverageByKey::Run");
|
||||
|
||||
auto results = vtkm::worklet::DescriptiveStatistics::Run(keyArray, valueArray);
|
||||
|
||||
// Copy/TransformCopy from results to outputKeyArray and outputValueArray
|
||||
auto results_key = vtkm::cont::make_ArrayHandleTransform(results, ExtractKey{});
|
||||
auto results_mean = vtkm::cont::make_ArrayHandleTransform(results, ExtractMean{});
|
||||
|
||||
vtkm::cont::ArrayCopy(results_key, outputKeyArray);
|
||||
vtkm::cont::ArrayCopy(results_mean, outputValueArray);
|
||||
// Extract results to outputKeyArray and outputValueArray
|
||||
outputKeyArray = results.GetFirstArray();
|
||||
// TODO: DescriptiveStatistics should write its output to a SOA instead of an AOS.
|
||||
// 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
|
||||
// all sorts of statistics, and we then throw them all away except for mean.
|
||||
auto resultsMean =
|
||||
vtkm::cont::make_ArrayHandleTransform(results.GetSecondArray(), ExtractMean{});
|
||||
vtkm::cont::ArrayCopyDevice(resultsMean, outputValueArray);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -20,13 +20,11 @@ set(headers
|
||||
ContourTreeUniformAugmented.h
|
||||
CoordinateSystemTransform.h
|
||||
CosmoTools.h
|
||||
CrossProduct.h
|
||||
DispatcherMapField.h
|
||||
DispatcherMapTopology.h
|
||||
DispatcherCellNeighborhood.h
|
||||
DispatcherPointNeighborhood.h
|
||||
DispatcherReduceByKey.h
|
||||
DotProduct.h
|
||||
FieldStatistics.h
|
||||
Gradient.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
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayCopyDevice.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.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
|
||||
permute_type permutedInput(maskedPermuteIndex, input);
|
||||
// Finally, copy the permuted values to the output array
|
||||
vtkm::cont::ArrayCopy(permutedInput, output);
|
||||
vtkm::cont::ArrayCopyDevice(permutedInput, output);
|
||||
} // permuteValues()
|
||||
|
||||
|
||||
|
@ -225,7 +225,7 @@ public:
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> 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::ArrayCopy(connCount, connectivity);
|
||||
|
||||
|
@ -27,9 +27,7 @@ set(unit_tests
|
||||
UnitTestContourTreeUniformDistributed.cxx
|
||||
UnitTestCoordinateSystemTransform.cxx
|
||||
UnitTestCosmoTools.cxx
|
||||
UnitTestCrossProduct.cxx
|
||||
UnitTestDescriptiveStatistics.cxx
|
||||
UnitTestDotProduct.cxx
|
||||
UnitTestFieldStatistics.cxx
|
||||
UnitTestKeys.cxx
|
||||
UnitTestMagnitude.cxx
|
||||
|
@ -70,7 +70,8 @@ void TryKeyType(KeyType)
|
||||
VTKM_TEST_ASSERT(keys.GetInputRange() == NUM_UNIQUE, "Keys has bad input range.");
|
||||
|
||||
// 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;
|
||||
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.)));
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArray;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, 1, nCells),
|
||||
cellFieldArray);
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleIndex(nCells), cellFieldArray);
|
||||
|
||||
ConnectivityArrayHandle connectivity(
|
||||
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