matrix.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /****************************************************************
  2. *
  3. * MODULE: v.generalize
  4. *
  5. * AUTHOR(S): Daniel Bundala
  6. *
  7. * PURPOSE: Definition of a matrix and basic operations with
  8. * matrices
  9. *
  10. * COPYRIGHT: (C) 2002-2005 by the GRASS Development Team
  11. *
  12. * This program is free software under the
  13. * GNU General Public License (>=v2).
  14. * Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. ****************************************************************/
  18. #include <string.h>
  19. #include <grass/gis.h>
  20. #include <grass/glocale.h>
  21. #include "matrix.h"
  22. int matrix_init(int rows, int cols, MATRIX *res)
  23. {
  24. int i, j;
  25. res->rows = rows;
  26. res->cols = cols;
  27. res->a = (double **)G_calloc(rows, sizeof(double *));
  28. if (res->a == NULL)
  29. return 0;
  30. for (i = 0; i < rows; i++) {
  31. res->a[i] = (double *)G_calloc(cols, sizeof(double));
  32. if (res->a[i] == NULL) {
  33. for (j = 0; j < i; j++)
  34. G_free(res->a[j]);
  35. G_free(res->a);
  36. return 0;
  37. }
  38. }
  39. return 1;
  40. }
  41. void matrix_free(MATRIX *m)
  42. {
  43. int i;
  44. for (i = 0; i < m->rows; i++)
  45. G_free(m->a[i]);
  46. G_free(m->a);
  47. return;
  48. }
  49. int matrix_mult(MATRIX *a, MATRIX *b, MATRIX *res)
  50. {
  51. if (a->cols != b->rows)
  52. return 0;
  53. /*if (!matrix_init(a.rows, b.cols, res))
  54. * return 0;
  55. */
  56. int i, j, k;
  57. for (i = 0; i < a->rows; i++)
  58. for (j = 0; j < b->cols; j++) {
  59. res->a[i][j] = 0;
  60. for (k = 0; k < a->cols; k++)
  61. res->a[i][j] += a->a[i][k] * b->a[k][j];
  62. }
  63. return 1;
  64. }
  65. int matrix_add_identity(double s, MATRIX *m)
  66. {
  67. if (m->rows != m->cols)
  68. return 0;
  69. int i;
  70. for (i = 0; i < m->rows; i++)
  71. m->a[i][i] += s;
  72. return 1;
  73. }
  74. /* three following functions implements elementary row operations on matrices */
  75. /* auxialiry function for matrix_inverse, swaps two rows of given matrix */
  76. void matrix_swap_rows(int x, int y, MATRIX *m)
  77. {
  78. int i;
  79. for (i = 0; i < m->cols; i++) {
  80. double t;
  81. t = m->a[x][i];
  82. m->a[x][i] = m->a[y][i];
  83. m->a[y][i] = t;
  84. }
  85. return;
  86. }
  87. /* auxiliary function for matrix_inverse, multiplies row of a matrix by
  88. * a scalar */
  89. void matrix_row_scalar(int row, double s, MATRIX *m)
  90. {
  91. int i;
  92. for (i = 0; i < m->cols; i++)
  93. m->a[row][i] *= s;
  94. return;
  95. }
  96. /* auxiliary function for matrix_inverse, adds a multiple of
  97. * one row to another.
  98. * i.e row[ra] = row[ra] + row[rb] * s;
  99. */
  100. void matrix_row_add_multiple(int ra, int rb, double s, MATRIX *m)
  101. {
  102. int i;
  103. for (i = 0; i < m->cols; i++)
  104. m->a[ra][i] += m->a[rb][i] * s;
  105. return;
  106. }
  107. /* TODO: don't test directly equality to zero */
  108. int matrix_inverse(MATRIX *a, MATRIX *res, int percents)
  109. {
  110. int i, j;
  111. /* not a square matrix */
  112. if (a->rows != a->cols)
  113. return 0;
  114. /* initialize output matrix to the identity matrix */
  115. if (!matrix_init(a->rows, a->rows, res)) {
  116. G_fatal_error(_("Out of memory"));
  117. return 0;
  118. }
  119. for (i = 0; i < a->rows; i++) {
  120. memset(res->a[i], 0, sizeof(double) * a->cols);
  121. res->a[i][i] = 1;
  122. }
  123. /* in order to obtain the inverse of a matrix, we run
  124. * gauss elimination on the matrix and each time we apply
  125. * elementary row operation on this matrix, we apply the
  126. * same operation on the identity matrix. Correctness of
  127. * this follows from the fact that an invertible matrix
  128. * is row equivalent to the identity matrix.
  129. */
  130. int n = a->rows;
  131. if (percents)
  132. G_percent_reset();
  133. for (i = 0; i < n; i++) {
  134. int found = 0;
  135. double c;
  136. if (percents)
  137. G_percent(i, n, 1);
  138. for (j = i; j < n; j++) {
  139. if (a->a[j][i] != 0) { /* need to change this row to something */
  140. found = 1; /* more sensible */
  141. matrix_swap_rows(i, j, a);
  142. matrix_swap_rows(i, j, res);
  143. break;
  144. }
  145. }
  146. if (!found)
  147. return 0;
  148. c = (double)1.0 / a->a[i][i];
  149. matrix_row_scalar(i, c, a);
  150. matrix_row_scalar(i, c, res);
  151. for (j = 0; j < n; j++) {
  152. if (i == j)
  153. continue;
  154. c = -a->a[j][i];
  155. if (c == 0.0)
  156. continue;
  157. matrix_row_add_multiple(j, i, c, a);
  158. matrix_row_add_multiple(j, i, c, res);
  159. }
  160. }
  161. return 1;
  162. }
  163. void matrix_mult_scalar(double s, MATRIX *m)
  164. {
  165. int i, j;
  166. for (i = 0; i < m->rows; i++)
  167. for (j = 0; j < m->cols; j++)
  168. m->a[i][j] *= s;
  169. }
  170. void matrix_add(MATRIX *a, MATRIX *b, MATRIX *res)
  171. {
  172. int i, j;
  173. for (i = 0; i < res->rows; i++)
  174. for (j = 0; j < res->cols; j++)
  175. res->a[i][j] = a->a[i][j] + b->a[i][j];
  176. }
  177. void matrix_print(MATRIX *a)
  178. {
  179. int i, j;
  180. for (i = 0; i < a->rows; i++) {
  181. double s = 0;
  182. for (j = 0; j < a->cols; j++) {
  183. printf("%.3lf ", a->a[i][j]);
  184. s += a->a[i][j];
  185. }
  186. printf("|%.5lf\n", s);
  187. }
  188. printf("\n");
  189. }