Template specializations for PartitionedMatrixView.

This speeds up the matrix vector products in the
IterativeSchurSolver by upto 40%.

Change-Id: Ib5e8d77c7269cf5ffdd2d161893734bb6d38215d
diff --git a/internal/ceres/iterative_schur_complement_solver.cc b/internal/ceres/iterative_schur_complement_solver.cc
index 1aac565..90013ff 100644
--- a/internal/ceres/iterative_schur_complement_solver.cc
+++ b/internal/ceres/iterative_schur_complement_solver.cc
@@ -38,6 +38,7 @@
 #include "ceres/block_sparse_matrix.h"
 #include "ceres/block_structure.h"
 #include "ceres/conjugate_gradients_solver.h"
+#include "ceres/detect_structure.h"
 #include "ceres/implicit_schur_complement.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/scoped_ptr.h"
@@ -69,17 +70,20 @@
   EventLogger event_logger("IterativeSchurComplementSolver::Solve");
 
   CHECK_NOTNULL(A->block_structure());
-
+  const int num_eliminate_blocks = options_.elimination_groups[0];
   // Initialize a ImplicitSchurComplement object.
   if (schur_complement_ == NULL) {
-    schur_complement_.reset(
-        new ImplicitSchurComplement(options_.elimination_groups[0],
-                                    options_.preconditioner_type == JACOBI));
+    DetectStructure(*(A->block_structure()),
+                    num_eliminate_blocks,
+                    &options_.row_block_size,
+                    &options_.e_block_size,
+                    &options_.f_block_size);
+    schur_complement_.reset(new ImplicitSchurComplement(options_));
   }
   schur_complement_->Init(*A, per_solve_options.D, b);
 
   const int num_schur_complement_blocks =
-      A->block_structure()->cols.size() - options_.elimination_groups[0];
+      A->block_structure()->cols.size() - num_eliminate_blocks;
   if (num_schur_complement_blocks == 0) {
     VLOG(2) << "No parameter blocks left in the schur complement.";
     LinearSolver::Summary cg_summary;
@@ -90,14 +94,12 @@
   }
 
   // Initialize the solution to the Schur complement system to zero.
-  //
-  // TODO(sameeragarwal): There maybe a better initialization than an
-  // all zeros solution. Explore other cheap starting points.
   reduced_linear_system_solution_.resize(schur_complement_->num_rows());
   reduced_linear_system_solution_.setZero();
 
-  // Instantiate a conjugate gradient solver that runs on the Schur complement
-  // matrix with the block diagonal of the matrix F'F as the preconditioner.
+  // Instantiate a conjugate gradient solver that runs on the Schur
+  // complement matrix with the block diagonal of the matrix F'F as
+  // the preconditioner.
   LinearSolver::Options cg_options;
   cg_options.max_num_iterations = options_.max_num_iterations;
   ConjugateGradientsSolver cg_solver(cg_options);