首页 > 技术文章 > 2-1 Gaussj

dLong 2015-04-29 23:01 原文

#include <math.h>
#include "..\CommonFiles\nrutil.h"
#define SWAP(a,b) {temp=(a);(a)=(b);(b)=temp;}

/* 完全主元法--高斯消去法*/
/* gdb 查看数组*(a+1)[2]@4*/
void gaussj(float **a, int n, float **b, int m) {
    int *indxc,*indxr,*ipiv;
    int i,icol,irow,j,k,l,ll;
    float big,dum,pivinv,temp;

    indxc=ivector(1,n);    /* 主元所在的列 */
    indxr=ivector(1,n); /* 主元所在的行 */
    ipiv=ivector(1,n);  /* ipiv用于记录主元*/

    for (j=1; j<=n; j++) ipiv[j]=0;

    for (i=1; i<=n; i++) {            // 约化列的主循环
        big=0.0;
        for (j=1; j<=n; j++)        // 用于寻求主元素的外层循环
            if (ipiv[j] != 1)        // 判断是否被选过主元 
                for (k=1; k<=n; k++) {
                    if (ipiv[k] == 0) {
                        if (fabs(a[j][k]) >= big) {
                            big=fabs(a[j][k]);
                            irow=j;                // 寻求主元核心成果就是求出irow和icol
                            icol=k;
                        }
                    } else if (ipiv[k] > 1) nrerror("gaussj: Singular Matrix-1");
                }
        ++(ipiv[icol]);
        /*
        ** 至此已经求得主元素,如果需要的话,进行行交换把主元素放到对角线位置上.
        ** 也就是把主元所在的行位置换到与主元所在列相等的行位置上.
        */
        if (irow != icol) {
            for (l=1; l<=n; l++) SWAP(a[irow][l],a[icol][l])
            for (l=1; l<=m; l++) SWAP(b[irow][l],b[icol][l])
        }
        /*
        ** indxc[i] 为第一个主元所在的列
        ** indxr[r] 为第一个主元所在的行 
        */
        indxr[i]=irow;
        indxc[i]=icol;
        if (a[icol][icol] == 0.0) nrerror("gaussj: 奇异矩阵Singular Matrix-2");
        
        pivinv=1.0/a[icol][icol];  /* 对第一个主元求倒数 */
        a[icol][icol]=1.0;
        for (l=1; l<=n; l++) a[icol][l] *= pivinv;
        for (l=1; l<=m; l++) b[icol][l] *= pivinv;
        
        for (ll=1; ll<=n; ll++)
            if (ll != icol) {
                dum=a[ll][icol];
                a[ll][icol]=0.0;
                for (l=1; l<=n; l++) a[ll][l] -= a[icol][l]*dum;
                for (l=1; l<=m; l++) b[ll][l] -= b[icol][l]*dum;
            }
    }
    
    /* 这是列约化的结尾为了使解向量保持原来的顺序,在根据交换的相反顺序交换个列*/
    for (l=n; l>=1; l--) {
        if (indxr[l] != indxc[l])/* 第一个主元所在的行和列不相等*/
            for (k=1; k<=n; k++)  
                SWAP(a[k][indxr[l]],a[k][indxc[l]]);
    }
    free_ivector(ipiv,1,n);
    free_ivector(indxr,1,n);
    free_ivector(indxc,1,n);
}
#undef SWAP

 

推荐阅读