2 /**-------------------------------------------------------------------**
4 **-------------------------------------------------------------------**
6 **-------------------------------------------------------------------**
7 ** First version: october 28th 2001 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
15 * Copyright (C) 2001-2005 Cedric Bastoul *
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 *
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 *
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 *
31 * CLooG, the Chunky Loop Generator *
32 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
34 ******************************************************************************/
35 /* CAUTION: the english used for comments is probably the worst you ever read,
36 * please feel free to correct and improve it !
42 # include "../../include/cloog/cloog.h"
45 /* Variables names for pretty printing. */
46 static char wild_name
[200][40];
48 static inline const char*
49 variable_output_function (ppl_dimension_type var
)
52 return wild_name
[var
+ 1];
58 error_handler (enum ppl_enum_error_code code
, const char* description
)
60 fprintf (stderr
, "PPL error code %d\n%s", code
, description
);
65 cloog_initialize (void)
67 sprintf (wild_name
[0], "1");
68 sprintf (wild_name
[1], "a");
69 sprintf (wild_name
[2], "b");
70 sprintf (wild_name
[3], "c");
71 sprintf (wild_name
[4], "d");
72 sprintf (wild_name
[5], "e");
73 sprintf (wild_name
[6], "f");
74 sprintf (wild_name
[7], "g");
75 sprintf (wild_name
[8], "h");
76 sprintf (wild_name
[9], "i");
77 sprintf (wild_name
[10], "j");
78 sprintf (wild_name
[11], "k");
79 sprintf (wild_name
[12], "l");
80 sprintf (wild_name
[13], "m");
81 sprintf (wild_name
[14], "n");
82 sprintf (wild_name
[15], "o");
83 sprintf (wild_name
[16], "p");
84 sprintf (wild_name
[17], "q");
85 sprintf (wild_name
[18], "r");
86 sprintf (wild_name
[19], "s");
87 sprintf (wild_name
[20], "t");
88 sprintf (wild_name
[21], "alpha");
89 sprintf (wild_name
[22], "beta");
90 sprintf (wild_name
[23], "gamma");
91 sprintf (wild_name
[24], "delta");
92 sprintf (wild_name
[25], "tau");
93 sprintf (wild_name
[26], "sigma");
94 sprintf (wild_name
[27], "chi");
95 sprintf (wild_name
[28], "omega");
96 sprintf (wild_name
[29], "pi");
97 sprintf (wild_name
[30], "ni");
98 sprintf (wild_name
[31], "Alpha");
99 sprintf (wild_name
[32], "Beta");
100 sprintf (wild_name
[33], "Gamma");
101 sprintf (wild_name
[34], "Delta");
102 sprintf (wild_name
[35], "Tau");
103 sprintf (wild_name
[36], "Sigma");
104 sprintf (wild_name
[37], "Chi");
105 sprintf (wild_name
[38], "Omega");
106 sprintf (wild_name
[39], "xxx");
108 if (ppl_initialize() < 0)
110 fprintf (stderr
, "Cannot initialize the Parma Polyhedra Library.\n");
114 if (ppl_set_error_handler (error_handler
) < 0)
116 fprintf (stderr
, "Cannot install the custom error handler.\n");
120 if (ppl_io_set_variable_output_function (variable_output_function
) < 0)
122 fprintf (stderr
, "Cannot install the PPL custom variable output function. \n");
128 cloog_pol_copy (polyhedron pol
)
135 res
= cloog_new_pol (cloog_pol_dim (pol
), cloog_pol_nbc (pol
));
137 if (cloog_pol_nbc (pol
))
138 cloog_vector_copy (pol
->Constraint
[0], res
->Constraint
[0],
139 cloog_pol_nbc (pol
) * (cloog_pol_dim (pol
) + 2));
145 * The maximal number of rays allowed to be allocated by PolyLib. In fact since
146 * version 5.20, PolyLib automatically tune the number of rays by multiplying
147 * by 2 this number each time the maximum is reached. For unknown reasons
148 * PolyLib makes a segmentation fault if this number is too small. If this
149 * number is too small, performances will be reduced, if it is too high, memory
150 * will be saturated. Note that the option "-rays X" set this number to X.
154 /* Unused in this backend. */
156 int cloog_domain_allocated
= 0;
157 int cloog_domain_freed
= 0;
158 int cloog_domain_max
= 0;
160 /* The same for Value variables since in GMP mode they have to be freed. */
161 int cloog_value_allocated
= 0;
162 int cloog_value_freed
= 0;
163 int cloog_value_max
= 0;
167 cloog_domain_polyhedron_set (CloogDomain
* d
, polyhedra_union p
)
173 cloog_domain_set_references (CloogDomain
* d
, int i
)
179 cloog_new_domain (polyhedra_union p
)
181 CloogDomain
*domain
= (CloogDomain
*) malloc (sizeof (CloogDomain
));
183 cloog_domain_set_references (domain
, 1);
188 cloog_domain_alloc (polyhedron p
)
190 return cloog_new_domain (cloog_new_upol (p
));
193 static inline CloogDomain
*
194 cloog_check_domain_id (CloogDomain
*dom
)
199 static inline CloogDomain
*
200 cloog_check_domain (CloogDomain
*dom
)
209 cloog_vector_min_not_zero (Value
* p
, unsigned len
, int *index
, Value
* min
)
212 int i
= cloog_first_non_zero (p
, len
);
216 value_set_si (*min
, 1);
221 value_absolute (*min
, p
[i
]);
224 for (i
= i
+ 1; i
< (int) len
; i
++)
226 if (value_zero_p (p
[i
]))
229 value_absolute (x
, p
[i
]);
230 if (value_lt (x
, *min
))
232 value_assign (*min
, x
);
241 cloog_vector_gcd (Value
* p
, int len
, Value
* gcd
)
244 int i
, non_zero
, min_index
= 0;
246 q
= (Value
*) malloc (len
* sizeof (Value
));
248 for (i
= 0; i
< len
; i
++)
251 for (cp
= p
, cq
= q
, i
= 0; i
< len
; i
++, cq
++, cp
++)
252 value_absolute (*cq
, *cp
);
256 cloog_vector_min_not_zero (q
, len
, &min_index
, gcd
);
258 if (value_notone_p (*gcd
))
260 for (cq
= q
, non_zero
= 0, i
= 0; i
< len
; i
++, cq
++)
263 value_modulus (*cq
, *cq
, *gcd
);
264 non_zero
|= value_notzero_p (*cq
);
273 for (i
= 0; i
< len
; i
++)
280 cloog_matrix_combine (Value
* p1
, Value
* p2
, Value
* p3
, int x
, unsigned len
)
282 Value a1
, a2
, gcd
, b1
, b2
, n1
;
284 value_init (a1
), value_init (a2
), value_init (gcd
),
285 value_init (b1
), value_init (b2
), value_init (n1
);
287 value_assign (a1
, p1
[x
]);
288 value_assign (a2
, p2
[x
]);
290 value_absolute (b1
, a1
);
291 value_absolute (b2
, a2
);
295 value_division (a1
, a1
, gcd
);
296 value_division (a2
, a2
, gcd
);
297 value_oppose (n1
, a1
);
298 cloog_vector_combine (p1
+ 1, p2
+ 1, p3
+ 1, a2
, n1
, len
);
299 cloog_vector_normalize (p3
+ 1, len
);
301 value_clear (a1
), value_clear (a2
), value_clear (gcd
),
302 value_clear (b1
), value_clear (b2
), value_clear (n1
);
305 /* In the matrix representation an equality has a 0 in the first
306 column. When the value of the first column is 1, the row
307 represents an inequality. */
310 cloog_matrix_row_is_eq_p (CloogMatrix
*matrix
, int row
)
312 return value_zero_p (matrix
->p
[row
][0]);
315 static ppl_Constraint_t
316 cloog_build_ppl_cstr (ppl_Linear_Expression_t expr
, int ineq
)
318 ppl_Constraint_t cstr
;
323 ppl_new_Constraint (&cstr
, expr
, PPL_CONSTRAINT_TYPE_EQUAL
);
327 ppl_new_Constraint (&cstr
, expr
, PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL
);
331 /* Should not happen. */
338 /* Translates to PPL row I from MATRIX. CST is the constant part that
339 is added to the constraint. When INEQ is 1 the constraint is
340 translated as an inequality, when INEQ is 0 it is translated as an
341 equality, when INEQ has another value, the first column of the
342 matrix is read for determining the type of the constraint. */
344 static ppl_Constraint_t
345 cloog_translate_constraint (CloogMatrix
*matrix
, int i
, int cst
, int ineq
)
348 ppl_Constraint_t res
;
349 ppl_Coefficient_t coef
;
350 ppl_Linear_Expression_t expr
;
351 ppl_dimension_type dim
= matrix
->NbColumns
- 2;
355 ppl_new_Coefficient (&coef
);
356 ppl_new_Linear_Expression_with_dimension (&expr
, dim
);
358 for (j
= 1; j
< matrix
->NbColumns
- 1; j
++)
360 ppl_assign_Coefficient_from_mpz_t (coef
, matrix
->p
[i
][j
]);
361 ppl_Linear_Expression_add_to_coefficient (expr
, j
- 1, coef
);
364 value_set_si (val
, cst
);
365 value_addto (val
, matrix
->p
[i
][matrix
->NbColumns
- 1], val
);
366 ppl_assign_Coefficient_from_mpz_t (coef
, val
);
368 ppl_Linear_Expression_add_to_inhomogeneous (expr
, coef
);
369 ppl_delete_Coefficient (coef
);
371 if (ineq
!= 0 && ineq
!= 1)
372 ineq
= !cloog_matrix_row_is_eq_p (matrix
, i
);
374 res
= cloog_build_ppl_cstr (expr
, ineq
);
375 ppl_delete_Linear_Expression (expr
);
379 /* Translates to PPL the opposite of row I from MATRIX. When INEQ is
380 1 the constraint is translated as an inequality, when INEQ is 0 it
381 is translated as an equality, when INEQ has another value, the
382 first column of the matrix is read for determining the type of the
385 static ppl_Constraint_t
386 cloog_translate_oppose_constraint (CloogMatrix
*matrix
, int i
, int cst
, int ineq
)
389 ppl_Constraint_t res
;
390 ppl_Coefficient_t coef
;
391 ppl_Linear_Expression_t expr
;
392 ppl_dimension_type dim
= matrix
->NbColumns
- 2;
397 ppl_new_Coefficient (&coef
);
398 ppl_new_Linear_Expression_with_dimension (&expr
, dim
);
400 for (j
= 1; j
< matrix
->NbColumns
- 1; j
++)
402 value_oppose (val
, matrix
->p
[i
][j
]);
403 ppl_assign_Coefficient_from_mpz_t (coef
, val
);
404 ppl_Linear_Expression_add_to_coefficient (expr
, j
- 1, coef
);
407 value_oppose (val
, matrix
->p
[i
][matrix
->NbColumns
- 1]);
408 value_set_si (val1
, cst
);
409 value_addto (val
, val
, val1
);
410 ppl_assign_Coefficient_from_mpz_t (coef
, val
);
411 ppl_Linear_Expression_add_to_inhomogeneous (expr
, coef
);
412 ppl_delete_Coefficient (coef
);
414 if (ineq
!= 0 && ineq
!= 1)
415 ineq
= !cloog_matrix_row_is_eq_p (matrix
, i
);
417 res
= cloog_build_ppl_cstr (expr
, ineq
);
418 ppl_delete_Linear_Expression (expr
);
422 /* Adds to PPL the constraints from MATRIX. */
425 cloog_translate_constraint_matrix_1 (ppl_Polyhedron_t ppl
, CloogMatrix
*matrix
)
429 for (i
= 0; i
< matrix
->NbRows
; i
++)
431 ppl_Constraint_t c
= cloog_translate_constraint (matrix
, i
, 0, -1);
432 ppl_Polyhedron_add_constraint_and_minimize (ppl
, c
);
433 ppl_delete_Constraint (c
);
437 static ppl_Polyhedron_t
438 cloog_translate_constraint_matrix (CloogMatrix
*matrix
)
440 ppl_Polyhedron_t ppl
;
441 ppl_dimension_type dim
= matrix
->NbColumns
- 2;
443 ppl_new_NNC_Polyhedron_from_space_dimension (&ppl
, dim
, 0);
444 cloog_translate_constraint_matrix_1 (ppl
, matrix
);
448 /* Put the constraint matrix of polyhedron RES under Cloog's normal
449 form: Cloog expects to see
459 These two forms are equivalent but the expected form uses rightmost
460 indices for inequalities. */
463 cloog_pol_normal_form (polyhedron res
)
465 int dim
= cloog_pol_dim (res
);
466 int nrows
= cloog_pol_nbc (res
);
468 int neqs
= cloog_pol_nbeq (res
);
470 for (j
= 1; j
<= dim
; j
++)
474 for (rank
= 0; rank
< neqs
; rank
++)
475 if (j
- 1 == cloog_first_non_zero (res
->Constraint
[rank
] + 1, dim
))
477 for (i
= neqs
; i
< nrows
; i
++)
478 if (value_notzero_p (res
->Constraint
[i
][j
]))
479 cloog_matrix_combine (res
->Constraint
[i
],
480 res
->Constraint
[rank
],
481 res
->Constraint
[i
], j
, dim
+ 1);
489 cloog_translate_ppl_polyhedron_1 (ppl_Polyhedron_t pol
)
492 ppl_dimension_type dim
;
493 ppl_const_Constraint_System_t pcs
;
494 ppl_Constraint_System_const_iterator_t cit
, end
;
495 int eqs
, orig_ineqs
, ineqs
, row
, i
;
496 ppl_const_Constraint_t pc
;
498 ppl_Polyhedron_get_minimized_constraints (pol
, &pcs
);
499 ppl_new_Constraint_System_const_iterator (&cit
);
500 ppl_new_Constraint_System_const_iterator (&end
);
502 for (eqs
= 0, ineqs
= 0,
503 ppl_Constraint_System_begin (pcs
, cit
),
504 ppl_Constraint_System_end (pcs
, end
);
505 !ppl_Constraint_System_const_iterator_equal_test (cit
, end
);
506 ppl_Constraint_System_const_iterator_increment (cit
))
508 ppl_Constraint_System_const_iterator_dereference (cit
, &pc
);
509 (ppl_Constraint_type (pc
) == PPL_CONSTRAINT_TYPE_EQUAL
) ? eqs
++ : ineqs
++;
512 ppl_Polyhedron_space_dimension (pol
, &dim
);
515 if (1 || orig_ineqs
== 0)
516 res
= cloog_new_pol (dim
, eqs
+ ineqs
+ 1);
518 res
= cloog_new_pol (dim
, eqs
+ ineqs
);
521 /* Sort constraints: Cloog expects to see in matrices the equalities
522 followed by inequalities. */
525 for (ppl_Constraint_System_begin (pcs
, cit
), ppl_Constraint_System_end (pcs
, end
);
526 !ppl_Constraint_System_const_iterator_equal_test (cit
, end
);
527 ppl_Constraint_System_const_iterator_increment (cit
))
529 ppl_Coefficient_t coef
;
530 ppl_dimension_type col
;
535 ppl_new_Coefficient (&coef
);
536 ppl_Constraint_System_const_iterator_dereference (cit
, &pc
);
538 neg
= (ppl_Constraint_type (pc
) == PPL_CONSTRAINT_TYPE_LESS_THAN
539 || ppl_Constraint_type (pc
) == PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL
) ? 1 : 0;
540 row
= (ppl_Constraint_type (pc
) == PPL_CONSTRAINT_TYPE_EQUAL
) ? eqs
++ : ineqs
++;
542 for (col
= 0; col
< dim
; col
++)
544 ppl_Constraint_coefficient (pc
, col
, coef
);
545 ppl_Coefficient_to_mpz_t (coef
, val
);
548 value_oppose (val
, val
);
550 value_assign (res
->Constraint
[row
][col
+ 1], val
);
553 ppl_Constraint_inhomogeneous_term (pc
, coef
);
554 ppl_Coefficient_to_mpz_t (coef
, val
);
555 value_assign (res
->Constraint
[row
][dim
+ 1], val
);
556 ppl_delete_Coefficient (coef
);
558 switch (ppl_Constraint_type (pc
))
560 case PPL_CONSTRAINT_TYPE_EQUAL
:
561 value_set_si (res
->Constraint
[row
][0], 0);
564 case PPL_CONSTRAINT_TYPE_LESS_THAN
:
565 case PPL_CONSTRAINT_TYPE_GREATER_THAN
:
566 value_decrement (res
->Constraint
[row
][dim
+ 1],
567 res
->Constraint
[row
][dim
+ 1]);
568 value_set_si (res
->Constraint
[row
][0], 1);
571 case PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL
:
572 case PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL
:
573 value_set_si (res
->Constraint
[row
][0], 1);
577 fprintf (stderr
, "PPL_CONSTRAINT_TYPE_%d not implemented yet\n",
578 ppl_Constraint_type (pc
));
582 ppl_delete_Constraint_System_const_iterator (cit
);
583 ppl_delete_Constraint_System_const_iterator (end
);
585 if (cloog_pol_nbeq (res
) == 2 && cloog_pol_nbc (res
) == 2
586 && cloog_first_non_zero (res
->Constraint
[0], dim
+ 2) == (int) dim
+ 1)
588 cloog_pol_free (res
);
589 return cloog_empty_polyhedron (dim
);
592 /* Add the positivity constraint. */
593 if (1 || orig_ineqs
== 0)
596 value_set_si (res
->Constraint
[row
][0], 1);
597 for (i
= 0; i
< (int) dim
; i
++)
598 value_set_si (res
->Constraint
[row
][i
+ 1], 0);
599 value_set_si (res
->Constraint
[row
][dim
+ 1], 1);
602 /* Put the matrix of RES in normal form. */
603 cloog_pol_normal_form (res
);
605 /* If we do not sort the matrices, Cloog is a random loop
607 cloog_pol_sort_rows (res
);
613 cloog_pol_from_matrix (CloogMatrix
* m
)
616 int ncolumns
= cloog_matrix_ncolumns (m
);
617 int nrows
= cloog_matrix_nrows (m
);
621 return cloog_universe_polyhedron (ncolumns
- 2);
624 p
= cloog_translate_constraint_matrix (m
);
625 res
= cloog_translate_ppl_polyhedron_1 (p
);
626 ppl_delete_Polyhedron (p
);
627 if ((int) cloog_pol_nbc (res
) < cloog_matrix_nrows (m
))
630 cloog_pol_free (res
);
631 res
= cloog_new_pol (ncolumns
- 2, nrows
);
632 cloog_vector_copy (m
->p
[0], res
->Constraint
[0], m
->NbRows
* m
->NbColumns
);
638 cloog_domain_matrix2domain (CloogMatrix
* matrix
)
640 return cloog_domain_alloc (cloog_pol_from_matrix (matrix
));
644 cloog_translate_ppl_polyhedron (ppl_Polyhedron_t p
)
646 polyhedron res
= cloog_translate_ppl_polyhedron_1 (p
);
647 return cloog_domain_alloc (res
);
651 cloog_pol_print (FILE * file
, polyhedron pol
)
659 fprintf (file
, "<null polyhedron>\n");
663 dim
= cloog_pol_dim (pol
) + 2;
664 nbc
= cloog_pol_nbc (pol
);
665 fprintf (file
, "POLYHEDRON Dimension:%d\n", cloog_pol_dim (pol
));
667 " Constraints:%d Equations:%d\n",
668 cloog_pol_nbc (pol
), cloog_pol_nbeq (pol
));
669 fprintf (file
, "Constraints %d %d\n", nbc
, dim
);
671 for (i
= 0; i
< (int) nbc
; i
++)
673 p
= pol
->Constraint
[i
];
675 if (value_notzero_p (*p
))
676 fprintf (file
, "Inequality: [");
678 fprintf (file
, "Equality: [");
682 for (j
= 1; j
< (int) dim
; j
++)
683 value_print (file
, "%4s ", *p
++);
685 fprintf (file
, " ]\n");
689 void debug_poly (polyhedron p
)
691 cloog_pol_print (stderr
, p
);
695 debug_ppl_poly (ppl_Polyhedron_t p
)
697 debug_poly (cloog_domain_polyhedron (cloog_translate_ppl_polyhedron (p
)));
701 cloog_domain_references (CloogDomain
* d
)
703 return d
->_references
;
707 * cloog_domain_print function:
708 * This function prints the content of a CloogDomain structure (domain) into
709 * a file (foo, possibly stdout).
712 cloog_domain_print (FILE * foo
, CloogDomain
* domain
)
714 polyhedra_union upol
= cloog_domain_upol (domain
);
718 cloog_pol_print (foo
, cloog_upol_polyhedron (upol
));
719 upol
= cloog_upol_next (upol
);
722 fprintf (foo
, "Number of active references: %d\n",
723 cloog_domain_references (domain
));
727 * cloog_domain_free function:
728 * This function frees the allocated memory for a CloogDomain structure
729 * (domain). It decrements the number of active references to this structure,
730 * if there are no more references on the structure, it frees it (with the
731 * included list of polyhedra).
734 cloog_domain_free (CloogDomain
* domain
)
738 cloog_domain_set_references (domain
,
739 cloog_domain_references (domain
) - 1);
741 if (cloog_domain_references (domain
) == 0)
744 polyhedra_union upol
= cloog_domain_upol (domain
);
748 polyhedra_union next_upol
;
750 cloog_pol_free (cloog_upol_polyhedron (upol
));
751 next_upol
= cloog_upol_next (upol
);
752 cloog_upol_free (upol
);
763 * cloog_domain_copy function:
764 * This function returns a copy of a CloogDomain structure (domain). To save
765 * memory this is not a memory copy but we increment a counter of active
766 * references inside the structure, then return a pointer to that structure.
769 cloog_domain_copy (CloogDomain
* domain
)
771 cloog_domain_set_references (domain
, cloog_domain_references (domain
) + 1);
776 * cloog_domain_convex function:
777 * Given a polyhedral domain (polyhedron), this function concatenates the lists
778 * of rays and lines of the two (or more) polyhedra in the domain into one
779 * combined list, and find the set of constraints which tightly bound all of
780 * those objects. It returns the corresponding polyhedron.
783 cloog_domain_convex (CloogDomain
* domain
)
787 polyhedra_union upol
= cloog_domain_upol (domain
);
788 CloogMatrix
*m
= cloog_upol_domain2matrix (upol
);
789 ppl_Polyhedron_t p1
= cloog_translate_constraint_matrix (m
);
791 upol
= cloog_upol_next (upol
);
794 ppl_const_Generator_System_t g
;
796 m
= cloog_upol_domain2matrix (upol
);
797 p2
= cloog_translate_constraint_matrix (m
);
798 ppl_Polyhedron_get_generators (p2
, &g
);
799 ppl_Polyhedron_add_generators_and_minimize (p1
, g
);
800 ppl_delete_Polyhedron (p2
);
802 upol
= cloog_upol_next (upol
);
805 res
= cloog_translate_ppl_polyhedron (p1
);
806 ppl_delete_Polyhedron (p1
);
812 cloog_domain_isconvex (CloogDomain
* domain
)
814 if (cloog_domain_polyhedron (domain
))
815 return !cloog_upol_next (cloog_domain_upol (domain
));
821 * cloog_domain_simple_convex:
822 * Given a list (union) of polyhedra, this function returns a "simple"
823 * convex hull of this union. In particular, the constraints of the
824 * the returned polyhedron consist of (parametric) lower and upper
825 * bounds on individual variables and constraints that appear in the
826 * original polyhedra.
828 * nb_par is the number of parameters of the domain.
831 cloog_domain_simple_convex (CloogDomain
* domain
, int nb_par
)
833 fprintf (stderr
, "cloog_domain_simple_convex (domain, nb_par = %d) is not implemented yet.\n", nb_par
);
834 fprintf (stderr
, "domain = \n");
835 cloog_domain_print (stderr
, domain
);
839 /* Returns non-zero when the constraint I in MATRIX is the positivity
840 constraint: "0 >= 0". */
843 cloog_positivity_constraint_p (CloogMatrix
*matrix
, int i
, int dim
)
847 for (j
= 1; j
< dim
; j
++)
848 if (value_notzero_p (matrix
->p
[i
][j
]))
854 /* Returns one when the constraint C is not in P, returns zero when C
858 non_redundant_constraint (ppl_Constraint_t c
, ppl_Polyhedron_t p
)
860 int rel
= ppl_Polyhedron_relation_with_Constraint (p
, c
);
862 if (rel
& PPL_POLY_CON_RELATION_IS_DISJOINT
)
865 if (rel
& PPL_POLY_CON_RELATION_IS_INCLUDED
)
868 if (rel
& PPL_POLY_CON_RELATION_STRICTLY_INTERSECTS
)
870 ppl_Constraint_System_t cs
;
872 ppl_const_Generator_System_t g
;
873 ppl_Generator_System_const_iterator_t git
, end
;
874 ppl_const_Generator_t cg
;
876 ppl_new_Constraint_System_from_Constraint (&cs
, c
);
877 ppl_new_NNC_Polyhedron_from_Constraint_System (&p1
, cs
);
878 ppl_Polyhedron_get_generators (p1
, &g
);
879 ppl_new_Generator_System_const_iterator (&git
);
880 ppl_new_Generator_System_const_iterator (&end
);
882 for (ppl_Generator_System_begin (g
, git
), ppl_Generator_System_end (g
, end
);
883 !ppl_Generator_System_const_iterator_equal_test (git
, end
);
884 ppl_Generator_System_const_iterator_increment (git
))
886 ppl_Generator_System_const_iterator_dereference (git
, &cg
);
887 rel
= ppl_Polyhedron_relation_with_Generator (p
, cg
);
889 if (!(rel
& PPL_POLY_GEN_RELATION_SUBSUMES
))
892 ppl_delete_Constraint_System (cs
);
893 ppl_delete_Polyhedron (p1
);
894 ppl_delete_Generator_System_const_iterator (git
);
895 ppl_delete_Generator_System_const_iterator (end
);
897 /* All generators are redundant. */
898 if (rel
& PPL_POLY_GEN_RELATION_SUBSUMES
)
905 /* Returns 1 if adding constraint C to polyhedron P changes the number
906 of constraints of P. */
909 changes_constraints (ppl_Constraint_t c
, ppl_Polyhedron_t p
)
911 int a1
= 0, a2
= 0, a3
= 0, a4
= 0, a5
= 0;
912 int b1
= 0, b2
= 0, b3
= 0, b4
= 0, b5
= 0;
914 ppl_const_Constraint_System_t g
;
915 ppl_Constraint_System_const_iterator_t git
, end
;
917 ppl_new_Constraint_System_const_iterator (&git
);
918 ppl_new_Constraint_System_const_iterator (&end
);
919 ppl_Polyhedron_get_minimized_constraints (p
, &g
);
921 for (ppl_Constraint_System_begin (g
, git
), ppl_Constraint_System_end (g
, end
);
922 !ppl_Constraint_System_const_iterator_equal_test (git
, end
);
923 ppl_Constraint_System_const_iterator_increment (git
))
925 ppl_const_Constraint_t pg
;
927 ppl_Constraint_System_const_iterator_dereference (git
, &pg
);
928 switch (ppl_Constraint_type (pg
))
930 case PPL_CONSTRAINT_TYPE_LESS_THAN
:
934 case PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL
:
938 case PPL_CONSTRAINT_TYPE_EQUAL
:
942 case PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL
:
946 case PPL_CONSTRAINT_TYPE_GREATER_THAN
:
955 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q
, p
);
956 ppl_Polyhedron_add_constraint_and_minimize (q
, c
);
957 ppl_Polyhedron_get_minimized_constraints (q
, &g
);
959 for (ppl_Constraint_System_begin (g
, git
), ppl_Constraint_System_end (g
, end
);
960 !ppl_Constraint_System_const_iterator_equal_test (git
, end
);
961 ppl_Constraint_System_const_iterator_increment (git
))
963 ppl_const_Constraint_t pg
;
965 ppl_Constraint_System_const_iterator_dereference (git
, &pg
);
966 switch (ppl_Constraint_type (pg
))
968 case PPL_CONSTRAINT_TYPE_LESS_THAN
:
972 case PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL
:
976 case PPL_CONSTRAINT_TYPE_EQUAL
:
980 case PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL
:
984 case PPL_CONSTRAINT_TYPE_GREATER_THAN
:
993 ppl_delete_Constraint_System_const_iterator (git
);
994 ppl_delete_Constraint_System_const_iterator (end
);
995 ppl_delete_Polyhedron (q
);
997 if (a1
!= b1
|| a2
!= b2
|| a3
!= b3
|| a4
!= b4
|| a5
!= b5
)
1003 /* Returns 1 if adding constraint C to polyhedron P changes the
1007 changes_generators (ppl_Constraint_t c
, ppl_Polyhedron_t p
)
1012 ppl_const_Generator_System_t g
;
1013 ppl_Generator_System_const_iterator_t git
, end
;
1015 ppl_new_Generator_System_const_iterator (&git
);
1016 ppl_new_Generator_System_const_iterator (&end
);
1017 ppl_Polyhedron_get_minimized_generators (p
, &g
);
1019 for (ppl_Generator_System_begin (g
, git
), ppl_Generator_System_end (g
, end
);
1020 !ppl_Generator_System_const_iterator_equal_test (git
, end
);
1021 ppl_Generator_System_const_iterator_increment (git
))
1023 ppl_const_Generator_t pg
;
1025 ppl_Generator_System_const_iterator_dereference (git
, &pg
);
1026 switch (ppl_Generator_type (pg
))
1028 case PPL_GENERATOR_TYPE_LINE
:
1029 case PPL_GENERATOR_TYPE_RAY
:
1033 case PPL_GENERATOR_TYPE_POINT
:
1034 case PPL_GENERATOR_TYPE_CLOSURE_POINT
:
1043 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q
, p
);
1044 ppl_Polyhedron_add_constraint (q
, c
);
1045 ppl_Polyhedron_get_minimized_generators (q
, &g
);
1047 for (ppl_Generator_System_begin (g
, git
), ppl_Generator_System_end (g
, end
);
1048 !ppl_Generator_System_const_iterator_equal_test (git
, end
);
1049 ppl_Generator_System_const_iterator_increment (git
))
1051 ppl_const_Generator_t pg
;
1053 ppl_Generator_System_const_iterator_dereference (git
, &pg
);
1054 switch (ppl_Generator_type (pg
))
1056 case PPL_GENERATOR_TYPE_LINE
:
1057 case PPL_GENERATOR_TYPE_RAY
:
1061 case PPL_GENERATOR_TYPE_POINT
:
1062 case PPL_GENERATOR_TYPE_CLOSURE_POINT
:
1071 ppl_delete_Generator_System_const_iterator (git
);
1072 ppl_delete_Generator_System_const_iterator (end
);
1073 ppl_delete_Polyhedron (q
);
1075 if (a1
>= b1
&& a2
>= b2
)
1081 /* Simplifies DOM1 in the context of DOM2. For example, DOM1 can
1082 contain the following conditions: i >= 0, i <= 5, and DOM2 is a
1083 loop around, i.e. the context of DOM1, that also contains the
1084 conditions i >= 0, i <= 5. So instead of generating a loop like:
1086 | for (i = 0; i < 6; i++)
1088 | if (i >= 0 && i <= 5)
1092 this function allows to detect that in the context of DOM2, the
1093 constraints of DOM1 are redundant, and so the following code should
1096 | for (i = 0; i < 6; i++)
1101 cloog_domain_simplify (CloogDomain
* dom1
, CloogDomain
* dom2
)
1104 CloogDomain
*res
= NULL
;
1105 polyhedra_union u1
, u2
;
1106 unsigned dim
= cloog_domain_dim (dom1
);
1107 CloogDomain
*inter
= cloog_domain_intersection (dom1
, dom2
);
1109 for (u1
= cloog_domain_upol (inter
); u1
; u1
= cloog_upol_next (u1
))
1111 CloogMatrix
*m1
= cloog_upol_domain2matrix (u1
);
1113 for (u2
= cloog_domain_upol (dom2
); u2
; u2
= cloog_upol_next (u2
))
1115 CloogMatrix
*m2
= cloog_upol_domain2matrix (u2
);
1116 ppl_Polyhedron_t p2
= cloog_translate_constraint_matrix (m2
);
1117 ppl_Polyhedron_t p3
;
1119 ppl_new_NNC_Polyhedron_from_space_dimension (&p3
, dim
, 0);
1121 for (i
= 0; i
< m1
->NbRows
; i
++)
1122 if (!cloog_positivity_constraint_p (m1
, i
, dim
+ 1))
1124 ppl_Constraint_t c1
= cloog_translate_constraint (m1
, i
, 0, -1);
1126 if (non_redundant_constraint (c1
, p2
)
1127 || changes_generators (c1
, p2
)
1128 || changes_constraints (c1
, p2
))
1129 ppl_Polyhedron_add_constraint_and_minimize (p3
, c1
);
1131 ppl_delete_Constraint (c1
);
1134 res
= cloog_domain_union (res
, cloog_translate_ppl_polyhedron (p3
));
1136 ppl_delete_Polyhedron (p2
);
1137 ppl_delete_Polyhedron (p3
);
1145 static polyhedra_union
1146 cloog_upol_copy (polyhedra_union p
)
1148 polyhedra_union res
= cloog_new_upol (cloog_pol_copy (cloog_upol_polyhedron (p
)));
1149 polyhedra_union upol
= res
;
1151 while (cloog_upol_next (p
))
1153 cloog_upol_set_next (upol
, cloog_new_upol (cloog_pol_copy (cloog_upol_polyhedron (p
))));
1154 upol
= cloog_upol_next (upol
);
1155 p
= cloog_upol_next (p
);
1161 /* Adds to D1 the union of polyhedra from D2, with no checks of
1162 redundancies between polyhedra. */
1164 static CloogDomain
*
1165 cloog_domain_add_domain (CloogDomain
*d1
, CloogDomain
*d2
)
1167 polyhedra_union upol
;
1175 upol
= cloog_domain_upol (d1
);
1176 while (cloog_upol_next (upol
))
1177 upol
= cloog_upol_next (upol
);
1179 cloog_upol_set_next (upol
, cloog_domain_upol (d2
));
1184 * cloog_domain_union function:
1185 * This function returns a new CloogDomain structure including a polyhedral
1186 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
1187 * two CloogDomain structures.
1190 cloog_domain_union (CloogDomain
* dom1
, CloogDomain
* dom2
)
1193 polyhedra_union head1
, head2
, tail1
, tail2
;
1194 polyhedra_union d1
, d2
;
1202 if (cloog_domain_dim (dom1
) != cloog_domain_dim (dom2
))
1204 fprintf (stderr
, "cloog_domain_union should not be called on domains of different dimensions.\n");
1210 for (d1
= cloog_domain_upol (dom1
); d1
; d1
= cloog_upol_next (d1
))
1213 ppl_Polyhedron_t ppl1
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d1
));
1215 for (d2
= cloog_domain_upol (dom2
); d2
; d2
= cloog_upol_next (d2
))
1217 ppl_Polyhedron_t ppl2
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d2
));
1219 if (ppl_Polyhedron_contains_Polyhedron (ppl2
, ppl1
))
1221 ppl_delete_Polyhedron (ppl2
);
1225 ppl_delete_Polyhedron (ppl2
);
1227 ppl_delete_Polyhedron (ppl1
);
1233 head1
= cloog_upol_copy (d1
);
1238 cloog_upol_set_next (tail1
, cloog_upol_copy (d1
));
1239 tail1
= cloog_upol_next (tail1
);
1246 for (d2
= cloog_domain_upol (dom2
); d2
; d2
= cloog_upol_next (d2
))
1249 ppl_Polyhedron_t ppl2
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d2
));
1251 for (d1
= head1
; d1
; d1
= cloog_upol_next (d1
))
1253 ppl_Polyhedron_t ppl1
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d1
));
1255 if (ppl_Polyhedron_contains_Polyhedron (ppl1
, ppl2
))
1257 ppl_delete_Polyhedron (ppl1
);
1261 ppl_delete_Polyhedron (ppl1
);
1263 ppl_delete_Polyhedron (ppl2
);
1269 head2
= cloog_upol_copy (d2
);
1274 cloog_upol_set_next (tail2
, cloog_upol_copy (d2
));
1275 tail2
= cloog_upol_next (tail2
);
1281 res
= cloog_new_domain (head2
);
1284 cloog_upol_set_next (tail1
, head2
);
1285 res
= cloog_new_domain (head1
);
1288 return cloog_check_domain (res
);
1292 * cloog_domain_intersection function:
1293 * This function returns a new CloogDomain structure including a polyhedral
1294 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
1295 * inside two CloogDomain structures.
1298 cloog_domain_intersection (CloogDomain
* dom1
, CloogDomain
* dom2
)
1300 CloogDomain
*res
= NULL
;
1301 polyhedra_union p1
, p2
;
1302 ppl_Polyhedron_t ppl1
, ppl2
;
1304 for (p1
= cloog_domain_upol (dom1
); p1
; p1
= cloog_upol_next (p1
))
1306 ppl1
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (p1
));
1308 for (p2
= cloog_domain_upol (dom2
); p2
; p2
= cloog_upol_next (p2
))
1310 ppl2
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (p2
));
1311 ppl_Polyhedron_intersection_assign (ppl2
, ppl1
);
1312 res
= cloog_domain_union (res
, cloog_translate_ppl_polyhedron (ppl2
));
1313 ppl_delete_Polyhedron (ppl2
);
1315 ppl_delete_Polyhedron (ppl1
);
1321 /* Returns d1 minus d2. */
1324 cloog_domain_difference (CloogDomain
* d1
, CloogDomain
* d2
)
1326 CloogDomain
*res
= NULL
, *d
= d1
;
1327 polyhedra_union p1
, p2
;
1329 if (cloog_domain_isempty (d2
))
1330 return cloog_domain_copy (d1
);
1332 for (p2
= cloog_domain_upol (d2
); p2
; p2
= cloog_upol_next (p2
))
1334 CloogMatrix
*matrix
= cloog_upol_domain2matrix (p2
);
1336 for (p1
= cloog_domain_upol (d
); p1
; p1
= cloog_upol_next (p1
))
1339 CloogMatrix
*m1
= cloog_upol_domain2matrix (p1
);
1341 for (i
= 0; i
< matrix
->NbRows
; i
++)
1343 ppl_Polyhedron_t p3
;
1344 ppl_Constraint_t cstr
;
1346 /* Don't handle "0 >= 0". */
1347 if (cloog_positivity_constraint_p (matrix
, i
,
1348 cloog_domain_dim (d
) + 1))
1351 /* Add the constraint "-matrix[i] - 1 >= 0". */
1352 p3
= cloog_translate_constraint_matrix (m1
);
1353 cstr
= cloog_translate_oppose_constraint (matrix
, i
, -1, 1);
1354 ppl_Polyhedron_add_constraint_and_minimize (p3
, cstr
);
1355 ppl_delete_Constraint (cstr
);
1356 res
= cloog_domain_union (res
, cloog_translate_ppl_polyhedron (p3
));
1357 ppl_delete_Polyhedron (p3
);
1359 /* For an equality, add the constraint "matrix[i] - 1 >= 0". */
1360 if (cloog_matrix_row_is_eq_p (matrix
, i
))
1362 p3
= cloog_translate_constraint_matrix (m1
);
1363 cstr
= cloog_translate_constraint (matrix
, i
, -1, 1);
1364 ppl_Polyhedron_add_constraint_and_minimize (p3
, cstr
);
1365 ppl_delete_Constraint (cstr
);
1366 res
= cloog_domain_union (res
, cloog_translate_ppl_polyhedron (p3
));
1367 ppl_delete_Polyhedron (p3
);
1376 res
= cloog_domain_empty (cloog_domain_dim (d2
));
1385 * cloog_domain_addconstraints function :
1386 * This function adds source's polyhedron constraints to target polyhedron: for
1387 * each element of the polyhedron inside 'target' (i.e. element of the union
1388 * of polyhedra) it adds the constraints of the corresponding element in
1390 * - August 10th 2002: first version.
1391 * Nota bene for future : it is possible that source and target don't have the
1392 * same number of elements (try iftest2 without non-shared constraint
1393 * elimination in cloog_loop_separate !). This function is yet another part
1394 * of the DomainSimplify patching problem...
1397 cloog_domain_addconstraints (CloogDomain
*domain_source
, CloogDomain
*domain_target
)
1400 ppl_Polyhedron_t ppl
;
1401 polyhedra_union source
, target
, last
;
1402 int dim
= cloog_domain_dim (domain_target
);
1404 source
= cloog_domain_upol (domain_source
);
1405 target
= cloog_domain_upol (domain_target
);
1407 ppl_new_NNC_Polyhedron_from_space_dimension (&ppl
, dim
, 0);
1408 cloog_translate_constraint_matrix_1 (ppl
, cloog_upol_domain2matrix (target
));
1409 cloog_translate_constraint_matrix_1 (ppl
, cloog_upol_domain2matrix (source
));
1410 res
= cloog_translate_ppl_polyhedron (ppl
);
1411 ppl_delete_Polyhedron (ppl
);
1412 last
= cloog_domain_upol (res
);
1414 source
= cloog_upol_next (source
);
1415 target
= cloog_upol_next (target
);
1419 ppl_new_NNC_Polyhedron_from_space_dimension (&ppl
, dim
, 0);
1420 cloog_translate_constraint_matrix_1 (ppl
, cloog_upol_domain2matrix (target
));
1424 cloog_translate_constraint_matrix_1 (ppl
, cloog_upol_domain2matrix (source
));
1425 source
= cloog_upol_next (source
);
1429 (last
, cloog_domain_upol (cloog_translate_ppl_polyhedron (ppl
)));
1430 ppl_delete_Polyhedron (ppl
);
1432 last
= cloog_upol_next (last
);
1433 target
= cloog_upol_next (target
);
1439 /* Compares P1 to P2: returns 0 when the polyhedra don't overlap,
1440 returns 1 when p1 >= p2, and returns -1 when p1 < p2. The ">"
1441 relation is the "contains" relation. */
1444 cloog_domain_polyhedron_compare (CloogMatrix
*m1
, CloogMatrix
*m2
, int level
, int nb_par
, int dimension
)
1447 ppl_Polyhedron_t q1
, q2
, q3
, q4
, q5
, q
;
1448 ppl_Polyhedron_t p1
, p2
;
1450 p1
= cloog_translate_constraint_matrix (m1
);
1451 if (ppl_Polyhedron_is_empty (p1
))
1453 ppl_delete_Polyhedron (p1
);
1457 p2
= cloog_translate_constraint_matrix (m2
);
1458 if (ppl_Polyhedron_is_empty (p2
))
1460 ppl_delete_Polyhedron (p2
);
1464 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q1
, p1
);
1465 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q2
, p2
);
1467 for (i
= level
; i
< dimension
- nb_par
+ 1; i
++)
1470 ppl_Coefficient_t d
;
1471 ppl_Linear_Expression_t expr
;
1475 value_set_si (val
, 1);
1476 ppl_new_Coefficient_from_mpz_t (&d
, val
);
1477 ppl_new_Linear_Expression_with_dimension (&expr
, dimension
);
1478 ppl_Linear_Expression_add_to_coefficient (expr
, i
- 1, d
);
1479 ppl_new_Generator (&g
, expr
, PPL_GENERATOR_TYPE_LINE
, d
);
1480 ppl_Polyhedron_add_generator (q1
, g
);
1481 ppl_Polyhedron_add_generator (q2
, g
);
1482 ppl_delete_Generator (g
);
1483 ppl_delete_Linear_Expression (expr
);
1484 ppl_delete_Coefficient (d
);
1487 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q
, q1
);
1488 ppl_Polyhedron_intersection_assign (q
, q2
);
1489 ppl_delete_Polyhedron (q1
);
1490 ppl_delete_Polyhedron (q2
);
1492 if (ppl_Polyhedron_is_empty (q
))
1494 ppl_delete_Polyhedron (p1
);
1495 ppl_delete_Polyhedron (p2
);
1496 ppl_delete_Polyhedron (q
);
1500 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q1
, p1
);
1501 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q2
, p2
);
1502 ppl_delete_Polyhedron (p1
);
1503 ppl_delete_Polyhedron (p2
);
1505 ppl_Polyhedron_intersection_assign (q1
, q
);
1506 ppl_Polyhedron_intersection_assign (q2
, q
);
1508 m1
= cloog_upol_domain2matrix (cloog_domain_upol (cloog_translate_ppl_polyhedron (q1
)));
1509 m2
= cloog_upol_domain2matrix (cloog_domain_upol (cloog_translate_ppl_polyhedron (q2
)));
1511 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q4
, q
);
1512 for (i
= 0; i
< m1
->NbRows
; i
++)
1513 if (value_one_p (m1
->p
[i
][0])
1514 && value_pos_p (m1
->p
[i
][level
]))
1516 ppl_Constraint_t c
= cloog_translate_constraint (m1
, i
, 0, 1);
1517 ppl_Polyhedron_add_constraint (q4
, c
);
1518 ppl_delete_Constraint (c
);
1521 for (i
= 0; i
< m2
->NbRows
; i
++)
1522 if (value_one_p (m2
->p
[i
][0])
1523 && value_neg_p (m2
->p
[i
][level
]))
1525 ppl_Constraint_t c
= cloog_translate_constraint (m2
, i
, 0, 1);
1526 ppl_Polyhedron_add_constraint (q4
, c
);
1527 ppl_delete_Constraint (c
);
1530 if (ppl_Polyhedron_is_empty (q4
))
1532 ppl_delete_Polyhedron (q
);
1533 ppl_delete_Polyhedron (q1
);
1534 ppl_delete_Polyhedron (q2
);
1535 ppl_delete_Polyhedron (q4
);
1539 ppl_delete_Polyhedron (q4
);
1540 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q3
, q
);
1541 for (i
= 0; i
< m1
->NbRows
; i
++)
1543 if (value_zero_p (m1
->p
[i
][0]))
1545 if (value_zero_p (m1
->p
[i
][level
]))
1548 else if (value_neg_p (m1
->p
[i
][level
]))
1550 ppl_Constraint_t c
= cloog_translate_oppose_constraint (m1
, i
, 0, 1);
1551 ppl_Polyhedron_add_constraint (q3
, c
);
1552 ppl_delete_Constraint (c
);
1557 ppl_Constraint_t c
= cloog_translate_constraint (m1
, i
, 0, 1);
1558 ppl_Polyhedron_add_constraint (q3
, c
);
1559 ppl_delete_Constraint (c
);
1563 else if (value_neg_p (m1
->p
[i
][level
]))
1565 ppl_Constraint_t c
= cloog_translate_oppose_constraint (m1
, i
, 0, 1);
1566 ppl_Polyhedron_add_constraint (q3
, c
);
1567 ppl_delete_Constraint (c
);
1573 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q5
, q3
);
1574 for (j
= 0; j
< m2
->NbRows
; j
++)
1576 if (value_zero_p (m2
->p
[j
][0]))
1578 if (value_zero_p (m2
->p
[j
][level
]))
1581 else if (value_pos_p (m2
->p
[j
][level
]))
1583 ppl_Constraint_t c
= cloog_translate_oppose_constraint (m2
, j
, 0, 1);
1584 ppl_Polyhedron_add_constraint (q5
, c
);
1585 ppl_delete_Constraint (c
);
1590 ppl_Constraint_t c
= cloog_translate_constraint (m2
, j
, 0, 1);
1591 ppl_Polyhedron_add_constraint (q5
, c
);
1592 ppl_delete_Constraint (c
);
1596 else if (value_pos_p (m2
->p
[j
][level
]))
1598 ppl_Constraint_t c
= cloog_translate_oppose_constraint (m2
, j
, 0, 1);
1599 ppl_Polyhedron_add_constraint (q5
, c
);
1600 ppl_delete_Constraint (c
);
1606 if (!ppl_Polyhedron_is_empty (q5
))
1608 ppl_delete_Polyhedron (q
);
1609 ppl_delete_Polyhedron (q1
);
1610 ppl_delete_Polyhedron (q2
);
1611 ppl_delete_Polyhedron (q3
);
1612 ppl_delete_Polyhedron (q5
);
1616 /* Reinitialize Q5. */
1617 ppl_delete_Polyhedron (q5
);
1618 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q5
, q3
);
1621 /* Reinitialize Q3. */
1622 ppl_delete_Polyhedron (q3
);
1623 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q3
, q
);
1626 ppl_delete_Polyhedron (q
);
1627 ppl_delete_Polyhedron (q1
);
1628 ppl_delete_Polyhedron (q2
);
1629 ppl_delete_Polyhedron (q3
);
1630 ppl_delete_Polyhedron (q5
);
1635 * cloog_domain_sort function:
1636 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
1637 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
1638 * (level) is the level to consider for partial ordering (nb_par) is the
1639 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
1640 * integers that contains a permutation specification after call in order to
1641 * apply the topological sorting.
1645 cloog_domain_sort (CloogDomain
**doms
, unsigned nb_pols
, unsigned level
,
1646 unsigned nb_par
, int *permut
)
1649 int dim
= cloog_domain_dim (doms
[0]);
1651 for (i
= 0; i
< (int) nb_pols
; i
++)
1654 /* Note that here we do a comparison per tuple of polyhedra.
1655 PolyLib does not do this, but instead it does fewer comparisons
1656 and with a complex reasoning they infer that it some comparisons
1657 are not useful. The result is that PolyLib has wrong permutations.
1659 FIXME: In the PolyLib backend, Cloog should use this algorithm
1660 instead of PolyhedronTSort, and cloog_domain_polyhedron_compare
1661 should be implemented with a simple call to PolyhedronLTQ: these
1662 two functions produce identical answers. */
1663 for (i
= 0; i
< (int) nb_pols
; i
++)
1664 for (j
= i
+ 1; j
< (int) nb_pols
; j
++)
1666 CloogMatrix
*m1
= cloog_upol_domain2matrix (cloog_domain_upol (doms
[i
]));
1667 CloogMatrix
*m2
= cloog_upol_domain2matrix (cloog_domain_upol (doms
[j
]));
1669 if (cloog_domain_polyhedron_compare (m1
, m2
, level
, nb_par
, dim
) == 1)
1672 permut
[i
] = permut
[j
];
1679 * cloog_domain_empty function:
1680 * This function allocates the memory space for a CloogDomain structure and
1681 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
1682 * Then it returns a pointer to the allocated space.
1683 * - June 10th 2005: first version.
1686 cloog_domain_empty (int dimension
)
1688 return cloog_domain_alloc (cloog_empty_polyhedron (dimension
));
1692 /******************************************************************************
1693 * Structure display function *
1694 ******************************************************************************/
1698 * cloog_domain_print_structure :
1699 * this function is a more human-friendly way to display the CloogDomain data
1700 * structure, it only shows the constraint system and includes an indentation
1701 * level (level) in order to work with others print_structure functions.
1702 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
1703 * - April 24th 2005: Initial version.
1704 * - May 26th 2005: Memory leak hunt.
1705 * - June 16th 2005: (Ced) Integration in domain.c.
1708 cloog_domain_print_structure (FILE * file
, CloogDomain
* domain
, int level
)
1711 CloogMatrix
*matrix
;
1713 /* Go to the right level. */
1714 for (i
= 0; i
< level
; i
++)
1715 fprintf (file
, "|\t");
1719 fprintf (file
, "+-- CloogDomain\n");
1721 /* Print the matrix. */
1722 matrix
= cloog_upol_domain2matrix (cloog_domain_upol (domain
));
1723 cloog_matrix_print_structure (file
, matrix
, level
);
1724 cloog_matrix_free (matrix
);
1727 for (i
= 0; i
< level
+ 1; i
++)
1728 fprintf (file
, "|\t");
1729 fprintf (file
, "\n");
1732 fprintf (file
, "+-- Null CloogDomain\n");
1738 * cloog_domain_list_print function:
1739 * This function prints the content of a CloogDomainList structure into a
1740 * file (foo, possibly stdout).
1741 * - November 6th 2001: first version.
1744 cloog_domain_list_print (FILE * foo
, CloogDomainList
* list
)
1746 while (list
!= NULL
)
1748 cloog_domain_print (foo
, cloog_domain (list
));
1749 list
= cloog_next_domain (list
);
1754 /******************************************************************************
1755 * Memory deallocation function *
1756 ******************************************************************************/
1760 * cloog_domain_list_free function:
1761 * This function frees the allocated memory for a CloogDomainList structure.
1762 * - November 6th 2001: first version.
1765 cloog_domain_list_free (CloogDomainList
* list
)
1767 CloogDomainList
*temp
;
1769 while (list
!= NULL
)
1771 temp
= cloog_next_domain (list
);
1772 cloog_domain_free (cloog_domain (list
));
1779 /******************************************************************************
1780 * Reading function *
1781 ******************************************************************************/
1785 * cloog_domain_read function:
1786 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
1787 * posibly stdin) and returns a pointer to a polyhedron containing the read
1789 * - October 18th 2001: first version.
1792 cloog_domain_read (FILE * foo
)
1794 CloogMatrix
*matrix
;
1795 CloogDomain
*domain
;
1797 matrix
= cloog_matrix_read (foo
);
1798 domain
= cloog_domain_matrix2domain (matrix
);
1799 cloog_matrix_free (matrix
);
1806 * cloog_domain_union_read function:
1807 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
1808 * returns a pointer to a Polyhedron containing the read information.
1809 * - September 9th 2002: first version.
1810 * - October 29th 2005: (debug) removal of a leak counting "correction" that
1811 * was just false since ages.
1814 cloog_domain_union_read (FILE * foo
)
1816 int i
, nb_components
;
1818 CloogDomain
*domain
, *temp
, *old
;
1820 /* domain reading: nb_components (constraint matrices). */
1821 while (fgets (s
, MAX_STRING
, foo
) == 0);
1822 while ((*s
== '#' || *s
== '\n') || (sscanf (s
, " %d", &nb_components
) < 1))
1823 fgets (s
, MAX_STRING
, foo
);
1825 if (nb_components
> 0)
1826 { /* 1. first part of the polyhedra union, */
1827 domain
= cloog_domain_read (foo
);
1828 /* 2. and the nexts. */
1829 for (i
= 1; i
< nb_components
; i
++)
1830 { /* Leak counting is OK since next allocated domain is freed here. */
1831 temp
= cloog_domain_read (foo
);
1833 domain
= cloog_domain_union (temp
, old
);
1834 cloog_domain_free (temp
);
1835 cloog_domain_free (old
);
1837 return cloog_check_domain (domain
);
1845 * cloog_domain_list_read function:
1846 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
1847 * returns a pointer to a CloogDomainList containing the read information.
1848 * - November 6th 2001: first version.
1851 cloog_domain_list_read (FILE * foo
)
1855 CloogDomainList
*list
, *now
, *next
;
1858 /* We read first the number of polyhedra in the list. */
1859 while (fgets (s
, MAX_STRING
, foo
) == 0);
1860 while ((*s
== '#' || *s
== '\n') || (sscanf (s
, " %d", &nb_pols
) < 1))
1861 fgets (s
, MAX_STRING
, foo
);
1863 /* Then we read the polyhedra. */
1867 list
= (CloogDomainList
*) malloc (sizeof (CloogDomainList
));
1868 cloog_set_domain (list
, cloog_domain_read (foo
));
1869 cloog_set_next_domain (list
, NULL
);
1871 for (i
= 1; i
< nb_pols
; i
++)
1873 next
= (CloogDomainList
*) malloc (sizeof (CloogDomainList
));
1874 cloog_set_domain (next
, cloog_domain_read (foo
));
1875 cloog_set_next_domain (next
, NULL
);
1876 cloog_set_next_domain (now
, next
);
1877 now
= cloog_next_domain (now
);
1884 /******************************************************************************
1885 * Processing functions *
1886 ******************************************************************************/
1889 * cloog_domain_isempty function:
1890 * This function returns 1 if the polyhedron given as input is empty, 0
1892 * - October 28th 2001: first version.
1895 cloog_domain_isempty (CloogDomain
* domain
)
1897 if (cloog_domain_polyhedron (domain
) == NULL
)
1900 if (cloog_upol_next (cloog_domain_upol (domain
)))
1903 return (cloog_domain_dim (domain
) < cloog_domain_nbeq (domain
)) ? 1 : 0;
1907 * cloog_domain_project function:
1908 * From Quillere's LoopGen 0.4. This function returns the projection of
1909 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
1910 * pointer to the projected Polyhedron.
1911 * - nb_par is the number of parameters.
1913 * - October 27th 2001: first version.
1914 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1918 cloog_domain_project (CloogDomain
* domain
, int level
, int nb_par
)
1920 CloogDomain
*res
= NULL
;
1921 polyhedra_union upol
= cloog_domain_upol (domain
);
1922 int i
, diff
= cloog_domain_dim (domain
) - level
- nb_par
;
1924 ppl_dimension_type
*to_remove
;
1928 fprintf (stderr
, "cloog_domain_project should not be called with"
1929 "cloog_domain_dim (domain) < level + nb_par");
1934 return cloog_domain_copy (domain
);
1937 to_remove
= (ppl_dimension_type
*) malloc (n
* sizeof (ppl_dimension_type
));
1939 for (i
= 0; i
< n
; i
++)
1940 to_remove
[i
] = i
+ level
;
1944 ppl_Polyhedron_t ppl
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (upol
));
1946 ppl_Polyhedron_remove_space_dimensions (ppl
, to_remove
, n
);
1947 res
= cloog_domain_add_domain (res
, cloog_translate_ppl_polyhedron (ppl
));
1948 ppl_delete_Polyhedron (ppl
);
1949 upol
= cloog_upol_next (upol
);
1956 * cloog_domain_extend function:
1957 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
1958 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
1959 * the (nb_par) parameters. This function does not free (domain), and returns
1961 * - nb_par is the number of parameters.
1963 * - October 27th 2001: first version.
1964 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1968 cloog_domain_extend (CloogDomain
* domain
, int dim
, int nb_par
)
1970 CloogDomain
*res
= NULL
;
1971 polyhedra_union upol
= cloog_domain_upol (domain
);
1972 int i
, k
, n
, diff
= dim
+ nb_par
- cloog_domain_dim (domain
);
1973 ppl_dimension_type
*map
;
1974 ppl_dimension_type to_add
= diff
;
1977 return cloog_domain_copy (domain
);
1980 map
= (ppl_dimension_type
*) malloc (n
* sizeof (ppl_dimension_type
));
1982 k
= cloog_domain_dim (domain
) - nb_par
;
1983 for (i
= 0; i
< k
; i
++)
1992 map
[i
] = i
- nb_par
;
1996 ppl_Polyhedron_t ppl
= cloog_translate_constraint_matrix (cloog_upol_domain2matrix (upol
));
1998 ppl_Polyhedron_add_space_dimensions_and_embed (ppl
, to_add
);
1999 ppl_Polyhedron_map_space_dimensions (ppl
, map
, n
);
2000 res
= cloog_domain_add_domain (res
, cloog_translate_ppl_polyhedron (ppl
));
2001 ppl_delete_Polyhedron (ppl
);
2002 upol
= cloog_upol_next (upol
);
2009 * cloog_domain_never_integral function:
2010 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
2011 * function returns a boolean set to 1 if there is this kind of 'never true'
2012 * constraint inside a polyhedron, 0 otherwise.
2013 * - domain is the polyhedron to check,
2015 * - November 28th 2001: first version.
2016 * - June 26th 2003: for iterators, more 'never true' constraints are found
2017 * (compare cholesky2 and vivien with a previous version),
2018 * checking for the parameters created (compare using vivien).
2019 * - June 28th 2003: Previously in loop.c and called
2020 * cloog_loop_simplify_nevertrue, now here !
2021 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
2023 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
2026 cloog_domain_never_integral (CloogDomain
* domain
)
2028 int i
, dimension
, nbc
;
2032 if ((domain
== NULL
) || (cloog_domain_polyhedron (domain
) == NULL
))
2036 value_init_c (modulo
);
2037 p
= cloog_domain_polyhedron (domain
);
2038 dimension
= cloog_domain_dim (domain
) + 2;
2039 nbc
= cloog_domain_nbconstraints (domain
);
2041 /* For each constraint... */
2042 for (i
= 0; i
< nbc
; i
++)
2043 { /* If we have an equality and the scalar part is not zero... */
2044 if (value_zero_p (p
->Constraint
[i
][0]) &&
2045 value_notzero_p (p
->Constraint
[i
][dimension
- 1]))
2046 { /* Then we check whether the scalar can be divided by the gcd of the
2047 * unknown vector (including iterators and parameters) or not. If not,
2048 * there is no integer point in the polyhedron and we return 1.
2050 cloog_vector_gcd (&(p
->Constraint
[i
][1]), dimension
- 2, &gcd
);
2051 value_modulus (modulo
,
2052 p
->Constraint
[i
][dimension
- 1],
2055 if (value_notzero_p (modulo
))
2057 value_clear_c (gcd
);
2058 value_clear_c (modulo
);
2064 value_clear_c (gcd
);
2065 value_clear_c (modulo
);
2070 cloog_vector_matrix_smallest_column (Value
* a
, int n
, int p
, int q
)
2072 int res
, numero
= 0, k
, allzero
;
2078 c
= a
+ q
- 1 + p
* (n
- 1);
2080 value_absolute (comp
, *c
);
2082 for (k
= n
; k
> q
; k
--, c
-= p
, value_absolute (comp
, *c
))
2084 if (value_notzero_p (comp
))
2088 value_assign (minus
, comp
);
2092 else if (value_ge (minus
, comp
))
2094 value_assign (minus
, comp
);
2104 value_absolute (comp
, *c
);
2105 if ((value_notzero_p (comp
)) && (value_ge (minus
, comp
)))
2111 value_clear (minus
);
2118 cloog_vector_matrix_swap_rows (Value
* a
, int i
, int j
, int p
)
2121 Value
*c1
= a
+ (i
- 1) * p
;
2122 Value
*c2
= a
+ (j
- 1) * p
;
2127 for (k
= 1; k
<= p
; k
++)
2129 value_assign (s
, *c1
);
2130 value_assign (*c1
, *c2
);
2131 value_assign (*c2
, s
);
2140 cloog_vector_matrix_swap_columns (Value
* a
, int i
, int j
, int n
, int p
)
2150 for (k
= 1; k
<= n
; k
++)
2152 value_assign (s
, *c1
);
2153 value_assign (*c1
, *c2
);
2154 value_assign (*c2
, s
);
2163 cloog_vector_matrix_oppose_line (Value
* a
, int i
, int p
)
2166 Value
*c
= a
+ (i
- 1) * p
;
2168 for (k
= 1; k
<= p
; k
++, c
++)
2169 value_oppose (*c
, *c
);
2173 cloog_vector_matrix_oppose_column (Value
* a
, int i
, int n
, int p
)
2176 Value
*c
= a
+ (i
- 1);
2178 for (k
= 1; k
<= n
; k
++, c
+= p
)
2179 value_oppose (*c
, *c
);
2183 cloog_vector_matrix_combine_line (Value
* a
, int i
, int j
,
2187 Value
*c1
= a
+ (i
- 1) * p
;
2188 Value
*c2
= a
+ (j
- 1) * p
;
2190 for (k
= 1; k
<= p
; k
++, c1
++, c2
++)
2191 value_addmul (*c1
, x
, *c2
);
2195 cloog_vector_matrix_combine_column (Value
* a
, int i
, int j
, Value x
, int n
, int p
)
2198 Value
*c1
= a
+ (i
- 1);
2199 Value
*c2
= a
+ (j
- 1);
2201 for (k
= 1; k
<= n
; k
++, c1
= c1
+ p
, c2
= c2
+ p
)
2202 value_addmul (*c1
, x
, *c2
);
2206 cloog_matrix_hermite_combine (Value
*a
, Value
*b
, Value c
, Value
*d
, int k
, int n
,
2207 int p
, int q
, Value pivot
, Value x
, Value x_inv
)
2212 value_division (x
, c
, pivot
);
2213 value_modulus (tmp
, c
, pivot
);
2215 if (value_neg_p (tmp
))
2216 value_decrement (x
, x
);
2220 value_oppose (x_inv
, x
);
2221 cloog_vector_matrix_combine_line (a
, k
, q
, x_inv
, p
);
2222 cloog_vector_matrix_combine_column (b
, q
, k
, x
, n
, n
);
2223 cloog_vector_matrix_combine_line (d
, k
, q
, x_inv
, n
);
2227 cloog_matrix_hermite_oppose (Value
*a
, Value
*b
, Value
*d
, int n
, int p
, int q
, Value pivot
)
2229 cloog_vector_matrix_oppose_line (a
, q
, p
);
2230 cloog_vector_matrix_oppose_line (d
, q
, n
);
2231 cloog_vector_matrix_oppose_column (b
, q
, n
, n
);
2232 value_oppose (pivot
, pivot
);
2236 cloog_matrix_hermite_1 (Value
* a
, Value
* b
, Value
* d
, int n
, int p
, int q
)
2239 Value x
, pivot
, x_inv
;
2249 for (i
= cloog_vector_matrix_smallest_column (a
, n
, p
, q
); i
!= 0;
2250 i
= cloog_vector_matrix_smallest_column (a
, n
, p
, q
))
2254 cloog_vector_matrix_swap_rows (a
, i
, q
, p
);
2255 cloog_vector_matrix_swap_columns (b
, i
, q
, n
, n
);
2256 cloog_vector_matrix_swap_rows (d
, i
, q
, n
);
2259 c
= a
+ (q
- 1) * (p
+ 1);
2260 value_assign (pivot
, *c
);
2261 if (value_neg_p (pivot
))
2262 cloog_matrix_hermite_oppose (a
, b
, d
, n
, p
, q
, pivot
);
2264 for (c
+= p
, k
= q
+ 1; k
<= n
; k
++, c
+= p
)
2265 if (value_notzero_p (*c
))
2266 cloog_matrix_hermite_combine (a
, b
, *c
, d
, k
, n
, p
, q
, pivot
, x
, x_inv
);
2270 value_assign (pivot
, *(c
+ (q
- 1) * p
));
2271 if (value_neg_p (pivot
))
2272 cloog_matrix_hermite_oppose (a
, b
, d
, n
, p
, q
, pivot
);
2274 if (value_notzero_p (pivot
))
2275 for (k
= 1; k
< q
; k
++, c
+= p
)
2276 if (value_notzero_p (*c
))
2277 cloog_matrix_hermite_combine (a
, b
, *c
, d
, k
, n
, p
, q
, pivot
, x
, x_inv
);
2279 cloog_matrix_hermite_1 (a
, b
, d
, n
, p
, q
+ 1);
2281 value_clear (pivot
);
2283 value_clear (x_inv
);
2287 static CloogMatrix
*
2288 cloog_matrix_add_null_row (CloogMatrix
* M
)
2291 CloogMatrix
*res
= cloog_matrix_alloc (M
->NbRows
+ 1, M
->NbColumns
);
2293 for (i
= 0; i
< M
->NbRows
; i
++)
2294 for (j
= 0; j
< M
->NbColumns
; j
++)
2295 value_assign (res
->p
[i
][j
], M
->p
[i
][j
]);
2297 for (j
= 0; j
< M
->NbColumns
; j
++)
2298 value_set_si (res
->p
[i
][j
], 0);
2303 static CloogMatrix
*
2304 cloog_matrix_transpose (CloogMatrix
* m
)
2307 CloogMatrix
*res
= cloog_matrix_alloc (m
->NbColumns
, m
->NbRows
);
2309 for (i
= 0; i
< (int) m
->NbRows
; i
++)
2310 for (j
= 0; j
< (int) m
->NbColumns
; j
++)
2311 value_assign (res
->p
[j
][i
], m
->p
[i
][j
]);
2317 cloog_vector_matrix_vectorify (CloogMatrix
* A
)
2320 Value
*res
= (Value
*) malloc (sizeof (Value
) * A
->NbRows
* A
->NbColumns
);
2322 for (i
= 0; i
< A
->NbRows
* A
->NbColumns
; i
++)
2323 value_init (res
[i
]);
2325 for (i
= 0; i
< A
->NbRows
; i
++)
2326 for (j
= 0; j
< A
->NbColumns
; j
++)
2327 value_assign (res
[i
* A
->NbColumns
+ j
], A
->p
[i
][j
]);
2332 static CloogMatrix
*
2333 cloog_vector_matrix_matrixify (Value
* A
, int NbRows
, int NbCols
)
2336 CloogMatrix
*res
= cloog_matrix_alloc (NbRows
, NbCols
);
2338 for (i
= 0; i
< NbRows
; i
++)
2339 for (j
= 0; j
< NbCols
; j
++)
2340 value_assign (res
->p
[i
][j
], A
[i
* NbCols
+ j
]);
2346 cloog_vector_matrix_identity (int n
)
2349 Value
*res
= (Value
*) malloc (sizeof (Value
) * n
* n
);
2352 for (i
= 0; i
< n
* n
; i
++)
2353 value_init (res
[i
]);
2355 for (i
= 1; i
<= n
; i
++)
2356 for (j
= 1; j
<= n
; j
++, ptr
++)
2358 value_set_si (*ptr
, 1);
2360 value_set_si (*ptr
, 0);
2366 cloog_matrix_hermite (CloogMatrix
* a
, CloogMatrix
** H
, CloogMatrix
** U
)
2369 CloogMatrix
*tu
, *transpose
= cloog_matrix_transpose (a
);
2370 Value
*va
= cloog_vector_matrix_vectorify (transpose
);
2371 Value
*vid
= cloog_vector_matrix_identity (a
->NbColumns
);
2372 Value
*vid_inv
= cloog_vector_matrix_identity (a
->NbColumns
);
2374 cloog_matrix_free (transpose
);
2376 cloog_matrix_hermite_1 (va
, vid
, vid_inv
,
2377 a
->NbColumns
, a
->NbRows
, 1);
2379 transpose
= cloog_vector_matrix_matrixify (va
, a
->NbColumns
, a
->NbRows
);
2380 H
[0] = cloog_matrix_transpose (transpose
);
2381 cloog_matrix_free (transpose
);
2383 tu
= cloog_vector_matrix_matrixify (vid
, a
->NbColumns
, a
->NbColumns
);
2384 U
[0] = cloog_matrix_transpose (tu
);
2385 cloog_matrix_free (tu
);
2387 for (i
= 0; i
< a
->NbRows
* a
->NbColumns
; i
++)
2388 value_clear (va
[i
]);
2390 for (i
= 0; i
< a
->NbColumns
* a
->NbColumns
; i
++)
2391 value_clear (vid
[i
]);
2393 for (i
= 0; i
< a
->NbColumns
* a
->NbColumns
; i
++)
2394 value_clear (vid_inv
[i
]);
2402 cloog_exchange_rows (CloogMatrix
* m
, int row1
, int row2
)
2406 for (i
= 0; i
< (int) m
->NbColumns
; i
++)
2407 value_swap (m
->p
[row1
][i
], m
->p
[row2
][i
]);
2410 static CloogMatrix
*
2411 cloog_dio_copy_submatrix (CloogMatrix
* matrix
)
2414 CloogMatrix
* copy
= cloog_matrix_alloc (matrix
->NbRows
- 1, matrix
->NbColumns
- 1) ;
2416 for (i
= 0; i
< copy
->NbRows
; i
++)
2417 for (j
= 0; j
< copy
->NbColumns
; j
++)
2418 value_assign(copy
->p
[i
][j
], matrix
->p
[i
][j
]) ;
2424 cloog_dio_rearrange_redundant_rows (CloogMatrix
* M
)
2426 int i
, end
, row
, rank
= 1;
2427 CloogMatrix
*A
, *L
, *H
, *U
;
2429 L
= cloog_dio_copy_submatrix (M
);
2433 A
= cloog_matrix_alloc (1, L
->NbColumns
);
2434 for (i
= 0; i
< L
->NbColumns
; i
++)
2435 value_assign (A
->p
[0][i
], L
->p
[0][i
]);
2437 end
= L
->NbRows
- 1;
2443 CloogMatrix
*temp
= cloog_matrix_add_null_row (A
);
2445 for (i
= 0; i
< A
->NbColumns
; i
++)
2446 value_assign (temp
->p
[row
][i
], L
->p
[row
][i
]);
2448 cloog_matrix_hermite (temp
, &H
, &U
);
2449 cloog_matrix_free (U
);
2452 for (i
= 0; i
< n
; i
++)
2453 if (value_zero_p (H
->p
[i
][i
]))
2456 cloog_matrix_free (H
);
2460 /* This is a redundant row: put it at the end. */
2461 cloog_exchange_rows (M
, row
, end
);
2468 cloog_matrix_free (A
);
2469 A
= cloog_matrix_copy (temp
);
2470 cloog_matrix_free (temp
);
2473 if (rank
== (end
>= L
->NbColumns
? L
->NbColumns
: end
)
2478 cloog_matrix_free (A
);
2481 cloog_matrix_free (L
);
2486 cloog_matrix_inverse_pivot (CloogMatrix
*m
, int low
, int up
, int i
, int j
,
2487 Value m1
, Value m2
, Value x
, Value piv
)
2491 for (c
= low
; c
< up
; ++c
)
2493 value_multiply (m1
, piv
, m
->p
[j
][c
]);
2494 value_multiply (m2
, x
, m
->p
[i
][c
]);
2495 value_subtract (m
->p
[j
][c
], m1
, m2
);
2500 cloog_matrix_inverse_den (CloogMatrix
*Mat
, CloogMatrix
*MatInv
, int k
, Value
*x
)
2504 Value
*res
= (Value
*) malloc (k
* sizeof (Value
));
2509 value_set_si (*x
, 1);
2511 for (j
= 0; j
< cloog_matrix_nrows (Mat
); ++j
)
2513 value_init (res
[j
]);
2514 value_assign (res
[j
], Mat
->p
[j
][j
]);
2515 cloog_vector_gcd (&MatInv
->p
[j
][0], k
, &gcd
);
2516 Gcd (gcd
, res
[j
], &gcd
);
2518 if (value_neg_p (res
[j
]))
2519 value_oppose (gcd
, gcd
);
2521 if (value_notone_p (gcd
))
2523 for (c
= 0; c
< k
; c
++)
2524 value_division (MatInv
->p
[j
][c
], MatInv
->p
[j
][c
], gcd
);
2525 value_division (res
[j
], res
[j
], gcd
);
2528 Gcd (*x
, res
[j
], &gcd
);
2529 value_division (m1
, res
[j
], gcd
);
2530 value_multiply (*x
, *x
, m1
);
2539 cloog_matrix_inverse_div (CloogMatrix
*MatInv
, Value
*den
, Value m1
, Value x
)
2543 if (value_notone_p (x
))
2544 for (j
= 0; j
< MatInv
->NbRows
; ++j
)
2546 for (c
= 0; c
< MatInv
->NbColumns
; c
++)
2548 value_division (m1
, x
, den
[j
]);
2549 value_multiply (MatInv
->p
[j
][c
], MatInv
->p
[j
][c
], m1
);
2555 cloog_matrix_inverse_triang (CloogMatrix
*Mat
, CloogMatrix
*MatInv
, Value
*m1
, Value
*m2
)
2565 for (i
= 0; i
< cloog_matrix_ncolumns (Mat
); ++i
)
2567 if (value_zero_p (Mat
->p
[i
][i
]))
2569 for (j
= i
; j
< cloog_matrix_nrows (Mat
); ++j
)
2570 if (value_notzero_p (Mat
->p
[j
][i
]))
2573 if (j
== cloog_matrix_nrows (Mat
))
2576 cloog_matrix_exchange_rows (Mat
, i
, j
);
2577 cloog_matrix_exchange_rows (MatInv
, i
, j
);
2580 for (j
= 0; j
< cloog_matrix_nrows (Mat
) ; ++j
)
2583 || !value_notzero_p (Mat
->p
[j
][i
]))
2586 value_assign (x
, Mat
->p
[j
][i
]);
2587 value_assign (piv
, Mat
->p
[i
][i
]);
2589 if (value_notone_p (gcd
))
2591 value_division (x
, x
, gcd
);
2592 value_division (piv
, piv
, gcd
);
2595 cloog_matrix_inverse_pivot (Mat
, ((j
> i
) ? i
: 0),
2596 cloog_matrix_nrows (Mat
),
2597 i
, j
, *m1
, *m2
, x
, piv
);
2598 cloog_matrix_inverse_pivot (MatInv
, 0, cloog_matrix_nrows (Mat
),
2599 i
, j
, *m1
, *m2
, x
, piv
);
2601 cloog_vector_gcd (&MatInv
->p
[j
][0], (unsigned) cloog_matrix_nrows (Mat
), m1
);
2602 cloog_vector_gcd (&Mat
->p
[j
][0], (unsigned) cloog_matrix_nrows (Mat
), m2
);
2603 Gcd (*m1
, *m2
, &gcd
);
2604 if (value_notone_p (gcd
))
2608 for (c
= 0; c
< cloog_matrix_nrows (Mat
); ++c
)
2610 value_division (Mat
->p
[j
][c
], Mat
->p
[j
][c
], gcd
);
2611 value_division (MatInv
->p
[j
][c
], MatInv
->p
[j
][c
], gcd
);
2627 cloog_matrix_inverse (CloogMatrix
* Mat
, CloogMatrix
* MatInv
)
2635 if (Mat
->NbRows
!= Mat
->NbColumns
)
2642 cloog_vector_set (MatInv
->p
[0], 0, cloog_matrix_nrows (Mat
) * cloog_matrix_nrows (Mat
));
2644 for (i
= 0; i
< cloog_matrix_nrows (Mat
); ++i
)
2645 value_set_si (MatInv
->p
[i
][i
], 1);
2647 if (!cloog_matrix_inverse_triang (Mat
, MatInv
, &m1
, &m2
))
2650 den
= cloog_matrix_inverse_den (Mat
, MatInv
, cloog_matrix_nrows (Mat
), &x
);
2651 cloog_matrix_inverse_div (MatInv
, den
, m1
, x
);
2655 for (j
= 0; j
< cloog_matrix_nrows (Mat
); ++j
)
2656 value_clear (den
[j
]);
2668 cloog_dio_copy (CloogMatrix
*m1
, CloogMatrix
*m2
)
2671 int n
= m2
->NbRows
- 1;
2672 int m
= m2
->NbColumns
- 1;
2674 for (i
= 0; i
< n
; i
++)
2675 for (j
= 0; j
< m
; j
++)
2676 value_assign (m1
->p
[i
][j
], m2
->p
[i
][j
]);
2680 cloog_dio_negate_coeffs (CloogMatrix
*m
)
2683 int n
= m
->NbRows
- 1;
2684 int k
= m
->NbColumns
- 1;
2685 Value
*res
= (Value
*) malloc (sizeof (Value
) * (n
));
2687 for (i
= 0; i
< n
; i
++)
2689 value_init (res
[i
]);
2690 value_oppose (res
[i
], m
->p
[i
][k
]);
2697 cloog_dio_get_first_diagonal_zero (CloogMatrix
*m
)
2699 int i
, n
= m
->NbRows
<= m
->NbColumns
? m
->NbRows
: m
->NbColumns
;
2702 for (i
= 0; i
< n
; i
++)
2703 if (value_notzero_p (m
->p
[i
][i
]))
2712 cloog_dio_reduce_diagonal (CloogMatrix
*m
, Value
*coeffs
, int nbc
, int rank
)
2715 Value
*res
= (Value
*) malloc (sizeof (Value
) * nbc
);
2721 for (i
= 0; i
< nbc
; i
++)
2722 value_init (res
[i
]);
2724 for (i
= 0; i
< rank
; i
++)
2726 value_set_si (sum
, 0);
2727 for (j
= 0; j
< i
; j
++)
2728 value_addmul (sum
, res
[j
], m
->p
[i
][j
]);
2730 value_subtract (tmp
, coeffs
[i
], sum
);
2731 value_modulus (tmp
, tmp
, m
->p
[i
][i
]);
2732 if (value_notzero_p (tmp
))
2734 for (i
= 0; i
< nbc
; i
++)
2735 value_clear (res
[i
]);
2744 value_subtract (tmp
, coeffs
[i
], sum
);
2745 value_division (res
[i
], tmp
, m
->p
[i
][i
]);
2748 for (i
= rank
; i
< m
->NbColumns
; i
++)
2749 value_set_si (res
[i
], 0);
2755 cloog_dio_check_coeffs (CloogMatrix
*m
, Value
*T
, Value
*coeffs
, int nbr
, int nbc
, int rank
)
2763 for (i
= rank
; i
< m
->NbRows
; i
++)
2765 value_set_si (sum
, 0);
2766 for (j
= 0; j
< m
->NbColumns
; j
++)
2767 value_addmul (sum
, T
[j
], m
->p
[i
][j
]);
2769 if (value_ne (sum
, coeffs
[i
]))
2771 for (i
= 0; i
< nbr
; i
++)
2772 value_clear (coeffs
[i
]);
2773 for (i
= 0; i
< nbc
; i
++)
2788 static CloogMatrix
*
2789 cloog_dio_init_U (CloogMatrix
*u
, int n
, int rank
)
2795 return cloog_matrix_alloc (0, 0);
2797 res
= cloog_matrix_alloc (n
, n
- rank
);
2799 for (i
= 0; i
< res
->NbRows
; i
++)
2800 for (j
= 0; j
< res
->NbColumns
; j
++)
2801 value_assign (res
->p
[i
][j
], u
->p
[i
][j
+ rank
]);
2807 cloog_dio_init_X (CloogMatrix
*u
, Value
*t
, int n
)
2810 Vector
*res
= Vector_Alloc (n
);
2814 for (i
= 0; i
< u
->NbRows
; i
++)
2816 value_set_si (sum
, 0);
2818 for (j
= 0; j
< u
->NbColumns
; j
++)
2819 value_addmul (sum
, u
->p
[i
][j
], t
[j
]);
2821 value_assign (res
->p
[i
], sum
);
2829 cloog_solve_diophantine (CloogMatrix
* m
, CloogMatrix
** u
, Vector
** x
)
2831 int i
, nbr
, nbc
, rank
;
2832 CloogMatrix
*A
, *temp
, *hermi
, *unimod
, *unimodinv
;
2836 A
= cloog_matrix_copy (m
);
2837 nbr
= A
->NbRows
- 1;
2839 cloog_dio_rearrange_redundant_rows (A
);
2841 temp
= cloog_matrix_alloc (A
->NbRows
- 1, A
->NbColumns
- 1);
2842 cloog_dio_copy (temp
, A
);
2843 coeffs
= cloog_dio_negate_coeffs (A
);
2844 cloog_matrix_free (A
);
2846 cloog_matrix_hermite (temp
, &hermi
, &unimod
);
2847 rank
= cloog_dio_get_first_diagonal_zero (hermi
);
2848 nbc
= temp
->NbColumns
;
2850 T
= cloog_dio_reduce_diagonal (hermi
, coeffs
, nbc
, rank
);
2851 unimodinv
= cloog_matrix_alloc (unimod
->NbRows
, unimod
->NbColumns
);
2854 || !cloog_dio_check_coeffs (hermi
, T
, coeffs
, nbr
, nbc
, rank
)
2855 || !cloog_matrix_inverse (unimod
, unimodinv
))
2857 *u
= cloog_matrix_alloc (0, 0);
2858 *x
= Vector_Alloc (0);
2860 for (i
= 0; i
< nbr
; i
++)
2861 value_clear (coeffs
[i
]);
2867 *u
= cloog_dio_init_U (unimodinv
, hermi
->NbColumns
, rank
);
2868 *x
= cloog_dio_init_X (unimodinv
, T
, m
->NbColumns
- 1);
2870 cloog_matrix_free (unimod
);
2871 cloog_matrix_free (unimodinv
);
2872 cloog_matrix_free (hermi
);
2873 cloog_matrix_free (temp
);
2875 for (i
= 0; i
< nbr
; i
++)
2876 value_clear (coeffs
[i
]);
2878 for (i
= 0; i
< nbc
; i
++)
2887 * cloog_domain_stride function:
2888 * This function finds the stride imposed to unknown with the column number
2889 * 'strided_level' in order to be integral. For instance, if we have a
2890 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
2891 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
2892 * the unknown i. The function returns the imposed stride in a parameter field.
2893 * - domain is the set of constraint we have to consider,
2894 * - strided_level is the column number of the unknown for which a stride have
2896 * - looking_level is the column number of the unknown that impose a stride to
2897 * the first unknown.
2898 * - stride is the stride that is returned back as a function parameter.
2899 * - offset is the value of the constant c if the condition is of the shape
2900 * (i + c)%s = 0, s being the stride.
2902 * - June 28th 2003: first version.
2903 * - July 14th 2003: can now look for multiple striding constraints and returns
2904 * the GCD of the strides and the common offset.
2905 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
2909 cloog_domain_stride (CloogDomain
*domain
, int strided_level
, int nb_par
, Value
*stride
, Value
*offset
)
2912 int n_col
, n_row
, rank
;
2916 polyhedron p
= cloog_domain_polyhedron (domain
);
2917 int dimension
= cloog_domain_dim (domain
);
2918 int nbeq
= cloog_domain_nbeq (domain
);
2920 /* Look at all equalities involving strided_level and the inner
2921 * iterators. We can ignore the outer iterators and the parameters
2922 * here because the lower bound on strided_level is assumed to
2925 n_col
= (1 + dimension
- nb_par
) - strided_level
;
2926 for (i
= 0, n_row
= 0; i
< nbeq
; i
++)
2927 if (cloog_first_non_zero
2928 (p
->Constraint
[i
] + strided_level
, n_col
) != -1)
2931 M
= cloog_matrix_alloc (n_row
+ 1, n_col
+ 1);
2932 for (i
= 0, n_row
= 0; i
< nbeq
; i
++)
2934 if (cloog_first_non_zero
2935 (p
->Constraint
[i
] + strided_level
, n_col
) == -1)
2937 cloog_vector_copy (p
->Constraint
[i
] + strided_level
,
2938 M
->p
[n_row
], n_col
);
2939 value_assign (M
->p
[n_row
][n_col
],
2940 p
->Constraint
[i
][1 + dimension
]);
2943 value_set_si (M
->p
[n_row
][n_col
], 1);
2945 /* Then look at the general solution to the above equalities. */
2946 rank
= cloog_solve_diophantine (M
, &U
, &V
);
2947 cloog_matrix_free (M
);
2951 /* There is no solution, so the body of this loop will
2952 * never execute. We just leave the constraints alone here so
2953 * that they will ensure the body will not be executed.
2954 * We should probably propagate this information up so that
2955 * the loop can be removed entirely.
2957 value_set_si (*offset
, 0);
2958 value_set_si (*stride
, 1);
2962 /* Compute the gcd of the coefficients defining strided_level. */
2963 cloog_vector_gcd (U
->p
[0], U
->NbColumns
, stride
);
2964 value_oppose (*offset
, V
->p
[0]);
2965 value_pmodulus (*offset
, *offset
, *stride
);
2968 cloog_matrix_free (U
);
2975 * cloog_domain_integral_lowerbound function:
2976 * This function returns 1 if the lower bound of an iterator (such as its
2977 * column rank in the constraint set 'domain' is 'level') is integral,
2978 * 0 otherwise. If the lower bound is actually integral, the function fills
2979 * the 'lower' field with the lower bound value.
2980 * - June 29th 2003: first version.
2981 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
2985 cloog_domain_integral_lowerbound (CloogDomain
*domain
, int level
, Value
*lower
)
2987 int i
, first_lower
= 1, dimension
, lower_constraint
= -1, nbc
;
2988 Value iterator
, constant
, tmp
;
2989 polyhedron p
= cloog_domain_polyhedron (domain
);
2990 dimension
= cloog_domain_dim (domain
);
2991 nbc
= cloog_domain_nbconstraints (domain
);
2993 /* We want one and only one lower bound (e.g. no equality, no maximum
2996 for (i
= 0; i
< nbc
; i
++)
2997 if (value_zero_p (p
->Constraint
[i
][0])
2998 && value_notzero_p (p
->Constraint
[i
][level
]))
3001 for (i
= 0; i
< nbc
; i
++)
3002 if (value_pos_p (p
->Constraint
[i
][level
]))
3007 lower_constraint
= i
;
3016 /* We want an integral lower bound: no other non-zero entry except the
3017 * iterator coefficient and the constant.
3019 for (i
= 1; i
< level
; i
++)
3021 (p
->Constraint
[lower_constraint
][i
]))
3024 for (i
= level
+ 1; i
<= dimension
; i
++)
3026 (p
->Constraint
[lower_constraint
][i
]))
3031 value_init_c (iterator
);
3032 value_init_c (constant
);
3035 /* If all is passed, then find the lower bound and return 1. */
3036 value_assign (iterator
,
3037 p
->Constraint
[lower_constraint
][level
]);
3038 value_oppose (constant
,
3039 p
->Constraint
[lower_constraint
][dimension
+ 1]);
3041 value_modulus (tmp
, constant
, iterator
);
3042 value_division (*lower
, constant
, iterator
);
3044 if (!(value_zero_p (tmp
) || value_neg_p (constant
)))
3045 value_increment (*lower
, *lower
);
3047 value_clear_c (iterator
);
3048 value_clear_c (constant
);
3049 value_clear_c (tmp
);
3055 * cloog_domain_lowerbound_update function:
3056 * This function updates the integral lower bound of an iterator (such as its
3057 * column rank in the constraint set 'domain' is 'level') into 'lower'.
3058 * - Jun 29th 2003: first version.
3059 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
3063 cloog_domain_lowerbound_update (CloogDomain
*domain
, int level
, Value lower
)
3066 int nbc
= cloog_domain_nbconstraints (domain
);
3067 int dim
= cloog_domain_dim (domain
);
3068 polyhedron p
= cloog_domain_polyhedron (domain
);
3070 /* There is only one lower bound, the first one is the good one. */
3071 for (i
= 0; i
< nbc
; i
++)
3072 if (value_pos_p (p
->Constraint
[i
][level
]))
3074 value_set_si (p
->Constraint
[i
][level
], 1);
3075 value_oppose (p
->Constraint
[i
][dim
+ 1], lower
);
3082 * cloog_domain_lazy_equal function:
3083 * This function returns 1 if the domains given as input are the same, 0 if it
3084 * is unable to decide. This function makes an entry-to-entry comparison between
3085 * the constraint systems, if all the entries are the same, the domains are
3086 * obviously the same and it returns 1, at the first difference, it returns 0.
3087 * This is a very fast way to verify this property. It has been shown (with the
3088 * CLooG benchmarks) that operations on equal domains are 17% of all the
3089 * polyhedral computations. For 75% of the actually identical domains, this
3090 * function answer that they are the same and allow to give immediately the
3091 * trivial solution instead of calling the heavy general functions of PolyLib.
3092 * - August 22th 2003: first version.
3093 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
3097 cloog_domain_lazy_equal (CloogDomain
* d1
, CloogDomain
* d2
)
3100 polyhedra_union u1
= cloog_domain_upol (d1
);
3101 polyhedra_union u2
= cloog_domain_upol (d2
);
3105 if ((cloog_upol_nbc (u1
) != cloog_upol_nbc (u2
)) ||
3106 (cloog_upol_dim (u1
) != cloog_upol_dim (u2
)))
3109 for (i
= 0; i
< (int) cloog_upol_nbc (u1
); i
++)
3110 for (j
= 0; j
< (int) cloog_upol_dim (u1
) + 2; j
++)
3111 if (value_ne (cloog_upol_polyhedron (u1
)->Constraint
[i
][j
],
3112 cloog_upol_polyhedron (u2
)->Constraint
[i
][j
]))
3115 u1
= cloog_upol_next (u1
);
3116 u2
= cloog_upol_next (u2
);
3127 * cloog_domain_lazy_block function:
3128 * This function returns 1 if the two domains d1 and d2 given as input are the
3129 * same (possibly except for a dimension equal to a constant where we accept
3130 * a difference of 1) AND if we are sure that there are no other domain in
3131 * the code generation problem that may put integral points between those of
3132 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
3133 * safely consider the two domains as only one with two statements (a block) ?".
3134 * This function is lazy: it asks for very standard scattering representation
3135 * (only one constraint per dimension which is an equality, and the constraints
3136 * are ordered per dimension depth: the left hand side of the constraint matrix
3137 * is the identity) and will answer NO at the very first problem.
3138 * - d1 and d2 are the two domains to check for blocking,
3139 * - scattering is the linked list of all domains,
3140 * - scattdims is the total number of scattering dimentions.
3142 * - April 30th 2005: beginning
3143 * - June 9th 2005: first working version.
3144 * - June 10th 2005: debugging.
3145 * - June 21rd 2005: Adaptation for GMP.
3146 * - October 16th 2005: (debug) some false blocks have been removed.
3149 cloog_domain_lazy_block (CloogDomain
*d1
, CloogDomain
*d2
, CloogDomainList
*scattering
, int scattdims
)
3151 int i
, j
, difference
= 0, different_constraint
= 0, nbc
;
3153 Value date1
, date2
, date3
, temp
;
3156 /* Some basic checks: we only accept convex domains, with same constraint
3157 * and dimension numbers.
3159 if (!cloog_domain_isconvex (d1
) || !cloog_domain_isconvex (d2
) ||
3160 (cloog_domain_nbconstraints (d1
) != cloog_domain_nbconstraints (d2
)) ||
3161 (cloog_domain_dim (d1
) != cloog_domain_dim (d2
)))
3164 p1
= cloog_domain_polyhedron (d1
);
3165 p2
= cloog_domain_polyhedron (d2
);
3166 nbc
= cloog_domain_nbconstraints (d1
);
3167 dim1
= cloog_domain_dim (d1
);
3168 dim2
= cloog_domain_dim (d2
);
3170 /* There should be only one difference between the two domains, it
3171 * has to be at the constant level and the difference must be of +1,
3172 * moreover, after the difference all domain coefficient has to be 0.
3173 * The matrix shape is:
3175 * |===========|=====|<- 0 line
3176 * |===========|=====|
3177 * |===========|====?|<- different_constraint line (found here)
3178 * |===========|0000=|
3179 * |===========|0000=|<- pX->NbConstraints line
3182 * | | (pX->Dimension + 2) column
3183 * | scattdims column
3187 value_init_c (temp
);
3188 for (i
= 0; i
< nbc
; i
++)
3190 if (difference
== 0)
3191 { /* All elements except scalar must be equal. */
3192 for (j
= 0; j
< dim1
+ 1; j
++)
3193 if (value_ne (p1
->Constraint
[i
][j
],
3194 p2
->Constraint
[i
][j
]))
3196 value_clear_c (temp
);
3199 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
3200 if (value_ne (p1
->Constraint
[i
][j
],
3201 p2
->Constraint
[i
][j
]))
3203 value_increment (temp
, p2
->Constraint
[i
][j
]);
3204 if (value_ne (p1
->Constraint
[i
][j
], temp
))
3206 value_clear_c (temp
);
3212 different_constraint
= i
;
3217 { /* Scattering coefficients must be equal. */
3218 for (j
= 0; j
< (scattdims
+ 1); j
++)
3219 if (value_ne (p1
->Constraint
[i
][j
],
3220 p2
->Constraint
[i
][j
]))
3222 value_clear_c (temp
);
3226 /* Domain coefficients must be 0. */
3227 for (; j
< dim1
+ 1; j
++)
3228 if (value_notzero_p (p1
->Constraint
[i
][j
])
3229 || value_notzero_p (p2
->Constraint
[i
][j
]))
3231 value_clear_c (temp
);
3235 /* Scalar must be equal. */
3236 if (value_ne (p1
->Constraint
[i
][j
],
3237 p2
->Constraint
[i
][j
]))
3239 value_clear_c (temp
);
3244 value_clear_c (temp
);
3246 /* If the domains are exactly the same, this is a block. */
3247 if (difference
== 0)
3250 /* Now a basic check that the constraint with the difference is an
3251 * equality of a dimension with a constant.
3253 for (i
= 0; i
<= different_constraint
; i
++)
3254 if (value_notzero_p (p1
->Constraint
[different_constraint
][i
]))
3257 if (value_notone_p (p1
->Constraint
[different_constraint
][different_constraint
+ 1]))
3260 for (i
= different_constraint
+ 2; i
< dim1
+ 1; i
++)
3261 if (value_notzero_p (p1
->Constraint
[different_constraint
][i
]))
3264 /* For the moment, d1 and d2 are a block candidate. There remains to check
3265 * that there is no other domain that may put an integral point between
3266 * them. In our lazy test we ensure this property by verifying that the
3267 * constraint matrices have a very strict shape: let us consider that the
3268 * dimension with the difference is d. Then the first d dimensions are
3269 * defined in their depth order using equalities (thus the first column begins
3270 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
3271 * the remaining simensions). If a domain can put integral points between the
3272 * domains of the block candidate, this means that the other entries on the
3273 * first d constraints are equal to those of d1 or d2. Thus we are looking for
3274 * such a constraint system, if it exists d1 and d2 is considered to not be
3275 * a block, it is a bock otherwise.
3277 * 1. Only equalities (for the first different_constraint+1 lines).
3278 * | 2. Must be the identity.
3279 * | | 3. Must be zero.
3280 * | | | 4. Elements are equal, the last one is either date1 or 2.
3283 * |0|100|00000|=====|<- 0 line
3284 * |0|010|00000|=====|
3285 * |0|001|00000|====?|<- different_constraint line
3286 * |*|***|*****|*****|
3287 * |*|***|*****|*****|<- pX->NbConstraints line
3290 * | | | (pX->Dimension + 2) column
3291 * | | scattdims column
3292 * | different_constraint+1 column
3296 /* Step 1 and 2. This is only necessary to check one domain because
3297 * we checked that they are equal on this part before.
3299 for (i
= 0; i
<= different_constraint
; i
++)
3301 for (j
= 0; j
< i
+ 1; j
++)
3302 if (value_notzero_p (p1
->Constraint
[i
][j
]))
3305 if (value_notone_p (p1
->Constraint
[i
][i
+ 1]))
3308 for (j
= i
+ 2; j
<= different_constraint
+ 1; j
++)
3309 if (value_notzero_p (p1
->Constraint
[i
][j
]))
3314 for (i
= 0; i
<= different_constraint
; i
++)
3315 for (j
= different_constraint
+ 2; j
<= scattdims
; j
++)
3316 if (value_notzero_p (p1
->Constraint
[i
][j
]))
3319 value_init_c (date1
);
3320 value_init_c (date2
);
3321 value_init_c (date3
);
3323 /* Now we have to check that the two different dates are unique. */
3324 value_assign (date1
, p1
->Constraint
[different_constraint
][dim1
+ 1]);
3325 value_assign (date2
, p2
->Constraint
[different_constraint
][dim2
+ 1]);
3327 /* Step 4. We check all domains except d1 and d2 and we look for at least
3328 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
3330 while (scattering
!= NULL
)
3332 if ((cloog_domain (scattering
) != d1
)
3333 && (cloog_domain (scattering
) != d2
))
3335 CloogDomain
*d3
= cloog_domain (scattering
);
3336 polyhedron p3
= cloog_domain_polyhedron (d3
);
3337 int dim3
= cloog_domain_dim (d3
);
3339 value_assign (date3
,
3340 p3
->Constraint
[different_constraint
][dim3
+ 1]);
3343 if (value_ne (date3
, date2
) && value_ne (date3
, date1
))
3346 for (i
= 0; (i
< different_constraint
) && (!difference
); i
++)
3347 for (j
= 0; (j
< dim3
+ 2) && !difference
; j
++)
3349 (p1
->Constraint
[i
][j
],
3350 p3
->Constraint
[i
][j
]))
3353 for (j
= 0; (j
< dim3
+ 1) && !difference
; j
++)
3355 (p1
->Constraint
[different_constraint
][j
],
3356 p3
->Constraint
[different_constraint
][j
]))
3361 value_clear_c (date1
);
3362 value_clear_c (date2
);
3363 value_clear_c (date3
);
3368 scattering
= cloog_next_domain (scattering
);
3371 value_clear_c (date1
);
3372 value_clear_c (date2
);
3373 value_clear_c (date3
);
3379 * cloog_domain_lazy_disjoint function:
3380 * This function returns 1 if the domains given as input are disjoint, 0 if it
3381 * is unable to decide. This function finds the unknown with fixed values in
3382 * both domains (on a given constraint, their column entry is not zero and
3383 * only the constant coefficient can be different from zero) and verify that
3384 * their values are the same. If not, the domains are obviously disjoint and
3385 * it returns 1, if there is not such case it returns 0. This is a very fast
3386 * way to verify this property. It has been shown (with the CLooG benchmarks)
3387 * that operations on disjoint domains are 36% of all the polyhedral
3388 * computations. For 94% of the actually identical domains, this
3389 * function answer that they are disjoint and allow to give immediately the
3390 * trivial solution instead of calling the heavy general functions of PolyLib.
3391 * - August 22th 2003: first version.
3392 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
3396 cloog_domain_lazy_disjoint (CloogDomain
* d1
, CloogDomain
* d2
)
3398 int i1
, j1
, i2
, j2
, scat_dim
, nbc1
, nbc2
;
3403 if (!cloog_domain_isconvex (d1
) || !cloog_domain_isconvex (d2
))
3406 p1
= cloog_domain_polyhedron (d1
);
3407 p2
= cloog_domain_polyhedron (d2
);
3408 nbc1
= cloog_domain_nbconstraints (d1
);
3409 nbc2
= cloog_domain_nbconstraints (d2
);
3410 dim1
= cloog_domain_dim (d1
);
3411 dim2
= cloog_domain_dim (d2
);
3412 value_init_c (scat_val
);
3414 for (i1
= 0; i1
< nbc1
; i1
++)
3416 if (value_notzero_p (p1
->Constraint
[i1
][0]))
3420 while (value_zero_p (p1
->Constraint
[i1
][scat_dim
]) &&
3424 if (value_notone_p (p1
->Constraint
[i1
][scat_dim
]))
3428 for (j1
= scat_dim
+ 1; j1
<= dim1
; j1
++)
3429 if (value_notzero_p (p1
->Constraint
[i1
][j1
]))
3435 value_assign (scat_val
,
3436 p1
->Constraint
[i1
][dim1
+ 1]);
3438 for (i2
= 0; i2
< nbc2
; i2
++)
3440 for (j2
= 0; j2
< scat_dim
; j2
++)
3441 if (value_notzero_p (p2
->Constraint
[i2
][j2
]))
3444 if ((j2
!= scat_dim
)
3446 value_notone_p (p2
->Constraint
[i2
][scat_dim
]))
3449 for (j2
= scat_dim
+ 1; j2
< dim2
; j2
++)
3450 if (value_notzero_p (p2
->Constraint
[i2
][j2
]))
3457 (p2
->Constraint
[i2
][dim2
+ 1], scat_val
))
3459 value_clear_c (scat_val
);
3466 value_clear_c (scat_val
);
3472 * cloog_domain_list_lazy_same function:
3473 * This function returns 1 if two domains in the list are the same, 0 if it
3474 * is unable to decide.
3475 * - February 9th 2004: first version.
3478 cloog_domain_list_lazy_same (CloogDomainList
* list
)
3479 { /*int i=1, j=1 ; */
3480 CloogDomainList
*current
, *next
;
3483 while (current
!= NULL
)
3485 next
= cloog_next_domain (current
);
3487 while (next
!= NULL
)
3489 if (cloog_domain_lazy_equal (cloog_domain (current
),
3490 cloog_domain (next
)))
3491 { /*printf("Same domains: %d and %d\n",i,j) ; */
3495 next
= cloog_next_domain (next
);
3498 current
= cloog_next_domain (current
);
3505 * cloog_domain_cut_first function:
3506 * this function returns a CloogDomain structure with everything except the
3507 * first part of the polyhedra union of the input domain as domain. After a call
3508 * to this function, there remains in the CloogDomain structure provided as
3509 * input only the first part of the original polyhedra union.
3510 * - April 20th 2005: first version, extracted from different part of loop.c.
3513 cloog_domain_cut_first (CloogDomain
* domain
)
3517 if (domain
&& cloog_domain_polyhedron (domain
))
3519 if (!cloog_upol_next (cloog_domain_upol (domain
)))
3522 rest
= cloog_new_domain (cloog_upol_next (cloog_domain_upol (domain
)));
3523 cloog_upol_set_next (cloog_domain_upol (domain
), NULL
);
3528 return cloog_check_domain (rest
);
3533 * cloog_domain_lazy_isscalar function:
3534 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
3535 * is scalar, this means that the only constraint on this dimension must have
3536 * the shape "x.dimension + scalar = 0" with x an integral variable. This
3537 * function is lazy since we only accept x=1 (further calculations are easier
3539 * - June 14th 2005: first version.
3540 * - June 21rd 2005: Adaptation for GMP.
3543 cloog_domain_lazy_isscalar (CloogDomain
* domain
, int dimension
)
3546 polyhedron p
= cloog_domain_polyhedron (domain
);
3547 int nbc
= cloog_domain_nbconstraints (domain
);
3548 int dim
= cloog_domain_dim (domain
);
3550 /* For each constraint... */
3551 for (i
= 0; i
< nbc
; i
++)
3552 { /* ...if it is concerned by the potentially scalar dimension... */
3554 (p
->Constraint
[i
][dimension
+ 1]))
3555 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
3556 for (j
= 0; j
<= dimension
; j
++)
3557 if (value_notzero_p (p
->Constraint
[i
][j
]))
3561 (p
->Constraint
[i
][dimension
+ 1]))
3564 for (j
= dimension
+ 2; j
< dim
+ 1; j
++)
3565 if (value_notzero_p (p
->Constraint
[i
][j
]))
3575 * cloog_domain_scalar function:
3576 * when we call this function, we know that "dimension" is a scalar dimension,
3577 * this function finds the scalar value in "domain" and returns it in "value".
3578 * - June 30th 2005: first version.
3581 cloog_domain_scalar (CloogDomain
* domain
, int dimension
, Value
* value
)
3584 polyhedron p
= cloog_domain_polyhedron (domain
);
3585 int nbc
= cloog_domain_nbconstraints (domain
);
3586 int dim
= cloog_domain_dim (domain
);
3588 /* For each constraint... */
3589 for (i
= 0; i
< nbc
; i
++)
3590 { /* ...if it is the equality defining the scalar dimension... */
3592 (p
->Constraint
[i
][dimension
+ 1])
3593 && value_zero_p (p
->Constraint
[i
][0]))
3594 { /* ...Then send the scalar value. */
3595 value_assign (*value
, p
->Constraint
[i
][dim
+ 1]);
3596 value_oppose (*value
, *value
);
3601 /* We should have found a scalar value: if not, there is an error. */
3602 fprintf (stderr
, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
3609 * cloog_domain_erase_dimension function:
3610 * this function returns a CloogDomain structure builds from 'domain' where
3611 * we removed the dimension 'dimension' and every constraint considering this
3612 * dimension. This is not a projection ! Every data concerning the
3613 * considered dimension is simply erased.
3614 * - June 14th 2005: first version.
3615 * - June 21rd 2005: Adaptation for GMP.
3618 cloog_domain_erase_dimension (CloogDomain
* domain
, int dimension
)
3620 int i
, j
, mi
, nb_dim
, nbc
;
3621 CloogMatrix
*matrix
;
3622 CloogDomain
*erased
;
3623 polyhedron p
= cloog_domain_polyhedron (domain
);
3625 nb_dim
= cloog_domain_dim (domain
);
3626 nbc
= cloog_domain_nbconstraints (domain
);
3628 /* The matrix is one column less and at least one constraint less. */
3629 matrix
= cloog_matrix_alloc (nbc
- 1, nb_dim
+ 1);
3631 /* mi is the constraint counter for the matrix. */
3633 for (i
= 0; i
< nbc
; i
++)
3634 if (value_zero_p (p
->Constraint
[i
][dimension
+ 1]))
3636 for (j
= 0; j
<= dimension
; j
++)
3637 value_assign (matrix
->p
[mi
][j
],
3638 p
->Constraint
[i
][j
]);
3640 for (j
= dimension
+ 2; j
< nb_dim
+ 2; j
++)
3641 value_assign (matrix
->p
[mi
][j
- 1],
3642 p
->Constraint
[i
][j
]);
3647 erased
= cloog_domain_matrix2domain (matrix
);
3648 cloog_matrix_free (matrix
);
3650 return cloog_check_domain (erased
);
3653 /* Number of polyhedra inside the union of disjoint polyhedra. */
3656 cloog_domain_nb_polyhedra (CloogDomain
* domain
)
3659 polyhedra_union upol
= cloog_domain_upol (domain
);
3664 upol
= cloog_upol_next (upol
);
3671 cloog_domain_print_polyhedra (FILE * foo
, CloogDomain
* domain
)
3673 polyhedra_union upol
= cloog_domain_upol (domain
);
3675 while (upol
!= NULL
)
3677 CloogMatrix
*matrix
= cloog_upol_domain2matrix (upol
);
3678 cloog_matrix_print (foo
, matrix
);
3679 cloog_matrix_free (matrix
);
3680 upol
= cloog_upol_next (upol
);
3685 debug_cloog_domain (CloogDomain
*domain
)
3687 cloog_domain_print_polyhedra (stderr
, domain
);
3691 debug_cloog_matrix (CloogMatrix
*m
)
3693 cloog_matrix_print (stderr
, m
);
3697 debug_value (Value v
)
3699 value_print (stderr
, VALUE_FMT
, v
);
3703 debug_values (Value
*p
, int length
)
3706 for (i
= 0; i
< length
; i
++)
3710 polyhedra_union
cloog_new_upol (polyhedron p
)
3712 polyhedra_union ppl
=
3713 (polyhedra_union
) malloc (sizeof (struct polyhedra_union
));
3714 ppl
->_polyhedron
= p
;
3719 Vector
*Vector_Alloc (unsigned length
)
3722 Vector
*vector
= (Vector
*) malloc (sizeof (Vector
));
3724 vector
->Size
= length
;
3725 vector
->p
= (Value
*) malloc (length
* sizeof (Value
));
3727 for (i
= 0; i
< length
; i
++)
3728 value_init (vector
->p
[i
]);
3733 polyhedron
cloog_new_pol (int dim
, int nrows
)
3736 polyhedron res
= (polyhedron
) malloc (sizeof (struct polyhedron
));
3737 int ncolumns
= dim
+ 2;
3738 int n
= nrows
* ncolumns
;
3739 Value
*p
= (Value
*) malloc (n
* sizeof (Value
));
3741 res
->Dimension
= dim
;
3742 res
->NbConstraints
= nrows
;
3743 res
->Constraint
= (Value
**) malloc (nrows
* sizeof (Value
*));
3745 for (i
= 0; i
< n
; ++i
)
3748 for (i
= 0; i
< nrows
; i
++, p
+= ncolumns
)
3749 res
->Constraint
[i
] = p
;