3 #include "isl_map_private.h"
7 #include "isl_equalities.h"
9 static struct isl_basic_set *uset_convex_hull_wrap(struct isl_set *set);
11 static void swap_ineq(struct isl_basic_map *bmap, unsigned i, unsigned j)
17 bmap->ineq[i] = bmap->ineq[j];
22 /* Return 1 if constraint c is redundant with respect to the constraints
23 * in bmap. If c is a lower [upper] bound in some variable and bmap
24 * does not have a lower [upper] bound in that variable, then c cannot
25 * be redundant and we do not need solve any lp.
27 int isl_basic_map_constraint_is_redundant(struct isl_basic_map **bmap,
28 isl_int *c, isl_int *opt_n, isl_int *opt_d)
30 enum isl_lp_result res;
37 total = isl_basic_map_total_dim(*bmap);
38 for (i = 0; i < total; ++i) {
40 if (isl_int_is_zero(c[1+i]))
42 sign = isl_int_sgn(c[1+i]);
43 for (j = 0; j < (*bmap)->n_ineq; ++j)
44 if (sign == isl_int_sgn((*bmap)->ineq[j][1+i]))
46 if (j == (*bmap)->n_ineq)
52 res = isl_solve_lp(*bmap, 0, c+1, (*bmap)->ctx->one, opt_n, opt_d);
53 if (res == isl_lp_unbounded)
55 if (res == isl_lp_error)
57 if (res == isl_lp_empty) {
58 *bmap = isl_basic_map_set_to_empty(*bmap);
62 isl_int_addmul(*opt_n, *opt_d, c[0]);
64 isl_int_add(*opt_n, *opt_n, c[0]);
65 return !isl_int_is_neg(*opt_n);
68 int isl_basic_set_constraint_is_redundant(struct isl_basic_set **bset,
69 isl_int *c, isl_int *opt_n, isl_int *opt_d)
71 return isl_basic_map_constraint_is_redundant(
72 (struct isl_basic_map **)bset, c, opt_n, opt_d);
75 /* Compute the convex hull of a basic map, by removing the redundant
76 * constraints. If the minimal value along the normal of a constraint
77 * is the same if the constraint is removed, then the constraint is redundant.
79 * Alternatively, we could have intersected the basic map with the
80 * corresponding equality and the checked if the dimension was that
83 struct isl_basic_map *isl_basic_map_convex_hull(struct isl_basic_map *bmap)
90 bmap = isl_basic_map_implicit_equalities(bmap);
94 if (F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
96 if (F_ISSET(bmap, ISL_BASIC_MAP_NO_REDUNDANT))
102 for (i = bmap->n_ineq-1; i >= 0; --i) {
104 swap_ineq(bmap, i, bmap->n_ineq-1);
106 redundant = isl_basic_map_constraint_is_redundant(&bmap,
107 bmap->ineq[bmap->n_ineq], &opt_n, &opt_d);
110 if (F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
113 swap_ineq(bmap, i, bmap->n_ineq-1);
115 isl_basic_map_drop_inequality(bmap, i);
117 isl_int_clear(opt_n);
118 isl_int_clear(opt_d);
120 F_SET(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
123 isl_int_clear(opt_n);
124 isl_int_clear(opt_d);
125 isl_basic_map_free(bmap);
129 struct isl_basic_set *isl_basic_set_convex_hull(struct isl_basic_set *bset)
131 return (struct isl_basic_set *)
132 isl_basic_map_convex_hull((struct isl_basic_map *)bset);
135 /* Check if the set set is bound in the direction of the affine
136 * constraint c and if so, set the constant term such that the
137 * resulting constraint is a bounding constraint for the set.
139 static int uset_is_bound(struct isl_ctx *ctx, struct isl_set *set,
140 isl_int *c, unsigned len)
148 isl_int_init(opt_denom);
150 for (j = 0; j < set->n; ++j) {
151 enum isl_lp_result res;
153 if (F_ISSET(set->p[j], ISL_BASIC_SET_EMPTY))
156 res = isl_solve_lp((struct isl_basic_map*)set->p[j],
157 0, c+1, ctx->one, &opt, &opt_denom);
158 if (res == isl_lp_unbounded)
160 if (res == isl_lp_error)
162 if (res == isl_lp_empty) {
163 set->p[j] = isl_basic_set_set_to_empty(set->p[j]);
168 if (!isl_int_is_one(opt_denom))
169 isl_seq_scale(c, c, opt_denom, len);
170 if (first || isl_int_lt(opt, c[0]))
171 isl_int_set(c[0], opt);
175 isl_int_clear(opt_denom);
176 isl_int_neg(c[0], c[0]);
180 isl_int_clear(opt_denom);
184 /* Check if "c" is a direction with both a lower bound and an upper
185 * bound in "set" that is independent of the previously found "n"
187 * If so, add it to the list, with the negative of the lower bound
188 * in the constant position, i.e., such that c corresponds to a bounding
189 * hyperplane (but not necessarily a facet).
191 static int is_independent_bound(struct isl_ctx *ctx,
192 struct isl_set *set, isl_int *c,
193 struct isl_mat *dirs, int n)
198 isl_seq_cpy(dirs->row[n]+1, c+1, dirs->n_col-1);
200 int pos = isl_seq_first_non_zero(dirs->row[n]+1, dirs->n_col-1);
203 for (i = 0; i < n; ++i) {
205 pos_i = isl_seq_first_non_zero(dirs->row[i]+1, dirs->n_col-1);
210 isl_seq_elim(dirs->row[n]+1, dirs->row[i]+1, pos,
211 dirs->n_col-1, NULL);
212 pos = isl_seq_first_non_zero(dirs->row[n]+1, dirs->n_col-1);
218 isl_seq_neg(dirs->row[n] + 1, dirs->row[n] + 1, dirs->n_col - 1);
219 is_bound = uset_is_bound(ctx, set, dirs->row[n], dirs->n_col);
220 isl_seq_neg(dirs->row[n] + 1, dirs->row[n] + 1, dirs->n_col - 1);
223 is_bound = uset_is_bound(ctx, set, dirs->row[n], dirs->n_col);
228 isl_int *t = dirs->row[n];
229 for (k = n; k > i; --k)
230 dirs->row[k] = dirs->row[k-1];
236 /* Compute and return a maximal set of linearly independent bounds
237 * on the set "set", based on the constraints of the basic sets
240 static struct isl_mat *independent_bounds(struct isl_ctx *ctx,
244 struct isl_mat *dirs = NULL;
245 unsigned dim = isl_set_n_dim(set);
247 dirs = isl_mat_alloc(ctx, dim, 1+dim);
252 for (i = 0; n < dim && i < set->n; ++i) {
254 struct isl_basic_set *bset = set->p[i];
256 for (j = 0; n < dim && j < bset->n_eq; ++j) {
257 f = is_independent_bound(ctx, set, bset->eq[j],
264 for (j = 0; n < dim && j < bset->n_ineq; ++j) {
265 f = is_independent_bound(ctx, set, bset->ineq[j],
276 isl_mat_free(ctx, dirs);
280 static struct isl_basic_set *isl_basic_set_set_rational(
281 struct isl_basic_set *bset)
286 if (F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
289 bset = isl_basic_set_cow(bset);
293 F_SET(bset, ISL_BASIC_MAP_RATIONAL);
295 return isl_basic_set_finalize(bset);
298 static struct isl_set *isl_set_set_rational(struct isl_set *set)
302 set = isl_set_cow(set);
305 for (i = 0; i < set->n; ++i) {
306 set->p[i] = isl_basic_set_set_rational(set->p[i]);
316 static struct isl_basic_set *isl_basic_set_add_equality(struct isl_ctx *ctx,
317 struct isl_basic_set *bset, isl_int *c)
323 if (F_ISSET(bset, ISL_BASIC_SET_EMPTY))
326 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
327 isl_assert(ctx, bset->n_div == 0, goto error);
328 dim = isl_basic_set_n_dim(bset);
329 bset = isl_basic_set_extend(bset, 0, dim, 0, 1, 0);
330 i = isl_basic_set_alloc_equality(bset);
333 isl_seq_cpy(bset->eq[i], c, 1 + dim);
336 isl_basic_set_free(bset);
340 static struct isl_set *isl_set_add_equality(struct isl_ctx *ctx,
341 struct isl_set *set, isl_int *c)
345 set = isl_set_cow(set);
348 for (i = 0; i < set->n; ++i) {
349 set->p[i] = isl_basic_set_add_equality(ctx, set->p[i], c);
359 /* Given a union of basic sets, construct the constraints for wrapping
360 * a facet around one of its ridges.
361 * In particular, if each of n the d-dimensional basic sets i in "set"
362 * contains the origin, satisfies the constraints x_1 >= 0 and x_2 >= 0
363 * and is defined by the constraints
367 * then the resulting set is of dimension n*(1+d) and has as contraints
376 static struct isl_basic_set *wrap_constraints(struct isl_ctx *ctx,
379 struct isl_basic_set *lp;
383 unsigned dim, lp_dim;
388 dim = 1 + isl_set_n_dim(set);
391 for (i = 0; i < set->n; ++i) {
392 n_eq += set->p[i]->n_eq;
393 n_ineq += set->p[i]->n_ineq;
395 lp = isl_basic_set_alloc(ctx, 0, dim * set->n, 0, n_eq, n_ineq);
398 lp_dim = isl_basic_set_n_dim(lp);
399 k = isl_basic_set_alloc_equality(lp);
400 isl_int_set_si(lp->eq[k][0], -1);
401 for (i = 0; i < set->n; ++i) {
402 isl_int_set_si(lp->eq[k][1+dim*i], 0);
403 isl_int_set_si(lp->eq[k][1+dim*i+1], 1);
404 isl_seq_clr(lp->eq[k]+1+dim*i+2, dim-2);
406 for (i = 0; i < set->n; ++i) {
407 k = isl_basic_set_alloc_inequality(lp);
408 isl_seq_clr(lp->ineq[k], 1+lp_dim);
409 isl_int_set_si(lp->ineq[k][1+dim*i], 1);
411 for (j = 0; j < set->p[i]->n_eq; ++j) {
412 k = isl_basic_set_alloc_equality(lp);
413 isl_seq_clr(lp->eq[k], 1+dim*i);
414 isl_seq_cpy(lp->eq[k]+1+dim*i, set->p[i]->eq[j], dim);
415 isl_seq_clr(lp->eq[k]+1+dim*(i+1), dim*(set->n-i-1));
418 for (j = 0; j < set->p[i]->n_ineq; ++j) {
419 k = isl_basic_set_alloc_inequality(lp);
420 isl_seq_clr(lp->ineq[k], 1+dim*i);
421 isl_seq_cpy(lp->ineq[k]+1+dim*i, set->p[i]->ineq[j], dim);
422 isl_seq_clr(lp->ineq[k]+1+dim*(i+1), dim*(set->n-i-1));
428 /* Given a facet "facet" of the convex hull of "set" and a facet "ridge"
429 * of that facet, compute the other facet of the convex hull that contains
432 * We first transform the set such that the facet constraint becomes
436 * I.e., the facet lies in
440 * and on that facet, the constraint that defines the ridge is
444 * (This transformation is not strictly needed, all that is needed is
445 * that the ridge contains the origin.)
447 * Since the ridge contains the origin, the cone of the convex hull
448 * will be of the form
453 * with this second constraint defining the new facet.
454 * The constant a is obtained by settting x_1 in the cone of the
455 * convex hull to 1 and minimizing x_2.
456 * Now, each element in the cone of the convex hull is the sum
457 * of elements in the cones of the basic sets.
458 * If a_i is the dilation factor of basic set i, then the problem
459 * we need to solve is
472 * the constraints of each (transformed) basic set.
473 * If a = n/d, then the constraint defining the new facet (in the transformed
476 * -n x_1 + d x_2 >= 0
478 * In the original space, we need to take the same combination of the
479 * corresponding constraints "facet" and "ridge".
481 * If a = -infty = "-1/0", then we just return the original facet constraint.
482 * This means that the facet is unbounded, but has a bounded intersection
483 * with the union of sets.
485 static isl_int *wrap_facet(struct isl_ctx *ctx, struct isl_set *set,
486 isl_int *facet, isl_int *ridge)
489 struct isl_mat *T = NULL;
490 struct isl_basic_set *lp = NULL;
492 enum isl_lp_result res;
496 set = isl_set_copy(set);
498 dim = 1 + isl_set_n_dim(set);
499 T = isl_mat_alloc(ctx, 3, dim);
502 isl_int_set_si(T->row[0][0], 1);
503 isl_seq_clr(T->row[0]+1, dim - 1);
504 isl_seq_cpy(T->row[1], facet, dim);
505 isl_seq_cpy(T->row[2], ridge, dim);
506 T = isl_mat_right_inverse(ctx, T);
507 set = isl_set_preimage(ctx, set, T);
511 lp = wrap_constraints(ctx, set);
512 obj = isl_vec_alloc(ctx, dim*set->n);
515 for (i = 0; i < set->n; ++i) {
516 isl_seq_clr(obj->block.data+dim*i, 2);
517 isl_int_set_si(obj->block.data[dim*i+2], 1);
518 isl_seq_clr(obj->block.data+dim*i+3, dim-3);
522 res = isl_solve_lp((struct isl_basic_map *)lp, 0,
523 obj->block.data, ctx->one, &num, &den);
524 if (res == isl_lp_ok) {
525 isl_int_neg(num, num);
526 isl_seq_combine(facet, num, facet, den, ridge, dim);
530 isl_vec_free(ctx, obj);
531 isl_basic_set_free(lp);
533 isl_assert(ctx, res == isl_lp_ok || res == isl_lp_unbounded,
537 isl_basic_set_free(lp);
538 isl_mat_free(ctx, T);
543 /* Given a set of d linearly independent bounding constraints of the
544 * convex hull of "set", compute the constraint of a facet of "set".
546 * We first compute the intersection with the first bounding hyperplane
547 * and remove the component corresponding to this hyperplane from
548 * other bounds (in homogeneous space).
549 * We then wrap around one of the remaining bounding constraints
550 * and continue the process until all bounding constraints have been
551 * taken into account.
552 * The resulting linear combination of the bounding constraints will
553 * correspond to a facet of the convex hull.
555 static struct isl_mat *initial_facet_constraint(struct isl_ctx *ctx,
556 struct isl_set *set, struct isl_mat *bounds)
558 struct isl_set *slice = NULL;
559 struct isl_basic_set *face = NULL;
560 struct isl_mat *m, *U, *Q;
562 unsigned dim = isl_set_n_dim(set);
564 isl_assert(ctx, set->n > 0, goto error);
565 isl_assert(ctx, bounds->n_row == dim, goto error);
567 while (bounds->n_row > 1) {
568 slice = isl_set_copy(set);
569 slice = isl_set_add_equality(ctx, slice, bounds->row[0]);
570 face = isl_set_affine_hull(slice);
573 if (face->n_eq == 1) {
574 isl_basic_set_free(face);
577 m = isl_mat_alloc(ctx, 1 + face->n_eq, 1 + dim);
580 isl_int_set_si(m->row[0][0], 1);
581 isl_seq_clr(m->row[0]+1, dim);
582 for (i = 0; i < face->n_eq; ++i)
583 isl_seq_cpy(m->row[1 + i], face->eq[i], 1 + dim);
584 U = isl_mat_right_inverse(ctx, m);
585 Q = isl_mat_right_inverse(ctx, isl_mat_copy(ctx, U));
586 U = isl_mat_drop_cols(ctx, U, 1 + face->n_eq,
588 Q = isl_mat_drop_rows(ctx, Q, 1 + face->n_eq,
590 U = isl_mat_drop_cols(ctx, U, 0, 1);
591 Q = isl_mat_drop_rows(ctx, Q, 0, 1);
592 bounds = isl_mat_product(ctx, bounds, U);
593 bounds = isl_mat_product(ctx, bounds, Q);
594 while (isl_seq_first_non_zero(bounds->row[bounds->n_row-1],
595 bounds->n_col) == -1) {
597 isl_assert(ctx, bounds->n_row > 1, goto error);
599 if (!wrap_facet(ctx, set, bounds->row[0],
600 bounds->row[bounds->n_row-1]))
602 isl_basic_set_free(face);
607 isl_basic_set_free(face);
608 isl_mat_free(ctx, bounds);
612 /* Given the bounding constraint "c" of a facet of the convex hull of "set",
613 * compute a hyperplane description of the facet, i.e., compute the facets
616 * We compute an affine transformation that transforms the constraint
625 * by computing the right inverse U of a matrix that starts with the rows
638 * Since z_1 is zero, we can drop this variable as well as the corresponding
639 * column of U to obtain
647 * with Q' equal to Q, but without the corresponding row.
648 * After computing the facets of the facet in the z' space,
649 * we convert them back to the x space through Q.
651 static struct isl_basic_set *compute_facet(struct isl_ctx *ctx,
652 struct isl_set *set, isl_int *c)
654 struct isl_mat *m, *U, *Q;
655 struct isl_basic_set *facet;
658 set = isl_set_copy(set);
659 dim = isl_set_n_dim(set);
660 m = isl_mat_alloc(ctx, 2, 1 + dim);
663 isl_int_set_si(m->row[0][0], 1);
664 isl_seq_clr(m->row[0]+1, dim);
665 isl_seq_cpy(m->row[1], c, 1+dim);
666 U = isl_mat_right_inverse(ctx, m);
667 Q = isl_mat_right_inverse(ctx, isl_mat_copy(ctx, U));
668 U = isl_mat_drop_cols(ctx, U, 1, 1);
669 Q = isl_mat_drop_rows(ctx, Q, 1, 1);
670 set = isl_set_preimage(ctx, set, U);
671 facet = uset_convex_hull_wrap(set);
672 facet = isl_basic_set_preimage(ctx, facet, Q);
679 /* Given an initial facet constraint, compute the remaining facets.
680 * We do this by running through all facets found so far and computing
681 * the adjacent facets through wrapping, adding those facets that we
682 * hadn't already found before.
684 * This function can still be significantly optimized by checking which of
685 * the facets of the basic sets are also facets of the convex hull and
686 * using all the facets so far to help in constructing the facets of the
689 * using the technique in section "3.1 Ridge Generation" of
690 * "Extended Convex Hull" by Fukuda et al.
692 static struct isl_basic_set *extend(struct isl_ctx *ctx, struct isl_set *set,
693 struct isl_mat *initial)
697 struct isl_basic_set *hull = NULL;
698 struct isl_basic_set *facet = NULL;
703 isl_assert(ctx, set->n > 0, goto error);
706 for (i = 0; i < set->n; ++i) {
707 n_ineq += set->p[i]->n_eq;
708 n_ineq += set->p[i]->n_ineq;
710 dim = isl_set_n_dim(set);
711 isl_assert(ctx, 1 + dim == initial->n_col, goto error);
712 hull = isl_basic_set_alloc(ctx, 0, dim, 0, 0, n_ineq);
713 hull = isl_basic_set_set_rational(hull);
716 k = isl_basic_set_alloc_inequality(hull);
719 isl_seq_cpy(hull->ineq[k], initial->row[0], initial->n_col);
720 for (i = 0; i < hull->n_ineq; ++i) {
721 facet = compute_facet(ctx, set, hull->ineq[i]);
724 if (facet->n_ineq + hull->n_ineq > n_ineq) {
725 hull = isl_basic_set_extend(hull,
726 0, dim, 0, 0, facet->n_ineq);
727 n_ineq = hull->n_ineq + facet->n_ineq;
729 for (j = 0; j < facet->n_ineq; ++j) {
730 k = isl_basic_set_alloc_inequality(hull);
733 isl_seq_cpy(hull->ineq[k], hull->ineq[i], 1+dim);
734 if (!wrap_facet(ctx, set, hull->ineq[k], facet->ineq[j]))
736 for (f = 0; f < k; ++f)
737 if (isl_seq_eq(hull->ineq[f], hull->ineq[k],
741 isl_basic_set_free_inequality(hull, 1);
743 isl_basic_set_free(facet);
745 hull = isl_basic_set_simplify(hull);
746 hull = isl_basic_set_finalize(hull);
749 isl_basic_set_free(facet);
750 isl_basic_set_free(hull);
754 /* Special case for computing the convex hull of a one dimensional set.
755 * We simply collect the lower and upper bounds of each basic set
756 * and the biggest of those.
758 static struct isl_basic_set *convex_hull_1d(struct isl_ctx *ctx,
761 struct isl_mat *c = NULL;
762 isl_int *lower = NULL;
763 isl_int *upper = NULL;
766 struct isl_basic_set *hull;
768 for (i = 0; i < set->n; ++i) {
769 set->p[i] = isl_basic_set_simplify(set->p[i]);
773 set = isl_set_remove_empty_parts(set);
776 isl_assert(ctx, set->n > 0, goto error);
777 c = isl_mat_alloc(ctx, 2, 2);
781 if (set->p[0]->n_eq > 0) {
782 isl_assert(ctx, set->p[0]->n_eq == 1, goto error);
785 if (isl_int_is_pos(set->p[0]->eq[0][1])) {
786 isl_seq_cpy(lower, set->p[0]->eq[0], 2);
787 isl_seq_neg(upper, set->p[0]->eq[0], 2);
789 isl_seq_neg(lower, set->p[0]->eq[0], 2);
790 isl_seq_cpy(upper, set->p[0]->eq[0], 2);
793 for (j = 0; j < set->p[0]->n_ineq; ++j) {
794 if (isl_int_is_pos(set->p[0]->ineq[j][1])) {
796 isl_seq_cpy(lower, set->p[0]->ineq[j], 2);
799 isl_seq_cpy(upper, set->p[0]->ineq[j], 2);
806 for (i = 0; i < set->n; ++i) {
807 struct isl_basic_set *bset = set->p[i];
811 for (j = 0; j < bset->n_eq; ++j) {
815 isl_int_mul(a, lower[0], bset->eq[j][1]);
816 isl_int_mul(b, lower[1], bset->eq[j][0]);
817 if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
818 isl_seq_cpy(lower, bset->eq[j], 2);
819 if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
820 isl_seq_neg(lower, bset->eq[j], 2);
823 isl_int_mul(a, upper[0], bset->eq[j][1]);
824 isl_int_mul(b, upper[1], bset->eq[j][0]);
825 if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
826 isl_seq_neg(upper, bset->eq[j], 2);
827 if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
828 isl_seq_cpy(upper, bset->eq[j], 2);
831 for (j = 0; j < bset->n_ineq; ++j) {
832 if (isl_int_is_pos(bset->ineq[j][1]))
834 if (isl_int_is_neg(bset->ineq[j][1]))
836 if (lower && isl_int_is_pos(bset->ineq[j][1])) {
837 isl_int_mul(a, lower[0], bset->ineq[j][1]);
838 isl_int_mul(b, lower[1], bset->ineq[j][0]);
839 if (isl_int_lt(a, b))
840 isl_seq_cpy(lower, bset->ineq[j], 2);
842 if (upper && isl_int_is_neg(bset->ineq[j][1])) {
843 isl_int_mul(a, upper[0], bset->ineq[j][1]);
844 isl_int_mul(b, upper[1], bset->ineq[j][0]);
845 if (isl_int_gt(a, b))
846 isl_seq_cpy(upper, bset->ineq[j], 2);
857 hull = isl_basic_set_alloc(ctx, 0, 1, 0, 0, 2);
858 hull = isl_basic_set_set_rational(hull);
862 k = isl_basic_set_alloc_inequality(hull);
863 isl_seq_cpy(hull->ineq[k], lower, 2);
866 k = isl_basic_set_alloc_inequality(hull);
867 isl_seq_cpy(hull->ineq[k], upper, 2);
869 hull = isl_basic_set_finalize(hull);
871 isl_mat_free(ctx, c);
875 isl_mat_free(ctx, c);
879 /* Project out final n dimensions using Fourier-Motzkin */
880 static struct isl_set *set_project_out(struct isl_ctx *ctx,
881 struct isl_set *set, unsigned n)
883 return isl_set_remove_dims(set, isl_set_n_dim(set) - n, n);
886 static struct isl_basic_set *convex_hull_0d(struct isl_set *set)
888 struct isl_basic_set *convex_hull;
893 if (isl_set_is_empty(set))
894 convex_hull = isl_basic_set_empty(isl_dim_copy(set->dim));
896 convex_hull = isl_basic_set_universe(isl_dim_copy(set->dim));
901 /* Compute the convex hull of a pair of basic sets without any parameters or
902 * integer divisions using Fourier-Motzkin elimination.
903 * The convex hull is the set of all points that can be written as
904 * the sum of points from both basic sets (in homogeneous coordinates).
905 * We set up the constraints in a space with dimensions for each of
906 * the three sets and then project out the dimensions corresponding
907 * to the two original basic sets, retaining only those corresponding
908 * to the convex hull.
910 static struct isl_basic_set *convex_hull_pair(struct isl_basic_set *bset1,
911 struct isl_basic_set *bset2)
914 struct isl_basic_set *bset[2];
915 struct isl_basic_set *hull = NULL;
918 if (!bset1 || !bset2)
921 dim = isl_basic_set_n_dim(bset1);
922 hull = isl_basic_set_alloc(bset1->ctx, 0, 2 + 3 * dim, 0,
923 1 + dim + bset1->n_eq + bset2->n_eq,
924 2 + bset1->n_ineq + bset2->n_ineq);
927 for (i = 0; i < 2; ++i) {
928 for (j = 0; j < bset[i]->n_eq; ++j) {
929 k = isl_basic_set_alloc_equality(hull);
932 isl_seq_clr(hull->eq[k], (i+1) * (1+dim));
933 isl_seq_clr(hull->eq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
934 isl_seq_cpy(hull->eq[k]+(i+1)*(1+dim), bset[i]->eq[j],
937 for (j = 0; j < bset[i]->n_ineq; ++j) {
938 k = isl_basic_set_alloc_inequality(hull);
941 isl_seq_clr(hull->ineq[k], (i+1) * (1+dim));
942 isl_seq_clr(hull->ineq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
943 isl_seq_cpy(hull->ineq[k]+(i+1)*(1+dim),
944 bset[i]->ineq[j], 1+dim);
946 k = isl_basic_set_alloc_inequality(hull);
949 isl_seq_clr(hull->ineq[k], 1+2+3*dim);
950 isl_int_set_si(hull->ineq[k][(i+1)*(1+dim)], 1);
952 for (j = 0; j < 1+dim; ++j) {
953 k = isl_basic_set_alloc_equality(hull);
956 isl_seq_clr(hull->eq[k], 1+2+3*dim);
957 isl_int_set_si(hull->eq[k][j], -1);
958 isl_int_set_si(hull->eq[k][1+dim+j], 1);
959 isl_int_set_si(hull->eq[k][2*(1+dim)+j], 1);
961 hull = isl_basic_set_set_rational(hull);
962 hull = isl_basic_set_remove_dims(hull, dim, 2*(1+dim));
963 hull = isl_basic_set_convex_hull(hull);
964 isl_basic_set_free(bset1);
965 isl_basic_set_free(bset2);
968 isl_basic_set_free(bset1);
969 isl_basic_set_free(bset2);
970 isl_basic_set_free(hull);
974 /* Compute the convex hull of a set without any parameters or
975 * integer divisions using Fourier-Motzkin elimination.
976 * In each step, we combined two basic sets until only one
979 static struct isl_basic_set *uset_convex_hull_elim(struct isl_set *set)
981 struct isl_basic_set *convex_hull = NULL;
983 convex_hull = isl_set_copy_basic_set(set);
984 set = isl_set_drop_basic_set(set, convex_hull);
988 struct isl_basic_set *t;
989 t = isl_set_copy_basic_set(set);
992 set = isl_set_drop_basic_set(set, t);
995 convex_hull = convex_hull_pair(convex_hull, t);
1001 isl_basic_set_free(convex_hull);
1005 static struct isl_basic_set *uset_convex_hull_wrap_with_bounds(
1006 struct isl_set *set, struct isl_mat *bounds)
1008 struct isl_basic_set *convex_hull = NULL;
1010 isl_assert(set->ctx, bounds->n_row == isl_set_n_dim(set), goto error);
1011 bounds = initial_facet_constraint(set->ctx, set, bounds);
1014 convex_hull = extend(set->ctx, set, bounds);
1015 isl_mat_free(set->ctx, bounds);
1024 /* Compute the convex hull of a set without any parameters or
1025 * integer divisions. Depending on whether the set is bounded,
1026 * we pass control to the wrapping based convex hull or
1027 * the Fourier-Motzkin elimination based convex hull.
1028 * We also handle a few special cases before checking the boundedness.
1030 static struct isl_basic_set *uset_convex_hull(struct isl_set *set)
1033 struct isl_basic_set *convex_hull = NULL;
1034 struct isl_mat *bounds;
1036 if (isl_set_n_dim(set) == 0)
1037 return convex_hull_0d(set);
1039 set = isl_set_set_rational(set);
1043 for (i = 0; i < set->n; ++i) {
1044 set->p[i] = isl_basic_set_convex_hull(set->p[i]);
1048 set = isl_set_remove_empty_parts(set);
1052 convex_hull = isl_basic_set_copy(set->p[0]);
1056 if (isl_set_n_dim(set) == 1)
1057 return convex_hull_1d(set->ctx, set);
1059 bounds = independent_bounds(set->ctx, set);
1062 if (bounds->n_row == isl_set_n_dim(set))
1063 return uset_convex_hull_wrap_with_bounds(set, bounds);
1064 isl_mat_free(set->ctx, bounds);
1066 return uset_convex_hull_elim(set);
1069 isl_basic_set_free(convex_hull);
1073 /* This is the core procedure, where "set" is a "pure" set, i.e.,
1074 * without parameters or divs and where the convex hull of set is
1075 * known to be full-dimensional.
1077 static struct isl_basic_set *uset_convex_hull_wrap(struct isl_set *set)
1080 struct isl_basic_set *convex_hull = NULL;
1081 struct isl_mat *bounds;
1083 if (isl_set_n_dim(set) == 0) {
1084 convex_hull = isl_basic_set_universe(isl_dim_copy(set->dim));
1086 convex_hull = isl_basic_set_set_rational(convex_hull);
1090 set = isl_set_set_rational(set);
1094 for (i = 0; i < set->n; ++i) {
1095 set->p[i] = isl_basic_set_convex_hull(set->p[i]);
1099 set = isl_set_remove_empty_parts(set);
1103 convex_hull = isl_basic_set_copy(set->p[0]);
1107 if (isl_set_n_dim(set) == 1)
1108 return convex_hull_1d(set->ctx, set);
1110 bounds = independent_bounds(set->ctx, set);
1113 return uset_convex_hull_wrap_with_bounds(set, bounds);
1119 /* Compute the convex hull of set "set" with affine hull "affine_hull",
1120 * We first remove the equalities (transforming the set), compute the
1121 * convex hull of the transformed set and then add the equalities back
1122 * (after performing the inverse transformation.
1124 static struct isl_basic_set *modulo_affine_hull(struct isl_ctx *ctx,
1125 struct isl_set *set, struct isl_basic_set *affine_hull)
1129 struct isl_basic_set *dummy;
1130 struct isl_basic_set *convex_hull;
1132 dummy = isl_basic_set_remove_equalities(
1133 isl_basic_set_copy(affine_hull), &T, &T2);
1136 isl_basic_set_free(dummy);
1137 set = isl_set_preimage(ctx, set, T);
1138 convex_hull = uset_convex_hull(set);
1139 convex_hull = isl_basic_set_preimage(ctx, convex_hull, T2);
1140 convex_hull = isl_basic_set_intersect(convex_hull, affine_hull);
1143 isl_basic_set_free(affine_hull);
1148 /* Compute the convex hull of a map.
1150 * The implementation was inspired by "Extended Convex Hull" by Fukuda et al.,
1151 * specifically, the wrapping of facets to obtain new facets.
1153 struct isl_basic_map *isl_map_convex_hull(struct isl_map *map)
1155 struct isl_basic_set *bset;
1156 struct isl_basic_map *model = NULL;
1157 struct isl_basic_set *affine_hull = NULL;
1158 struct isl_basic_map *convex_hull = NULL;
1159 struct isl_set *set = NULL;
1160 struct isl_ctx *ctx;
1167 convex_hull = isl_basic_map_empty_like_map(map);
1172 map = isl_map_align_divs(map);
1173 model = isl_basic_map_copy(map->p[0]);
1174 set = isl_map_underlying_set(map);
1178 affine_hull = isl_set_affine_hull(isl_set_copy(set));
1181 if (affine_hull->n_eq != 0)
1182 bset = modulo_affine_hull(ctx, set, affine_hull);
1184 isl_basic_set_free(affine_hull);
1185 bset = uset_convex_hull(set);
1188 convex_hull = isl_basic_map_overlying_set(bset, model);
1190 F_CLR(convex_hull, ISL_BASIC_MAP_RATIONAL);
1194 isl_basic_map_free(model);
1198 struct isl_basic_set *isl_set_convex_hull(struct isl_set *set)
1200 return (struct isl_basic_set *)
1201 isl_map_convex_hull((struct isl_map *)set);
1204 /* Compute a superset of the convex hull of map that is described
1205 * by only translates of the constraints in the constituents of map.
1207 * The implementation is not very efficient. In particular, if
1208 * constraints with the same normal appear in more than one
1209 * basic map, they will be (re)examined each time.
1211 struct isl_basic_map *isl_map_simple_hull(struct isl_map *map)
1213 struct isl_set *set = NULL;
1214 struct isl_basic_map *model = NULL;
1215 struct isl_basic_map *hull;
1216 struct isl_basic_set *bset = NULL;
1224 hull = isl_basic_map_empty_like_map(map);
1229 hull = isl_basic_map_copy(map->p[0]);
1234 map = isl_map_align_divs(map);
1235 model = isl_basic_map_copy(map->p[0]);
1238 for (i = 0; i < map->n; ++i) {
1241 n_ineq += map->p[i]->n_ineq;
1244 set = isl_map_underlying_set(map);
1248 bset = isl_set_affine_hull(isl_set_copy(set));
1251 dim = isl_basic_set_n_dim(bset);
1252 bset = isl_basic_set_extend(bset, 0, dim, 0, 0, n_ineq);
1256 for (i = 0; i < set->n; ++i) {
1257 for (j = 0; j < set->p[i]->n_ineq; ++j) {
1261 k = isl_basic_set_alloc_inequality(bset);
1264 isl_seq_cpy(bset->ineq[k], set->p[i]->ineq[j], 1 + dim);
1265 is_bound = uset_is_bound(set->ctx, set, bset->ineq[k],
1270 isl_basic_set_free_inequality(bset, 1);
1274 bset = isl_basic_set_simplify(bset);
1275 bset = isl_basic_set_finalize(bset);
1276 bset = isl_basic_set_convex_hull(bset);
1278 hull = isl_basic_map_overlying_set(bset, isl_basic_map_copy(model));
1283 isl_basic_set_free(bset);
1285 isl_basic_map_free(model);
1289 struct isl_basic_set *isl_set_simple_hull(struct isl_set *set)
1291 return (struct isl_basic_set *)
1292 isl_map_simple_hull((struct isl_map *)set);