| 1 | /////////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 2 | // 
 | 
|---|
| 3 | //  Levenberg - Marquardt non-linear minimization algorithm
 | 
|---|
| 4 | //  Copyright (C) 2004-05  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 | #ifndef LM_REAL // not included by lmlec.c
 | 
|---|
| 21 | #error This file should not be compiled directly!
 | 
|---|
| 22 | #endif
 | 
|---|
| 23 | 
 | 
|---|
| 24 | 
 | 
|---|
| 25 | /* precision-specific definitions */
 | 
|---|
| 26 | #define LMLEC_DATA LM_ADD_PREFIX(lmlec_data)
 | 
|---|
| 27 | #define LMLEC_ELIM LM_ADD_PREFIX(lmlec_elim)
 | 
|---|
| 28 | #define LMLEC_FUNC LM_ADD_PREFIX(lmlec_func)
 | 
|---|
| 29 | #define LMLEC_JACF LM_ADD_PREFIX(lmlec_jacf)
 | 
|---|
| 30 | #define LEVMAR_LEC_DER LM_ADD_PREFIX(levmar_lec_der)
 | 
|---|
| 31 | #define LEVMAR_LEC_DIF LM_ADD_PREFIX(levmar_lec_dif)
 | 
|---|
| 32 | #define LEVMAR_DER LM_ADD_PREFIX(levmar_der)
 | 
|---|
| 33 | #define LEVMAR_DIF LM_ADD_PREFIX(levmar_dif)
 | 
|---|
| 34 | #define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
 | 
|---|
| 35 | #define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
 | 
|---|
| 36 | #define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
 | 
|---|
| 37 | 
 | 
|---|
| 38 | #define GEQP3 LM_MK_LAPACK_NAME(geqp3)
 | 
|---|
| 39 | #define ORGQR LM_MK_LAPACK_NAME(orgqr)
 | 
|---|
| 40 | #define TRTRI LM_MK_LAPACK_NAME(trtri)
 | 
|---|
| 41 | 
 | 
|---|
| 42 | struct LMLEC_DATA{
 | 
|---|
| 43 |   LM_REAL *c, *Z, *p, *jac;
 | 
|---|
| 44 |   int ncnstr;
 | 
|---|
| 45 |   void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata);
 | 
|---|
| 46 |   void (*jacf)(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata);
 | 
|---|
| 47 |   void *adata;
 | 
|---|
| 48 | };
 | 
|---|
| 49 | 
 | 
|---|
| 50 | /* prototypes for LAPACK routines */
 | 
|---|
| 51 | #ifdef __cplusplus
 | 
|---|
| 52 | extern "C" {
 | 
|---|
| 53 | #endif
 | 
|---|
| 54 | extern int GEQP3(int *m, int *n, LM_REAL *a, int *lda, int *jpvt,
 | 
|---|
| 55 |                    LM_REAL *tau, LM_REAL *work, int *lwork, int *info);
 | 
|---|
| 56 | 
 | 
|---|
| 57 | extern int ORGQR(int *m, int *n, int *k, LM_REAL *a, int *lda, LM_REAL *tau,
 | 
|---|
| 58 |                    LM_REAL *work, int *lwork, int *info);
 | 
|---|
| 59 | 
 | 
|---|
| 60 | extern int TRTRI(char *uplo, char *diag, int *n, LM_REAL *a, int *lda, int *info);
 | 
|---|
| 61 | #ifdef __cplusplus
 | 
|---|
| 62 | }
 | 
|---|
| 63 | #endif
 | 
|---|
| 64 | 
 | 
|---|
| 65 | /*
 | 
|---|
| 66 |  * This function implements an elimination strategy for linearly constrained
 | 
|---|
| 67 |  * optimization problems. The strategy relies on QR decomposition to transform
 | 
|---|
| 68 |  * an optimization problem constrained by Ax=b to an equivalent, unconstrained
 | 
|---|
| 69 |  * one. Also referred to as "null space" or "reduced Hessian" method.
 | 
|---|
| 70 |  * See pp. 430-433 (chap. 15) of "Numerical Optimization" by Nocedal-Wright
 | 
|---|
| 71 |  * for details.
 | 
|---|
| 72 |  *
 | 
|---|
| 73 |  * A is mxn with m<=n and rank(A)=m
 | 
|---|
| 74 |  * Two matrices Y and Z of dimensions nxm and nx(n-m) are computed from A^T so that
 | 
|---|
| 75 |  * their columns are orthonormal and every x can be written as x=Y*b + Z*x_z=
 | 
|---|
| 76 |  * c + Z*x_z, where c=Y*b is a fixed vector of dimension n and x_z is an
 | 
|---|
| 77 |  * arbitrary vector of dimension n-m. Then, the problem of minimizing f(x)
 | 
|---|
| 78 |  * subject to Ax=b is equivalent to minimizing f(c + Z*x_z) with no constraints.
 | 
|---|
| 79 |  * The computed Y and Z are such that any solution of Ax=b can be written as
 | 
|---|
| 80 |  * x=Y*x_y + Z*x_z for some x_y, x_z. Furthermore, A*Y is nonsingular, A*Z=0
 | 
|---|
| 81 |  * and Z spans the null space of A.
 | 
|---|
| 82 |  *
 | 
|---|
| 83 |  * The function accepts A, b and computes c, Y, Z. If b or c is NULL, c is not
 | 
|---|
| 84 |  * computed. Also, Y can be NULL in which case it is not referenced.
 | 
|---|
| 85 |  * The function returns LM_ERROR in case of error, A's computed rank if successful
 | 
|---|
| 86 |  *
 | 
|---|
| 87 |  */
 | 
|---|
| 88 | static int LMLEC_ELIM(LM_REAL *A, LM_REAL *b, LM_REAL *c, LM_REAL *Y, LM_REAL *Z, int m, int n)
 | 
