00001 #include "vnl_discrete_diff.h"
00002 #include <vnl/vnl_least_squares_function.h>
00003 #include <vcl_cassert.h>
00004
00005
00006
00007
00008 bool vnl_discrete_diff_fwd(vnl_least_squares_function *lsf,
00009 double h_,
00010 vnl_vector<double> const &x,
00011 vnl_matrix<double> &J)
00012 {
00013 vnl_vector<double> y(lsf->get_number_of_residuals());
00014 lsf->f(x,y);
00015 if (lsf->failure)
00016 return false;
00017 vnl_vector<double> h(lsf->get_number_of_unknowns());
00018 h.fill(h_);
00019 return vnl_discrete_diff_fwd(lsf,h,x,y,J);
00020 }
00021
00022 bool vnl_discrete_diff_fwd(vnl_least_squares_function *lsf,
00023 vnl_vector<double> const &h,
00024 vnl_vector<double> const &x,
00025 vnl_matrix<double> &J)
00026 {
00027 vnl_vector<double> y(lsf->get_number_of_residuals());
00028 lsf->f(x,y);
00029 if (lsf->failure)
00030 return false;
00031 return vnl_discrete_diff_fwd(lsf,h,x,y,J);
00032 }
00033
00034 bool vnl_discrete_diff_fwd(vnl_least_squares_function *lsf,
00035 vnl_vector<double> const &h,
00036 vnl_vector<double> const &x,
00037 vnl_vector<double> const &y,
00038 vnl_matrix<double> &J)
00039 {
00040 unsigned m=J.rows();
00041 unsigned n=J.columns();
00042 assert(m==lsf->get_number_of_residuals());
00043 assert(m==y.size());
00044 assert(n==lsf->get_number_of_unknowns());
00045 assert(n==h.size());
00046 assert(n==x.size());
00047
00048 vnl_vector<double> tx(n);
00049 vnl_vector<double> ty(m);
00050
00051 for (unsigned j=0;j<n;j++) {
00052 tx=x; tx(j) += h(j);
00053 lsf->f(tx,ty);
00054 if (lsf->failure)
00055 return false;
00056 for (unsigned i=0;i<m;i++)
00057 J(i,j) = (ty(i)-y(i))/h(j);
00058 }
00059 return true;
00060 }
00061
00062 bool vnl_discrete_diff_sym(vnl_least_squares_function *lsf,
00063 double h_,
00064 vnl_vector<double> const &x,
00065 vnl_matrix<double> &J)
00066 {
00067 vnl_vector<double> h(lsf->get_number_of_unknowns());
00068 h.fill(h_);
00069 return vnl_discrete_diff_sym(lsf,h,x,J);
00070 }
00071
00072 bool vnl_discrete_diff_sym(vnl_least_squares_function *lsf,
00073 vnl_vector<double> const &h,
00074 vnl_vector<double> const &x,
00075 vnl_matrix<double> &J)
00076 {
00077 unsigned m=J.rows();
00078 unsigned n=J.columns();
00079 assert(m==lsf->get_number_of_residuals());
00080 assert(n==lsf->get_number_of_unknowns());
00081 assert(n==h.size());
00082 assert(n==x.size());
00083
00084 vnl_vector<double> xp(n),xm(n);
00085 vnl_vector<double> yp(m),ym(m);
00086
00087 for (unsigned j=0;j<n;j++) {
00088 xp=x; xp(j) += h(j);
00089 lsf->f(xp,yp);
00090 if (lsf->failure)
00091 return false;
00092
00093 xm=x; xm(j) -= h(j);
00094 lsf->f(xm,ym);
00095 if (lsf->failure)
00096 return false;
00097
00098 for (unsigned i=0;i<m;i++)
00099 J(i,j) = (yp(i)-ym(i))/(2*h(j));
00100 }
00101 return true;
00102 }
00103
00104
00105
00106 #include <vcl_iostream.h>
00107
00108 void vnl_discrete_diff_test_lsf(vnl_least_squares_function *lsf, vnl_vector<double> const &x)
00109 {
00110 unsigned int m = lsf->get_number_of_residuals();
00111 unsigned int n = lsf->get_number_of_unknowns ();
00112 assert(x.size() == n);
00113
00114 vnl_matrix<double> J1(m, n);
00115 lsf->gradf(x, J1);
00116
00117 vnl_matrix<double> J2(m, n);
00118 vnl_discrete_diff_sym(lsf, 0.0001, x, J2);
00119
00120 double e = (J1 - J2).fro_norm();
00121
00122 double t = cos_angle(J1, J2);
00123
00124
00125 vcl_cerr << __FILE__ ": e = " << e << vcl_endl
00126 << __FILE__ ": t = " << t << vcl_endl;
00127 }