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"
30 static void lambda_matrix_get_column (lambda_matrix
, int, int,
33 /* Allocate a matrix of M rows x N cols. */
36 lambda_matrix_new (int m
, int n
)
41 mat
= ggc_alloc (m
* sizeof (lambda_vector
));
43 for (i
= 0; i
< m
; i
++)
44 mat
[i
] = lambda_vector_new (n
);
49 /* Copy the elements of M x N matrix MAT1 to MAT2. */
52 lambda_matrix_copy (lambda_matrix mat1
, lambda_matrix mat2
,
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. */
64 lambda_matrix_id (lambda_matrix mat
, int size
)
68 for (i
= 0; i
< size
; i
++)
69 for (j
= 0; j
< size
; j
++)
70 mat
[i
][j
] = (i
== j
) ? 1 : 0;
73 /* Return true if MAT is the identity matrix of SIZE */
76 lambda_matrix_id_p (lambda_matrix mat
, int size
)
79 for (i
= 0; i
< size
; i
++)
80 for (j
= 0; j
< size
; j
++)
96 /* Negate the elements of the M x N matrix MAT1 and store it in MAT2. */
99 lambda_matrix_negate (lambda_matrix mat1
, lambda_matrix mat2
, int m
, int n
)
103 for (i
= 0; i
< m
; i
++)
104 lambda_vector_negate (mat1
[i
], mat2
[i
], n
);
107 /* Take the transpose of matrix MAT1 and store it in MAT2.
108 MAT1 is an M x N matrix, so MAT2 must be N x M. */
111 lambda_matrix_transpose (lambda_matrix mat1
, lambda_matrix mat2
, int m
, int n
)
115 for (i
= 0; i
< n
; i
++)
116 for (j
= 0; j
< m
; j
++)
117 mat2
[i
][j
] = mat1
[j
][i
];
121 /* Add two M x N matrices together: MAT3 = MAT1+MAT2. */
124 lambda_matrix_add (lambda_matrix mat1
, lambda_matrix mat2
,
125 lambda_matrix mat3
, int m
, int n
)
129 for (i
= 0; i
< m
; i
++)
130 lambda_vector_add (mat1
[i
], mat2
[i
], mat3
[i
], n
);
133 /* MAT3 = CONST1 * MAT1 + CONST2 * MAT2. All matrices are M x N. */
136 lambda_matrix_add_mc (lambda_matrix mat1
, int const1
,
137 lambda_matrix mat2
, int const2
,
138 lambda_matrix mat3
, int m
, int n
)
142 for (i
= 0; i
< m
; i
++)
143 lambda_vector_add_mc (mat1
[i
], const1
, mat2
[i
], const2
, mat3
[i
], n
);
146 /* Multiply two matrices: MAT3 = MAT1 * MAT2.
147 MAT1 is an M x R matrix, and MAT2 is R x N. The resulting MAT2
148 must therefore be M x N. */
151 lambda_matrix_mult (lambda_matrix mat1
, lambda_matrix mat2
,
152 lambda_matrix mat3
, int m
, int r
, int n
)
157 for (i
= 0; i
< m
; i
++)
159 for (j
= 0; j
< n
; j
++)
162 for (k
= 0; k
< r
; k
++)
163 mat3
[i
][j
] += mat1
[i
][k
] * mat2
[k
][j
];
168 /* Get column COL from the matrix MAT and store it in VEC. MAT has
169 N rows, so the length of VEC must be N. */
172 lambda_matrix_get_column (lambda_matrix mat
, int n
, int col
,
177 for (i
= 0; i
< n
; i
++)
178 vec
[i
] = mat
[i
][col
];
181 /* Delete rows r1 to r2 (not including r2). */
184 lambda_matrix_delete_rows (lambda_matrix mat
, int rows
, int from
, int to
)
190 for (i
= to
; i
< rows
; i
++)
191 mat
[i
- dist
] = mat
[i
];
193 for (i
= rows
- dist
; i
< rows
; i
++)
197 /* Swap rows R1 and R2 in matrix MAT. */
200 lambda_matrix_row_exchange (lambda_matrix mat
, int r1
, int r2
)
209 /* Add a multiple of row R1 of matrix MAT with N columns to row R2:
210 R2 = R2 + CONST1 * R1. */
213 lambda_matrix_row_add (lambda_matrix mat
, int n
, int r1
, int r2
, int const1
)
220 for (i
= 0; i
< n
; i
++)
221 mat
[r2
][i
] += const1
* mat
[r1
][i
];
224 /* Negate row R1 of matrix MAT which has N columns. */
227 lambda_matrix_row_negate (lambda_matrix mat
, int n
, int r1
)
229 lambda_vector_negate (mat
[r1
], mat
[r1
], n
);
232 /* Multiply row R1 of matrix MAT with N columns by CONST1. */
235 lambda_matrix_row_mc (lambda_matrix mat
, int n
, int r1
, int const1
)
239 for (i
= 0; i
< n
; i
++)
240 mat
[r1
][i
] *= const1
;
243 /* Exchange COL1 and COL2 in matrix MAT. M is the number of rows. */
246 lambda_matrix_col_exchange (lambda_matrix mat
, int m
, int col1
, int col2
)
250 for (i
= 0; i
< m
; i
++)
253 mat
[i
][col1
] = mat
[i
][col2
];
258 /* Add a multiple of column C1 of matrix MAT with M rows to column C2:
259 C2 = C2 + CONST1 * C1. */
262 lambda_matrix_col_add (lambda_matrix mat
, int m
, int c1
, int c2
, int const1
)
269 for (i
= 0; i
< m
; i
++)
270 mat
[i
][c2
] += const1
* mat
[i
][c1
];
273 /* Negate column C1 of matrix MAT which has M rows. */
276 lambda_matrix_col_negate (lambda_matrix mat
, int m
, int c1
)
280 for (i
= 0; i
< m
; i
++)
284 /* Multiply column C1 of matrix MAT with M rows by CONST1. */
287 lambda_matrix_col_mc (lambda_matrix mat
, int m
, int c1
, int const1
)
291 for (i
= 0; i
< m
; i
++)
292 mat
[i
][c1
] *= const1
;
295 /* Compute the inverse of the N x N matrix MAT and store it in INV.
297 We don't _really_ compute the inverse of MAT. Instead we compute
298 det(MAT)*inv(MAT), and we return det(MAT) to the caller as the function
299 result. This is necessary to preserve accuracy, because we are dealing
300 with integer matrices here.
302 The algorithm used here is a column based Gauss-Jordan elimination on MAT
303 and the identity matrix in parallel. The inverse is the result of applying
304 the same operations on the identity matrix that reduce MAT to the identity
307 When MAT is a 2 x 2 matrix, we don't go through the whole process, because
308 it is easily inverted by inspection and it is a very common case. */
310 static int lambda_matrix_inverse_hard (lambda_matrix
, lambda_matrix
, int);
313 lambda_matrix_inverse (lambda_matrix mat
, lambda_matrix inv
, int n
)
326 det
= (a
* d
- b
* c
);
338 return lambda_matrix_inverse_hard (mat
, inv
, n
);
341 /* If MAT is not a special case, invert it the hard way. */
344 lambda_matrix_inverse_hard (lambda_matrix mat
, lambda_matrix inv
, int n
)
351 temp
= lambda_matrix_new (n
, n
);
352 lambda_matrix_copy (mat
, temp
, n
, n
);
353 lambda_matrix_id (inv
, n
);
355 /* Reduce TEMP to a lower triangular form, applying the same operations on
356 INV which starts as the identity matrix. N is the number of rows and
358 for (j
= 0; j
< n
; j
++)
362 /* Make every element in the current row positive. */
363 for (i
= j
; i
< n
; i
++)
366 lambda_matrix_col_negate (temp
, n
, i
);
367 lambda_matrix_col_negate (inv
, n
, i
);
370 /* Sweep the upper triangle. Stop when only the diagonal element in the
371 current row is nonzero. */
372 while (lambda_vector_first_nz (row
, n
, j
+ 1) < n
)
374 int min_col
= lambda_vector_min_nz (row
, n
, j
);
375 lambda_matrix_col_exchange (temp
, n
, j
, min_col
);
376 lambda_matrix_col_exchange (inv
, n
, j
, min_col
);
378 for (i
= j
+ 1; i
< n
; i
++)
382 factor
= -1 * row
[i
];
386 lambda_matrix_col_add (temp
, n
, j
, i
, factor
);
387 lambda_matrix_col_add (inv
, n
, j
, i
, factor
);
392 /* Reduce TEMP from a lower triangular to the identity matrix. Also compute
393 the determinant, which now is simply the product of the elements on the
394 diagonal of TEMP. If one of these elements is 0, the matrix has 0 as an
395 eigenvalue so it is singular and hence not invertible. */
397 for (j
= n
- 1; j
>= 0; j
--)
404 /* If the matrix is singular, abort. */
408 determinant
= determinant
* diagonal
;
410 /* If the diagonal is not 1, then multiply the each row by the
411 diagonal so that the middle number is now 1, rather than a
415 for (i
= 0; i
< j
; i
++)
416 lambda_matrix_col_mc (inv
, n
, i
, diagonal
);
417 for (i
= j
+ 1; i
< n
; i
++)
418 lambda_matrix_col_mc (inv
, n
, i
, diagonal
);
420 row
[j
] = diagonal
= 1;
423 /* Sweep the lower triangle column wise. */
424 for (i
= j
- 1; i
>= 0; i
--)
428 int factor
= -row
[i
];
429 lambda_matrix_col_add (temp
, n
, j
, i
, factor
);
430 lambda_matrix_col_add (inv
, n
, j
, i
, factor
);
439 /* Decompose a N x N matrix MAT to a product of a lower triangular H
440 and a unimodular U matrix such that MAT = H.U. N is the size of
444 lambda_matrix_hermite (lambda_matrix mat
, int n
,
445 lambda_matrix H
, lambda_matrix U
)
448 int i
, j
, factor
, minimum_col
;
450 lambda_matrix_copy (mat
, H
, n
, n
);
451 lambda_matrix_id (U
, n
);
453 for (j
= 0; j
< n
; j
++)
457 /* Make every element of H[j][j..n] positive. */
458 for (i
= j
; i
< n
; i
++)
462 lambda_matrix_col_negate (H
, n
, i
);
463 lambda_vector_negate (U
[i
], U
[i
], n
);
467 /* Stop when only the diagonal element is nonzero. */
468 while (lambda_vector_first_nz (row
, n
, j
+ 1) < n
)
470 minimum_col
= lambda_vector_min_nz (row
, n
, j
);
471 lambda_matrix_col_exchange (H
, n
, j
, minimum_col
);
472 lambda_matrix_row_exchange (U
, j
, minimum_col
);
474 for (i
= j
+ 1; i
< n
; i
++)
476 factor
= row
[i
] / row
[j
];
477 lambda_matrix_col_add (H
, n
, j
, i
, -1 * factor
);
478 lambda_matrix_row_add (U
, n
, i
, j
, factor
);
484 /* Given an M x N integer matrix A, this function determines an M x
485 M unimodular matrix U, and an M x N echelon matrix S such that
486 "U.A = S". This decomposition is also known as "right Hermite".
488 Ref: Algorithm 2.1 page 33 in "Loop Transformations for
489 Restructuring Compilers" Utpal Banerjee. */
492 lambda_matrix_right_hermite (lambda_matrix A
, int m
, int n
,
493 lambda_matrix S
, lambda_matrix U
)
497 lambda_matrix_copy (A
, S
, m
, n
);
498 lambda_matrix_id (U
, m
);
500 for (j
= 0; j
< n
; j
++)
502 if (lambda_vector_first_nz (S
[j
], m
, i0
) < m
)
505 for (i
= m
- 1; i
>= i0
; i
--)
509 int sigma
, factor
, a
, b
;
513 sigma
= (a
* b
< 0) ? -1: 1;
516 factor
= sigma
* (a
/ b
);
518 lambda_matrix_row_add (S
, n
, i
, i
-1, -factor
);
519 lambda_matrix_row_exchange (S
, i
, i
-1);
521 lambda_matrix_row_add (U
, m
, i
, i
-1, -factor
);
522 lambda_matrix_row_exchange (U
, i
, i
-1);
529 /* Given an M x N integer matrix A, this function determines an M x M
530 unimodular matrix V, and an M x N echelon matrix S such that "A =
531 V.S". This decomposition is also known as "left Hermite".
533 Ref: Algorithm 2.2 page 36 in "Loop Transformations for
534 Restructuring Compilers" Utpal Banerjee. */
537 lambda_matrix_left_hermite (lambda_matrix A
, int m
, int n
,
538 lambda_matrix S
, lambda_matrix V
)
542 lambda_matrix_copy (A
, S
, m
, n
);
543 lambda_matrix_id (V
, m
);
545 for (j
= 0; j
< n
; j
++)
547 if (lambda_vector_first_nz (S
[j
], m
, i0
) < m
)
550 for (i
= m
- 1; i
>= i0
; i
--)
554 int sigma
, factor
, a
, b
;
558 sigma
= (a
* b
< 0) ? -1: 1;
561 factor
= sigma
* (a
/ b
);
563 lambda_matrix_row_add (S
, n
, i
, i
-1, -factor
);
564 lambda_matrix_row_exchange (S
, i
, i
-1);
566 lambda_matrix_col_add (V
, m
, i
-1, i
, factor
);
567 lambda_matrix_col_exchange (V
, m
, i
, i
-1);
574 /* When it exists, return the first nonzero row in MAT after row
575 STARTROW. Otherwise return rowsize. */
578 lambda_matrix_first_nz_vec (lambda_matrix mat
, int rowsize
, int colsize
,
584 for (j
= startrow
; (j
< rowsize
) && !found
; j
++)
587 && (lambda_vector_first_nz (mat
[j
], colsize
, startrow
) < colsize
))
596 /* Calculate the projection of E sub k to the null space of B. */
599 lambda_matrix_project_to_null (lambda_matrix B
, int rowsize
,
600 int colsize
, int k
, lambda_vector x
)
602 lambda_matrix M1
, M2
, M3
, I
;
605 /* Compute c(I-B^T inv(B B^T) B) e sub k. */
607 /* M1 is the transpose of B. */
608 M1
= lambda_matrix_new (colsize
, colsize
);
609 lambda_matrix_transpose (B
, M1
, rowsize
, colsize
);
612 M2
= lambda_matrix_new (colsize
, colsize
);
613 lambda_matrix_mult (B
, M1
, M2
, rowsize
, colsize
, rowsize
);
616 M3
= lambda_matrix_new (colsize
, colsize
);
617 determinant
= lambda_matrix_inverse (M2
, M3
, rowsize
);
619 /* M2 = B^T (inv(B B^T)) */
620 lambda_matrix_mult (M1
, M3
, M2
, colsize
, rowsize
, rowsize
);
622 /* M1 = B^T (inv(B B^T)) B */
623 lambda_matrix_mult (M2
, B
, M1
, colsize
, rowsize
, colsize
);
624 lambda_matrix_negate (M1
, M1
, colsize
, colsize
);
626 I
= lambda_matrix_new (colsize
, colsize
);
627 lambda_matrix_id (I
, colsize
);
629 lambda_matrix_add_mc (I
, determinant
, M1
, 1, M2
, colsize
, colsize
);
631 lambda_matrix_get_column (M2
, colsize
, k
- 1, x
);
635 /* Multiply a vector VEC by a matrix MAT.
636 MAT is an M*N matrix, and VEC is a vector with length N. The result
637 is stored in DEST which must be a vector of length M. */
640 lambda_matrix_vector_mult (lambda_matrix matrix
, int m
, int n
,
641 lambda_vector vec
, lambda_vector dest
)
645 lambda_vector_clear (dest
, m
);
646 for (i
= 0; i
< m
; i
++)
647 for (j
= 0; j
< n
; j
++)
648 dest
[i
] += matrix
[i
][j
] * vec
[j
];
651 /* Print out an M x N matrix MAT to OUTFILE. */
654 print_lambda_matrix (FILE * outfile
, lambda_matrix matrix
, int m
, int n
)
658 for (i
= 0; i
< m
; i
++)
659 print_lambda_vector (outfile
, matrix
[i
], n
);
660 fprintf (outfile
, "\n");