mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Merge topic 'Variant_As'
e1f5c4dd9 Modify VariantAH::AsVirtual to cast to new ValueType if needed. Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Robert Maynard <robert.maynard@kitware.com> Merge-request: !1585
This commit is contained in:
commit
ad15ae1553
6
docs/changelog/Variant_AsVirtual_force_cast.md
Normal file
6
docs/changelog/Variant_AsVirtual_force_cast.md
Normal file
@ -0,0 +1,6 @@
|
||||
# VariantArrayHandle::AsVirtual<T>() performs casting
|
||||
|
||||
The AsVirtual<T> method of VariantArrayHandle now works for any arithmetic type,
|
||||
not just the actual type of the underlying array. This works by inserting an
|
||||
ArrayHandleCast between the underlying concrete array and the new
|
||||
ArrayHandleVirtual when needed.
|
@ -24,6 +24,13 @@
|
||||
|
||||
#include <vtkm/cont/ArrayHandleTransform.h>
|
||||
|
||||
#include <vtkm/cont/Logging.h>
|
||||
|
||||
#include <vtkm/BaseComponent.h>
|
||||
#include <vtkm/Range.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
@ -62,6 +69,60 @@ public:
|
||||
ArrayHandleCast(const ArrayHandleType& handle)
|
||||
: Superclass(handle)
|
||||
{
|
||||
this->ValidateTypeCast<typename ArrayHandleType::ValueType>();
|
||||
}
|
||||
|
||||
private:
|
||||
// Log warnings if type cast is valid but lossy:
|
||||
template <typename SrcValueType>
|
||||
VTKM_CONT static typename std::enable_if<!std::is_same<T, SrcValueType>::value>::type
|
||||
ValidateTypeCast()
|
||||
{
|
||||
#ifdef VTKM_ENABLE_LOGGING
|
||||
using DstValueType = T;
|
||||
using SrcComp = typename vtkm::BaseComponent<SrcValueType>::Type;
|
||||
using DstComp = typename vtkm::BaseComponent<DstValueType>::Type;
|
||||
using SrcLimits = std::numeric_limits<SrcComp>;
|
||||
using DstLimits = std::numeric_limits<DstComp>;
|
||||
|
||||
const vtkm::Range SrcRange{ SrcLimits::min(), SrcLimits::max() };
|
||||
const vtkm::Range DstRange{ DstLimits::min(), DstLimits::max() };
|
||||
|
||||
const bool RangeLoss = (SrcRange.Max > DstRange.Max || SrcRange.Min < DstRange.Min);
|
||||
const bool PrecLoss = SrcLimits::digits > DstLimits::digits;
|
||||
|
||||
if (RangeLoss && PrecLoss)
|
||||
{
|
||||
VTKM_LOG_F(vtkm::cont::LogLevel::Warn,
|
||||
"VariantArrayHandle::AsVirtual: Casting ComponentType of "
|
||||
"%s to %s reduces range and precision.",
|
||||
vtkm::cont::TypeToString<SrcValueType>().c_str(),
|
||||
vtkm::cont::TypeToString<DstValueType>().c_str());
|
||||
}
|
||||
else if (RangeLoss)
|
||||
{
|
||||
VTKM_LOG_F(vtkm::cont::LogLevel::Warn,
|
||||
"VariantArrayHandle::AsVirtual: Casting ComponentType of "
|
||||
"%s to %s reduces range.",
|
||||
vtkm::cont::TypeToString<SrcValueType>().c_str(),
|
||||
vtkm::cont::TypeToString<DstValueType>().c_str());
|
||||
}
|
||||
else if (PrecLoss)
|
||||
{
|
||||
VTKM_LOG_F(vtkm::cont::LogLevel::Warn,
|
||||
"VariantArrayHandle::AsVirtual: Casting ComponentType of "
|
||||
"%s to %s reduces precision.",
|
||||
vtkm::cont::TypeToString<SrcValueType>().c_str(),
|
||||
vtkm::cont::TypeToString<DstValueType>().c_str());
|
||||
}
|
||||
#endif // Logging
|
||||
}
|
||||
|
||||
template <typename SrcValueType>
|
||||
VTKM_CONT static typename std::enable_if<std::is_same<T, SrcValueType>::value>::type
|
||||
ValidateTypeCast()
|
||||
{
|
||||
//no-op if types match
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -136,13 +136,22 @@ public:
|
||||
return internal::variant::Cast<ArrayHandleType>(this->ArrayContainer.get());
|
||||
}
|
||||
|
||||
/// Returns this array cast to a \c ArrayHandleVirtual of the given type. Throws \c
|
||||
/// ErrorBadType if the cast does not work.
|
||||
/// Returns this array cast to a \c ArrayHandleVirtual of the given type.
|
||||
/// This will perform type conversions as necessary, and will log warnings
|
||||
/// if the conversion is lossy.
|
||||
///
|
||||
template <typename T>
|
||||
/// This method internally uses CastAndCall. A custom storage tag list may
|
||||
/// be specified in the second template parameter, which will be passed to
|
||||
/// the CastAndCall.
|
||||
///
|
||||
template <typename T, typename StorageTagList = VTKM_DEFAULT_STORAGE_LIST_TAG>
|
||||
VTKM_CONT vtkm::cont::ArrayHandleVirtual<T> AsVirtual() const
|
||||
{
|
||||
return internal::variant::Cast<vtkm::cont::ArrayHandleVirtual<T>>(this->ArrayContainer.get());
|
||||
VTKM_IS_LIST_TAG(StorageTagList);
|
||||
vtkm::cont::internal::variant::ForceCastToVirtual caster;
|
||||
vtkm::cont::ArrayHandleVirtual<T> output;
|
||||
this->CastAndCall(StorageTagList{}, caster, output);
|
||||
return output;
|
||||
}
|
||||
|
||||
/// Given a references to an ArrayHandle object, casts this array to the
|
||||
|
@ -22,15 +22,17 @@
|
||||
|
||||
#include <vtkm/cont/vtkm_cont_export.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleVirtual.h>
|
||||
#include <vtkm/cont/ArrayHandleVirtual.hxx>
|
||||
#include <vtkm/cont/ErrorBadType.h>
|
||||
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <typeindex>
|
||||
|
||||
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
@ -221,7 +223,6 @@ struct VTKM_ALWAYS_EXPORT Caster<T, vtkm::cont::StorageTagVirtual>
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT ArrayHandleType Cast(const VariantArrayHandleContainerBase* container)
|
||||
{ //container could be nullptr
|
||||
@ -231,6 +232,54 @@ VTKM_CONT ArrayHandleType Cast(const VariantArrayHandleContainerBase* container)
|
||||
auto ret = Caster<Type, Storage>{}(container);
|
||||
return ArrayHandleType(std::move(ret));
|
||||
}
|
||||
|
||||
struct ForceCastToVirtual
|
||||
{
|
||||
template <typename SrcValueType, typename Storage, typename DstValueType>
|
||||
VTKM_CONT typename std::enable_if<std::is_same<SrcValueType, DstValueType>::value>::type
|
||||
operator()(const vtkm::cont::ArrayHandle<SrcValueType, Storage>& input,
|
||||
vtkm::cont::ArrayHandleVirtual<DstValueType>& output) const
|
||||
{ // ValueTypes match
|
||||
output = vtkm::cont::make_ArrayHandleVirtual<DstValueType>(input);
|
||||
}
|
||||
|
||||
template <typename SrcValueType, typename Storage, typename DstValueType>
|
||||
VTKM_CONT typename std::enable_if<!std::is_same<SrcValueType, DstValueType>::value>::type
|
||||
operator()(const vtkm::cont::ArrayHandle<SrcValueType, Storage>& input,
|
||||
vtkm::cont::ArrayHandleVirtual<DstValueType>& output) const
|
||||
{ // ValueTypes do not match
|
||||
this->ValidateWidthAndCast<SrcValueType, DstValueType>(input, output);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename S,
|
||||
typename D,
|
||||
typename InputType,
|
||||
vtkm::IdComponent SSize = vtkm::VecTraits<S>::NUM_COMPONENTS,
|
||||
vtkm::IdComponent DSize = vtkm::VecTraits<D>::NUM_COMPONENTS>
|
||||
VTKM_CONT typename std::enable_if<SSize == DSize>::type ValidateWidthAndCast(
|
||||
const InputType& input,
|
||||
vtkm::cont::ArrayHandleVirtual<D>& output) const
|
||||
{ // number of components match
|
||||
auto casted = vtkm::cont::make_ArrayHandleCast<D>(input);
|
||||
output = vtkm::cont::make_ArrayHandleVirtual<D>(casted);
|
||||
}
|
||||
|
||||
template <typename S,
|
||||
typename D,
|
||||
vtkm::IdComponent SSize = vtkm::VecTraits<S>::NUM_COMPONENTS,
|
||||
vtkm::IdComponent DSize = vtkm::VecTraits<D>::NUM_COMPONENTS>
|
||||
VTKM_CONT typename std::enable_if<SSize != DSize>::type ValidateWidthAndCast(
|
||||
const ArrayHandleBase&,
|
||||
ArrayHandleBase&) const
|
||||
{ // number of components do not match
|
||||
std::ostringstream str;
|
||||
str << "VariantArrayHandle::AsVirtual: Cannot cast from " << vtkm::cont::TypeToString<S>()
|
||||
<< " to " << vtkm::cont::TypeToString<D>() << "; "
|
||||
"number of components must match exactly.";
|
||||
throw vtkm::cont::ErrorBadType(str.str());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace vtkm
|
||||
@ -266,11 +267,85 @@ void CheckCastToArrayHandle(const ArrayHandleType& array)
|
||||
|
||||
ArrayHandleType castArray2 = arrayVariant.Cast<ArrayHandleType>();
|
||||
VTKM_TEST_ASSERT(array == castArray2, "Did not get back same array.");
|
||||
}
|
||||
|
||||
using T = typename ArrayHandleType::ValueType;
|
||||
vtkm::cont::ArrayHandleVirtual<T> castArray3 = arrayVariant.AsVirtual<T>();
|
||||
VTKM_TEST_ASSERT(castArray3.GetNumberOfValues() == castArray2.GetNumberOfValues(),
|
||||
"Did not get back virtual array handle representation.");
|
||||
// A vtkm::Vec if NumComps > 1, otherwise a scalar
|
||||
template <typename T, vtkm::IdComponent NumComps>
|
||||
using VecOrScalar = typename std::conditional<(NumComps > 1), vtkm::Vec<T, NumComps>, T>::type;
|
||||
|
||||
template <typename ArrayType>
|
||||
void CheckCastToVirtualArrayHandle(const ArrayType& array)
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(ArrayType);
|
||||
|
||||
using ValueType = typename ArrayType::ValueType;
|
||||
using VTraits = vtkm::VecTraits<ValueType>;
|
||||
using ComponentType = typename VTraits::ComponentType;
|
||||
static constexpr vtkm::IdComponent NumComps = VTraits::NUM_COMPONENTS;
|
||||
|
||||
using Storage = typename ArrayType::StorageTag;
|
||||
using StorageList = vtkm::ListTagAppendUnique<VTKM_DEFAULT_STORAGE_LIST_TAG, Storage>;
|
||||
|
||||
using TypeList = vtkm::ListTagAppendUnique<VTKM_DEFAULT_TYPE_LIST_TAG, ValueType>;
|
||||
using VariantArrayType = vtkm::cont::VariantArrayHandleBase<TypeList>;
|
||||
|
||||
VariantArrayType arrayVariant = array;
|
||||
|
||||
{
|
||||
auto testArray = arrayVariant.template AsVirtual<ValueType, StorageList>();
|
||||
VTKM_TEST_ASSERT(testArray.GetNumberOfValues() == array.GetNumberOfValues(),
|
||||
"Did not get back virtual array handle representation.");
|
||||
}
|
||||
|
||||
{
|
||||
auto testArray =
|
||||
arrayVariant.template AsVirtual<VecOrScalar<vtkm::Int8, NumComps>, StorageList>();
|
||||
VTKM_TEST_ASSERT(testArray.GetNumberOfValues() == array.GetNumberOfValues(),
|
||||
"Did not get back virtual array handle representation.");
|
||||
}
|
||||
|
||||
{
|
||||
auto testArray =
|
||||
arrayVariant.template AsVirtual<VecOrScalar<vtkm::Int64, NumComps>, StorageList>();
|
||||
VTKM_TEST_ASSERT(testArray.GetNumberOfValues() == array.GetNumberOfValues(),
|
||||
"Did not get back virtual array handle representation.");
|
||||
}
|
||||
|
||||
{
|
||||
auto testArray =
|
||||
arrayVariant.template AsVirtual<VecOrScalar<vtkm::UInt64, NumComps>, StorageList>();
|
||||
VTKM_TEST_ASSERT(testArray.GetNumberOfValues() == array.GetNumberOfValues(),
|
||||
"Did not get back virtual array handle representation.");
|
||||
}
|
||||
|
||||
{
|
||||
auto testArray =
|
||||
arrayVariant.template AsVirtual<VecOrScalar<vtkm::Float32, NumComps>, StorageList>();
|
||||
VTKM_TEST_ASSERT(testArray.GetNumberOfValues() == array.GetNumberOfValues(),
|
||||
"Did not get back virtual array handle representation.");
|
||||
}
|
||||
|
||||
{
|
||||
auto testArray =
|
||||
arrayVariant.template AsVirtual<VecOrScalar<vtkm::Float64, NumComps>, StorageList>();
|
||||
VTKM_TEST_ASSERT(testArray.GetNumberOfValues() == array.GetNumberOfValues(),
|
||||
"Did not get back virtual array handle representation.");
|
||||
}
|
||||
|
||||
bool threw = false;
|
||||
try
|
||||
{
|
||||
arrayVariant.template AsVirtual<vtkm::Vec<ComponentType, NumComps + 1>, StorageList>();
|
||||
}
|
||||
catch (vtkm::cont::ErrorBadType&)
|
||||
{
|
||||
// caught expected exception
|
||||
threw = true;
|
||||
}
|
||||
|
||||
VTKM_TEST_ASSERT(threw,
|
||||
"Casting to different vector width did not throw expected "
|
||||
"ErrorBadType exception.");
|
||||
}
|
||||
|
||||
template <typename T, typename ArrayVariantType>
|
||||
@ -385,6 +460,13 @@ void TryUnusualTypeAndStorage()
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
void TryCastToArrayHandle(const ArrayHandleType& array)
|
||||
{
|
||||
CheckCastToArrayHandle(array);
|
||||
CheckCastToVirtualArrayHandle(array);
|
||||
}
|
||||
|
||||
void TryCastToArrayHandle()
|
||||
{
|
||||
std::cout << " Normal array handle." << std::endl;
|
||||
@ -393,42 +475,43 @@ void TryCastToArrayHandle()
|
||||
{
|
||||
buffer[index] = TestValue(index, vtkm::Id());
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> array = vtkm::cont::make_ArrayHandle(buffer, ARRAY_SIZE);
|
||||
CheckCastToArrayHandle(array);
|
||||
TryCastToArrayHandle(array);
|
||||
|
||||
std::cout << " Cast array handle." << std::endl;
|
||||
CheckCastToArrayHandle(vtkm::cont::make_ArrayHandleCast(array, vtkm::FloatDefault()));
|
||||
TryCastToArrayHandle(vtkm::cont::make_ArrayHandleCast(array, vtkm::FloatDefault()));
|
||||
|
||||
std::cout << " Composite vector array handle." << std::endl;
|
||||
CheckCastToArrayHandle(vtkm::cont::make_ArrayHandleCompositeVector(array, array));
|
||||
TryCastToArrayHandle(vtkm::cont::make_ArrayHandleCompositeVector(array, array));
|
||||
|
||||
std::cout << " Constant array handle." << std::endl;
|
||||
CheckCastToArrayHandle(vtkm::cont::make_ArrayHandleConstant(5, ARRAY_SIZE));
|
||||
TryCastToArrayHandle(vtkm::cont::make_ArrayHandleConstant(5, ARRAY_SIZE));
|
||||
|
||||
std::cout << " Counting array handle." << std::endl;
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> countingArray(ARRAY_SIZE - 1, -1, ARRAY_SIZE);
|
||||
CheckCastToArrayHandle(countingArray);
|
||||
TryCastToArrayHandle(countingArray);
|
||||
|
||||
std::cout << " Group vec array handle" << std::endl;
|
||||
vtkm::cont::ArrayHandleGroupVec<vtkm::cont::ArrayHandle<vtkm::Id>, 2> groupVecArray(array);
|
||||
CheckCastToArrayHandle(groupVecArray);
|
||||
TryCastToArrayHandle(groupVecArray);
|
||||
|
||||
std::cout << " Implicit array handle." << std::endl;
|
||||
CheckCastToArrayHandle(
|
||||
TryCastToArrayHandle(
|
||||
vtkm::cont::make_ArrayHandleImplicit(TestValueFunctor<vtkm::FloatDefault>(), ARRAY_SIZE));
|
||||
|
||||
std::cout << " Index array handle." << std::endl;
|
||||
CheckCastToArrayHandle(vtkm::cont::ArrayHandleIndex(ARRAY_SIZE));
|
||||
TryCastToArrayHandle(vtkm::cont::ArrayHandleIndex(ARRAY_SIZE));
|
||||
|
||||
std::cout << " Permutation array handle." << std::endl;
|
||||
CheckCastToArrayHandle(vtkm::cont::make_ArrayHandlePermutation(countingArray, array));
|
||||
TryCastToArrayHandle(vtkm::cont::make_ArrayHandlePermutation(countingArray, array));
|
||||
|
||||
std::cout << " Transform array handle." << std::endl;
|
||||
CheckCastToArrayHandle(
|
||||
TryCastToArrayHandle(
|
||||
vtkm::cont::make_ArrayHandleTransform(countingArray, TestValueFunctor<vtkm::FloatDefault>()));
|
||||
|
||||
std::cout << " Uniform point coordinates array handle." << std::endl;
|
||||
CheckCastToArrayHandle(vtkm::cont::ArrayHandleUniformPointCoordinates(vtkm::Id3(ARRAY_SIZE)));
|
||||
TryCastToArrayHandle(vtkm::cont::ArrayHandleUniformPointCoordinates(vtkm::Id3(ARRAY_SIZE)));
|
||||
|
||||
// std::cout << " Zip array handle." << std::endl;
|
||||
// CheckCastToArrayHandle(vtkm::cont::make_ArrayHandleZip(countingArray, array));
|
||||
|
Loading…
Reference in New Issue
Block a user