| [5443b1] | 1 | /* ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 2 | // 
 | 
|---|
 | 3 | //  Matlab MEX file for the Levenberg - Marquardt minimization algorithm
 | 
|---|
 | 4 | //  Copyright (C) 2007  Manolis Lourakis (lourakis at ics forth gr)
 | 
|---|
 | 5 | //  Institute of Computer Science, Foundation for Research & Technology - Hellas
 | 
|---|
 | 6 | //  Heraklion, Crete, Greece.
 | 
|---|
 | 7 | //
 | 
|---|
 | 8 | //  This program is free software; you can redistribute it and/or modify
 | 
|---|
 | 9 | //  it under the terms of the GNU General Public License as published by
 | 
|---|
 | 10 | //  the Free Software Foundation; either version 2 of the License, or
 | 
|---|
 | 11 | //  (at your option) any later version.
 | 
|---|
 | 12 | //
 | 
|---|
 | 13 | //  This program is distributed in the hope that it will be useful,
 | 
|---|
 | 14 | //  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 15 | //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 16 | //  GNU General Public License for more details.
 | 
|---|
 | 17 | //
 | 
|---|
 | 18 | //////////////////////////////////////////////////////////////////////////////// */
 | 
|---|
 | 19 | 
 | 
|---|
 | 20 | #include <stdio.h>
 | 
|---|
 | 21 | #include <stdlib.h>
 | 
|---|
 | 22 | #include <stdarg.h>
 | 
|---|
 | 23 | #include <math.h>
 | 
|---|
 | 24 | #include <string.h>
 | 
|---|
 | 25 | #include <ctype.h>
 | 
|---|
 | 26 | 
 | 
|---|
 | 27 | #include <levmar.h>
 | 
|---|
 | 28 | 
 | 
|---|
 | 29 | #include <mex.h>
 | 
|---|
 | 30 | 
 | 
|---|
 | 31 | /**
 | 
|---|
 | 32 | #define DEBUG
 | 
|---|
 | 33 | **/
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | #ifndef HAVE_LAPACK
 | 
|---|
 | 36 | #ifdef _MSC_VER
 | 
|---|
 | 37 | #pragma message("LAPACK not available, certain functionalities cannot be compiled!")
 | 
|---|
 | 38 | #else
 | 
|---|
 | 39 | #warning LAPACK not available, certain functionalities cannot be compiled
 | 
|---|
 | 40 | #endif /* _MSC_VER */
 | 
|---|
 | 41 | #endif /* HAVE_LAPACK */
 | 
|---|
 | 42 | 
 | 
|---|
 | 43 | #define __MAX__(A, B)     ((A)>=(B)? (A) : (B))
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 | #define MIN_UNCONSTRAINED     0
 | 
|---|
 | 46 | #define MIN_CONSTRAINED_BC    1
 | 
|---|
 | 47 | #define MIN_CONSTRAINED_LEC   2
 | 
|---|
 | 48 | #define MIN_CONSTRAINED_BLEC  3
 | 
|---|
 | 49 | #define MIN_CONSTRAINED_BLEIC 4
 | 
|---|
 | 50 | #define MIN_CONSTRAINED_BLIC  5
 | 
|---|
 | 51 | #define MIN_CONSTRAINED_LEIC  6
 | 
|---|
 | 52 | #define MIN_CONSTRAINED_LIC   7
 | 
|---|
 | 53 | 
 | 
|---|
 | 54 | struct mexdata {
 | 
|---|
 | 55 |   /* matlab names of the fitting function & its Jacobian */
 | 
|---|
 | 56 |   char *fname, *jacname;
 | 
|---|
 | 57 | 
 | 
|---|
 | 58 |   /* binary flags specifying if input p0 is a row or column vector */
 | 
|---|
 | 59 |   int isrow_p0;
 | 
|---|
 | 60 | 
 | 
|---|
 | 61 |   /* rhs args to be passed to matlab. rhs[0] is reserved for
 | 
|---|
 | 62 |    * passing the parameter vector. If present, problem-specific
 | 
|---|
 | 63 |    * data are passed in rhs[1], rhs[2], etc
 | 
|---|
 | 64 |    */
 | 
|---|
 | 65 |   mxArray **rhs;
 | 
|---|
 | 66 |   int nrhs; /* >= 1 */
 | 
|---|
 | 67 | };
 | 
|---|
 | 68 | 
 | 
|---|
 | 69 | /* display printf-style error messages in matlab */
 | 
|---|
 | 70 | static void matlabFmtdErrMsgTxt(char *fmt, ...)
 | 
|---|
 | 71 | {
 | 
|---|
 | 72 | char  buf[256];
 | 
|---|
 | 73 | va_list args;
 | 
|---|
 | 74 | 
 | 
|---|
 | 75 |   va_start(args, fmt);
 | 
|---|
 | 76 |   vsprintf(buf, fmt, args);
 | 
|---|
 | 77 |   va_end(args);
 | 
|---|
 | 78 | 
 | 
|---|
 | 79 |   mexErrMsgTxt(buf);
 | 
|---|
 | 80 | }
 | 
|---|
 | 81 | 
 | 
|---|
 | 82 | /* display printf-style warning messages in matlab */
 | 
|---|
 | 83 | static void matlabFmtdWarnMsgTxt(char *fmt, ...)
 | 
|---|
 | 84 | {
 | 
|---|
 | 85 | char  buf[256];
 | 
|---|
 | 86 | va_list args;
 | 
|---|
 | 87 | 
 | 
|---|
 | 88 |   va_start(args, fmt);
 | 
|---|
 | 89 |   vsprintf(buf, fmt, args);
 | 
|---|
 | 90 |   va_end(args);
 | 
|---|
 | 91 | 
 | 
|---|
 | 92 |   mexWarnMsgTxt(buf);
 | 
|---|
 | 93 | }
 | 
|---|
 | 94 | 
 | 
|---|
 | 95 | static void func(double *p, double *hx, int m, int n, void *adata)
 | 
|---|
 | 96 | {
 | 
|---|
 | 97 | mxArray *lhs[1];
 | 
|---|
 | 98 | double *mp, *mx;
 | 
|---|
 | 99 | register int i;
 | 
|---|
 | 100 | struct mexdata *dat=(struct mexdata *)adata;
 | 
|---|
 | 101 |     
 | 
|---|
 | 102 |   /* prepare to call matlab */
 | 
|---|
 | 103 |   mp=mxGetPr(dat->rhs[0]);
 | 
|---|
 | 104 |   for(i=0; i<m; ++i)
 | 
|---|
 | 105 |     mp[i]=p[i];
 | 
|---|
 | 106 |     
 | 
|---|
 | 107 |   /* invoke matlab */
 | 
|---|
 | 108 |   mexCallMATLAB(1, lhs, dat->nrhs, dat->rhs, dat->fname);
 | 
|---|
 | 109 | 
 | 
|---|
 | 110 |   /* copy back results & cleanup */
 | 
|---|
 | 111 |   mx=mxGetPr(lhs[0]);
 | 
|---|
 | 112 |   for(i=0; i<n; ++i)
 | 
|---|
 | 113 |     hx[i]=mx[i];
 | 
|---|
 | 114 | 
 | 
|---|
 | 115 |   /* delete the matrix created by matlab */
 | 
|---|
 | 116 |   mxDestroyArray(lhs[0]);
 | 
|---|
 | 117 | }
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 | static void jacfunc(double *p, double *j, int m, int n, void *adata)
 | 
