00001 #ifndef LM_DIFF
00002 #define LM_DIFF
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <cminpack.h>
00028 #include <stdlib.h>
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00056 class LMDiff{
00057 public:
00058
00059
00060
00061
00062 typedef struct {
00063 double ftol;
00064 double xtol;
00065 double gtol;
00066 double epsilon;
00067 double stepbound;
00068 double fnorm;
00069 int maxcall;
00070 int nfev;
00071 int nprint;
00072 int info;
00073 } lm_control_type;
00074
00075
00076
00077 typedef struct {
00078 int nfev;
00079 int nprint;
00080 int stop;
00081 } lm_status_type;
00082
00083
00084
00085 static char * Message(const int & i){
00086 static char *lm_infmsg[] = {
00087 "improper input parameters",
00088 "the relative error in the sum of squares is at most tol",
00089 "the relative error between x and the solution is at most tol",
00090 "both errors are at most tol",
00091 "fvec is orthogonal to the columns of the jacobian to machine precision",
00092 "number of calls to fcn has reached or exceeded 200*(n+1)",
00093 "tol is too small. no further reduction in the sum of squares is possible",
00094 "tol too small. no further improvement in approximate solution x possible",
00095 "not enough memory"
00096 };
00097 return lm_infmsg[i];
00098 }
00099 lm_control_type control;
00100
00102 void InitControl(){lm_initialize_control();}
00103
00105 typedef int (lm_evaluate_type) (
00106 void *user_data,
00107 int m,
00108 int n,
00109 const double* n_var,
00110 double* fvec,
00111 int iflag
00112 );
00113
00114 void Run (
00115 int m,
00116 int n ,
00117 double* par,
00118 lm_evaluate_type *evaluate,
00119 void *data,
00120 lm_control_type *control
00121 );
00122
00123
00124
00125
00126 void Run( int m_dat,int n_par, double* par, lm_evaluate_type *evaluate,
00127 void *data );
00128
00129 private:
00130 void lm_initialize_control( );
00131 };
00132
00133
00134
00135
00136
00137
00138 void LMDiff::lm_initialize_control( )
00139 {
00140 control.maxcall = 10000;
00141 control.epsilon = 1.e-14;
00142 control.stepbound = 100.;
00143 control.ftol = 1.e-14;
00144 control.xtol = 1.e-14;
00145 control.gtol = 1.e-14;
00146 control.nprint = 0;
00147 }
00148
00149 void LMDiff::Run( int m_dat,int n_par, double* par, lm_evaluate_type *evaluate,
00150 void *data ){Run( m_dat, n_par, par, evaluate, data, &control);}
00151
00152
00153 void LMDiff::Run( int m_dat,int n_par, double* par, lm_evaluate_type *evaluate,
00154 void *data, lm_control_type *control )
00155 {
00156
00157
00158
00159 double *fvec, *diag, *fjac, *qtf, *wa1, *wa2, *wa3, *wa4;
00160 int *ipvt;
00161
00162 int n = n_par;
00163 int m = m_dat;
00164
00165 if (!(fvec = (double*) malloc( m*sizeof(double))) ||
00166 !(diag = (double*) malloc(n* sizeof(double))) ||
00167 !(qtf = (double*) malloc(n* sizeof(double))) ||
00168 !(fjac = (double*) malloc(n*m*sizeof(double))) ||
00169 !(wa1 = (double*) malloc(n* sizeof(double))) ||
00170 !(wa2 = (double*) malloc(n* sizeof(double))) ||
00171 !(wa3 = (double*) malloc(n* sizeof(double))) ||
00172 !(wa4 = (double*) malloc( m*sizeof(double))) ||
00173 !(ipvt = (int*) malloc(n* sizeof(int)))) {
00174 control->info = 9;
00175 return;
00176 }
00177
00178
00179
00180 control->info = 0;
00181 control->nfev = 0;
00182
00183 control->info =
00184 lmdif(
00185 evaluate,
00186 data,
00187 m,
00188 n,
00189 par,
00190 fvec,
00191 control->ftol,
00192 control->xtol,
00193 control->gtol,
00194 control->maxcall*(n+1),
00195 control->epsilon,
00196 diag,
00197 1,
00198 control->stepbound,
00199 control->nprint,
00200 &(control->nfev),
00201 fjac,
00202 m,
00203 ipvt,
00204 qtf,
00205 wa1,
00206 wa2,
00207 wa3,
00208 wa4
00209 );
00210
00211 if (control->info >= 8) control->info = 4;
00212
00213
00214
00215 free(fvec);
00216 free(diag);
00217 free(qtf);
00218 free(fjac);
00219 free(wa1);
00220 free(wa2);
00221 free(wa3 );
00222 free(wa4);
00223 free(ipvt);
00224 }
00225
00226 #endif