Enable visibility based preconditioners for CX_SPARSE and EIGEN_SPARSE

CLUSTER_JACOBI and CLUSTER_TRIDIAGONAL preconditioners require a sparse
Cholesky factorization library. Previously this code was hard coded to
use SuiteSparse. Once SparseCholesky abstraction was introduced, it
became possible to use it with Eigen or CXSParse.

Unfortunately the old code path that was enforcing the requirement
of SuiteSparse was not removed.

This change does the following:

1. Remove the SUITE_SPARSE restriction on CLUSTER_TRIDIAGONAL and
   CLUSTER_JACOBI
2. Redo the checking code to be ifdef free and more general.
3. Add bundle adjustment tests to test these configurations.

Thanks to Bjorn Piltz for catching and reporting this bug.

Change-Id: I637791f6f8149694b6aa75f6a4b6417398cb9590
diff --git a/internal/ceres/generate_bundle_adjustment_tests.py b/internal/ceres/generate_bundle_adjustment_tests.py
index 89cf8c7..86452b5 100644
--- a/internal/ceres/generate_bundle_adjustment_tests.py
+++ b/internal/ceres/generate_bundle_adjustment_tests.py
@@ -47,7 +47,11 @@
   ('ITERATIVE_SCHUR',        'NO_SPARSE',        'JACOBI'),
   ('ITERATIVE_SCHUR',        'NO_SPARSE',        'SCHUR_JACOBI'),
   ('ITERATIVE_SCHUR',        'SUITE_SPARSE',     'CLUSTER_JACOBI'),
+  ('ITERATIVE_SCHUR',        'EIGEN_SPARSE',     'CLUSTER_JACOBI'),
+  ('ITERATIVE_SCHUR',        'CX_SPARSE',        'CLUSTER_JACOBI'),
   ('ITERATIVE_SCHUR',        'SUITE_SPARSE',     'CLUSTER_TRIDIAGONAL'),
+  ('ITERATIVE_SCHUR',        'EIGEN_SPARSE',     'CLUSTER_TRIDIAGONAL'),
+  ('ITERATIVE_SCHUR',        'CX_SPARSE',        'CLUSTER_TRIDIAGONAL'),
   ('SPARSE_NORMAL_CHOLESKY', 'SUITE_SPARSE',     'IDENTITY'),
   ('SPARSE_NORMAL_CHOLESKY', 'EIGEN_SPARSE',     'IDENTITY'),
   ('SPARSE_NORMAL_CHOLESKY', 'CX_SPARSE',        'IDENTITY'),
@@ -122,13 +126,14 @@
 TEST_F(BundleAdjustmentTest,
        %(test_class_name)s) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = %(num_threads)s;
    options->linear_solver_type = %(linear_solver)s;
    options->sparse_linear_algebra_library_type = %(sparse_backend)s;
    options->preconditioner_type = %(preconditioner)s;
    if (%(ordering)s) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/CMakeLists.txt b/internal/ceres/generated_bundle_adjustment_tests/CMakeLists.txt
index 008fb8f..0a9cf59 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/CMakeLists.txt
+++ b/internal/ceres/generated_bundle_adjustment_tests/CMakeLists.txt
@@ -51,10 +51,26 @@
 ceres_test(ba_iterschur_suitesparse_clustjacobi_auto_threads)
 ceres_test(ba_iterschur_suitesparse_clustjacobi_user)
 ceres_test(ba_iterschur_suitesparse_clustjacobi_user_threads)
+ceres_test(ba_iterschur_eigensparse_clustjacobi_auto)
+ceres_test(ba_iterschur_eigensparse_clustjacobi_auto_threads)
+ceres_test(ba_iterschur_eigensparse_clustjacobi_user)
+ceres_test(ba_iterschur_eigensparse_clustjacobi_user_threads)
+ceres_test(ba_iterschur_cxsparse_clustjacobi_auto)
+ceres_test(ba_iterschur_cxsparse_clustjacobi_auto_threads)
+ceres_test(ba_iterschur_cxsparse_clustjacobi_user)
+ceres_test(ba_iterschur_cxsparse_clustjacobi_user_threads)
 ceres_test(ba_iterschur_suitesparse_clusttri_auto)
 ceres_test(ba_iterschur_suitesparse_clusttri_auto_threads)
 ceres_test(ba_iterschur_suitesparse_clusttri_user)
 ceres_test(ba_iterschur_suitesparse_clusttri_user_threads)
