wrapper for lmdif1 + eigenization of calling test

This commit is contained in:
Thomas Capricelli 2009-08-10 17:16:43 +02:00
parent 80372c18ee
commit bb1204a145
2 changed files with 59 additions and 40 deletions

View File

@ -266,5 +266,30 @@ int ei_lmdif(
); );
} }
template<typename Functor, typename Scalar>
int ei_lmdif1(
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > &x,
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > &fvec,
VectorXi &iwa,
Scalar tol = Eigen::ei_sqrt(Eigen::machine_epsilon<Scalar>())
)
{
int n = x.size();
int ldfjac = fvec.size();
int lwa = ldfjac*n+5*n+ldfjac;
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > wa(lwa);
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > fjac(ldfjac, n);
iwa.resize(n);
wa.resize(lwa);
return lmdif1 (
Functor::f, 0,
fvec.size(), n, x.data(), fvec.data(),
tol,
iwa.data(),
wa.data(), lwa
);
}
#endif // EIGEN_NONLINEAR_MATHFUNCTIONS_H #endif // EIGEN_NONLINEAR_MATHFUNCTIONS_H

View File

@ -684,8 +684,9 @@ void testLmstr()
for (j=1; j<=n; j++) VERIFY_IS_APPROX(x[j-1], x_ref[j-1]); for (j=1; j<=n; j++) VERIFY_IS_APPROX(x[j-1], x_ref[j-1]);
} }
int fcn_lmdif1(void * /*p*/, int /*m*/, int /*n*/, const double *x, double *fvec, int /*iflag*/) struct lmdif1_functor {
{ static int f(void * /*p*/, int /*m*/, int /*n*/, const double *x, double *fvec, int /*iflag*/)
{
/* function fcn for lmdif1 example */ /* function fcn for lmdif1 example */
int i; int i;
@ -703,39 +704,32 @@ int fcn_lmdif1(void * /*p*/, int /*m*/, int /*n*/, const double *x, double *fvec
fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3)); fvec[i] = y[i] - (x[0] + tmp1/(x[1]*tmp2 + x[2]*tmp3));
} }
return 0; return 0;
} }
};
void testLmdif1() void testLmdif1()
{ {
int m, n, info, lwa, iwa[3]; int m=15, n=3, info;
double tol, fnorm, x[3], fvec[15], wa[75];
m = 15; Eigen::VectorXd x(n), fvec(m);
n = 3; VectorXi iwa;
/* the following starting values provide a rough fit. */ /* the following starting values provide a rough fit. */
x.setConstant(n, 1.);
x[0] = 1.e0; // do the computation
x[1] = 1.e0; info = ei_lmdif1<lmdif1_functor,double>(x, fvec, iwa);
x[2] = 1.e0;
lwa = 75; // check return value
VERIFY( 1 == info);
/* set tol to the square root of the machine precision. unless high // check norm
precision solutions are required, this is the recommended VERIFY_IS_APPROX(fvec.norm(), 0.09063596);
setting. */
tol = sqrt(dpmpar(1)); // check x
VectorXd x_ref(n);
info = lmdif1(fcn_lmdif1, 0, m, n, x, fvec, tol, iwa, wa, lwa); x_ref << 0.0824106, 1.1330366, 2.3436947;
VERIFY_IS_APPROX(x, x_ref);
fnorm = enorm(m, fvec);
VERIFY_IS_APPROX(fnorm, 0.09063596);
VERIFY(info==1);
double x_ref[] = {0.0824106, 1.1330366, 2.3436947 };
int j;
for (j=1; j<=n; j++) VERIFY_IS_APPROX(x[j-1], x_ref[j-1]);
} }