OpenKalman
cholesky_factor.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-2023 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_CHOLESKY_FACTOR_HPP
17 #define OPENKALMAN_CHOLESKY_FACTOR_HPP
18 
19 
20 namespace OpenKalman
21 {
29 #ifdef __cpp_concepts
30  template<triangle_type tri, hermitian_matrix<applicability::permitted> A> requires
31  (tri != triangle_type::diagonal or diagonal_matrix<A>)
32  constexpr triangular_matrix<tri> decltype(auto)
33 #else
34  template<triangle_type tri, typename A, std::enable_if_t<hermitian_matrix<A, applicability::permitted> and
35  (tri != triangle_type::diagonal or diagonal_matrix<A>), int> = 0>
36  constexpr decltype(auto)
37 #endif
39  {
40  if constexpr (not square_shaped<A>)
41  if (not is_square_shaped(a)) throw std::invalid_argument {"Argument to cholesky_factor must be a square matrix"};
42 
43  if constexpr (zero<A> or identity_matrix<A>)
44  {
45  return std::forward<A>(a);
46  }
47  else if constexpr (constant_diagonal_matrix<A>)
48  {
49  auto sq = values::sqrt(constant_diagonal_value{a});
50  return to_diagonal(make_constant<A>(sq, get_pattern_collection<0>(a)));
51  }
52  else if constexpr (constant_matrix<A>)
53  {
54  auto m = [](const auto& a){
55  auto sq = values::sqrt(constant_value{a});
56  auto v = *is_square_shaped(a);
57  auto dim = get_dimension(v);
58 
59  if constexpr (tri == triangle_type::lower)
60  {
61  auto col0 = make_constant<A>(sq, dim, coordinates::Axis{});
62  return attach_pattern(concatenate<1>(col0, make_zero<A>(dim, dim - coordinates::Axis{})), v, v);
63  }
64  else
65  {
66  static_assert(tri == triangle_type::upper);
67  auto row0 = make_constant<A>(sq, coordinates::Axis{}, dim);
68  return attach_pattern(concatenate<0>(row0, make_zero<A>(dim - coordinates::Axis{}, dim)), v, v);
69  }
70  }(a);
71 
72  auto ret {make_triangular_matrix<tri>(std::move(m))};
73  using C0 = vector_space_descriptor_of_t<A, 0>;
74  using C1 = vector_space_descriptor_of_t<A, 1>;
75  using Cret = std::conditional_t<dynamic_pattern<C0>, C1, C0>;
76 
77  if constexpr (coordinates::euclidean_pattern<Cret>) return ret;
78  //else return make_square_root_covariance<Cret>(ret);
79  else return ret; // \todo change to make_triangular_matrix
80  }
81  else if constexpr (diagonal_matrix<A>)
82  {
83  // \todo Add facility to potentially use native library operators such as a square-root operator.
84  return to_diagonal(n_ary_operation([](const auto x){ return values::sqrt(x); }, diagonal_of(std::forward<A>(a))));
85  }
86  else
87  {
88  return interface::library_interface<stdex::remove_cvref_t<A>>::template cholesky_factor<tri>(std::forward<A>(a));
89  }
90  }
91 
92 
100 #ifdef __cpp_concepts
101  template<hermitian_matrix<applicability::permitted> A>
102  constexpr triangular_matrix decltype(auto)
103 #else
104  template<typename A, std::enable_if_t<hermitian_matrix<A, applicability::permitted>, int> = 0>
105  constexpr decltype(auto)
106 #endif
108  {
109  constexpr auto u = diagonal_matrix<A> ? triangle_type::diagonal :
110  hermitian_adapter<A, HermitianAdapterType::upper> ? triangle_type::upper : triangle_type::lower;
111  return cholesky_factor<u>(std::forward<A>(a));
112  }
113 
114 }
115 
116 
117 #endif
constexpr auto attach_pattern(Arg &&arg, P &&p)
Attach a pattern_collection to an indexible object.
Definition: attach_pattern.hpp:36
constexpr auto n_ary_operation(const std::tuple< Ds... > &d_tup, Operation &&operation, Args &&...args)
Perform a component-wise n-ary operation, using broadcasting to match the size of a pattern matrix...
Definition: n_ary_operation.hpp:325
Definition: get.cpp:44
A lower-left triangular matrix.
constexpr auto is_square_shaped(const T &t)
Determine whether an object is square_shaped.
Definition: is_square_shaped.hpp:69
decltype(auto) constexpr to_diagonal(Arg &&arg)
Convert an indexible object into a diagonal matrix.
Definition: to_diagonal.hpp:33
A diagonal matrix (both a lower-left and an upper-right triangular matrix).
constexpr auto get_dimension(const Arg &arg)
Get the vector dimension of coordinates::pattern Arg.
Definition: get_dimension.hpp:54
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
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:42
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
An upper-right triangular matrix.
constexpr auto constant_value(T &&t)
The constant value associated with a constant_object or constant_diagonal_object. ...
Definition: constant_value.hpp:37
A structure representing the dimensions associated with of a particular index.
Definition: Dimensions.hpp:42
decltype(auto) constexpr cholesky_factor(A &&a)
Take the Cholesky factor of a matrix.
Definition: cholesky_factor.hpp:38