2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
12 #include "isl_map_private.h"
15 /* Given a map that represents a path with the length of the path
16 * encoded as the difference between the last output coordindate
17 * and the last input coordinate, set this length to either
18 * exactly "length" (if "exactly" is set) or at least "length"
19 * (if "exactly" is not set).
21 static __isl_give isl_map *set_path_length(__isl_take isl_map *map,
22 int exactly, int length)
25 struct isl_basic_map *bmap;
34 dim = isl_map_get_dim(map);
35 d = isl_dim_size(dim, isl_dim_in);
36 nparam = isl_dim_size(dim, isl_dim_param);
37 bmap = isl_basic_map_alloc_dim(dim, 0, 1, 1);
39 k = isl_basic_map_alloc_equality(bmap);
42 k = isl_basic_map_alloc_inequality(bmap);
47 isl_seq_clr(c, 1 + isl_basic_map_total_dim(bmap));
48 isl_int_set_si(c[0], -length);
49 isl_int_set_si(c[1 + nparam + d - 1], -1);
50 isl_int_set_si(c[1 + nparam + d + d - 1], 1);
52 bmap = isl_basic_map_finalize(bmap);
53 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
57 isl_basic_map_free(bmap);
62 /* Check whether the overapproximation of the power of "map" is exactly
63 * the power of "map". Let R be "map" and A_k the overapproximation.
64 * The approximation is exact if
67 * A_k = A_{k-1} \circ R k >= 2
69 * Since A_k is known to be an overapproximation, we only need to check
72 * A_k \subset A_{k-1} \circ R k >= 2
74 * In practice, "app" has an extra input and output coordinate
75 * to encode the length of the path. So, we first need to add
76 * this coordinate to "map" and set the length of the path to
79 static int check_power_exactness(__isl_take isl_map *map,
80 __isl_take isl_map *app)
86 map = isl_map_add(map, isl_dim_in, 1);
87 map = isl_map_add(map, isl_dim_out, 1);
88 map = set_path_length(map, 1, 1);
90 app_1 = set_path_length(isl_map_copy(app), 1, 1);
92 exact = isl_map_is_subset(app_1, map);
95 if (!exact || exact < 0) {
101 app_1 = set_path_length(isl_map_copy(app), 0, 1);
102 app_2 = set_path_length(app, 0, 2);
103 app_1 = isl_map_apply_range(map, app_1);
105 exact = isl_map_is_subset(app_2, app_1);
113 /* Check whether the overapproximation of the power of "map" is exactly
114 * the power of "map", possibly after projecting out the power (if "project"
117 * If "project" is set and if "steps" can only result in acyclic paths,
120 * A = R \cup (A \circ R)
122 * where A is the overapproximation with the power projected out, i.e.,
123 * an overapproximation of the transitive closure.
124 * More specifically, since A is known to be an overapproximation, we check
126 * A \subset R \cup (A \circ R)
128 * Otherwise, we check if the power is exact.
130 * Note that "app" has an extra input and output coordinate to encode
131 * the length of the part. If we are only interested in the transitive
132 * closure, then we can simply project out these coordinates first.
134 static int check_exactness(__isl_take isl_map *map, __isl_take isl_map *app,
142 return check_power_exactness(map, app);
144 d = isl_map_dim(map, isl_dim_in);
145 app = set_path_length(app, 0, 1);
146 app = isl_map_project_out(app, isl_dim_in, d, 1);
147 app = isl_map_project_out(app, isl_dim_out, d, 1);
149 test = isl_map_apply_range(isl_map_copy(map), isl_map_copy(app));
150 test = isl_map_union(test, isl_map_copy(map));
152 exact = isl_map_is_subset(app, test);
167 * The transitive closure implementation is based on the paper
168 * "Computing the Transitive Closure of a Union of Affine Integer
169 * Tuple Relations" by Anna Beletska, Denis Barthou, Wlodzimierz Bielecki and
173 /* Given a set of n offsets v_i (the rows of "steps"), construct a relation
174 * of the given dimension specification (Z^{n+1} -> Z^{n+1})
175 * that maps an element x to any element that can be reached
176 * by taking a non-negative number of steps along any of
177 * the extended offsets v'_i = [v_i 1].
180 * { [x] -> [y] : exists k_i >= 0, y = x + \sum_i k_i v'_i }
182 * For any element in this relation, the number of steps taken
183 * is equal to the difference in the final coordinates.
185 static __isl_give isl_map *path_along_steps(__isl_take isl_dim *dim,
186 __isl_keep isl_mat *steps)
189 struct isl_basic_map *path = NULL;
197 d = isl_dim_size(dim, isl_dim_in);
199 nparam = isl_dim_size(dim, isl_dim_param);
201 path = isl_basic_map_alloc_dim(isl_dim_copy(dim), n, d, n);
203 for (i = 0; i < n; ++i) {
204 k = isl_basic_map_alloc_div(path);
207 isl_assert(steps->ctx, i == k, goto error);
208 isl_int_set_si(path->div[k][0], 0);
211 for (i = 0; i < d; ++i) {
212 k = isl_basic_map_alloc_equality(path);
215 isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
216 isl_int_set_si(path->eq[k][1 + nparam + i], 1);
217 isl_int_set_si(path->eq[k][1 + nparam + d + i], -1);
219 for (j = 0; j < n; ++j)
220 isl_int_set_si(path->eq[k][1 + nparam + 2 * d + j], 1);
222 for (j = 0; j < n; ++j)
223 isl_int_set(path->eq[k][1 + nparam + 2 * d + j],
227 for (i = 0; i < n; ++i) {
228 k = isl_basic_map_alloc_inequality(path);
231 isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
232 isl_int_set_si(path->ineq[k][1 + nparam + 2 * d + i], 1);
237 path = isl_basic_map_simplify(path);
238 path = isl_basic_map_finalize(path);
239 return isl_map_from_basic_map(path);
242 isl_basic_map_free(path);
251 /* Return PURE_PARAM if only the coefficients of the parameters are non-zero.
252 * Return PURE_VAR if only the coefficients of the set variables are non-zero.
253 * Return MIXED if only the coefficients of the parameters and the set
254 * variables are non-zero and if moreover the parametric constant
255 * can never attain positive values.
256 * Return IMPURE otherwise.
258 static int purity(__isl_keep isl_basic_set *bset, isl_int *c, int *div_purity,
269 n_div = isl_basic_set_dim(bset, isl_dim_div);
270 d = isl_basic_set_dim(bset, isl_dim_set);
271 nparam = isl_basic_set_dim(bset, isl_dim_param);
273 for (i = 0; i < n_div; ++i) {
274 if (isl_int_is_zero(c[1 + nparam + d + i]))
276 switch (div_purity[i]) {
277 case PURE_PARAM: p = 1; break;
278 case PURE_VAR: v = 1; break;
279 default: return IMPURE;
282 if (!p && isl_seq_first_non_zero(c + 1, nparam) == -1)
284 if (!v && isl_seq_first_non_zero(c + 1 + nparam, d) == -1)
289 bset = isl_basic_set_copy(bset);
290 bset = isl_basic_set_cow(bset);
291 bset = isl_basic_set_extend_constraints(bset, 0, 1);
292 k = isl_basic_set_alloc_inequality(bset);
295 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
296 isl_seq_cpy(bset->ineq[k], c, 1 + nparam);
297 for (i = 0; i < n_div; ++i) {
298 if (div_purity[i] != PURE_PARAM)
300 isl_int_set(bset->ineq[k][1 + nparam + d + i],
301 c[1 + nparam + d + i]);
303 isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
304 empty = isl_basic_set_is_empty(bset);
305 isl_basic_set_free(bset);
307 return empty < 0 ? -1 : empty ? MIXED : IMPURE;
309 isl_basic_set_free(bset);
313 /* Return an array of integers indicating the type of each div in bset.
314 * If the div is (recursively) defined in terms of only the parameters,
315 * then the type is PURE_PARAM.
316 * If the div is (recursively) defined in terms of only the set variables,
317 * then the type is PURE_VAR.
318 * Otherwise, the type is IMPURE.
320 static __isl_give int *get_div_purity(__isl_keep isl_basic_set *bset)
331 n_div = isl_basic_set_dim(bset, isl_dim_div);
332 d = isl_basic_set_dim(bset, isl_dim_set);
333 nparam = isl_basic_set_dim(bset, isl_dim_param);
335 div_purity = isl_alloc_array(bset->ctx, int, n_div);
339 for (i = 0; i < bset->n_div; ++i) {
341 if (isl_int_is_zero(bset->div[i][0])) {
342 div_purity[i] = IMPURE;
345 if (isl_seq_first_non_zero(bset->div[i] + 2, nparam) != -1)
347 if (isl_seq_first_non_zero(bset->div[i] + 2 + nparam, d) != -1)
349 for (j = 0; j < i; ++j) {
350 if (isl_int_is_zero(bset->div[i][2 + nparam + d + j]))
352 switch (div_purity[j]) {
353 case PURE_PARAM: p = 1; break;
354 case PURE_VAR: v = 1; break;
355 default: p = v = 1; break;
358 div_purity[i] = v ? p ? IMPURE : PURE_VAR : PURE_PARAM;
364 /* Given a path with the as yet unconstrained length at position "pos",
365 * check if setting the length to zero results in only the identity
368 int empty_path_is_identity(__isl_keep isl_basic_map *path, unsigned pos)
370 isl_basic_map *test = NULL;
371 isl_basic_map *id = NULL;
375 test = isl_basic_map_copy(path);
376 test = isl_basic_map_extend_constraints(test, 1, 0);
377 k = isl_basic_map_alloc_equality(test);
380 isl_seq_clr(test->eq[k], 1 + isl_basic_map_total_dim(test));
381 isl_int_set_si(test->eq[k][pos], 1);
382 id = isl_basic_map_identity(isl_dim_domain(isl_basic_map_get_dim(path)));
383 is_id = isl_basic_map_is_subset(test, id);
384 isl_basic_map_free(test);
385 isl_basic_map_free(id);
388 isl_basic_map_free(test);
392 __isl_give isl_basic_map *add_delta_constraints(__isl_take isl_basic_map *path,
393 __isl_keep isl_basic_set *delta, unsigned off, unsigned nparam,
394 unsigned d, int *div_purity, int eq)
397 int n = eq ? delta->n_eq : delta->n_ineq;
398 isl_int **delta_c = eq ? delta->eq : delta->ineq;
399 isl_int **path_c = eq ? path->eq : path->ineq;
402 n_div = isl_basic_set_dim(delta, isl_dim_div);
404 for (i = 0; i < n; ++i) {
405 int p = purity(delta, delta_c[i], div_purity, eq);
411 k = isl_basic_map_alloc_equality(path);
413 k = isl_basic_map_alloc_inequality(path);
416 isl_seq_clr(path_c[k], 1 + isl_basic_map_total_dim(path));
418 isl_seq_cpy(path_c[k] + off,
419 delta_c[i] + 1 + nparam, d);
420 isl_int_set(path_c[k][off + d], delta_c[i][0]);
421 } else if (p == PURE_PARAM) {
422 isl_seq_cpy(path_c[k], delta_c[i], 1 + nparam);
424 isl_seq_cpy(path_c[k] + off,
425 delta_c[i] + 1 + nparam, d);
426 isl_seq_cpy(path_c[k], delta_c[i], 1 + nparam);
428 isl_seq_cpy(path_c[k] + off - n_div,
429 delta_c[i] + 1 + nparam + d, n_div);
434 isl_basic_map_free(path);
438 /* Given a set of offsets "delta", construct a relation of the
439 * given dimension specification (Z^{n+1} -> Z^{n+1}) that
440 * is an overapproximation of the relations that
441 * maps an element x to any element that can be reached
442 * by taking a non-negative number of steps along any of
443 * the elements in "delta".
444 * That is, construct an approximation of
446 * { [x] -> [y] : exists f \in \delta, k \in Z :
447 * y = x + k [f, 1] and k >= 0 }
449 * For any element in this relation, the number of steps taken
450 * is equal to the difference in the final coordinates.
452 * In particular, let delta be defined as
454 * \delta = [p] -> { [x] : A x + a >= and B p + b >= 0 and
455 * C x + C'p + c >= 0 and
456 * D x + D'p + d >= 0 }
458 * where the constraints C x + C'p + c >= 0 are such that the parametric
459 * constant term of each constraint j, "C_j x + C'_j p + c_j",
460 * can never attain positive values, then the relation is constructed as
462 * { [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
463 * A f + k a >= 0 and B p + b >= 0 and
464 * C f + C'p + c >= 0 and k >= 1 }
465 * union { [x] -> [x] }
467 * If the zero-length paths happen to correspond exactly to the identity
468 * mapping, then we return
470 * { [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
471 * A f + k a >= 0 and B p + b >= 0 and
472 * C f + C'p + c >= 0 and k >= 0 }
476 * Existentially quantified variables in \delta are handled by
477 * classifying them as independent of the parameters, purely
478 * parameter dependent and others. Constraints containing
479 * any of the other existentially quantified variables are removed.
480 * This is safe, but leads to an additional overapproximation.
482 static __isl_give isl_map *path_along_delta(__isl_take isl_dim *dim,
483 __isl_take isl_basic_set *delta)
485 isl_basic_map *path = NULL;
492 int *div_purity = NULL;
496 n_div = isl_basic_set_dim(delta, isl_dim_div);
497 d = isl_basic_set_dim(delta, isl_dim_set);
498 nparam = isl_basic_set_dim(delta, isl_dim_param);
499 path = isl_basic_map_alloc_dim(isl_dim_copy(dim), n_div + d + 1,
500 d + 1 + delta->n_eq, delta->n_ineq + 1);
501 off = 1 + nparam + 2 * (d + 1) + n_div;
503 for (i = 0; i < n_div + d + 1; ++i) {
504 k = isl_basic_map_alloc_div(path);
507 isl_int_set_si(path->div[k][0], 0);
510 for (i = 0; i < d + 1; ++i) {
511 k = isl_basic_map_alloc_equality(path);
514 isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
515 isl_int_set_si(path->eq[k][1 + nparam + i], 1);
516 isl_int_set_si(path->eq[k][1 + nparam + d + 1 + i], -1);
517 isl_int_set_si(path->eq[k][off + i], 1);
520 div_purity = get_div_purity(delta);
524 path = add_delta_constraints(path, delta, off, nparam, d, div_purity, 1);
525 path = add_delta_constraints(path, delta, off, nparam, d, div_purity, 0);
527 is_id = empty_path_is_identity(path, off + d);
531 k = isl_basic_map_alloc_inequality(path);
534 isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
536 isl_int_set_si(path->ineq[k][0], -1);
537 isl_int_set_si(path->ineq[k][off + d], 1);
540 isl_basic_set_free(delta);
541 path = isl_basic_map_finalize(path);
544 return isl_map_from_basic_map(path);
546 return isl_basic_map_union(path,
547 isl_basic_map_identity(isl_dim_domain(dim)));
551 isl_basic_set_free(delta);
552 isl_basic_map_free(path);
556 /* Given a dimenion specification Z^{n+1} -> Z^{n+1} and a parameter "param",
557 * construct a map that equates the parameter to the difference
558 * in the final coordinates and imposes that this difference is positive.
561 * { [x,x_s] -> [y,y_s] : k = y_s - x_s > 0 }
563 static __isl_give isl_map *equate_parameter_to_length(__isl_take isl_dim *dim,
566 struct isl_basic_map *bmap;
571 d = isl_dim_size(dim, isl_dim_in);
572 nparam = isl_dim_size(dim, isl_dim_param);
573 bmap = isl_basic_map_alloc_dim(dim, 0, 1, 1);
574 k = isl_basic_map_alloc_equality(bmap);
577 isl_seq_clr(bmap->eq[k], 1 + isl_basic_map_total_dim(bmap));
578 isl_int_set_si(bmap->eq[k][1 + param], -1);
579 isl_int_set_si(bmap->eq[k][1 + nparam + d - 1], -1);
580 isl_int_set_si(bmap->eq[k][1 + nparam + d + d - 1], 1);
582 k = isl_basic_map_alloc_inequality(bmap);
585 isl_seq_clr(bmap->ineq[k], 1 + isl_basic_map_total_dim(bmap));
586 isl_int_set_si(bmap->ineq[k][1 + param], 1);
587 isl_int_set_si(bmap->ineq[k][0], -1);
589 bmap = isl_basic_map_finalize(bmap);
590 return isl_map_from_basic_map(bmap);
592 isl_basic_map_free(bmap);
596 /* Check whether "path" is acyclic, where the last coordinates of domain
597 * and range of path encode the number of steps taken.
598 * That is, check whether
600 * { d | d = y - x and (x,y) in path }
602 * does not contain any element with positive last coordinate (positive length)
603 * and zero remaining coordinates (cycle).
605 static int is_acyclic(__isl_take isl_map *path)
610 struct isl_set *delta;
612 delta = isl_map_deltas(path);
613 dim = isl_set_dim(delta, isl_dim_set);
614 for (i = 0; i < dim; ++i) {
616 delta = isl_set_lower_bound_si(delta, isl_dim_set, i, 1);
618 delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
621 acyclic = isl_set_is_empty(delta);
627 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
628 * and a dimension specification (Z^{n+1} -> Z^{n+1}),
629 * construct a map that is an overapproximation of the map
630 * that takes an element from the space D \times Z to another
631 * element from the same space, such that the first n coordinates of the
632 * difference between them is a sum of differences between images
633 * and pre-images in one of the R_i and such that the last coordinate
634 * is equal to the number of steps taken.
637 * \Delta_i = { y - x | (x, y) in R_i }
639 * then the constructed map is an overapproximation of
641 * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
642 * d = (\sum_i k_i \delta_i, \sum_i k_i) }
644 * The elements of the singleton \Delta_i's are collected as the
645 * rows of the steps matrix. For all these \Delta_i's together,
646 * a single path is constructed.
647 * For each of the other \Delta_i's, we compute an overapproximation
648 * of the paths along elements of \Delta_i.
649 * Since each of these paths performs an addition, composition is
650 * symmetric and we can simply compose all resulting paths in any order.
652 static __isl_give isl_map *construct_extended_path(__isl_take isl_dim *dim,
653 __isl_keep isl_map *map, int *project)
655 struct isl_mat *steps = NULL;
656 struct isl_map *path = NULL;
660 d = isl_map_dim(map, isl_dim_in);
662 path = isl_map_identity(isl_dim_domain(isl_dim_copy(dim)));
664 steps = isl_mat_alloc(map->ctx, map->n, d);
669 for (i = 0; i < map->n; ++i) {
670 struct isl_basic_set *delta;
672 delta = isl_basic_map_deltas(isl_basic_map_copy(map->p[i]));
674 for (j = 0; j < d; ++j) {
677 fixed = isl_basic_set_fast_dim_is_fixed(delta, j,
680 isl_basic_set_free(delta);
689 path = isl_map_apply_range(path,
690 path_along_delta(isl_dim_copy(dim), delta));
691 path = isl_map_coalesce(path);
693 isl_basic_set_free(delta);
700 path = isl_map_apply_range(path,
701 path_along_steps(isl_dim_copy(dim), steps));
704 if (project && *project) {
705 *project = is_acyclic(isl_map_copy(path));
720 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
721 * and a dimension specification (Z^{n+1} -> Z^{n+1}),
722 * construct a map that is the union of the identity map and
723 * an overapproximation of the map
724 * that takes an element from the dom R \times Z to an
725 * element from ran R \times Z, such that the first n coordinates of the
726 * difference between them is a sum of differences between images
727 * and pre-images in one of the R_i and such that the last coordinate
728 * is equal to the number of steps taken.
731 * \Delta_i = { y - x | (x, y) in R_i }
733 * then the constructed map is an overapproximation of
735 * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
736 * d = (\sum_i k_i \delta_i, \sum_i k_i) and
737 * x in dom R and x + d in ran R } union
740 static __isl_give isl_map *construct_component(__isl_take isl_dim *dim,
741 __isl_keep isl_map *map, int *exact, int project)
743 struct isl_set *domain = NULL;
744 struct isl_set *range = NULL;
745 struct isl_set *overlap;
746 struct isl_map *app = NULL;
747 struct isl_map *path = NULL;
749 domain = isl_map_domain(isl_map_copy(map));
750 domain = isl_set_coalesce(domain);
751 range = isl_map_range(isl_map_copy(map));
752 range = isl_set_coalesce(range);
753 overlap = isl_set_intersect(isl_set_copy(domain), isl_set_copy(range));
754 if (isl_set_is_empty(overlap) == 1) {
755 isl_set_free(domain);
757 isl_set_free(overlap);
760 map = isl_map_copy(map);
761 map = isl_map_add(map, isl_dim_in, 1);
762 map = isl_map_add(map, isl_dim_out, 1);
763 map = set_path_length(map, 1, 1);
766 isl_set_free(overlap);
767 app = isl_map_from_domain_and_range(domain, range);
768 app = isl_map_add(app, isl_dim_in, 1);
769 app = isl_map_add(app, isl_dim_out, 1);
771 path = construct_extended_path(isl_dim_copy(dim), map,
772 exact && *exact ? &project : NULL);
773 app = isl_map_intersect(app, path);
775 if (exact && *exact &&
776 (*exact = check_exactness(isl_map_copy(map), isl_map_copy(app),
780 return isl_map_union(app, isl_map_identity(isl_dim_domain(dim)));
787 /* Structure for representing the nodes in the graph being traversed
788 * using Tarjan's algorithm.
789 * index represents the order in which nodes are visited.
790 * min_index is the index of the root of a (sub)component.
791 * on_stack indicates whether the node is currently on the stack.
793 struct basic_map_sort_node {
798 /* Structure for representing the graph being traversed
799 * using Tarjan's algorithm.
800 * len is the number of nodes
801 * node is an array of nodes
802 * stack contains the nodes on the path from the root to the current node
803 * sp is the stack pointer
804 * index is the index of the last node visited
805 * order contains the elements of the components separated by -1
806 * op represents the current position in order
808 struct basic_map_sort {
810 struct basic_map_sort_node *node;
818 static void basic_map_sort_free(struct basic_map_sort *s)
828 static struct basic_map_sort *basic_map_sort_alloc(struct isl_ctx *ctx, int len)
830 struct basic_map_sort *s;
833 s = isl_calloc_type(ctx, struct basic_map_sort);
837 s->node = isl_alloc_array(ctx, struct basic_map_sort_node, len);
840 for (i = 0; i < len; ++i)
841 s->node[i].index = -1;
842 s->stack = isl_alloc_array(ctx, int, len);
845 s->order = isl_alloc_array(ctx, int, 2 * len);
855 basic_map_sort_free(s);
859 /* Check whether in the computation of the transitive closure
860 * "bmap1" (R_1) should follow (or be part of the same component as)
863 * That is check whether
871 * If so, then there is no reason for R_1 to immediately follow R_2
874 static int basic_map_follows(__isl_keep isl_basic_map *bmap1,
875 __isl_keep isl_basic_map *bmap2)
877 struct isl_map *map12 = NULL;
878 struct isl_map *map21 = NULL;
881 map21 = isl_map_from_basic_map(
882 isl_basic_map_apply_range(
883 isl_basic_map_copy(bmap2),
884 isl_basic_map_copy(bmap1)));
885 subset = isl_map_is_empty(map21);
893 map12 = isl_map_from_basic_map(
894 isl_basic_map_apply_range(
895 isl_basic_map_copy(bmap1),
896 isl_basic_map_copy(bmap2)));
898 subset = isl_map_is_subset(map21, map12);
903 return subset < 0 ? -1 : !subset;
909 /* Perform Tarjan's algorithm for computing the strongly connected components
910 * in the graph with the disjuncts of "map" as vertices and with an
911 * edge between any pair of disjuncts such that the first has
912 * to be applied after the second.
914 static int power_components_tarjan(struct basic_map_sort *s,
915 __isl_keep isl_map *map, int i)
919 s->node[i].index = s->index;
920 s->node[i].min_index = s->index;
921 s->node[i].on_stack = 1;
923 s->stack[s->sp++] = i;
925 for (j = s->len - 1; j >= 0; --j) {
930 if (s->node[j].index >= 0 &&
931 (!s->node[j].on_stack ||
932 s->node[j].index > s->node[i].min_index))
935 f = basic_map_follows(map->p[i], map->p[j]);
941 if (s->node[j].index < 0) {
942 power_components_tarjan(s, map, j);
943 if (s->node[j].min_index < s->node[i].min_index)
944 s->node[i].min_index = s->node[j].min_index;
945 } else if (s->node[j].index < s->node[i].min_index)
946 s->node[i].min_index = s->node[j].index;
949 if (s->node[i].index != s->node[i].min_index)
953 j = s->stack[--s->sp];
954 s->node[j].on_stack = 0;
955 s->order[s->op++] = j;
957 s->order[s->op++] = -1;
962 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
963 * and a dimension specification (Z^{n+1} -> Z^{n+1}),
964 * construct a map that is the union of the identity map and
965 * an overapproximation of the map
966 * that takes an element from the dom R \times Z to an
967 * element from ran R \times Z, such that the first n coordinates of the
968 * difference between them is a sum of differences between images
969 * and pre-images in one of the R_i and such that the last coordinate
970 * is equal to the number of steps taken.
973 * \Delta_i = { y - x | (x, y) in R_i }
975 * then the constructed map is an overapproximation of
977 * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
978 * d = (\sum_i k_i \delta_i, \sum_i k_i) and
979 * x in dom R and x + d in ran R } union
982 * We first split the map into strongly connected components, perform
983 * the above on each component and the join the results in the correct
984 * order. The power of each of the components needs to be extended
985 * with the identity map because a path in the global result need
986 * not go through every component.
987 * The final result will then also contain the identity map, but
988 * this part will be removed when the length of the path is forced
989 * to be strictly positive.
991 static __isl_give isl_map *construct_power_components(__isl_take isl_dim *dim,
992 __isl_keep isl_map *map, int *exact, int project)
995 struct isl_map *path = NULL;
996 struct basic_map_sort *s = NULL;
1001 return construct_component(dim, map, exact, project);
1003 s = basic_map_sort_alloc(map->ctx, map->n);
1006 for (i = map->n - 1; i >= 0; --i) {
1007 if (s->node[i].index >= 0)
1009 if (power_components_tarjan(s, map, i) < 0)
1015 path = isl_map_identity(isl_dim_domain(isl_dim_copy(dim)));
1017 struct isl_map *comp;
1018 comp = isl_map_alloc_dim(isl_map_get_dim(map), n, 0);
1019 while (s->order[i] != -1) {
1020 comp = isl_map_add_basic_map(comp,
1021 isl_basic_map_copy(map->p[s->order[i]]));
1025 path = isl_map_apply_range(path,
1026 construct_component(isl_dim_copy(dim), comp,
1032 basic_map_sort_free(s);
1037 basic_map_sort_free(s);
1042 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D,
1043 * construct a map that is an overapproximation of the map
1044 * that takes an element from the space D to another
1045 * element from the same space, such that the difference between
1046 * them is a strictly positive sum of differences between images
1047 * and pre-images in one of the R_i.
1048 * The number of differences in the sum is equated to parameter "param".
1051 * \Delta_i = { y - x | (x, y) in R_i }
1053 * then the constructed map is an overapproximation of
1055 * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
1056 * d = \sum_i k_i \delta_i and k = \sum_i k_i > 0 }
1058 * We first construct an extended mapping with an extra coordinate
1059 * that indicates the number of steps taken. In particular,
1060 * the difference in the last coordinate is equal to the number
1061 * of steps taken to move from a domain element to the corresponding
1063 * In the final step, this difference is equated to the parameter "param"
1064 * and made positive. The extra coordinates are subsequently projected out.
1066 static __isl_give isl_map *construct_power(__isl_keep isl_map *map,
1067 unsigned param, int *exact, int project)
1069 struct isl_map *app = NULL;
1070 struct isl_map *diff;
1071 struct isl_dim *dim = NULL;
1077 dim = isl_map_get_dim(map);
1079 d = isl_dim_size(dim, isl_dim_in);
1080 dim = isl_dim_add(dim, isl_dim_in, 1);
1081 dim = isl_dim_add(dim, isl_dim_out, 1);
1083 app = construct_power_components(isl_dim_copy(dim), map,
1086 diff = equate_parameter_to_length(dim, param);
1087 app = isl_map_intersect(app, diff);
1088 app = isl_map_project_out(app, isl_dim_in, d, 1);
1089 app = isl_map_project_out(app, isl_dim_out, d, 1);
1094 /* Compute the positive powers of "map", or an overapproximation.
1095 * The power is given by parameter "param". If the result is exact,
1096 * then *exact is set to 1.
1097 * If project is set, then we are actually interested in the transitive
1098 * closure, so we can use a more relaxed exactness check.
1100 static __isl_give isl_map *map_power(__isl_take isl_map *map, unsigned param,
1101 int *exact, int project)
1103 struct isl_map *app = NULL;
1108 map = isl_map_remove_empty_parts(map);
1112 if (isl_map_fast_is_empty(map))
1115 isl_assert(map->ctx, param < isl_map_dim(map, isl_dim_param), goto error);
1116 isl_assert(map->ctx,
1117 isl_map_dim(map, isl_dim_in) == isl_map_dim(map, isl_dim_out),
1120 app = construct_power(map, param, exact, project);
1130 /* Compute the positive powers of "map", or an overapproximation.
1131 * The power is given by parameter "param". If the result is exact,
1132 * then *exact is set to 1.
1134 __isl_give isl_map *isl_map_power(__isl_take isl_map *map, unsigned param,
1137 return map_power(map, param, exact, 0);
1140 /* Compute the transitive closure of "map", or an overapproximation.
1141 * If the result is exact, then *exact is set to 1.
1142 * Simply compute the powers of map and then project out the parameter
1143 * describing the power.
1145 __isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
1153 param = isl_map_dim(map, isl_dim_param);
1154 map = isl_map_add(map, isl_dim_param, 1);
1155 map = map_power(map, param, exact, 1);
1156 map = isl_map_project_out(map, isl_dim_param, param, 1);