Add ArcTanLoss, TolerantLoss and ComposedLossFunction.

Based on work by James Roseborough.

Change-Id: Idc4e0b099028f67702bfc7fe3e43dbd96b6f9256
diff --git a/include/ceres/loss_function.h b/include/ceres/loss_function.h
index c95a0a0..f178991 100644
--- a/include/ceres/loss_function.h
+++ b/include/ceres/loss_function.h
@@ -213,6 +213,77 @@
   const double c_;
 };
 
+// Loss that is capped beyond a certain level using the arc-tangent function.
+// The scaling parameter 'a' determines the level where falloff occurs.
+// For costs much smaller than 'a', the loss function is linear and behaves like
+// TrivialLoss, and for values much larger than 'a' the value asymptotically
+// approaches the constant value of a * PI / 2.
+//
+//   rho(s) = a atan(s / a).
+//
+// At s = 0: rho = [0, 1, 0].
+class ArctanLoss : public LossFunction {
+ public:
+  explicit ArctanLoss(double a) : a_(a), b_(1 / (a * a)) { }
+  virtual void Evaluate(double, double*) const;
+ private:
+  const double a_;
+  // b = 1 / a^2.
+  const double b_;
+};
+
+// Loss function that maps to approximately zero cost in a range around the
+// origin, and reverts to linear in error (quadratic in cost) beyond this range.
+// The tolerance parameter 'a' sets the nominal point at which the
+// transition occurs, and the transition size parameter 'b' sets the nominal
+// distance over which most of the transition occurs. Both a and b must be
+// greater than zero, and typically b will be set to a fraction of a.
+// The slope rho'[s] varies smoothly from about 0 at s <= a - b to
+// about 1 at s >= a + b.
+//
+// The term is computed as:
+//
+//   rho(s) = b log(1 + exp((s - a) / b)) - c0.
+//
+// where c0 is chosen so that rho(0) == 0
+//
+//   c0 = b log(1 + exp(-a / b)
+//
+// This has the following useful properties:
+//
+//   rho(s) == 0               for s = 0
+//   rho'(s) ~= 0              for s << a - b
+//   rho'(s) ~= 1              for s >> a + b
+//   rho''(s) > 0              for all s
+//
+// In addition, all derivatives are continuous, and the curvature is
+// concentrated in the range a - b to a + b.
+//
+// At s = 0: rho = [0, ~0, ~0].
+class TolerantLoss : public LossFunction {
+ public:
+  explicit TolerantLoss(double a, double b);
+  virtual void Evaluate(double, double*) const;
+
+ private:
+  const double a_, b_, c_;
+};
+
+// Composition of two loss functions.  The error is the result of first
+// evaluating g followed by f to yield the composition f(g(s)).
+// The loss functions must not be NULL.
+class ComposedLoss : public LossFunction {
+ public:
+  explicit ComposedLoss(const LossFunction* f, Ownership ownership_f,
+                        const LossFunction* g, Ownership ownership_g);
+  virtual ~ComposedLoss();
+  virtual void Evaluate(double, double*) const;
+
+ private:
+  internal::scoped_ptr<const LossFunction> f_, g_;
+  const Ownership ownership_f_, ownership_g_;
+};
+
 // The discussion above has to do with length scaling: it affects the space
 // in which s is measured. Sometimes you want to simply scale the output
 // value of the robustifier. For example, you might want to weight