C++程序  |  83行  |  4.38 KB

// 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<T>
//     bool Map(const T* const quaternion_parameters, T* residuals) {
//       Quaternion<T> 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<typename T, int N>
struct MathLimits<ceres::Jet<T, N> > {
  typedef ceres::Jet<T, N> Type;
  typedef ceres::Jet<T, N> 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<T>::IsPosInf(x.a);
    for (int i = 0; i < N && !found_inf; ++i) {
      found_inf = MathLimits<T>::IsPosInf(x.v[i]);
    }
    return found_inf;
  }
  static bool IsNegInf(const Type x) {
    bool found_inf = MathLimits<T>::IsNegInf(x.a);
    for (int i = 0; i < N && !found_inf; ++i) {
      found_inf = MathLimits<T>::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<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kPosMin          = ceres::Jet<T, N>(MathLimits<T>::kPosMin);    // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kPosMax          = ceres::Jet<T, N>(MathLimits<T>::kPosMax);    // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kMin             = ceres::Jet<T, N>(MathLimits<T>::kMin);       // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kMax             = ceres::Jet<T, N>(MathLimits<T>::kMax);       // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kNegMin          = ceres::Jet<T, N>(MathLimits<T>::kNegMin);    // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kNegMax          = ceres::Jet<T, N>(MathLimits<T>::kNegMax);    // NOLINT
template<typename T, int N> const int              MathLimits<ceres::Jet<T, N> >::kMin10Exp        = MathLimits<T>::kMin10Exp;                    // NOLINT
template<typename T, int N> const int              MathLimits<ceres::Jet<T, N> >::kMax10Exp        = MathLimits<T>::kMax10Exp;                    // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kEpsilon         = ceres::Jet<T, N>(MathLimits<T>::kEpsilon);   // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kStdError        = ceres::Jet<T, N>(MathLimits<T>::kStdError);  // NOLINT
template<typename T, int N> const int              MathLimits<ceres::Jet<T, N> >::kPrecisionDigits = MathLimits<T>::kPrecisionDigits;             // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kNaN             = ceres::Jet<T, N>(MathLimits<T>::kNaN);       // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kPosInf          = ceres::Jet<T, N>(MathLimits<T>::kPosInf);    // NOLINT
template<typename T, int N> const ceres::Jet<T, N> MathLimits<ceres::Jet<T, N> >::kNegInf          = ceres::Jet<T, N>(MathLimits<T>::kNegInf);    // NOLINT

#endif  // JET_TRAITS_H