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
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 COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include "coretypes.h"
29 static void lambda_matrix_get_column (lambda_matrix
, int, int,
32 /* Allocate a matrix of M rows x N cols. */
35 lambda_matrix_new (int m
, int n
)
40 mat
= ggc_alloc (m
* sizeof (lambda_vector
));
42 for (i
= 0; i
< m
; i
++)
43 mat
[i
] = lambda_vector_new (n
);
48 /* Copy the elements of M x N matrix MAT1 to MAT2. */
51 lambda_matrix_copy (lambda_matrix mat1
, lambda_matrix mat2
,
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. */
63 lambda_matrix_id (lambda_matrix mat
, int size
)
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. */
75 lambda_matrix_negate (lambda_matrix mat1
, lambda_matrix mat2
, int m
, int n
)
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. */
87 lambda_matrix_transpose (lambda_matrix mat1
, lambda_matrix mat2
, int m
, int n
)
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. */
100 lambda_matrix_add (lambda_matrix mat1
, lambda_matrix mat2
,
101 lambda_matrix mat3
, int m
, int n
)
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. */
112 lambda_matrix_add_mc (lambda_matrix mat1
, int const1
,
113 lambda_matrix mat2
, int const2
,
114 lambda_matrix mat3
, int m
, int n
)
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. */
127 lambda_matrix_mult (lambda_matrix mat1
, lambda_matrix mat2
,
128 lambda_matrix mat3
, int m
, int r
, int n
)
133 for (i
= 0; i
< m
; i
++)
135 for (j
= 0; j
< n
; j
++)
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. */
148 lambda_matrix_get_column (lambda_matrix mat
, int n
, int col
,
153 for (i
= 0; i
< n
; i
++)
154 vec
[i
] = mat
[i
][col
];
157 /* Delete rows r1 to r2 (not including r2). */
160 lambda_matrix_delete_rows (lambda_matrix mat
, int rows
, int from
, int to
)
166 for (i
= to
; i
< rows
; i
++)
167 mat
[i
- dist
] = mat
[i
];
169 for (i
= rows
- dist
; i
< rows
; i
++)
173 /* Swap rows R1 and R2 in matrix MAT. */
176 lambda_matrix_row_exchange (lambda_matrix mat
, int r1
, int r2
)
185 /* Add a multiple of row R1 of matrix MAT with N columns to row R2:
186 R2 = R2 + CONST1 * R1. */
189 lambda_matrix_row_add (lambda_matrix mat
, int n
, int r1
, int r2
, int const1
)
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. */
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. */
211 lambda_matrix_row_mc (lambda_matrix mat
, int n
, int r1
, int const1
)
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. */
222 lambda_matrix_col_exchange (lambda_matrix mat
, int m
, int col1
, int col2
)
226 for (i
= 0; i
< m
; i
++)
229 mat
[i
][col1
] = mat
[i
][col2
];
234 /* Add a multiple of column C1 of matrix MAT with M rows to column C2:
235 C2 = C2 + CONST1 * C1. */
238 lambda_matrix_col_add (lambda_matrix mat
, int m
, int c1
, int c2
, int const1
)
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. */
252 lambda_matrix_col_negate (lambda_matrix mat
, int m
, int c1
)
256 for (i
= 0; i
< m
; i
++)
260 /* Multiply column C1 of matrix MAT with M rows by CONST1. */
263 lambda_matrix_col_mc (lambda_matrix mat
, int m
, int c1
, int const1
)
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
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
)
302 det
= (a
* d
- b
* c
);
314 return lambda_matrix_inverse_hard (mat
, inv
, n
);
317 /* If MAT is not a special case, invert it the hard way. */
320 lambda_matrix_inverse_hard (lambda_matrix mat
, lambda_matrix inv
, int n
)
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
334 for (j
= 0; j
< n
; j
++)
338 /* Make every element in the current row positive. */
339 for (i
= j
; i
< n
; i
++)
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
++)
358 factor
= -1 * row
[i
];
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. */
373 for (j
= n
- 1; j
>= 0; j
--)
380 /* If the matrix is singular, 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
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
--)
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
);
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
420 lambda_matrix_hermite (lambda_matrix mat
, int n
,
421 lambda_matrix H
, lambda_matrix U
)
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
++)
433 /* Make every element of H[j][j..n] positive. */
434 for (i
= j
; i
< n
; i
++)
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. */
468 lambda_matrix_right_hermite (lambda_matrix A
, int m
, int n
,
469 lambda_matrix S
, lambda_matrix U
)
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
)
481 for (i
= m
- 1; i
>= i0
; i
--)
485 int sigma
, factor
, a
, b
;
489 sigma
= (a
* b
< 0) ? -1: 1;
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. */
513 lambda_matrix_left_hermite (lambda_matrix A
, int m
, int n
,
514 lambda_matrix S
, lambda_matrix V
)
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
)
526 for (i
= m
- 1; i
>= i0
; i
--)
530 int sigma
, factor
, a
, b
;
534 sigma
= (a
* b
< 0) ? -1: 1;
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
,
560 for (j
= startrow
; (j
< rowsize
) && !found
; j
++)
563 && (lambda_vector_first_nz (mat
[j
], colsize
, startrow
) < colsize
))
572 /* Calculate the projection of E sub k to the null space of B. */
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
;
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
);
588 M2
= lambda_matrix_new (colsize
, colsize
);
589 lambda_matrix_mult (B
, M1
, M2
, rowsize
, colsize
, rowsize
);
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. */
616 lambda_matrix_vector_mult (lambda_matrix matrix
, int m
, int n
,
617 lambda_vector vec
, lambda_vector dest
)
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. */
630 print_lambda_matrix (FILE * outfile
, lambda_matrix matrix
, int m
, int n
)
634 for (i
= 0; i
< m
; i
++)
635 print_lambda_vector (outfile
, matrix
[i
], n
);
636 fprintf (outfile
, "\n");