GCC Code Coverage Report


Directory: ./
File: unittest/tridiagonal-matrix.cpp
Date: 2024-08-27 18:20:05
Exec Total Coverage
Lines: 0 89 0.0%
Branches: 0 860 0.0%

Line Branch Exec Source
1 //
2 // Copyright (c) 2024 INRIA
3 //
4
5 #include <iostream>
6
7 #include <pinocchio/math/tridiagonal-matrix.hpp>
8
9 #include <boost/variant.hpp> // to avoid C99 warnings
10
11 #include <boost/test/unit_test.hpp>
12 #include <boost/utility/binary.hpp>
13
14 BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)
15
16 using namespace pinocchio;
17
18 BOOST_AUTO_TEST_CASE(test_zero)
19 {
20 const Eigen::DenseIndex mat_size = 20;
21 TridiagonalSymmetricMatrixTpl<double> tridiagonal_matrix(mat_size);
22
23 tridiagonal_matrix.setZero();
24 BOOST_CHECK(tridiagonal_matrix.isZero(0));
25 BOOST_CHECK(tridiagonal_matrix.isDiagonal(0));
26 BOOST_CHECK(tridiagonal_matrix.matrix().isZero(0));
27 }
28
29 BOOST_AUTO_TEST_CASE(test_identity)
30 {
31 const Eigen::DenseIndex mat_size = 20;
32 TridiagonalSymmetricMatrixTpl<double> tridiagonal_matrix(mat_size);
33 typedef TridiagonalSymmetricMatrixTpl<double>::PlainMatrixType PlainMatrixType;
34
35 tridiagonal_matrix.setIdentity();
36 BOOST_CHECK(tridiagonal_matrix.isIdentity(0));
37 BOOST_CHECK(tridiagonal_matrix.isDiagonal(0));
38
39 BOOST_CHECK(tridiagonal_matrix.rows() == mat_size);
40 BOOST_CHECK(tridiagonal_matrix.cols() == mat_size);
41 BOOST_CHECK(tridiagonal_matrix.diagonal().size() == mat_size);
42 BOOST_CHECK(tridiagonal_matrix.subDiagonal().size() == mat_size - 1);
43
44 BOOST_CHECK(tridiagonal_matrix.diagonal().isOnes(0));
45 BOOST_CHECK(tridiagonal_matrix.subDiagonal().isZero(0));
46 BOOST_CHECK(tridiagonal_matrix.matrix().isIdentity(0));
47
48 // Fill matrix
49 {
50 PlainMatrixType mat(mat_size, mat_size);
51 mat = tridiagonal_matrix;
52
53 BOOST_CHECK(mat.isIdentity(0));
54 }
55
56 // Matrix multiplication left and right
57 for (int k = 0; k < 1000; ++k)
58 {
59 PlainMatrixType mat = PlainMatrixType::Random(mat_size, mat_size);
60
61 PlainMatrixType plain(mat_size, mat_size);
62 plain = tridiagonal_matrix;
63
64 PlainMatrixType res_apply_on_the_right = tridiagonal_matrix * mat;
65 PlainMatrixType res_apply_on_the_right_ref = plain * mat;
66 BOOST_CHECK(res_apply_on_the_right.isApprox(res_apply_on_the_right_ref));
67
68 PlainMatrixType res_apply_on_the_left = mat * tridiagonal_matrix;
69 PlainMatrixType res_apply_on_the_left_ref = mat * plain;
70 BOOST_CHECK(res_apply_on_the_left.isApprox(res_apply_on_the_left_ref));
71 }
72 }
73
74 BOOST_AUTO_TEST_CASE(test_random)
75 {
76 const Eigen::DenseIndex mat_size = 20;
77 TridiagonalSymmetricMatrixTpl<double> tridiagonal_matrix(mat_size);
78 typedef TridiagonalSymmetricMatrixTpl<double>::PlainMatrixType PlainMatrixType;
79
80 tridiagonal_matrix.setRandom();
81
82 BOOST_CHECK(tridiagonal_matrix.rows() == mat_size);
83 BOOST_CHECK(tridiagonal_matrix.cols() == mat_size);
84 BOOST_CHECK(tridiagonal_matrix.diagonal().size() == mat_size);
85 BOOST_CHECK(tridiagonal_matrix.subDiagonal().size() == mat_size - 1);
86
87 // Fill matrix
88 {
89 PlainMatrixType mat(mat_size, mat_size);
90 mat = tridiagonal_matrix;
91
92 BOOST_CHECK(mat.diagonal() == tridiagonal_matrix.diagonal());
93 BOOST_CHECK(mat.diagonal<-1>() == tridiagonal_matrix.subDiagonal());
94 BOOST_CHECK(mat.diagonal<+1>().conjugate() == tridiagonal_matrix.subDiagonal().conjugate());
95 }
96
97 // Matrix multiplication
98 for (int k = 0; k < 1000; ++k)
99 {
100 PlainMatrixType rhs_mat = PlainMatrixType::Random(mat_size, mat_size);
101
102 PlainMatrixType plain(mat_size, mat_size);
103 plain = tridiagonal_matrix;
104
105 PlainMatrixType res = tridiagonal_matrix * rhs_mat;
106
107 PlainMatrixType res_ref = plain * rhs_mat;
108 BOOST_CHECK(res.isApprox(res_ref));
109 BOOST_CHECK((tridiagonal_matrix * PlainMatrixType::Identity(mat_size, mat_size))
110 .isApprox(tridiagonal_matrix.matrix()));
111 }
112 }
113
114 BOOST_AUTO_TEST_CASE(test_inverse)
115 {
116 typedef TridiagonalSymmetricMatrixTpl<double> TridiagonalSymmetricMatrixd;
117 const Eigen::DenseIndex mat_size = 10;
118 TridiagonalSymmetricMatrixTpl<double> tridiagonal_matrix(mat_size);
119 typedef TridiagonalSymmetricMatrixTpl<double>::PlainMatrixType PlainMatrixType;
120
121 tridiagonal_matrix.setRandom();
122
123 PlainMatrixType plain_mat(mat_size, mat_size);
124 plain_mat = tridiagonal_matrix;
125 const PlainMatrixType plain_mat_inverse = plain_mat.inverse();
126
127 const TridiagonalSymmetricMatrixInverse<TridiagonalSymmetricMatrixd> &
128 tridiagonal_matrix_inverse = tridiagonal_matrix.inverse();
129
130 BOOST_CHECK(tridiagonal_matrix_inverse.rows() == tridiagonal_matrix.rows());
131 BOOST_CHECK(tridiagonal_matrix_inverse.cols() == tridiagonal_matrix.cols());
132
133 const auto & tridiagonal_matrix_ref = tridiagonal_matrix_inverse.inverse();
134 BOOST_CHECK(&tridiagonal_matrix_ref == &tridiagonal_matrix);
135
136 const PlainMatrixType tridiagonal_matrix_inverse_plain = tridiagonal_matrix_inverse;
137 BOOST_CHECK(tridiagonal_matrix_inverse_plain.isApprox(plain_mat_inverse));
138
139 // Matrix multiplication
140 for (int k = 0; k < 1; ++k)
141 {
142 PlainMatrixType rhs_mat = PlainMatrixType::Random(mat_size, mat_size);
143
144 PlainMatrixType res(mat_size, mat_size);
145 res = tridiagonal_matrix_ref * rhs_mat;
146
147 BOOST_CHECK(res.isApprox((plain_mat * rhs_mat).eval()));
148
149 res = tridiagonal_matrix_inverse * rhs_mat;
150 const PlainMatrixType res_ref = plain_mat_inverse * rhs_mat;
151
152 BOOST_CHECK(res.isApprox(res_ref));
153 }
154
155 // Test diagonal
156 {
157 Eigen::MatrixXd sub_diagonal_matrix = Eigen::MatrixXd::Zero(mat_size, mat_size);
158 sub_diagonal_matrix.diagonal<1>().setRandom();
159 sub_diagonal_matrix.diagonal().setRandom();
160 sub_diagonal_matrix.diagonal<-1>().setRandom();
161
162 const Eigen::MatrixXd test_mat = Eigen::MatrixXd::Random(mat_size, mat_size);
163 const Eigen::MatrixXd res_ref = sub_diagonal_matrix * test_mat;
164
165 Eigen::MatrixXd res(mat_size, mat_size); // res.setZero();
166 res.noalias() = sub_diagonal_matrix.diagonal().asDiagonal() * test_mat;
167 res.topRows(mat_size - 1) +=
168 sub_diagonal_matrix.diagonal<1>().asDiagonal() * test_mat.bottomRows(mat_size - 1);
169 res.bottomRows(mat_size - 1) +=
170 sub_diagonal_matrix.diagonal<-1>().asDiagonal() * test_mat.topRows(mat_size - 1);
171 BOOST_CHECK(res.isApprox(res_ref));
172 }
173 }
174
175 BOOST_AUTO_TEST_SUITE_END()
176