ガウス | spin on the RITZ

ガウス

自分用メモ

http://home.f01.itscom.net/toge/programingreport/articlerecord.html

http://www9.plala.or.jp/sgwr-t/c_sub/ConvHTML.html


#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct {
    int h;
    int w;
    double **m;
} Matrix;

void error_message(char *m)
{
    printf("エラー : %s\n", m);
    exit(1);
}

Matrix *create_matrix(int height, int width)
{
    Matrix *mat;
    int i;
    
    mat = (Matrix*)malloc(sizeof(mat));
    if (mat == NULL)
        error_message("Matrix メモリ確保失敗");
    mat->m = (double**)malloc(sizeof(double*)*height);
    if (mat->m == NULL)
        error_message("m メモリ確保失敗");
    for (i = 0;i < width;i++) {
        mat->m[i] = (double*)malloc(sizeof(double)*width);
        if (mat->m[i] == NULL)
            error_message("各行 メモリ確保失敗");
    }
    mat->h = height;
    mat->w = width;
    
    return mat;
}

void free_matrix(Matrix *mat)
{
    int i;
    
    for (i = 0;i < mat->h;i++)
        free(mat->m[i]);
    free(mat->m);
    free(mat);
}

int gauss(Matrix *temp)
{
    int i, j, k, d;
    double alpha;
    double copy;
    double max;
    int size;

    if(temp->h > temp->w)
        size = temp->w;
    else
        size = temp->h;
    
    for(i=0; i<size; i++){
        d = i;
        max = fabs(temp->m[i][i]);

        for(j=i+1; j<temp->h; j++){
            if(max < fabs(temp->m[j][i])){
                d = j;
                max = fabs(temp->m[j][i]);
            }
        }
        for(j=i; j<temp->w; j++){
            copy = temp->m[i][j];
            temp->m[i][j] = temp->m[d][j];
            temp->m[d][j] = copy;
        }

        for(j=i+1; j<temp->h; j++){
            if(!temp->m[i][i]) {
                return 1;
            }
            alpha = temp->m[j][i] / temp->m[i][i];

            for(k=i; k<temp->w; k++){
                temp->m[j][k] -= alpha*temp->m[i][k];
            }
        }
    }

    return 0;
}

double *backward(Matrix *matrix)
{
    int i, j;
    double b;
    double *temp;
    int width, height, size;

    width = matrix->w;
    size = height = matrix->h;

    temp = (double*)malloc(sizeof(double) * height);
    temp[size-1] = matrix->m[height-1][width-1] / matrix->m[height-1][width-2];

    for(i = size-2; i >= 0; i--){
        b = matrix->m[i][width-1];
        for(j=i+1; j<size; j++){
            b -= matrix->m[i][j]*temp[j];
        }
        if(!matrix->m[i][i]) {
            return NULL;
        }
        temp[i] = b/matrix->m[i][i];
    }

    return temp;
}

int main(void)
{
    Matrix *mat;
    int height, width;
    int i, k;
    double *d;

    scanf("%d %d", &height, &width);
    mat = create_matrix(height, width);
    srand(time(NULL));
    for (i = 0;i < height;i++) {
        for (k = 0;k < width;k++) {
            scanf("%lf", &mat->m[i][k]);
            printf("%6.2f ", mat->m[i][k]);
        }
        printf("\n");
    }
    gauss(mat);
    for (i = 0;i < height;i++) {
        for (k = 0;k < width;k++) {
            printf("%6.2f ", mat->m[i][k]);
        }
        printf("\n");
    }
    d = backward(mat);
    for (i = 0;i < mat->h;i++)
        printf("x%2d = %lf\n",i+1,d[i]);
    
    return 0;
}