|---|
 | 120 | {
 | 
|---|
 | 121 | mxArray *lhs[1];
 | 
|---|
 | 122 | double *mp;
 | 
|---|
 | 123 | double *mj;
 | 
|---|
 | 124 | register int i, k;
 | 
|---|
 | 125 | struct mexdata *dat=(struct mexdata *)adata;
 | 
|---|
 | 126 |     
 | 
|---|
 | 127 |   /* prepare to call matlab */
 | 
|---|
 | 128 |   mp=mxGetPr(dat->rhs[0]);
 | 
|---|
 | 129 |   for(i=0; i<m; ++i)
 | 
|---|
 | 130 |     mp[i]=p[i];
 | 
|---|
 | 131 | 
 | 
|---|
 | 132 |   /* invoke matlab */
 | 
|---|
 | 133 |   mexCallMATLAB(1, lhs, dat->nrhs, dat->rhs, dat->jacname);
 | 
|---|
 | 134 |     
 | 
|---|
 | 135 |   /* copy back results & cleanup. Note that the nxm Jacobian 
 | 
|---|
 | 136 |    * computed by matlab should be transposed so that
 | 
|---|
 | 137 |    * levmar gets it in row major, as expected
 | 
|---|
 | 138 |    */
 | 
|---|
 | 139 |   mj=mxGetPr(lhs[0]);
 | 
|---|
 | 140 |   for(i=0; i<n; ++i)
 | 
|---|
 | 141 |     for(k=0; k<m; ++k)
 | 
|---|
 | 142 |       j[i*m+k]=mj[i+k*n];
 | 
|---|
 | 143 | 
 | 
|---|
 | 144 |   /* delete the matrix created by matlab */
 | 
|---|
 | 145 |   mxDestroyArray(lhs[0]);
 | 
|---|
 | 146 | }
 | 
|---|
 | 147 | 
 | 
|---|
 | 148 | /* matlab matrices are in column-major, this routine converts them to row major for levmar */
 | 
|---|
 | 149 | static double *getTranspose(mxArray *Am)
 | 
|---|
 | 150 | {
 | 
|---|
 | 151 | int m, n;
 | 
|---|
 | 152 | double *At, *A;
 | 
|---|
 | 153 | register int i, j;
 | 
|---|
 | 154 | 
 | 
|---|
 | 155 |   m=mxGetM(Am);
 | 
|---|
 | 156 |   n=mxGetN(Am);
 | 
|---|
 | 157 |   A=mxGetPr(Am);
 | 
|---|
 | 158 |   At=mxMalloc(m*n*sizeof(double));
 | 
|---|
 | 159 | 
 | 
|---|
 | 160 |   for(i=0; i<m; i++)
 | 
|---|
 | 161 |     for(j=0; j<n; j++)
 | 
|---|
 | 162 |       At[i*n+j]=A[i+j*m];
 | 
|---|
 | 163 |   
 | 
|---|
 | 164 |   return At;
 | 
|---|
 | 165 | }
 | 
|---|
 | 166 | 
 | 
|---|
 | 167 | /* check the supplied matlab function and its Jacobian. Returns 1 on error, 0 otherwise */
 | 
|---|
 | 168 | static int checkFuncAndJacobian(double *p, int  m, int n, int havejac, struct mexdata *dat)
 | 
|---|
 | 169 | {
 | 
|---|
 | 170 | mxArray *lhs[1];
 | 
|---|
 | 171 | register int i;
 | 
|---|
 | 172 | int ret=0;
 | 
|---|
 | 173 | double *mp;
 | 
|---|
 | 174 | 
 | 
|---|
 | 175 |   mexSetTrapFlag(1); /* handle errors in the MEX-file */
 | 
|---|
 | 176 | 
 | 
|---|
 | 177 |   mp=mxGetPr(dat->rhs[0]);
 | 
|---|
 | 178 |   for(i=0; i<m; ++i)
 | 
|---|
 | 179 |     mp[i]=p[i];
 | 
|---|
 | 180 | 
 | 
|---|
 | 181 |   /* attempt to call the supplied func */
 | 
|---|
 | 182 |   i=mexCallMATLAB(1, lhs, dat->nrhs, dat->rhs, dat->fname);
 | 
|---|
 | 183 |   if(i){
 | 
|---|
 | 184 |     fprintf(stderr, "levmar: error calling '%s'.\n", dat->fname);
 | 
|---|
 | 185 |     ret=1;
 | 
|---|
 | 186 |   }
 | 
|---|
 | 187 |   else if(!mxIsDouble(lhs[0]) || mxIsComplex(lhs[0]) || !(mxGetM(lhs[0])==1 || mxGetN(lhs[0])==1) ||
 | 
|---|
 | 188 |       __MAX__(mxGetM(lhs[0]), mxGetN(lhs[0]))!=n){
 | 
|---|
 | 189 |     fprintf(stderr, "levmar: '%s' should produce a real vector with %d elements (got %d).\n",
 | 
|---|
 | 190 |                     dat->fname, n, __MAX__(mxGetM(lhs[0]), mxGetN(lhs[0])));
 | 
|---|
 | 191 |     ret=1;
 | 
|---|
 | 192 |   }
 | 
|---|
 | 193 |   /* delete the matrix created by matlab */
 | 
|---|
 | 194 |   mxDestroyArray(lhs[0]);
 | 
|---|
 | 195 | 
 | 
|---|
 | 196 |   if(havejac){
 | 
|---|
 | 197 |     /* attempt to call the supplied jac  */
 | 
|---|
 | 198 |     i=mexCallMATLAB(1, lhs, dat->nrhs, dat->rhs, dat->jacname);
 | 
|---|
 | 199 |     if(i){
 | 
|---|
 | 200 |       fprintf(stderr, "levmar: error calling '%s'.\n", dat->jacname);
 | 
|---|
 | 201 |       ret=1;
 | 
|---|
 | 202 |     }
 | 
|---|
 | 203 |     else if(!mxIsDouble(lhs[0]) || mxIsComplex(lhs[0]) || mxGetM(lhs[0])!=n || mxGetN(lhs[0])!=m){
 | 
|---|
 | 204 |       fprintf(stderr, "levmar: '%s' should produce a real %dx%d matrix (got %dx%d).\n",
 | 
|---|
 | 205 |                       dat->jacname, n, m, mxGetM(lhs[0]), mxGetN(lhs[0]));
 | 
|---|
 | 206 |       ret=1;
 | 
|---|
 | 207 |     }
 | 
|---|
 | 208 |     else if(mxIsSparse(lhs[0])){
 | 
|---|
 | 209 |       fprintf(stderr, "levmar: '%s' should produce a real dense matrix (got a sparse one).\n", dat->jacname);
 | 
|---|
 | 210 |       ret=1;
 | 
|---|
 | 211 |     }
 | 
|---|
 | 212 |     /* delete the matrix created by matlab */
 | 
|---|
 | 213 |     mxDestroyArray(lhs[0]);
 | 
|---|
 | 214 |   }
 | 
|---|
 | 215 | 
 | 
|---|
 | 216 |   mexSetTrapFlag(0); /* on error terminate the MEX-file and return control to the MATLAB prompt */
 | 
|---|
 | 217 | 
 | 
|---|
 | 218 |   return ret;
 | 
|---|
 | 219 | }
 | 
