1#ifndef STAN_MATH_FWD_FUN_SYLVESTER_SOLVER_HPP
2#define STAN_MATH_FWD_FUN_SYLVESTER_SOLVER_HPP
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>
44 = Eigen::Matrix<std::complex<fvar_t>, Eigen::Dynamic, Eigen::Dynamic>;
52 if (
unlikely(A.rows() == 0 || B.rows() == 0)) {
53 return ret_type(A.rows(), B.rows());
56 using complex_inner_t = std::complex<typename fvar_t::Scalar>;
59 auto tangent = [](
const auto& 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_);
72 const auto& A_ref =
to_ref(A);
73 const auto& B_ref =
to_ref(B);
74 const auto& C_ref =
to_ref(C);
78 = Eigen::Matrix<complex_inner_t, Eigen::Dynamic, Eigen::Dynamic>;
82 inner_mat_t rhs = inner_mat_t::Zero(X.rows(), X.cols());
84 rhs += tangent(C_ref);
87 rhs -= tangent(A_ref) * X;
90 rhs -= X * tangent(B_ref);
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) {
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()));
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.
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 ...
T value_of(const fvar< T > &v)
Return the value of the specified variable.
T imag(const std::complex< T > &z)
Return the imaginary component of the complex argument.
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
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
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...