|---|
| 89 | {
 | 
|---|
| 90 | static LM_REAL eps=LM_CNST(-1.0);
 | 
|---|
| 91 | 
 | 
|---|
| 92 | LM_REAL *buf=NULL;
 | 
|---|
| 93 | LM_REAL *a, *tau, *work, *r, aux;
 | 
|---|
| 94 | register LM_REAL tmp;
 | 
|---|
| 95 | int a_sz, jpvt_sz, tau_sz, r_sz, Y_sz, worksz;
 | 
|---|
| 96 | int info, rank, *jpvt, tot_sz, mintmn, tm, tn;
 | 
|---|
| 97 | register int i, j, k;
 | 
|---|
| 98 | 
 | 
|---|
| 99 |   if(m>n){
 | 
|---|
| 100 |     fprintf(stderr, RCAT("matrix of constraints cannot have more rows than columns in", LMLEC_ELIM) "()!\n");
 | 
|---|
| 101 |     return LM_ERROR;
 | 
|---|
| 102 |   }
 | 
|---|
| 103 | 
 | 
|---|
| 104 |   tm=n; tn=m; // transpose dimensions
 | 
|---|
| 105 |   mintmn=m;
 | 
|---|
| 106 | 
 | 
|---|
| 107 |   /* calculate required memory size */
 | 
|---|
| 108 |   worksz=-1; // workspace query. Optimal work size is returned in aux
 | 
|---|
| 109 |   //ORGQR((int *)&tm, (int *)&tm, (int *)&mintmn, NULL, (int *)&tm, NULL, (LM_REAL *)&aux, &worksz, &info);
 | 
|---|
| 110 |   GEQP3((int *)&tm, (int *)&tn, NULL, (int *)&tm, NULL, NULL, (LM_REAL *)&aux, (int *)&worksz, &info);
 | 
|---|
| 111 |   worksz=(int)aux;
 | 
|---|
| 112 |   a_sz=tm*tm; // tm*tn is enough for xgeqp3()
 | 
|---|
| 113 |   jpvt_sz=tn;
 | 
|---|
| 114 |   tau_sz=mintmn;
 | 
|---|
| 115 |   r_sz=mintmn*mintmn; // actually smaller if a is not of full row rank
 | 
|---|
| 116 |   Y_sz=(Y)? 0 : tm*tn;
 | 
|---|
| 117 | 
 | 
|---|
| 118 |   tot_sz=(a_sz + tau_sz + r_sz + worksz + Y_sz)*sizeof(LM_REAL) + jpvt_sz*sizeof(int); /* should be arranged in that order for proper doubles alignment */
 | 
|---|
| 119 |   buf=(LM_REAL *)malloc(tot_sz); /* allocate a "big" memory chunk at once */
 | 
|---|
| 120 |   if(!buf){
 | 
|---|
| 121 |     fprintf(stderr, RCAT("Memory allocation request failed in ", LMLEC_ELIM) "()\n");
 | 
|---|
| 122 |     return LM_ERROR;
 | 
|---|
| 123 |   }
 | 
|---|
| 124 | 
 | 
|---|
| 125 |   a=buf;
 | 
|---|
| 126 |   tau=a+a_sz;
 | 
|---|
| 127 |   r=tau+tau_sz;
 | 
|---|
| 128 |   work=r+r_sz;
 | 
|---|
| 129 |   if(!Y){
 | 
|---|
| 130 |     Y=work+worksz;
 | 
|---|
| 131 |     jpvt=(int *)(Y+Y_sz);
 | 
|---|
| 132 |   }
 | 
|---|
| 133 |   else
 | 
|---|
| 134 |     jpvt=(int *)(work+worksz);
 | 
|---|
| 135 | 
 | 
|---|
| 136 |   /* copy input array so that LAPACK won't destroy it. Note that copying is
 | 
|---|
| 137 |    * done in row-major order, which equals A^T in column-major
 | 
|---|
| 138 |    */
 | 
|---|
| 139 |   for(i=0; i<tm*tn; ++i)
 | 
|---|
| 140 |       a[i]=A[i];
 | 
|---|
| 141 | 
 | 
|---|
| 142 |   /* clear jpvt */
 | 
|---|
| 143 |   for(i=0; i<jpvt_sz; ++i) jpvt[i]=0;
 | 
|---|
| 144 | 
 | 
|---|
| 145 |   /* rank revealing QR decomposition of A^T*/
 | 
|---|
| 146 |   GEQP3((int *)&tm, (int *)&tn, a, (int *)&tm, jpvt, tau, work, (int *)&worksz, &info);
 | 
|---|
| 147 |   //dgeqpf_((int *)&tm, (int *)&tn, a, (int *)&tm, jpvt, tau, work, &info);
 | 
|---|
| 148 |   /* error checking */
 | 
|---|
| 149 |   if(info!=0){
 | 
|---|
| 150 |     if(info<0){
 | 
|---|
| 151 |       fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", GEQP3) " in ", LMLEC_ELIM) "()\n", -info);
 | 
|---|
| 152 |     }
 | 
|---|
| 153 |     else if(info>0){
 | 
|---|
| 154 |       fprintf(stderr, RCAT(RCAT("unknown LAPACK error (%d) for ", GEQP3) " in ", LMLEC_ELIM) "()\n", info);
 | 
|---|
| 155 |     }
 | 
|---|
| 156 |     free(buf);
 | 
|---|
| 157 |     return LM_ERROR;
 | 
|---|
| 158 |   }
 | 
|---|
| 159 |   /* the upper triangular part of a now contains the upper triangle of the unpermuted R */
 | 
|---|
| 160 | 
 | 
|---|
| 161 |   if(eps<0.0){
 | 
|---|
| 162 |     LM_REAL aux;
 | 
|---|
| 163 | 
 | 
|---|
| 164 |     /* compute machine epsilon. DBL_EPSILON should do also */
 | 
|---|
| 165 |     for(eps=LM_CNST(1.0); aux=eps+LM_CNST(1.0), aux-LM_CNST(1.0)>0.0; eps*=LM_CNST(0.5))
 | 
|---|
| 166 |                               ;
 | 
|---|
| 167 |     eps*=LM_CNST(2.0);
 | 
|---|
| 168 |   }
 | 
|---|
| 169 | 
 | 
|---|
| 170 |   tmp=tm*LM_CNST(10.0)*eps*FABS(a[0]); // threshold. tm is max(tm, tn)
 | 
|---|
| 171 |   tmp=(tmp>LM_CNST(1E-12))? tmp : LM_CNST(1E-12); // ensure that threshold is not too small
 | 
|---|
| 172 |   /* compute A^T's numerical rank by counting the non-zeros in R's diagonal */
 | 
|---|
| 173 |   for(i=rank=0; i<mintmn; ++i)
 | 
|---|
| 174 |     if(a[i*(tm+1)]>tmp || a[i*(tm+1)]<-tmp) ++rank; /* loop across R's diagonal elements */
 | 
|---|
| 175 |     else break; /* diagonal is arranged in absolute decreasing order */
 | 
|---|
| 176 | 
 | 
|---|
| 177 |   if(rank<tn){
 | 
|---|
| 178 |     fprintf(stderr, RCAT("\nConstraints matrix in ",  LMLEC_ELIM) "() is not of full row rank (i.e. %d < %d)!\n"
 | 
|---|
| 179 |             "Make sure that you do not specify redundant or inconsistent constraints.\n\n", rank, tn);
 | 
|---|
| 180 |     free(buf);
 | 
|---|
| 181 |     return LM_ERROR;
 | 
|---|
| 182 |   }
 | 
|---|
| 183 | 
 | 
|---|
| 184 |   /* compute the permuted inverse transpose of R */
 | 
|---|
| 185 |   /* first, copy R from the upper triangular part of a to the lower part of r (thus transposing it). R is rank x rank */
 | 
|---|
| 186 |   for(j=0; j<rank; ++j){
 | 
|---|
| 187 |     for(i=0; i<=j; ++i)
 | 
|---|
| 188 |       r[j+i*rank]=a[i+j*tm];
 | 
|---|
| 189 |     for(i=j+1; i<rank; ++i)
 | 
|---|
| 190 |       r[j+i*rank]=0.0; // upper part is zero
 | 
|---|
| 191 |   }
 | 
|---|
| 192 |   /* r now contains R^T */
 | 
|---|
| 193 | 
 | 
|---|
| 194 |   /* compute the inverse */
 | 
|---|
| 195 |   TRTRI("L", "N", (int *)&rank, r, (int *)&rank, &info);
 | 
|---|
| 196 |   /* error checking */
 | 
|---|
| 197 |   if(info!=0){
 | 
|---|
| 198 |     if(info<0){
 | 
|---|
| 199 |       fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", TRTRI) " in ", LMLEC_ELIM) "()\n", -info);
 | 
|---|
| 200 |     }
 | 
|---|
| 201 |     else if(info>0){
 | 
|---|
| 202 |       fprintf(stderr, RCAT(RCAT("A(%d, %d) is exactly zero for ", TRTRI) " (singular matrix) in ", LMLEC_ELIM) "()\n", info, info);
 | 
|---|
| 203 |     }
 | 
|---|
| 204 |     free(buf);
 | 
|---|
| 205 |     return LM_ERROR;
 | 
|---|
| 206 |   }
 | 
|---|
| 207 | 
 | 
|---|
| 208 |   /* finally, permute R^-T using Y as intermediate storage */
 | 
|---|
| 209 |   for(j=0; j<rank; ++j)
 | 
|---|
| 210 |     for(i=0, k=jpvt[j]-1; i<rank; ++i)
 | 
|---|
| 211 |       Y[i+k*rank]=r[i+j*rank];
 | 
|---|
| 212 | 
 | 
|---|
| 213 |   for(i=0; i<rank*rank; ++i) // copy back to r
 | 
|---|
| 214 |     r[i]=Y[i];
 | 
|---|
| 215 | 
 | 
|---|
| 216 |   /* resize a to be tm x tm, filling with zeroes */
 | 
|---|
| 217 |   for(i=tm*tn; i<tm*tm; ++i)
 | 
|---|
| 218 |     a[i]=0.0;
 | 
|---|
| 219 | 
 | 
|---|
| 220 |   /* compute Q in a as the product of elementary reflectors. Q is tm x tm */
 | 
|---|
| 221 |   ORGQR((int *)&tm, (int *)&tm, (int *)&mintmn, a, (int *)&tm, tau, work, &worksz, &info);
 | 
|---|
| 222 |   /* error checking */
 | 
|---|
| 223 |   if(info!=0){
 | 
|---|
| 224 |     if(info<0){
 | 
|---|
| 225 |       fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", ORGQR) " in ", LMLEC_ELIM) "()\n", -info);
 | 
|---|
| 226 |     }
 | 
|---|
| 227 |     else if(info>0){
 | 
|---|
| 228 |       fprintf(stderr, RCAT(RCAT("unknown LAPACK error (%d) for ", ORGQR) " in ", LMLEC_ELIM) "()\n", info);
 | 
|---|
| 229 |     }
 | 
|---|
| 230 |     free(buf);
 | 
|---|
| 231 |     return LM_ERROR;
 | 
|---|
| 232 |   }
 | 
|---|
| 233 | 
 | 
|---|
| 234 |   /* compute Y=Q_1*R^-T*P^T. Y is tm x rank */
 | 
|---|
| 235 |   for(i=0; i<tm; ++i)
 | 
|---|
| 236 |     for(j=0; j<rank; ++j){
 | 
|---|
| 237 |       for(k=0, tmp=0.0; k<rank; ++k)
 | 
|---|
| 238 |         tmp+=a[i+k*tm]*r[k+j*rank];
 | 
|---|
| 239 |       Y[i*rank+j]=tmp;
 | 
|---|
| 240 |     }
 | 
|---|
| 241 | 
 | 
|---|
| 242 |   if(b && c){
 | 
|---|
| 243 |     /* compute c=Y*b */
 | 
|---|
| 244 |     for(i=0; i<tm; ++i){
 | 
|---|
| 245 |       for(j=0, tmp=0.0; j<rank; ++j)
 | 
|---|
| 246 |         tmp+=Y[i*rank+j]*b[j];
 | 
|---|
| 247 | 
 | 
|---|
| 248 |       c[i]=tmp;
 | 
|---|
| 249 |     }
 | 
|---|
| 250 |   }
 | 
|---|
| 251 | 
 | 
|---|
| 252 |   /* copy Q_2 into Z. Z is tm x (tm-rank) */
 | 
|---|
| 253 |   for(j=0; j<tm-rank; ++j)
 | 
|---|
| 254 |     for(i=0, k=j+rank; i<tm; ++i)
 | 
|---|
| 255 |       Z[i*(tm-rank)+j]=a[i+k*tm];
 | 
|---|
| 256 | 
 | 
|---|
| 257 |   free(buf);
 | 
|---|
| 258 | 
 | 
|---|
| 259 |   return rank;
 | 
|---|
| 260 | }
 | 
