Remove a level of indirection when using CellInfo

The CellInfo struct contains a mutex, which interacts poorly
with some standard library containers which may move things around.
As a result we were using std::unique_ptr<CellInfo> in these
containers, but this change gets rid of that level of indirection
as std::unordered_map can construct CellInfo in place and we can
replace the use of std::vector with an array we know will not be
resized.

This improves the performance of the schur eliminator a bit but
also the performance of the block diagonal preconditioners.

Change-Id: If3ccd1273a754d9c5112e6e611ce31066b6b27b5
diff --git a/internal/ceres/block_random_access_diagonal_matrix.cc b/internal/ceres/block_random_access_diagonal_matrix.cc
index 357fc31..643dbf1 100644
--- a/internal/ceres/block_random_access_diagonal_matrix.cc
+++ b/internal/ceres/block_random_access_diagonal_matrix.cc
@@ -52,10 +52,10 @@
     : context_(context), num_threads_(num_threads) {
   m_ = CompressedRowSparseMatrix::CreateBlockDiagonalMatrix(nullptr, blocks);
   double* values = m_->mutable_values();
-  layout_.reserve(blocks.size());
-  for (auto& block : blocks) {
-    layout_.emplace_back(std::make_unique<CellInfo>(values));
-    values += block.size * block.size;
+  layout_ = std::make_unique<CellInfo[]>(blocks.size());
+  for (int i = 0; i < blocks.size(); ++i) {
+    layout_[i].values = values;
+    values += blocks[i].size * blocks[i].size;
   }
 }
 
@@ -77,7 +77,7 @@
   *col = 0;
   *row_stride = stride;
   *col_stride = stride;
-  return layout_[row_block_id].get();
+  return &layout_[row_block_id];
 }
 
 // Assume that the user does not hold any locks on any cell blocks
@@ -91,9 +91,9 @@
   auto& blocks = m_->row_blocks();
   const int num_blocks = blocks.size();
   ParallelFor(context_, 0, num_blocks, num_threads_, [this, blocks](int i) {
-    auto* cell_info = layout_[i].get();
+    auto& cell_info = layout_[i];
     auto& block = blocks[i];
-    MatrixRef b(cell_info->values, block.size, block.size);
+    MatrixRef b(cell_info.values, block.size, block.size);
     b = b.selfadjointView<Eigen::Upper>().llt().solve(
         Matrix::Identity(block.size, block.size));
   });
@@ -107,9 +107,9 @@
   const int num_blocks = blocks.size();
   ParallelFor(
       context_, 0, num_blocks, num_threads_, [this, blocks, x, y](int i) {
-        auto* cell_info = layout_[i].get();
+        auto& cell_info = layout_[i];
         auto& block = blocks[i];
-        ConstMatrixRef b(cell_info->values, block.size, block.size);
+        ConstMatrixRef b(cell_info.values, block.size, block.size);
         VectorRef(y + block.position, block.size).noalias() +=
             b * ConstVectorRef(x + block.position, block.size);
       });
diff --git a/internal/ceres/block_random_access_diagonal_matrix.h b/internal/ceres/block_random_access_diagonal_matrix.h
index e5f50b0..9671f3e 100644
--- a/internal/ceres/block_random_access_diagonal_matrix.h
+++ b/internal/ceres/block_random_access_diagonal_matrix.h
@@ -33,7 +33,6 @@
 
 #include <memory>
 #include <utility>
-#include <vector>
 
 #include "ceres/block_random_access_matrix.h"
 #include "ceres/block_structure.h"
@@ -85,7 +84,7 @@
   ContextImpl* context_ = nullptr;
   const int num_threads_ = 1;
   std::unique_ptr<CompressedRowSparseMatrix> m_;
-  std::vector<std::unique_ptr<CellInfo>> layout_;
+  std::unique_ptr<CellInfo[]> layout_;
 };
 
 }  // namespace ceres::internal
diff --git a/internal/ceres/block_random_access_sparse_matrix.cc b/internal/ceres/block_random_access_sparse_matrix.cc
index 271544e..b9f8b36 100644
--- a/internal/ceres/block_random_access_sparse_matrix.cc
+++ b/internal/ceres/block_random_access_sparse_matrix.cc
@@ -91,8 +91,7 @@
     for (auto& c : cells) {
       const int col_block_id = c.block_id;
       double* const data = values + c.position;
-      layout_[IntPairToInt64(row_block_id, col_block_id)] =
-          std::make_unique<CellInfo>(data);
+      layout_.emplace(IntPairToInt64(row_block_id, col_block_id), data);
     }
   }
 }
@@ -113,7 +112,7 @@
   *col = 0;
   *row_stride = blocks_[row_block_id].size;
   *col_stride = blocks_[col_block_id].size;
-  return it->second.get();
+  return &it->second;
 }
 
 // Assume that the user does not hold any locks on any cell blocks
diff --git a/internal/ceres/block_random_access_sparse_matrix.h b/internal/ceres/block_random_access_sparse_matrix.h
index c509a01..5121832 100644
--- a/internal/ceres/block_random_access_sparse_matrix.h
+++ b/internal/ceres/block_random_access_sparse_matrix.h
@@ -113,8 +113,8 @@
   const int num_threads_ = 1;
 
   // A mapping from <row_block_id, col_block_id> to the position in
-  // the values array of tsm_ where the block is stored.
-  using LayoutType = std::unordered_map<int64_t, std::unique_ptr<CellInfo>>;
+  // the values array of bsm_ where the block is stored.
+  using LayoutType = std::unordered_map<std::int64_t, CellInfo>;
   LayoutType layout_;
 
   // The underlying matrix object which actually stores the cells.