From 6323d6803e1ec708e300c350ae69c1436edae119 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Mon, 2 Sep 2019 21:52:56 -0600 Subject: [PATCH] Add recursive component queries to VecTraits Added a BaseComponentType to VecTraits that recursively finds the base (non-Vec) type of a Vec. This is useful when dealing with potentially nested Vec's (e.g. Vec, N>) and you need to keep the structure but know the base type. Also added a couple of templates for keeping the structure but changing the type. These are ReplaceComponentType and ReplaceBaseComponentType. These allow you to create new Vec's with the same structure as the query Vec but with differen component types. --- docs/changelog/vec-traits-base-components.md | 34 +++++ vtkm/Matrix.h | 10 ++ vtkm/VecAxisAlignedPointCoordinates.h | 8 ++ vtkm/VecFromPortal.h | 1 + vtkm/VecFromPortalPermute.h | 1 + vtkm/VecTraits.h | 133 ++++++++++++++++++- vtkm/VecVariable.h | 9 ++ vtkm/testing/VecTraitsTests.h | 35 +++++ 8 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 docs/changelog/vec-traits-base-components.md diff --git a/docs/changelog/vec-traits-base-components.md b/docs/changelog/vec-traits-base-components.md new file mode 100644 index 000000000..1db6b06de --- /dev/null +++ b/docs/changelog/vec-traits-base-components.md @@ -0,0 +1,34 @@ +# Recursive base component queries to VecTraits + +This change adds a recursive `BaseComponentType` to `VecTraits` that +recursively finds the base (non-`Vec`) type of a `Vec`. This is useful when +dealing with potentially nested `Vec`s (e.g. `Vec, N>`) and you +want to know the precision of the math being defined. + +``` cpp +using NestedVec = vtkm::Vec, 8>; + +// ComponentType becomes vtkm::Vec +using ComponentType = typename vtkm::VecTraits::ComponentType; + +// BaseComponentType becomes vtkm::Float32 +using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; +``` + +Also added the ability to `VecTraits` to change the component type of a +vector. The template `RepalceComponentType` resolves to a `Vec` of the same +type with the component replaced with a new type. The template +`ReplaceBaseComponentType` traverses down a nested type and replaces the +base type. + +``` cpp +using NestedVec = vtkm::Vec, 8>; + +// NewVec1 becomes vtkm::Vec +using NewVec1 = + typename vtkm::VecTraits::template ReplaceComponentType; + +// NewVec2 becomes vtkm::Vec, 8> +using NewVec1 = + typename vtkm::VecTraits::template ReplaceBaseComponentType; +``` diff --git a/vtkm/Matrix.h b/vtkm/Matrix.h index 29a0df97e..3a313f950 100644 --- a/vtkm/Matrix.h +++ b/vtkm/Matrix.h @@ -541,6 +541,7 @@ private: public: using ComponentType = T; + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; static constexpr vtkm::IdComponent NUM_COMPONENTS = NumRow * NumCol; using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents; using IsSizeStatic = vtkm::VecTraitsTagSizeStatic; @@ -567,6 +568,15 @@ public: { GetComponent(matrix, component) = value; } + + template + using ReplaceComponentType = vtkm::Matrix; + + template + using ReplaceBaseComponentType = + vtkm::Matrix::template ReplaceBaseComponentType, + NumRow, + NumCol>; }; //--------------------------------------------------------------------------- diff --git a/vtkm/VecAxisAlignedPointCoordinates.h b/vtkm/VecAxisAlignedPointCoordinates.h index 7b980ef4a..ea4c08d85 100644 --- a/vtkm/VecAxisAlignedPointCoordinates.h +++ b/vtkm/VecAxisAlignedPointCoordinates.h @@ -147,6 +147,7 @@ struct VecTraits> using VecType = vtkm::VecAxisAlignedPointCoordinates; using ComponentType = vtkm::Vec3f; + using BaseComponentType = vtkm::FloatDefault; using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents; using IsSizeStatic = vtkm::VecTraitsTagSizeStatic; @@ -161,6 +162,13 @@ struct VecTraits> return vector[componentIndex]; } + // These are a bit of a hack since VecAxisAlignedPointCoordinates only supports one component + // type. Using these might not work as expected. + template + using ReplaceComponentType = vtkm::Vec; + template + using ReplaceBaseComponenttype = vtkm::Vec, NUM_COMPONENTS>; + template VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec& dest) { diff --git a/vtkm/VecFromPortal.h b/vtkm/VecFromPortal.h index 729732fbc..0a0381ca5 100644 --- a/vtkm/VecFromPortal.h +++ b/vtkm/VecFromPortal.h @@ -99,6 +99,7 @@ struct VecTraits> using VecType = vtkm::VecFromPortal; using ComponentType = typename VecType::ComponentType; + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents; using IsSizeStatic = vtkm::VecTraitsTagSizeVariable; diff --git a/vtkm/VecFromPortalPermute.h b/vtkm/VecFromPortalPermute.h index 93377e06c..f1056b3e5 100644 --- a/vtkm/VecFromPortalPermute.h +++ b/vtkm/VecFromPortalPermute.h @@ -136,6 +136,7 @@ struct VecTraits> using VecType = vtkm::VecFromPortalPermute; using ComponentType = typename VecType::ComponentType; + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents; using IsSizeStatic = vtkm::VecTraitsTagSizeVariable; diff --git a/vtkm/VecTraits.h b/vtkm/VecTraits.h index 77374f064..357e27167 100644 --- a/vtkm/VecTraits.h +++ b/vtkm/VecTraits.h @@ -66,10 +66,19 @@ template struct VTKM_NEVER_EXPORT VecTraits { #ifdef VTKM_DOXYGEN_ONLY - /// Type of the components in the vector. + /// \brief Type of the components in the vector. + /// + /// If the type is really a scalar, then the component type is the same as the scalar type. /// using ComponentType = typename VecType::ComponentType; + /// \brief Base component type in the vector. + /// + /// Similar to ComponentType except that for nested vectors (e.g. Vec, N>), it + /// returns the base scalar type at the end of the composition (T in this example). + /// + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; + /// \brief Number of components in the vector. /// /// This is only defined for vectors of a static size. @@ -111,6 +120,27 @@ struct VTKM_NEVER_EXPORT VecTraits vtkm::IdComponent component, ComponentType value); + /// \brief Get a vector of the same type but with a different component. + /// + /// This type resolves to another vector with a different component type. For example, + /// vtkm::VecTraits>::ReplaceComponentType is vtkm::Vec. + /// This replacement is not recursive. So VecTraits, N>::ReplaceComponentType + /// is vtkm::Vec. + /// + template + using ReplaceComponentType = VecTemplate; + + /// \brief Get a vector of the same type but with a different base component. + /// + /// This type resolves to another vector with a different base component type. The replacement + /// is recursive for nested types. For example, + /// VecTraits, N>::ReplaceComponentType is Vec, N>. + /// + template + using ReplaceBaseComponentType = VecTemplate< + typename VecTraits::template ReplaceBaseComponentType, + N>; + /// Copies the components in the given vector into a given Vec object. /// template @@ -158,10 +188,19 @@ struct VTKM_NEVER_EXPORT VecTraits> { using VecType = vtkm::Vec; - /// Type of the components in the vector. + /// \brief Type of the components in the vector. + /// + /// If the type is really a scalar, then the component type is the same as the scalar type. /// using ComponentType = typename VecType::ComponentType; + /// \brief Base component type in the vector. + /// + /// Similar to ComponentType except that for nested vectors (e.g. Vec, N>), it + /// returns the base scalar type at the end of the composition (T in this example). + /// + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; + /// Number of components in the vector. /// static constexpr vtkm::IdComponent NUM_COMPONENTS = VecType::NUM_COMPONENTS; @@ -208,6 +247,27 @@ struct VTKM_NEVER_EXPORT VecTraits> vector[component] = value; } + /// \brief Get a vector of the same type but with a different component. + /// + /// This type resolves to another vector with a different component type. For example, + /// vtkm::VecTraits>::ReplaceComponentType is vtkm::Vec. + /// This replacement is not recursive. So VecTraits, N>::ReplaceComponentType + /// is vtkm::Vec. + /// + template + using ReplaceComponentType = vtkm::Vec; + + /// \brief Get a vector of the same type but with a different base component. + /// + /// This type resolves to another vector with a different base component type. The replacement + /// is recursive for nested types. For example, + /// VecTraits, N>::ReplaceComponentType is Vec, N>. + /// + template + using ReplaceBaseComponentType = vtkm::Vec< + typename vtkm::VecTraits::template ReplaceBaseComponentType, + Size>; + /// Converts whatever type this vector is into the standard VTKm Tuple. /// template @@ -222,10 +282,19 @@ struct VTKM_NEVER_EXPORT VecTraits> { using VecType = vtkm::VecC; - /// Type of the components in the vector. + /// \brief Type of the components in the vector. + /// + /// If the type is really a scalar, then the component type is the same as the scalar type. /// using ComponentType = typename VecType::ComponentType; + /// \brief Base component type in the vector. + /// + /// Similar to ComponentType except that for nested vectors (e.g. Vec, N>), it + /// returns the base scalar type at the end of the composition (T in this example). + /// + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; + /// Number of components in the given vector. /// VTKM_EXEC_CONT @@ -273,6 +342,26 @@ struct VTKM_NEVER_EXPORT VecTraits> vector[component] = value; } + /// \brief Get a vector of the same type but with a different component. + /// + /// This type resolves to another vector with a different component type. For example, + /// vtkm::VecTraits>::ReplaceComponentType is vtkm::Vec. + /// This replacement is not recursive. So VecTraits, N>::ReplaceComponentType + /// is vtkm::Vec. + /// + template + using ReplaceComponentType = vtkm::VecC; + + /// \brief Get a vector of the same type but with a different base component. + /// + /// This type resolves to another vector with a different base component type. The replacement + /// is recursive for nested types. For example, + /// VecTraits, N>::ReplaceComponentType is Vec, N>. + /// + template + using ReplaceBaseComponentType = vtkm::VecC< + typename vtkm::VecTraits::template ReplaceBaseComponentType>; + /// Converts whatever type this vector is into the standard VTKm Tuple. /// template @@ -287,10 +376,19 @@ struct VTKM_NEVER_EXPORT VecTraits> { using VecType = vtkm::VecCConst; - /// Type of the components in the vector. + /// \brief Type of the components in the vector. + /// + /// If the type is really a scalar, then the component type is the same as the scalar type. /// using ComponentType = typename VecType::ComponentType; + /// \brief Base component type in the vector. + /// + /// Similar to ComponentType except that for nested vectors (e.g. Vec, N>), it + /// returns the base scalar type at the end of the composition (T in this example). + /// + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; + /// Number of components in the given vector. /// VTKM_EXEC_CONT @@ -333,6 +431,26 @@ struct VTKM_NEVER_EXPORT VecTraits> vector[component] = value; } + /// \brief Get a vector of the same type but with a different component. + /// + /// This type resolves to another vector with a different component type. For example, + /// vtkm::VecTraits>::ReplaceComponentType is vtkm::Vec. + /// This replacement is not recursive. So VecTraits, N>::ReplaceComponentType + /// is vtkm::Vec. + /// + template + using ReplaceComponentType = vtkm::VecCConst; + + /// \brief Get a vector of the same type but with a different base component. + /// + /// This type resolves to another vector with a different base component type. The replacement + /// is recursive for nested types. For example, + /// VecTraits, N>::ReplaceComponentType is Vec, N>. + /// + template + using ReplaceBaseComponentType = vtkm::VecCConst< + typename vtkm::VecTraits::template ReplaceBaseComponentType>; + /// Converts whatever type this vector is into the standard VTKm Tuple. /// template @@ -350,6 +468,7 @@ template struct VTKM_NEVER_EXPORT VecTraitsBasic { using ComponentType = ScalarType; + using BaseComponentType = ScalarType; static constexpr vtkm::IdComponent NUM_COMPONENTS = 1; using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent; using IsSizeStatic = vtkm::VecTraitsTagSizeStatic; @@ -372,6 +491,12 @@ struct VTKM_NEVER_EXPORT VecTraitsBasic vector = value; } + template + using ReplaceComponentType = NewComponentType; + + template + using ReplaceBaseComponentType = NewComponentType; + template VTKM_EXEC_CONT static void CopyInto(const ScalarType& src, vtkm::Vec& dest) { diff --git a/vtkm/VecVariable.h b/vtkm/VecVariable.h index 54627fdd7..1fca86ba9 100644 --- a/vtkm/VecVariable.h +++ b/vtkm/VecVariable.h @@ -103,6 +103,7 @@ struct VecTraits> using VecType = vtkm::VecVariable; using ComponentType = typename VecType::ComponentType; + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents; using IsSizeStatic = vtkm::VecTraitsTagSizeVariable; @@ -131,6 +132,14 @@ struct VecTraits> vector[componentIndex] = value; } + template + using ReplaceComponentType = vtkm::VecVariable; + + template + using ReplaceBaseComponentType = vtkm::VecVariable< + typename vtkm::VecTraits::template ReplaceBaseComponentType, + MaxSize>; + template VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec& dest) { diff --git a/vtkm/testing/VecTraitsTests.h b/vtkm/testing/VecTraitsTests.h index babc0b0ef..e84db5b72 100644 --- a/vtkm/testing/VecTraitsTests.h +++ b/vtkm/testing/VecTraitsTests.h @@ -25,6 +25,7 @@ #include +#include #include #include @@ -154,6 +155,40 @@ static void TestVecTypeImpl(const typename std::remove_const::type& inVector, TestVecTypeWritableImpl( inVector, vectorCopy, outVector, typename VecIsWritable::type()); + + // Compiler checks for base component types + using BaseComponentType = typename vtkm::VecTraits::BaseComponentType; + VTKM_STATIC_ASSERT((std::is_same::DimensionalityTag, + vtkm::TypeTraitsScalarTag>::value)); + VTKM_STATIC_ASSERT((std::is_same::BaseComponentType, + BaseComponentType>::value)); + + // Compiler checks for replacing component types + using ReplaceWithVecComponent = + typename vtkm::VecTraits::template ReplaceComponentType>; + VTKM_STATIC_ASSERT( + (std::is_same::DimensionalityTag, + vtkm::TypeTraitsVectorTag>::value && + std::is_same::ComponentType, + vtkm::Vec>::value) || + (std::is_same::DimensionalityTag, + vtkm::TypeTraitsScalarTag>::value && + std::is_same::ComponentType, char>::value)); + VTKM_STATIC_ASSERT( + (std::is_same::BaseComponentType, + char>::value)); + using ReplaceBaseComponent = + typename vtkm::VecTraits::template ReplaceBaseComponentType; + VTKM_STATIC_ASSERT( + (std::is_same::DimensionalityTag, + vtkm::TypeTraitsVectorTag>::value && + std::is_same::ComponentType, + vtkm::Vec>::value) || + (std::is_same::DimensionalityTag, + vtkm::TypeTraitsScalarTag>::value && + std::is_same::ComponentType, short>::value)); + VTKM_STATIC_ASSERT(( + std::is_same::BaseComponentType, short>::value)); } inline void CheckVecComponentsTag(vtkm::VecTraitsTagMultipleComponents)