perform special options tests in a loop
[cloog.git] / source / domain.c
blobee2919511ef1b540d5b4499408037796997679e6
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 !
40 # include <stdlib.h>
41 # include <stdio.h>
42 # include <ctype.h>
43 # include "../include/cloog/cloog.h"
46 /**
47 * The maximal number of rays allowed to be allocated by PolyLib. In fact since
48 * version 5.20, PolyLib automatically tune the number of rays by multiplying
49 * by 2 this number each time the maximum is reached. For unknown reasons
50 * PolyLib makes a segmentation fault if this number is too small. If this
51 * number is too small, performances will be reduced, if it is too high, memory
52 * will be saturated. Note that the option "-rays X" set this number to X.
54 int MAX_RAYS = 50 ;
57 /******************************************************************************
58 * Memory leaks hunting *
59 ******************************************************************************/
62 /**
63 * These functions and global variables are devoted to memory leaks hunting: we
64 * want to know at each moment how many Polyhedron structures had been allocated
65 * (cloog_domain_allocated) and how many had been freed (cloog_domain_freed).
66 * Each time a Polyhedron structure is allocated, a call to the function
67 * cloog_domain_leak_up() must be carried out, and respectively
68 * cloog_domain_leak_down() when a Polyhedron structure is freed. The special
69 * variable cloog_domain_max gives the maximal number of Polyhedron structures
70 * simultaneously alive (i.e. allocated and non-freed) in memory.
71 * - July 3rd->11th 2003: first version (memory leaks hunt and correction).
75 int cloog_domain_allocated = 0 ;
76 int cloog_domain_freed = 0 ;
77 int cloog_domain_max = 0 ;
80 static void cloog_domain_leak_up()
81 { cloog_domain_allocated ++ ;
82 if ((cloog_domain_allocated-cloog_domain_freed) > cloog_domain_max)
83 cloog_domain_max = cloog_domain_allocated - cloog_domain_freed ;
87 static void cloog_domain_leak_down()
88 { cloog_domain_freed ++ ;
92 /* The same for Value variables since in GMP mode they have to be freed. */
93 int cloog_value_allocated = 0 ;
94 int cloog_value_freed = 0 ;
95 int cloog_value_max = 0 ;
98 void cloog_value_leak_up()
99 { cloog_value_allocated ++ ;
100 if ((cloog_value_allocated-cloog_value_freed) > cloog_value_max)
101 cloog_value_max = cloog_value_allocated - cloog_value_freed ;
105 void cloog_value_leak_down()
106 { cloog_value_freed ++ ;
110 /******************************************************************************
111 * PolyLib interface *
112 ******************************************************************************/
115 /* CLooG makes an intensive use of polyhedral operations and the PolyLib do
116 * the job. Here are the interfaces to all the PolyLib calls (CLooG uses 19
117 * PolyLib functions), with or without some adaptations. If another polyhedral
118 * library can be used, only these functions have to be changed.
119 * - April 16th 2005: Since PolyLib 5.20, compacting is no more useful and have
120 * been removed. The direct use of the PolyLib's Polyhedron
121 * data structure is also replaced with the CloogDomain data
122 * structure that includes the Polyhedron and an additional
123 * counter on how many pointers point on this structure.
124 * This allows to save memory (cloog_domain_copy now only
125 * increment the counter) while memory leaks are avoided (the
126 * function cloog_domain_free decrements the counter and
127 * actually frees the data structure only when its value
128 * is 0).
133 * cloog_domain_matrix2domain function:
134 * Given a matrix of constraints (matrix), this function constructs and returns
135 * the corresponding domain (i.e. the CloogDomain structure including the
136 * polyhedron with its double representation: constraint matrix and the set of
137 * rays).
139 CloogDomain * cloog_domain_matrix2domain(CloogMatrix * matrix)
140 { return (cloog_domain_alloc(Constraints2Polyhedron(matrix,MAX_RAYS))) ;
145 * cloog_domain_domain2matrix function:
146 * Given a polyhedron (in domain), this function returns its corresponding
147 * matrix of constraints.
149 CloogMatrix * cloog_domain_domain2matrix(CloogDomain * domain)
151 return cloog_matrix_matrix(Polyhedron2Constraints(domain->polyhedron));
156 * cloog_domain_print function:
157 * This function prints the content of a CloogDomain structure (domain) into
158 * a file (foo, possibly stdout).
160 void cloog_domain_print(FILE * foo, CloogDomain * domain)
161 { Polyhedron_Print(foo,P_VALUE_FMT,domain->polyhedron) ;
162 fprintf(foo,"Number of active references: %d\n",domain->references) ;
167 * cloog_polyhedron_print function:
168 * This function prints the content of a Polyhedron structure (polyhedron) into
169 * a file (foo, possibly stdout). Just there as a development facility.
171 void cloog_polyhedron_print(FILE * foo, Polyhedron * polyhedron)
172 { Polyhedron_Print(foo,P_VALUE_FMT,polyhedron) ;
177 * cloog_domain_free function:
178 * This function frees the allocated memory for a CloogDomain structure
179 * (domain). It decrements the number of active references to this structure,
180 * if there are no more references on the structure, it frees it (with the
181 * included list of polyhedra).
183 void cloog_domain_free(CloogDomain * domain)
184 { if (domain != NULL)
185 { domain->references -- ;
187 if (domain->references == 0)
188 { if (domain->polyhedron != NULL)
189 { cloog_domain_leak_down() ;
190 Domain_Free(domain->polyhedron) ;
192 free(domain) ;
199 * cloog_domain_copy function:
200 * This function returns a copy of a CloogDomain structure (domain). To save
201 * memory this is not a memory copy but we increment a counter of active
202 * references inside the structure, then return a pointer to that structure.
204 CloogDomain * cloog_domain_copy(CloogDomain * domain)
205 { domain->references ++ ;
206 return domain ;
211 * cloog_domain_image function:
212 * This function returns a CloogDomain structure such that the included
213 * polyhedral domain is computed from the former one into another
214 * domain according to a given affine mapping function (mapping).
216 CloogDomain * cloog_domain_image(CloogDomain * domain, CloogMatrix * mapping)
217 { return (cloog_domain_alloc(DomainImage(domain->polyhedron,mapping,MAX_RAYS)));
222 * cloog_domain_preimage function:
223 * Given a polyhedral domain (polyhedron) inside a CloogDomain structure and a
224 * mapping function (mapping), this function returns a new CloogDomain structure
225 * with a polyhedral domain which when transformed by mapping function (mapping)
226 * gives (polyhedron).
228 CloogDomain * cloog_domain_preimage(CloogDomain * domain, CloogMatrix * mapping)
229 { return (cloog_domain_alloc(DomainPreimage(domain->polyhedron,
230 mapping,MAX_RAYS))) ;
235 * cloog_domain_convex function:
236 * Given a polyhedral domain (polyhedron), this function concatenates the lists
237 * of rays and lines of the two (or more) polyhedra in the domain into one
238 * combined list, and find the set of constraints which tightly bound all of
239 * those objects. It returns the corresponding polyhedron.
241 CloogDomain * cloog_domain_convex(CloogDomain * domain)
242 { return (cloog_domain_alloc(DomainConvex(domain->polyhedron,MAX_RAYS)));
247 * cloog_domain_simplified_hull:
248 * Given a list (union) of polyhedra, this function returns a single
249 * polyhedron that contains this union and uses only contraints that
250 * appear in one or more of the polyhedra in the list.
252 * We simply iterate over all constraints of all polyhedra and test
253 * whether all rays of the other polyhedra satisfy/saturate the constraint.
255 static CloogDomain *cloog_domain_simplified_hull(CloogDomain * domain)
257 int dim = cloog_domain_dimension(domain);
258 int i, j, k, l;
259 int nb_pol = 0, nb_constraints = 0;
260 Polyhedron *P;
261 CloogMatrix **rays, *matrix;
262 Value tmp;
263 CloogDomain *bounds;
265 value_init(tmp);
266 for (P = domain->polyhedron; P; P = P->next) {
267 ++nb_pol;
268 nb_constraints += P->NbConstraints;
270 matrix = cloog_matrix_alloc(nb_constraints, 1 + dim + 1);
271 nb_constraints = 0;
272 rays = (CloogMatrix **)malloc(nb_pol * sizeof(CloogMatrix*));
273 for (P = domain->polyhedron, i = 0; P; P = P->next, ++i)
274 rays[i] = Polyhedron2Rays(P);
276 for (P = domain->polyhedron, i = 0; P; P = P->next, ++i) {
277 CloogMatrix *constraints = Polyhedron2Constraints(P);
278 for (j = 0; j < constraints->NbRows; ++j) {
279 for (k = 0; k < nb_pol; ++k) {
280 if (i == k)
281 continue;
282 for (l = 0; l < rays[k]->NbRows; ++l) {
283 Inner_Product(constraints->p[j]+1, rays[k]->p[l]+1, dim+1, &tmp);
284 if (value_neg_p(tmp))
285 break;
286 if ((value_zero_p(constraints->p[j][0]) ||
287 value_zero_p(rays[k]->p[l][0])) && value_pos_p(tmp))
288 break;
290 if (l < rays[k]->NbRows)
291 break;
293 if (k == nb_pol)
294 Vector_Copy(constraints->p[j], matrix->p[nb_constraints++], 1+dim+1);
296 Matrix_Free(constraints);
299 for (P = domain->polyhedron, i = 0; P; P = P->next, ++i)
300 Matrix_Free(rays[i]);
301 free(rays);
302 value_clear(tmp);
304 matrix->NbRows = nb_constraints;
305 bounds = cloog_domain_matrix2domain(matrix);
306 cloog_matrix_free(matrix);
308 return bounds;
313 * cloog_domain_simple_convex:
314 * Given a list (union) of polyhedra, this function returns a "simple"
315 * convex hull of this union. In particular, the constraints of the
316 * the returned polyhedron consist of (parametric) lower and upper
317 * bounds on individual variables and constraints that appear in the
318 * original polyhedra.
320 * nb_par is the number of parameters of the domain.
322 CloogDomain * cloog_domain_simple_convex(CloogDomain * domain, int nb_par)
324 int i;
325 int dim = cloog_domain_dimension(domain) - nb_par;
326 CloogDomain *convex = NULL;
328 if (cloog_domain_isconvex(domain))
329 return cloog_domain_copy(domain);
331 for (i = 0; i < dim; ++i) {
332 CloogDomain *bounds = cloog_domain_bounds(domain, i, nb_par);
334 if (!convex)
335 convex = bounds;
336 else {
337 CloogDomain *temp = cloog_domain_intersection(convex, bounds);
338 cloog_domain_free(bounds);
339 cloog_domain_free(convex);
340 convex = temp;
343 if (dim > 1) {
344 CloogDomain *temp, *bounds;
346 bounds = cloog_domain_simplified_hull(domain);
347 temp = cloog_domain_intersection(convex, bounds);
348 cloog_domain_free(bounds);
349 cloog_domain_free(convex);
350 convex = temp;
353 return convex;
358 * cloog_domain_simplify function:
359 * Given two polyhedral domains (pol1) and (pol2) inside two CloogDomain
360 * structures, this function finds the largest domain set (or the smallest list
361 * of non-redundant constraints), that when intersected with polyhedral
362 * domain (pol2) equals (Pol1)intersect(Pol2). The output is a new CloogDomain
363 * structure with a polyhedral domain with the "redundant" constraints removed.
364 * NB: this function do not work as expected with unions of polyhedra...
366 CloogDomain * cloog_domain_simplify(CloogDomain * dom1, CloogDomain * dom2)
368 CloogMatrix *M, *M2;
369 CloogDomain *dom;
370 Polyhedron *P = dom1->polyhedron;
372 /* DomainSimplify doesn't remove all redundant equalities,
373 * so we remove them here first in case both dom1 and dom2
374 * are single polyhedra (i.e., not unions of polyhedra).
376 if (!dom1->polyhedron->next && !dom2->polyhedron->next &&
377 P->NbEq && dom2->polyhedron->NbEq) {
378 int i, row;
379 int rows = P->NbEq + dom2->polyhedron->NbEq;
380 int cols = P->Dimension+2;
381 int rank;
382 M = cloog_matrix_alloc(rows, cols);
383 M2 = cloog_matrix_alloc(P->NbConstraints, cols);
384 Vector_Copy(dom2->polyhedron->Constraint[0], M->p[0],
385 dom2->polyhedron->NbEq * cols);
386 rank = dom2->polyhedron->NbEq;
387 row = 0;
388 for (i = 0; i < P->NbEq; ++i) {
389 Vector_Copy(P->Constraint[i], M->p[rank], cols);
390 if (Gauss(M, rank+1, cols-1) > rank) {
391 Vector_Copy(P->Constraint[i], M2->p[row++], cols);
392 rank++;
395 if (row < P->NbEq) {
396 Vector_Copy(P->Constraint[P->NbEq], M2->p[row],
397 (P->NbConstraints - P->NbEq) * cols);
398 P = Constraints2Polyhedron(M2, MAX_RAYS);
400 cloog_matrix_free(M2);
401 cloog_matrix_free(M);
403 dom = cloog_domain_alloc(DomainSimplify(P, dom2->polyhedron,MAX_RAYS));
404 if (P != dom1->polyhedron)
405 Polyhedron_Free(P);
406 return dom;
411 * cloog_domain_union function:
412 * This function returns a new CloogDomain structure including a polyhedral
413 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
414 * two CloogDomain structures.
416 CloogDomain * cloog_domain_union(CloogDomain * dom1, CloogDomain * dom2)
417 { return (cloog_domain_alloc(DomainUnion(dom1->polyhedron,
418 dom2->polyhedron,MAX_RAYS))) ;
423 * cloog_domain_disjoint function:
424 * This function returns a new CloogDomain structure including a polyhedral
425 * domain represented using union of *disjoint* polyhedra (no intersection
426 * between the different union components).
428 CloogDomain * cloog_domain_disjoint(CloogDomain * dom)
429 { return (cloog_domain_alloc(Disjoint_Domain(dom->polyhedron,0,MAX_RAYS))) ;
434 * cloog_domain_intersection function:
435 * This function returns a new CloogDomain structure including a polyhedral
436 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
437 * inside two CloogDomain structures.
439 CloogDomain * cloog_domain_intersection(CloogDomain * dom1, CloogDomain * dom2)
440 { return (cloog_domain_alloc(DomainIntersection(dom1->polyhedron,
441 dom2->polyhedron,MAX_RAYS))) ;
446 * cloog_domain_difference function:
447 * This function returns a new CloogDomain structure including a polyhedral
448 * domain which is the difference of two polyhedral domains domain \ minus
449 * inside two CloogDomain structures.
450 * - November 8th 2001: first version.
452 CloogDomain * cloog_domain_difference(CloogDomain * domain, CloogDomain * minus)
453 { if (cloog_domain_isempty(minus))
454 return(cloog_domain_copy(domain)) ;
455 else
456 return (cloog_domain_alloc(DomainDifference(domain->polyhedron,
457 minus->polyhedron,MAX_RAYS))) ;
462 * cloog_domain_includes function:
463 * This function returns 1 if the polyhedral domain inside 'container' includes
464 * the polyhedral domain inside 'contents', 0 otherwise.
465 * - September 14th 2002: first version.
467 int cloog_domain_includes(CloogDomain * container, CloogDomain * contents)
468 { int is_in ;
469 Polyhedron * p1, * p2 ;
471 for (p1=container->polyhedron; p1; p1=p1->next)
472 { is_in = 0 ;
474 for (p2=contents->polyhedron; p2; p2=p2->next)
475 if (PolyhedronIncludes(p1,p2))
476 { is_in = 1 ;
477 break ;
480 if (!is_in)
481 return 0 ;
484 return 1 ;
489 * cloog_domain_addconstraints function :
490 * This function adds source's polyhedron constraints to target polyhedron: for
491 * each element of the polyhedron inside 'target' (i.e. element of the union
492 * of polyhedra) it adds the constraints of the corresponding element in
493 * 'source'.
494 * - August 10th 2002: first version.
495 * Nota bene for future : it is possible that source and target don't have the
496 * same number of elements (try iftest2 without non-shared constraint
497 * elimination in cloog_loop_separate !). This function is yet another part
498 * of the DomainSimplify patching problem...
500 CloogDomain * cloog_domain_addconstraints(domain_source, domain_target)
501 CloogDomain * domain_source, * domain_target ;
502 { unsigned nb_constraint ;
503 Value * constraints ;
504 Polyhedron * source, * target, * new, * next, * last ;
506 source = domain_source->polyhedron ;
507 target = domain_target->polyhedron ;
509 constraints = source->p_Init ;
510 nb_constraint = source->NbConstraints ;
511 source = source->next ;
512 new = AddConstraints(constraints,nb_constraint,target,MAX_RAYS) ;
513 last = new ;
514 next = target->next ;
516 while (next != NULL)
517 { /* BUG !!! This is actually a bug. I don't know yet how to cleanly avoid
518 * the situation where source and target do not have the same number of
519 * elements. So this 'if' is an awful trick, waiting for better.
521 if (source != NULL)
522 { constraints = source->p_Init ;
523 nb_constraint = source->NbConstraints ;
524 source = source->next ;
526 last->next = AddConstraints(constraints,nb_constraint,next,MAX_RAYS) ;
527 last = last->next ;
528 next = next->next ;
531 return (cloog_domain_alloc(new)) ;
536 * cloog_domain_sort function:
537 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
538 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
539 * (level) is the level to consider for partial ordering (nb_par) is the
540 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
541 * integers that contains a permutation specification after call in order to
542 * apply the topological sorting.
544 void cloog_domain_sort(pols, nb_pols, level, nb_par, permut)
545 Polyhedron ** pols ;
546 unsigned nb_pols, level, nb_par ;
547 int * permut ;
548 { int * time ;
550 /* time is an array of (nb_pols) integers to store logical time values. We
551 * do not use it, but it is compulsory for PolyhedronTSort.
553 time = (int *)malloc(nb_pols*sizeof(int)) ;
555 /* PolyhedronTSort will fill up permut (and time). */
556 PolyhedronTSort(pols,nb_pols,level,nb_par,time,permut,MAX_RAYS) ;
558 free(time) ;
563 * cloog_domain_empty function:
564 * This function allocates the memory space for a CloogDomain structure and
565 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
566 * Then it returns a pointer to the allocated space.
567 * - June 10th 2005: first version.
569 CloogDomain * cloog_domain_empty(int dimension)
570 { return (cloog_domain_alloc(Empty_Polyhedron(dimension))) ;
574 /******************************************************************************
575 * Structure display function *
576 ******************************************************************************/
580 * cloog_domain_print_structure :
581 * this function is a more human-friendly way to display the CloogDomain data
582 * structure, it only shows the constraint system and includes an indentation
583 * level (level) in order to work with others print_structure functions.
584 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
585 * - April 24th 2005: Initial version.
586 * - May 26th 2005: Memory leak hunt.
587 * - June 16th 2005: (Ced) Integration in domain.c.
589 void cloog_domain_print_structure(FILE * file, CloogDomain * domain, int level)
590 { int i ;
591 CloogMatrix * matrix ;
593 /* Go to the right level. */
594 for(i=0; i<level; i++)
595 fprintf(file,"|\t") ;
597 if (domain != NULL)
598 { fprintf(file,"+-- CloogDomain\n") ;
600 /* Print the matrix. */
601 matrix = cloog_domain_domain2matrix(domain) ;
602 cloog_matrix_print_structure(file,matrix,level) ;
603 cloog_matrix_free(matrix) ;
605 /* A blank line. */
606 for (i=0; i<level+1; i++)
607 fprintf(file,"|\t") ;
608 fprintf(file,"\n") ;
610 else
611 fprintf(file,"+-- Null CloogDomain\n") ;
617 * cloog_domain_list_print function:
618 * This function prints the content of a CloogDomainList structure into a
619 * file (foo, possibly stdout).
620 * - November 6th 2001: first version.
622 void cloog_domain_list_print(FILE * foo, CloogDomainList * list)
623 { while (list != NULL)
624 { cloog_domain_print(foo,list->domain) ;
625 list = list->next ;
630 /******************************************************************************
631 * Memory deallocation function *
632 ******************************************************************************/
636 * cloog_domain_list_free function:
637 * This function frees the allocated memory for a CloogDomainList structure.
638 * - November 6th 2001: first version.
640 void cloog_domain_list_free(CloogDomainList * list)
641 { CloogDomainList * temp ;
643 while (list != NULL)
644 { temp = list->next ;
645 cloog_domain_free(list->domain) ;
646 free(list) ;
647 list = temp ;
652 /******************************************************************************
653 * Reading function *
654 ******************************************************************************/
658 * cloog_domain_read function:
659 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
660 * posibly stdin) and returns a pointer to a polyhedron containing the read
661 * information.
662 * - October 18th 2001: first version.
664 CloogDomain * cloog_domain_read(FILE * foo)
665 { CloogMatrix * matrix ;
666 CloogDomain * domain ;
668 matrix = cloog_matrix_read(foo) ;
669 domain = cloog_domain_matrix2domain(matrix) ;
670 cloog_matrix_free(matrix) ;
672 return(domain) ;
677 * cloog_domain_union_read function:
678 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
679 * returns a pointer to a Polyhedron containing the read information.
680 * - September 9th 2002: first version.
681 * - October 29th 2005: (debug) removal of a leak counting "correction" that
682 * was just false since ages.
684 CloogDomain * cloog_domain_union_read(FILE * foo)
685 { int i, nb_components ;
686 char s[MAX_STRING] ;
687 CloogDomain * domain, * temp, * old ;
689 /* domain reading: nb_components (constraint matrices). */
690 while (fgets(s,MAX_STRING,foo) == 0) ;
691 while ((*s=='#' || *s=='\n') || (sscanf(s," %d",&nb_components)<1))
692 fgets(s,MAX_STRING,foo) ;
694 if (nb_components > 0)
695 { /* 1. first part of the polyhedra union, */
696 domain = cloog_domain_read(foo) ;
697 /* 2. and the nexts. */
698 for (i=1;i<nb_components;i++)
699 { /* Leak counting is OK since next allocated domain is freed here. */
700 temp = cloog_domain_read(foo) ;
701 old = domain ;
702 domain = cloog_domain_union(temp,old) ;
703 cloog_domain_free(temp) ;
704 cloog_domain_free(old) ;
706 return domain ;
708 else
709 return NULL ;
714 * cloog_domain_list_read function:
715 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
716 * returns a pointer to a CloogDomainList containing the read information.
717 * - November 6th 2001: first version.
719 CloogDomainList * cloog_domain_list_read(FILE * foo)
720 { int i, nb_pols ;
721 char s[MAX_STRING] ;
722 CloogDomainList * list, * now, * next ;
725 /* We read first the number of polyhedra in the list. */
726 while (fgets(s,MAX_STRING,foo) == 0) ;
727 while ((*s=='#' || *s=='\n') || (sscanf(s," %d",&nb_pols)<1))
728 fgets(s,MAX_STRING,foo) ;
730 /* Then we read the polyhedra. */
731 list = NULL ;
732 if (nb_pols > 0)
733 { list = (CloogDomainList *)malloc(sizeof(CloogDomainList)) ;
734 list->domain = cloog_domain_read(foo) ;
735 list->next = NULL ;
736 now = list ;
737 for (i=1;i<nb_pols;i++)
738 { next = (CloogDomainList *)malloc(sizeof(CloogDomainList)) ;
739 next->domain = cloog_domain_read(foo) ;
740 next->next = NULL ;
741 now->next = next ;
742 now = now->next ;
745 return(list) ;
749 /******************************************************************************
750 * Processing functions *
751 ******************************************************************************/
755 * cloog_domain_malloc function:
756 * This function allocates the memory space for a CloogDomain structure and
757 * sets its fields with default values. Then it returns a pointer to the
758 * allocated space.
759 * - November 21th 2005: first version.
761 CloogDomain * cloog_domain_malloc()
762 { CloogDomain * domain ;
764 domain = (CloogDomain *)malloc(sizeof(CloogDomain)) ;
765 if (domain == NULL)
766 { fprintf(stderr, "[CLooG]ERROR: memory overflow.\n") ;
767 exit(1) ;
769 cloog_domain_leak_up() ;
771 /* We set the various fields with default values. */
772 domain->polyhedron = NULL ;
773 domain->references = 1 ;
775 return domain ;
780 * cloog_domain_alloc function:
781 * This function allocates the memory space for a CloogDomain structure and
782 * sets its fields with those given as input. Then it returns a pointer to the
783 * allocated space.
784 * - April 19th 2005: first version.
785 * - November 21th 2005: cloog_domain_malloc use.
787 CloogDomain * cloog_domain_alloc(Polyhedron * polyhedron)
788 { CloogDomain * domain ;
790 if (polyhedron == NULL)
791 return NULL ;
792 else
793 { domain = cloog_domain_malloc() ;
794 domain->polyhedron = polyhedron ;
796 return domain ;
802 * cloog_domain_isempty function:
803 * This function returns 1 if the polyhedron given as input is empty, 0
804 * otherwise.
805 * - October 28th 2001: first version.
807 int cloog_domain_isempty(CloogDomain * domain)
808 { if (domain->polyhedron == NULL)
809 return 1 ;
811 if (domain->polyhedron->next)
812 return(0) ;
813 return((domain->polyhedron->Dimension < domain->polyhedron->NbEq) ? 1 : 0) ;
818 * cloog_domain_universe function:
819 * This function returns 1 if the polyhedron given as input describe the
820 * universe of its dimension, 0 otherwise. Nb: the NbBid field of a polyhedron
821 * gives the number of bidirectionnal rays.
822 * - November 19th 2001: first version.
824 int cloog_domain_universe(CloogDomain * domain)
825 { if (domain->polyhedron->next)
826 return(0) ;
827 return((domain->polyhedron->Dimension == domain->polyhedron->NbBid) ? 1 : 0) ;
832 * cloog_domain_project function:
833 * From Quillere's LoopGen 0.4. This function returns the projection of
834 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
835 * pointer to the projected Polyhedron.
836 * - nb_par is the number of parameters.
838 * - October 27th 2001: first version.
839 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
840 * CLooG 0.12.1).
842 CloogDomain * cloog_domain_project(CloogDomain * domain, int level, int nb_par)
843 { int row, column, nb_rows, nb_columns, difference ;
844 CloogDomain * projected_domain ;
845 CloogMatrix * matrix ;
847 nb_rows = level + nb_par + 1 ;
848 nb_columns = domain->polyhedron->Dimension + 1 ;
849 difference = nb_columns - nb_rows ;
851 if (difference == 0)
852 return(cloog_domain_copy(domain)) ;
854 matrix = cloog_matrix_alloc(nb_rows,nb_columns) ;
856 for (row=0;row<level;row++)
857 for (column=0;column<nb_columns; column++)
858 value_set_si(matrix->p[row][column],(row == column ? 1 : 0)) ;
860 for (;row<nb_rows;row++)
861 for (column=0;column<nb_columns;column++)
862 value_set_si(matrix->p[row][column],(row+difference == column ? 1 : 0)) ;
864 projected_domain = cloog_domain_image(domain,matrix) ;
865 cloog_matrix_free(matrix) ;
867 return(projected_domain) ;
872 * cloog_domain_bounds:
873 * Given a list (union) of polyhedra "domain", this function returns a single
874 * polyhedron with constraints that reflect the (parametric) lower and
875 * upper bound on dimension "dim".
877 * nb_par is the number of parameters of the domain.
879 CloogDomain * cloog_domain_bounds(CloogDomain * domain, int dim, int nb_par)
881 int row, nb_rows, nb_columns, difference;
882 CloogDomain * projected_domain, *extended_domain, *bounds;
883 CloogMatrix * matrix ;
885 nb_rows = 1 + nb_par + 1;
886 nb_columns = domain->polyhedron->Dimension + 1 ;
887 difference = nb_columns - nb_rows ;
889 if (difference == 0)
890 return(cloog_domain_convex(domain));
892 matrix = cloog_matrix_alloc(nb_rows, nb_columns);
894 value_set_si(matrix->p[0][dim], 1);
895 for (row = 1; row < nb_rows; row++)
896 value_set_si(matrix->p[row][row+difference], 1);
898 projected_domain = cloog_domain_image(domain,matrix) ;
899 extended_domain = cloog_domain_preimage(projected_domain, matrix);
900 cloog_domain_free(projected_domain);
901 cloog_matrix_free(matrix) ;
902 bounds = cloog_domain_convex(extended_domain);
903 cloog_domain_free(extended_domain);
905 return bounds;
910 * cloog_domain_extend function:
911 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
912 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
913 * the (nb_par) parameters. This function does not free (domain), and returns
914 * a new polyhedron.
915 * - nb_par is the number of parameters.
917 * - October 27th 2001: first version.
918 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
919 * CLooG 0.12.1).
921 CloogDomain * cloog_domain_extend(CloogDomain * domain, int dim, int nb_par)
922 { int row, column, nb_rows, nb_columns, difference ;
923 CloogDomain * extended_domain ;
924 CloogMatrix * matrix ;
926 nb_rows = 1 + domain->polyhedron->Dimension ;
927 nb_columns = dim + nb_par + 1 ;
928 difference = nb_columns - nb_rows ;
930 if (difference == 0)
931 return(cloog_domain_copy(domain)) ;
933 matrix = cloog_matrix_alloc(nb_rows,nb_columns) ;
935 for (row=0;row<domain->polyhedron->Dimension-nb_par;row++)
936 for (column=0;column<nb_columns;column++)
937 value_set_si(matrix->p[row][column],(row == column ? 1 : 0)) ;
939 for (;row<=domain->polyhedron->Dimension;row++)
940 for (column=0;column<nb_columns;column++)
941 value_set_si(matrix->p[row][column],(row+difference == column ? 1 : 0)) ;
943 extended_domain = cloog_domain_preimage(domain,matrix) ;
944 cloog_matrix_free(matrix) ;
946 return(extended_domain) ;
951 * cloog_domain_never_integral function:
952 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
953 * function returns a boolean set to 1 if there is this kind of 'never true'
954 * constraint inside a polyhedron, 0 otherwise.
955 * - domain is the polyhedron to check,
957 * - November 28th 2001: first version.
958 * - June 26th 2003: for iterators, more 'never true' constraints are found
959 * (compare cholesky2 and vivien with a previous version),
960 * checking for the parameters created (compare using vivien).
961 * - June 28th 2003: Previously in loop.c and called
962 * cloog_loop_simplify_nevertrue, now here !
963 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
964 * CLooG 0.12.1).
965 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
967 int cloog_domain_never_integral(CloogDomain * domain)
968 { int i, dimension ;
969 Value gcd, modulo ;
970 Polyhedron * polyhedron ;
972 if ((domain == NULL) || (domain->polyhedron == NULL))
973 return 1 ;
975 value_init_c(gcd) ;
976 value_init_c(modulo) ;
977 polyhedron = domain->polyhedron ;
978 dimension = polyhedron->Dimension + 2 ;
980 /* For each constraint... */
981 for (i=0; i<polyhedron->NbConstraints; i++)
982 { /* If we have an equality and the scalar part is not zero... */
983 if (value_zero_p(polyhedron->Constraint[i][0]) &&
984 value_notzero_p(polyhedron->Constraint[i][dimension-1]))
985 { /* Then we check whether the scalar can be divided by the gcd of the
986 * unknown vector (including iterators and parameters) or not. If not,
987 * there is no integer point in the polyhedron and we return 1.
989 Vector_Gcd(&(polyhedron->Constraint[i][1]),dimension-2,&gcd) ;
990 value_modulus(modulo,polyhedron->Constraint[i][dimension-1],gcd) ;
992 if (value_notzero_p(modulo))
993 { value_clear_c(gcd) ;
994 value_clear_c(modulo) ;
995 return 1 ;
1000 value_clear_c(gcd) ;
1001 value_clear_c(modulo) ;
1002 return(0) ;
1007 * cloog_domain_stride function:
1008 * This function finds the stride imposed to unknown with the column number
1009 * 'strided_level' in order to be integral. For instance, if we have a
1010 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
1011 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
1012 * the unknown i. The function returns the imposed stride in a parameter field.
1013 * - domain is the set of constraint we have to consider,
1014 * - strided_level is the column number of the unknown for which a stride have
1015 * to be found,
1016 * - looking_level is the column number of the unknown that impose a stride to
1017 * the first unknown.
1018 * - stride is the stride that is returned back as a function parameter.
1019 * - offset is the value of the constant c if the condition is of the shape
1020 * (i + c)%s = 0, s being the stride.
1022 * - June 28th 2003: first version.
1023 * - July 14th 2003: can now look for multiple striding constraints and returns
1024 * the GCD of the strides and the common offset.
1025 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1026 * CLooG 0.12.1).
1028 void cloog_domain_stride(domain, strided_level, nb_par, stride, offset)
1029 CloogDomain * domain ;
1030 int strided_level, nb_par ;
1031 Value * stride, * offset;
1032 { int i, dimension;
1033 Polyhedron * polyhedron ;
1034 int n_col, n_row, rank;
1035 CloogMatrix *M;
1036 Matrix *U;
1037 Vector *V;
1039 polyhedron = domain->polyhedron ;
1040 dimension = polyhedron->Dimension ;
1042 /* Look at all equalities involving strided_level and the inner
1043 * iterators. We can ignore the outer iterators and the parameters
1044 * here because the lower bound on strided_level is assumed to
1045 * be a constant.
1047 n_col = (1+dimension-nb_par) - strided_level;
1048 for (i=0, n_row=0; i < polyhedron->NbEq; i++)
1049 if (First_Non_Zero(polyhedron->Constraint[i]+strided_level, n_col) != -1)
1050 ++n_row;
1052 M = cloog_matrix_alloc(n_row+1, n_col+1);
1053 for (i=0, n_row = 0; i < polyhedron->NbEq; i++) {
1054 if (First_Non_Zero(polyhedron->Constraint[i]+strided_level, n_col) == -1)
1055 continue;
1056 Vector_Copy(polyhedron->Constraint[i]+strided_level, M->p[n_row], n_col);
1057 value_assign(M->p[n_row][n_col], polyhedron->Constraint[i][1+dimension]);
1058 ++n_row;
1060 value_set_si(M->p[n_row][n_col], 1);
1062 /* Then look at the general solution to the above equalities. */
1063 rank = SolveDiophantine(M, &U, &V);
1064 cloog_matrix_free(M);
1066 if (rank == -1) {
1067 /* There is no solution, so the body of this loop will
1068 * never execute. We just leave the constraints alone here so
1069 * that they will ensure the body will not be executed.
1070 * We should probably propagate this information up so that
1071 * the loop can be removed entirely.
1073 value_set_si(*offset, 0);
1074 value_set_si(*stride, 1);
1075 } else {
1076 /* Compute the gcd of the coefficients defining strided_level. */
1077 Vector_Gcd(U->p[0], U->NbColumns, stride);
1078 value_oppose(*offset, V->p[0]);
1079 value_pmodulus(*offset, *offset, *stride);
1081 Matrix_Free(U);
1082 Vector_Free(V);
1084 return ;
1089 * cloog_domain_integral_lowerbound function:
1090 * This function returns 1 if the lower bound of an iterator (such as its
1091 * column rank in the constraint set 'domain' is 'level') is integral,
1092 * 0 otherwise. If the lower bound is actually integral, the function fills
1093 * the 'lower' field with the lower bound value.
1094 * - June 29th 2003: first version.
1095 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1096 * CLooG 0.12.1).
1098 int cloog_domain_integral_lowerbound(domain, level, lower)
1099 CloogDomain * domain ;
1100 int level ;
1101 Value * lower ;
1102 { int i, first_lower=1, dimension, lower_constraint=-1 ;
1103 Value iterator, constant, tmp;
1104 Polyhedron * polyhedron ;
1106 polyhedron = domain->polyhedron ;
1107 dimension = polyhedron->Dimension ;
1109 /* We want one and only one lower bound (e.g. no equality, no maximum
1110 * calculation...).
1112 for (i=0; i<polyhedron->NbConstraints; i++)
1113 if (value_zero_p(polyhedron->Constraint[i][0]) &&
1114 value_notzero_p(polyhedron->Constraint[i][level]))
1115 return 0 ;
1117 for (i=0; i<polyhedron->NbConstraints; i++)
1118 if (value_pos_p(polyhedron->Constraint[i][level]))
1119 { if (first_lower)
1120 { first_lower = 0 ;
1121 lower_constraint = i ;
1123 else
1124 return 0 ;
1126 if (first_lower)
1127 return 0 ;
1129 /* We want an integral lower bound: no other non-zero entry except the
1130 * iterator coefficient and the constant.
1132 for (i=1; i<level; i++)
1133 if (value_notzero_p(polyhedron->Constraint[lower_constraint][i]))
1134 return 0 ;
1135 for (i=level+1; i<=polyhedron->Dimension; i++)
1136 if (value_notzero_p(polyhedron->Constraint[lower_constraint][i]))
1137 return 0 ;
1139 value_init_c(iterator) ;
1140 value_init_c(constant) ;
1141 value_init_c(tmp) ;
1143 /* If all is passed, then find the lower bound and return 1. */
1144 value_assign(iterator, polyhedron->Constraint[lower_constraint][level]) ;
1145 value_oppose(constant, polyhedron->Constraint[lower_constraint][dimension+1]);
1147 value_modulus(tmp, constant, iterator) ;
1148 value_division(*lower, constant, iterator) ;
1150 if (!(value_zero_p(tmp) || value_neg_p(constant)))
1151 value_increment(*lower, *lower) ;
1153 value_clear_c(iterator) ;
1154 value_clear_c(constant) ;
1155 value_clear_c(tmp) ;
1157 return 1 ;
1162 * cloog_domain_lowerbound_update function:
1163 * This function updates the integral lower bound of an iterator (such as its
1164 * column rank in the constraint set 'domain' is 'level') into 'lower'.
1165 * - Jun 29th 2003: first version.
1166 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1167 * CLooG 0.12.1).
1169 void cloog_domain_lowerbound_update(domain, level, lower)
1170 CloogDomain * domain ;
1171 int level ;
1172 Value lower ;
1173 { int i ;
1174 Polyhedron * polyhedron ;
1176 polyhedron = domain->polyhedron ;
1178 /* There is only one lower bound, the first one is the good one. */
1179 for (i=0; i<polyhedron->NbConstraints; i++)
1180 if (value_pos_p(polyhedron->Constraint[i][level]))
1181 { value_set_si(polyhedron->Constraint[i][level], 1) ;
1182 value_oppose(polyhedron->Constraint[i][polyhedron->Dimension+1], lower) ;
1183 break ;
1189 * cloog_domain_lazy_equal function:
1190 * This function returns 1 if the domains given as input are the same, 0 if it
1191 * is unable to decide. This function makes an entry-to-entry comparison between
1192 * the constraint systems, if all the entries are the same, the domains are
1193 * obviously the same and it returns 1, at the first difference, it returns 0.
1194 * This is a very fast way to verify this property. It has been shown (with the
1195 * CLooG benchmarks) that operations on equal domains are 17% of all the
1196 * polyhedral computations. For 75% of the actually identical domains, this
1197 * function answer that they are the same and allow to give immediately the
1198 * trivial solution instead of calling the heavy general functions of PolyLib.
1199 * - August 22th 2003: first version.
1200 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1201 * CLooG 0.12.1).
1203 int cloog_domain_lazy_equal(CloogDomain * d1, CloogDomain * d2)
1204 { int i, nb_elements ;
1205 Polyhedron * p1, * p2 ;
1207 p1 = d1->polyhedron ;
1208 p2 = d2->polyhedron ;
1210 while ((p1 != NULL) && (p2 != NULL))
1211 { if ((p1->NbConstraints != p2->NbConstraints) ||
1212 (p1->Dimension != p2->Dimension))
1213 return 0 ;
1215 nb_elements = p1->NbConstraints * (p1->Dimension + 2) ;
1217 for (i=0;i<nb_elements;i++)
1218 if (value_ne(p1->p_Init[i], p2->p_Init[i]))
1219 return 0 ;
1221 p1 = p1->next ;
1222 p2 = p2->next ;
1225 if ((p1 != NULL) || (p2 != NULL))
1226 return 0 ;
1228 return 1 ;
1233 * cloog_domain_lazy_block function:
1234 * This function returns 1 if the two domains d1 and d2 given as input are the
1235 * same (possibly except for a dimension equal to a constant where we accept
1236 * a difference of 1) AND if we are sure that there are no other domain in
1237 * the code generation problem that may put integral points between those of
1238 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
1239 * safely consider the two domains as only one with two statements (a block) ?".
1240 * This function is lazy: it asks for very standard scattering representation
1241 * (only one constraint per dimension which is an equality, and the constraints
1242 * are ordered per dimension depth: the left hand side of the constraint matrix
1243 * is the identity) and will answer NO at the very first problem.
1244 * - d1 and d2 are the two domains to check for blocking,
1245 * - scattering is the linked list of all domains,
1246 * - scattdims is the total number of scattering dimentions.
1248 * - April 30th 2005: beginning
1249 * - June 9th 2005: first working version.
1250 * - June 10th 2005: debugging.
1251 * - June 21rd 2005: Adaptation for GMP.
1252 * - October 16th 2005: (debug) some false blocks have been removed.
1254 int cloog_domain_lazy_block(d1, d2, scattering, scattdims)
1255 CloogDomain * d1, * d2 ;
1256 CloogDomainList * scattering ;
1257 int scattdims ;
1258 { int i, j, difference=0, different_constraint=0 ;
1259 Value date1, date2, date3, temp ;
1260 Polyhedron * p1, * p2, * p3 ;
1262 p1 = d1->polyhedron ;
1263 p2 = d2->polyhedron ;
1265 /* Some basic checks: we only accept convex domains, with same constraint
1266 * and dimension numbers.
1268 if ((p1->next != NULL) || (p2->next != NULL) ||
1269 (p1->NbConstraints != p2->NbConstraints) ||
1270 (p1->Dimension != p2->Dimension))
1271 return 0 ;
1273 /* There should be only one difference between the two domains, it
1274 * has to be at the constant level and the difference must be of +1,
1275 * moreover, after the difference all domain coefficient has to be 0.
1276 * The matrix shape is:
1278 * |===========|=====|<- 0 line
1279 * |===========|=====|
1280 * |===========|====?|<- different_constraint line (found here)
1281 * |===========|0000=|
1282 * |===========|0000=|<- pX->NbConstraints line
1283 * ^ ^ ^
1284 * | | |
1285 * | | (pX->Dimension + 2) column
1286 * | scattdims column
1287 * 0 column
1290 value_init_c(temp) ;
1291 for (i=0;i<p1->NbConstraints;i++)
1292 { if (difference == 0)
1293 { /* All elements except scalar must be equal. */
1294 for (j=0;j<(p1->Dimension + 1);j++)
1295 if (value_ne(p1->Constraint[i][j],p2->Constraint[i][j]))
1296 { value_clear_c(temp) ;
1297 return 0 ;
1299 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
1300 if (value_ne(p1->Constraint[i][j],p2->Constraint[i][j]))
1301 { value_increment(temp,p2->Constraint[i][j]) ;
1302 if (value_ne(p1->Constraint[i][j],temp))
1303 { value_clear_c(temp) ;
1304 return 0 ;
1306 else
1307 { difference = 1 ;
1308 different_constraint = i ;
1312 else
1313 { /* Scattering coefficients must be equal. */
1314 for (j=0;j<(scattdims+1);j++)
1315 if (value_ne(p1->Constraint[i][j],p2->Constraint[i][j]))
1316 { value_clear_c(temp) ;
1317 return 0 ;
1320 /* Domain coefficients must be 0. */
1321 for (;j<(p1->Dimension + 1);j++)
1322 if (value_notzero_p(p1->Constraint[i][j]) ||
1323 value_notzero_p(p2->Constraint[i][j]))
1324 { value_clear_c(temp) ;
1325 return 0 ;
1328 /* Scalar must be equal. */
1329 if (value_ne(p1->Constraint[i][j],p2->Constraint[i][j]))
1330 { value_clear_c(temp) ;
1331 return 0 ;
1335 value_clear_c(temp) ;
1337 /* If the domains are exactly the same, this is a block. */
1338 if (difference == 0)
1339 return 1 ;
1341 /* Now a basic check that the constraint with the difference is an
1342 * equality of a dimension with a constant.
1344 for (i=0;i<=different_constraint;i++)
1345 if (value_notzero_p(p1->Constraint[different_constraint][i]))
1346 return 0 ;
1348 if (value_notone_p(p1->Constraint[different_constraint]
1349 [different_constraint+1]))
1350 return 0 ;
1352 for (i=different_constraint+2;i<(p1->Dimension + 1);i++)
1353 if (value_notzero_p(p1->Constraint[different_constraint][i]))
1354 return 0 ;
1356 /* For the moment, d1 and d2 are a block candidate. There remains to check
1357 * that there is no other domain that may put an integral point between
1358 * them. In our lazy test we ensure this property by verifying that the
1359 * constraint matrices have a very strict shape: let us consider that the
1360 * dimension with the difference is d. Then the first d dimensions are
1361 * defined in their depth order using equalities (thus the first column begins
1362 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
1363 * the remaining simensions). If a domain can put integral points between the
1364 * domains of the block candidate, this means that the other entries on the
1365 * first d constraints are equal to those of d1 or d2. Thus we are looking for
1366 * such a constraint system, if it exists d1 and d2 is considered to not be
1367 * a block, it is a bock otherwise.
1369 * 1. Only equalities (for the first different_constraint+1 lines).
1370 * | 2. Must be the identity.
1371 * | | 3. Must be zero.
1372 * | | | 4. Elements are equal, the last one is either date1 or 2.
1373 * | | | |
1374 * | /-\ /---\ /---\
1375 * |0|100|00000|=====|<- 0 line
1376 * |0|010|00000|=====|
1377 * |0|001|00000|====?|<- different_constraint line
1378 * |*|***|*****|*****|
1379 * |*|***|*****|*****|<- pX->NbConstraints line
1380 * ^ ^ ^ ^
1381 * | | | |
1382 * | | | (pX->Dimension + 2) column
1383 * | | scattdims column
1384 * | different_constraint+1 column
1385 * 0 column
1388 /* Step 1 and 2. This is only necessary to check one domain because
1389 * we checked that they are equal on this part before.
1391 for (i=0;i<=different_constraint;i++)
1392 { for (j=0;j<i+1;j++)
1393 if (value_notzero_p(p1->Constraint[i][j]))
1394 return 0 ;
1396 if (value_notone_p(p1->Constraint[i][i+1]))
1397 return 0 ;
1399 for (j=i+2;j<=different_constraint+1;j++)
1400 if (value_notzero_p(p1->Constraint[i][j]))
1401 return 0 ;
1404 /* Step 3. */
1405 for (i=0;i<=different_constraint;i++)
1406 for (j=different_constraint+2;j<=scattdims;j++)
1407 if (value_notzero_p(p1->Constraint[i][j]))
1408 return 0 ;
1410 value_init_c(date1) ;
1411 value_init_c(date2) ;
1412 value_init_c(date3) ;
1414 /* Now we have to check that the two different dates are unique. */
1415 value_assign(date1, p1->Constraint[different_constraint][p1->Dimension + 1]) ;
1416 value_assign(date2, p2->Constraint[different_constraint][p2->Dimension + 1]) ;
1418 /* Step 4. We check all domains except d1 and d2 and we look for at least
1419 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
1421 while (scattering != NULL)
1422 { if ((scattering->domain != d1) && (scattering->domain != d2))
1423 { p3 = scattering->domain->polyhedron ;
1424 value_assign(date3,p3->Constraint[different_constraint][p3->Dimension+1]);
1425 difference = 0 ;
1427 if (value_ne(date3,date2) && value_ne(date3,date1))
1428 difference = 1 ;
1430 for (i=0;(i<different_constraint)&&(!difference);i++)
1431 for (j=0;(j<(p3->Dimension + 2))&&(!difference);j++)
1432 if (value_ne(p1->Constraint[i][j],p3->Constraint[i][j]))
1433 difference = 1 ;
1435 for (j=0;(j<(p3->Dimension + 1))&&(!difference);j++)
1436 if (value_ne(p1->Constraint[different_constraint][j],
1437 p3->Constraint[different_constraint][j]))
1438 difference = 1 ;
1440 if (!difference)
1441 { value_clear_c(date1) ;
1442 value_clear_c(date2) ;
1443 value_clear_c(date3) ;
1444 return 0 ;
1448 scattering = scattering->next ;
1451 value_clear_c(date1) ;
1452 value_clear_c(date2) ;
1453 value_clear_c(date3) ;
1454 return 1 ;
1459 * cloog_domain_lazy_disjoint function:
1460 * This function returns 1 if the domains given as input are disjoint, 0 if it
1461 * is unable to decide. This function finds the unknown with fixed values in
1462 * both domains (on a given constraint, their column entry is not zero and
1463 * only the constant coefficient can be different from zero) and verify that
1464 * their values are the same. If not, the domains are obviously disjoint and
1465 * it returns 1, if there is not such case it returns 0. This is a very fast
1466 * way to verify this property. It has been shown (with the CLooG benchmarks)
1467 * that operations on disjoint domains are 36% of all the polyhedral
1468 * computations. For 94% of the actually identical domains, this
1469 * function answer that they are disjoint and allow to give immediately the
1470 * trivial solution instead of calling the heavy general functions of PolyLib.
1471 * - August 22th 2003: first version.
1472 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1473 * CLooG 0.12.1).
1475 int cloog_domain_lazy_disjoint(CloogDomain * d1, CloogDomain * d2)
1476 { int i1, j1, i2, j2, scat_dim ;
1477 Value scat_val ;
1478 Polyhedron * p1, * p2 ;
1480 p1 = d1->polyhedron ;
1481 p2 = d2->polyhedron ;
1483 if ((p1->next != NULL) || (p2->next != NULL))
1484 return 0 ;
1486 value_init_c(scat_val) ;
1488 for (i1=0; i1<p1->NbConstraints; i1++)
1489 { if (value_notzero_p(p1->Constraint[i1][0]))
1490 continue ;
1492 scat_dim = 1 ;
1493 while (value_zero_p(p1->Constraint[i1][scat_dim]) &&
1494 (scat_dim < p1->Dimension))
1495 scat_dim ++ ;
1497 if (value_notone_p(p1->Constraint[i1][scat_dim]))
1498 continue ;
1499 else
1500 { for (j1=scat_dim+1; j1<=p1->Dimension; j1++)
1501 if (value_notzero_p(p1->Constraint[i1][j1]))
1502 break ;
1504 if (j1 != p1->Dimension+1)
1505 continue ;
1507 value_assign(scat_val,p1->Constraint[i1][p1->Dimension+1]) ;
1509 for (i2=0; i2<p2->NbConstraints; i2++)
1510 { for (j2=0;j2<scat_dim;j2++)
1511 if (value_notzero_p(p2->Constraint[i2][j2]))
1512 break ;
1514 if ((j2 != scat_dim) || value_notone_p(p2->Constraint[i2][scat_dim]))
1515 continue ;
1517 for (j2=scat_dim+1; j2<=p2->Dimension; j2++)
1518 if (value_notzero_p(p2->Constraint[i2][j2]))
1519 break ;
1521 if (j2 != p2->Dimension+1)
1522 continue ;
1524 if (value_ne(p2->Constraint[i2][p2->Dimension+1],scat_val))
1525 { value_clear_c(scat_val) ;
1526 return 1 ;
1532 value_clear_c(scat_val) ;
1533 return 0 ;
1538 * cloog_domain_list_lazy_same function:
1539 * This function returns 1 if two domains in the list are the same, 0 if it
1540 * is unable to decide.
1541 * - February 9th 2004: first version.
1543 int cloog_domain_list_lazy_same(CloogDomainList * list)
1544 { /*int i=1, j=1 ;*/
1545 CloogDomainList * current, * next ;
1547 current = list ;
1548 while (current != NULL)
1549 { next = current->next ;
1550 /*j=i+1;*/
1551 while (next != NULL)
1552 { if (cloog_domain_lazy_equal(current->domain,next->domain))
1553 { /*printf("Same domains: %d and %d\n",i,j) ;*/
1554 return 1 ;
1556 /*j++ ;*/
1557 next = next->next ;
1559 /*i++ ;*/
1560 current = current->next ;
1563 return 0 ;
1568 * cloog_domain_grow function:
1569 * This function extend the polyhedron (domain) onto the dimension (level) by a
1570 * step of 1, if (lower) is 1 then the lower bound of the dimension is the same
1571 * minus one, if (lower) is 0 then the upper bound of the dimension is the
1572 * same plus one. This function frees the Polyhedron structure given as input
1573 * and returns the extended one.
1574 * - March 27th 2004: first version.
1575 * - June 21rd 2005: Adaptation for GMP.
1577 CloogDomain * cloog_domain_grow(CloogDomain * domain, int level, int lower)
1578 { int i, scalar_dim ;
1579 CloogMatrix * matrix ;
1580 CloogDomain * grow ;
1582 matrix = cloog_domain_domain2matrix(domain) ;
1583 cloog_domain_free(domain) ;
1584 scalar_dim = matrix->NbColumns - 1 ;
1586 for (i=0;i<matrix->NbRows;i++)
1587 if (value_one_p(matrix->p[i][0]))
1588 { if (((lower == 1) && value_pos_p(matrix->p[i][level])) ||
1589 ((lower == 0) && value_neg_p(matrix->p[i][level])))
1590 value_increment(matrix->p[i][scalar_dim],matrix->p[i][scalar_dim]) ;
1593 grow = cloog_domain_matrix2domain(matrix) ;
1594 cloog_matrix_free(matrix) ;
1595 return grow ;
1600 * Those functions are provided for "object encapsulation", to separate as much
1601 * as possible the inside of the CloogDomain structure from the rest of the
1602 * program, in order to ease the change of polyhedral library. For efficiency
1603 * reasons, they are defined and used as macros in domain.h.
1604 * - April 20th 2005: setting.
1606 Polyhedron * cloog_domain_polyhedron(CloogDomain * domain)
1607 { return domain->polyhedron ;
1610 int cloog_domain_dimension(CloogDomain * domain)
1611 { return domain->polyhedron->Dimension ;
1614 int cloog_domain_nbconstraints(CloogDomain * domain)
1615 { return domain->polyhedron->NbConstraints ;
1618 int cloog_domain_isconvex(CloogDomain * domain)
1619 { return (domain->polyhedron->next == NULL)? 1 : 0 ;
1625 * cloog_domain_cut_first function:
1626 * this function returns a CloogDomain structure with everything except the
1627 * first part of the polyhedra union of the input domain as domain. After a call
1628 * to this function, there remains in the CloogDomain structure provided as
1629 * input only the first part of the original polyhedra union.
1630 * - April 20th 2005: first version, extracted from different part of loop.c.
1632 CloogDomain * cloog_domain_cut_first(CloogDomain * domain)
1633 { CloogDomain * rest ;
1635 if ((domain != NULL) && (domain->polyhedron != NULL))
1636 { rest = cloog_domain_alloc(domain->polyhedron->next) ;
1637 domain->polyhedron->next = NULL ;
1639 else
1640 rest = NULL ;
1642 return rest ;
1647 * cloog_domain_lazy_isscalar function:
1648 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
1649 * is scalar, this means that the only constraint on this dimension must have
1650 * the shape "x.dimension + scalar = 0" with x an integral variable. This
1651 * function is lazy since we only accept x=1 (further calculations are easier
1652 * in this way).
1653 * - June 14th 2005: first version.
1654 * - June 21rd 2005: Adaptation for GMP.
1656 int cloog_domain_lazy_isscalar(CloogDomain * domain, int dimension)
1657 { int i, j ;
1658 Polyhedron * polyhedron ;
1660 polyhedron = domain->polyhedron ;
1661 /* For each constraint... */
1662 for (i=0;i<polyhedron->NbConstraints;i++)
1663 { /* ...if it is concerned by the potentially scalar dimension... */
1664 if (value_notzero_p(polyhedron->Constraint[i][dimension+1]))
1665 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
1666 for (j=0;j<=dimension;j++)
1667 if (value_notzero_p(polyhedron->Constraint[i][j]))
1668 return 0 ;
1670 if (value_notone_p(polyhedron->Constraint[i][dimension+1]))
1671 return 0 ;
1673 for (j=dimension+2;j<(polyhedron->Dimension + 1);j++)
1674 if (value_notzero_p(polyhedron->Constraint[i][j]))
1675 return 0 ;
1679 return 1 ;
1684 * cloog_domain_scalar function:
1685 * when we call this function, we know that "dimension" is a scalar dimension,
1686 * this function finds the scalar value in "domain" and returns it in "value".
1687 * - June 30th 2005: first version.
1689 void cloog_domain_scalar(CloogDomain * domain, int dimension, Value * value)
1690 { int i ;
1691 Polyhedron * polyhedron ;
1693 polyhedron = domain->polyhedron ;
1694 /* For each constraint... */
1695 for (i=0;i<polyhedron->NbConstraints;i++)
1696 { /* ...if it is the equality defining the scalar dimension... */
1697 if (value_notzero_p(polyhedron->Constraint[i][dimension+1]) &&
1698 value_zero_p(polyhedron->Constraint[i][0]))
1699 { /* ...Then send the scalar value. */
1700 value_assign(*value,polyhedron->Constraint[i][polyhedron->Dimension+1]) ;
1701 value_oppose(*value,*value) ;
1702 return ;
1706 /* We should have found a scalar value: if not, there is an error. */
1707 fprintf(stderr, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
1708 dimension) ;
1709 exit(0) ;
1714 * cloog_domain_erase_dimension function:
1715 * this function returns a CloogDomain structure builds from 'domain' where
1716 * we removed the dimension 'dimension' and every constraint considering this
1717 * dimension. This is not a projection ! Every data concerning the
1718 * considered dimension is simply erased.
1719 * - June 14th 2005: first version.
1720 * - June 21rd 2005: Adaptation for GMP.
1722 CloogDomain * cloog_domain_erase_dimension(CloogDomain * domain, int dimension)
1723 { int i, j, mi, nb_dim ;
1724 CloogMatrix * matrix ;
1725 CloogDomain * erased ;
1726 Polyhedron * polyhedron ;
1728 polyhedron = domain->polyhedron ;
1729 nb_dim = polyhedron->Dimension ;
1731 /* The matrix is one column less and at least one constraint less. */
1732 matrix = cloog_matrix_alloc(polyhedron->NbConstraints-1,nb_dim+1) ;
1734 /* mi is the constraint counter for the matrix. */
1735 mi = 0 ;
1736 for (i=0;i<polyhedron->NbConstraints;i++)
1737 if (value_zero_p(polyhedron->Constraint[i][dimension+1]))
1738 { for (j=0;j<=dimension;j++)
1739 value_assign(matrix->p[mi][j],polyhedron->Constraint[i][j]) ;
1741 for (j=dimension+2;j<nb_dim+2;j++)
1742 value_assign(matrix->p[mi][j-1],polyhedron->Constraint[i][j]) ;
1744 mi ++ ;
1747 erased = cloog_domain_matrix2domain(matrix) ;
1748 cloog_matrix_free(matrix) ;
1750 return erased ;
1755 * To change the order of the part of a polyhedral union, for funny results !
1756 * - September 10th 2005.
1758 void cloog_domain_reverse(CloogDomain * domain)
1759 { Polyhedron * polyhedron, * p, * q ,* r ;
1761 polyhedron = domain->polyhedron ;
1763 if ((polyhedron == NULL)||(polyhedron->next == NULL))
1764 return ;
1766 q = polyhedron->next ;
1767 polyhedron->next = NULL ;
1768 r = q->next ;
1769 q->next = polyhedron ;
1770 while (r != NULL)
1771 { p = q ;
1772 q = r ;
1773 r = r->next ;
1774 q->next = p ;
1776 domain->polyhedron = q ;