Add sinh, cosh, tanh and tan functions to automatic differentiation
Change-Id: I6eb43fe9b340d4074ed3eed1461dda315f6e8ce8
diff --git a/include/ceres/jet.h b/include/ceres/jet.h
index 000bd1c..7299a48 100644
--- a/include/ceres/jet.h
+++ b/include/ceres/jet.h
@@ -405,7 +405,6 @@
// double-valued and Jet-valued functions, but we are not allowed to put
// Jet-valued functions inside namespace std.
//
-// Missing: cosh, sinh, tanh, tan
// TODO(keir): Switch to "using".
inline double abs (double x) { return std::abs(x); }
inline double log (double x) { return std::log(x); }
@@ -415,6 +414,11 @@
inline double acos (double x) { return std::acos(x); }
inline double sin (double x) { return std::sin(x); }
inline double asin (double x) { return std::asin(x); }
+inline double tan (double x) { return std::tan(x); }
+inline double atan (double x) { return std::atan(x); }
+inline double sinh (double x) { return std::sinh(x); }
+inline double cosh (double x) { return std::cosh(x); }
+inline double tanh (double x) { return std::tanh(x); }
inline double pow (double x, double y) { return std::pow(x, y); }
inline double atan2(double y, double x) { return std::atan2(y, x); }
@@ -495,6 +499,58 @@
return g;
}
+// tan(a + h) ~= tan(a) + (1 + tan(a)^2) h
+template <typename T, int N> inline
+Jet<T, N> tan(const Jet<T, N>& f) {
+ Jet<T, N> g;
+ g.a = tan(f.a);
+ double tan_a = tan(f.a);
+ const T tmp = T(1.0) + tan_a * tan_a;
+ g.v = tmp * f.v;
+ return g;
+}
+
+// atan(a + h) ~= atan(a) + 1 / (1 + a^2) h
+template <typename T, int N> inline
+Jet<T, N> atan(const Jet<T, N>& f) {
+ Jet<T, N> g;
+ g.a = atan(f.a);
+ const T tmp = T(1.0) / (T(1.0) + f.a * f.a);
+ g.v = tmp * f.v;
+ return g;
+}
+
+// sinh(a + h) ~= sinh(a) + cosh(a) h
+template <typename T, int N> inline
+Jet<T, N> sinh(const Jet<T, N>& f) {
+ Jet<T, N> g;
+ g.a = sinh(f.a);
+ const T cosh_a = cosh(f.a);
+ g.v = cosh_a * f.v;
+ return g;
+}
+
+// cosh(a + h) ~= cosh(a) + sinh(a) h
+template <typename T, int N> inline
+Jet<T, N> cosh(const Jet<T, N>& f) {
+ Jet<T, N> g;
+ g.a = cosh(f.a);
+ const T sinh_a = sinh(f.a);
+ g.v = sinh_a * f.v;
+ return g;
+}
+
+// tanh(a + h) ~= tanh(a) + (1 - tanh(a)^2) h
+template <typename T, int N> inline
+Jet<T, N> tanh(const Jet<T, N>& f) {
+ Jet<T, N> g;
+ g.a = tanh(f.a);
+ double tanh_fa = tanh(f.a);
+ const T tmp = 1 - tanh_fa * tanh_fa;
+ g.v = tmp * f.v;
+ return g;
+}
+
// Jet Classification. It is not clear what the appropriate semantics are for
// these classifications. This picks that IsFinite and isnormal are "all"
// operations, i.e. all elements of the jet must be finite for the jet itself
@@ -645,6 +701,11 @@
template<typename T, int N> inline Jet<T, N> ei_log (const Jet<T, N>& x) { return log(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_sin (const Jet<T, N>& x) { return sin(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_cos (const Jet<T, N>& x) { return cos(x); } // NOLINT
+template<typename T, int N> inline Jet<T, N> ei_tan (const Jet<T, N>& x) { return tan(x); } // NOLINT
+template<typename T, int N> inline Jet<T, N> ei_atan(const Jet<T, N>& x) { return atan(x); } // NOLINT
+template<typename T, int N> inline Jet<T, N> ei_sinh(const Jet<T, N>& x) { return sinh(x); } // NOLINT
+template<typename T, int N> inline Jet<T, N> ei_cosh(const Jet<T, N>& x) { return cosh(x); } // NOLINT
+template<typename T, int N> inline Jet<T, N> ei_tanh(const Jet<T, N>& x) { return tanh(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_pow (const Jet<T, N>& x, Jet<T, N> y) { return pow(x, y); } // NOLINT
// Note: This has to be in the ceres namespace for argument dependent lookup to