OSDN Git Service

* config/rs6000/darwin.h (SUBTARGET_OPTIONS): Move from here, to...
[pf3gnuchains/gcc-fork.git] / gcc / lambda-mat.c
1 /* Integer matrix math routines
2    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3    Contributed by Daniel Berlin <dberlin@dberlin.org>.
4
5 This file is part of GCC.
6
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.
11
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.
16
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"
28
29 static void lambda_matrix_get_column (lambda_matrix, int, int, 
30                                       lambda_vector);
31
32 /* Allocate a matrix of M rows x  N cols.  */
33
34 lambda_matrix
35 lambda_matrix_new (int m, int n)
36 {
37   lambda_matrix mat;
38   int i;
39
40   mat = ggc_alloc (m * sizeof (lambda_vector));
41   
42   for (i = 0; i < m; i++)
43     mat[i] = lambda_vector_new (n);
44
45   return mat;
46 }
47
48 /* Copy the elements of M x N matrix MAT1 to MAT2.  */
49
50 void
51 lambda_matrix_copy (lambda_matrix mat1, lambda_matrix mat2,
52                     int m, int n)
53 {
54   int i;
55
56   for (i = 0; i < m; i++)
57     lambda_vector_copy (mat1[i], mat2[i], n);
58 }
59
60 /* Store the N x N identity matrix in MAT.  */
61
62 void
63 lambda_matrix_id (lambda_matrix mat, int size)
64 {
65   int i, j;
66
67   for (i = 0; i < size; i++)
68     for (j = 0; j < size; j++)
69       mat[i][j] = (i == j) ? 1 : 0;
70 }
71
72 /* Negate the elements of the M x N matrix MAT1 and store it in MAT2.  */
73
74 void
75 lambda_matrix_negate (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
76 {
77   int i;
78
79   for (i = 0; i < m; i++)
80     lambda_vector_negate (mat1[i], mat2[i], n);
81 }
82
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.  */
85
86 void
87 lambda_matrix_transpose (lambda_matrix mat1, lambda_matrix mat2, int m, int n)
88 {
89   int i, j;
90
91   for (i = 0; i < n; i++)
92     for (j = 0; j < m; j++)
93       mat2[i][j] = mat1[j][i];
94 }
95
96
97 /* Add two M x N matrices together: MAT3 = MAT1+MAT2.  */
98
99 void
100 lambda_matrix_add (lambda_matrix mat1, lambda_matrix mat2,
101                    lambda_matrix mat3, int m, int n)
102 {
103   int i;
104
105   for (i = 0; i < m; i++)
106     lambda_vector_add (mat1[i], mat2[i], mat3[i], n);
107 }
108
109 /* MAT3 = CONST1 * MAT1 + CONST2 * MAT2.  All matrices are M x N.  */
110
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)
115 {
116   int i;
117
118   for (i = 0; i < m; i++)
119     lambda_vector_add_mc (mat1[i], const1, mat2[i], const2, mat3[i], n);
120 }
121
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.  */
125
126 void
127 lambda_matrix_mult (lambda_matrix mat1, lambda_matrix mat2,
128                     lambda_matrix mat3, int m, int r, int n)
129 {
130
131   int i, j, k;
132
133   for (i = 0; i < m; i++)
134     {
135       for (j = 0; j < n; j++)
136         {
137           mat3[i][j] = 0;
138           for (k = 0; k < r; k++)
139             mat3[i][j] += mat1[i][k] * mat2[k][j];
140         }
141     }
142 }
143
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.  */
146
147 static void
148 lambda_matrix_get_column (lambda_matrix mat, int n, int col,
149                           lambda_vector vec)
150 {
151   int i;
152
153   for (i = 0; i < n; i++)
154     vec[i] = mat[i][col];
155 }
156
157 /* Delete rows r1 to r2 (not including r2). */
158
159 void
160 lambda_matrix_delete_rows (lambda_matrix mat, int rows, int from, int to)
161 {
162   int i;
163   int dist;
164   dist = to - from;
165
166   for (i = to; i < rows; i++)
167     mat[i - dist] = mat[i];
168
169   for (i = rows - dist; i < rows; i++)
170     mat[i] = NULL;
171 }
172
173 /* Swap rows R1 and R2 in matrix MAT.  */
174
175 void
176 lambda_matrix_row_exchange (lambda_matrix mat, int r1, int r2)
177 {
178   lambda_vector row;
179
180   row = mat[r1];
181   mat[r1] = mat[r2];
182   mat[r2] = row;
183 }
184
185 /* Add a multiple of row R1 of matrix MAT with N columns to row R2:
186    R2 = R2 + CONST1 * R1.  */
187
188 void
189 lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2, int const1)
190 {
191   int i;
192
193   if (const1 == 0)
194     return;
195
196   for (i = 0; i < n; i++)
197     mat[r2][i] += const1 * mat[r1][i];
198 }
199
200 /* Negate row R1 of matrix MAT which has N columns.  */
201
202 void
203 lambda_matrix_row_negate (lambda_matrix mat, int n, int r1)
204 {
205   lambda_vector_negate (mat[r1], mat[r1], n);
206 }
207
208 /* Multiply row R1 of matrix MAT with N columns by CONST1.  */
209
210 void
211 lambda_matrix_row_mc (lambda_matrix mat, int n, int r1, int const1)
212 {
213   int i;
214
215   for (i = 0; i < n; i++)
216     mat[r1][i] *= const1;
217 }
218
219 /* Exchange COL1 and COL2 in matrix MAT. M is the number of rows.  */
220
221 void
222 lambda_matrix_col_exchange (lambda_matrix mat, int m, int col1, int col2)
223 {
224   int i;
225   int tmp;
226   for (i = 0; i < m; i++)
227     {
228       tmp = mat[i][col1];
229       mat[i][col1] = mat[i][col2];
230       mat[i][col2] = tmp;
231     }
232 }
233
234 /* Add a multiple of column C1 of matrix MAT with M rows to column C2:
235    C2 = C2 + CONST1 * C1.  */
236
237 void
238 lambda_matrix_col_add (lambda_matrix mat, int m, int c1, int c2, int const1)
239 {
240   int i;
241
242   if (const1 == 0)
243     return;
244
245   for (i = 0; i < m; i++)
246     mat[i][c2] += const1 * mat[i][c1];
247 }
248
249 /* Negate column C1 of matrix MAT which has M rows.  */
250
251 void
252 lambda_matrix_col_negate (lambda_matrix mat, int m, int c1)
253 {
254   int i;
255
256   for (i = 0; i < m; i++)
257     mat[i][c1] *= -1;
258 }
259
260 /* Multiply column C1 of matrix MAT with M rows by CONST1.  */
261
262 void
263 lambda_matrix_col_mc (lambda_matrix mat, int m, int c1, int const1)
264 {
265   int i;
266
267   for (i = 0; i < m; i++)
268     mat[i][c1] *= const1;
269 }
270
271 /* Compute the inverse of the N x N matrix MAT and store it in INV.
272
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.
277
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.
282
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.  */
285
286 static int lambda_matrix_inverse_hard (lambda_matrix, lambda_matrix, int);
287
288 int
289 lambda_matrix_inverse (lambda_matrix mat, lambda_matrix inv, int n)
290 {
291   if (n == 2)
292     {
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)
304         {
305           det *= -1;
306           inv[0][0] *= -1;
307           inv[1][0] *= -1;
308           inv[0][1] *= -1;
309           inv[1][1] *= -1;
310         }
311       return det;
312     }
313   else
314     return lambda_matrix_inverse_hard (mat, inv, n);
315 }
316
317 /* If MAT is not a special case, invert it the hard way.  */
318
319 static int
320 lambda_matrix_inverse_hard (lambda_matrix mat, lambda_matrix inv, int n)
321 {
322   lambda_vector row;
323   lambda_matrix temp;
324   int i, j;
325   int determinant;
326
327   temp = lambda_matrix_new (n, n);
328   lambda_matrix_copy (mat, temp, n, n);
329   lambda_matrix_id (inv, n);
330
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++)
335     {
336       row = temp[j];
337
338       /* Make every element in the current row positive.  */
339       for (i = j; i < n; i++)
340         if (row[i] < 0)
341           {
342             lambda_matrix_col_negate (temp, n, i);
343             lambda_matrix_col_negate (inv, n, i);
344           }
345
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)
349         {
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);
353
354           for (i = j + 1; i < n; i++)
355             {
356               int factor;
357
358               factor = -1 * row[i];
359               if (row[j] != 1)
360                 factor /= row[j];
361
362               lambda_matrix_col_add (temp, n, j, i, factor);
363               lambda_matrix_col_add (inv, n, j, i, factor);
364             }
365         }
366     }
367
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--)
374     {
375       int diagonal;
376
377       row = temp[j];
378       diagonal = row[j];
379
380       /* If the matrix is singular, abort.  */
381       if (diagonal == 0)
382         abort ();
383
384       determinant = determinant * diagonal;
385
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)
390         {
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);
395
396           row[j] = diagonal = 1;
397         }
398
399       /* Sweep the lower triangle column wise.  */
400       for (i = j - 1; i >= 0; i--)
401         {
402           if (row[i])
403             {
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);
407             }
408
409         }
410     }
411
412   return determinant;
413 }
414
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.  */
418
419 void
420 lambda_matrix_hermite (lambda_matrix mat, int n,
421                        lambda_matrix H, lambda_matrix U)
422 {
423   lambda_vector row;
424   int i, j, factor, minimum_col;
425
426   lambda_matrix_copy (mat, H, n, n);
427   lambda_matrix_id (U, n);
428
429   for (j = 0; j < n; j++)
430     {
431       row = H[j];
432
433       /* Make every element of H[j][j..n] positive.  */
434       for (i = j; i < n; i++)
435         {
436           if (row[i] < 0)
437             {
438               lambda_matrix_col_negate (H, n, i);
439               lambda_vector_negate (U[i], U[i], n);
440             }
441         }
442
443       /* Stop when only the diagonal element is non-zero.  */
444       while (lambda_vector_first_nz (row, n, j + 1) < n)
445         {
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);
449
450           for (i = j + 1; i < n; i++)
451             {
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);
455             }
456         }
457     }
458 }
459
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".
463    
464    Ref: Algorithm 2.1 page 33 in "Loop Transformations for
465    Restructuring Compilers" Utpal Banerjee. */
466
467 void
468 lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
469                              lambda_matrix S, lambda_matrix U)
470 {
471   int i, j, i0 = 0;
472
473   lambda_matrix_copy (A, S, m, n);
474   lambda_matrix_id (U, m);
475
476   for (j = 0; j < n; j++)
477     {
478       if (lambda_vector_first_nz (S[j], m, i0) < m)
479         {
480           ++i0;
481           for (i = m - 1; i >= i0; i--)
482             {
483               while (S[i][j] != 0)
484                 {
485                   int sigma, factor, a, b;
486
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);
493
494                   lambda_matrix_row_add (S, n, i, i-1, -factor);
495                   lambda_matrix_row_exchange (S, i, i-1);
496
497                   lambda_matrix_row_add (U, m, i, i-1, -factor);
498                   lambda_matrix_row_exchange (U, i, i-1);
499                 }
500             }
501         }
502     }
503 }
504
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".
508    
509    Ref: Algorithm 2.2 page 36 in "Loop Transformations for
510    Restructuring Compilers" Utpal Banerjee. */
511
512 void
513 lambda_matrix_left_hermite (lambda_matrix A, int m, int n,
514                              lambda_matrix S, lambda_matrix V)
515 {
516   int i, j, i0 = 0;
517
518   lambda_matrix_copy (A, S, m, n);
519   lambda_matrix_id (V, m);
520
521   for (j = 0; j < n; j++)
522     {
523       if (lambda_vector_first_nz (S[j], m, i0) < m)
524         {
525           ++i0;
526           for (i = m - 1; i >= i0; i--)
527             {
528               while (S[i][j] != 0)
529                 {
530                   int sigma, factor, a, b;
531
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);
538
539                   lambda_matrix_row_add (S, n, i, i-1, -factor);
540                   lambda_matrix_row_exchange (S, i, i-1);
541
542                   lambda_matrix_col_add (V, m, i-1, i, factor);
543                   lambda_matrix_col_exchange (V, m, i, i-1);
544                 }
545             }
546         }
547     }
548 }
549
550 /* When it exists, return the first non-zero row in MAT after row
551    STARTROW.  Otherwise return rowsize.  */
552
553 int
554 lambda_matrix_first_nz_vec (lambda_matrix mat, int rowsize, int colsize,
555                             int startrow)
556 {
557   int j;
558   bool found = false;
559
560   for (j = startrow; (j < rowsize) && !found; j++)
561     {
562       if ((mat[j] != NULL)
563           && (lambda_vector_first_nz (mat[j], colsize, startrow) < colsize))
564         found = true;
565     }
566
567   if (found)
568     return j - 1;
569   return rowsize;
570 }
571
572 /* Calculate the projection of E sub k to the null space of B.  */
573
574 void
575 lambda_matrix_project_to_null (lambda_matrix B, int rowsize,
576                                int colsize, int k, lambda_vector x)
577 {
578   lambda_matrix M1, M2, M3, I;
579   int determinant;
580
581   /* compute c(I-B^T inv(B B^T) B) e sub k   */
582
583   /* M1 is the transpose of B */
584   M1 = lambda_matrix_new (colsize, colsize);
585   lambda_matrix_transpose (B, M1, rowsize, colsize);
586
587   /* M2 = B * B^T */
588   M2 = lambda_matrix_new (colsize, colsize);
589   lambda_matrix_mult (B, M1, M2, rowsize, colsize, rowsize);
590
591   /* M3 = inv(M2) */
592   M3 = lambda_matrix_new (colsize, colsize);
593   determinant = lambda_matrix_inverse (M2, M3, rowsize);
594
595   /* M2 = B^T (inv(B B^T)) */
596   lambda_matrix_mult (M1, M3, M2, colsize, rowsize, rowsize);
597
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);
601
602   I = lambda_matrix_new (colsize, colsize);
603   lambda_matrix_id (I, colsize);
604
605   lambda_matrix_add_mc (I, determinant, M1, 1, M2, colsize, colsize);
606
607   lambda_matrix_get_column (M2, colsize, k - 1, x);
608
609 }
610
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.  */
614
615 void
616 lambda_matrix_vector_mult (lambda_matrix matrix, int m, int n,
617                            lambda_vector vec, lambda_vector dest)
618 {
619   int i, j;
620
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];
625 }
626
627 /* Print out an M x N matrix MAT to OUTFILE.  */
628
629 void
630 print_lambda_matrix (FILE * outfile, lambda_matrix matrix, int m, int n)
631 {
632   int i;
633
634   for (i = 0; i < m; i++)
635     print_lambda_vector (outfile, matrix[i], n);
636   fprintf (outfile, "\n");
637 }
638