|---|
 | 220 | 
 | 
|---|
 | 221 | 
 | 
|---|
 | 222 | /*
 | 
|---|
 | 223 | [ret, p, info, covar]=levmar_der (f, j, p0, x, itmax, opts, 'unc'                              ...)
 | 
|---|
 | 224 | [ret, p, info, covar]=levmar_bc  (f, j, p0, x, itmax, opts, 'bc',   lb, ub,                    ...)
 | 
|---|
 | 225 | [ret, p, info, covar]=levmar_bc  (f, j, p0, x, itmax, opts, 'bc',   lb, ub, dscl,              ...)
 | 
|---|
 | 226 | [ret, p, info, covar]=levmar_lec (f, j, p0, x, itmax, opts, 'lec',                A, b,        ...)
 | 
|---|
 | 227 | [ret, p, info, covar]=levmar_blec(f, j, p0, x, itmax, opts, 'blec', lb, ub,       A, b, wghts, ...)
 | 
|---|
 | 228 | 
 | 
|---|
 | 229 | [ret, p, info, covar]=levmar_bleic(f, j, p0, x, itmax, opts, 'bleic', lb, ub,       A, b, C, d, ...)
 | 
|---|
 | 230 | [ret, p, info, covar]=levmar_blic (f, j, p0, x, itmax, opts, 'blic',  lb, ub,             C, d, ...)
 | 
|---|
 | 231 | [ret, p, info, covar]=levmar_leic (f, j, p0, x, itmax, opts, 'leic',                A, b, C, d, ...)
 | 
|---|
 | 232 | [ret, p, info, covar]=levmar_lic  (f, j, p0, x, itmax, opts, 'lic',                       C, d, ...)
 | 
|---|
 | 233 | 
 | 
|---|
 | 234 | */
 | 
|---|
 | 235 | 
 | 
|---|
 | 236 | void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *Prhs[])
 | 
