1 // Type traits for google3's custom MathUtil traits class. This is needed to
2 // enable embedding Jet objects inside the Quaternion class, found in
3 // util/math/quaternion.h. Including this file makes it possible to use
4 // quaternions inside Ceres cost functions which are automatically
5 // differentiated; for example:
6 //
7 //   struct MyCostFunction {
8 //     template<T>
9 //     bool Map(const T* const quaternion_parameters, T* residuals) {
10 //       Quaternion<T> quaternion(quaternion_parameters);
11 //       ...
12 //     }
13 //   }
14 //
15 // NOTE(keir): This header must be included before quaternion.h or other
16 // file relying on traits. Adding a direct dependency on this header from
17 // mathlimits.h is a bad idea, so it is up to clients to use the correct include
18 // order.
19 
20 #ifndef JET_TRAITS_H
21 #define JET_TRAITS_H
22 
23 #include "ceres/jet.h"
24 #include "util/math/mathlimits.h"
25 
26 template<typename T, int N>
27 struct MathLimits<ceres::Jet<T, N> > {
28   typedef ceres::Jet<T, N> Type;
29   typedef ceres::Jet<T, N> UnsignedType;
30   static const bool kIsSigned = true;
31   static const bool kIsInteger = false;
32   static const Type kPosMin;
33   static const Type kPosMax;
34   static const Type kMin;
35   static const Type kMax;
36   static const Type kNegMin;
37   static const Type kNegMax;
38   static const int  kMin10Exp;
39   static const int  kMax10Exp;
40   static const Type kEpsilon;
41   static const Type kStdError;
42   static const int  kPrecisionDigits;
43   static const Type kNaN;
44   static const Type kPosInf;
45   static const Type kNegInf;
46   static bool IsFinite(const Type x) { return isfinite(x); }
47   static bool IsNaN   (const Type x) { return isnan(x);    }
48   static bool IsInf   (const Type x) { return isinf(x);    }
49   static bool IsPosInf(const Type x) {
50     bool found_inf = MathLimits<T>::IsPosInf(x.a);
51     for (int i = 0; i < N && !found_inf; ++i) {
52       found_inf = MathLimits<T>::IsPosInf(x.v[i]);
53     }
54     return found_inf;
55   }
56   static bool IsNegInf(const Type x) {
57     bool found_inf = MathLimits<T>::IsNegInf(x.a);
58     for (int i = 0; i < N && !found_inf; ++i) {
59       found_inf = MathLimits<T>::IsNegInf(x.v[i]);
60     }
61     return found_inf;
62   }
63 };
64 
65 // Since every one of these items is a simple forward to the scalar type
66 // underlying the jet, use a tablular format which makes the structure clear.
67 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kPosMin          = ceres::Jet<T, N>(MathLimits<T>::kPosMin);    // NOLINT
68 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kPosMax          = ceres::Jet<T, N>(MathLimits<T>::kPosMax);    // NOLINT
69 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kMin             = ceres::Jet<T, N>(MathLimits<T>::kMin);       // NOLINT
70 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kMax             = ceres::Jet<T, N>(MathLimits<T>::kMax);       // NOLINT
71 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kNegMin          = ceres::Jet<T, N>(MathLimits<T>::kNegMin);    // NOLINT
72 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kNegMax          = ceres::Jet<T, N>(MathLimits<T>::kNegMax);    // NOLINT
73 template<typename T, int N> const int              MathLimits<ceres::Jet<T, N> >::kMin10Exp        = MathLimits<T>::kMin10Exp;                    // NOLINT
74 template<typename T, int N> const int              MathLimits<ceres::Jet<T, N> >::kMax10Exp        = MathLimits<T>::kMax10Exp;                    // NOLINT
75 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kEpsilon         = ceres::Jet<T, N>(MathLimits<T>::kEpsilon);   // NOLINT
76 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kStdError        = ceres::Jet<T, N>(MathLimits<T>::kStdError);  // NOLINT
77 template<typename T, int N> const int              MathLimits<ceres::Jet<T, N> >::kPrecisionDigits = MathLimits<T>::kPrecisionDigits;             // NOLINT
78 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kNaN             = ceres::Jet<T, N>(MathLimits<T>::kNaN);       // NOLINT
79 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kPosInf          = ceres::Jet<T, N>(MathLimits<T>::kPosInf);    // NOLINT
80 template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kNegInf          = ceres::Jet<T, N>(MathLimits<T>::kNegInf);    // NOLINT
81 
82 #endif  // JET_TRAITS_H
83