⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc_core.c

📁 levenberg marquit算法的.C源码
💻 C
📖 第 1 页 / 共 2 页
字号:
        temp=eps*FABS((fvecp[i]-fvec[i])/eps - err[i])/(FABS(fvec[i])+FABS(fvecp[i]));    err[i]=one;    if(temp>epsmch && temp<eps)        err[i]=((LM_REAL)log10(temp) - epslog)/epslog;    if(temp>=eps) err[i]=zero;  }  free(buf);  return;}#ifdef HAVE_LAPACK/* * This function computes the pseudoinverse of a square matrix A * into B using SVD. A and B can coincide *  * The function returns 0 in case of error (e.g. A is singular), * the rank of A if successfull * * A, B are mxm * */static int LEVMAR_PSEUDOINVERSE(LM_REAL *A, LM_REAL *B, int m){LM_REAL *buf=NULL;int buf_sz=0;static LM_REAL eps=CNST(-1.0);register int i, j;LM_REAL *a, *u, *s, *vt, *work;int a_sz, u_sz, s_sz, vt_sz, tot_sz;LM_REAL thresh, one_over_denom;int info, rank, worksz, *iwork, iworksz;     /* calculate required memory size */  worksz=16*m; /* more than needed */  iworksz=8*m;  a_sz=m*m;  u_sz=m*m; s_sz=m; vt_sz=m*m;  tot_sz=iworksz*sizeof(int) + (a_sz + u_sz + s_sz + vt_sz + worksz)*sizeof(LM_REAL);    buf_sz=tot_sz;    buf=(LM_REAL *)malloc(buf_sz);    if(!buf){      fprintf(stderr, RCAT("memory allocation in ", LEVMAR_PSEUDOINVERSE) "() failed!\n");      exit(1);    }  iwork=(int *)buf;  a=(LM_REAL *)(iwork+iworksz);  /* store A (column major!) into a */  for(i=0; i<m; i++)    for(j=0; j<m; j++)      a[i+j*m]=A[i*m+j];  u=a + a_sz;  s=u+u_sz;  vt=s+s_sz;  work=vt+vt_sz;  /* SVD decomposition of A */  GESVD("A", "A", (int *)&m, (int *)&m, a, (int *)&m, s, u, (int *)&m, vt, (int *)&m, work, (int *)&worksz, &info);  //GESDD("A", (int *)&m, (int *)&m, a, (int *)&m, s, u, (int *)&m, vt, (int *)&m, work, (int *)&worksz, iwork, &info);  /* error treatment */  if(info!=0){    if(info<0){      fprintf(stderr, RCAT(RCAT(RCAT("LAPACK error: illegal value for argument %d of ", GESVD), "/" GESDD) " in ", LEVMAR_PSEUDOINVERSE) "()\n", -info);      exit(1);    }    else{      fprintf(stderr, RCAT("LAPACK error: dgesdd (dbdsdc)/dgesvd (dbdsqr) failed to converge in ", LEVMAR_PSEUDOINVERSE) "() [info=%d]\n", info);      free(buf);      return 0;    }  }  if(eps<0.0){    LM_REAL aux;    /* compute machine epsilon */    for(eps=CNST(1.0); aux=eps+CNST(1.0), aux-CNST(1.0)>0.0; eps*=CNST(0.5))                                          ;    eps*=CNST(2.0);  }  /* compute the pseudoinverse in B */	for(i=0; i<a_sz; i++) B[i]=0.0; /* initialize to zero */  for(rank=0, thresh=eps*s[0]; rank<m && s[rank]>thresh; rank++){    one_over_denom=CNST(1.0)/s[rank];    for(j=0; j<m; j++)      for(i=0; i<m; i++)        B[i*m+j]+=vt[rank+i*m]*u[j+rank*m]*one_over_denom;  }  free(buf);	return rank;}#else // no LAPACK/* * This function computes the inverse of A in B. A and B can coincide * * The function employs LAPACK-free LU decomposition of A to solve m linear * systems A*B_i=I_i, where B_i and I_i are the i-th columns of B and I. * * A and B are mxm * * The function returns 0 in case of error, * 1 if successfull * */static int LEVMAR_LUINVERSE(LM_REAL *A, LM_REAL *B, int m){void *buf=NULL;int buf_sz=0;register int i, j, k, l;int *idx, maxi=-1, idx_sz, a_sz, x_sz, work_sz, tot_sz;LM_REAL *a, *x, *work, max, sum, tmp;  /* calculate required memory size */  idx_sz=m;  a_sz=m*m;  x_sz=m;  work_sz=m;  tot_sz=idx_sz*sizeof(int) + (a_sz+x_sz+work_sz)*sizeof(LM_REAL);  buf_sz=tot_sz;  buf=(void *)malloc(tot_sz);  if(!buf){    fprintf(stderr, RCAT("memory allocation in ", LEVMAR_LUINVERSE) "() failed!\n");    exit(1);  }  idx=(int *)buf;  a=(LM_REAL *)(idx + idx_sz);  x=a + a_sz;  work=x + x_sz;  /* avoid destroying A by copying it to a */  for(i=0; i<a_sz; ++i) a[i]=A[i];  /* compute the LU decomposition of a row permutation of matrix a; the permutation itself is saved in idx[] */	for(i=0; i<m; ++i){		max=0.0;		for(j=0; j<m; ++j)			if((tmp=FABS(a[i*m+j]))>max)        max=tmp;		  if(max==0.0){        fprintf(stderr, RCAT("Singular matrix A in ", LEVMAR_LUINVERSE) "()!\n");        free(buf);        return 0;      }		  work[i]=CNST(1.0)/max;	}	for(j=0; j<m; ++j){		for(i=0; i<j; ++i){			sum=a[i*m+j];			for(k=0; k<i; ++k)        sum-=a[i*m+k]*a[k*m+j];			a[i*m+j]=sum;		}		max=0.0;		for(i=j; i<m; ++i){			sum=a[i*m+j];			for(k=0; k<j; ++k)        sum-=a[i*m+k]*a[k*m+j];			a[i*m+j]=sum;			if((tmp=work[i]*FABS(sum))>=max){				max=tmp;				maxi=i;			}		}		if(j!=maxi){			for(k=0; k<m; ++k){				tmp=a[maxi*m+k];				a[maxi*m+k]=a[j*m+k];				a[j*m+k]=tmp;			}			work[maxi]=work[j];		}		idx[j]=maxi;		if(a[j*m+j]==0.0)      a[j*m+j]=LM_REAL_EPSILON;		if(j!=m-1){			tmp=CNST(1.0)/(a[j*m+j]);			for(i=j+1; i<m; ++i)        a[i*m+j]*=tmp;		}	}  /* The decomposition has now replaced a. Solve the m linear systems using   * forward and back substitution   */  for(l=0; l<m; ++l){    for(i=0; i<m; ++i) x[i]=0.0;    x[l]=CNST(1.0);	  for(i=k=0; i<m; ++i){		  j=idx[i];		  sum=x[j];		  x[j]=x[i];		  if(k!=0)			  for(j=k-1; j<i; ++j)          sum-=a[i*m+j]*x[j];		  else        if(sum!=0.0)			    k=i+1;		  x[i]=sum;	  }	  for(i=m-1; i>=0; --i){		  sum=x[i];		  for(j=i+1; j<m; ++j)        sum-=a[i*m+j]*x[j];		  x[i]=sum/a[i*m+i];	  }    for(i=0; i<m; ++i)      B[i*m+l]=x[i];  }  free(buf);  return 1;}#endif /* HAVE_LAPACK *//* * This function computes in C the covariance matrix corresponding to a least * squares fit. JtJ is the approximate Hessian at the solution (i.e. J^T*J, where * J is the jacobian at the solution), sumsq is the sum of squared residuals * (i.e. goodnes of fit) at the solution, m is the number of parameters (variables) * and n the number of observations. JtJ can coincide with C. *  * if JtJ is of full rank, C is computed as sumsq/(n-m)*(JtJ)^-1 * otherwise and if LAPACK is available, C=sumsq/(n-r)*(JtJ)^+ * where r is JtJ's rank and ^+ denotes the pseudoinverse * The diagonal of C is made up from the estimates of the variances * of the estimated regression coefficients. * See the documentation of routine E04YCF from the NAG fortran lib * * The function returns the rank of JtJ if successful, 0 on error * * A and C are mxm * */int LEVMAR_COVAR(LM_REAL *JtJ, LM_REAL *C, LM_REAL sumsq, int m, int n){register int i;int rnk;LM_REAL fact;#ifdef HAVE_LAPACK   rnk=LEVMAR_PSEUDOINVERSE(JtJ, C, m);   if(!rnk) return 0;#else#ifdef _MSC_VER#pragma message("LAPACK not available, LU will be used for matrix inversion when computing the covariance; this might be unstable at times")#else#warning LAPACK not available, LU will be used for matrix inversion when computing the covariance; this might be unstable at times#endif // _MSC_VER   rnk=LEVMAR_LUINVERSE(JtJ, C, m);   if(!rnk) return 0;   rnk=m; /* assume full rank */#endif /* HAVE_LAPACK */   fact=sumsq/(LM_REAL)(n-rnk);   for(i=0; i<m*m; ++i)     C[i]*=fact;   return rnk;}/* undefine everything. THIS MUST REMAIN AT THE END OF THE FILE */#undef LEVMAR_PSEUDOINVERSE#undef LEVMAR_LUINVERSE#undef LEVMAR_COVAR#undef LEVMAR_CHKJAC#undef FDIF_FORW_JAC_APPROX#undef FDIF_CENT_JAC_APPROX#undef TRANS_MAT_MAT_MULT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -