From 54626cd5fcb131fd7944494953a20fe13b8ecf88 Mon Sep 17 00:00:00 2001 From: maxence-wz Date: Fri, 2 Feb 2024 11:56:57 +0100 Subject: [PATCH] Use C++20 concepts to define the VectorConcept --- include/TFEL/Math/Vector/VectorConcept.hxx | 42 +++++++++++-------- .../Math/Vector/VectorConceptOperations.hxx | 40 ++++-------------- .../Math/Vector/VectorConceptOperations.ixx | 19 ++++----- include/TFEL/Math/matrix.hxx | 2 +- include/TFEL/Math/tvector.hxx | 2 +- include/TFEL/Math/vector.hxx | 2 +- tests/Math/include/function_unary_tests.hxx | 17 ++++---- tests/Math/include/function_unary_tests.ixx | 26 +++++++----- 8 files changed, 64 insertions(+), 86 deletions(-) diff --git a/include/TFEL/Math/Vector/VectorConcept.hxx b/include/TFEL/Math/Vector/VectorConcept.hxx index 144a82f0e..ffbcb5f91 100644 --- a/include/TFEL/Math/Vector/VectorConcept.hxx +++ b/include/TFEL/Math/Vector/VectorConcept.hxx @@ -30,41 +30,47 @@ namespace tfel::math { struct VectorTag {}; // end of VectorTag template - struct VectorConcept { - typedef VectorTag ConceptTag; - - protected: - VectorConcept() = default; - VectorConcept(VectorConcept&&) = default; - VectorConcept(const VectorConcept&) = default; - VectorConcept& operator=(const VectorConcept&) = default; - ~VectorConcept() = default; + struct VectorConceptBase { + using ConceptTag = VectorTag; }; /*! - * \brief an helper function which returns if the given type implements the - * `VectorConcept`. - * \tparam VectorType: type tested + * \brief definition of the VectorConcept concept + * a class matching the vector concept must expose the `VectorTag` and have + * access operators. */ - template - TFEL_HOST_DEVICE constexpr bool implementsVectorConcept() { - return tfel::meta::implements(); - } // end of implementsVectorConcept + template + concept VectorConcept = + (std::is_same_v::ConceptTag, VectorTag>)&& // + (requires(const T t, const unsigned short i) { t[i]; }) && // + (requires(const T t, const unsigned short i) { t(i); }); //! paratial specialisation for vectors template struct ConceptRebind { - using type = VectorConcept; + using type = VectorConceptBase; }; //! \brief a simple alias for backward compatibility with versions prior //! to 4.0 template using VectorTraits = - std::conditional_t(), + std::conditional_t, MathObjectTraits, MathObjectTraits>; + /*! + * \brief an helper function which returns if the given type implements the + * `VectorConcept`. + * \tparam VectorType: type tested + * \note function given for backward compatibility with versions prior + * to 5.0 + */ + template + [[deprecated]] TFEL_HOST_DEVICE constexpr bool implementsVectorConcept() { + return VectorConcept; + } // end of implementsVectorConcept + } // end of namespace tfel::math #include "TFEL/Math/Vector/VectorConceptOperations.hxx" diff --git a/include/TFEL/Math/Vector/VectorConceptOperations.hxx b/include/TFEL/Math/Vector/VectorConceptOperations.hxx index 012e50d38..ff88d51a9 100644 --- a/include/TFEL/Math/Vector/VectorConceptOperations.hxx +++ b/include/TFEL/Math/Vector/VectorConceptOperations.hxx @@ -16,6 +16,7 @@ #include #include +#include "TFEL/Math/power.hxx" #include "TFEL/Config/TFELConfig.hxx" #include "TFEL/TypeTraits/RealPartType.hxx" #include "TFEL/Math/ExpressionTemplates/Expr.hxx" @@ -82,28 +83,6 @@ namespace tfel::math { Expr>>; }; - template - struct IsVectorVectorOperationValid { - static constexpr bool cond = - (implementsVectorConcept() && implementsVectorConcept() && - (!isInvalid>())); - }; - - template - struct IsScalarVectorOperationValid { - static constexpr bool cond = - (isScalar() && implementsVectorConcept() && - (!isInvalid>())); - }; - - template - struct IsEuclidianNormValid { - static constexpr bool cond = - implementsVectorConcept() && - !isInvalid>::type>(); - }; - /*! * \return the inner product of a vector * \param const T1&, the left vector. @@ -113,23 +92,18 @@ namespace tfel::math { * \warning the operator| has not the priority expected for such * an operation : use of parenthesis is required. */ - template - TFEL_HOST_DEVICE - std::enable_if_t::cond, - BinaryOperationResult> - operator|(const T1&, const T2&); + template + TFEL_HOST_DEVICE constexpr auto operator|(const T1&, const T2&) requires( + !isInvalid>()); /*! * \brief return the euclidian norm of a tvector * \param v : the vector. * \return const typename tfel::typetraits::RealPartType::type, the result */ - template - TFEL_HOST_DEVICE - std::enable_if_t::cond, - typename tfel::typetraits::RealPartType< - BinaryOperationResult>::type> - norm(const T1&); + template + TFEL_HOST_DEVICE auto norm(const T1& v) requires( + !isInvalid>()); } // end of namespace tfel::math diff --git a/include/TFEL/Math/Vector/VectorConceptOperations.ixx b/include/TFEL/Math/Vector/VectorConceptOperations.ixx index a90467447..42fec6190 100644 --- a/include/TFEL/Math/Vector/VectorConceptOperations.ixx +++ b/include/TFEL/Math/Vector/VectorConceptOperations.ixx @@ -17,23 +17,18 @@ namespace tfel::math { - template - TFEL_HOST_DEVICE - std::enable_if_t::cond, - BinaryOperationResult> - operator|(const T1& a, const T2& b) { + template + TFEL_HOST_DEVICE constexpr auto operator|(const T1& a, const T2& b) requires( + !isInvalid>()) { typedef BinaryOperationResult Result; typedef BinaryOperationHandler Handle; return Handle::template exe(a, b); } - template - TFEL_HOST_DEVICE - std::enable_if_t::cond, - typename tfel::typetraits::RealPartType< - BinaryOperationResult>::type> - norm(const T1& v) { - return std::sqrt(real(v | v)); + template + TFEL_HOST_DEVICE auto norm(const T1& v) requires( + !isInvalid>()) { + return power<1, 2>(real(v | v)); } } // end of namespace tfel::math diff --git a/include/TFEL/Math/matrix.hxx b/include/TFEL/Math/matrix.hxx index ef9ee58ca..4c5952943 100644 --- a/include/TFEL/Math/matrix.hxx +++ b/include/TFEL/Math/matrix.hxx @@ -29,7 +29,7 @@ namespace tfel::math { */ template struct matrix - : VectorConcept>, + : VectorConceptBase>, GenericRuntimeArray, RuntimeRowMajorMatrixArrayPolicy> { //! \brief a simple alias diff --git a/include/TFEL/Math/tvector.hxx b/include/TFEL/Math/tvector.hxx index 628068aac..f24b9d0ce 100644 --- a/include/TFEL/Math/tvector.hxx +++ b/include/TFEL/Math/tvector.hxx @@ -80,7 +80,7 @@ namespace tfel::math { }; // end of struct DerivativeTypeDispatcher template - struct tvector : VectorConcept>, + struct tvector : VectorConceptBase>, GenericFixedSizeArray, FixedSizeVectorPolicy> { //! \brief a simple alias diff --git a/include/TFEL/Math/vector.hxx b/include/TFEL/Math/vector.hxx index e30c70a3b..accf1f530 100644 --- a/include/TFEL/Math/vector.hxx +++ b/include/TFEL/Math/vector.hxx @@ -26,7 +26,7 @@ namespace tfel::math { template - struct vector : VectorConcept>, + struct vector : VectorConceptBase>, GenericRuntimeArray, RuntimeVectorArrayPolicy> { //! \brief a simple alias diff --git a/tests/Math/include/function_unary_tests.hxx b/tests/Math/include/function_unary_tests.hxx index 86aa20e37..9dd52e83d 100644 --- a/tests/Math/include/function_unary_tests.hxx +++ b/tests/Math/include/function_unary_tests.hxx @@ -18,15 +18,14 @@ #include "TFEL/Math/Matrix/MatrixConcept.hxx" #include "TFEL/Math/Stensor/StensorConcept.hxx" -template -void function(const tfel::math::VectorConcept&); - -template -void function(const tfel::math::VectorConcept&, - const typename tfel::math::MathObjectTraits::NumType, - const typename tfel::math::MathObjectTraits::NumType, - const typename tfel::math::MathObjectTraits::NumType, - const typename tfel::math::MathObjectTraits::NumType, +void function(const tfel::math::VectorConcept auto&); + +template +void function(const VectorType&, + const tfel::math::numeric_type, + const tfel::math::numeric_type, + const tfel::math::numeric_type, + const tfel::math::numeric_type, const unsigned int); template diff --git a/tests/Math/include/function_unary_tests.ixx b/tests/Math/include/function_unary_tests.ixx index 092908d82..af7bd08fb 100644 --- a/tests/Math/include/function_unary_tests.ixx +++ b/tests/Math/include/function_unary_tests.ixx @@ -25,21 +25,25 @@ } \ static_cast(0) -template -std::enable_if_t(), void> -function(const VectorType& x) { +// template +// std::enable_if_t(), void> +// function(const VectorType& x) { +// std::cout << x(0) << " " << x(1) << " " << x(2) << std::endl; +// std::cout << "------" << std::endl; +// } + +void function(const tfel::math::VectorConcept auto& x) { std::cout << x(0) << " " << x(1) << " " << x(2) << std::endl; std::cout << "------" << std::endl; } -template -std::enable_if_t(), void> -function(const VectorType& x, - const tfel::math::numeric_type v0, - const tfel::math::numeric_type v1, - const tfel::math::numeric_type v2, - const tfel::math::numeric_type eps, - const unsigned int test_number) { +template +void function(const VectorType& x, + const tfel::math::numeric_type v0, + const tfel::math::numeric_type v1, + const tfel::math::numeric_type v2, + const tfel::math::numeric_type eps, + const unsigned int test_number) { #ifdef TFEL_VERBOSE std::cout << "Test : " << test_number << std::endl; #else