11d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// Ceres Solver - A fast non-linear least squares minimizer
21d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// Copyright 2013 Google Inc. All rights reserved.
31d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// http://code.google.com/p/ceres-solver/
41d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//
51d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// Redistribution and use in source and binary forms, with or without
61d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// modification, are permitted provided that the following conditions are met:
71d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//
81d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// * Redistributions of source code must retain the above copyright notice,
91d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//   this list of conditions and the following disclaimer.
101d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// * Redistributions in binary form must reproduce the above copyright notice,
111d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//   this list of conditions and the following disclaimer in the documentation
121d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//   and/or other materials provided with the distribution.
131d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// * Neither the name of Google Inc. nor the names of its contributors may be
141d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//   used to endorse or promote products derived from this software without
151d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//   specific prior written permission.
161d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//
171d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
181d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
211d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
221d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
231d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
241d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
251d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
261d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
271d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// POSSIBILITY OF SUCH DAMAGE.
281d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling//
291d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling// Author: sameeragarwal@google.com (Sameer Agarwal)
301d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
311d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include "ceres/incomplete_lq_factorization.h"
321d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
331d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include "Eigen/Dense"
341d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include "ceres/compressed_row_sparse_matrix.h"
351d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include "ceres/internal/scoped_ptr.h"
361d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include "glog/logging.h"
371d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling#include "gtest/gtest.h"
381d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
391d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingnamespace ceres {
401d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingnamespace internal {
411d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
421d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingvoid ExpectMatricesAreEqual(const CompressedRowSparseMatrix& expected,
431d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                            const CompressedRowSparseMatrix& actual,
441d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                            const double tolerance) {
451d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(expected.num_rows(), actual.num_rows());
461d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(expected.num_cols(), actual.num_cols());
471d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  for (int i = 0; i < expected.num_rows(); ++i) {
481d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(expected.rows()[i], actual.rows()[i]);
491d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
501d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
511d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  for (int i = 0; i < actual.num_nonzeros(); ++i) {
521d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(expected.cols()[i], actual.cols()[i]);
531d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_NEAR(expected.values()[i], actual.values()[i], tolerance);
541d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
551d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling}
561d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
571d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha HaeberlingTEST(IncompleteQRFactorization, OneByOneMatrix) {
581d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  CompressedRowSparseMatrix matrix(1, 1, 1);
591d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  matrix.mutable_rows()[0] = 0;
601d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  matrix.mutable_rows()[1] = 1;
611d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  matrix.mutable_cols()[0] = 0;
621d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  matrix.mutable_values()[0] = 2;
631d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
641d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  scoped_ptr<CompressedRowSparseMatrix> l(
651d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      IncompleteLQFactorization(matrix, 1, 0.0, 1, 0.0));
661d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  ExpectMatricesAreEqual(matrix, *l, 1e-16);
671d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling}
681d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
691d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha HaeberlingTEST(IncompleteLQFactorization, CompleteFactorization) {
701d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  double dense_matrix[] = {
711d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.00000,  0.00000,  0.20522,  0.00000,  0.49077,  0.92835,  0.00000,  0.83825,  0.00000,  0.00000,  // NOLINT
721d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.00000,  0.00000,  0.00000,  0.62491,  0.38144,  0.00000,  0.79394,  0.79178,  0.00000,  0.44382,  // NOLINT
731d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.00000,  0.00000,  0.00000,  0.61517,  0.55941,  0.00000,  0.00000,  0.00000,  0.00000,  0.60664,  // NOLINT
741d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.00000,  0.00000,  0.00000,  0.00000,  0.45031,  0.00000,  0.64132,  0.00000,  0.38832,  0.00000,  // NOLINT
751d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  0.57121,  0.00000,  0.01375,  0.70640,  0.00000,  // NOLINT
761d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.00000,  0.00000,  0.07451,  0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  // NOLINT
771d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.68095,  0.00000,  0.00000,  0.95473,  0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  // NOLINT
781d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.00000,  0.00000,  0.00000,  0.00000,  0.59374,  0.00000,  0.00000,  0.00000,  0.49139,  0.00000,  // NOLINT
791d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.91276,  0.96641,  0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  0.00000,  0.91797,  // NOLINT
801d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    0.96828,  0.00000,  0.00000,  0.72583,  0.00000,  0.00000,  0.81459,  0.00000,  0.04560,  0.00000   // NOLINT
811d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  };
821d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
831d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  CompressedRowSparseMatrix matrix(10, 10, 100);
841d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  int* rows = matrix.mutable_rows();
851d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  int* cols = matrix.mutable_cols();
861d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  double* values = matrix.mutable_values();
871d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
881d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  int idx = 0;
891d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  for (int i = 0; i < 10; ++i) {
901d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    rows[i] = idx;
911d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int j = 0; j < 10; ++j) {
921d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      const double v = dense_matrix[i * 10 + j];
931d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      if (fabs(v) > 1e-6) {
941d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling        cols[idx] = j;
951d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling        values[idx] = v;
961d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling        ++idx;
971d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      }
981d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
991d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
1001d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  rows[10] = idx;
1011d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1021d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  scoped_ptr<CompressedRowSparseMatrix> lmatrix(
1031d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      IncompleteLQFactorization(matrix, 10, 0.0, 10, 0.0));
1041d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1051d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  ConstMatrixRef mref(dense_matrix, 10, 10);
1061d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1071d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  // Use Cholesky factorization to compute the L matrix.
1081d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  Matrix expected_l_matrix  = (mref * mref.transpose()).llt().matrixL();
1091d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  Matrix actual_l_matrix;
1101d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  lmatrix->ToDenseMatrix(&actual_l_matrix);
1111d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1121d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_NEAR((expected_l_matrix * expected_l_matrix.transpose() -
1131d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling               actual_l_matrix * actual_l_matrix.transpose()).norm(),
1141d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling              0.0,
1151d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling              1e-10)
1161d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      << "expected: \n" << expected_l_matrix
1171d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      << "\actual: \n" << actual_l_matrix;
1181d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling}
1191d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1201d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha HaeberlingTEST(IncompleteLQFactorization, DropEntriesAndAddRow) {
1211d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  // Allocate space and then make it a zero sized matrix.
1221d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  CompressedRowSparseMatrix matrix(10, 10, 100);
1231d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  matrix.set_num_rows(0);
1241d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1251d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  vector<pair<int, double> > scratch(10);
1261d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1271d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  Vector dense_vector(10);
1281d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  dense_vector(0) = 5;
1291d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  dense_vector(1) = 1;
1301d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  dense_vector(2) = 2;
1311d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  dense_vector(3) = 3;
1321d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  dense_vector(4) = 1;
1331d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  dense_vector(5) = 4;
1341d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1351d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  // Add a row with just one entry.
1361d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  DropEntriesAndAddRow(dense_vector, 1, 1, 0, &scratch, &matrix);
1371d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_rows(), 1);
1381d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_cols(), 10);
1391d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_nonzeros(), 1);
1401d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[0], 5.0);
1411d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[0], 0);
1421d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1431d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  // Add a row with six entries
1441d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  DropEntriesAndAddRow(dense_vector, 6, 10, 0, &scratch, &matrix);
1451d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_rows(), 2);
1461d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_cols(), 10);
1471d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_nonzeros(), 7);
1481d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  for (int idx = matrix.rows()[1]; idx < matrix.rows()[2]; ++idx) {
1491d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(matrix.cols()[idx], idx - matrix.rows()[1]);
1501d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(matrix.values()[idx], dense_vector(idx - matrix.rows()[1]));
1511d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
1521d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1531d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  // Add the top 3 entries.
1541d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  DropEntriesAndAddRow(dense_vector, 6, 3, 0, &scratch, &matrix);
1551d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_rows(), 3);
1561d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_cols(), 10);
1571d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_nonzeros(), 10);
1581d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1591d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[2]], 0);
1601d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[2] + 1], 3);
1611d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[2] + 2], 5);
1621d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1631d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[2]], 5);
1641d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[2] + 1], 3);
1651d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[2] + 2], 4);
1661d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1671d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  // Only keep entries greater than 1.0;
1681d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  DropEntriesAndAddRow(dense_vector, 6, 6, 0.2, &scratch, &matrix);
1691d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_rows(), 4);
1701d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_cols(), 10);
1711d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_nonzeros(), 14);
1721d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1731d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[3]], 0);
1741d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[3] + 1], 2);
1751d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[3] + 2], 3);
1761d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[3] + 3], 5);
1771d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1781d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[3]], 5);
1791d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[3] + 1], 2);
1801d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[3] + 2], 3);
1811d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[3] + 3], 4);
1821d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1831d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  // Only keep the top 2 entries greater than 1.0
1841d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  DropEntriesAndAddRow(dense_vector, 6, 2, 0.2, &scratch, &matrix);
1851d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_rows(), 5);
1861d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_cols(), 10);
1871d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.num_nonzeros(), 16);
1881d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1891d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[4]], 0);
1901d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.cols()[matrix.rows()[4] + 1], 5);
1911d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1921d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[4]], 5);
1931d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  EXPECT_EQ(matrix.values()[matrix.rows()[4] + 1], 4);
1941d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling}
1951d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1961d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
1971d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling}  // namespace internal
1981d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling}  // namespace ceres
199