Make ArrayHandleCast storage type shorter

This commit is contained in:
Kenneth Moreland 2019-12-18 14:55:47 -07:00
parent c470df0015
commit 944a3c4c14
4 changed files with 217 additions and 31 deletions

@ -0,0 +1,31 @@
# Shorter fancy array handle classnames
Many of the fancy `ArrayHandle`s use the generic builders like
`ArrayHandleTransform` and `ArrayHandleImplicit` for their implementation.
Such is fine, but because they use functors and other such generic items to
template their `Storage`, you can end up with very verbose classnames. This
is an issue for humans trying to discern classnames. It can also be an
issue for compilers that end up with very long resolved classnames that
might get truncated if they extend past what was expected.
The fix was for these classes to declare their own `Storage` tag and then
implement their `Storage` and `ArrayTransport` classes as trivial
subclasses of the generic `ArrayHandleImplicit` or `ArrayHandleTransport`.
Here is a list of classes that were updated.
#### `ArrayHandleCast<TargetT, vtkm::cont::ArrayHandle<SourceT, SourceStorage>>`
Old storage:
``` cpp
vtkm::cont::internal::StorageTagTransform<
vtkm::cont::ArrayHandle<SourceT, SourceStorage>,
vtkm::cont::internal::Cast<TargetT, SourceT>,
vtkm::cont::internal::Cast<SourceT, TargetT>>
```
New Storage:
``` cpp
vtkm::cont::StorageTagCast<SourceT, SourceStorage>
```