|---|
| 261 | 
 | 
|---|
| 262 | /* constrained measurements: given pp, compute the measurements at c + Z*pp */
 | 
|---|
| 263 | static void LMLEC_FUNC(LM_REAL *pp, LM_REAL *hx, int mm, int n, void *adata)
 | 
|---|
| 264 | {
 | 
|---|
| 265 | struct LMLEC_DATA *data=(struct LMLEC_DATA *)adata;
 | 
|---|
| 266 | int m;
 | 
|---|
| 267 | register int i, j;
 | 
|---|
| 268 | register LM_REAL sum;
 | 
|---|
| 269 | LM_REAL *c, *Z, *p, *Zimm;
 | 
|---|
| 270 | 
 | 
|---|
| 271 |   m=mm+data->ncnstr;
 | 
|---|
| 272 |   c=data->c;
 | 
|---|
| 273 |   Z=data->Z;
 | 
|---|
| 274 |   p=data->p;
 | 
|---|
| 275 |   /* p=c + Z*pp */
 | 
|---|
| 276 |   for(i=0; i<m; ++i){
 | 
|---|
| 277 |     Zimm=Z+i*mm;
 | 
|---|
| 278 |     for(j=0, sum=c[i]; j<mm; ++j)
 | 
|---|
| 279 |       sum+=Zimm[j]*pp[j]; // sum+=Z[i*mm+j]*pp[j];
 | 
|---|
| 280 |     p[i]=sum;
 | 
|---|
| 281 |   }
 | 
|---|
| 282 | 
 | 
|---|
| 283 |   (*(data->func))(p, hx, m, n, data->adata);
 | 
|---|
| 284 | }
 | 