|---|
 | 237 | {
 | 
|---|
 | 238 | register int i;
 | 
|---|
 | 239 | register double *pdbl;
 | 
|---|
 | 240 | mxArray **prhs=(mxArray **)&Prhs[0], *At, *Ct;
 | 
|---|
 | 241 | struct mexdata mdata;
 | 
|---|
 | 242 | int len, status;
 | 
|---|
 | 243 | double *p, *p0, *ret, *x;
 | 
|---|
 | 244 | int m, n, havejac, Arows, Crows, itmax, nopts, mintype, nextra;
 | 
|---|
 | 245 | double opts[LM_OPTS_SZ]={LM_INIT_MU, LM_STOP_THRESH, LM_STOP_THRESH, LM_STOP_THRESH, LM_DIFF_DELTA};
 | 
|---|
 | 246 | double info[LM_INFO_SZ];
 | 
|---|
 | 247 | double *lb=NULL, *ub=NULL, *dscl=NULL, *A=NULL, *b=NULL, *wghts=NULL, *C=NULL, *d=NULL, *covar=NULL;
 | 
|---|
 | 248 | 
 | 
|---|
 | 249 |   /* parse input args; start by checking their number */
 | 
|---|
 | 250 |   if((nrhs<5))
 | 
|---|
 | 251 |     matlabFmtdErrMsgTxt("levmar: at least 5 input arguments required (got %d).", nrhs);
 | 
|---|
 | 252 |   if(nlhs>4)
 | 
|---|
 | 253 |     matlabFmtdErrMsgTxt("levmar: too many output arguments (max. 4, got %d).", nlhs);
 | 
|---|
 | 254 |   else if(nlhs<2)
 | 
|---|
 | 255 |     matlabFmtdErrMsgTxt("levmar: too few output arguments (min. 2, got %d).", nlhs);
 | 
|---|
 | 256 |     
 | 
|---|
 | 257 |   /* note that in order to accommodate optional args, prhs & nrhs are adjusted accordingly below */
 | 
|---|
 | 258 | 
 | 
|---|
 | 259 |   /** func **/
 | 
|---|
 | 260 |   /* first argument must be a string , i.e. a char row vector */
 | 
|---|
 | 261 |   if(mxIsChar(prhs[0])!=1)
 | 
|---|
 | 262 |     mexErrMsgTxt("levmar: first argument must be a string.");
 | 
|---|
 | 263 |   if(mxGetM(prhs[0])!=1)
 | 
|---|
 | 264 |     mexErrMsgTxt("levmar: first argument must be a string (i.e. char row vector).");
 | 
|---|
 | 265 |   /* store supplied name */
 | 
|---|
 | 266 |   len=mxGetN(prhs[0])+1;
 | 
|---|
 | 267 |   mdata.fname=mxCalloc(len, sizeof(char));
 | 
|---|
 | 268 |   status=mxGetString(prhs[0], mdata.fname, len);
 | 
|---|
 | 269 |   if(status!=0)
 | 
|---|
 | 270 |     mexErrMsgTxt("levmar: not enough space. String is truncated.");
 | 
|---|
 | 271 | 
 | 
|---|
 | 272 |   /** jac (optional) **/
 | 
|---|
 | 273 |   /* check whether second argument is a string */
 | 
|---|
 | 274 |   if(mxIsChar(prhs[1])==1){
 | 
|---|
 | 275 |     if(mxGetM(prhs[1])!=1)
 | 
|---|
 | 276 |       mexErrMsgTxt("levmar: second argument must be a string (i.e. row vector).");
 | 
|---|
 | 277 |     /* store supplied name */
 | 
|---|
 | 278 |     len=mxGetN(prhs[1])+1;
 | 
|---|
 | 279 |     mdata.jacname=mxCalloc(len, sizeof(char));
 | 
|---|
 | 280 |     status=mxGetString(prhs[1], mdata.jacname, len);
 | 
|---|
 | 281 |     if(status!=0)
 | 
|---|
 | 282 |       mexErrMsgTxt("levmar: not enough space. String is truncated.");
 | 
|---|
 | 283 |     havejac=1;
 | 
|---|
 | 284 | 
 | 
|---|
 | 285 |     ++prhs;
 | 
|---|
 | 286 |     --nrhs;
 | 
|---|
 | 287 |   }
 | 
|---|
 | 288 |   else{
 | 
|---|
 | 289 |     mdata.jacname=NULL;
 | 
|---|
 | 290 |     havejac=0;
 | 
|---|
 | 291 |   }
 | 
|---|
 | 292 | 
 | 
|---|
 | 293 | #ifdef DEBUG
 | 
|---|
 | 294 |   fflush(stderr);
 | 
|---|
 | 295 |   fprintf(stderr, "LEVMAR: %s analytic Jacobian\n", havejac? "with" : "no");
 | 
|---|
 | 296 | #endif /* DEBUG */
 | 
|---|
 | 297 | 
 | 
|---|
 | 298 | /* CHECK 
 | 
|---|
 | 299 | if(!mxIsDouble(prhs[1]) || mxIsComplex(prhs[1]) || !(mxGetM(prhs[1])==1 && mxGetN(prhs[1])==1))
 | 
|---|
 | 300 | */
 | 
|---|
 | 301 | 
 | 
|---|
 | 302 |   /** p0 **/
 | 
|---|
 | 303 |   /* the second required argument must be a real row or column vector */
 | 
|---|
 | 304 |   if(!mxIsDouble(prhs[1]) || mxIsComplex(prhs[1]) || !(mxGetM(prhs[1])==1 || mxGetN(prhs[1])==1))
 | 
|---|
 | 305 |     mexErrMsgTxt("levmar: p0 must be a real vector.");
 | 
|---|
 | 306 |   p0=mxGetPr(prhs[1]);
 | 
|---|
 | 307 |   /* determine if we have a row or column vector and retrieve its 
 | 
|---|
 | 308 |    * size, i.e. the number of parameters
 | 
|---|
 | 309 |    */
 | 
|---|
 | 310 |   if(mxGetM(prhs[1])==1){
 | 
|---|
 | 311 |     m=mxGetN(prhs[1]);
 | 
|---|
 | 312 |     mdata.isrow_p0=1;
 | 
|---|
 | 313 |   }
 | 
|---|
 | 314 |   else{
 | 
|---|
 | 315 |     m=mxGetM(prhs[1]);
 | 
|---|
 | 316 |     mdata.isrow_p0=0;
 | 
|---|
 | 317 |   }
 | 
|---|
 | 318 |   /* copy input parameter vector to avoid destroying it */
 | 
|---|
 | 319 |   p=mxMalloc(m*sizeof(double));
 | 
|---|
 | 320 |   for(i=0; i<m; ++i)
 | 
|---|
 | 321 |     p[i]=p0[i];
 | 
|---|
 | 322 |     
 | 
|---|
 | 323 |   /** x **/
 | 
|---|
 | 324 |   /* the third required argument must be a real row or column vector */
 | 
|---|
 | 325 |   if(!mxIsDouble(prhs[2]) || mxIsComplex(prhs[2]) || !(mxGetM(prhs[2])==1 || mxGetN(prhs[2])==1))
 | 
|---|
 | 326 |     mexErrMsgTxt("levmar: x must be a real vector.");
 | 
|---|
 | 327 |   x=mxGetPr(prhs[2]);
 | 
|---|
 | 328 |   n=__MAX__(mxGetM(prhs[2]), mxGetN(prhs[2]));
 | 
|---|
 | 329 | 
 | 
|---|
 | 330 |   /** itmax **/
 | 
|---|
 | 331 |   /* the fourth required argument must be a scalar */
 | 
|---|
 | 332 |   if(!mxIsDouble(prhs[3]) || mxIsComplex(prhs[3]) || mxGetM(prhs[3])!=1 || mxGetN(prhs[3])!=1)
 | 
|---|
 | 333 |     mexErrMsgTxt("levmar: itmax must be a scalar.");
 | 
|---|
 | 334 |   itmax=(int)mxGetScalar(prhs[3]);
 | 
|---|
 | 335 |     
 | 
|---|
 | 336 |   /** opts **/
 | 
|---|
 | 337 |   /* the fifth required argument must be a real row or column vector */
 | 
|---|
 | 338 |   if(!mxIsDouble(prhs[4]) || mxIsComplex(prhs[4]) || (!(mxGetM(prhs[4])==1 || mxGetN(prhs[4])==1) &&
 | 
|---|
 | 339 |                                                       !(mxGetM(prhs[4])==0 && mxGetN(prhs[4])==0)))
 | 
|---|
 | 340 |     mexErrMsgTxt("levmar: opts must be a real vector.");
 | 
|---|
 | 341 |   pdbl=mxGetPr(prhs[4]);
 | 
|---|
 | 342 |   nopts=__MAX__(mxGetM(prhs[4]), mxGetN(prhs[4]));
 | 
|---|
 | 343 |   if(nopts!=0){ /* if opts==[], nothing needs to be done and the defaults are used */
 | 
|---|
 | 344 |     if(nopts>LM_OPTS_SZ)
 | 
|---|
 | 345 |       matlabFmtdErrMsgTxt("levmar: opts must have at most %d elements, got %d.", LM_OPTS_SZ, nopts);
 | 
|---|
 | 346 |     else if(nopts<((havejac)? LM_OPTS_SZ-1 : LM_OPTS_SZ))
 | 
|---|
 | 347 |       matlabFmtdWarnMsgTxt("levmar: only the %d first elements of opts specified, remaining set to defaults.", nopts);
 | 
|---|
 | 348 |     for(i=0; i<nopts; ++i)
 | 
|---|
 | 349 |       opts[i]=pdbl[i];
 | 
|---|
 | 350 |   }
 | 
|---|
 | 351 | #ifdef DEBUG
 | 
|---|
 | 352 |   else{
 | 
|---|
 | 353 |     fflush(stderr);
 | 
|---|
 | 354 |     fprintf(stderr, "LEVMAR: empty options vector, using defaults\n");
 | 
|---|
 | 355 |   }
 | 
|---|
 | 356 | #endif /* DEBUG */
 | 
|---|
 | 357 | 
 | 
|---|
 | 358 |   /** mintype (optional) **/
 | 
|---|
 | 359 |   /* check whether sixth argument is a string */
 | 
|---|
 | 360 |   if(nrhs>=6 && mxIsChar(prhs[5])==1 && mxGetM(prhs[5])==1){
 | 
|---|
 | 361 |     char *minhowto;
 | 
|---|
 | 362 | 
 | 
|---|
 | 363 |     /* examine supplied name */
 | 
|---|
 | 364 |     len=mxGetN(prhs[5])+1;
 | 
|---|
 | 365 |     minhowto=mxCalloc(len, sizeof(char));
 | 
|---|
 | 366 |     status=mxGetString(prhs[5], minhowto, len);
 | 
|---|
 | 367 |     if(status!=0)
 | 
|---|
 | 368 |       mexErrMsgTxt("levmar: not enough space. String is truncated.");
 | 
|---|
 | 369 | 
 | 
|---|
 | 370 |     for(i=0; minhowto[i]; ++i)
 | 
|---|
 | 371 |       minhowto[i]=tolower(minhowto[i]);
 | 
|---|
 | 372 |     if(!strncmp(minhowto, "unc", 3)) mintype=MIN_UNCONSTRAINED;
 | 
|---|
 | 373 |     else if(!strncmp(minhowto, "bc", 2)) mintype=MIN_CONSTRAINED_BC;
 | 
|---|
 | 374 |     else if(!strncmp(minhowto, "lec", 3)) mintype=MIN_CONSTRAINED_LEC;
 | 
|---|
 | 375 |     else if(!strncmp(minhowto, "blec", 4)) mintype=MIN_CONSTRAINED_BLEC;
 | 
|---|
 | 376 |     else if(!strncmp(minhowto, "bleic", 5)) mintype=MIN_CONSTRAINED_BLEIC;
 | 
|---|
 | 377 |     else if(!strncmp(minhowto, "blic", 4)) mintype=MIN_CONSTRAINED_BLIC;
 | 
|---|
 | 378 |     else if(!strncmp(minhowto, "leic", 4)) mintype=MIN_CONSTRAINED_LEIC;
 | 
|---|
 | 379 |     else if(!strncmp(minhowto, "lic", 3)) mintype=MIN_CONSTRAINED_BLIC;
 | 
|---|
 | 380 |     else matlabFmtdErrMsgTxt("levmar: unknown minimization type '%s'.", minhowto);
 | 
|---|
 | 381 | 
 | 
|---|
 | 382 |     mxFree(minhowto);
 | 
|---|
 | 383 | 
 | 
|---|
 | 384 |     ++prhs;
 | 
|---|
 | 385 |     --nrhs;
 | 
|---|
 | 386 |   }
 | 
|---|
 | 387 |   else
 | 
|---|
 | 388 |     mintype=MIN_UNCONSTRAINED;
 | 
|---|
 | 389 | 
 | 
|---|
 | 390 |   if(mintype==MIN_UNCONSTRAINED) goto extraargs;
 | 
|---|
 | 391 | 
 | 
|---|
 | 392 |   /* arguments below this point are optional and their presence depends
 | 
|---|
 | 393 |    * upon the minimization type determined above
 | 
|---|
 | 394 |    */
 | 
|---|
 | 395 |   /** lb, ub **/
 | 
|---|
 | 396 |   if(nrhs>=7 && (mintype==MIN_CONSTRAINED_BC || mintype==MIN_CONSTRAINED_BLEC || mintype==MIN_CONSTRAINED_BLIC || mintype==MIN_CONSTRAINED_BLEIC)){
 | 
|---|
 | 397 |     /* check if the next two arguments are real row or column vectors */
 | 
|---|
 | 398 |     if(mxIsDouble(prhs[5]) && !mxIsComplex(prhs[5]) && (mxGetM(prhs[5])==1 || mxGetN(prhs[5])==1)){
 | 
|---|
 | 399 |       if(mxIsDouble(prhs[6]) && !mxIsComplex(prhs[6]) && (mxGetM(prhs[6])==1 || mxGetN(prhs[6])==1)){
 | 
|---|
 | 400 |         if((i=__MAX__(mxGetM(prhs[5]), mxGetN(prhs[5])))!=m)
 | 
|---|
 | 401 |           matlabFmtdErrMsgTxt("levmar: lb must have %d elements, got %d.", m, i);
 | 
|---|
 | 402 |         if((i=__MAX__(mxGetM(prhs[6]), mxGetN(prhs[6])))!=m)
 | 
|---|
 | 403 |           matlabFmtdErrMsgTxt("levmar: ub must have %d elements, got %d.", m, i);
 | 
|---|
 | 404 | 
 | 
|---|
 | 405 |         lb=mxGetPr(prhs[5]);
 | 
|---|
 | 406 |         ub=mxGetPr(prhs[6]);
 | 
|---|
 | 407 | 
 | 
|---|
 | 408 |         prhs+=2;
 | 
|---|
 | 409 |         nrhs-=2;
 | 
|---|
 | 410 |       }
 | 
|---|
 | 411 |     }
 | 
|---|
 | 412 |   }
 | 
|---|
 | 413 | 
 | 
|---|
 | 414 |   /** dscl **/
 | 
|---|
 | 415 |   if(nrhs>=7 && (mintype==MIN_CONSTRAINED_BC)){
 | 
|---|
 | 416 |     /* check if the next argument is a real row or column vector */
 | 
|---|
 | 417 |     if(mxIsDouble(prhs[5]) && !mxIsComplex(prhs[5]) && (mxGetM(prhs[5])==1 || mxGetN(prhs[5])==1)){
 | 
|---|
 | 418 |       if((i=__MAX__(mxGetM(prhs[5]), mxGetN(prhs[5])))!=m)
 | 
|---|
 | 419 |         matlabFmtdErrMsgTxt("levmar: dscl must have %d elements, got %d.", m, i);
 | 
|---|
 | 420 | 
 | 
|---|
 | 421 |       dscl=mxGetPr(prhs[5]);
 | 
|---|
 | 422 | 
 | 
|---|
 | 423 |       ++prhs;
 | 
|---|
 | 424 |       --nrhs;
 | 
|---|
 | 425 |     }
 | 
|---|
 | 426 |   }
 | 
|---|
 | 427 | 
 | 
|---|
 | 428 |   /** A, b **/
 | 
|---|
 | 429 |   if(nrhs>=7 && (mintype==MIN_CONSTRAINED_LEC || mintype==MIN_CONSTRAINED_BLEC || mintype==MIN_CONSTRAINED_LEIC || mintype==MIN_CONSTRAINED_BLEIC)){
 | 
|---|
 | 430 |     /* check if the next two arguments are a real matrix and a real row or column vector */
 | 
|---|
 | 431 |     if(mxIsDouble(prhs[5]) && !mxIsComplex(prhs[5]) && mxGetM(prhs[5])>=1 && mxGetN(prhs[5])>=1){
 | 
|---|
 | 432 |       if(mxIsDouble(prhs[6]) && !mxIsComplex(prhs[6]) && (mxGetM(prhs[6])==1 || mxGetN(prhs[6])==1)){
 | 
|---|
 | 433 |         if((i=mxGetN(prhs[5]))!=m)
 | 
|---|
 | 434 |           matlabFmtdErrMsgTxt("levmar: A must have %d columns, got %d.", m, i);
 | 
|---|
 | 435 |         if((i=__MAX__(mxGetM(prhs[6]), mxGetN(prhs[6])))!=(Arows=mxGetM(prhs[5])))
 | 
|---|
 | 436 |           matlabFmtdErrMsgTxt("levmar: b must have %d elements, got %d.", Arows, i);
 | 
|---|
 | 437 | 
 | 
|---|
 | 438 |         At=prhs[5];
 | 
|---|
 | 439 |         b=mxGetPr(prhs[6]);
 | 
|---|
 | 440 |         A=getTranspose(At);
 | 
|---|
 | 441 | 
 | 
|---|
 | 442 |         prhs+=2;
 | 
|---|
 | 443 |         nrhs-=2;
 | 
|---|
 | 444 |       }
 | 
|---|
 | 445 |     }
 | 
|---|
 | 446 |   }
 | 
|---|
 | 447 | 
 | 
|---|
 | 448 |   /* wghts */
 | 
|---|
 | 449 |   /* check if we have a weights vector */
 | 
|---|
 | 450 |   if(nrhs>=6 && mintype==MIN_CONSTRAINED_BLEC){ /* only check if we have seen both box & linear constraints */
 | 
|---|
 | 451 |     if(mxIsDouble(prhs[5]) && !mxIsComplex(prhs[5]) && (mxGetM(prhs[5])==1 || mxGetN(prhs[5])==1)){
 | 
|---|
 | 452 |       if(__MAX__(mxGetM(prhs[5]), mxGetN(prhs[5]))==m){
 | 
|---|
 | 453 |         wghts=mxGetPr(prhs[5]);
 | 
|---|
 | 454 | 
 | 
|---|
 | 455 |         ++prhs;
 | 
|---|
 | 456 |         --nrhs;
 | 
|---|
 | 457 |       }
 | 
|---|
 | 458 |     }
 | 
|---|
 | 459 |   }
 | 
|---|
 | 460 | 
 | 
|---|
 | 461 |   /** C, d **/
 | 
|---|
 | 462 |   if(nrhs>=7 && (mintype==MIN_CONSTRAINED_BLEIC || mintype==MIN_CONSTRAINED_BLIC || mintype==MIN_CONSTRAINED_LEIC || mintype==MIN_CONSTRAINED_LIC)){
 | 
|---|
 | 463 |     /* check if the next two arguments are a real matrix and a real row or column vector */
 | 
|---|
 | 464 |     if(mxIsDouble(prhs[5]) && !mxIsComplex(prhs[5]) && mxGetM(prhs[5])>=1 && mxGetN(prhs[5])>=1){
 | 
|---|
 | 465 |       if(mxIsDouble(prhs[6]) && !mxIsComplex(prhs[6]) && (mxGetM(prhs[6])==1 || mxGetN(prhs[6])==1)){
 | 
|---|
 | 466 |         if((i=mxGetN(prhs[5]))!=m)
 | 
|---|
 | 467 |           matlabFmtdErrMsgTxt("levmar: C must have %d columns, got %d.", m, i);
 | 
|---|
 | 468 |         if((i=__MAX__(mxGetM(prhs[6]), mxGetN(prhs[6])))!=(Crows=mxGetM(prhs[5])))
 | 
|---|
 | 469 |           matlabFmtdErrMsgTxt("levmar: d must have %d elements, got %d.", Crows, i);
 | 
|---|
 | 470 | 
 | 
|---|
 | 471 |         Ct=prhs[5];
 | 
|---|
 | 472 |         d=mxGetPr(prhs[6]);
 | 
|---|
 | 473 |         C=getTranspose(Ct);
 | 
|---|
 | 474 | 
 | 
|---|
 | 475 |         prhs+=2;
 | 
|---|
 | 476 |         nrhs-=2;
 | 
|---|
 | 477 |       }
 | 
|---|
 | 478 |     }
 | 
|---|
 | 479 |   }
 | 
|---|
 | 480 | 
 | 
|---|
 | 481 |   /* arguments below this point are assumed to be extra arguments passed
 | 
|---|
 | 482 |    * to every invocation of the fitting function and its Jacobian
 | 
|---|
 | 483 |    */
 | 
|---|
 | 484 | 
 | 
|---|
 | 485 | extraargs:
 | 
|---|
 | 486 |   /* handle any extra args and allocate memory for
 | 
|---|
 | 487 |    * passing the current parameter estimate to matlab
 | 
|---|
 | 488 |    */
 | 
|---|
 | 489 |   nextra=nrhs-5;
 | 
|---|
 | 490 |   mdata.nrhs=nextra+1;
 | 
|---|
 | 491 |   mdata.rhs=(mxArray **)mxMalloc(mdata.nrhs*sizeof(mxArray *));
 | 
|---|
 | 492 |   for(i=0; i<nextra; ++i)
 | 
|---|
 | 493 |     mdata.rhs[i+1]=(mxArray *)prhs[nrhs-nextra+i]; /* discard 'const' modifier */
 | 
|---|
 | 494 | #ifdef DEBUG
 | 
|---|
 | 495 |   fflush(stderr);
 | 
|---|
 | 496 |   fprintf(stderr, "LEVMAR: %d extra args\n", nextra);
 | 
|---|
 | 497 | #endif /* DEBUG */
 | 
|---|
 | 498 | 
 | 
|---|
 | 499 |   if(mdata.isrow_p0){ /* row vector */
 | 
|---|
 | 500 |     mdata.rhs[0]=mxCreateDoubleMatrix(1, m, mxREAL);
 | 
|---|
 | 501 |     /*
 | 
|---|
 | 502 |     mxSetM(mdata.rhs[0], 1);
 | 
|---|
 | 503 |     mxSetN(mdata.rhs[0], m);
 | 
|---|
 | 504 |     */
 | 
|---|
 | 505 |   }
 | 
|---|
 | 506 |   else{ /* column vector */
 | 
|---|
 | 507 |     mdata.rhs[0]=mxCreateDoubleMatrix(m, 1, mxREAL);
 | 
|---|
 | 508 |     /*
 | 
|---|
 | 509 |     mxSetM(mdata.rhs[0], m);
 | 
|---|
 | 510 |     mxSetN(mdata.rhs[0], 1);
 | 
|---|
 | 511 |     */
 | 
|---|
 | 512 |   }
 | 
|---|
 | 513 | 
 | 
|---|
 | 514 |   /* ensure that the supplied function & Jacobian are as expected */
 | 
|---|
 | 515 |   if(checkFuncAndJacobian(p, m, n, havejac, &mdata)){
 | 
|---|
 | 516 |     status=LM_ERROR;
 | 
|---|
 | 517 |     goto cleanup;
 | 
|---|
 | 518 |   }
 | 
|---|
 | 519 | 
 | 
|---|
 | 520 |   if(nlhs>3) /* covariance output required */
 | 
|---|
 | 521 |     covar=mxMalloc(m*m*sizeof(double));
 | 
|---|
 | 522 | 
 | 
|---|
 | 523 |   /* invoke levmar */
 | 
|---|
 | 524 |   switch(mintype){
 | 
|---|
 | 525 |     case MIN_UNCONSTRAINED: /* no constraints */
 | 
|---|
 | 526 |       if(havejac)
 | 
|---|
 | 527 |         status=dlevmar_der(func, jacfunc, p, x, m, n, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 528 |       else
 | 
|---|
 | 529 |         status=dlevmar_dif(func,          p, x, m, n, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 530 | #ifdef DEBUG
 | 
|---|
 | 531 |   fflush(stderr);
 | 
|---|
 | 532 |   fprintf(stderr, "LEVMAR: calling dlevmar_der()/dlevmar_dif()\n");
 | 
|---|
 | 533 | #endif /* DEBUG */
 | 
|---|
 | 534 |     break;
 | 
|---|
 | 535 |     case MIN_CONSTRAINED_BC: /* box constraints */
 | 
|---|
 | 536 |       if(havejac)
 | 
|---|
 | 537 |         status=dlevmar_bc_der(func, jacfunc, p, x, m, n, lb, ub, dscl, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 538 |       else
 | 
|---|
 | 539 |         status=dlevmar_bc_dif(func,          p, x, m, n, lb, ub, dscl, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 540 | #ifdef DEBUG
 | 
|---|
 | 541 |   fflush(stderr);
 | 
|---|
 | 542 |   fprintf(stderr, "LEVMAR: calling dlevmar_bc_der()/dlevmar_bc_dif()\n");
 | 
|---|
 | 543 | #endif /* DEBUG */
 | 
|---|
 | 544 |     break;
 | 
|---|
 | 545 |     case MIN_CONSTRAINED_LEC:  /* linear equation constraints */
 | 
|---|
 | 546 | #ifdef HAVE_LAPACK
 | 
|---|
 | 547 |       if(havejac)
 | 
|---|
 | 548 |         status=dlevmar_lec_der(func, jacfunc, p, x, m, n, A, b, Arows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 549 |       else
 | 
|---|
 | 550 |         status=dlevmar_lec_dif(func,          p, x, m, n, A, b, Arows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 551 | #else
 | 
|---|
 | 552 |       mexErrMsgTxt("levmar: no linear constraints support, HAVE_LAPACK was not defined during MEX-file compilation.");
 | 
|---|
 | 553 | #endif /* HAVE_LAPACK */
 | 
|---|
 | 554 | 
 | 
|---|
 | 555 | #ifdef DEBUG
 | 
|---|
 | 556 |   fflush(stderr);
 | 
|---|
 | 557 |   fprintf(stderr, "LEVMAR: calling dlevmar_lec_der()/dlevmar_lec_dif()\n");
 | 
|---|
 | 558 | #endif /* DEBUG */
 | 
|---|
 | 559 |     break;
 | 
|---|
 | 560 |     case MIN_CONSTRAINED_BLEC: /* box & linear equation constraints */
 | 
|---|
 | 561 | #ifdef HAVE_LAPACK
 | 
|---|
 | 562 |       if(havejac)
 | 
|---|
 | 563 |         status=dlevmar_blec_der(func, jacfunc, p, x, m, n, lb, ub, A, b, Arows, wghts, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 564 |       else
 | 
|---|
 | 565 |         status=dlevmar_blec_dif(func,          p, x, m, n, lb, ub, A, b, Arows, wghts, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 566 | #else
 | 
|---|
 | 567 |       mexErrMsgTxt("levmar: no box & linear constraints support, HAVE_LAPACK was not defined during MEX-file compilation.");
 | 
|---|
 | 568 | #endif /* HAVE_LAPACK */
 | 
|---|
 | 569 | 
 | 
|---|
 | 570 | #ifdef DEBUG
 | 
|---|
 | 571 |   fflush(stderr);
 | 
|---|
 | 572 |   fprintf(stderr, "LEVMAR: calling dlevmar_blec_der()/dlevmar_blec_dif()\n");
 | 
|---|
 | 573 | #endif /* DEBUG */
 | 
|---|
 | 574 |     break;
 | 
|---|
 | 575 |     case MIN_CONSTRAINED_BLEIC: /* box, linear equation & inequalities constraints */
 | 
|---|
 | 576 | #ifdef HAVE_LAPACK
 | 
|---|
 | 577 |       if(havejac)
 | 
|---|
 | 578 |         status=dlevmar_bleic_der(func, jacfunc, p, x, m, n, lb, ub, A, b, Arows, C, d, Crows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 579 |       else
 | 
|---|
 | 580 |         status=dlevmar_bleic_dif(func, p, x, m, n, lb, ub, A, b, Arows, C, d, Crows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 581 | #else
 | 
|---|
 | 582 |       mexErrMsgTxt("levmar: no box, linear equation & inequality constraints support, HAVE_LAPACK was not defined during MEX-file compilation.");
 | 
|---|
 | 583 | #endif /* HAVE_LAPACK */
 | 
|---|
 | 584 | 
 | 
|---|
 | 585 | #ifdef DEBUG
 | 
|---|
 | 586 |   fflush(stderr);
 | 
|---|
 | 587 |   fprintf(stderr, "LEVMAR: calling dlevmar_bleic_der()/dlevmar_bleic_dif()\n");
 | 
|---|
 | 588 | #endif /* DEBUG */
 | 
|---|
 | 589 |     break;
 | 
|---|
 | 590 |     case MIN_CONSTRAINED_BLIC: /* box, linear inequalities constraints */
 | 
|---|
 | 591 | #ifdef HAVE_LAPACK
 | 
|---|
 | 592 |       if(havejac)
 | 
|---|
 | 593 |         status=dlevmar_bleic_der(func, jacfunc, p, x, m, n, lb, ub, NULL, NULL, 0, C, d, Crows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 594 |       else
 | 
|---|
 | 595 |         status=dlevmar_bleic_dif(func, p, x, m, n, lb, ub, NULL, NULL, 0, C, d, Crows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 596 | #else
 | 
|---|
 | 597 |       mexErrMsgTxt("levmar: no box & linear inequality constraints support, HAVE_LAPACK was not defined during MEX-file compilation.");
 | 
|---|
 | 598 | #endif /* HAVE_LAPACK */
 | 
|---|
 | 599 | 
 | 
|---|
 | 600 | #ifdef DEBUG
 | 
|---|
 | 601 |   fflush(stderr);
 | 
|---|
 | 602 |   fprintf(stderr, "LEVMAR: calling dlevmar_blic_der()/dlevmar_blic_dif()\n");
 | 
|---|
 | 603 | #endif /* DEBUG */
 | 
|---|
 | 604 |     break;
 | 
|---|
 | 605 |     case MIN_CONSTRAINED_LEIC: /* linear equation & inequalities constraints */
 | 
|---|
 | 606 | #ifdef HAVE_LAPACK
 | 
|---|
 | 607 |       if(havejac)
 | 
|---|
 | 608 |         status=dlevmar_bleic_der(func, jacfunc, p, x, m, n, NULL, NULL, A, b, Arows, C, d, Crows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 609 |       else
 | 
|---|
 | 610 |         status=dlevmar_bleic_dif(func, p, x, m, n, NULL, NULL, A, b, Arows, C, d, Crows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 611 | #else
 | 
|---|
 | 612 |       mexErrMsgTxt("levmar: no linear equation & inequality constraints support, HAVE_LAPACK was not defined during MEX-file compilation.");
 | 
|---|
 | 613 | #endif /* HAVE_LAPACK */
 | 
|---|
 | 614 | 
 | 
|---|
 | 615 | #ifdef DEBUG
 | 
|---|
 | 616 |   fflush(stderr);
 | 
|---|
 | 617 |   fprintf(stderr, "LEVMAR: calling dlevmar_leic_der()/dlevmar_leic_dif()\n");
 | 
|---|
 | 618 | #endif /* DEBUG */
 | 
|---|
 | 619 |     break;
 | 
|---|
 | 620 |     case MIN_CONSTRAINED_LIC: /* linear inequalities constraints */
 | 
|---|
 | 621 | #ifdef HAVE_LAPACK
 | 
|---|
 | 622 |       if(havejac)
 | 
|---|
 | 623 |         status=dlevmar_bleic_der(func, jacfunc, p, x, m, n, NULL, NULL, NULL, NULL, 0, C, d, Crows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 624 |       else
 | 
|---|
 | 625 |         status=dlevmar_bleic_dif(func, p, x, m, n, NULL, NULL, NULL, NULL, 0, C, d, Crows, itmax, opts, info, NULL, covar, (void *)&mdata);
 | 
|---|
 | 626 | #else
 | 
|---|
 | 627 |       mexErrMsgTxt("levmar: no linear equation & inequality constraints support, HAVE_LAPACK was not defined during MEX-file compilation.");
 | 
|---|
 | 628 | #endif /* HAVE_LAPACK */
 | 
|---|
 | 629 | 
 | 
|---|
 | 630 | #ifdef DEBUG
 | 
|---|
 | 631 |   fflush(stderr);
 | 
|---|
 | 632 |   fprintf(stderr, "LEVMAR: calling dlevmar_lic_der()/dlevmar_lic_dif()\n");
 | 
|---|
 | 633 | #endif /* DEBUG */
 | 
|---|
 | 634 |     break;
 | 
|---|
 | 635 |     default:
 | 
|---|
 | 636 |       mexErrMsgTxt("levmar: unexpected internal error.");
 | 
|---|
 | 637 |   }
 | 
|---|
 | 638 | 
 | 
|---|
 | 639 | #ifdef DEBUG
 | 
|---|
 | 640 |   fflush(stderr);
 | 
|---|
 | 641 |   printf("LEVMAR: minimization returned %d in %g iter, reason %g\n\tSolution: ", status, info[5], info[6]);
 | 
|---|
 | 642 |   for(i=0; i<m; ++i)
 | 
|---|
 | 643 |     printf("%.7g ", p[i]);
 | 
|---|
 | 644 |   printf("\n\n\tMinimization info:\n\t");
 | 
|---|
 | 645 |   for(i=0; i<LM_INFO_SZ; ++i)
 | 
|---|
 | 646 |     printf("%g ", info[i]);
 | 
|---|
 | 647 |   printf("\n");
 | 
|---|
 | 648 | #endif /* DEBUG */
 | 
|---|
 | 649 | 
 | 
|---|
 | 650 |   /* copy back return results */
 | 
|---|
 | 651 |   /** ret **/
 | 
|---|
 | 652 |   plhs[0]=mxCreateDoubleMatrix(1, 1, mxREAL);
 | 
|---|
 | 653 |   ret=mxGetPr(plhs[0]);
 | 
|---|
 | 654 |   ret[0]=(double)status;
 | 
|---|
 | 655 | 
 | 
|---|
 | 656 |   /** popt **/
 | 
|---|
 | 657 |   plhs[1]=(mdata.isrow_p0==1)? mxCreateDoubleMatrix(1, m, mxREAL) : mxCreateDoubleMatrix(m, 1, mxREAL);
 | 
|---|
 | 658 |   pdbl=mxGetPr(plhs[1]);
 | 
|---|
 | 659 |   for(i=0; i<m; ++i)
 | 
|---|
 | 660 |     pdbl[i]=p[i];
 | 
|---|
 | 661 | 
 | 
|---|
 | 662 |   /** info **/
 | 
|---|
 | 663 |   if(nlhs>2){
 | 
|---|
 | 664 |     plhs[2]=mxCreateDoubleMatrix(1, LM_INFO_SZ, mxREAL);
 | 
|---|
 | 665 |     pdbl=mxGetPr(plhs[2]);
 | 
|---|
 | 666 |     for(i=0; i<LM_INFO_SZ; ++i)
 | 
|---|
 | 667 |       pdbl[i]=info[i];
 | 
|---|
 | 668 |   }
 | 
|---|
 | 669 | 
 | 
|---|
 | 670 |   /** covar **/
 | 
|---|
 | 671 |   if(nlhs>3){
 | 
|---|
 | 672 |     plhs[3]=mxCreateDoubleMatrix(m, m, mxREAL);
 | 
|---|
 | 673 |     pdbl=mxGetPr(plhs[3]);
 | 
|---|
 | 674 |     for(i=0; i<m*m; ++i) /* covariance matrices are symmetric, thus no need to transpose! */
 | 
|---|
 | 675 |       pdbl[i]=covar[i];
 | 
|---|
 | 676 |   }
 | 
|---|
 | 677 | 
 | 
|---|
 | 678 | cleanup:
 | 
|---|
 | 679 |   /* cleanup */
 | 
|---|
 | 680 |   mxDestroyArray(mdata.rhs[0]);
 | 
|---|
 | 681 |   if(A) mxFree(A);
 | 
|---|
 | 682 |   if(C) mxFree(C);
 | 
|---|
 | 683 | 
 | 
|---|
 | 684 |   mxFree(mdata.fname);
 | 
|---|
 | 685 |   if(havejac) mxFree(mdata.jacname);
 | 
|---|
 | 686 |   mxFree(p);
 | 
|---|
 | 687 |   mxFree(mdata.rhs);
 | 
|---|
 | 688 |   if(covar) mxFree(covar);
 | 
|---|
 | 689 | 
 | 
|---|
 | 690 |   if(status==LM_ERROR)
 | 
|---|
 | 691 |     mexWarnMsgTxt("levmar: optimization returned with an error!");
 | 
|---|
 | 692 | }
 | 
|---|