123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /****************************************************************
- *
- * MODULE: v.generalize
- *
- * AUTHOR(S): Daniel Bundala
- *
- * PURPOSE: Definition of a matrix and basic operations with
- * matrices
- *
- * COPYRIGHT: (C) 2002-2005 by the GRASS Development Team
- *
- * This program is free software under the
- * GNU General Public License (>=v2).
- * Read the file COPYING that comes with GRASS
- * for details.
- *
- ****************************************************************/
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- #include "matrix.h"
- int matrix_init(int rows, int cols, MATRIX *res)
- {
- int i, j;
- res->rows = rows;
- res->cols = cols;
- res->a = (double **)G_calloc(rows, sizeof(double *));
- if (res->a == NULL)
- return 0;
- for (i = 0; i < rows; i++) {
- res->a[i] = (double *)G_calloc(cols, sizeof(double));
- if (res->a[i] == NULL) {
- for (j = 0; j < i; j++)
- G_free(res->a[j]);
- G_free(res->a);
- return 0;
- }
- }
- return 1;
- }
- void matrix_free(MATRIX *m)
- {
- int i;
- for (i = 0; i < m->rows; i++)
- G_free(m->a[i]);
- G_free(m->a);
- return;
- }
- int matrix_mult(MATRIX *a, MATRIX *b, MATRIX *res)
- {
- if (a->cols != b->rows)
- return 0;
- /*if (!matrix_init(a.rows, b.cols, res))
- * return 0;
- */
- int i, j, k;
- for (i = 0; i < a->rows; i++)
- for (j = 0; j < b->cols; j++) {
- res->a[i][j] = 0;
- for (k = 0; k < a->cols; k++)
- res->a[i][j] += a->a[i][k] * b->a[k][j];
- }
- return 1;
- }
- int matrix_add_identity(double s, MATRIX *m)
- {
- if (m->rows != m->cols)
- return 0;
- int i;
- for (i = 0; i < m->rows; i++)
- m->a[i][i] += s;
- return 1;
- }
- /* three following functions implements elementary row operations on matrices */
- /* auxialiry function for matrix_inverse, swaps two rows of given matrix */
- void matrix_swap_rows(int x, int y, MATRIX *m)
- {
- int i;
- for (i = 0; i < m->cols; i++) {
- double t;
- t = m->a[x][i];
- m->a[x][i] = m->a[y][i];
- m->a[y][i] = t;
- }
- return;
- }
- /* auxiliary function for matrix_inverse, multiplies row of a matrix by
- * a scalar */
- void matrix_row_scalar(int row, double s, MATRIX *m)
- {
- int i;
- for (i = 0; i < m->cols; i++)
- m->a[row][i] *= s;
- return;
- }
- /* auxiliary function for matrix_inverse, adds a multiple of
- * one row to another.
- * i.e row[ra] = row[ra] + row[rb] * s;
- */
- void matrix_row_add_multiple(int ra, int rb, double s, MATRIX *m)
- {
- int i;
- for (i = 0; i < m->cols; i++)
- m->a[ra][i] += m->a[rb][i] * s;
- return;
- }
- /* TODO: don't test directly equality to zero */
- int matrix_inverse(MATRIX *a, MATRIX *res, int percents)
- {
- int i, j;
- /* not a square matrix */
- if (a->rows != a->cols)
- return 0;
- /* initialize output matrix to the identity matrix */
- if (!matrix_init(a->rows, a->rows, res)) {
- G_fatal_error(_("Out of memory"));
- return 0;
- }
- for (i = 0; i < a->rows; i++) {
- memset(res->a[i], 0, sizeof(double) * a->cols);
- res->a[i][i] = 1;
- }
- /* in order to obtain the inverse of a matrix, we run
- * gauss elimination on the matrix and each time we apply
- * elementary row operation on this matrix, we apply the
- * same operation on the identity matrix. Correctness of
- * this follows from the fact that an invertible matrix
- * is row equivalent to the identity matrix.
- */
- int n = a->rows;
- if (percents)
- G_percent_reset();
- for (i = 0; i < n; i++) {
- int found = 0;
- double c;
- if (percents)
- G_percent(i, n, 1);
- for (j = i; j < n; j++) {
- if (a->a[j][i] != 0) { /* need to change this row to something */
- found = 1; /* more sensible */
- matrix_swap_rows(i, j, a);
- matrix_swap_rows(i, j, res);
- break;
- }
- }
- if (!found)
- return 0;
- c = (double)1.0 / a->a[i][i];
- matrix_row_scalar(i, c, a);
- matrix_row_scalar(i, c, res);
- for (j = 0; j < n; j++) {
- if (i == j)
- continue;
- c = -a->a[j][i];
- if (c == 0.0)
- continue;
- matrix_row_add_multiple(j, i, c, a);
- matrix_row_add_multiple(j, i, c, res);
- }
- }
- return 1;
- }
- void matrix_mult_scalar(double s, MATRIX *m)
- {
- int i, j;
- for (i = 0; i < m->rows; i++)
- for (j = 0; j < m->cols; j++)
- m->a[i][j] *= s;
- }
- void matrix_add(MATRIX *a, MATRIX *b, MATRIX *res)
- {
- int i, j;
- for (i = 0; i < res->rows; i++)
- for (j = 0; j < res->cols; j++)
- res->a[i][j] = a->a[i][j] + b->a[i][j];
- }
- void matrix_print(MATRIX *a)
- {
- int i, j;
- for (i = 0; i < a->rows; i++) {
- double s = 0;
- for (j = 0; j < a->cols; j++) {
- printf("%.3lf ", a->a[i][j]);
- s += a->a[i][j];
- }
- printf("|%.5lf\n", s);
- }
- printf("\n");
- }
|