Merge topic 'replace-variantarrayhandle-impl'
386301719 Test UnknownArrayHandle behavior on special arrays 872da1f8e Suppress unnecessary deprecation warnings on VS bb443bbc2 Replace the implementation of VariantArrayHandle Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Robert Maynard <robert.maynard@kitware.com> Merge-request: !2255
This commit is contained in:
commit
06579aac8c
@ -183,7 +183,6 @@ set(sources
|
|||||||
DataSetBuilderExplicit.cxx
|
DataSetBuilderExplicit.cxx
|
||||||
DataSetBuilderRectilinear.cxx
|
DataSetBuilderRectilinear.cxx
|
||||||
DataSetBuilderUniform.cxx
|
DataSetBuilderUniform.cxx
|
||||||
internal/VariantArrayHandleContainer.cxx
|
|
||||||
Field.cxx
|
Field.cxx
|
||||||
FieldRangeCompute.cxx
|
FieldRangeCompute.cxx
|
||||||
FieldRangeGlobalCompute.cxx
|
FieldRangeGlobalCompute.cxx
|
||||||
|
@ -220,6 +220,7 @@ class VTKM_CONT_EXPORT UnknownArrayHandle
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
VTKM_CONT UnknownArrayHandle() = default;
|
VTKM_CONT UnknownArrayHandle() = default;
|
||||||
|
UnknownArrayHandle(const UnknownArrayHandle&) = default;
|
||||||
|
|
||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
VTKM_CONT UnknownArrayHandle(const vtkm::cont::ArrayHandle<T, S>& array)
|
VTKM_CONT UnknownArrayHandle(const vtkm::cont::ArrayHandle<T, S>& array)
|
||||||
@ -227,6 +228,8 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnknownArrayHandle& operator=(const vtkm::cont::UnknownArrayHandle&) = default;
|
||||||
|
|
||||||
/// \brief Create a new array of the same type as this array.
|
/// \brief Create a new array of the same type as this array.
|
||||||
///
|
///
|
||||||
/// This method creates a new array that is the same type as this one and
|
/// This method creates a new array that is the same type as this one and
|
||||||
@ -323,6 +326,14 @@ public:
|
|||||||
template <typename ArrayHandleType>
|
template <typename ArrayHandleType>
|
||||||
VTKM_CONT bool CanConvert() const;
|
VTKM_CONT bool CanConvert() const;
|
||||||
|
|
||||||
|
// MSVC will issue deprecation warnings here if this template is instantiated with
|
||||||
|
// a deprecated class even if the template is used from a section of code where
|
||||||
|
// deprecation warnings are suppressed. This is annoying behavior since this template
|
||||||
|
// has no control over what class it is used with. To get around it, we have to
|
||||||
|
// suppress all deprecation warnings here.
|
||||||
|
#ifdef VTKM_MSVC
|
||||||
|
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||||
|
#endif
|
||||||
///@{
|
///@{
|
||||||
/// Returns this array cast appropriately and stored in the given `ArrayHandle` type.
|
/// Returns this array cast appropriately and stored in the given `ArrayHandle` type.
|
||||||
/// Throws an `ErrorBadType` if the stored array cannot be stored in the given array type.
|
/// Throws an `ErrorBadType` if the stored array cannot be stored in the given array type.
|
||||||
@ -363,6 +374,9 @@ public:
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
///@}
|
///@}
|
||||||
|
#ifdef VTKM_MSVC
|
||||||
|
VTKM_DEPRECATED_SUPPRESS_END
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Call a functor using the underlying array type.
|
/// \brief Call a functor using the underlying array type.
|
||||||
///
|
///
|
||||||
@ -476,8 +490,17 @@ struct UnknownArrayHandleMultplexerCastTry
|
|||||||
bool& converted) const
|
bool& converted) const
|
||||||
{
|
{
|
||||||
using ArrayType = vtkm::cont::ArrayHandle<T, S>;
|
using ArrayType = vtkm::cont::ArrayHandle<T, S>;
|
||||||
if (!converted && unknownArray.CanConvert<ArrayType>())
|
if (unknownArray.CanConvert<ArrayType>())
|
||||||
{
|
{
|
||||||
|
if (converted && !unknownArray.IsType<ArrayType>())
|
||||||
|
{
|
||||||
|
// The array has already been converted and pushed in the multiplexer. It is
|
||||||
|
// possible that multiple array types can be put in the ArrayHandleMultiplexer
|
||||||
|
// (for example, and ArrayHandle or an ArrayHandle that has been cast). Exact
|
||||||
|
// matches will override other matches (hence, the second part of the condition),
|
||||||
|
// but at this point we have already found a better array to put inside.
|
||||||
|
return;
|
||||||
|
}
|
||||||
outputArray.GetStorage().SetArray(unknownArray.AsArrayHandle<ArrayType>());
|
outputArray.GetStorage().SetArray(unknownArray.AsArrayHandle<ArrayType>());
|
||||||
converted = true;
|
converted = true;
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,71 @@
|
|||||||
#include <vtkm/cont/ErrorBadType.h>
|
#include <vtkm/cont/ErrorBadType.h>
|
||||||
#include <vtkm/cont/Logging.h>
|
#include <vtkm/cont/Logging.h>
|
||||||
#include <vtkm/cont/StorageList.h>
|
#include <vtkm/cont/StorageList.h>
|
||||||
|
#include <vtkm/cont/UncertainArrayHandle.h>
|
||||||
#include <vtkm/cont/internal/VariantArrayHandleContainer.h>
|
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
namespace cont
|
namespace cont
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
namespace variant
|
||||||
|
{
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace internal::variant
|
||||||
|
|
||||||
/// \brief VariantArrayHandle superclass holding common operations.
|
/// \brief VariantArrayHandle superclass holding common operations.
|
||||||
///
|
///
|
||||||
/// `VariantArrayHandleCommon` is a superclass to all `VariantArrayHandleBase`
|
/// `VariantArrayHandleCommon` is a superclass to all `VariantArrayHandleBase`
|
||||||
@ -40,43 +97,28 @@ namespace cont
|
|||||||
///
|
///
|
||||||
/// See the documentation of `VariantArrayHandleBase` for more information.
|
/// See the documentation of `VariantArrayHandleBase` for more information.
|
||||||
///
|
///
|
||||||
class VTKM_ALWAYS_EXPORT VariantArrayHandleCommon
|
class VTKM_ALWAYS_EXPORT VariantArrayHandleCommon : public vtkm::cont::UnknownArrayHandle
|
||||||
{
|
{
|
||||||
std::shared_ptr<vtkm::cont::internal::VariantArrayHandleContainerBase> ArrayContainer;
|
using Superclass = vtkm::cont::UnknownArrayHandle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Superclass::Superclass;
|
||||||
|
|
||||||
VTKM_CONT VariantArrayHandleCommon() = default;
|
VTKM_CONT VariantArrayHandleCommon() = default;
|
||||||
|
|
||||||
template <typename T, typename Storage>
|
VTKM_CONT VariantArrayHandleCommon(const vtkm::cont::UnknownArrayHandle& array)
|
||||||
VTKM_CONT VariantArrayHandleCommon(const vtkm::cont::ArrayHandle<T, Storage>& array)
|
: Superclass(array)
|
||||||
: ArrayContainer(std::make_shared<internal::VariantArrayHandleContainer<T>>(
|
|
||||||
vtkm::cont::ArrayHandleVirtual<T>{ array }))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
// MSVC will issue deprecation warnings here if this template is instantiated with
|
||||||
VTKM_CONT VariantArrayHandleCommon(
|
// a deprecated class even if the template is used from a section of code where
|
||||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>& array)
|
// deprecation warnings are suppressed. This is annoying behavior since this template
|
||||||
: ArrayContainer(std::make_shared<internal::VariantArrayHandleContainer<T>>(array))
|
// has no control over what class it is used with. To get around it, we have to
|
||||||
{
|
// suppress all deprecation warnings here.
|
||||||
}
|
#ifdef VTKM_MSVC
|
||||||
|
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
||||||
/// Returns true if this array matches the array handle type passed in.
|
#endif
|
||||||
///
|
|
||||||
template <typename ArrayHandleType>
|
|
||||||
VTKM_CONT bool IsType() const
|
|
||||||
{
|
|
||||||
return internal::variant::IsType<ArrayHandleType>(this->ArrayContainer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if this array matches the ValueType type passed in.
|
|
||||||
///
|
|
||||||
template <typename T>
|
|
||||||
VTKM_CONT bool IsValueType() const
|
|
||||||
{
|
|
||||||
return internal::variant::IsValueType<T>(this->ArrayContainer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns this array cast to the given \c ArrayHandle type. Throws \c
|
/// Returns this array cast to the given \c ArrayHandle type. Throws \c
|
||||||
/// ErrorBadType if the cast does not work. Use \c IsType
|
/// ErrorBadType if the cast does not work. Use \c IsType
|
||||||
/// to check if the cast can happen.
|
/// to check if the cast can happen.
|
||||||
@ -84,19 +126,11 @@ public:
|
|||||||
template <typename ArrayHandleType>
|
template <typename ArrayHandleType>
|
||||||
VTKM_CONT ArrayHandleType Cast() const
|
VTKM_CONT ArrayHandleType Cast() const
|
||||||
{
|
{
|
||||||
// MSVC will issue deprecation warnings if this templated method is instantiated with
|
return this->AsArrayHandle<ArrayHandleType>();
|
||||||
// a deprecated class here even if the method is called from a section of code where
|
|
||||||
// deprecation warnings are suppressed. This is annoying behavior since this templated
|
|
||||||
// method has no control over what class it is used from. To get around it, we have to
|
|
||||||
// suppress all deprecation warnings here.
|
|
||||||
#ifdef VTKM_MSVC
|
|
||||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
|
||||||
#endif
|
|
||||||
return internal::variant::Cast<ArrayHandleType>(this->ArrayContainer.get());
|
|
||||||
#ifdef VTKM_MSVC
|
|
||||||
VTKM_DEPRECATED_SUPPRESS_END
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#ifdef VTKM_MSVC
|
||||||
|
VTKM_DEPRECATED_SUPPRESS_END
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Call a functor using the underlying array type.
|
/// \brief Call a functor using the underlying array type.
|
||||||
///
|
///
|
||||||
@ -106,7 +140,11 @@ public:
|
|||||||
/// calling differs from that of the `CastAndCall` methods of subclasses.)
|
/// calling differs from that of the `CastAndCall` methods of subclasses.)
|
||||||
///
|
///
|
||||||
template <typename TypeList, typename StorageList, typename Functor, typename... Args>
|
template <typename TypeList, typename StorageList, typename Functor, typename... Args>
|
||||||
VTKM_CONT void CastAndCall(Functor&& functor, Args&&... args) const;
|
VTKM_CONT void CastAndCall(Functor&& functor, Args&&... args) const
|
||||||
|
{
|
||||||
|
this->CastAndCallForTypes<TypeList, StorageList>(std::forward<Functor>(functor),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns this array cast to a `ArrayHandleVirtual` of the given type.
|
/// Returns this array cast to a `ArrayHandleVirtual` of the given type.
|
||||||
/// This will perform type conversions as necessary, and will log warnings
|
/// This will perform type conversions as necessary, and will log warnings
|
||||||
@ -141,7 +179,10 @@ public:
|
|||||||
///
|
///
|
||||||
///@{
|
///@{
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
VTKM_CONT void AsMultiplexer(vtkm::cont::ArrayHandleMultiplexer<T...>& result) const;
|
VTKM_CONT void AsMultiplexer(vtkm::cont::ArrayHandleMultiplexer<T...>& result) const
|
||||||
|
{
|
||||||
|
this->AsArrayHandle(result);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ArrayHandleMultiplexerType>
|
template <typename ArrayHandleMultiplexerType>
|
||||||
VTKM_CONT ArrayHandleMultiplexerType AsMultiplexer() const
|
VTKM_CONT ArrayHandleMultiplexerType AsMultiplexer() const
|
||||||
@ -175,40 +216,8 @@ public:
|
|||||||
///
|
///
|
||||||
VTKM_CONT VariantArrayHandleCommon NewInstance() const
|
VTKM_CONT VariantArrayHandleCommon NewInstance() const
|
||||||
{
|
{
|
||||||
VariantArrayHandleCommon instance;
|
return VariantArrayHandleCommon(this->Superclass::NewInstance());
|
||||||
instance.ArrayContainer = this->ArrayContainer->NewInstance();
|
|
||||||
return instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Releases any resources being used in the execution environment (that are
|
|
||||||
/// not being shared by the control environment).
|
|
||||||
///
|
|
||||||
void ReleaseResourcesExecution() { return this->ArrayContainer->ReleaseResourcesExecution(); }
|
|
||||||
|
|
||||||
|
|
||||||
/// Releases all resources in both the control and execution environments.
|
|
||||||
///
|
|
||||||
void ReleaseResources() { return this->ArrayContainer->ReleaseResources(); }
|
|
||||||
|
|
||||||
/// \brief Get the number of components in each array value.
|
|
||||||
///
|
|
||||||
/// This method will query the array type for the number of components in
|
|
||||||
/// each value of the array. The number of components is determined by
|
|
||||||
/// the \c VecTraits::NUM_COMPONENTS trait class.
|
|
||||||
///
|
|
||||||
VTKM_CONT
|
|
||||||
vtkm::IdComponent GetNumberOfComponents() const
|
|
||||||
{
|
|
||||||
return this->ArrayContainer->GetNumberOfComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Get the number of values in the array.
|
|
||||||
///
|
|
||||||
VTKM_CONT
|
|
||||||
vtkm::Id GetNumberOfValues() const { return this->ArrayContainer->GetNumberOfValues(); }
|
|
||||||
|
|
||||||
VTKM_CONT
|
|
||||||
void PrintSummary(std::ostream& out) const { this->ArrayContainer->PrintSummary(out); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Holds an array handle without having to specify template parameters.
|
/// \brief Holds an array handle without having to specify template parameters.
|
||||||
@ -263,6 +272,18 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VTKM_CONT explicit VariantArrayHandleBase(const vtkm::cont::UnknownArrayHandle& src)
|
||||||
|
: Superclass(src)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename StorageList>
|
||||||
|
VTKM_CONT VariantArrayHandleBase(
|
||||||
|
const vtkm::cont::UncertainArrayHandle<TypeList, StorageList>& src)
|
||||||
|
: Superclass(src)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
VTKM_CONT VariantArrayHandleBase(const VariantArrayHandleBase&) = default;
|
VTKM_CONT VariantArrayHandleBase(const VariantArrayHandleBase&) = default;
|
||||||
VTKM_CONT VariantArrayHandleBase(VariantArrayHandleBase&&) noexcept = default;
|
VTKM_CONT VariantArrayHandleBase(VariantArrayHandleBase&&) noexcept = default;
|
||||||
|
|
||||||
@ -276,6 +297,11 @@ public:
|
|||||||
VariantArrayHandleBase<TypeList>& operator=(VariantArrayHandleBase<TypeList>&&) noexcept =
|
VariantArrayHandleBase<TypeList>& operator=(VariantArrayHandleBase<TypeList>&&) noexcept =
|
||||||
default;
|
default;
|
||||||
|
|
||||||
|
VTKM_CONT operator vtkm::cont::UncertainArrayHandle<TypeList, VTKM_DEFAULT_STORAGE_LIST>() const
|
||||||
|
{
|
||||||
|
return vtkm::cont::UncertainArrayHandle<TypeList, VTKM_DEFAULT_STORAGE_LIST>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Returns this array cast to a \c ArrayHandleVirtual of the given type.
|
/// Returns this array cast to a \c ArrayHandleVirtual of the given type.
|
||||||
/// This will perform type conversions as necessary, and will log warnings
|
/// This will perform type conversions as necessary, and will log warnings
|
||||||
@ -392,207 +418,6 @@ VTKM_CONT inline ArrayHandleType Cast(const vtkm::cont::VariantArrayHandleBase<T
|
|||||||
return variant.template Cast<ArrayHandleType>();
|
return variant.template Cast<ArrayHandleType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// Out of class implementations
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
struct VariantArrayHandleTry
|
|
||||||
{
|
|
||||||
template <typename T, typename Storage, typename Functor, typename... Args>
|
|
||||||
void operator()(vtkm::List<T, Storage>,
|
|
||||||
Functor&& f,
|
|
||||||
bool& called,
|
|
||||||
const vtkm::cont::internal::VariantArrayHandleContainerBase& container,
|
|
||||||
Args&&... args) const
|
|
||||||
{
|
|
||||||
using DerivedArrayType = vtkm::cont::ArrayHandle<T, Storage>;
|
|
||||||
if (!called && vtkm::cont::internal::variant::IsType<DerivedArrayType>(&container))
|
|
||||||
{
|
|
||||||
called = true;
|
|
||||||
const auto* derivedContainer =
|
|
||||||
static_cast<const vtkm::cont::internal::VariantArrayHandleContainer<T>*>(&container);
|
|
||||||
DerivedArrayType derivedArray = derivedContainer->Array.template Cast<DerivedArrayType>();
|
|
||||||
VTKM_LOG_CAST_SUCC(container, derivedArray);
|
|
||||||
|
|
||||||
// If you get a compile error here, it means that you have called CastAndCall for a
|
|
||||||
// vtkm::cont::VariantArrayHandle and the arguments of the functor do not match those
|
|
||||||
// being passed. This is often because it is calling the functor with an ArrayHandle
|
|
||||||
// type that was not expected. Either add overloads to the functor to accept all
|
|
||||||
// possible array types or constrain the types tried for the CastAndCall. Note that
|
|
||||||
// the functor will be called with an array of type vtkm::cont::ArrayHandle<T, S>.
|
|
||||||
// Directly using a subclass of ArrayHandle (e.g. vtkm::cont::ArrayHandleConstant<T>)
|
|
||||||
// might not work.
|
|
||||||
f(derivedArray, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct IsUndefinedStorage
|
|
||||||
{
|
|
||||||
};
|
|
||||||
template <typename T, typename U>
|
|
||||||
struct IsUndefinedStorage<vtkm::List<T, U>> : vtkm::cont::internal::IsInvalidArrayHandle<T, U>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TypeList, typename StorageList>
|
|
||||||
using ListDynamicTypes =
|
|
||||||
vtkm::ListRemoveIf<vtkm::ListCross<TypeList, StorageList>, IsUndefinedStorage>;
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename TypeList, typename StorageTagList, typename Functor, typename... Args>
|
|
||||||
VTKM_CONT void VariantArrayHandleCommon::CastAndCall(Functor&& f, Args&&... args) const
|
|
||||||
{
|
|
||||||
using crossProduct = detail::ListDynamicTypes<TypeList, StorageTagList>;
|
|
||||||
|
|
||||||
bool called = false;
|
|
||||||
const auto& ref = *this->ArrayContainer;
|
|
||||||
vtkm::ListForEach(detail::VariantArrayHandleTry{},
|
|
||||||
crossProduct{},
|
|
||||||
std::forward<Functor>(f),
|
|
||||||
called,
|
|
||||||
ref,
|
|
||||||
std::forward<Args>(args)...);
|
|
||||||
if (!called)
|
|
||||||
{
|
|
||||||
// throw an exception
|
|
||||||
VTKM_LOG_CAST_FAIL(*this, TypeList);
|
|
||||||
detail::ThrowCastAndCallException(ref, typeid(TypeList));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
struct VariantArrayHandleTryMultiplexer
|
|
||||||
{
|
|
||||||
template <typename T, typename Storage, typename... ArrayTypes>
|
|
||||||
VTKM_CONT void operator()(const vtkm::cont::ArrayHandle<T, Storage>&,
|
|
||||||
const vtkm::cont::VariantArrayHandleCommon& self,
|
|
||||||
vtkm::cont::ArrayHandleMultiplexer<ArrayTypes...>& result) const
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandle<T, Storage> targetArray;
|
|
||||||
bool foundArray = false;
|
|
||||||
this->FetchArray(targetArray, self, foundArray, result.IsValid());
|
|
||||||
if (foundArray)
|
|
||||||
{
|
|
||||||
result.SetArray(targetArray);
|
|
||||||
VTKM_LOG_CAST_SUCC(self, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename T, typename Storage>
|
|
||||||
VTKM_CONT void FetchArrayExact(vtkm::cont::ArrayHandle<T, Storage>& targetArray,
|
|
||||||
const vtkm::cont::VariantArrayHandleCommon& self,
|
|
||||||
bool& foundArray) const
|
|
||||||
{
|
|
||||||
using ArrayType = vtkm::cont::ArrayHandle<T, Storage>;
|
|
||||||
if (self.IsType<ArrayType>())
|
|
||||||
{
|
|
||||||
targetArray = self.Cast<ArrayType>();
|
|
||||||
foundArray = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foundArray = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Storage>
|
|
||||||
VTKM_CONT void FetchArray(vtkm::cont::ArrayHandle<T, Storage>& targetArray,
|
|
||||||
const vtkm::cont::VariantArrayHandleCommon& self,
|
|
||||||
bool& foundArray,
|
|
||||||
bool vtkmNotUsed(foundArrayInPreviousCall)) const
|
|
||||||
{
|
|
||||||
this->FetchArrayExact(targetArray, self, foundArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special condition for transformed arrays. Instead of pulling out the
|
|
||||||
// transform, pull out the array that is being transformed.
|
|
||||||
template <typename T, typename SrcArray, typename ForwardTransform, typename ReverseTransform>
|
|
||||||
VTKM_CONT void FetchArray(
|
|
||||||
vtkm::cont::ArrayHandle<
|
|
||||||
T,
|
|
||||||
vtkm::cont::internal::StorageTagTransform<SrcArray, ForwardTransform, ReverseTransform>>&
|
|
||||||
targetArray,
|
|
||||||
const vtkm::cont::VariantArrayHandleCommon& self,
|
|
||||||
bool& foundArray,
|
|
||||||
bool foundArrayInPreviousCall) const
|
|
||||||
{
|
|
||||||
// Attempt to get the array itself first
|
|
||||||
this->FetchArrayExact(targetArray, self, foundArray);
|
|
||||||
|
|
||||||
// Try to get the array to be transformed first, but only do so if the array was not already
|
|
||||||
// found in another call to this functor. This is to give precedence to getting the array
|
|
||||||
// exactly rather than creating our own transform.
|
|
||||||
if (!foundArray && !foundArrayInPreviousCall)
|
|
||||||
{
|
|
||||||
SrcArray srcArray;
|
|
||||||
this->FetchArray(srcArray, self, foundArray, foundArrayInPreviousCall);
|
|
||||||
if (foundArray)
|
|
||||||
{
|
|
||||||
targetArray =
|
|
||||||
vtkm::cont::ArrayHandleTransform<SrcArray, ForwardTransform, ReverseTransform>(srcArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special condition for cast arrays. Instead of pulling out an ArrayHandleCast, pull out
|
|
||||||
// the array that is being cast.
|
|
||||||
template <typename TargetT, typename SourceT, typename SourceStorage>
|
|
||||||
VTKM_CONT void FetchArray(
|
|
||||||
vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>>&
|
|
||||||
targetArray,
|
|
||||||
const vtkm::cont::VariantArrayHandleCommon& self,
|
|
||||||
bool& foundArray,
|
|
||||||
bool foundArrayInPreviousCall) const
|
|
||||||
{
|
|
||||||
// Attempt to get the array itself first
|
|
||||||
this->FetchArrayExact(targetArray, self, foundArray);
|
|
||||||
|
|
||||||
// Try to get the array to be transformed first, but only do so if the array was not already
|
|
||||||
// found in another call to this functor. This is to give precedence to getting the array
|
|
||||||
// exactly rather than creating our own transform.
|
|
||||||
if (!foundArray && !foundArrayInPreviousCall)
|
|
||||||
{
|
|
||||||
using SrcArray = vtkm::cont::ArrayHandle<SourceT, SourceStorage>;
|
|
||||||
SrcArray srcArray;
|
|
||||||
this->FetchArray(srcArray, self, foundArray, foundArrayInPreviousCall);
|
|
||||||
if (foundArray)
|
|
||||||
{
|
|
||||||
targetArray =
|
|
||||||
vtkm::cont::ArrayHandleCast<TargetT, vtkm::cont::ArrayHandle<SourceT, SourceStorage>>(
|
|
||||||
srcArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename... T>
|
|
||||||
inline VTKM_CONT void VariantArrayHandleCommon::AsMultiplexer(
|
|
||||||
vtkm::cont::ArrayHandleMultiplexer<T...>& result) const
|
|
||||||
{
|
|
||||||
// Make sure IsValid is clear
|
|
||||||
result = vtkm::cont::ArrayHandleMultiplexer<T...>{};
|
|
||||||
vtkm::ListForEach(detail::VariantArrayHandleTryMultiplexer{}, vtkm::List<T...>{}, *this, result);
|
|
||||||
if (!result.IsValid())
|
|
||||||
{
|
|
||||||
// Could not put the class into the multiplexer. Throw an exception.
|
|
||||||
VTKM_LOG_CAST_FAIL(*this, vtkm::List<T...>);
|
|
||||||
detail::ThrowAsMultiplexerException(*this->ArrayContainer, { typeid(T).name()... });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -612,72 +437,24 @@ struct DynamicTransformTraits<vtkm::cont::VariantArrayHandleBase<TypeList>>
|
|||||||
namespace mangled_diy_namespace
|
namespace mangled_diy_namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace internal
|
|
||||||
{
|
|
||||||
|
|
||||||
struct VariantArrayHandleSerializeFunctor
|
|
||||||
{
|
|
||||||
template <typename ArrayHandleType>
|
|
||||||
void operator()(const ArrayHandleType& ah, BinaryBuffer& bb) const
|
|
||||||
{
|
|
||||||
vtkmdiy::save(bb, vtkm::cont::SerializableTypeString<ArrayHandleType>::Get());
|
|
||||||
vtkmdiy::save(bb, ah);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VariantArrayHandleDeserializeFunctor
|
|
||||||
{
|
|
||||||
template <typename T, typename S, typename TypeList>
|
|
||||||
void operator()(vtkm::List<T, S>,
|
|
||||||
vtkm::cont::VariantArrayHandleBase<TypeList>& dh,
|
|
||||||
const std::string& typeString,
|
|
||||||
bool& success,
|
|
||||||
BinaryBuffer& bb) const
|
|
||||||
{
|
|
||||||
using ArrayHandleType = vtkm::cont::ArrayHandle<T, S>;
|
|
||||||
|
|
||||||
if (!success && (typeString == vtkm::cont::SerializableTypeString<ArrayHandleType>::Get()))
|
|
||||||
{
|
|
||||||
ArrayHandleType ah;
|
|
||||||
vtkmdiy::load(bb, ah);
|
|
||||||
dh = vtkm::cont::VariantArrayHandleBase<TypeList>(ah);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // internal
|
|
||||||
|
|
||||||
template <typename TypeList>
|
template <typename TypeList>
|
||||||
struct Serialization<vtkm::cont::VariantArrayHandleBase<TypeList>>
|
struct Serialization<vtkm::cont::VariantArrayHandleBase<TypeList>>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using Type = vtkm::cont::VariantArrayHandleBase<TypeList>;
|
using Type = vtkm::cont::VariantArrayHandleBase<TypeList>;
|
||||||
|
using ImplObject = vtkm::cont::UncertainArrayHandle<TypeList, VTKM_DEFAULT_STORAGE_LIST>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static VTKM_CONT void save(BinaryBuffer& bb, const Type& obj)
|
static VTKM_CONT void save(BinaryBuffer& bb, const Type& obj)
|
||||||
{
|
{
|
||||||
obj.CastAndCall(internal::VariantArrayHandleSerializeFunctor{}, bb);
|
vtkmdiy::save(bb, ImplObject(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
static VTKM_CONT void load(BinaryBuffer& bb, Type& obj)
|
static VTKM_CONT void load(BinaryBuffer& bb, Type& obj)
|
||||||
{
|
{
|
||||||
std::string typeString;
|
ImplObject implObj;
|
||||||
vtkmdiy::load(bb, typeString);
|
vtkmdiy::load(bb, implObj);
|
||||||
|
obj = implObj;
|
||||||
bool success = false;
|
|
||||||
vtkm::ListForEach(internal::VariantArrayHandleDeserializeFunctor{},
|
|
||||||
vtkm::cont::detail::ListDynamicTypes<TypeList, VTKM_DEFAULT_STORAGE_LIST>{},
|
|
||||||
obj,
|
|
||||||
typeString,
|
|
||||||
success,
|
|
||||||
bb);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
throw vtkm::cont::ErrorBadType(
|
|
||||||
"Error deserializing VariantArrayHandle. Message TypeString: " + typeString);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ set(headers
|
|||||||
ReverseConnectivityBuilder.h
|
ReverseConnectivityBuilder.h
|
||||||
StorageError.h
|
StorageError.h
|
||||||
TransferInfo.h
|
TransferInfo.h
|
||||||
VariantArrayHandleContainer.h
|
|
||||||
VirtualObjectTransfer.h
|
VirtualObjectTransfer.h
|
||||||
VirtualObjectTransferInstantiate.h
|
VirtualObjectTransferInstantiate.h
|
||||||
VirtualObjectTransferShareWithControl.h
|
VirtualObjectTransferShareWithControl.h
|
||||||
|
@ -1,68 +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 <sstream>
|
|
||||||
#include <typeindex>
|
|
||||||
|
|
||||||
#include <vtkm/cont/ErrorBadValue.h>
|
|
||||||
#include <vtkm/cont/internal/VariantArrayHandleContainer.h>
|
|
||||||
|
|
||||||
namespace vtkm
|
|
||||||
{
|
|
||||||
namespace cont
|
|
||||||
{
|
|
||||||
namespace internal
|
|
||||||
{
|
|
||||||
|
|
||||||
VariantArrayHandleContainerBase::VariantArrayHandleContainerBase()
|
|
||||||
: TypeIndex(typeid(nullptr))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantArrayHandleContainerBase::VariantArrayHandleContainerBase(const std::type_info& typeinfo)
|
|
||||||
: TypeIndex(typeinfo)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantArrayHandleContainerBase::~VariantArrayHandleContainerBase() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
VTKM_CONT_EXPORT void ThrowCastAndCallException(
|
|
||||||
const vtkm::cont::internal::VariantArrayHandleContainerBase& ref,
|
|
||||||
const std::type_info& type)
|
|
||||||
{
|
|
||||||
std::ostringstream out;
|
|
||||||
out << "Could not find appropriate cast for array in CastAndCall.\n"
|
|
||||||
"Array: ";
|
|
||||||
ref.PrintSummary(out);
|
|
||||||
out << "TypeList: " << type.name() << "\n";
|
|
||||||
throw vtkm::cont::ErrorBadValue(out.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT_EXPORT void ThrowAsMultiplexerException(
|
|
||||||
const vtkm::cont::internal::VariantArrayHandleContainerBase& ref,
|
|
||||||
const std::initializer_list<std::string>& arrayTypes)
|
|
||||||
{
|
|
||||||
std::ostringstream out;
|
|
||||||
out << "Could not find appropriate cast for array in AsMultiplexer.\n"
|
|
||||||
"Array: ";
|
|
||||||
ref.PrintSummary(out);
|
|
||||||
out << "Supported arrays:\n";
|
|
||||||
for (auto&& type : arrayTypes)
|
|
||||||
{
|
|
||||||
out << " " << type << "\n";
|
|
||||||
}
|
|
||||||
throw vtkm::cont::ErrorBadValue(out.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace vtkm::cont::detail
|
|
@ -1,301 +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_cont_VariantArrayHandleContainer_h
|
|
||||||
#define vtk_m_cont_VariantArrayHandleContainer_h
|
|
||||||
|
|
||||||
#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
|
|
||||||
{
|
|
||||||
|
|
||||||
// Forward declaration needed for GetContainer
|
|
||||||
template <typename TypeList>
|
|
||||||
class VariantArrayHandleBase;
|
|
||||||
|
|
||||||
namespace internal
|
|
||||||
{
|
|
||||||
|
|
||||||
/// \brief Base class for VariantArrayHandleContainer
|
|
||||||
///
|
|
||||||
struct VTKM_CONT_EXPORT VariantArrayHandleContainerBase
|
|
||||||
{
|
|
||||||
std::type_index TypeIndex;
|
|
||||||
|
|
||||||
VariantArrayHandleContainerBase();
|
|
||||||
explicit VariantArrayHandleContainerBase(const std::type_info& hash);
|
|
||||||
|
|
||||||
// This must exist so that subclasses are destroyed correctly.
|
|
||||||
virtual ~VariantArrayHandleContainerBase();
|
|
||||||
|
|
||||||
virtual vtkm::Id GetNumberOfValues() const = 0;
|
|
||||||
virtual vtkm::IdComponent GetNumberOfComponents() const = 0;
|
|
||||||
|
|
||||||
virtual void ReleaseResourcesExecution() = 0;
|
|
||||||
virtual void ReleaseResources() = 0;
|
|
||||||
|
|
||||||
virtual void PrintSummary(std::ostream& out) const = 0;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<VariantArrayHandleContainerBase> NewInstance() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief ArrayHandle container that can use C++ run-time type information.
|
|
||||||
///
|
|
||||||
/// The \c VariantArrayHandleContainer holds ArrayHandle objects
|
|
||||||
/// (with different template parameters) so that it can polymorphically answer
|
|
||||||
/// simple questions about the object.
|
|
||||||
///
|
|
||||||
template <typename T>
|
|
||||||
struct VTKM_ALWAYS_EXPORT VariantArrayHandleContainer final : public VariantArrayHandleContainerBase
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandleVirtual<T> Array;
|
|
||||||
mutable vtkm::IdComponent NumberOfComponents = 0;
|
|
||||||
|
|
||||||
VariantArrayHandleContainer()
|
|
||||||
: VariantArrayHandleContainerBase(typeid(T))
|
|
||||||
, Array()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantArrayHandleContainer(const vtkm::cont::ArrayHandleVirtual<T>& array)
|
|
||||||
: VariantArrayHandleContainerBase(typeid(T))
|
|
||||||
, Array(array)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~VariantArrayHandleContainer<T>() override = default;
|
|
||||||
|
|
||||||
vtkm::Id GetNumberOfValues() const override { return this->Array.GetNumberOfValues(); }
|
|
||||||
|
|
||||||
vtkm::IdComponent GetNumberOfComponents() const override
|
|
||||||
{
|
|
||||||
// Cache number of components to avoid unnecessary device to host transfers of the array.
|
|
||||||
// Also assumes that the number of components is constant accross all elements and
|
|
||||||
// throughout the life of the array.
|
|
||||||
if (this->NumberOfComponents == 0)
|
|
||||||
{
|
|
||||||
this->NumberOfComponents =
|
|
||||||
this->GetNumberOfComponents(typename vtkm::VecTraits<T>::IsSizeStatic{});
|
|
||||||
}
|
|
||||||
return this->NumberOfComponents;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReleaseResourcesExecution() override { this->Array.ReleaseResourcesExecution(); }
|
|
||||||
void ReleaseResources() override { this->Array.ReleaseResources(); }
|
|
||||||
|
|
||||||
void PrintSummary(std::ostream& out) const override
|
|
||||||
{
|
|
||||||
vtkm::cont::printSummary_ArrayHandle(this->Array, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<VariantArrayHandleContainerBase> NewInstance() const override
|
|
||||||
{
|
|
||||||
return std::make_shared<VariantArrayHandleContainer<T>>(this->Array.NewInstance());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
vtkm::IdComponent GetNumberOfComponents(VecTraitsTagSizeStatic) const
|
|
||||||
{
|
|
||||||
return vtkm::VecTraits<T>::NUM_COMPONENTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
vtkm::IdComponent GetNumberOfComponents(VecTraitsTagSizeVariable) const
|
|
||||||
{
|
|
||||||
return (this->Array.GetNumberOfValues() == 0)
|
|
||||||
? 0
|
|
||||||
: vtkm::VecTraits<T>::GetNumberOfComponents(this->Array.ReadPortal().Get(0));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace variant
|
|
||||||
{
|
|
||||||
|
|
||||||
// One instance of a template class cannot access the private members of
|
|
||||||
// another instance of a template class. However, I want to be able to copy
|
|
||||||
// construct a VariantArrayHandle from another VariantArrayHandle of any other
|
|
||||||
// type. Since you cannot partially specialize friendship, use this accessor
|
|
||||||
// class to get at the internals for the copy constructor.
|
|
||||||
struct GetContainer
|
|
||||||
{
|
|
||||||
template <typename TypeList>
|
|
||||||
VTKM_CONT static const std::shared_ptr<VariantArrayHandleContainerBase>& Extract(
|
|
||||||
const vtkm::cont::VariantArrayHandleBase<TypeList>& src)
|
|
||||||
{
|
|
||||||
return src.ArrayContainer;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
VTKM_CONT bool IsValueType(const VariantArrayHandleContainerBase* container)
|
|
||||||
{
|
|
||||||
if (container == nullptr)
|
|
||||||
{ //you can't use typeid on nullptr of polymorphic types
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//needs optimizations based on platform. !OSX can use typeid
|
|
||||||
return container->TypeIndex == std::type_index(typeid(T));
|
|
||||||
// return (nullptr != dynamic_cast<const VariantArrayHandleContainer<T>*>(container));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ArrayHandleType>
|
|
||||||
VTKM_CONT inline bool IsType(const VariantArrayHandleContainerBase* container)
|
|
||||||
{ //container could be nullptr
|
|
||||||
using T = typename ArrayHandleType::ValueType;
|
|
||||||
if (!IsValueType<T>(container))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto* derived = static_cast<const VariantArrayHandleContainer<T>*>(container);
|
|
||||||
return vtkm::cont::IsType<ArrayHandleType>(derived->Array);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename S>
|
|
||||||
struct VTKM_ALWAYS_EXPORT Caster
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandle<T, S> operator()(const VariantArrayHandleContainerBase* container) const
|
|
||||||
{
|
|
||||||
//This needs to be reworked
|
|
||||||
using ArrayHandleType = vtkm::cont::ArrayHandle<T, S>;
|
|
||||||
if (!IsValueType<T>(container))
|
|
||||||
{
|
|
||||||
VTKM_LOG_CAST_FAIL(container, ArrayHandleType);
|
|
||||||
throwFailedDynamicCast(vtkm::cont::TypeToString(container),
|
|
||||||
vtkm::cont::TypeToString<ArrayHandleType>());
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto* derived = static_cast<const VariantArrayHandleContainer<T>*>(container);
|
|
||||||
return vtkm::cont::Cast<vtkm::cont::ArrayHandle<T, S>>(derived->Array);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct VTKM_ALWAYS_EXPORT Caster<T, vtkm::cont::StorageTagVirtual>
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual> operator()(
|
|
||||||
const VariantArrayHandleContainerBase* container) const
|
|
||||||
{
|
|
||||||
if (!IsValueType<T>(container))
|
|
||||||
{
|
|
||||||
VTKM_LOG_CAST_FAIL(container, vtkm::cont::ArrayHandleVirtual<T>);
|
|
||||||
throwFailedDynamicCast(vtkm::cont::TypeToString(container),
|
|
||||||
vtkm::cont::TypeToString<vtkm::cont::ArrayHandleVirtual<T>>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Technically, this method returns a copy of the \c ArrayHandle. But
|
|
||||||
// because \c ArrayHandle acts like a shared pointer, it is valid to
|
|
||||||
// do the copy.
|
|
||||||
const auto* derived = static_cast<const VariantArrayHandleContainer<T>*>(container);
|
|
||||||
VTKM_LOG_CAST_SUCC(container, derived->Array);
|
|
||||||
return derived->Array;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// MSVC will issue deprecation warnings here if this template is instantiated with
|
|
||||||
// a deprecated class even if the template is used from a section of code where
|
|
||||||
// deprecation warnings are suppressed. This is annoying behavior since this template
|
|
||||||
// has no control over what class it is used with. To get around it, we have to
|
|
||||||
// suppress all deprecation warnings here.
|
|
||||||
#ifdef VTKM_MSVC
|
|
||||||
VTKM_DEPRECATED_SUPPRESS_BEGIN
|
|
||||||
#endif
|
|
||||||
template <typename ArrayHandleType>
|
|
||||||
VTKM_CONT ArrayHandleType Cast(const VariantArrayHandleContainerBase* container)
|
|
||||||
{ //container could be nullptr
|
|
||||||
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
|
||||||
using Type = typename ArrayHandleType::ValueType;
|
|
||||||
using Storage = typename ArrayHandleType::StorageTag;
|
|
||||||
auto ret = Caster<Type, Storage>{}(container);
|
|
||||||
return ArrayHandleType(std::move(ret));
|
|
||||||
}
|
|
||||||
#ifdef VTKM_MSVC
|
|
||||||
VTKM_DEPRECATED_SUPPRESS_END
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace variant
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
VTKM_CONT_EXPORT void ThrowCastAndCallException(
|
|
||||||
const vtkm::cont::internal::VariantArrayHandleContainerBase&,
|
|
||||||
const std::type_info&);
|
|
||||||
|
|
||||||
VTKM_CONT_EXPORT void ThrowAsMultiplexerException(
|
|
||||||
const vtkm::cont::internal::VariantArrayHandleContainerBase& ref,
|
|
||||||
const std::initializer_list<std::string>& arrayTypes);
|
|
||||||
} // namespace detail
|
|
||||||
}
|
|
||||||
} //namespace vtkm::cont
|
|
||||||
|
|
||||||
#endif
|
|
@ -11,6 +11,7 @@
|
|||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||||
#include <vtkm/cont/ArrayHandleVirtual.h>
|
#include <vtkm/cont/ArrayHandleVirtual.h>
|
||||||
|
#include <vtkm/cont/ArrayHandleVirtual.hxx>
|
||||||
|
|
||||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||||
|
|
||||||
|
@ -157,27 +157,86 @@ vtkm::cont::UnknownArrayHandle CreateArrayUnknown(T t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ArrayHandleType>
|
template <typename ArrayHandleType>
|
||||||
void CheckCastToArrayHandle(const ArrayHandleType& array)
|
void CheckAsArrayHandle(const ArrayHandleType& array)
|
||||||
{
|
{
|
||||||
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
||||||
|
using T = typename ArrayHandleType::ValueType;
|
||||||
|
|
||||||
vtkm::cont::UnknownArrayHandle arrayUnknown = array;
|
vtkm::cont::UnknownArrayHandle arrayUnknown = array;
|
||||||
VTKM_TEST_ASSERT(!arrayUnknown.IsType<vtkm::cont::ArrayHandle<UnusualType>>(),
|
VTKM_TEST_ASSERT(!arrayUnknown.IsType<vtkm::cont::ArrayHandle<UnusualType>>(),
|
||||||
"Dynamic array reporting is wrong type.");
|
"Dynamic array reporting is wrong type.");
|
||||||
|
|
||||||
ArrayHandleType castArray1;
|
{
|
||||||
arrayUnknown.AsArrayHandle(castArray1);
|
std::cout << " Normal get ArrayHandle" << std::endl;
|
||||||
VTKM_TEST_ASSERT(arrayUnknown.CanConvert<ArrayHandleType>(), "Did not query handle correctly.");
|
ArrayHandleType retreivedArray1;
|
||||||
VTKM_TEST_ASSERT(array == castArray1, "Did not get back same array.");
|
arrayUnknown.AsArrayHandle(retreivedArray1);
|
||||||
|
VTKM_TEST_ASSERT(arrayUnknown.CanConvert<ArrayHandleType>(), "Did not query handle correctly.");
|
||||||
|
VTKM_TEST_ASSERT(array == retreivedArray1, "Did not get back same array.");
|
||||||
|
|
||||||
ArrayHandleType castArray2 = arrayUnknown.AsArrayHandle<ArrayHandleType>();
|
ArrayHandleType retreivedArray2 = arrayUnknown.AsArrayHandle<ArrayHandleType>();
|
||||||
VTKM_TEST_ASSERT(array == castArray2, "Did not get back same array.");
|
VTKM_TEST_ASSERT(array == retreivedArray2, "Did not get back same array.");
|
||||||
|
}
|
||||||
|
|
||||||
vtkm::cont::UnknownArrayHandle arrayUnknown2 = vtkm::cont::ArrayHandleMultiplexer<
|
{
|
||||||
ArrayHandleType,
|
std::cout << " Put in cast array, get actual array" << std::endl;
|
||||||
vtkm::cont::ArrayHandleConstant<typename ArrayHandleType::ValueType>>(array);
|
auto castArray = vtkm::cont::make_ArrayHandleCast<vtkm::Float64>(array);
|
||||||
VTKM_TEST_ASSERT(arrayUnknown2.IsType<ArrayHandleType>(),
|
vtkm::cont::UnknownArrayHandle arrayUnknown2(castArray);
|
||||||
"Putting in multiplexer did not pull out array.");
|
VTKM_TEST_ASSERT(arrayUnknown2.IsType<ArrayHandleType>());
|
||||||
|
ArrayHandleType retrievedArray = arrayUnknown2.AsArrayHandle<ArrayHandleType>();
|
||||||
|
VTKM_TEST_ASSERT(array == retrievedArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::cout << " Get array as cast" << std::endl;
|
||||||
|
vtkm::cont::ArrayHandleCast<vtkm::Float64, ArrayHandleType> castArray;
|
||||||
|
arrayUnknown.AsArrayHandle(castArray);
|
||||||
|
VTKM_TEST_ASSERT(test_equal_portals(array.ReadPortal(), castArray.ReadPortal()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::cout << " Put in multiplexer, get actual array" << std::endl;
|
||||||
|
vtkm::cont::UnknownArrayHandle arrayUnknown2 = vtkm::cont::ArrayHandleMultiplexer<
|
||||||
|
ArrayHandleType,
|
||||||
|
vtkm::cont::ArrayHandleConstant<typename ArrayHandleType::ValueType>>(array);
|
||||||
|
VTKM_TEST_ASSERT(arrayUnknown2.IsType<ArrayHandleType>(),
|
||||||
|
"Putting in multiplexer did not pull out array.");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::cout << " Make sure multiplex array prefers direct array (1st arg)" << std::endl;
|
||||||
|
using MultiplexerType =
|
||||||
|
vtkm::cont::ArrayHandleMultiplexer<ArrayHandleType,
|
||||||
|
vtkm::cont::ArrayHandleCast<T, ArrayHandleType>>;
|
||||||
|
MultiplexerType multiplexArray = arrayUnknown.AsArrayHandle<MultiplexerType>();
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(multiplexArray.IsValid());
|
||||||
|
VTKM_TEST_ASSERT(multiplexArray.GetStorage().GetArrayHandleVariant().GetIndex() == 0);
|
||||||
|
VTKM_TEST_ASSERT(test_equal_portals(multiplexArray.ReadPortal(), array.ReadPortal()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::cout << " Make sure multiplex array prefers direct array (2nd arg)" << std::endl;
|
||||||
|
using MultiplexerType =
|
||||||
|
vtkm::cont::ArrayHandleMultiplexer<vtkm::cont::ArrayHandleCast<T, vtkm::cont::ArrayHandle<T>>,
|
||||||
|
ArrayHandleType>;
|
||||||
|
MultiplexerType multiplexArray = arrayUnknown.AsArrayHandle<MultiplexerType>();
|
||||||
|
|
||||||
|
VTKM_TEST_ASSERT(multiplexArray.IsValid());
|
||||||
|
VTKM_TEST_ASSERT(multiplexArray.GetStorage().GetArrayHandleVariant().GetIndex() == 1);
|
||||||
|
VTKM_TEST_ASSERT(test_equal_portals(multiplexArray.ReadPortal(), array.ReadPortal()));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::cout << " Make sure adding arrays follows nesting of special arrays" << std::endl;
|
||||||
|
vtkm::cont::ArrayHandleMultiplexer<vtkm::cont::ArrayHandle<vtkm::Int64>,
|
||||||
|
vtkm::cont::ArrayHandleCast<vtkm::Int64, ArrayHandleType>>
|
||||||
|
multiplexer(vtkm::cont::make_ArrayHandleCast<vtkm::Int64>(array));
|
||||||
|
auto crazyArray = vtkm::cont::make_ArrayHandleCast<vtkm::Float64>(multiplexer);
|
||||||
|
vtkm::cont::UnknownArrayHandle arrayUnknown2(crazyArray);
|
||||||
|
VTKM_TEST_ASSERT(arrayUnknown2.IsType<ArrayHandleType>());
|
||||||
|
ArrayHandleType retrievedArray = arrayUnknown2.AsArrayHandle<ArrayHandleType>();
|
||||||
|
VTKM_TEST_ASSERT(array == retrievedArray);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A vtkm::Vec if NumComps > 1, otherwise a scalar
|
// A vtkm::Vec if NumComps > 1, otherwise a scalar
|
||||||
@ -320,12 +379,12 @@ void TryUnusualType()
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ArrayHandleType>
|
template <typename ArrayHandleType>
|
||||||
void TryCastToArrayHandle(const ArrayHandleType& array)
|
void TryAsArrayHandle(const ArrayHandleType& array)
|
||||||
{
|
{
|
||||||
CheckCastToArrayHandle(array);
|
CheckAsArrayHandle(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TryCastToArrayHandle()
|
void TryAsArrayHandle()
|
||||||
{
|
{
|
||||||
std::cout << " Normal array handle." << std::endl;
|
std::cout << " Normal array handle." << std::endl;
|
||||||
vtkm::Id buffer[ARRAY_SIZE];
|
vtkm::Id buffer[ARRAY_SIZE];
|
||||||
@ -336,10 +395,10 @@ void TryCastToArrayHandle()
|
|||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> array =
|
vtkm::cont::ArrayHandle<vtkm::Id> array =
|
||||||
vtkm::cont::make_ArrayHandle(buffer, ARRAY_SIZE, vtkm::CopyFlag::On);
|
vtkm::cont::make_ArrayHandle(buffer, ARRAY_SIZE, vtkm::CopyFlag::On);
|
||||||
TryCastToArrayHandle(array);
|
TryAsArrayHandle(array);
|
||||||
|
|
||||||
std::cout << " Constant array handle." << std::endl;
|
std::cout << " Constant array handle." << std::endl;
|
||||||
TryCastToArrayHandle(vtkm::cont::make_ArrayHandleConstant(5, ARRAY_SIZE));
|
TryAsArrayHandle(vtkm::cont::make_ArrayHandleConstant(5, ARRAY_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrySetCastArray()
|
void TrySetCastArray()
|
||||||
@ -386,8 +445,8 @@ void TestUnknownArrayHandle()
|
|||||||
std::cout << "Try unusual type." << std::endl;
|
std::cout << "Try unusual type." << std::endl;
|
||||||
TryUnusualType();
|
TryUnusualType();
|
||||||
|
|
||||||
std::cout << "Try CastToArrayHandle" << std::endl;
|
std::cout << "Try AsArrayHandle" << std::endl;
|
||||||
TryCastToArrayHandle();
|
TryAsArrayHandle();
|
||||||
|
|
||||||
std::cout << "Try setting ArrayHandleCast" << std::endl;
|
std::cout << "Try setting ArrayHandleCast" << std::endl;
|
||||||
TrySetCastArray();
|
TrySetCastArray();
|
||||||
|
@ -230,11 +230,16 @@ void CheckCastToArrayHandle(const ArrayHandleType& array)
|
|||||||
|
|
||||||
ArrayHandleType castArray1;
|
ArrayHandleType castArray1;
|
||||||
arrayVariant.CopyTo(castArray1);
|
arrayVariant.CopyTo(castArray1);
|
||||||
VTKM_TEST_ASSERT(arrayVariant.IsType<ArrayHandleType>(), "Did not query handle correctly.");
|
VTKM_TEST_ASSERT(arrayVariant.CanConvert<ArrayHandleType>(), "Did not query handle correctly.");
|
||||||
VTKM_TEST_ASSERT(array == castArray1, "Did not get back same array.");
|
//VTKM_TEST_ASSERT(array == castArray1, "Did not get back same array.");
|
||||||
|
auto result = vtkm::cont::testing::test_equal_ArrayHandles(array, castArray1);
|
||||||
|
VTKM_TEST_ASSERT(result, result.GetMergedMessage());
|
||||||
|
|
||||||
|
|
||||||
ArrayHandleType castArray2 = arrayVariant.Cast<ArrayHandleType>();
|
ArrayHandleType castArray2 = arrayVariant.Cast<ArrayHandleType>();
|
||||||
VTKM_TEST_ASSERT(array == castArray2, "Did not get back same array.");
|
//VTKM_TEST_ASSERT(array == castArray2, "Did not get back same array.");
|
||||||
|
result = vtkm::cont::testing::test_equal_ArrayHandles(array, castArray2);
|
||||||
|
VTKM_TEST_ASSERT(result, result.GetMergedMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// A vtkm::Vec if NumComps > 1, otherwise a scalar
|
// A vtkm::Vec if NumComps > 1, otherwise a scalar
|
||||||
|
Loading…
Reference in New Issue
Block a user