|---|
| 285 | 
 | 
|---|
| 286 | /* constrained Jacobian: given pp, compute the Jacobian at c + Z*pp
 | 
|---|
| 287 |  * Using the chain rule, the Jacobian with respect to pp equals the
 | 
|---|
| 288 |  * product of the Jacobian with respect to p (at c + Z*pp) times Z
 | 
|---|
| 289 |  */
 | 
|---|
| 290 | static void LMLEC_JACF(LM_REAL *pp, LM_REAL *jacjac, int mm, int n, void *adata)
 | 
|---|
| 291 | {
 | 
|---|
| 292 | struct LMLEC_DATA *data=(struct LMLEC_DATA *)adata;
 | 
|---|
| 293 | int m;
 | 
|---|
| 294 | register int i, j, l;
 | 
|---|
| 295 | register LM_REAL sum, *aux1, *aux2;
 | 
|---|
| 296 | LM_REAL *c, *Z, *p, *jac; 
 | 
|---|
| 297 | 
 | 
|---|
| 298 |   m=mm+data->ncnstr;
 | 
|---|
| 299 |   c=data->c;
 | 
|---|
| 300 |   Z=data->Z;
 | 
|---|
| 301 |   p=data->p;
 | 
|---|
| 302 |   jac=data->jac;
 | 
|---|
| 303 |   /* p=c + Z*pp */
 | 
|---|
| 304 |   for(i=0; i<m; ++i){
 | 
|---|
| 305 |     aux1=Z+i*mm;
 | 
|---|
| 306 |     for(j=0, sum=c[i]; j<mm; ++j)
 | 
|---|
| 307 |       sum+=aux1[j]*pp[j]; // sum+=Z[i*mm+j]*pp[j];
 | 
|---|
| 308 |     p[i]=sum;
 | 
|---|
| 309 |   }
 | 
|---|
| 310 | 
 | 
|---|
| 311 |   (*(data->jacf))(p, jac, m, n, data->adata);
 | 
|---|
| 312 | 
 | 
|---|
| 313 |   /* compute jac*Z in jacjac */
 | 
|---|
| 314 |   if(n*m<=__BLOCKSZ__SQ){ // this is a small problem
 | 
|---|
| 315 |     /* This is the straightforward way to compute jac*Z. However, due to
 | 
|---|
| 316 |      * its noncontinuous memory access pattern, it incures many cache misses when
 | 
|---|
| 317 |      * applied to large minimization problems (i.e. problems involving a large
 | 
|---|
| 318 |      * number of free variables and measurements), in which jac is too large to
 | 
|---|
| 319 |      * fit in the L1 cache. For such problems, a cache-efficient blocking scheme
 | 
|---|
| 320 |      * is preferable. On the other hand, the straightforward algorithm is faster
 | 
|---|
| 321 |      * on small problems since in this case it avoids the overheads of blocking.
 | 
|---|
| 322 |      */
 | 
|---|
| 323 | 
 | 
|---|
| 324 |     for(i=0; i<n; ++i){
 | 
|---|
| 325 |       aux1=jac+i*m;
 | 
|---|
| 326 |       aux2=jacjac+i*mm;
 | 
|---|
| 327 |       for(j=0; j<mm; ++j){
 | 
|---|
| 328 |         for(l=0, sum=0.0; l<m; ++l)
 | 
|---|
| 329 |           sum+=aux1[l]*Z[l*mm+j]; // sum+=jac[i*m+l]*Z[l*mm+j];
 | 
|---|
| 330 | 
 | 
|---|
| 331 |         aux2[j]=sum; // jacjac[i*mm+j]=sum;
 | 
|---|
| 332 |       }
 | 
|---|
| 333 |     }
 | 
|---|
| 334 |   }
 | 
|---|
| 335 |   else{ // this is a large problem
 | 
|---|
| 336 |     /* Cache efficient computation of jac*Z based on blocking
 | 
|---|
| 337 |      */
 | 
|---|
| 338 | #define __MIN__(x, y) (((x)<=(y))? (x) : (y))
 | 
|---|
| 339 |     register int jj, ll;
 | 
|---|
| 340 | 
 | 
|---|
| 341 |     for(jj=0; jj<mm; jj+=__BLOCKSZ__){
 | 
|---|
| 342 |       for(i=0; i<n; ++i){
 | 
|---|
| 343 |         aux1=jacjac+i*mm;
 | 
|---|
| 344 |         for(j=jj; j<__MIN__(jj+__BLOCKSZ__, mm); ++j)
 | 
|---|
| 345 |           aux1[j]=0.0; //jacjac[i*mm+j]=0.0;
 | 
|---|
| 346 |       }
 | 
|---|
| 347 | 
 | 
|---|
| 348 |       for(ll=0; ll<m; ll+=__BLOCKSZ__){
 | 
|---|
| 349 |         for(i=0; i<n; ++i){
 | 
|---|
| 350 |           aux1=jacjac+i*mm; aux2=jac+i*m;
 | 
|---|
| 351 |           for(j=jj; j<__MIN__(jj+__BLOCKSZ__, mm); ++j){
 | 
|---|
| 352 |             sum=0.0;
 | 
|---|
| 353 |             for(l=ll; l<__MIN__(ll+__BLOCKSZ__, m); ++l)
 | 
|---|
| 354 |               sum+=aux2[l]*Z[l*mm+j]; //jac[i*m+l]*Z[l*mm+j];
 | 
|---|
| 355 |             aux1[j]+=sum; //jacjac[i*mm+j]+=sum;
 | 
|---|
| 356 |           }
 | 
|---|
| 357 |         }
 | 
|---|
| 358 |       }
 | 
|---|
| 359 |     }
 | 
|---|
| 360 |   }
 | 
|---|
| 361 | }
 | 
