Initial commit of Ceres Solver.
diff --git a/internal/ceres/corrector_test.cc b/internal/ceres/corrector_test.cc
new file mode 100644
index 0000000..b2556af
--- /dev/null
+++ b/internal/ceres/corrector_test.cc
@@ -0,0 +1,276 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2010, 2011, 2012 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: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/corrector.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include "gtest/gtest.h"
+#include "ceres/random.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+// If rho[1] is zero, the Corrector constructor should crash.
+TEST(Corrector, ZeroGradientDeathTest) {
+  const double kRho[] = {0.0, 0.0, 0.0};
+  ASSERT_DEATH({Corrector c(1.0, kRho);},
+               ".*");
+}
+
+// If rho[1] is negative, the Corrector constructor should crash.
+TEST(Corrector, NegativeGradientDeathTest) {
+  const double kRho[] = {0.0, -0.1, 0.0};
+  ASSERT_DEATH({Corrector c(1.0, kRho);},
+               ".*");
+}
+
+TEST(Corrector, ScalarCorrection) {
+  double residuals = sqrt(3.0);
+  double jacobian = 10.0;
+  double sq_norm = residuals * residuals;
+
+  const double kRho[] = {sq_norm, 0.1, -0.01};
+
+  // In light of the rho'' < 0 clamping now implemented in
+  // corrector.cc, alpha = 0 whenever rho'' < 0.
+  const double kAlpha = 0.0;
+
+  // Thus the expected value of the residual is
+  // residual[i] * sqrt(kRho[1]) / (1.0 - kAlpha).
+  const double kExpectedResidual =
+      residuals * sqrt(kRho[1]) / (1 - kAlpha);
+
+  // The jacobian in this case will be
+  // sqrt(kRho[1]) * (1 - kAlpha) * jacobian.
+  const double kExpectedJacobian = sqrt(kRho[1]) * (1 - kAlpha) * jacobian;
+
+  Corrector c(sq_norm, kRho);
+  c.CorrectJacobian(1.0, 1.0, &residuals, &jacobian);
+  c.CorrectResiduals(1.0, &residuals);
+
+  ASSERT_NEAR(residuals, kExpectedResidual, 1e-6);
+  ASSERT_NEAR(kExpectedJacobian, jacobian, 1e-6);
+}
+
+TEST(Corrector, ScalarCorrectionZeroResidual) {
+  double residuals = 0.0;
+  double jacobian = 10.0;
+  double sq_norm = residuals * residuals;
+
+  const double kRho[] = {0.0, 0.1, -0.01};
+  Corrector c(sq_norm, kRho);
+
+  // The alpha equation is
+  // 1/2 alpha^2 - alpha + 0.0 = 0.
+  // i.e. alpha = 1.0 - sqrt(1.0).
+  //      alpha = 0.0.
+  // Thus the expected value of the residual is
+  // residual[i] * sqrt(kRho[1])
+  const double kExpectedResidual = residuals * sqrt(kRho[1]);
+
+  // The jacobian in this case will be
+  // sqrt(kRho[1]) * jacobian.
+  const double kExpectedJacobian = sqrt(kRho[1]) * jacobian;
+
+  c.CorrectJacobian(1, 1, &residuals, &jacobian);
+  c.CorrectResiduals(1, &residuals);
+
+  ASSERT_NEAR(residuals, kExpectedResidual, 1e-6);
+  ASSERT_NEAR(kExpectedJacobian, jacobian, 1e-6);
+}
+
+// Scaling behaviour for one dimensional functions.
+TEST(Corrector, ScalarCorrectionAlphaClamped) {
+  double residuals = sqrt(3.0);
+  double jacobian = 10.0;
+  double sq_norm = residuals * residuals;
+
+  const double kRho[] = {3, 0.1, -0.1};
+
+  // rho[2] < 0 -> alpha = 0.0
+  const double kAlpha = 0.0;
+
+  // Thus the expected value of the residual is
+  // residual[i] * sqrt(kRho[1]) / (1.0 - kAlpha).
+  const double kExpectedResidual =
+      residuals * sqrt(kRho[1]) / (1.0 - kAlpha);
+
+  // The jacobian in this case will be scaled by
+  // sqrt(rho[1]) * (1 - alpha) * J.
+  const double kExpectedJacobian = sqrt(kRho[1]) *
+      (1.0 - kAlpha) * jacobian;
+
+  Corrector c(sq_norm, kRho);
+  c.CorrectJacobian(1, 1, &residuals, &jacobian);
+  c.CorrectResiduals(1, &residuals);
+
+  ASSERT_NEAR(residuals, kExpectedResidual, 1e-6);
+  ASSERT_NEAR(kExpectedJacobian, jacobian, 1e-6);
+}
+
+// Test that the corrected multidimensional residual and jacobians
+// match the expected values and the resulting modified normal
+// equations match the robustified gauss newton approximation.
+TEST(Corrector, MultidimensionalGaussNewtonApproximation) {
+  double residuals[3];
+  double jacobian[2 * 3];
+  double rho[3];
+
+  // Eigen matrix references for linear algebra.
+  MatrixRef jac(jacobian, 3, 2);
+  VectorRef res(residuals, 3);
+
+  // Ground truth values of the modified jacobian and residuals.
+  Matrix g_jac(3, 2);
+  Vector g_res(3);
+
+  // Ground truth values of the robustified Gauss-Newton
+  // approximation.
+  Matrix g_hess(2, 2);
+  Vector g_grad(2);
+
+  // Corrected hessian and gradient implied by the modified jacobian
+  // and hessians.
+  Matrix c_hess(2, 2);
+  Vector c_grad(2);
+
+  srand(5);
+  for (int iter = 0; iter < 10000; ++iter) {
+    // Initialize the jacobian and residual.
+    for (int i = 0; i < 2 * 3; ++i)
+      jacobian[i] = RandDouble();
+    for (int i = 0; i < 3; ++i)
+      residuals[i] = RandDouble();
+
+    const double sq_norm = res.dot(res);
+
+    rho[0] = sq_norm;
+    rho[1] = RandDouble();
+    rho[2] = 2.0 * RandDouble() - 1.0;
+
+    // If rho[2] > 0, then the curvature correction to the correction
+    // and the gauss newton approximation will match. Otherwise, we
+    // will clamp alpha to 0.
+
+    const double kD = 1 + 2 * rho[2] / rho[1] * sq_norm;
+    const double kAlpha = (rho[2] > 0.0) ? 1 - sqrt(kD) : 0.0;
+
+    // Ground truth values.
+    g_res = sqrt(rho[1]) / (1.0 - kAlpha) * res;
+    g_jac = sqrt(rho[1]) * (jac - kAlpha / sq_norm *
+                            res * res.transpose() * jac);
+
+    g_grad = rho[1] * jac.transpose() * res;
+    g_hess = rho[1] * jac.transpose() * jac +
+        2.0 * rho[2] * jac.transpose() * res * res.transpose() * jac;
+
+    Corrector c(sq_norm, rho);
+    c.CorrectJacobian(3, 2, residuals, jacobian);
+    c.CorrectResiduals(3, residuals);
+
+    // Corrected gradient and hessian.
+    c_grad  = jac.transpose() * res;
+    c_hess = jac.transpose() * jac;
+
+    ASSERT_NEAR((g_res - res).norm(), 0.0, 1e-10);
+    ASSERT_NEAR((g_jac - jac).norm(), 0.0, 1e-10);
+
+    ASSERT_NEAR((g_grad - c_grad).norm(), 0.0, 1e-10);
+  }
+}
+
+TEST(Corrector, MultidimensionalGaussNewtonApproximationZeroResidual) {
+  double residuals[3];
+  double jacobian[2 * 3];
+  double rho[3];
+
+  // Eigen matrix references for linear algebra.
+  MatrixRef jac(jacobian, 3, 2);
+  VectorRef res(residuals, 3);
+
+  // Ground truth values of the modified jacobian and residuals.
+  Matrix g_jac(3, 2);
+  Vector g_res(3);
+
+  // Ground truth values of the robustified Gauss-Newton
+  // approximation.
+  Matrix g_hess(2, 2);
+  Vector g_grad(2);
+
+  // Corrected hessian and gradient implied by the modified jacobian
+  // and hessians.
+  Matrix c_hess(2, 2);
+  Vector c_grad(2);
+
+  srand(5);
+  for (int iter = 0; iter < 10000; ++iter) {
+    // Initialize the jacobian.
+    for (int i = 0; i < 2 * 3; ++i)
+      jacobian[i] = RandDouble();
+
+    // Zero residuals
+    res.setZero();
+
+    const double sq_norm = res.dot(res);
+
+    rho[0] = sq_norm;
+    rho[1] = RandDouble();
+    rho[2] = 2 * RandDouble() - 1.0;
+
+    // Ground truth values.
+    g_res = sqrt(rho[1]) * res;
+    g_jac = sqrt(rho[1]) * jac;
+
+    g_grad = rho[1] * jac.transpose() * res;
+    g_hess = rho[1] * jac.transpose() * jac +
+        2.0 * rho[2] * jac.transpose() * res * res.transpose() * jac;
+
+    Corrector c(sq_norm, rho);
+    c.CorrectJacobian(3, 2, residuals, jacobian);
+    c.CorrectResiduals(3, residuals);
+
+    // Corrected gradient and hessian.
+    c_grad = jac.transpose() * res;
+    c_hess = jac.transpose() * jac;
+
+    ASSERT_NEAR((g_res - res).norm(), 0.0, 1e-10);
+    ASSERT_NEAR((g_jac - jac).norm(), 0.0, 1e-10);
+
+    ASSERT_NEAR((g_grad - c_grad).norm(), 0.0, 1e-10);
+    ASSERT_NEAR((g_hess - c_hess).norm(), 0.0, 1e-10);
+  }
+}
+
+}  // namespace internal
+}  // namespace ceres