Initial commit of Ceres Solver.
diff --git a/internal/ceres/loss_function_test.cc b/internal/ceres/loss_function_test.cc
new file mode 100644
index 0000000..eaeb2d8
--- /dev/null
+++ b/internal/ceres/loss_function_test.cc
@@ -0,0 +1,168 @@
+// 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/loss_function.h"
+
+#include <cstddef>
+
+#include <glog/logging.h>
+#include "gtest/gtest.h"
+
+namespace ceres {
+namespace internal {
+namespace {
+
+// Helper function for testing a LossFunction callback.
+//
+// Compares the values of rho'(s) and rho''(s) computed by the
+// callback with estimates obtained by symmetric finite differencing
+// of rho(s).
+void AssertLossFunctionIsValid(const LossFunction& loss, double s) {
+  CHECK_GT(s, 0);
+
+  // Evaluate rho(s), rho'(s) and rho''(s).
+  double rho[3];
+  loss.Evaluate(s, rho);
+
+  // Use symmetric finite differencing to estimate rho'(s) and
+  // rho''(s).
+  const double kH = 1e-4;
+  // Values at s + kH.
+  double fwd[3];
+  // Values at s - kH.
+  double bwd[3];
+  loss.Evaluate(s + kH, fwd);
+  loss.Evaluate(s - kH, bwd);
+
+  // First derivative.
+  const double fd_1 = (fwd[0] - bwd[0]) / (2 * kH);
+  ASSERT_NEAR(fd_1, rho[1], 1e-6);
+
+  // Second derivative.
+  const double fd_2 = (fwd[0] - 2*rho[0] + bwd[0]) / (kH * kH);
+  ASSERT_NEAR(fd_2, rho[2], 1e-6);
+}
+}  // namespace
+
+// Try two values of the scaling a = 0.7 and 1.3
+// (where scaling makes sense) and of the squared norm
+// s = 0.357 and 1.792
+//
+// Note that for the Huber loss the test exercises both code paths
+//  (i.e. both small and large values of s).
+
+TEST(LossFunction, TrivialLoss) {
+  AssertLossFunctionIsValid(TrivialLoss(), 0.357);
+  AssertLossFunctionIsValid(TrivialLoss(), 1.792);
+}
+
+TEST(LossFunction, HuberLoss) {
+  AssertLossFunctionIsValid(HuberLoss(0.7), 0.357);
+  AssertLossFunctionIsValid(HuberLoss(0.7), 1.792);
+  AssertLossFunctionIsValid(HuberLoss(1.3), 0.357);
+  AssertLossFunctionIsValid(HuberLoss(1.3), 1.792);
+}
+
+TEST(LossFunction, SoftLOneLoss) {
+  AssertLossFunctionIsValid(SoftLOneLoss(0.7), 0.357);
+  AssertLossFunctionIsValid(SoftLOneLoss(0.7), 1.792);
+  AssertLossFunctionIsValid(SoftLOneLoss(1.3), 0.357);
+  AssertLossFunctionIsValid(SoftLOneLoss(1.3), 1.792);
+}
+
+TEST(LossFunction, CauchyLoss) {
+  AssertLossFunctionIsValid(CauchyLoss(0.7), 0.357);
+  AssertLossFunctionIsValid(CauchyLoss(0.7), 1.792);
+  AssertLossFunctionIsValid(CauchyLoss(1.3), 0.357);
+  AssertLossFunctionIsValid(CauchyLoss(1.3), 1.792);
+}
+
+TEST(LossFunction, ScaledLoss) {
+  // Wrap a few loss functions, and a few scale factors. This can't combine
+  // construction with the call to AssertLossFunctionIsValid() because Apple's
+  // GCC is unable to eliminate the copy of ScaledLoss, which is not copyable.
+  {
+    ScaledLoss scaled_loss(NULL, 6, TAKE_OWNERSHIP);
+    AssertLossFunctionIsValid(scaled_loss, 0.323);
+  }
+  {
+    ScaledLoss scaled_loss(new TrivialLoss(), 10, TAKE_OWNERSHIP);
+    AssertLossFunctionIsValid(scaled_loss, 0.357);
+  }
+  {
+    ScaledLoss scaled_loss(new HuberLoss(0.7), 0.1, TAKE_OWNERSHIP);
+    AssertLossFunctionIsValid(scaled_loss, 1.792);
+  }
+  {
+    ScaledLoss scaled_loss(new SoftLOneLoss(1.3), 0.1, TAKE_OWNERSHIP);
+    AssertLossFunctionIsValid(scaled_loss, 1.792);
+  }
+  {
+    ScaledLoss scaled_loss(new CauchyLoss(1.3), 10, TAKE_OWNERSHIP);
+    AssertLossFunctionIsValid(scaled_loss, 1.792);
+  }
+}
+
+TEST(LossFunction, LossFunctionWrapper) {
+  // Initialization
+  HuberLoss loss_function1(1.0);
+  LossFunctionWrapper loss_function_wrapper(new HuberLoss(1.0),
+                                            TAKE_OWNERSHIP);
+
+  double s = 0.862;
+  double rho_gold[3];
+  double rho[3];
+  loss_function1.Evaluate(s, rho_gold);
+  loss_function_wrapper.Evaluate(s, rho);
+  for (int i = 0; i < 3; ++i) {
+    EXPECT_NEAR(rho[i], rho_gold[i], 1e-12);
+  }
+
+  // Resetting
+  HuberLoss loss_function2(0.5);
+  loss_function_wrapper.Reset(new HuberLoss(0.5), TAKE_OWNERSHIP);
+  loss_function_wrapper.Evaluate(s, rho);
+  loss_function2.Evaluate(s, rho_gold);
+  for (int i = 0; i < 3; ++i) {
+    EXPECT_NEAR(rho[i], rho_gold[i], 1e-12);
+  }
+
+  // Not taking ownership.
+  HuberLoss loss_function3(0.3);
+  loss_function_wrapper.Reset(&loss_function3, DO_NOT_TAKE_OWNERSHIP);
+  loss_function_wrapper.Evaluate(s, rho);
+  loss_function3.Evaluate(s, rho_gold);
+  for (int i = 0; i < 3; ++i) {
+    EXPECT_NEAR(rho[i], rho_gold[i], 1e-12);
+  }
+}
+
+}  // namespace internal
+}  // namespace ceres