Skip to content

Commit

Permalink
Merge pull request #497 from thelfer/493-tfel-mathintroduce-the-vecto…
Browse files Browse the repository at this point in the history
…r-concept

Use C++20 concepts to define the VectorConcept
  • Loading branch information
thelfer authored Feb 2, 2024
2 parents 5d84a11 + 54626cd commit f66aba8
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 86 deletions.
42 changes: 24 additions & 18 deletions include/TFEL/Math/Vector/VectorConcept.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,47 @@ namespace tfel::math {
struct VectorTag {}; // end of VectorTag

template <typename T>
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 <typename VectorType>
TFEL_HOST_DEVICE constexpr bool implementsVectorConcept() {
return tfel::meta::implements<VectorType, VectorConcept>();
} // end of implementsVectorConcept
template <typename T>
concept VectorConcept =
(std::is_same_v<typename std::decay_t<T>::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 <typename Type>
struct ConceptRebind<VectorTag, Type> {
using type = VectorConcept<Type>;
using type = VectorConceptBase<Type>;
};

//! \brief a simple alias for backward compatibility with versions prior
//! to 4.0
template <typename VectorType>
using VectorTraits =
std::conditional_t<implementsVectorConcept<VectorType>(),
std::conditional_t<VectorConcept<VectorType>,
MathObjectTraits<VectorType>,
MathObjectTraits<tfel::meta::InvalidType>>;

/*!
* \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 <typename VectorType>
[[deprecated]] TFEL_HOST_DEVICE constexpr bool implementsVectorConcept() {
return VectorConcept<VectorType>;
} // end of implementsVectorConcept

} // end of namespace tfel::math

#include "TFEL/Math/Vector/VectorConceptOperations.hxx"
Expand Down
40 changes: 7 additions & 33 deletions include/TFEL/Math/Vector/VectorConceptOperations.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <cmath>
#include <type_traits>
#include "TFEL/Math/power.hxx"
#include "TFEL/Config/TFELConfig.hxx"
#include "TFEL/TypeTraits/RealPartType.hxx"
#include "TFEL/Math/ExpressionTemplates/Expr.hxx"
Expand Down Expand Up @@ -82,28 +83,6 @@ namespace tfel::math {
Expr<Result, UnaryOperation<A, OpNeg>>>;
};

template <typename T1, typename T2, typename Op>
struct IsVectorVectorOperationValid {
static constexpr bool cond =
(implementsVectorConcept<T1>() && implementsVectorConcept<T2>() &&
(!isInvalid<BinaryOperationResult<T1, T2, Op>>()));
};

template <typename T1, typename T2, typename Op>
struct IsScalarVectorOperationValid {
static constexpr bool cond =
(isScalar<T1>() && implementsVectorConcept<T2>() &&
(!isInvalid<BinaryOperationResult<T1, T2, Op>>()));
};

template <typename T1>
struct IsEuclidianNormValid {
static constexpr bool cond =
implementsVectorConcept<T1>() &&
!isInvalid<typename tfel::typetraits::RealPartType<
BinaryOperationResult<T1, T1, OpDotProduct>>::type>();
};

/*!
* \return the inner product of a vector
* \param const T1&, the left vector.
Expand All @@ -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 <typename T1, typename T2>
TFEL_HOST_DEVICE
std::enable_if_t<IsVectorVectorOperationValid<T1, T2, OpDotProduct>::cond,
BinaryOperationResult<T1, T2, OpDotProduct>>
operator|(const T1&, const T2&);
template <VectorConcept T1, VectorConcept T2>
TFEL_HOST_DEVICE constexpr auto operator|(const T1&, const T2&) requires(
!isInvalid<BinaryOperationResult<T1, T2, OpDotProduct>>());

/*!
* \brief return the euclidian norm of a tvector
* \param v : the vector.
* \return const typename tfel::typetraits::RealPartType<T>::type, the result
*/
template <typename T1>
TFEL_HOST_DEVICE
std::enable_if_t<IsEuclidianNormValid<T1>::cond,
typename tfel::typetraits::RealPartType<
BinaryOperationResult<T1, T1, OpDotProduct>>::type>
norm(const T1&);
template <VectorConcept T1>
TFEL_HOST_DEVICE auto norm(const T1& v) requires(
!isInvalid<BinaryOperationResult<T1, T1, OpDotProduct>>());

} // end of namespace tfel::math

Expand Down
19 changes: 7 additions & 12 deletions include/TFEL/Math/Vector/VectorConceptOperations.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,18 @@

namespace tfel::math {

template <typename T1, typename T2>
TFEL_HOST_DEVICE
std::enable_if_t<IsVectorVectorOperationValid<T1, T2, OpDotProduct>::cond,
BinaryOperationResult<T1, T2, OpDotProduct>>
operator|(const T1& a, const T2& b) {
template <VectorConcept T1, VectorConcept T2>
TFEL_HOST_DEVICE constexpr auto operator|(const T1& a, const T2& b) requires(
!isInvalid<BinaryOperationResult<T1, T2, OpDotProduct>>()) {
typedef BinaryOperationResult<T1, T2, OpDotProduct> Result;
typedef BinaryOperationHandler<T1, T2, OpDotProduct> Handle;
return Handle::template exe<Result, T1, T2>(a, b);
}

template <typename T1>
TFEL_HOST_DEVICE
std::enable_if_t<IsEuclidianNormValid<T1>::cond,
typename tfel::typetraits::RealPartType<
BinaryOperationResult<T1, T1, OpDotProduct>>::type>
norm(const T1& v) {
return std::sqrt(real(v | v));
template <VectorConcept T1>
TFEL_HOST_DEVICE auto norm(const T1& v) requires(
!isInvalid<BinaryOperationResult<T1, T1, OpDotProduct>>()) {
return power<1, 2>(real(v | v));
}

} // end of namespace tfel::math
Expand Down
2 changes: 1 addition & 1 deletion include/TFEL/Math/matrix.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace tfel::math {
*/
template <typename ValueType>
struct matrix
: VectorConcept<matrix<ValueType>>,
: VectorConceptBase<matrix<ValueType>>,
GenericRuntimeArray<matrix<ValueType>,
RuntimeRowMajorMatrixArrayPolicy<ValueType>> {
//! \brief a simple alias
Expand Down
2 changes: 1 addition & 1 deletion include/TFEL/Math/tvector.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ namespace tfel::math {
}; // end of struct DerivativeTypeDispatcher

template <unsigned short N, typename ValueType = double>
struct tvector : VectorConcept<tvector<N, ValueType>>,
struct tvector : VectorConceptBase<tvector<N, ValueType>>,
GenericFixedSizeArray<tvector<N, ValueType>,
FixedSizeVectorPolicy<N, ValueType>> {
//! \brief a simple alias
Expand Down
2 changes: 1 addition & 1 deletion include/TFEL/Math/vector.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
namespace tfel::math {

template <typename ValueType>
struct vector : VectorConcept<vector<ValueType>>,
struct vector : VectorConceptBase<vector<ValueType>>,
GenericRuntimeArray<vector<ValueType>,
RuntimeVectorArrayPolicy<ValueType>> {
//! \brief a simple alias
Expand Down
17 changes: 8 additions & 9 deletions tests/Math/include/function_unary_tests.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@
#include "TFEL/Math/Matrix/MatrixConcept.hxx"
#include "TFEL/Math/Stensor/StensorConcept.hxx"

template <class T>
void function(const tfel::math::VectorConcept<T>&);

template <class T>
void function(const tfel::math::VectorConcept<T>&,
const typename tfel::math::MathObjectTraits<T>::NumType,
const typename tfel::math::MathObjectTraits<T>::NumType,
const typename tfel::math::MathObjectTraits<T>::NumType,
const typename tfel::math::MathObjectTraits<T>::NumType,
void function(const tfel::math::VectorConcept auto&);

template <tfel::math::VectorConcept VectorType>
void function(const VectorType&,
const tfel::math::numeric_type<VectorType>,
const tfel::math::numeric_type<VectorType>,
const tfel::math::numeric_type<VectorType>,
const tfel::math::numeric_type<VectorType>,
const unsigned int);

template <class T>
Expand Down
26 changes: 15 additions & 11 deletions tests/Math/include/function_unary_tests.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,25 @@
} \
static_cast<void>(0)

template <typename VectorType>
std::enable_if_t<tfel::math::implementsVectorConcept<VectorType>(), void>
function(const VectorType& x) {
// template <typename VectorType>
// std::enable_if_t<tfel::math::implementsVectorConcept<VectorType>(), 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 <typename VectorType>
std::enable_if_t<tfel::math::implementsVectorConcept<VectorType>(), void>
function(const VectorType& x,
const tfel::math::numeric_type<VectorType> v0,
const tfel::math::numeric_type<VectorType> v1,
const tfel::math::numeric_type<VectorType> v2,
const tfel::math::numeric_type<VectorType> eps,
const unsigned int test_number) {
template <tfel::math::VectorConcept VectorType>
void function(const VectorType& x,
const tfel::math::numeric_type<VectorType> v0,
const tfel::math::numeric_type<VectorType> v1,
const tfel::math::numeric_type<VectorType> v2,
const tfel::math::numeric_type<VectorType> eps,
const unsigned int test_number) {
#ifdef TFEL_VERBOSE
std::cout << "Test : " << test_number << std::endl;
#else
Expand Down

0 comments on commit f66aba8

Please sign in to comment.