//============================================================================ // 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 vtkm_testing_VecTraitsTest_h #define vtkm_testing_VecTraitsTest_h //GCC 4+ when running the test code have false positive warnings //about uninitialized vtkm::VecC<> when filled by VecTraits::CopyInto. //The testing code already verifies that CopyInto works by verifying the //results, so we are going to suppress `-Wmaybe-uninitialized` for this //file //This block has to go before we include any vtkm file that brings in // otherwise the warning suppression will not work #include #if (defined(VTKM_GCC) && __GNUC__ >= 4) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif // gcc 4+ #include #include #include #include namespace vtkm { namespace testing { namespace detail { inline void CompareDimensionalityTags(vtkm::TypeTraitsScalarTag, vtkm::VecTraitsTagSingleComponent) { // If we are here, everything is fine. } inline void CompareDimensionalityTags(vtkm::TypeTraitsVectorTag, vtkm::VecTraitsTagMultipleComponents) { // If we are here, everything is fine. } template inline void CheckIsStatic(const T&, vtkm::VecTraitsTagSizeStatic) { VTKM_TEST_ASSERT(vtkm::VecTraits::NUM_COMPONENTS == NUM_COMPONENTS, "Traits returns unexpected number of components"); } template inline void CheckIsStatic(const T&, vtkm::VecTraitsTagSizeVariable) { // If we are here, everything is fine. } template struct VecIsWritable { using type = std::true_type; }; template struct VecIsWritable> { using type = std::false_type; }; // Part of TestVecTypeImpl that writes to the Vec type template static void TestVecTypeWritableImpl(const T& inVector, const VecCopyType& vectorCopy, T& outVector, std::true_type) { using Traits = vtkm::VecTraits; using ComponentType = typename Traits::ComponentType; { const ComponentType multiplier = 4; for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; i++) { Traits::SetComponent( outVector, i, ComponentType(multiplier * Traits::GetComponent(inVector, i))); } vtkm::Vec resultCopy; Traits::CopyInto(outVector, resultCopy); VTKM_TEST_ASSERT(test_equal(resultCopy, multiplier * vectorCopy), "Got bad result for scalar multiple"); } { const ComponentType multiplier = 7; for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; i++) { Traits::GetComponent(outVector, i) = ComponentType(multiplier * Traits::GetComponent(inVector, i)); } vtkm::Vec resultCopy; Traits::CopyInto(outVector, resultCopy); VTKM_TEST_ASSERT(test_equal(resultCopy, multiplier * vectorCopy), "Got bad result for scalar multiple"); } } template static void TestVecTypeWritableImpl(const T& vtkmNotUsed(inVector), const VecCopyType& vtkmNotUsed(vectorCopy), T& vtkmNotUsed(outVector), std::false_type) { // Skip writable functionality. } /// Compares some manual arithmetic through type traits to arithmetic with /// the Tuple class. template static void TestVecTypeImpl(const typename std::remove_const::type& inVector, typename std::remove_const::type& outVector) { using Traits = vtkm::VecTraits; using ComponentType = typename Traits::ComponentType; using NonConstT = typename std::remove_const::type; CheckIsStatic(inVector, typename Traits::IsSizeStatic()); VTKM_TEST_ASSERT(Traits::GetNumberOfComponents(inVector) == NUM_COMPONENTS, "Traits returned wrong number of components."); vtkm::Vec vectorCopy; Traits::CopyInto(inVector, vectorCopy); VTKM_TEST_ASSERT(test_equal(vectorCopy, inVector), "CopyInto does not work."); { auto expected = vtkm::Dot(vectorCopy, vectorCopy); decltype(expected) result = 0; for (vtkm::IdComponent i = 0; i < NUM_COMPONENTS; i++) { ComponentType component = Traits::GetComponent(inVector, i); result = result + (component * component); } VTKM_TEST_ASSERT(test_equal(result, expected), "Got bad result for dot product"); } // This will fail to compile if the tags are wrong. detail::CompareDimensionalityTags(typename vtkm::TypeTraits::DimensionalityTag(), typename vtkm::VecTraits::HasMultipleComponents()); 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) { // If we are running here, everything is fine. } } // namespace detail /// Checks to make sure that the HasMultipleComponents tag is actually for /// multiple components. Should only be called for vector classes that actually /// have multiple components. /// template inline void TestVecComponentsTag() { // This will fail to compile if the tag is wrong // (i.e. not vtkm::VecTraitsTagMultipleComponents) detail::CheckVecComponentsTag(typename vtkm::VecTraits::HasMultipleComponents()); } namespace detail { inline void CheckScalarComponentsTag(vtkm::VecTraitsTagSingleComponent) { // If we are running here, everything is fine. } } // namespace detail /// Compares some manual arithmetic through type traits to arithmetic with /// the Tuple class. template static void TestVecType(const T& inVector, T& outVector) { detail::TestVecTypeImpl(inVector, outVector); detail::TestVecTypeImpl(inVector, outVector); } /// Checks to make sure that the HasMultipleComponents tag is actually for a /// single component. Should only be called for "vector" classes that actually /// have only a single component (that is, are really scalars). /// template inline void TestScalarComponentsTag() { // This will fail to compile if the tag is wrong // (i.e. not vtkm::VecTraitsTagSingleComponent) detail::CheckScalarComponentsTag(typename vtkm::VecTraits::HasMultipleComponents()); } } } // namespace vtkm::testing #if (defined(VTKM_GCC) && __GNUC__ > 4 && __GNUC__ < 7) #pragma GCC diagnostic pop #endif // gcc 5 or 6 #endif //vtkm_testing_VecTraitsTest_h