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

📄 axb_core.c

📁 A sparse variant of the Levenberg-Marquardt algorithm implemented by levmar has been applied to bund
💻 C
📖 第 1 页 / 共 2 页
字号:
    }  }  /* solve using the computed Cholesky in one lapack call */  POTRS("U", (int *)&m, (int *)&nrhs, a, (int *)&m, b, (int *)&m, &info);  if(info<0){    fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", POTRS) " in ", AX_EQ_B_CHOL) "()\n", -info);    exit(1);  }#if 0  /* alternative: solve the linear system U^T y = b ... */  TRTRS("U", "T", "N", (int *)&m, (int *)&nrhs, a, (int *)&m, b, (int *)&m, &info);  /* error treatment */  if(info!=0){    if(info<0){      fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", TRTRS) " in ", AX_EQ_B_CHOL) "()\n", -info);      exit(1);    }    else{      fprintf(stderr, RCAT("LAPACK error: the %d-th diagonal element of A is zero (singular matrix) in ", AX_EQ_B_CHOL) "()\n", info);#ifndef LINSOLVERS_RETAIN_MEMORY      free(buf);#endif      return 0;    }  }  /* ... solve the linear system U x = y */  TRTRS("U", "N", "N", (int *)&m, (int *)&nrhs, a, (int *)&m, b, (int *)&m, &info);  /* error treatment */  if(info!=0){    if(info<0){      fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", TRTRS) "in ", AX_EQ_B_CHOL) "()\n", -info);      exit(1);    }    else{      fprintf(stderr, RCAT("LAPACK error: the %d-th diagonal element of A is zero (singular matrix) in ", AX_EQ_B_CHOL) "()\n", info);#ifndef LINSOLVERS_RETAIN_MEMORY      free(buf);#endif      return 0;    }  }#endif /* 0 */	/* copy the result in x */	for(i=0; i<m; i++)    x[i]=b[i];#ifndef LINSOLVERS_RETAIN_MEMORY  free(buf);#endif	return 1;}/* * This function returns the solution of Ax = b * * The function employs LU decomposition: * If A=L U with L lower and U upper triangular, then the original system * amounts to solving * L y = b, U x = y * * A is mxm, b is mx1 * * The function returns 0 in case of error, 1 if successful * * This function is often called repetitively to solve problems of identical * dimensions. To avoid repetitive malloc's and free's, allocated memory is * retained between calls and free'd-malloc'ed when not of the appropriate size. * A call with NULL as the first argument forces this memory to be released. */int AX_EQ_B_LU(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m){__STATIC__ LM_REAL *buf=NULL;__STATIC__ int buf_sz=0;int a_sz, ipiv_sz, b_sz, tot_sz;register int i, j;int info, *ipiv, nrhs=1;LM_REAL *a, *b;       if(!A)#ifdef LINSOLVERS_RETAIN_MEMORY    {      if(buf) free(buf);      buf=NULL;      buf_sz=0;      return 1;    }#else      return 1; /* NOP */#endif /* LINSOLVERS_RETAIN_MEMORY */       /* calculate required memory size */    ipiv_sz=m;    a_sz=m*m;    b_sz=m;    tot_sz=(a_sz + b_sz)*sizeof(LM_REAL) + ipiv_sz*sizeof(int); /* should be arranged in that order for proper doubles alignment */#ifdef LINSOLVERS_RETAIN_MEMORY    if(tot_sz>buf_sz){ /* insufficient memory, allocate a "big" memory chunk at once */      if(buf) free(buf); /* free previously allocated memory */      buf_sz=tot_sz;      buf=(LM_REAL *)malloc(buf_sz);      if(!buf){        fprintf(stderr, RCAT("memory allocation in ", AX_EQ_B_LU) "() failed!\n");        exit(1);      }    }#else      buf_sz=tot_sz;      buf=(LM_REAL *)malloc(buf_sz);      if(!buf){        fprintf(stderr, RCAT("memory allocation in ", AX_EQ_B_LU) "() failed!\n");        exit(1);      }#endif /* LINSOLVERS_RETAIN_MEMORY */    a=buf;    b=a+a_sz;    ipiv=(int *)(b+b_sz);    /* store A (column major!) into a and B into b */	  for(i=0; i<m; i++){		  for(j=0; j<m; j++)        a[i+j*m]=A[i*m+j];      b[i]=B[i];    }  /* LU decomposition for A */	GETRF((int *)&m, (int *)&m, a, (int *)&m, ipiv, (int *)&info);  	if(info!=0){		if(info<0){      fprintf(stderr, RCAT(RCAT("argument %d of ", GETRF) " illegal in ", AX_EQ_B_LU) "()\n", -info);			exit(1);		}		else{      fprintf(stderr, RCAT(RCAT("singular matrix A for ", GETRF) " in ", AX_EQ_B_LU) "()\n");#ifndef LINSOLVERS_RETAIN_MEMORY      free(buf);#endif			return 0;		}	}  /* solve the system with the computed LU */  GETRS("N", (int *)&m, (int *)&nrhs, a, (int *)&m, ipiv, b, (int *)&m, (int *)&info);	if(info!=0){		if(info<0){			fprintf(stderr, RCAT(RCAT("argument %d of ", GETRS) " illegal in ", AX_EQ_B_LU) "()\n", -info);			exit(1);		}		else{			fprintf(stderr, RCAT(RCAT("unknown error for ", GETRS) " in ", AX_EQ_B_LU) "()\n");#ifndef LINSOLVERS_RETAIN_MEMORY      free(buf);#endif			return 0;		}	}	/* copy the result in x */	for(i=0; i<m; i++){		x[i]=b[i];	}#ifndef LINSOLVERS_RETAIN_MEMORY  free(buf);#endif	return 1;}/* * This function returns the solution of Ax = b * * The function is based on SVD decomposition: * If A=U D V^T with U, V orthogonal and D diagonal, the linear system becomes * (U D V^T) x = b or x=V D^{-1} U^T b * Note that V D^{-1} U^T is the pseudoinverse A^+ * * A is mxm, b is mx1. * * The function returns 0 in case of error, 1 if successful * * This function is often called repetitively to solve problems of identical * dimensions. To avoid repetitive malloc's and free's, allocated memory is * retained between calls and free'd-malloc'ed when not of the appropriate size. * A call with NULL as the first argument forces this memory to be released. */int AX_EQ_B_SVD(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m){__STATIC__ LM_REAL *buf=NULL;__STATIC__ int buf_sz=0;static LM_REAL eps=LM_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;register LM_REAL sum;int info, rank, worksz, *iwork, iworksz;       if(!A)#ifdef LINSOLVERS_RETAIN_MEMORY    {      if(buf) free(buf);      buf=NULL;      buf_sz=0;      return 1;    }#else      return 1; /* NOP */#endif /* LINSOLVERS_RETAIN_MEMORY */     /* calculate required memory size */#if 1 /* use optimal size */  worksz=-1; // workspace query. Keep in mind that GESDD requires more memory than GESVD  /* note that optimal work size is returned in thresh */  GESVD("A", "A", (int *)&m, (int *)&m, NULL, (int *)&m, NULL, NULL, (int *)&m, NULL, (int *)&m, (LM_REAL *)&thresh, (int *)&worksz, &info);  //GESDD("A", (int *)&m, (int *)&m, NULL, (int *)&m, NULL, NULL, (int *)&m, NULL, (int *)&m, (LM_REAL *)&thresh, (int *)&worksz, NULL, &info);  worksz=(int)thresh;#else /* use minimum size */  worksz=5*m; // min worksize for GESVD  //worksz=m*(7*m+4); // min worksize for GESDD#endif  iworksz=8*m;  a_sz=m*m;  u_sz=m*m; s_sz=m; vt_sz=m*m;  tot_sz=(a_sz + u_sz + s_sz + vt_sz + worksz)*sizeof(LM_REAL) + iworksz*sizeof(int); /* should be arranged in that order for proper doubles alignment */#ifdef LINSOLVERS_RETAIN_MEMORY  if(tot_sz>buf_sz){ /* insufficient memory, allocate a "big" memory chunk at once */    if(buf) free(buf); /* free previously allocated memory */    buf_sz=tot_sz;    buf=(LM_REAL *)malloc(buf_sz);    if(!buf){      fprintf(stderr, RCAT("memory allocation in ", AX_EQ_B_SVD) "() failed!\n");      exit(1);    }  }#else    buf_sz=tot_sz;    buf=(LM_REAL *)malloc(buf_sz);    if(!buf){      fprintf(stderr, RCAT("memory allocation in ", AX_EQ_B_SVD) "() failed!\n");      exit(1);    }#endif /* LINSOLVERS_RETAIN_MEMORY */  a=buf;  u=a+a_sz;  s=u+u_sz;  vt=s+s_sz;  work=vt+vt_sz;  iwork=(int *)(work+worksz);  /* 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];  /* 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 ", AX_EQ_B_SVD) "()\n", -info);      exit(1);    }    else{      fprintf(stderr, RCAT("LAPACK error: dgesdd (dbdsdc)/dgesvd (dbdsqr) failed to converge in ", AX_EQ_B_SVD) "() [info=%d]\n", info);#ifndef LINSOLVERS_RETAIN_MEMORY      free(buf);#endif      return 0;    }  }  if(eps<0.0){    LM_REAL aux;    /* compute machine epsilon */    for(eps=LM_CNST(1.0); aux=eps+LM_CNST(1.0), aux-LM_CNST(1.0)>0.0; eps*=LM_CNST(0.5))                                          ;    eps*=LM_CNST(2.0);  }  /* compute the pseudoinverse in a */	for(i=0; i<a_sz; i++) a[i]=0.0; /* initialize to zero */  for(rank=0, thresh=eps*s[0]; rank<m && s[rank]>thresh; rank++){    one_over_denom=LM_CNST(1.0)/s[rank];    for(j=0; j<m; j++)      for(i=0; i<m; i++)        a[i*m+j]+=vt[rank+i*m]*u[j+rank*m]*one_over_denom;  }	/* compute A^+ b in x */	for(i=0; i<m; i++){	  for(j=0, sum=0.0; j<m; j++)      sum+=a[i*m+j]*B[j];    x[i]=sum;  }#ifndef LINSOLVERS_RETAIN_MEMORY  free(buf);#endif	return 1;}/* undefine all. IT MUST REMAIN IN THIS POSITION IN FILE */#undef AX_EQ_B_QR#undef AX_EQ_B_QRLS#undef AX_EQ_B_CHOL#undef AX_EQ_B_LU#undef AX_EQ_B_SVD#undef GEQRF#undef ORGQR#undef TRTRS#undef POTF2#undef POTRF#undef POTRS#undef GETRF#undef GETRS#undef GESVD#undef GESDD#else // no LAPACK/* precision-specific definitions */#define AX_EQ_B_LU LM_ADD_PREFIX(Ax_eq_b_LU_noLapack)/* * This function returns the solution of Ax = b * * The function employs LU decomposition followed by forward/back substitution (see  * also the LAPACK-based LU solver above) * * A is mxm, b is mx1 * * The function returns 0 in case of error, 1 if successful * * This function is often called repetitively to solve problems of identical * dimensions. To avoid repetitive malloc's and free's, allocated memory is * retained between calls and free'd-malloc'ed when not of the appropriate size. * A call with NULL as the first argument forces this memory to be released. */int AX_EQ_B_LU(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m){__STATIC__ void *buf=NULL;__STATIC__ int buf_sz=0;register int i, j, k;int *idx, maxi=-1, idx_sz, a_sz, work_sz, tot_sz;LM_REAL *a, *work, max, sum, tmp;    if(!A)#ifdef LINSOLVERS_RETAIN_MEMORY    {      if(buf) free(buf);      buf=NULL;      buf_sz=0;      return 1;    }#else    return 1; /* NOP */#endif /* LINSOLVERS_RETAIN_MEMORY */     /* calculate required memory size */  idx_sz=m;  a_sz=m*m;  work_sz=m;  tot_sz=(a_sz+work_sz)*sizeof(LM_REAL) + idx_sz*sizeof(int); /* should be arranged in that order for proper doubles alignment */#ifdef LINSOLVERS_RETAIN_MEMORY  if(tot_sz>buf_sz){ /* insufficient memory, allocate a "big" memory chunk at once */    if(buf) free(buf); /* free previously allocated memory */    buf_sz=tot_sz;    buf=(void *)malloc(tot_sz);    if(!buf){      fprintf(stderr, RCAT("memory allocation in ", AX_EQ_B_LU) "() failed!\n");      exit(1);    }  }#else    buf_sz=tot_sz;    buf=(void *)malloc(tot_sz);    if(!buf){      fprintf(stderr, RCAT("memory allocation in ", AX_EQ_B_LU) "() failed!\n");      exit(1);    }#endif /* LINSOLVERS_RETAIN_MEMORY */  a=buf;  work=a+a_sz;  idx=(int *)(work+work_sz);  /* avoid destroying A, B by copying them to a, x resp. */  for(i=0; i<m; ++i){ // B & 1st row of A    a[i]=A[i];    x[i]=B[i];  }  for(  ; i<a_sz; ++i) a[i]=A[i]; // copy A's remaining rows  /****  for(i=0; i<m; ++i){    for(j=0; j<m; ++j)      a[i*m+j]=A[i*m+j];    x[i]=B[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 ", AX_EQ_B_LU) "()!\n");#ifndef LINSOLVERS_RETAIN_MEMORY        free(buf);#endif        return 0;      }		  work[i]=LM_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=LM_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 linear system using   * forward and back substitution   */	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];	}#ifndef LINSOLVERS_RETAIN_MEMORY  free(buf);#endif  return 1;}/* undefine all. IT MUST REMAIN IN THIS POSITION IN FILE */#undef AX_EQ_B_LU#endif /* HAVE_LAPACK */

⌨️ 快捷键说明

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