move polylib specific functions in the domain.c polylib backend
[cloog-ppl.git] / source / polylib / domain.c
blob96fb9934a3834271131492450592929d2e15f1b9
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 static 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 static CloogMatrix * cloog_domain_domain2matrix(CloogDomain * domain)
151 return cloog_matrix_matrix(Polyhedron2Constraints(cloog_domain_polyhedron (domain)));
154 static inline int cloog_domain_references (CloogDomain *d)
156 return d->_references;
159 static inline void cloog_domain_set_references (CloogDomain *d, int i)
161 d->_references = i;
165 * cloog_domain_print function:
166 * This function prints the content of a CloogDomain structure (domain) into
167 * a file (foo, possibly stdout).
169 void cloog_domain_print(FILE * foo, CloogDomain * domain)
170 { Polyhedron_Print(foo,P_VALUE_FMT,cloog_domain_polyhedron (domain)) ;
171 fprintf (foo, "Number of active references: %d\n", cloog_domain_references (domain));
176 * cloog_polyhedron_print function:
177 * This function prints the content of a Polyhedron structure (polyhedron) into
178 * a file (foo, possibly stdout). Just there as a development facility.
180 void cloog_polyhedron_print(FILE * foo, Polyhedron * polyhedron)
181 { Polyhedron_Print(foo,P_VALUE_FMT,polyhedron) ;
186 * cloog_domain_free function:
187 * This function frees the allocated memory for a CloogDomain structure
188 * (domain). It decrements the number of active references to this structure,
189 * if there are no more references on the structure, it frees it (with the
190 * included list of polyhedra).
192 void cloog_domain_free(CloogDomain * domain)
193 { if (domain != NULL)
195 cloog_domain_set_references (domain, cloog_domain_references (domain) - 1);
197 if (cloog_domain_references (domain) == 0)
199 if (cloog_domain_polyhedron (domain) != NULL)
201 cloog_domain_leak_down ();
202 Domain_Free(cloog_domain_polyhedron (domain)) ;
205 free(domain) ;
212 * cloog_domain_copy function:
213 * This function returns a copy of a CloogDomain structure (domain). To save
214 * memory this is not a memory copy but we increment a counter of active
215 * references inside the structure, then return a pointer to that structure.
217 CloogDomain * cloog_domain_copy(CloogDomain * domain)
219 cloog_domain_set_references (domain, cloog_domain_references (domain) + 1);
220 return domain ;
225 * cloog_domain_image function:
226 * This function returns a CloogDomain structure such that the included
227 * polyhedral domain is computed from the former one into another
228 * domain according to a given affine mapping function (mapping).
230 static CloogDomain * cloog_domain_image(CloogDomain * domain, CloogMatrix * mapping)
231 { return (cloog_domain_alloc(DomainImage(cloog_domain_polyhedron (domain),mapping,MAX_RAYS)));
236 * cloog_domain_preimage function:
237 * Given a polyhedral domain (polyhedron) inside a CloogDomain structure and a
238 * mapping function (mapping), this function returns a new CloogDomain structure
239 * with a polyhedral domain which when transformed by mapping function (mapping)
240 * gives (polyhedron).
242 static CloogDomain * cloog_domain_preimage(CloogDomain * domain, CloogMatrix * mapping)
243 { return (cloog_domain_alloc(DomainPreimage(cloog_domain_polyhedron (domain),
244 mapping,MAX_RAYS))) ;
249 * cloog_domain_convex function:
250 * Given a polyhedral domain (polyhedron), this function concatenates the lists
251 * of rays and lines of the two (or more) polyhedra in the domain into one
252 * combined list, and find the set of constraints which tightly bound all of
253 * those objects. It returns the corresponding polyhedron.
255 CloogDomain * cloog_domain_convex(CloogDomain * domain)
256 { return (cloog_domain_alloc(DomainConvex(cloog_domain_polyhedron (domain),MAX_RAYS)));
259 static inline Polyhedron * cloog_polyhedron_next (Polyhedron *p)
261 return p->next ;
264 static inline void cloog_polyhedron_set_next (Polyhedron *p, Polyhedron *n)
266 p->next = n;
269 static inline Polyhedron * cloog_domain_polyhedron_next (CloogDomain * domain)
271 return cloog_polyhedron_next (cloog_domain_polyhedron (domain));
274 static inline void cloog_domain_polyhedron_set_next (CloogDomain *d,
275 Polyhedron *n)
277 cloog_polyhedron_set_next (cloog_domain_polyhedron (d), n) ;
280 static inline unsigned cloog_polyhedron_nbc (Polyhedron *p)
282 return p->NbConstraints;
285 static inline Value *cloog_polyhedron_c (Polyhedron *p, int i)
287 return p->Constraint[i];
290 static inline Value cloog_polyhedron_cval (Polyhedron *p, int i, int j)
292 return p->Constraint[i][j];
295 static inline void cloog_polyhedron_cval_set_si (Polyhedron *p, int i, int j, int k)
297 value_set_si (p->Constraint[i][j], k);
300 static inline void cloog_polyhedron_cval_oppose (Polyhedron *p, int i, int j, int k)
302 value_oppose (p->Constraint[i][j], k);
305 static inline void cloog_polyhedron_c_gcd (Polyhedron *p, int i, int j, int k, Value *gcd)
307 Vector_Gcd(&(p->Constraint[i][1]), k, gcd);
310 static inline unsigned cloog_polyhedron_nbeq (Polyhedron *p)
312 return p->NbEq;
315 static inline unsigned cloog_domain_nbeq (CloogDomain *d)
317 return cloog_polyhedron_nbeq (cloog_domain_polyhedron (d));
320 static inline unsigned cloog_polyhedron_dim (Polyhedron *p)
322 return p->Dimension;
326 int cloog_domain_isconvex (CloogDomain *domain)
328 return !cloog_domain_polyhedron_next (domain);
331 unsigned cloog_domain_dim (CloogDomain *d)
333 return cloog_polyhedron_dim (cloog_domain_polyhedron (d));
338 * cloog_domain_simplified_hull:
339 * Given a list (union) of polyhedra, this function returns a single
340 * polyhedron that contains this union and uses only contraints that
341 * appear in one or more of the polyhedra in the list.
343 * We simply iterate over all constraints of all polyhedra and test
344 * whether all rays of the other polyhedra satisfy/saturate the constraint.
346 static CloogDomain *cloog_domain_simplified_hull(CloogDomain * domain)
348 int dim = cloog_domain_dim (domain);
349 int i, j, k, l;
350 int nb_pol = 0, nb_constraints = 0;
351 Polyhedron *P;
352 CloogMatrix **rays, *matrix;
353 Value tmp;
354 CloogDomain *bounds;
356 value_init(tmp);
357 for (P = cloog_domain_polyhedron (domain); P; P = cloog_polyhedron_next (P)) {
358 ++nb_pol;
359 nb_constraints += cloog_polyhedron_nbc (P);
361 matrix = cloog_matrix_alloc(nb_constraints, 1 + dim + 1);
362 nb_constraints = 0;
363 rays = (CloogMatrix **)malloc(nb_pol * sizeof(CloogMatrix*));
364 for (P = cloog_domain_polyhedron (domain), i = 0; P; P = cloog_polyhedron_next (P), ++i)
365 rays[i] = Polyhedron2Rays(P);
367 for (P = cloog_domain_polyhedron (domain), i = 0; P; P = cloog_polyhedron_next (P), ++i) {
368 CloogMatrix *constraints = Polyhedron2Constraints(P);
369 for (j = 0; j < constraints->NbRows; ++j) {
370 for (k = 0; k < nb_pol; ++k) {
371 if (i == k)
372 continue;
373 for (l = 0; l < rays[k]->NbRows; ++l) {
374 Inner_Product(constraints->p[j]+1, rays[k]->p[l]+1, dim+1, &tmp);
375 if (value_neg_p(tmp))
376 break;
377 if ((value_zero_p(cloog_matrix_element(constraints, j, 0)) ||
378 value_zero_p(cloog_matrix_element(rays[k], l, 0))) && value_pos_p(tmp))
379 break;
381 if (l < rays[k]->NbRows)
382 break;
384 if (k == nb_pol)
385 Vector_Copy(constraints->p[j], matrix->p[nb_constraints++], 1+dim+1);
387 Matrix_Free(constraints);
390 for (P = cloog_domain_polyhedron (domain), i = 0; P; P = cloog_polyhedron_next (P), ++i)
391 Matrix_Free(rays[i]);
392 free(rays);
393 value_clear(tmp);
395 matrix->NbRows = nb_constraints;
396 bounds = cloog_domain_matrix2domain(matrix);
397 cloog_matrix_free(matrix);
399 return bounds;
403 * cloog_domain_bounds:
404 * Given a list (union) of polyhedra "domain", this function returns a single
405 * polyhedron with constraints that reflect the (parametric) lower and
406 * upper bound on dimension "dim".
408 * nb_par is the number of parameters of the domain.
410 static CloogDomain * cloog_domain_bounds(CloogDomain * domain, int dim, int nb_par)
412 int row, nb_rows, nb_columns, difference;
413 CloogDomain * projected_domain, *extended_domain, *bounds;
414 CloogMatrix * matrix ;
416 nb_rows = 1 + nb_par + 1;
417 nb_columns = cloog_domain_dim (domain) + 1 ;
418 difference = nb_columns - nb_rows ;
420 if (difference == 0)
421 return(cloog_domain_convex(domain));
423 matrix = cloog_matrix_alloc(nb_rows, nb_columns);
425 cloog_matrix_element_set_si(matrix, 0, dim, 1);
426 for (row = 1; row < nb_rows; row++)
427 cloog_matrix_element_set_si(matrix, row, row+difference, 1);
429 projected_domain = cloog_domain_image(domain,matrix) ;
430 extended_domain = cloog_domain_preimage(projected_domain, matrix);
431 cloog_domain_free(projected_domain);
432 cloog_matrix_free(matrix) ;
433 bounds = cloog_domain_convex(extended_domain);
434 cloog_domain_free(extended_domain);
436 return bounds;
440 * cloog_domain_simple_convex:
441 * Given a list (union) of polyhedra, this function returns a "simple"
442 * convex hull of this union. In particular, the constraints of the
443 * the returned polyhedron consist of (parametric) lower and upper
444 * bounds on individual variables and constraints that appear in the
445 * original polyhedra.
447 * nb_par is the number of parameters of the domain.
449 CloogDomain * cloog_domain_simple_convex(CloogDomain * domain, int nb_par)
451 int i;
452 int dim = cloog_domain_dim (domain) - nb_par;
453 CloogDomain *convex = NULL;
455 if (cloog_domain_isconvex(domain))
456 return cloog_domain_copy(domain);
458 for (i = 0; i < dim; ++i) {
459 CloogDomain *bounds = cloog_domain_bounds(domain, i, nb_par);
461 if (!convex)
462 convex = bounds;
463 else {
464 CloogDomain *temp = cloog_domain_intersection(convex, bounds);
465 cloog_domain_free(bounds);
466 cloog_domain_free(convex);
467 convex = temp;
470 if (dim > 1) {
471 CloogDomain *temp, *bounds;
473 bounds = cloog_domain_simplified_hull(domain);
474 temp = cloog_domain_intersection(convex, bounds);
475 cloog_domain_free(bounds);
476 cloog_domain_free(convex);
477 convex = temp;
480 return convex;
485 * cloog_domain_simplify function:
486 * Given two polyhedral domains (pol1) and (pol2) inside two CloogDomain
487 * structures, this function finds the largest domain set (or the smallest list
488 * of non-redundant constraints), that when intersected with polyhedral
489 * domain (pol2) equals (Pol1)intersect(Pol2). The output is a new CloogDomain
490 * structure with a polyhedral domain with the "redundant" constraints removed.
491 * NB: this function do not work as expected with unions of polyhedra...
493 CloogDomain * cloog_domain_simplify(CloogDomain * dom1, CloogDomain * dom2)
495 CloogMatrix *M, *M2;
496 CloogDomain *dom;
497 Polyhedron *P = cloog_domain_polyhedron (dom1);
499 /* DomainSimplify doesn't remove all redundant equalities,
500 * so we remove them here first in case both dom1 and dom2
501 * are single polyhedra (i.e., not unions of polyhedra).
503 if (cloog_domain_isconvex (dom1)
504 && cloog_domain_isconvex (dom2)
505 && cloog_polyhedron_nbeq (P) && cloog_domain_nbeq (dom2)) {
506 int i, row;
507 int rows = cloog_polyhedron_nbeq (P) + cloog_domain_nbeq (dom2);
508 int cols = cloog_polyhedron_dim (P) + 2;
509 int rank;
510 M = cloog_matrix_alloc(rows, cols);
511 M2 = cloog_matrix_alloc(cloog_polyhedron_nbc (P), cols);
512 Vector_Copy(cloog_polyhedron_c (cloog_domain_polyhedron (dom2), 0), M->p[0],
513 cloog_domain_nbeq (dom2) * cols);
514 rank = cloog_domain_nbeq (dom2);
515 row = 0;
516 for (i = 0; i < cloog_polyhedron_nbeq (P); ++i) {
517 Vector_Copy(cloog_polyhedron_c (P, i), M->p[rank], cols);
518 if (Gauss(M, rank+1, cols-1) > rank) {
519 Vector_Copy(cloog_polyhedron_c (P, i), M2->p[row++], cols);
520 rank++;
523 if (row < cloog_polyhedron_nbeq (P)) {
524 Vector_Copy(cloog_polyhedron_c (P, cloog_polyhedron_nbeq (P)), M2->p[row],
525 (cloog_polyhedron_nbc (P) - cloog_polyhedron_nbeq (P)) * cols);
526 P = Constraints2Polyhedron(M2, MAX_RAYS);
528 cloog_matrix_free(M2);
529 cloog_matrix_free(M);
531 dom = cloog_domain_alloc(DomainSimplify(P, cloog_domain_polyhedron (dom2),MAX_RAYS));
532 if (P != cloog_domain_polyhedron (dom1))
533 Polyhedron_Free(P);
534 return dom;
539 * cloog_domain_union function:
540 * This function returns a new CloogDomain structure including a polyhedral
541 * domain which is the union of two polyhedral domains (pol1) U (pol2) inside
542 * two CloogDomain structures.
544 CloogDomain * cloog_domain_union(CloogDomain * dom1, CloogDomain * dom2)
545 { return (cloog_domain_alloc(DomainUnion(cloog_domain_polyhedron (dom1),
546 cloog_domain_polyhedron (dom2),MAX_RAYS))) ;
551 * cloog_domain_intersection function:
552 * This function returns a new CloogDomain structure including a polyhedral
553 * domain which is the intersection of two polyhedral domains (pol1)inter(pol2)
554 * inside two CloogDomain structures.
556 CloogDomain * cloog_domain_intersection(CloogDomain * dom1, CloogDomain * dom2)
557 { return (cloog_domain_alloc(DomainIntersection(cloog_domain_polyhedron (dom1),
558 cloog_domain_polyhedron (dom2),MAX_RAYS))) ;
563 * cloog_domain_difference function:
564 * This function returns a new CloogDomain structure including a polyhedral
565 * domain which is the difference of two polyhedral domains domain \ minus
566 * inside two CloogDomain structures.
567 * - November 8th 2001: first version.
569 CloogDomain * cloog_domain_difference(CloogDomain * domain, CloogDomain * minus)
570 { if (cloog_domain_isempty(minus))
571 return(cloog_domain_copy(domain)) ;
572 else
573 return (cloog_domain_alloc(DomainDifference(cloog_domain_polyhedron (domain),
574 cloog_domain_polyhedron (minus),MAX_RAYS))) ;
579 * cloog_domain_addconstraints function :
580 * This function adds source's polyhedron constraints to target polyhedron: for
581 * each element of the polyhedron inside 'target' (i.e. element of the union
582 * of polyhedra) it adds the constraints of the corresponding element in
583 * 'source'.
584 * - August 10th 2002: first version.
585 * Nota bene for future : it is possible that source and target don't have the
586 * same number of elements (try iftest2 without non-shared constraint
587 * elimination in cloog_loop_separate !). This function is yet another part
588 * of the DomainSimplify patching problem...
590 CloogDomain * cloog_domain_addconstraints(domain_source, domain_target)
591 CloogDomain * domain_source, * domain_target ;
592 { unsigned nb_constraint ;
593 Value * constraints ;
594 Polyhedron * source, * target, * new, * next, * last ;
596 source = cloog_domain_polyhedron (domain_source) ;
597 target = cloog_domain_polyhedron (domain_target) ;
599 constraints = source->p_Init ;
600 nb_constraint = cloog_polyhedron_nbc (source) ;
601 source = cloog_polyhedron_next (source) ;
602 new = AddConstraints(constraints,nb_constraint,target,MAX_RAYS) ;
603 last = new ;
604 next = cloog_polyhedron_next (target) ;
606 while (next != NULL)
607 { /* BUG !!! This is actually a bug. I don't know yet how to cleanly avoid
608 * the situation where source and target do not have the same number of
609 * elements. So this 'if' is an awful trick, waiting for better.
611 if (source != NULL)
612 { constraints = source->p_Init ;
613 nb_constraint = cloog_polyhedron_nbc (source) ;
614 source = cloog_polyhedron_next (source) ;
616 cloog_polyhedron_set_next (last, AddConstraints (constraints, nb_constraint,
617 next, MAX_RAYS));
618 last = cloog_polyhedron_next (last);
619 next = cloog_polyhedron_next (next);
622 return (cloog_domain_alloc(new)) ;
627 * cloog_domain_sort function:
628 * This function topologically sorts (nb_pols) polyhedra. Here (pols) is a an
629 * array of pointers to polyhedra, (nb_pols) is the number of polyhedra,
630 * (level) is the level to consider for partial ordering (nb_par) is the
631 * parameter space dimension, (permut) if not NULL, is an array of (nb_pols)
632 * integers that contains a permutation specification after call in order to
633 * apply the topological sorting.
635 void cloog_domain_sort(pols, nb_pols, level, nb_par, permut)
636 Polyhedron ** pols ;
637 unsigned nb_pols, level, nb_par ;
638 int * permut ;
639 { int * time ;
641 /* time is an array of (nb_pols) integers to store logical time values. We
642 * do not use it, but it is compulsory for PolyhedronTSort.
644 time = (int *)malloc(nb_pols*sizeof(int)) ;
646 /* PolyhedronTSort will fill up permut (and time). */
647 PolyhedronTSort(pols,nb_pols,level,nb_par,time,permut,MAX_RAYS) ;
649 free(time) ;
654 * cloog_domain_empty function:
655 * This function allocates the memory space for a CloogDomain structure and
656 * sets its polyhedron to an empty polyhedron with 'dimension' dimensions.
657 * Then it returns a pointer to the allocated space.
658 * - June 10th 2005: first version.
660 CloogDomain * cloog_domain_empty(int dimension)
661 { return (cloog_domain_alloc(Empty_Polyhedron(dimension))) ;
665 /******************************************************************************
666 * Structure display function *
667 ******************************************************************************/
671 * cloog_domain_print_structure :
672 * this function is a more human-friendly way to display the CloogDomain data
673 * structure, it only shows the constraint system and includes an indentation
674 * level (level) in order to work with others print_structure functions.
675 * Written by Olivier Chorier, Luc Marchaud, Pierre Martin and Romain Tartiere.
676 * - April 24th 2005: Initial version.
677 * - May 26th 2005: Memory leak hunt.
678 * - June 16th 2005: (Ced) Integration in domain.c.
680 void cloog_domain_print_structure(FILE * file, CloogDomain * domain, int level)
681 { int i ;
682 CloogMatrix * matrix ;
684 /* Go to the right level. */
685 for(i=0; i<level; i++)
686 fprintf(file,"|\t") ;
688 if (domain != NULL)
689 { fprintf(file,"+-- CloogDomain\n") ;
691 /* Print the matrix. */
692 matrix = cloog_domain_domain2matrix(domain) ;
693 cloog_matrix_print_structure(file,matrix,level) ;
694 cloog_matrix_free(matrix) ;
696 /* A blank line. */
697 for (i=0; i<level+1; i++)
698 fprintf(file,"|\t") ;
699 fprintf(file,"\n") ;
701 else
702 fprintf(file,"+-- Null CloogDomain\n") ;
708 * cloog_domain_list_print function:
709 * This function prints the content of a CloogDomainList structure into a
710 * file (foo, possibly stdout).
711 * - November 6th 2001: first version.
713 void cloog_domain_list_print(FILE * foo, CloogDomainList * list)
715 while (list != NULL)
717 cloog_domain_print (foo, cloog_domain (list)) ;
718 list = cloog_next_domain (list) ;
723 /******************************************************************************
724 * Memory deallocation function *
725 ******************************************************************************/
729 * cloog_domain_list_free function:
730 * This function frees the allocated memory for a CloogDomainList structure.
731 * - November 6th 2001: first version.
733 void cloog_domain_list_free(CloogDomainList * list)
734 { CloogDomainList * temp ;
736 while (list != NULL)
738 temp = cloog_next_domain (list) ;
739 cloog_domain_free (cloog_domain (list)) ;
740 free(list) ;
741 list = temp ;
746 /******************************************************************************
747 * Reading function *
748 ******************************************************************************/
752 * cloog_domain_read function:
753 * Adaptation from the PolyLib. This function reads a matrix into a file (foo,
754 * posibly stdin) and returns a pointer to a polyhedron containing the read
755 * information.
756 * - October 18th 2001: first version.
758 CloogDomain * cloog_domain_read(FILE * foo)
759 { CloogMatrix * matrix ;
760 CloogDomain * domain ;
762 matrix = cloog_matrix_read(foo) ;
763 domain = cloog_domain_matrix2domain(matrix) ;
764 cloog_matrix_free(matrix) ;
766 return(domain) ;
771 * cloog_domain_union_read function:
772 * This function reads a union of polyhedra into a file (foo, posibly stdin) and
773 * returns a pointer to a Polyhedron containing the read information.
774 * - September 9th 2002: first version.
775 * - October 29th 2005: (debug) removal of a leak counting "correction" that
776 * was just false since ages.
778 CloogDomain * cloog_domain_union_read(FILE * foo)
779 { int i, nb_components ;
780 char s[MAX_STRING] ;
781 CloogDomain * domain, * temp, * old ;
783 /* domain reading: nb_components (constraint matrices). */
784 while (fgets(s,MAX_STRING,foo) == 0) ;
785 while ((*s=='#' || *s=='\n') || (sscanf(s," %d",&nb_components)<1))
786 fgets(s,MAX_STRING,foo) ;
788 if (nb_components > 0)
789 { /* 1. first part of the polyhedra union, */
790 domain = cloog_domain_read(foo) ;
791 /* 2. and the nexts. */
792 for (i=1;i<nb_components;i++)
793 { /* Leak counting is OK since next allocated domain is freed here. */
794 temp = cloog_domain_read(foo) ;
795 old = domain ;
796 domain = cloog_domain_union(temp,old) ;
797 cloog_domain_free(temp) ;
798 cloog_domain_free(old) ;
800 return domain ;
802 else
803 return NULL ;
808 * cloog_domain_list_read function:
809 * This function reads a list of polyhedra into a file (foo, posibly stdin) and
810 * returns a pointer to a CloogDomainList containing the read information.
811 * - November 6th 2001: first version.
813 CloogDomainList * cloog_domain_list_read(FILE * foo)
814 { int i, nb_pols ;
815 char s[MAX_STRING] ;
816 CloogDomainList * list, * now, * next ;
819 /* We read first the number of polyhedra in the list. */
820 while (fgets(s,MAX_STRING,foo) == 0) ;
821 while ((*s=='#' || *s=='\n') || (sscanf(s," %d",&nb_pols)<1))
822 fgets(s,MAX_STRING,foo) ;
824 /* Then we read the polyhedra. */
825 list = NULL ;
826 if (nb_pols > 0)
827 { list = (CloogDomainList *)malloc(sizeof(CloogDomainList)) ;
828 cloog_set_domain (list, cloog_domain_read (foo));
829 cloog_set_next_domain (list, NULL);
830 now = list ;
831 for (i=1;i<nb_pols;i++)
832 { next = (CloogDomainList *)malloc(sizeof(CloogDomainList)) ;
833 cloog_set_domain (next, cloog_domain_read (foo));
834 cloog_set_next_domain (next, NULL);
835 cloog_set_next_domain (now, next);
836 now = cloog_next_domain (now);
839 return(list) ;
843 /******************************************************************************
844 * Processing functions *
845 ******************************************************************************/
849 * cloog_domain_malloc function:
850 * This function allocates the memory space for a CloogDomain structure and
851 * sets its fields with default values. Then it returns a pointer to the
852 * allocated space.
853 * - November 21th 2005: first version.
855 static CloogDomain * cloog_domain_malloc()
856 { CloogDomain * domain ;
858 domain = (CloogDomain *)malloc(sizeof(CloogDomain)) ;
859 if (domain == NULL)
860 { fprintf(stderr, "[CLooG]ERROR: memory overflow.\n") ;
861 exit(1) ;
863 cloog_domain_leak_up() ;
865 /* We set the various fields with default values. */
866 cloog_domain_polyhedron_set (domain, NULL) ;
867 cloog_domain_set_references (domain, 1);
869 return domain ;
874 * cloog_domain_alloc function:
875 * This function allocates the memory space for a CloogDomain structure and
876 * sets its fields with those given as input. Then it returns a pointer to the
877 * allocated space.
878 * - April 19th 2005: first version.
879 * - November 21th 2005: cloog_domain_malloc use.
881 CloogDomain * cloog_domain_alloc(Polyhedron * polyhedron)
882 { CloogDomain * domain ;
884 if (polyhedron == NULL)
885 return NULL ;
886 else
887 { domain = cloog_domain_malloc() ;
888 cloog_domain_polyhedron_set (domain, polyhedron) ;
890 return domain ;
896 * cloog_domain_isempty function:
897 * This function returns 1 if the polyhedron given as input is empty, 0
898 * otherwise.
899 * - October 28th 2001: first version.
901 int cloog_domain_isempty(CloogDomain * domain)
902 { if (cloog_domain_polyhedron (domain) == NULL)
903 return 1 ;
905 if (cloog_domain_polyhedron_next (domain))
906 return(0) ;
908 return((cloog_domain_dim (domain)
909 < cloog_domain_nbeq (domain)) ? 1 : 0) ;
914 * cloog_domain_project function:
915 * From Quillere's LoopGen 0.4. This function returns the projection of
916 * (domain) on the (level) first dimensions (i.e. outer loops). It returns a
917 * pointer to the projected Polyhedron.
918 * - nb_par is the number of parameters.
920 * - October 27th 2001: first version.
921 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
922 * CLooG 0.12.1).
924 CloogDomain * cloog_domain_project(CloogDomain * domain, int level, int nb_par)
925 { int row, column, nb_rows, nb_columns, difference ;
926 CloogDomain * projected_domain ;
927 CloogMatrix * matrix ;
929 nb_rows = level + nb_par + 1 ;
930 nb_columns = cloog_domain_dim (domain) + 1 ;
931 difference = nb_columns - nb_rows ;
933 if (difference == 0)
934 return(cloog_domain_copy(domain)) ;
936 matrix = cloog_matrix_alloc(nb_rows,nb_columns) ;
938 for (row=0;row<level;row++)
939 for (column=0;column<nb_columns; column++)
940 cloog_matrix_element_set_si(matrix, row, column, (row == column ? 1 : 0)) ;
942 for (;row<nb_rows;row++)
943 for (column=0;column<nb_columns;column++)
944 cloog_matrix_element_set_si (matrix, row, column, (row+difference == column ? 1 : 0)) ;
946 projected_domain = cloog_domain_image(domain,matrix) ;
947 cloog_matrix_free(matrix) ;
949 return(projected_domain) ;
953 * cloog_domain_extend function:
954 * From Quillere's LoopGen 0.4. This function returns the (domain) given as
955 * input with (dim)+(nb_par) dimensions. The new dimensions are added before
956 * the (nb_par) parameters. This function does not free (domain), and returns
957 * a new polyhedron.
958 * - nb_par is the number of parameters.
960 * - October 27th 2001: first version.
961 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
962 * CLooG 0.12.1).
964 CloogDomain * cloog_domain_extend(CloogDomain * domain, int dim, int nb_par)
965 { int row, column, nb_rows, nb_columns, difference ;
966 CloogDomain * extended_domain ;
967 CloogMatrix * matrix ;
969 nb_rows = 1 + cloog_domain_dim (domain) ;
970 nb_columns = dim + nb_par + 1 ;
971 difference = nb_columns - nb_rows ;
973 if (difference == 0)
974 return(cloog_domain_copy(domain)) ;
976 matrix = cloog_matrix_alloc(nb_rows,nb_columns) ;
978 for (row=0;row<cloog_domain_dim (domain) - nb_par;row++)
979 for (column=0;column<nb_columns;column++)
980 cloog_matrix_element_set_si(matrix, row, column, (row == column ? 1 : 0)) ;
982 for (;row<=cloog_domain_dim (domain); row++)
983 for (column=0;column<nb_columns;column++)
984 cloog_matrix_element_set_si(matrix, row, column, (row+difference == column ? 1 : 0)) ;
986 extended_domain = cloog_domain_preimage(domain,matrix) ;
987 cloog_matrix_free(matrix) ;
989 return(extended_domain) ;
994 * cloog_domain_never_integral function:
995 * For us, an equality like 3*i -4 = 0 is always false since 4%3 != 0. This
996 * function returns a boolean set to 1 if there is this kind of 'never true'
997 * constraint inside a polyhedron, 0 otherwise.
998 * - domain is the polyhedron to check,
1000 * - November 28th 2001: first version.
1001 * - June 26th 2003: for iterators, more 'never true' constraints are found
1002 * (compare cholesky2 and vivien with a previous version),
1003 * checking for the parameters created (compare using vivien).
1004 * - June 28th 2003: Previously in loop.c and called
1005 * cloog_loop_simplify_nevertrue, now here !
1006 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1007 * CLooG 0.12.1).
1008 * - October 14th 2005: Complete rewriting, not faster but code quite shorter.
1010 int cloog_domain_never_integral(CloogDomain * domain)
1011 { int i, dimension ;
1012 Value gcd, modulo ;
1013 Polyhedron * polyhedron ;
1015 if ((domain == NULL) || (cloog_domain_polyhedron (domain) == NULL))
1016 return 1 ;
1018 value_init_c(gcd) ;
1019 value_init_c(modulo) ;
1020 polyhedron = cloog_domain_polyhedron (domain) ;
1021 dimension = cloog_domain_dim (domain) + 2 ;
1023 /* For each constraint... */
1024 for (i=0; i<cloog_polyhedron_nbc (polyhedron); i++)
1025 { /* If we have an equality and the scalar part is not zero... */
1026 if (value_zero_p(cloog_polyhedron_cval (polyhedron, i, 0)) &&
1027 value_notzero_p(cloog_polyhedron_cval (polyhedron, i, dimension-1)))
1028 { /* Then we check whether the scalar can be divided by the gcd of the
1029 * unknown vector (including iterators and parameters) or not. If not,
1030 * there is no integer point in the polyhedron and we return 1.
1032 cloog_polyhedron_c_gcd (polyhedron, i, 1, dimension-2, &gcd) ;
1033 value_modulus(modulo,cloog_polyhedron_cval (polyhedron, i, dimension - 1), gcd) ;
1035 if (value_notzero_p(modulo))
1036 { value_clear_c(gcd) ;
1037 value_clear_c(modulo) ;
1038 return 1 ;
1043 value_clear_c(gcd) ;
1044 value_clear_c(modulo) ;
1045 return(0) ;
1050 * cloog_domain_stride function:
1051 * This function finds the stride imposed to unknown with the column number
1052 * 'strided_level' in order to be integral. For instance, if we have a
1053 * constraint like -i - 2j + 2k = 0, and we consider k, then k can be integral
1054 * only if (i + 2j)%2 = 0. Then only if i%2 = 0. Then k imposes a stride 2 to
1055 * the unknown i. The function returns the imposed stride in a parameter field.
1056 * - domain is the set of constraint we have to consider,
1057 * - strided_level is the column number of the unknown for which a stride have
1058 * to be found,
1059 * - looking_level is the column number of the unknown that impose a stride to
1060 * the first unknown.
1061 * - stride is the stride that is returned back as a function parameter.
1062 * - offset is the value of the constant c if the condition is of the shape
1063 * (i + c)%s = 0, s being the stride.
1065 * - June 28th 2003: first version.
1066 * - July 14th 2003: can now look for multiple striding constraints and returns
1067 * the GCD of the strides and the common offset.
1068 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1069 * CLooG 0.12.1).
1071 void cloog_domain_stride(domain, strided_level, nb_par, stride, offset)
1072 CloogDomain * domain ;
1073 int strided_level, nb_par ;
1074 Value * stride, * offset;
1075 { int i, dimension;
1076 Polyhedron * polyhedron ;
1077 int n_col, n_row, rank;
1078 CloogMatrix *M;
1079 Matrix *U;
1080 Vector *V;
1082 polyhedron = cloog_domain_polyhedron (domain) ;
1083 dimension = cloog_domain_dim (domain);
1085 /* Look at all equalities involving strided_level and the inner
1086 * iterators. We can ignore the outer iterators and the parameters
1087 * here because the lower bound on strided_level is assumed to
1088 * be a constant.
1090 n_col = (1+dimension-nb_par) - strided_level;
1091 for (i=0, n_row=0; i < cloog_polyhedron_nbeq (polyhedron); i++)
1092 if (First_Non_Zero(cloog_polyhedron_c (polyhedron, i) + strided_level, n_col) != -1)
1093 ++n_row;
1095 M = cloog_matrix_alloc(n_row+1, n_col+1);
1096 for (i=0, n_row = 0; i < cloog_polyhedron_nbeq (polyhedron); i++) {
1097 if (First_Non_Zero(cloog_polyhedron_c (polyhedron, i) + strided_level, n_col) == -1)
1098 continue;
1099 Vector_Copy(cloog_polyhedron_c (polyhedron, i) + strided_level, M->p[n_row], n_col);
1100 cloog_matrix_element_assign(M, n_row, n_col, cloog_polyhedron_cval (polyhedron, i, 1 + dimension));
1101 ++n_row;
1103 cloog_matrix_element_set_si(M, n_row, n_col, 1);
1105 /* Then look at the general solution to the above equalities. */
1106 rank = SolveDiophantine(M, &U, &V);
1107 cloog_matrix_free(M);
1109 if (rank == -1) {
1110 /* There is no solution, so the body of this loop will
1111 * never execute. We just leave the constraints alone here so
1112 * that they will ensure the body will not be executed.
1113 * We should probably propagate this information up so that
1114 * the loop can be removed entirely.
1116 value_set_si(*offset, 0);
1117 value_set_si(*stride, 1);
1118 } else {
1119 /* Compute the gcd of the coefficients defining strided_level. */
1120 Vector_Gcd(U->p[0], U->NbColumns, stride);
1121 value_oppose(*offset, V->p[0]);
1122 value_pmodulus(*offset, *offset, *stride);
1124 Matrix_Free(U);
1125 Vector_Free(V);
1127 return ;
1132 * cloog_domain_integral_lowerbound function:
1133 * This function returns 1 if the lower bound of an iterator (such as its
1134 * column rank in the constraint set 'domain' is 'level') is integral,
1135 * 0 otherwise. If the lower bound is actually integral, the function fills
1136 * the 'lower' field with the lower bound value.
1137 * - June 29th 2003: first version.
1138 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1139 * CLooG 0.12.1).
1141 int cloog_domain_integral_lowerbound(domain, level, lower)
1142 CloogDomain * domain ;
1143 int level ;
1144 Value * lower ;
1145 { int i, first_lower=1, dimension, lower_constraint=-1 ;
1146 Value iterator, constant, tmp;
1147 Polyhedron * polyhedron ;
1149 polyhedron = cloog_domain_polyhedron (domain) ;
1150 dimension = cloog_domain_dim (domain);
1152 /* We want one and only one lower bound (e.g. no equality, no maximum
1153 * calculation...).
1155 for (i=0; i<cloog_polyhedron_nbc (polyhedron); i++)
1156 if (value_zero_p(cloog_polyhedron_cval (polyhedron, i, 0))
1157 && value_notzero_p(cloog_polyhedron_cval (polyhedron, i, level)))
1158 return 0 ;
1160 for (i=0; i<cloog_polyhedron_nbc (polyhedron); i++)
1161 if (value_pos_p (cloog_polyhedron_cval (polyhedron, i, level)))
1163 if (first_lower)
1165 first_lower = 0 ;
1166 lower_constraint = i ;
1168 else
1169 return 0 ;
1172 if (first_lower)
1173 return 0 ;
1175 /* We want an integral lower bound: no other non-zero entry except the
1176 * iterator coefficient and the constant.
1178 for (i=1; i<level; i++)
1179 if (value_notzero_p(cloog_polyhedron_cval (polyhedron, lower_constraint, i)))
1180 return 0 ;
1182 for (i=level+1; i <= cloog_polyhedron_dim (polyhedron); i++)
1183 if (value_notzero_p(cloog_polyhedron_cval (polyhedron, lower_constraint, i)))
1184 return 0 ;
1186 value_init_c(iterator) ;
1187 value_init_c(constant) ;
1188 value_init_c(tmp) ;
1190 /* If all is passed, then find the lower bound and return 1. */
1191 value_assign(iterator, cloog_polyhedron_cval (polyhedron, lower_constraint, level)) ;
1192 value_oppose(constant, cloog_polyhedron_cval (polyhedron, lower_constraint, dimension + 1));
1194 value_modulus(tmp, constant, iterator) ;
1195 value_division(*lower, constant, iterator) ;
1197 if (!(value_zero_p(tmp) || value_neg_p(constant)))
1198 value_increment(*lower, *lower) ;
1200 value_clear_c(iterator) ;
1201 value_clear_c(constant) ;
1202 value_clear_c(tmp) ;
1204 return 1 ;
1209 * cloog_domain_lowerbound_update function:
1210 * This function updates the integral lower bound of an iterator (such as its
1211 * column rank in the constraint set 'domain' is 'level') into 'lower'.
1212 * - Jun 29th 2003: first version.
1213 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1214 * CLooG 0.12.1).
1216 void cloog_domain_lowerbound_update(domain, level, lower)
1217 CloogDomain * domain ;
1218 int level ;
1219 Value lower ;
1220 { int i ;
1221 Polyhedron * polyhedron ;
1223 polyhedron = cloog_domain_polyhedron (domain) ;
1225 /* There is only one lower bound, the first one is the good one. */
1226 for (i=0; i<cloog_polyhedron_nbc (polyhedron); i++)
1227 if (value_pos_p(cloog_polyhedron_cval (polyhedron, i, level)))
1229 cloog_polyhedron_cval_set_si (polyhedron, i, level, 1) ;
1230 cloog_polyhedron_cval_oppose (polyhedron, i, cloog_polyhedron_dim (polyhedron) + 1, lower) ;
1231 break ;
1237 * cloog_domain_lazy_equal function:
1238 * This function returns 1 if the domains given as input are the same, 0 if it
1239 * is unable to decide. This function makes an entry-to-entry comparison between
1240 * the constraint systems, if all the entries are the same, the domains are
1241 * obviously the same and it returns 1, at the first difference, it returns 0.
1242 * This is a very fast way to verify this property. It has been shown (with the
1243 * CLooG benchmarks) that operations on equal domains are 17% of all the
1244 * polyhedral computations. For 75% of the actually identical domains, this
1245 * function answer that they are the same and allow to give immediately the
1246 * trivial solution instead of calling the heavy general functions of PolyLib.
1247 * - August 22th 2003: first version.
1248 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1249 * CLooG 0.12.1).
1251 int cloog_domain_lazy_equal(CloogDomain * d1, CloogDomain * d2)
1252 { int i, nb_elements ;
1253 Polyhedron * p1, * p2 ;
1255 p1 = cloog_domain_polyhedron (d1) ;
1256 p2 = cloog_domain_polyhedron (d2) ;
1258 while ((p1 != NULL) && (p2 != NULL))
1259 { if ((cloog_polyhedron_nbc (p1) != cloog_polyhedron_nbc (p2)) ||
1260 (cloog_polyhedron_dim (p1) != cloog_polyhedron_dim (p2)))
1261 return 0 ;
1263 nb_elements = cloog_polyhedron_nbc (p1) * (cloog_polyhedron_dim (p1) + 2) ;
1265 for (i=0;i<nb_elements;i++)
1266 if (value_ne(p1->p_Init[i], p2->p_Init[i]))
1267 return 0 ;
1269 p1 = cloog_polyhedron_next (p1) ;
1270 p2 = cloog_polyhedron_next (p2) ;
1273 if ((p1 != NULL) || (p2 != NULL))
1274 return 0 ;
1276 return 1 ;
1281 * cloog_domain_lazy_block function:
1282 * This function returns 1 if the two domains d1 and d2 given as input are the
1283 * same (possibly except for a dimension equal to a constant where we accept
1284 * a difference of 1) AND if we are sure that there are no other domain in
1285 * the code generation problem that may put integral points between those of
1286 * d1 and d2 (0 otherwise). In fact this function answers the question "can I
1287 * safely consider the two domains as only one with two statements (a block) ?".
1288 * This function is lazy: it asks for very standard scattering representation
1289 * (only one constraint per dimension which is an equality, and the constraints
1290 * are ordered per dimension depth: the left hand side of the constraint matrix
1291 * is the identity) and will answer NO at the very first problem.
1292 * - d1 and d2 are the two domains to check for blocking,
1293 * - scattering is the linked list of all domains,
1294 * - scattdims is the total number of scattering dimentions.
1296 * - April 30th 2005: beginning
1297 * - June 9th 2005: first working version.
1298 * - June 10th 2005: debugging.
1299 * - June 21rd 2005: Adaptation for GMP.
1300 * - October 16th 2005: (debug) some false blocks have been removed.
1302 int cloog_domain_lazy_block(d1, d2, scattering, scattdims)
1303 CloogDomain * d1, * d2 ;
1304 CloogDomainList * scattering ;
1305 int scattdims ;
1306 { int i, j, difference=0, different_constraint=0 ;
1307 Value date1, date2, date3, temp ;
1308 Polyhedron * p1, * p2, * p3 ;
1310 p1 = cloog_domain_polyhedron (d1) ;
1311 p2 = cloog_domain_polyhedron (d2) ;
1313 /* Some basic checks: we only accept convex domains, with same constraint
1314 * and dimension numbers.
1316 if (cloog_polyhedron_next (p1) || cloog_polyhedron_next (p2) ||
1317 (cloog_polyhedron_nbc (p1) != cloog_polyhedron_nbc (p2)) ||
1318 (cloog_polyhedron_dim (p1) != cloog_polyhedron_dim (p2)))
1319 return 0 ;
1321 /* There should be only one difference between the two domains, it
1322 * has to be at the constant level and the difference must be of +1,
1323 * moreover, after the difference all domain coefficient has to be 0.
1324 * The matrix shape is:
1326 * |===========|=====|<- 0 line
1327 * |===========|=====|
1328 * |===========|====?|<- different_constraint line (found here)
1329 * |===========|0000=|
1330 * |===========|0000=|<- pX->NbConstraints line
1331 * ^ ^ ^
1332 * | | |
1333 * | | (pX->Dimension + 2) column
1334 * | scattdims column
1335 * 0 column
1338 value_init_c(temp) ;
1339 for (i=0;i<cloog_polyhedron_nbc (p1);i++)
1340 { if (difference == 0)
1341 { /* All elements except scalar must be equal. */
1342 for (j=0; j < (cloog_polyhedron_dim (p1) + 1); j++)
1343 if (value_ne(cloog_polyhedron_cval (p1, i, j),
1344 cloog_polyhedron_cval (p2, i, j)))
1346 value_clear_c(temp) ;
1347 return 0 ;
1349 /* The scalar may differ from +1 (now j=(p1->Dimension + 1)). */
1350 if (value_ne(cloog_polyhedron_cval (p1, i, j),
1351 cloog_polyhedron_cval (p2, i, j)))
1353 value_increment(temp, cloog_polyhedron_cval (p2, i, j)) ;
1354 if (value_ne (cloog_polyhedron_cval (p1, i, j), temp))
1356 value_clear_c(temp) ;
1357 return 0 ;
1359 else
1361 difference = 1 ;
1362 different_constraint = i ;
1366 else
1367 { /* Scattering coefficients must be equal. */
1368 for (j=0;j<(scattdims+1);j++)
1369 if (value_ne(cloog_polyhedron_cval (p1, i, j),
1370 cloog_polyhedron_cval (p2, i, j)))
1372 value_clear_c(temp) ;
1373 return 0 ;
1376 /* Domain coefficients must be 0. */
1377 for (; j < (cloog_polyhedron_dim (p1) + 1);j++)
1378 if (value_notzero_p (cloog_polyhedron_cval (p1, i, j))
1379 || value_notzero_p (cloog_polyhedron_cval (p2, i, j)))
1381 value_clear_c(temp) ;
1382 return 0 ;
1385 /* Scalar must be equal. */
1386 if (value_ne(cloog_polyhedron_cval (p1, i, j),
1387 cloog_polyhedron_cval (p2, i, j)))
1389 value_clear_c(temp) ;
1390 return 0 ;
1394 value_clear_c(temp) ;
1396 /* If the domains are exactly the same, this is a block. */
1397 if (difference == 0)
1398 return 1 ;
1400 /* Now a basic check that the constraint with the difference is an
1401 * equality of a dimension with a constant.
1403 for (i=0;i<=different_constraint;i++)
1404 if (value_notzero_p(cloog_polyhedron_cval (p1, different_constraint, i)))
1405 return 0 ;
1407 if (value_notone_p(cloog_polyhedron_cval (p1, different_constraint,
1408 different_constraint + 1)))
1409 return 0 ;
1411 for (i=different_constraint+2;i<(cloog_polyhedron_dim (p1) + 1);i++)
1412 if (value_notzero_p(cloog_polyhedron_cval (p1, different_constraint, i)))
1413 return 0 ;
1415 /* For the moment, d1 and d2 are a block candidate. There remains to check
1416 * that there is no other domain that may put an integral point between
1417 * them. In our lazy test we ensure this property by verifying that the
1418 * constraint matrices have a very strict shape: let us consider that the
1419 * dimension with the difference is d. Then the first d dimensions are
1420 * defined in their depth order using equalities (thus the first column begins
1421 * with d zeroes, there is a d*d identity matrix and a zero-matrix for
1422 * the remaining simensions). If a domain can put integral points between the
1423 * domains of the block candidate, this means that the other entries on the
1424 * first d constraints are equal to those of d1 or d2. Thus we are looking for
1425 * such a constraint system, if it exists d1 and d2 is considered to not be
1426 * a block, it is a bock otherwise.
1428 * 1. Only equalities (for the first different_constraint+1 lines).
1429 * | 2. Must be the identity.
1430 * | | 3. Must be zero.
1431 * | | | 4. Elements are equal, the last one is either date1 or 2.
1432 * | | | |
1433 * | /-\ /---\ /---\
1434 * |0|100|00000|=====|<- 0 line
1435 * |0|010|00000|=====|
1436 * |0|001|00000|====?|<- different_constraint line
1437 * |*|***|*****|*****|
1438 * |*|***|*****|*****|<- pX->NbConstraints line
1439 * ^ ^ ^ ^
1440 * | | | |
1441 * | | | (pX->Dimension + 2) column
1442 * | | scattdims column
1443 * | different_constraint+1 column
1444 * 0 column
1447 /* Step 1 and 2. This is only necessary to check one domain because
1448 * we checked that they are equal on this part before.
1450 for (i=0;i<=different_constraint;i++)
1451 { for (j=0;j<i+1;j++)
1452 if (value_notzero_p (cloog_polyhedron_cval (p1, i, j)))
1453 return 0 ;
1455 if (value_notone_p(cloog_polyhedron_cval (p1, i, i+1)))
1456 return 0 ;
1458 for (j=i+2;j<=different_constraint+1;j++)
1459 if (value_notzero_p(cloog_polyhedron_cval (p1, i, j)))
1460 return 0 ;
1463 /* Step 3. */
1464 for (i=0;i<=different_constraint;i++)
1465 for (j=different_constraint+2;j<=scattdims;j++)
1466 if (value_notzero_p(cloog_polyhedron_cval (p1, i, j)))
1467 return 0 ;
1469 value_init_c(date1) ;
1470 value_init_c(date2) ;
1471 value_init_c(date3) ;
1473 /* Now we have to check that the two different dates are unique. */
1474 value_assign (date1, cloog_polyhedron_cval (p1, different_constraint,
1475 cloog_polyhedron_dim (p1) + 1)) ;
1476 value_assign (date2, cloog_polyhedron_cval (p2, different_constraint,
1477 cloog_polyhedron_dim (p2) + 1)) ;
1479 /* Step 4. We check all domains except d1 and d2 and we look for at least
1480 * a difference with d1 or d2 on the first different_constraint+1 dimensions.
1482 while (scattering != NULL)
1484 if ((cloog_domain (scattering) != d1) && (cloog_domain (scattering) != d2))
1486 p3 = cloog_domain_polyhedron (cloog_domain (scattering)) ;
1487 value_assign (date3, cloog_polyhedron_cval (p3, different_constraint,
1488 cloog_polyhedron_dim (p3) + 1));
1489 difference = 0 ;
1491 if (value_ne(date3,date2) && value_ne(date3,date1))
1492 difference = 1 ;
1494 for (i=0;(i<different_constraint)&&(!difference);i++)
1495 for (j=0;(j<(cloog_polyhedron_dim (p3) + 2))&&(!difference);j++)
1496 if (value_ne (cloog_polyhedron_cval (p1, i, j),
1497 cloog_polyhedron_cval (p3, i, j)))
1498 difference = 1 ;
1500 for (j=0;(j<(cloog_polyhedron_dim (p3) + 1))&&(!difference);j++)
1501 if (value_ne (cloog_polyhedron_cval (p1, different_constraint, j),
1502 cloog_polyhedron_cval (p3, different_constraint, j)))
1503 difference = 1 ;
1505 if (!difference)
1507 value_clear_c(date1) ;
1508 value_clear_c(date2) ;
1509 value_clear_c(date3) ;
1510 return 0 ;
1514 scattering = cloog_next_domain (scattering);
1517 value_clear_c(date1) ;
1518 value_clear_c(date2) ;
1519 value_clear_c(date3) ;
1520 return 1 ;
1525 * cloog_domain_lazy_disjoint function:
1526 * This function returns 1 if the domains given as input are disjoint, 0 if it
1527 * is unable to decide. This function finds the unknown with fixed values in
1528 * both domains (on a given constraint, their column entry is not zero and
1529 * only the constant coefficient can be different from zero) and verify that
1530 * their values are the same. If not, the domains are obviously disjoint and
1531 * it returns 1, if there is not such case it returns 0. This is a very fast
1532 * way to verify this property. It has been shown (with the CLooG benchmarks)
1533 * that operations on disjoint domains are 36% of all the polyhedral
1534 * computations. For 94% of the actually identical domains, this
1535 * function answer that they are disjoint and allow to give immediately the
1536 * trivial solution instead of calling the heavy general functions of PolyLib.
1537 * - August 22th 2003: first version.
1538 * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of
1539 * CLooG 0.12.1).
1541 int cloog_domain_lazy_disjoint(CloogDomain * d1, CloogDomain * d2)
1543 int i1, j1, i2, j2, scat_dim ;
1544 Value scat_val ;
1545 Polyhedron * p1, * p2 ;
1547 p1 = cloog_domain_polyhedron (d1) ;
1548 p2 = cloog_domain_polyhedron (d2) ;
1550 if (cloog_polyhedron_next (p1) || cloog_polyhedron_next (p2))
1551 return 0 ;
1553 value_init_c(scat_val) ;
1555 for (i1=0; i1<cloog_polyhedron_nbc (p1); i1++)
1557 if (value_notzero_p (cloog_polyhedron_cval (p1, i1, 0)))
1558 continue ;
1560 scat_dim = 1 ;
1561 while (value_zero_p(cloog_polyhedron_cval (p1, i1, scat_dim)) &&
1562 (scat_dim < cloog_polyhedron_dim (p1)))
1563 scat_dim ++ ;
1565 if (value_notone_p(cloog_polyhedron_cval (p1, i1, scat_dim)))
1566 continue ;
1567 else
1569 for (j1=scat_dim+1; j1<=cloog_polyhedron_dim (p1); j1++)
1570 if (value_notzero_p(cloog_polyhedron_cval (p1, i1, j1)))
1571 break ;
1573 if (j1 != cloog_polyhedron_dim (p1)+1)
1574 continue ;
1576 value_assign (scat_val, cloog_polyhedron_cval (p1, i1, cloog_polyhedron_dim (p1) + 1)) ;
1578 for (i2=0; i2<cloog_polyhedron_nbc (p2); i2++)
1580 for (j2=0;j2<scat_dim;j2++)
1581 if (value_notzero_p (cloog_polyhedron_cval (p2, i2, j2)))
1582 break ;
1584 if ((j2 != scat_dim)
1585 || value_notone_p(cloog_polyhedron_cval (p2, i2, scat_dim)))
1586 continue ;
1588 for (j2=scat_dim+1; j2 < cloog_polyhedron_dim (p2); j2++)
1589 if (value_notzero_p(cloog_polyhedron_cval (p2, i2, j2)))
1590 break ;
1592 if (j2 != cloog_polyhedron_dim (p2))
1593 continue ;
1595 if (value_ne(cloog_polyhedron_cval (p2, i2, cloog_polyhedron_dim (p2) + 1), scat_val))
1597 value_clear_c(scat_val) ;
1598 return 1 ;
1604 value_clear_c(scat_val) ;
1605 return 0 ;
1610 * cloog_domain_list_lazy_same function:
1611 * This function returns 1 if two domains in the list are the same, 0 if it
1612 * is unable to decide.
1613 * - February 9th 2004: first version.
1615 int cloog_domain_list_lazy_same(CloogDomainList * list)
1616 { /*int i=1, j=1 ;*/
1617 CloogDomainList * current, * next ;
1619 current = list ;
1620 while (current != NULL)
1622 next = cloog_next_domain (current);
1623 /*j=i+1;*/
1624 while (next != NULL)
1626 if (cloog_domain_lazy_equal (cloog_domain (current),
1627 cloog_domain (next)))
1628 { /*printf("Same domains: %d and %d\n",i,j) ;*/
1629 return 1 ;
1631 /*j++ ;*/
1632 next = cloog_next_domain (next) ;
1634 /*i++ ;*/
1635 current = cloog_next_domain (current) ;
1638 return 0 ;
1642 * cloog_domain_cut_first function:
1643 * this function returns a CloogDomain structure with everything except the
1644 * first part of the polyhedra union of the input domain as domain. After a call
1645 * to this function, there remains in the CloogDomain structure provided as
1646 * input only the first part of the original polyhedra union.
1647 * - April 20th 2005: first version, extracted from different part of loop.c.
1649 CloogDomain * cloog_domain_cut_first(CloogDomain * domain)
1650 { CloogDomain * rest ;
1652 if ((domain != NULL) && (cloog_domain_polyhedron (domain) != NULL))
1653 { rest = cloog_domain_alloc(cloog_domain_polyhedron_next (domain)) ;
1654 cloog_domain_polyhedron_set_next (domain, NULL) ;
1656 else
1657 rest = NULL ;
1659 return rest ;
1664 * cloog_domain_lazy_isscalar function:
1665 * this function returns 1 if the dimension 'dimension' in the domain 'domain'
1666 * is scalar, this means that the only constraint on this dimension must have
1667 * the shape "x.dimension + scalar = 0" with x an integral variable. This
1668 * function is lazy since we only accept x=1 (further calculations are easier
1669 * in this way).
1670 * - June 14th 2005: first version.
1671 * - June 21rd 2005: Adaptation for GMP.
1673 int cloog_domain_lazy_isscalar(CloogDomain * domain, int dimension)
1674 { int i, j ;
1675 Polyhedron * polyhedron ;
1677 polyhedron = cloog_domain_polyhedron (domain) ;
1678 /* For each constraint... */
1679 for (i=0;i<cloog_polyhedron_nbc (polyhedron);i++)
1680 { /* ...if it is concerned by the potentially scalar dimension... */
1681 if (value_notzero_p (cloog_polyhedron_cval (polyhedron, i, dimension+1)))
1682 { /* ...check that the constraint has the shape "dimension + scalar = 0". */
1683 for (j=0;j<=dimension;j++)
1684 if (value_notzero_p(cloog_polyhedron_cval (polyhedron, i, j)))
1685 return 0 ;
1687 if (value_notone_p(cloog_polyhedron_cval (polyhedron, i, dimension + 1)))
1688 return 0 ;
1690 for (j=dimension+2;j<(cloog_polyhedron_dim (polyhedron) + 1);j++)
1691 if (value_notzero_p(cloog_polyhedron_cval (polyhedron, i, j)))
1692 return 0 ;
1696 return 1 ;
1701 * cloog_domain_scalar function:
1702 * when we call this function, we know that "dimension" is a scalar dimension,
1703 * this function finds the scalar value in "domain" and returns it in "value".
1704 * - June 30th 2005: first version.
1706 void cloog_domain_scalar(CloogDomain * domain, int dimension, Value * value)
1707 { int i ;
1708 Polyhedron * polyhedron ;
1710 polyhedron = cloog_domain_polyhedron (domain) ;
1711 /* For each constraint... */
1712 for (i=0;i<cloog_polyhedron_nbc (polyhedron);i++)
1713 { /* ...if it is the equality defining the scalar dimension... */
1714 if (value_notzero_p(cloog_polyhedron_cval (polyhedron, i, dimension+1)) &&
1715 value_zero_p(cloog_polyhedron_cval (polyhedron, i, 0)))
1716 { /* ...Then send the scalar value. */
1717 value_assign(*value,cloog_polyhedron_cval (polyhedron, i,
1718 cloog_polyhedron_dim (polyhedron) + 1)) ;
1719 value_oppose(*value,*value) ;
1720 return ;
1724 /* We should have found a scalar value: if not, there is an error. */
1725 fprintf(stderr, "[CLooG]ERROR: dimension %d is not scalar as expected.\n",
1726 dimension) ;
1727 exit(0) ;
1732 * cloog_domain_erase_dimension function:
1733 * this function returns a CloogDomain structure builds from 'domain' where
1734 * we removed the dimension 'dimension' and every constraint considering this
1735 * dimension. This is not a projection ! Every data concerning the
1736 * considered dimension is simply erased.
1737 * - June 14th 2005: first version.
1738 * - June 21rd 2005: Adaptation for GMP.
1740 CloogDomain * cloog_domain_erase_dimension(CloogDomain * domain, int dimension)
1741 { int i, j, mi, nb_dim ;
1742 CloogMatrix * matrix ;
1743 CloogDomain * erased ;
1744 Polyhedron * polyhedron ;
1746 polyhedron = cloog_domain_polyhedron (domain) ;
1747 nb_dim = cloog_domain_dim (domain);
1749 /* The matrix is one column less and at least one constraint less. */
1750 matrix = cloog_matrix_alloc(cloog_polyhedron_nbc (polyhedron)-1,nb_dim+1) ;
1752 /* mi is the constraint counter for the matrix. */
1753 mi = 0 ;
1754 for (i=0;i<cloog_polyhedron_nbc (polyhedron);i++)
1755 if (value_zero_p(cloog_polyhedron_cval (polyhedron, i, dimension+1)))
1756 { for (j=0;j<=dimension;j++)
1757 cloog_matrix_element_assign(matrix, mi, j, cloog_polyhedron_cval (polyhedron, i, j)) ;
1759 for (j=dimension+2;j<nb_dim+2;j++)
1760 cloog_matrix_element_assign(matrix, mi, j-1, cloog_polyhedron_cval (polyhedron, i, j)) ;
1762 mi ++ ;
1765 erased = cloog_domain_matrix2domain(matrix) ;
1766 cloog_matrix_free(matrix) ;
1768 return erased ;
1771 CloogMatrix *
1772 cloog_simplify_domain_matrix_with_equalities (CloogDomain *domain, int level,
1773 CloogMatrix *equal, int nb_parameters)
1775 CloogMatrix *temp, *res;
1777 temp = cloog_domain_domain2matrix (domain);
1778 cloog_matrix_normalize (temp, level);
1779 res = cloog_matrix_simplify (temp, equal, level, nb_parameters);
1780 cloog_matrix_free(temp);
1782 return res;