16 #ifndef OPENKALMAN_HERMITIANADAPTER_HPP 17 #define OPENKALMAN_HERMITIANADAPTER_HPP 24 template<square_shaped<applicability::permitted> NestedObject, HermitianAdapterType storage_triangle> requires
25 (index_count_v<NestedObject> <= 2) and
28 (not constant_diagonal_matrix<NestedObject> or values::
not_complex<constant_diagonal_value<NestedObject>>) and
31 template<
typename NestedObject, HermitianAdapterType storage_triangle>
37 #ifndef __cpp_concepts 38 static_assert(square_shaped<NestedObject, applicability::permitted>);
39 static_assert(index_count_v<NestedObject> <= 2);
41 static_assert([]{
if constexpr (constant_matrix<NestedObject>)
return values::not_complex<constant_value<NestedObject>>;
else return true; }());
42 static_assert([]{
if constexpr (constant_diagonal_matrix<NestedObject>)
return values::not_complex<constant_diagonal_value<NestedObject>>;
else return true; }());
43 static_assert(not triangular_matrix<NestedObject, triangle_type::any> or
triangular_matrix<NestedObject, static_cast<triangle_type>(storage_triangle)>);
51 static constexpr
auto dim = dynamic_dimension<NestedObject, 0> ? index_dimension_of_v<NestedObject, 1> :
52 index_dimension_of_v<NestedObject, 0>;
57 using Scalar = scalar_type_of_t<NestedObject>;
62 HermitianAdapter() requires std::default_initializable<NestedObject> and (not has_dynamic_dimensions<NestedObject>)
64 template<
bool Enable =
true, std::enable_if_t<Enable and
65 stdex::default_initializable<NestedObject> and (not has_dynamic_dimensions<NestedObject>),
int> = 0>
73 template<diagonal_matrix Arg> requires
75 diagonal_matrix<NestedObject> and
76 internal::has_nested_vector<NestedObject> and
77 vector_space_descriptors_may_match_with<Arg, NestedObject> and
78 requires(Arg&& arg) { NestedObject {
diagonal_of(std::forward<Arg>(arg))}; }
80 template<
typename Arg, std::enable_if_t<
81 (not std::is_base_of_v<HermitianAdapter, std::decay_t<Arg>>) and
82 diagonal_matrix<Arg> and
83 diagonal_matrix<NestedObject> and
84 internal::has_nested_vector<NestedObject> and vector_space_descriptors_match_with<Arg, NestedObject> and
85 stdex::constructible_from<NestedObject, decltype(
diagonal_of(std::declval<Arg&&>()))>,
int> = 0>
92 template<diagonal_matrix Arg> requires (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
93 (not diagonal_matrix<NestedObject> or
94 not requires(Arg&& arg) { NestedObject {
diagonal_of(std::forward<Arg>(arg))}; }) and
95 std::constructible_from<NestedObject, Arg&&>
97 template<
typename Arg, std::enable_if_t<
98 diagonal_matrix<Arg> and (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
99 (not diagonal_matrix<NestedObject> or
100 not stdex::constructible_from<NestedObject, decltype(
diagonal_of(std::declval<Arg&&>()))>) and
101 stdex::constructible_from<NestedObject, Arg&&>,
int> = 0>
107 #ifdef __cpp_concepts 108 template<hermitian_adapter<storage_triangle> Arg> requires (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
110 std::constructible_from<NestedObject, decltype(nested_object(std::declval<Arg&&>()))>
113 template<
typename Arg, std::enable_if_t<
114 hermitian_adapter<Arg, storage_triangle> and (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
116 stdex::constructible_from<NestedObject, decltype(nested_object(std::declval<Arg&&>()))>,
int> = 0>
122 #ifdef __cpp_concepts 123 template<hermitian_adapter Arg> requires (not diagonal_matrix<Arg>) and
128 template<
typename Arg, std::enable_if_t<
129 hermitian_adapter<Arg> and (not diagonal_matrix<Arg>) and
132 stdex::constructible_from<NestedObject, decltype(transpose(nested_object(std::declval<Arg&&>())))>,
int> = 0>
138 #ifdef __cpp_concepts 139 template<hermitian_matrix Arg> requires (not diagonal_matrix<Arg>) and
141 std::constructible_from<NestedObject, Arg&&>
143 template<
typename Arg, std::enable_if_t<hermitian_matrix<Arg> and (not diagonal_matrix<Arg>) and
144 (not has_nested_
object<Arg>) and (hermitian_adapter_type_of<Arg>::value == storage_triangle) and
145 stdex::constructible_from<NestedObject, Arg&&>,
int> = 0>
151 #ifdef __cpp_concepts 152 template<hermitian_matrix Arg> requires (not diagonal_matrix<Arg>) and
154 requires(Arg&& arg) { NestedObject {
transpose(std::forward<Arg>(arg))}; }
156 template<
typename Arg, std::enable_if_t<hermitian_matrix<Arg> and (not diagonal_matrix<Arg>) and
157 (not has_nested_
object<Arg>) and (hermitian_adapter_type_of<Arg>::value != storage_triangle) and
158 stdex::constructible_from<NestedObject, decltype(transpose(std::declval<Arg&&>()))>,
int> = 0>
164 #ifdef __cpp_concepts 165 template<square_shaped<applicability::permitted> Arg> requires (not hermitian_adapter<Arg>) and (not diagonal_matrix<NestedObject>) and
166 std::constructible_from<NestedObject, Arg&&>
168 template<
typename Arg, std::enable_if_t<square_shaped<Arg, applicability::permitted> and
169 not hermitian_adapter<Arg> and not diagonal_matrix<NestedObject> and
170 stdex::constructible_from<NestedObject, Arg&&>,
int> = 0>
173 [](Arg&& arg) -> decltype(
auto) {
174 if constexpr (dynamic_dimension<Arg, 0> and dim != stdex::dynamic_extent) assert(get_index_dimension_of<0>(arg) == dim);
175 if constexpr (dynamic_dimension<Arg, 1> and dim != stdex::dynamic_extent) assert(get_index_dimension_of<1>(arg) == dim);
176 return std::forward<Arg>(arg);
177 }(std::forward<Arg>(arg))} {}
181 #ifdef __cpp_concepts 182 template<square_shaped<applicability::permitted> Arg> requires (not hermitian_matrix<Arg>) and diagonal_matrix<NestedObject> and
183 requires(Arg&& arg) { NestedObject {
diagonal_of(std::forward<Arg>(arg))}; }
185 template<
typename Arg, std::enable_if_t<square_shaped<Arg, applicability::permitted> and (not hermitian_matrix<Arg>) and
186 diagonal_matrix<NestedObject> and stdex::constructible_from<NestedObject, decltype(diagonal_of(std::declval<Arg&&>()))>,
int> = 0>
189 [](Arg&& arg) -> decltype(
auto) {
190 if constexpr (dynamic_dimension<Arg, 0> and dim != stdex::dynamic_extent) assert(get_index_dimension_of<0>(arg) == dim);
191 if constexpr (dynamic_dimension<Arg, 1> and dim != stdex::dynamic_extent) assert(get_index_dimension_of<1>(arg) == dim);
193 }(std::forward<Arg>(arg))} {}
201 #ifdef __cpp_concepts 202 template<std::convertible_to<const Scalar> ... Args> requires (
sizeof...(Args) > 0) and
203 requires(Args ... args) { NestedObject {make_dense_object_from<NestedObject>(
static_cast<const Scalar
>(args)...)}; }
205 template<
typename ... Args, std::enable_if_t<
206 std::conjunction_v<std::is_convertible<Args, const Scalar>...> and (
sizeof...(Args) > 0) and
207 (stdex::constructible_from<NestedObject,
210 Dimensions<static_cast<std::size_t>(
values::sqrt(
sizeof...(Args)))>,
211 Dimensions<static_cast<std::size_t>(
values::sqrt(
sizeof...(Args)))>>>> or
212 (diagonal_matrix<NestedObject> and stdex::constructible_from<NestedObject,
216 :
Base {make_dense_object_from<NestedObject>(
static_cast<const Scalar
>(args)...)} {}
220 #ifdef __cpp_concepts 221 template<hermitian_matrix Arg> requires (not std::is_base_of_v<
HermitianAdapter, std::decay_t<Arg>>) and
222 vector_space_descriptors_may_match_with<NestedObject, Arg> and (not diagonal_matrix<NestedObject> or diagonal_matrix<Arg>) and
223 (writable<NestedObject> or std::assignable_from<NestedObject, Arg&&>)
225 template<
typename Arg, std::enable_if_t<hermitian_matrix<Arg> and
226 (not std::is_base_of_v<HermitianAdapter, std::decay_t<Arg>>) and vector_space_descriptors_may_match_with<NestedObject, Arg> and
227 (not diagonal_matrix<NestedObject> or diagonal_matrix<Arg>) and
228 (writable<NestedObject> or std::is_assignable_v<NestedObject, Arg&&>),
int> = 0>
232 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), std::forward<Arg>(arg));
233 else if (hermitian_adapter_type_of_v<Arg> != storage_triangle) Base::operator=(
adjoint(std::forward<Arg>(arg)));
234 else Base::operator=(std::forward<Arg>(arg));
239 #ifdef __cpp_concepts 240 template<vector_space_descriptors_may_match_with<NestedObject> Arg, HermitianAdapterType t> requires diagonal_matrix<Arg> or
241 (not diagonal_matrix<NestedObject>)
243 template<
typename Arg, HermitianAdapterType t, std::enable_if_t<vector_space_descriptors_may_match_with<Arg, NestedObject> and
244 (diagonal_matrix<Arg> or (not diagonal_matrix<NestedObject>)),
int> = 0>
248 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), this->
nested_object() + std::forward<Arg>(arg));
249 else if (t != storage_triangle) Base::operator+=(
adjoint(std::forward<Arg>(arg)));
250 else Base::operator+=(std::forward<Arg>(arg));
255 #ifdef __cpp_concepts 256 template<vector_space_descriptors_may_match_with<NestedObject> Arg, HermitianAdapterType t> requires diagonal_matrix<Arg> or
257 (not diagonal_matrix<NestedObject>)
259 template<
typename Arg, HermitianAdapterType t, std::enable_if_t<vector_space_descriptors_may_match_with<Arg, NestedObject> and
260 (diagonal_matrix<Arg> or (not diagonal_matrix<NestedObject>)),
int> = 0>
264 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), this->
nested_object() - std::forward<Arg>(arg));
265 else if (t != storage_triangle) Base::operator-=(
adjoint(std::forward<Arg>(arg)));
266 else Base::operator-=(std::forward<Arg>(arg));
271 #ifdef __cpp_concepts 272 template<std::convertible_to<Scalar> S>
274 template<
typename S, std::enable_if_t<stdex::convertible_to<S, Scalar>,
int> = 0>
276 auto& operator*=(
const S s)
278 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), scalar_product(this->
nested_object(), s));
279 else Base::operator*=(s);
284 #ifdef __cpp_concepts 285 template<std::convertible_to<Scalar> S>
287 template<
typename S, std::enable_if_t<stdex::convertible_to<S, Scalar>,
int> = 0>
289 auto& operator/=(
const S s)
291 if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->
nested_object(), scalar_quotient(this->
nested_object(), s));
292 else Base::operator/=(s);
297 #ifdef __cpp_concepts 298 template<
typename Arg> requires std::same_as<std::decay_t<Arg>,
HermitianAdapter>
299 friend decltype(
auto) operator-(Arg&& arg)
301 return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(-
nested_object(std::forward<Arg>(arg)));
304 decltype(
auto) operator-()
const&
306 return make_hermitian_matrix<storage_triangle>(-
nested_object(*
this));
309 decltype(
auto) operator-()
const&&
311 return make_hermitian_matrix<storage_triangle>(-
nested_object(std::move(*
this)));
316 #ifdef __cpp_concepts 317 template<
typename Arg, std::convertible_to<const scalar_type_of_t<Arg>> S> requires std::same_as<std::decay_t<Arg>,
HermitianAdapter>
319 template<
typename Arg,
typename S, std::enable_if_t<
320 std::is_same_v<std::decay_t<Arg>,
HermitianAdapter> and stdex::convertible_to<S, const scalar_type_of_t<Arg>>>>
322 friend decltype(
auto) operator*(Arg&& arg, S s)
324 return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(
nested_object(std::forward<Arg>(arg)) * s);
328 #ifdef __cpp_concepts 329 template<
typename Arg, std::convertible_to<const scalar_type_of_t<Arg>> S> requires std::same_as<std::decay_t<Arg>,
HermitianAdapter>
331 template<
typename Arg,
typename S, std::enable_if_t<
332 std::is_same_v<std::decay_t<Arg>,
HermitianAdapter> and stdex::convertible_to<S, const scalar_type_of_t<Arg>>>>
334 friend decltype(
auto) operator*(S s, Arg&& arg)
336 return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(s *
nested_object(std::forward<Arg>(arg)));
340 #ifdef __cpp_concepts 341 template<
typename Arg, std::convertible_to<const scalar_type_of_t<Arg>> S> requires std::same_as<std::decay_t<Arg>,
HermitianAdapter>
343 template<
typename Arg,
typename S, std::enable_if_t<
344 std::is_same_v<std::decay_t<Arg>,
HermitianAdapter> and stdex::convertible_to<S, const scalar_type_of_t<Arg>>>>
346 friend decltype(
auto) operator/(Arg&& arg, S s)
348 return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(
nested_object(std::forward<Arg>(arg)) / s);
358 #ifdef __cpp_concepts 359 template<hermitian_matrix<applicability::permitted> M>
361 template<
typename M, std::enable_if_t<hermitian_matrix<M, applicability::permitted>,
int> = 0>
368 #ifdef __cpp_concepts 369 template<triangular_matrix M> requires (not hermitian_matrix<M, applicability::permitted>)
371 template<
typename M, std::enable_if_t<triangular_matrix<M> and
372 (not hermitian_matrix<M, applicability::permitted>),
int> = 0>
375 std::conditional_t<triangular_adapter<M>, nested_object_of_t<M>, M>,
379 #ifdef __cpp_concepts 380 template<indexible M> requires
381 (not hermitian_matrix<M, applicability::permitted>) and (not triangular_matrix<M>)
383 template<
typename M, std::enable_if_t<indexible<M> and
384 (not hermitian_matrix<M, applicability::permitted>) and (not triangular_matrix<M>),
int> = 0>
395 template<
typename NestedObject, HermitianAdapterType storage_type>
398 using scalar_type = scalar_type_of_t<NestedObject>;
400 template<
typename Arg>
401 static constexpr
auto count_indices(
const Arg& arg) {
return std::integral_constant<std::size_t, 2>{}; }
404 template<
typename Arg,
typename N>
407 return internal::most_fixed_pattern(
413 template<
typename Arg>
420 template<
typename Arg>
421 static constexpr
auto get_constant(
const Arg& arg)
427 template<
typename Arg>
428 static constexpr
auto get_constant_diagonal(
const Arg& arg)
434 template<applicability b>
435 static constexpr
bool one_dimensional = OpenKalman::one_dimensional<NestedObject, b>;
438 template<applicability b>
439 static constexpr
bool is_square =
true;
442 template<triangle_type t>
443 static constexpr
bool triangle_type_value = triangular_matrix<NestedObject, triangle_type::diagonal>;
446 static constexpr
bool is_hermitian =
true;
452 static constexpr
bool is_writable =
false;
455 #ifdef __cpp_lib_concepts 456 template<
typename Arg> requires raw_data_defined_for<nested_object_of_t<Arg&>>
458 template<typename Arg, std::enable_if_t<raw_data_defined_for<typename nested_object_of<Arg&>::type>,
int> = 0>
460 static constexpr
auto *
const 461 raw_data(Arg& arg) {
return internal::raw_data(
nested_object(arg)); }
464 static constexpr data_layout layout = OpenKalman::one_dimensional<NestedObject> ? layout_of_v<NestedObject> :
data_layout::none;
typename nested_object_of< T >::type nested_object_of_t
Helper type for nested_object_of.
Definition: nested_object_of.hpp:58
A hermitian matrix wrapper.
Definition: HermitianAdapter.hpp:33
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:56
HermitianAdapter(Args ... args)
Construct from a list of scalar coefficients, in row-major order.
Definition: HermitianAdapter.hpp:215
triangle_type
The type of a triangular matrix.
Definition: enumerations.hpp:26
A lower-left triangular matrix.
The concept, trait, or restraint is permitted, but whether it applies is not necessarily known at com...
constexpr auto count_indices(const T &)
Get the number of indices necessary to address all the components of an indexible object...
Definition: count_indices.hpp:51
decltype(auto) constexpr get_pattern_collection(T &&t)
Get the coordinates::pattern_collection associated with indexible object T.
Definition: get_pattern_collection.hpp:59
HermitianAdapterType
The type of a hermitian adapter, indicating which triangle of the nested matrix is used...
Definition: enumerations.hpp:79
constexpr bool not_complex
T is a value in which either its type is not complex or its imaginary component is 0...
Definition: not_complex.hpp:48
Definition: AdapterBase.hpp:37
constexpr bool triangular_matrix
Specifies that an argument is an indexible object having a given triangle_type (e.g., upper, lower, or diagonal).
Definition: triangular_matrix.hpp:36
The root namespace for OpenKalman.
Definition: basics.hpp:34
Definition: object_traits.hpp:38
decltype(auto) constexpr transpose(Arg &&arg)
Swap any two indices of an indexible_object.
Definition: transpose.hpp:163
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:36
HermitianAdapter(Arg &&arg)
Construct from a hermitian, non-diagonal wrapper of the opposite storage type.
Definition: HermitianAdapter.hpp:134
An upper-right triangular matrix.
constexpr NestedObject & nested_object() &
Get the nested object.
Definition: AdapterBase.hpp:76
Dimensions< 1 > Axis
Alias for a 1D Euclidean coordinates::pattern object.
Definition: Dimensions.hpp:171
constexpr auto constant_value(T &&t)
The constant value associated with a constant_object or constant_diagonal_object. ...
Definition: constant_value.hpp:37
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 that internal::has_nested_vector.
Definition: HermitianAdapter.hpp:87
HermitianAdapter()
Default constructor.
Definition: HermitianAdapter.hpp:66
decltype(auto) constexpr adjoint(Arg &&arg)
Take the conjugate-transpose of an indexible_object.
Definition: adjoint.hpp:35
Basic definitions for OpenKalman as a whole.
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:35
The triangle_type associated with the storage triangle of one or more matrices.
Definition: hermitian_adapter_type_of.hpp:31
auto & operator=(Arg &&arg)
Assign from another hermitian_matrix.
Definition: HermitianAdapter.hpp:230