support log10 jet

Change-Id: I1425f7c8fc891cf941a162b8e5b427b5ab4e71da
diff --git a/include/ceres/jet.h b/include/ceres/jet.h
index 62e9828..e45caf2 100644
--- a/include/ceres/jet.h
+++ b/include/ceres/jet.h
@@ -404,6 +404,7 @@
 using std::isnan;
 using std::isnormal;
 using std::log;
+using std::log10;
 using std::log1p;
 using std::log2;
 using std::norm;
@@ -473,6 +474,14 @@
   return Jet<T, N>(log(f.a), f.v * a_inverse);
 }
 
+// log10(a + h) ~= log10(a) + h / (a log(10))
+template <typename T, int N>
+inline Jet<T, N> log10(const Jet<T, N>& f) {
+  // Most compilers will expand log(10) to a constant.
+  const T a_inverse = T(1.0) / (f.a * log(T(10.0)));
+  return Jet<T, N>(log10(f.a), f.v * a_inverse);
+}
+
 // log1p(a + h) ~= log1p(a) + h / (1 + a)
 template <typename T, int N>
 inline Jet<T, N> log1p(const Jet<T, N>& f) {
diff --git a/internal/ceres/jet_test.cc b/internal/ceres/jet_test.cc
index 6a7011d..bceb9e4 100644
--- a/internal/ceres/jet_test.cc
+++ b/internal/ceres/jet_test.cc
@@ -702,6 +702,17 @@
   NumericalTest("exp2", exp2<double, 2>, 1e-5);
   NumericalTest("exp2", exp2<double, 2>, 1.0);
 
+  {  // Check that log10(x) == log(x) / log(10)
+    J z = log10(x);
+    J w = log(x) / log(10.0);
+    VL << "z = " << z;
+    VL << "w = " << w;
+    ExpectJetsClose(z, w);
+  }
+  NumericalTest("log10", log10<double, 2>, 1e-5);
+  NumericalTest("log10", log10<double, 2>, 1.0);
+  NumericalTest("log10", log10<double, 2>, 98.76);
+
   {  // Check that log2(x) == log(x) / log(2)
     J z = log2(x);
     J w = log(x) / log(2.0);