16 #ifndef OPENKALMAN_HERMITIANADAPTER_HPP 17 #define OPENKALMAN_HERMITIANADAPTER_HPP 22 template<square_shaped<Applicability::permitted> NestedObject, HermitianAdapterType storage_triangle> requires
23 (index_count_v<NestedObject> <= 2) and
29 template<
typename NestedObject, HermitianAdapterType storage_triangle>
35 #ifndef __cpp_concepts 36 static_assert(square_shaped<NestedObject, Applicability::permitted>);
37 static_assert(index_count_v<NestedObject> <= 2);
39 static_assert([]{
if constexpr (constant_matrix<NestedObject>)
return values::not_complex<constant_coefficient<NestedObject>>;
else return true; }());
40 static_assert([]{
if constexpr (constant_diagonal_matrix<NestedObject>)
return values::not_complex<constant_diagonal_coefficient<NestedObject>>;
else return true; }());
41 static_assert(not triangular_matrix<NestedObject, TriangleType::any> or
triangular_matrix<NestedObject, static_cast<TriangleType>(storage_triangle)>);
49 static constexpr
auto dim = dynamic_dimension<NestedObject, 0> ? index_dimension_of_v<NestedObject, 1> :
50 index_dimension_of_v<NestedObject, 0>;
60 HermitianAdapter() requires std::default_initializable<NestedObject> and (not has_dynamic_dimensions<NestedObject>)
62 template<
typename T = NestedObject, std::enable_if_t<
63 std::is_default_constructible_v<T> and (not has_dynamic_dimensions<NestedObject>),
int> = 0>
71 template<diagonal_matrix Arg> requires (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
72 diagonal_adapter<NestedObject> and vector_space_descriptors_may_match_with<Arg, NestedObject> and
73 requires(Arg&& arg) { NestedObject {
diagonal_of(std::forward<Arg>(arg))}; }
75 template<
typename Arg, std::enable_if_t<(not std::is_base_of_v<HermitianAdapter, std::decay_t<Arg>>) and
76 diagonal_matrix<Arg> and diagonal_adapter<NestedObject> and vector_space_descriptors_match_with<Arg, NestedObject> and
77 std::is_constructible_v<NestedObject, decltype(diagonal_of(std::declval<Arg&&>()))>,
int> = 0>
84 template<diagonal_matrix Arg> requires (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
85 (not diagonal_matrix<NestedObject> or
86 not requires(Arg&& arg) { NestedObject {
diagonal_of(std::forward<Arg>(arg))}; }) and
87 std::constructible_from<NestedObject, Arg&&>
89 template<
typename Arg, std::enable_if_t<
90 diagonal_matrix<Arg> and (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
91 (not diagonal_matrix<NestedObject> or
92 not std::is_constructible_v<NestedObject, decltype(
diagonal_of(std::declval<Arg&&>()))>) and
93 std::is_constructible_v<NestedObject, Arg&&>,
int> = 0>
100 template<hermitian_adapter<storage_triangle> Arg> requires (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
102 std::constructible_from<NestedObject, decltype(nested_object(std::declval<Arg&&>()))>
105 template<
typename Arg, std::enable_if_t<
106 hermitian_adapter<Arg, storage_triangle> and (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
108 std::is_constructible_v<NestedObject, decltype(nested_object(std::declval<Arg&&>()))>,
int> = 0>
114 #ifdef __cpp_concepts 115 template<hermitian_adapter Arg> requires (not diagonal_matrix<Arg>) and
120 template<
typename Arg, std::enable_if_t<
121 hermitian_adapter<Arg> and (not diagonal_matrix<Arg>) and
124 std::is_constructible_v<NestedObject, decltype(transpose(nested_object(std::declval<Arg&&>())))>,
int> = 0>
130 #ifdef __cpp_concepts 131 template<hermitian_matrix Arg> requires (not diagonal_matrix<Arg>) and
133 std::constructible_from<NestedObject, Arg&&>
135 template<
typename Arg, std::enable_if_t<hermitian_matrix<Arg> and (not diagonal_matrix<Arg>) and
136 (not has_nested_
object<Arg>) and (hermitian_adapter_type_of<Arg>::value == storage_triangle) and
137 std::is_constructible_v<NestedObject, Arg&&>,
int> = 0>
143 #ifdef __cpp_concepts 144 template<hermitian_matrix Arg> requires (not diagonal_matrix<Arg>) and
146 requires(Arg&& arg) { NestedObject {
transpose(std::forward<Arg>(arg))}; }
148 template<
typename Arg, std::enable_if_t<hermitian_matrix<Arg> and (not diagonal_matrix<Arg>) and
149 (not has_nested_
object<Arg>) and (hermitian_adapter_type_of<Arg>::value != storage_triangle) and
150 std::is_constructible_v<NestedObject, decltype(transpose(std::declval<Arg&&>()))>,
int> = 0>
156 #ifdef __cpp_concepts 157 template<square_shaped<Applicability::permitted> Arg> requires (not hermitian_adapter<Arg>) and (not diagonal_matrix<NestedObject>) and
158 std::constructible_from<NestedObject, Arg&&>
160 template<
typename Arg, std::enable_if_t<square_shaped<Arg, Applicability::permitted> and
161 not hermitian_adapter<Arg> and not diagonal_matrix<NestedObject> and
162 std::is_constructible_v<NestedObject, Arg&&>,
int> = 0>
165 [](Arg&& arg) -> decltype(
auto) {
166 if constexpr (dynamic_dimension<Arg, 0> and dim !=
dynamic_size) assert(get_index_dimension_of<0>(arg) == dim);
167 if constexpr (dynamic_dimension<Arg, 1> and dim !=
dynamic_size) assert(get_index_dimension_of<1>(arg) == dim);
168 return std::forward<Arg>(arg);
169 }(std::forward<Arg>(arg))} {}
173 #ifdef __cpp_concepts 174 template<square_shaped<Applicability::permitted> Arg> requires (not hermitian_matrix<Arg>) and diagonal_matrix<NestedObject> and
175 requires(Arg&& arg) { NestedObject {
diagonal_of(std::forward<Arg>(arg))}; }
177 template<
typename Arg, std::enable_if_t<square_shaped<Arg, Applicability::permitted> and (not hermitian_matrix<Arg>) and
178 diagonal_matrix<NestedObject> and std::is_constructible_v<NestedObject, decltype(diagonal_of(std::declval<Arg&&>()))>,
int> = 0>
181 [](Arg&& arg) -> decltype(
auto) {
182 if constexpr (dynamic_dimension<Arg, 0> and dim !=
dynamic_size) assert(get_index_dimension_of<0>(arg) == dim);
183 if constexpr (dynamic_dimension<Arg, 1> and dim !=
dynamic_size) assert(get_index_dimension_of<1>(arg) == dim);
185 }(std::forward<Arg>(arg))} {}
193 #ifdef __cpp_concepts 194 template<std::convertible_to<const Scalar> ... Args> requires (
sizeof...(Args) > 0) and
195 requires(Args ... args) { NestedObject {make_dense_object_from<NestedObject>(
static_cast<const Scalar
>(args)...)}; }
197 template<
typename ... Args, std::enable_if_t<
198 std::conjunction_v<std::is_convertible<Args, const Scalar>...> and (
sizeof...(Args) > 0) and
199 (std::is_constructible_v<NestedObject,
202 Dimensions<static_cast<std::size_t>(
values::sqrt(
sizeof...(Args)))>,
203 Dimensions<static_cast<std::size_t>(
values::sqrt(
sizeof...(Args)))>>>> or
204 (diagonal_matrix<NestedObject> and std::is_constructible_v<NestedObject,
208 :
Base {make_dense_object_from<NestedObject>(
static_cast<const Scalar
>(args)...)} {}
212 #ifdef __cpp_concepts 213 template<hermitian_matrix Arg> requires (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
214 vector_space_descriptors_may_match_with<NestedObject, Arg> and (not diagonal_matrix<NestedObject> or diagonal_matrix<Arg>) and
215 (writable<NestedObject> or std::assignable_from<NestedObject, Arg&&>)
217 template<
typename Arg, std::enable_if_t<hermitian_matrix<Arg> and
218 (not std::is_base_of_v<HermitianAdapter, std::decay_t<Arg>>) and vector_space_descriptors_may_match_with<NestedObject, Arg> and
219 (not diagonal_matrix<NestedObject> or diagonal_matrix<Arg>) and
220 (writable<NestedObject> or std::is_assignable_v<NestedObject, Arg&&>),
int> = 0>
224 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), std::forward<Arg>(arg));
225 else if (hermitian_adapter_type_of_v<Arg> != storage_triangle)
Base::operator=(
adjoint(std::forward<Arg>(arg)));
231 #ifdef __cpp_concepts 232 template<vector_space_descriptors_may_match_with<NestedObject> Arg, HermitianAdapterType t> requires diagonal_matrix<Arg> or
233 (not diagonal_matrix<NestedObject>)
235 template<
typename Arg, HermitianAdapterType t, std::enable_if_t<vector_space_descriptors_may_match_with<Arg, NestedObject> and
236 (diagonal_matrix<Arg> or (not diagonal_matrix<NestedObject>)),
int> = 0>
240 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), this->
nested_object() + std::forward<Arg>(arg));
241 else if (t != storage_triangle) Base::operator+=(
adjoint(std::forward<Arg>(arg)));
242 else Base::operator+=(std::forward<Arg>(arg));
247 #ifdef __cpp_concepts 248 template<vector_space_descriptors_may_match_with<NestedObject> Arg, HermitianAdapterType t> requires diagonal_matrix<Arg> or
249 (not diagonal_matrix<NestedObject>)
251 template<
typename Arg, HermitianAdapterType t, std::enable_if_t<vector_space_descriptors_may_match_with<Arg, NestedObject> and
252 (diagonal_matrix<Arg> or (not diagonal_matrix<NestedObject>)),
int> = 0>
256 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), this->
nested_object() - std::forward<Arg>(arg));
257 else if (t != storage_triangle) Base::operator-=(
adjoint(std::forward<Arg>(arg)));
258 else Base::operator-=(std::forward<Arg>(arg));
263 #ifdef __cpp_concepts 264 template<std::convertible_to<Scalar> S>
266 template<
typename S, std::enable_if_t<std::is_convertible_v<S, Scalar>,
int> = 0>
268 auto& operator*=(
const S s)
270 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), scalar_product(this->
nested_object(), s));
271 else Base::operator*=(s);
276 #ifdef __cpp_concepts 277 template<std::convertible_to<Scalar> S>
279 template<
typename S, std::enable_if_t<std::is_convertible_v<S, Scalar>,
int> = 0>
281 auto& operator/=(
const S s)
283 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), scalar_quotient(this->
nested_object(), s));
284 else Base::operator/=(s);
289 #ifdef __cpp_concepts 290 template<
typename Arg> requires std::same_as<std::decay_t<Arg>,
HermitianAdapter>
291 friend decltype(
auto) operator-(Arg&& arg)
293 return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(-
nested_object(std::forward<Arg>(arg)));
296 decltype(
auto) operator-()
const&
298 return make_hermitian_matrix<storage_triangle>(-
nested_object(*
this));
301 decltype(
auto) operator-()
const&&
303 return make_hermitian_matrix<storage_triangle>(-
nested_object(std::move(*
this)));
308 #ifdef __cpp_concepts 309 template<
typename Arg, std::convertible_to<const scalar_type_of_t<Arg>> S> requires std::same_as<std::decay_t<Arg>,
HermitianAdapter>
311 template<
typename Arg,
typename S, std::enable_if_t<
312 std::is_same_v<std::decay_t<Arg>,
HermitianAdapter> and std::is_convertible_v<S, const scalar_type_of_t<Arg>>>>
314 friend decltype(
auto) operator*(Arg&& arg, S s)
316 return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(
nested_object(std::forward<Arg>(arg)) * s);
320 #ifdef __cpp_concepts 321 template<
typename Arg, std::convertible_to<const scalar_type_of_t<Arg>> S> requires std::same_as<std::decay_t<Arg>,
HermitianAdapter>
323 template<
typename Arg,
typename S, std::enable_if_t<
324 std::is_same_v<std::decay_t<Arg>,
HermitianAdapter> and std::is_convertible_v<S, const scalar_type_of_t<Arg>>>>
326 friend decltype(
auto) operator*(S s, Arg&& arg)
328 return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(s *
nested_object(std::forward<Arg>(arg)));
332 #ifdef __cpp_concepts 333 template<
typename Arg, std::convertible_to<const scalar_type_of_t<Arg>> S> requires std::same_as<std::decay_t<Arg>,
HermitianAdapter>
335 template<
typename Arg,
typename S, std::enable_if_t<
336 std::is_same_v<std::decay_t<Arg>,
HermitianAdapter> and std::is_convertible_v<S, const scalar_type_of_t<Arg>>>>
338 friend decltype(
auto) operator/(Arg&& arg, S s)
340 return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(
nested_object(std::forward<Arg>(arg)) / s);
350 #ifdef __cpp_concepts 351 template<hermitian_matrix<Applicability::permitted> M>
353 template<
typename M, std::enable_if_t<hermitian_matrix<M, Applicability::permitted>,
int> = 0>
360 #ifdef __cpp_concepts 361 template<triangular_matrix M> requires (not hermitian_matrix<M, Applicability::permitted>)
363 template<
typename M, std::enable_if_t<triangular_matrix<M> and
364 (not hermitian_matrix<M, Applicability::permitted>),
int> = 0>
367 std::conditional_t<triangular_adapter<M>, nested_object_of_t<M>, M>,
371 #ifdef __cpp_concepts 372 template<indexible M> requires
373 (not hermitian_matrix<M, Applicability::permitted>) and (not triangular_matrix<M>)
375 template<
typename M, std::enable_if_t<indexible<M> and
376 (not hermitian_matrix<M, Applicability::permitted>) and (not triangular_matrix<M>),
int> = 0>
387 template<
typename NestedObject, HermitianAdapterType storage_type>
392 template<
typename Arg>
393 static constexpr
auto count_indices(
const Arg& arg) {
return std::integral_constant<std::size_t, 2>{}; }
396 template<
typename Arg,
typename N>
399 return internal::best_vector_space_descriptor(
400 OpenKalman::get_vector_space_descriptor<0>(
nested_object(arg)),
401 OpenKalman::get_vector_space_descriptor<1>(
nested_object(arg)));
405 template<
typename Arg>
412 template<
typename Arg>
413 static constexpr
auto get_constant(
const Arg& arg)
419 template<
typename Arg>
420 static constexpr
auto get_constant_diagonal(
const Arg& arg)
426 template<Applicability b>
427 static constexpr
bool one_dimensional = OpenKalman::one_dimensional<NestedObject, b>;
430 template<Applicability b>
431 static constexpr
bool is_square =
true;
434 template<TriangleType t>
435 static constexpr
bool is_triangular = triangular_matrix<NestedObject, TriangleType::diagonal>;
438 static constexpr
bool is_hermitian =
true;
444 static constexpr
bool is_writable =
false;
447 #ifdef __cpp_lib_concepts 448 template<
typename Arg> requires raw_data_defined_for<nested_object_of_t<Arg&>>
450 template<typename Arg, std::enable_if_t<raw_data_defined_for<typename nested_object_of<Arg&>::type>,
int> = 0>
452 static constexpr
auto *
const 453 raw_data(Arg& arg) {
return internal::raw_data(
nested_object(arg)); }
456 static constexpr
Layout layout = OpenKalman::one_dimensional<NestedObject> ? layout_of_v<NestedObject> :
Layout::none;
466 #endif //OPENKALMAN_HERMITIANADAPTER_HPP constexpr auto count_indices(const T &t)
Get the number of indices available to address the components of an indexible object.
Definition: count_indices.hpp:33
typename nested_object_of< T >::type nested_object_of_t
Helper type for nested_object_of.
Definition: nested_object_of.hpp:66
A hermitian matrix wrapper.
Definition: HermitianAdapter.hpp:31
constexpr NestedObject & nested_object() &
Get the nested object.
Definition: AdapterBase.hpp:97
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:83
TriangleType
The type of a triangular matrix.
Definition: global-definitions.hpp:60
Definition: indexible_object_traits.hpp:36
HermitianAdapter(Args ... args)
Construct from a list of scalar coefficients, in row-major order.
Definition: HermitianAdapter.hpp:207
constexpr bool constant_matrix
Specifies that all components of an object are the same constant value.
Definition: constant_matrix.hpp:31
constexpr AdapterBase & operator=(Arg &&arg)
Assign from another compatible indexible object.
Definition: AdapterBase.hpp:82
No storage layout (e.g., if the elements are calculated rather than stored).
typename scalar_type_of< T >::type scalar_type_of_t
helper template for scalar_type_of.
Definition: scalar_type_of.hpp:54
HermitianAdapterType
The type of a hermitian adapter, indicating which triangle of the nested matrix is used...
Definition: global-definitions.hpp:78
constexpr bool not_complex
T is a values::value in which either its type is not a values::complex or its imaginary component is ...
Definition: not_complex.hpp:47
constexpr bool constant_diagonal_matrix
Specifies that all diagonal elements of a diagonal object are the same constant value.
Definition: constant_diagonal_matrix.hpp:34
An upper-right triangular matrix.
Definition: AdapterBase.hpp:36
constexpr bool triangular_matrix
Specifies that a type is a triangular matrix (upper, lower, or diagonal).
Definition: triangular_matrix.hpp:37
The constant associated with T, assuming T is a constant_matrix.
Definition: constant_coefficient.hpp:36
decltype(auto) constexpr transpose(Arg &&arg)
Take the transpose of a matrix.
Definition: transpose.hpp:58
The root namespace for OpenKalman.
Definition: basics.hpp:34
The concept, trait, or restraint is permitted, but whether it applies is not necessarily known at com...
The constant associated with T, assuming T is a constant_diagonal_matrix.
Definition: constant_diagonal_coefficient.hpp:32
constexpr auto sqrt(const Arg &arg)
A constexpr alternative to std::sqrt.
Definition: sqrt.hpp:46
decltype(auto) constexpr diagonal_of(Arg &&arg)
Extract a column vector (or column slice for rank>2 tensors) comprising the diagonal elements...
Definition: diagonal_of.hpp:33
HermitianAdapter(Arg &&arg)
Construct from a hermitian, non-diagonal wrapper of the opposite storage type.
Definition: HermitianAdapter.hpp:126
decltype(auto) constexpr adjoint(Arg &&arg)
Take the adjoint of a matrix.
Definition: adjoint.hpp:33
Layout
The layout format of a multidimensional array.
Definition: global-definitions.hpp:47
std::decay_t< decltype(make_dense_object< T, layout, S >(std::declval< D >()))> dense_writable_matrix_t
An alias for a dense, writable matrix, patterned on parameter T.
Definition: dense_writable_matrix_t.hpp:38
HermitianAdapter(Arg &&arg)
Construct from a diagonal matrix if NestedObject is a diagonal_adapter.
Definition: HermitianAdapter.hpp:79
HermitianAdapter()
Default constructor.
Definition: HermitianAdapter.hpp:64
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:34
constant_diagonal_coefficient(T &&) -> constant_diagonal_coefficient< std::decay_t< T >>
Deduction guide for constant_diagonal_coefficient.
constant_coefficient(const T &) -> constant_coefficient< T >
Deduction guide for constant_coefficient.
The TriangleType associated with the storage triangle of one or more matrices.
Definition: hermitian_adapter_type_of.hpp:28
A lower-left triangular matrix.
auto & operator=(Arg &&arg)
Assign from another hermitian_matrix.
Definition: HermitianAdapter.hpp:222
constexpr auto get_vector_space_descriptor(const T &t, const N &n)
Get the coordinates::pattern object for index N of indexible object T.
Definition: get_vector_space_descriptor.hpp:56