Squashed 'third_party/ceres/' changes from e51e9b46f..399cda773

399cda773 Update build documentation to reflect detection of Eigen via config mode
bb127272f Fix typos.
a0ec5c32a Update version history for 2.0.0RC2
3f6d27367 Unify symbol visibility configuration for all compilers
29c2912ee Unbreak the bazel build some more
bf47e1a36 Fix the Bazel build.
600e8c529 fix minor typos
bdcdcc78a update docs for changed cmake usage
3f69e5b36 Corrections from William Rucklidge
8bfdb02fb Rewrite uses of VLOG_IF and LOG_IF.
d1b35ffc1 Corrections from William Rucklidge
f34e80e91 Add dividers between licenses.
65c397dae Fix formatting
f63b1fea9 Add the MIT license text corresponding to the libmv derived files.
542613c13 minor formatting fix for trust_region_minimizer.cc
6d9e9843d Remove inclusion of ceres/eigen.h
eafeca5dc Fix a logging bug in TrustRegionMinimizer.
1fd0be916 Fix default initialisation of IterationCallback::cost
137bbe845 add info about clang-format to contributing docs
d3f66d77f fix formatting generated files (best effort)
a9c7361c8 minor formatting fix (wrongly updated in earlier commit)
7b8f675bf fix formatting for (non-generated) internal source files
921368ce3 Fix a number of typos in covariance.h
7b6b2491c fix formatting for examples
82275d8a4 some fixes for Linux and macOS install docs
9d762d74f fix formatting for public header files
c76478c48 gitignore *.pyc
4e69a475c Fix potential for mismatched release/debug TBB libraries
8e1d8e32a A number of small changes.
368a738e5 AutoDiffCostFunction: optional ownership
8cbd721c1 Add erf and erfc to jet.h, including tests in jet_test.cc
31366cff2 Benchmarks for dynamic autodiff.
29fb08aea Use CMAKE_PREFIX_PATH to pass Homebrew install location
242c703b5 Minor fixes to the documentation
79bbf9510 Add changelog for 2.0.0
41d05f13d Fix lint errors in evaluation_callback_test.cc
4b67903c1 Remove unused variables from problem_test.cc
10449fc36 Add Apache license to the LICENSE file for FixedArray
8c3ecec6d Fix some minor errors in IterationCallback docs
7d3ffcb42 Remove forced CONFIG from find_package(Eigen3)
a029fc0f9 Use latest FindTBB.cmake from VTK project
aa1abbc57 Replace use of GFLAGS_LIBRARIES with export gflags target
db2af1be8 Add Problem::EvaluateResidualBlockAssumingParametersUnchanged
ab4ed32cd Replace NULL with nullptr in the documentation.
ee280e27a Allow SubsetParameterization to accept an empty vector of constant parameters.
4b8c731d8 Fix a bug in DynamicAutoDiffCostFunction
5cb5b35a9 Fixed incorrect argument name in RotationMatrixToQuaternion()
e39d9ed1d Add a missing term and remove a superfluous word
27cab77b6 Reformulate some sentences
8ac6655ce Fix documentation formatting issues
7ef83e075 Update minimum required C++ version for Ceres to C++14
1d75e7568 Improve documentation for LocalParameterization
763398ca4 Update the section on Preconditioners
a614f788a Call EvaluationCallback before evaluating the fixed cost.
70308f7bb Simplify documentation generation.
e886d7e65 Reduce the number of minimizer iterations in evaluation_callback_test.cc
9483e6f2f Simplify DynamicCompressedRowJacobianWriter::Write
323cc55bb Update the version in package.xml to 2.0.0.
303b078b5 Fix few typos and alter a NULL to nullptr.
cca93fed6 Bypass Ceres' FindGlog.cmake in CeresConfig.cmake if possible
77fc1d0fc Use build_depend for private dependencies in Catkin package.xml
a09682f00 Fix MSVC version check to support use of clang-cl front-end
b70687fcc Add namespace qualified Ceres::ceres CMake target
99efa54bd Replace type aliases deprecated/removed in C++17/C++20 from FixedArray
adb973e4a NULL -> nullptr
27b717951 Respect FIND_QUIETLY flag in cmake config file
646959ef1 Do not export class template LineParameterization
1f128d070 Change the type of parameter index/offset to match their getter/setter
072c8f070 Initialize integer variables with integer instead of double
8c36bcc81 Use inline & -inlinehint-threshold in auto-diff benchmarks
57cf20aa5 static const -> static constexpr where we can.
40b27482a Add std::numeric_limit specialization for Jets
e751d6e4f Remove AutodiffCodegen
e9eb76f8e Remove AutodiffCodegen CMake integration
9435e08a7 More clang-tidy and wjr@ comment fixes
d93fac4b7 Remove AutodiffCodegen Tests
2281c6ed2 Fixes for comments from William Rucklidge
d797a87a4 Use Ridders' method in GradientChecker.
41675682d Fix a MSVC type deduction bug in ComputeHouseholderVector
947ec0c1f Remove AutodiffCodegen autodiff benchmarks
27183d661 Allow LocalParameterizations to have zero local size.
7ac7d79dc Remove HelloWorldCodegen example
8c8738bf8 Add photometric and relative-pose residuals to autodiff benchmarks
9f7fb66d6 Add a constant cost function to the autodiff benchmarks
ab0d373e4 Fix a comment in autodiff.h
27bb99714 Change SVD algorithm in covariance computation.
84fdac38e Add const to GetCovarianceMatrix*
6bde61d6b Add line local parameterization.
2c1c0932e Update documentation in autodiff.h
8904fa488 Inline Jet initialization in Autodiff
18a464d4e Remove an errant CR from local_parameterization.cc
5c85f2179 Use ArraySelector in Autodiff
80477ff07 Add class ArraySelector
e7a30359e Pass kNumResiduals to Autodiff
f339d71dd Refactor the automatic differentiation benchmarks.
d37b4cb15 Fix some include headers in codegen/test_utils.cc/h
550766e6d Add Autodiff Brdf Benchmark
8da9876e7 Add more autodiff benchmarks
6da364713 Fix Tukey loss function
cf4185c4e Add Codegen BA Benchmark
75dd30fae Simplify GenerateCodeForFunctor
9049688c6 Default Initialize ExpressionRef to Zero
bf1aff2f0 Fix 3+ nested Jet constructor
92d6541c7 Move Codegen files into codegen/ directory
8e962f37d Add Autodiff Codegen Tests
13c7a22ce Codegen Optimizer API
90799e29e Fix install and unnecessary string copy
032d5844c AutoDiff Code Generation - CMake Integration
d82de91b8 Add ExpressionGraph::Erase(ExpressionId)
c8e35e19f Add namespaces to generated functions and constants
75e575cae Fix use of incomplete type in defaulted Problem methods
8def19616 Remove ExpressionRef Move Constructor
f26f95410 Fix windows MSVC build.
fdf9cfd32 Add functions to find the matching ELSE, ENDIF expressions
678c05b28 Fix invert PSD matrix.
a384a7e96 Remove not used using declaration
a60136b7a Add COMMENT ExpressionType
f212c9295 Let Problem::SetParameterization be called more than once.
a3696835b use CMake function to create CeresConfigVersion
67fcff918 Make Problem movable.
19728e72d Add documentation for Problem::IsParameterBlockConstant
ba6e5fb4a Make the custom uninstall target optional
8547cbd55 Make EventLogger more efficient.
edb8322bd Update the minimum required version of Eigen to 3.3.
aa6ef417f Specify Eigen3_DIR in iOS and Android Travis CI builds
4655f2549 Use find_package() instead of find_dependency() in CeresConfig.cmake
a548766d1 Use glfags target
33dd469a5 Use Eigen3::Eigen target
47e784bb4 NULL-jacobians are handled correctly in generated autodiff code
edd54b83e Update Jet.h and rotation.h to use the new IF/ELSE macros
848c1f90c Update return type in code generator and add tests for logical functions
5010421bb Add the expression return type as a member to Expression
f4dc670ee Improve testing of the codegen system
572ec4a5a Rework Expression creation and insertion
c7337154e Disable the code generation module by default
7fa0f3db4 Explicitly state PUBLIC/PRIVATE when linking
4362a2169 Run clang-format on the public headers. Also update copyright year.
c56702aac Fix installation of codegen headers
0d03e74dc Fix the include in the autodiff codegen example
d16026440 Autodiff Codegen Part 4: Public API
d1703db45 Moved AutoDiffCodeGen macros to a separate (public) header
5ce6c063d Fix ExpressionRef copy constructor and add a move constructor
a90b5a12c Pass ExpressionRef by const reference instead of by value
ea057678c Remove MakeFunctionCall() and add test for Ternary
1084c5460 Quote all configure-expanded paths
3d756b07c Test Expressions with 'insert' instead of a macro
486d81812 Add ExpressionGraph::InsertExpression
3831a1dd3 Expression and ExpressionGraph comparison
9bb1dcb84 Remove definition of ExpressionRef::ExpressionRef(double&);
5be2e4883 Autodiff Codegen Part 3: CodeGenerator
6cd633043 Remove unused ExpressionTypes
7d0d69a4d Fix ExpressionRef
6ba8c57d2 Fix expression_test IsArithmetic
2b494cfb3 Update Travis CI to Bionic & Xcode 11.2
a3dde6877 Require Xcode >= 11.2 on macOS 10.15 (Catalina)
6fd4f072d Autodiff Codegen Part 2: Conditionals
52d6477a4 Detect and disable -fstack-check on macOS 10.15 with Xcode 11
46ca461b7 Fix `gradient_check_relative_precision` docs typo
4247d420f Autodiff Codegen Part 1: Expressions
ba62397d8 Run clang-format on jet.h
667062dcc Introduce BlockSparseMatrixData
17becf461 Remove a CHECK failure from covariance_impl.cc
d7f428e5c Add a missing cast in rotation.h
ea4d66e7e clang-tidy fixes.
be15b842a Integrate the SchurEliminatorForOneFBlock for the case <2,3,6>
087b28f1b Remove use of SetUsage as it creates compilation problems.
573046d7f Protect declarations of lapack functions under CERES_NO_LAPACK
71d638ef3 Add a specialized schur eliminator.
2ffddaccf Use override & final instead of just using virtual.
e4577dd6d Use override instead of virtual for subclasses.
3e5db5bc2 Fixing documentation typo.
82d325b73 Avoid memory allocations in Accelerate Sparse[Refactor/Solve]().
f66b51382 Fix some clang-tidy warnings.
0428e2dd0 Fix missing #include of <memory>
487c1aa51 Expose SubsetPreconditioner in the API
bf709ecac Move EvaluationCallback from Solver::Options to Problem::Options.
059bcb7f8 Drop ROS dependency on catkin
c4dbc927d Default to any other sparse libraries over Accelerate
db1f5b57a Allow some methods in Problem to use const double*.
a60c14525 Explicitly delete the copy constructor and copy assignment operator
084042c25 Lint changes from William Rucklidge
93d869020 Use selfAdjoingView<Upper> in InvertPSDMatrix.
a0cd0854a Speed up InvertPSDMatrix
7b53262b7 Allow Solver::Options::max_num_line_search_step_size_iterations = 0.
3e2cdca54 Make LineSearchMinizer work correctly with negative valued functions.
3ff12a878 Fix a clang-tidy warning in problem_test.cc
57441fe90 Fix two bugs.
1b852c57e Add Problem::EvaluateResidualBlock.
54ba6c27b Fix missing declaration warnings in Ceres code
fac46d50e Modernize ProductParameterization.
53dc6213f Add some missing string-to-enum-to-string convertors.
c0aa9a263 Add checks in rotation.h for inplace operations.
0f57fa82d Update Bazel WORKSPACE for newest Bazel
f8e5fba7b TripletSparseMatrix: guard against self-assignment
939253c20 Fix Eigen alignment issues.
bf67daf79 Add the missing <array> header to fixed_array.h
25e1cdbb6 Switch to FixedArray implementation from abseil.
d467a627b IdentityTransformation -> IdentityParameterization
eaec6a9d0 Fix more typos in CostFunctionToFunctor documentation.
99b5aa4aa Fix typos in CostFunctionToFunctor documentation.
ee7e2cb3c Set Homebrew paths via HINTS not CMAKE_PREFIX_PATH
4f8a01853 Revert "Fix custom Eigen on macos (EIGEN_INCLUDE_DIR_HINTS)"
e6c5c7226 Fix custom Eigen on macos (EIGEN_INCLUDE_DIR_HINTS)
5a56d522e Add the 3,3,3 template specialization.
df5c23116 Reorder initializer list to make -Wreorder happy
0fcfdb0b4 Fix the build breakage caused by the last commit.
9b9e9f0dc Reduce machoness of macro definition in cost_functor_to_function_test.cc
21d40daa0 Remove UTF-8 chars
9350e57a4 Enable optional use of sanitizers
0456edffb Update Travis CI Linux distro to 16.04 (Xenial)
bef0dfe35 Fix a typo in cubic_interpolation.h
056ba9bb1 Add AutoDiffFirstOrderFunction
6e527392d Update googletest/googlemock to db9b85e2.
1b2940749 Clarify documentation of BiCubicInterpolator::Evaluate for out-of-bounds values

