Line data Source code
1 : #ifndef C50A72AB_25E1_45C6_93E5_6607B9D345E3
2 : #define C50A72AB_25E1_45C6_93E5_6607B9D345E3
3 :
4 :
5 : #include "base/first_include.h" // IWYU pragma: keep
6 : #include "base/interface_contract.h" // IWYU pragma: keep
7 : #include "base/require_copy_intf.h"
8 : #include "base/require_move_intf.h"
9 : #include "math/linalg/square_matrix.h" // IWYU pragma: keep
10 :
11 : namespace tracking
12 : {
13 : namespace math
14 : {
15 : namespace contract
16 : {
17 : #if __cplusplus == 202002L
18 : // clang-format off
19 : namespace covariance
20 : {
21 : template<typename T>
22 : concept has_dim_constant = requires {
23 : requires std::is_same_v<decltype(T::dim), const sint32>;
24 : };
25 : template<typename T>
26 : concept has_fromDiagonal_static_member_func = requires {
27 : { T::FromDiagonal(std::declval<DiagonalMatrix<typename T::value_type, T::dim>>()) } -> std::same_as<T>;
28 : };
29 : template<typename T>
30 : concept has_identity_static_member_func = requires {
31 : { T::Identity() } -> std::same_as<T>;
32 : };
33 : template<typename T>
34 : concept has_setIdentity_member_func = requires {
35 : { std::declval<T>().setIdentity() } -> std::same_as<void>;
36 : };
37 : template<typename T>
38 : concept has_setVariance_member_func = requires {
39 : { std::declval<T>().setVariance(std::declval<int>(), std::declval<typename T::value_type>()) } -> std::same_as<void>;
40 : };
41 : template<typename T>
42 : concept has_inverse_member_func = requires {
43 : { std::declval<const T>().inverse() } -> std::same_as<tl::expected<T, Errors>>;
44 : };
45 : template<typename T>
46 : concept has_composed_inverse_member_func = requires {
47 : { std::declval<const T>().composed_inverse() } -> std::same_as<tl::expected<typename T::compose_type, Errors>>;
48 : };
49 : template<typename T>
50 : concept has_apaT_member_func = requires {
51 : { std::declval<const T>().apaT(std::declval<SquareMatrix<typename T::value_type, T::dim, true>>()) } -> std::same_as<T>;
52 : };
53 : template<typename T>
54 : concept has_apaT_inplace_member_func = requires {
55 : { std::declval<T>().apaT(std::declval<SquareMatrix<typename T::value_type, T::dim, true>>()) } -> std::same_as<void>;
56 : };
57 : template<typename T>
58 : concept has_round_brackets_op = requires {
59 : { std::declval<T>().operator()() } -> std::convertible_to<typename T::compose_type&>;
60 : };
61 : template<typename T>
62 : concept has_round_brackets_const_op = requires {
63 : { std::declval<const T>().operator()() } -> std::convertible_to<typename T::compose_type>; // allow const reference as well as plain type
64 : };
65 : template<typename T>
66 : concept has_at_unsafe_member_func = requires {
67 : { std::declval<const T>().at_unsafe(std::declval<int>(), std::declval<int>()) } -> std::same_as<typename T::value_type>;
68 : };
69 : template<typename T>
70 : concept has_round_brackets_const_op_int_int = requires {
71 : { std::declval<const T>().operator()(std::declval<int>(), std::declval<int>()) } -> std::same_as<tl::expected<typename T::value_type, Errors>>;
72 : };
73 : template<typename T>
74 : concept has_round_brackets_op_int_int = requires {
75 : { std::declval<T>().operator()(std::declval<int>(), std::declval<int>()) } -> std::same_as<typename T::value_type&>;
76 : };
77 : template<typename T>
78 : concept has_square_brackets_const_op_int = requires {
79 : { std::declval<const T>().operator[](std::declval<int>()) } -> std::same_as<typename T::value_type>;
80 : };
81 : template<typename T>
82 : concept has_square_brackets_op_int = requires {
83 : { std::declval<T>().operator[](std::declval<int>()) } -> std::same_as<typename T::value_type&>;
84 : };
85 : template<typename T>
86 : concept has_determinant_member_func = requires {
87 : { std::declval<const T>().determinant() } -> std::same_as<typename T::value_type>;
88 : };
89 : template<typename T>
90 : concept has_trace_member_func = requires {
91 : { std::declval<const T>().trace() } -> std::same_as<typename T::value_type>;
92 : };
93 : template<typename T>
94 : concept has_isSymmetric_member_func = requires {
95 : { std::declval<const T>().isSymmetric() } -> std::same_as<bool>;
96 : };
97 : template<typename T>
98 : concept has_isPositiveSemiDefinite_member_func = requires {
99 : { std::declval<const T>().isPositiveSemiDefinite() } -> std::same_as<bool>;
100 : };
101 : template<typename T>
102 : concept has_isPositiveDefinite_member_func = requires {
103 : { std::declval<const T>().isPositiveDefinite() } -> std::same_as<bool>;
104 : };
105 : // clang-format on
106 : } // namespace covariance
107 : #endif // __cplusplus == 202002L
108 :
109 : template <typename ImplType>
110 : struct CovarianceMatrixIntf
111 : : public base::contract::RequireCopyIntf<ImplType>
112 : , public base::contract::RequireMoveIntf<ImplType>
113 : {
114 679 : CovarianceMatrixIntf()
115 : : base::contract::RequireCopyIntf<ImplType>()
116 718 : , base::contract::RequireMoveIntf<ImplType>()
117 : {
118 : static_assert(std::is_floating_point<typename ImplType::value_type>());
119 : static_assert(ImplType::dim > 0);
120 :
121 : #if __cplusplus == 202002L
122 : // mandatory funcs
123 : static_assert(covariance::has_dim_constant<ImplType>, ERR_MSG_MISSING_FUNCTION);
124 : static_assert(covariance::has_fromDiagonal_static_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
125 : static_assert(covariance::has_identity_static_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
126 : static_assert(covariance::has_setIdentity_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
127 : static_assert(covariance::has_setVariance_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
128 : static_assert(covariance::has_inverse_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
129 : static_assert(covariance::has_composed_inverse_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
130 : static_assert(covariance::has_apaT_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
131 : static_assert(covariance::has_apaT_inplace_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
132 : static_assert(covariance::has_round_brackets_const_op<ImplType>, ERR_MSG_MISSING_FUNCTION);
133 : static_assert(covariance::has_round_brackets_const_op_int_int<ImplType>, ERR_MSG_MISSING_FUNCTION);
134 : static_assert(covariance::has_determinant_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
135 : static_assert(covariance::has_trace_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
136 : static_assert(covariance::has_isSymmetric_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
137 : static_assert(covariance::has_isPositiveSemiDefinite_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
138 : static_assert(covariance::has_isPositiveDefinite_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
139 : static_assert(covariance::has_at_unsafe_member_func<ImplType>, ERR_MSG_MISSING_FUNCTION);
140 : // unexpected funcs
141 : static_assert(!covariance::has_round_brackets_op<ImplType>, ERR_MSG_DEFINED_UNEXPECTED_FUNCTION);
142 : static_assert(!covariance::has_round_brackets_op_int_int<ImplType>, ERR_MSG_DEFINED_UNEXPECTED_FUNCTION);
143 : static_assert(!covariance::has_square_brackets_const_op_int<ImplType>, ERR_MSG_DEFINED_UNEXPECTED_FUNCTION);
144 : static_assert(!covariance::has_square_brackets_op_int<ImplType>, ERR_MSG_DEFINED_UNEXPECTED_FUNCTION);
145 : #endif // __cplusplus == 202002L
146 : }
147 : };
148 :
149 : } // namespace contract
150 : } // namespace math
151 : } // namespace tracking
152 :
153 : #endif // C50A72AB_25E1_45C6_93E5_6607B9D345E3
|