@ -24,14 +24,127 @@ namespace vtkm
namespace cont
{
template <typename SourceT, typename SourceStorage>
struct StorageTagCast
{
};
namespace internal
{
template <typename FromType, typename ToType>
struct VTKM_ALWAYS_EXPORT Cast
{
// The following operator looks like it should never issue a cast warning because of
// the static_cast (and we don't want it to issue a warning). However, if ToType is
// an object that has a constructor that takes a value that FromType can be cast to,
// that cast can cause a warning. For example, if FromType is vtkm::Float64 and ToType
// is vtkm::Vec<vtkm::Float32, 3>, the static_cast will first implicitly cast the
// Float64 to a Float32 (which causes a warning) before using the static_cast to
// construct the Vec with the Float64. The easiest way around the problem is to
// just disable all conversion warnings here. (The pragmas are taken from those
// used in Types.h for the VecBase class.)
#if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8)))
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wfloat-conversion"
#endif // gcc || clang
#endif //not using cuda < 8
#if defined(VTKM_MSVC)
#pragma warning(push)
#pragma warning(disable : 4244)
#endif
VTKM_EXEC_CONT
ToType operator()(const FromType& val) const { return static_cast<ToType>(val); }
#if (!(defined(VTKM_CUDA) && (__CUDACC_VER_MAJOR__ < 8)))
#if (defined(VTKM_GCC) || defined(VTKM_CLANG))
#pragma GCC diagnostic pop
#endif // gcc || clang
#endif // not using cuda < 8
#if defined(VTKM_MSVC)
#pragma warning(pop)
#endif
};
namespace detail
{
template <typename TargetT, typename SourceT, typename SourceStorage, bool... CastFlags>
struct ArrayHandleCastTraits;
template <typename TargetT, typename SourceT, typename SourceStorage>
struct ArrayHandleCastTraits<TargetT, SourceT, SourceStorage>
: ArrayHandleCastTraits<TargetT,
SourceT,
SourceStorage,
std::is_convertible<SourceT, TargetT>::value,
std::is_convertible<TargetT, SourceT>::value>
{
};
// Case where the forward cast is invalid, so this array is invalid.
template <typename TargetT, typename SourceT, typename SourceStorage, bool CanCastBackward>
struct ArrayHandleCastTraits<TargetT, SourceT, SourceStorage, false, CanCastBackward>
{
struct StorageSuperclass : vtkm::cont::internal::UndefinedStorage
{
using PortalType = vtkm::cont::internal::detail::UndefinedArrayPortal<TargetT>;
using PortalConstType = vtkm::cont::internal::detail::UndefinedArrayPortal<TargetT>;
};
};
// Case where the forward cast is valid but the backward cast is invalid.
template <typename TargetT, typename SourceT, typename SourceStorage>
struct ArrayHandleCastTraits<TargetT, SourceT, SourceStorage, true, false>
{
using StorageTagSuperclass = StorageTagTransform<vtkm::cont::ArrayHandle<SourceT, SourceStorage>,
vtkm::cont::internal::Cast<SourceT, TargetT>>;
using StorageSuperclass = vtkm::cont::internal::Storage<TargetT, StorageTagSuperclass>;
template <typename Device>
using ArrayTransferSuperclass = ArrayTransfer<TargetT, StorageTagSuperclass, Device>;
};
// Case where both forward and backward casts are valid.
template <typename TargetT, typename SourceT, typename SourceStorage>
struct ArrayHandleCastTraits<TargetT, SourceT, SourceStorage, true, true>
{
using StorageTagSuperclass = StorageTagTransform<vtkm::cont::ArrayHandle<SourceT, SourceStorage>,
vtkm::cont::internal::Cast<SourceT, TargetT>,
vtkm::cont::internal::Cast<TargetT, SourceT>>;
using StorageSuperclass = vtkm::cont::internal::Storage<TargetT, StorageTagSuperclass>;
template <typename Device>
using ArrayTransferSuperclass = ArrayTransfer<TargetT, StorageTagSuperclass, Device>;
};
} // namespace detail
template <typename TargetT, typename SourceT, typename SourceStorage>
struct Storage<TargetT, StorageTagCast<SourceT, SourceStorage>>
: detail::ArrayHandleCastTraits<TargetT, SourceT, SourceStorage>::StorageSuperclass
{
using Superclass =
typename detail::ArrayHandleCastTraits<TargetT, SourceT, SourceStorage>::StorageSuperclass;
using Superclass::Superclass;
};
template <typename TargetT, typename SourceT, typename SourceStorage, typename Device>
struct ArrayTransfer<TargetT, StorageTagCast<SourceT, SourceStorage>, Device>
: detail::ArrayHandleCastTraits<TargetT,
SourceT,
SourceStorage>::template ArrayTransferSuperclass<Device>
{
using Superclass =
typename detail::ArrayHandleCastTraits<TargetT,
SourceT,
SourceStorage>::template ArrayTransferSuperclass<Device>;
using Superclass::Superclass;
};
} // namespace internal
@ -44,20 +157,21 @@ struct VTKM_ALWAYS_EXPORT Cast
///
template <typename T, typename ArrayHandleType>
class ArrayHandleCast
: public vtkm::cont::ArrayHandleTransform<ArrayHandleType,
internal::Cast<typename ArrayHandleType::ValueType, T>,
internal::Cast<T, typename ArrayHandleType::ValueType>>
: public vtkm::cont::ArrayHandle<
T,
StorageTagCast<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>>
{
public:
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleCast,
(ArrayHandleCast<T, ArrayHandleType>),
(vtkm::cont::ArrayHandleTransform<ArrayHandleType,
internal::Cast<typename ArrayHandleType::ValueType, T>,
internal::Cast<T, typename ArrayHandleType::ValueType>>));
(vtkm::cont::ArrayHandle<
T,
StorageTagCast<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>>));
ArrayHandleCast(const ArrayHandleType& handle)
: Superclass(handle)
ArrayHandleCast(const vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
typename ArrayHandleType::StorageTag>& handle)
: Superclass(typename Superclass::StorageType(handle))
{
this->ValidateTypeCast<typename ArrayHandleType::ValueType>();
}
@ -168,23 +282,21 @@ namespace vtkm
namespace cont
{
template <typename T1, typename T2>
struct SerializableTypeString<vtkm::cont::internal::Cast<T1, T2>>
template <typename T, typename AH>
struct SerializableTypeString<vtkm::cont::ArrayHandleCast<T, AH>>
{
static VTKM_CONT const std::string& Get()
{
static std::string name = "AH_Cast_Functor<" + SerializableTypeString<T1>::Get() + "," +
SerializableTypeString<T2>::Get() + ">";
static std::string name = "AH_Cast<" + SerializableTypeString<T>::Get() + "," +
SerializableTypeString<typename AH::ValueType>::Get() + "," +
SerializableTypeString<typename AH::StorageTag>::Get() + ">";
return name;
}
};
template <typename T, typename AH>
struct SerializableTypeString<vtkm::cont::ArrayHandleCast<T, AH>>
: SerializableTypeString<
vtkm::cont::ArrayHandleTransform<AH,
vtkm::cont::internal::Cast<typename AH::ValueType, T>,
vtkm::cont::internal::Cast<T, typename AH::ValueType>>>
template <typename T1, typename T2, typename S>
struct SerializableTypeString<vtkm::cont::ArrayHandle<T1, vtkm::cont::StorageTagCast<T2, S>>>
: SerializableTypeString<vtkm::cont::ArrayHandleCast<T1, vtkm::cont::ArrayHandle<T2, S>>>
{
};
}
@ -193,20 +305,33 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleCast<T, AH>>
namespace mangled_diy_namespace
{
template <typename T1, typename T2>
struct Serialization<vtkm::cont::internal::Cast<T1, T2>>
template <typename TargetT, typename SourceT, typename SourceStorage>
struct Serialization<
vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>>>
{
static VTKM_CONT void save(BinaryBuffer&, const vtkm::cont::internal::Cast<T1, T2>&) {}
private:
using BaseType =
vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>>;
static VTKM_CONT void load(BinaryBuffer&, vtkm::cont::internal::Cast<T1, T2>&) {}
public:
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
{
vtkmdiy::save(bb, obj.GetStorage().GetArray());
}
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
{
vtkm::cont::ArrayHandle<SourceT, SourceStorage> array;
vtkmdiy::load(bb, array);
obj = BaseType(array);
}
};
template <typename T, typename AH>
struct Serialization<vtkm::cont::ArrayHandleCast<T, AH>>
: Serialization<
vtkm::cont::ArrayHandleTransform<AH,
vtkm::cont::internal::Cast<typename AH::ValueType, T>,
vtkm::cont::internal::Cast<T, typename AH::ValueType>>>
template <typename TargetT, typename AH>
struct Serialization<vtkm::cont::ArrayHandleCast<TargetT, AH>>
: Serialization<vtkm::cont::ArrayHandle<
TargetT,
vtkm::cont::StorageTagCast<typename AH::ValueType, typename AH::StorageTag>>>
{
};

@ -382,8 +382,8 @@ public:
VTKM_CONT
Storage(const ArrayHandleType& array,
const FunctorType& functor,
const InverseFunctorType& inverseFunctor)
const FunctorType& functor = FunctorType(),
const InverseFunctorType& inverseFunctor = InverseFunctorType())
: Array(array)
, Functor(functor)
, InverseFunctor(inverseFunctor)

@ -489,7 +489,7 @@ private:
this->FetchArrayExact(targetArray, self, foundArray);
}
// Special condition for transformed arrays (including cast arrays). Instead of pulling out the
// Special condition for transformed arrays. Instead of pulling out the
// transform, pull out the array that is being transformed.
template <typename T,
typename SrcArray,
@ -522,6 +522,36 @@ private:
}
}
}
// 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, typename... TypeList>
VTKM_CONT void FetchArray(
vtkm::cont::ArrayHandle<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage>>&
targetArray,
const vtkm::cont::VariantArrayHandleBase<TypeList...>& 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