Automatic Differentiation
 
Loading...
Searching...
No Matches
sylvester_solver.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_FWD_FUN_SYLVESTER_SOLVER_HPP
2#define STAN_MATH_FWD_FUN_SYLVESTER_SOLVER_HPP
3
11#include <complex>
12#include <type_traits>
13
14namespace stan {
15namespace math {
16
37template <typename MatA, typename MatB, typename MatC,
38 require_all_matrix_t<MatA, MatB, MatC>* = nullptr,
39 require_any_bt_fvar<MatA, MatB, MatC>* = nullptr>
40inline auto sylvester_solver(const MatA& A, const MatB& B, const MatC& C) {
41 using fvar_t
43 using ret_type
44 = Eigen::Matrix<std::complex<fvar_t>, Eigen::Dynamic, Eigen::Dynamic>;
45
46 check_square("sylvester_solver", "A", A);
47 check_square("sylvester_solver", "B", B);
48 check_size_match("sylvester_solver", "rows of A", A.rows(), "rows of C",
49 C.rows());
50 check_size_match("sylvester_solver", "rows of B", B.rows(), "cols of C",
51 C.cols());
52 if (unlikely(A.rows() == 0 || B.rows() == 0)) {
53 return ret_type(A.rows(), B.rows());
54 }
55
56 using complex_inner_t = std::complex<typename fvar_t::Scalar>;
57
58 // tangent of an fvar or complex<fvar> matrix, staying real or complex
59 auto tangent = [](const auto& x) {
60 return x
61 .unaryExpr([](const auto& v) {
62 if constexpr (is_complex<std::decay_t<decltype(v)>>::value) {
63 return std::complex<std::decay_t<decltype(v.real().d_)>>(
64 v.real().d_, v.imag().d_);
65 } else {
66 return v.d_;
67 }
68 })
69 .eval();
70 };
71
72 const auto& A_ref = to_ref(A);
73 const auto& B_ref = to_ref(B);
74 const auto& C_ref = to_ref(C);
75 const auto& A_val = to_ref(value_of(A_ref));
76 const auto& B_val = to_ref(value_of(B_ref));
77 using inner_mat_t
78 = Eigen::Matrix<complex_inner_t, Eigen::Dynamic, Eigen::Dynamic>;
79
80 auto X = sylvester_solver(A_val, B_val, value_of(C_ref));
81
82 inner_mat_t rhs = inner_mat_t::Zero(X.rows(), X.cols());
83 if constexpr (is_fvar<base_type_t<MatC>>::value) {
84 rhs += tangent(C_ref);
85 }
86 if constexpr (is_fvar<base_type_t<MatA>>::value) {
87 rhs -= tangent(A_ref) * X;
88 }
89 if constexpr (is_fvar<base_type_t<MatB>>::value) {
90 rhs -= X * tangent(B_ref);
91 }
92 inner_mat_t X_d = sylvester_solver(A_val, B_val, rhs);
93 const Eigen::Index X_rows = X.rows();
94 const Eigen::Index X_cols = X.cols();
95 ret_type res(X_rows, X_cols);
96 for (Eigen::Index j = 0; j < X_cols; ++j) {
97 for (Eigen::Index i = 0; i < X_rows; ++i) {
98 res(i, j)
99 = std::complex<fvar_t>(fvar_t(X(i, j).real(), X_d(i, j).real()),
100 fvar_t(X(i, j).imag(), X_d(i, j).imag()));
101 }
102 }
103 return res;
104}
105
106} // namespace math
107} // namespace stan
108#endif
#define unlikely(x)
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
void check_square(const char *function, const char *name, const T_y &y)
Check if the specified matrix is square.
T real(const std::complex< T > &z)
Return the real component of the complex argument.
Definition real.hpp:18
auto sylvester_solver(const MatA &A, const MatB &B, const MatC &C)
Solve the Sylvester equation A X + X B = C for X, forward mode.
T eval(T &&arg)
Inputs which have a plain_type equal to the own time are forwarded unmodified (for Eigen expressions ...
Definition eval.hpp:20
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
T imag(const std::complex< T > &z)
Return the imaginary component of the complex argument.
Definition imag.hpp:18
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:18
void check_size_match(const char *function, const char *name_i, T_size1 i, const char *name_j, T_size2 j)
Check if the provided sizes match.
typename base_type< T >::type base_type_t
Definition base_type.hpp:31
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
If T is a complex type (that is, an instance of std::complex) or a cv-qualified version thereof,...
Defines a static member function type which is defined to be false as the primitive scalar types cann...
Definition is_fvar.hpp:16