pass the number of parameters to functions reading polyhedra
[cloog/uuh.git] / source / polylib / domain.c
blobbc6c9dc20c5c4dc8a042db36606ebded7b4c4b3f
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 <cloog/polylib/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 /******************************************************************************
93 * PolyLib interface *
94 ******************************************************************************/
97 /* CLooG makes an intensive use of polyhedral operations and the PolyLib do
98 * the job. Here are the interfaces to all the PolyLib calls (CLooG uses 19
99 * PolyLib functions), with or without some adaptations. If another polyhedral
100 * library can be used, only these functions have to be changed.
101 * - April 16th 2005: Since PolyLib 5.20, compacting is no more useful and have
102 * been removed. The direct use of the PolyLib's Polyhedron
103 * data structure is also replaced with the CloogDomain data
104 * structure that includes the Polyhedron and an additional
105 * counter on how many pointers point on this structure.
106 * This allows to save memory (cloog_domain_copy now only
107 * increment the counter) while memory leaks are avoided (the
108 * function cloog_domain_free decrements the counter and
109 * actually frees the data structure only when its value
110 * is 0).
114 * Returns true if each scattering dimension is defined in terms
115 * of the original iterators.
117 int cloog_scattering_fully_specified(CloogScattering *scattering,
118 CloogDomain *domain)
120 int scattering_dim = cloog_domain_dimension(scattering) -
121 cloog_domain_dimension(domain);
122 return scattering->polyhedron->NbEq >= scattering_dim;
126 * cloog_domain_matrix2domain function:
127 * Given a matrix of constraints (matrix), this function constructs and returns
128 * the corresponding domain (i.e. the CloogDomain structure including the
129 * polyhedron with its double representation: constraint matrix and the set of
130 * rays).
132 CloogDomain * cloog_domain_matrix2domain(CloogMatrix * matrix)
133 { return (cloog_domain_alloc(Constraints2Polyhedron(matrix,MAX_RAYS))) ;
138 * cloog_domain_domain2matrix function:
139 * Given a polyhedron (in domain), this function returns its corresponding
140 * matrix of constraints.
142 CloogMatrix * cloog_domain_domain2matrix(CloogDomain * domain)
144 return cloog_matrix_matrix(Polyhedron2Constraints(domain->polyhedron));
147 CloogConstraints *cloog_domain_constraints(CloogDomain *domain)
149 return cloog_domain_domain2matrix(domain);
154 * cloog_domain_print function:
155 * This function prints the content of a CloogDomain structure (domain) into
156 * a file (foo, possibly stdout).
158 void cloog_domain_print(FILE * foo, CloogDomain * domain)
159 { Polyhedron_Print(foo,P_VALUE_FMT,domain->polyhedron) ;
160 fprintf(foo,"Number of active references: %d\n",domain->references) ;
163 void cloog_domain_print_constraints(FILE *foo, CloogDomain *domain,
164 int print_number)
166 Polyhedron *polyhedron;
167 CloogMatrix *matrix;
169 if (print_number) {
170 int j = 0;
171 /* Number of polyhedron inside the union of disjoint polyhedra. */
172 for (polyhedron = cloog_domain_polyhedron(domain); polyhedron;
173 polyhedron = polyhedron->next)
174 ++j;
175 fprintf(foo, "%d\n", j);
178 /* The polyhedra themselves. */
179 for (polyhedron = cloog_domain_polyhedron(domain); polyhedron;
180 polyhedron = polyhedron->next) {
181 matrix = cloog_matrix_matrix(Polyhedron2Constraints(polyhedron));
182 cloog_matrix_print(foo,matrix);
183 cloog_matrix_free(matrix);
188 * cloog_polyhedron_print function:
189 * This function prints the content of a Polyhedron structure (polyhedron) into
190 * a file (foo, possibly stdout). Just there as a development facility.
192 void cloog_polyhedron_print(FILE * foo, Polyhedron * polyhedron)
193 { Polyhedron_Print(foo,P_VALUE_FMT,polyhedron) ;
198 * cloog_domain_free function:
199 * This function frees the allocated memory for a CloogDomain structure
200 * (domain). It decrements the number of active references to this structure,
201 * if there are no more references on the structure, it frees it (with the
202 * included list of polyhedra).
204 void cloog_domain_free(CloogDomain * domain)
205 { if (domain != NULL)
206 { domain->references -- ;
208 if (domain->references == 0)
209 { if (domain->polyhedron != NULL)
210 { cloog_domain_leak_down() ;
211 Domain_Free(domain->polyhedron) ;
213 free(domain) ;
218 void cloog_scattering_free(CloogDomain * domain)
220 cloog_domain_free(domain);
225 * cloog_domain_copy function:
226 * This function returns a copy of a CloogDomain structure (domain). To save
227 * memory this is not a memory copy but we increment a counter of active
228 * references inside the structure, then return a pointer to that structure.
230 CloogDomain * cloog_domain_copy(CloogDomain * domain)
231 { domain->references ++ ;
232 return domain ;
237 * cloog_domain_image function:
238 * This function returns a CloogDomain structure such that the included
239 * polyhedral domain is computed from the former one into another
240 * domain according to a given affine mapping function (mapping).
242 CloogDomain * cloog_domain_image(CloogDomain * domain, CloogMatrix * mapping)
243 { return (cloog_domain_alloc(DomainImage(domain->polyhedron,mapping,MAX_RAYS)));
248 * cloog_domain_preimage function:
249 * Given a polyhedral domain (polyhedron) inside a CloogDomain structure and a
250 * mapping function (mapping), this function returns a new CloogDomain structure
251 * with a polyhedral domain which when transformed by mapping function (mapping)
252 * gives (polyhedron).
254 CloogDomain * cloog_domain_preimage(CloogDomain * domain, CloogMatrix * mapping)
255 { return (cloog_domain_alloc(DomainPreimage(domain->polyhedron,
256 mapping,MAX_RAYS))) ;
261 * cloog_domain_convex function:
262 * Given a polyhedral domain (polyhedron), this function concatenates the lists
263 * of rays and lines of the two (or more) polyhedra in the domain into one
264 * combined list, and find the set of constraints which tightly bound all of
265 * those objects. It returns the corresponding polyhedron.
267 CloogDomain * cloog_domain_convex(CloogDomain * domain)
268 { return (cloog_domain_alloc(DomainConvex(domain->polyhedron,MAX_RAYS)));
273 * cloog_domain_simplified_hull:
274 * Given a list (union) of polyhedra, this function returns a single
275 * polyhedron that contains this union and uses only contraints that
276 * appear in one or more of the polyhedra in the list.
278 * We simply iterate over all constraints of all polyhedra and test
279 * whether all rays of the other polyhedra satisfy/saturate the constraint.
281 static CloogDomain *cloog_domain_simplified_hull(CloogDomain * domain)
283 int dim = cloog_domain_dimension(domain);
284 int i, j, k, l;
285 int nb_pol = 0, nb_constraints = 0;
286 Polyhedron *P;
287 CloogMatrix **rays, *matrix;
288 Value tmp;
289 CloogDomain *bounds;
291 value_init(tmp);
292 for (P = domain->polyhedron; P; P = P->next) {
293 ++nb_pol;
294 nb_constraints += P->NbConstraints;
296 matrix = cloog_matrix_alloc(nb_constraints, 1 + dim + 1);
297 nb_constraints = 0;
298 rays = (CloogMatrix **)malloc(nb_pol * sizeof(CloogMatrix*));
299 for (P = domain->polyhedron, i = 0; P; P = P->next, ++i)
300 rays[i] = Polyhedron2Rays(P);
302 for (P = domain->polyhedron, i = 0; P; P = P->next, ++i) {
303 CloogMatrix *constraints = Polyhedron2Constraints(P);
304 for (j = 0; j < constraints->NbRows; ++j) {
305 for (k = 0; k < nb_pol; ++k) {
306 if (i == k)
307 continue;
308 for (l = 0; l < rays[k]->NbRows; ++l) {
309 Inner_Product(constraints->p[j]+1, rays[k]->p[l]+1, dim+1, &tmp);
310 if (value_neg_p(tmp))
311 break;
312 if ((value_zero_p(constraints->p[j][0]) ||
313 value_zero_p(rays[k]->p[l][0])) && value_pos_p(tmp))
314 break;
316 if (l < rays[k]->NbRows)
317 break;
319 if (k == nb_pol)
320 Vector_Copy(constraints->p[j], matrix->p[nb_constraints++], 1+dim+1);
322 Matrix_Free(constraints);
325 for (P = domain->polyhedron, i = 0; P; P = P->next, ++i)
326 Matrix_Free(rays[i]);
327 free(rays);
328 value_clear(tmp);
330 matrix->NbRows = nb_constraints;
331 bounds = cloog_domain_matrix2domain(matrix);
332 cloog_matrix_free(matrix);
334 return bounds;
339 * cloog_domain_simple_convex:
340 * Given a list (union) of polyhedra, this function returns a "simple"
341 * convex hull of this union. In particular, the constraints of the
342 * the returned polyhedron consist of (parametric) lower and upper
343 * bounds on individual variables and constraints that appear in the
344 * original polyhedra.
346 * nb_par is the number of parameters of the domain.
348 CloogDomain * cloog_domain_simple_convex(CloogDomain * domain, int nb_par)
350 int i;
351 int dim = cloog_domain_dimension(domain) - nb_par;
352 CloogDomain *convex = NULL;
354 if (cloog_domain_isconvex(domain))
355 return cloog_domain_copy(domain);
357 for (i = 0; i < dim; ++i) {
358 CloogDomain *bounds = cloog_domain_bounds(domain, i, nb_par);
360 if (!convex)
361 convex = bounds;
362 else {
363 CloogDomain *temp = cloog_domain_intersection(convex, bounds);
364 cloog_domain_free(bounds);
365 cloog_domain_free(convex);
366 convex = temp;
369 if (dim > 1) {
370 CloogDomain *temp, *bounds;
372 bounds = cloog_domain_simplified_hull(domain);
373 temp = cloog_domain_intersection(convex, bounds);
374 cloog_domain_free(bounds);
375 cloog_domain_free(convex);
376 convex = temp;
379 return convex;
384 * cloog_domain_simplify function:
385 * Given two polyhedral domains (pol1) and (pol2) inside two CloogDomain
386 * structures, this function finds the largest domain set (or the smallest list
387 * of non-redundant constraints), that when intersected with polyhedral
388 * domain (pol2) equals (Pol1)intersect(Pol2). The output is a new CloogDomain
389 * structure with a polyhedral domain with the "redundant" constraints removed.
390 * NB: this function do not work as expected with unions of polyhedra...
392 CloogDomain * cloog_domain_simplify(CloogDomain * dom1, CloogDomain * dom2)
394 CloogMatrix *M, *M2;
395 CloogDomain *dom;
396 Polyhedron *P = dom1->polyhedron;
398 /* DomainSimplify doesn't remove all redundant equalities,
399 * so we remove them here first in case both dom1 and dom2
400 * are single polyhedra (i.e., not unions of polyhedra).
402 if (!dom1->polyhedron->next && !dom2->polyhedron->next &&
403 P->NbEq && dom2->polyhedron->NbEq) {
404 int i, row;
405 int rows = P->NbEq + dom2->polyhedron->NbEq;
406 int cols = P->Dimension+2;
407 int rank;
408 M = cloog_matrix_alloc(rows, cols);
409 M2 = cloog_matrix_alloc(P->NbConstraints, cols);
410 Vector_Copy(dom2->polyhedron->Constraint[0], M->p[0],
411 dom2->polyhedron->NbEq * cols);
412 rank = dom2->polyhedron->NbEq;
413 row = 0;
414 for (i = 0; i < P->NbEq; ++i) {
415 Vector_Copy(P->Constraint[i], M->p[rank], cols);
416 if (Gauss(M, rank+1, cols-1) > rank) {
417 Vector_Copy(P->Constraint[i], M2->p[row++], cols);
418 rank++;
421 if (row < P->NbEq) {
422 Vector_Copy(P->Constraint[P->NbEq], M2->p[row],
423 (P->NbConstraints - P->NbEq) * cols);
424 P = Constraints2Polyhedron(M2, MAX_RAYS);
426 cloog_matrix_free(M2);
427 cloog_matrix_free(M);
429 dom = cloog_domain_alloc(DomainSimplify(P, dom2->polyhedron,MAX_RAYS));
430 if (P != dom1->polyhedron)
431 Polyhedron_Free(P);
432 return dom;
437 * cloog_domain_union function:
438 * This function returns a new CloogDomain structure including a polyhedral
439 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
440 * two CloogDomain structures.
442 CloogDomain * cloog_domain_union(CloogDomain * dom1, CloogDomain * dom2)
443 { return (cloog_domain_alloc(DomainUnion(dom1->polyhedron,
444 dom2->polyhedron,MAX_RAYS))) ;
449 * cloog_domain_intersection function:
450 * This function returns a new CloogDomain structure including a polyhedral
451 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
452 * inside two CloogDomain structures.
454 CloogDomain * cloog_domain_intersection(CloogDomain * dom1, CloogDomain * dom2)
455 { return (cloog_domain_alloc(DomainIntersection(dom1->polyhedron,
456 dom2->polyhedron,MAX_RAYS))) ;
461 * cloog_domain_difference function:
462 * This function returns a new CloogDomain structure including a polyhedral
463 * domain which is the difference of two polyhedral domains domain \ minus
464 * inside two CloogDomain structures.
465 * - November 8th 2001: first version.
467 CloogDomain * cloog_domain_difference(CloogDomain * domain, CloogDomain * minus)
468 { if (cloog_domain_isempty(minus))
469 return(cloog_domain_copy(domain)) ;
470 else
471 return (cloog_domain_alloc(DomainDifference(domain->polyhedron,
472 minus->polyhedron,MAX_RAYS))) ;
477 * cloog_domain_addconstraints function :
478 * This function adds source's polyhedron constraints to target polyhedron: for
479 * each element of the polyhedron inside 'target' (i.e. element of the union
480 * of polyhedra) it adds the constraints of the corresponding element in
481 * 'source'.
482 * - August 10th 2002: first version.
483 * Nota bene for future : it is possible that source and target don't have the
484 * same number of elements (try iftest2 without non-shared constraint
485 * elimination in cloog_loop_separate !). This function is yet another part
486 * of the DomainSimplify patching problem...
488 CloogDomain * cloog_domain_addconstraints(domain_source, domain_target)
489 CloogDomain * domain_source, * domain_target ;
490 { unsigned nb_constraint ;
491 Value * constraints ;
492 Polyhedron * source, * target, * new, * next, * last ;
494 source = domain_source->polyhedron ;
495 target = domain_target->polyhedron ;
497 constraints = source->p_Init ;
498 nb_constraint = source->NbConstraints ;
499 source = source->next ;
500 new = AddConstraints(constraints,nb_constraint,target,MAX_RAYS) ;
501 last = new ;
502 next = target->next ;
504 while (next != NULL)
505 { /* BUG !!! This is actually a bug. I don't know yet how to cleanly avoid
506 * the situation where source and target do not have the same number of
507 * elements. So this 'if' is an awful trick, waiting for better.
509 if (source != NULL)
510 { constraints = source->p_Init ;
511 nb_constraint = source->NbConstraints ;
512 source = source->next ;
514 last->next = AddConstraints(constraints,nb_constraint,next,MAX_RAYS) ;
515 last = last->next ;
516 next = next->next ;
519 return (cloog_domain_alloc(new)) ;
524 * cloog_domain_sort function:
525 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
526 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
527 * (level) is the level to consider for partial ordering (nb_par) is the
528 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
529 * integers that contains a permutation specification after call in order to
530 * apply the topological sorting.
532 void cloog_domain_sort(CloogDomain **doms, unsigned nb_doms, unsigned level,
533 unsigned nb_par, int *permut)
535 int i, *time;
536 Polyhedron **pols = (Polyhedron **) malloc(nb_doms * sizeof(Polyhedron *));
538 for (i = 0; i < nb_doms; i++)
539 pols[i] = cloog_domain_polyhedron(doms[i]);
541 /* time is an array of (nb_doms) integers to store logical time values. We
542 * do not use it, but it is compulsory for PolyhedronTSort.
544 time = (int *)malloc(nb_doms * sizeof(int));
546 /* PolyhedronTSort will fill up permut (and time). */
547 PolyhedronTSort(pols, nb_doms, level, nb_par, time, permut, MAX_RAYS);
549 free(pols);
550 free(time) ;
555 * cloog_domain_empty function:
556 * This function allocates the memory space for a CloogDomain structure and
557 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
558 * Then it returns a pointer to the allocated space.
559 * - June 10th 2005: first version.
561 CloogDomain * cloog_domain_empty(int dimension)
562 { return (cloog_domain_alloc(Empty_Polyhedron(dimension))) ;
566 /******************************************************************************
567 * Structure display function *
568 ******************************************************************************/
572 * cloog_domain_print_structure :
573 * this function is a more human-friendly way to display the CloogDomain data
574 * structure, it only shows the constraint system and includes an indentation
575 * level (level) in order to work with others print_structure functions.
576 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
577 * - April 24th 2005: Initial version.
578 * - May 26th 2005: Memory leak hunt.
579 * - June 16th 2005: (Ced) Integration in domain.c.
581 void cloog_domain_print_structure(FILE *file, CloogDomain *domain, int level,
582 const char *name)
583 { int i ;
584 CloogMatrix * matrix ;
586 /* Go to the right level. */
587 for(i=0; i<level; i++)
588 fprintf(file,"|\t") ;
590 if (domain != NULL)
591 { fprintf(file,"+-- %s\n", name);
593 /* Print the matrix. */
594 matrix = cloog_domain_domain2matrix(domain) ;
595 cloog_matrix_print_structure(file,matrix,level) ;
596 cloog_matrix_free(matrix) ;
598 /* A blank line. */
599 for (i=0; i<level+1; i++)
600 fprintf(file,"|\t") ;
601 fprintf(file,"\n") ;
603 else
604 fprintf(file,"+-- Null CloogDomain\n") ;
610 * cloog_scattering_list_print function:
611 * This function prints the content of a CloogScatteringList structure into a
612 * file (foo, possibly stdout).
613 * - November 6th 2001: first version.
615 void cloog_scattering_list_print(FILE * foo, CloogScatteringList * list)
616 { while (list != NULL)
617 { cloog_domain_print(foo,list->domain) ;
618 list = list->next ;
623 /******************************************************************************
624 * Memory deallocation function *
625 ******************************************************************************/
629 * cloog_scattering_list_free function:
630 * This function frees the allocated memory for a CloogScatteringList structure.
631 * - November 6th 2001: first version.
633 void cloog_scattering_list_free(CloogScatteringList * list)
634 { CloogScatteringList * temp ;
636 while (list != NULL)
637 { temp = list->next ;
638 cloog_domain_free(list->domain) ;
639 free(list) ;
640 list = temp ;
645 /******************************************************************************
646 * Reading function *
647 ******************************************************************************/
651 * cloog_domain_read function:
652 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
653 * posibly stdin) and returns a pointer to a polyhedron containing the read
654 * information.
655 * - October 18th 2001: first version.
657 CloogDomain * cloog_domain_read(FILE * foo, int nb_parameters,
658 CloogOptions *options)
659 { CloogMatrix * matrix ;
660 CloogDomain * domain ;
662 matrix = cloog_matrix_read(foo) ;
663 domain = cloog_domain_matrix2domain(matrix) ;
664 cloog_matrix_free(matrix) ;
666 return(domain) ;
671 * cloog_domain_union_read function:
672 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
673 * returns a pointer to a Polyhedron containing the read information.
674 * - September 9th 2002: first version.
675 * - October 29th 2005: (debug) removal of a leak counting "correction" that
676 * was just false since ages.
678 CloogDomain * cloog_domain_union_read(FILE * foo, int nb_parameters,
679 CloogOptions *options)
680 { int i, nb_components ;
681 char s[MAX_STRING] ;
682 CloogDomain * domain, * temp, * old ;
684 /* domain reading: nb_components (constraint matrices). */
685 while (fgets(s,MAX_STRING,foo) == 0) ;
686 while ((*s=='#' || *s=='\n') || (sscanf(s," %d",&nb_components)<1))
687 fgets(s,MAX_STRING,foo) ;
689 if (nb_components > 0)
690 { /* 1. first part of the polyhedra union, */
691 domain = cloog_domain_read(foo, nb_parameters, options);
692 /* 2. and the nexts. */
693 for (i=1;i<nb_components;i++)
694 { /* Leak counting is OK since next allocated domain is freed here. */
695 temp = cloog_domain_read(foo, nb_parameters, options);
696 old = domain ;
697 domain = cloog_domain_union(temp,old) ;
698 cloog_domain_free(temp) ;
699 cloog_domain_free(old) ;
701 return domain ;
703 else
704 return NULL ;
709 * cloog_scattering_list_read function:
710 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
711 * returns a pointer to a CloogScatteringList containing the read information.
712 * - November 6th 2001: first version.
714 CloogScatteringList * cloog_scattering_list_read(FILE * foo,
715 int nb_parameters, CloogOptions *options)
716 { int i, nb_pols ;
717 char s[MAX_STRING] ;
718 CloogScatteringList * list, * now, * next ;
721 /* We read first the number of polyhedra in the list. */
722 while (fgets(s,MAX_STRING,foo) == 0) ;
723 while ((*s=='#' || *s=='\n') || (sscanf(s," %d",&nb_pols)<1))
724 fgets(s,MAX_STRING,foo) ;
726 /* Then we read the polyhedra. */
727 list = NULL ;
728 if (nb_pols > 0)
729 { list = (CloogScatteringList *)malloc(sizeof(CloogScatteringList)) ;
730 list->domain = cloog_domain_read(foo, nb_parameters, options);
731 list->next = NULL ;
732 now = list ;
733 for (i=1;i<nb_pols;i++)
734 { next = (CloogScatteringList *)malloc(sizeof(CloogScatteringList)) ;
735 next->domain = cloog_domain_read(foo, nb_parameters, options);
736 next->next = NULL ;
737 now->next = next ;
738 now = now->next ;
741 return(list) ;
745 /******************************************************************************
746 * Processing functions *
747 ******************************************************************************/
751 * cloog_domain_malloc function:
752 * This function allocates the memory space for a CloogDomain structure and
753 * sets its fields with default values. Then it returns a pointer to the
754 * allocated space.
755 * - November 21th 2005: first version.
757 CloogDomain * cloog_domain_malloc()
758 { CloogDomain * domain ;
760 domain = (CloogDomain *)malloc(sizeof(CloogDomain)) ;
761 if (domain == NULL)
762 { fprintf(stderr, "[CLooG]ERROR: memory overflow.\n") ;
763 exit(1) ;
765 cloog_domain_leak_up() ;
767 /* We set the various fields with default values. */
768 domain->polyhedron = NULL ;
769 domain->references = 1 ;
771 return domain ;
776 * cloog_domain_alloc function:
777 * This function allocates the memory space for a CloogDomain structure and
778 * sets its fields with those given as input. Then it returns a pointer to the
779 * allocated space.
780 * - April 19th 2005: first version.
781 * - November 21th 2005: cloog_domain_malloc use.
783 CloogDomain * cloog_domain_alloc(Polyhedron * polyhedron)
784 { CloogDomain * domain ;
786 if (polyhedron == NULL)
787 return NULL ;
788 else
789 { domain = cloog_domain_malloc() ;
790 domain->polyhedron = polyhedron ;
792 return domain ;
798 * cloog_domain_isempty function:
799 * This function returns 1 if the polyhedron given as input is empty, 0
800 * otherwise.
801 * - October 28th 2001: first version.
803 int cloog_domain_isempty(CloogDomain * domain)
804 { if (domain->polyhedron == NULL)
805 return 1 ;
807 if (domain->polyhedron->next)
808 return(0) ;
809 return((domain->polyhedron->Dimension < domain->polyhedron->NbEq) ? 1 : 0) ;
814 * cloog_domain_universe function:
815 * This function returns the complete dim-dimensional space.
817 CloogDomain *cloog_domain_universe(unsigned dim, CloogOptions *options)
819 return cloog_domain_alloc(Universe_Polyhedron(dim));
824 * cloog_domain_project function:
825 * From Quillere's LoopGen 0.4. This function returns the projection of
826 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
827 * pointer to the projected Polyhedron.
828 * - nb_par is the number of parameters.
830 * - October 27th 2001: first version.
831 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
832 * CLooG 0.12.1).
834 CloogDomain * cloog_domain_project(CloogDomain * domain, int level, int nb_par)
835 { int row, column, nb_rows, nb_columns, difference ;
836 CloogDomain * projected_domain ;
837 CloogMatrix * matrix ;
839 nb_rows = level + nb_par + 1 ;
840 nb_columns = domain->polyhedron->Dimension + 1 ;
841 difference = nb_columns - nb_rows ;
843 if (difference == 0)
844 return(cloog_domain_copy(domain)) ;
846 matrix = cloog_matrix_alloc(nb_rows,nb_columns) ;
848 for (row=0;row<level;row++)
849 for (column=0;column<nb_columns; column++)
850 value_set_si(matrix->p[row][column],(row == column ? 1 : 0)) ;
852 for (;row<nb_rows;row++)
853 for (column=0;column<nb_columns;column++)
854 value_set_si(matrix->p[row][column],(row+difference == column ? 1 : 0)) ;
856 projected_domain = cloog_domain_image(domain,matrix) ;
857 cloog_matrix_free(matrix) ;
859 return(projected_domain) ;
864 * cloog_domain_bounds:
865 * Given a list (union) of polyhedra "domain", this function returns a single
866 * polyhedron with constraints that reflect the (parametric) lower and
867 * upper bound on dimension "dim".
869 * nb_par is the number of parameters of the domain.
871 CloogDomain * cloog_domain_bounds(CloogDomain * domain, int dim, int nb_par)
873 int row, nb_rows, nb_columns, difference;
874 CloogDomain * projected_domain, *extended_domain, *bounds;
875 CloogMatrix * matrix ;
877 nb_rows = 1 + nb_par + 1;
878 nb_columns = domain->polyhedron->Dimension + 1 ;
879 difference = nb_columns - nb_rows ;
881 if (difference == 0)
882 return(cloog_domain_convex(domain));
884 matrix = cloog_matrix_alloc(nb_rows, nb_columns);
886 value_set_si(matrix->p[0][dim], 1);
887 for (row = 1; row < nb_rows; row++)
888 value_set_si(matrix->p[row][row+difference], 1);
890 projected_domain = cloog_domain_image(domain,matrix) ;
891 extended_domain = cloog_domain_preimage(projected_domain, matrix);
892 cloog_domain_free(projected_domain);
893 cloog_matrix_free(matrix) ;
894 bounds = cloog_domain_convex(extended_domain);
895 cloog_domain_free(extended_domain);
897 return bounds;
902 * cloog_domain_extend function:
903 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
904 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
905 * the (nb_par) parameters. This function does not free (domain), and returns
906 * a new polyhedron.
907 * - nb_par is the number of parameters.
909 * - October 27th 2001: first version.
910 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
911 * CLooG 0.12.1).
913 CloogDomain * cloog_domain_extend(CloogDomain * domain, int dim, int nb_par)
914 { int row, column, nb_rows, nb_columns, difference ;
915 CloogDomain * extended_domain ;
916 CloogMatrix * matrix ;
918 nb_rows = 1 + domain->polyhedron->Dimension ;
919 nb_columns = dim + nb_par + 1 ;
920 difference = nb_columns - nb_rows ;
922 if (difference == 0)
923 return(cloog_domain_copy(domain)) ;
925 matrix = cloog_matrix_alloc(nb_rows,nb_columns) ;
927 for (row=0;row<domain->polyhedron->Dimension-nb_par;row++)
928 for (column=0;column<nb_columns;column++)
929 value_set_si(matrix->p[row][column],(row == column ? 1 : 0)) ;
931 for (;row<=domain->polyhedron->Dimension;row++)
932 for (column=0;column<nb_columns;column++)
933 value_set_si(matrix->p[row][column],(row+difference == column ? 1 : 0)) ;
935 extended_domain = cloog_domain_preimage(domain,matrix) ;
936 cloog_matrix_free(matrix) ;
938 return(extended_domain) ;
943 * cloog_domain_never_integral function:
944 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
945 * function returns a boolean set to 1 if there is this kind of 'never true'
946 * constraint inside a polyhedron, 0 otherwise.
947 * - domain is the polyhedron to check,
949 * - November 28th 2001: first version.
950 * - June 26th 2003: for iterators, more 'never true' constraints are found
951 * (compare cholesky2 and vivien with a previous version),
952 * checking for the parameters created (compare using vivien).
953 * - June 28th 2003: Previously in loop.c and called
954 * cloog_loop_simplify_nevertrue, now here !
955 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
956 * CLooG 0.12.1).
957 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
959 int cloog_domain_never_integral(CloogDomain * domain)
960 { int i, dimension ;
961 Value gcd, modulo ;
962 Polyhedron * polyhedron ;
964 if ((domain == NULL) || (domain->polyhedron == NULL))
965 return 1 ;
967 value_init_c(gcd) ;
968 value_init_c(modulo) ;
969 polyhedron = domain->polyhedron ;
970 dimension = polyhedron->Dimension + 2 ;
972 /* For each constraint... */
973 for (i=0; i<polyhedron->NbConstraints; i++)
974 { /* If we have an equality and the scalar part is not zero... */
975 if (value_zero_p(polyhedron->Constraint[i][0]) &&
976 value_notzero_p(polyhedron->Constraint[i][dimension-1]))
977 { /* Then we check whether the scalar can be divided by the gcd of the
978 * unknown vector (including iterators and parameters) or not. If not,
979 * there is no integer point in the polyhedron and we return 1.
981 Vector_Gcd(&(polyhedron->Constraint[i][1]),dimension-2,&gcd) ;
982 value_modulus(modulo,polyhedron->Constraint[i][dimension-1],gcd) ;
984 if (value_notzero_p(modulo))
985 { value_clear_c(gcd) ;
986 value_clear_c(modulo) ;
987 return 1 ;
992 value_clear_c(gcd) ;
993 value_clear_c(modulo) ;
994 return(0) ;
999 * cloog_domain_stride function:
1000 * This function finds the stride imposed to unknown with the column number
1001 * 'strided_level' in order to be integral. For instance, if we have a
1002 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
1003 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
1004 * the unknown i. The function returns the imposed stride in a parameter field.
1005 * - domain is the set of constraint we have to consider,
1006 * - strided_level is the column number of the unknown for which a stride have
1007 * to be found,
1008 * - looking_level is the column number of the unknown that impose a stride to
1009 * the first unknown.
1010 * - stride is the stride that is returned back as a function parameter.
1011 * - offset is the value of the constant c if the condition is of the shape
1012 * (i + c)%s = 0, s being the stride.
1014 * - June 28th 2003: first version.
1015 * - July 14th 2003: can now look for multiple striding constraints and returns
1016 * the GCD of the strides and the common offset.
1017 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1018 * CLooG 0.12.1).
1020 void cloog_domain_stride(domain, strided_level, nb_par, stride, offset)
1021 CloogDomain * domain ;
1022 int strided_level, nb_par ;
1023 Value * stride, * offset;
1024 { int i, dimension;
1025 Polyhedron * polyhedron ;
1026 int n_col, n_row, rank;
1027 CloogMatrix *M;
1028 Matrix *U;
1029 Vector *V;
1031 polyhedron = domain->polyhedron ;
1032 dimension = polyhedron->Dimension ;
1034 /* Look at all equalities involving strided_level and the inner
1035 * iterators. We can ignore the outer iterators and the parameters
1036 * here because the lower bound on strided_level is assumed to
1037 * be a constant.
1039 n_col = (1+dimension-nb_par) - strided_level;
1040 for (i=0, n_row=0; i < polyhedron->NbEq; i++)
1041 if (First_Non_Zero(polyhedron->Constraint[i]+strided_level, n_col) != -1)
1042 ++n_row;
1044 M = cloog_matrix_alloc(n_row+1, n_col+1);
1045 for (i=0, n_row = 0; i < polyhedron->NbEq; i++) {
1046 if (First_Non_Zero(polyhedron->Constraint[i]+strided_level, n_col) == -1)
1047 continue;
1048 Vector_Copy(polyhedron->Constraint[i]+strided_level, M->p[n_row], n_col);
1049 value_assign(M->p[n_row][n_col], polyhedron->Constraint[i][1+dimension]);
1050 ++n_row;
1052 value_set_si(M->p[n_row][n_col], 1);
1054 /* Then look at the general solution to the above equalities. */
1055 rank = SolveDiophantine(M, &U, &V);
1056 cloog_matrix_free(M);
1058 if (rank == -1) {
1059 /* There is no solution, so the body of this loop will
1060 * never execute. We just leave the constraints alone here so
1061 * that they will ensure the body will not be executed.
1062 * We should probably propagate this information up so that
1063 * the loop can be removed entirely.
1065 value_set_si(*offset, 0);
1066 value_set_si(*stride, 1);
1067 } else {
1068 /* Compute the gcd of the coefficients defining strided_level. */
1069 Vector_Gcd(U->p[0], U->NbColumns, stride);
1070 value_oppose(*offset, V->p[0]);
1071 value_pmodulus(*offset, *offset, *stride);
1073 Matrix_Free(U);
1074 Vector_Free(V);
1076 return ;
1081 * cloog_domain_integral_lowerbound function:
1082 * This function returns 1 if the lower bound of an iterator (such as its
1083 * column rank in the constraint set 'domain' is 'level') is integral,
1084 * 0 otherwise. If the lower bound is actually integral, the function fills
1085 * the 'lower' field with the lower bound value.
1086 * - June 29th 2003: first version.
1087 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1088 * CLooG 0.12.1).
1090 int cloog_domain_integral_lowerbound(domain, level, lower)
1091 CloogDomain * domain ;
1092 int level ;
1093 Value * lower ;
1094 { int i, first_lower=1, dimension, lower_constraint=-1 ;
1095 Value iterator, constant, tmp;
1096 Polyhedron * polyhedron ;
1098 polyhedron = domain->polyhedron ;
1099 dimension = polyhedron->Dimension ;
1101 /* We want one and only one lower bound (e.g. no equality, no maximum
1102 * calculation...).
1104 for (i=0; i<polyhedron->NbConstraints; i++)
1105 if (value_zero_p(polyhedron->Constraint[i][0]) &&
1106 value_notzero_p(polyhedron->Constraint[i][level]))
1107 return 0 ;
1109 for (i=0; i<polyhedron->NbConstraints; i++)
1110 if (value_pos_p(polyhedron->Constraint[i][level]))
1111 { if (first_lower)
1112 { first_lower = 0 ;
1113 lower_constraint = i ;
1115 else
1116 return 0 ;
1118 if (first_lower)
1119 return 0 ;
1121 /* We want an integral lower bound: no other non-zero entry except the
1122 * iterator coefficient and the constant.
1124 for (i=1; i<level; i++)
1125 if (value_notzero_p(polyhedron->Constraint[lower_constraint][i]))
1126 return 0 ;
1127 for (i=level+1; i<=polyhedron->Dimension; i++)
1128 if (value_notzero_p(polyhedron->Constraint[lower_constraint][i]))
1129 return 0 ;
1131 value_init_c(iterator) ;
1132 value_init_c(constant) ;
1133 value_init_c(tmp) ;
1135 /* If all is passed, then find the lower bound and return 1. */
1136 value_assign(iterator, polyhedron->Constraint[lower_constraint][level]) ;
1137 value_oppose(constant, polyhedron->Constraint[lower_constraint][dimension+1]);
1139 value_modulus(tmp, constant, iterator) ;
1140 value_division(*lower, constant, iterator) ;
1142 if (!(value_zero_p(tmp) || value_neg_p(constant)))
1143 value_increment(*lower, *lower) ;
1145 value_clear_c(iterator) ;
1146 value_clear_c(constant) ;
1147 value_clear_c(tmp) ;
1149 return 1 ;
1154 * cloog_domain_lowerbound_update function:
1155 * This function updates the integral lower bound of an iterator (such as its
1156 * column rank in the constraint set 'domain' is 'level') into 'lower'.
1157 * - Jun 29th 2003: first version.
1158 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1159 * CLooG 0.12.1).
1161 void cloog_domain_lowerbound_update(domain, level, lower)
1162 CloogDomain * domain ;
1163 int level ;
1164 Value lower ;
1165 { int i ;
1166 Polyhedron * polyhedron ;
1168 polyhedron = domain->polyhedron ;
1170 /* There is only one lower bound, the first one is the good one. */
1171 for (i=0; i<polyhedron->NbConstraints; i++)
1172 if (value_pos_p(polyhedron->Constraint[i][level]))
1173 { value_set_si(polyhedron->Constraint[i][level], 1) ;
1174 value_oppose(polyhedron->Constraint[i][polyhedron->Dimension+1], lower) ;
1175 break ;
1181 * cloog_domain_lazy_equal function:
1182 * This function returns 1 if the domains given as input are the same, 0 if it
1183 * is unable to decide. This function makes an entry-to-entry comparison between
1184 * the constraint systems, if all the entries are the same, the domains are
1185 * obviously the same and it returns 1, at the first difference, it returns 0.
1186 * This is a very fast way to verify this property. It has been shown (with the
1187 * CLooG benchmarks) that operations on equal domains are 17% of all the
1188 * polyhedral computations. For 75% of the actually identical domains, this
1189 * function answer that they are the same and allow to give immediately the
1190 * trivial solution instead of calling the heavy general functions of PolyLib.
1191 * - August 22th 2003: first version.
1192 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1193 * CLooG 0.12.1).
1195 int cloog_domain_lazy_equal(CloogDomain * d1, CloogDomain * d2)
1196 { int i, nb_elements ;
1197 Polyhedron * p1, * p2 ;
1199 p1 = d1->polyhedron ;
1200 p2 = d2->polyhedron ;
1202 while ((p1 != NULL) && (p2 != NULL))
1203 { if ((p1->NbConstraints != p2->NbConstraints) ||
1204 (p1->Dimension != p2->Dimension))
1205 return 0 ;
1207 nb_elements = p1->NbConstraints * (p1->Dimension + 2) ;
1209 for (i=0;i<nb_elements;i++)
1210 if (value_ne(p1->p_Init[i], p2->p_Init[i]))
1211 return 0 ;
1213 p1 = p1->next ;
1214 p2 = p2->next ;
1217 if ((p1 != NULL) || (p2 != NULL))
1218 return 0 ;
1220 return 1 ;
1225 * cloog_scattering_lazy_block function:
1226 * This function returns 1 if the two domains d1 and d2 given as input are the
1227 * same (possibly except for a dimension equal to a constant where we accept
1228 * a difference of 1) AND if we are sure that there are no other domain in
1229 * the code generation problem that may put integral points between those of
1230 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
1231 * safely consider the two domains as only one with two statements (a block) ?".
1232 * This function is lazy: it asks for very standard scattering representation
1233 * (only one constraint per dimension which is an equality, and the constraints
1234 * are ordered per dimension depth: the left hand side of the constraint matrix
1235 * is the identity) and will answer NO at the very first problem.
1236 * - d1 and d2 are the two domains to check for blocking,
1237 * - scattering is the linked list of all domains,
1238 * - scattdims is the total number of scattering dimentions.
1240 * - April 30th 2005: beginning
1241 * - June 9th 2005: first working version.
1242 * - June 10th 2005: debugging.
1243 * - June 21rd 2005: Adaptation for GMP.
1244 * - October 16th 2005: (debug) some false blocks have been removed.
1246 int cloog_scattering_lazy_block(CloogScattering *d1, CloogScattering *d2,
1247 CloogScatteringList *scattering, int scattdims)
1248 { int i, j, difference=0, different_constraint=0 ;
1249 Value date1, date2, date3, temp ;
1250 Polyhedron * p1, * p2, * p3 ;
1252 p1 = d1->polyhedron ;
1253 p2 = d2->polyhedron ;
1255 /* Some basic checks: we only accept convex domains, with same constraint
1256 * and dimension numbers.
1258 if ((p1->next != NULL) || (p2->next != NULL) ||
1259 (p1->NbConstraints != p2->NbConstraints) ||
1260 (p1->Dimension != p2->Dimension))
1261 return 0 ;
1263 /* There should be only one difference between the two domains, it
1264 * has to be at the constant level and the difference must be of +1,
1265 * moreover, after the difference all domain coefficient has to be 0.
1266 * The matrix shape is:
1268 * |===========|=====|<- 0 line
1269 * |===========|=====|
1270 * |===========|====?|<- different_constraint line (found here)
1271 * |===========|0000=|
1272 * |===========|0000=|<- pX->NbConstraints line
1273 * ^ ^ ^
1274 * | | |
1275 * | | (pX->Dimension + 2) column
1276 * | scattdims column
1277 * 0 column
1280 value_init_c(temp) ;
1281 for (i=0;i<p1->NbConstraints;i++)
1282 { if (difference == 0)
1283 { /* All elements except scalar must be equal. */
1284 for (j=0;j<(p1->Dimension + 1);j++)
1285 if (value_ne(p1->Constraint[i][j],p2->Constraint[i][j]))
1286 { value_clear_c(temp) ;
1287 return 0 ;
1289 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
1290 if (value_ne(p1->Constraint[i][j],p2->Constraint[i][j]))
1291 { value_increment(temp,p2->Constraint[i][j]) ;
1292 if (value_ne(p1->Constraint[i][j],temp))
1293 { value_clear_c(temp) ;
1294 return 0 ;
1296 else
1297 { difference = 1 ;
1298 different_constraint = i ;
1302 else
1303 { /* Scattering coefficients must be equal. */
1304 for (j=0;j<(scattdims+1);j++)
1305 if (value_ne(p1->Constraint[i][j],p2->Constraint[i][j]))
1306 { value_clear_c(temp) ;
1307 return 0 ;
1310 /* Domain coefficients must be 0. */
1311 for (;j<(p1->Dimension + 1);j++)
1312 if (value_notzero_p(p1->Constraint[i][j]) ||
1313 value_notzero_p(p2->Constraint[i][j]))
1314 { value_clear_c(temp) ;
1315 return 0 ;
1318 /* Scalar must be equal. */
1319 if (value_ne(p1->Constraint[i][j],p2->Constraint[i][j]))
1320 { value_clear_c(temp) ;
1321 return 0 ;
1325 value_clear_c(temp) ;
1327 /* If the domains are exactly the same, this is a block. */
1328 if (difference == 0)
1329 return 1 ;
1331 /* Now a basic check that the constraint with the difference is an
1332 * equality of a dimension with a constant.
1334 for (i=0;i<=different_constraint;i++)
1335 if (value_notzero_p(p1->Constraint[different_constraint][i]))
1336 return 0 ;
1338 if (value_notone_p(p1->Constraint[different_constraint]
1339 [different_constraint+1]))
1340 return 0 ;
1342 for (i=different_constraint+2;i<(p1->Dimension + 1);i++)
1343 if (value_notzero_p(p1->Constraint[different_constraint][i]))
1344 return 0 ;
1346 /* For the moment, d1 and d2 are a block candidate. There remains to check
1347 * that there is no other domain that may put an integral point between
1348 * them. In our lazy test we ensure this property by verifying that the
1349 * constraint matrices have a very strict shape: let us consider that the
1350 * dimension with the difference is d. Then the first d dimensions are
1351 * defined in their depth order using equalities (thus the first column begins
1352 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
1353 * the remaining simensions). If a domain can put integral points between the
1354 * domains of the block candidate, this means that the other entries on the
1355 * first d constraints are equal to those of d1 or d2. Thus we are looking for
1356 * such a constraint system, if it exists d1 and d2 is considered to not be
1357 * a block, it is a bock otherwise.
1359 * 1. Only equalities (for the first different_constraint+1 lines).
1360 * | 2. Must be the identity.
1361 * | | 3. Must be zero.
1362 * | | | 4. Elements are equal, the last one is either date1 or 2.
1363 * | | | |
1364 * | /-\ /---\ /---\
1365 * |0|100|00000|=====|<- 0 line
1366 * |0|010|00000|=====|
1367 * |0|001|00000|====?|<- different_constraint line
1368 * |*|***|*****|*****|
1369 * |*|***|*****|*****|<- pX->NbConstraints line
1370 * ^ ^ ^ ^
1371 * | | | |
1372 * | | | (pX->Dimension + 2) column
1373 * | | scattdims column
1374 * | different_constraint+1 column
1375 * 0 column
1378 /* Step 1 and 2. This is only necessary to check one domain because
1379 * we checked that they are equal on this part before.
1381 for (i=0;i<=different_constraint;i++)
1382 { for (j=0;j<i+1;j++)
1383 if (value_notzero_p(p1->Constraint[i][j]))
1384 return 0 ;
1386 if (value_notone_p(p1->Constraint[i][i+1]))
1387 return 0 ;
1389 for (j=i+2;j<=different_constraint+1;j++)
1390 if (value_notzero_p(p1->Constraint[i][j]))
1391 return 0 ;
1394 /* Step 3. */
1395 for (i=0;i<=different_constraint;i++)
1396 for (j=different_constraint+2;j<=scattdims;j++)
1397 if (value_notzero_p(p1->Constraint[i][j]))
1398 return 0 ;
1400 value_init_c(date1) ;
1401 value_init_c(date2) ;
1402 value_init_c(date3) ;
1404 /* Now we have to check that the two different dates are unique. */
1405 value_assign(date1, p1->Constraint[different_constraint][p1->Dimension + 1]) ;
1406 value_assign(date2, p2->Constraint[different_constraint][p2->Dimension + 1]) ;
1408 /* Step 4. We check all domains except d1 and d2 and we look for at least
1409 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
1411 while (scattering != NULL)
1412 { if ((scattering->domain != d1) && (scattering->domain != d2))
1413 { p3 = scattering->domain->polyhedron ;
1414 value_assign(date3,p3->Constraint[different_constraint][p3->Dimension+1]);
1415 difference = 0 ;
1417 if (value_ne(date3,date2) && value_ne(date3,date1))
1418 difference = 1 ;
1420 for (i=0;(i<different_constraint)&&(!difference);i++)
1421 for (j=0;(j<(p3->Dimension + 2))&&(!difference);j++)
1422 if (value_ne(p1->Constraint[i][j],p3->Constraint[i][j]))
1423 difference = 1 ;
1425 for (j=0;(j<(p3->Dimension + 1))&&(!difference);j++)
1426 if (value_ne(p1->Constraint[different_constraint][j],
1427 p3->Constraint[different_constraint][j]))
1428 difference = 1 ;
1430 if (!difference)
1431 { value_clear_c(date1) ;
1432 value_clear_c(date2) ;
1433 value_clear_c(date3) ;
1434 return 0 ;
1438 scattering = scattering->next ;
1441 value_clear_c(date1) ;
1442 value_clear_c(date2) ;
1443 value_clear_c(date3) ;
1444 return 1 ;
1449 * cloog_domain_lazy_disjoint function:
1450 * This function returns 1 if the domains given as input are disjoint, 0 if it
1451 * is unable to decide. This function finds the unknown with fixed values in
1452 * both domains (on a given constraint, their column entry is not zero and
1453 * only the constant coefficient can be different from zero) and verify that
1454 * their values are the same. If not, the domains are obviously disjoint and
1455 * it returns 1, if there is not such case it returns 0. This is a very fast
1456 * way to verify this property. It has been shown (with the CLooG benchmarks)
1457 * that operations on disjoint domains are 36% of all the polyhedral
1458 * computations. For 94% of the actually identical domains, this
1459 * function answer that they are disjoint and allow to give immediately the
1460 * trivial solution instead of calling the heavy general functions of PolyLib.
1461 * - August 22th 2003: first version.
1462 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1463 * CLooG 0.12.1).
1465 int cloog_domain_lazy_disjoint(CloogDomain * d1, CloogDomain * d2)
1466 { int i1, j1, i2, j2, scat_dim ;
1467 Value scat_val ;
1468 Polyhedron * p1, * p2 ;
1470 p1 = d1->polyhedron ;
1471 p2 = d2->polyhedron ;
1473 if ((p1->next != NULL) || (p2->next != NULL))
1474 return 0 ;
1476 value_init_c(scat_val) ;
1478 for (i1=0; i1<p1->NbConstraints; i1++)
1479 { if (value_notzero_p(p1->Constraint[i1][0]))
1480 continue ;
1482 scat_dim = 1 ;
1483 while (value_zero_p(p1->Constraint[i1][scat_dim]) &&
1484 (scat_dim < p1->Dimension))
1485 scat_dim ++ ;
1487 if (value_notone_p(p1->Constraint[i1][scat_dim]))
1488 continue ;
1489 else
1490 { for (j1=scat_dim+1; j1<=p1->Dimension; j1++)
1491 if (value_notzero_p(p1->Constraint[i1][j1]))
1492 break ;
1494 if (j1 != p1->Dimension+1)
1495 continue ;
1497 value_assign(scat_val,p1->Constraint[i1][p1->Dimension+1]) ;
1499 for (i2=0; i2<p2->NbConstraints; i2++)
1500 { for (j2=0;j2<scat_dim;j2++)
1501 if (value_notzero_p(p2->Constraint[i2][j2]))
1502 break ;
1504 if ((j2 != scat_dim) || value_notone_p(p2->Constraint[i2][scat_dim]))
1505 continue ;
1507 for (j2=scat_dim+1; j2<=p2->Dimension; j2++)
1508 if (value_notzero_p(p2->Constraint[i2][j2]))
1509 break ;
1511 if (j2 != p2->Dimension+1)
1512 continue ;
1514 if (value_ne(p2->Constraint[i2][p2->Dimension+1],scat_val))
1515 { value_clear_c(scat_val) ;
1516 return 1 ;
1522 value_clear_c(scat_val) ;
1523 return 0 ;
1528 * cloog_scattering_list_lazy_same function:
1529 * This function returns 1 if two domains in the list are the same, 0 if it
1530 * is unable to decide.
1531 * - February 9th 2004: first version.
1533 int cloog_scattering_list_lazy_same(CloogScatteringList * list)
1534 { /*int i=1, j=1 ;*/
1535 CloogScatteringList * current, * next ;
1537 current = list ;
1538 while (current != NULL)
1539 { next = current->next ;
1540 /*j=i+1;*/
1541 while (next != NULL)
1542 { if (cloog_domain_lazy_equal(current->domain,next->domain))
1543 { /*printf("Same domains: %d and %d\n",i,j) ;*/
1544 return 1 ;
1546 /*j++ ;*/
1547 next = next->next ;
1549 /*i++ ;*/
1550 current = current->next ;
1553 return 0 ;
1558 * Those functions are provided for "object encapsulation", to separate as much
1559 * as possible the inside of the CloogDomain structure from the rest of the
1560 * program, in order to ease the change of polyhedral library. For efficiency
1561 * reasons, they are defined and used as macros in domain.h.
1562 * - April 20th 2005: setting.
1564 Polyhedron * cloog_domain_polyhedron(CloogDomain * domain)
1565 { return domain->polyhedron ;
1568 int cloog_domain_nbconstraints(CloogDomain * domain)
1569 { return domain->polyhedron->NbConstraints ;
1573 int cloog_domain_dimension(CloogDomain * domain)
1574 { return domain->polyhedron->Dimension ;
1577 int cloog_scattering_dimension(CloogScattering *scatt, CloogDomain *domain)
1579 return cloog_domain_dimension(scatt) - cloog_domain_dimension(domain);
1582 int cloog_domain_isconvex(CloogDomain * domain)
1583 { return (domain->polyhedron->next == NULL)? 1 : 0 ;
1588 * cloog_domain_cut_first function:
1589 * this function returns a CloogDomain structure with everything except the
1590 * first part of the polyhedra union of the input domain as domain. After a call
1591 * to this function, there remains in the CloogDomain structure provided as
1592 * input only the first part of the original polyhedra union.
1593 * - April 20th 2005: first version, extracted from different part of loop.c.
1595 CloogDomain * cloog_domain_cut_first(CloogDomain * domain)
1596 { CloogDomain * rest ;
1598 if ((domain != NULL) && (domain->polyhedron != NULL))
1599 { rest = cloog_domain_alloc(domain->polyhedron->next) ;
1600 domain->polyhedron->next = NULL ;
1602 else
1603 rest = NULL ;
1605 return rest ;
1610 * cloog_scattering_lazy_isscalar function:
1611 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
1612 * is scalar, this means that the only constraint on this dimension must have
1613 * the shape "x.dimension + scalar = 0" with x an integral variable. This
1614 * function is lazy since we only accept x=1 (further calculations are easier
1615 * in this way).
1616 * - June 14th 2005: first version.
1617 * - June 21rd 2005: Adaptation for GMP.
1619 int cloog_scattering_lazy_isscalar(CloogScattering *domain, int dimension)
1620 { int i, j ;
1621 Polyhedron * polyhedron ;
1623 polyhedron = domain->polyhedron ;
1624 /* For each constraint... */
1625 for (i=0;i<polyhedron->NbConstraints;i++)
1626 { /* ...if it is concerned by the potentially scalar dimension... */
1627 if (value_notzero_p(polyhedron->Constraint[i][dimension+1]))
1628 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
1629 for (j=0;j<=dimension;j++)
1630 if (value_notzero_p(polyhedron->Constraint[i][j]))
1631 return 0 ;
1633 if (value_notone_p(polyhedron->Constraint[i][dimension+1]))
1634 return 0 ;
1636 for (j=dimension+2;j<(polyhedron->Dimension + 1);j++)
1637 if (value_notzero_p(polyhedron->Constraint[i][j]))
1638 return 0 ;
1642 return 1 ;
1647 * cloog_scattering_scalar function:
1648 * when we call this function, we know that "dimension" is a scalar dimension,
1649 * this function finds the scalar value in "domain" and returns it in "value".
1650 * - June 30th 2005: first version.
1652 void cloog_scattering_scalar(CloogScattering *domain, int dimension, Value * value)
1653 { int i ;
1654 Polyhedron * polyhedron ;
1656 polyhedron = domain->polyhedron ;
1657 /* For each constraint... */
1658 for (i=0;i<polyhedron->NbConstraints;i++)
1659 { /* ...if it is the equality defining the scalar dimension... */
1660 if (value_notzero_p(polyhedron->Constraint[i][dimension+1]) &&
1661 value_zero_p(polyhedron->Constraint[i][0]))
1662 { /* ...Then send the scalar value. */
1663 value_assign(*value,polyhedron->Constraint[i][polyhedron->Dimension+1]) ;
1664 value_oppose(*value,*value) ;
1665 return ;
1669 /* We should have found a scalar value: if not, there is an error. */
1670 fprintf(stderr, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
1671 dimension) ;
1672 exit(0) ;
1677 * cloog_scattering_erase_dimension function:
1678 * this function returns a CloogDomain structure builds from 'domain' where
1679 * we removed the dimension 'dimension' and every constraint considering this
1680 * dimension. This is not a projection ! Every data concerning the
1681 * considered dimension is simply erased.
1682 * - June 14th 2005: first version.
1683 * - June 21rd 2005: Adaptation for GMP.
1685 CloogDomain *cloog_scattering_erase_dimension(CloogScattering *domain,
1686 int dimension)
1687 { int i, j, mi, nb_dim ;
1688 CloogMatrix * matrix ;
1689 CloogDomain * erased ;
1690 Polyhedron * polyhedron ;
1692 polyhedron = domain->polyhedron ;
1693 nb_dim = polyhedron->Dimension ;
1695 /* The matrix is one column less and at least one constraint less. */
1696 matrix = cloog_matrix_alloc(polyhedron->NbConstraints-1,nb_dim+1) ;
1698 /* mi is the constraint counter for the matrix. */
1699 mi = 0 ;
1700 for (i=0;i<polyhedron->NbConstraints;i++)
1701 if (value_zero_p(polyhedron->Constraint[i][dimension+1]))
1702 { for (j=0;j<=dimension;j++)
1703 value_assign(matrix->p[mi][j],polyhedron->Constraint[i][j]) ;
1705 for (j=dimension+2;j<nb_dim+2;j++)
1706 value_assign(matrix->p[mi][j-1],polyhedron->Constraint[i][j]) ;
1708 mi ++ ;
1711 erased = cloog_domain_matrix2domain(matrix) ;
1712 cloog_matrix_free(matrix) ;
1714 return erased ;
1719 * cloog_domain_cube:
1720 * Construct and return a dim-dimensional cube, with values ranging
1721 * between min and max in each dimension.
1723 CloogDomain *cloog_domain_cube(int dim, cloog_int_t min, cloog_int_t max,
1724 CloogOptions *options)
1726 int i;
1727 Matrix *M;
1728 Polyhedron *P;
1730 M = Matrix_Alloc(2*dim, 2+dim);
1731 for (i = 0; i < dim; ++i) {
1732 value_set_si(M->p[2*i][0], 1);
1733 value_set_si(M->p[2*i][1+i], 1);
1734 value_oppose(M->p[2*i][1+dim], min);
1735 value_set_si(M->p[2*i+1][0], 1);
1736 value_set_si(M->p[2*i+1][1+i], -1);
1737 value_assign(M->p[2*i+1][1+dim], max);
1739 P = Constraints2Polyhedron(M, MAX_RAYS);
1740 Matrix_Free(M);
1741 return cloog_domain_alloc(P);
1745 * cloog_domain_scatter function:
1746 * This function add the scattering (scheduling) informations in a domain.
1748 CloogDomain *cloog_domain_scatter(CloogDomain *domain, CloogScattering *scatt)
1749 { int scatt_dim ;
1750 CloogDomain *ext, *newdom, *newpart, *temp;
1752 newdom = NULL ;
1753 scatt_dim = cloog_scattering_dimension(scatt, domain);
1755 /* For each polyhedron of domain (it can be an union of polyhedra). */
1756 while (domain != NULL)
1757 { /* Extend the domain by adding the scattering dimensions as the new
1758 * first domain dimensions.
1760 ext = cloog_domain_extend(domain,scatt_dim,cloog_domain_dimension(domain)) ;
1761 /* Then add the scattering constraints. */
1762 newpart = cloog_domain_addconstraints(scatt,ext) ;
1763 cloog_domain_free(ext) ;
1765 if (newdom != NULL)
1766 { temp = newdom ;
1767 newdom = cloog_domain_union(newdom,newpart) ;
1768 cloog_domain_free(temp) ;
1769 cloog_domain_free(newpart) ;
1771 else
1772 newdom = newpart ;
1774 /* We don't want to free the rest of the list. */
1775 temp = domain ;
1776 domain = cloog_domain_cut_first(temp) ;
1777 cloog_domain_free(temp) ;
1780 return newdom;