1 #ifndef STAN_MATH_REV_FUN_EIGENVALUES_HPP
2 #define STAN_MATH_REV_FUN_EIGENVALUES_HPP
3 
4 #include <stan/math/rev/meta.hpp>
5 #include <stan/math/rev/core.hpp>
6 #include <stan/math/rev/fun/value_of_rec.hpp>
7 #include <stan/math/rev/core/typedefs.hpp>
8 #include <stan/math/prim/fun/Eigen.hpp>
9 #include <stan/math/prim/err/check_symmetric.hpp>
10 #include <stan/math/prim/err/check_nonzero_size.hpp>
11 #include <stan/math/prim/fun/typedefs.hpp>
12 #include <stan/math/prim/fun/value_of_rec.hpp>
13 
14 namespace stan {
15 namespace math {
16 
17 /**
18  * Return the eigenvalues of the specified symmetric matrix.
19  * <p>See <code>eigen_decompose()</code> for more information.
20  * @tparam T type of input matrix.
21  * @param m Specified matrix.
22  * @return Eigenvalues of matrix.
23  */
24 template <typename T, require_rev_matrix_t<T>* = nullptr>
eigenvalues_sym(const T & m)25 inline auto eigenvalues_sym(const T& m) {
26   using return_t = return_var_matrix_t<T>;
27   if (unlikely(m.size() == 0)) {
28     return return_t(m);
29   }
30   check_symmetric("eigenvalues_sym", "m", m);
31 
32   auto arena_m = to_arena(m);
33   Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> solver(arena_m.val());
34   arena_t<return_t> eigenvals = solver.eigenvalues();
35   auto eigenvecs = to_arena(solver.eigenvectors());
36 
37   reverse_pass_callback([eigenvals, arena_m, eigenvecs]() mutable {
38     arena_m.adj()
39         += eigenvecs * eigenvals.adj().asDiagonal() * eigenvecs.transpose();
40   });
41 
42   return return_t(eigenvals);
43 }
44 
45 }  // namespace math
46 }  // namespace stan
47 #endif
48