Clean tsort, and some of the memory deallocation problems.
[cloog-ppl.git] / source / ppl / domain.c
blobe12a5f034dd5853722596ef54ed4245f8fd1510f
2 /**-------------------------------------------------------------------**
3 ** CLooG **
4 **-------------------------------------------------------------------**
5 ** domain.c **
6 **-------------------------------------------------------------------**
7 ** First version: october 28th 2001 **
8 **-------------------------------------------------------------------**/
11 /******************************************************************************
12 * CLooG : the Chunky Loop Generator (experimental) *
13 ******************************************************************************
14 * *
15 * Copyright (C) 2001-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 !
39 # include <stdlib.h>
40 # include <stdio.h>
41 # include <ctype.h>
42 # include "../../include/cloog/cloog.h"
43 #include "matrix.h"
45 static int cloog_check_polyhedral_ops = 1;
46 static int cloog_return_ppl_result = 0;
47 static int cloog_print_debug = 0;
49 static CloogDomain *
50 print_result (char *s, CloogDomain *d)
52 if (cloog_print_debug)
54 fprintf (stderr, "%s \n", s);
55 debug_cloog_domain (d);
57 return d;
60 /* Variables names for pretty printing. */
61 static char wild_name[200][40];
63 static inline const char*
64 variable_output_function (ppl_dimension_type var)
66 if (var < 40)
67 return wild_name[var + 1];
68 else
69 return 0;
72 static inline void
73 error_handler (enum ppl_enum_error_code code, const char* description)
75 fprintf (stderr, "PPL error code %d\n%s", code, description);
76 exit (1);
79 void
80 cloog_initialize (void)
82 sprintf (wild_name[0], "1");
83 sprintf (wild_name[1], "a");
84 sprintf (wild_name[2], "b");
85 sprintf (wild_name[3], "c");
86 sprintf (wild_name[4], "d");
87 sprintf (wild_name[5], "e");
88 sprintf (wild_name[6], "f");
89 sprintf (wild_name[7], "g");
90 sprintf (wild_name[8], "h");
91 sprintf (wild_name[9], "i");
92 sprintf (wild_name[10], "j");
93 sprintf (wild_name[11], "k");
94 sprintf (wild_name[12], "l");
95 sprintf (wild_name[13], "m");
96 sprintf (wild_name[14], "n");
97 sprintf (wild_name[15], "o");
98 sprintf (wild_name[16], "p");
99 sprintf (wild_name[17], "q");
100 sprintf (wild_name[18], "r");
101 sprintf (wild_name[19], "s");
102 sprintf (wild_name[20], "t");
103 sprintf (wild_name[21], "alpha");
104 sprintf (wild_name[22], "beta");
105 sprintf (wild_name[23], "gamma");
106 sprintf (wild_name[24], "delta");
107 sprintf (wild_name[25], "tau");
108 sprintf (wild_name[26], "sigma");
109 sprintf (wild_name[27], "chi");
110 sprintf (wild_name[28], "omega");
111 sprintf (wild_name[29], "pi");
112 sprintf (wild_name[30], "ni");
113 sprintf (wild_name[31], "Alpha");
114 sprintf (wild_name[32], "Beta");
115 sprintf (wild_name[33], "Gamma");
116 sprintf (wild_name[34], "Delta");
117 sprintf (wild_name[35], "Tau");
118 sprintf (wild_name[36], "Sigma");
119 sprintf (wild_name[37], "Chi");
120 sprintf (wild_name[38], "Omega");
121 sprintf (wild_name[39], "xxx");
123 if (ppl_initialize() < 0)
125 fprintf (stderr, "Cannot initialize the Parma Polyhedra Library.\n");
126 exit (1);
129 if (ppl_set_error_handler (error_handler) < 0)
131 fprintf (stderr, "Cannot install the custom error handler.\n");
132 exit (1);
135 if (ppl_io_set_variable_output_function (variable_output_function) < 0)
137 fprintf (stderr, "Cannot install the PPL custom variable output function. \n");
138 exit (1);
142 static inline Polyhedron *
143 u2p (ppl_polyhedra_union * upol)
145 Polyhedron *res = Polyhedron_Copy (cloog_upol_polyhedron (upol));
146 Polyhedron *p = res;
148 while (upol)
150 ppl_polyhedra_union *next = cloog_upol_next (upol);
151 Polyhedron *n;
153 if (next)
154 n = Polyhedron_Copy (cloog_upol_polyhedron (next));
155 else
156 n = NULL;
158 p->next = n;
159 p = n;
160 upol = next;
163 return res;
166 static inline Polyhedron *
167 d2p (CloogDomain * d)
169 return u2p (cloog_domain_upol (d));
173 static inline ppl_polyhedra_union *
174 p2u (Polyhedron * p)
176 ppl_polyhedra_union *u = cloog_new_upol (p);
177 ppl_polyhedra_union *res = u;
179 while (p)
181 Polyhedron *next = p->next;
182 ppl_polyhedra_union *n;
184 if (next)
185 n = cloog_new_upol (next);
186 else
187 n = NULL;
189 cloog_upol_set_next (u, n);
190 u = n;
191 p->next = NULL;
192 p = next;
195 return res;
199 * The maximal number of rays allowed to be allocated by PolyLib. In fact since
200 * version 5.20, PolyLib automatically tune the number of rays by multiplying
201 * by 2 this number each time the maximum is reached. For unknown reasons
202 * PolyLib makes a segmentation fault if this number is too small. If this
203 * number is too small, performances will be reduced, if it is too high, memory
204 * will be saturated. Note that the option "-rays X" set this number to X.
206 int MAX_RAYS = 50;
208 /* Unused in this backend. */
210 int cloog_domain_allocated = 0;
211 int cloog_domain_freed = 0;
212 int cloog_domain_max = 0;
214 /* The same for Value variables since in GMP mode they have to be freed. */
215 int cloog_value_allocated = 0;
216 int cloog_value_freed = 0;
217 int cloog_value_max = 0;
220 void
221 cloog_value_leak_up ()
223 cloog_value_allocated++;
224 if ((cloog_value_allocated - cloog_value_freed) > cloog_value_max)
225 cloog_value_max = cloog_value_allocated - cloog_value_freed;
229 void
230 cloog_value_leak_down ()
232 cloog_value_freed++;
235 static inline void
236 cloog_domain_polyhedron_set (CloogDomain * d, ppl_polyhedra_union * p)
238 d->_polyhedron = p;
241 static inline void
242 cloog_domain_set_references (CloogDomain * d, int i)
244 d->_references = i;
247 static CloogDomain *
248 cloog_new_domain (ppl_polyhedra_union *p)
250 CloogDomain *domain = (CloogDomain *) malloc (sizeof (CloogDomain));
251 domain->_polyhedron = p;
252 cloog_domain_set_references (domain, 1);
253 return domain;
256 static CloogDomain *
257 cloog_domain_alloc (Polyhedron *p)
259 return print_result ("cloog_domain_alloc", cloog_new_domain (p2u (p)));
262 void
263 debug_polyhedron (Polyhedron *p)
265 debug_cloog_domain (cloog_domain_alloc (p));
268 static inline CloogDomain *
269 cloog_check_domain_id (CloogDomain *dom)
271 return dom;
274 static inline CloogDomain *
275 cloog_check_domain (CloogDomain *dom)
277 if (!dom)
278 return dom;
280 /* FIXME: Remove this check. */
281 if (cloog_domain_polyhedron (dom)->next)
283 fprintf (stderr, "polyhedra of domains should be convex.\n");
284 exit (1);
287 return dom;
291 * cloog_domain_matrix2domain function:
292 * Given a matrix of constraints (matrix), this function constructs and returns
293 * the corresponding domain (i.e. the CloogDomain structure including the
294 * polyhedron with its double representation: constraint matrix and the set of
295 * rays).
297 static CloogDomain *
298 cloog_domain_matrix2domain (CloogMatrix * matrix)
300 return print_result ("cloog_domain_matrix2domain", cloog_check_domain (cloog_domain_alloc (Constraints2Polyhedron (matrix, MAX_RAYS))));
303 static inline CloogMatrix *
304 cloog_upol_domain2matrix (ppl_polyhedra_union * upol)
306 return Polyhedron2Constraints (cloog_upol_polyhedron (upol));
309 /* In the matrix representation an equality has a 0 in the first
310 column. When the value of the first column is 1, the row
311 represents an inequality. */
313 static inline int
314 cloog_matrix_row_is_eq_p (CloogMatrix *matrix, int row)
316 return value_zero_p (matrix->p[row][0]);
319 static ppl_Constraint_t
320 cloog_build_ppl_cstr (ppl_Linear_Expression_t expr, int ineq)
322 ppl_Constraint_t cstr;
324 switch (ineq)
326 case 0:
327 ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_EQUAL);
328 break;
330 case 1:
331 ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_GREATER_THAN_OR_EQUAL);
332 break;
334 default:
335 /* Should not happen. */
336 exit (1);
339 return cstr;
342 /* Translates to PPL row I from MATRIX. CST is the constant part that
343 is added to the constraint. When INEQ is 1 the constraint is
344 translated as an inequality, when INEQ is 0 it is translated as an
345 equality, when INEQ has another value, the first column of the
346 matrix is read for determining the type of the constraint. */
348 static ppl_Constraint_t
349 cloog_translate_constraint (CloogMatrix *matrix, int i, int cst, int ineq)
351 int j;
352 ppl_Constraint_t res;
353 ppl_Coefficient_t coef;
354 ppl_Linear_Expression_t expr;
355 ppl_dimension_type dim = matrix->NbColumns - 2;
356 Value val;
358 value_init (val);
359 ppl_new_Coefficient (&coef);
360 ppl_new_Linear_Expression_with_dimension (&expr, dim);
362 for (j = 1; j < matrix->NbColumns - 1; j++)
364 ppl_assign_Coefficient_from_mpz_t (coef, matrix->p[i][j]);
365 ppl_Linear_Expression_add_to_coefficient (expr, j - 1, coef);
368 value_set_si (val, cst);
369 value_addto (val, matrix->p[i][matrix->NbColumns - 1], val);
370 ppl_assign_Coefficient_from_mpz_t (coef, val);
371 ppl_Linear_Expression_add_to_inhomogeneous (expr, coef);
372 ppl_delete_Coefficient (coef);
374 if (ineq != 0 && ineq != 1)
375 ineq = !cloog_matrix_row_is_eq_p (matrix, i);
377 res = cloog_build_ppl_cstr (expr, ineq);
378 ppl_delete_Linear_Expression (expr);
379 return res;
382 /* Translates to PPL the opposite of row I from MATRIX. When INEQ is
383 1 the constraint is translated as an inequality, when INEQ is 0 it
384 is translated as an equality, when INEQ has another value, the
385 first column of the matrix is read for determining the type of the
386 constraint. */
388 static ppl_Constraint_t
389 cloog_translate_oppose_constraint (CloogMatrix *matrix, int i, int cst, int ineq)
391 int j;
392 ppl_Constraint_t res;
393 ppl_Coefficient_t coef;
394 ppl_Linear_Expression_t expr;
395 ppl_dimension_type dim = matrix->NbColumns - 2;
396 Value val, val1;
398 value_init (val);
399 value_init (val1);
400 ppl_new_Coefficient (&coef);
401 ppl_new_Linear_Expression_with_dimension (&expr, dim);
403 for (j = 1; j < matrix->NbColumns - 1; j++)
405 value_oppose (val, matrix->p[i][j]);
406 ppl_assign_Coefficient_from_mpz_t (coef, val);
407 ppl_Linear_Expression_add_to_coefficient (expr, j - 1, coef);
410 value_oppose (val, matrix->p[i][matrix->NbColumns - 1]);
411 value_set_si (val1, cst);
412 value_addto (val, val, val1);
413 ppl_assign_Coefficient_from_mpz_t (coef, val);
414 ppl_Linear_Expression_add_to_inhomogeneous (expr, coef);
415 ppl_delete_Coefficient (coef);
417 if (ineq != 0 && ineq != 1)
418 ineq = !cloog_matrix_row_is_eq_p (matrix, i);
420 res = cloog_build_ppl_cstr (expr, ineq);
421 ppl_delete_Linear_Expression (expr);
422 return res;
425 /* Adds to PPL the constraints from MATRIX. */
427 static void
428 cloog_translate_constraint_matrix_1 (ppl_Polyhedron_t ppl, CloogMatrix *matrix)
430 int i;
432 for (i = 0; i < matrix->NbRows; i++)
434 ppl_Constraint_t c = cloog_translate_constraint (matrix, i, 0, -1);
435 ppl_Polyhedron_add_constraint (ppl, c);
436 ppl_delete_Constraint (c);
440 static ppl_Polyhedron_t
441 cloog_translate_constraint_matrix (CloogMatrix *matrix)
443 ppl_Polyhedron_t ppl;
444 ppl_dimension_type dim = matrix->NbColumns - 2;
446 ppl_new_NNC_Polyhedron_from_dimension (&ppl, dim);
447 cloog_translate_constraint_matrix_1 (ppl, matrix);
448 return ppl;
451 static CloogDomain *
452 cloog_translate_ppl_polyhedron (ppl_Polyhedron_t pol)
454 CloogDomain *res;
455 CloogMatrix *matrix ;
456 ppl_dimension_type dim;
457 ppl_const_Constraint_System_t pcs;
458 ppl_Constraint_System_const_iterator_t cit, end;
459 int row;
461 ppl_Polyhedron_constraints (pol, &pcs);
462 ppl_new_Constraint_System_const_iterator (&cit);
463 ppl_new_Constraint_System_const_iterator (&end);
465 for (row = 0, ppl_Constraint_System_begin (pcs, cit), ppl_Constraint_System_end (pcs, end);
466 !ppl_Constraint_System_const_iterator_equal_test (cit, end);
467 ppl_Constraint_System_const_iterator_increment (cit), row++);
469 ppl_Polyhedron_space_dimension (pol, &dim);
470 matrix = cloog_matrix_alloc (row, dim + 2);
472 for (row = 0, ppl_Constraint_System_begin (pcs, cit), ppl_Constraint_System_end (pcs, end);
473 !ppl_Constraint_System_const_iterator_equal_test (cit, end);
474 ppl_Constraint_System_const_iterator_increment (cit), row++)
476 ppl_const_Constraint_t pc;
477 ppl_Coefficient_t coef;
478 ppl_dimension_type col;
479 Value val;
480 int neg;
482 value_init (val);
483 ppl_new_Coefficient (&coef);
484 ppl_Constraint_System_const_iterator_dereference (cit, &pc);
486 neg = (ppl_Constraint_type (pc) == PPL_CONSTRAINT_TYPE_LESS_THAN
487 || ppl_Constraint_type (pc) == PPL_CONSTRAINT_TYPE_LESS_THAN_OR_EQUAL) ? 1 : 0;
489 for (col = 0; col < dim; col++)
491 ppl_Constraint_coefficient (pc, col, coef);
492 ppl_Coefficient_to_mpz_t (coef, val);
494 if (neg)
495 value_oppose (val, val);
497 value_assign (matrix->p[row][col+1], val);
500 ppl_Constraint_inhomogeneous_term (pc, coef);
501 ppl_Coefficient_to_mpz_t (coef, val);
502 value_assign (matrix->p[row][dim + 1], val);
504 switch (ppl_Constraint_type (pc))
506 case PPL_CONSTRAINT_TYPE_EQUAL:
507 value_set_si (matrix->p[row][0], 0);
508 break;
510 case PPL_CONSTRAINT_TYPE_LESS_THAN:
511 case PPL_CONSTRAINT_TYPE_GREATER_THAN:
512 value_decrement (matrix->p[row][dim + 1], matrix->p[row][dim + 1]);
513 value_set_si (matrix->p[row][0], 1);
514 break;
516 case PPL_CONSTRAINT_TYPE_LESS_THAN_OR_EQUAL:
517 case PPL_CONSTRAINT_TYPE_GREATER_THAN_OR_EQUAL:
518 value_set_si (matrix->p[row][0], 1);
519 break;
521 default:
522 fprintf (stderr, "PPL_CONSTRAINT_TYPE_%d not implemented yet\n",
523 ppl_Constraint_type (pc));
524 exit (1);
528 res = cloog_domain_matrix2domain (matrix);
529 return print_result ("cloog_translate_ppl_polyhedron", cloog_check_domain (res));
532 void debug_poly (Polyhedron *p)
534 Polyhedron_Print (stderr, P_VALUE_FMT, p);
537 void
538 debug_ppl_poly (ppl_Polyhedron_t p)
540 debug_poly (cloog_domain_polyhedron (cloog_translate_ppl_polyhedron (p)));
543 static inline int
544 cloog_domain_references (CloogDomain * d)
546 return d->_references;
550 * cloog_domain_print function:
551 * This function prints the content of a CloogDomain structure (domain) into
552 * a file (foo, possibly stdout).
554 void
555 cloog_domain_print (FILE * foo, CloogDomain * domain)
557 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
559 while (upol)
561 Polyhedron_Print (foo, P_VALUE_FMT, cloog_upol_polyhedron (upol));
562 upol = cloog_upol_next (upol);
565 fprintf (foo, "Number of active references: %d\n",
566 cloog_domain_references (domain));
570 * cloog_domain_free function:
571 * This function frees the allocated memory for a CloogDomain structure
572 * (domain). It decrements the number of active references to this structure,
573 * if there are no more references on the structure, it frees it (with the
574 * included list of polyhedra).
576 void
577 cloog_domain_free (CloogDomain * domain)
579 if (domain)
581 cloog_domain_set_references (domain,
582 cloog_domain_references (domain) - 1);
584 if (cloog_domain_references (domain) == 0)
587 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
589 while (upol)
591 Polyhedron_Free (cloog_upol_polyhedron (upol));
592 upol = cloog_upol_next (upol);
595 free (domain);
602 * cloog_domain_copy function:
603 * This function returns a copy of a CloogDomain structure (domain). To save
604 * memory this is not a memory copy but we increment a counter of active
605 * references inside the structure, then return a pointer to that structure.
607 CloogDomain *
608 cloog_domain_copy (CloogDomain * domain)
610 cloog_domain_set_references (domain, cloog_domain_references (domain) + 1);
611 return print_result ("cloog_domain_copy", domain);
616 * cloog_domain_image function:
617 * This function returns a CloogDomain structure such that the included
618 * polyhedral domain is computed from the former one into another
619 * domain according to a given affine mapping function (mapping).
621 static CloogDomain *
622 cloog_domain_image (CloogDomain * domain, CloogMatrix * mapping)
624 Polyhedron *p = d2p (domain);
625 CloogDomain *res =
626 cloog_check_domain (cloog_domain_alloc
627 (DomainImage (p, mapping, MAX_RAYS)));
628 Polyhedron_Free (p);
629 return print_result ("cloog_domain_image", res);
634 * cloog_domain_preimage function:
635 * Given a polyhedral domain (polyhedron) inside a CloogDomain structure and a
636 * mapping function (mapping), this function returns a new CloogDomain structure
637 * with a polyhedral domain which when transformed by mapping function (mapping)
638 * gives (polyhedron).
640 static CloogDomain *
641 cloog_domain_preimage (CloogDomain * domain, CloogMatrix * mapping)
643 Polyhedron *p = d2p (domain);
644 CloogDomain *res =
645 cloog_check_domain (cloog_domain_alloc
646 (DomainPreimage (p, mapping, MAX_RAYS)));
647 Polyhedron_Free (p);
648 return print_result ("cloog_domain_preimage", res);
651 static CloogDomain *cloog_domain_difference_1 (CloogDomain *, CloogDomain *);
653 static CloogDomain *
654 cloog_check_domains (CloogDomain *ppl, CloogDomain *polylib)
656 /* Cannot use cloog_domain_lazy_equal (polylib, ppl) here as this
657 function is too dumb: it does not detect permutations of
658 constraints. */
659 if (!cloog_domain_isempty (cloog_domain_difference_1 (ppl, polylib))
660 || !cloog_domain_isempty (cloog_domain_difference_1 (polylib, ppl)))
662 fprintf (stderr, "different domains ( \n ppl (\n");
663 cloog_domain_print (stderr, ppl);
664 fprintf (stderr, ") \n polylib (\n");
665 cloog_domain_print (stderr, polylib);
666 fprintf (stderr, "))\n");
667 exit (1);
670 if (cloog_return_ppl_result)
671 return ppl;
672 else
673 return polylib;
677 * cloog_domain_convex function:
678 * Given a polyhedral domain (polyhedron), this function concatenates the lists
679 * of rays and lines of the two (or more) polyhedra in the domain into one
680 * combined list, and find the set of constraints which tightly bound all of
681 * those objects. It returns the corresponding polyhedron.
683 CloogDomain *
684 cloog_domain_convex (CloogDomain * domain)
686 Polyhedron *p = d2p (domain);
687 CloogDomain *res =
688 cloog_check_domain (cloog_domain_alloc
689 (DomainConvex (p, MAX_RAYS)));
690 Polyhedron_Free (p);
691 return print_result ("cloog_domain_convex", res);
694 static inline unsigned
695 cloog_upol_nbc (ppl_polyhedra_union * p)
697 return cloog_upol_polyhedron (p)->NbConstraints;
700 static inline int
701 cloog_domain_nbconstraints (CloogDomain * domain)
703 return cloog_domain_polyhedron (domain)->NbConstraints;
706 static inline unsigned
707 cloog_upol_nbeq (ppl_polyhedra_union * d)
709 return cloog_upol_polyhedron (d)->NbEq;
712 static inline unsigned
713 cloog_domain_nbeq (CloogDomain * d)
715 return cloog_domain_polyhedron (d)->NbEq;
718 static inline unsigned
719 cloog_upol_dim (ppl_polyhedra_union * p)
721 return cloog_upol_polyhedron (p)->Dimension;
725 cloog_domain_isconvex (CloogDomain * domain)
727 if (cloog_domain_polyhedron (domain))
728 return !cloog_upol_next (cloog_domain_upol (domain));
730 return 1;
733 unsigned
734 cloog_domain_dim (CloogDomain * d)
736 return cloog_domain_polyhedron (d)->Dimension;
740 * cloog_domain_simple_convex:
741 * Given a list (union) of polyhedra, this function returns a "simple"
742 * convex hull of this union. In particular, the constraints of the
743 * the returned polyhedron consist of (parametric) lower and upper
744 * bounds on individual variables and constraints that appear in the
745 * original polyhedra.
747 * nb_par is the number of parameters of the domain.
749 CloogDomain *
750 cloog_domain_simple_convex (CloogDomain * domain, int nb_par)
752 fprintf (stderr, "cloog_domain_simple_convex is not implemented yet.\n");
753 exit (1);
758 * cloog_domain_simplify function:
759 * Given two polyhedral domains (pol1) and (pol2) inside two CloogDomain
760 * structures, this function finds the largest domain set (or the smallest list
761 * of non-redundant constraints), that when intersected with polyhedral
762 * domain (pol2) equals (Pol1)intersect(Pol2). The output is a new CloogDomain
763 * structure with a polyhedral domain with the "redundant" constraints removed.
764 * NB: this function do not work as expected with unions of polyhedra...
766 CloogDomain *
767 cloog_domain_simplify (CloogDomain * dom1, CloogDomain * dom2)
769 CloogMatrix *M, *M2;
770 CloogDomain *dom;
771 Polyhedron *d2, *P = d2p (dom1);
772 int nbc = cloog_domain_nbconstraints (dom1);
774 /* DomainSimplify doesn't remove all redundant equalities,
775 * so we remove them here first in case both dom1 and dom2
776 * are single polyhedra (i.e., not unions of polyhedra).
778 if (cloog_domain_isconvex (dom1) && cloog_domain_isconvex (dom2)
779 && cloog_domain_nbeq (dom1) && cloog_domain_nbeq (dom2))
781 int i, row;
782 int rows = cloog_domain_nbeq (dom1) + cloog_domain_nbeq (dom2);
783 int cols = cloog_domain_dim (dom1) + 2;
784 int rank;
785 M = cloog_matrix_alloc (rows, cols);
786 M2 = cloog_matrix_alloc (nbc, cols);
787 Vector_Copy (cloog_domain_polyhedron (dom2)->Constraint[0],
788 M->p[0], cloog_domain_nbeq (dom2) * cols);
789 rank = cloog_domain_nbeq (dom2);
790 row = 0;
791 for (i = 0; i < cloog_domain_nbeq (dom1); ++i)
793 Vector_Copy (P->Constraint[i], M->p[rank], cols);
794 if (Gauss (M, rank + 1, cols - 1) > rank)
796 Vector_Copy (P->Constraint[i], M2->p[row++], cols);
797 rank++;
800 if (row < cloog_domain_nbeq (dom1))
802 Vector_Copy (P->Constraint[cloog_domain_nbeq (dom1)],
803 M2->p[row], (nbc - cloog_domain_nbeq (dom1)) * cols);
804 P = Constraints2Polyhedron (M2, MAX_RAYS);
806 cloog_matrix_free (M2);
807 cloog_matrix_free (M);
809 d2 = d2p (dom2);
810 dom = cloog_domain_alloc (DomainSimplify (P, d2, MAX_RAYS));
811 Polyhedron_Free (d2);
812 Polyhedron_Free (P);
813 return print_result ("cloog_domain_simplify", cloog_check_domain (dom));
816 static ppl_polyhedra_union *
817 cloog_upol_copy (ppl_polyhedra_union *p)
819 ppl_polyhedra_union *res = cloog_new_upol (Polyhedron_Copy (cloog_upol_polyhedron (p)));
820 ppl_polyhedra_union *upol = res;
822 while (cloog_upol_next (p))
824 cloog_upol_set_next (upol, cloog_new_upol (Polyhedron_Copy (cloog_upol_polyhedron (p))));
825 upol = cloog_upol_next (upol);
826 p = cloog_upol_next (p);
829 return res;
832 /* Adds to D1 the union of polyhedra from D2, with no checks of
833 redundancies between polyhedra. */
835 CloogDomain *
836 cloog_domain_add_domain (CloogDomain *d1, CloogDomain *d2)
838 ppl_polyhedra_union *upol;
840 if (!d1)
841 return d2;
843 if (!d2)
844 return d1;
846 upol = cloog_domain_upol (d1);
847 while (cloog_upol_next (upol))
848 upol = cloog_upol_next (upol);
850 cloog_upol_set_next (upol, cloog_domain_upol (d2));
851 return d1;
855 * cloog_domain_union function:
856 * This function returns a new CloogDomain structure including a polyhedral
857 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
858 * two CloogDomain structures.
860 CloogDomain *
861 cloog_domain_union (CloogDomain * dom1, CloogDomain * dom2)
863 CloogDomain *res;
864 ppl_polyhedra_union *head1, *head2, *tail1, *tail2;
865 ppl_polyhedra_union *d1, *d2;
867 if (!dom1)
868 return dom2;
870 if (!dom2)
871 return dom1;
873 if (cloog_domain_dim (dom1) != cloog_domain_dim (dom2))
875 fprintf (stderr, "cloog_domain_union should not be called on domains of different dimensions.\n");
876 exit (1);
879 head1 = NULL;
880 tail1 = NULL;
881 for (d1 = cloog_domain_upol (dom1); d1; d1 = cloog_upol_next (d1))
883 int found = 0;
884 ppl_Polyhedron_t ppl1 = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d1));
886 for (d2 = cloog_domain_upol (dom2); d2; d2 = cloog_upol_next (d2))
888 ppl_Polyhedron_t ppl2 = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d2));
890 if (ppl_Polyhedron_contains_Polyhedron (ppl2, ppl1))
892 found = 1;
893 break;
897 if (!found)
899 if (!tail1)
901 head1 = cloog_upol_copy (d1);
902 tail1 = head1;
904 else
906 cloog_upol_set_next (tail1, cloog_upol_copy (d1));
907 tail1 = cloog_upol_next (tail1);
912 head2 = NULL;
913 tail2 = NULL;
914 for (d2 = cloog_domain_upol (dom2); d2; d2 = cloog_upol_next (d2))
916 int found = 0;
917 ppl_Polyhedron_t ppl2 = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d2));
919 for (d1 = head1; d1; d1 = cloog_upol_next (d1))
921 ppl_Polyhedron_t ppl1 = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d1));
923 if (ppl_Polyhedron_contains_Polyhedron (ppl1, ppl2))
925 found = 1;
926 break;
930 if (!found)
932 if (!tail2)
934 head2 = cloog_upol_copy (d2);
935 tail2 = head2;
937 else
939 cloog_upol_set_next (tail2, cloog_upol_copy (d2));
940 tail2 = cloog_upol_next (tail2);
945 if (!head1)
946 res = cloog_new_domain (head2);
947 else
949 cloog_upol_set_next (tail1, head2);
950 res = cloog_new_domain (head1);
953 if (cloog_check_polyhedral_ops)
955 Polyhedron *p1 = d2p (dom1);
956 Polyhedron *p2 = d2p (dom2);
958 cloog_check_domains (res, cloog_domain_alloc (DomainUnion (p1, p2, MAX_RAYS)));
960 Polyhedron_Free (p1);
961 Polyhedron_Free (p2);
964 return print_result ("cloog_domain_union", cloog_check_domain (res));
968 * cloog_domain_intersection function:
969 * This function returns a new CloogDomain structure including a polyhedral
970 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
971 * inside two CloogDomain structures.
973 CloogDomain *
974 cloog_domain_intersection (CloogDomain * dom1, CloogDomain * dom2)
976 CloogDomain *res;
977 ppl_polyhedra_union *p1, *p2;
978 ppl_Polyhedron_t ppl1, ppl2;
980 res = cloog_domain_empty (cloog_domain_dim (dom1));
982 for (p1 = cloog_domain_upol (dom1); p1; p1 = cloog_upol_next (p1))
984 ppl1 = cloog_translate_constraint_matrix (Polyhedron2Constraints (cloog_upol_polyhedron (p1)));
986 for (p2 = cloog_domain_upol (dom2); p2; p2 = cloog_upol_next (p2))
988 ppl2 = cloog_translate_constraint_matrix (Polyhedron2Constraints (cloog_upol_polyhedron (p2)));
989 ppl_Polyhedron_intersection_assign (ppl2, ppl1);
991 res = cloog_domain_union (res, cloog_translate_ppl_polyhedron (ppl2));
995 if (cloog_check_polyhedral_ops)
997 Polyhedron *a1 = d2p (dom1);
998 Polyhedron *a2 = d2p (dom2);
1000 res = cloog_check_domains (res, cloog_domain_alloc (DomainIntersection (a1, a2, MAX_RAYS)));
1002 Polyhedron_Free (a1);
1003 Polyhedron_Free (a2);
1006 return print_result ("cloog_domain_intersection", res);
1011 * cloog_domain_difference function:
1012 * This function returns a new CloogDomain structure including a polyhedral
1013 * domain which is the difference of two polyhedral domains domain \ minus
1014 * inside two CloogDomain structures.
1015 * - November 8th 2001: first version.
1018 static CloogDomain *
1019 cloog_domain_difference_1 (CloogDomain * domain, CloogDomain * minus)
1021 if (cloog_domain_isempty (minus))
1022 return print_result ("cloog_domain_difference", cloog_domain_copy (domain));
1023 else
1025 Polyhedron *p1 = d2p (domain);
1026 Polyhedron *p2 = d2p (minus);
1027 CloogDomain *res = cloog_domain_alloc (DomainDifference (p1, p2, MAX_RAYS));
1028 Polyhedron_Free (p1);
1029 Polyhedron_Free (p2);
1030 return print_result ("cloog_domain_difference", res);
1034 /* Returns non-zero when the constraint I in MATRIX is the positivity
1035 constraint: "0 >= 0". */
1037 static int
1038 cloog_positivity_constraint_p (CloogMatrix *matrix, int i, int dim)
1040 int j;
1042 for (j = 1; j < dim; j++)
1043 if (value_notzero_p (matrix->p[i][j]))
1044 break;
1046 return (j == dim);
1049 /* Returns d1 minus d2. */
1051 CloogDomain *
1052 cloog_domain_difference (CloogDomain * d1, CloogDomain * d2)
1054 CloogDomain *res = NULL, *d = d1;
1055 ppl_polyhedra_union *p1, *p2;
1057 if (cloog_domain_isempty (d2))
1058 return print_result ("cloog_domain_difference", cloog_domain_copy (d1));
1060 for (p2 = cloog_domain_upol (d2); p2; p2 = cloog_upol_next (p2))
1062 CloogMatrix *matrix = cloog_upol_domain2matrix (p2);
1064 for (p1 = cloog_domain_upol (d); p1; p1 = cloog_upol_next (p1))
1066 int i;
1067 CloogMatrix *m1 = cloog_upol_domain2matrix (p1);
1069 for (i = 0; i < matrix->NbRows; i++)
1071 ppl_Polyhedron_t p3;
1072 ppl_Constraint_t cstr;
1074 /* Don't handle "0 >= 0". */
1075 if (cloog_positivity_constraint_p (matrix, i,
1076 cloog_domain_dim (d) + 1))
1077 continue;
1079 /* Add the constraint "-matrix[i] - 1 >= 0". */
1080 p3 = cloog_translate_constraint_matrix (m1);
1081 cstr = cloog_translate_oppose_constraint (matrix, i, -1, 1);
1082 ppl_Polyhedron_add_constraint_and_minimize (p3, cstr);
1083 ppl_delete_Constraint (cstr);
1084 res = cloog_domain_union (res, cloog_translate_ppl_polyhedron (p3));
1086 /* For an equality, add the constraint "matrix[i] - 1 >= 0". */
1087 if (cloog_matrix_row_is_eq_p (matrix, i))
1089 p3 = cloog_translate_constraint_matrix (m1);
1090 cstr = cloog_translate_constraint (matrix, i, -1, 1);
1091 ppl_Polyhedron_add_constraint_and_minimize (p3, cstr);
1092 ppl_delete_Constraint (cstr);
1093 res = cloog_domain_union (res, cloog_translate_ppl_polyhedron (p3));
1097 d = res;
1098 res = NULL;
1101 if (!d)
1102 res = cloog_domain_empty (cloog_domain_dim (d2));
1103 else
1104 res = d;
1106 if (cloog_check_polyhedral_ops)
1107 return print_result ("cloog_domain_difference", cloog_check_domains
1108 (res, cloog_domain_difference_1 (d1, d2)));
1110 return print_result ("cloog_domain_difference", res);
1115 * cloog_domain_addconstraints function :
1116 * This function adds source's polyhedron constraints to target polyhedron: for
1117 * each element of the polyhedron inside 'target' (i.e. element of the union
1118 * of polyhedra) it adds the constraints of the corresponding element in
1119 * 'source'.
1120 * - August 10th 2002: first version.
1121 * Nota bene for future : it is possible that source and target don't have the
1122 * same number of elements (try iftest2 without non-shared constraint
1123 * elimination in cloog_loop_separate !). This function is yet another part
1124 * of the DomainSimplify patching problem...
1126 static CloogDomain *
1127 cloog_domain_addconstraints_1 (domain_source, domain_target)
1128 CloogDomain *domain_source, *domain_target;
1130 unsigned nb_constraint;
1131 Value *constraints;
1132 ppl_polyhedra_union *source, *target, *new, *next, *last;
1134 source = cloog_domain_upol (domain_source);
1135 target = cloog_domain_upol (domain_target);
1137 constraints = cloog_upol_polyhedron (source)->p_Init;
1138 nb_constraint = cloog_upol_nbc (source);
1139 last = new = cloog_new_upol (AddConstraints (constraints, nb_constraint,
1140 u2p (target), MAX_RAYS));
1141 source = cloog_upol_next (source);
1142 next = cloog_upol_next (target);
1144 while (next)
1145 { /* BUG !!! This is actually a bug. I don't know yet how to cleanly avoid
1146 * the situation where source and target do not have the same number of
1147 * elements. So this 'if' is an awful trick, waiting for better.
1149 if (source)
1151 constraints = cloog_upol_polyhedron (source)->p_Init;
1152 nb_constraint = cloog_upol_nbc (source);
1153 source = cloog_upol_next (source);
1155 cloog_upol_set_next
1156 (last, cloog_new_upol (AddConstraints (constraints, nb_constraint,
1157 u2p (next), MAX_RAYS)));
1158 last = cloog_upol_next (last);
1159 next = cloog_upol_next (next);
1162 return print_result ("cloog_domain_addconstraints", cloog_check_domain (cloog_new_domain (new)));
1165 CloogDomain *
1166 cloog_domain_addconstraints (CloogDomain *domain_source, CloogDomain *domain_target)
1168 CloogDomain *res;
1169 ppl_Polyhedron_t ppl;
1170 ppl_polyhedra_union *source, *target, *last;
1171 int dim = cloog_domain_dim (domain_target);
1173 source = cloog_domain_upol (domain_source);
1174 target = cloog_domain_upol (domain_target);
1176 ppl_new_NNC_Polyhedron_from_dimension (&ppl, dim);
1177 cloog_translate_constraint_matrix_1 (ppl, cloog_upol_domain2matrix (target));
1178 cloog_translate_constraint_matrix_1 (ppl, cloog_upol_domain2matrix (source));
1179 res = cloog_translate_ppl_polyhedron (ppl);
1180 last = cloog_domain_upol (res);
1182 source = cloog_upol_next (source);
1183 target = cloog_upol_next (target);
1185 while (target)
1187 ppl_new_NNC_Polyhedron_from_dimension (&ppl, dim);
1188 cloog_translate_constraint_matrix_1 (ppl, cloog_upol_domain2matrix (target));
1190 if (source)
1192 cloog_translate_constraint_matrix_1 (ppl, cloog_upol_domain2matrix (source));
1193 source = cloog_upol_next (source);
1196 cloog_upol_set_next
1197 (last, cloog_domain_upol (cloog_translate_ppl_polyhedron (ppl)));
1199 last = cloog_upol_next (last);
1200 target = cloog_upol_next (target);
1203 if (cloog_check_polyhedral_ops)
1204 return print_result ("cloog_domain_addconstraints", cloog_check_domains
1205 (res, cloog_domain_addconstraints_1 (domain_source,
1206 domain_target)));
1208 return print_result ("cloog_domain_addconstraints", res);
1211 /* Compares P1 to P2: returns 0 when the polyhedra don't overlap,
1212 returns 1 when p1 >= p2, and returns -1 when p1 < p2. The ">"
1213 relation is the "contains" relation. */
1215 static int
1216 cloog_domain_polyhedron_compare (CloogMatrix *m1, CloogMatrix *m2, int level, int nb_par, int dimension)
1218 int i, j;
1219 ppl_Polyhedron_t q1, q2, q3, q4, q5, q;
1220 ppl_Polyhedron_t p1, p2;
1222 p1 = cloog_translate_constraint_matrix (m1);
1223 if (ppl_Polyhedron_is_empty (p1))
1224 return 0;
1226 p2 = cloog_translate_constraint_matrix (m2);
1227 if (ppl_Polyhedron_is_empty (p2))
1228 return 0;
1230 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q1, p1);
1231 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q2, p2);
1233 for (i = level; i < dimension - nb_par + 1; i++)
1235 Value val;
1236 ppl_Coefficient_t d;
1237 ppl_Linear_Expression_t expr;
1238 ppl_Generator_t g;
1240 value_init (val);
1241 value_set_si (val, 1);
1242 ppl_new_Coefficient_from_mpz_t (&d, val);
1243 ppl_new_Linear_Expression_with_dimension (&expr, dimension);
1244 ppl_Linear_Expression_add_to_coefficient (expr, i - 1, d);
1245 ppl_new_Generator (&g, expr, PPL_GENERATOR_TYPE_LINE, d);
1246 ppl_Polyhedron_add_generator (q1, g);
1247 ppl_Polyhedron_add_generator (q2, g);
1250 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q, q1);
1251 ppl_Polyhedron_intersection_assign (q, q2);
1253 if (ppl_Polyhedron_is_empty (q))
1254 return 0;
1256 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q1, p1);
1257 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q2, p2);
1259 ppl_Polyhedron_intersection_assign (q1, q);
1260 ppl_Polyhedron_intersection_assign (q2, q);
1262 m1 = cloog_upol_domain2matrix (cloog_domain_upol (cloog_translate_ppl_polyhedron (q1)));
1263 m2 = cloog_upol_domain2matrix (cloog_domain_upol (cloog_translate_ppl_polyhedron (q2)));
1265 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q4, q);
1266 for (i = 0; i < m1->NbRows; i++)
1267 if (value_one_p (m1->p[i][0])
1268 && value_pos_p (m1->p[i][level]))
1270 ppl_Constraint_t c = cloog_translate_constraint (m1, i, 0, 1);
1271 ppl_Polyhedron_add_constraint (q4, c);
1272 ppl_delete_Constraint (c);
1275 for (i = 0; i < m2->NbRows; i++)
1276 if (value_one_p (m2->p[i][0])
1277 && value_neg_p (m2->p[i][level]))
1279 ppl_Constraint_t c = cloog_translate_constraint (m2, i, 0, 1);
1280 ppl_Polyhedron_add_constraint (q4, c);
1281 ppl_delete_Constraint (c);
1284 if (ppl_Polyhedron_is_empty (q4))
1285 return 1;
1288 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q3, q);
1289 for (i = 0; i < m1->NbRows; i++)
1291 if (value_zero_p (m1->p[i][0]))
1293 if (value_zero_p (m1->p[i][level]))
1294 continue;
1296 else if (value_neg_p (m1->p[i][level]))
1298 ppl_Constraint_t c = cloog_translate_oppose_constraint (m1, i, 0, 1);
1299 ppl_Polyhedron_add_constraint (q3, c);
1300 ppl_delete_Constraint (c);
1303 else
1305 ppl_Constraint_t c = cloog_translate_constraint (m1, i, 0, 1);
1306 ppl_Polyhedron_add_constraint (q3, c);
1307 ppl_delete_Constraint (c);
1311 else if (value_neg_p (m1->p[i][level]))
1313 ppl_Constraint_t c = cloog_translate_oppose_constraint (m1, i, 0, 1);
1314 ppl_Polyhedron_add_constraint (q3, c);
1315 ppl_delete_Constraint (c);
1318 else
1319 continue;
1321 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q5, q3);
1322 for (j = 0; j < m2->NbRows; j++)
1324 if (value_zero_p (m2->p[j][0]))
1326 if (value_zero_p (m2->p[j][level]))
1327 continue;
1329 else if (value_pos_p (m2->p[j][level]))
1331 ppl_Constraint_t c = cloog_translate_oppose_constraint (m2, j, 0, 1);
1332 ppl_Polyhedron_add_constraint (q5, c);
1333 ppl_delete_Constraint (c);
1336 else
1338 ppl_Constraint_t c = cloog_translate_constraint (m2, j, 0, 1);
1339 ppl_Polyhedron_add_constraint (q5, c);
1340 ppl_delete_Constraint (c);
1344 else if (value_pos_p (m2->p[j][level]))
1346 ppl_Constraint_t c = cloog_translate_oppose_constraint (m2, j, 0, 1);
1347 ppl_Polyhedron_add_constraint (q5, c);
1348 ppl_delete_Constraint (c);
1351 else
1352 continue;
1354 if (!ppl_Polyhedron_is_empty (q5))
1355 return -1;
1357 /* Reinitialize Q5. */
1358 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q5, q3);
1361 /* Reinitialize Q3. */
1362 ppl_new_NNC_Polyhedron_from_NNC_Polyhedron (&q3, q);
1365 return 1;
1369 * cloog_domain_sort function:
1370 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
1371 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
1372 * (level) is the level to consider for partial ordering (nb_par) is the
1373 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
1374 * integers that contains a permutation specification after call in order to
1375 * apply the topological sorting.
1378 void
1379 cloog_domain_sort (CloogDomain **doms, unsigned nb_pols, unsigned level,
1380 unsigned nb_par, int *permut)
1382 int i, j;
1383 int dim = cloog_domain_dim (doms[0]);
1385 for (i = 0; i < nb_pols; i++)
1386 permut[i] = i + 1;
1388 /* Note that here we do a comparison per tuple of polyhedra.
1389 PolyLib does not do this, but instead it does fewer comparisons
1390 and with a complex reasoning they infer that it some comparisons
1391 are not useful. The result is that PolyLib has wrong permutations.
1393 FIXME: In the PolyLib backend, Cloog should use this algorithm
1394 instead of PolyhedronTSort, and cloog_domain_polyhedron_compare
1395 should be implemented with a simple call to PolyhedronLTQ: these
1396 two functions produce identical answers. */
1397 for (i = 0; i < nb_pols; i++)
1398 for (j = i + 1; j < nb_pols; j++)
1400 CloogMatrix *m1 = cloog_upol_domain2matrix (cloog_domain_upol (doms[i]));
1401 CloogMatrix *m2 = cloog_upol_domain2matrix (cloog_domain_upol (doms[j]));
1403 if (cloog_domain_polyhedron_compare (m1, m2, level, nb_par, dim) == 1)
1405 int v = permut[i];
1406 permut[i] = permut[j];
1407 permut[j] = v;
1413 * cloog_domain_empty function:
1414 * This function allocates the memory space for a CloogDomain structure and
1415 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
1416 * Then it returns a pointer to the allocated space.
1417 * - June 10th 2005: first version.
1419 CloogDomain *
1420 cloog_domain_empty (int dimension)
1422 return (cloog_domain_alloc (Empty_Polyhedron (dimension)));
1426 /******************************************************************************
1427 * Structure display function *
1428 ******************************************************************************/
1432 * cloog_domain_print_structure :
1433 * this function is a more human-friendly way to display the CloogDomain data
1434 * structure, it only shows the constraint system and includes an indentation
1435 * level (level) in order to work with others print_structure functions.
1436 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
1437 * - April 24th 2005: Initial version.
1438 * - May 26th 2005: Memory leak hunt.
1439 * - June 16th 2005: (Ced) Integration in domain.c.
1441 void
1442 cloog_domain_print_structure (FILE * file, CloogDomain * domain, int level)
1444 int i;
1445 CloogMatrix *matrix;
1447 /* Go to the right level. */
1448 for (i = 0; i < level; i++)
1449 fprintf (file, "|\t");
1451 if (domain != NULL)
1453 fprintf (file, "+-- CloogDomain\n");
1455 /* Print the matrix. */
1456 matrix = cloog_upol_domain2matrix (cloog_domain_upol (domain));
1457 cloog_matrix_print_structure (file, matrix, level);
1458 cloog_matrix_free (matrix);
1460 /* A blank line. */
1461 for (i = 0; i < level + 1; i++)
1462 fprintf (file, "|\t");
1463 fprintf (file, "\n");
1465 else
1466 fprintf (file, "+-- Null CloogDomain\n");
1472 * cloog_domain_list_print function:
1473 * This function prints the content of a CloogDomainList structure into a
1474 * file (foo, possibly stdout).
1475 * - November 6th 2001: first version.
1477 void
1478 cloog_domain_list_print (FILE * foo, CloogDomainList * list)
1480 while (list != NULL)
1482 cloog_domain_print (foo, cloog_domain (list));
1483 list = cloog_next_domain (list);
1488 /******************************************************************************
1489 * Memory deallocation function *
1490 ******************************************************************************/
1494 * cloog_domain_list_free function:
1495 * This function frees the allocated memory for a CloogDomainList structure.
1496 * - November 6th 2001: first version.
1498 void
1499 cloog_domain_list_free (CloogDomainList * list)
1501 CloogDomainList *temp;
1503 while (list != NULL)
1505 temp = cloog_next_domain (list);
1506 cloog_domain_free (cloog_domain (list));
1507 free (list);
1508 list = temp;
1513 /******************************************************************************
1514 * Reading function *
1515 ******************************************************************************/
1519 * cloog_domain_read function:
1520 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
1521 * posibly stdin) and returns a pointer to a polyhedron containing the read
1522 * information.
1523 * - October 18th 2001: first version.
1525 CloogDomain *
1526 cloog_domain_read (FILE * foo)
1528 CloogMatrix *matrix;
1529 CloogDomain *domain;
1531 matrix = cloog_matrix_read (foo);
1532 domain = cloog_domain_matrix2domain (matrix);
1533 cloog_matrix_free (matrix);
1535 return print_result ("cloog_domain_read", domain);
1540 * cloog_domain_union_read function:
1541 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
1542 * returns a pointer to a Polyhedron containing the read information.
1543 * - September 9th 2002: first version.
1544 * - October 29th 2005: (debug) removal of a leak counting "correction" that
1545 * was just false since ages.
1547 CloogDomain *
1548 cloog_domain_union_read (FILE * foo)
1550 int i, nb_components;
1551 char s[MAX_STRING];
1552 CloogDomain *domain, *temp, *old;
1554 /* domain reading: nb_components (constraint matrices). */
1555 while (fgets (s, MAX_STRING, foo) == 0);
1556 while ((*s == '#' || *s == '\n') || (sscanf (s, " %d", &nb_components) < 1))
1557 fgets (s, MAX_STRING, foo);
1559 if (nb_components > 0)
1560 { /* 1. first part of the polyhedra union, */
1561 domain = cloog_domain_read (foo);
1562 /* 2. and the nexts. */
1563 for (i = 1; i < nb_components; i++)
1564 { /* Leak counting is OK since next allocated domain is freed here. */
1565 temp = cloog_domain_read (foo);
1566 old = domain;
1567 domain = cloog_domain_union (temp, old);
1568 cloog_domain_free (temp);
1569 cloog_domain_free (old);
1571 return print_result ("cloog_domain_union_read", cloog_check_domain (domain));
1573 else
1574 return NULL;
1579 * cloog_domain_list_read function:
1580 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
1581 * returns a pointer to a CloogDomainList containing the read information.
1582 * - November 6th 2001: first version.
1584 CloogDomainList *
1585 cloog_domain_list_read (FILE * foo)
1587 int i, nb_pols;
1588 char s[MAX_STRING];
1589 CloogDomainList *list, *now, *next;
1592 /* We read first the number of polyhedra in the list. */
1593 while (fgets (s, MAX_STRING, foo) == 0);
1594 while ((*s == '#' || *s == '\n') || (sscanf (s, " %d", &nb_pols) < 1))
1595 fgets (s, MAX_STRING, foo);
1597 /* Then we read the polyhedra. */
1598 list = NULL;
1599 if (nb_pols > 0)
1601 list = (CloogDomainList *) malloc (sizeof (CloogDomainList));
1602 cloog_set_domain (list, cloog_domain_read (foo));
1603 cloog_set_next_domain (list, NULL);
1604 now = list;
1605 for (i = 1; i < nb_pols; i++)
1607 next = (CloogDomainList *) malloc (sizeof (CloogDomainList));
1608 cloog_set_domain (next, cloog_domain_read (foo));
1609 cloog_set_next_domain (next, NULL);
1610 cloog_set_next_domain (now, next);
1611 now = cloog_next_domain (now);
1614 return list;
1618 /******************************************************************************
1619 * Processing functions *
1620 ******************************************************************************/
1623 * cloog_domain_isempty function:
1624 * This function returns 1 if the polyhedron given as input is empty, 0
1625 * otherwise.
1626 * - October 28th 2001: first version.
1629 cloog_domain_isempty (CloogDomain * domain)
1631 if (cloog_domain_polyhedron (domain) == NULL)
1632 return 1;
1634 if (cloog_upol_next (cloog_domain_upol (domain)))
1635 return 0;
1637 return ((cloog_domain_dim (domain) < cloog_domain_nbeq (domain)) ? 1 : 0);
1641 * cloog_domain_project function:
1642 * From Quillere's LoopGen 0.4. This function returns the projection of
1643 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
1644 * pointer to the projected Polyhedron.
1645 * - nb_par is the number of parameters.
1647 * - October 27th 2001: first version.
1648 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1649 * CLooG 0.12.1).
1651 CloogDomain *
1652 cloog_domain_project_1 (CloogDomain * domain, int level, int nb_par)
1654 int row, column, nb_rows, nb_columns, difference;
1655 CloogDomain *projected_domain;
1656 CloogMatrix *matrix;
1658 nb_rows = level + nb_par + 1;
1659 nb_columns = cloog_domain_dim (domain) + 1;
1660 difference = nb_columns - nb_rows;
1662 if (difference == 0)
1663 return print_result ("cloog_domain_project", cloog_domain_copy (domain));
1665 matrix = cloog_matrix_alloc (nb_rows, nb_columns);
1667 for (row = 0; row < level; row++)
1668 for (column = 0; column < nb_columns; column++)
1669 value_set_si (matrix->p[row][column], (row == column ? 1 : 0));
1671 for (; row < nb_rows; row++)
1672 for (column = 0; column < nb_columns; column++)
1673 value_set_si (matrix->p[row][column],
1674 (row + difference == column ? 1 : 0));
1676 projected_domain = cloog_domain_image (domain, matrix);
1677 cloog_matrix_free (matrix);
1679 return print_result ("cloog_domain_project_1", cloog_check_domain (projected_domain));
1682 CloogDomain *
1683 cloog_domain_project (CloogDomain * domain, int level, int nb_par)
1685 CloogDomain *res = NULL;
1686 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
1687 int i, diff = cloog_domain_dim (domain) - level - nb_par;
1688 size_t n;
1689 ppl_dimension_type *to_remove;
1691 if (diff < 0)
1693 fprintf (stderr, "cloog_domain_project should not be called with"
1694 "cloog_domain_dim (domain) < level + nb_par");
1695 exit (1);
1698 if (diff == 0)
1699 return print_result ("cloog_domain_project", cloog_domain_copy (domain));
1701 n = diff;
1702 to_remove = (ppl_dimension_type *) malloc (n * sizeof (ppl_dimension_type));
1704 for (i = 0; i < n; i++)
1705 to_remove[i] = i + level;
1707 while (upol)
1709 ppl_Polyhedron_t ppl = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (upol));
1711 ppl_Polyhedron_remove_space_dimensions (ppl, to_remove, n);
1712 res = cloog_domain_add_domain (res, cloog_translate_ppl_polyhedron (ppl));
1713 upol = cloog_upol_next (upol);
1716 if (cloog_check_polyhedral_ops)
1717 return print_result ("cloog_domain_project",
1718 cloog_check_domains
1719 (res, cloog_domain_project_1 (domain, level, nb_par)));
1721 return print_result ("cloog_domain_project", res);
1725 * cloog_domain_extend function:
1726 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
1727 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
1728 * the (nb_par) parameters. This function does not free (domain), and returns
1729 * a new polyhedron.
1730 * - nb_par is the number of parameters.
1732 * - October 27th 2001: first version.
1733 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1734 * CLooG 0.12.1).
1736 CloogDomain *
1737 cloog_domain_extend_1 (CloogDomain * domain, int dim, int nb_par)
1739 int row, column, nb_rows, nb_columns, difference;
1740 CloogDomain *extended_domain;
1741 CloogMatrix *matrix;
1743 nb_rows = 1 + cloog_domain_dim (domain);
1744 nb_columns = dim + nb_par + 1;
1745 difference = nb_columns - nb_rows;
1747 if (difference == 0)
1748 return print_result ("cloog_domain_extend_1", cloog_domain_copy (domain));
1750 matrix = cloog_matrix_alloc (nb_rows, nb_columns);
1752 for (row = 0; row < cloog_domain_dim (domain) - nb_par; row++)
1753 for (column = 0; column < nb_columns; column++)
1754 value_set_si (matrix->p[row][column], (row == column ? 1 : 0));
1756 for (; row <= cloog_domain_dim (domain); row++)
1757 for (column = 0; column < nb_columns; column++)
1758 value_set_si (matrix->p[row][column],
1759 (row + difference == column ? 1 : 0));
1761 extended_domain = cloog_domain_preimage (domain, matrix);
1762 cloog_matrix_free (matrix);
1764 return print_result ("cloog_domain_extend_1", cloog_check_domain (extended_domain));
1767 CloogDomain *
1768 cloog_domain_extend (CloogDomain * domain, int dim, int nb_par)
1770 CloogDomain *res = NULL;
1771 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
1772 int i, k, n, diff = dim + nb_par - cloog_domain_dim (domain);
1773 ppl_dimension_type *map;
1774 ppl_dimension_type to_add = diff;
1776 if (diff == 0)
1777 return print_result ("cloog_domain_extend", cloog_domain_copy (domain));
1779 n = dim + nb_par;
1780 map = (ppl_dimension_type *) malloc (n * sizeof (ppl_dimension_type));
1782 k = cloog_domain_dim (domain) - nb_par;
1783 for (i = 0; i < k; i++)
1784 map[i] = i;
1786 k += nb_par;
1787 for (; i < k; i++)
1788 map[i] = i + diff;
1790 k += diff;
1791 for (; i < k; i++)
1792 map[i] = i - nb_par;
1794 while (upol)
1796 ppl_Polyhedron_t ppl = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (upol));
1798 ppl_Polyhedron_add_space_dimensions_and_embed (ppl, to_add);
1799 ppl_Polyhedron_map_space_dimensions (ppl, map, n);
1800 res = cloog_domain_add_domain (res, cloog_translate_ppl_polyhedron (ppl));
1801 upol = cloog_upol_next (upol);
1804 if (cloog_check_polyhedral_ops)
1805 return print_result ("cloog_domain_extend",
1806 cloog_check_domains
1807 (res, cloog_domain_extend_1 (domain, dim, nb_par)));
1809 return print_result ("cloog_domain_extend", res);
1813 * cloog_domain_never_integral function:
1814 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
1815 * function returns a boolean set to 1 if there is this kind of 'never true'
1816 * constraint inside a polyhedron, 0 otherwise.
1817 * - domain is the polyhedron to check,
1819 * - November 28th 2001: first version.
1820 * - June 26th 2003: for iterators, more 'never true' constraints are found
1821 * (compare cholesky2 and vivien with a previous version),
1822 * checking for the parameters created (compare using vivien).
1823 * - June 28th 2003: Previously in loop.c and called
1824 * cloog_loop_simplify_nevertrue, now here !
1825 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1826 * CLooG 0.12.1).
1827 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
1830 cloog_domain_never_integral (CloogDomain * domain)
1832 int i, dimension, nbc;
1833 Value gcd, modulo;
1834 Polyhedron *polyhedron;
1836 if ((domain == NULL) || (cloog_domain_polyhedron (domain) == NULL))
1837 return 1;
1839 value_init_c (gcd);
1840 value_init_c (modulo);
1841 polyhedron = d2p (domain);
1842 dimension = cloog_domain_dim (domain) + 2;
1843 nbc = cloog_domain_nbconstraints (domain);
1845 /* For each constraint... */
1846 for (i = 0; i < nbc; i++)
1847 { /* If we have an equality and the scalar part is not zero... */
1848 if (value_zero_p (polyhedron->Constraint[i][0]) &&
1849 value_notzero_p (polyhedron->Constraint[i][dimension - 1]))
1850 { /* Then we check whether the scalar can be divided by the gcd of the
1851 * unknown vector (including iterators and parameters) or not. If not,
1852 * there is no integer point in the polyhedron and we return 1.
1854 Vector_Gcd (&(polyhedron->Constraint[i][1]), dimension - 2, &gcd);
1855 value_modulus (modulo,
1856 polyhedron->Constraint[i][dimension - 1],
1857 gcd);
1859 if (value_notzero_p (modulo))
1861 value_clear_c (gcd);
1862 value_clear_c (modulo);
1863 Polyhedron_Free (polyhedron);
1864 return 1;
1869 value_clear_c (gcd);
1870 value_clear_c (modulo);
1871 Polyhedron_Free (polyhedron);
1872 return (0);
1877 * cloog_domain_stride function:
1878 * This function finds the stride imposed to unknown with the column number
1879 * 'strided_level' in order to be integral. For instance, if we have a
1880 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
1881 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
1882 * the unknown i. The function returns the imposed stride in a parameter field.
1883 * - domain is the set of constraint we have to consider,
1884 * - strided_level is the column number of the unknown for which a stride have
1885 * to be found,
1886 * - looking_level is the column number of the unknown that impose a stride to
1887 * the first unknown.
1888 * - stride is the stride that is returned back as a function parameter.
1889 * - offset is the value of the constant c if the condition is of the shape
1890 * (i + c)%s = 0, s being the stride.
1892 * - June 28th 2003: first version.
1893 * - July 14th 2003: can now look for multiple striding constraints and returns
1894 * the GCD of the strides and the common offset.
1895 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1896 * CLooG 0.12.1).
1898 void
1899 cloog_domain_stride (domain, strided_level, nb_par, stride, offset)
1900 CloogDomain *domain;
1901 int strided_level, nb_par;
1902 Value *stride, *offset;
1904 int i;
1905 int n_col, n_row, rank;
1906 CloogMatrix *M;
1907 Matrix *U;
1908 Vector *V;
1909 Polyhedron *polyhedron = d2p (domain);
1910 int dimension = cloog_domain_dim (domain);
1911 int nbeq = cloog_domain_nbeq (domain);
1913 /* Look at all equalities involving strided_level and the inner
1914 * iterators. We can ignore the outer iterators and the parameters
1915 * here because the lower bound on strided_level is assumed to
1916 * be a constant.
1918 n_col = (1 + dimension - nb_par) - strided_level;
1919 for (i = 0, n_row = 0; i < nbeq; i++)
1920 if (First_Non_Zero
1921 (polyhedron->Constraint[i] + strided_level, n_col) != -1)
1922 ++n_row;
1924 M = cloog_matrix_alloc (n_row + 1, n_col + 1);
1925 for (i = 0, n_row = 0; i < nbeq; i++)
1927 if (First_Non_Zero
1928 (polyhedron->Constraint[i] + strided_level, n_col) == -1)
1929 continue;
1930 Vector_Copy (polyhedron->Constraint[i] + strided_level,
1931 M->p[n_row], n_col);
1932 value_assign (M->p[n_row][n_col],
1933 polyhedron->Constraint[i][1 + dimension]);
1934 ++n_row;
1936 value_set_si (M->p[n_row][n_col], 1);
1938 /* Then look at the general solution to the above equalities. */
1939 rank = SolveDiophantine (M, &U, &V);
1940 cloog_matrix_free (M);
1942 if (rank == -1)
1944 /* There is no solution, so the body of this loop will
1945 * never execute. We just leave the constraints alone here so
1946 * that they will ensure the body will not be executed.
1947 * We should probably propagate this information up so that
1948 * the loop can be removed entirely.
1950 value_set_si (*offset, 0);
1951 value_set_si (*stride, 1);
1953 else
1955 /* Compute the gcd of the coefficients defining strided_level. */
1956 Vector_Gcd (U->p[0], U->NbColumns, stride);
1957 value_oppose (*offset, V->p[0]);
1958 value_pmodulus (*offset, *offset, *stride);
1960 Matrix_Free (U);
1961 Vector_Free (V);
1962 Polyhedron_Free (polyhedron);
1963 return;
1968 * cloog_domain_integral_lowerbound function:
1969 * This function returns 1 if the lower bound of an iterator (such as its
1970 * column rank in the constraint set 'domain' is 'level') is integral,
1971 * 0 otherwise. If the lower bound is actually integral, the function fills
1972 * the 'lower' field with the lower bound value.
1973 * - June 29th 2003: first version.
1974 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1975 * CLooG 0.12.1).
1978 cloog_domain_integral_lowerbound (domain, level, lower)
1979 CloogDomain *domain;
1980 int level;
1981 Value *lower;
1983 int i, first_lower = 1, dimension, lower_constraint = -1, nbc;
1984 Value iterator, constant, tmp;
1985 Polyhedron *polyhedron;
1987 polyhedron = d2p (domain);
1988 dimension = cloog_domain_dim (domain);
1989 nbc = cloog_domain_nbconstraints (domain);
1991 /* We want one and only one lower bound (e.g. no equality, no maximum
1992 * calculation...).
1994 for (i = 0; i < nbc; i++)
1995 if (value_zero_p (polyhedron->Constraint[i][0])
1996 && value_notzero_p (polyhedron->Constraint[i][level]))
1998 Polyhedron_Free (polyhedron);
1999 return 0;
2002 for (i = 0; i < nbc; i++)
2003 if (value_pos_p (polyhedron->Constraint[i][level]))
2005 if (first_lower)
2007 first_lower = 0;
2008 lower_constraint = i;
2010 else
2012 Polyhedron_Free (polyhedron);
2013 return 0;
2017 if (first_lower)
2019 Polyhedron_Free (polyhedron);
2020 return 0;
2023 /* We want an integral lower bound: no other non-zero entry except the
2024 * iterator coefficient and the constant.
2026 for (i = 1; i < level; i++)
2027 if (value_notzero_p
2028 (polyhedron->Constraint[lower_constraint][i]))
2030 Polyhedron_Free (polyhedron);
2031 return 0;
2034 for (i = level + 1; i <= dimension; i++)
2035 if (value_notzero_p
2036 (polyhedron->Constraint[lower_constraint][i]))
2038 Polyhedron_Free (polyhedron);
2039 return 0;
2042 value_init_c (iterator);
2043 value_init_c (constant);
2044 value_init_c (tmp);
2046 /* If all is passed, then find the lower bound and return 1. */
2047 value_assign (iterator,
2048 polyhedron->Constraint[lower_constraint][level]);
2049 value_oppose (constant,
2050 polyhedron->Constraint[lower_constraint][dimension + 1]);
2052 value_modulus (tmp, constant, iterator);
2053 value_division (*lower, constant, iterator);
2055 if (!(value_zero_p (tmp) || value_neg_p (constant)))
2056 value_increment (*lower, *lower);
2058 value_clear_c (iterator);
2059 value_clear_c (constant);
2060 value_clear_c (tmp);
2061 Polyhedron_Free (polyhedron);
2062 return 1;
2067 * cloog_domain_lowerbound_update function:
2068 * This function updates the integral lower bound of an iterator (such as its
2069 * column rank in the constraint set 'domain' is 'level') into 'lower'.
2070 * - Jun 29th 2003: first version.
2071 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
2072 * CLooG 0.12.1).
2074 void
2075 cloog_domain_lowerbound_update (domain, level, lower)
2076 CloogDomain *domain;
2077 int level;
2078 Value lower;
2080 int i;
2081 int nbc = cloog_domain_nbconstraints (domain);
2082 int dim = cloog_domain_dim (domain);
2083 Polyhedron *polyhedron = cloog_domain_polyhedron (domain);
2085 /* There is only one lower bound, the first one is the good one. */
2086 for (i = 0; i < nbc; i++)
2087 if (value_pos_p (polyhedron->Constraint[i][level]))
2089 value_set_si (polyhedron->Constraint[i][level], 1);
2090 value_oppose (polyhedron->Constraint[i][dim + 1], lower);
2091 break;
2097 * cloog_domain_lazy_equal function:
2098 * This function returns 1 if the domains given as input are the same, 0 if it
2099 * is unable to decide. This function makes an entry-to-entry comparison between
2100 * the constraint systems, if all the entries are the same, the domains are
2101 * obviously the same and it returns 1, at the first difference, it returns 0.
2102 * This is a very fast way to verify this property. It has been shown (with the
2103 * CLooG benchmarks) that operations on equal domains are 17% of all the
2104 * polyhedral computations. For 75% of the actually identical domains, this
2105 * function answer that they are the same and allow to give immediately the
2106 * trivial solution instead of calling the heavy general functions of PolyLib.
2107 * - August 22th 2003: first version.
2108 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
2109 * CLooG 0.12.1).
2112 cloog_domain_lazy_equal (CloogDomain * d1, CloogDomain * d2)
2114 int i, nb_elements;
2115 ppl_polyhedra_union *u1 = cloog_domain_upol (d1);
2116 ppl_polyhedra_union *u2 = cloog_domain_upol (d2);
2118 while (u1 && u2)
2120 if ((cloog_upol_nbc (u1) != cloog_upol_nbc (u2)) ||
2121 (cloog_upol_dim (u1) != cloog_upol_dim (u2)))
2122 return 0;
2124 nb_elements =
2125 cloog_upol_nbc (u1) * (cloog_upol_dim (u1) + 2);
2127 for (i = 0; i < nb_elements; i++)
2128 if (value_ne (cloog_upol_polyhedron (u1)->p_Init[i],
2129 cloog_upol_polyhedron (u2)->p_Init[i]))
2130 return 0;
2132 u1 = cloog_upol_next (u1);
2133 u2 = cloog_upol_next (u2);
2136 if (u1 || u2)
2137 return 0;
2139 return 1;
2144 * cloog_domain_lazy_block function:
2145 * This function returns 1 if the two domains d1 and d2 given as input are the
2146 * same (possibly except for a dimension equal to a constant where we accept
2147 * a difference of 1) AND if we are sure that there are no other domain in
2148 * the code generation problem that may put integral points between those of
2149 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
2150 * safely consider the two domains as only one with two statements (a block) ?".
2151 * This function is lazy: it asks for very standard scattering representation
2152 * (only one constraint per dimension which is an equality, and the constraints
2153 * are ordered per dimension depth: the left hand side of the constraint matrix
2154 * is the identity) and will answer NO at the very first problem.
2155 * - d1 and d2 are the two domains to check for blocking,
2156 * - scattering is the linked list of all domains,
2157 * - scattdims is the total number of scattering dimentions.
2159 * - April 30th 2005: beginning
2160 * - June 9th 2005: first working version.
2161 * - June 10th 2005: debugging.
2162 * - June 21rd 2005: Adaptation for GMP.
2163 * - October 16th 2005: (debug) some false blocks have been removed.
2166 cloog_domain_lazy_block (d1, d2, scattering, scattdims)
2167 CloogDomain *d1, *d2;
2168 CloogDomainList *scattering;
2169 int scattdims;
2171 int i, j, difference = 0, different_constraint = 0, nbc;
2172 int dim1, dim2;
2173 Value date1, date2, date3, temp;
2174 Polyhedron *p1, *p2;
2176 /* Some basic checks: we only accept convex domains, with same constraint
2177 * and dimension numbers.
2179 if (!cloog_domain_isconvex (d1) || !cloog_domain_isconvex (d2) ||
2180 (cloog_domain_nbconstraints (d1) != cloog_domain_nbconstraints (d2)) ||
2181 (cloog_domain_dim (d1) != cloog_domain_dim (d2)))
2182 return 0;
2184 p1 = d2p (d1);
2185 p2 = d2p (d2);
2186 nbc = cloog_domain_nbconstraints (d1);
2187 dim1 = cloog_domain_dim (d1);
2188 dim2 = cloog_domain_dim (d2);
2190 /* There should be only one difference between the two domains, it
2191 * has to be at the constant level and the difference must be of +1,
2192 * moreover, after the difference all domain coefficient has to be 0.
2193 * The matrix shape is:
2195 * |===========|=====|<- 0 line
2196 * |===========|=====|
2197 * |===========|====?|<- different_constraint line (found here)
2198 * |===========|0000=|
2199 * |===========|0000=|<- pX->NbConstraints line
2200 * ^ ^ ^
2201 * | | |
2202 * | | (pX->Dimension + 2) column
2203 * | scattdims column
2204 * 0 column
2207 value_init_c (temp);
2208 for (i = 0; i < nbc; i++)
2210 if (difference == 0)
2211 { /* All elements except scalar must be equal. */
2212 for (j = 0; j < dim1 + 1; j++)
2213 if (value_ne (p1->Constraint[i][j],
2214 p2->Constraint[i][j]))
2216 value_clear_c (temp);
2217 Polyhedron_Free (p1);
2218 Polyhedron_Free (p2);
2219 return 0;
2221 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
2222 if (value_ne (p1->Constraint[i][j],
2223 p2->Constraint[i][j]))
2225 value_increment (temp, p2->Constraint[i][j]);
2226 if (value_ne (p1->Constraint[i][j], temp))
2228 value_clear_c (temp);
2229 Polyhedron_Free (p1);
2230 Polyhedron_Free (p2);
2231 return 0;
2233 else
2235 difference = 1;
2236 different_constraint = i;
2240 else
2241 { /* Scattering coefficients must be equal. */
2242 for (j = 0; j < (scattdims + 1); j++)
2243 if (value_ne (p1->Constraint[i][j],
2244 p2->Constraint[i][j]))
2246 value_clear_c (temp);
2247 Polyhedron_Free (p1);
2248 Polyhedron_Free (p2);
2249 return 0;
2252 /* Domain coefficients must be 0. */
2253 for (; j < dim1 + 1; j++)
2254 if (value_notzero_p (p1->Constraint[i][j])
2255 || value_notzero_p (p2->Constraint[i][j]))
2257 value_clear_c (temp);
2258 Polyhedron_Free (p1);
2259 Polyhedron_Free (p2);
2260 return 0;
2263 /* Scalar must be equal. */
2264 if (value_ne (p1->Constraint[i][j],
2265 p2->Constraint[i][j]))
2267 value_clear_c (temp);
2268 Polyhedron_Free (p1);
2269 Polyhedron_Free (p2);
2270 return 0;
2274 value_clear_c (temp);
2276 /* If the domains are exactly the same, this is a block. */
2277 if (difference == 0)
2279 Polyhedron_Free (p1);
2280 Polyhedron_Free (p2);
2281 return 1;
2284 /* Now a basic check that the constraint with the difference is an
2285 * equality of a dimension with a constant.
2287 for (i = 0; i <= different_constraint; i++)
2288 if (value_notzero_p (p1->Constraint[different_constraint][i]))
2290 Polyhedron_Free (p1);
2291 Polyhedron_Free (p2);
2292 return 0;
2295 if (value_notone_p (p1->Constraint[different_constraint][different_constraint + 1]))
2297 Polyhedron_Free (p1);
2298 Polyhedron_Free (p2);
2299 return 0;
2302 for (i = different_constraint + 2; i < dim1 + 1; i++)
2303 if (value_notzero_p (p1->Constraint[different_constraint][i]))
2305 Polyhedron_Free (p1);
2306 Polyhedron_Free (p2);
2307 return 0;
2310 /* For the moment, d1 and d2 are a block candidate. There remains to check
2311 * that there is no other domain that may put an integral point between
2312 * them. In our lazy test we ensure this property by verifying that the
2313 * constraint matrices have a very strict shape: let us consider that the
2314 * dimension with the difference is d. Then the first d dimensions are
2315 * defined in their depth order using equalities (thus the first column begins
2316 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
2317 * the remaining simensions). If a domain can put integral points between the
2318 * domains of the block candidate, this means that the other entries on the
2319 * first d constraints are equal to those of d1 or d2. Thus we are looking for
2320 * such a constraint system, if it exists d1 and d2 is considered to not be
2321 * a block, it is a bock otherwise.
2323 * 1. Only equalities (for the first different_constraint+1 lines).
2324 * | 2. Must be the identity.
2325 * | | 3. Must be zero.
2326 * | | | 4. Elements are equal, the last one is either date1 or 2.
2327 * | | | |
2328 * | /-\ /---\ /---\
2329 * |0|100|00000|=====|<- 0 line
2330 * |0|010|00000|=====|
2331 * |0|001|00000|====?|<- different_constraint line
2332 * |*|***|*****|*****|
2333 * |*|***|*****|*****|<- pX->NbConstraints line
2334 * ^ ^ ^ ^
2335 * | | | |
2336 * | | | (pX->Dimension + 2) column
2337 * | | scattdims column
2338 * | different_constraint+1 column
2339 * 0 column
2342 /* Step 1 and 2. This is only necessary to check one domain because
2343 * we checked that they are equal on this part before.
2345 for (i = 0; i <= different_constraint; i++)
2347 for (j = 0; j < i + 1; j++)
2348 if (value_notzero_p (p1->Constraint[i][j]))
2350 Polyhedron_Free (p1);
2351 Polyhedron_Free (p2);
2352 return 0;
2355 if (value_notone_p (p1->Constraint[i][i + 1]))
2357 Polyhedron_Free (p1);
2358 Polyhedron_Free (p2);
2359 return 0;
2362 for (j = i + 2; j <= different_constraint + 1; j++)
2363 if (value_notzero_p (p1->Constraint[i][j]))
2365 Polyhedron_Free (p1);
2366 Polyhedron_Free (p2);
2367 return 0;
2371 /* Step 3. */
2372 for (i = 0; i <= different_constraint; i++)
2373 for (j = different_constraint + 2; j <= scattdims; j++)
2374 if (value_notzero_p (p1->Constraint[i][j]))
2376 Polyhedron_Free (p1);
2377 Polyhedron_Free (p2);
2378 return 0;
2381 value_init_c (date1);
2382 value_init_c (date2);
2383 value_init_c (date3);
2385 /* Now we have to check that the two different dates are unique. */
2386 value_assign (date1, p1->Constraint[different_constraint][dim1 + 1]);
2387 value_assign (date2, p2->Constraint[different_constraint][dim2 + 1]);
2389 /* Step 4. We check all domains except d1 and d2 and we look for at least
2390 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
2392 while (scattering != NULL)
2394 if ((cloog_domain (scattering) != d1)
2395 && (cloog_domain (scattering) != d2))
2397 CloogDomain *d3 = cloog_domain (scattering);
2398 Polyhedron *p3 = d2p (d3);
2399 int dim3 = cloog_domain_dim (d3);
2401 value_assign (date3,
2402 p3->Constraint[different_constraint][dim3 + 1]);
2403 difference = 0;
2405 if (value_ne (date3, date2) && value_ne (date3, date1))
2406 difference = 1;
2408 for (i = 0; (i < different_constraint) && (!difference); i++)
2409 for (j = 0; (j < dim3 + 2) && !difference; j++)
2410 if (value_ne
2411 (p1->Constraint[i][j],
2412 p3->Constraint[i][j]))
2413 difference = 1;
2415 for (j = 0; (j < dim3 + 1) && !difference; j++)
2416 if (value_ne
2417 (p1->Constraint[different_constraint][j],
2418 p3->Constraint[different_constraint][j]))
2419 difference = 1;
2421 Polyhedron_Free (p3);
2422 if (!difference)
2424 value_clear_c (date1);
2425 value_clear_c (date2);
2426 value_clear_c (date3);
2427 Polyhedron_Free (p1);
2428 Polyhedron_Free (p2);
2429 return 0;
2433 scattering = cloog_next_domain (scattering);
2436 Polyhedron_Free (p1);
2437 Polyhedron_Free (p2);
2438 value_clear_c (date1);
2439 value_clear_c (date2);
2440 value_clear_c (date3);
2441 return 1;
2446 * cloog_domain_lazy_disjoint function:
2447 * This function returns 1 if the domains given as input are disjoint, 0 if it
2448 * is unable to decide. This function finds the unknown with fixed values in
2449 * both domains (on a given constraint, their column entry is not zero and
2450 * only the constant coefficient can be different from zero) and verify that
2451 * their values are the same. If not, the domains are obviously disjoint and
2452 * it returns 1, if there is not such case it returns 0. This is a very fast
2453 * way to verify this property. It has been shown (with the CLooG benchmarks)
2454 * that operations on disjoint domains are 36% of all the polyhedral
2455 * computations. For 94% of the actually identical domains, this
2456 * function answer that they are disjoint and allow to give immediately the
2457 * trivial solution instead of calling the heavy general functions of PolyLib.
2458 * - August 22th 2003: first version.
2459 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
2460 * CLooG 0.12.1).
2463 cloog_domain_lazy_disjoint (CloogDomain * d1, CloogDomain * d2)
2465 int i1, j1, i2, j2, scat_dim, nbc1, nbc2;
2466 int dim1, dim2;
2467 Value scat_val;
2468 Polyhedron *p1, *p2;
2470 if (!cloog_domain_isconvex (d1) || !cloog_domain_isconvex (d2))
2471 return 0;
2473 p1 = d2p (d1);
2474 p2 = d2p (d2);
2475 nbc1 = cloog_domain_nbconstraints (d1);
2476 nbc2 = cloog_domain_nbconstraints (d2);
2477 dim1 = cloog_domain_dim (d1);
2478 dim2 = cloog_domain_dim (d2);
2479 value_init_c (scat_val);
2481 for (i1 = 0; i1 < nbc1; i1++)
2483 if (value_notzero_p (p1->Constraint[i1][0]))
2484 continue;
2486 scat_dim = 1;
2487 while (value_zero_p (p1->Constraint[i1][scat_dim]) &&
2488 (scat_dim < dim1))
2489 scat_dim++;
2491 if (value_notone_p (p1->Constraint[i1][scat_dim]))
2492 continue;
2493 else
2495 for (j1 = scat_dim + 1; j1 <= dim1; j1++)
2496 if (value_notzero_p (p1->Constraint[i1][j1]))
2497 break;
2499 if (j1 != dim1 + 1)
2500 continue;
2502 value_assign (scat_val,
2503 p1->Constraint[i1][dim1 + 1]);
2505 for (i2 = 0; i2 < nbc2; i2++)
2507 for (j2 = 0; j2 < scat_dim; j2++)
2508 if (value_notzero_p (p2->Constraint[i2][j2]))
2509 break;
2511 if ((j2 != scat_dim)
2513 value_notone_p (p2->Constraint[i2][scat_dim]))
2514 continue;
2516 for (j2 = scat_dim + 1; j2 < dim2; j2++)
2517 if (value_notzero_p (p2->Constraint[i2][j2]))
2518 break;
2520 if (j2 != dim2)
2521 continue;
2523 if (value_ne
2524 (p2->Constraint[i2][dim2 + 1], scat_val))
2526 value_clear_c (scat_val);
2527 return 1;
2533 value_clear_c (scat_val);
2534 Polyhedron_Free (p1);
2535 Polyhedron_Free (p2);
2536 return 0;
2541 * cloog_domain_list_lazy_same function:
2542 * This function returns 1 if two domains in the list are the same, 0 if it
2543 * is unable to decide.
2544 * - February 9th 2004: first version.
2547 cloog_domain_list_lazy_same (CloogDomainList * list)
2548 { /*int i=1, j=1 ; */
2549 CloogDomainList *current, *next;
2551 current = list;
2552 while (current != NULL)
2554 next = cloog_next_domain (current);
2555 /*j=i+1; */
2556 while (next != NULL)
2558 if (cloog_domain_lazy_equal (cloog_domain (current),
2559 cloog_domain (next)))
2560 { /*printf("Same domains: %d and %d\n",i,j) ; */
2561 return 1;
2563 /*j++ ; */
2564 next = cloog_next_domain (next);
2566 /*i++ ; */
2567 current = cloog_next_domain (current);
2570 return 0;
2574 * cloog_domain_cut_first function:
2575 * this function returns a CloogDomain structure with everything except the
2576 * first part of the polyhedra union of the input domain as domain. After a call
2577 * to this function, there remains in the CloogDomain structure provided as
2578 * input only the first part of the original polyhedra union.
2579 * - April 20th 2005: first version, extracted from different part of loop.c.
2581 CloogDomain *
2582 cloog_domain_cut_first (CloogDomain * domain)
2584 CloogDomain *rest;
2586 if (domain && cloog_domain_polyhedron (domain))
2588 if (!cloog_upol_next (cloog_domain_upol (domain)))
2589 return NULL;
2591 rest = cloog_new_domain (cloog_upol_next (cloog_domain_upol (domain)));
2592 cloog_upol_set_next (cloog_domain_upol (domain), NULL);
2594 else
2595 rest = NULL;
2597 return print_result ("cloog_domain_cut_first", cloog_check_domain (rest));
2602 * cloog_domain_lazy_isscalar function:
2603 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
2604 * is scalar, this means that the only constraint on this dimension must have
2605 * the shape "x.dimension + scalar = 0" with x an integral variable. This
2606 * function is lazy since we only accept x=1 (further calculations are easier
2607 * in this way).
2608 * - June 14th 2005: first version.
2609 * - June 21rd 2005: Adaptation for GMP.
2612 cloog_domain_lazy_isscalar (CloogDomain * domain, int dimension)
2614 int i, j;
2615 Polyhedron *polyhedron = d2p (domain);
2616 int nbc = cloog_domain_nbconstraints (domain);
2617 int dim = cloog_domain_dim (domain);
2619 /* For each constraint... */
2620 for (i = 0; i < nbc; i++)
2621 { /* ...if it is concerned by the potentially scalar dimension... */
2622 if (value_notzero_p
2623 (polyhedron->Constraint[i][dimension + 1]))
2624 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
2625 for (j = 0; j <= dimension; j++)
2626 if (value_notzero_p (polyhedron->Constraint[i][j]))
2628 Polyhedron_Free (polyhedron);
2629 return 0;
2632 if (value_notone_p
2633 (polyhedron->Constraint[i][dimension + 1]))
2635 Polyhedron_Free (polyhedron);
2636 return 0;
2639 for (j = dimension + 2; j < dim + 1; j++)
2640 if (value_notzero_p (polyhedron->Constraint[i][j]))
2642 Polyhedron_Free (polyhedron);
2643 return 0;
2648 Polyhedron_Free (polyhedron);
2649 return 1;
2654 * cloog_domain_scalar function:
2655 * when we call this function, we know that "dimension" is a scalar dimension,
2656 * this function finds the scalar value in "domain" and returns it in "value".
2657 * - June 30th 2005: first version.
2659 void
2660 cloog_domain_scalar (CloogDomain * domain, int dimension, Value * value)
2662 int i;
2663 Polyhedron *polyhedron = d2p (domain);
2664 int nbc = cloog_domain_nbconstraints (domain);
2665 int dim = cloog_domain_dim (domain);
2667 /* For each constraint... */
2668 for (i = 0; i < nbc; i++)
2669 { /* ...if it is the equality defining the scalar dimension... */
2670 if (value_notzero_p
2671 (polyhedron->Constraint[i][dimension + 1])
2672 && value_zero_p (polyhedron->Constraint[i][0]))
2673 { /* ...Then send the scalar value. */
2674 value_assign (*value, polyhedron->Constraint[i][dim + 1]);
2675 value_oppose (*value, *value);
2676 Polyhedron_Free (polyhedron);
2677 return;
2681 /* We should have found a scalar value: if not, there is an error. */
2682 fprintf (stderr, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
2683 dimension);
2684 Polyhedron_Free (polyhedron);
2685 exit (0);
2690 * cloog_domain_erase_dimension function:
2691 * this function returns a CloogDomain structure builds from 'domain' where
2692 * we removed the dimension 'dimension' and every constraint considering this
2693 * dimension. This is not a projection ! Every data concerning the
2694 * considered dimension is simply erased.
2695 * - June 14th 2005: first version.
2696 * - June 21rd 2005: Adaptation for GMP.
2698 CloogDomain *
2699 cloog_domain_erase_dimension (CloogDomain * domain, int dimension)
2701 int i, j, mi, nb_dim, nbc;
2702 CloogMatrix *matrix;
2703 CloogDomain *erased;
2704 Polyhedron *polyhedron;
2706 polyhedron = d2p (domain);
2707 nb_dim = cloog_domain_dim (domain);
2708 nbc = cloog_domain_nbconstraints (domain);
2710 /* The matrix is one column less and at least one constraint less. */
2711 matrix = cloog_matrix_alloc (nbc - 1, nb_dim + 1);
2713 /* mi is the constraint counter for the matrix. */
2714 mi = 0;
2715 for (i = 0; i < nbc; i++)
2716 if (value_zero_p (polyhedron->Constraint[i][dimension + 1]))
2718 for (j = 0; j <= dimension; j++)
2719 value_assign (matrix->p[mi][j],
2720 polyhedron->Constraint[i][j]);
2722 for (j = dimension + 2; j < nb_dim + 2; j++)
2723 value_assign (matrix->p[mi][j - 1],
2724 polyhedron->Constraint[i][j]);
2726 mi++;
2729 erased = cloog_domain_matrix2domain (matrix);
2730 cloog_matrix_free (matrix);
2732 Polyhedron_Free (polyhedron);
2733 return print_result ("cloog_domain_erase_dimension", cloog_check_domain (erased));
2736 /* Number of polyhedra inside the union of disjoint polyhedra. */
2738 unsigned
2739 cloog_domain_nb_polyhedra (CloogDomain * domain)
2741 unsigned res = 0;
2742 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
2744 while (upol)
2746 res++;
2747 upol = cloog_upol_next (upol);
2750 return res;
2753 void
2754 cloog_domain_print_polyhedra (FILE * foo, CloogDomain * domain)
2756 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
2758 while (upol != NULL)
2760 CloogMatrix *matrix = cloog_upol_domain2matrix (upol);
2761 cloog_matrix_print (foo, matrix);
2762 cloog_matrix_free (matrix);
2763 upol = cloog_upol_next (upol);
2767 void
2768 debug_cloog_domain (CloogDomain *domain)
2770 cloog_domain_print_polyhedra (stderr, domain);
2773 void
2774 debug_cloog_matrix (CloogMatrix *m)
2776 cloog_matrix_print (stderr, m);