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<TriangleType triangle_type, hermitian_matrix<Applicability::permitted> A> requires
31  (triangle_type != TriangleType::diagonal or diagonal_matrix<A>)
32  constexpr triangular_matrix<triangle_type> decltype(auto)
33 #else
34  template<TriangleType triangle_type, typename A, std::enable_if_t<hermitian_matrix<A, Applicability::permitted> and
35  (triangle_type != TriangleType::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  {
50  return to_diagonal(make_constant<A>(sq, get_vector_space_descriptor<0>(a)));
51  }
52  else if constexpr (constant_matrix<A>)
53  {
54  auto m = [](const auto& a){
55  auto sq = values::sqrt(constant_coefficient{a});
56  auto v = *is_square_shaped(a);
57  auto dim = get_dimension(v);
58 
59  if constexpr (triangle_type == TriangleType::lower)
60  {
61  auto col0 = make_constant<A>(sq, dim, coordinates::Axis{});
62  return make_vector_space_adapter(concatenate<1>(col0, make_zero<A>(dim, dim - coordinates::Axis{})), v, v);
63  }
64  else
65  {
66  static_assert(triangle_type == TriangleType::upper);
67  auto row0 = make_constant<A>(sq, coordinates::Axis{}, dim);
68  return make_vector_space_adapter(concatenate<0>(row0, make_zero<A>(dim - coordinates::Axis{}, dim)), v, v);
69  }
70  }(a);
71 
72  auto ret {make_triangular_matrix<triangle_type>(std::move(m))};
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<std::decay_t<A>>::template cholesky_factor<triangle_type>(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> ? TriangleType::diagonal :
110  hermitian_adapter<A, HermitianAdapterType::upper> ? TriangleType::upper : TriangleType::lower;
111  return cholesky_factor<u>(std::forward<A>(a));
112  }
113 
114 } // namespace OpenKalman
115 
116 
117 #endif //OPENKALMAN_CHOLESKY_FACTOR_HPP
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:319
Definition: get.cpp:25
auto make_vector_space_adapter(Arg &&arg, Descriptors &&descriptors)
If necessary, wrap an object in a wrapper that adds vector space descriptors for each index...
Definition: make_vector_space_adapter.hpp:37
constexpr auto is_square_shaped(const T &t)
Determine whether an object is square_shaped at runtime.
Definition: is_square_shaped.hpp:63
decltype(auto) constexpr to_diagonal(Arg &&arg)
Convert an indexible object into a diagonal matrix.
Definition: to_diagonal.hpp:32
An upper-right triangular matrix.
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
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:37
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
typename vector_space_descriptor_of< T, N >::type vector_space_descriptor_of_t
helper template for vector_space_descriptor_of.
Definition: vector_space_descriptor_of.hpp:56
A structure representing the dimensions associated with of a particular index.
Definition: Dimensions.hpp:42
A diagonal matrix (both a lower-left and an upper-right triangular matrix).
A lower-left triangular matrix.
decltype(auto) constexpr cholesky_factor(A &&a)
Take the Cholesky factor of a matrix.
Definition: cholesky_factor.hpp:38