* config/mips/mips.md (length): Don't use mips_fetch_insns for indexed
[official-gcc.git] / gcc / lambda-mat.c
blob987fa5e1fd17c46b13c867ffc1d4c5522a6459df
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 "lambda.h"
29 static void lambda_matrix_get_column (lambda_matrix, int, int,
30 lambda_vector);
32 /* Allocate a matrix of M rows x N cols. */
34 lambda_matrix
35 lambda_matrix_new (int m, int n)
37 lambda_matrix mat;
38 int i;
40 mat = ggc_alloc (m * sizeof (lambda_vector));
42 for (i = 0; i < m; i++)
43 mat[i] = lambda_vector_new (n);
45 return mat;
48 /* Copy the elements of M x N matrix MAT1 to MAT2. */
50 void
51 lambda_matrix_copy (lambda_matrix mat1, lambda_matrix mat2,
52 int m, int n)
54 int i;
56 for (i = 0; i < m; i++)
57 lambda_vector_copy (mat1[i], mat2[i], n);
60 /* Store the N x N identity matrix in MAT. */
62 void
63 lambda_matrix_id (lambda_matrix mat, int size)
65 int i, j;
67 for (i = 0; i < size; i++)
68 for (j = 0; j < size; j++)
69 mat[i][j] = (i == j) ? 1 : 0;
72 /* Negate the elements of the M x N matrix MAT1 and store it in MAT2. */
74 void
75 lambda_matrix_negate (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
77 int i;
79 for (i = 0; i < m; i++)
80 lambda_vector_negate (mat1[i], mat2[i], n);
83 /* Take the transpose of matrix MAT1 and store it in MAT2.
84 MAT1 is an M x N matrix, so MAT2 must be N x M. */
86 void
87 lambda_matrix_transpose (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
89 int i, j;
91 for (i = 0; i < n; i++)
92 for (j = 0; j < m; j++)
93 mat2[i][j] = mat1[j][i];
97 /* Add two M x N matrices together: MAT3 = MAT1+MAT2. */
99 void
100 lambda_matrix_add (lambda_matrix mat1, lambda_matrix mat2,
101 lambda_matrix mat3, int m, int n)
103 int i;
105 for (i = 0; i < m; i++)
106 lambda_vector_add (mat1[i], mat2[i], mat3[i], n);
109 /* MAT3 = CONST1 * MAT1 + CONST2 * MAT2. All matrices are M x N. */
111 void
112 lambda_matrix_add_mc (lambda_matrix mat1, int const1,
113 lambda_matrix mat2, int const2,
114 lambda_matrix mat3, int m, int n)
116 int i;
118 for (i = 0; i < m; i++)
119 lambda_vector_add_mc (mat1[i], const1, mat2[i], const2, mat3[i], n);
122 /* Multiply two matrices: MAT3 = MAT1 * MAT2.
123 MAT1 is an M x R matrix, and MAT2 is R x N. The resulting MAT2
124 must therefore be M x N. */
126 void
127 lambda_matrix_mult (lambda_matrix mat1, lambda_matrix mat2,
128 lambda_matrix mat3, int m, int r, int n)
131 int i, j, k;
133 for (i = 0; i < m; i++)
135 for (j = 0; j < n; j++)
137 mat3[i][j] = 0;
138 for (k = 0; k < r; k++)
139 mat3[i][j] += mat1[i][k] * mat2[k][j];
144 /* Get column COL from the matrix MAT and store it in VEC. MAT has
145 N rows, so the length of VEC must be N. */
147 static void
148 lambda_matrix_get_column (lambda_matrix mat, int n, int col,
149 lambda_vector vec)
151 int i;
153 for (i = 0; i < n; i++)
154 vec[i] = mat[i][col];
157 /* Delete rows r1 to r2 (not including r2). */
159 void
160 lambda_matrix_delete_rows (lambda_matrix mat, int rows, int from, int to)
162 int i;
163 int dist;
164 dist = to - from;
166 for (i = to; i < rows; i++)
167 mat[i - dist] = mat[i];
169 for (i = rows - dist; i < rows; i++)
170 mat[i] = NULL;
173 /* Swap rows R1 and R2 in matrix MAT. */
175 void
176 lambda_matrix_row_exchange (lambda_matrix mat, int r1, int r2)
178 lambda_vector row;
180 row = mat[r1];
181 mat[r1] = mat[r2];
182 mat[r2] = row;
185 /* Add a multiple of row R1 of matrix MAT with N columns to row R2:
186 R2 = R2 + CONST1 * R1. */
188 void
189 lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2, int const1)
191 int i;
193 if (const1 == 0)
194 return;
196 for (i = 0; i < n; i++)
197 mat[r2][i] += const1 * mat[r1][i];
200 /* Negate row R1 of matrix MAT which has N columns. */
202 void
203 lambda_matrix_row_negate (lambda_matrix mat, int n, int r1)
205 lambda_vector_negate (mat[r1], mat[r1], n);
208 /* Multiply row R1 of matrix MAT with N columns by CONST1. */
210 void
211 lambda_matrix_row_mc (lambda_matrix mat, int n, int r1, int const1)
213 int i;
215 for (i = 0; i < n; i++)
216 mat[r1][i] *= const1;
219 /* Exchange COL1 and COL2 in matrix MAT. M is the number of rows. */
221 void
222 lambda_matrix_col_exchange (lambda_matrix mat, int m, int col1, int col2)
224 int i;
225 int tmp;
226 for (i = 0; i < m; i++)
228 tmp = mat[i][col1];
229 mat[i][col1] = mat[i][col2];
230 mat[i][col2] = tmp;
234 /* Add a multiple of column C1 of matrix MAT with M rows to column C2:
235 C2 = C2 + CONST1 * C1. */
237 void
238 lambda_matrix_col_add (lambda_matrix mat, int m, int c1, int c2, int const1)
240 int i;
242 if (const1 == 0)
243 return;
245 for (i = 0; i < m; i++)
246 mat[i][c2] += const1 * mat[i][c1];
249 /* Negate column C1 of matrix MAT which has M rows. */
251 void
252 lambda_matrix_col_negate (lambda_matrix mat, int m, int c1)
254 int i;
256 for (i = 0; i < m; i++)
257 mat[i][c1] *= -1;
260 /* Multiply column C1 of matrix MAT with M rows by CONST1. */
262 void
263 lambda_matrix_col_mc (lambda_matrix mat, int m, int c1, int const1)
265 int i;
267 for (i = 0; i < m; i++)
268 mat[i][c1] *= const1;
271 /* Compute the inverse of the N x N matrix MAT and store it in INV.
273 We don't _really_ compute the inverse of MAT. Instead we compute
274 det(MAT)*inv(MAT), and we return det(MAT) to the caller as the function
275 result. This is necessary to preserve accuracy, because we are dealing
276 with integer matrices here.
278 The algorithm used here is a column based Gauss-Jordan elimination on MAT
279 and the identity matrix in parallel. The inverse is the result of applying
280 the same operations on the identity matrix that reduce MAT to the identity
281 matrix.
283 When MAT is a 2 x 2 matrix, we don't go through the whole process, because
284 it is easily inverted by inspection and it is a very common case. */
286 static int lambda_matrix_inverse_hard (lambda_matrix, lambda_matrix, int);
289 lambda_matrix_inverse (lambda_matrix mat, lambda_matrix inv, int n)
291 if (n == 2)
293 int a, b, c, d, det;
294 a = mat[0][0];
295 b = mat[1][0];
296 c = mat[0][1];
297 d = mat[1][1];
298 inv[0][0] = d;
299 inv[0][1] = -c;
300 inv[1][0] = -b;
301 inv[1][1] = a;
302 det = (a * d - b * c);
303 if (det < 0)
305 det *= -1;
306 inv[0][0] *= -1;
307 inv[1][0] *= -1;
308 inv[0][1] *= -1;
309 inv[1][1] *= -1;
311 return det;
313 else
314 return lambda_matrix_inverse_hard (mat, inv, n);
317 /* If MAT is not a special case, invert it the hard way. */
319 static int
320 lambda_matrix_inverse_hard (lambda_matrix mat, lambda_matrix inv, int n)
322 lambda_vector row;
323 lambda_matrix temp;
324 int i, j;
325 int determinant;
327 temp = lambda_matrix_new (n, n);
328 lambda_matrix_copy (mat, temp, n, n);
329 lambda_matrix_id (inv, n);
331 /* Reduce TEMP to a lower triangular form, applying the same operations on
332 INV which starts as the identity matrix. N is the number of rows and
333 columns. */
334 for (j = 0; j < n; j++)
336 row = temp[j];
338 /* Make every element in the current row positive. */
339 for (i = j; i < n; i++)
340 if (row[i] < 0)
342 lambda_matrix_col_negate (temp, n, i);
343 lambda_matrix_col_negate (inv, n, i);
346 /* Sweep the upper triangle. Stop when only the diagonal element in the
347 current row is nonzero. */
348 while (lambda_vector_first_nz (row, n, j + 1) < n)
350 int min_col = lambda_vector_min_nz (row, n, j);
351 lambda_matrix_col_exchange (temp, n, j, min_col);
352 lambda_matrix_col_exchange (inv, n, j, min_col);
354 for (i = j + 1; i < n; i++)
356 int factor;
358 factor = -1 * row[i];
359 if (row[j] != 1)
360 factor /= row[j];
362 lambda_matrix_col_add (temp, n, j, i, factor);
363 lambda_matrix_col_add (inv, n, j, i, factor);
368 /* Reduce TEMP from a lower triangular to the identity matrix. Also compute
369 the determinant, which now is simply the product of the elements on the
370 diagonal of TEMP. If one of these elements is 0, the matrix has 0 as an
371 eigenvalue so it is singular and hence not invertible. */
372 determinant = 1;
373 for (j = n - 1; j >= 0; j--)
375 int diagonal;
377 row = temp[j];
378 diagonal = row[j];
380 /* If the matrix is singular, abort. */
381 if (diagonal == 0)
382 abort ();
384 determinant = determinant * diagonal;
386 /* If the diagonal is not 1, then multiply the each row by the
387 diagonal so that the middle number is now 1, rather than a
388 rational. */
389 if (diagonal != 1)
391 for (i = 0; i < j; i++)
392 lambda_matrix_col_mc (inv, n, i, diagonal);
393 for (i = j + 1; i < n; i++)
394 lambda_matrix_col_mc (inv, n, i, diagonal);
396 row[j] = diagonal = 1;
399 /* Sweep the lower triangle column wise. */
400 for (i = j - 1; i >= 0; i--)
402 if (row[i])
404 int factor = -row[i];
405 lambda_matrix_col_add (temp, n, j, i, factor);
406 lambda_matrix_col_add (inv, n, j, i, factor);
412 return determinant;
415 /* Decompose a N x N matrix MAT to a product of a lower triangular H
416 and a unimodular U matrix such that MAT = H.U. N is the size of
417 the rows of MAT. */
419 void
420 lambda_matrix_hermite (lambda_matrix mat, int n,
421 lambda_matrix H, lambda_matrix U)
423 lambda_vector row;
424 int i, j, factor, minimum_col;
426 lambda_matrix_copy (mat, H, n, n);
427 lambda_matrix_id (U, n);
429 for (j = 0; j < n; j++)
431 row = H[j];
433 /* Make every element of H[j][j..n] positive. */
434 for (i = j; i < n; i++)
436 if (row[i] < 0)
438 lambda_matrix_col_negate (H, n, i);
439 lambda_vector_negate (U[i], U[i], n);
443 /* Stop when only the diagonal element is non-zero. */
444 while (lambda_vector_first_nz (row, n, j + 1) < n)
446 minimum_col = lambda_vector_min_nz (row, n, j);
447 lambda_matrix_col_exchange (H, n, j, minimum_col);
448 lambda_matrix_row_exchange (U, j, minimum_col);
450 for (i = j + 1; i < n; i++)
452 factor = row[i] / row[j];
453 lambda_matrix_col_add (H, n, j, i, -1 * factor);
454 lambda_matrix_row_add (U, n, i, j, factor);
460 /* Given an M x N integer matrix A, this function determines an M x
461 M unimodular matrix U, and an M x N echelon matrix S such that
462 "U.A = S". This decomposition is also known as "right Hermite".
464 Ref: Algorithm 2.1 page 33 in "Loop Transformations for
465 Restructuring Compilers" Utpal Banerjee. */
467 void
468 lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
469 lambda_matrix S, lambda_matrix U)
471 int i, j, i0 = 0;
473 lambda_matrix_copy (A, S, m, n);
474 lambda_matrix_id (U, m);
476 for (j = 0; j < n; j++)
478 if (lambda_vector_first_nz (S[j], m, i0) < m)
480 ++i0;
481 for (i = m - 1; i >= i0; i--)
483 while (S[i][j] != 0)
485 int sigma, factor, a, b;
487 a = S[i-1][j];
488 b = S[i][j];
489 sigma = (a * b < 0) ? -1: 1;
490 a = abs (a);
491 b = abs (b);
492 factor = sigma * (a / b);
494 lambda_matrix_row_add (S, n, i, i-1, -factor);
495 lambda_matrix_row_exchange (S, i, i-1);
497 lambda_matrix_row_add (U, m, i, i-1, -factor);
498 lambda_matrix_row_exchange (U, i, i-1);
505 /* Given an M x N integer matrix A, this function determines an M x M
506 unimodular matrix V, and an M x N echelon matrix S such that "A =
507 V.S". This decomposition is also known as "left Hermite".
509 Ref: Algorithm 2.2 page 36 in "Loop Transformations for
510 Restructuring Compilers" Utpal Banerjee. */
512 void
513 lambda_matrix_left_hermite (lambda_matrix A, int m, int n,
514 lambda_matrix S, lambda_matrix V)
516 int i, j, i0 = 0;
518 lambda_matrix_copy (A, S, m, n);
519 lambda_matrix_id (V, m);
521 for (j = 0; j < n; j++)
523 if (lambda_vector_first_nz (S[j], m, i0) < m)
525 ++i0;
526 for (i = m - 1; i >= i0; i--)
528 while (S[i][j] != 0)
530 int sigma, factor, a, b;
532 a = S[i-1][j];
533 b = S[i][j];
534 sigma = (a * b < 0) ? -1: 1;
535 a = abs (a);
536 b = abs (b);
537 factor = sigma * (a / b);
539 lambda_matrix_row_add (S, n, i, i-1, -factor);
540 lambda_matrix_row_exchange (S, i, i-1);
542 lambda_matrix_col_add (V, m, i-1, i, factor);
543 lambda_matrix_col_exchange (V, m, i, i-1);
550 /* When it exists, return the first non-zero row in MAT after row
551 STARTROW. Otherwise return rowsize. */
554 lambda_matrix_first_nz_vec (lambda_matrix mat, int rowsize, int colsize,
555 int startrow)
557 int j;
558 bool found = false;
560 for (j = startrow; (j < rowsize) && !found; j++)
562 if ((mat[j] != NULL)
563 && (lambda_vector_first_nz (mat[j], colsize, startrow) < colsize))
564 found = true;
567 if (found)
568 return j - 1;
569 return rowsize;
572 /* Calculate the projection of E sub k to the null space of B. */
574 void
575 lambda_matrix_project_to_null (lambda_matrix B, int rowsize,
576 int colsize, int k, lambda_vector x)
578 lambda_matrix M1, M2, M3, I;
579 int determinant;
581 /* compute c(I-B^T inv(B B^T) B) e sub k */
583 /* M1 is the transpose of B */
584 M1 = lambda_matrix_new (colsize, colsize);
585 lambda_matrix_transpose (B, M1, rowsize, colsize);
587 /* M2 = B * B^T */
588 M2 = lambda_matrix_new (colsize, colsize);
589 lambda_matrix_mult (B, M1, M2, rowsize, colsize, rowsize);
591 /* M3 = inv(M2) */
592 M3 = lambda_matrix_new (colsize, colsize);
593 determinant = lambda_matrix_inverse (M2, M3, rowsize);
595 /* M2 = B^T (inv(B B^T)) */
596 lambda_matrix_mult (M1, M3, M2, colsize, rowsize, rowsize);
598 /* M1 = B^T (inv(B B^T)) B */
599 lambda_matrix_mult (M2, B, M1, colsize, rowsize, colsize);
600 lambda_matrix_negate (M1, M1, colsize, colsize);
602 I = lambda_matrix_new (colsize, colsize);
603 lambda_matrix_id (I, colsize);
605 lambda_matrix_add_mc (I, determinant, M1, 1, M2, colsize, colsize);
607 lambda_matrix_get_column (M2, colsize, k - 1, x);
611 /* Multiply a vector VEC by a matrix MAT.
612 MAT is an M*N matrix, and VEC is a vector with length N. The result
613 is stored in DEST which must be a vector of length M. */
615 void
616 lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n,
617 lambda_vector vec, lambda_vector dest)
619 int i, j;
621 lambda_vector_clear (dest, m);
622 for (i = 0; i < m; i++)
623 for (j = 0; j < n; j++)
624 dest[i] += matrix[i][j] * vec[j];
627 /* Print out an M x N matrix MAT to OUTFILE. */
629 void
630 print_lambda_matrix (FILE * outfile, lambda_matrix matrix, int m, int n)
632 int i;
634 for (i = 0; i < m; i++)
635 print_lambda_vector (outfile, matrix[i], n);
636 fprintf (outfile, "\n");