2004-08-26 Matthias Klose <doko@debian.org>
[official-gcc.git] / gcc / lambda-mat.c
blobdddfd3a01101a87e7a7a5e62a16e23975e0933f3
1 /* Integer matrix math routines
2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3 Contributed by Daniel Berlin <dberlin@dberlin.org>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "ggc.h"
26 #include "varray.h"
27 #include "tree.h"
28 #include "lambda.h"
30 static void lambda_matrix_get_column (lambda_matrix, int, int,
31 lambda_vector);
33 /* Allocate a matrix of M rows x N cols. */
35 lambda_matrix
36 lambda_matrix_new (int m, int n)
38 lambda_matrix mat;
39 int i;
41 mat = ggc_alloc (m * sizeof (lambda_vector));
43 for (i = 0; i < m; i++)
44 mat[i] = lambda_vector_new (n);
46 return mat;
49 /* Copy the elements of M x N matrix MAT1 to MAT2. */
51 void
52 lambda_matrix_copy (lambda_matrix mat1, lambda_matrix mat2,
53 int m, int n)
55 int i;
57 for (i = 0; i < m; i++)
58 lambda_vector_copy (mat1[i], mat2[i], n);
61 /* Store the N x N identity matrix in MAT. */
63 void
64 lambda_matrix_id (lambda_matrix mat, int size)
66 int i, j;
68 for (i = 0; i < size; i++)
69 for (j = 0; j < size; j++)
70 mat[i][j] = (i == j) ? 1 : 0;
73 /* Negate the elements of the M x N matrix MAT1 and store it in MAT2. */
75 void
76 lambda_matrix_negate (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
78 int i;
80 for (i = 0; i < m; i++)
81 lambda_vector_negate (mat1[i], mat2[i], n);
84 /* Take the transpose of matrix MAT1 and store it in MAT2.
85 MAT1 is an M x N matrix, so MAT2 must be N x M. */
87 void
88 lambda_matrix_transpose (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
90 int i, j;
92 for (i = 0; i < n; i++)
93 for (j = 0; j < m; j++)
94 mat2[i][j] = mat1[j][i];
98 /* Add two M x N matrices together: MAT3 = MAT1+MAT2. */
100 void
101 lambda_matrix_add (lambda_matrix mat1, lambda_matrix mat2,
102 lambda_matrix mat3, int m, int n)
104 int i;
106 for (i = 0; i < m; i++)
107 lambda_vector_add (mat1[i], mat2[i], mat3[i], n);
110 /* MAT3 = CONST1 * MAT1 + CONST2 * MAT2. All matrices are M x N. */
112 void
113 lambda_matrix_add_mc (lambda_matrix mat1, int const1,
114 lambda_matrix mat2, int const2,
115 lambda_matrix mat3, int m, int n)
117 int i;
119 for (i = 0; i < m; i++)
120 lambda_vector_add_mc (mat1[i], const1, mat2[i], const2, mat3[i], n);
123 /* Multiply two matrices: MAT3 = MAT1 * MAT2.
124 MAT1 is an M x R matrix, and MAT2 is R x N. The resulting MAT2
125 must therefore be M x N. */
127 void
128 lambda_matrix_mult (lambda_matrix mat1, lambda_matrix mat2,
129 lambda_matrix mat3, int m, int r, int n)
132 int i, j, k;
134 for (i = 0; i < m; i++)
136 for (j = 0; j < n; j++)
138 mat3[i][j] = 0;
139 for (k = 0; k < r; k++)
140 mat3[i][j] += mat1[i][k] * mat2[k][j];
145 /* Get column COL from the matrix MAT and store it in VEC. MAT has
146 N rows, so the length of VEC must be N. */
148 static void
149 lambda_matrix_get_column (lambda_matrix mat, int n, int col,
150 lambda_vector vec)
152 int i;
154 for (i = 0; i < n; i++)
155 vec[i] = mat[i][col];
158 /* Delete rows r1 to r2 (not including r2). */
160 void
161 lambda_matrix_delete_rows (lambda_matrix mat, int rows, int from, int to)
163 int i;
164 int dist;
165 dist = to - from;
167 for (i = to; i < rows; i++)
168 mat[i - dist] = mat[i];
170 for (i = rows - dist; i < rows; i++)
171 mat[i] = NULL;
174 /* Swap rows R1 and R2 in matrix MAT. */
176 void
177 lambda_matrix_row_exchange (lambda_matrix mat, int r1, int r2)
179 lambda_vector row;
181 row = mat[r1];
182 mat[r1] = mat[r2];
183 mat[r2] = row;
186 /* Add a multiple of row R1 of matrix MAT with N columns to row R2:
187 R2 = R2 + CONST1 * R1. */
189 void
190 lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2, int const1)
192 int i;
194 if (const1 == 0)
195 return;
197 for (i = 0; i < n; i++)
198 mat[r2][i] += const1 * mat[r1][i];
201 /* Negate row R1 of matrix MAT which has N columns. */
203 void
204 lambda_matrix_row_negate (lambda_matrix mat, int n, int r1)
206 lambda_vector_negate (mat[r1], mat[r1], n);
209 /* Multiply row R1 of matrix MAT with N columns by CONST1. */
211 void
212 lambda_matrix_row_mc (lambda_matrix mat, int n, int r1, int const1)
214 int i;
216 for (i = 0; i < n; i++)
217 mat[r1][i] *= const1;
220 /* Exchange COL1 and COL2 in matrix MAT. M is the number of rows. */
222 void
223 lambda_matrix_col_exchange (lambda_matrix mat, int m, int col1, int col2)
225 int i;
226 int tmp;
227 for (i = 0; i < m; i++)
229 tmp = mat[i][col1];
230 mat[i][col1] = mat[i][col2];
231 mat[i][col2] = tmp;
235 /* Add a multiple of column C1 of matrix MAT with M rows to column C2:
236 C2 = C2 + CONST1 * C1. */
238 void
239 lambda_matrix_col_add (lambda_matrix mat, int m, int c1, int c2, int const1)
241 int i;
243 if (const1 == 0)
244 return;
246 for (i = 0; i < m; i++)
247 mat[i][c2] += const1 * mat[i][c1];
250 /* Negate column C1 of matrix MAT which has M rows. */
252 void
253 lambda_matrix_col_negate (lambda_matrix mat, int m, int c1)
255 int i;
257 for (i = 0; i < m; i++)
258 mat[i][c1] *= -1;
261 /* Multiply column C1 of matrix MAT with M rows by CONST1. */
263 void
264 lambda_matrix_col_mc (lambda_matrix mat, int m, int c1, int const1)
266 int i;
268 for (i = 0; i < m; i++)
269 mat[i][c1] *= const1;
272 /* Compute the inverse of the N x N matrix MAT and store it in INV.
274 We don't _really_ compute the inverse of MAT. Instead we compute
275 det(MAT)*inv(MAT), and we return det(MAT) to the caller as the function
276 result. This is necessary to preserve accuracy, because we are dealing
277 with integer matrices here.
279 The algorithm used here is a column based Gauss-Jordan elimination on MAT
280 and the identity matrix in parallel. The inverse is the result of applying
281 the same operations on the identity matrix that reduce MAT to the identity
282 matrix.
284 When MAT is a 2 x 2 matrix, we don't go through the whole process, because
285 it is easily inverted by inspection and it is a very common case. */
287 static int lambda_matrix_inverse_hard (lambda_matrix, lambda_matrix, int);
290 lambda_matrix_inverse (lambda_matrix mat, lambda_matrix inv, int n)
292 if (n == 2)
294 int a, b, c, d, det;
295 a = mat[0][0];
296 b = mat[1][0];
297 c = mat[0][1];
298 d = mat[1][1];
299 inv[0][0] = d;
300 inv[0][1] = -c;
301 inv[1][0] = -b;
302 inv[1][1] = a;
303 det = (a * d - b * c);
304 if (det < 0)
306 det *= -1;
307 inv[0][0] *= -1;
308 inv[1][0] *= -1;
309 inv[0][1] *= -1;
310 inv[1][1] *= -1;
312 return det;
314 else
315 return lambda_matrix_inverse_hard (mat, inv, n);
318 /* If MAT is not a special case, invert it the hard way. */
320 static int
321 lambda_matrix_inverse_hard (lambda_matrix mat, lambda_matrix inv, int n)
323 lambda_vector row;
324 lambda_matrix temp;
325 int i, j;
326 int determinant;
328 temp = lambda_matrix_new (n, n);
329 lambda_matrix_copy (mat, temp, n, n);
330 lambda_matrix_id (inv, n);
332 /* Reduce TEMP to a lower triangular form, applying the same operations on
333 INV which starts as the identity matrix. N is the number of rows and
334 columns. */
335 for (j = 0; j < n; j++)
337 row = temp[j];
339 /* Make every element in the current row positive. */
340 for (i = j; i < n; i++)
341 if (row[i] < 0)
343 lambda_matrix_col_negate (temp, n, i);
344 lambda_matrix_col_negate (inv, n, i);
347 /* Sweep the upper triangle. Stop when only the diagonal element in the
348 current row is nonzero. */
349 while (lambda_vector_first_nz (row, n, j + 1) < n)
351 int min_col = lambda_vector_min_nz (row, n, j);
352 lambda_matrix_col_exchange (temp, n, j, min_col);
353 lambda_matrix_col_exchange (inv, n, j, min_col);
355 for (i = j + 1; i < n; i++)
357 int factor;
359 factor = -1 * row[i];
360 if (row[j] != 1)
361 factor /= row[j];
363 lambda_matrix_col_add (temp, n, j, i, factor);
364 lambda_matrix_col_add (inv, n, j, i, factor);
369 /* Reduce TEMP from a lower triangular to the identity matrix. Also compute
370 the determinant, which now is simply the product of the elements on the
371 diagonal of TEMP. If one of these elements is 0, the matrix has 0 as an
372 eigenvalue so it is singular and hence not invertible. */
373 determinant = 1;
374 for (j = n - 1; j >= 0; j--)
376 int diagonal;
378 row = temp[j];
379 diagonal = row[j];
381 /* If the matrix is singular, abort. */
382 if (diagonal == 0)
383 abort ();
385 determinant = determinant * diagonal;
387 /* If the diagonal is not 1, then multiply the each row by the
388 diagonal so that the middle number is now 1, rather than a
389 rational. */
390 if (diagonal != 1)
392 for (i = 0; i < j; i++)
393 lambda_matrix_col_mc (inv, n, i, diagonal);
394 for (i = j + 1; i < n; i++)
395 lambda_matrix_col_mc (inv, n, i, diagonal);
397 row[j] = diagonal = 1;
400 /* Sweep the lower triangle column wise. */
401 for (i = j - 1; i >= 0; i--)
403 if (row[i])
405 int factor = -row[i];
406 lambda_matrix_col_add (temp, n, j, i, factor);
407 lambda_matrix_col_add (inv, n, j, i, factor);
413 return determinant;
416 /* Decompose a N x N matrix MAT to a product of a lower triangular H
417 and a unimodular U matrix such that MAT = H.U. N is the size of
418 the rows of MAT. */
420 void
421 lambda_matrix_hermite (lambda_matrix mat, int n,
422 lambda_matrix H, lambda_matrix U)
424 lambda_vector row;
425 int i, j, factor, minimum_col;
427 lambda_matrix_copy (mat, H, n, n);
428 lambda_matrix_id (U, n);
430 for (j = 0; j < n; j++)
432 row = H[j];
434 /* Make every element of H[j][j..n] positive. */
435 for (i = j; i < n; i++)
437 if (row[i] < 0)
439 lambda_matrix_col_negate (H, n, i);
440 lambda_vector_negate (U[i], U[i], n);
444 /* Stop when only the diagonal element is non-zero. */
445 while (lambda_vector_first_nz (row, n, j + 1) < n)
447 minimum_col = lambda_vector_min_nz (row, n, j);
448 lambda_matrix_col_exchange (H, n, j, minimum_col);
449 lambda_matrix_row_exchange (U, j, minimum_col);
451 for (i = j + 1; i < n; i++)
453 factor = row[i] / row[j];
454 lambda_matrix_col_add (H, n, j, i, -1 * factor);
455 lambda_matrix_row_add (U, n, i, j, factor);
461 /* Given an M x N integer matrix A, this function determines an M x
462 M unimodular matrix U, and an M x N echelon matrix S such that
463 "U.A = S". This decomposition is also known as "right Hermite".
465 Ref: Algorithm 2.1 page 33 in "Loop Transformations for
466 Restructuring Compilers" Utpal Banerjee. */
468 void
469 lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
470 lambda_matrix S, lambda_matrix U)
472 int i, j, i0 = 0;
474 lambda_matrix_copy (A, S, m, n);
475 lambda_matrix_id (U, m);
477 for (j = 0; j < n; j++)
479 if (lambda_vector_first_nz (S[j], m, i0) < m)
481 ++i0;
482 for (i = m - 1; i >= i0; i--)
484 while (S[i][j] != 0)
486 int sigma, factor, a, b;
488 a = S[i-1][j];
489 b = S[i][j];
490 sigma = (a * b < 0) ? -1: 1;
491 a = abs (a);
492 b = abs (b);
493 factor = sigma * (a / b);
495 lambda_matrix_row_add (S, n, i, i-1, -factor);
496 lambda_matrix_row_exchange (S, i, i-1);
498 lambda_matrix_row_add (U, m, i, i-1, -factor);
499 lambda_matrix_row_exchange (U, i, i-1);
506 /* Given an M x N integer matrix A, this function determines an M x M
507 unimodular matrix V, and an M x N echelon matrix S such that "A =
508 V.S". This decomposition is also known as "left Hermite".
510 Ref: Algorithm 2.2 page 36 in "Loop Transformations for
511 Restructuring Compilers" Utpal Banerjee. */
513 void
514 lambda_matrix_left_hermite (lambda_matrix A, int m, int n,
515 lambda_matrix S, lambda_matrix V)
517 int i, j, i0 = 0;
519 lambda_matrix_copy (A, S, m, n);
520 lambda_matrix_id (V, m);
522 for (j = 0; j < n; j++)
524 if (lambda_vector_first_nz (S[j], m, i0) < m)
526 ++i0;
527 for (i = m - 1; i >= i0; i--)
529 while (S[i][j] != 0)
531 int sigma, factor, a, b;
533 a = S[i-1][j];
534 b = S[i][j];
535 sigma = (a * b < 0) ? -1: 1;
536 a = abs (a);
537 b = abs (b);
538 factor = sigma * (a / b);
540 lambda_matrix_row_add (S, n, i, i-1, -factor);
541 lambda_matrix_row_exchange (S, i, i-1);
543 lambda_matrix_col_add (V, m, i-1, i, factor);
544 lambda_matrix_col_exchange (V, m, i, i-1);
551 /* When it exists, return the first non-zero row in MAT after row
552 STARTROW. Otherwise return rowsize. */
555 lambda_matrix_first_nz_vec (lambda_matrix mat, int rowsize, int colsize,
556 int startrow)
558 int j;
559 bool found = false;
561 for (j = startrow; (j < rowsize) && !found; j++)
563 if ((mat[j] != NULL)
564 && (lambda_vector_first_nz (mat[j], colsize, startrow) < colsize))
565 found = true;
568 if (found)
569 return j - 1;
570 return rowsize;
573 /* Calculate the projection of E sub k to the null space of B. */
575 void
576 lambda_matrix_project_to_null (lambda_matrix B, int rowsize,
577 int colsize, int k, lambda_vector x)
579 lambda_matrix M1, M2, M3, I;
580 int determinant;
582 /* compute c(I-B^T inv(B B^T) B) e sub k */
584 /* M1 is the transpose of B */
585 M1 = lambda_matrix_new (colsize, colsize);
586 lambda_matrix_transpose (B, M1, rowsize, colsize);
588 /* M2 = B * B^T */
589 M2 = lambda_matrix_new (colsize, colsize);
590 lambda_matrix_mult (B, M1, M2, rowsize, colsize, rowsize);
592 /* M3 = inv(M2) */
593 M3 = lambda_matrix_new (colsize, colsize);
594 determinant = lambda_matrix_inverse (M2, M3, rowsize);
596 /* M2 = B^T (inv(B B^T)) */
597 lambda_matrix_mult (M1, M3, M2, colsize, rowsize, rowsize);
599 /* M1 = B^T (inv(B B^T)) B */
600 lambda_matrix_mult (M2, B, M1, colsize, rowsize, colsize);
601 lambda_matrix_negate (M1, M1, colsize, colsize);
603 I = lambda_matrix_new (colsize, colsize);
604 lambda_matrix_id (I, colsize);
606 lambda_matrix_add_mc (I, determinant, M1, 1, M2, colsize, colsize);
608 lambda_matrix_get_column (M2, colsize, k - 1, x);
612 /* Multiply a vector VEC by a matrix MAT.
613 MAT is an M*N matrix, and VEC is a vector with length N. The result
614 is stored in DEST which must be a vector of length M. */
616 void
617 lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n,
618 lambda_vector vec, lambda_vector dest)
620 int i, j;
622 lambda_vector_clear (dest, m);
623 for (i = 0; i < m; i++)
624 for (j = 0; j < n; j++)
625 dest[i] += matrix[i][j] * vec[j];
628 /* Print out an M x N matrix MAT to OUTFILE. */
630 void
631 print_lambda_matrix (FILE * outfile, lambda_matrix matrix, int m, int n)
633 int i;
635 for (i = 0; i < m; i++)
636 print_lambda_vector (outfile, matrix[i], n);
637 fprintf (outfile, "\n");