diff --git a/matrix/SparseVector.hpp b/matrix/SparseVector.hpp index 2940076e50b5..ca4659a7a39b 100644 --- a/matrix/SparseVector.hpp +++ b/matrix/SparseVector.hpp @@ -166,6 +166,20 @@ matrix::Vector operator*(const matrix::Matrix& mat, const m return res; } +// returns x.T * A * x +template +Type quadraticForm(const matrix::SquareMatrix& A, const matrix::SparseVector& x) { + Type res = Type(0); + for (size_t i = 0; i < x.non_zeros(); i++) { + Type tmp = Type(0); + for (size_t j = 0; j < x.non_zeros(); j++) { + tmp += A(x.index(i), x.index(j)) * x.atCompressedIndex(j); + } + res += x.atCompressedIndex(i) * tmp; + } + return res; +} + template constexpr size_t SparseVector::_indices[SparseVector::N]; diff --git a/test/sparseVector.cpp b/test/sparseVector.cpp index 4bfb718bd1fb..9c2dbd122462 100644 --- a/test/sparseVector.cpp +++ b/test/sparseVector.cpp @@ -91,6 +91,17 @@ TEST(sparseVectorTest, multiplicationWithDenseMatrix) { EXPECT_TRUE(isEqual(res_dense, res_sparse)); } +TEST(sparseVectorTest, quadraticForm) { + float matrix_data[9] = {1, 2, 3, + 2, 4, 5, + 3, 5, 6 + }; + const SquareMatrix dense_matrix(matrix_data); + const Vector3f dense_vec(0.f, 1.f, 5.f); + const SparseVectorf<3, 1, 2> sparse_vec(dense_vec); + EXPECT_FLOAT_EQ(quadraticForm(dense_matrix, sparse_vec), 204.f); +} + TEST(sparseVectorTest, norms) { const float data[2] = {3.f, 4.f}; const SparseVectorf<4, 1, 3> sparse_vec(data);