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)