mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Add UnknownArrayHandle
This commit is contained in:
parent
ede0c179b7
commit
e47cedd972
@ -176,9 +176,9 @@ struct MultiplexerShrinkFunctor
|
||||
struct MultiplexerReleaseResourcesFunctor
|
||||
{
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT vtkm::Id operator()(ArrayHandleType&& array) const
|
||||
VTKM_CONT void operator()(ArrayHandleType&& array) const
|
||||
{
|
||||
return array.ReleaseResources();
|
||||
array.ReleaseResources();
|
||||
}
|
||||
};
|
||||
|
||||
@ -334,6 +334,10 @@ public:
|
||||
}
|
||||
|
||||
VTKM_CONT ArrayHandleVariantType& GetArrayHandleVariant() { return this->ArrayHandleVariant; }
|
||||
VTKM_CONT const ArrayHandleVariantType& GetArrayHandleVariant() const
|
||||
{
|
||||
return this->ArrayHandleVariant;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -116,6 +116,7 @@ set(headers
|
||||
Token.h
|
||||
TryExecute.h
|
||||
SerializableTypeString.h
|
||||
UnknownArrayHandle.h
|
||||
VariantArrayHandle.h
|
||||
VirtualObjectHandle.h
|
||||
)
|
||||
@ -191,6 +192,7 @@ set(sources
|
||||
RuntimeDeviceInformation.cxx
|
||||
StorageVirtual.cxx
|
||||
Timer.cxx
|
||||
UnknownArrayHandle.cxx
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
@ -19,11 +19,13 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
class CoordinateSystem;
|
||||
class Field;
|
||||
|
||||
template <typename T, typename S>
|
||||
class ArrayHandle;
|
||||
|
||||
class CoordinateSystem;
|
||||
class Field;
|
||||
class UnknownArrayHandle;
|
||||
|
||||
template <vtkm::IdComponent>
|
||||
class CellSetStructured;
|
||||
@ -65,6 +67,13 @@ void CastAndCall(const vtkm::cont::ArrayHandle<T, U>& handle, Functor&& f, Args&
|
||||
f(handle, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// A specialization of CastAndCall for UnknownArrayHandle.
|
||||
/// Since we have no hints on the types, use VTKM_DEFAULT_TYPE_LIST
|
||||
/// and VTKM_DEFAULT_STORAGE_LIST.
|
||||
// actually implemented in vtkm/cont/UnknownArrayHandle
|
||||
template <typename Functor, typename... Args>
|
||||
void CastAndCall(const UnknownArrayHandle& handle, Functor&& f, Args&&... args);
|
||||
|
||||
/// A specialization of CastAndCall for basic CellSetStructured types,
|
||||
/// Since the type is already known no deduction is needed.
|
||||
/// This specialization is used to simplify numerous worklet algorithms
|
||||
|
71
vtkm/cont/UnknownArrayHandle.cxx
Normal file
71
vtkm/cont/UnknownArrayHandle.cxx
Normal file
@ -0,0 +1,71 @@
|
||||
//============================================================================
|
||||
// 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/UnknownArrayHandle.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
std::shared_ptr<UnknownAHContainer> UnknownAHContainer::MakeNewInstance() const
|
||||
{
|
||||
// Start by doing an invalid copy to create a new container, then swap out the pointer
|
||||
// to the array handle to make sure that each object will delete its own ArrayHandle
|
||||
// when they get destroyed.
|
||||
std::shared_ptr<UnknownAHContainer> newContainer(new UnknownAHContainer(*this));
|
||||
newContainer->ArrayHandlePointer = this->NewInstance();
|
||||
return newContainer;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
VTKM_CONT bool UnknownArrayHandle::IsValueTypeImpl(std::type_index type) const
|
||||
{
|
||||
if (!this->Container)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Needs optimization based on platform. OSX cannot compare typeid across translation units?
|
||||
return this->Container->ValueType == type;
|
||||
}
|
||||
|
||||
VTKM_CONT bool UnknownArrayHandle::IsStorageTypeImpl(std::type_index type) const
|
||||
{
|
||||
if (!this->Container)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Needs optimization based on platform. OSX cannot compare typeid across translation units?
|
||||
return this->Container->StorageType == type;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
VTKM_CONT_EXPORT void ThrowCastAndCallException(const vtkm::cont::UnknownArrayHandle& 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());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
}
|
||||
} // namespace vtkm::cont
|
540
vtkm/cont/UnknownArrayHandle.h
Normal file
540
vtkm/cont/UnknownArrayHandle.h
Normal file
@ -0,0 +1,540 @@
|
||||
//============================================================================
|
||||
// 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_UnknownArrayHandle_h
|
||||
#define vtk_m_cont_UnknownArrayHandle_h
|
||||
|
||||
#include <vtkm/cont/vtkm_cont_export.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleMultiplexer.h>
|
||||
|
||||
#include <vtkm/cont/DefaultTypes.h>
|
||||
|
||||
#include <memory>
|
||||
#include <typeindex>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHDelete(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
delete arrayHandle;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void* UnknownADNewInstance()
|
||||
{
|
||||
return new vtkm::cont::ArrayHandle<T, S>;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static vtkm::Id UnknownAHNumberOfValues(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
return arrayHandle->GetNumberOfValues();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static vtkm::IdComponent UnknownAHNumberOfComponents()
|
||||
{
|
||||
return vtkm::VecTraits<T>::NUM_COMPONENTS;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHReleaseResources(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
arrayHandle->ReleaseResources();
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHReleaseResourcesExecution(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
arrayHandle->ReleaseResourcesExecution();
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHPrintSummary(void* mem, std::ostream& out, bool full)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
vtkm::cont::printSummary_ArrayHandle(*arrayHandle, out, full);
|
||||
}
|
||||
|
||||
struct VTKM_CONT_EXPORT UnknownAHContainer;
|
||||
|
||||
struct MakeUnknownAHContainerFunctor
|
||||
{
|
||||
template <typename T, typename S>
|
||||
std::shared_ptr<UnknownAHContainer> operator()(const vtkm::cont::ArrayHandle<T, S>& array) const;
|
||||
};
|
||||
|
||||
struct VTKM_CONT_EXPORT UnknownAHContainer
|
||||
{
|
||||
void* ArrayHandlePointer;
|
||||
|
||||
std::type_index ValueType;
|
||||
std::type_index StorageType;
|
||||
|
||||
using DeleteType = void(void*);
|
||||
DeleteType* DeleteFunction;
|
||||
|
||||
using NewInstanceType = void*();
|
||||
NewInstanceType& NewInstance;
|
||||
|
||||
using NumberOfValuesType = vtkm::Id(void*);
|
||||
NumberOfValuesType* NumberOfValues;
|
||||
|
||||
using NumberOfComponentsType = vtkm::IdComponent();
|
||||
NumberOfComponentsType* NumberOfComponents;
|
||||
|
||||
using ReleaseResourcesType = void(void*);
|
||||
ReleaseResourcesType* ReleaseResources;
|
||||
ReleaseResourcesType* ReleaseResourcesExecution;
|
||||
|
||||
using PrintSummaryType = void(void*, std::ostream&, bool);
|
||||
PrintSummaryType* PrintSummary;
|
||||
|
||||
void operator=(const UnknownAHContainer&) = delete;
|
||||
|
||||
~UnknownAHContainer() { this->DeleteFunction(this->ArrayHandlePointer); }
|
||||
|
||||
std::shared_ptr<UnknownAHContainer> MakeNewInstance() const;
|
||||
|
||||
template <typename T, typename S>
|
||||
static std::shared_ptr<UnknownAHContainer> Make(const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
{
|
||||
return std::shared_ptr<UnknownAHContainer>(new UnknownAHContainer(array));
|
||||
}
|
||||
|
||||
template <typename TargetT, typename SourceT, typename SourceS>
|
||||
static std::shared_ptr<UnknownAHContainer> Make(
|
||||
const vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceS>>& array)
|
||||
{
|
||||
return Make(array.GetStorage().GetArray());
|
||||
}
|
||||
|
||||
template <typename T, typename... Ss>
|
||||
static std::shared_ptr<UnknownAHContainer> Make(
|
||||
const vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagMultiplexer<Ss...>>& array)
|
||||
{
|
||||
auto&& variant = array.GetStorage().GetArrayHandleVariant();
|
||||
if (variant.IsValid())
|
||||
{
|
||||
return variant.CastAndCall(MakeUnknownAHContainerFunctor{});
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::shared_ptr<UnknownAHContainer>{};
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
UnknownAHContainer(const UnknownAHContainer&) = default;
|
||||
|
||||
template <typename T, typename S>
|
||||
explicit UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
: ArrayHandlePointer(new vtkm::cont::ArrayHandle<T, S>(array))
|
||||
, ValueType(typeid(T))
|
||||
, StorageType(typeid(S))
|
||||
, DeleteFunction(detail::UnknownAHDelete<T, S>)
|
||||
, NewInstance(detail::UnknownADNewInstance<T, S>)
|
||||
, NumberOfValues(detail::UnknownAHNumberOfValues<T, S>)
|
||||
, NumberOfComponents(detail::UnknownAHNumberOfComponents<T>)
|
||||
, ReleaseResources(detail::UnknownAHReleaseResources<T, S>)
|
||||
, ReleaseResourcesExecution(detail::UnknownAHReleaseResourcesExecution<T, S>)
|
||||
, PrintSummary(detail::UnknownAHPrintSummary<T, S>)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename S>
|
||||
inline std::shared_ptr<UnknownAHContainer> MakeUnknownAHContainerFunctor::operator()(
|
||||
const vtkm::cont::ArrayHandle<T, S>& array) const
|
||||
{
|
||||
return UnknownAHContainer::Make(array);
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief An ArrayHandle of an unknown type and storage.
|
||||
///
|
||||
/// `UnknownArrayHandle` holds an `ArrayHandle` object using runtime polymorphism
|
||||
/// to manage different value types and storage rather than compile-time templates.
|
||||
/// This adds a programming convenience that helps avoid a proliferation of
|
||||
/// templates. It also provides the management necessary to interface VTK-m with
|
||||
/// data sources where types will not be known until runtime and is the storage
|
||||
/// mechanism for classes like `DataSet` and `Field` that can hold numerous
|
||||
/// types.
|
||||
///
|
||||
/// To interface between the runtime polymorphism and the templated algorithms
|
||||
/// in VTK-m, `UnknownArrayHandle` contains a method named `CastAndCallForTypes`
|
||||
/// that determines the correct type from some known list of value types and
|
||||
/// storage. This mechanism is used internally by VTK-m's worklet invocation
|
||||
/// mechanism to determine the type when running algorithms.
|
||||
///
|
||||
/// If the `UnknownArrayHandle` is used in a context where the possible array
|
||||
/// types can be whittled down to a finite list (or you have to), you can
|
||||
/// specify lists of value types and storage using the `ResetTypesAndStorage`
|
||||
/// method. This will convert this object to an `UncertainArrayHandle` of the
|
||||
/// given types. In cases where a finite set of types need to specified but
|
||||
/// there is no known subset, `VTKM_DEFAULT_TYPE_LIST` and
|
||||
/// `VTKM_DEFAULT_STORAGE_LIST` can be used.
|
||||
///
|
||||
/// `ArrayHandleCast` and `ArrayHandleMultiplexer` are treated special. If
|
||||
/// the `UnknownArrayHandle` is set to an `ArrayHandle` of one of these
|
||||
/// types, it will actually store the `ArrayHandle` contained. Likewise,
|
||||
/// if the `ArrayHandle` is retrieved as one of these types, it will
|
||||
/// automatically convert it if possible.
|
||||
///
|
||||
class VTKM_CONT_EXPORT UnknownArrayHandle
|
||||
{
|
||||
std::shared_ptr<detail::UnknownAHContainer> Container;
|
||||
|
||||
VTKM_CONT bool IsValueTypeImpl(std::type_index type) const;
|
||||
VTKM_CONT bool IsStorageTypeImpl(std::type_index type) const;
|
||||
|
||||
public:
|
||||
VTKM_CONT UnknownArrayHandle() = default;
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_CONT UnknownArrayHandle(const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
: Container(detail::UnknownAHContainer::Make(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
|
||||
/// returns a new variant array handle for it. This method is convenient when
|
||||
/// creating output arrays that should be the same type as some input array.
|
||||
///
|
||||
VTKM_CONT UnknownArrayHandle NewInstance() const
|
||||
{
|
||||
UnknownArrayHandle newArray;
|
||||
newArray.Container = this->Container->MakeNewInstance();
|
||||
return newArray;
|
||||
}
|
||||
|
||||
/// Returns true if this array matches the ValueType template argument.
|
||||
///
|
||||
template <typename ValueType>
|
||||
VTKM_CONT bool IsValueType() const
|
||||
{
|
||||
return this->IsValueTypeImpl(typeid(ValueType));
|
||||
}
|
||||
|
||||
/// Returns true if this array matches the StorageType template argument.
|
||||
///
|
||||
template <typename StorageType>
|
||||
VTKM_CONT bool IsStorageType() const
|
||||
{
|
||||
return this->IsStorageTypeImpl(typeid(StorageType));
|
||||
}
|
||||
|
||||
/// Returns true if this array matches the ArrayHandleType template argument.
|
||||
///
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT bool IsType() const
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
||||
return (this->IsValueType<typename ArrayHandleType::ValueType>() &&
|
||||
this->IsStorageType<typename ArrayHandleType::StorageTag>());
|
||||
}
|
||||
|
||||
/// \brief Returns the number of values in the array.
|
||||
///
|
||||
VTKM_CONT vtkm::Id GetNumberOfValues() const
|
||||
{
|
||||
return this->Container->NumberOfValues(this->Container->ArrayHandlePointer);
|
||||
}
|
||||
|
||||
/// \brief Returns the number of components for each value in the array.
|
||||
///
|
||||
/// If the array holds `vtkm::Vec` objects, this will return the number of components
|
||||
/// in each value. If the array holds a basic C type (such as `float`), this will return 1.
|
||||
///
|
||||
VTKM_CONT vtkm::IdComponent GetNumberOfComponents() const
|
||||
{
|
||||
return this->Container->NumberOfComponents();
|
||||
}
|
||||
|
||||
/// \brief Determine if the contained array can be passed to the given array type.
|
||||
///
|
||||
/// This method will return true if calling `AsArrayHandle` of the given type will
|
||||
/// succeed. The result is similar to `IsType`, and if `IsType` returns true, then
|
||||
/// this will return true. However, this method will also return true for other
|
||||
/// types such as an `ArrayHandleMultiplexer` that can contain the array.
|
||||
///
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT bool CanConvert() const;
|
||||
|
||||
///@{
|
||||
/// 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.
|
||||
/// Use the `IsType` method to determine if the array can be returned with the given type.
|
||||
///
|
||||
template <typename T, typename S>
|
||||
VTKM_CONT void AsArrayHandle(vtkm::cont::ArrayHandle<T, S>& array) const
|
||||
{
|
||||
using ArrayType = vtkm::cont::ArrayHandle<T, S>;
|
||||
if (!this->IsType<ArrayType>())
|
||||
{
|
||||
VTKM_LOG_CAST_FAIL(*this, decltype(array));
|
||||
throwFailedDynamicCast(vtkm::cont::TypeToString(*this), vtkm::cont::TypeToString(array));
|
||||
}
|
||||
|
||||
array = *reinterpret_cast<ArrayType*>(this->Container->ArrayHandlePointer);
|
||||
}
|
||||
|
||||
template <typename T, typename... Ss>
|
||||
VTKM_CONT void AsArrayHandle(
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagMultiplexer<Ss...>>& array) const;
|
||||
|
||||
template <typename TargetT, typename SourceT, typename SourceS>
|
||||
VTKM_CONT void AsArrayHandle(
|
||||
vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceS>>& array) const
|
||||
{
|
||||
using ContainedArrayType = vtkm::cont::ArrayHandle<SourceT, SourceS>;
|
||||
array = vtkm::cont::ArrayHandleCast<TargetT, ContainedArrayType>(
|
||||
this->AsArrayHandle<ContainedArrayType>());
|
||||
}
|
||||
|
||||
template <typename ArrayType>
|
||||
VTKM_CONT ArrayType AsArrayHandle() const
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(ArrayType);
|
||||
ArrayType array;
|
||||
this->AsArrayHandle(array);
|
||||
return array;
|
||||
}
|
||||
///@}
|
||||
|
||||
/// \brief Call a functor using the underlying array type.
|
||||
///
|
||||
/// `CastAndCall` attempts to cast the held array to a specific value type,
|
||||
/// and then calls the given functor with the cast array. You must specify
|
||||
/// the `TypeList` and `StorageList` as template arguments.
|
||||
///
|
||||
template <typename TypeList, typename StorageList, typename Functor, typename... Args>
|
||||
VTKM_CONT void CastAndCallForTypes(Functor&& functor, Args&&... args) const;
|
||||
|
||||
/// Releases any resources being used in the execution environment (that are
|
||||
/// not being shared by the control environment).
|
||||
///
|
||||
VTKM_CONT void ReleaseResourcesExecution() const
|
||||
{
|
||||
return this->Container->ReleaseResourcesExecution(this->Container->ArrayHandlePointer);
|
||||
}
|
||||
|
||||
/// Releases all resources in both the control and execution environments.
|
||||
///
|
||||
VTKM_CONT void ReleaseResources() const
|
||||
{
|
||||
return this->Container->ReleaseResources(this->Container->ArrayHandlePointer);
|
||||
}
|
||||
|
||||
VTKM_CONT void PrintSummary(std::ostream& out, bool full = false) const
|
||||
{
|
||||
this->Container->PrintSummary(this->Container->ArrayHandlePointer, out, full);
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// Out of class implementations
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T, typename S>
|
||||
struct UnknownArrayHandleCanConvert
|
||||
{
|
||||
VTKM_CONT bool operator()(const vtkm::cont::UnknownArrayHandle& array) const
|
||||
{
|
||||
return array.IsType<vtkm::cont::ArrayHandle<T, S>>();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TargetT, typename SourceT, typename SourceS>
|
||||
struct UnknownArrayHandleCanConvert<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceS>>
|
||||
{
|
||||
VTKM_CONT bool operator()(const vtkm::cont::UnknownArrayHandle& array) const
|
||||
{
|
||||
return UnknownArrayHandleCanConvert<SourceT, SourceS>{}(array);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct UnknownArrayHandleCanConvertTry
|
||||
{
|
||||
template <typename S>
|
||||
VTKM_CONT void operator()(S, const vtkm::cont::UnknownArrayHandle& array, bool& canConvert) const
|
||||
{
|
||||
canConvert |= UnknownArrayHandleCanConvert<T, S>{}(array);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Ss>
|
||||
struct UnknownArrayHandleCanConvert<T, vtkm::cont::StorageTagMultiplexer<Ss...>>
|
||||
{
|
||||
VTKM_CONT bool operator()(const vtkm::cont::UnknownArrayHandle& array) const
|
||||
{
|
||||
bool canConvert = false;
|
||||
vtkm::ListForEach(UnknownArrayHandleCanConvertTry<T>{}, vtkm::List<Ss...>{}, array, canConvert);
|
||||
return canConvert;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
VTKM_CONT bool UnknownArrayHandle::CanConvert() const
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
||||
|
||||
return detail::UnknownArrayHandleCanConvert<typename ArrayHandleType::ValueType,
|
||||
typename ArrayHandleType::StorageTag>{}(*this);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct UnknownArrayHandleMultplexerCastTry
|
||||
{
|
||||
template <typename T, typename S, typename... Ss>
|
||||
VTKM_CONT void operator()(
|
||||
S,
|
||||
const vtkm::cont::UnknownArrayHandle& unknownArray,
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagMultiplexer<Ss...>>& outputArray,
|
||||
bool& converted) const
|
||||
{
|
||||
using ArrayType = vtkm::cont::ArrayHandle<T, S>;
|
||||
if (!converted && unknownArray.CanConvert<ArrayType>())
|
||||
{
|
||||
outputArray.GetStorage().SetArray(unknownArray.AsArrayHandle<ArrayType>());
|
||||
converted = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename... Ss>
|
||||
void UnknownArrayHandle::AsArrayHandle(
|
||||
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagMultiplexer<Ss...>>& array) const
|
||||
{
|
||||
bool converted = false;
|
||||
vtkm::ListForEach(
|
||||
detail::UnknownArrayHandleMultplexerCastTry{}, vtkm::List<Ss...>{}, *this, array, converted);
|
||||
|
||||
if (!converted)
|
||||
{
|
||||
VTKM_LOG_CAST_FAIL(*this, decltype(array));
|
||||
throwFailedDynamicCast(vtkm::cont::TypeToString(*this), vtkm::cont::TypeToString(array));
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct UnknownArrayHandleTry
|
||||
{
|
||||
template <typename T, typename S, typename Functor, typename... Args>
|
||||
void operator()(vtkm::List<T, S>,
|
||||
Functor&& f,
|
||||
bool& called,
|
||||
const vtkm::cont::UnknownArrayHandle& unknownArray,
|
||||
Args&&... args) const
|
||||
{
|
||||
using DerivedArrayType = vtkm::cont::ArrayHandle<T, S>;
|
||||
if (!called && unknownArray.IsType<DerivedArrayType>())
|
||||
{
|
||||
called = true;
|
||||
DerivedArrayType derivedArray;
|
||||
unknownArray.AsArrayHandle(derivedArray);
|
||||
VTKM_LOG_CAST_SUCC(unknownArray, derivedArray);
|
||||
|
||||
// If you get a compile error here, it means that you have called CastAndCall for a
|
||||
// vtkm::cont::UnknownArrayHandle 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 IsUndefinedArrayType
|
||||
{
|
||||
};
|
||||
template <typename T, typename U>
|
||||
struct IsUndefinedArrayType<vtkm::List<T, U>> : vtkm::cont::internal::IsInvalidArrayHandle<T, U>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TypeList, typename StorageList>
|
||||
using ListAllArrayTypes =
|
||||
vtkm::ListRemoveIf<vtkm::ListCross<TypeList, StorageList>, IsUndefinedArrayType>;
|
||||
|
||||
|
||||
VTKM_CONT_EXPORT void ThrowCastAndCallException(const vtkm::cont::UnknownArrayHandle&,
|
||||
const std::type_info&);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
|
||||
template <typename TypeList, typename StorageTagList, typename Functor, typename... Args>
|
||||
VTKM_CONT void UnknownArrayHandle::CastAndCallForTypes(Functor&& f, Args&&... args) const
|
||||
{
|
||||
using crossProduct = detail::ListAllArrayTypes<TypeList, StorageTagList>;
|
||||
|
||||
bool called = false;
|
||||
vtkm::ListForEach(detail::UnknownArrayHandleTry{},
|
||||
crossProduct{},
|
||||
std::forward<Functor>(f),
|
||||
called,
|
||||
*this,
|
||||
std::forward<Args>(args)...);
|
||||
if (!called)
|
||||
{
|
||||
// throw an exception
|
||||
VTKM_LOG_CAST_FAIL(*this, TypeList);
|
||||
detail::ThrowCastAndCallException(*this, typeid(TypeList));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Functor, typename... Args>
|
||||
void CastAndCall(const UnknownArrayHandle& handle, Functor&& f, Args&&... args)
|
||||
{
|
||||
handle.CastAndCallForTypes<VTKM_DEFAULT_TYPE_LIST, VTKM_DEFAULT_STORAGE_LIST>(
|
||||
std::forward<Functor>(f), std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
#endif //vtk_m_cont_UnknownArrayHandle_h
|
@ -88,6 +88,7 @@ set(unit_tests
|
||||
UnitTestTimer.cxx
|
||||
UnitTestToken.cxx
|
||||
UnitTestTryExecute.cxx
|
||||
UnitTestUnknownArrayHandle.cxx
|
||||
UnitTestVariantArrayHandle.cxx
|
||||
)
|
||||
|
||||
|
398
vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx
Normal file
398
vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx
Normal file
@ -0,0 +1,398 @@
|
||||
//============================================================================
|
||||
// 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/UnknownArrayHandle.h>
|
||||
|
||||
#include <vtkm/TypeTraits.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Make an "unusual" type to use in the test. This is simply a type that
|
||||
// is sure not to be declared elsewhere.
|
||||
struct UnusualType
|
||||
{
|
||||
using T = vtkm::Id;
|
||||
T X;
|
||||
UnusualType() = default;
|
||||
UnusualType(T x)
|
||||
: X(x)
|
||||
{
|
||||
}
|
||||
UnusualType& operator=(T x)
|
||||
{
|
||||
this->X = x;
|
||||
return *this;
|
||||
}
|
||||
operator T() const { return this->X; }
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
|
||||
// UnknownArrayHandle requires its value type to have a defined VecTraits
|
||||
// class. One of the tests is to use an "unusual" array.
|
||||
// Make an implementation here. Because I am lazy, this is only a partial
|
||||
// implementation.
|
||||
template <>
|
||||
struct VecTraits<UnusualType> : VecTraits<UnusualType::T>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace vtkm
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const vtkm::Id ARRAY_SIZE = 10;
|
||||
|
||||
struct CheckFunctor
|
||||
{
|
||||
template <typename T, typename S>
|
||||
static void CheckArray(const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
{
|
||||
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE, "Unexpected array size.");
|
||||
CheckPortal(array.ReadPortal());
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static void CheckArray(const vtkm::cont::ArrayHandle<UnusualType, S>& array)
|
||||
{
|
||||
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE, "Unexpected array size.");
|
||||
auto portal = array.ReadPortal();
|
||||
for (vtkm::Id index = 0; index < array.GetNumberOfValues(); ++index)
|
||||
{
|
||||
VTKM_TEST_ASSERT(portal.Get(index) == TestValue(index, UnusualType::T{}));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
void operator()(const vtkm::cont::ArrayHandle<T, S>& array, bool& called) const
|
||||
{
|
||||
called = true;
|
||||
std::cout << " Checking for array type " << typeid(T).name() << " with storage "
|
||||
<< typeid(S).name() << std::endl;
|
||||
|
||||
CheckArray(array);
|
||||
}
|
||||
};
|
||||
|
||||
void BasicUnknownArrayChecks(const vtkm::cont::UnknownArrayHandle& array,
|
||||
vtkm::IdComponent numComponents)
|
||||
{
|
||||
VTKM_TEST_ASSERT(array.GetNumberOfValues() == ARRAY_SIZE,
|
||||
"Dynamic array reports unexpected size.");
|
||||
VTKM_TEST_ASSERT(array.GetNumberOfComponents() == numComponents,
|
||||
"Dynamic array reports unexpected number of components.");
|
||||
}
|
||||
|
||||
void CheckUnknownArrayDefaults(const vtkm::cont::UnknownArrayHandle& array,
|
||||
vtkm::IdComponent numComponents)
|
||||
{
|
||||
BasicUnknownArrayChecks(array, numComponents);
|
||||
|
||||
std::cout << " CastAndCall with default types" << std::endl;
|
||||
bool called = false;
|
||||
CastAndCall(array, CheckFunctor(), called);
|
||||
}
|
||||
|
||||
template <typename TypeList, typename StorageList>
|
||||
void CheckUnknownArray(const vtkm::cont::UnknownArrayHandle& array, vtkm::IdComponent numComponents)
|
||||
{
|
||||
VTKM_IS_LIST(TypeList);
|
||||
VTKM_IS_LIST(StorageList);
|
||||
|
||||
BasicUnknownArrayChecks(array, numComponents);
|
||||
|
||||
std::cout << " CastAndCall with given types" << std::endl;
|
||||
bool called = false;
|
||||
array.CastAndCallForTypes<TypeList, StorageList>(CheckFunctor{}, called);
|
||||
|
||||
VTKM_TEST_ASSERT(
|
||||
called, "The functor was never called (and apparently a bad value exception not thrown).");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
vtkm::cont::ArrayHandle<T> CreateArray(T)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<T> array;
|
||||
array.Allocate(ARRAY_SIZE);
|
||||
SetPortal(array.WritePortal());
|
||||
return array;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<UnusualType> CreateArray(UnusualType)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<UnusualType> array;
|
||||
array.Allocate(ARRAY_SIZE);
|
||||
auto portal = array.WritePortal();
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; ++index)
|
||||
{
|
||||
portal.Set(index, TestValue(index, UnusualType::T{}));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
vtkm::cont::UnknownArrayHandle CreateArrayUnknown(T t)
|
||||
{
|
||||
return vtkm::cont::UnknownArrayHandle(CreateArray(t));
|
||||
}
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
void CheckCastToArrayHandle(const ArrayHandleType& array)
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
||||
|
||||
vtkm::cont::UnknownArrayHandle arrayUnknown = array;
|
||||
VTKM_TEST_ASSERT(!arrayUnknown.IsType<vtkm::cont::ArrayHandle<UnusualType>>(),
|
||||
"Dynamic array reporting is wrong type.");
|
||||
|
||||
ArrayHandleType castArray1;
|
||||
arrayUnknown.AsArrayHandle(castArray1);
|
||||
VTKM_TEST_ASSERT(arrayUnknown.CanConvert<ArrayHandleType>(), "Did not query handle correctly.");
|
||||
VTKM_TEST_ASSERT(array == castArray1, "Did not get back same array.");
|
||||
|
||||
ArrayHandleType castArray2 = arrayUnknown.AsArrayHandle<ArrayHandleType>();
|
||||
VTKM_TEST_ASSERT(array == castArray2, "Did not get back same array.");
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
// 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 T>
|
||||
void TryNewInstance(vtkm::cont::UnknownArrayHandle originalArray)
|
||||
{
|
||||
// This check should already have been performed by caller, but just in case.
|
||||
CheckUnknownArray<vtkm::List<T>, VTKM_DEFAULT_STORAGE_LIST>(originalArray,
|
||||
vtkm::VecTraits<T>::NUM_COMPONENTS);
|
||||
|
||||
std::cout << "Create new instance of array." << std::endl;
|
||||
vtkm::cont::UnknownArrayHandle newArray = originalArray.NewInstance();
|
||||
|
||||
std::cout << "Get a static instance of the new array (which checks the type)." << std::endl;
|
||||
vtkm::cont::ArrayHandle<T> staticArray;
|
||||
newArray.AsArrayHandle(staticArray);
|
||||
|
||||
std::cout << "Fill the new array with invalid values and make sure the original" << std::endl
|
||||
<< "is uneffected." << std::endl;
|
||||
staticArray.Allocate(ARRAY_SIZE);
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
|
||||
{
|
||||
staticArray.WritePortal().Set(index, TestValue(index + 100, T()));
|
||||
}
|
||||
CheckUnknownArray<vtkm::List<T>, VTKM_DEFAULT_STORAGE_LIST>(originalArray,
|
||||
vtkm::VecTraits<T>::NUM_COMPONENTS);
|
||||
|
||||
std::cout << "Set the new static array to expected values and make sure the new" << std::endl
|
||||
<< "dynamic array points to the same new values." << std::endl;
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
|
||||
{
|
||||
staticArray.WritePortal().Set(index, TestValue(index, T()));
|
||||
}
|
||||
CheckUnknownArray<vtkm::List<T>, VTKM_DEFAULT_STORAGE_LIST>(newArray,
|
||||
vtkm::VecTraits<T>::NUM_COMPONENTS);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TryAsMultiplexer(vtkm::cont::UnknownArrayHandle sourceArray)
|
||||
{
|
||||
auto originalArray = sourceArray.AsArrayHandle<vtkm::cont::ArrayHandle<T>>();
|
||||
|
||||
{
|
||||
std::cout << "Get multiplex array through direct type." << std::endl;
|
||||
using MultiplexerType = vtkm::cont::ArrayHandleMultiplexer<vtkm::cont::ArrayHandle<T>,
|
||||
vtkm::cont::ArrayHandleConstant<T>>;
|
||||
VTKM_TEST_ASSERT(sourceArray.CanConvert<MultiplexerType>());
|
||||
MultiplexerType multiplexArray = sourceArray.AsArrayHandle<MultiplexerType>();
|
||||
|
||||
VTKM_TEST_ASSERT(multiplexArray.IsValid());
|
||||
VTKM_TEST_ASSERT(test_equal_portals(multiplexArray.ReadPortal(), originalArray.ReadPortal()));
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "Get multiplex array through cast type." << std::endl;
|
||||
using CastT = typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<vtkm::Float64>;
|
||||
using MultiplexerType = vtkm::cont::ArrayHandleMultiplexer<
|
||||
vtkm::cont::ArrayHandle<CastT>,
|
||||
vtkm::cont::ArrayHandleCast<CastT, vtkm::cont::ArrayHandle<T>>>;
|
||||
VTKM_TEST_ASSERT(sourceArray.CanConvert<MultiplexerType>());
|
||||
MultiplexerType multiplexArray = sourceArray.AsArrayHandle<MultiplexerType>();
|
||||
|
||||
VTKM_TEST_ASSERT(multiplexArray.IsValid());
|
||||
VTKM_TEST_ASSERT(test_equal_portals(multiplexArray.ReadPortal(), originalArray.ReadPortal()));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Maybe we should support this, but right now we don't
|
||||
{
|
||||
std::cout << "Make sure multiplex array prefers direct array (1st arg)" << std::endl;
|
||||
using MultiplexerType = vtkm::cont::ArrayHandleMultiplexer<
|
||||
vtkm::cont::ArrayHandle<T>,
|
||||
vtkm::cont::ArrayHandleCast<T, vtkm::cont::ArrayHandle<T>>>;
|
||||
MultiplexerType multiplexArray = sourceArray.AsArrayHandle<MultiplexerType>();
|
||||
|
||||
VTKM_TEST_ASSERT(multiplexArray.IsValid());
|
||||
VTKM_TEST_ASSERT(multiplexArray.GetStorage().GetArrayHandleVariant().GetIndex() == 0);
|
||||
VTKM_TEST_ASSERT(test_equal_portals(multiplexArray.ReadPortal(), originalArray.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>>,
|
||||
vtkm::cont::ArrayHandle<T>>;
|
||||
MultiplexerType multiplexArray = sourceArray.AsArrayHandle<MultiplexerType>();
|
||||
|
||||
VTKM_TEST_ASSERT(multiplexArray.IsValid());
|
||||
VTKM_TEST_ASSERT(multiplexArray.GetStorage().GetArrayHandleVariant().GetIndex() == 1);
|
||||
VTKM_TEST_ASSERT(test_equal_portals(multiplexArray.ReadPortal(), originalArray.ReadPortal()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TryDefaultType()
|
||||
{
|
||||
vtkm::cont::UnknownArrayHandle array = CreateArrayUnknown(T{});
|
||||
|
||||
CheckUnknownArrayDefaults(array, vtkm::VecTraits<T>::NUM_COMPONENTS);
|
||||
|
||||
TryNewInstance<T>(array);
|
||||
|
||||
TryAsMultiplexer<T>(array);
|
||||
}
|
||||
|
||||
struct TryBasicVTKmType
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
vtkm::cont::UnknownArrayHandle array = CreateArrayUnknown(T());
|
||||
|
||||
CheckUnknownArray<vtkm::TypeListAll, VTKM_DEFAULT_STORAGE_LIST>(
|
||||
array, vtkm::VecTraits<T>::NUM_COMPONENTS);
|
||||
|
||||
TryNewInstance<T>(array);
|
||||
}
|
||||
};
|
||||
|
||||
void TryUnusualType()
|
||||
{
|
||||
// A string is an unlikely type to be declared elsewhere in VTK-m.
|
||||
vtkm::cont::UnknownArrayHandle array = CreateArrayUnknown(UnusualType{});
|
||||
|
||||
try
|
||||
{
|
||||
CheckUnknownArray<VTKM_DEFAULT_TYPE_LIST, VTKM_DEFAULT_STORAGE_LIST>(array, 1);
|
||||
VTKM_TEST_FAIL("CastAndCall failed to error for unrecognized type.");
|
||||
}
|
||||
catch (vtkm::cont::ErrorBadValue&)
|
||||
{
|
||||
std::cout << " Caught exception for unrecognized type." << std::endl;
|
||||
}
|
||||
CheckUnknownArray<vtkm::List<UnusualType>, VTKM_DEFAULT_STORAGE_LIST>(array, 1);
|
||||
std::cout << " Found type when type list was reset." << std::endl;
|
||||
}
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
void TryCastToArrayHandle(const ArrayHandleType& array)
|
||||
{
|
||||
CheckCastToArrayHandle(array);
|
||||
}
|
||||
|
||||
void TryCastToArrayHandle()
|
||||
{
|
||||
std::cout << " Normal array handle." << std::endl;
|
||||
vtkm::Id buffer[ARRAY_SIZE];
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
|
||||
{
|
||||
buffer[index] = TestValue(index, vtkm::Id());
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> array =
|
||||
vtkm::cont::make_ArrayHandle(buffer, ARRAY_SIZE, vtkm::CopyFlag::On);
|
||||
TryCastToArrayHandle(array);
|
||||
|
||||
std::cout << " Constant array handle." << std::endl;
|
||||
TryCastToArrayHandle(vtkm::cont::make_ArrayHandleConstant(5, ARRAY_SIZE));
|
||||
}
|
||||
|
||||
void TrySetCastArray()
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> knownArray = CreateArray(vtkm::Id{});
|
||||
vtkm::cont::UnknownArrayHandle unknownArray(
|
||||
vtkm::cont::make_ArrayHandleCast<vtkm::Float32>(knownArray));
|
||||
|
||||
// The unknownArray should actually hold the original knownArray type even though we gave it
|
||||
// a cast array.
|
||||
CheckUnknownArray<vtkm::List<vtkm::Id>, vtkm::List<VTKM_DEFAULT_STORAGE_TAG>>(unknownArray, 1);
|
||||
}
|
||||
|
||||
void TrySetMultiplexerArray()
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> knownArray = CreateArray(vtkm::Id{});
|
||||
vtkm::cont::ArrayHandleMultiplexer<vtkm::cont::ArrayHandle<vtkm::Id>,
|
||||
vtkm::cont::ArrayHandleConstant<vtkm::Id>>
|
||||
multiplexerArray(knownArray);
|
||||
vtkm::cont::UnknownArrayHandle unknownArray(multiplexerArray);
|
||||
|
||||
// The unknownArray should actually hold the original knownArray type even though we gave it
|
||||
// a multiplexer array.
|
||||
CheckUnknownArray<vtkm::List<vtkm::Id>, vtkm::List<VTKM_DEFAULT_STORAGE_TAG>>(unknownArray, 1);
|
||||
}
|
||||
|
||||
struct DefaultTypeFunctor
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
TryDefaultType<T>();
|
||||
}
|
||||
};
|
||||
|
||||
void TestUnknownArrayHandle()
|
||||
{
|
||||
std::cout << "Try common types with default type lists." << std::endl;
|
||||
vtkm::testing::Testing::TryTypes(DefaultTypeFunctor{}, VTKM_DEFAULT_TYPE_LIST{});
|
||||
|
||||
std::cout << "Try exemplar VTK-m types." << std::endl;
|
||||
vtkm::testing::Testing::TryTypes(TryBasicVTKmType{});
|
||||
|
||||
std::cout << "Try unusual type." << std::endl;
|
||||
TryUnusualType();
|
||||
|
||||
std::cout << "Try CastToArrayHandle" << std::endl;
|
||||
TryCastToArrayHandle();
|
||||
|
||||
std::cout << "Try setting ArrayHandleCast" << std::endl;
|
||||
TrySetCastArray();
|
||||
|
||||
std::cout << "Try setting ArrayHandleMultiplexer" << std::endl;
|
||||
TrySetMultiplexerArray();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestUnknownArrayHandle(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestUnknownArrayHandle, argc, argv);
|
||||
}
|
Loading…
Reference in New Issue
Block a user