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