1 /* Integer matrix math routines
2 Copyright (C) 2003, 2004, 2005, 2007, 2008 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 3, or (at your option) any later
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
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
24 #include "tree-flow.h"
27 /* Allocate a matrix of M rows x N cols. */
30 lambda_matrix_new (int m, int n, struct obstack * lambda_obstack)
35 mat = (lambda_matrix) obstack_alloc (lambda_obstack,
36 sizeof (lambda_vector *) * m);
38 for (i = 0; i < m; i++)
39 mat[i] = lambda_vector_new (n);
44 /* Copy the elements of M x N matrix MAT1 to MAT2. */
47 lambda_matrix_copy (lambda_matrix mat1, lambda_matrix mat2,
52 for (i = 0; i < m; i++)
53 lambda_vector_copy (mat1[i], mat2[i], n);
56 /* Store the N x N identity matrix in MAT. */
59 lambda_matrix_id (lambda_matrix mat, int size)
63 for (i = 0; i < size; i++)
64 for (j = 0; j < size; j++)
65 mat[i][j] = (i == j) ? 1 : 0;
68 /* Return true if MAT is the identity matrix of SIZE */
71 lambda_matrix_id_p (lambda_matrix mat, int size)
74 for (i = 0; i < size; i++)
75 for (j = 0; j < size; j++)
91 /* Negate the elements of the M x N matrix MAT1 and store it in MAT2. */
94 lambda_matrix_negate (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
98 for (i = 0; i < m; i++)
99 lambda_vector_negate (mat1[i], mat2[i], n);
102 /* Take the transpose of matrix MAT1 and store it in MAT2.
103 MAT1 is an M x N matrix, so MAT2 must be N x M. */
106 lambda_matrix_transpose (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
110 for (i = 0; i < n; i++)
111 for (j = 0; j < m; j++)
112 mat2[i][j] = mat1[j][i];
116 /* Add two M x N matrices together: MAT3 = MAT1+MAT2. */
119 lambda_matrix_add (lambda_matrix mat1, lambda_matrix mat2,
120 lambda_matrix mat3, int m, int n)
124 for (i = 0; i < m; i++)
125 lambda_vector_add (mat1[i], mat2[i], mat3[i], n);
128 /* MAT3 = CONST1 * MAT1 + CONST2 * MAT2. All matrices are M x N. */
131 lambda_matrix_add_mc (lambda_matrix mat1, int const1,
132 lambda_matrix mat2, int const2,
133 lambda_matrix mat3, int m, int n)
137 for (i = 0; i < m; i++)
138 lambda_vector_add_mc (mat1[i], const1, mat2[i], const2, mat3[i], n);
141 /* Multiply two matrices: MAT3 = MAT1 * MAT2.
142 MAT1 is an M x R matrix, and MAT2 is R x N. The resulting MAT2
143 must therefore be M x N. */
146 lambda_matrix_mult (lambda_matrix mat1, lambda_matrix mat2,
147 lambda_matrix mat3, int m, int r, int n)
152 for (i = 0; i < m; i++)
154 for (j = 0; j < n; j++)
157 for (k = 0; k < r; k++)
158 mat3[i][j] += mat1[i][k] * mat2[k][j];
163 /* Delete rows r1 to r2 (not including r2). */
166 lambda_matrix_delete_rows (lambda_matrix mat, int rows, int from, int to)
172 for (i = to; i < rows; i++)
173 mat[i - dist] = mat[i];
175 for (i = rows - dist; i < rows; i++)
179 /* Swap rows R1 and R2 in matrix MAT. */
182 lambda_matrix_row_exchange (lambda_matrix mat, int r1, int r2)
191 /* Add a multiple of row R1 of matrix MAT with N columns to row R2:
192 R2 = R2 + CONST1 * R1. */
195 lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2, int const1)
202 for (i = 0; i < n; i++)
203 mat[r2][i] += const1 * mat[r1][i];
206 /* Negate row R1 of matrix MAT which has N columns. */
209 lambda_matrix_row_negate (lambda_matrix mat, int n, int r1)
211 lambda_vector_negate (mat[r1], mat[r1], n);
214 /* Multiply row R1 of matrix MAT with N columns by CONST1. */
217 lambda_matrix_row_mc (lambda_matrix mat, int n, int r1, int const1)
221 for (i = 0; i < n; i++)
222 mat[r1][i] *= const1;
225 /* Exchange COL1 and COL2 in matrix MAT. M is the number of rows. */
228 lambda_matrix_col_exchange (lambda_matrix mat, int m, int col1, int col2)
232 for (i = 0; i < m; i++)
235 mat[i][col1] = mat[i][col2];
240 /* Add a multiple of column C1 of matrix MAT with M rows to column C2:
241 C2 = C2 + CONST1 * C1. */
244 lambda_matrix_col_add (lambda_matrix mat, int m, int c1, int c2, int const1)
251 for (i = 0; i < m; i++)
252 mat[i][c2] += const1 * mat[i][c1];
255 /* Negate column C1 of matrix MAT which has M rows. */
258 lambda_matrix_col_negate (lambda_matrix mat, int m, int c1)
262 for (i = 0; i < m; i++)
266 /* Multiply column C1 of matrix MAT with M rows by CONST1. */
269 lambda_matrix_col_mc (lambda_matrix mat, int m, int c1, int const1)
273 for (i = 0; i < m; i++)
274 mat[i][c1] *= const1;
277 /* Compute the inverse of the N x N matrix MAT and store it in INV.
279 We don't _really_ compute the inverse of MAT. Instead we compute
280 det(MAT)*inv(MAT), and we return det(MAT) to the caller as the function
281 result. This is necessary to preserve accuracy, because we are dealing
282 with integer matrices here.
284 The algorithm used here is a column based Gauss-Jordan elimination on MAT
285 and the identity matrix in parallel. The inverse is the result of applying
286 the same operations on the identity matrix that reduce MAT to the identity
289 When MAT is a 2 x 2 matrix, we don't go through the whole process, because
290 it is easily inverted by inspection and it is a very common case. */
292 static int lambda_matrix_inverse_hard (lambda_matrix, lambda_matrix, int,
296 lambda_matrix_inverse (lambda_matrix mat, lambda_matrix inv, int n,
297 struct obstack * lambda_obstack)
310 det = (a * d - b * c);
322 return lambda_matrix_inverse_hard (mat, inv, n, lambda_obstack);
325 /* If MAT is not a special case, invert it the hard way. */
328 lambda_matrix_inverse_hard (lambda_matrix mat, lambda_matrix inv, int n,
329 struct obstack * lambda_obstack)
336 temp = lambda_matrix_new (n, n, lambda_obstack);
337 lambda_matrix_copy (mat, temp, n, n);
338 lambda_matrix_id (inv, n);
340 /* Reduce TEMP to a lower triangular form, applying the same operations on
341 INV which starts as the identity matrix. N is the number of rows and
343 for (j = 0; j < n; j++)
347 /* Make every element in the current row positive. */
348 for (i = j; i < n; i++)
351 lambda_matrix_col_negate (temp, n, i);
352 lambda_matrix_col_negate (inv, n, i);
355 /* Sweep the upper triangle. Stop when only the diagonal element in the
356 current row is nonzero. */
357 while (lambda_vector_first_nz (row, n, j + 1) < n)
359 int min_col = lambda_vector_min_nz (row, n, j);
360 lambda_matrix_col_exchange (temp, n, j, min_col);
361 lambda_matrix_col_exchange (inv, n, j, min_col);
363 for (i = j + 1; i < n; i++)
367 factor = -1 * row[i];
371 lambda_matrix_col_add (temp, n, j, i, factor);
372 lambda_matrix_col_add (inv, n, j, i, factor);
377 /* Reduce TEMP from a lower triangular to the identity matrix. Also compute
378 the determinant, which now is simply the product of the elements on the
379 diagonal of TEMP. If one of these elements is 0, the matrix has 0 as an
380 eigenvalue so it is singular and hence not invertible. */
382 for (j = n - 1; j >= 0; j--)
389 /* The matrix must not be singular. */
390 gcc_assert (diagonal);
392 determinant = determinant * diagonal;
394 /* If the diagonal is not 1, then multiply the each row by the
395 diagonal so that the middle number is now 1, rather than a
399 for (i = 0; i < j; i++)
400 lambda_matrix_col_mc (inv, n, i, diagonal);
401 for (i = j + 1; i < n; i++)
402 lambda_matrix_col_mc (inv, n, i, diagonal);
404 row[j] = diagonal = 1;
407 /* Sweep the lower triangle column wise. */
408 for (i = j - 1; i >= 0; i--)
412 int factor = -row[i];
413 lambda_matrix_col_add (temp, n, j, i, factor);
414 lambda_matrix_col_add (inv, n, j, i, factor);
423 /* Decompose a N x N matrix MAT to a product of a lower triangular H
424 and a unimodular U matrix such that MAT = H.U. N is the size of
428 lambda_matrix_hermite (lambda_matrix mat, int n,
429 lambda_matrix H, lambda_matrix U)
432 int i, j, factor, minimum_col;
434 lambda_matrix_copy (mat, H, n, n);
435 lambda_matrix_id (U, n);
437 for (j = 0; j < n; j++)
441 /* Make every element of H[j][j..n] positive. */
442 for (i = j; i < n; i++)
446 lambda_matrix_col_negate (H, n, i);
447 lambda_vector_negate (U[i], U[i], n);
451 /* Stop when only the diagonal element is nonzero. */
452 while (lambda_vector_first_nz (row, n, j + 1) < n)
454 minimum_col = lambda_vector_min_nz (row, n, j);
455 lambda_matrix_col_exchange (H, n, j, minimum_col);
456 lambda_matrix_row_exchange (U, j, minimum_col);
458 for (i = j + 1; i < n; i++)
460 factor = row[i] / row[j];
461 lambda_matrix_col_add (H, n, j, i, -1 * factor);
462 lambda_matrix_row_add (U, n, i, j, factor);
468 /* Given an M x N integer matrix A, this function determines an M x
469 M unimodular matrix U, and an M x N echelon matrix S such that
470 "U.A = S". This decomposition is also known as "right Hermite".
472 Ref: Algorithm 2.1 page 33 in "Loop Transformations for
473 Restructuring Compilers" Utpal Banerjee. */
476 lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
477 lambda_matrix S, lambda_matrix U)
481 lambda_matrix_copy (A, S, m, n);
482 lambda_matrix_id (U, m);
484 for (j = 0; j < n; j++)
486 if (lambda_vector_first_nz (S[j], m, i0) < m)
489 for (i = m - 1; i >= i0; i--)
493 int sigma, factor, a, b;
497 sigma = (a * b < 0) ? -1: 1;
500 factor = sigma * (a / b);
502 lambda_matrix_row_add (S, n, i, i-1, -factor);
503 lambda_matrix_row_exchange (S, i, i-1);
505 lambda_matrix_row_add (U, m, i, i-1, -factor);
506 lambda_matrix_row_exchange (U, i, i-1);
513 /* Given an M x N integer matrix A, this function determines an M x M
514 unimodular matrix V, and an M x N echelon matrix S such that "A =
515 V.S". This decomposition is also known as "left Hermite".
517 Ref: Algorithm 2.2 page 36 in "Loop Transformations for
518 Restructuring Compilers" Utpal Banerjee. */
521 lambda_matrix_left_hermite (lambda_matrix A, int m, int n,
522 lambda_matrix S, lambda_matrix V)
526 lambda_matrix_copy (A, S, m, n);
527 lambda_matrix_id (V, m);
529 for (j = 0; j < n; j++)
531 if (lambda_vector_first_nz (S[j], m, i0) < m)
534 for (i = m - 1; i >= i0; i--)
538 int sigma, factor, a, b;
542 sigma = (a * b < 0) ? -1: 1;
545 factor = sigma * (a / b);
547 lambda_matrix_row_add (S, n, i, i-1, -factor);
548 lambda_matrix_row_exchange (S, i, i-1);
550 lambda_matrix_col_add (V, m, i-1, i, factor);
551 lambda_matrix_col_exchange (V, m, i, i-1);
558 /* When it exists, return the first nonzero row in MAT after row
559 STARTROW. Otherwise return rowsize. */
562 lambda_matrix_first_nz_vec (lambda_matrix mat, int rowsize, int colsize,
568 for (j = startrow; (j < rowsize) && !found; j++)
571 && (lambda_vector_first_nz (mat[j], colsize, startrow) < colsize))
580 /* Multiply a vector VEC by a matrix MAT.
581 MAT is an M*N matrix, and VEC is a vector with length N. The result
582 is stored in DEST which must be a vector of length M. */
585 lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n,
586 lambda_vector vec, lambda_vector dest)
590 lambda_vector_clear (dest, m);
591 for (i = 0; i < m; i++)
592 for (j = 0; j < n; j++)
593 dest[i] += matrix[i][j] * vec[j];
596 /* Print out an M x N matrix MAT to OUTFILE. */
599 print_lambda_matrix (FILE * outfile, lambda_matrix matrix, int m, int n)
603 for (i = 0; i < m; i++)
604 print_lambda_vector (outfile, matrix[i], n);
605 fprintf (outfile, "\n");