7e6591585c37f06e98d2054cd81f31f564efc84a
[platform/upstream/isl.git] / isl_transitive_closure.c
1 /*
2  * Copyright 2010      INRIA Saclay
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 license
5  *
6  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8  * 91893 Orsay, France 
9  */
10
11 #include "isl_map.h"
12 #include "isl_map_private.h"
13 #include "isl_seq.h"
14 #include <isl_lp.h>
15
16 int isl_map_is_transitively_closed(__isl_keep isl_map *map)
17 {
18         isl_map *map2;
19         int closed;
20
21         map2 = isl_map_apply_range(isl_map_copy(map), isl_map_copy(map));
22         closed = isl_map_is_subset(map2, map);
23         isl_map_free(map2);
24
25         return closed;
26 }
27  
28 /* Given a map that represents a path with the length of the path
29  * encoded as the difference between the last output coordindate
30  * and the last input coordinate, set this length to either
31  * exactly "length" (if "exactly" is set) or at least "length"
32  * (if "exactly" is not set).
33  */
34 static __isl_give isl_map *set_path_length(__isl_take isl_map *map,
35         int exactly, int length)
36 {
37         struct isl_dim *dim;
38         struct isl_basic_map *bmap;
39         unsigned d;
40         unsigned nparam;
41         int k;
42         isl_int *c;
43
44         if (!map)
45                 return NULL;
46
47         dim = isl_map_get_dim(map);
48         d = isl_dim_size(dim, isl_dim_in);
49         nparam = isl_dim_size(dim, isl_dim_param);
50         bmap = isl_basic_map_alloc_dim(dim, 0, 1, 1);
51         if (exactly) {
52                 k = isl_basic_map_alloc_equality(bmap);
53                 c = bmap->eq[k];
54         } else {
55                 k = isl_basic_map_alloc_inequality(bmap);
56                 c = bmap->ineq[k];
57         }
58         if (k < 0)
59                 goto error;
60         isl_seq_clr(c, 1 + isl_basic_map_total_dim(bmap));
61         isl_int_set_si(c[0], -length);
62         isl_int_set_si(c[1 + nparam + d - 1], -1);
63         isl_int_set_si(c[1 + nparam + d + d - 1], 1);
64
65         bmap = isl_basic_map_finalize(bmap);
66         map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
67
68         return map;
69 error:
70         isl_basic_map_free(bmap);
71         isl_map_free(map);
72         return NULL;
73 }
74
75 /* Check whether the overapproximation of the power of "map" is exactly
76  * the power of "map".  Let R be "map" and A_k the overapproximation.
77  * The approximation is exact if
78  *
79  *      A_1 = R
80  *      A_k = A_{k-1} \circ R                   k >= 2
81  *
82  * Since A_k is known to be an overapproximation, we only need to check
83  *
84  *      A_1 \subset R
85  *      A_k \subset A_{k-1} \circ R             k >= 2
86  *
87  * In practice, "app" has an extra input and output coordinate
88  * to encode the length of the path.  So, we first need to add
89  * this coordinate to "map" and set the length of the path to
90  * one.
91  */
92 static int check_power_exactness(__isl_take isl_map *map,
93         __isl_take isl_map *app)
94 {
95         int exact;
96         isl_map *app_1;
97         isl_map *app_2;
98
99         map = isl_map_add(map, isl_dim_in, 1);
100         map = isl_map_add(map, isl_dim_out, 1);
101         map = set_path_length(map, 1, 1);
102
103         app_1 = set_path_length(isl_map_copy(app), 1, 1);
104
105         exact = isl_map_is_subset(app_1, map);
106         isl_map_free(app_1);
107
108         if (!exact || exact < 0) {
109                 isl_map_free(app);
110                 isl_map_free(map);
111                 return exact;
112         }
113
114         app_1 = set_path_length(isl_map_copy(app), 0, 1);
115         app_2 = set_path_length(app, 0, 2);
116         app_1 = isl_map_apply_range(map, app_1);
117
118         exact = isl_map_is_subset(app_2, app_1);
119
120         isl_map_free(app_1);
121         isl_map_free(app_2);
122
123         return exact;
124 }
125
126 /* Check whether the overapproximation of the power of "map" is exactly
127  * the power of "map", possibly after projecting out the power (if "project"
128  * is set).
129  *
130  * If "project" is set and if "steps" can only result in acyclic paths,
131  * then we check
132  *
133  *      A = R \cup (A \circ R)
134  *
135  * where A is the overapproximation with the power projected out, i.e.,
136  * an overapproximation of the transitive closure.
137  * More specifically, since A is known to be an overapproximation, we check
138  *
139  *      A \subset R \cup (A \circ R)
140  *
141  * Otherwise, we check if the power is exact.
142  *
143  * Note that "app" has an extra input and output coordinate to encode
144  * the length of the part.  If we are only interested in the transitive
145  * closure, then we can simply project out these coordinates first.
146  */
147 static int check_exactness(__isl_take isl_map *map, __isl_take isl_map *app,
148         int project)
149 {
150         isl_map *test;
151         int exact;
152         unsigned d;
153
154         if (!project)
155                 return check_power_exactness(map, app);
156
157         d = isl_map_dim(map, isl_dim_in);
158         app = set_path_length(app, 0, 1);
159         app = isl_map_project_out(app, isl_dim_in, d, 1);
160         app = isl_map_project_out(app, isl_dim_out, d, 1);
161
162         test = isl_map_apply_range(isl_map_copy(map), isl_map_copy(app));
163         test = isl_map_union(test, isl_map_copy(map));
164
165         exact = isl_map_is_subset(app, test);
166
167         isl_map_free(app);
168         isl_map_free(test);
169
170         isl_map_free(map);
171
172         return exact;
173 }
174
175 /*
176  * The transitive closure implementation is based on the paper
177  * "Computing the Transitive Closure of a Union of Affine Integer
178  * Tuple Relations" by Anna Beletska, Denis Barthou, Wlodzimierz Bielecki and
179  * Albert Cohen.
180  */
181
182 /* Given a set of n offsets v_i (the rows of "steps"), construct a relation
183  * of the given dimension specification (Z^{n+1} -> Z^{n+1})
184  * that maps an element x to any element that can be reached
185  * by taking a non-negative number of steps along any of
186  * the extended offsets v'_i = [v_i 1].
187  * That is, construct
188  *
189  * { [x] -> [y] : exists k_i >= 0, y = x + \sum_i k_i v'_i }
190  *
191  * For any element in this relation, the number of steps taken
192  * is equal to the difference in the final coordinates.
193  */
194 static __isl_give isl_map *path_along_steps(__isl_take isl_dim *dim,
195         __isl_keep isl_mat *steps)
196 {
197         int i, j, k;
198         struct isl_basic_map *path = NULL;
199         unsigned d;
200         unsigned n;
201         unsigned nparam;
202
203         if (!dim || !steps)
204                 goto error;
205
206         d = isl_dim_size(dim, isl_dim_in);
207         n = steps->n_row;
208         nparam = isl_dim_size(dim, isl_dim_param);
209
210         path = isl_basic_map_alloc_dim(isl_dim_copy(dim), n, d, n);
211
212         for (i = 0; i < n; ++i) {
213                 k = isl_basic_map_alloc_div(path);
214                 if (k < 0)
215                         goto error;
216                 isl_assert(steps->ctx, i == k, goto error);
217                 isl_int_set_si(path->div[k][0], 0);
218         }
219
220         for (i = 0; i < d; ++i) {
221                 k = isl_basic_map_alloc_equality(path);
222                 if (k < 0)
223                         goto error;
224                 isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
225                 isl_int_set_si(path->eq[k][1 + nparam + i], 1);
226                 isl_int_set_si(path->eq[k][1 + nparam + d + i], -1);
227                 if (i == d - 1)
228                         for (j = 0; j < n; ++j)
229                                 isl_int_set_si(path->eq[k][1 + nparam + 2 * d + j], 1);
230                 else
231                         for (j = 0; j < n; ++j)
232                                 isl_int_set(path->eq[k][1 + nparam + 2 * d + j],
233                                             steps->row[j][i]);
234         }
235
236         for (i = 0; i < n; ++i) {
237                 k = isl_basic_map_alloc_inequality(path);
238                 if (k < 0)
239                         goto error;
240                 isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
241                 isl_int_set_si(path->ineq[k][1 + nparam + 2 * d + i], 1);
242         }
243
244         isl_dim_free(dim);
245
246         path = isl_basic_map_simplify(path);
247         path = isl_basic_map_finalize(path);
248         return isl_map_from_basic_map(path);
249 error:
250         isl_dim_free(dim);
251         isl_basic_map_free(path);
252         return NULL;
253 }
254
255 #define IMPURE          0
256 #define PURE_PARAM      1
257 #define PURE_VAR        2
258 #define MIXED           3
259
260 /* Check whether the parametric constant term of constraint c is never
261  * positive in "bset".
262  */
263 static int parametric_constant_never_positive(__isl_keep isl_basic_set *bset,
264         isl_int *c, int *div_purity)
265 {
266         unsigned d;
267         unsigned n_div;
268         unsigned nparam;
269         int i;
270         int k;
271         int empty;
272
273         n_div = isl_basic_set_dim(bset, isl_dim_div);
274         d = isl_basic_set_dim(bset, isl_dim_set);
275         nparam = isl_basic_set_dim(bset, isl_dim_param);
276
277         bset = isl_basic_set_copy(bset);
278         bset = isl_basic_set_cow(bset);
279         bset = isl_basic_set_extend_constraints(bset, 0, 1);
280         k = isl_basic_set_alloc_inequality(bset);
281         if (k < 0)
282                 goto error;
283         isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
284         isl_seq_cpy(bset->ineq[k], c, 1 + nparam);
285         for (i = 0; i < n_div; ++i) {
286                 if (div_purity[i] != PURE_PARAM)
287                         continue;
288                 isl_int_set(bset->ineq[k][1 + nparam + d + i],
289                             c[1 + nparam + d + i]);
290         }
291         isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
292         empty = isl_basic_set_is_empty(bset);
293         isl_basic_set_free(bset);
294
295         return empty;
296 error:
297         isl_basic_set_free(bset);
298         return -1;
299 }
300
301 /* Return PURE_PARAM if only the coefficients of the parameters are non-zero.
302  * Return PURE_VAR if only the coefficients of the set variables are non-zero.
303  * Return MIXED if only the coefficients of the parameters and the set
304  *      variables are non-zero and if moreover the parametric constant
305  *      can never attain positive values.
306  * Return IMPURE otherwise.
307  */
308 static int purity(__isl_keep isl_basic_set *bset, isl_int *c, int *div_purity,
309         int eq)
310 {
311         unsigned d;
312         unsigned n_div;
313         unsigned nparam;
314         int empty;
315         int i;
316         int p = 0, v = 0;
317
318         n_div = isl_basic_set_dim(bset, isl_dim_div);
319         d = isl_basic_set_dim(bset, isl_dim_set);
320         nparam = isl_basic_set_dim(bset, isl_dim_param);
321
322         for (i = 0; i < n_div; ++i) {
323                 if (isl_int_is_zero(c[1 + nparam + d + i]))
324                         continue;
325                 switch (div_purity[i]) {
326                 case PURE_PARAM: p = 1; break;
327                 case PURE_VAR: v = 1; break;
328                 default: return IMPURE;
329                 }
330         }
331         if (!p && isl_seq_first_non_zero(c + 1, nparam) == -1)
332                 return PURE_VAR;
333         if (!v && isl_seq_first_non_zero(c + 1 + nparam, d) == -1)
334                 return PURE_PARAM;
335
336         empty = parametric_constant_never_positive(bset, c, div_purity);
337         if (eq && empty >= 0 && !empty) {
338                 isl_seq_neg(c, c, 1 + nparam + d + n_div);
339                 empty = parametric_constant_never_positive(bset, c, div_purity);
340         }
341
342         return empty < 0 ? -1 : empty ? MIXED : IMPURE;
343 }
344
345 /* Return an array of integers indicating the type of each div in bset.
346  * If the div is (recursively) defined in terms of only the parameters,
347  * then the type is PURE_PARAM.
348  * If the div is (recursively) defined in terms of only the set variables,
349  * then the type is PURE_VAR.
350  * Otherwise, the type is IMPURE.
351  */
352 static __isl_give int *get_div_purity(__isl_keep isl_basic_set *bset)
353 {
354         int i, j;
355         int *div_purity;
356         unsigned d;
357         unsigned n_div;
358         unsigned nparam;
359
360         if (!bset)
361                 return NULL;
362
363         n_div = isl_basic_set_dim(bset, isl_dim_div);
364         d = isl_basic_set_dim(bset, isl_dim_set);
365         nparam = isl_basic_set_dim(bset, isl_dim_param);
366
367         div_purity = isl_alloc_array(bset->ctx, int, n_div);
368         if (!div_purity)
369                 return NULL;
370
371         for (i = 0; i < bset->n_div; ++i) {
372                 int p = 0, v = 0;
373                 if (isl_int_is_zero(bset->div[i][0])) {
374                         div_purity[i] = IMPURE;
375                         continue;
376                 }
377                 if (isl_seq_first_non_zero(bset->div[i] + 2, nparam) != -1)
378                         p = 1;
379                 if (isl_seq_first_non_zero(bset->div[i] + 2 + nparam, d) != -1)
380                         v = 1;
381                 for (j = 0; j < i; ++j) {
382                         if (isl_int_is_zero(bset->div[i][2 + nparam + d + j]))
383                                 continue;
384                         switch (div_purity[j]) {
385                         case PURE_PARAM: p = 1; break;
386                         case PURE_VAR: v = 1; break;
387                         default: p = v = 1; break;
388                         }
389                 }
390                 div_purity[i] = v ? p ? IMPURE : PURE_VAR : PURE_PARAM;
391         }
392
393         return div_purity;
394 }
395
396 /* Given a path with the as yet unconstrained length at position "pos",
397  * check if setting the length to zero results in only the identity
398  * mapping.
399  */
400 int empty_path_is_identity(__isl_keep isl_basic_map *path, unsigned pos)
401 {
402         isl_basic_map *test = NULL;
403         isl_basic_map *id = NULL;
404         int k;
405         int is_id;
406
407         test = isl_basic_map_copy(path);
408         test = isl_basic_map_extend_constraints(test, 1, 0);
409         k = isl_basic_map_alloc_equality(test);
410         if (k < 0)
411                 goto error;
412         isl_seq_clr(test->eq[k], 1 + isl_basic_map_total_dim(test));
413         isl_int_set_si(test->eq[k][pos], 1);
414         id = isl_basic_map_identity(isl_dim_domain(isl_basic_map_get_dim(path)));
415         is_id = isl_basic_map_is_equal(test, id);
416         isl_basic_map_free(test);
417         isl_basic_map_free(id);
418         return is_id;
419 error:
420         isl_basic_map_free(test);
421         return -1;
422 }
423
424 __isl_give isl_basic_map *add_delta_constraints(__isl_take isl_basic_map *path,
425         __isl_keep isl_basic_set *delta, unsigned off, unsigned nparam,
426         unsigned d, int *div_purity, int eq)
427 {
428         int i, k;
429         int n = eq ? delta->n_eq : delta->n_ineq;
430         isl_int **delta_c = eq ? delta->eq : delta->ineq;
431         unsigned n_div;
432
433         n_div = isl_basic_set_dim(delta, isl_dim_div);
434
435         for (i = 0; i < n; ++i) {
436                 isl_int *path_c;
437                 int p = purity(delta, delta_c[i], div_purity, eq);
438                 if (p < 0)
439                         goto error;
440                 if (p == IMPURE)
441                         continue;
442                 if (eq && p != MIXED) {
443                         k = isl_basic_map_alloc_equality(path);
444                         path_c = path->eq[k];
445                 } else {
446                         k = isl_basic_map_alloc_inequality(path);
447                         path_c = path->ineq[k];
448                 }
449                 if (k < 0)
450                         goto error;
451                 isl_seq_clr(path_c, 1 + isl_basic_map_total_dim(path));
452                 if (p == PURE_VAR) {
453                         isl_seq_cpy(path_c + off,
454                                     delta_c[i] + 1 + nparam, d);
455                         isl_int_set(path_c[off + d], delta_c[i][0]);
456                 } else if (p == PURE_PARAM) {
457                         isl_seq_cpy(path_c, delta_c[i], 1 + nparam);
458                 } else {
459                         isl_seq_cpy(path_c + off,
460                                     delta_c[i] + 1 + nparam, d);
461                         isl_seq_cpy(path_c, delta_c[i], 1 + nparam);
462                 }
463                 isl_seq_cpy(path_c + off - n_div,
464                             delta_c[i] + 1 + nparam + d, n_div);
465         }
466
467         return path;
468 error:
469         isl_basic_map_free(path);
470         return NULL;
471 }
472
473 /* Given a set of offsets "delta", construct a relation of the
474  * given dimension specification (Z^{n+1} -> Z^{n+1}) that
475  * is an overapproximation of the relations that
476  * maps an element x to any element that can be reached
477  * by taking a non-negative number of steps along any of
478  * the elements in "delta".
479  * That is, construct an approximation of
480  *
481  *      { [x] -> [y] : exists f \in \delta, k \in Z :
482  *                                      y = x + k [f, 1] and k >= 0 }
483  *
484  * For any element in this relation, the number of steps taken
485  * is equal to the difference in the final coordinates.
486  *
487  * In particular, let delta be defined as
488  *
489  *      \delta = [p] -> { [x] : A x + a >= and B p + b >= 0 and
490  *                              C x + C'p + c >= 0 and
491  *                              D x + D'p + d >= 0 }
492  *
493  * where the constraints C x + C'p + c >= 0 are such that the parametric
494  * constant term of each constraint j, "C_j x + C'_j p + c_j",
495  * can never attain positive values, then the relation is constructed as
496  *
497  *      { [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
498  *                      A f + k a >= 0 and B p + b >= 0 and
499  *                      C f + C'p + c >= 0 and k >= 1 }
500  *      union { [x] -> [x] }
501  *
502  * If the zero-length paths happen to correspond exactly to the identity
503  * mapping, then we return
504  *
505  *      { [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
506  *                      A f + k a >= 0 and B p + b >= 0 and
507  *                      C f + C'p + c >= 0 and k >= 0 }
508  *
509  * instead.
510  *
511  * Existentially quantified variables in \delta are handled by
512  * classifying them as independent of the parameters, purely
513  * parameter dependent and others.  Constraints containing
514  * any of the other existentially quantified variables are removed.
515  * This is safe, but leads to an additional overapproximation.
516  */
517 static __isl_give isl_map *path_along_delta(__isl_take isl_dim *dim,
518         __isl_take isl_basic_set *delta)
519 {
520         isl_basic_map *path = NULL;
521         unsigned d;
522         unsigned n_div;
523         unsigned nparam;
524         unsigned off;
525         int i, k;
526         int is_id;
527         int *div_purity = NULL;
528
529         if (!delta)
530                 goto error;
531         n_div = isl_basic_set_dim(delta, isl_dim_div);
532         d = isl_basic_set_dim(delta, isl_dim_set);
533         nparam = isl_basic_set_dim(delta, isl_dim_param);
534         path = isl_basic_map_alloc_dim(isl_dim_copy(dim), n_div + d + 1,
535                         d + 1 + delta->n_eq, delta->n_eq + delta->n_ineq + 1);
536         off = 1 + nparam + 2 * (d + 1) + n_div;
537
538         for (i = 0; i < n_div + d + 1; ++i) {
539                 k = isl_basic_map_alloc_div(path);
540                 if (k < 0)
541                         goto error;
542                 isl_int_set_si(path->div[k][0], 0);
543         }
544
545         for (i = 0; i < d + 1; ++i) {
546                 k = isl_basic_map_alloc_equality(path);
547                 if (k < 0)
548                         goto error;
549                 isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
550                 isl_int_set_si(path->eq[k][1 + nparam + i], 1);
551                 isl_int_set_si(path->eq[k][1 + nparam + d + 1 + i], -1);
552                 isl_int_set_si(path->eq[k][off + i], 1);
553         }
554
555         div_purity = get_div_purity(delta);
556         if (!div_purity)
557                 goto error;
558
559         path = add_delta_constraints(path, delta, off, nparam, d, div_purity, 1);
560         path = add_delta_constraints(path, delta, off, nparam, d, div_purity, 0);
561
562         is_id = empty_path_is_identity(path, off + d);
563         if (is_id < 0)
564                 goto error;
565
566         k = isl_basic_map_alloc_inequality(path);
567         if (k < 0)
568                 goto error;
569         isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
570         if (!is_id)
571                 isl_int_set_si(path->ineq[k][0], -1);
572         isl_int_set_si(path->ineq[k][off + d], 1);
573                         
574         free(div_purity);
575         isl_basic_set_free(delta);
576         path = isl_basic_map_finalize(path);
577         if (is_id) {
578                 isl_dim_free(dim);
579                 return isl_map_from_basic_map(path);
580         }
581         return isl_basic_map_union(path,
582                                 isl_basic_map_identity(isl_dim_domain(dim)));
583 error:
584         free(div_purity);
585         isl_dim_free(dim);
586         isl_basic_set_free(delta);
587         isl_basic_map_free(path);
588         return NULL;
589 }
590
591 /* Given a dimension specification Z^{n+1} -> Z^{n+1} and a parameter "param",
592  * construct a map that equates the parameter to the difference
593  * in the final coordinates and imposes that this difference is positive.
594  * That is, construct
595  *
596  *      { [x,x_s] -> [y,y_s] : k = y_s - x_s > 0 }
597  */
598 static __isl_give isl_map *equate_parameter_to_length(__isl_take isl_dim *dim,
599         unsigned param)
600 {
601         struct isl_basic_map *bmap;
602         unsigned d;
603         unsigned nparam;
604         int k;
605
606         d = isl_dim_size(dim, isl_dim_in);
607         nparam = isl_dim_size(dim, isl_dim_param);
608         bmap = isl_basic_map_alloc_dim(dim, 0, 1, 1);
609         k = isl_basic_map_alloc_equality(bmap);
610         if (k < 0)
611                 goto error;
612         isl_seq_clr(bmap->eq[k], 1 + isl_basic_map_total_dim(bmap));
613         isl_int_set_si(bmap->eq[k][1 + param], -1);
614         isl_int_set_si(bmap->eq[k][1 + nparam + d - 1], -1);
615         isl_int_set_si(bmap->eq[k][1 + nparam + d + d - 1], 1);
616
617         k = isl_basic_map_alloc_inequality(bmap);
618         if (k < 0)
619                 goto error;
620         isl_seq_clr(bmap->ineq[k], 1 + isl_basic_map_total_dim(bmap));
621         isl_int_set_si(bmap->ineq[k][1 + param], 1);
622         isl_int_set_si(bmap->ineq[k][0], -1);
623
624         bmap = isl_basic_map_finalize(bmap);
625         return isl_map_from_basic_map(bmap);
626 error:
627         isl_basic_map_free(bmap);
628         return NULL;
629 }
630
631 /* Check whether "path" is acyclic, where the last coordinates of domain
632  * and range of path encode the number of steps taken.
633  * That is, check whether
634  *
635  *      { d | d = y - x and (x,y) in path }
636  *
637  * does not contain any element with positive last coordinate (positive length)
638  * and zero remaining coordinates (cycle).
639  */
640 static int is_acyclic(__isl_take isl_map *path)
641 {
642         int i;
643         int acyclic;
644         unsigned dim;
645         struct isl_set *delta;
646
647         delta = isl_map_deltas(path);
648         dim = isl_set_dim(delta, isl_dim_set);
649         for (i = 0; i < dim; ++i) {
650                 if (i == dim -1)
651                         delta = isl_set_lower_bound_si(delta, isl_dim_set, i, 1);
652                 else
653                         delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
654         }
655
656         acyclic = isl_set_is_empty(delta);
657         isl_set_free(delta);
658
659         return acyclic;
660 }
661
662 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
663  * and a dimension specification (Z^{n+1} -> Z^{n+1}),
664  * construct a map that is an overapproximation of the map
665  * that takes an element from the space D \times Z to another
666  * element from the same space, such that the first n coordinates of the
667  * difference between them is a sum of differences between images
668  * and pre-images in one of the R_i and such that the last coordinate
669  * is equal to the number of steps taken.
670  * That is, let
671  *
672  *      \Delta_i = { y - x | (x, y) in R_i }
673  *
674  * then the constructed map is an overapproximation of
675  *
676  *      { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
677  *                              d = (\sum_i k_i \delta_i, \sum_i k_i) }
678  *
679  * The elements of the singleton \Delta_i's are collected as the
680  * rows of the steps matrix.  For all these \Delta_i's together,
681  * a single path is constructed.
682  * For each of the other \Delta_i's, we compute an overapproximation
683  * of the paths along elements of \Delta_i.
684  * Since each of these paths performs an addition, composition is
685  * symmetric and we can simply compose all resulting paths in any order.
686  */
687 static __isl_give isl_map *construct_extended_path(__isl_take isl_dim *dim,
688         __isl_keep isl_map *map, int *project)
689 {
690         struct isl_mat *steps = NULL;
691         struct isl_map *path = NULL;
692         unsigned d;
693         int i, j, n;
694
695         d = isl_map_dim(map, isl_dim_in);
696
697         path = isl_map_identity(isl_dim_domain(isl_dim_copy(dim)));
698
699         steps = isl_mat_alloc(map->ctx, map->n, d);
700         if (!steps)
701                 goto error;
702
703         n = 0;
704         for (i = 0; i < map->n; ++i) {
705                 struct isl_basic_set *delta;
706
707                 delta = isl_basic_map_deltas(isl_basic_map_copy(map->p[i]));
708
709                 for (j = 0; j < d; ++j) {
710                         int fixed;
711
712                         fixed = isl_basic_set_fast_dim_is_fixed(delta, j,
713                                                             &steps->row[n][j]);
714                         if (fixed < 0) {
715                                 isl_basic_set_free(delta);
716                                 goto error;
717                         }
718                         if (!fixed)
719                                 break;
720                 }
721
722
723                 if (j < d) {
724                         path = isl_map_apply_range(path,
725                                 path_along_delta(isl_dim_copy(dim), delta));
726                         path = isl_map_coalesce(path);
727                 } else {
728                         isl_basic_set_free(delta);
729                         ++n;
730                 }
731         }
732
733         if (n > 0) {
734                 steps->n_row = n;
735                 path = isl_map_apply_range(path,
736                                 path_along_steps(isl_dim_copy(dim), steps));
737         }
738
739         if (project && *project) {
740                 *project = is_acyclic(isl_map_copy(path));
741                 if (*project < 0)
742                         goto error;
743         }
744
745         isl_dim_free(dim);
746         isl_mat_free(steps);
747         return path;
748 error:
749         isl_dim_free(dim);
750         isl_mat_free(steps);
751         isl_map_free(path);
752         return NULL;
753 }
754
755 static int isl_set_overlaps(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
756 {
757         isl_set *i;
758         int no_overlap;
759
760         i = isl_set_intersect(isl_set_copy(set1), isl_set_copy(set2));
761         no_overlap = isl_set_is_empty(i);
762         isl_set_free(i);
763
764         return no_overlap < 0 ? -1 : !no_overlap;
765 }
766
767 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
768  * and a dimension specification (Z^{n+1} -> Z^{n+1}),
769  * construct a map that is an overapproximation of the map
770  * that takes an element from the dom R \times Z to an
771  * element from ran R \times Z, such that the first n coordinates of the
772  * difference between them is a sum of differences between images
773  * and pre-images in one of the R_i and such that the last coordinate
774  * is equal to the number of steps taken.
775  * That is, let
776  *
777  *      \Delta_i = { y - x | (x, y) in R_i }
778  *
779  * then the constructed map is an overapproximation of
780  *
781  *      { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
782  *                              d = (\sum_i k_i \delta_i, \sum_i k_i) and
783  *                              x in dom R and x + d in ran R and
784  *                              \sum_i k_i >= 1 }
785  */
786 static __isl_give isl_map *construct_component(__isl_take isl_dim *dim,
787         __isl_keep isl_map *map, int *exact, int project)
788 {
789         struct isl_set *domain = NULL;
790         struct isl_set *range = NULL;
791         struct isl_map *app = NULL;
792         struct isl_map *path = NULL;
793
794         domain = isl_map_domain(isl_map_copy(map));
795         domain = isl_set_coalesce(domain);
796         range = isl_map_range(isl_map_copy(map));
797         range = isl_set_coalesce(range);
798         if (!isl_set_overlaps(domain, range)) {
799                 isl_set_free(domain);
800                 isl_set_free(range);
801                 isl_dim_free(dim);
802
803                 map = isl_map_copy(map);
804                 map = isl_map_add(map, isl_dim_in, 1);
805                 map = isl_map_add(map, isl_dim_out, 1);
806                 map = set_path_length(map, 1, 1);
807                 return map;
808         }
809         app = isl_map_from_domain_and_range(domain, range);
810         app = isl_map_add(app, isl_dim_in, 1);
811         app = isl_map_add(app, isl_dim_out, 1);
812
813         path = construct_extended_path(isl_dim_copy(dim), map,
814                                         exact && *exact ? &project : NULL);
815         app = isl_map_intersect(app, path);
816
817         if (exact && *exact &&
818             (*exact = check_exactness(isl_map_copy(map), isl_map_copy(app),
819                                       project)) < 0)
820                 goto error;
821
822         isl_dim_free(dim);
823         app = set_path_length(app, 0, 1);
824         return app;
825 error:
826         isl_dim_free(dim);
827         isl_map_free(app);
828         return NULL;
829 }
830
831 /* Call construct_component and, if "project" is set, project out
832  * the final coordinates.
833  */
834 static __isl_give isl_map *construct_projected_component(
835         __isl_take isl_dim *dim,
836         __isl_keep isl_map *map, int *exact, int project)
837 {
838         isl_map *app;
839         unsigned d;
840
841         if (!dim)
842                 return NULL;
843         d = isl_dim_size(dim, isl_dim_in);
844
845         app = construct_component(dim, map, exact, project);
846         if (project) {
847                 app = isl_map_project_out(app, isl_dim_in, d - 1, 1);
848                 app = isl_map_project_out(app, isl_dim_out, d - 1, 1);
849         }
850         return app;
851 }
852
853 /* Compute an extended version, i.e., with path lengths, of
854  * an overapproximation of the transitive closure of "bmap"
855  * with path lengths greater than or equal to zero and with
856  * domain and range equal to "dom".
857  */
858 static __isl_give isl_map *q_closure(__isl_take isl_dim *dim,
859         __isl_take isl_set *dom, __isl_keep isl_basic_map *bmap, int *exact)
860 {
861         int project = 1;
862         isl_map *path;
863         isl_map *map;
864         isl_map *app;
865
866         dom = isl_set_add(dom, isl_dim_set, 1);
867         app = isl_map_from_domain_and_range(dom, isl_set_copy(dom));
868         map = isl_map_from_basic_map(isl_basic_map_copy(bmap));
869         path = construct_extended_path(dim, map, &project);
870         app = isl_map_intersect(app, path);
871
872         if ((*exact = check_exactness(map, isl_map_copy(app), project)) < 0)
873                 goto error;
874
875         return app;
876 error:
877         isl_map_free(app);
878         return NULL;
879 }
880
881 /* Check whether qc has any elements of length at least one
882  * with domain and/or range outside of dom and ran.
883  */
884 static int has_spurious_elements(__isl_keep isl_map *qc,
885         __isl_keep isl_set *dom, __isl_keep isl_set *ran)
886 {
887         isl_set *s;
888         int subset;
889         unsigned d;
890
891         if (!qc || !dom || !ran)
892                 return -1;
893
894         d = isl_map_dim(qc, isl_dim_in);
895
896         qc = isl_map_copy(qc);
897         qc = set_path_length(qc, 0, 1);
898         qc = isl_map_project_out(qc, isl_dim_in, d - 1, 1);
899         qc = isl_map_project_out(qc, isl_dim_out, d - 1, 1);
900
901         s = isl_map_domain(isl_map_copy(qc));
902         subset = isl_set_is_subset(s, dom);
903         isl_set_free(s);
904         if (subset < 0)
905                 goto error;
906         if (!subset) {
907                 isl_map_free(qc);
908                 return 1;
909         }
910
911         s = isl_map_range(qc);
912         subset = isl_set_is_subset(s, ran);
913         isl_set_free(s);
914
915         return subset < 0 ? -1 : !subset;
916 error:
917         isl_map_free(qc);
918         return -1;
919 }
920
921 #define LEFT    2
922 #define RIGHT   1
923
924 /* For each basic map in "map", except i, check whether it combines
925  * with the transitive closure that is reflexive on C combines
926  * to the left and to the right.
927  *
928  * In particular, if
929  *
930  *      dom map_j \subseteq C
931  *
932  * then right[j] is set to 1.  Otherwise, if
933  *
934  *      ran map_i \cap dom map_j = \emptyset
935  *
936  * then right[j] is set to 0.  Otherwise, composing to the right
937  * is impossible.
938  *
939  * Similar, for composing to the left, we have if
940  *
941  *      ran map_j \subseteq C
942  *
943  * then left[j] is set to 1.  Otherwise, if
944  *
945  *      dom map_i \cap ran map_j = \emptyset
946  *
947  * then left[j] is set to 0.  Otherwise, composing to the left
948  * is impossible.
949  *
950  * The return value is or'd with LEFT if composing to the left
951  * is possible and with RIGHT if composing to the right is possible.
952  */
953 static int composability(__isl_keep isl_set *C, int i,
954         isl_set **dom, isl_set **ran, int *left, int *right,
955         __isl_keep isl_map *map)
956 {
957         int j;
958         int ok;
959
960         ok = LEFT | RIGHT;
961         for (j = 0; j < map->n && ok; ++j) {
962                 int overlaps, subset;
963                 if (j == i)
964                         continue;
965
966                 if (ok & RIGHT) {
967                         if (!dom[j])
968                                 dom[j] = isl_set_from_basic_set(
969                                         isl_basic_map_domain(
970                                                 isl_basic_map_copy(map->p[j])));
971                         if (!dom[j])
972                                 return -1;
973                         overlaps = isl_set_overlaps(ran[i], dom[j]);
974                         if (overlaps < 0)
975                                 return -1;
976                         if (!overlaps)
977                                 right[j] = 0;
978                         else {
979                                 subset = isl_set_is_subset(dom[j], C);
980                                 if (subset < 0)
981                                         return -1;
982                                 if (subset)
983                                         right[j] = 1;
984                                 else
985                                         ok &= ~RIGHT;
986                         }
987                 }
988
989                 if (ok & LEFT) {
990                         if (!ran[j])
991                                 ran[j] = isl_set_from_basic_set(
992                                         isl_basic_map_range(
993                                                 isl_basic_map_copy(map->p[j])));
994                         if (!ran[j])
995                                 return -1;
996                         overlaps = isl_set_overlaps(dom[i], ran[j]);
997                         if (overlaps < 0)
998                                 return -1;
999                         if (!overlaps)
1000                                 left[j] = 0;
1001                         else {
1002                                 subset = isl_set_is_subset(ran[j], C);
1003                                 if (subset < 0)
1004                                         return -1;
1005                                 if (subset)
1006                                         left[j] = 1;
1007                                 else
1008                                         ok &= ~LEFT;
1009                         }
1010                 }
1011         }
1012
1013         return ok;
1014 }
1015
1016 /* Return a map that is a union of the basic maps in "map", except i,
1017  * composed to left and right with qc based on the entries of "left"
1018  * and "right".
1019  */
1020 static __isl_give isl_map *compose(__isl_keep isl_map *map, int i,
1021         __isl_take isl_map *qc, int *left, int *right)
1022 {
1023         int j;
1024         isl_map *comp;
1025
1026         comp = isl_map_empty(isl_map_get_dim(map));
1027         for (j = 0; j < map->n; ++j) {
1028                 isl_map *map_j;
1029
1030                 if (j == i)
1031                         continue;
1032
1033                 map_j = isl_map_from_basic_map(isl_basic_map_copy(map->p[j]));
1034                 if (left && left[j])
1035                         map_j = isl_map_apply_range(map_j, isl_map_copy(qc));
1036                 if (right && right[j])
1037                         map_j = isl_map_apply_range(isl_map_copy(qc), map_j);
1038                 comp = isl_map_union(comp, map_j);
1039         }
1040
1041         comp = isl_map_compute_divs(comp);
1042         comp = isl_map_coalesce(comp);
1043
1044         isl_map_free(qc);
1045
1046         return comp;
1047 }
1048
1049 /* Compute the transitive closure of "map" incrementally by
1050  * computing
1051  *
1052  *      map_i^+ \cup qc^+
1053  *
1054  * or
1055  *
1056  *      map_i^+ \cup ((id \cup map_i^) \circ qc^+)
1057  *
1058  * or
1059  *
1060  *      map_i^+ \cup (qc^+ \circ (id \cup map_i^))
1061  *
1062  * depending on whether left or right are NULL.
1063  */
1064 static __isl_give isl_map *compute_incremental(
1065         __isl_take isl_dim *dim, __isl_keep isl_map *map,
1066         int i, __isl_take isl_map *qc, int *left, int *right, int *exact)
1067 {
1068         isl_map *map_i;
1069         isl_map *tc;
1070         isl_map *rtc = NULL;
1071
1072         if (!map)
1073                 goto error;
1074         isl_assert(map->ctx, left || right, goto error);
1075
1076         map_i = isl_map_from_basic_map(isl_basic_map_copy(map->p[i]));
1077         tc = construct_projected_component(isl_dim_copy(dim), map_i,
1078                                                 exact, 1);
1079         isl_map_free(map_i);
1080
1081         if (*exact)
1082                 qc = isl_map_transitive_closure(qc, exact);
1083
1084         if (!*exact) {
1085                 isl_dim_free(dim);
1086                 isl_map_free(tc);
1087                 isl_map_free(qc);
1088                 return isl_map_universe(isl_map_get_dim(map));
1089         }
1090
1091         if (!left || !right)
1092                 rtc = isl_map_union(isl_map_copy(tc),
1093                         isl_map_identity(isl_dim_domain(isl_map_get_dim(tc))));
1094         if (!right)
1095                 qc = isl_map_apply_range(rtc, qc);
1096         if (!left)
1097                 qc = isl_map_apply_range(qc, rtc);
1098         qc = isl_map_union(tc, qc);
1099
1100         isl_dim_free(dim);
1101
1102         return qc;
1103 error:
1104         isl_dim_free(dim);
1105         isl_map_free(qc);
1106         return NULL;
1107 }
1108
1109 /* Given a map "map", try to find a basic map such that
1110  * map^+ can be computed as
1111  *
1112  * map^+ = map_i^+ \cup
1113  *    \bigcup_j ((map_i^+ \cup Id_C)^+ \circ map_j \circ (map_i^+ \cup Id_C))^+
1114  *
1115  * with C the simple hull of the domain and range of the input map.
1116  * map_i^ \cup Id_C is computed by allowing the path lengths to be zero
1117  * and by intersecting domain and range with C.
1118  * Of course, we need to check that this is actually equal to map_i^ \cup Id_C.
1119  * Also, we only use the incremental computation if all the transitive
1120  * closures are exact and if the number of basic maps in the union,
1121  * after computing the integer divisions, is smaller than the number
1122  * of basic maps in the input map.
1123  */
1124 static int incemental_on_entire_domain(__isl_keep isl_dim *dim,
1125         __isl_keep isl_map *map,
1126         isl_set **dom, isl_set **ran, int *left, int *right,
1127         __isl_give isl_map **res)
1128 {
1129         int i;
1130         isl_set *C;
1131         unsigned d;
1132
1133         *res = NULL;
1134
1135         C = isl_set_union(isl_map_domain(isl_map_copy(map)),
1136                           isl_map_range(isl_map_copy(map)));
1137         C = isl_set_from_basic_set(isl_set_simple_hull(C));
1138         if (!C)
1139                 return -1;
1140         if (C->n != 1) {
1141                 isl_set_free(C);
1142                 return 0;
1143         }
1144
1145         d = isl_map_dim(map, isl_dim_in);
1146
1147         for (i = 0; i < map->n; ++i) {
1148                 isl_map *qc;
1149                 int exact_i, spurious;
1150                 int j;
1151                 dom[i] = isl_set_from_basic_set(isl_basic_map_domain(
1152                                         isl_basic_map_copy(map->p[i])));
1153                 ran[i] = isl_set_from_basic_set(isl_basic_map_range(
1154                                         isl_basic_map_copy(map->p[i])));
1155                 qc = q_closure(isl_dim_copy(dim), isl_set_copy(C),
1156                                 map->p[i], &exact_i);
1157                 if (!qc)
1158                         goto error;
1159                 if (!exact_i) {
1160                         isl_map_free(qc);
1161                         continue;
1162                 }
1163                 spurious = has_spurious_elements(qc, dom[i], ran[i]);
1164                 if (spurious) {
1165                         isl_map_free(qc);
1166                         if (spurious < 0)
1167                                 goto error;
1168                         continue;
1169                 }
1170                 qc = isl_map_project_out(qc, isl_dim_in, d, 1);
1171                 qc = isl_map_project_out(qc, isl_dim_out, d, 1);
1172                 qc = isl_map_compute_divs(qc);
1173                 for (j = 0; j < map->n; ++j)
1174                         left[j] = right[j] = 1;
1175                 qc = compose(map, i, qc, left, right);
1176                 if (!qc)
1177                         goto error;
1178                 if (qc->n >= map->n) {
1179                         isl_map_free(qc);
1180                         continue;
1181                 }
1182                 *res = compute_incremental(isl_dim_copy(dim), map, i, qc,
1183                                 left, right, &exact_i);
1184                 if (!*res)
1185                         goto error;
1186                 if (exact_i)
1187                         break;
1188                 isl_map_free(*res);
1189                 *res = NULL;
1190         }
1191
1192         isl_set_free(C);
1193
1194         return *res != NULL;
1195 error:
1196         isl_set_free(C);
1197         return -1;
1198 }
1199
1200 /* Try and compute the transitive closure of "map" as
1201  *
1202  * map^+ = map_i^+ \cup
1203  *    \bigcup_j ((map_i^+ \cup Id_C)^+ \circ map_j \circ (map_i^+ \cup Id_C))^+
1204  *
1205  * with C either the simple hull of the domain and range of the entire
1206  * map or the simple hull of domain and range of map_i.
1207  */
1208 static __isl_give isl_map *incremental_closure(__isl_take isl_dim *dim,
1209         __isl_keep isl_map *map, int *exact, int project)
1210 {
1211         int i;
1212         isl_set **dom = NULL;
1213         isl_set **ran = NULL;
1214         int *left = NULL;
1215         int *right = NULL;
1216         isl_set *C;
1217         unsigned d;
1218         isl_map *res = NULL;
1219
1220         if (!project)
1221                 return construct_projected_component(dim, map, exact, project);
1222
1223         if (!map)
1224                 goto error;
1225         if (map->n <= 1)
1226                 return construct_projected_component(dim, map, exact, project);
1227
1228         d = isl_map_dim(map, isl_dim_in);
1229
1230         dom = isl_calloc_array(map->ctx, isl_set *, map->n);
1231         ran = isl_calloc_array(map->ctx, isl_set *, map->n);
1232         left = isl_calloc_array(map->ctx, int, map->n);
1233         right = isl_calloc_array(map->ctx, int, map->n);
1234         if (!ran || !dom || !left || !right)
1235                 goto error;
1236
1237         if (incemental_on_entire_domain(dim, map, dom, ran, left, right, &res) < 0)
1238                 goto error;
1239
1240         for (i = 0; !res && i < map->n; ++i) {
1241                 isl_map *qc;
1242                 int exact_i, spurious, comp;
1243                 if (!dom[i])
1244                         dom[i] = isl_set_from_basic_set(
1245                                         isl_basic_map_domain(
1246                                                 isl_basic_map_copy(map->p[i])));
1247                 if (!dom[i])
1248                         goto error;
1249                 if (!ran[i])
1250                         ran[i] = isl_set_from_basic_set(
1251                                         isl_basic_map_range(
1252                                                 isl_basic_map_copy(map->p[i])));
1253                 if (!ran[i])
1254                         goto error;
1255                 C = isl_set_union(isl_set_copy(dom[i]),
1256                                       isl_set_copy(ran[i]));
1257                 C = isl_set_from_basic_set(isl_set_simple_hull(C));
1258                 if (!C)
1259                         goto error;
1260                 if (C->n != 1) {
1261                         isl_set_free(C);
1262                         continue;
1263                 }
1264                 comp = composability(C, i, dom, ran, left, right, map);
1265                 if (!comp || comp < 0) {
1266                         isl_set_free(C);
1267                         if (comp < 0)
1268                                 goto error;
1269                         continue;
1270                 }
1271                 qc = q_closure(isl_dim_copy(dim), C, map->p[i], &exact_i);
1272                 if (!qc)
1273                         goto error;
1274                 if (!exact_i) {
1275                         isl_map_free(qc);
1276                         continue;
1277                 }
1278                 spurious = has_spurious_elements(qc, dom[i], ran[i]);
1279                 if (spurious) {
1280                         isl_map_free(qc);
1281                         if (spurious < 0)
1282                                 goto error;
1283                         continue;
1284                 }
1285                 qc = isl_map_project_out(qc, isl_dim_in, d, 1);
1286                 qc = isl_map_project_out(qc, isl_dim_out, d, 1);
1287                 qc = isl_map_compute_divs(qc);
1288                 qc = compose(map, i, qc, (comp & LEFT) ? left : NULL,
1289                                 (comp & RIGHT) ? right : NULL);
1290                 if (!qc)
1291                         goto error;
1292                 if (qc->n >= map->n) {
1293                         isl_map_free(qc);
1294                         continue;
1295                 }
1296                 res = compute_incremental(isl_dim_copy(dim), map, i, qc,
1297                                 (comp & LEFT) ? left : NULL,
1298                                 (comp & RIGHT) ? right : NULL, &exact_i);
1299                 if (!res)
1300                         goto error;
1301                 if (exact_i)
1302                         break;
1303                 isl_map_free(res);
1304                 res = NULL;
1305         }
1306
1307         for (i = 0; i < map->n; ++i) {
1308                 isl_set_free(dom[i]);
1309                 isl_set_free(ran[i]);
1310         }
1311         free(dom);
1312         free(ran);
1313         free(left);
1314         free(right);
1315
1316         if (res) {
1317                 isl_dim_free(dim);
1318                 return res;
1319         }
1320
1321         return construct_projected_component(dim, map, exact, project);
1322 error:
1323         if (dom)
1324                 for (i = 0; i < map->n; ++i)
1325                         isl_set_free(dom[i]);
1326         free(dom);
1327         if (ran)
1328                 for (i = 0; i < map->n; ++i)
1329                         isl_set_free(ran[i]);
1330         free(ran);
1331         free(left);
1332         free(right);
1333         isl_dim_free(dim);
1334         return NULL;
1335 }
1336
1337 /* Given an array of sets "set", add "dom" at position "pos"
1338  * and search for elements at earlier positions that overlap with "dom".
1339  * If any can be found, then merge all of them, together with "dom", into
1340  * a single set and assign the union to the first in the array,
1341  * which becomes the new group leader for all groups involved in the merge.
1342  * During the search, we only consider group leaders, i.e., those with
1343  * group[i] = i, as the other sets have already been combined
1344  * with one of the group leaders.
1345  */
1346 static int merge(isl_set **set, int *group, __isl_take isl_set *dom, int pos)
1347 {
1348         int i;
1349
1350         group[pos] = pos;
1351         set[pos] = isl_set_copy(dom);
1352
1353         for (i = pos - 1; i >= 0; --i) {
1354                 int o;
1355
1356                 if (group[i] != i)
1357                         continue;
1358
1359                 o = isl_set_overlaps(set[i], dom);
1360                 if (o < 0)
1361                         goto error;
1362                 if (!o)
1363                         continue;
1364
1365                 set[i] = isl_set_union(set[i], set[group[pos]]);
1366                 if (!set[i])
1367                         goto error;
1368                 set[group[pos]] = NULL;
1369                 group[group[pos]] = i;
1370                 group[pos] = i;
1371         }
1372
1373         isl_set_free(dom);
1374         return 0;
1375 error:
1376         isl_set_free(dom);
1377         return -1;
1378 }
1379
1380 /* Replace each entry in the n by n grid of maps by the cross product
1381  * with the relation { [i] -> [i + 1] }.
1382  */
1383 static int add_length(__isl_keep isl_map *map, isl_map ***grid, int n)
1384 {
1385         int i, j, k;
1386         isl_dim *dim;
1387         isl_basic_map *bstep;
1388         isl_map *step;
1389         unsigned nparam;
1390
1391         if (!map)
1392                 return -1;
1393
1394         dim = isl_map_get_dim(map);
1395         nparam = isl_dim_size(dim, isl_dim_param);
1396         dim = isl_dim_drop(dim, isl_dim_in, 0, isl_dim_size(dim, isl_dim_in));
1397         dim = isl_dim_drop(dim, isl_dim_out, 0, isl_dim_size(dim, isl_dim_out));
1398         dim = isl_dim_add(dim, isl_dim_in, 1);
1399         dim = isl_dim_add(dim, isl_dim_out, 1);
1400         bstep = isl_basic_map_alloc_dim(dim, 0, 1, 0);
1401         k = isl_basic_map_alloc_equality(bstep);
1402         if (k < 0) {
1403                 isl_basic_map_free(bstep);
1404                 return -1;
1405         }
1406         isl_seq_clr(bstep->eq[k], 1 + isl_basic_map_total_dim(bstep));
1407         isl_int_set_si(bstep->eq[k][0], 1);
1408         isl_int_set_si(bstep->eq[k][1 + nparam], 1);
1409         isl_int_set_si(bstep->eq[k][1 + nparam + 1], -1);
1410         bstep = isl_basic_map_finalize(bstep);
1411         step = isl_map_from_basic_map(bstep);
1412
1413         for (i = 0; i < n; ++i)
1414                 for (j = 0; j < n; ++j)
1415                         grid[i][j] = isl_map_product(grid[i][j],
1416                                                      isl_map_copy(step));
1417
1418         isl_map_free(step);
1419
1420         return 0;
1421 }
1422
1423 /* Given a partition of the domains and ranges of the basic maps in "map",
1424  * apply the Floyd-Warshall algorithm with the elements in the partition
1425  * as vertices.
1426  *
1427  * In particular, there are "n" elements in the partition and "group" is
1428  * an array of length 2 * map->n with entries in [0,n-1].
1429  *
1430  * We first construct a matrix of relations based on the partition information,
1431  * apply Floyd-Warshall on this matrix of relations and then take the
1432  * union of all entries in the matrix as the final result.
1433  *
1434  * The algorithm iterates over all vertices.  In each step, the whole
1435  * matrix is updated to include all paths that go to the current vertex,
1436  * possibly stay there a while (including passing through earlier vertices)
1437  * and then come back.  At the start of each iteration, the diagonal
1438  * element corresponding to the current vertex is replaced by its
1439  * transitive closure to account for all indirect paths that stay
1440  * in the current vertex.
1441  *
1442  * If we are actually computing the power instead of the transitive closure,
1443  * i.e., when "project" is not set, then the result should have the
1444  * path lengths encoded as the difference between an extra pair of
1445  * coordinates.  We therefore apply the nested transitive closures
1446  * to relations that include these lengths.  In particular, we replace
1447  * the input relation by the cross product with the unit length relation
1448  * { [i] -> [i + 1] }.
1449  */
1450 static __isl_give isl_map *floyd_warshall_with_groups(__isl_take isl_dim *dim,
1451         __isl_keep isl_map *map, int *exact, int project, int *group, int n)
1452 {
1453         int i, j, k;
1454         int r, p, q;
1455         isl_map ***grid = NULL;
1456         isl_map *app;
1457
1458         if (!map)
1459                 goto error;
1460
1461         if (n == 1) {
1462                 free(group);
1463                 return incremental_closure(dim, map, exact, project);
1464         }
1465
1466         grid = isl_calloc_array(map->ctx, isl_map **, n);
1467         if (!grid)
1468                 goto error;
1469         for (i = 0; i < n; ++i) {
1470                 grid[i] = isl_calloc_array(map->ctx, isl_map *, n);
1471                 if (!grid[i])
1472                         goto error;
1473                 for (j = 0; j < n; ++j)
1474                         grid[i][j] = isl_map_empty(isl_map_get_dim(map));
1475         }
1476
1477         for (k = 0; k < map->n; ++k) {
1478                 i = group[2 * k];
1479                 j = group[2 * k + 1];
1480                 grid[i][j] = isl_map_union(grid[i][j],
1481                                 isl_map_from_basic_map(
1482                                         isl_basic_map_copy(map->p[k])));
1483         }
1484
1485         if (!project && add_length(map, grid, n) < 0)
1486                 goto error;
1487
1488         for (r = 0; r < n; ++r) {
1489                 int r_exact;
1490                 grid[r][r] = isl_map_transitive_closure(grid[r][r],
1491                                 (exact && *exact) ? &r_exact : NULL);
1492                 if (exact && *exact && !r_exact)
1493                         *exact = 0;
1494
1495                 for (p = 0; p < n; ++p)
1496                         for (q = 0; q < n; ++q) {
1497                                 isl_map *loop;
1498                                 if (p == r && q == r)
1499                                         continue;
1500                                 loop = isl_map_apply_range(
1501                                                 isl_map_copy(grid[p][r]),
1502                                                 isl_map_copy(grid[r][q]));
1503                                 grid[p][q] = isl_map_union(grid[p][q], loop);
1504                                 loop = isl_map_apply_range(
1505                                                 isl_map_copy(grid[p][r]),
1506                                         isl_map_apply_range(
1507                                                 isl_map_copy(grid[r][r]),
1508                                                 isl_map_copy(grid[r][q])));
1509                                 grid[p][q] = isl_map_union(grid[p][q], loop);
1510                                 grid[p][q] = isl_map_coalesce(grid[p][q]);
1511                         }
1512         }
1513
1514         app = isl_map_empty(isl_map_get_dim(map));
1515
1516         for (i = 0; i < n; ++i) {
1517                 for (j = 0; j < n; ++j)
1518                         app = isl_map_union(app, grid[i][j]);
1519                 free(grid[i]);
1520         }
1521         free(grid);
1522
1523         free(group);
1524         isl_dim_free(dim);
1525
1526         return app;
1527 error:
1528         if (grid)
1529                 for (i = 0; i < n; ++i) {
1530                         if (!grid[i])
1531                                 continue;
1532                         for (j = 0; j < n; ++j)
1533                                 isl_map_free(grid[i][j]);
1534                         free(grid[i]);
1535                 }
1536         free(grid);
1537         free(group);
1538         isl_dim_free(dim);
1539         return NULL;
1540 }
1541
1542 /* Check if the domains and ranges of the basic maps in "map" can
1543  * be partitioned, and if so, apply Floyd-Warshall on the elements
1544  * of the partition.  Note that we also apply this algorithm
1545  * if we want to compute the power, i.e., when "project" is not set.
1546  * However, the results are unlikely to be exact since the recursive
1547  * calls inside the Floyd-Warshall algorithm typically result in
1548  * non-linear path lengths quite quickly.
1549  *
1550  * To find the partition, we simply consider all of the domains
1551  * and ranges in turn and combine those that overlap.
1552  * "set" contains the partition elements and "group" indicates
1553  * to which partition element a given domain or range belongs.
1554  * The domain of basic map i corresponds to element 2 * i in these arrays,
1555  * while the domain corresponds to element 2 * i + 1.
1556  * During the construction group[k] is either equal to k,
1557  * in which case set[k] contains the union of all the domains and
1558  * ranges in the corresponding group, or is equal to some l < k,
1559  * with l another domain or range in the same group.
1560  */
1561 static __isl_give isl_map *floyd_warshall(__isl_take isl_dim *dim,
1562         __isl_keep isl_map *map, int *exact, int project)
1563 {
1564         int i;
1565         isl_set **set = NULL;
1566         int *group = NULL;
1567         int n;
1568
1569         if (!map)
1570                 goto error;
1571         if (map->n <= 1)
1572                 return incremental_closure(dim, map, exact, project);
1573
1574         set = isl_calloc_array(map->ctx, isl_set *, 2 * map->n);
1575         group = isl_alloc_array(map->ctx, int, 2 * map->n);
1576
1577         if (!set || !group)
1578                 goto error;
1579
1580         for (i = 0; i < map->n; ++i) {
1581                 isl_set *dom;
1582                 dom = isl_set_from_basic_set(isl_basic_map_domain(
1583                                 isl_basic_map_copy(map->p[i])));
1584                 if (merge(set, group, dom, 2 * i) < 0)
1585                         goto error;
1586                 dom = isl_set_from_basic_set(isl_basic_map_range(
1587                                 isl_basic_map_copy(map->p[i])));
1588                 if (merge(set, group, dom, 2 * i + 1) < 0)
1589                         goto error;
1590         }
1591
1592         n = 0;
1593         for (i = 0; i < 2 * map->n; ++i)
1594                 if (group[i] == i)
1595                         group[i] = n++;
1596                 else
1597                         group[i] = group[group[i]];
1598
1599         for (i = 0; i < 2 * map->n; ++i)
1600                 isl_set_free(set[i]);
1601
1602         free(set);
1603
1604         return floyd_warshall_with_groups(dim, map, exact, project, group, n);
1605 error:
1606         for (i = 0; i < 2 * map->n; ++i)
1607                 isl_set_free(set[i]);
1608         free(set);
1609         free(group);
1610         isl_dim_free(dim);
1611         return NULL;
1612 }
1613
1614 /* Structure for representing the nodes in the graph being traversed
1615  * using Tarjan's algorithm.
1616  * index represents the order in which nodes are visited.
1617  * min_index is the index of the root of a (sub)component.
1618  * on_stack indicates whether the node is currently on the stack.
1619  */
1620 struct basic_map_sort_node {
1621         int index;
1622         int min_index;
1623         int on_stack;
1624 };
1625 /* Structure for representing the graph being traversed
1626  * using Tarjan's algorithm.
1627  * len is the number of nodes
1628  * node is an array of nodes
1629  * stack contains the nodes on the path from the root to the current node
1630  * sp is the stack pointer
1631  * index is the index of the last node visited
1632  * order contains the elements of the components separated by -1
1633  * op represents the current position in order
1634  *
1635  * check_closed is set if we may have used the fact that
1636  * a pair of basic maps can be interchanged
1637  */
1638 struct basic_map_sort {
1639         int len;
1640         struct basic_map_sort_node *node;
1641         int *stack;
1642         int sp;
1643         int index;
1644         int *order;
1645         int op;
1646         int check_closed;
1647 };
1648
1649 static void basic_map_sort_free(struct basic_map_sort *s)
1650 {
1651         if (!s)
1652                 return;
1653         free(s->node);
1654         free(s->stack);
1655         free(s->order);
1656         free(s);
1657 }
1658
1659 static struct basic_map_sort *basic_map_sort_alloc(struct isl_ctx *ctx, int len)
1660 {
1661         struct basic_map_sort *s;
1662         int i;
1663
1664         s = isl_calloc_type(ctx, struct basic_map_sort);
1665         if (!s)
1666                 return NULL;
1667         s->len = len;
1668         s->node = isl_alloc_array(ctx, struct basic_map_sort_node, len);
1669         if (!s->node)
1670                 goto error;
1671         for (i = 0; i < len; ++i)
1672                 s->node[i].index = -1;
1673         s->stack = isl_alloc_array(ctx, int, len);
1674         if (!s->stack)
1675                 goto error;
1676         s->order = isl_alloc_array(ctx, int, 2 * len);
1677         if (!s->order)
1678                 goto error;
1679
1680         s->sp = 0;
1681         s->index = 0;
1682         s->op = 0;
1683
1684         s->check_closed = 0;
1685
1686         return s;
1687 error:
1688         basic_map_sort_free(s);
1689         return NULL;
1690 }
1691
1692 /* Check whether in the computation of the transitive closure
1693  * "bmap1" (R_1) should follow (or be part of the same component as)
1694  * "bmap2" (R_2).
1695  *
1696  * That is check whether
1697  *
1698  *      R_1 \circ R_2
1699  *
1700  * is a subset of
1701  *
1702  *      R_2 \circ R_1
1703  *
1704  * If so, then there is no reason for R_1 to immediately follow R_2
1705  * in any path.
1706  *
1707  * *check_closed is set if the subset relation holds while
1708  * R_1 \circ R_2 is not empty.
1709  */
1710 static int basic_map_follows(__isl_keep isl_basic_map *bmap1,
1711         __isl_keep isl_basic_map *bmap2, int *check_closed)
1712 {
1713         struct isl_map *map12 = NULL;
1714         struct isl_map *map21 = NULL;
1715         int subset;
1716
1717         map21 = isl_map_from_basic_map(
1718                         isl_basic_map_apply_range(
1719                                 isl_basic_map_copy(bmap2),
1720                                 isl_basic_map_copy(bmap1)));
1721         subset = isl_map_is_empty(map21);
1722         if (subset < 0)
1723                 goto error;
1724         if (subset) {
1725                 isl_map_free(map21);
1726                 return 0;
1727         }
1728
1729         map12 = isl_map_from_basic_map(
1730                         isl_basic_map_apply_range(
1731                                 isl_basic_map_copy(bmap1),
1732                                 isl_basic_map_copy(bmap2)));
1733
1734         subset = isl_map_is_subset(map21, map12);
1735
1736         isl_map_free(map12);
1737         isl_map_free(map21);
1738
1739         if (subset)
1740                 *check_closed = 1;
1741
1742         return subset < 0 ? -1 : !subset;
1743 error:
1744         isl_map_free(map21);
1745         return -1;
1746 }
1747
1748 /* Perform Tarjan's algorithm for computing the strongly connected components
1749  * in the graph with the disjuncts of "map" as vertices and with an
1750  * edge between any pair of disjuncts such that the first has
1751  * to be applied after the second.
1752  */
1753 static int power_components_tarjan(struct basic_map_sort *s,
1754         __isl_keep isl_map *map, int i)
1755 {
1756         int j;
1757
1758         s->node[i].index = s->index;
1759         s->node[i].min_index = s->index;
1760         s->node[i].on_stack = 1;
1761         s->index++;
1762         s->stack[s->sp++] = i;
1763
1764         for (j = s->len - 1; j >= 0; --j) {
1765                 int f;
1766
1767                 if (j == i)
1768                         continue;
1769                 if (s->node[j].index >= 0 &&
1770                         (!s->node[j].on_stack ||
1771                          s->node[j].index > s->node[i].min_index))
1772                         continue;
1773
1774                 f = basic_map_follows(map->p[i], map->p[j], &s->check_closed);
1775                 if (f < 0)
1776                         return -1;
1777                 if (!f)
1778                         continue;
1779
1780                 if (s->node[j].index < 0) {
1781                         power_components_tarjan(s, map, j);
1782                         if (s->node[j].min_index < s->node[i].min_index)
1783                                 s->node[i].min_index = s->node[j].min_index;
1784                 } else if (s->node[j].index < s->node[i].min_index)
1785                         s->node[i].min_index = s->node[j].index;
1786         }
1787
1788         if (s->node[i].index != s->node[i].min_index)
1789                 return 0;
1790
1791         do {
1792                 j = s->stack[--s->sp];
1793                 s->node[j].on_stack = 0;
1794                 s->order[s->op++] = j;
1795         } while (j != i);
1796         s->order[s->op++] = -1;
1797
1798         return 0;
1799 }
1800
1801 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
1802  * and a dimension specification (Z^{n+1} -> Z^{n+1}),
1803  * construct a map that is an overapproximation of the map
1804  * that takes an element from the dom R \times Z to an
1805  * element from ran R \times Z, such that the first n coordinates of the
1806  * difference between them is a sum of differences between images
1807  * and pre-images in one of the R_i and such that the last coordinate
1808  * is equal to the number of steps taken.
1809  * If "project" is set, then these final coordinates are not included,
1810  * i.e., a relation of type Z^n -> Z^n is returned.
1811  * That is, let
1812  *
1813  *      \Delta_i = { y - x | (x, y) in R_i }
1814  *
1815  * then the constructed map is an overapproximation of
1816  *
1817  *      { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
1818  *                              d = (\sum_i k_i \delta_i, \sum_i k_i) and
1819  *                              x in dom R and x + d in ran R }
1820  *
1821  * or
1822  *
1823  *      { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
1824  *                              d = (\sum_i k_i \delta_i) and
1825  *                              x in dom R and x + d in ran R }
1826  *
1827  * if "project" is set.
1828  *
1829  * We first split the map into strongly connected components, perform
1830  * the above on each component and then join the results in the correct
1831  * order, at each join also taking in the union of both arguments
1832  * to allow for paths that do not go through one of the two arguments.
1833  */
1834 static __isl_give isl_map *construct_power_components(__isl_take isl_dim *dim,
1835         __isl_keep isl_map *map, int *exact, int project)
1836 {
1837         int i, n, c;
1838         struct isl_map *path = NULL;
1839         struct basic_map_sort *s = NULL;
1840         int *orig_exact;
1841         int local_exact;
1842
1843         if (!map)
1844                 goto error;
1845         if (map->n <= 1)
1846                 return floyd_warshall(dim, map, exact, project);
1847
1848         s = basic_map_sort_alloc(map->ctx, map->n);
1849         if (!s)
1850                 goto error;
1851         for (i = map->n - 1; i >= 0; --i) {
1852                 if (s->node[i].index >= 0)
1853                         continue;
1854                 if (power_components_tarjan(s, map, i) < 0)
1855                         goto error;
1856         }
1857
1858         orig_exact = exact;
1859         if (s->check_closed && !exact)
1860                 exact = &local_exact;
1861
1862         c = 0;
1863         i = 0;
1864         n = map->n;
1865         if (project)
1866                 path = isl_map_empty(isl_map_get_dim(map));
1867         else
1868                 path = isl_map_empty(isl_dim_copy(dim));
1869         while (n) {
1870                 struct isl_map *comp;
1871                 isl_map *path_comp, *path_comb;
1872                 comp = isl_map_alloc_dim(isl_map_get_dim(map), n, 0);
1873                 while (s->order[i] != -1) {
1874                         comp = isl_map_add_basic_map(comp,
1875                                     isl_basic_map_copy(map->p[s->order[i]]));
1876                         --n;
1877                         ++i;
1878                 }
1879                 path_comp = floyd_warshall(isl_dim_copy(dim),
1880                                                 comp, exact, project);
1881                 path_comb = isl_map_apply_range(isl_map_copy(path),
1882                                                 isl_map_copy(path_comp));
1883                 path = isl_map_union(path, path_comp);
1884                 path = isl_map_union(path, path_comb);
1885                 isl_map_free(comp);
1886                 ++i;
1887                 ++c;
1888         }
1889
1890         if (c > 1 && s->check_closed && !*exact) {
1891                 int closed;
1892
1893                 closed = isl_map_is_transitively_closed(path);
1894                 if (closed < 0)
1895                         goto error;
1896                 if (!closed) {
1897                         basic_map_sort_free(s);
1898                         isl_map_free(path);
1899                         return floyd_warshall(dim, map, orig_exact, project);
1900                 }
1901         }
1902
1903         basic_map_sort_free(s);
1904         isl_dim_free(dim);
1905
1906         return path;
1907 error:
1908         basic_map_sort_free(s);
1909         isl_dim_free(dim);
1910         isl_map_free(path);
1911         return NULL;
1912 }
1913
1914 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D,
1915  * construct a map that is an overapproximation of the map
1916  * that takes an element from the space D to another
1917  * element from the same space, such that the difference between
1918  * them is a strictly positive sum of differences between images
1919  * and pre-images in one of the R_i.
1920  * The number of differences in the sum is equated to parameter "param".
1921  * That is, let
1922  *
1923  *      \Delta_i = { y - x | (x, y) in R_i }
1924  *
1925  * then the constructed map is an overapproximation of
1926  *
1927  *      { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
1928  *                              d = \sum_i k_i \delta_i and k = \sum_i k_i > 0 }
1929  * or
1930  *
1931  *      { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
1932  *                              d = \sum_i k_i \delta_i and \sum_i k_i > 0 }
1933  *
1934  * if "project" is set.
1935  *
1936  * If "project" is not set, then
1937  * we construct an extended mapping with an extra coordinate
1938  * that indicates the number of steps taken.  In particular,
1939  * the difference in the last coordinate is equal to the number
1940  * of steps taken to move from a domain element to the corresponding
1941  * image element(s).
1942  */
1943 static __isl_give isl_map *construct_power(__isl_keep isl_map *map,
1944         int *exact, int project)
1945 {
1946         struct isl_map *app = NULL;
1947         struct isl_dim *dim = NULL;
1948         unsigned d;
1949
1950         if (!map)
1951                 return NULL;
1952
1953         dim = isl_map_get_dim(map);
1954
1955         d = isl_dim_size(dim, isl_dim_in);
1956         dim = isl_dim_add(dim, isl_dim_in, 1);
1957         dim = isl_dim_add(dim, isl_dim_out, 1);
1958
1959         app = construct_power_components(isl_dim_copy(dim), map,
1960                                         exact, project);
1961
1962         isl_dim_free(dim);
1963
1964         return app;
1965 }
1966
1967 /* Compute the positive powers of "map", or an overapproximation.
1968  * If the result is exact, then *exact is set to 1.
1969  *
1970  * If project is set, then we are actually interested in the transitive
1971  * closure, so we can use a more relaxed exactness check.
1972  * The lengths of the paths are also projected out instead of being
1973  * encoded as the difference between an extra pair of final coordinates.
1974  */
1975 static __isl_give isl_map *map_power(__isl_take isl_map *map,
1976         int *exact, int project)
1977 {
1978         struct isl_map *app = NULL;
1979
1980         if (exact)
1981                 *exact = 1;
1982
1983         if (!map)
1984                 return NULL;
1985
1986         isl_assert(map->ctx,
1987                 isl_map_dim(map, isl_dim_in) == isl_map_dim(map, isl_dim_out),
1988                 goto error);
1989
1990         app = construct_power(map, exact, project);
1991
1992         isl_map_free(map);
1993         return app;
1994 error:
1995         isl_map_free(map);
1996         isl_map_free(app);
1997         return NULL;
1998 }
1999
2000 /* Compute the positive powers of "map", or an overapproximation.
2001  * The power is given by parameter "param".  If the result is exact,
2002  * then *exact is set to 1.
2003  * map_power constructs an extended relation with the path lengths
2004  * encoded as the difference between the final coordinates.
2005  * In the final step, this difference is equated to the parameter "param"
2006  * and made positive.  The extra coordinates are subsequently projected out.
2007  */
2008 __isl_give isl_map *isl_map_power(__isl_take isl_map *map, unsigned param,
2009         int *exact)
2010 {
2011         isl_dim *dim;
2012         isl_map *diff;
2013         unsigned d;
2014
2015         if (!map)
2016                 return NULL;
2017
2018         isl_assert(map->ctx, param < isl_map_dim(map, isl_dim_param),
2019                 goto error);
2020
2021         d = isl_map_dim(map, isl_dim_in);
2022
2023         map = isl_map_compute_divs(map);
2024         map = isl_map_coalesce(map);
2025
2026         if (isl_map_fast_is_empty(map))
2027                 return map;
2028
2029         map = map_power(map, exact, 0);
2030
2031         dim = isl_map_get_dim(map);
2032         diff = equate_parameter_to_length(dim, param);
2033         map = isl_map_intersect(map, diff);
2034         map = isl_map_project_out(map, isl_dim_in, d, 1);
2035         map = isl_map_project_out(map, isl_dim_out, d, 1);
2036
2037         return map;
2038 error:
2039         isl_map_free(map);
2040         return NULL;
2041 }
2042
2043 /* Check whether equality i of bset is a pure stride constraint
2044  * on a single dimensions, i.e., of the form
2045  *
2046  *      v = k e
2047  *
2048  * with k a constant and e an existentially quantified variable.
2049  */
2050 static int is_eq_stride(__isl_keep isl_basic_set *bset, int i)
2051 {
2052         int k;
2053         unsigned nparam;
2054         unsigned d;
2055         unsigned n_div;
2056         int pos1;
2057         int pos2;
2058
2059         if (!bset)
2060                 return -1;
2061
2062         if (!isl_int_is_zero(bset->eq[i][0]))
2063                 return 0;
2064
2065         nparam = isl_basic_set_dim(bset, isl_dim_param);
2066         d = isl_basic_set_dim(bset, isl_dim_set);
2067         n_div = isl_basic_set_dim(bset, isl_dim_div);
2068
2069         if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
2070                 return 0;
2071         pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
2072         if (pos1 == -1)
2073                 return 0;
2074         if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1, 
2075                                         d - pos1 - 1) != -1)
2076                 return 0;
2077
2078         pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
2079         if (pos2 == -1)
2080                 return 0;
2081         if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d  + pos2 + 1,
2082                                    n_div - pos2 - 1) != -1)
2083                 return 0;
2084         if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
2085             !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
2086                 return 0;
2087
2088         return 1;
2089 }
2090
2091 /* Given a map, compute the smallest superset of this map that is of the form
2092  *
2093  *      { i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
2094  *
2095  * (where p ranges over the (non-parametric) dimensions),
2096  * compute the transitive closure of this map, i.e.,
2097  *
2098  *      { i -> j : exists k > 0:
2099  *              k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
2100  *
2101  * and intersect domain and range of this transitive closure with
2102  * the given domain and range.
2103  *
2104  * If with_id is set, then try to include as much of the identity mapping
2105  * as possible, by computing
2106  *
2107  *      { i -> j : exists k >= 0:
2108  *              k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
2109  *
2110  * instead (i.e., allow k = 0).
2111  *
2112  * In practice, we compute the difference set
2113  *
2114  *      delta  = { j - i | i -> j in map },
2115  *
2116  * look for stride constraint on the individual dimensions and compute
2117  * (constant) lower and upper bounds for each individual dimension,
2118  * adding a constraint for each bound not equal to infinity.
2119  */
2120 static __isl_give isl_map *box_closure_on_domain(__isl_take isl_map *map,
2121         __isl_take isl_set *dom, __isl_take isl_set *ran, int with_id)
2122 {
2123         int i;
2124         int k;
2125         unsigned d;
2126         unsigned nparam;
2127         unsigned total;
2128         isl_dim *dim;
2129         isl_set *delta;
2130         isl_map *app = NULL;
2131         isl_basic_set *aff = NULL;
2132         isl_basic_map *bmap = NULL;
2133         isl_vec *obj = NULL;
2134         isl_int opt;
2135
2136         isl_int_init(opt);
2137
2138         delta = isl_map_deltas(isl_map_copy(map));
2139
2140         aff = isl_set_affine_hull(isl_set_copy(delta));
2141         if (!aff)
2142                 goto error;
2143         dim = isl_map_get_dim(map);
2144         d = isl_dim_size(dim, isl_dim_in);
2145         nparam = isl_dim_size(dim, isl_dim_param);
2146         total = isl_dim_total(dim);
2147         bmap = isl_basic_map_alloc_dim(dim,
2148                                         aff->n_div + 1, aff->n_div, 2 * d + 1);
2149         for (i = 0; i < aff->n_div + 1; ++i) {
2150                 k = isl_basic_map_alloc_div(bmap);
2151                 if (k < 0)
2152                         goto error;
2153                 isl_int_set_si(bmap->div[k][0], 0);
2154         }
2155         for (i = 0; i < aff->n_eq; ++i) {
2156                 if (!is_eq_stride(aff, i))
2157                         continue;
2158                 k = isl_basic_map_alloc_equality(bmap);
2159                 if (k < 0)
2160                         goto error;
2161                 isl_seq_clr(bmap->eq[k], 1 + nparam);
2162                 isl_seq_cpy(bmap->eq[k] + 1 + nparam + d,
2163                                 aff->eq[i] + 1 + nparam, d);
2164                 isl_seq_neg(bmap->eq[k] + 1 + nparam,
2165                                 aff->eq[i] + 1 + nparam, d);
2166                 isl_seq_cpy(bmap->eq[k] + 1 + nparam + 2 * d,
2167                                 aff->eq[i] + 1 + nparam + d, aff->n_div);
2168                 isl_int_set_si(bmap->eq[k][1 + total + aff->n_div], 0);
2169         }
2170         obj = isl_vec_alloc(map->ctx, 1 + nparam + d);
2171         if (!obj)
2172                 goto error;
2173         isl_seq_clr(obj->el, 1 + nparam + d);
2174         for (i = 0; i < d; ++ i) {
2175                 enum isl_lp_result res;
2176
2177                 isl_int_set_si(obj->el[1 + nparam + i], 1);
2178
2179                 res = isl_set_solve_lp(delta, 0, obj->el, map->ctx->one, &opt,
2180                                         NULL, NULL);
2181                 if (res == isl_lp_error)
2182                         goto error;
2183                 if (res == isl_lp_ok) {
2184                         k = isl_basic_map_alloc_inequality(bmap);
2185                         if (k < 0)
2186                                 goto error;
2187                         isl_seq_clr(bmap->ineq[k],
2188                                         1 + nparam + 2 * d + bmap->n_div);
2189                         isl_int_set_si(bmap->ineq[k][1 + nparam + i], -1);
2190                         isl_int_set_si(bmap->ineq[k][1 + nparam + d + i], 1);
2191                         isl_int_neg(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], opt);
2192                 }
2193
2194                 res = isl_set_solve_lp(delta, 1, obj->el, map->ctx->one, &opt,
2195                                         NULL, NULL);
2196                 if (res == isl_lp_error)
2197                         goto error;
2198                 if (res == isl_lp_ok) {
2199                         k = isl_basic_map_alloc_inequality(bmap);
2200                         if (k < 0)
2201                                 goto error;
2202                         isl_seq_clr(bmap->ineq[k],
2203                                         1 + nparam + 2 * d + bmap->n_div);
2204                         isl_int_set_si(bmap->ineq[k][1 + nparam + i], 1);
2205                         isl_int_set_si(bmap->ineq[k][1 + nparam + d + i], -1);
2206                         isl_int_set(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], opt);
2207                 }
2208
2209                 isl_int_set_si(obj->el[1 + nparam + i], 0);
2210         }
2211         k = isl_basic_map_alloc_inequality(bmap);
2212         if (k < 0)
2213                 goto error;
2214         isl_seq_clr(bmap->ineq[k],
2215                         1 + nparam + 2 * d + bmap->n_div);
2216         if (!with_id)
2217                 isl_int_set_si(bmap->ineq[k][0], -1);
2218         isl_int_set_si(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], 1);
2219
2220         app = isl_map_from_domain_and_range(dom, ran);
2221
2222         isl_vec_free(obj);
2223         isl_basic_set_free(aff);
2224         isl_map_free(map);
2225         bmap = isl_basic_map_finalize(bmap);
2226         isl_set_free(delta);
2227         isl_int_clear(opt);
2228
2229         map = isl_map_from_basic_map(bmap);
2230         map = isl_map_intersect(map, app);
2231
2232         return map;
2233 error:
2234         isl_vec_free(obj);
2235         isl_basic_map_free(bmap);
2236         isl_basic_set_free(aff);
2237         isl_set_free(dom);
2238         isl_set_free(ran);
2239         isl_map_free(map);
2240         isl_set_free(delta);
2241         isl_int_clear(opt);
2242         return NULL;
2243 }
2244
2245 /* Given a map, compute the smallest superset of this map that is of the form
2246  *
2247  *      { i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
2248  *
2249  * (where p ranges over the (non-parametric) dimensions),
2250  * compute the transitive closure of this map, i.e.,
2251  *
2252  *      { i -> j : exists k > 0:
2253  *              k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
2254  *
2255  * and intersect domain and range of this transitive closure with
2256  * domain and range of the original map.
2257  */
2258 static __isl_give isl_map *box_closure(__isl_take isl_map *map)
2259 {
2260         isl_set *domain;
2261         isl_set *range;
2262
2263         domain = isl_map_domain(isl_map_copy(map));
2264         domain = isl_set_coalesce(domain);
2265         range = isl_map_range(isl_map_copy(map));
2266         range = isl_set_coalesce(range);
2267
2268         return box_closure_on_domain(map, domain, range, 0);
2269 }
2270
2271 /* Given a map, compute the smallest superset of this map that is of the form
2272  *
2273  *      { i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
2274  *
2275  * (where p ranges over the (non-parametric) dimensions),
2276  * compute the transitive and partially reflexive closure of this map, i.e.,
2277  *
2278  *      { i -> j : exists k >= 0:
2279  *              k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
2280  *
2281  * and intersect domain and range of this transitive closure with
2282  * the given domain.
2283  */
2284 static __isl_give isl_map *box_closure_with_identity(__isl_take isl_map *map,
2285         __isl_take isl_set *dom)
2286 {
2287         return box_closure_on_domain(map, dom, isl_set_copy(dom), 1);
2288 }
2289
2290 /* Check whether app is the transitive closure of map.
2291  * In particular, check that app is acyclic and, if so,
2292  * check that
2293  *
2294  *      app \subset (map \cup (map \circ app))
2295  */
2296 static int check_exactness_omega(__isl_keep isl_map *map,
2297         __isl_keep isl_map *app)
2298 {
2299         isl_set *delta;
2300         int i;
2301         int is_empty, is_exact;
2302         unsigned d;
2303         isl_map *test;
2304
2305         delta = isl_map_deltas(isl_map_copy(app));
2306         d = isl_set_dim(delta, isl_dim_set);
2307         for (i = 0; i < d; ++i)
2308                 delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
2309         is_empty = isl_set_is_empty(delta);
2310         isl_set_free(delta);
2311         if (is_empty < 0)
2312                 return -1;
2313         if (!is_empty)
2314                 return 0;
2315
2316         test = isl_map_apply_range(isl_map_copy(app), isl_map_copy(map));
2317         test = isl_map_union(test, isl_map_copy(map));
2318         is_exact = isl_map_is_subset(app, test);
2319         isl_map_free(test);
2320
2321         return is_exact;
2322 }
2323
2324 /* Check if basic map M_i can be combined with all the other
2325  * basic maps such that
2326  *
2327  *      (\cup_j M_j)^+
2328  *
2329  * can be computed as
2330  *
2331  *      M_i \cup (\cup_{j \ne i} M_i^* \circ M_j \circ M_i^*)^+
2332  *
2333  * In particular, check if we can compute a compact representation
2334  * of
2335  *
2336  *              M_i^* \circ M_j \circ M_i^*
2337  *
2338  * for each j != i.
2339  * Let M_i^? be an extension of M_i^+ that allows paths
2340  * of length zero, i.e., the result of box_closure(., 1).
2341  * The criterion, as proposed by Kelly et al., is that
2342  * id = M_i^? - M_i^+ can be represented as a basic map
2343  * and that
2344  *
2345  *      id \circ M_j \circ id = M_j
2346  *
2347  * for each j != i.
2348  *
2349  * If this function returns 1, then tc and qc are set to
2350  * M_i^+ and M_i^?, respectively.
2351  */
2352 static int can_be_split_off(__isl_keep isl_map *map, int i,
2353         __isl_give isl_map **tc, __isl_give isl_map **qc)
2354 {
2355         isl_map *map_i, *id = NULL;
2356         int j = -1;
2357         isl_set *C;
2358
2359         *tc = NULL;
2360         *qc = NULL;
2361
2362         C = isl_set_union(isl_map_domain(isl_map_copy(map)),
2363                           isl_map_range(isl_map_copy(map)));
2364         C = isl_set_from_basic_set(isl_set_simple_hull(C));
2365         if (!C)
2366                 goto error;
2367
2368         map_i = isl_map_from_basic_map(isl_basic_map_copy(map->p[i]));
2369         *tc = box_closure(isl_map_copy(map_i));
2370         *qc = box_closure_with_identity(map_i, C);
2371         id = isl_map_subtract(isl_map_copy(*qc), isl_map_copy(*tc));
2372
2373         if (!id || !*qc)
2374                 goto error;
2375         if (id->n != 1 || (*qc)->n != 1)
2376                 goto done;
2377
2378         for (j = 0; j < map->n; ++j) {
2379                 isl_map *map_j, *test;
2380                 int is_ok;
2381
2382                 if (i == j)
2383                         continue;
2384                 map_j = isl_map_from_basic_map(
2385                                         isl_basic_map_copy(map->p[j]));
2386                 test = isl_map_apply_range(isl_map_copy(id),
2387                                                 isl_map_copy(map_j));
2388                 test = isl_map_apply_range(test, isl_map_copy(id));
2389                 is_ok = isl_map_is_equal(test, map_j);
2390                 isl_map_free(map_j);
2391                 isl_map_free(test);
2392                 if (is_ok < 0)
2393                         goto error;
2394                 if (!is_ok)
2395                         break;
2396         }
2397
2398 done:
2399         isl_map_free(id);
2400         if (j == map->n)
2401                 return 1;
2402
2403         isl_map_free(*qc);
2404         isl_map_free(*tc);
2405         *qc = NULL;
2406         *tc = NULL;
2407
2408         return 0;
2409 error:
2410         isl_map_free(id);
2411         isl_map_free(*qc);
2412         isl_map_free(*tc);
2413         *qc = NULL;
2414         *tc = NULL;
2415         return -1;
2416 }
2417
2418 static __isl_give isl_map *box_closure_with_check(__isl_take isl_map *map,
2419         int *exact)
2420 {
2421         isl_map *app;
2422
2423         app = box_closure(isl_map_copy(map));
2424         if (exact)
2425                 *exact = check_exactness_omega(map, app);
2426
2427         isl_map_free(map);
2428         return app;
2429 }
2430
2431 /* Compute an overapproximation of the transitive closure of "map"
2432  * using a variation of the algorithm from
2433  * "Transitive Closure of Infinite Graphs and its Applications"
2434  * by Kelly et al.
2435  *
2436  * We first check whether we can can split of any basic map M_i and
2437  * compute
2438  *
2439  *      (\cup_j M_j)^+
2440  *
2441  * as
2442  *
2443  *      M_i \cup (\cup_{j \ne i} M_i^* \circ M_j \circ M_i^*)^+
2444  *
2445  * using a recursive call on the remaining map.
2446  *
2447  * If not, we simply call box_closure on the whole map.
2448  */
2449 static __isl_give isl_map *transitive_closure_omega(__isl_take isl_map *map,
2450         int *exact)
2451 {
2452         int i, j;
2453         int exact_i;
2454         isl_map *app;
2455
2456         if (!map)
2457                 return NULL;
2458         if (map->n == 1)
2459                 return box_closure_with_check(map, exact);
2460
2461         for (i = 0; i < map->n; ++i) {
2462                 int ok;
2463                 isl_map *qc, *tc;
2464                 ok = can_be_split_off(map, i, &tc, &qc);
2465                 if (ok < 0)
2466                         goto error;
2467                 if (!ok)
2468                         continue;
2469
2470                 app = isl_map_alloc_dim(isl_map_get_dim(map), map->n - 1, 0);
2471
2472                 for (j = 0; j < map->n; ++j) {
2473                         if (j == i)
2474                                 continue;
2475                         app = isl_map_add_basic_map(app,
2476                                                 isl_basic_map_copy(map->p[j]));
2477                 }
2478
2479                 app = isl_map_apply_range(isl_map_copy(qc), app);
2480                 app = isl_map_apply_range(app, qc);
2481
2482                 app = isl_map_union(tc, transitive_closure_omega(app, NULL));
2483                 exact_i = check_exactness_omega(map, app);
2484                 if (exact_i == 1) {
2485                         if (exact)
2486                                 *exact = exact_i;
2487                         isl_map_free(map);
2488                         return app;
2489                 }
2490                 isl_map_free(app);
2491                 if (exact_i < 0)
2492                         goto error;
2493         }
2494
2495         return box_closure_with_check(map, exact);
2496 error:
2497         isl_map_free(map);
2498         return NULL;
2499 }
2500
2501 /* Compute the transitive closure  of "map", or an overapproximation.
2502  * If the result is exact, then *exact is set to 1.
2503  * Simply use map_power to compute the powers of map, but tell
2504  * it to project out the lengths of the paths instead of equating
2505  * the length to a parameter.
2506  */
2507 __isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
2508         int *exact)
2509 {
2510         int closed;
2511
2512         if (!map)
2513                 goto error;
2514
2515         if (map->ctx->opt->closure == ISL_CLOSURE_OMEGA)
2516                 return transitive_closure_omega(map, exact);
2517
2518         map = isl_map_compute_divs(map);
2519         map = isl_map_coalesce(map);
2520         closed = isl_map_is_transitively_closed(map);
2521         if (closed < 0)
2522                 goto error;
2523         if (closed) {
2524                 if (exact)
2525                         *exact = 1;
2526                 return map;
2527         }
2528
2529         map = map_power(map, exact, 1);
2530
2531         return map;
2532 error:
2533         isl_map_free(map);
2534         return NULL;
2535 }