// -*- coding: utf-8 // vim: set fileencoding=utf-8
// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
/** * This class allows you to add a method df() to your functor, which will * use numerical differentiation to compute an approximate of the * derivative for the functor. Of course, if you have an analytical form * for the derivative, you should rather implement df() by yourself. * * More information on * http://en.wikipedia.org/wiki/Numerical_differentiation * * Currently only "Forward" and "Central" scheme are implemented.
*/ template<typename _Functor, NumericalDiffMode mode=Forward> class NumericalDiff : public _Functor
{ public: typedef _Functor Functor; typedeftypename Functor::Scalar Scalar; typedeftypename Functor::InputType InputType; typedeftypename Functor::ValueType ValueType; typedeftypename Functor::JacobianType JacobianType;
/** * return the number of evaluation of functor
*/ int df(const InputType& _x, JacobianType &jac) const
{ using std::sqrt; using std::abs; /* Local variables */
Scalar h; int nfev=0; consttypename InputType::Index n = _x.size(); const Scalar eps = sqrt(((std::max)(epsfcn,NumTraits<Scalar>::epsilon() )));
ValueType val1, val2;
InputType x = _x; // TODO : we should do this only if the size is not already known
val1.resize(Functor::values());
val2.resize(Functor::values());
// initialization switch(mode) { case Forward: // compute f(x)
Functor::operator()(x, val1); nfev++; break; case Central: // do nothing break; default:
eigen_assert(false);
};
// Function Body for (int j = 0; j < n; ++j) {
h = eps * abs(x[j]); if (h == 0.) {
h = eps;
} switch(mode) { case Forward:
x[j] += h;
Functor::operator()(x, val2);
nfev++;
x[j] = _x[j];
jac.col(j) = (val2-val1)/h; break; case Central:
x[j] += h;
Functor::operator()(x, val2); nfev++;
x[j] -= 2*h;
Functor::operator()(x, val1); nfev++;
x[j] = _x[j];
jac.col(j) = (val2-val1)/(2*h); break; default:
eigen_assert(false);
};
} return nfev;
} private:
Scalar epsfcn;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.