|---|
| 362 | #undef __MIN__
 | 
|---|
| 363 | 
 | 
|---|
| 364 | 
 | 
|---|
| 365 | /* 
 | 
|---|
| 366 |  * This function is similar to LEVMAR_DER except that the minimization
 | 
|---|
| 367 |  * is performed subject to the linear constraints A p=b, A is kxm, b kx1
 | 
|---|
| 368 |  *
 | 
|---|
| 369 |  * This function requires an analytic Jacobian. In case the latter is unavailable,
 | 
|---|
| 370 |  * use LEVMAR_LEC_DIF() bellow
 | 
|---|
| 371 |  *
 | 
|---|
| 372 |  */
 | 
|---|
| 373 | int LEVMAR_LEC_DER(
 | 
|---|
| 374 |   void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in  R^n */
 | 
|---|
| 375 |   void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),  /* function to evaluate the Jacobian \part x / \part p */ 
 | 
|---|
| 376 |   LM_REAL *p,         /* I/O: initial parameter estimates. On output has the estimated solution */
 | 
|---|
| 377 |   LM_REAL *x,         /* I: measurement vector. NULL implies a zero vector */
 | 
|---|
| 378 |   int m,              /* I: parameter vector dimension (i.e. #unknowns) */
 | 
|---|
| 379 |   int n,              /* I: measurement vector dimension */
 | 
|---|
| 380 |   LM_REAL *A,         /* I: constraints matrix, kxm */
 | 
|---|
| 381 |   LM_REAL *b,         /* I: right hand constraints vector, kx1 */
 | 
|---|
| 382 |   int k,              /* I: number of constraints (i.e. A's #rows) */
 | 
|---|
| 383 |   int itmax,          /* I: maximum number of iterations */
 | 
|---|
| 384 |   LM_REAL opts[4],    /* I: minim. options [\mu, \epsilon1, \epsilon2, \epsilon3]. Respectively the scale factor for initial \mu,
 | 
|---|
| 385 |                        * stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2. Set to NULL for defaults to be used
 | 
|---|
| 386 |                        */
 | 
|---|
| 387 |   LM_REAL info[LM_INFO_SZ],
 | 
|---|
| 388 |                                                    /* O: information regarding the minimization. Set to NULL if don't care
 | 
|---|
| 389 |                       * info[0]= ||e||_2 at initial p.
 | 
|---|
| 390 |                       * info[1-4]=[ ||e||_2, ||J^T e||_inf,  ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
 | 
|---|
| 391 |                       * info[5]= # iterations,
 | 
|---|
| 392 |                       * info[6]=reason for terminating: 1 - stopped by small gradient J^T e
 | 
|---|
| 393 |                       *                                 2 - stopped by small Dp
 | 
|---|
| 394 |                       *                                 3 - stopped by itmax
 | 
|---|
| 395 |                       *                                 4 - singular matrix. Restart from current p with increased mu 
 | 
|---|
| 396 |                       *                                 5 - no further error reduction is possible. Restart with increased mu
 | 
|---|
| 397 |                       *                                 6 - stopped by small ||e||_2
 | 
|---|
| 398 |                       *                                 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
 | 
|---|
| 399 |                       * info[7]= # function evaluations
 | 
|---|
| 400 |                       * info[8]= # Jacobian evaluations
 | 
|---|
| 401 |                       * info[9]= # linear systems solved, i.e. # attempts for reducing error
 | 
|---|
| 402 |                       */
 | 
|---|
| 403 |   LM_REAL *work,     /* working memory at least LM_LEC_DER_WORKSZ() reals large, allocated if NULL */
 | 
|---|
| 404 |   LM_REAL *covar,    /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
 | 
|---|
| 405 |   void *adata)       /* pointer to possibly additional data, passed uninterpreted to func & jacf.
 | 
|---|
| 406 |                       * Set to NULL if not needed
 | 
|---|
| 407 |                       */
 | 