Change-Id: Id61dd832e8fbe286deb0799aa1399d4017031dae
git-subtree-dir: third_party/ceres
git-subtree-split: 399cda773035d99eaf1f4a129a666b3c4df9d1b1
diff --git a/include/ceres/internal/array_selector.h b/include/ceres/internal/array_selector.h
new file mode 100644
index 0000000..841797f
--- /dev/null
+++ b/include/ceres/internal/array_selector.h
@@ -0,0 +1,95 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2020 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.
+//
+// Author: darius.rueckert@fau.de (Darius Rueckert)
+//
+
+#ifndef CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
+#define CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
+
+#include <array>
+#include <vector>
+
+#include "ceres/internal/fixed_array.h"
+#include "ceres/types.h"
+
+namespace ceres {
+namespace internal {
+
+// StaticFixedArray selects the best array implementation based on template
+// arguments. If the size is not known at compile-time, pass
+// ceres::DYNAMIC as a size-template argument.
+//
+// Three different containers are selected in different scenarios:
+//
+//   num_elements == DYNAMIC:
+//      -> ceres::internal::FixedArray<T, max_stack_size>(size)
+
+//   num_elements != DYNAMIC  &&  num_elements <= max_stack_size
+//      -> std::array<T,num_elements>
+
+//   num_elements != DYNAMIC  &&  num_elements >  max_stack_size
+//      -> std::vector<T>(num_elements)
+//
+template <typename T,
+          int num_elements,
+          int max_num_elements_on_stack,
+          bool dynamic = (num_elements == DYNAMIC),
+          bool fits_on_stack = (num_elements <= max_num_elements_on_stack)>
+struct ArraySelector {};
+
+template <typename T,
+          int num_elements,
+          int max_num_elements_on_stack,
+          bool fits_on_stack>
+struct ArraySelector<T,
+                     num_elements,
+                     max_num_elements_on_stack,
+                     true,
+                     fits_on_stack>
+    : ceres::internal::FixedArray<T, max_num_elements_on_stack> {
+  ArraySelector(int s)
+      : ceres::internal::FixedArray<T, max_num_elements_on_stack>(s) {}
+};
+
+template <typename T, int num_elements, int max_num_elements_on_stack>
+struct ArraySelector<T, num_elements, max_num_elements_on_stack, false, true>
+    : std::array<T, num_elements> {
+  ArraySelector(int s) { CHECK_EQ(s, num_elements); }
+};
+
+template <typename T, int num_elements, int max_num_elements_on_stack>
+struct ArraySelector<T, num_elements, max_num_elements_on_stack, false, false>
+    : std::vector<T> {
+  ArraySelector(int s) : std::vector<T>(s) { CHECK_EQ(s, num_elements); }
+};
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
diff --git a/include/ceres/internal/autodiff.h b/include/ceres/internal/autodiff.h
index ff47fbf..9d7de75 100644
--- a/include/ceres/internal/autodiff.h
+++ b/include/ceres/internal/autodiff.h
@@ -1,5 +1,5 @@
 // Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2015 Google Inc. All rights reserved.
+// Copyright 2019 Google Inc. All rights reserved.
 // http://ceres-solver.org/
 //
 // Redistribution and use in source and binary forms, with or without
@@ -143,7 +143,9 @@
 #include <stddef.h>
 
 #include <array>
+#include <utility>
 
+#include "ceres/internal/array_selector.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/fixed_array.h"
 #include "ceres/internal/parameter_dims.h"
@@ -152,6 +154,17 @@
 #include "ceres/types.h"
 #include "glog/logging.h"
 
+// If the number of parameters exceeds this values, the corresponding jets are
+// placed on the heap. This will reduce performance by a factor of 2-5 on
+// current compilers.
+#ifndef CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK
+#define CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK 50
+#endif
+
+#ifndef CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK
+#define CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK 20
+#endif
+
 namespace ceres {
 namespace internal {
 
@@ -169,16 +182,24 @@
 //
 // is what would get put in dst if N was 3, offset was 3, and the jet type JetT
 // was 8-dimensional.
-template <int Offset, int N, typename T, typename JetT>
-inline void Make1stOrderPerturbation(const T* src, JetT* dst) {
-  DCHECK(src);
-  DCHECK(dst);
-  for (int j = 0; j < N; ++j) {
-    dst[j].a = src[j];
-    dst[j].v.setZero();
-    dst[j].v[Offset + j] = T(1.0);
+template <int j, int N, int Offset, typename T, typename JetT>
+struct Make1stOrderPerturbation {
+ public:
+  inline static void Apply(const T* src, JetT* dst) {
+    if (j == 0) {
+      DCHECK(src);
+      DCHECK(dst);
+    }
+    dst[j] = JetT(src[j], j + Offset);
+    Make1stOrderPerturbation<j + 1, N, Offset, T, JetT>::Apply(src, dst);
   }
-}
+};
+
+template <int N, int Offset, typename T, typename JetT>
+struct Make1stOrderPerturbation<N, N, Offset, T, JetT> {
+ public:
+  static void Apply(const T* src, JetT* dst) {}
+};
 
 // Calls Make1stOrderPerturbation for every parameter block.
 //
@@ -186,26 +207,31 @@
 // If one having three parameter blocks with dimensions (3, 2, 4), the call
 // Make1stOrderPerturbations<integer_sequence<3, 2, 4>::Apply(params, x);
 // will result in the following calls to Make1stOrderPerturbation:
-// Make1stOrderPerturbation<0, 3>(params[0], x + 0);
-// Make1stOrderPerturbation<3, 2>(params[1], x + 3);
-// Make1stOrderPerturbation<5, 4>(params[2], x + 5);
+// Make1stOrderPerturbation<0, 3, 0>::Apply(params[0], x + 0);
+// Make1stOrderPerturbation<0, 2, 3>::Apply(params[1], x + 3);
+// Make1stOrderPerturbation<0, 4, 5>::Apply(params[2], x + 5);
 template <typename Seq, int ParameterIdx = 0, int Offset = 0>
 struct Make1stOrderPerturbations;
 
 template <int N, int... Ns, int ParameterIdx, int Offset>
-struct Make1stOrderPerturbations<integer_sequence<int, N, Ns...>, ParameterIdx,
+struct Make1stOrderPerturbations<std::integer_sequence<int, N, Ns...>,
+                                 ParameterIdx,
                                  Offset> {
   template <typename T, typename JetT>
-  static void Apply(T const* const* parameters, JetT* x) {
-    Make1stOrderPerturbation<Offset, N>(parameters[ParameterIdx], x + Offset);
-    Make1stOrderPerturbations<integer_sequence<int, Ns...>, ParameterIdx + 1,
+  inline static void Apply(T const* const* parameters, JetT* x) {
+    Make1stOrderPerturbation<0, N, Offset, T, JetT>::Apply(
+        parameters[ParameterIdx], x + Offset);
+    Make1stOrderPerturbations<std::integer_sequence<int, Ns...>,
+                              ParameterIdx + 1,
                               Offset + N>::Apply(parameters, x);
   }
 };
 
 // End of 'recursion'. Nothing more to do.
 template <int ParameterIdx, int Total>
-struct Make1stOrderPerturbations<integer_sequence<int>, ParameterIdx, Total> {
+struct Make1stOrderPerturbations<std::integer_sequence<int>,
+                                 ParameterIdx,
+                                 Total> {
   template <typename T, typename JetT>
   static void Apply(T const* const* /* NOT USED */, JetT* /* NOT USED */) {}
 };
@@ -253,61 +279,83 @@
 struct Take1stOrderParts;
 
 template <int N, int... Ns, int ParameterIdx, int Offset>
-struct Take1stOrderParts<integer_sequence<int, N, Ns...>, ParameterIdx,
+struct Take1stOrderParts<std::integer_sequence<int, N, Ns...>,
+                         ParameterIdx,
                          Offset> {
   template <typename JetT, typename T>
-  static void Apply(int num_outputs, JetT* output, T** jacobians) {
+  inline static void Apply(int num_outputs, JetT* output, T** jacobians) {
     if (jacobians[ParameterIdx]) {
       Take1stOrderPart<Offset, N>(num_outputs, output, jacobians[ParameterIdx]);
     }
-    Take1stOrderParts<integer_sequence<int, Ns...>, ParameterIdx + 1,
+    Take1stOrderParts<std::integer_sequence<int, Ns...>,
+                      ParameterIdx + 1,
                       Offset + N>::Apply(num_outputs, output, jacobians);
   }
 };
 
 // End of 'recursion'. Nothing more to do.
 template <int ParameterIdx, int Offset>
-struct Take1stOrderParts<integer_sequence<int>, ParameterIdx, Offset> {
+struct Take1stOrderParts<std::integer_sequence<int>, ParameterIdx, Offset> {
   template <typename T, typename JetT>
-  static void Apply(int /* NOT USED*/, JetT* /* NOT USED*/,
+  static void Apply(int /* NOT USED*/,
+                    JetT* /* NOT USED*/,
                     T** /* NOT USED */) {}
 };
 
-template <typename ParameterDims, typename Functor, typename T>
+template <int kNumResiduals,
+          typename ParameterDims,
+          typename Functor,
+          typename T>
 inline bool AutoDifferentiate(const Functor& functor,
-                              T const *const *parameters,
-                              int num_outputs,
+                              T const* const* parameters,
+                              int dynamic_num_outputs,
                               T* function_value,
                               T** jacobians) {
-  DCHECK_GT(num_outputs, 0);
-
   typedef Jet<T, ParameterDims::kNumParameters> JetT;
-  FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(ParameterDims::kNumParameters +
-                                               num_outputs);
-
   using Parameters = typename ParameterDims::Parameters;
 
-  // These are the positions of the respective jets in the fixed array x.
+  if (kNumResiduals != DYNAMIC) {
+    DCHECK_EQ(kNumResiduals, dynamic_num_outputs);
+  }
+
+  ArraySelector<JetT,
+                ParameterDims::kNumParameters,
+                CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK>
+      parameters_as_jets(ParameterDims::kNumParameters);
+
+  // Pointers to the beginning of each parameter block
   std::array<JetT*, ParameterDims::kNumParameterBlocks> unpacked_parameters =
-      ParameterDims::GetUnpackedParameters(x.get());
-  JetT* output = x.get() + ParameterDims::kNumParameters;
+      ParameterDims::GetUnpackedParameters(parameters_as_jets.data());
+
+  // If the number of residuals is fixed, we use the template argument as the
+  // number of outputs. Otherwise we use the num_outputs parameter. Note: The
+  // ?-operator here is compile-time evaluated, therefore num_outputs is also
+  // a compile-time constant for functors with fixed residuals.
+  const int num_outputs =
+      kNumResiduals == DYNAMIC ? dynamic_num_outputs : kNumResiduals;
+  DCHECK_GT(num_outputs, 0);
+
+  ArraySelector<JetT, kNumResiduals, CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK>
+      residuals_as_jets(num_outputs);
 
   // Invalidate the output Jets, so that we can detect if the user
   // did not assign values to all of them.
   for (int i = 0; i < num_outputs; ++i) {
-    output[i].a = kImpossibleValue;
-    output[i].v.setConstant(kImpossibleValue);
+    residuals_as_jets[i].a = kImpossibleValue;
+    residuals_as_jets[i].v.setConstant(kImpossibleValue);
   }
 
-  Make1stOrderPerturbations<Parameters>::Apply(parameters, x.get());
+  Make1stOrderPerturbations<Parameters>::Apply(parameters,
+                                               parameters_as_jets.data());
 
-  if (!VariadicEvaluate<ParameterDims>(functor, unpacked_parameters.data(),
-                                       output)) {
+  if (!VariadicEvaluate<ParameterDims>(
+          functor, unpacked_parameters.data(), residuals_as_jets.data())) {
     return false;
   }
 
-  Take0thOrderPart(num_outputs, output, function_value);
-  Take1stOrderParts<Parameters>::Apply(num_outputs, output, jacobians);
+  Take0thOrderPart(num_outputs, residuals_as_jets.data(), function_value);
+  Take1stOrderParts<Parameters>::Apply(
+      num_outputs, residuals_as_jets.data(), jacobians);
 
   return true;
 }
diff --git a/include/ceres/internal/disable_warnings.h b/include/ceres/internal/disable_warnings.h
index fd848fe..d7766a0 100644
--- a/include/ceres/internal/disable_warnings.h
+++ b/include/ceres/internal/disable_warnings.h
@@ -34,11 +34,11 @@
 #define CERES_WARNINGS_DISABLED
 
 #ifdef _MSC_VER
-#pragma warning( push )
+#pragma warning(push)
 // Disable the warning C4251 which is triggered by stl classes in
 // Ceres' public interface. To quote MSDN: "C4251 can be ignored "
 // "if you are deriving from a type in the Standard C++ Library"
-#pragma warning( disable : 4251 )
+#pragma warning(disable : 4251)
 #endif
 
 #endif  // CERES_WARNINGS_DISABLED
diff --git a/include/ceres/internal/eigen.h b/include/ceres/internal/eigen.h
index 59545df..b6d0b7f 100644
--- a/include/ceres/internal/eigen.h
+++ b/include/ceres/internal/eigen.h
@@ -36,31 +36,26 @@
 namespace ceres {
 
 typedef Eigen::Matrix<double, Eigen::Dynamic, 1> Vector;
-typedef Eigen::Matrix<double,
-                      Eigen::Dynamic,
-                      Eigen::Dynamic,
-                      Eigen::RowMajor> Matrix;
+typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
+    Matrix;
 typedef Eigen::Map<Vector> VectorRef;
 typedef Eigen::Map<Matrix> MatrixRef;
 typedef Eigen::Map<const Vector> ConstVectorRef;
 typedef Eigen::Map<const Matrix> ConstMatrixRef;
 
 // Column major matrices for DenseSparseMatrix/DenseQRSolver
-typedef Eigen::Matrix<double,
-                      Eigen::Dynamic,
-                      Eigen::Dynamic,
-                      Eigen::ColMajor> ColMajorMatrix;
+typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>
+    ColMajorMatrix;
 
-typedef Eigen::Map<ColMajorMatrix, 0,
-                   Eigen::Stride<Eigen::Dynamic, 1>> ColMajorMatrixRef;
+typedef Eigen::Map<ColMajorMatrix, 0, Eigen::Stride<Eigen::Dynamic, 1>>
+    ColMajorMatrixRef;
 
-typedef Eigen::Map<const ColMajorMatrix,
-                   0,
-                   Eigen::Stride<Eigen::Dynamic, 1>> ConstColMajorMatrixRef;
+typedef Eigen::Map<const ColMajorMatrix, 0, Eigen::Stride<Eigen::Dynamic, 1>>
+    ConstColMajorMatrixRef;
 
 // C++ does not support templated typdefs, thus the need for this
 // struct so that we can support statically sized Matrix and Maps.
- template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
+template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
 struct EigenTypes {
   typedef Eigen::Matrix<double,
                         num_rows,
diff --git a/include/ceres/internal/fixed_array.h b/include/ceres/internal/fixed_array.h
index dcb2ace..dcbddcd 100644
--- a/include/ceres/internal/fixed_array.h
+++ b/include/ceres/internal/fixed_array.h
@@ -1,188 +1,465 @@
-// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2015 Google Inc. All rights reserved.
-// http://ceres-solver.org/
+// Copyright 2018 The Abseil Authors.
 //
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
 //
-// * 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.
+//      https://www.apache.org/licenses/LICENSE-2.0
 //
-// 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.
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 //
-// Author: rennie@google.com (Jeffrey Rennie)
-// Author: sanjay@google.com (Sanjay Ghemawat) -- renamed to FixedArray
+// -----------------------------------------------------------------------------
+// File: fixed_array.h
+// -----------------------------------------------------------------------------
+//
+// A `FixedArray<T>` represents a non-resizable array of `T` where the length of
+// the array can be determined at run-time. It is a good replacement for
+// non-standard and deprecated uses of `alloca()` and variable length arrays
+// within the GCC extension. (See
+// https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html).
+//
+// `FixedArray` allocates small arrays inline, keeping performance fast by
+// avoiding heap operations. It also helps reduce the chances of
+// accidentally overflowing your stack if large input is passed to
+// your function.
 
 #ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
 #define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
 
+#include <Eigen/Core>  // For Eigen::aligned_allocator
+#include <algorithm>
+#include <array>
 #include <cstddef>
-#include "Eigen/Core"
-#include "ceres/internal/manual_constructor.h"
+#include <memory>
+#include <tuple>
+#include <type_traits>
+
+#include "ceres/internal/memory.h"
 #include "glog/logging.h"
 
 namespace ceres {
 namespace internal {
 
-// A FixedArray<T> represents a non-resizable array of T where the
-// length of the array does not need to be a compile time constant.
-//
-// FixedArray allocates small arrays inline, and large arrays on
-// the heap.  It is a good replacement for non-standard and deprecated
-// uses of alloca() and variable length arrays (a GCC extension).
-//
-// FixedArray keeps performance fast for small arrays, because it
-// avoids heap operations.  It also helps reduce the chances of
-// accidentally overflowing your stack if large input is passed to
-// your function.
-//
-// Also, FixedArray is useful for writing portable code.  Not all
-// compilers support arrays of dynamic size.
+constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
 
-// Most users should not specify an inline_elements argument and let
-// FixedArray<> automatically determine the number of elements
-// to store inline based on sizeof(T).
+// The default fixed array allocator.
 //
-// If inline_elements is specified, the FixedArray<> implementation
-// will store arrays of length <= inline_elements inline.
-//
-// Finally note that unlike vector<T> FixedArray<T> will not zero-initialize
-// simple types like int, double, bool, etc.
-//
-// Non-POD types will be default-initialized just like regular vectors or
-// arrays.
+// As one can not easily detect if a struct contains or inherits from a fixed
+// size Eigen type, to be safe the Eigen::aligned_allocator is used by default.
+// But trivial types can never contain Eigen types, so std::allocator is used to
+// safe some heap memory.
+template <typename T>
+using FixedArrayDefaultAllocator =
+    typename std::conditional<std::is_trivial<T>::value,
+                              std::allocator<T>,
+                              Eigen::aligned_allocator<T>>::type;
 
-#if defined(_WIN64)
-   typedef __int64      ssize_t;
-#elif defined(_WIN32)
-   typedef __int32      ssize_t;
-#endif
-
-template <typename T, ssize_t inline_elements = -1>
+// -----------------------------------------------------------------------------
+// FixedArray
+// -----------------------------------------------------------------------------
+//
+// A `FixedArray` provides a run-time fixed-size array, allocating a small array
+// inline for efficiency.
+//
+// Most users should not specify an `inline_elements` argument and let
+// `FixedArray` automatically determine the number of elements
+// to store inline based on `sizeof(T)`. If `inline_elements` is specified, the
+// `FixedArray` implementation will use inline storage for arrays with a
+// length <= `inline_elements`.
+//
+// Note that a `FixedArray` constructed with a `size_type` argument will
+// default-initialize its values by leaving trivially constructible types
+// uninitialized (e.g. int, int[4], double), and others default-constructed.
+// This matches the behavior of c-style arrays and `std::array`, but not
+// `std::vector`.
+//
+// Note that `FixedArray` does not provide a public allocator; if it requires a
+// heap allocation, it will do so with global `::operator new[]()` and
+// `::operator delete[]()`, even if T provides class-scope overrides for these
+// operators.
+template <typename T,
+          size_t N = kFixedArrayUseDefault,
+          typename A = FixedArrayDefaultAllocator<T>>
 class FixedArray {
+  static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
+                "Arrays with unknown bounds cannot be used with FixedArray.");
+
+  static constexpr size_t kInlineBytesDefault = 256;
+
+  using AllocatorTraits = std::allocator_traits<A>;
+  // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
+  // but this seems to be mostly pedantic.
+  template <typename Iterator>
+  using EnableIfForwardIterator = typename std::enable_if<std::is_convertible<
+      typename std::iterator_traits<Iterator>::iterator_category,
+      std::forward_iterator_tag>::value>::type;
+  static constexpr bool DefaultConstructorIsNonTrivial() {
+    return !std::is_trivially_default_constructible<StorageElement>::value;
+  }
+
  public:
-  // For playing nicely with stl:
-  typedef T value_type;
-  typedef T* iterator;
-  typedef T const* const_iterator;
-  typedef T& reference;
-  typedef T const& const_reference;
-  typedef T* pointer;
-  typedef std::ptrdiff_t difference_type;
-  typedef size_t size_type;
+  using allocator_type = typename AllocatorTraits::allocator_type;
+  using value_type = typename AllocatorTraits::value_type;
+  using pointer = typename AllocatorTraits::pointer;
+  using const_pointer = typename AllocatorTraits::const_pointer;
+  using reference = value_type&;
+  using const_reference = const value_type&;
+  using size_type = typename AllocatorTraits::size_type;
+  using difference_type = typename AllocatorTraits::difference_type;
+  using iterator = pointer;
+  using const_iterator = const_pointer;
+  using reverse_iterator = std::reverse_iterator<iterator>;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
 
-  // REQUIRES: n >= 0
-  // Creates an array object that can store "n" elements.
+  static constexpr size_type inline_elements =
+      (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
+                                  : static_cast<size_type>(N));
+
+  FixedArray(const FixedArray& other,
+             const allocator_type& a = allocator_type())
+      : FixedArray(other.begin(), other.end(), a) {}
+
+  FixedArray(FixedArray&& other, const allocator_type& a = allocator_type())
+      : FixedArray(std::make_move_iterator(other.begin()),
+                   std::make_move_iterator(other.end()),
+                   a) {}
+
+  // Creates an array object that can store `n` elements.
+  // Note that trivially constructible elements will be uninitialized.
+  explicit FixedArray(size_type n, const allocator_type& a = allocator_type())
+      : storage_(n, a) {
+    if (DefaultConstructorIsNonTrivial()) {
+      ConstructRange(storage_.alloc(), storage_.begin(), storage_.end());
+    }
+  }
+
+  // Creates an array initialized with `n` copies of `val`.
+  FixedArray(size_type n,
+             const value_type& val,
+             const allocator_type& a = allocator_type())
+      : storage_(n, a) {
+    ConstructRange(storage_.alloc(), storage_.begin(), storage_.end(), val);
+  }
+
+  // Creates an array initialized with the size and contents of `init_list`.
+  FixedArray(std::initializer_list<value_type> init_list,
+             const allocator_type& a = allocator_type())
+      : FixedArray(init_list.begin(), init_list.end(), a) {}
+
+  // Creates an array initialized with the elements from the input
+  // range. The array's size will always be `std::distance(first, last)`.
+  // REQUIRES: Iterator must be a forward_iterator or better.
+  template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr>
+  FixedArray(Iterator first,
+             Iterator last,
+             const allocator_type& a = allocator_type())
+      : storage_(std::distance(first, last), a) {
+    CopyRange(storage_.alloc(), storage_.begin(), first, last);
+  }
+
+  ~FixedArray() noexcept {
+    for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
+      AllocatorTraits::destroy(storage_.alloc(), cur);
+    }
+  }
+
+  // Assignments are deleted because they break the invariant that the size of a
+  // `FixedArray` never changes.
+  void operator=(FixedArray&&) = delete;
+  void operator=(const FixedArray&) = delete;
+
+  // FixedArray::size()
   //
-  // FixedArray<T> will not zero-initialize POD (simple) types like int,
-  // double, bool, etc.
-  // Non-POD types will be default-initialized just like regular vectors or
-  // arrays.
-  explicit FixedArray(size_type n);
+  // Returns the length of the fixed array.
+  size_type size() const { return storage_.size(); }
 
-  // Releases any resources.
-  ~FixedArray();
-
-  // Returns the length of the array.
-  inline size_type size() const { return size_; }
-
-  // Returns the memory size of the array in bytes.
-  inline size_t memsize() const { return size_ * sizeof(T); }
-
-  // Returns a pointer to the underlying element array.
-  inline const T* get() const { return &array_[0].element; }
-  inline T* get() { return &array_[0].element; }
-
-  // REQUIRES: 0 <= i < size()
-  // Returns a reference to the "i"th element.
-  inline T& operator[](size_type i) {
-    DCHECK_LT(i, size_);
-    return array_[i].element;
+  // FixedArray::max_size()
+  //
+  // Returns the largest possible value of `std::distance(begin(), end())` for a
+  // `FixedArray<T>`. This is equivalent to the most possible addressable bytes
+  // over the number of bytes taken by T.
+  constexpr size_type max_size() const {
+    return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
   }
 
+  // FixedArray::empty()
+  //
+  // Returns whether or not the fixed array is empty.
+  bool empty() const { return size() == 0; }
+
+  // FixedArray::memsize()
+  //
+  // Returns the memory size of the fixed array in bytes.
+  size_t memsize() const { return size() * sizeof(value_type); }
+
+  // FixedArray::data()
+  //
+  // Returns a const T* pointer to elements of the `FixedArray`. This pointer
+  // can be used to access (but not modify) the contained elements.
+  const_pointer data() const { return AsValueType(storage_.begin()); }
+
+  // Overload of FixedArray::data() to return a T* pointer to elements of the
+  // fixed array. This pointer can be used to access and modify the contained
+  // elements.
+  pointer data() { return AsValueType(storage_.begin()); }
+
+  // FixedArray::operator[]
+  //
+  // Returns a reference the ith element of the fixed array.
   // REQUIRES: 0 <= i < size()
-  // Returns a reference to the "i"th element.
-  inline const T& operator[](size_type i) const {
-    DCHECK_LT(i, size_);
-    return array_[i].element;
+  reference operator[](size_type i) {
+    DCHECK_LT(i, size());
+    return data()[i];
   }
 
-  inline iterator begin() { return &array_[0].element; }
-  inline iterator end() { return &array_[size_].element; }
+  // Overload of FixedArray::operator()[] to return a const reference to the
+  // ith element of the fixed array.
+  // REQUIRES: 0 <= i < size()
+  const_reference operator[](size_type i) const {
+    DCHECK_LT(i, size());
+    return data()[i];
+  }
 
-  inline const_iterator begin() const { return &array_[0].element; }
-  inline const_iterator end() const { return &array_[size_].element; }
+  // FixedArray::front()
+  //
+  // Returns a reference to the first element of the fixed array.
+  reference front() { return *begin(); }
+
+  // Overload of FixedArray::front() to return a reference to the first element
+  // of a fixed array of const values.
+  const_reference front() const { return *begin(); }
+
+  // FixedArray::back()
+  //
+  // Returns a reference to the last element of the fixed array.
+  reference back() { return *(end() - 1); }
+
+  // Overload of FixedArray::back() to return a reference to the last element
+  // of a fixed array of const values.
+  const_reference back() const { return *(end() - 1); }
+
+  // FixedArray::begin()
+  //
+  // Returns an iterator to the beginning of the fixed array.
+  iterator begin() { return data(); }
+
+  // Overload of FixedArray::begin() to return a const iterator to the
+  // beginning of the fixed array.
+  const_iterator begin() const { return data(); }
+
+  // FixedArray::cbegin()
+  //
+  // Returns a const iterator to the beginning of the fixed array.
+  const_iterator cbegin() const { return begin(); }
+
+  // FixedArray::end()
+  //
+  // Returns an iterator to the end of the fixed array.
+  iterator end() { return data() + size(); }
+
+  // Overload of FixedArray::end() to return a const iterator to the end of the
+  // fixed array.
+  const_iterator end() const { return data() + size(); }
+
+  // FixedArray::cend()
+  //
+  // Returns a const iterator to the end of the fixed array.
+  const_iterator cend() const { return end(); }
+
+  // FixedArray::rbegin()
+  //
+  // Returns a reverse iterator from the end of the fixed array.
+  reverse_iterator rbegin() { return reverse_iterator(end()); }
+
+  // Overload of FixedArray::rbegin() to return a const reverse iterator from
+  // the end of the fixed array.
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end());
+  }
+
+  // FixedArray::crbegin()
+  //
+  // Returns a const reverse iterator from the end of the fixed array.
+  const_reverse_iterator crbegin() const { return rbegin(); }
+
+  // FixedArray::rend()
+  //
+  // Returns a reverse iterator from the beginning of the fixed array.
+  reverse_iterator rend() { return reverse_iterator(begin()); }
+
+  // Overload of FixedArray::rend() for returning a const reverse iterator
+  // from the beginning of the fixed array.
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(begin());
+  }
+
+  // FixedArray::crend()
+  //
+  // Returns a reverse iterator from the beginning of the fixed array.
+  const_reverse_iterator crend() const { return rend(); }
+
+  // FixedArray::fill()
+  //
+  // Assigns the given `value` to all elements in the fixed array.
+  void fill(const value_type& val) { std::fill(begin(), end(), val); }
+
+  // Relational operators. Equality operators are elementwise using
+  // `operator==`, while order operators order FixedArrays lexicographically.
+  friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
+    return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+  }
+
+  friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
+    return !(lhs == rhs);
+  }
+
+  friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) {
+    return std::lexicographical_compare(
+        lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+  }
+
+  friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) {
+    return rhs < lhs;
+  }
+
+  friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) {
+    return !(rhs < lhs);
+  }
+
+  friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {
+    return !(lhs < rhs);
+  }
 
  private:
-  // Container to hold elements of type T.  This is necessary to handle
-  // the case where T is a (C-style) array.  The size of InnerContainer
-  // and T must be the same, otherwise callers' assumptions about use
-  // of this code will be broken.
-  struct InnerContainer {
-    T element;
+  // StorageElement
+  //
+  // For FixedArrays with a C-style-array value_type, StorageElement is a POD
+  // wrapper struct called StorageElementWrapper that holds the value_type
+  // instance inside. This is needed for construction and destruction of the
+  // entire array regardless of how many dimensions it has. For all other cases,
+  // StorageElement is just an alias of value_type.
+  //
+  // Maintainer's Note: The simpler solution would be to simply wrap value_type
+  // in a struct whether it's an array or not. That causes some paranoid
+  // diagnostics to misfire, believing that 'data()' returns a pointer to a
+  // single element, rather than the packed array that it really is.
+  // e.g.:
+  //
+  //     FixedArray<char> buf(1);
+  //     sprintf(buf.data(), "foo");
+  //
+  //     error: call to int __builtin___sprintf_chk(etc...)
+  //     will always overflow destination buffer [-Werror]
+  //
+  template <typename OuterT,
+            typename InnerT = typename std::remove_extent<OuterT>::type,
+            size_t InnerN = std::extent<OuterT>::value>
+  struct StorageElementWrapper {
+    InnerT array[InnerN];
   };
 
-  // How many elements should we store inline?
-  //   a. If not specified, use a default of 256 bytes (256 bytes
-  //      seems small enough to not cause stack overflow or unnecessary
-  //      stack pollution, while still allowing stack allocation for
-  //      reasonably long character arrays.
-  //   b. Never use 0 length arrays (not ISO C++)
-  static const size_type S1 = ((inline_elements < 0)
-                               ? (256/sizeof(T)) : inline_elements);
-  static const size_type S2 = (S1 <= 0) ? 1 : S1;
-  static const size_type kInlineElements = S2;
+  using StorageElement =
+      typename std::conditional<std::is_array<value_type>::value,
+                                StorageElementWrapper<value_type>,
+                                value_type>::type;
 
-  size_type const       size_;
-  InnerContainer* const array_;
+  static pointer AsValueType(pointer ptr) { return ptr; }
+  static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
+    return std::addressof(ptr->array);
+  }
 
-  // Allocate some space, not an array of elements of type T, so that we can
-  // skip calling the T constructors and destructors for space we never use.
-  ManualConstructor<InnerContainer> inline_space_[kInlineElements];
+  static_assert(sizeof(StorageElement) == sizeof(value_type), "");
+  static_assert(alignof(StorageElement) == alignof(value_type), "");
+
+  class NonEmptyInlinedStorage {
+   public:
+    StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
+    void AnnotateConstruct(size_type) {}
+    void AnnotateDestruct(size_type) {}
+
+    // #ifdef ADDRESS_SANITIZER
+    //     void* RedzoneBegin() { return &redzone_begin_; }
+    //     void* RedzoneEnd() { return &redzone_end_ + 1; }
+    // #endif  // ADDRESS_SANITIZER
+
+   private:
+    // ADDRESS_SANITIZER_REDZONE(redzone_begin_);
+    alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
+    // ADDRESS_SANITIZER_REDZONE(redzone_end_);
+  };
+
+  class EmptyInlinedStorage {
+   public:
+    StorageElement* data() { return nullptr; }
+    void AnnotateConstruct(size_type) {}
+    void AnnotateDestruct(size_type) {}
+  };
+
+  using InlinedStorage =
+      typename std::conditional<inline_elements == 0,
+                                EmptyInlinedStorage,
+                                NonEmptyInlinedStorage>::type;
+
+  // Storage
+  //
+  // An instance of Storage manages the inline and out-of-line memory for
+  // instances of FixedArray. This guarantees that even when construction of
+  // individual elements fails in the FixedArray constructor body, the
+  // destructor for Storage will still be called and out-of-line memory will be
+  // properly deallocated.
+  //
+  class Storage : public InlinedStorage {
+   public:
+    Storage(size_type n, const allocator_type& a)
+        : size_alloc_(n, a), data_(InitializeData()) {}
+
+    ~Storage() noexcept {
+      if (UsingInlinedStorage(size())) {
+        InlinedStorage::AnnotateDestruct(size());
+      } else {
+        AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size());
+      }
+    }
+
+    size_type size() const { return std::get<0>(size_alloc_); }
+    StorageElement* begin() const { return data_; }
+    StorageElement* end() const { return begin() + size(); }
+    allocator_type& alloc() { return std::get<1>(size_alloc_); }
+
+   private:
+    static bool UsingInlinedStorage(size_type n) {
+      return n <= inline_elements;
+    }
+
+    StorageElement* InitializeData() {
+      if (UsingInlinedStorage(size())) {
+        InlinedStorage::AnnotateConstruct(size());
+        return InlinedStorage::data();
+      } else {
+        return reinterpret_cast<StorageElement*>(
+            AllocatorTraits::allocate(alloc(), size()));
+      }
+    }
+
+    // Using std::tuple and not absl::CompressedTuple, as it has a lot of
+    // dependencies to other absl headers.
+    std::tuple<size_type, allocator_type> size_alloc_;
+    StorageElement* data_;
+  };
+
+  Storage storage_;
 };
 
-// Implementation details follow
+template <typename T, size_t N, typename A>
+constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
 
-template <class T, ssize_t S>
-inline FixedArray<T, S>::FixedArray(typename FixedArray<T, S>::size_type n)
-    : size_(n),
-      array_((n <= kInlineElements
-              ? reinterpret_cast<InnerContainer*>(inline_space_)
-              : new InnerContainer[n])) {
-  // Construct only the elements actually used.
-  if (array_ == reinterpret_cast<InnerContainer*>(inline_space_)) {
-    for (size_t i = 0; i != size_; ++i) {
-      inline_space_[i].Init();
-    }
-  }
-}
-
-template <class T, ssize_t S>
-inline FixedArray<T, S>::~FixedArray() {
-  if (array_ != reinterpret_cast<InnerContainer*>(inline_space_)) {
-    delete[] array_;
-  } else {
-    for (size_t i = 0; i != size_; ++i) {
-      inline_space_[i].Destroy();
-    }
-  }
-}
+template <typename T, size_t N, typename A>
+constexpr typename FixedArray<T, N, A>::size_type
+    FixedArray<T, N, A>::inline_elements;
 
 }  // namespace internal
 }  // namespace ceres
diff --git a/include/ceres/internal/householder_vector.h b/include/ceres/internal/householder_vector.h
new file mode 100644
index 0000000..55f68e5
--- /dev/null
+++ b/include/ceres/internal/householder_vector.h
@@ -0,0 +1,88 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2015 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// 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.
+//
+// Author: vitus@google.com (Michael Vitus)
+
+#ifndef CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
+#define CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
+
+#include "Eigen/Core"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+// Algorithm 5.1.1 from 'Matrix Computations' by Golub et al. (Johns Hopkins
+// Studies in Mathematical Sciences) but using the nth element of the input
+// vector as pivot instead of first. This computes the vector v with v(n) = 1
+// and beta such that H = I - beta * v * v^T is orthogonal and
+// H * x = ||x||_2 * e_n.
+//
+// NOTE: Some versions of MSVC have trouble deducing the type of v if
+// you do not specify all the template arguments explicitly.
+template <typename XVectorType, typename Scalar, int N>
+void ComputeHouseholderVector(const XVectorType& x,
+                              Eigen::Matrix<Scalar, N, 1>* v,
+                              Scalar* beta) {
+  CHECK(beta != nullptr);
+  CHECK(v != nullptr);
+  CHECK_GT(x.rows(), 1);
+  CHECK_EQ(x.rows(), v->rows());
+
+  Scalar sigma = x.head(x.rows() - 1).squaredNorm();
+  *v = x;
+  (*v)(v->rows() - 1) = Scalar(1.0);
+
+  *beta = Scalar(0.0);
+  const Scalar& x_pivot = x(x.rows() - 1);
+
+  if (sigma <= Scalar(std::numeric_limits<double>::epsilon())) {
+    if (x_pivot < Scalar(0.0)) {
+      *beta = Scalar(2.0);
+    }
+    return;
+  }
+
+  const Scalar mu = sqrt(x_pivot * x_pivot + sigma);
+  Scalar v_pivot = Scalar(1.0);
+
+  if (x_pivot <= Scalar(0.0)) {
+    v_pivot = x_pivot - mu;
+  } else {
+    v_pivot = -sigma / (x_pivot + mu);
+  }
+
+  *beta = Scalar(2.0) * v_pivot * v_pivot / (sigma + v_pivot * v_pivot);
+
+  v->head(v->rows() - 1) /= v_pivot;
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
diff --git a/include/ceres/internal/integer_sequence.h b/include/ceres/internal/integer_sequence.h
deleted file mode 100644
index 3936b92..0000000
--- a/include/ceres/internal/integer_sequence.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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.
-//
-// Author: jodebo_beck@gmx.de (Johannes Beck)
-//
-// This class mimics std::integer_sequence. That is the reason to follow the
-// naming convention of the stl and not the google one. Once Ceres switches
-// to c++ 14 this class can be removed.
-
-#ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_H_
-#define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_H_
-
-#if __cplusplus >= 201402L
-// We have at least c++ 14 support. Use integer_sequence from the standard.
-// Sometimes the STL implementation uses a compiler intrinsic to generate
-// the sequences which will speed up compilation.
-#include <utility>
-
-namespace ceres {
-namespace internal {
-template <typename T, T... Ns>
-using integer_sequence = std::integer_sequence<T, Ns...>;
-
-template <typename T, T N>
-using make_integer_sequence = std::make_integer_sequence<T, N>;
-
-}  // namespace internal
-}  // namespace ceres
-#else
-
-namespace ceres {
-namespace internal {
-
-template <typename T, T... Ns>
-struct integer_sequence {
-  using value_type = T;
-};
-
-// Implementation of make_integer_sequence.
-//
-// Recursively instantiate make_integer_sequence_impl until Ns
-// contains the sequence 0, 1, ..., Total-1.
-//
-// Example for Total = 4:
-//                            T    CurIdx, Total, Ns...
-// make_integer_sequence_impl<int, 0,      4                >
-// make_integer_sequence_impl<int, 1,      4,     0         >
-// make_integer_sequence_impl<int, 2,      4,     0, 1      >
-// make_integer_sequence_impl<int, 3,      4,     0, 1, 2   >
-// make_integer_sequence_impl<int, 4,      4,     0, 1, 2, 3>
-//                                                ^^^^^^^^^^
-//                                                resulting sequence.
-//
-// The implemented algorithm has linear complexity for simplicity. A O(log(N))
-// implementation can be found e.g. here:
-// https://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence
-template <typename T, T CurIdx, T Total, T... Ns>
-struct make_integer_sequence_impl {
-  using type = typename make_integer_sequence_impl<T, CurIdx + 1, Total, Ns...,
-                                                   CurIdx>::type;
-};
-
-// End of 'recursion' when CurIdx reaches Total. All indices 0, 1, ..., N-1 are
-// contained in Ns. The final integer_sequence is created here.
-template <typename T, T Total, T... Ns>
-struct make_integer_sequence_impl<T, Total, Total, Ns...> {
-  using type = integer_sequence<T, Ns...>;
-};
-
-// A helper alias template to simplify creation of integer_sequence with 0, 1,
-// ..., N-1 as Ns:
-template <typename T, T N>
-using make_integer_sequence =
-    typename make_integer_sequence_impl<T, 0, N>::type;
-
-}  // namespace internal
-}  // namespace ceres
-
-#endif
-
-#endif  // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_H_
diff --git a/include/ceres/internal/integer_sequence_algorithm.h b/include/ceres/internal/integer_sequence_algorithm.h
index bdeab93..8c0f3bc 100644
--- a/include/ceres/internal/integer_sequence_algorithm.h
+++ b/include/ceres/internal/integer_sequence_algorithm.h
@@ -35,7 +35,7 @@
 #ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
 #define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
 
-#include "integer_sequence.h"
+#include <utility>
 
 namespace ceres {
 namespace internal {
@@ -61,33 +61,34 @@
 
 // Strip of and sum the first number.
 template <typename T, T N, T... Ns>
-struct SumImpl<integer_sequence<T, N, Ns...>> {
-  static constexpr T Value = N + SumImpl<integer_sequence<T, Ns...>>::Value;
+struct SumImpl<std::integer_sequence<T, N, Ns...>> {
+  static constexpr T Value =
+      N + SumImpl<std::integer_sequence<T, Ns...>>::Value;
 };
 
 // Strip of and sum the first two numbers.
 template <typename T, T N1, T N2, T... Ns>
-struct SumImpl<integer_sequence<T, N1, N2, Ns...>> {
+struct SumImpl<std::integer_sequence<T, N1, N2, Ns...>> {
   static constexpr T Value =
-      N1 + N2 + SumImpl<integer_sequence<T, Ns...>>::Value;
+      N1 + N2 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
 };
 
 // Strip of and sum the first four numbers.
 template <typename T, T N1, T N2, T N3, T N4, T... Ns>
-struct SumImpl<integer_sequence<T, N1, N2, N3, N4, Ns...>> {
+struct SumImpl<std::integer_sequence<T, N1, N2, N3, N4, Ns...>> {
   static constexpr T Value =
-      N1 + N2 + N3 + N4 + SumImpl<integer_sequence<T, Ns...>>::Value;
+      N1 + N2 + N3 + N4 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
 };
 
 // Only one number is left. 'Value' is just that number ('recursion' ends).
 template <typename T, T N>
-struct SumImpl<integer_sequence<T, N>> {
+struct SumImpl<std::integer_sequence<T, N>> {
   static constexpr T Value = N;
 };
 
 // No number is left. 'Value' is the identity element (for sum this is zero).
 template <typename T>
-struct SumImpl<integer_sequence<T>> {
+struct SumImpl<std::integer_sequence<T>> {
   static constexpr T Value = T(0);
 };
 
@@ -129,16 +130,20 @@
 struct ExclusiveScanImpl;
 
 template <typename T, T Sum, T N, T... Ns, T... Rs>
-struct ExclusiveScanImpl<T, Sum, integer_sequence<T, N, Ns...>,
-                         integer_sequence<T, Rs...>> {
+struct ExclusiveScanImpl<T,
+                         Sum,
+                         std::integer_sequence<T, N, Ns...>,
+                         std::integer_sequence<T, Rs...>> {
   using Type =
-      typename ExclusiveScanImpl<T, Sum + N, integer_sequence<T, Ns...>,
-                                 integer_sequence<T, Rs..., Sum>>::Type;
+      typename ExclusiveScanImpl<T,
+                                 Sum + N,
+                                 std::integer_sequence<T, Ns...>,
+                                 std::integer_sequence<T, Rs..., Sum>>::Type;
 };
 
 // End of 'recursion'. The resulting type is SeqOut.
 template <typename T, T Sum, typename SeqOut>
-struct ExclusiveScanImpl<T, Sum, integer_sequence<T>, SeqOut> {
+struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T>, SeqOut> {
   using Type = SeqOut;
 };
 
@@ -152,7 +157,7 @@
 
  public:
   using Type =
-      typename ExclusiveScanImpl<T, T(0), Seq, integer_sequence<T>>::Type;
+      typename ExclusiveScanImpl<T, T(0), Seq, std::integer_sequence<T>>::Type;
 };
 
 // Helper to use exclusive scan without typename.
diff --git a/include/ceres/internal/line_parameterization.h b/include/ceres/internal/line_parameterization.h
new file mode 100644
index 0000000..eda3901
--- /dev/null
+++ b/include/ceres/internal/line_parameterization.h
@@ -0,0 +1,183 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2020 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.
+//
+// Author: jodebo_beck@gmx.de (Johannes Beck)
+//
+
+#ifndef CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
+#define CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
+
+#include "householder_vector.h"
+
+namespace ceres {
+
+template <int AmbientSpaceDimension>
+bool LineParameterization<AmbientSpaceDimension>::Plus(
+    const double* x_ptr,
+    const double* delta_ptr,
+    double* x_plus_delta_ptr) const {
+  // We seek a box plus operator of the form
+  //
+  //   [o*, d*] = Plus([o, d], [delta_o, delta_d])
+  //
+  // where o is the origin point, d is the direction vector, delta_o is
+  // the delta of the origin point and delta_d the delta of the direction and
+  // o* and d* is the updated origin point and direction.
+  //
+  // We separate the Plus operator into the origin point and directional part
+  //   d* = Plus_d(d, delta_d)
+  //   o* = Plus_o(o, d, delta_o)
+  //
+  // The direction update function Plus_d is the same as for the homogeneous
+  // vector parameterization:
+  //
+  //   d* = H_{v(d)} [0.5 sinc(0.5 |delta_d|) delta_d, cos(0.5 |delta_d|)]^T
+  //
+  // where H is the householder matrix
+  //   H_{v} = I - (2 / |v|^2) v v^T
+  // and
+  //   v(d) = d - sign(d_n) |d| e_n.
+  //
+  // The origin point update function Plus_o is defined as
+  //
+  //   o* = o + H_{v(d)} [0.5 delta_o, 0]^T.
+
+  static constexpr int kDim = AmbientSpaceDimension;
+  using AmbientVector = Eigen::Matrix<double, kDim, 1>;
+  using AmbientVectorRef = Eigen::Map<Eigen::Matrix<double, kDim, 1>>;
+  using ConstAmbientVectorRef =
+      Eigen::Map<const Eigen::Matrix<double, kDim, 1>>;
+  using ConstTangentVectorRef =
+      Eigen::Map<const Eigen::Matrix<double, kDim - 1, 1>>;
+
+  ConstAmbientVectorRef o(x_ptr);
+  ConstAmbientVectorRef d(x_ptr + kDim);
+
+  ConstTangentVectorRef delta_o(delta_ptr);
+  ConstTangentVectorRef delta_d(delta_ptr + kDim - 1);
+  AmbientVectorRef o_plus_delta(x_plus_delta_ptr);
+  AmbientVectorRef d_plus_delta(x_plus_delta_ptr + kDim);
+
+  const double norm_delta_d = delta_d.norm();
+
+  o_plus_delta = o;
+
+  // Shortcut for zero delta direction.
+  if (norm_delta_d == 0.0) {
+    d_plus_delta = d;
+
+    if (delta_o.isZero(0.0)) {
+      return true;
+    }
+  }
+
+  // Calculate the householder transformation which is needed for f_d and f_o.
+  AmbientVector v;
+  double beta;
+
+  // NOTE: The explicit template arguments are needed here because
+  // ComputeHouseholderVector is templated and some versions of MSVC
+  // have trouble deducing the type of v automatically.
+  internal::ComputeHouseholderVector<ConstAmbientVectorRef, double, kDim>(
+      d, &v, &beta);
+
+  if (norm_delta_d != 0.0) {
+    // Map the delta from the minimum representation to the over parameterized
+    // homogeneous vector. See section A6.9.2 on page 624 of Hartley & Zisserman
+    // (2nd Edition) for a detailed description.  Note there is a typo on Page
+    // 625, line 4 so check the book errata.
+    const double norm_delta_div_2 = 0.5 * norm_delta_d;
+    const double sin_delta_by_delta =
+        std::sin(norm_delta_div_2) / norm_delta_div_2;
+
+    // Apply the delta update to remain on the unit sphere. See section A6.9.3
+    // on page 625 of Hartley & Zisserman (2nd Edition) for a detailed
+    // description.
+    AmbientVector y;
+    y.template head<kDim - 1>() = 0.5 * sin_delta_by_delta * delta_d;
+    y[kDim - 1] = std::cos(norm_delta_div_2);
+
+    d_plus_delta = d.norm() * (y - v * (beta * (v.transpose() * y)));
+  }
+
+  // The null space is in the direction of the line, so the tangent space is
+  // perpendicular to the line direction. This is achieved by using the
+  // householder matrix of the direction and allow only movements
+  // perpendicular to e_n.
+  //
+  // The factor of 0.5 is used to be consistent with the line direction
+  // update.
+  AmbientVector y;
+  y << 0.5 * delta_o, 0;
+  o_plus_delta += y - v * (beta * (v.transpose() * y));
+
+  return true;
+}
+
+template <int AmbientSpaceDimension>
+bool LineParameterization<AmbientSpaceDimension>::ComputeJacobian(
+    const double* x_ptr, double* jacobian_ptr) const {
+  static constexpr int kDim = AmbientSpaceDimension;
+  using AmbientVector = Eigen::Matrix<double, kDim, 1>;
+  using ConstAmbientVectorRef =
+      Eigen::Map<const Eigen::Matrix<double, kDim, 1>>;
+  using MatrixRef = Eigen::Map<
+      Eigen::Matrix<double, 2 * kDim, 2 * (kDim - 1), Eigen::RowMajor>>;
+
+  ConstAmbientVectorRef d(x_ptr + kDim);
+  MatrixRef jacobian(jacobian_ptr);
+
+  // Clear the Jacobian as only half of the matrix is not zero.
+  jacobian.setZero();
+
+  AmbientVector v;
+  double beta;
+
+  // NOTE: The explicit template arguments are needed here because
+  // ComputeHouseholderVector is templated and some versions of MSVC
+  // have trouble deducing the type of v automatically.
+  internal::ComputeHouseholderVector<ConstAmbientVectorRef, double, kDim>(
+      d, &v, &beta);
+
+  // The Jacobian is equal to J = 0.5 * H.leftCols(kDim - 1) where H is
+  // the Householder matrix (H = I - beta * v * v') for the origin point. For
+  // the line direction part the Jacobian is scaled by the norm of the
+  // direction.
+  for (int i = 0; i < kDim - 1; ++i) {
+    jacobian.block(0, i, kDim, 1) = -0.5 * beta * v(i) * v;
+    jacobian.col(i)(i) += 0.5;
+  }
+
+  jacobian.template block<kDim, kDim - 1>(kDim, kDim - 1) =
+      jacobian.template block<kDim, kDim - 1>(0, 0) * d.norm();
+  return true;
+}
+
+}  // namespace ceres
+
+#endif  // CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
diff --git a/include/ceres/internal/manual_constructor.h b/include/ceres/internal/manual_constructor.h
deleted file mode 100644
index 60f147a..0000000
--- a/include/ceres/internal/manual_constructor.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2015 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.
-//
-// Author: kenton@google.com (Kenton Varda)
-//
-// ManualConstructor statically-allocates space in which to store some
-// object, but does not initialize it.  You can then call the constructor
-// and destructor for the object yourself as you see fit.  This is useful
-// for memory management optimizations, where you want to initialize and
-// destroy an object multiple times but only allocate it once.
-//
-// (When I say ManualConstructor statically allocates space, I mean that
-// the ManualConstructor object itself is forced to be the right size.)
-
-#ifndef CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
-#define CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
-
-#include <new>
-#include <utility>
-
-namespace ceres {
-namespace internal {
-
-// ------- Define CERES_ALIGNED_CHAR_ARRAY --------------------------------
-
-// Platform independent macros to get aligned memory allocations.
-// For example
-//
-//   MyFoo my_foo CERES_ALIGN_ATTRIBUTE(16);
-//
-// Gives us an instance of MyFoo which is aligned at a 16 byte
-// boundary.
-#if defined(_MSC_VER)
-#define CERES_ALIGN_ATTRIBUTE(n) __declspec(align(n))
-#define CERES_ALIGN_OF(T) __alignof(T)
-#elif defined(__GNUC__)
-#define CERES_ALIGN_ATTRIBUTE(n) __attribute__((aligned(n)))
-#define CERES_ALIGN_OF(T) __alignof(T)
-#endif
-
-#ifndef CERES_ALIGNED_CHAR_ARRAY
-
-// Because MSVC and older GCCs require that the argument to their alignment
-// construct to be a literal constant integer, we use a template instantiated
-// at all the possible powers of two.
-template<int alignment, int size> struct AlignType { };
-template<int size> struct AlignType<0, size> { typedef char result[size]; };
-
-#if !defined(CERES_ALIGN_ATTRIBUTE)
-#define CERES_ALIGNED_CHAR_ARRAY you_must_define_CERES_ALIGNED_CHAR_ARRAY_for_your_compiler
-#else  // !defined(CERES_ALIGN_ATTRIBUTE)
-
-#define CERES_ALIGN_TYPE_TEMPLATE(X) \
-  template<int size> struct AlignType<X, size> { \
-    typedef CERES_ALIGN_ATTRIBUTE(X) char result[size]; \
-  }
-
-CERES_ALIGN_TYPE_TEMPLATE(1);
-CERES_ALIGN_TYPE_TEMPLATE(2);
-CERES_ALIGN_TYPE_TEMPLATE(4);
-CERES_ALIGN_TYPE_TEMPLATE(8);
-CERES_ALIGN_TYPE_TEMPLATE(16);
-CERES_ALIGN_TYPE_TEMPLATE(32);
-CERES_ALIGN_TYPE_TEMPLATE(64);
-CERES_ALIGN_TYPE_TEMPLATE(128);
-CERES_ALIGN_TYPE_TEMPLATE(256);
-CERES_ALIGN_TYPE_TEMPLATE(512);
-CERES_ALIGN_TYPE_TEMPLATE(1024);
-CERES_ALIGN_TYPE_TEMPLATE(2048);
-CERES_ALIGN_TYPE_TEMPLATE(4096);
-CERES_ALIGN_TYPE_TEMPLATE(8192);
-// Any larger and MSVC++ will complain.
-
-#undef CERES_ALIGN_TYPE_TEMPLATE
-
-#define CERES_ALIGNED_CHAR_ARRAY(T, Size) \
-  typename AlignType<CERES_ALIGN_OF(T), sizeof(T) * Size>::result
-
-#endif  // !defined(CERES_ALIGN_ATTRIBUTE)
-
-#endif  // CERES_ALIGNED_CHAR_ARRAY
-
-template <typename Type>
-class ManualConstructor {
- public:
-  // No constructor or destructor because one of the most useful uses of
-  // this class is as part of a union, and members of a union cannot have
-  // constructors or destructors.  And, anyway, the whole point of this
-  // class is to bypass these.
-
-  inline Type* get() {
-    return reinterpret_cast<Type*>(space_);
-  }
-  inline const Type* get() const  {
-    return reinterpret_cast<const Type*>(space_);
-  }
-
-  inline Type* operator->() { return get(); }
-  inline const Type* operator->() const { return get(); }
-
-  inline Type& operator*() { return *get(); }
-  inline const Type& operator*() const { return *get(); }
-
-  // This is needed to get around the strict aliasing warning GCC generates.
-  inline void* space() {
-    return reinterpret_cast<void*>(space_);
-  }
-
-  template <typename... Ts>
-  inline void Init(Ts&&... ps) {
-    new(space()) Type(std::forward<Ts>(ps)...);
-  }
-
-  inline void Destroy() {
-    get()->~Type();
-  }
-
- private:
-  CERES_ALIGNED_CHAR_ARRAY(Type, 1) space_;
-};
-
-#undef CERES_ALIGNED_CHAR_ARRAY
-
-}  // namespace internal
-}  // namespace ceres
-
-#endif  // CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
diff --git a/include/ceres/internal/memory.h b/include/ceres/internal/memory.h
new file mode 100644
index 0000000..45c5b67
--- /dev/null
+++ b/include/ceres/internal/memory.h
@@ -0,0 +1,90 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: memory.h
+// -----------------------------------------------------------------------------
+//
+// This header file contains utility functions for managing the creation and
+// conversion of smart pointers. This file is an extension to the C++
+// standard <memory> library header file.
+
+#ifndef CERES_PUBLIC_INTERNAL_MEMORY_H_
+#define CERES_PUBLIC_INTERNAL_MEMORY_H_
+
+#include <memory>
+
+#ifdef CERES_HAVE_EXCEPTIONS
+#define CERES_INTERNAL_TRY try
+#define CERES_INTERNAL_CATCH_ANY catch (...)
+#define CERES_INTERNAL_RETHROW \
+  do {                         \
+    throw;                     \
+  } while (false)
+#else  // CERES_HAVE_EXCEPTIONS
+#define CERES_INTERNAL_TRY if (true)
+#define CERES_INTERNAL_CATCH_ANY else if (false)
+#define CERES_INTERNAL_RETHROW \
+  do {                         \
+  } while (false)
+#endif  // CERES_HAVE_EXCEPTIONS
+
+namespace ceres {
+namespace internal {
+
+template <typename Allocator, typename Iterator, typename... Args>
+void ConstructRange(Allocator& alloc,
+                    Iterator first,
+                    Iterator last,
+                    const Args&... args) {
+  for (Iterator cur = first; cur != last; ++cur) {
+    CERES_INTERNAL_TRY {
+      std::allocator_traits<Allocator>::construct(
+          alloc, std::addressof(*cur), args...);
+    }
+    CERES_INTERNAL_CATCH_ANY {
+      while (cur != first) {
+        --cur;
+        std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
+      }
+      CERES_INTERNAL_RETHROW;
+    }
+  }
+}
+
+template <typename Allocator, typename Iterator, typename InputIterator>
+void CopyRange(Allocator& alloc,
+               Iterator destination,
+               InputIterator first,
+               InputIterator last) {
+  for (Iterator cur = destination; first != last;
+       static_cast<void>(++cur), static_cast<void>(++first)) {
+    CERES_INTERNAL_TRY {
+      std::allocator_traits<Allocator>::construct(
+          alloc, std::addressof(*cur), *first);
+    }
+    CERES_INTERNAL_CATCH_ANY {
+      while (cur != destination) {
+        --cur;
+        std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
+      }
+      CERES_INTERNAL_RETHROW;
+    }
+  }
+}
+
+}  // namespace internal
+}  // namespace ceres
+
+#endif  // CERES_PUBLIC_INTERNAL_MEMORY_H_
diff --git a/include/ceres/internal/numeric_diff.h b/include/ceres/internal/numeric_diff.h
index 8851bc7..ff7a2c3 100644
--- a/include/ceres/internal/numeric_diff.h
+++ b/include/ceres/internal/numeric_diff.h
@@ -36,6 +36,7 @@
 #define CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
 
 #include <cstring>
+#include <utility>
 
 #include "Eigen/Dense"
 #include "Eigen/StdVector"
@@ -46,15 +47,17 @@
 #include "ceres/types.h"
 #include "glog/logging.h"
 
-
 namespace ceres {
 namespace internal {
 
 // This is split from the main class because C++ doesn't allow partial template
 // specializations for member functions. The alternative is to repeat the main
 // class for differing numbers of parameters, which is also unfortunate.
-template <typename CostFunctor, NumericDiffMethodType kMethod,
-          int kNumResiduals, typename ParameterDims, int kParameterBlock,
+template <typename CostFunctor,
+          NumericDiffMethodType kMethod,
+          int kNumResiduals,
+          typename ParameterDims,
+          int kParameterBlock,
           int kParameterBlockSize>
 struct NumericDiff {
   // Mutates parameters but must restore them before return.
@@ -65,23 +68,23 @@
       int num_residuals,
       int parameter_block_index,
       int parameter_block_size,
-      double **parameters,
-      double *jacobian) {
+      double** parameters,
+      double* jacobian) {
+    using Eigen::ColMajor;
     using Eigen::Map;
     using Eigen::Matrix;
     using Eigen::RowMajor;
-    using Eigen::ColMajor;
 
     DCHECK(jacobian);
 
     const int num_residuals_internal =
         (kNumResiduals != ceres::DYNAMIC ? kNumResiduals : num_residuals);
     const int parameter_block_index_internal =
-        (kParameterBlock != ceres::DYNAMIC ? kParameterBlock :
-                                             parameter_block_index);
+        (kParameterBlock != ceres::DYNAMIC ? kParameterBlock
+                                           : parameter_block_index);
     const int parameter_block_size_internal =
-        (kParameterBlockSize != ceres::DYNAMIC ? kParameterBlockSize :
-                                                 parameter_block_size);
+        (kParameterBlockSize != ceres::DYNAMIC ? kParameterBlockSize
+                                               : parameter_block_size);
 
     typedef Matrix<double, kNumResiduals, 1> ResidualVector;
     typedef Matrix<double, kParameterBlockSize, 1> ParameterVector;
@@ -96,17 +99,17 @@
                    (kParameterBlockSize == 1) ? ColMajor : RowMajor>
         JacobianMatrix;
 
-    Map<JacobianMatrix> parameter_jacobian(jacobian,
-                                           num_residuals_internal,
-                                           parameter_block_size_internal);
+    Map<JacobianMatrix> parameter_jacobian(
+        jacobian, num_residuals_internal, parameter_block_size_internal);
 
     Map<ParameterVector> x_plus_delta(
         parameters[parameter_block_index_internal],
         parameter_block_size_internal);
     ParameterVector x(x_plus_delta);
-    ParameterVector step_size = x.array().abs() *
-        ((kMethod == RIDDERS) ? options.ridders_relative_initial_step_size :
-        options.relative_step_size);
+    ParameterVector step_size =
+        x.array().abs() * ((kMethod == RIDDERS)
+                               ? options.ridders_relative_initial_step_size
+                               : options.relative_step_size);
 
     // It is not a good idea to make the step size arbitrarily
     // small. This will lead to problems with round off and numerical
@@ -117,22 +120,24 @@
     // For Ridders' method, the initial step size is required to be large,
     // thus ridders_relative_initial_step_size is used.
     if (kMethod == RIDDERS) {
-      min_step_size = std::max(min_step_size,
-                               options.ridders_relative_initial_step_size);
+      min_step_size =
+          std::max(min_step_size, options.ridders_relative_initial_step_size);
     }
 
     // For each parameter in the parameter block, use finite differences to
     // compute the derivative for that parameter.
     FixedArray<double> temp_residual_array(num_residuals_internal);
     FixedArray<double> residual_array(num_residuals_internal);
-    Map<ResidualVector> residuals(residual_array.get(),
+    Map<ResidualVector> residuals(residual_array.data(),
                                   num_residuals_internal);
 
     for (int j = 0; j < parameter_block_size_internal; ++j) {
       const double delta = std::max(min_step_size, step_size(j));
 
       if (kMethod == RIDDERS) {
-        if (!EvaluateRiddersJacobianColumn(functor, j, delta,
+        if (!EvaluateRiddersJacobianColumn(functor,
+                                           j,
+                                           delta,
                                            options,
                                            num_residuals_internal,
                                            parameter_block_size_internal,
@@ -140,20 +145,22 @@
                                            residuals_at_eval_point,
                                            parameters,
                                            x_plus_delta.data(),
-                                           temp_residual_array.get(),
-                                           residual_array.get())) {
+                                           temp_residual_array.data(),
+                                           residual_array.data())) {
           return false;
         }
       } else {
-        if (!EvaluateJacobianColumn(functor, j, delta,
+        if (!EvaluateJacobianColumn(functor,
+                                    j,
+                                    delta,
                                     num_residuals_internal,
                                     parameter_block_size_internal,
                                     x.data(),
                                     residuals_at_eval_point,
                                     parameters,
                                     x_plus_delta.data(),
-                                    temp_residual_array.get(),
-                                    residual_array.get())) {
+                                    temp_residual_array.data(),
+                                    residual_array.data())) {
           return false;
         }
       }
@@ -181,8 +188,7 @@
     typedef Matrix<double, kParameterBlockSize, 1> ParameterVector;
 
     Map<const ParameterVector> x(x_ptr, parameter_block_size);
-    Map<ParameterVector> x_plus_delta(x_plus_delta_ptr,
-                                      parameter_block_size);
+    Map<ParameterVector> x_plus_delta(x_plus_delta_ptr, parameter_block_size);
 
     Map<ResidualVector> residuals(residuals_ptr, num_residuals);
     Map<ResidualVector> temp_residuals(temp_residuals_ptr, num_residuals);
@@ -190,9 +196,8 @@
     // Mutate 1 element at a time and then restore.
     x_plus_delta(parameter_index) = x(parameter_index) + delta;
 
-    if (!VariadicEvaluate<ParameterDims>(*functor,
-                                         parameters,
-                                         residuals.data())) {
+    if (!VariadicEvaluate<ParameterDims>(
+            *functor, parameters, residuals.data())) {
       return false;
     }
 
@@ -205,9 +210,8 @@
       // Compute the function on the other side of x(parameter_index).
       x_plus_delta(parameter_index) = x(parameter_index) - delta;
 
-      if (!VariadicEvaluate<ParameterDims>(*functor,
-                                           parameters,
-                                           temp_residuals.data())) {
+      if (!VariadicEvaluate<ParameterDims>(
+              *functor, parameters, temp_residuals.data())) {
         return false;
       }
 
@@ -216,8 +220,7 @@
     } else {
       // Forward difference only; reuse existing residuals evaluation.
       residuals -=
-          Map<const ResidualVector>(residuals_at_eval_point,
-                                    num_residuals);
+          Map<const ResidualVector>(residuals_at_eval_point, num_residuals);
     }
 
     // Restore x_plus_delta.
@@ -253,17 +256,17 @@
       double* x_plus_delta_ptr,
       double* temp_residuals_ptr,
       double* residuals_ptr) {
+    using Eigen::aligned_allocator;
     using Eigen::Map;
     using Eigen::Matrix;
-    using Eigen::aligned_allocator;
 
     typedef Matrix<double, kNumResiduals, 1> ResidualVector;
-    typedef Matrix<double, kNumResiduals, Eigen::Dynamic> ResidualCandidateMatrix;
+    typedef Matrix<double, kNumResiduals, Eigen::Dynamic>
+        ResidualCandidateMatrix;
     typedef Matrix<double, kParameterBlockSize, 1> ParameterVector;
 
     Map<const ParameterVector> x(x_ptr, parameter_block_size);
-    Map<ParameterVector> x_plus_delta(x_plus_delta_ptr,
-                                      parameter_block_size);
+    Map<ParameterVector> x_plus_delta(x_plus_delta_ptr, parameter_block_size);
 
     Map<ResidualVector> residuals(residuals_ptr, num_residuals);
     Map<ResidualVector> temp_residuals(temp_residuals_ptr, num_residuals);
@@ -274,18 +277,16 @@
     // As the derivative is estimated, the step size decreases.
     // By default, the step sizes are chosen so that the middle column
     // of the Romberg tableau uses the input delta.
-    double current_step_size = delta *
-        pow(options.ridders_step_shrink_factor,
-            options.max_num_ridders_extrapolations / 2);
+    double current_step_size =
+        delta * pow(options.ridders_step_shrink_factor,
+                    options.max_num_ridders_extrapolations / 2);
 
     // Double-buffering temporary differential candidate vectors
     // from previous step size.
     ResidualCandidateMatrix stepsize_candidates_a(
-        num_residuals,
-        options.max_num_ridders_extrapolations);
+        num_residuals, options.max_num_ridders_extrapolations);
     ResidualCandidateMatrix stepsize_candidates_b(
-        num_residuals,
-        options.max_num_ridders_extrapolations);
+        num_residuals, options.max_num_ridders_extrapolations);
     ResidualCandidateMatrix* current_candidates = &stepsize_candidates_a;
     ResidualCandidateMatrix* previous_candidates = &stepsize_candidates_b;
 
@@ -303,7 +304,9 @@
     //  3. Extrapolation becomes numerically unstable.
     for (int i = 0; i < options.max_num_ridders_extrapolations; ++i) {
       // Compute the numerical derivative at this step size.
-      if (!EvaluateJacobianColumn(functor, parameter_index, current_step_size,
+      if (!EvaluateJacobianColumn(functor,
+                                  parameter_index,
+                                  current_step_size,
                                   num_residuals,
                                   parameter_block_size,
                                   x.data(),
@@ -326,23 +329,24 @@
 
       // Extrapolation factor for Richardson acceleration method (see below).
       double richardson_factor = options.ridders_step_shrink_factor *
-          options.ridders_step_shrink_factor;
+                                 options.ridders_step_shrink_factor;
       for (int k = 1; k <= i; ++k) {
         // Extrapolate the various orders of finite differences using
         // the Richardson acceleration method.
         current_candidates->col(k) =
             (richardson_factor * current_candidates->col(k - 1) -
-             previous_candidates->col(k - 1)) / (richardson_factor - 1.0);
+             previous_candidates->col(k - 1)) /
+            (richardson_factor - 1.0);
 
         richardson_factor *= options.ridders_step_shrink_factor *
-            options.ridders_step_shrink_factor;
+                             options.ridders_step_shrink_factor;
 
         // Compute the difference between the previous value and the current.
         double candidate_error = std::max(
-            (current_candidates->col(k) -
-             current_candidates->col(k - 1)).norm(),
-            (current_candidates->col(k) -
-             previous_candidates->col(k - 1)).norm());
+            (current_candidates->col(k) - current_candidates->col(k - 1))
+                .norm(),
+            (current_candidates->col(k) - previous_candidates->col(k - 1))
+                .norm());
 
         // If the error has decreased, update results.
         if (candidate_error <= norm_error) {
@@ -364,8 +368,9 @@
       // Check to see if the current gradient estimate is numerically unstable.
       // If so, bail out and return the last stable result.
       if (i > 0) {
-        double tableau_error = (current_candidates->col(i) -
-            previous_candidates->col(i - 1)).norm();
+        double tableau_error =
+            (current_candidates->col(i) - previous_candidates->col(i - 1))
+                .norm();
 
         // Compare current error to the chosen candidate's error.
         if (tableau_error >= 2 * norm_error) {
@@ -437,7 +442,7 @@
 
 template <typename ParameterDims, int N, int... Ns, int ParameterIdx>
 struct EvaluateJacobianForParameterBlocks<ParameterDims,
-                                          integer_sequence<int, N, Ns...>,
+                                          std::integer_sequence<int, N, Ns...>,
                                           ParameterIdx> {
   template <NumericDiffMethodType method,
             int kNumResiduals,
@@ -468,7 +473,7 @@
     }
 
     return EvaluateJacobianForParameterBlocks<ParameterDims,
-                                              integer_sequence<int, Ns...>,
+                                              std::integer_sequence<int, Ns...>,
                                               ParameterIdx + 1>::
         template Apply<method, kNumResiduals>(functor,
                                               residuals_at_eval_point,
@@ -481,14 +486,18 @@
 
 // End of 'recursion'. Nothing more to do.
 template <typename ParameterDims, int ParameterIdx>
-struct EvaluateJacobianForParameterBlocks<ParameterDims, integer_sequence<int>,
+struct EvaluateJacobianForParameterBlocks<ParameterDims,
+                                          std::integer_sequence<int>,
                                           ParameterIdx> {
-  template <NumericDiffMethodType method, int kNumResiduals,
+  template <NumericDiffMethodType method,
+            int kNumResiduals,
             typename CostFunctor>
   static bool Apply(const CostFunctor* /* NOT USED*/,
                     const double* /* NOT USED*/,
-                    const NumericDiffOptions& /* NOT USED*/, int /* NOT USED*/,
-                    double** /* NOT USED*/, double** /* NOT USED*/) {
+                    const NumericDiffOptions& /* NOT USED*/,
+                    int /* NOT USED*/,
+                    double** /* NOT USED*/,
+                    double** /* NOT USED*/) {
     return true;
   }
 };
diff --git a/include/ceres/internal/parameter_dims.h b/include/ceres/internal/parameter_dims.h
index 2272e8d..2402106 100644
--- a/include/ceres/internal/parameter_dims.h
+++ b/include/ceres/internal/parameter_dims.h
@@ -32,8 +32,8 @@
 #define CERES_PUBLIC_INTERNAL_PARAMETER_DIMS_H_
 
 #include <array>
+#include <utility>
 
-#include "ceres/internal/integer_sequence.h"
 #include "ceres/internal/integer_sequence_algorithm.h"
 
 namespace ceres {
@@ -41,16 +41,16 @@
 
 // Checks, whether the given parameter block sizes are valid. Valid means every
 // dimension is bigger than zero.
-constexpr bool IsValidParameterDimensionSequence(integer_sequence<int>) {
+constexpr bool IsValidParameterDimensionSequence(std::integer_sequence<int>) {
   return true;
 }
 
 template <int N, int... Ts>
 constexpr bool IsValidParameterDimensionSequence(
-    integer_sequence<int, N, Ts...>) {
+    std::integer_sequence<int, N, Ts...>) {
   return (N <= 0) ? false
                   : IsValidParameterDimensionSequence(
-                        integer_sequence<int, Ts...>());
+                        std::integer_sequence<int, Ts...>());
 }
 
 // Helper class that represents the parameter dimensions. The parameter
@@ -66,7 +66,7 @@
 template <bool IsDynamic, int... Ns>
 class ParameterDims {
  public:
-  using Parameters = integer_sequence<int, Ns...>;
+  using Parameters = std::integer_sequence<int, Ns...>;
 
   // The parameter dimensions are only valid if all parameter block dimensions
   // are greater than zero.
@@ -82,7 +82,7 @@
                 "At least one parameter block must be specified.");
 
   static constexpr int kNumParameters =
-      Sum<integer_sequence<int, Ns...>>::Value;
+      Sum<std::integer_sequence<int, Ns...>>::Value;
 
   static constexpr int GetDim(int dim) { return params_[dim]; }
 
@@ -98,7 +98,7 @@
  private:
   template <typename T, int... Indices>
   static inline std::array<T*, kNumParameterBlocks> GetUnpackedParameters(
-      T* ptr, integer_sequence<int, Indices...>) {
+      T* ptr, std::integer_sequence<int, Indices...>) {
     return std::array<T*, kNumParameterBlocks>{{ptr + Indices...}};
   }
 
diff --git a/include/ceres/internal/port.h b/include/ceres/internal/port.h
index 07bb505..040a1ef 100644
--- a/include/ceres/internal/port.h
+++ b/include/ceres/internal/port.h
@@ -35,56 +35,76 @@
 #include "ceres/internal/config.h"
 
 #if defined(CERES_USE_OPENMP)
-#  if defined(CERES_USE_CXX11_THREADS) || defined(CERES_NO_THREADS)
-#    error CERES_USE_OPENMP is mutually exclusive to CERES_USE_CXX11_THREADS and CERES_NO_THREADS
-#  endif
-#elif defined(CERES_USE_CXX11_THREADS)
-#  if defined(CERES_USE_OPENMP) || defined(CERES_NO_THREADS)
-#    error CERES_USE_CXX11_THREADS is mutually exclusive to CERES_USE_OPENMP, CERES_USE_CXX11_THREADS and CERES_NO_THREADS
-#  endif
+#if defined(CERES_USE_CXX_THREADS) || defined(CERES_NO_THREADS)
+#error CERES_USE_OPENMP is mutually exclusive to CERES_USE_CXX_THREADS and CERES_NO_THREADS
+#endif
+#elif defined(CERES_USE_CXX_THREADS)
+#if defined(CERES_USE_OPENMP) || defined(CERES_NO_THREADS)
+#error CERES_USE_CXX_THREADS is mutually exclusive to CERES_USE_OPENMP, CERES_USE_CXX_THREADS and CERES_NO_THREADS
+#endif
 #elif defined(CERES_NO_THREADS)
-#  if defined(CERES_USE_OPENMP) || defined(CERES_USE_CXX11_THREADS)
-#    error CERES_NO_THREADS is mutually exclusive to CERES_USE_OPENMP and CERES_USE_CXX11_THREADS
-#  endif
+#if defined(CERES_USE_OPENMP) || defined(CERES_USE_CXX_THREADS)
+#error CERES_NO_THREADS is mutually exclusive to CERES_USE_OPENMP and CERES_USE_CXX_THREADS
+#endif
 #else
-#  error One of CERES_USE_OPENMP, CERES_USE_CXX11_THREADS or CERES_NO_THREADS must be defined.
+#  error One of CERES_USE_OPENMP, CERES_USE_CXX_THREADS or CERES_NO_THREADS must be defined.
 #endif
 
 // CERES_NO_SPARSE should be automatically defined by config.h if Ceres was
 // compiled without any sparse back-end.  Verify that it has not subsequently
 // been inconsistently redefined.
 #if defined(CERES_NO_SPARSE)
-#  if !defined(CERES_NO_SUITESPARSE)
-#    error CERES_NO_SPARSE requires CERES_NO_SUITESPARSE.
-#  endif
-#  if !defined(CERES_NO_CXSPARSE)
-#    error CERES_NO_SPARSE requires CERES_NO_CXSPARSE
-#  endif
-#  if !defined(CERES_NO_ACCELERATE_SPARSE)
-#    error CERES_NO_SPARSE requires CERES_NO_ACCELERATE_SPARSE
-#  endif
-#  if defined(CERES_USE_EIGEN_SPARSE)
-#    error CERES_NO_SPARSE requires !CERES_USE_EIGEN_SPARSE
-#  endif
+#if !defined(CERES_NO_SUITESPARSE)
+#error CERES_NO_SPARSE requires CERES_NO_SUITESPARSE.
+#endif
+#if !defined(CERES_NO_CXSPARSE)
+#error CERES_NO_SPARSE requires CERES_NO_CXSPARSE
+#endif
+#if !defined(CERES_NO_ACCELERATE_SPARSE)
+#error CERES_NO_SPARSE requires CERES_NO_ACCELERATE_SPARSE
+#endif
+#if defined(CERES_USE_EIGEN_SPARSE)
+#error CERES_NO_SPARSE requires !CERES_USE_EIGEN_SPARSE
+#endif
 #endif
 
 // A macro to signal which functions and classes are exported when
-// building a DLL with MSVC.
-//
-// Note that the ordering here is important, CERES_BUILDING_SHARED_LIBRARY
-// is only defined locally when Ceres is compiled, it is never exported to
-// users.  However, in order that we do not have to configure config.h
-// separately for building vs installing, if we are using MSVC and building
-// a shared library, then both CERES_BUILDING_SHARED_LIBRARY and
-// CERES_USING_SHARED_LIBRARY will be defined when Ceres is compiled.
-// Hence it is important that the check for CERES_BUILDING_SHARED_LIBRARY
-// happens first.
-#if defined(_MSC_VER) && defined(CERES_BUILDING_SHARED_LIBRARY)
-# define CERES_EXPORT __declspec(dllexport)
-#elif defined(_MSC_VER) && defined(CERES_USING_SHARED_LIBRARY)
-# define CERES_EXPORT __declspec(dllimport)
+// building a shared library.
+#if defined(_MSC_VER)
+#define CERES_API_SHARED_IMPORT __declspec(dllimport)
+#define CERES_API_SHARED_EXPORT __declspec(dllexport)
+#elif defined(__GNUC__)
+#define CERES_API_SHARED_IMPORT __attribute__((visibility("default")))
+#define CERES_API_SHARED_EXPORT __attribute__((visibility("default")))
 #else
-# define CERES_EXPORT
+#define CERES_API_SHARED_IMPORT
+#define CERES_API_SHARED_EXPORT
+#endif
+
+// CERES_BUILDING_SHARED_LIBRARY is only defined locally when Ceres itself is
+// compiled as a shared library, it is never exported to users.  In order that
+// we do not have to configure config.h separately when building Ceres as either
+// a static or dynamic library, we define both CERES_USING_SHARED_LIBRARY and
+// CERES_BUILDING_SHARED_LIBRARY when building as a shared library.
+#if defined(CERES_USING_SHARED_LIBRARY)
+#if defined(CERES_BUILDING_SHARED_LIBRARY)
+// Compiling Ceres itself as a shared library.
+#define CERES_EXPORT CERES_API_SHARED_EXPORT
+#else
+// Using Ceres as a shared library.
+#define CERES_EXPORT CERES_API_SHARED_IMPORT
+#endif
+#else
+// Ceres was compiled as a static library, export everything.
+#define CERES_EXPORT
+#endif
+
+// Unit tests reach in and test internal functionality so we need a way to make
+// those symbols visible
+#ifdef CERES_EXPORT_INTERNAL_SYMBOLS
+#define CERES_EXPORT_INTERNAL CERES_EXPORT
+#else
+#define CERES_EXPORT_INTERNAL
 #endif
 
 #endif  // CERES_PUBLIC_INTERNAL_PORT_H_
diff --git a/include/ceres/internal/reenable_warnings.h b/include/ceres/internal/reenable_warnings.h
index 7e41025..2c5db06 100644
--- a/include/ceres/internal/reenable_warnings.h
+++ b/include/ceres/internal/reenable_warnings.h
@@ -32,7 +32,7 @@
 #undef CERES_WARNINGS_DISABLED
 
 #ifdef _MSC_VER
-#pragma warning( pop )
+#pragma warning(pop)
 #endif
 
 #endif  // CERES_WARNINGS_DISABLED
diff --git a/include/ceres/internal/variadic_evaluate.h b/include/ceres/internal/variadic_evaluate.h
index 26428d0..47ff6b1 100644
--- a/include/ceres/internal/variadic_evaluate.h
+++ b/include/ceres/internal/variadic_evaluate.h
@@ -36,6 +36,7 @@
 #include <stddef.h>
 
 #include <type_traits>
+#include <utility>
 
 #include "ceres/cost_function.h"
 #include "ceres/internal/parameter_dims.h"
@@ -45,9 +46,11 @@
 
 // For fixed size cost functors
 template <typename Functor, typename T, int... Indices>
-inline bool VariadicEvaluateImpl(const Functor& functor, T const* const* input,
-                                 T* output, std::false_type /*is_dynamic*/,
-                                 integer_sequence<int, Indices...>) {
+inline bool VariadicEvaluateImpl(const Functor& functor,
+                                 T const* const* input,
+                                 T* output,
+                                 std::false_type /*is_dynamic*/,
+                                 std::integer_sequence<int, Indices...>) {
   static_assert(sizeof...(Indices),
                 "Invalid number of parameter blocks. At least one parameter "
                 "block must be specified.");
@@ -56,26 +59,31 @@
 
 // For dynamic sized cost functors
 template <typename Functor, typename T>
-inline bool VariadicEvaluateImpl(const Functor& functor, T const* const* input,
-                                 T* output, std::true_type /*is_dynamic*/,
-                                 integer_sequence<int>) {
+inline bool VariadicEvaluateImpl(const Functor& functor,
+                                 T const* const* input,
+                                 T* output,
+                                 std::true_type /*is_dynamic*/,
+                                 std::integer_sequence<int>) {
   return functor(input, output);
 }
 
 // For ceres cost functors (not ceres::CostFunction)
 template <typename ParameterDims, typename Functor, typename T>
-inline bool VariadicEvaluateImpl(const Functor& functor, T const* const* input,
-                                 T* output, const void* /* NOT USED */) {
+inline bool VariadicEvaluateImpl(const Functor& functor,
+                                 T const* const* input,
+                                 T* output,
+                                 const void* /* NOT USED */) {
   using ParameterBlockIndices =
-      make_integer_sequence<int, ParameterDims::kNumParameterBlocks>;
+      std::make_integer_sequence<int, ParameterDims::kNumParameterBlocks>;
   using IsDynamic = std::integral_constant<bool, ParameterDims::kIsDynamic>;
-  return VariadicEvaluateImpl(functor, input, output, IsDynamic(),
-                              ParameterBlockIndices());
+  return VariadicEvaluateImpl(
+      functor, input, output, IsDynamic(), ParameterBlockIndices());
 }
 
 // For ceres::CostFunction
 template <typename ParameterDims, typename Functor, typename T>
-inline bool VariadicEvaluateImpl(const Functor& functor, T const* const* input,
+inline bool VariadicEvaluateImpl(const Functor& functor,
+                                 T const* const* input,
                                  T* output,
                                  const CostFunction* /* NOT USED */) {
   return functor.Evaluate(input, output, nullptr);
@@ -94,7 +102,8 @@
 // blocks. The signature of the functor must have the following signature
 // 'bool()(const T* i_1, const T* i_2, ... const T* i_n, T* output)'.
 template <typename ParameterDims, typename Functor, typename T>
-inline bool VariadicEvaluate(const Functor& functor, T const* const* input,
+inline bool VariadicEvaluate(const Functor& functor,
+                             T const* const* input,
                              T* output) {
   return VariadicEvaluateImpl<ParameterDims>(functor, input, output, &functor);
 }