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
, 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
);