+ceres_test(ba_iterschur_eigensparse_clusttri_auto)
+ceres_test(ba_iterschur_eigensparse_clusttri_auto_threads)
+ceres_test(ba_iterschur_eigensparse_clusttri_user)
+ceres_test(ba_iterschur_eigensparse_clusttri_user_threads)
+ceres_test(ba_iterschur_cxsparse_clusttri_auto)
+ceres_test(ba_iterschur_cxsparse_clusttri_auto_threads)
+ceres_test(ba_iterschur_cxsparse_clusttri_user)
+ceres_test(ba_iterschur_cxsparse_clusttri_user_threads)
 ceres_test(ba_sparsecholesky_suitesparse_auto)
 ceres_test(ba_sparsecholesky_suitesparse_auto_threads)
 ceres_test(ba_sparsecholesky_suitesparse_user)
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_auto_test.cc
index c6cbaa5..642e9f2 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_auto_test.cc
@@ -43,13 +43,14 @@
 TEST_F(BundleAdjustmentTest,
        DenseSchur_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = DENSE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_auto_threads_test.cc
index bbbcbb6..10b19b7 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_auto_threads_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        DenseSchur_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = DENSE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_user_test.cc
index 48cd4c8..f852a46 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_user_test.cc
@@ -43,13 +43,14 @@
 TEST_F(BundleAdjustmentTest,
        DenseSchur_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = DENSE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_user_threads_test.cc
index ec070bf..324998f 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_denseschur_user_threads_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        DenseSchur_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = DENSE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_auto_test.cc
new file mode 100644
index 0000000..4ee23a5
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_auto_test.cc
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifndef CERES_NO_CXSPARSE
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_CxSparse_ClusterJacobi_AutomaticOrdering) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 1;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = CX_SPARSE;
+   options->preconditioner_type = CLUSTER_JACOBI;
+   if (kAutomaticOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_CXSPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_auto_threads_test.cc
new file mode 100644
index 0000000..85c5d83
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_auto_threads_test.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifndef CERES_NO_CXSPARSE
+#ifndef CERES_NO_THREADS
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_CxSparse_ClusterJacobi_AutomaticOrdering_Threads) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 4;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = CX_SPARSE;
+   options->preconditioner_type = CLUSTER_JACOBI;
+   if (kAutomaticOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_THREADS
+#endif  // CERES_NO_CXSPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_user_test.cc
new file mode 100644
index 0000000..5b03651
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_user_test.cc
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifndef CERES_NO_CXSPARSE
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_CxSparse_ClusterJacobi_UserOrdering) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 1;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = CX_SPARSE;
+   options->preconditioner_type = CLUSTER_JACOBI;
+   if (kUserOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_CXSPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_user_threads_test.cc
new file mode 100644
index 0000000..e855875
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clustjacobi_user_threads_test.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifndef CERES_NO_CXSPARSE
+#ifndef CERES_NO_THREADS
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_CxSparse_ClusterJacobi_UserOrdering_Threads) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 4;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = CX_SPARSE;
+   options->preconditioner_type = CLUSTER_JACOBI;
+   if (kUserOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_THREADS
+#endif  // CERES_NO_CXSPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_auto_test.cc
new file mode 100644
index 0000000..acc6e0d
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_auto_test.cc
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifndef CERES_NO_CXSPARSE
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_CxSparse_ClusterTridiagonal_AutomaticOrdering) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 1;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = CX_SPARSE;
+   options->preconditioner_type = CLUSTER_TRIDIAGONAL;
+   if (kAutomaticOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_CXSPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_auto_threads_test.cc
new file mode 100644
index 0000000..62c9924
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_auto_threads_test.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifndef CERES_NO_CXSPARSE
+#ifndef CERES_NO_THREADS
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_CxSparse_ClusterTridiagonal_AutomaticOrdering_Threads) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 4;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = CX_SPARSE;
+   options->preconditioner_type = CLUSTER_TRIDIAGONAL;
+   if (kAutomaticOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_THREADS
+#endif  // CERES_NO_CXSPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_user_test.cc
new file mode 100644
index 0000000..bd86d9c
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_user_test.cc
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifndef CERES_NO_CXSPARSE
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_CxSparse_ClusterTridiagonal_UserOrdering) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 1;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = CX_SPARSE;
+   options->preconditioner_type = CLUSTER_TRIDIAGONAL;
+   if (kUserOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_CXSPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_user_threads_test.cc
new file mode 100644
index 0000000..ea53a6e
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_cxsparse_clusttri_user_threads_test.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifndef CERES_NO_CXSPARSE
+#ifndef CERES_NO_THREADS
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_CxSparse_ClusterTridiagonal_UserOrdering_Threads) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 4;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = CX_SPARSE;
+   options->preconditioner_type = CLUSTER_TRIDIAGONAL;
+   if (kUserOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_THREADS
+#endif  // CERES_NO_CXSPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_auto_test.cc
new file mode 100644
index 0000000..78cd02e
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_auto_test.cc
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifdef CERES_USE_EIGEN_SPARSE
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_EigenSparse_ClusterJacobi_AutomaticOrdering) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 1;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
+   options->preconditioner_type = CLUSTER_JACOBI;
+   if (kAutomaticOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_USE_EIGEN_SPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_auto_threads_test.cc
new file mode 100644
index 0000000..83693b1
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_auto_threads_test.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifdef CERES_USE_EIGEN_SPARSE
+#ifndef CERES_NO_THREADS
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_EigenSparse_ClusterJacobi_AutomaticOrdering_Threads) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 4;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
+   options->preconditioner_type = CLUSTER_JACOBI;
+   if (kAutomaticOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_THREADS
+#endif  // CERES_USE_EIGEN_SPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_user_test.cc
new file mode 100644
index 0000000..dcc42cd
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_user_test.cc
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifdef CERES_USE_EIGEN_SPARSE
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_EigenSparse_ClusterJacobi_UserOrdering) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 1;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
+   options->preconditioner_type = CLUSTER_JACOBI;
+   if (kUserOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_USE_EIGEN_SPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_user_threads_test.cc
new file mode 100644
index 0000000..8566dce
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clustjacobi_user_threads_test.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifdef CERES_USE_EIGEN_SPARSE
+#ifndef CERES_NO_THREADS
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_EigenSparse_ClusterJacobi_UserOrdering_Threads) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 4;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
+   options->preconditioner_type = CLUSTER_JACOBI;
+   if (kUserOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_THREADS
+#endif  // CERES_USE_EIGEN_SPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_auto_test.cc
new file mode 100644
index 0000000..aef25fe
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_auto_test.cc
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifdef CERES_USE_EIGEN_SPARSE
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_EigenSparse_ClusterTridiagonal_AutomaticOrdering) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 1;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
+   options->preconditioner_type = CLUSTER_TRIDIAGONAL;
+   if (kAutomaticOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_USE_EIGEN_SPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_auto_threads_test.cc
new file mode 100644
index 0000000..58389c6
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_auto_threads_test.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifdef CERES_USE_EIGEN_SPARSE
+#ifndef CERES_NO_THREADS
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_EigenSparse_ClusterTridiagonal_AutomaticOrdering_Threads) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 4;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
+   options->preconditioner_type = CLUSTER_TRIDIAGONAL;
+   if (kAutomaticOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_THREADS
+#endif  // CERES_USE_EIGEN_SPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_user_test.cc
new file mode 100644
index 0000000..eee6da0
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_user_test.cc
@@ -0,0 +1,65 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifdef CERES_USE_EIGEN_SPARSE
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_EigenSparse_ClusterTridiagonal_UserOrdering) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 1;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
+   options->preconditioner_type = CLUSTER_TRIDIAGONAL;
+   if (kUserOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_USE_EIGEN_SPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_user_threads_test.cc
new file mode 100644
index 0000000..826239b
--- /dev/null
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_eigensparse_clusttri_user_threads_test.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2018 Google Inc. All rights reserved.
+// http://ceres-solver.org/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// ========================================
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
+// ========================================
+//
+// This file is generated using generate_bundle_adjustment_tests.py.
+
+#include "bundle_adjustment_test_util.h"
+
+#ifdef CERES_USE_EIGEN_SPARSE
+#ifndef CERES_NO_THREADS
+
+namespace ceres {
+namespace internal {
+
+TEST_F(BundleAdjustmentTest,
+       IterativeSchur_EigenSparse_ClusterTridiagonal_UserOrdering_Threads) {  // NOLINT
+   BundleAdjustmentProblem bundle_adjustment_problem;
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
+   options->num_threads = 4;
+   options->linear_solver_type = ITERATIVE_SCHUR;
+   options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
+   options->preconditioner_type = CLUSTER_TRIDIAGONAL;
+   if (kUserOrdering) {
+     options->linear_solver_ordering.reset();
+   }
+   Problem* problem = bundle_adjustment_problem.mutable_problem();
+   RunSolverForConfigAndExpectResidualsMatch(*options, problem);
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_NO_THREADS
+#endif  // CERES_USE_EIGEN_SPARSE
+
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_auto_test.cc
index 5f36b2e..e59be90 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_auto_test.cc
@@ -43,13 +43,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_Jacobi_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = JACOBI;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_auto_threads_test.cc
index 8312db2..7bcdad2 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_auto_threads_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_Jacobi_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = JACOBI;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_user_test.cc
index 82f394a..c58f2fd 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_user_test.cc
@@ -43,13 +43,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_Jacobi_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = JACOBI;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_user_threads_test.cc
index 78f5524..ef73824 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_jacobi_user_threads_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_Jacobi_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = JACOBI;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_auto_test.cc
index 5407f3c..0f775e1 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_auto_test.cc
@@ -43,13 +43,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SchurJacobi_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = SCHUR_JACOBI;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_auto_threads_test.cc
index ed04d8f..9d91c81 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_auto_threads_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SchurJacobi_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = SCHUR_JACOBI;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_user_test.cc
index 4299738..564104c 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_user_test.cc
@@ -43,13 +43,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SchurJacobi_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = SCHUR_JACOBI;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_user_threads_test.cc
index 46a320a..f37de7a 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_schurjacobi_user_threads_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SchurJacobi_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = NO_SPARSE;
    options->preconditioner_type = SCHUR_JACOBI;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_auto_test.cc
index b87d386..71b774e 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_auto_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SuiteSparse_ClusterJacobi_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = CLUSTER_JACOBI;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_auto_threads_test.cc
index 414a3e9..23706a6 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_auto_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SuiteSparse_ClusterJacobi_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = CLUSTER_JACOBI;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_user_test.cc
index b0da4af..e2a3bb2 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_user_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SuiteSparse_ClusterJacobi_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = CLUSTER_JACOBI;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_user_threads_test.cc
index 0078911..05b270c 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clustjacobi_user_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SuiteSparse_ClusterJacobi_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = CLUSTER_JACOBI;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_auto_test.cc
index dc35fc8..04ad42e 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_auto_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SuiteSparse_ClusterTridiagonal_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = CLUSTER_TRIDIAGONAL;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_auto_threads_test.cc
index b8b8613..2164c11 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_auto_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SuiteSparse_ClusterTridiagonal_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = CLUSTER_TRIDIAGONAL;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_user_test.cc
index bdea636..a0c213c 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_user_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SuiteSparse_ClusterTridiagonal_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = CLUSTER_TRIDIAGONAL;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_user_threads_test.cc
index e8b844a..15eb761 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_iterschur_suitesparse_clusttri_user_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        IterativeSchur_SuiteSparse_ClusterTridiagonal_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = ITERATIVE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = CLUSTER_TRIDIAGONAL;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_auto_test.cc
index 00c0757..b47daef 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_auto_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_CxSparse_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = CX_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_auto_threads_test.cc
index 52a86c3..22d1002 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_auto_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_CxSparse_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = CX_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_user_test.cc
index 9a4cdb5..e0c5268 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_user_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_CxSparse_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = CX_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_user_threads_test.cc
index 960630a..2ea905a 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_cxsparse_user_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_CxSparse_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = CX_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_auto_test.cc
index c4575df..ce502d6 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_auto_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_EigenSparse_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_auto_threads_test.cc
index 1cda776..b91a6d4 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_auto_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_EigenSparse_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_user_test.cc
index e9e42af..e17caf6 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_user_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_EigenSparse_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_user_threads_test.cc
index a3aa368..b17f480 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_eigensparse_user_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_EigenSparse_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_auto_test.cc
index f699981..e114a51 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_auto_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_SuiteSparse_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_auto_threads_test.cc
index 7253075..3340f2f 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_auto_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_SuiteSparse_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_user_test.cc
index dae0ed6..8998e90 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_user_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_SuiteSparse_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_user_threads_test.cc
index 82bec88..b13e26d 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparsecholesky_suitesparse_user_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseNormalCholesky_SuiteSparse_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_auto_test.cc
index a623cb9..6d9fb7c 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_auto_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_CxSparse_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = CX_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_auto_threads_test.cc
index 8d13c66..69e8cce 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_auto_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_CxSparse_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = CX_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_user_test.cc
index 73b0787..f60b7c1 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_user_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_CxSparse_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = CX_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_user_threads_test.cc
index 9318a27..cfb9798 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_cxsparse_user_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_CxSparse_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = CX_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_auto_test.cc
index eb31fed..a143591 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_auto_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_EigenSparse_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_auto_threads_test.cc
index d9c9b0b..111c2a4 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_auto_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_EigenSparse_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_user_test.cc
index 0e34884..9ad242e 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_user_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_EigenSparse_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_user_threads_test.cc
index bf7d5f4..abd914d 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_eigensparse_user_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_EigenSparse_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = EIGEN_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_auto_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_auto_test.cc
index 7e8853f..21d0e50 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_auto_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_auto_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_SuiteSparse_AutomaticOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_auto_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_auto_threads_test.cc
index 823dcfe..145eb9d 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_auto_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_auto_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_SuiteSparse_AutomaticOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kAutomaticOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_user_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_user_test.cc
index a375c94..f73cc7d 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_user_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_user_test.cc
@@ -45,13 +45,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_SuiteSparse_UserOrdering) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 1;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_user_threads_test.cc b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_user_threads_test.cc
index 9af1d56..b0d67d7 100644
--- a/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_user_threads_test.cc
+++ b/internal/ceres/generated_bundle_adjustment_tests/ba_sparseschur_suitesparse_user_threads_test.cc
@@ -46,13 +46,14 @@
 TEST_F(BundleAdjustmentTest,
        SparseSchur_SuiteSparse_UserOrdering_Threads) {  // NOLINT
    BundleAdjustmentProblem bundle_adjustment_problem;
-   Solver::Options* options = bundle_adjustment_problem.mutable_solver_options();
+   Solver::Options* options =
+     bundle_adjustment_problem.mutable_solver_options();
    options->num_threads = 4;
    options->linear_solver_type = SPARSE_SCHUR;
    options->sparse_linear_algebra_library_type = SUITE_SPARSE;
    options->preconditioner_type = IDENTITY;
    if (kUserOrdering) {
-    options->linear_solver_ordering.reset();
+     options->linear_solver_ordering.reset();
    }
    Problem* problem = bundle_adjustment_problem.mutable_problem();
    RunSolverForConfigAndExpectResidualsMatch(*options, problem);
diff --git a/internal/ceres/solver.cc b/internal/ceres/solver.cc
index 3fa4be1..d38982a 100644
--- a/internal/ceres/solver.cc
+++ b/internal/ceres/solver.cc
@@ -59,6 +59,8 @@
 using std::map;
 using std::string;
 using std::vector;
+using internal::StringAppendF;
+using internal::StringPrintf;
 
 #define OPTION_OP(x, y, OP)                                             \
   if (!(options.x OP y)) {                                              \
@@ -146,100 +148,59 @@
     return false;
   }
 
-  if (options.preconditioner_type == CLUSTER_JACOBI &&
-      options.sparse_linear_algebra_library_type != SUITE_SPARSE) {
-    *error =  "CLUSTER_JACOBI requires "
-        "Solver::Options::sparse_linear_algebra_library_type to be "
-        "SUITE_SPARSE.";
+  if (options.dense_linear_algebra_library_type == LAPACK &&
+      !IsDenseLinearAlgebraLibraryTypeAvailable(LAPACK) &&
+      (options.linear_solver_type == DENSE_NORMAL_CHOLESKY ||
+       options.linear_solver_type == DENSE_QR ||
+       options.linear_solver_type == DENSE_SCHUR)) {
+    *error = StringPrintf(
+        "Can't use %s with "
+        "Solver::Options::dense_linear_algebra_library_type = LAPACK "
+        "because LAPACK was not enabled when Ceres was built.",
+        LinearSolverTypeToString(options.linear_solver_type));
     return false;
   }
 
-  if (options.preconditioner_type == CLUSTER_TRIDIAGONAL &&
-      options.sparse_linear_algebra_library_type != SUITE_SPARSE) {
-    *error =  "CLUSTER_TRIDIAGONAL requires "
-        "Solver::Options::sparse_linear_algebra_library_type to be "
-        "SUITE_SPARSE.";
-    return false;
-  }
-
-#ifdef CERES_NO_LAPACK
-  if (options.dense_linear_algebra_library_type == LAPACK) {
-    if (options.linear_solver_type == DENSE_NORMAL_CHOLESKY) {
-      *error = "Can't use DENSE_NORMAL_CHOLESKY with LAPACK because "
-          "LAPACK was not enabled when Ceres was built.";
-      return false;
-    } else if (options.linear_solver_type == DENSE_QR) {
-      *error = "Can't use DENSE_QR with LAPACK because "
-          "LAPACK was not enabled when Ceres was built.";
-      return false;
-    } else if (options.linear_solver_type == DENSE_SCHUR) {
-      *error = "Can't use DENSE_SCHUR with LAPACK because "
-          "LAPACK was not enabled when Ceres was built.";
-      return false;
-    }
-  }
-#endif
-
-#ifdef CERES_NO_SUITESPARSE
-  if (options.sparse_linear_algebra_library_type == SUITE_SPARSE) {
-    if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY) {
-      *error = "Can't use SPARSE_NORMAL_CHOLESKY with SUITESPARSE because "
-             "SuiteSparse was not enabled when Ceres was built.";
-      return false;
-    } else if (options.linear_solver_type == SPARSE_SCHUR) {
-      *error = "Can't use SPARSE_SCHUR with SUITESPARSE because "
-          "SuiteSparse was not enabled when Ceres was built.";
-      return false;
-    } else if (options.preconditioner_type == CLUSTER_JACOBI) {
-      *error =  "CLUSTER_JACOBI preconditioner not supported. "
-          "SuiteSparse was not enabled when Ceres was built.";
-      return false;
-    } else if (options.preconditioner_type == CLUSTER_TRIDIAGONAL) {
-      *error =  "CLUSTER_TRIDIAGONAL preconditioner not supported. "
-          "SuiteSparse was not enabled when Ceres was built.";
-    return false;
-    }
-  }
-#endif
-
-#ifdef CERES_NO_CXSPARSE
-  if (options.sparse_linear_algebra_library_type == CX_SPARSE) {
-    if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY) {
-      *error = "Can't use SPARSE_NORMAL_CHOLESKY with CX_SPARSE because "
-             "CXSparse was not enabled when Ceres was built.";
-      return false;
-    } else if (options.linear_solver_type == SPARSE_SCHUR) {
-      *error = "Can't use SPARSE_SCHUR with CX_SPARSE because "
-          "CXSparse was not enabled when Ceres was built.";
-      return false;
-    }
-  }
-#endif
-
-#ifndef CERES_USE_EIGEN_SPARSE
-  if (options.sparse_linear_algebra_library_type == EIGEN_SPARSE) {
-    if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY) {
-      *error = "Can't use SPARSE_NORMAL_CHOLESKY with EIGEN_SPARSE because "
-          "Eigen's sparse linear algebra was not enabled when Ceres was "
-          "built.";
-      return false;
-    } else if (options.linear_solver_type == SPARSE_SCHUR) {
-      *error = "Can't use SPARSE_SCHUR with EIGEN_SPARSE because "
-          "Eigen's sparse linear algebra was not enabled when Ceres was "
-          "built.";
-      return false;
-    }
-  }
-#endif
-
   if (options.sparse_linear_algebra_library_type == NO_SPARSE) {
-    if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY) {
-      *error = "Can't use SPARSE_NORMAL_CHOLESKY as "
-          "sparse_linear_algebra_library_type is NO_SPARSE.";
+    const char* error_template =
+        "Can't use %s with "
+        "Solver::Options::sparse_linear_algebra_library_type = NO_SPARSE.";
+    const char* name = nullptr;
+
+    if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY ||
+        options.linear_solver_type == SPARSE_SCHUR) {
+      name = LinearSolverTypeToString(options.linear_solver_type);
+    } else if (options.linear_solver_type == ITERATIVE_SCHUR &&
+               (options.preconditioner_type == CLUSTER_JACOBI ||
+                options.preconditioner_type == CLUSTER_TRIDIAGONAL)) {
+      name = PreconditionerTypeToString(options.preconditioner_type);
+    }
+
+    if (name != nullptr) {
+      *error = StringPrintf(error_template, name);
       return false;
-    } else if (options.linear_solver_type == SPARSE_SCHUR) {
-      *error = "Can't use SPARSE_SCHUR as "
-          "sparse_linear_algebra_library_type is NO_SPARSE.";
+    }
+  } else if (!IsSparseLinearAlgebraLibraryTypeAvailable(
+                 options.sparse_linear_algebra_library_type)) {
+    const char* error_template =
+        "Can't use %s with "
+        "Solver::Options::sparse_linear_algebra_library_type = %s, "
+        "because support was not enabled when Ceres Solver was built.";
+    const char* name = nullptr;
+    if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY ||
+        options.linear_solver_type == SPARSE_SCHUR) {
+      name = LinearSolverTypeToString(options.linear_solver_type);
+    } else if (options.linear_solver_type == ITERATIVE_SCHUR &&
+               (options.preconditioner_type == CLUSTER_JACOBI ||
+                options.preconditioner_type == CLUSTER_TRIDIAGONAL)) {
+      name = PreconditionerTypeToString(options.preconditioner_type);
+    }
+
+    if (name != nullptr) {
+      *error = StringPrintf(error_template,
+                            name,
+                            SparseLinearAlgebraLibraryTypeToString(
+                                options.sparse_linear_algebra_library_type));
       return false;
     }
   }
@@ -633,9 +594,6 @@
   solver.Solve(options, problem, summary);
 }
 
-using internal::StringAppendF;
-using internal::StringPrintf;
-
 string Solver::Summary::BriefReport() const {
   return StringPrintf("Ceres Solver Report: "
                       "Iterations: %d, "