|---|
| 408 | {
 | 
|---|
| 409 |   struct LMLEC_DATA data;
 | 
|---|
| 410 |   LM_REAL *ptr, *Z, *pp, *p0, *Zimm; /* Z is mxmm */
 | 
|---|
| 411 |   int mm, ret;
 | 
|---|
| 412 |   register int i, j;
 | 
|---|
| 413 |   register LM_REAL tmp;
 | 
|---|
| 414 |   LM_REAL locinfo[LM_INFO_SZ];
 | 
|---|
| 415 | 
 | 
|---|
| 416 |   if(!jacf){
 | 
|---|
| 417 |     fprintf(stderr, RCAT("No function specified for computing the Jacobian in ", LEVMAR_LEC_DER)
 | 
|---|
| 418 |       RCAT("().\nIf no such function is available, use ", LEVMAR_LEC_DIF) RCAT("() rather than ", LEVMAR_LEC_DER) "()\n");
 | 
|---|
| 419 |     return LM_ERROR;
 | 
|---|
| 420 |   }
 | 
|---|
| 421 | 
 | 
|---|
| 422 |   mm=m-k;
 | 
|---|
| 423 | 
 | 
|---|
| 424 |   if(n<mm){
 | 
|---|
| 425 |     fprintf(stderr, LCAT(LEVMAR_LEC_DER, "(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"), n, k, m);
 | 
|---|
| 426 |     return LM_ERROR;
 | 
|---|
| 427 |   }
 | 
|---|
| 428 | 
 | 
|---|
| 429 |   ptr=(LM_REAL *)malloc((2*m + m*mm + n*m + mm)*sizeof(LM_REAL));
 | 
|---|
| 430 |   if(!ptr){
 | 
|---|
| 431 |     fprintf(stderr, LCAT(LEVMAR_LEC_DER, "(): memory allocation request failed\n"));
 | 
|---|
| 432 |     return LM_ERROR;
 | 
|---|
| 433 |   }
 | 
|---|
| 434 |   data.p=p;
 | 
|---|
| 435 |   p0=ptr;
 | 
|---|
| 436 |   data.c=p0+m;
 | 
|---|
| 437 |   data.Z=Z=data.c+m;
 | 
|---|
| 438 |   data.jac=data.Z+m*mm;
 | 
|---|
| 439 |   pp=data.jac+n*m;
 | 
|---|
| 440 |   data.ncnstr=k;
 | 
|---|
| 441 |   data.func=func;
 | 
|---|
| 442 |   data.jacf=jacf;
 | 
|---|
| 443 |   data.adata=adata;
 | 
|---|
| 444 | 
 | 
|---|
| 445 |   ret=LMLEC_ELIM(A, b, data.c, NULL, Z, k, m); // compute c, Z
 | 
|---|
| 446 |   if(ret==LM_ERROR){
 | 
|---|
| 447 |     free(ptr);
 | 
|---|
| 448 |     return LM_ERROR;
 | 
|---|
| 449 |   }
 | 
|---|
| 450 | 
 | 
|---|
| 451 |   /* compute pp s.t. p = c + Z*pp or (Z^T Z)*pp=Z^T*(p-c)
 | 
|---|
| 452 |    * Due to orthogonality, Z^T Z = I and the last equation
 | 
|---|
| 453 |    * becomes pp=Z^T*(p-c). Also, save the starting p in p0
 | 
|---|
| 454 |    */
 | 
|---|
| 455 |   for(i=0; i<m; ++i){
 | 
|---|
| 456 |     p0[i]=p[i];
 | 
|---|
| 457 |     p[i]-=data.c[i];
 | 
|---|
| 458 |   }
 | 
|---|
| 459 | 
 | 
|---|
| 460 |   /* Z^T*(p-c) */
 | 
|---|
| 461 |   for(i=0; i<mm; ++i){
 | 
|---|
| 462 |     for(j=0, tmp=0.0; j<m; ++j)
 | 
|---|
| 463 |       tmp+=Z[j*mm+i]*p[j];
 | 
|---|
| 464 |     pp[i]=tmp;
 | 
|---|
| 465 |   }
 | 
|---|
| 466 | 
 | 
|---|
| 467 |   /* compute the p corresponding to pp (i.e. c + Z*pp) and compare with p0 */
 | 
|---|
| 468 |   for(i=0; i<m; ++i){
 | 
|---|
| 469 |     Zimm=Z+i*mm;
 | 
|---|
| 470 |     for(j=0, tmp=data.c[i]; j<mm; ++j)
 | 
|---|
| 471 |       tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
 | 
|---|
| 472 |     if(FABS(tmp-p0[i])>LM_CNST(1E-03))
 | 
|---|
| 473 |       fprintf(stderr, RCAT("Warning: component %d of starting point not feasible in ", LEVMAR_LEC_DER) "()! [%.10g reset to %.10g]\n",
 | 
|---|
| 474 |                       i, p0[i], tmp);
 | 
|---|
| 475 |   }
 | 
|---|
| 476 | 
 | 
|---|
| 477 |   if(!info) info=locinfo; /* make sure that LEVMAR_DER() is called with non-null info */
 | 
|---|
| 478 |   /* note that covariance computation is not requested from LEVMAR_DER() */
 | 
|---|
| 479 |   ret=LEVMAR_DER(LMLEC_FUNC, LMLEC_JACF, pp, x, mm, n, itmax, opts, info, work, NULL, (void *)&data);
 | 
|---|
| 480 | 
 | 
|---|
| 481 |   /* p=c + Z*pp */
 | 
|---|
| 482 |   for(i=0; i<m; ++i){
 | 
|---|
| 483 |     Zimm=Z+i*mm;
 | 
|---|
| 484 |     for(j=0, tmp=data.c[i]; j<mm; ++j)
 | 
|---|
| 485 |       tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
 | 
|---|
| 486 |     p[i]=tmp;
 | 
|---|
| 487 |   }
 | 
|---|
| 488 | 
 | 
|---|
| 489 |   /* compute the covariance from the Jacobian in data.jac */
 | 
|---|
| 490 |   if(covar){
 | 
|---|
| 491 |     LEVMAR_TRANS_MAT_MAT_MULT(data.jac, covar, n, m); /* covar = J^T J */
 | 
|---|
| 492 |     LEVMAR_COVAR(covar, covar, info[1], m, n);
 | 
|---|
| 493 |   }
 | 
|---|
| 494 | 
 | 
|---|
| 495 |   free(ptr);
 | 
|---|
| 496 | 
 | 
|---|
| 497 |   return ret;
 | 
|---|
| 498 | }
 | 
