// Type traits for google3's custom MathUtil traits class. This is needed to // enable embedding Jet objects inside the Quaternion class, found in // util/math/quaternion.h. Including this file makes it possible to use // quaternions inside Ceres cost functions which are automatically // differentiated; for example: // // struct MyCostFunction { // template // bool Map(const T* const quaternion_parameters, T* residuals) { // Quaternion quaternion(quaternion_parameters); // ... // } // } // // NOTE(keir): This header must be included before quaternion.h or other // file relying on traits. Adding a direct dependency on this header from // mathlimits.h is a bad idea, so it is up to clients to use the correct include // order. #ifndef JET_TRAITS_H #define JET_TRAITS_H #include "ceres/jet.h" #include "util/math/mathlimits.h" template struct MathLimits > { typedef ceres::Jet Type; typedef ceres::Jet UnsignedType; static const bool kIsSigned = true; static const bool kIsInteger = false; static const Type kPosMin; static const Type kPosMax; static const Type kMin; static const Type kMax; static const Type kNegMin; static const Type kNegMax; static const int kMin10Exp; static const int kMax10Exp; static const Type kEpsilon; static const Type kStdError; static const int kPrecisionDigits; static const Type kNaN; static const Type kPosInf; static const Type kNegInf; static bool IsFinite(const Type x) { return isfinite(x); } static bool IsNaN (const Type x) { return isnan(x); } static bool IsInf (const Type x) { return isinf(x); } static bool IsPosInf(const Type x) { bool found_inf = MathLimits::IsPosInf(x.a); for (int i = 0; i < N && !found_inf; ++i) { found_inf = MathLimits::IsPosInf(x.v[i]); } return found_inf; } static bool IsNegInf(const Type x) { bool found_inf = MathLimits::IsNegInf(x.a); for (int i = 0; i < N && !found_inf; ++i) { found_inf = MathLimits::IsNegInf(x.v[i]); } return found_inf; } }; // Since every one of these items is a simple forward to the scalar type // underlying the jet, use a tablular format which makes the structure clear. template const ceres::Jet MathLimits >::kPosMin = ceres::Jet(MathLimits::kPosMin); // NOLINT template const ceres::Jet MathLimits >::kPosMax = ceres::Jet(MathLimits::kPosMax); // NOLINT template const ceres::Jet MathLimits >::kMin = ceres::Jet(MathLimits::kMin); // NOLINT template const ceres::Jet MathLimits >::kMax = ceres::Jet(MathLimits::kMax); // NOLINT template const ceres::Jet MathLimits >::kNegMin = ceres::Jet(MathLimits::kNegMin); // NOLINT template const ceres::Jet MathLimits >::kNegMax = ceres::Jet(MathLimits::kNegMax); // NOLINT template const int MathLimits >::kMin10Exp = MathLimits::kMin10Exp; // NOLINT template const int MathLimits >::kMax10Exp = MathLimits::kMax10Exp; // NOLINT template const ceres::Jet MathLimits >::kEpsilon = ceres::Jet(MathLimits::kEpsilon); // NOLINT template const ceres::Jet MathLimits >::kStdError = ceres::Jet(MathLimits::kStdError); // NOLINT template const int MathLimits >::kPrecisionDigits = MathLimits::kPrecisionDigits; // NOLINT template const ceres::Jet MathLimits >::kNaN = ceres::Jet(MathLimits::kNaN); // NOLINT template const ceres::Jet MathLimits >::kPosInf = ceres::Jet(MathLimits::kPosInf); // NOLINT template const ceres::Jet MathLimits >::kNegInf = ceres::Jet(MathLimits::kNegInf); // NOLINT #endif // JET_TRAITS_H