Minor refactoring/cleanup in IterativeSchurComplementSolver

The code for creating and updating preconditioners has been pulled
out in into its own function for better readability.

Change-Id: I5335de3b158a8485cf6d052ee37d0d8fd57145e9
diff --git a/internal/ceres/block_jacobi_preconditioner.h b/internal/ceres/block_jacobi_preconditioner.h
index 1400729..0541db5 100644
--- a/internal/ceres/block_jacobi_preconditioner.h
+++ b/internal/ceres/block_jacobi_preconditioner.h
@@ -31,7 +31,6 @@
 #ifndef CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_
 #define CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_
 
-#include <vector>
 #include "ceres/block_random_access_diagonal_matrix.h"
 #include "ceres/internal/scoped_ptr.h"
 #include "ceres/preconditioner.h"
@@ -62,8 +61,8 @@
   virtual void RightMultiply(const double* x, double* y) const;
   virtual int num_rows() const { return m_->num_rows(); }
   virtual int num_cols() const { return m_->num_rows(); }
-
   const BlockRandomAccessDiagonalMatrix& matrix() const { return *m_; }
+
  private:
   virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D);
 
diff --git a/internal/ceres/iterative_schur_complement_solver.cc b/internal/ceres/iterative_schur_complement_solver.cc
index 9d4e30d..bf2a3fb 100644
--- a/internal/ceres/iterative_schur_complement_solver.cc
+++ b/internal/ceres/iterative_schur_complement_solver.cc
@@ -56,11 +56,9 @@
 
 IterativeSchurComplementSolver::IterativeSchurComplementSolver(
     const LinearSolver::Options& options)
-    : options_(options) {
-}
+    : options_(options) {}
 
-IterativeSchurComplementSolver::~IterativeSchurComplementSolver() {
-}
+IterativeSchurComplementSolver::~IterativeSchurComplementSolver() {}
 
 LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
     BlockSparseMatrix* A,
@@ -86,29 +84,59 @@
       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;
-    cg_summary.num_iterations = 0;
-    cg_summary.termination_type = LINEAR_SOLVER_SUCCESS;
+    LinearSolver::Summary summary;
+    summary.num_iterations = 0;
+    summary.termination_type = LINEAR_SOLVER_SUCCESS;
     schur_complement_->BackSubstitute(NULL, x);
-    return cg_summary;
+    return summary;
   }
 
   // Initialize the solution to the Schur complement system to zero.
   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.
   LinearSolver::Options cg_options;
   cg_options.min_num_iterations = options_.min_num_iterations;
   cg_options.max_num_iterations = options_.max_num_iterations;
   ConjugateGradientsSolver cg_solver(cg_options);
-  LinearSolver::PerSolveOptions cg_per_solve_options;
 
+  LinearSolver::PerSolveOptions cg_per_solve_options;
   cg_per_solve_options.r_tolerance = per_solve_options.r_tolerance;
   cg_per_solve_options.q_tolerance = per_solve_options.q_tolerance;
 
