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 #include "basics/basics.hpp"
20 
21 namespace OpenKalman
22 {
23 #ifdef __cpp_concepts
24  template<square_shaped<applicability::permitted> NestedObject, HermitianAdapterType storage_triangle> requires
25  (index_count_v<NestedObject> <= 2) and
26  (storage_triangle == HermitianAdapterType::lower or storage_triangle == HermitianAdapterType::upper) and
27  (not constant_matrix<NestedObject> or values::not_complex<constant_value<NestedObject>>) and
28  (not constant_diagonal_matrix<NestedObject> or values::not_complex<constant_diagonal_value<NestedObject>>) and
29  (not triangular_matrix<NestedObject, triangle_type::any> or triangular_matrix<NestedObject, static_cast<triangle_type>(storage_triangle)>)
30 #else
31  template<typename NestedObject, HermitianAdapterType storage_triangle>
32 #endif
34  : OpenKalman::internal::AdapterBase<HermitianAdapter<NestedObject, storage_triangle>, NestedObject>
35  {
36 
37 #ifndef __cpp_concepts
38  static_assert(square_shaped<NestedObject, applicability::permitted>);
39  static_assert(index_count_v<NestedObject> <= 2);
40  static_assert(storage_triangle == HermitianAdapterType::lower or storage_triangle == HermitianAdapterType::upper);
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)>);
44 #endif
45 
46 
47  private:
48 
50 
51  static constexpr auto dim = dynamic_dimension<NestedObject, 0> ? index_dimension_of_v<NestedObject, 1> :
52  index_dimension_of_v<NestedObject, 0>;
53 
54 
55  public:
56 
57  using Scalar = scalar_type_of_t<NestedObject>;
58 
59 
61 #ifdef __cpp_concepts
62  HermitianAdapter() requires std::default_initializable<NestedObject> and (not has_dynamic_dimensions<NestedObject>)
63 #else
64  template<bool Enable = true, std::enable_if_t<Enable and
65  stdex::default_initializable<NestedObject> and (not has_dynamic_dimensions<NestedObject>), int> = 0>
67 #endif
68  : Base {} {}
69 
70 
72 #ifdef __cpp_concepts
73  template<diagonal_matrix Arg> requires
74  (not std::is_base_of_v<HermitianAdapter, std::decay_t<Arg>>) and
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))}; }
79 #else
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>
86 #endif
87  HermitianAdapter(Arg&& arg) : Base {diagonal_of(std::forward<Arg>(arg))} {}
88 
89 
91 #ifdef __cpp_concepts
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&&>
96 #else
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>
102 #endif
103  HermitianAdapter(Arg&& arg) : Base {std::forward<Arg>(arg)} {}
104 
105 
107 #ifdef __cpp_concepts
108  template<hermitian_adapter<storage_triangle> Arg> requires (not std::is_base_of_v<HermitianAdapter, std::decay_t<Arg>>) and
109  (not diagonal_matrix<Arg>) and square_shaped<nested_object_of_t<Arg>, applicability::permitted> and
110  std::constructible_from<NestedObject, decltype(nested_object(std::declval<Arg&&>()))>
111  //alt: requires(Arg&& arg) { NestedObject {nested_object(std::forward<Arg>(arg))}; } -- not accepted in GCC 10
112 #else
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
115  (not diagonal_matrix<Arg>) and square_shaped<nested_object_of_t<Arg>, applicability::permitted> and
116  stdex::constructible_from<NestedObject, decltype(nested_object(std::declval<Arg&&>()))>, int> = 0>
117 #endif
118  HermitianAdapter(Arg&& arg) : Base {nested_object(std::forward<Arg>(arg))} {}
119 
120 
122 #ifdef __cpp_concepts
123  template<hermitian_adapter Arg> requires (not diagonal_matrix<Arg>) and
124  (hermitian_adapter_type_of<Arg>::value != storage_triangle) and
125  square_shaped<nested_object_of_t<Arg>, applicability::permitted> and
126  requires(Arg&& arg) { NestedObject {transpose(nested_object(std::forward<Arg>(arg)))}; }
127 #else
128  template<typename Arg, std::enable_if_t<
129  hermitian_adapter<Arg> and (not diagonal_matrix<Arg>) and
130  (hermitian_adapter_type_of<Arg>::value != storage_triangle) and
131  square_shaped<nested_object_of_t<Arg>, applicability::permitted> and
132  stdex::constructible_from<NestedObject, decltype(transpose(nested_object(std::declval<Arg&&>())))>, int> = 0>
133 #endif
134  HermitianAdapter(Arg&& arg) : Base {transpose(nested_object(std::forward<Arg>(arg)))} {}
135 
136 
138 #ifdef __cpp_concepts
139  template<hermitian_matrix Arg> requires (not diagonal_matrix<Arg>) and
140  (not has_nested_object<Arg>) and (hermitian_adapter_type_of<Arg>::value == storage_triangle) and
141  std::constructible_from<NestedObject, Arg&&>
142 #else
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>
146 #endif
147  HermitianAdapter(Arg&& arg) : Base {std::forward<Arg>(arg)} {}
148 
149 
151 #ifdef __cpp_concepts
152  template<hermitian_matrix Arg> requires (not diagonal_matrix<Arg>) and
153  (not has_nested_object<Arg>) and (hermitian_adapter_type_of<Arg>::value != storage_triangle) and
154  requires(Arg&& arg) { NestedObject {transpose(std::forward<Arg>(arg))}; }
155 #else
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>
159 #endif
160  HermitianAdapter(Arg&& arg) : Base {transpose(std::forward<Arg>(arg))} {}
161 
162 
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&&>
167 #else
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>
171 #endif
172  explicit HermitianAdapter(Arg&& arg) : Base {
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))} {}
178 
179 
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))}; }
184 #else
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>
187 #endif
188  explicit HermitianAdapter(Arg&& arg) : Base {
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);
192  return diagonal_of(std::forward<Arg>(arg));
193  }(std::forward<Arg>(arg))} {}
194 
195 
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)...)}; }
204 #else
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,
208  dense_writable_matrix_t<NestedObject, data_layout::none, Scalar,
209  std::tuple<
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,
213  dense_writable_matrix_t<NestedObject, data_layout::none, Scalar, std::tuple<Dimensions<sizeof...(Args)>, Axis>>>)), int> = 0>
214 #endif
215  HermitianAdapter(Args ... args)
216  : Base {make_dense_object_from<NestedObject>(static_cast<const Scalar>(args)...)} {}
217 
218 
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&&>)
224 #else
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>
229 #endif
230  auto& operator=(Arg&& arg)
231  {
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));
235  return *this;
236  }
237 
238 
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>)
242 #else
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>
245 #endif
246  auto& operator+=(const HermitianAdapter<Arg, t>& arg)
247  {
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));
251  return *this;
252  }
253 
254 
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>)
258 #else
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>
261 #endif
262  auto& operator-=(const HermitianAdapter<Arg, t>& arg)
263  {
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));
267  return *this;
268  }
269 
270 
271 #ifdef __cpp_concepts
272  template<std::convertible_to<Scalar> S>
273 #else
274  template<typename S, std::enable_if_t<stdex::convertible_to<S, Scalar>, int> = 0>
275 #endif
276  auto& operator*=(const S s)
277  {
278  if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->nested_object(), scalar_product(this->nested_object(), s));
279  else Base::operator*=(s);
280  return *this;
281  }
282 
283 
284 #ifdef __cpp_concepts
285  template<std::convertible_to<Scalar> S>
286 #else
287  template<typename S, std::enable_if_t<stdex::convertible_to<S, Scalar>, int> = 0>
288 #endif
289  auto& operator/=(const S s)
290  {
291  if constexpr (writable<NestedObject>) internal::set_triangle<storage_triangle>(this->nested_object(), scalar_quotient(this->nested_object(), s));
292  else Base::operator/=(s);
293  return *this;
294  }
295 
296 
297 #ifdef __cpp_concepts
298  template<typename Arg> requires std::same_as<std::decay_t<Arg>, HermitianAdapter>
299  friend decltype(auto) operator-(Arg&& arg)
300  {
301  return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(-nested_object(std::forward<Arg>(arg)));
302  }
303 #else
304  decltype(auto) operator-() const&
305  {
306  return make_hermitian_matrix<storage_triangle>(-nested_object(*this));
307  }
308 
309  decltype(auto) operator-() const&&
310  {
311  return make_hermitian_matrix<storage_triangle>(-nested_object(std::move(*this)));
312  }
313 #endif
314 
315 
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>
318 #else
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>>>>
321 #endif
322  friend decltype(auto) operator*(Arg&& arg, S s)
323  {
324  return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(nested_object(std::forward<Arg>(arg)) * s);
325  }
326 
327 
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>
330 #else
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>>>>
333 #endif
334  friend decltype(auto) operator*(S s, Arg&& arg)
335  {
336  return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(s * nested_object(std::forward<Arg>(arg)));
337  }
338 
339 
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>
342 #else
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>>>>
345 #endif
346  friend decltype(auto) operator/(Arg&& arg, S s)
347  {
348  return make_hermitian_matrix<hermitian_adapter_type_of_v<Arg>>(nested_object(std::forward<Arg>(arg)) / s);
349  }
350 
351  };
352 
353 
354  // ------------------------------- //
355  // Deduction Guides //
356  // ------------------------------- //
357 
358 #ifdef __cpp_concepts
359  template<hermitian_matrix<applicability::permitted> M>
360 #else
361  template<typename M, std::enable_if_t<hermitian_matrix<M, applicability::permitted>, int> = 0>
362 #endif
363  explicit HermitianAdapter(M&&) -> HermitianAdapter<
364  std::conditional_t<hermitian_adapter<M>, nested_object_of_t<M>, M>,
365  hermitian_adapter<M> ? hermitian_adapter_type_of_v<M> : HermitianAdapterType::lower>;
366 
367 
368 #ifdef __cpp_concepts
369  template<triangular_matrix M> requires (not hermitian_matrix<M, applicability::permitted>)
370 #else
371  template<typename M, std::enable_if_t<triangular_matrix<M> and
372  (not hermitian_matrix<M, applicability::permitted>), int> = 0>
373 #endif
374  explicit HermitianAdapter(M&&) -> HermitianAdapter<
375  std::conditional_t<triangular_adapter<M>, nested_object_of_t<M>, M>,
376  triangular_matrix<M, triangle_type::lower> ? HermitianAdapterType::lower : HermitianAdapterType::upper>;
377 
378 
379 #ifdef __cpp_concepts
380  template<indexible M> requires
381  (not hermitian_matrix<M, applicability::permitted>) and (not triangular_matrix<M>)
382 #else
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>
385 #endif
387 
388 
389  // ------------------------- //
390  // Interfaces //
391  // ------------------------- //
392 
393  namespace interface
394  {
395  template<typename NestedObject, HermitianAdapterType storage_type>
396  struct object_traits<HermitianAdapter<NestedObject, storage_type>>
397  {
398  using scalar_type = scalar_type_of_t<NestedObject>;
399 
400  template<typename Arg>
401  static constexpr auto count_indices(const Arg& arg) { return std::integral_constant<std::size_t, 2>{}; }
402 
403 
404  template<typename Arg, typename N>
405  static constexpr auto get_pattern_collection(Arg&& arg, N n)
406  {
407  return internal::most_fixed_pattern(
408  OpenKalman::get_pattern_collection<0>(nested_object(arg)),
409  OpenKalman::get_pattern_collection<1>(nested_object(arg)));
410  }
411 
412 
413  template<typename Arg>
414  static decltype(auto) nested_object(Arg&& arg)
415  {
416  return std::forward<Arg>(arg).nested_object();
417  }
418 
419 
420  template<typename Arg>
421  static constexpr auto get_constant(const Arg& arg)
422  {
424  }
425 
426 
427  template<typename Arg>
428  static constexpr auto get_constant_diagonal(const Arg& arg)
429  {
430  return constant_diagonal_value {OpenKalman::nested_object(arg)};
431  }
432 
433 
434  template<applicability b>
435  static constexpr bool one_dimensional = OpenKalman::one_dimensional<NestedObject, b>;
436 
437 
438  template<applicability b>
439  static constexpr bool is_square = true;
440 
441 
442  template<triangle_type t>
443  static constexpr bool triangle_type_value = triangular_matrix<NestedObject, triangle_type::diagonal>;
444 
445 
446  static constexpr bool is_hermitian = true;
447 
448 
449  static constexpr HermitianAdapterType hermitian_adapter_type = storage_type;
450 
451 
452  static constexpr bool is_writable = false;
453 
454 
455 #ifdef __cpp_lib_concepts
456  template<typename Arg> requires raw_data_defined_for<nested_object_of_t<Arg&>>
457 #else
458  template<typename Arg, std::enable_if_t<raw_data_defined_for<typename nested_object_of<Arg&>::type>, int> = 0>
459 #endif
460  static constexpr auto * const
461  raw_data(Arg& arg) { return internal::raw_data(nested_object(arg)); }
462 
463 
464  static constexpr data_layout layout = OpenKalman::one_dimensional<NestedObject> ? layout_of_v<NestedObject> : data_layout::none;
465 
466  };
467 
468  }
469 
470 }
471 
472 
473 
474 #endif
475 
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