1 #ifndef STAN_MATH_PRIM_MAT_ERR_CHECK_SYMMETRIC_HPP
2 #define STAN_MATH_PRIM_MAT_ERR_CHECK_SYMMETRIC_HPP
3 
4 #include <stan/math/prim/scal/err/domain_error.hpp>
5 #include <stan/math/prim/mat/err/check_square.hpp>
6 #include <stan/math/prim/mat/err/constraint_tolerance.hpp>
7 #include <stan/math/prim/mat/fun/Eigen.hpp>
8 #include <stan/math/prim/mat/meta/index_type.hpp>
9 #include <stan/math/prim/mat/fun/value_of.hpp>
10 #include <stan/math/prim/scal/meta/error_index.hpp>
11 #include <sstream>
12 #include <string>
13 
14 namespace stan {
15 namespace math {
16 
17 /**
18  * Check if the specified matrix is symmetric.
19  *
20  * The error message is either 0 or 1 indexed, specified by
21  * <code>stan::error_index::value</code>.
22  *
23  * @tparam T_y Type of scalar.
24  *
25  * @param function Function name (for error messages)
26  * @param name Variable name (for error messages)
27  * @param y Matrix to test
28  *
29  * @throw <code>std::invalid_argument</code> if the matrix is not square.
30  * @throw <code>std::domain_error</code> if any element not on the
31  *   main diagonal is <code>NaN</code>
32  */
33 template <typename T_y>
check_symmetric(const char * function,const char * name,const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic> & y)34 inline void check_symmetric(
35     const char* function, const char* name,
36     const Eigen::Matrix<T_y, Eigen::Dynamic, Eigen::Dynamic>& y) {
37   check_square(function, name, y);
38 
39   using Eigen::Dynamic;
40   using Eigen::Matrix;
41   using std::fabs;
42 
43   typedef typename index_type<Matrix<T_y, Dynamic, Dynamic> >::type size_type;
44 
45   size_type k = y.rows();
46   if (k == 1)
47     return;
48   for (size_type m = 0; m < k; ++m) {
49     for (size_type n = m + 1; n < k; ++n) {
50       if (!(fabs(value_of(y(m, n)) - value_of(y(n, m)))
51             <= CONSTRAINT_TOLERANCE)) {
52         std::ostringstream msg1;
53         msg1 << "is not symmetric. " << name << "["
54              << stan::error_index::value + m << ","
55              << stan::error_index::value + n << "] = ";
56         std::string msg1_str(msg1.str());
57         std::ostringstream msg2;
58         msg2 << ", but " << name << "[" << stan::error_index::value + n << ","
59              << stan::error_index::value + m << "] = " << y(n, m);
60         std::string msg2_str(msg2.str());
61         domain_error(function, name, y(m, n), msg1_str.c_str(),
62                      msg2_str.c_str());
63       }
64     }
65   }
66 }
67 
68 }  // namespace math
69 }  // namespace stan
70 #endif
71