|---|
| 499 | 
 | 
|---|
| 500 | /* Similar to the LEVMAR_LEC_DER() function above, except that the Jacobian is approximated
 | 
|---|
| 501 |  * with the aid of finite differences (forward or central, see the comment for the opts argument)
 | 
|---|
| 502 |  */
 | 
|---|
| 503 | int LEVMAR_LEC_DIF(
 | 
|---|
| 504 |   void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in  R^n */
 | 
|---|
| 505 |   LM_REAL *p,         /* I/O: initial parameter estimates. On output has the estimated solution */
 | 
|---|
| 506 |   LM_REAL *x,         /* I: measurement vector. NULL implies a zero vector */
 | 
|---|
| 507 |   int m,              /* I: parameter vector dimension (i.e. #unknowns) */
 | 
|---|
| 508 |   int n,              /* I: measurement vector dimension */
 | 
|---|
| 509 |   LM_REAL *A,         /* I: constraints matrix, kxm */
 | 
|---|
| 510 |   LM_REAL *b,         /* I: right hand constraints vector, kx1 */
 | 
|---|
| 511 |   int k,              /* I: number of constraints (i.e. A's #rows) */
 | 
|---|
| 512 |   int itmax,          /* I: maximum number of iterations */
 | 
|---|
| 513 |   LM_REAL opts[5],    /* I: opts[0-3] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
 | 
|---|
| 514 |                        * scale factor for initial \mu, stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2 and
 | 
|---|
| 515 |                        * the step used in difference approximation to the Jacobian. Set to NULL for defaults to be used.
 | 
|---|
| 516 |                        * If \delta<0, the Jacobian is approximated with central differences which are more accurate
 | 
|---|
| 517 |                        * (but slower!) compared to the forward differences employed by default. 
 | 
|---|
| 518 |                        */
 | 
|---|
| 519 |   LM_REAL info[LM_INFO_SZ],
 | 
|---|
| 520 |                                                    /* O: information regarding the minimization. Set to NULL if don't care
 | 
|---|
| 521 |                       * info[0]= ||e||_2 at initial p.
 | 
|---|
| 522 |                       * info[1-4]=[ ||e||_2, ||J^T e||_inf,  ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
 | 
|---|
| 523 |                       * info[5]= # iterations,
 | 
|---|
| 524 |                       * info[6]=reason for terminating: 1 - stopped by small gradient J^T e
 | 
|---|
| 525 |                       *                                 2 - stopped by small Dp
 | 
|---|
| 526 |                       *                                 3 - stopped by itmax
 | 
|---|
| 527 |                       *                                 4 - singular matrix. Restart from current p with increased mu 
 | 
|---|
| 528 |                       *                                 5 - no further error reduction is possible. Restart with increased mu
 | 
|---|
| 529 |                       *                                 6 - stopped by small ||e||_2
 | 
|---|
| 530 |                       *                                 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
 | 
|---|
| 531 |                       * info[7]= # function evaluations
 | 
|---|
| 532 |                       * info[8]= # Jacobian evaluations
 | 
|---|
| 533 |                       * info[9]= # linear systems solved, i.e. # attempts for reducing error
 | 
|---|
| 534 |                       */
 | 
|---|
| 535 |   LM_REAL *work,     /* working memory at least LM_LEC_DIF_WORKSZ() reals large, allocated if NULL */
 | 
|---|
| 536 |   LM_REAL *covar,    /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
 | 
|---|
| 537 |   void *adata)       /* pointer to possibly additional data, passed uninterpreted to func.
 | 
|---|
| 538 |                       * Set to NULL if not needed
 | 
|---|
| 539 |                       */
 | 
|---|
| 540 | {
 | 
|---|
| 541 |   struct LMLEC_DATA data;
 | 
|---|
| 542 |   LM_REAL *ptr, *Z, *pp, *p0, *Zimm; /* Z is mxmm */
 | 
|---|
| 543 |   int mm, ret;
 | 
|---|
| 544 |   register int i, j;
 | 
|---|
| 545 |   register LM_REAL tmp;
 | 
|---|
| 546 |   LM_REAL locinfo[LM_INFO_SZ];
 | 
|---|
| 547 | 
 | 
|---|
| 548 |   mm=m-k;
 | 
|---|
| 549 | 
 | 
|---|
| 550 |   if(n<mm){
 | 
|---|
| 551 |     fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"), n, k, m);
 | 
|---|
| 552 |     return LM_ERROR;
 | 
|---|
| 553 |   }
 | 
|---|
| 554 | 
 | 
|---|
| 555 |   ptr=(LM_REAL *)malloc((2*m + m*mm + mm)*sizeof(LM_REAL));
 | 
|---|
| 556 |   if(!ptr){
 | 
|---|
| 557 |     fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): memory allocation request failed\n"));
 | 
|---|
| 558 |     return LM_ERROR;
 | 
|---|
| 559 |   }
 | 
|---|
| 560 |   data.p=p;
 | 
|---|
| 561 |   p0=ptr;
 | 
|---|
| 562 |   data.c=p0+m;
 | 
|---|
| 563 |   data.Z=Z=data.c+m;
 | 
|---|
| 564 |   data.jac=NULL;
 | 
|---|
| 565 |   pp=data.Z+m*mm;
 | 
|---|
| 566 |   data.ncnstr=k;
 | 
|---|
| 567 |   data.func=func;
 | 
|---|
| 568 |   data.jacf=NULL;
 | 
|---|
| 569 |   data.adata=adata;
 | 
|---|
| 570 | 
 | 
|---|
| 571 |   ret=LMLEC_ELIM(A, b, data.c, NULL, Z, k, m); // compute c, Z
 | 
