]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/lambda-mat.c
Do not include unnecessary .h files.
[thirdparty/gcc.git] / gcc / lambda-mat.c
CommitLineData
98975653 1/* Integer matrix math routines
66647d44 2 Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
98975653
DB
3 Contributed by Daniel Berlin <dberlin@dberlin.org>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9dcd6f09 9Software Foundation; either version 3, or (at your option) any later
98975653
DB
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
9dcd6f09
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
98975653
DB
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
726a989a 24#include "tree-flow.h"
98975653
DB
25#include "lambda.h"
26
98975653
DB
27/* Allocate a matrix of M rows x N cols. */
28
29lambda_matrix
f873b205 30lambda_matrix_new (int m, int n, struct obstack * lambda_obstack)
98975653
DB
31{
32 lambda_matrix mat;
33 int i;
34
f873b205
LB
35 mat = (lambda_matrix) obstack_alloc (lambda_obstack,
36 sizeof (lambda_vector *) * m);
b8698a0f 37
98975653
DB
38 for (i = 0; i < m; i++)
39 mat[i] = lambda_vector_new (n);
40
41 return mat;
42}
43
44/* Copy the elements of M x N matrix MAT1 to MAT2. */
45
46void
47lambda_matrix_copy (lambda_matrix mat1, lambda_matrix mat2,
48 int m, int n)
49{
50 int i;
51
52 for (i = 0; i < m; i++)
53 lambda_vector_copy (mat1[i], mat2[i], n);
54}
55
56/* Store the N x N identity matrix in MAT. */
57
58void
59lambda_matrix_id (lambda_matrix mat, int size)
60{
61 int i, j;
62
63 for (i = 0; i < size; i++)
64 for (j = 0; j < size; j++)
65 mat[i][j] = (i == j) ? 1 : 0;
66}
67
f67d92e9
DB
68/* Return true if MAT is the identity matrix of SIZE */
69
70bool
71lambda_matrix_id_p (lambda_matrix mat, int size)
72{
73 int i, j;
74 for (i = 0; i < size; i++)
75 for (j = 0; j < size; j++)
76 {
77 if (i == j)
78 {
79 if (mat[i][j] != 1)
80 return false;
81 }
82 else
83 {
84 if (mat[i][j] != 0)
85 return false;
86 }
87 }
88 return true;
89}
90
98975653
DB
91/* Negate the elements of the M x N matrix MAT1 and store it in MAT2. */
92
93void
94lambda_matrix_negate (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
95{
96 int i;
97
98 for (i = 0; i < m; i++)
99 lambda_vector_negate (mat1[i], mat2[i], n);
100}
101
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. */
104
105void
106lambda_matrix_transpose (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
107{
108 int i, j;
109
110 for (i = 0; i < n; i++)
111 for (j = 0; j < m; j++)
112 mat2[i][j] = mat1[j][i];
113}
114
115
116/* Add two M x N matrices together: MAT3 = MAT1+MAT2. */
117
118void
119lambda_matrix_add (lambda_matrix mat1, lambda_matrix mat2,
120 lambda_matrix mat3, int m, int n)
121{
122 int i;
123
124 for (i = 0; i < m; i++)
125 lambda_vector_add (mat1[i], mat2[i], mat3[i], n);
126}
127
128/* MAT3 = CONST1 * MAT1 + CONST2 * MAT2. All matrices are M x N. */
129
130void
131lambda_matrix_add_mc (lambda_matrix mat1, int const1,
132 lambda_matrix mat2, int const2,
133 lambda_matrix mat3, int m, int n)
134{
135 int i;
136
137 for (i = 0; i < m; i++)
138 lambda_vector_add_mc (mat1[i], const1, mat2[i], const2, mat3[i], n);
139}
140
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. */
144
145void
146lambda_matrix_mult (lambda_matrix mat1, lambda_matrix mat2,
147 lambda_matrix mat3, int m, int r, int n)
148{
149
150 int i, j, k;
151
152 for (i = 0; i < m; i++)
153 {
154 for (j = 0; j < n; j++)
155 {
156 mat3[i][j] = 0;
157 for (k = 0; k < r; k++)
158 mat3[i][j] += mat1[i][k] * mat2[k][j];
159 }
160 }
161}
162
8c27b7d4 163/* Delete rows r1 to r2 (not including r2). */
98975653
DB
164
165void
166lambda_matrix_delete_rows (lambda_matrix mat, int rows, int from, int to)
167{
168 int i;
169 int dist;
170 dist = to - from;
171
172 for (i = to; i < rows; i++)
173 mat[i - dist] = mat[i];
174
175 for (i = rows - dist; i < rows; i++)
176 mat[i] = NULL;
177}
178
179/* Swap rows R1 and R2 in matrix MAT. */
180
181void
182lambda_matrix_row_exchange (lambda_matrix mat, int r1, int r2)
183{
184 lambda_vector row;
185
186 row = mat[r1];
187 mat[r1] = mat[r2];
188 mat[r2] = row;
189}
190
191/* Add a multiple of row R1 of matrix MAT with N columns to row R2:
192 R2 = R2 + CONST1 * R1. */
193
194void
195lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2, int const1)
196{
197 int i;
198
199 if (const1 == 0)
200 return;
201
202 for (i = 0; i < n; i++)
203 mat[r2][i] += const1 * mat[r1][i];
204}
205
206/* Negate row R1 of matrix MAT which has N columns. */
207
208void
209lambda_matrix_row_negate (lambda_matrix mat, int n, int r1)
210{
211 lambda_vector_negate (mat[r1], mat[r1], n);
212}
213
214/* Multiply row R1 of matrix MAT with N columns by CONST1. */
215
216void
217lambda_matrix_row_mc (lambda_matrix mat, int n, int r1, int const1)
218{
219 int i;
220
221 for (i = 0; i < n; i++)
222 mat[r1][i] *= const1;
223}
224
225/* Exchange COL1 and COL2 in matrix MAT. M is the number of rows. */
226
227void
228lambda_matrix_col_exchange (lambda_matrix mat, int m, int col1, int col2)
229{
230 int i;
231 int tmp;
232 for (i = 0; i < m; i++)
233 {
234 tmp = mat[i][col1];
235 mat[i][col1] = mat[i][col2];
236 mat[i][col2] = tmp;
237 }
238}
239
240/* Add a multiple of column C1 of matrix MAT with M rows to column C2:
241 C2 = C2 + CONST1 * C1. */
242
243void
244lambda_matrix_col_add (lambda_matrix mat, int m, int c1, int c2, int const1)
245{
246 int i;
247
248 if (const1 == 0)
249 return;
250
251 for (i = 0; i < m; i++)
252 mat[i][c2] += const1 * mat[i][c1];
253}
254
255/* Negate column C1 of matrix MAT which has M rows. */
256
257void
258lambda_matrix_col_negate (lambda_matrix mat, int m, int c1)
259{
260 int i;
261
262 for (i = 0; i < m; i++)
263 mat[i][c1] *= -1;
264}
265
266/* Multiply column C1 of matrix MAT with M rows by CONST1. */
267
268void
269lambda_matrix_col_mc (lambda_matrix mat, int m, int c1, int const1)
270{
271 int i;
272
273 for (i = 0; i < m; i++)
274 mat[i][c1] *= const1;
275}
276
277/* Compute the inverse of the N x N matrix MAT and store it in INV.
278
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.
283
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
287 matrix.
288
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. */
291
f873b205
LB
292static int lambda_matrix_inverse_hard (lambda_matrix, lambda_matrix, int,
293 struct obstack *);
98975653
DB
294
295int
f873b205
LB
296lambda_matrix_inverse (lambda_matrix mat, lambda_matrix inv, int n,
297 struct obstack * lambda_obstack)
98975653
DB
298{
299 if (n == 2)
300 {
301 int a, b, c, d, det;
302 a = mat[0][0];
303 b = mat[1][0];
304 c = mat[0][1];
b8698a0f 305 d = mat[1][1];
98975653
DB
306 inv[0][0] = d;
307 inv[0][1] = -c;
308 inv[1][0] = -b;
309 inv[1][1] = a;
310 det = (a * d - b * c);
311 if (det < 0)
312 {
313 det *= -1;
314 inv[0][0] *= -1;
315 inv[1][0] *= -1;
316 inv[0][1] *= -1;
317 inv[1][1] *= -1;
318 }
319 return det;
320 }
321 else
f873b205 322 return lambda_matrix_inverse_hard (mat, inv, n, lambda_obstack);
98975653
DB
323}
324
325/* If MAT is not a special case, invert it the hard way. */
326
327static int
f873b205
LB
328lambda_matrix_inverse_hard (lambda_matrix mat, lambda_matrix inv, int n,
329 struct obstack * lambda_obstack)
98975653
DB
330{
331 lambda_vector row;
332 lambda_matrix temp;
333 int i, j;
334 int determinant;
335
f873b205 336 temp = lambda_matrix_new (n, n, lambda_obstack);
98975653
DB
337 lambda_matrix_copy (mat, temp, n, n);
338 lambda_matrix_id (inv, n);
339
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
342 columns. */
343 for (j = 0; j < n; j++)
344 {
345 row = temp[j];
346
347 /* Make every element in the current row positive. */
348 for (i = j; i < n; i++)
349 if (row[i] < 0)
350 {
351 lambda_matrix_col_negate (temp, n, i);
352 lambda_matrix_col_negate (inv, n, i);
353 }
354
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)
358 {
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);
362
363 for (i = j + 1; i < n; i++)
364 {
365 int factor;
366
367 factor = -1 * row[i];
368 if (row[j] != 1)
369 factor /= row[j];
370
371 lambda_matrix_col_add (temp, n, j, i, factor);
372 lambda_matrix_col_add (inv, n, j, i, factor);
373 }
374 }
375 }
376
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. */
381 determinant = 1;
382 for (j = n - 1; j >= 0; j--)
383 {
384 int diagonal;
385
386 row = temp[j];
387 diagonal = row[j];
388
41806d92
NS
389 /* The matrix must not be singular. */
390 gcc_assert (diagonal);
98975653
DB
391
392 determinant = determinant * diagonal;
393
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
396 rational. */
397 if (diagonal != 1)
398 {
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);
403
404 row[j] = diagonal = 1;
405 }
406
407 /* Sweep the lower triangle column wise. */
408 for (i = j - 1; i >= 0; i--)
409 {
410 if (row[i])
411 {
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);
415 }
416
417 }
418 }
419
420 return determinant;
421}
422
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
425 the rows of MAT. */
426
427void
428lambda_matrix_hermite (lambda_matrix mat, int n,
429 lambda_matrix H, lambda_matrix U)
430{
431 lambda_vector row;
432 int i, j, factor, minimum_col;
433
434 lambda_matrix_copy (mat, H, n, n);
435 lambda_matrix_id (U, n);
436
437 for (j = 0; j < n; j++)
438 {
439 row = H[j];
440
441 /* Make every element of H[j][j..n] positive. */
442 for (i = j; i < n; i++)
443 {
444 if (row[i] < 0)
445 {
446 lambda_matrix_col_negate (H, n, i);
447 lambda_vector_negate (U[i], U[i], n);
448 }
449 }
450
8e3c61c5 451 /* Stop when only the diagonal element is nonzero. */
98975653
DB
452 while (lambda_vector_first_nz (row, n, j + 1) < n)
453 {
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);
457
458 for (i = j + 1; i < n; i++)
459 {
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);
463 }
464 }
465 }
466}
467
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".
b8698a0f 471
98975653 472 Ref: Algorithm 2.1 page 33 in "Loop Transformations for
8c27b7d4 473 Restructuring Compilers" Utpal Banerjee. */
98975653
DB
474
475void
476lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
477 lambda_matrix S, lambda_matrix U)
478{
479 int i, j, i0 = 0;
480
481 lambda_matrix_copy (A, S, m, n);
482 lambda_matrix_id (U, m);
483
484 for (j = 0; j < n; j++)
485 {
486 if (lambda_vector_first_nz (S[j], m, i0) < m)
487 {
488 ++i0;
489 for (i = m - 1; i >= i0; i--)
490 {
491 while (S[i][j] != 0)
492 {
493 int sigma, factor, a, b;
494
495 a = S[i-1][j];
496 b = S[i][j];
497 sigma = (a * b < 0) ? -1: 1;
498 a = abs (a);
499 b = abs (b);
500 factor = sigma * (a / b);
501
502 lambda_matrix_row_add (S, n, i, i-1, -factor);
503 lambda_matrix_row_exchange (S, i, i-1);
504
505 lambda_matrix_row_add (U, m, i, i-1, -factor);
506 lambda_matrix_row_exchange (U, i, i-1);
507 }
508 }
509 }
510 }
511}
512
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".
b8698a0f 516
98975653 517 Ref: Algorithm 2.2 page 36 in "Loop Transformations for
8c27b7d4 518 Restructuring Compilers" Utpal Banerjee. */
98975653
DB
519
520void
521lambda_matrix_left_hermite (lambda_matrix A, int m, int n,
522 lambda_matrix S, lambda_matrix V)
523{
524 int i, j, i0 = 0;
525
526 lambda_matrix_copy (A, S, m, n);
527 lambda_matrix_id (V, m);
528
529 for (j = 0; j < n; j++)
530 {
531 if (lambda_vector_first_nz (S[j], m, i0) < m)
532 {
533 ++i0;
534 for (i = m - 1; i >= i0; i--)
535 {
536 while (S[i][j] != 0)
537 {
538 int sigma, factor, a, b;
539
540 a = S[i-1][j];
541 b = S[i][j];
542 sigma = (a * b < 0) ? -1: 1;
543 a = abs (a);
544 b = abs (b);
545 factor = sigma * (a / b);
546
547 lambda_matrix_row_add (S, n, i, i-1, -factor);
548 lambda_matrix_row_exchange (S, i, i-1);
549
550 lambda_matrix_col_add (V, m, i-1, i, factor);
551 lambda_matrix_col_exchange (V, m, i, i-1);
552 }
553 }
554 }
555 }
556}
557
8e3c61c5 558/* When it exists, return the first nonzero row in MAT after row
98975653
DB
559 STARTROW. Otherwise return rowsize. */
560
561int
562lambda_matrix_first_nz_vec (lambda_matrix mat, int rowsize, int colsize,
563 int startrow)
564{
565 int j;
566 bool found = false;
567
568 for (j = startrow; (j < rowsize) && !found; j++)
569 {
570 if ((mat[j] != NULL)
571 && (lambda_vector_first_nz (mat[j], colsize, startrow) < colsize))
572 found = true;
573 }
574
575 if (found)
576 return j - 1;
577 return rowsize;
578}
579
98975653
DB
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. */
583
584void
585lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n,
586 lambda_vector vec, lambda_vector dest)
587{
588 int i, j;
589
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];
594}
595
596/* Print out an M x N matrix MAT to OUTFILE. */
597
598void
599print_lambda_matrix (FILE * outfile, lambda_matrix matrix, int m, int n)
600{
601 int i;
602
603 for (i = 0; i < m; i++)
604 print_lambda_vector (outfile, matrix[i], n);
605 fprintf (outfile, "\n");
606}
607