OSDN Git Service

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