+  if (!CreateAndOrUpdatePreconditioner(A, per_solve_options.D)) {
+    LinearSolver::Summary summary;
+    summary.num_iterations = 0;
+    summary.termination_type = LINEAR_SOLVER_FAILURE;
+    summary.message = "Preconditioner creation or update failed.";
+    return summary;
+  }
+
+  if (preconditioner_.get() != NULL) {
+    cg_per_solve_options.preconditioner = preconditioner_.get();
+  }
+
+  event_logger.AddEvent("Setup");
+  LinearSolver::Summary summary =
+      cg_solver.Solve(schur_complement_.get(),
+                      schur_complement_->rhs().data(),
+                      cg_per_solve_options,
+                      reduced_linear_system_solution_.data());
+  if (summary.termination_type != LINEAR_SOLVER_FAILURE &&
+      summary.termination_type != LINEAR_SOLVER_FATAL_ERROR) {
+    schur_complement_->BackSubstitute(reduced_linear_system_solution_.data(),
+                                      x);
+  }
+  event_logger.AddEvent("Solve");
+  return summary;
+}
+
+bool IterativeSchurComplementSolver::CreateAndOrUpdatePreconditioner(
+    BlockSparseMatrix* A, double* D) {
+  if (options_.preconditioner_type == IDENTITY) {
+    return true;
+  }
+
   Preconditioner::Options preconditioner_options;
   preconditioner_options.type = options_.preconditioner_type;
   preconditioner_options.visibility_clustering_type =
@@ -121,61 +149,27 @@
   preconditioner_options.f_block_size = options_.f_block_size;
   preconditioner_options.elimination_groups = options_.elimination_groups;
 
-  switch (options_.preconditioner_type) {
-    case IDENTITY:
-      break;
-    case JACOBI:
-      preconditioner_.reset(
-          new SparseMatrixPreconditionerWrapper(
-              schur_complement_->block_diagonal_FtF_inverse()));
-      break;
-    case SCHUR_JACOBI:
-      if (preconditioner_.get() == NULL) {
-        preconditioner_.reset(
-            new SchurJacobiPreconditioner(*A->block_structure(),
-                                          preconditioner_options));
-      }
-      break;
-    case CLUSTER_JACOBI:
-    case CLUSTER_TRIDIAGONAL:
-      if (preconditioner_.get() == NULL) {
-        preconditioner_.reset(
-            new VisibilityBasedPreconditioner(*A->block_structure(),
-                                              preconditioner_options));
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unknown Preconditioner Type";
-  }
-
-  bool preconditioner_update_was_successful = true;
-  if (preconditioner_.get() != NULL) {
-    preconditioner_update_was_successful =
-        preconditioner_->Update(*A, per_solve_options.D);
-    cg_per_solve_options.preconditioner = preconditioner_.get();
-  }
-  event_logger.AddEvent("Setup");
-
-  LinearSolver::Summary cg_summary;
-  cg_summary.num_iterations = 0;
-  cg_summary.termination_type = LINEAR_SOLVER_FAILURE;
-
-  // TODO(sameeragarwal): Refactor preconditioners to return a more
-  // sane message.
-  cg_summary.message = "Preconditioner update failed.";
-  if (preconditioner_update_was_successful) {
-    cg_summary = cg_solver.Solve(schur_complement_.get(),
-                                 schur_complement_->rhs().data(),
-                                 cg_per_solve_options,
-                                 reduced_linear_system_solution_.data());
-    if (cg_summary.termination_type != LINEAR_SOLVER_FAILURE &&
-        cg_summary.termination_type != LINEAR_SOLVER_FATAL_ERROR) {
-      schur_complement_->BackSubstitute(
-          reduced_linear_system_solution_.data(), x);
+  if (preconditioner_.get() == NULL) {
+    switch (options_.preconditioner_type) {
+      case JACOBI:
+        preconditioner_.reset(new SparseMatrixPreconditionerWrapper(
+            schur_complement_->block_diagonal_FtF_inverse()));
+        break;
+      case SCHUR_JACOBI:
+        preconditioner_.reset(new SchurJacobiPreconditioner(
+            *A->block_structure(), preconditioner_options));
+        break;
+      case CLUSTER_JACOBI:
+      case CLUSTER_TRIDIAGONAL:
+        preconditioner_.reset(new VisibilityBasedPreconditioner(
+            *A->block_structure(), preconditioner_options));
+        break;
+      default:
+        LOG(FATAL) << "Unknown Preconditioner Type";
     }
   }
-  event_logger.AddEvent("Solve");
-  return cg_summary;
+
+  return preconditioner_->Update(*A, D);
 }
 
 }  // namespace internal
diff --git a/internal/ceres/iterative_schur_complement_solver.h b/internal/ceres/iterative_schur_complement_solver.h
index e90d310..ed99f2d 100644
--- a/internal/ceres/iterative_schur_complement_solver.h
+++ b/internal/ceres/iterative_schur_complement_solver.h
@@ -79,6 +79,8 @@
       const LinearSolver::PerSolveOptions& options,
       double* x);
 
+  bool CreateAndOrUpdatePreconditioner(BlockSparseMatrix* A, double* D);
+
   LinearSolver::Options options_;
   scoped_ptr<internal::ImplicitSchurComplement> schur_complement_;
   scoped_ptr<Preconditioner> preconditioner_;