|---|
| 572 |   if(ret==LM_ERROR){
 | 
|---|
| 573 |     free(ptr);
 | 
|---|
| 574 |     return LM_ERROR;
 | 
|---|
| 575 |   }
 | 
|---|
| 576 | 
 | 
|---|
| 577 |   /* compute pp s.t. p = c + Z*pp or (Z^T Z)*pp=Z^T*(p-c)
 | 
|---|
| 578 |    * Due to orthogonality, Z^T Z = I and the last equation
 | 
|---|
| 579 |    * becomes pp=Z^T*(p-c). Also, save the starting p in p0
 | 
|---|
| 580 |    */
 | 
|---|
| 581 |   for(i=0; i<m; ++i){
 | 
|---|
| 582 |     p0[i]=p[i];
 | 
|---|
| 583 |     p[i]-=data.c[i];
 | 
|---|
| 584 |   }
 | 
|---|
| 585 | 
 | 
|---|
| 586 |   /* Z^T*(p-c) */
 | 
|---|
| 587 |   for(i=0; i<mm; ++i){
 | 
|---|
| 588 |     for(j=0, tmp=0.0; j<m; ++j)
 | 
|---|
| 589 |       tmp+=Z[j*mm+i]*p[j];
 | 
|---|
| 590 |     pp[i]=tmp;
 | 
|---|
| 591 |   }
 | 
|---|
| 592 | 
 | 
|---|
| 593 |   /* compute the p corresponding to pp (i.e. c + Z*pp) and compare with p0 */
 | 
|---|
| 594 |   for(i=0; i<m; ++i){
 | 
|---|
| 595 |     Zimm=Z+i*mm;
 | 
|---|
| 596 |     for(j=0, tmp=data.c[i]; j<mm; ++j)
 | 
|---|
| 597 |       tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
 | 
|---|
| 598 |     if(FABS(tmp-p0[i])>LM_CNST(1E-03))
 | 
|---|
| 599 |       fprintf(stderr, RCAT("Warning: component %d of starting point not feasible in ", LEVMAR_LEC_DIF) "()! [%.10g reset to %.10g]\n",
 | 
|---|
| 600 |                       i, p0[i], tmp);
 | 
|---|
| 601 |   }
 | 
|---|
| 602 | 
 | 
|---|
| 603 |   if(!info) info=locinfo; /* make sure that LEVMAR_DIF() is called with non-null info */
 | 
|---|
| 604 |   /* note that covariance computation is not requested from LEVMAR_DIF() */
 | 
|---|
| 605 |   ret=LEVMAR_DIF(LMLEC_FUNC, pp, x, mm, n, itmax, opts, info, work, NULL, (void *)&data);
 | 
|---|
| 606 | 
 | 
|---|
| 607 |   /* p=c + Z*pp */
 | 
|---|
| 608 |   for(i=0; i<m; ++i){
 | 
|---|
| 609 |     Zimm=Z+i*mm;
 | 
|---|
| 610 |     for(j=0, tmp=data.c[i]; j<mm; ++j)
 | 
|---|
| 611 |       tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
 | 
|---|
| 612 |     p[i]=tmp;
 | 
|---|
| 613 |   }
 | 
|---|
| 614 | 
 | 
|---|
| 615 |   /* compute the Jacobian with finite differences and use it to estimate the covariance */
 | 
|---|
| 616 |   if(covar){
 | 
|---|
| 617 |     LM_REAL *hx, *wrk, *jac;
 | 
|---|
| 618 | 
 | 
|---|
| 619 |     hx=(LM_REAL *)malloc((2*n+n*m)*sizeof(LM_REAL));
 | 
|---|
| 620 |     if(!hx){
 | 
|---|
| 621 |       fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): memory allocation request failed\n"));
 | 
|---|
| 622 |       free(ptr);
 | 
|---|
| 623 |       return LM_ERROR;
 | 
|---|
| 624 |     }
 | 
|---|
| 625 | 
 | 
|---|
| 626 |     wrk=hx+n;
 | 
|---|
| 627 |     jac=wrk+n;
 | 
|---|
| 628 | 
 | 
|---|
| 629 |     (*func)(p, hx, m, n, adata); /* evaluate function at p */
 | 
|---|
| 630 |     LEVMAR_FDIF_FORW_JAC_APPROX(func, p, hx, wrk, (LM_REAL)LM_DIFF_DELTA, jac, m, n, adata); /* compute the Jacobian at p */
 | 
|---|
| 631 |     LEVMAR_TRANS_MAT_MAT_MULT(jac, covar, n, m); /* covar = J^T J */
 | 
|---|
| 632 |     LEVMAR_COVAR(covar, covar, info[1], m, n);
 | 
|---|
| 633 |     free(hx);
 | 
|---|
| 634 |   }
 | 
|---|
| 635 | 
 | 
|---|
| 636 |   free(ptr);
 | 
|---|
| 637 | 
 | 
|---|
| 638 |   return ret;
 | 
|---|
| 639 | }
 | 
|---|
| 640 | 
 | 
|---|
| 641 | /* undefine all. THIS MUST REMAIN AT THE END OF THE FILE */
 | 
|---|
| 642 | #undef LMLEC_DATA
 | 
|---|
| 643 | #undef LMLEC_ELIM
 | 
|---|
| 644 | #undef LMLEC_FUNC
 | 
|---|
| 645 | #undef LMLEC_JACF
 | 
|---|
| 646 | #undef LEVMAR_FDIF_FORW_JAC_APPROX
 | 
|---|
| 647 | #undef LEVMAR_COVAR
 | 
|---|
| 648 | #undef LEVMAR_TRANS_MAT_MAT_MULT
 | 
|---|
| 649 | #undef LEVMAR_LEC_DER
 | 
|---|
| 650 | #undef LEVMAR_LEC_DIF
 | 
|---|
| 651 | #undef LEVMAR_DER
 | 
|---|
| 652 | #undef LEVMAR_DIF
 | 
|---|
| 653 | 
 | 
|---|
| 654 | #undef GEQP3
 | 
|---|
| 655 | #undef ORGQR
 | 
|---|
| 656 | #undef TRTRI
 | 
|---|