Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef EIGEN_NUMERICAL_DIFF_H
00014 #define EIGEN_NUMERICAL_DIFF_H
00015
00016 namespace Eigen {
00017
00018 enum NumericalDiffMode {
00019 Forward,
00020 Central
00021 };
00022
00023
00035 template<typename _Functor, NumericalDiffMode mode=Forward>
00036 class NumericalDiff : public _Functor
00037 {
00038 public:
00039 typedef _Functor Functor;
00040 typedef typename Functor::Scalar Scalar;
00041 typedef typename Functor::InputType InputType;
00042 typedef typename Functor::ValueType ValueType;
00043 typedef typename Functor::JacobianType JacobianType;
00044
00045 NumericalDiff(Scalar _epsfcn=0.) : Functor(), epsfcn(_epsfcn) {}
00046 NumericalDiff(const Functor& f, Scalar _epsfcn=0.) : Functor(f), epsfcn(_epsfcn) {}
00047
00048
00049 template<typename T0>
00050 NumericalDiff(const T0& a0) : Functor(a0), epsfcn(0) {}
00051 template<typename T0, typename T1>
00052 NumericalDiff(const T0& a0, const T1& a1) : Functor(a0, a1), epsfcn(0) {}
00053 template<typename T0, typename T1, typename T2>
00054 NumericalDiff(const T0& a0, const T1& a1, const T2& a2) : Functor(a0, a1, a2), epsfcn(0) {}
00055
00056 enum {
00057 InputsAtCompileTime = Functor::InputsAtCompileTime,
00058 ValuesAtCompileTime = Functor::ValuesAtCompileTime
00059 };
00060
00064 int df(const InputType& _x, JacobianType &jac) const
00065 {
00066 using std::sqrt;
00067 using std::abs;
00068
00069 Scalar h;
00070 int nfev=0;
00071 const typename InputType::Index n = _x.size();
00072 const Scalar eps = sqrt(((std::max)(epsfcn,NumTraits<Scalar>::epsilon() )));
00073 ValueType val1, val2;
00074 InputType x = _x;
00075
00076 val1.resize(Functor::values());
00077 val2.resize(Functor::values());
00078
00079
00080 switch(mode) {
00081 case Forward:
00082
00083 Functor::operator()(x, val1); nfev++;
00084 break;
00085 case Central:
00086
00087 break;
00088 default:
00089 eigen_assert(false);
00090 };
00091
00092
00093 for (int j = 0; j < n; ++j) {
00094 h = eps * abs(x[j]);
00095 if (h == 0.) {
00096 h = eps;
00097 }
00098 switch(mode) {
00099 case Forward:
00100 x[j] += h;
00101 Functor::operator()(x, val2);
00102 nfev++;
00103 x[j] = _x[j];
00104 jac.col(j) = (val2-val1)/h;
00105 break;
00106 case Central:
00107 x[j] += h;
00108 Functor::operator()(x, val2); nfev++;
00109 x[j] -= 2*h;
00110 Functor::operator()(x, val1); nfev++;
00111 x[j] = _x[j];
00112 jac.col(j) = (val2-val1)/(2*h);
00113 break;
00114 default:
00115 eigen_assert(false);
00116 };
00117 }
00118 return nfev;
00119 }
00120 private:
00121 Scalar epsfcn;
00122
00123 NumericalDiff& operator=(const NumericalDiff&);
00124 };
00125
00126 }
00127
00128
00129 #endif // EIGEN_NUMERICAL_DIFF_H
00130