cleanup.
[cloog-ppl.git] / source / ppl / domain.c
blob8ccd439291292fb8c8271aaacac0a35a8af57d8a
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 static inline CloogDomain *
263 cloog_check_domain_id (CloogDomain *dom)
265 return dom;
268 static inline CloogDomain *
269 cloog_check_domain (CloogDomain *dom)
271 if (!dom)
272 return dom;
274 /* FIXME: Remove this check. */
275 if (cloog_domain_polyhedron (dom)->next)
277 fprintf (stderr, "polyhedra of domains should be convex.\n");
278 exit (1);
281 return dom;
285 * cloog_domain_matrix2domain function:
286 * Given a matrix of constraints (matrix), this function constructs and returns
287 * the corresponding domain (i.e. the CloogDomain structure including the
288 * polyhedron with its double representation: constraint matrix and the set of
289 * rays).
291 static CloogDomain *
292 cloog_domain_matrix2domain (CloogMatrix * matrix)
294 return print_result ("cloog_domain_matrix2domain", cloog_check_domain (cloog_domain_alloc (Constraints2Polyhedron (matrix, MAX_RAYS))));
297 static inline CloogMatrix *
298 cloog_upol_domain2matrix (ppl_polyhedra_union * upol)
300 return Polyhedron2Constraints (cloog_upol_polyhedron (upol));
303 /* In the matrix representation an equality has a 0 in the first
304 column. When the value of the first column is 1, the row
305 represents an inequality. */
307 static inline int
308 cloog_matrix_row_is_eq_p (CloogMatrix *matrix, int row)
310 return value_zero_p (matrix->p[row][0]);
313 /* Adds to PPL the constraints from MATRIX. */
315 static void
316 cloog_translate_constraint_matrix_1 (ppl_Polyhedron_t ppl, CloogMatrix *matrix)
318 int i, j;
319 ppl_Constraint_t cstr;
320 ppl_Linear_Expression_t expr;
321 ppl_Coefficient_t coef;
322 ppl_dimension_type dim = matrix->NbColumns - 2;
324 ppl_new_Coefficient (&coef);
326 for (i = 0; i < matrix->NbRows; i++)
328 ppl_new_Linear_Expression_with_dimension (&expr, dim);
330 for (j = 1; j < matrix->NbColumns - 1; j++)
332 ppl_assign_Coefficient_from_mpz_t (coef, matrix->p[i][j]);
333 ppl_Linear_Expression_add_to_coefficient (expr, j - 1, coef);
336 ppl_assign_Coefficient_from_mpz_t
337 (coef, matrix->p[i][matrix->NbColumns - 1]);
338 ppl_Linear_Expression_add_to_inhomogeneous (expr, coef);
340 if (cloog_matrix_row_is_eq_p (matrix, i))
341 ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_EQUAL);
342 else
343 ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_GREATER_THAN_OR_EQUAL);
345 ppl_Polyhedron_add_constraint (ppl, cstr);
348 if (cloog_check_polyhedral_ops)
349 ppl_Polyhedron_OK (ppl);
352 static ppl_Polyhedron_t
353 cloog_translate_constraint_matrix (CloogMatrix *matrix)
355 ppl_Polyhedron_t ppl;
356 ppl_dimension_type dim = matrix->NbColumns - 2;
358 ppl_new_NNC_Polyhedron_from_dimension (&ppl, dim);
359 cloog_translate_constraint_matrix_1 (ppl, matrix);
360 return ppl;
363 static CloogDomain *
364 cloog_translate_ppl_polyhedron (ppl_Polyhedron_t pol)
366 CloogDomain *res;
367 CloogMatrix *matrix ;
368 ppl_dimension_type dim;
369 ppl_const_Constraint_System_t pcs;
370 ppl_Constraint_System_const_iterator_t cit, end;
371 int row;
373 ppl_Polyhedron_constraints (pol, &pcs);
374 ppl_new_Constraint_System_const_iterator (&cit);
375 ppl_new_Constraint_System_const_iterator (&end);
377 for (row = 0, ppl_Constraint_System_begin (pcs, cit), ppl_Constraint_System_end (pcs, end);
378 !ppl_Constraint_System_const_iterator_equal_test (cit, end);
379 ppl_Constraint_System_const_iterator_increment (cit), row++);
381 ppl_Polyhedron_space_dimension (pol, &dim);
382 matrix = cloog_matrix_alloc (row, dim + 2);
384 for (row = 0, ppl_Constraint_System_begin (pcs, cit), ppl_Constraint_System_end (pcs, end);
385 !ppl_Constraint_System_const_iterator_equal_test (cit, end);
386 ppl_Constraint_System_const_iterator_increment (cit), row++)
388 ppl_const_Constraint_t pc;
389 ppl_Coefficient_t coef;
390 ppl_dimension_type col;
391 Value val;
392 int neg;
394 value_init (val);
395 ppl_new_Coefficient (&coef);
396 ppl_Constraint_System_const_iterator_dereference (cit, &pc);
398 neg = (ppl_Constraint_type (pc) == PPL_CONSTRAINT_TYPE_LESS_THAN
399 || ppl_Constraint_type (pc) == PPL_CONSTRAINT_TYPE_LESS_THAN_OR_EQUAL) ? 1 : 0;
401 for (col = 0; col < dim; col++)
403 ppl_Constraint_coefficient (pc, col, coef);
404 ppl_Coefficient_to_mpz_t (coef, val);
406 if (neg)
407 value_oppose (val, val);
409 value_assign (matrix->p[row][col+1], val);
412 ppl_Constraint_inhomogeneous_term (pc, coef);
413 ppl_Coefficient_to_mpz_t (coef, val);
414 value_assign (matrix->p[row][dim + 1], val);
416 switch (ppl_Constraint_type (pc))
418 case PPL_CONSTRAINT_TYPE_EQUAL:
419 value_set_si (matrix->p[row][0], 0);
420 break;
422 case PPL_CONSTRAINT_TYPE_LESS_THAN:
423 case PPL_CONSTRAINT_TYPE_GREATER_THAN:
424 value_decrement (matrix->p[row][dim + 1], matrix->p[row][dim + 1]);
425 value_set_si (matrix->p[row][0], 1);
426 break;
428 case PPL_CONSTRAINT_TYPE_LESS_THAN_OR_EQUAL:
429 case PPL_CONSTRAINT_TYPE_GREATER_THAN_OR_EQUAL:
430 value_set_si (matrix->p[row][0], 1);
431 break;
433 default:
434 fprintf (stderr, "PPL_CONSTRAINT_TYPE_%d not implemented yet\n",
435 ppl_Constraint_type (pc));
436 exit (1);
440 res = cloog_domain_matrix2domain (matrix);
441 return print_result ("cloog_translate_ppl_polyhedron", cloog_check_domain (res));
444 static inline int
445 cloog_domain_references (CloogDomain * d)
447 return d->_references;
451 * cloog_domain_print function:
452 * This function prints the content of a CloogDomain structure (domain) into
453 * a file (foo, possibly stdout).
455 void
456 cloog_domain_print (FILE * foo, CloogDomain * domain)
458 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
460 while (upol)
462 Polyhedron_Print (foo, P_VALUE_FMT, cloog_upol_polyhedron (upol));
463 upol = cloog_upol_next (upol);
466 fprintf (foo, "Number of active references: %d\n",
467 cloog_domain_references (domain));
471 * cloog_domain_free function:
472 * This function frees the allocated memory for a CloogDomain structure
473 * (domain). It decrements the number of active references to this structure,
474 * if there are no more references on the structure, it frees it (with the
475 * included list of polyhedra).
477 void
478 cloog_domain_free (CloogDomain * domain)
480 if (domain)
482 cloog_domain_set_references (domain,
483 cloog_domain_references (domain) - 1);
485 if (cloog_domain_references (domain) == 0)
488 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
490 while (upol)
492 Polyhedron_Free (cloog_upol_polyhedron (upol));
493 upol = cloog_upol_next (upol);
496 free (domain);
503 * cloog_domain_copy function:
504 * This function returns a copy of a CloogDomain structure (domain). To save
505 * memory this is not a memory copy but we increment a counter of active
506 * references inside the structure, then return a pointer to that structure.
508 CloogDomain *
509 cloog_domain_copy (CloogDomain * domain)
511 cloog_domain_set_references (domain, cloog_domain_references (domain) + 1);
512 return print_result ("cloog_domain_copy", domain);
517 * cloog_domain_image function:
518 * This function returns a CloogDomain structure such that the included
519 * polyhedral domain is computed from the former one into another
520 * domain according to a given affine mapping function (mapping).
522 static CloogDomain *
523 cloog_domain_image (CloogDomain * domain, CloogMatrix * mapping)
525 Polyhedron *p = d2p (domain);
526 CloogDomain *res =
527 cloog_check_domain (cloog_domain_alloc
528 (DomainImage (p, mapping, MAX_RAYS)));
529 Polyhedron_Free (p);
530 return print_result ("cloog_domain_image", res);
535 * cloog_domain_preimage function:
536 * Given a polyhedral domain (polyhedron) inside a CloogDomain structure and a
537 * mapping function (mapping), this function returns a new CloogDomain structure
538 * with a polyhedral domain which when transformed by mapping function (mapping)
539 * gives (polyhedron).
541 static CloogDomain *
542 cloog_domain_preimage (CloogDomain * domain, CloogMatrix * mapping)
544 Polyhedron *p = d2p (domain);
545 CloogDomain *res =
546 cloog_check_domain (cloog_domain_alloc
547 (DomainPreimage (p, mapping, MAX_RAYS)));
548 Polyhedron_Free (p);
549 return print_result ("cloog_domain_preimage", res);
552 static CloogDomain *
553 cloog_check_domains (CloogDomain *ppl, CloogDomain *polylib)
555 /* Cannot use cloog_domain_lazy_equal (polylib, ppl) here as this
556 function is too dumb: it does not detect permutations of
557 constraints. */
558 if (!cloog_domain_isempty (cloog_domain_difference (ppl, polylib))
559 || !cloog_domain_isempty (cloog_domain_difference (polylib, ppl)))
561 fprintf (stderr, "different domains ( \n ppl (\n");
562 cloog_domain_print (stderr, ppl);
563 fprintf (stderr, ") \n polylib (\n");
564 cloog_domain_print (stderr, polylib);
565 fprintf (stderr, "))\n");
566 exit (1);
569 if (cloog_return_ppl_result)
570 return ppl;
571 else
572 return polylib;
576 * cloog_domain_convex function:
577 * Given a polyhedral domain (polyhedron), this function concatenates the lists
578 * of rays and lines of the two (or more) polyhedra in the domain into one
579 * combined list, and find the set of constraints which tightly bound all of
580 * those objects. It returns the corresponding polyhedron.
582 CloogDomain *
583 cloog_domain_convex (CloogDomain * domain)
585 Polyhedron *p = d2p (domain);
586 CloogDomain *res =
587 cloog_check_domain (cloog_domain_alloc
588 (DomainConvex (p, MAX_RAYS)));
589 Polyhedron_Free (p);
590 return print_result ("cloog_domain_convex", res);
593 static inline unsigned
594 cloog_upol_nbc (ppl_polyhedra_union * p)
596 return cloog_upol_polyhedron (p)->NbConstraints;
599 static inline int
600 cloog_domain_nbconstraints (CloogDomain * domain)
602 return cloog_domain_polyhedron (domain)->NbConstraints;
605 static inline unsigned
606 cloog_upol_nbeq (ppl_polyhedra_union * d)
608 return cloog_upol_polyhedron (d)->NbEq;
611 static inline unsigned
612 cloog_domain_nbeq (CloogDomain * d)
614 return cloog_domain_polyhedron (d)->NbEq;
617 static inline unsigned
618 cloog_upol_dim (ppl_polyhedra_union * p)
620 return cloog_upol_polyhedron (p)->Dimension;
624 cloog_domain_isconvex (CloogDomain * domain)
626 if (cloog_domain_polyhedron (domain))
627 return !cloog_upol_next (cloog_domain_upol (domain));
629 return 1;
632 unsigned
633 cloog_domain_dim (CloogDomain * d)
635 return cloog_domain_polyhedron (d)->Dimension;
639 * cloog_domain_simple_convex:
640 * Given a list (union) of polyhedra, this function returns a "simple"
641 * convex hull of this union. In particular, the constraints of the
642 * the returned polyhedron consist of (parametric) lower and upper
643 * bounds on individual variables and constraints that appear in the
644 * original polyhedra.
646 * nb_par is the number of parameters of the domain.
648 CloogDomain *
649 cloog_domain_simple_convex (CloogDomain * domain, int nb_par)
651 fprintf (stderr, "cloog_domain_simple_convex is not implemented yet.\n");
652 exit (1);
657 * cloog_domain_simplify function:
658 * Given two polyhedral domains (pol1) and (pol2) inside two CloogDomain
659 * structures, this function finds the largest domain set (or the smallest list
660 * of non-redundant constraints), that when intersected with polyhedral
661 * domain (pol2) equals (Pol1)intersect(Pol2). The output is a new CloogDomain
662 * structure with a polyhedral domain with the "redundant" constraints removed.
663 * NB: this function do not work as expected with unions of polyhedra...
665 CloogDomain *
666 cloog_domain_simplify (CloogDomain * dom1, CloogDomain * dom2)
668 CloogMatrix *M, *M2;
669 CloogDomain *dom;
670 Polyhedron *d2, *P = d2p (dom1);
671 int nbc = cloog_domain_nbconstraints (dom1);
673 /* DomainSimplify doesn't remove all redundant equalities,
674 * so we remove them here first in case both dom1 and dom2
675 * are single polyhedra (i.e., not unions of polyhedra).
677 if (cloog_domain_isconvex (dom1) && cloog_domain_isconvex (dom2)
678 && cloog_domain_nbeq (dom1) && cloog_domain_nbeq (dom2))
680 int i, row;
681 int rows = cloog_domain_nbeq (dom1) + cloog_domain_nbeq (dom2);
682 int cols = cloog_domain_dim (dom1) + 2;
683 int rank;
684 M = cloog_matrix_alloc (rows, cols);
685 M2 = cloog_matrix_alloc (nbc, cols);
686 Vector_Copy (cloog_domain_polyhedron (dom2)->Constraint[0],
687 M->p[0], cloog_domain_nbeq (dom2) * cols);
688 rank = cloog_domain_nbeq (dom2);
689 row = 0;
690 for (i = 0; i < cloog_domain_nbeq (dom1); ++i)
692 Vector_Copy (P->Constraint[i], M->p[rank], cols);
693 if (Gauss (M, rank + 1, cols - 1) > rank)
695 Vector_Copy (P->Constraint[i], M2->p[row++], cols);
696 rank++;
699 if (row < cloog_domain_nbeq (dom1))
701 Vector_Copy (P->Constraint[cloog_domain_nbeq (dom1)],
702 M2->p[row], (nbc - cloog_domain_nbeq (dom1)) * cols);
703 P = Constraints2Polyhedron (M2, MAX_RAYS);
705 cloog_matrix_free (M2);
706 cloog_matrix_free (M);
708 d2 = d2p (dom2);
709 dom = cloog_domain_alloc (DomainSimplify (P, d2, MAX_RAYS));
710 Polyhedron_Free (d2);
711 Polyhedron_Free (P);
712 return print_result ("cloog_domain_simplify", cloog_check_domain (dom));
715 static ppl_polyhedra_union *
716 cloog_upol_copy (ppl_polyhedra_union *p)
718 ppl_polyhedra_union *res = cloog_new_upol (Polyhedron_Copy (cloog_upol_polyhedron (p)));
719 ppl_polyhedra_union *upol = res;
721 while (cloog_upol_next (p))
723 cloog_upol_set_next (upol, cloog_new_upol (Polyhedron_Copy (cloog_upol_polyhedron (p))));
724 upol = cloog_upol_next (upol);
725 p = cloog_upol_next (p);
728 return res;
731 /* Adds to D1 the union of polyhedra from D2, with no checks of
732 redundancies between polyhedra. */
734 CloogDomain *
735 cloog_domain_add_domain (CloogDomain *d1, CloogDomain *d2)
737 ppl_polyhedra_union *upol;
739 if (!d1)
740 return d2;
742 if (!d2)
743 return d1;
745 upol = cloog_domain_upol (d1);
746 while (cloog_upol_next (upol))
747 upol = cloog_upol_next (upol);
749 cloog_upol_set_next (upol, cloog_domain_upol (d2));
750 return d1;
754 * cloog_domain_union function:
755 * This function returns a new CloogDomain structure including a polyhedral
756 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
757 * two CloogDomain structures.
759 CloogDomain *
760 cloog_domain_union (CloogDomain * dom1, CloogDomain * dom2)
762 CloogDomain *res;
763 ppl_polyhedra_union *head1, *head2, *tail1, *tail2;
764 ppl_polyhedra_union *d1, *d2;
766 if (!dom1)
767 return dom2;
769 if (!dom2)
770 return dom1;
772 if (cloog_domain_dim (dom1) != cloog_domain_dim (dom2))
774 fprintf (stderr, "cloog_domain_union should not be called on domains of different dimensions.\n");
775 exit (1);
778 head1 = NULL;
779 tail1 = NULL;
780 for (d1 = cloog_domain_upol (dom1); d1; d1 = cloog_upol_next (d1))
782 int found = 0;
783 ppl_Polyhedron_t ppl1 = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d1));
785 for (d2 = cloog_domain_upol (dom2); d2; d2 = cloog_upol_next (d2))
787 ppl_Polyhedron_t ppl2 = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d2));
789 if (ppl_Polyhedron_contains_Polyhedron (ppl2, ppl1))
791 found = 1;
792 break;
796 if (!found)
798 if (!tail1)
800 head1 = cloog_upol_copy (d1);
801 tail1 = head1;
803 else
805 cloog_upol_set_next (tail1, cloog_upol_copy (d1));
806 tail1 = cloog_upol_next (tail1);
811 head2 = NULL;
812 tail2 = NULL;
813 for (d2 = cloog_domain_upol (dom2); d2; d2 = cloog_upol_next (d2))
815 int found = 0;
816 ppl_Polyhedron_t ppl2 = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d2));
818 for (d1 = head1; d1; d1 = cloog_upol_next (d1))
820 ppl_Polyhedron_t ppl1 = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (d1));
822 if (ppl_Polyhedron_contains_Polyhedron (ppl1, ppl2))
824 found = 1;
825 break;
829 if (!found)
831 if (!tail2)
833 head2 = cloog_upol_copy (d2);
834 tail2 = head2;
836 else
838 cloog_upol_set_next (tail2, cloog_upol_copy (d2));
839 tail2 = cloog_upol_next (tail2);
844 if (!head1)
845 res = cloog_new_domain (head2);
846 else
848 cloog_upol_set_next (tail1, head2);
849 res = cloog_new_domain (head1);
852 if (cloog_check_polyhedral_ops)
854 Polyhedron *p1 = d2p (dom1);
855 Polyhedron *p2 = d2p (dom2);
857 cloog_check_domains (res, cloog_domain_alloc (DomainUnion (p1, p2, MAX_RAYS)));
859 Polyhedron_Free (p1);
860 Polyhedron_Free (p2);
863 return print_result ("cloog_domain_union", cloog_check_domain (res));
867 * cloog_domain_intersection function:
868 * This function returns a new CloogDomain structure including a polyhedral
869 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
870 * inside two CloogDomain structures.
872 CloogDomain *
873 cloog_domain_intersection (CloogDomain * dom1, CloogDomain * dom2)
875 CloogDomain *res;
876 ppl_polyhedra_union *p1, *p2;
877 ppl_Polyhedron_t ppl1, ppl2;
879 res = cloog_domain_empty (cloog_domain_dim (dom1));
881 for (p1 = cloog_domain_upol (dom1); p1; p1 = cloog_upol_next (p1))
883 ppl1 = cloog_translate_constraint_matrix (Polyhedron2Constraints (cloog_upol_polyhedron (p1)));
885 for (p2 = cloog_domain_upol (dom2); p2; p2 = cloog_upol_next (p2))
887 ppl2 = cloog_translate_constraint_matrix (Polyhedron2Constraints (cloog_upol_polyhedron (p2)));
888 ppl_Polyhedron_intersection_assign (ppl2, ppl1);
890 res = cloog_domain_union (res, cloog_translate_ppl_polyhedron (ppl2));
894 if (cloog_check_polyhedral_ops)
896 Polyhedron *a1 = d2p (dom1);
897 Polyhedron *a2 = d2p (dom2);
899 res = cloog_check_domains (res, cloog_domain_alloc (DomainIntersection (a1, a2, MAX_RAYS)));
901 Polyhedron_Free (a1);
902 Polyhedron_Free (a2);
905 return print_result ("cloog_domain_intersection", res);
910 * cloog_domain_difference function:
911 * This function returns a new CloogDomain structure including a polyhedral
912 * domain which is the difference of two polyhedral domains domain \ minus
913 * inside two CloogDomain structures.
914 * - November 8th 2001: first version.
916 CloogDomain *
917 cloog_domain_difference (CloogDomain * domain, CloogDomain * minus)
919 if (cloog_domain_isempty (minus))
920 return print_result ("cloog_domain_difference", cloog_domain_copy (domain));
921 else
923 Polyhedron *p1 = d2p (domain);
924 Polyhedron *p2 = d2p (minus);
925 CloogDomain *res = cloog_domain_alloc (DomainDifference (p1, p2, MAX_RAYS));
926 Polyhedron_Free (p1);
927 Polyhedron_Free (p2);
928 return print_result ("cloog_domain_difference", res);
934 * cloog_domain_addconstraints function :
935 * This function adds source's polyhedron constraints to target polyhedron: for
936 * each element of the polyhedron inside 'target' (i.e. element of the union
937 * of polyhedra) it adds the constraints of the corresponding element in
938 * 'source'.
939 * - August 10th 2002: first version.
940 * Nota bene for future : it is possible that source and target don't have the
941 * same number of elements (try iftest2 without non-shared constraint
942 * elimination in cloog_loop_separate !). This function is yet another part
943 * of the DomainSimplify patching problem...
945 CloogDomain *
946 cloog_domain_addconstraints (domain_source, domain_target)
947 CloogDomain *domain_source, *domain_target;
949 unsigned nb_constraint;
950 Value *constraints;
951 ppl_polyhedra_union *source, *target, *new, *next, *last;
953 source = cloog_domain_upol (domain_source);
954 target = cloog_domain_upol (domain_target);
956 constraints = cloog_upol_polyhedron (source)->p_Init;
957 nb_constraint = cloog_upol_nbc (source);
958 last = new = cloog_new_upol (AddConstraints (constraints, nb_constraint,
959 u2p (target), MAX_RAYS));
960 source = cloog_upol_next (source);
961 next = cloog_upol_next (target);
963 while (next)
964 { /* BUG !!! This is actually a bug. I don't know yet how to cleanly avoid
965 * the situation where source and target do not have the same number of
966 * elements. So this 'if' is an awful trick, waiting for better.
968 if (source)
970 constraints = cloog_upol_polyhedron (source)->p_Init;
971 nb_constraint = cloog_upol_nbc (source);
972 source = cloog_upol_next (source);
974 cloog_upol_set_next
975 (last, cloog_new_upol (AddConstraints (constraints, nb_constraint,
976 u2p (next), MAX_RAYS)));
977 last = cloog_upol_next (last);
978 next = cloog_upol_next (next);
981 return print_result ("cloog_domain_addconstraints", cloog_check_domain (cloog_new_domain (new)));
986 * cloog_domain_sort function:
987 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
988 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
989 * (level) is the level to consider for partial ordering (nb_par) is the
990 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
991 * integers that contains a permutation specification after call in order to
992 * apply the topological sorting.
994 void
995 cloog_domain_sort (doms, nb_pols, level, nb_par, permut)
996 CloogDomain **doms;
997 unsigned nb_pols, level, nb_par;
998 int *permut;
1000 int *time, i;
1001 Polyhedron **pols = (Polyhedron **) malloc (nb_pols * sizeof (Polyhedron *));
1003 for (i = 0; i < nb_pols; i++)
1004 pols[i] = cloog_domain_polyhedron (doms[i]);
1006 /* time is an array of (nb_pols) integers to store logical time values. We
1007 * do not use it, but it is compulsory for PolyhedronTSort.
1009 time = (int *) malloc (nb_pols * sizeof (int));
1011 /* PolyhedronTSort will fill up permut (and time). */
1012 PolyhedronTSort (pols, nb_pols, level, nb_par, time, permut, MAX_RAYS);
1014 free (pols);
1015 free (time);
1020 * cloog_domain_empty function:
1021 * This function allocates the memory space for a CloogDomain structure and
1022 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
1023 * Then it returns a pointer to the allocated space.
1024 * - June 10th 2005: first version.
1026 CloogDomain *
1027 cloog_domain_empty (int dimension)
1029 return (cloog_domain_alloc (Empty_Polyhedron (dimension)));
1033 /******************************************************************************
1034 * Structure display function *
1035 ******************************************************************************/
1039 * cloog_domain_print_structure :
1040 * this function is a more human-friendly way to display the CloogDomain data
1041 * structure, it only shows the constraint system and includes an indentation
1042 * level (level) in order to work with others print_structure functions.
1043 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
1044 * - April 24th 2005: Initial version.
1045 * - May 26th 2005: Memory leak hunt.
1046 * - June 16th 2005: (Ced) Integration in domain.c.
1048 void
1049 cloog_domain_print_structure (FILE * file, CloogDomain * domain, int level)
1051 int i;
1052 CloogMatrix *matrix;
1054 /* Go to the right level. */
1055 for (i = 0; i < level; i++)
1056 fprintf (file, "|\t");
1058 if (domain != NULL)
1060 fprintf (file, "+-- CloogDomain\n");
1062 /* Print the matrix. */
1063 matrix = cloog_upol_domain2matrix (cloog_domain_upol (domain));
1064 cloog_matrix_print_structure (file, matrix, level);
1065 cloog_matrix_free (matrix);
1067 /* A blank line. */
1068 for (i = 0; i < level + 1; i++)
1069 fprintf (file, "|\t");
1070 fprintf (file, "\n");
1072 else
1073 fprintf (file, "+-- Null CloogDomain\n");
1079 * cloog_domain_list_print function:
1080 * This function prints the content of a CloogDomainList structure into a
1081 * file (foo, possibly stdout).
1082 * - November 6th 2001: first version.
1084 void
1085 cloog_domain_list_print (FILE * foo, CloogDomainList * list)
1087 while (list != NULL)
1089 cloog_domain_print (foo, cloog_domain (list));
1090 list = cloog_next_domain (list);
1095 /******************************************************************************
1096 * Memory deallocation function *
1097 ******************************************************************************/
1101 * cloog_domain_list_free function:
1102 * This function frees the allocated memory for a CloogDomainList structure.
1103 * - November 6th 2001: first version.
1105 void
1106 cloog_domain_list_free (CloogDomainList * list)
1108 CloogDomainList *temp;
1110 while (list != NULL)
1112 temp = cloog_next_domain (list);
1113 cloog_domain_free (cloog_domain (list));
1114 free (list);
1115 list = temp;
1120 /******************************************************************************
1121 * Reading function *
1122 ******************************************************************************/
1126 * cloog_domain_read function:
1127 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
1128 * posibly stdin) and returns a pointer to a polyhedron containing the read
1129 * information.
1130 * - October 18th 2001: first version.
1132 CloogDomain *
1133 cloog_domain_read (FILE * foo)
1135 CloogMatrix *matrix;
1136 CloogDomain *domain;
1138 matrix = cloog_matrix_read (foo);
1139 domain = cloog_domain_matrix2domain (matrix);
1140 cloog_matrix_free (matrix);
1142 return print_result ("cloog_domain_read", domain);
1147 * cloog_domain_union_read function:
1148 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
1149 * returns a pointer to a Polyhedron containing the read information.
1150 * - September 9th 2002: first version.
1151 * - October 29th 2005: (debug) removal of a leak counting "correction" that
1152 * was just false since ages.
1154 CloogDomain *
1155 cloog_domain_union_read (FILE * foo)
1157 int i, nb_components;
1158 char s[MAX_STRING];
1159 CloogDomain *domain, *temp, *old;
1161 /* domain reading: nb_components (constraint matrices). */
1162 while (fgets (s, MAX_STRING, foo) == 0);
1163 while ((*s == '#' || *s == '\n') || (sscanf (s, " %d", &nb_components) < 1))
1164 fgets (s, MAX_STRING, foo);
1166 if (nb_components > 0)
1167 { /* 1. first part of the polyhedra union, */
1168 domain = cloog_domain_read (foo);
1169 /* 2. and the nexts. */
1170 for (i = 1; i < nb_components; i++)
1171 { /* Leak counting is OK since next allocated domain is freed here. */
1172 temp = cloog_domain_read (foo);
1173 old = domain;
1174 domain = cloog_domain_union (temp, old);
1175 cloog_domain_free (temp);
1176 cloog_domain_free (old);
1178 return print_result ("cloog_domain_union_read", cloog_check_domain (domain));
1180 else
1181 return NULL;
1186 * cloog_domain_list_read function:
1187 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
1188 * returns a pointer to a CloogDomainList containing the read information.
1189 * - November 6th 2001: first version.
1191 CloogDomainList *
1192 cloog_domain_list_read (FILE * foo)
1194 int i, nb_pols;
1195 char s[MAX_STRING];
1196 CloogDomainList *list, *now, *next;
1199 /* We read first the number of polyhedra in the list. */
1200 while (fgets (s, MAX_STRING, foo) == 0);
1201 while ((*s == '#' || *s == '\n') || (sscanf (s, " %d", &nb_pols) < 1))
1202 fgets (s, MAX_STRING, foo);
1204 /* Then we read the polyhedra. */
1205 list = NULL;
1206 if (nb_pols > 0)
1208 list = (CloogDomainList *) malloc (sizeof (CloogDomainList));
1209 cloog_set_domain (list, cloog_domain_read (foo));
1210 cloog_set_next_domain (list, NULL);
1211 now = list;
1212 for (i = 1; i < nb_pols; i++)
1214 next = (CloogDomainList *) malloc (sizeof (CloogDomainList));
1215 cloog_set_domain (next, cloog_domain_read (foo));
1216 cloog_set_next_domain (next, NULL);
1217 cloog_set_next_domain (now, next);
1218 now = cloog_next_domain (now);
1221 return list;
1225 /******************************************************************************
1226 * Processing functions *
1227 ******************************************************************************/
1230 * cloog_domain_isempty function:
1231 * This function returns 1 if the polyhedron given as input is empty, 0
1232 * otherwise.
1233 * - October 28th 2001: first version.
1236 cloog_domain_isempty (CloogDomain * domain)
1238 if (cloog_domain_polyhedron (domain) == NULL)
1239 return 1;
1241 if (cloog_upol_next (cloog_domain_upol (domain)))
1242 return 0;
1244 return ((cloog_domain_dim (domain) < cloog_domain_nbeq (domain)) ? 1 : 0);
1248 * cloog_domain_project function:
1249 * From Quillere's LoopGen 0.4. This function returns the projection of
1250 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
1251 * pointer to the projected Polyhedron.
1252 * - nb_par is the number of parameters.
1254 * - October 27th 2001: first version.
1255 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1256 * CLooG 0.12.1).
1258 CloogDomain *
1259 cloog_domain_project_1 (CloogDomain * domain, int level, int nb_par)
1261 int row, column, nb_rows, nb_columns, difference;
1262 CloogDomain *projected_domain;
1263 CloogMatrix *matrix;
1265 nb_rows = level + nb_par + 1;
1266 nb_columns = cloog_domain_dim (domain) + 1;
1267 difference = nb_columns - nb_rows;
1269 if (difference == 0)
1270 return print_result ("cloog_domain_project", cloog_domain_copy (domain));
1272 matrix = cloog_matrix_alloc (nb_rows, nb_columns);
1274 for (row = 0; row < level; row++)
1275 for (column = 0; column < nb_columns; column++)
1276 value_set_si (matrix->p[row][column], (row == column ? 1 : 0));
1278 for (; row < nb_rows; row++)
1279 for (column = 0; column < nb_columns; column++)
1280 value_set_si (matrix->p[row][column],
1281 (row + difference == column ? 1 : 0));
1283 projected_domain = cloog_domain_image (domain, matrix);
1284 cloog_matrix_free (matrix);
1286 return print_result ("cloog_domain_project_1", cloog_check_domain (projected_domain));
1289 CloogDomain *
1290 cloog_domain_project (CloogDomain * domain, int level, int nb_par)
1292 CloogDomain *res = NULL;
1293 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
1294 int i, diff = cloog_domain_dim (domain) - level - nb_par;
1295 size_t n;
1296 ppl_dimension_type *to_remove;
1298 if (diff < 0)
1300 fprintf (stderr, "cloog_domain_project should not be called with"
1301 "cloog_domain_dim (domain) < level + nb_par");
1302 exit (1);
1305 if (diff == 0)
1306 return print_result ("cloog_domain_project", cloog_domain_copy (domain));
1308 n = diff;
1309 to_remove = (ppl_dimension_type *) malloc (n * sizeof (ppl_dimension_type));
1311 for (i = 0; i < n; i++)
1312 to_remove[i] = i + level;
1314 while (upol)
1316 ppl_Polyhedron_t ppl = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (upol));
1318 ppl_Polyhedron_remove_space_dimensions (ppl, to_remove, n);
1319 res = cloog_domain_add_domain (res, cloog_translate_ppl_polyhedron (ppl));
1320 upol = cloog_upol_next (upol);
1323 if (cloog_check_polyhedral_ops)
1324 return print_result ("cloog_domain_project",
1325 cloog_check_domains
1326 (res, cloog_domain_project_1 (domain, level, nb_par)));
1328 return print_result ("cloog_domain_project", res);
1332 * cloog_domain_extend function:
1333 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
1334 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
1335 * the (nb_par) parameters. This function does not free (domain), and returns
1336 * a new polyhedron.
1337 * - nb_par is the number of parameters.
1339 * - October 27th 2001: first version.
1340 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1341 * CLooG 0.12.1).
1343 CloogDomain *
1344 cloog_domain_extend_1 (CloogDomain * domain, int dim, int nb_par)
1346 int row, column, nb_rows, nb_columns, difference;
1347 CloogDomain *extended_domain;
1348 CloogMatrix *matrix;
1350 nb_rows = 1 + cloog_domain_dim (domain);
1351 nb_columns = dim + nb_par + 1;
1352 difference = nb_columns - nb_rows;
1354 if (difference == 0)
1355 return print_result ("cloog_domain_extend_1", cloog_domain_copy (domain));
1357 matrix = cloog_matrix_alloc (nb_rows, nb_columns);
1359 for (row = 0; row < cloog_domain_dim (domain) - nb_par; row++)
1360 for (column = 0; column < nb_columns; column++)
1361 value_set_si (matrix->p[row][column], (row == column ? 1 : 0));
1363 for (; row <= cloog_domain_dim (domain); row++)
1364 for (column = 0; column < nb_columns; column++)
1365 value_set_si (matrix->p[row][column],
1366 (row + difference == column ? 1 : 0));
1368 extended_domain = cloog_domain_preimage (domain, matrix);
1369 cloog_matrix_free (matrix);
1371 return print_result ("cloog_domain_extend_1", cloog_check_domain (extended_domain));
1374 CloogDomain *
1375 cloog_domain_extend (CloogDomain * domain, int dim, int nb_par)
1377 CloogDomain *res = NULL;
1378 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
1379 int i, k, n, diff = dim + nb_par - cloog_domain_dim (domain);
1380 ppl_dimension_type *map;
1381 ppl_dimension_type to_add = diff;
1383 if (diff == 0)
1384 return print_result ("cloog_domain_extend", cloog_domain_copy (domain));
1386 n = dim + nb_par;
1387 map = (ppl_dimension_type *) malloc (n * sizeof (ppl_dimension_type));
1389 k = cloog_domain_dim (domain) - nb_par;
1390 for (i = 0; i < k; i++)
1391 map[i] = i;
1393 k += nb_par;
1394 for (; i < k; i++)
1395 map[i] = i + diff;
1397 k += diff;
1398 for (; i < k; i++)
1399 map[i] = i - nb_par;
1401 while (upol)
1403 ppl_Polyhedron_t ppl = cloog_translate_constraint_matrix (cloog_upol_domain2matrix (upol));
1405 ppl_Polyhedron_add_space_dimensions_and_embed (ppl, to_add);
1406 ppl_Polyhedron_map_space_dimensions (ppl, map, n);
1407 res = cloog_domain_add_domain (res, cloog_translate_ppl_polyhedron (ppl));
1408 upol = cloog_upol_next (upol);
1411 if (cloog_check_polyhedral_ops)
1412 return print_result ("cloog_domain_extend",
1413 cloog_check_domains
1414 (res, cloog_domain_extend_1 (domain, dim, nb_par)));
1416 return print_result ("cloog_domain_extend", res);
1420 * cloog_domain_never_integral function:
1421 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
1422 * function returns a boolean set to 1 if there is this kind of 'never true'
1423 * constraint inside a polyhedron, 0 otherwise.
1424 * - domain is the polyhedron to check,
1426 * - November 28th 2001: first version.
1427 * - June 26th 2003: for iterators, more 'never true' constraints are found
1428 * (compare cholesky2 and vivien with a previous version),
1429 * checking for the parameters created (compare using vivien).
1430 * - June 28th 2003: Previously in loop.c and called
1431 * cloog_loop_simplify_nevertrue, now here !
1432 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1433 * CLooG 0.12.1).
1434 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
1437 cloog_domain_never_integral (CloogDomain * domain)
1439 int i, dimension, nbc;
1440 Value gcd, modulo;
1441 Polyhedron *polyhedron;
1443 if ((domain == NULL) || (cloog_domain_polyhedron (domain) == NULL))
1444 return 1;
1446 value_init_c (gcd);
1447 value_init_c (modulo);
1448 polyhedron = d2p (domain);
1449 dimension = cloog_domain_dim (domain) + 2;
1450 nbc = cloog_domain_nbconstraints (domain);
1452 /* For each constraint... */
1453 for (i = 0; i < nbc; i++)
1454 { /* If we have an equality and the scalar part is not zero... */
1455 if (value_zero_p (polyhedron->Constraint[i][0]) &&
1456 value_notzero_p (polyhedron->Constraint[i][dimension - 1]))
1457 { /* Then we check whether the scalar can be divided by the gcd of the
1458 * unknown vector (including iterators and parameters) or not. If not,
1459 * there is no integer point in the polyhedron and we return 1.
1461 Vector_Gcd (&(polyhedron->Constraint[i][1]), dimension - 2, &gcd);
1462 value_modulus (modulo,
1463 polyhedron->Constraint[i][dimension - 1],
1464 gcd);
1466 if (value_notzero_p (modulo))
1468 value_clear_c (gcd);
1469 value_clear_c (modulo);
1470 Polyhedron_Free (polyhedron);
1471 return 1;
1476 value_clear_c (gcd);
1477 value_clear_c (modulo);
1478 Polyhedron_Free (polyhedron);
1479 return (0);
1484 * cloog_domain_stride function:
1485 * This function finds the stride imposed to unknown with the column number
1486 * 'strided_level' in order to be integral. For instance, if we have a
1487 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
1488 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
1489 * the unknown i. The function returns the imposed stride in a parameter field.
1490 * - domain is the set of constraint we have to consider,
1491 * - strided_level is the column number of the unknown for which a stride have
1492 * to be found,
1493 * - looking_level is the column number of the unknown that impose a stride to
1494 * the first unknown.
1495 * - stride is the stride that is returned back as a function parameter.
1496 * - offset is the value of the constant c if the condition is of the shape
1497 * (i + c)%s = 0, s being the stride.
1499 * - June 28th 2003: first version.
1500 * - July 14th 2003: can now look for multiple striding constraints and returns
1501 * the GCD of the strides and the common offset.
1502 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1503 * CLooG 0.12.1).
1505 void
1506 cloog_domain_stride (domain, strided_level, nb_par, stride, offset)
1507 CloogDomain *domain;
1508 int strided_level, nb_par;
1509 Value *stride, *offset;
1511 int i;
1512 int n_col, n_row, rank;
1513 CloogMatrix *M;
1514 Matrix *U;
1515 Vector *V;
1516 Polyhedron *polyhedron = d2p (domain);
1517 int dimension = cloog_domain_dim (domain);
1518 int nbeq = cloog_domain_nbeq (domain);
1520 /* Look at all equalities involving strided_level and the inner
1521 * iterators. We can ignore the outer iterators and the parameters
1522 * here because the lower bound on strided_level is assumed to
1523 * be a constant.
1525 n_col = (1 + dimension - nb_par) - strided_level;
1526 for (i = 0, n_row = 0; i < nbeq; i++)
1527 if (First_Non_Zero
1528 (polyhedron->Constraint[i] + strided_level, n_col) != -1)
1529 ++n_row;
1531 M = cloog_matrix_alloc (n_row + 1, n_col + 1);
1532 for (i = 0, n_row = 0; i < nbeq; i++)
1534 if (First_Non_Zero
1535 (polyhedron->Constraint[i] + strided_level, n_col) == -1)
1536 continue;
1537 Vector_Copy (polyhedron->Constraint[i] + strided_level,
1538 M->p[n_row], n_col);
1539 value_assign (M->p[n_row][n_col],
1540 polyhedron->Constraint[i][1 + dimension]);
1541 ++n_row;
1543 value_set_si (M->p[n_row][n_col], 1);
1545 /* Then look at the general solution to the above equalities. */
1546 rank = SolveDiophantine (M, &U, &V);
1547 cloog_matrix_free (M);
1549 if (rank == -1)
1551 /* There is no solution, so the body of this loop will
1552 * never execute. We just leave the constraints alone here so
1553 * that they will ensure the body will not be executed.
1554 * We should probably propagate this information up so that
1555 * the loop can be removed entirely.
1557 value_set_si (*offset, 0);
1558 value_set_si (*stride, 1);
1560 else
1562 /* Compute the gcd of the coefficients defining strided_level. */
1563 Vector_Gcd (U->p[0], U->NbColumns, stride);
1564 value_oppose (*offset, V->p[0]);
1565 value_pmodulus (*offset, *offset, *stride);
1567 Matrix_Free (U);
1568 Vector_Free (V);
1569 Polyhedron_Free (polyhedron);
1570 return;
1575 * cloog_domain_integral_lowerbound function:
1576 * This function returns 1 if the lower bound of an iterator (such as its
1577 * column rank in the constraint set 'domain' is 'level') is integral,
1578 * 0 otherwise. If the lower bound is actually integral, the function fills
1579 * the 'lower' field with the lower bound value.
1580 * - June 29th 2003: first version.
1581 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1582 * CLooG 0.12.1).
1585 cloog_domain_integral_lowerbound (domain, level, lower)
1586 CloogDomain *domain;
1587 int level;
1588 Value *lower;
1590 int i, first_lower = 1, dimension, lower_constraint = -1, nbc;
1591 Value iterator, constant, tmp;
1592 Polyhedron *polyhedron;
1594 polyhedron = d2p (domain);
1595 dimension = cloog_domain_dim (domain);
1596 nbc = cloog_domain_nbconstraints (domain);
1598 /* We want one and only one lower bound (e.g. no equality, no maximum
1599 * calculation...).
1601 for (i = 0; i < nbc; i++)
1602 if (value_zero_p (polyhedron->Constraint[i][0])
1603 && value_notzero_p (polyhedron->Constraint[i][level]))
1605 Polyhedron_Free (polyhedron);
1606 return 0;
1609 for (i = 0; i < nbc; i++)
1610 if (value_pos_p (polyhedron->Constraint[i][level]))
1612 if (first_lower)
1614 first_lower = 0;
1615 lower_constraint = i;
1617 else
1619 Polyhedron_Free (polyhedron);
1620 return 0;
1624 if (first_lower)
1626 Polyhedron_Free (polyhedron);
1627 return 0;
1630 /* We want an integral lower bound: no other non-zero entry except the
1631 * iterator coefficient and the constant.
1633 for (i = 1; i < level; i++)
1634 if (value_notzero_p
1635 (polyhedron->Constraint[lower_constraint][i]))
1637 Polyhedron_Free (polyhedron);
1638 return 0;
1641 for (i = level + 1; i <= dimension; i++)
1642 if (value_notzero_p
1643 (polyhedron->Constraint[lower_constraint][i]))
1645 Polyhedron_Free (polyhedron);
1646 return 0;
1649 value_init_c (iterator);
1650 value_init_c (constant);
1651 value_init_c (tmp);
1653 /* If all is passed, then find the lower bound and return 1. */
1654 value_assign (iterator,
1655 polyhedron->Constraint[lower_constraint][level]);
1656 value_oppose (constant,
1657 polyhedron->Constraint[lower_constraint][dimension + 1]);
1659 value_modulus (tmp, constant, iterator);
1660 value_division (*lower, constant, iterator);
1662 if (!(value_zero_p (tmp) || value_neg_p (constant)))
1663 value_increment (*lower, *lower);
1665 value_clear_c (iterator);
1666 value_clear_c (constant);
1667 value_clear_c (tmp);
1668 Polyhedron_Free (polyhedron);
1669 return 1;
1674 * cloog_domain_lowerbound_update function:
1675 * This function updates the integral lower bound of an iterator (such as its
1676 * column rank in the constraint set 'domain' is 'level') into 'lower'.
1677 * - Jun 29th 2003: first version.
1678 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1679 * CLooG 0.12.1).
1681 void
1682 cloog_domain_lowerbound_update (domain, level, lower)
1683 CloogDomain *domain;
1684 int level;
1685 Value lower;
1687 int i;
1688 int nbc = cloog_domain_nbconstraints (domain);
1689 int dim = cloog_domain_dim (domain);
1690 Polyhedron *polyhedron = cloog_domain_polyhedron (domain);
1692 /* There is only one lower bound, the first one is the good one. */
1693 for (i = 0; i < nbc; i++)
1694 if (value_pos_p (polyhedron->Constraint[i][level]))
1696 value_set_si (polyhedron->Constraint[i][level], 1);
1697 value_oppose (polyhedron->Constraint[i][dim + 1], lower);
1698 break;
1704 * cloog_domain_lazy_equal function:
1705 * This function returns 1 if the domains given as input are the same, 0 if it
1706 * is unable to decide. This function makes an entry-to-entry comparison between
1707 * the constraint systems, if all the entries are the same, the domains are
1708 * obviously the same and it returns 1, at the first difference, it returns 0.
1709 * This is a very fast way to verify this property. It has been shown (with the
1710 * CLooG benchmarks) that operations on equal domains are 17% of all the
1711 * polyhedral computations. For 75% of the actually identical domains, this
1712 * function answer that they are the same and allow to give immediately the
1713 * trivial solution instead of calling the heavy general functions of PolyLib.
1714 * - August 22th 2003: first version.
1715 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1716 * CLooG 0.12.1).
1719 cloog_domain_lazy_equal (CloogDomain * d1, CloogDomain * d2)
1721 int i, nb_elements;
1722 ppl_polyhedra_union *u1 = cloog_domain_upol (d1);
1723 ppl_polyhedra_union *u2 = cloog_domain_upol (d2);
1725 while (u1 && u2)
1727 if ((cloog_upol_nbc (u1) != cloog_upol_nbc (u2)) ||
1728 (cloog_upol_dim (u1) != cloog_upol_dim (u2)))
1729 return 0;
1731 nb_elements =
1732 cloog_upol_nbc (u1) * (cloog_upol_dim (u1) + 2);
1734 for (i = 0; i < nb_elements; i++)
1735 if (value_ne (cloog_upol_polyhedron (u1)->p_Init[i],
1736 cloog_upol_polyhedron (u2)->p_Init[i]))
1737 return 0;
1739 u1 = cloog_upol_next (u1);
1740 u2 = cloog_upol_next (u2);
1743 if (u1 || u2)
1744 return 0;
1746 return 1;
1751 * cloog_domain_lazy_block function:
1752 * This function returns 1 if the two domains d1 and d2 given as input are the
1753 * same (possibly except for a dimension equal to a constant where we accept
1754 * a difference of 1) AND if we are sure that there are no other domain in
1755 * the code generation problem that may put integral points between those of
1756 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
1757 * safely consider the two domains as only one with two statements (a block) ?".
1758 * This function is lazy: it asks for very standard scattering representation
1759 * (only one constraint per dimension which is an equality, and the constraints
1760 * are ordered per dimension depth: the left hand side of the constraint matrix
1761 * is the identity) and will answer NO at the very first problem.
1762 * - d1 and d2 are the two domains to check for blocking,
1763 * - scattering is the linked list of all domains,
1764 * - scattdims is the total number of scattering dimentions.
1766 * - April 30th 2005: beginning
1767 * - June 9th 2005: first working version.
1768 * - June 10th 2005: debugging.
1769 * - June 21rd 2005: Adaptation for GMP.
1770 * - October 16th 2005: (debug) some false blocks have been removed.
1773 cloog_domain_lazy_block (d1, d2, scattering, scattdims)
1774 CloogDomain *d1, *d2;
1775 CloogDomainList *scattering;
1776 int scattdims;
1778 int i, j, difference = 0, different_constraint = 0, nbc;
1779 int dim1, dim2;
1780 Value date1, date2, date3, temp;
1781 Polyhedron *p1, *p2;
1783 /* Some basic checks: we only accept convex domains, with same constraint
1784 * and dimension numbers.
1786 if (!cloog_domain_isconvex (d1) || !cloog_domain_isconvex (d2) ||
1787 (cloog_domain_nbconstraints (d1) != cloog_domain_nbconstraints (d2)) ||
1788 (cloog_domain_dim (d1) != cloog_domain_dim (d2)))
1789 return 0;
1791 p1 = d2p (d1);
1792 p2 = d2p (d2);
1793 nbc = cloog_domain_nbconstraints (d1);
1794 dim1 = cloog_domain_dim (d1);
1795 dim2 = cloog_domain_dim (d2);
1797 /* There should be only one difference between the two domains, it
1798 * has to be at the constant level and the difference must be of +1,
1799 * moreover, after the difference all domain coefficient has to be 0.
1800 * The matrix shape is:
1802 * |===========|=====|<- 0 line
1803 * |===========|=====|
1804 * |===========|====?|<- different_constraint line (found here)
1805 * |===========|0000=|
1806 * |===========|0000=|<- pX->NbConstraints line
1807 * ^ ^ ^
1808 * | | |
1809 * | | (pX->Dimension + 2) column
1810 * | scattdims column
1811 * 0 column
1814 value_init_c (temp);
1815 for (i = 0; i < nbc; i++)
1817 if (difference == 0)
1818 { /* All elements except scalar must be equal. */
1819 for (j = 0; j < dim1 + 1; j++)
1820 if (value_ne (p1->Constraint[i][j],
1821 p2->Constraint[i][j]))
1823 value_clear_c (temp);
1824 Polyhedron_Free (p1);
1825 Polyhedron_Free (p2);
1826 return 0;
1828 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
1829 if (value_ne (p1->Constraint[i][j],
1830 p2->Constraint[i][j]))
1832 value_increment (temp, p2->Constraint[i][j]);
1833 if (value_ne (p1->Constraint[i][j], temp))
1835 value_clear_c (temp);
1836 Polyhedron_Free (p1);
1837 Polyhedron_Free (p2);
1838 return 0;
1840 else
1842 difference = 1;
1843 different_constraint = i;
1847 else
1848 { /* Scattering coefficients must be equal. */
1849 for (j = 0; j < (scattdims + 1); j++)
1850 if (value_ne (p1->Constraint[i][j],
1851 p2->Constraint[i][j]))
1853 value_clear_c (temp);
1854 Polyhedron_Free (p1);
1855 Polyhedron_Free (p2);
1856 return 0;
1859 /* Domain coefficients must be 0. */
1860 for (; j < dim1 + 1; j++)
1861 if (value_notzero_p (p1->Constraint[i][j])
1862 || value_notzero_p (p2->Constraint[i][j]))
1864 value_clear_c (temp);
1865 Polyhedron_Free (p1);
1866 Polyhedron_Free (p2);
1867 return 0;
1870 /* Scalar must be equal. */
1871 if (value_ne (p1->Constraint[i][j],
1872 p2->Constraint[i][j]))
1874 value_clear_c (temp);
1875 Polyhedron_Free (p1);
1876 Polyhedron_Free (p2);
1877 return 0;
1881 value_clear_c (temp);
1883 /* If the domains are exactly the same, this is a block. */
1884 if (difference == 0)
1886 Polyhedron_Free (p1);
1887 Polyhedron_Free (p2);
1888 return 1;
1891 /* Now a basic check that the constraint with the difference is an
1892 * equality of a dimension with a constant.
1894 for (i = 0; i <= different_constraint; i++)
1895 if (value_notzero_p (p1->Constraint[different_constraint][i]))
1897 Polyhedron_Free (p1);
1898 Polyhedron_Free (p2);
1899 return 0;
1902 if (value_notone_p (p1->Constraint[different_constraint][different_constraint + 1]))
1904 Polyhedron_Free (p1);
1905 Polyhedron_Free (p2);
1906 return 0;
1909 for (i = different_constraint + 2; i < dim1 + 1; i++)
1910 if (value_notzero_p (p1->Constraint[different_constraint][i]))
1912 Polyhedron_Free (p1);
1913 Polyhedron_Free (p2);
1914 return 0;
1917 /* For the moment, d1 and d2 are a block candidate. There remains to check
1918 * that there is no other domain that may put an integral point between
1919 * them. In our lazy test we ensure this property by verifying that the
1920 * constraint matrices have a very strict shape: let us consider that the
1921 * dimension with the difference is d. Then the first d dimensions are
1922 * defined in their depth order using equalities (thus the first column begins
1923 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
1924 * the remaining simensions). If a domain can put integral points between the
1925 * domains of the block candidate, this means that the other entries on the
1926 * first d constraints are equal to those of d1 or d2. Thus we are looking for
1927 * such a constraint system, if it exists d1 and d2 is considered to not be
1928 * a block, it is a bock otherwise.
1930 * 1. Only equalities (for the first different_constraint+1 lines).
1931 * | 2. Must be the identity.
1932 * | | 3. Must be zero.
1933 * | | | 4. Elements are equal, the last one is either date1 or 2.
1934 * | | | |
1935 * | /-\ /---\ /---\
1936 * |0|100|00000|=====|<- 0 line
1937 * |0|010|00000|=====|
1938 * |0|001|00000|====?|<- different_constraint line
1939 * |*|***|*****|*****|
1940 * |*|***|*****|*****|<- pX->NbConstraints line
1941 * ^ ^ ^ ^
1942 * | | | |
1943 * | | | (pX->Dimension + 2) column
1944 * | | scattdims column
1945 * | different_constraint+1 column
1946 * 0 column
1949 /* Step 1 and 2. This is only necessary to check one domain because
1950 * we checked that they are equal on this part before.
1952 for (i = 0; i <= different_constraint; i++)
1954 for (j = 0; j < i + 1; j++)
1955 if (value_notzero_p (p1->Constraint[i][j]))
1957 Polyhedron_Free (p1);
1958 Polyhedron_Free (p2);
1959 return 0;
1962 if (value_notone_p (p1->Constraint[i][i + 1]))
1964 Polyhedron_Free (p1);
1965 Polyhedron_Free (p2);
1966 return 0;
1969 for (j = i + 2; j <= different_constraint + 1; j++)
1970 if (value_notzero_p (p1->Constraint[i][j]))
1972 Polyhedron_Free (p1);
1973 Polyhedron_Free (p2);
1974 return 0;
1978 /* Step 3. */
1979 for (i = 0; i <= different_constraint; i++)
1980 for (j = different_constraint + 2; j <= scattdims; j++)
1981 if (value_notzero_p (p1->Constraint[i][j]))
1983 Polyhedron_Free (p1);
1984 Polyhedron_Free (p2);
1985 return 0;
1988 value_init_c (date1);
1989 value_init_c (date2);
1990 value_init_c (date3);
1992 /* Now we have to check that the two different dates are unique. */
1993 value_assign (date1, p1->Constraint[different_constraint][dim1 + 1]);
1994 value_assign (date2, p2->Constraint[different_constraint][dim2 + 1]);
1996 /* Step 4. We check all domains except d1 and d2 and we look for at least
1997 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
1999 while (scattering != NULL)
2001 if ((cloog_domain (scattering) != d1)
2002 && (cloog_domain (scattering) != d2))
2004 CloogDomain *d3 = cloog_domain (scattering);
2005 Polyhedron *p3 = d2p (d3);
2006 int dim3 = cloog_domain_dim (d3);
2008 value_assign (date3,
2009 p3->Constraint[different_constraint][dim3 + 1]);
2010 difference = 0;
2012 if (value_ne (date3, date2) && value_ne (date3, date1))
2013 difference = 1;
2015 for (i = 0; (i < different_constraint) && (!difference); i++)
2016 for (j = 0; (j < dim3 + 2) && !difference; j++)
2017 if (value_ne
2018 (p1->Constraint[i][j],
2019 p3->Constraint[i][j]))
2020 difference = 1;
2022 for (j = 0; (j < dim3 + 1) && !difference; j++)
2023 if (value_ne
2024 (p1->Constraint[different_constraint][j],
2025 p3->Constraint[different_constraint][j]))
2026 difference = 1;
2028 Polyhedron_Free (p3);
2029 if (!difference)
2031 value_clear_c (date1);
2032 value_clear_c (date2);
2033 value_clear_c (date3);
2034 Polyhedron_Free (p1);
2035 Polyhedron_Free (p2);
2036 return 0;
2040 scattering = cloog_next_domain (scattering);
2043 Polyhedron_Free (p1);
2044 Polyhedron_Free (p2);
2045 value_clear_c (date1);
2046 value_clear_c (date2);
2047 value_clear_c (date3);
2048 return 1;
2053 * cloog_domain_lazy_disjoint function:
2054 * This function returns 1 if the domains given as input are disjoint, 0 if it
2055 * is unable to decide. This function finds the unknown with fixed values in
2056 * both domains (on a given constraint, their column entry is not zero and
2057 * only the constant coefficient can be different from zero) and verify that
2058 * their values are the same. If not, the domains are obviously disjoint and
2059 * it returns 1, if there is not such case it returns 0. This is a very fast
2060 * way to verify this property. It has been shown (with the CLooG benchmarks)
2061 * that operations on disjoint domains are 36% of all the polyhedral
2062 * computations. For 94% of the actually identical domains, this
2063 * function answer that they are disjoint and allow to give immediately the
2064 * trivial solution instead of calling the heavy general functions of PolyLib.
2065 * - August 22th 2003: first version.
2066 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
2067 * CLooG 0.12.1).
2070 cloog_domain_lazy_disjoint (CloogDomain * d1, CloogDomain * d2)
2072 int i1, j1, i2, j2, scat_dim, nbc1, nbc2;
2073 int dim1, dim2;
2074 Value scat_val;
2075 Polyhedron *p1, *p2;
2077 if (!cloog_domain_isconvex (d1) || !cloog_domain_isconvex (d2))
2078 return 0;
2080 p1 = d2p (d1);
2081 p2 = d2p (d2);
2082 nbc1 = cloog_domain_nbconstraints (d1);
2083 nbc2 = cloog_domain_nbconstraints (d2);
2084 dim1 = cloog_domain_dim (d1);
2085 dim2 = cloog_domain_dim (d2);
2086 value_init_c (scat_val);
2088 for (i1 = 0; i1 < nbc1; i1++)
2090 if (value_notzero_p (p1->Constraint[i1][0]))
2091 continue;
2093 scat_dim = 1;
2094 while (value_zero_p (p1->Constraint[i1][scat_dim]) &&
2095 (scat_dim < dim1))
2096 scat_dim++;
2098 if (value_notone_p (p1->Constraint[i1][scat_dim]))
2099 continue;
2100 else
2102 for (j1 = scat_dim + 1; j1 <= dim1; j1++)
2103 if (value_notzero_p (p1->Constraint[i1][j1]))
2104 break;
2106 if (j1 != dim1 + 1)
2107 continue;
2109 value_assign (scat_val,
2110 p1->Constraint[i1][dim1 + 1]);
2112 for (i2 = 0; i2 < nbc2; i2++)
2114 for (j2 = 0; j2 < scat_dim; j2++)
2115 if (value_notzero_p (p2->Constraint[i2][j2]))
2116 break;
2118 if ((j2 != scat_dim)
2120 value_notone_p (p2->Constraint[i2][scat_dim]))
2121 continue;
2123 for (j2 = scat_dim + 1; j2 < dim2; j2++)
2124 if (value_notzero_p (p2->Constraint[i2][j2]))
2125 break;
2127 if (j2 != dim2)
2128 continue;
2130 if (value_ne
2131 (p2->Constraint[i2][dim2 + 1], scat_val))
2133 value_clear_c (scat_val);
2134 return 1;
2140 value_clear_c (scat_val);
2141 Polyhedron_Free (p1);
2142 Polyhedron_Free (p2);
2143 return 0;
2148 * cloog_domain_list_lazy_same function:
2149 * This function returns 1 if two domains in the list are the same, 0 if it
2150 * is unable to decide.
2151 * - February 9th 2004: first version.
2154 cloog_domain_list_lazy_same (CloogDomainList * list)
2155 { /*int i=1, j=1 ; */
2156 CloogDomainList *current, *next;
2158 current = list;
2159 while (current != NULL)
2161 next = cloog_next_domain (current);
2162 /*j=i+1; */
2163 while (next != NULL)
2165 if (cloog_domain_lazy_equal (cloog_domain (current),
2166 cloog_domain (next)))
2167 { /*printf("Same domains: %d and %d\n",i,j) ; */
2168 return 1;
2170 /*j++ ; */
2171 next = cloog_next_domain (next);
2173 /*i++ ; */
2174 current = cloog_next_domain (current);
2177 return 0;
2181 * cloog_domain_cut_first function:
2182 * this function returns a CloogDomain structure with everything except the
2183 * first part of the polyhedra union of the input domain as domain. After a call
2184 * to this function, there remains in the CloogDomain structure provided as
2185 * input only the first part of the original polyhedra union.
2186 * - April 20th 2005: first version, extracted from different part of loop.c.
2188 CloogDomain *
2189 cloog_domain_cut_first (CloogDomain * domain)
2191 CloogDomain *rest;
2193 if (domain && cloog_domain_polyhedron (domain))
2195 if (!cloog_upol_next (cloog_domain_upol (domain)))
2196 return NULL;
2198 rest = cloog_new_domain (cloog_upol_next (cloog_domain_upol (domain)));
2199 cloog_upol_set_next (cloog_domain_upol (domain), NULL);
2201 else
2202 rest = NULL;
2204 return print_result ("cloog_domain_cut_first", cloog_check_domain (rest));
2209 * cloog_domain_lazy_isscalar function:
2210 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
2211 * is scalar, this means that the only constraint on this dimension must have
2212 * the shape "x.dimension + scalar = 0" with x an integral variable. This
2213 * function is lazy since we only accept x=1 (further calculations are easier
2214 * in this way).
2215 * - June 14th 2005: first version.
2216 * - June 21rd 2005: Adaptation for GMP.
2219 cloog_domain_lazy_isscalar (CloogDomain * domain, int dimension)
2221 int i, j;
2222 Polyhedron *polyhedron = d2p (domain);
2223 int nbc = cloog_domain_nbconstraints (domain);
2224 int dim = cloog_domain_dim (domain);
2226 /* For each constraint... */
2227 for (i = 0; i < nbc; i++)
2228 { /* ...if it is concerned by the potentially scalar dimension... */
2229 if (value_notzero_p
2230 (polyhedron->Constraint[i][dimension + 1]))
2231 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
2232 for (j = 0; j <= dimension; j++)
2233 if (value_notzero_p (polyhedron->Constraint[i][j]))
2235 Polyhedron_Free (polyhedron);
2236 return 0;
2239 if (value_notone_p
2240 (polyhedron->Constraint[i][dimension + 1]))
2242 Polyhedron_Free (polyhedron);
2243 return 0;
2246 for (j = dimension + 2; j < dim + 1; j++)
2247 if (value_notzero_p (polyhedron->Constraint[i][j]))
2249 Polyhedron_Free (polyhedron);
2250 return 0;
2255 Polyhedron_Free (polyhedron);
2256 return 1;
2261 * cloog_domain_scalar function:
2262 * when we call this function, we know that "dimension" is a scalar dimension,
2263 * this function finds the scalar value in "domain" and returns it in "value".
2264 * - June 30th 2005: first version.
2266 void
2267 cloog_domain_scalar (CloogDomain * domain, int dimension, Value * value)
2269 int i;
2270 Polyhedron *polyhedron = d2p (domain);
2271 int nbc = cloog_domain_nbconstraints (domain);
2272 int dim = cloog_domain_dim (domain);
2274 /* For each constraint... */
2275 for (i = 0; i < nbc; i++)
2276 { /* ...if it is the equality defining the scalar dimension... */
2277 if (value_notzero_p
2278 (polyhedron->Constraint[i][dimension + 1])
2279 && value_zero_p (polyhedron->Constraint[i][0]))
2280 { /* ...Then send the scalar value. */
2281 value_assign (*value, polyhedron->Constraint[i][dim + 1]);
2282 value_oppose (*value, *value);
2283 Polyhedron_Free (polyhedron);
2284 return;
2288 /* We should have found a scalar value: if not, there is an error. */
2289 fprintf (stderr, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
2290 dimension);
2291 Polyhedron_Free (polyhedron);
2292 exit (0);
2297 * cloog_domain_erase_dimension function:
2298 * this function returns a CloogDomain structure builds from 'domain' where
2299 * we removed the dimension 'dimension' and every constraint considering this
2300 * dimension. This is not a projection ! Every data concerning the
2301 * considered dimension is simply erased.
2302 * - June 14th 2005: first version.
2303 * - June 21rd 2005: Adaptation for GMP.
2305 CloogDomain *
2306 cloog_domain_erase_dimension (CloogDomain * domain, int dimension)
2308 int i, j, mi, nb_dim, nbc;
2309 CloogMatrix *matrix;
2310 CloogDomain *erased;
2311 Polyhedron *polyhedron;
2313 polyhedron = d2p (domain);
2314 nb_dim = cloog_domain_dim (domain);
2315 nbc = cloog_domain_nbconstraints (domain);
2317 /* The matrix is one column less and at least one constraint less. */
2318 matrix = cloog_matrix_alloc (nbc - 1, nb_dim + 1);
2320 /* mi is the constraint counter for the matrix. */
2321 mi = 0;
2322 for (i = 0; i < nbc; i++)
2323 if (value_zero_p (polyhedron->Constraint[i][dimension + 1]))
2325 for (j = 0; j <= dimension; j++)
2326 value_assign (matrix->p[mi][j],
2327 polyhedron->Constraint[i][j]);
2329 for (j = dimension + 2; j < nb_dim + 2; j++)
2330 value_assign (matrix->p[mi][j - 1],
2331 polyhedron->Constraint[i][j]);
2333 mi++;
2336 erased = cloog_domain_matrix2domain (matrix);
2337 cloog_matrix_free (matrix);
2339 Polyhedron_Free (polyhedron);
2340 return print_result ("cloog_domain_erase_dimension", cloog_check_domain (erased));
2343 /* Number of polyhedra inside the union of disjoint polyhedra. */
2345 unsigned
2346 cloog_domain_nb_polyhedra (CloogDomain * domain)
2348 unsigned res = 0;
2349 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
2351 while (upol)
2353 res++;
2354 upol = cloog_upol_next (upol);
2357 return res;
2360 void
2361 cloog_domain_print_polyhedra (FILE * foo, CloogDomain * domain)
2363 ppl_polyhedra_union *upol = cloog_domain_upol (domain);
2365 while (upol != NULL)
2367 CloogMatrix *matrix = cloog_upol_domain2matrix (upol);
2368 cloog_matrix_print (foo, matrix);
2369 cloog_matrix_free (matrix);
2370 upol = cloog_upol_next (upol);
2374 void
2375 debug_cloog_domain (CloogDomain *domain)
2377 cloog_domain_print_polyhedra (stderr, domain);
2380 void
2381 debug_cloog_matrix (CloogMatrix *m)
2383 cloog_matrix_print (stderr, m);