Simplify the implementation to convert from BlockSparseMatrix to
CompressedRowSparseMatrix.

Since the conversion from BlockSparseMatrix to CompressedRowSparseMatrix
is not used in any performance-critical context, this CL simplifies it
by re-using existing conversions.

Change-Id: I51263bc95cc056efb31961ccda548cd7be35b2a4
diff --git a/internal/ceres/block_sparse_matrix.cc b/internal/ceres/block_sparse_matrix.cc
index 90bd926..4202470 100644
--- a/internal/ceres/block_sparse_matrix.cc
+++ b/internal/ceres/block_sparse_matrix.cc
@@ -168,39 +168,11 @@
   }
 }
 
-void BlockSparseMatrix::ToCRSMatrix(CRSMatrix* crs_matrix) const {
-  CHECK(crs_matrix != nullptr);
-  crs_matrix->num_rows = num_rows_;
-  crs_matrix->num_cols = num_cols_;
-  vector<int>& rows = crs_matrix->rows;
-  vector<int>& cols = crs_matrix->cols;
-  vector<double>& values = crs_matrix->values;
-  rows.clear();
-  cols.clear();
-  values.clear();
-  rows.reserve(num_nonzeros_ + 1);
-  cols.reserve(num_nonzeros_);
-  values.reserve(num_nonzeros_);
-
-  for (const auto& row_block : block_structure_->rows) {
-    int row_block_size = row_block.block.size;
-    const vector<Cell>& cells = row_block.cells;
-    for (int r = 0; r < row_block_size; ++r) {
-      rows.push_back(values.size());
-      for (const auto& cell : cells) {
-        int col_block_id = cell.block_id;
-        int col_block_size = block_structure_->cols[col_block_id].size;
-        int col_start = block_structure_->cols[col_block_id].position;
-        const MatrixRef m(
-            values_.get() + cell.position, row_block_size, col_block_size);
-        for (int c = 0; c < col_block_size; ++c) {
-          cols.push_back(c + col_start);
-          values.push_back(m(r, c));
-        }
-      }
-    }
-  }
-  rows.push_back(values.size());
+void BlockSparseMatrix::ToCompressedRowSparseMatrix(
+    CompressedRowSparseMatrix* crs_matrix) const {
+  TripletSparseMatrix ts_matrix;
+  this->ToTripletSparseMatrix(&ts_matrix);
+  *crs_matrix = *CompressedRowSparseMatrix::FromTripletSparseMatrix(ts_matrix);
 }
 
 void BlockSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
diff --git a/internal/ceres/block_sparse_matrix.h b/internal/ceres/block_sparse_matrix.h
index 44cb5e5..b7ea1df 100644
--- a/internal/ceres/block_sparse_matrix.h
+++ b/internal/ceres/block_sparse_matrix.h
@@ -38,7 +38,7 @@
 #include <random>
 
 #include "ceres/block_structure.h"
-#include "ceres/crs_matrix.h"
+#include "ceres/compressed_row_sparse_matrix.h"
 #include "ceres/internal/disable_warnings.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/export.h"
@@ -76,7 +76,7 @@
   void LeftMultiplyAndAccumulate(const double* x, double* y) const final;
   void SquaredColumnNorm(double* x) const final;
   void ScaleColumns(const double* scale) final;
-  void ToCRSMatrix(CRSMatrix* matrix) const;
+  void ToCompressedRowSparseMatrix(CompressedRowSparseMatrix* matrix) const;
   void ToDenseMatrix(Matrix* dense_matrix) const final;
   void ToTextFile(FILE* file) const final;
 
diff --git a/internal/ceres/block_sparse_matrix_test.cc b/internal/ceres/block_sparse_matrix_test.cc
index 4b02abf..7d7d4c9 100644
--- a/internal/ceres/block_sparse_matrix_test.cc
+++ b/internal/ceres/block_sparse_matrix_test.cc
@@ -45,13 +45,6 @@
 namespace internal {
 
 namespace {
-template <typename T>
-void CheckVectorEq(const std::vector<T>& a, const std::vector<T>& b) {
-  EXPECT_EQ(a.size(), b.size());
-  for (int i = 0; i < a.size(); ++i) {
-    EXPECT_EQ(a[i], b[i]);
-  }
-}
 
 std::unique_ptr<BlockSparseMatrix> CreateTestMatrixFromId(int id) {
   if (id == 0) {
@@ -321,25 +314,39 @@
 TEST(BlockSparseMatrix, ToCRSMatrix) {
   {
     std::unique_ptr<BlockSparseMatrix> m = CreateTestMatrixFromId(0);
-    CRSMatrix m_crs;
-    m->ToCRSMatrix(&m_crs);
+    CompressedRowSparseMatrix m_crs(
+        m->num_rows(), m->num_cols(), m->num_nonzeros());
+    m->ToCompressedRowSparseMatrix(&m_crs);
     std::vector<int> rows_expected = {0, 2, 4, 7, 10};
     std::vector<int> cols_expected = {0, 1, 0, 1, 2, 3, 4, 2, 3, 4};
     std::vector<double> values_expected = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-    CheckVectorEq(rows_expected, m_crs.rows);
-    CheckVectorEq(cols_expected, m_crs.cols);
-    CheckVectorEq(values_expected, m_crs.values);
+    for (int i = 0; i < rows_expected.size(); ++i) {
+      EXPECT_EQ(m_crs.rows()[i], rows_expected[i]);
+    }
+    for (int i = 0; i < cols_expected.size(); ++i) {
+      EXPECT_EQ(m_crs.cols()[i], cols_expected[i]);
+    }
+    for (int i = 0; i < values_expected.size(); ++i) {
+      EXPECT_EQ(m_crs.values()[i], values_expected[i]);
+    }
   }
   {
     std::unique_ptr<BlockSparseMatrix> m = CreateTestMatrixFromId(1);
-    CRSMatrix m_crs;
-    m->ToCRSMatrix(&m_crs);
+    CompressedRowSparseMatrix m_crs(
+        m->num_rows(), m->num_cols(), m->num_nonzeros());
+    m->ToCompressedRowSparseMatrix(&m_crs);
     std::vector<int> rows_expected = {0, 4, 8, 9};
     std::vector<int> cols_expected = {0, 1, 3, 4, 0, 1, 3, 4, 2};
     std::vector<double> values_expected = {1, 2, 5, 6, 3, 4, 7, 8, 9};
-    CheckVectorEq(rows_expected, m_crs.rows);
-    CheckVectorEq(cols_expected, m_crs.cols);
-    CheckVectorEq(values_expected, m_crs.values);
+    for (int i = 0; i < rows_expected.size(); ++i) {
+      EXPECT_EQ(m_crs.rows()[i], rows_expected[i]);
+    }
+    for (int i = 0; i < cols_expected.size(); ++i) {
+      EXPECT_EQ(m_crs.cols()[i], cols_expected[i]);
+    }
+    for (int i = 0; i < values_expected.size(); ++i) {
+      EXPECT_EQ(m_crs.values()[i], values_expected[i]);
+    }
   }
 }