perform special options tests in a loop
[cloog.git] / source / matrix.c
blobfd5c121e7d927673036ba3148951aa7ca48d9758
2 /**-------------------------------------------------------------------**
3 ** CLooG **
4 **-------------------------------------------------------------------**
5 ** matrix.c **
6 **-------------------------------------------------------------------**
7 ** First version: april 17th 2005 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
14 * *
15 * Copyright (C) 2005 Cedric Bastoul *
16 * *
17 * This is free software; you can redistribute it and/or modify it under the *
18 * terms of the GNU General Public License as published by the Free Software *
19 * Foundation; either version 2 of the License, or (at your option) any later *
20 * version. *
21 * *
22 * This software is distributed in the hope that it will be useful, but *
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
25 * for more details. *
26 * *
27 * You should have received a copy of the GNU General Public License along *
28 * with software; if not, write to the Free Software Foundation, Inc., *
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
30 * *
31 * CLooG, the Chunky Loop Generator *
32 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
33 * *
34 ******************************************************************************/
35 /* CAUTION: the english used for comments is probably the worst you ever read,
36 * please feel free to correct and improve it !
40 # include <stdlib.h>
41 # include <stdio.h>
42 # include <ctype.h>
43 # include "../include/cloog/cloog.h"
47 /******************************************************************************
48 * Memory leaks hunting *
49 ******************************************************************************/
52 /**
53 * These functions and global variables are devoted to memory leaks hunting: we
54 * want to know at each moment how many CloogMatrix structures are allocated
55 * (cloog_matrix_allocated) and how many had been freed (cloog_matrix_freed).
56 * Each time a CloogMatrix structure is allocated, a call to the function
57 * cloog_matrix_leak_up() must be carried out, and respectively
58 * cloog_matrix_leak_down() when a CloogMatrix structure is freed. The special
59 * variable cloog_matrix_max gives the maximal number of CloogMatrix structures
60 * simultaneously alive (i.e. allocated and non-freed) in memory.
61 * - April 17th 2005: first version.
65 int cloog_matrix_allocated = 0 ;
66 int cloog_matrix_freed = 0 ;
67 int cloog_matrix_max = 0 ;
70 static void cloog_matrix_leak_up()
71 { cloog_matrix_allocated ++ ;
72 if ((cloog_matrix_allocated-cloog_matrix_freed) > cloog_matrix_max)
73 cloog_matrix_max = cloog_matrix_allocated - cloog_matrix_freed ;
77 static void cloog_matrix_leak_down()
78 { cloog_matrix_freed ++ ;
82 /******************************************************************************
83 * PolyLib interface *
84 ******************************************************************************/
87 /**
88 * CLooG makes an intensive use of matrix operations and the PolyLib do
89 * the job. Here are the interfaces to all the PolyLib calls (CLooG uses 18
90 * PolyLib functions), with or without some adaptations. If another matrix
91 * library can be used, only these functions have to be changed.
95 /**
96 * cloog_matrix_print function:
97 * This function prints the content of a CloogMatrix structure (matrix) into a
98 * file (foo, possibly stdout).
100 void cloog_matrix_print(FILE * foo, CloogMatrix * matrix)
101 { Matrix_Print(foo,P_VALUE_FMT,matrix) ;
106 * cloog_matrix_free function:
107 * This function frees the allocated memory for a CloogMatrix structure
108 * (matrix).
110 void cloog_matrix_free(CloogMatrix * matrix)
111 { cloog_matrix_leak_down() ;
112 Matrix_Free(matrix) ;
117 * cloog_matrix_alloc function:
118 * This function allocates the memory space for a CloogMatrix structure having
119 * nb_rows rows and nb_columns columns, it set its elements to 0.
121 CloogMatrix * cloog_matrix_alloc(unsigned nb_rows, unsigned nb_columns)
122 { cloog_matrix_leak_up() ;
123 return Matrix_Alloc(nb_rows,nb_columns) ;
128 * cloog_matrix_matrix function:
129 * This function converts a PolyLib Matrix to a CloogMatrix structure.
131 CloogMatrix * cloog_matrix_matrix(Matrix *matrix)
133 cloog_matrix_leak_up();
134 return matrix;
138 /******************************************************************************
139 * Structure display function *
140 ******************************************************************************/
144 * cloog_loop_print_structure function:
145 * Displays a CloogMatrix structure (matrix) into a file (file, possibly stdout)
146 * in a way that trends to be understandable without falling in a deep
147 * depression or, for the lucky ones, getting a headache... It includes an
148 * indentation level (level) in order to work with others print_structure
149 * functions. Written by Olivier Chorier, Luc Marchaud, Pierre Martin and
150 * Romain Tartiere.
151 * - April 24th 2005: Initial version.
152 * - June 2nd 2005: (Ced) Extraction from cloog_loop_print_structure and
153 * integration in matrix.c.
154 * - June 22rd 2005: Adaptation for GMP.
156 void cloog_matrix_print_structure(FILE * file, CloogMatrix * matrix, int level)
157 { int i, j ;
159 /* Display the matrix. */
160 for (i=0; i<matrix->NbRows; i++)
161 { for(j=0; j<=level; j++)
162 fprintf(file,"|\t") ;
164 fprintf(file,"[ ") ;
166 for (j=0; j<matrix->NbColumns; j++)
167 { value_print(file,P_VALUE_FMT,matrix->p[i][j]) ;
168 fprintf(file," ") ;
171 fprintf(file,"]\n") ;
176 /******************************************************************************
177 * Reading function *
178 ******************************************************************************/
182 * cloog_matrix_read function:
183 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
184 * posibly stdin) and returns a pointer this matrix.
185 * October 18th 2001: first version.
186 * - April 17th 2005: this function moved from domain.c to here.
187 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
188 * CLooG 0.12.1).
190 CloogMatrix * cloog_matrix_read(FILE * foo)
191 { unsigned NbRows, NbColumns ;
192 int i, j, n ;
193 char *c, s[MAX_STRING], str[MAX_STRING] ;
194 CloogMatrix * matrix ;
195 Value * p ;
197 while (fgets(s,MAX_STRING,foo) == 0) ;
198 while ((*s=='#' || *s=='\n') || (sscanf(s," %u %u",&NbRows,&NbColumns)<2))
199 fgets(s,MAX_STRING,foo) ;
201 matrix = cloog_matrix_alloc(NbRows,NbColumns) ;
203 p = matrix->p_Init ;
204 for (i=0;i<matrix->NbRows;i++)
205 { do
206 { c = fgets(s,MAX_STRING,foo) ;
207 while ((c != NULL) && isspace(*c) && (*c != '\n'))
208 c++ ;
210 while (c != NULL && (*c == '#' || *c == '\n'));
212 if (c == NULL)
213 { fprintf(stderr, "[CLooG]ERROR: not enough rows.\n") ;
214 exit(1) ;
216 for (j=0;j<matrix->NbColumns;j++)
217 { if (c == NULL || *c == '#' || *c == '\n')
218 { fprintf(stderr, "[CLooG]ERROR: not enough columns.\n") ;
219 exit(1) ;
221 /* NdCed : Dans le n ca met strlen(str). */
222 if (sscanf(c,"%s%n",str,&n) == 0)
223 { fprintf(stderr, "[CLooG]ERROR: not enough rows.\n") ;
224 exit(1) ;
226 value_read(*(p++),str) ;
227 c += n ;
231 return(matrix) ;
235 /******************************************************************************
236 * Processing functions *
237 ******************************************************************************/
241 * Function cloog_matrix_normalize:
242 * This function will modify the constraint system in such a way that when
243 * there is an equality depending on the element at level 'level', there are
244 * no more (in)equalities depending on this element. For instance, try
245 * test/valilache.cloog with options -f 8 -l 9, with and without the call
246 * to this function. At a given moment, for the level L we will have
247 * 32*P=L && L>=1 (P is a lower level), this constraint system cannot be
248 * translated directly into a source code. Thus, we normalize the domain to
249 * remove L from the inequalities. In our example, this leads to
250 * 32*P=L && 32*P>=1, that can be transated to the code
251 * if (P>=1) { L=32*P ; ... }. This function solves the DaeGon Kim bug.
252 * WARNING: Remember that if there is another call to Polylib after a call to
253 * this function, we have to recall this function.
254 * -June 16th 2005: first version (adaptation from URGent June-7th-2005 by
255 * N. Vasilache).
256 * - June 21rd 2005: Adaptation for GMP.
257 * - November 4th 2005: Complete rewriting, simpler and faster. It is no more an
258 * adaptation from URGent.
260 void cloog_matrix_normalize(CloogMatrix * matrix, int level)
261 { int ref, i, j ;
262 Value factor_i, factor_ref, temp_i, temp_ref, gcd ;
264 if (matrix == NULL)
265 return ;
267 /* Don't "normalize" the constant term. */
268 if (level == matrix->NbColumns-1)
269 return;
271 /* Let us find an equality for the current level that can be propagated. */
272 for (ref=0;ref<matrix->NbRows;ref++)
273 if (value_zero_p(matrix->p[ref][0]) && value_notzero_p(matrix->p[ref][level]))
274 { value_init_c(gcd) ;
275 value_init_c(temp_i) ;
276 value_init_c(temp_ref) ;
277 value_init_c(factor_i) ;
278 value_init_c(factor_ref) ;
280 /* Row "ref" is the reference equality, now let us find a row to simplify.*/
281 for (i=ref+1;i<matrix->NbRows;i++)
282 if (value_notzero_p(matrix->p[i][level]))
283 { /* Now let us set to 0 the "level" coefficient of row "j" using "ref".
284 * First we compute the factors to apply to each row vector element.
286 Gcd(matrix->p[ref][level],matrix->p[i][level],&gcd) ;
287 value_division(factor_i,matrix->p[ref][level],gcd) ;
288 value_division(factor_ref,matrix->p[i][level],gcd) ;
290 /* Maybe we are simplifying an inequality: factor_i must not be <0. */
291 if (value_neg_p(factor_i))
292 { value_absolute(factor_i,factor_i) ;
293 value_oppose(factor_ref,factor_ref) ;
296 /* Now update the vector. */
297 for (j=1;j<matrix->NbColumns;j++)
298 { value_multiply(temp_i,factor_i,matrix->p[i][j]) ;
299 value_multiply(temp_ref,factor_ref,matrix->p[ref][j]) ;
300 value_substract(matrix->p[i][j],temp_i,temp_ref) ;
303 /* Normalize (divide by GCD of all elements) the updated vector. */
304 Vector_Normalize(&(matrix->p[i][1]),matrix->NbColumns-1) ;
307 value_clear_c(gcd) ;
308 value_clear_c(temp_i) ;
309 value_clear_c(temp_ref) ;
310 value_clear_c(factor_i) ;
311 value_clear_c(factor_ref) ;
312 break ;
318 * cloog_matrix_equality_update function:
319 * this function updates a matrix of equalities where each row corresponds to
320 * the equality "=0" of an affine expression such that the entry at column
321 * "row" (="level") is not zero. This matrix is upper-triangular, except the
322 * row number "level-1" which has to be updated for the matrix to be triangular.
323 * The first element of each row gives the equality type and is not related to
324 * the expression which is equal to zero. This function achieves the processing.
325 * - equal is the matrix to be updated,
326 * - level gives the row that has to be updated (it is actually row "level-1"),
327 * - nb_par is the number of parameters of the program.
329 * - September 20th 2005: first version.
331 void cloog_matrix_equality_update(CloogMatrix * equal, int level, int nb_par)
332 { int i, j ;
333 Value gcd, factor_level, factor_outer, temp_level, temp_outer ;
335 value_init_c(gcd) ;
336 value_init_c(temp_level) ;
337 value_init_c(temp_outer) ;
338 value_init_c(factor_level) ;
339 value_init_c(factor_outer) ;
341 /* For each previous level, */
342 for (i=level-2;i>=0;i--)
343 { /* if the corresponding iterator is inside the current equality and is equal
344 * to something,
346 if (value_notzero_p(equal->p[level-1][i+1]) &&
347 value_notzero_p(equal->p[i][0]))
348 { /* Compute the Greatest Common Divisor. */
349 Gcd(equal->p[level-1][i+1],equal->p[i][i+1],&gcd) ;
351 /* Compute the factors to apply to each row vector element. */
352 value_division(factor_level,equal->p[i][i+1],gcd) ;
353 value_division(factor_outer,equal->p[level-1][i+1],gcd) ;
355 /* Now update the row 'level'. */
356 /* - the iterators, up to level, */
357 for (j=1;j<=level;j++)
358 { value_multiply(temp_level,factor_level,equal->p[level-1][j]) ;
359 value_multiply(temp_outer,factor_outer,equal->p[i][j]) ;
360 value_substract(equal->p[level-1][j],temp_level,temp_outer) ;
362 /* - between last useful iterator (level) and the first parameter, the
363 * matrix is sparse (full of zeroes), we just do nothing there.
364 * - the parameters and the scalar.
366 for (j=0;j<nb_par+1;j++)
367 { value_multiply(temp_level,factor_level,
368 equal->p[level-1][equal->NbColumns-j-1]) ;
369 value_multiply(temp_outer,factor_outer,
370 equal->p[i][equal->NbColumns-j-1]) ;
371 value_substract(equal->p[level-1][equal->NbColumns-j-1],
372 temp_level,temp_outer) ;
377 /* Normalize (divide by GCD of all elements) the updated equality. */
378 Vector_Normalize(&(equal->p[level-1][1]),equal->NbColumns-1) ;
380 value_clear_c(gcd) ;
381 value_clear_c(temp_level) ;
382 value_clear_c(temp_outer) ;
383 value_clear_c(factor_level) ;
384 value_clear_c(factor_outer) ;
389 * cloog_matrix_copy function:
390 * this functions builds and returns a "hard copy" (not a pointer copy) of a
391 * CloogMatrix data structure.
392 * - October 26th 2005: first version.
394 CloogMatrix * cloog_matrix_copy(CloogMatrix * matrix)
395 { int i, j ;
396 CloogMatrix * copy ;
398 copy = cloog_matrix_alloc(matrix->NbRows,matrix->NbColumns) ;
400 for (i=0;i<matrix->NbRows;i++)
401 for (j=0;j<matrix->NbColumns;j++)
402 value_assign(copy->p[i][j],matrix->p[i][j]) ;
404 return copy ;
409 * cloog_matrix_vector_copy function:
410 * this function rutuns a hard copy of the vector "vector" of length "length"
411 * provided as input.
412 * - November 3rd 2005: first version.
414 Value * cloog_matrix_vector_copy(Value * vector, int length)
415 { int i ;
416 Value * copy ;
418 /* We allocate the memory space for the new vector, and we fill it with
419 * the original coefficients.
421 copy = (Value *)malloc(length * sizeof(Value)) ;
422 for (i=0;i<length;i++)
423 { value_init_c(copy[i]) ;
424 value_assign(copy[i],vector[i]) ;
427 return copy ;
432 * cloog_matrix_vector_simplify function:
433 * this function simplify an affine expression with its coefficients in
434 * "vector" of length "length" thanks to an equality matrix "equal" that gives
435 * for some elements of the affine expression an equality with other elements,
436 * preferably constants. For instance, if the vector contains i+j+3 and the
437 * equality matrix gives i=n and j=2, the vector is simplified to n+3 and is
438 * returned in a new vector.
439 * - vector is the array of affine expression coefficients
440 * - equal is the matrix of equalities,
441 * - length is the vector length,
442 * - level is a level we don't want to simplify (-1 if none),
443 * - nb_par is the number of parameters of the program.
445 * - September 20th 2005: first version.
446 * - November 2nd 2005: (debug) we are simplifying inequalities, thus we are
447 * not allowed to multiply the vector by a negative
448 * constant.Problem found after a report of Michael
449 * Classen.
451 Value * cloog_matrix_vector_simplify(vector, equal, length, level, nb_par)
452 Value * vector ;
453 CloogMatrix * equal ;
454 int length, level, nb_par ;
455 { int i, j ;
456 Value gcd, factor_vector, factor_equal, temp_vector, temp_equal, * simplified;
458 simplified = cloog_matrix_vector_copy(vector,length) ;
460 value_init_c(gcd) ;
461 value_init_c(temp_vector) ;
462 value_init_c(temp_equal) ;
463 value_init_c(factor_vector) ;
464 value_init_c(factor_equal) ;
466 /* For each non-null coefficient in the vector, */
467 for (i=length-nb_par-2;i>0;i--)
468 if (i != level)
469 { /* if the coefficient in not null, and there exists a useful equality */
470 if ((value_notzero_p(simplified[i])) &&
471 (value_notzero_p(equal->p[i-1][0])))
472 { /* Compute the Greatest Common Divisor. */
473 Gcd(simplified[i],equal->p[i-1][i],&gcd) ;
475 /* Compute the factors to apply to each row vector element. */
476 value_division(factor_vector,equal->p[i-1][i],gcd) ;
477 value_division(factor_equal,simplified[i],gcd) ;
479 /* We are simplifying an inequality: factor_vector must not be <0. */
480 if (value_neg_p(factor_vector))
481 { value_absolute(factor_vector,factor_vector) ;
482 value_oppose(factor_equal,factor_equal) ;
485 /* Now update the vector. */
486 /* - the iterators, up to the current level, */
487 for (j=1;j<=length-nb_par-2;j++)
488 { value_multiply(temp_vector,factor_vector,simplified[j]) ;
489 value_multiply(temp_equal,factor_equal,equal->p[i-1][j]) ;
490 value_substract(simplified[j],temp_vector,temp_equal) ;
492 /* - between last useful iterator (i) and the first parameter, the equal
493 * matrix is sparse (full of zeroes), we just do nothing there.
494 * - the parameters and the scalar.
496 for (j=0;j<nb_par+1;j++)
497 { value_multiply(temp_vector,factor_vector,simplified[length-1-j]) ;
498 value_multiply(temp_equal,factor_equal,
499 equal->p[i-1][equal->NbColumns-j-1]) ;
500 value_substract(simplified[length-1-j],temp_vector,temp_equal) ;
505 /* Normalize (divide by GCD of all elements) the updated vector. */
506 Vector_Normalize(&(simplified[1]),length-1) ;
508 value_clear_c(gcd) ;
509 value_clear_c(temp_vector) ;
510 value_clear_c(temp_equal) ;
511 value_clear_c(factor_vector) ;
512 value_clear_c(factor_equal) ;
514 return simplified ;
519 * cloog_matrix_simplify function:
520 * this function simplify all constraints inside the matrix "matrix" thanks to
521 * an equality matrix "equal" that gives for some elements of the affine
522 * constraint an equality with other elements, preferably constants.
523 * For instance, if a row of the matrix contains i+j+3>=0 and the equality
524 * matrix gives i=n and j=2, the constraint is simplified to n+3>=0. The
525 * simplified constraints are returned back inside a new simplified matrix.
526 * - matrix is the set of constraints to simplify,
527 * - equal is the matrix of equalities,
528 * - level is a level we don't want to simplify (-1 if none),
529 * - nb_par is the number of parameters of the program.
531 * - November 4th 2005: first version.
533 CloogMatrix * cloog_matrix_simplify(matrix, equal, level, nb_par)
534 CloogMatrix * matrix, * equal ;
535 int level, nb_par ;
536 { int i, j, k ;
537 Value * vector ;
538 CloogMatrix * simplified ;
540 if (matrix == NULL)
541 return NULL ;
543 /* The simplified matrix is such that each row has been simplified thanks
544 * tho the "equal" matrix. We allocate the memory for the simplified matrix,
545 * then for each row of the original matrix, we compute the simplified
546 * vector and we copy its content into the according simplified row.
548 simplified = cloog_matrix_alloc(matrix->NbRows,matrix->NbColumns) ;
549 for (i=0;i<matrix->NbRows;i++)
550 { vector = cloog_matrix_vector_simplify(matrix->p[i],equal,matrix->NbColumns,
551 level,nb_par) ;
552 for (j=0;j<matrix->NbColumns;j++)
553 value_assign(simplified->p[i][j],vector[j]) ;
555 cloog_matrix_vector_free(vector,matrix->NbColumns) ;
558 /* After simplification, it may happen that few constraints are the same,
559 * we remove them here by replacing them with 0=0 constraints.
561 for (i=0;i<simplified->NbRows;i++)
562 for (j=i+1;j<simplified->NbRows;j++)
563 { for (k=0;k<simplified->NbColumns;k++)
564 if (value_ne(simplified->p[i][k],simplified->p[j][k]))
565 break ;
567 if (k == matrix->NbColumns)
568 { for (k=0;k<matrix->NbColumns;k++)
569 value_set_si(simplified->p[j][k],0) ;
573 return simplified ;
578 * cloog_matrix_vector_free function:
579 * this function clears the elements of a vector "vector" of length "length",
580 * then frees the vector itself this is useful for the GMP version of CLooG
581 * which has to clear all elements.
582 * - October 29th 2005: first version.
584 void cloog_matrix_vector_free(Value * vector, int length)
585 { int i ;
587 for (i=0;i<length;i++)
588 value_clear_c(vector[i]) ;
589 free(vector) ;