OpenKalman
HermitianAdapter.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2019-2021 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
16 #ifndef OPENKALMAN_HERMITIANADAPTER_HPP
17 #define OPENKALMAN_HERMITIANADAPTER_HPP
18 
19 namespace OpenKalman
20 {
21 #ifdef __cpp_concepts
22  template<square_shaped<Applicability::permitted> NestedObject, HermitianAdapterType storage_triangle> requires
23  (index_count_v<NestedObject> <= 2) and
24  (storage_triangle == HermitianAdapterType::lower or storage_triangle == HermitianAdapterType::upper) and
25  (not constant_matrix<NestedObject> or values::not_complex<constant_coefficient<NestedObject>>) and
26  (not constant_diagonal_matrix<NestedObject> or values::not_complex<constant_diagonal_coefficient<NestedObject>>) and
27  (not triangular_matrix<NestedObject, TriangleType::any> or triangular_matrix<NestedObject, static_cast<TriangleType>(storage_triangle)>)
28 #else
29  template<typename NestedObject, HermitianAdapterType storage_triangle>
30 #endif
32  : OpenKalman::internal::AdapterBase<HermitianAdapter<NestedObject, storage_triangle>, NestedObject>
33  {
34 
35 #ifndef __cpp_concepts
36  static_assert(square_shaped<NestedObject, Applicability::permitted>);
37  static_assert(index_count_v<NestedObject> <= 2);
38  static_assert(storage_triangle == HermitianAdapterType::lower or storage_triangle == HermitianAdapterType::upper);
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)>);
42 #endif
43 
44 
45  private:
46 
48 
49  static constexpr auto dim = dynamic_dimension<NestedObject, 0> ? index_dimension_of_v<NestedObject, 1> :
50  index_dimension_of_v<NestedObject, 0>;
51 
52 
53  public:
54 
55  using Scalar = scalar_type_of_t<NestedObject>;
56 
57 
59 #ifdef __cpp_concepts
60  HermitianAdapter() requires std::default_initializable<NestedObject> and (not has_dynamic_dimensions<NestedObject>)
61 #else
62  template<typename T = NestedObject, std::enable_if_t<
63  std::is_default_constructible_v<T> and (not has_dynamic_dimensions<NestedObject>), int> = 0>
65 #endif
66  : Base {} {}
67 
68 
70 #ifdef __cpp_concepts
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))}; }
74 #else
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>
78 #endif
79  HermitianAdapter(Arg&& arg) : Base {diagonal_of(std::forward<Arg>(arg))} {}
80 
81 
83 #ifdef __cpp_concepts
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&&>
88 #else
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>
94 #endif
95  HermitianAdapter(Arg&& arg) : Base {std::forward<Arg>(arg)} {}
96 
97 
99 #ifdef __cpp_concepts
100  template<hermitian_adapter<storage_triangle> Arg> requires (not std::is_base_of_v<HermitianAdapter, std::decay_t<Arg>>) and
101  (not diagonal_matrix<Arg>) and square_shaped<nested_object_of_t<Arg>, Applicability::permitted> and
102  std::constructible_from<NestedObject, decltype(nested_object(std::declval<Arg&&>()))>
103  //alt: requires(Arg&& arg) { NestedObject {nested_object(std::forward<Arg>(arg))}; } -- not accepted in GCC 10
104 #else
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
107  (not diagonal_matrix<Arg>) and square_shaped<nested_object_of_t<Arg>, Applicability::permitted> and
108  std::is_constructible_v<NestedObject, decltype(nested_object(std::declval<Arg&&>()))>, int> = 0>
109 #endif
110  HermitianAdapter(Arg&& arg) : Base {nested_object(std::forward<Arg>(arg))} {}
111 
112 
114 #ifdef __cpp_concepts
115  template<hermitian_adapter Arg> requires (not diagonal_matrix<Arg>) and
116  (hermitian_adapter_type_of<Arg>::value != storage_triangle) and
117  square_shaped<nested_object_of_t<Arg>, Applicability::permitted> and
118  requires(Arg&& arg) { NestedObject {transpose(nested_object(std::forward<Arg>(arg)))}; }
119 #else
120  template<typename Arg, std::enable_if_t<
121  hermitian_adapter<Arg> and (not diagonal_matrix<Arg>) and
122  (hermitian_adapter_type_of<Arg>::value != storage_triangle) and
123  square_shaped<nested_object_of_t<Arg>, Applicability::permitted> and
124  std::is_constructible_v<NestedObject, decltype(transpose(nested_object(std::declval<Arg&&>())))>, int> = 0>
125 #endif
126  HermitianAdapter(Arg&& arg) : Base {transpose(nested_object(std::forward<Arg>(arg)))} {}
127 
128 
130 #ifdef __cpp_concepts
131  template<hermitian_matrix Arg> requires (not diagonal_matrix<Arg>) and
132  (not has_nested_object<Arg>) and (hermitian_adapter_type_of<Arg>::value == storage_triangle) and
133  std::constructible_from<NestedObject, Arg&&>
134 #else
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>
138 #endif
139  HermitianAdapter(Arg&& arg) : Base {std::forward<Arg>(arg)} {}
140 
141 
143 #ifdef __cpp_concepts
144  template<hermitian_matrix Arg> requires (not diagonal_matrix<Arg>) and
145  (not has_nested_object<Arg>) and (hermitian_adapter_type_of<Arg>::value != storage_triangle) and
146  requires(Arg&& arg) { NestedObject {transpose(std::forward<Arg>(arg))}; }
147 #else
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>
151 #endif
152  HermitianAdapter(Arg&& arg) : Base {transpose(std::forward<Arg>(arg))} {}
153 
154 
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&&>
159 #else
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>
163 #endif
164  explicit HermitianAdapter(Arg&& arg) : Base {
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))} {}
170 
171 
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))}; }
176 #else
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>
179 #endif
180  explicit HermitianAdapter(Arg&& arg) : Base {
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);
184  return diagonal_of(std::forward<Arg>(arg));
185  }(std::forward<Arg>(arg))} {}
186 
187 
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)...)}; }
196 #else
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,
200  dense_writable_matrix_t<NestedObject, Layout::none, Scalar,
201  std::tuple<
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,
205  dense_writable_matrix_t<NestedObject, Layout::none, Scalar, std::tuple<Dimensions<sizeof...(Args)>, Axis>>>)), int> = 0>
206 #endif
207  HermitianAdapter(Args ... args)
208  : Base {make_dense_object_from<NestedObject>(static_cast<const Scalar>(args)...)} {}
209 
210 
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&&>)
216 #else
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>
221 #endif
222  auto& operator=(Arg&& arg)
223  {
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)));
226  else Base::operator=(std::forward<Arg>(arg));
227  return *this;
228  }
229 
230 
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>)
234 #else
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>
237 #endif
238  auto& operator+=(const HermitianAdapter<Arg, t>& arg)
239  {
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));
243  return *this;
244  }
245 
246 
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>)
250 #else
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>
253 #endif
254  auto& operator-=(const HermitianAdapter<Arg, t>& arg)
255  {
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));
259  return *this;
260  }
261 
262 
263 #ifdef __cpp_concepts
264  template<std::convertible_to<Scalar> S>
265 #else
266  template<typename S, std::enable_if_t<std::is_convertible_v<S, Scalar>, int> = 0>
267 #endif
268  auto& operator*=(const S s)
269  {
270  if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->nested_object(), scalar_product(this->nested_object(), s));
271  else Base::operator*=(s);
272  return *this;
273  }
274 
275 
276 #ifdef __cpp_concepts
277  template<std::convertible_to<Scalar> S>
278 #else
279  template<typename S, std::enable_if_t<std::is_convertible_v<S, Scalar>, int> = 0>
280 #endif
281  auto& operator/=(const S s)
282  {
283  if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->nested_object(), scalar_quotient(this->nested_object(), s));
284  else Base::operator/=(s);
285  return *this;
286  }
287 
288 
289 #ifdef __cpp_concepts
290  template<typename Arg> requires std::same_as<std::decay_t<Arg>, HermitianAdapter>
291  friend decltype(auto) operator-(Arg&& arg)
292  {
293  return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(-nested_object(std::forward<Arg>(arg)));
294  }
295 #else
296  decltype(auto) operator-() const&
297  {
298  return make_hermitian_matrix<storage_triangle>(-nested_object(*this));
299  }
300 
301  decltype(auto) operator-() const&&
302  {
303  return make_hermitian_matrix<storage_triangle>(-nested_object(std::move(*this)));
304  }
305 #endif
306 
307 
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>
310 #else
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>>>>
313 #endif
314  friend decltype(auto) operator*(Arg&& arg, S s)
315  {
316  return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(nested_object(std::forward<Arg>(arg)) * s);
317  }
318 
319 
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>
322 #else
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>>>>
325 #endif
326  friend decltype(auto) operator*(S s, Arg&& arg)
327  {
328  return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(s * nested_object(std::forward<Arg>(arg)));
329  }
330 
331 
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>
334 #else
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>>>>
337 #endif
338  friend decltype(auto) operator/(Arg&& arg, S s)
339  {
340  return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(nested_object(std::forward<Arg>(arg)) / s);
341  }
342 
343  };
344 
345 
346  // ------------------------------- //
347  // Deduction Guides //
348  // ------------------------------- //
349 
350 #ifdef __cpp_concepts
351  template<hermitian_matrix<Applicability::permitted> M>
352 #else
353  template<typename M, std::enable_if_t<hermitian_matrix<M, Applicability::permitted>, int> = 0>
354 #endif
355  explicit HermitianAdapter(M&&) -> HermitianAdapter<
356  std::conditional_t<hermitian_adapter<M>, nested_object_of_t<M>, M>,
357  hermitian_adapter<M> ? hermitian_adapter_type_of_v<M> : HermitianAdapterType::lower>;
358 
359 
360 #ifdef __cpp_concepts
361  template<triangular_matrix M> requires (not hermitian_matrix<M, Applicability::permitted>)
362 #else
363  template<typename M, std::enable_if_t<triangular_matrix<M> and
364  (not hermitian_matrix<M, Applicability::permitted>), int> = 0>
365 #endif
366  explicit HermitianAdapter(M&&) -> HermitianAdapter<
367  std::conditional_t<triangular_adapter<M>, nested_object_of_t<M>, M>,
368  triangular_matrix<M, TriangleType::lower> ? HermitianAdapterType::lower : HermitianAdapterType::upper>;
369 
370 
371 #ifdef __cpp_concepts
372  template<indexible M> requires
373  (not hermitian_matrix<M, Applicability::permitted>) and (not triangular_matrix<M>)
374 #else
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>
377 #endif
379 
380 
381  // ------------------------- //
382  // Interfaces //
383  // ------------------------- //
384 
385  namespace interface
386  {
387  template<typename NestedObject, HermitianAdapterType storage_type>
388  struct indexible_object_traits<HermitianAdapter<NestedObject, storage_type>>
389  {
390  using scalar_type = scalar_type_of_t<NestedObject>;
391 
392  template<typename Arg>
393  static constexpr auto count_indices(const Arg& arg) { return std::integral_constant<std::size_t, 2>{}; }
394 
395 
396  template<typename Arg, typename N>
397  static constexpr auto get_vector_space_descriptor(Arg&& arg, N n)
398  {
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)));
402  }
403 
404 
405  template<typename Arg>
406  static decltype(auto) nested_object(Arg&& arg)
407  {
408  return std::forward<Arg>(arg).nested_object();
409  }
410 
411 
412  template<typename Arg>
413  static constexpr auto get_constant(const Arg& arg)
414  {
416  }
417 
418 
419  template<typename Arg>
420  static constexpr auto get_constant_diagonal(const Arg& arg)
421  {
423  }
424 
425 
426  template<Applicability b>
427  static constexpr bool one_dimensional = OpenKalman::one_dimensional<NestedObject, b>;
428 
429 
430  template<Applicability b>
431  static constexpr bool is_square = true;
432 
433 
434  template<TriangleType t>
435  static constexpr bool is_triangular = triangular_matrix<NestedObject, TriangleType::diagonal>;
436 
437 
438  static constexpr bool is_hermitian = true;
439 
440 
441  static constexpr HermitianAdapterType hermitian_adapter_type = storage_type;
442 
443 
444  static constexpr bool is_writable = false;
445 
446 
447 #ifdef __cpp_lib_concepts
448  template<typename Arg> requires raw_data_defined_for<nested_object_of_t<Arg&>>
449 #else
450  template<typename Arg, std::enable_if_t<raw_data_defined_for<typename nested_object_of<Arg&>::type>, int> = 0>
451 #endif
452  static constexpr auto * const
453  raw_data(Arg& arg) { return internal::raw_data(nested_object(arg)); }
454 
455 
456  static constexpr Layout layout = OpenKalman::one_dimensional<NestedObject> ? layout_of_v<NestedObject> : Layout::none;
457 
458  };
459 
460  } // namespace interface
461 
462 } // namespace OpenKalman
463 
464 
465 
466 #endif //OPENKALMAN_HERMITIANADAPTER_HPP
467 
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