• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2014      INRIA Rocquencourt
4  *
5  * Use of this software is governed by the MIT license
6  *
7  * Written by Sven Verdoolaege, K.U.Leuven, Departement
8  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
10  * B.P. 105 - 78153 Le Chesnay, France
11  */
12 
13 #include <isl_ctx_private.h>
14 #include <isl_map_private.h>
15 #include <isl_lp_private.h>
16 #include <isl/map.h>
17 #include <isl_mat_private.h>
18 #include <isl_vec_private.h>
19 #include <isl/set.h>
20 #include <isl_seq.h>
21 #include <isl_options_private.h>
22 #include "isl_equalities.h"
23 #include "isl_tab.h"
24 #include <isl_sort.h>
25 
26 #include <bset_to_bmap.c>
27 #include <bset_from_bmap.c>
28 #include <set_to_map.c>
29 
30 static __isl_give isl_basic_set *uset_convex_hull_wrap_bounded(
31 	__isl_take isl_set *set);
32 
33 /* Remove redundant
34  * constraints.  If the minimal value along the normal of a constraint
35  * is the same if the constraint is removed, then the constraint is redundant.
36  *
37  * Since some constraints may be mutually redundant, sort the constraints
38  * first such that constraints that involve existentially quantified
39  * variables are considered for removal before those that do not.
40  * The sorting is also needed for the use in map_simple_hull.
41  *
42  * Note that isl_tab_detect_implicit_equalities may also end up
43  * marking some constraints as redundant.  Make sure the constraints
44  * are preserved and undo those marking such that isl_tab_detect_redundant
45  * can consider the constraints in the sorted order.
46  *
47  * Alternatively, we could have intersected the basic map with the
48  * corresponding equality and then checked if the dimension was that
49  * of a facet.
50  */
isl_basic_map_remove_redundancies(__isl_take isl_basic_map * bmap)51 __isl_give isl_basic_map *isl_basic_map_remove_redundancies(
52 	__isl_take isl_basic_map *bmap)
53 {
54 	struct isl_tab *tab;
55 
56 	if (!bmap)
57 		return NULL;
58 
59 	bmap = isl_basic_map_gauss(bmap, NULL);
60 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
61 		return bmap;
62 	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NO_REDUNDANT))
63 		return bmap;
64 	if (bmap->n_ineq <= 1)
65 		return bmap;
66 
67 	bmap = isl_basic_map_sort_constraints(bmap);
68 	tab = isl_tab_from_basic_map(bmap, 0);
69 	if (!tab)
70 		goto error;
71 	tab->preserve = 1;
72 	if (isl_tab_detect_implicit_equalities(tab) < 0)
73 		goto error;
74 	if (isl_tab_restore_redundant(tab) < 0)
75 		goto error;
76 	tab->preserve = 0;
77 	if (isl_tab_detect_redundant(tab) < 0)
78 		goto error;
79 	bmap = isl_basic_map_update_from_tab(bmap, tab);
80 	isl_tab_free(tab);
81 	if (!bmap)
82 		return NULL;
83 	ISL_F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
84 	ISL_F_SET(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
85 	return bmap;
86 error:
87 	isl_tab_free(tab);
88 	isl_basic_map_free(bmap);
89 	return NULL;
90 }
91 
isl_basic_set_remove_redundancies(__isl_take isl_basic_set * bset)92 __isl_give isl_basic_set *isl_basic_set_remove_redundancies(
93 	__isl_take isl_basic_set *bset)
94 {
95 	return bset_from_bmap(
96 		isl_basic_map_remove_redundancies(bset_to_bmap(bset)));
97 }
98 
99 /* Remove redundant constraints in each of the basic maps.
100  */
isl_map_remove_redundancies(__isl_take isl_map * map)101 __isl_give isl_map *isl_map_remove_redundancies(__isl_take isl_map *map)
102 {
103 	return isl_map_inline_foreach_basic_map(map,
104 					    &isl_basic_map_remove_redundancies);
105 }
106 
isl_set_remove_redundancies(__isl_take isl_set * set)107 __isl_give isl_set *isl_set_remove_redundancies(__isl_take isl_set *set)
108 {
109 	return isl_map_remove_redundancies(set);
110 }
111 
112 /* Check if the set set is bound in the direction of the affine
113  * constraint c and if so, set the constant term such that the
114  * resulting constraint is a bounding constraint for the set.
115  */
uset_is_bound(__isl_keep isl_set * set,isl_int * c,unsigned len)116 static isl_bool uset_is_bound(__isl_keep isl_set *set, isl_int *c, unsigned len)
117 {
118 	int first;
119 	int j;
120 	isl_int opt;
121 	isl_int opt_denom;
122 
123 	isl_int_init(opt);
124 	isl_int_init(opt_denom);
125 	first = 1;
126 	for (j = 0; j < set->n; ++j) {
127 		enum isl_lp_result res;
128 
129 		if (ISL_F_ISSET(set->p[j], ISL_BASIC_SET_EMPTY))
130 			continue;
131 
132 		res = isl_basic_set_solve_lp(set->p[j],
133 				0, c, set->ctx->one, &opt, &opt_denom, NULL);
134 		if (res == isl_lp_unbounded)
135 			break;
136 		if (res == isl_lp_error)
137 			goto error;
138 		if (res == isl_lp_empty) {
139 			set->p[j] = isl_basic_set_set_to_empty(set->p[j]);
140 			if (!set->p[j])
141 				goto error;
142 			continue;
143 		}
144 		if (first || isl_int_is_neg(opt)) {
145 			if (!isl_int_is_one(opt_denom))
146 				isl_seq_scale(c, c, opt_denom, len);
147 			isl_int_sub(c[0], c[0], opt);
148 		}
149 		first = 0;
150 	}
151 	isl_int_clear(opt);
152 	isl_int_clear(opt_denom);
153 	return isl_bool_ok(j >= set->n);
154 error:
155 	isl_int_clear(opt);
156 	isl_int_clear(opt_denom);
157 	return isl_bool_error;
158 }
159 
isl_set_add_basic_set_equality(__isl_take isl_set * set,isl_int * c)160 static __isl_give isl_set *isl_set_add_basic_set_equality(
161 	__isl_take isl_set *set, isl_int *c)
162 {
163 	int i;
164 
165 	set = isl_set_cow(set);
166 	if (!set)
167 		return NULL;
168 	for (i = 0; i < set->n; ++i) {
169 		set->p[i] = isl_basic_set_add_eq(set->p[i], c);
170 		if (!set->p[i])
171 			goto error;
172 	}
173 	return set;
174 error:
175 	isl_set_free(set);
176 	return NULL;
177 }
178 
179 /* Given a union of basic sets, construct the constraints for wrapping
180  * a facet around one of its ridges.
181  * In particular, if each of n the d-dimensional basic sets i in "set"
182  * contains the origin, satisfies the constraints x_1 >= 0 and x_2 >= 0
183  * and is defined by the constraints
184  *				    [ 1 ]
185  *				A_i [ x ]  >= 0
186  *
187  * then the resulting set is of dimension n*(1+d) and has as constraints
188  *
189  *				    [ a_i ]
190  *				A_i [ x_i ] >= 0
191  *
192  *				      a_i   >= 0
193  *
194  *			\sum_i x_{i,1} = 1
195  */
wrap_constraints(__isl_keep isl_set * set)196 static __isl_give isl_basic_set *wrap_constraints(__isl_keep isl_set *set)
197 {
198 	struct isl_basic_set *lp;
199 	unsigned n_eq;
200 	unsigned n_ineq;
201 	int i, j, k;
202 	isl_size dim, lp_dim;
203 
204 	dim = isl_set_dim(set, isl_dim_set);
205 	if (dim < 0)
206 		return NULL;
207 
208 	dim += 1;
209 	n_eq = 1;
210 	n_ineq = set->n;
211 	for (i = 0; i < set->n; ++i) {
212 		n_eq += set->p[i]->n_eq;
213 		n_ineq += set->p[i]->n_ineq;
214 	}
215 	lp = isl_basic_set_alloc(set->ctx, 0, dim * set->n, 0, n_eq, n_ineq);
216 	lp = isl_basic_set_set_rational(lp);
217 	if (!lp)
218 		return NULL;
219 	lp_dim = isl_basic_set_dim(lp, isl_dim_set);
220 	if (lp_dim < 0)
221 		return isl_basic_set_free(lp);
222 	k = isl_basic_set_alloc_equality(lp);
223 	isl_int_set_si(lp->eq[k][0], -1);
224 	for (i = 0; i < set->n; ++i) {
225 		isl_int_set_si(lp->eq[k][1+dim*i], 0);
226 		isl_int_set_si(lp->eq[k][1+dim*i+1], 1);
227 		isl_seq_clr(lp->eq[k]+1+dim*i+2, dim-2);
228 	}
229 	for (i = 0; i < set->n; ++i) {
230 		k = isl_basic_set_alloc_inequality(lp);
231 		isl_seq_clr(lp->ineq[k], 1+lp_dim);
232 		isl_int_set_si(lp->ineq[k][1+dim*i], 1);
233 
234 		for (j = 0; j < set->p[i]->n_eq; ++j) {
235 			k = isl_basic_set_alloc_equality(lp);
236 			isl_seq_clr(lp->eq[k], 1+dim*i);
237 			isl_seq_cpy(lp->eq[k]+1+dim*i, set->p[i]->eq[j], dim);
238 			isl_seq_clr(lp->eq[k]+1+dim*(i+1), dim*(set->n-i-1));
239 		}
240 
241 		for (j = 0; j < set->p[i]->n_ineq; ++j) {
242 			k = isl_basic_set_alloc_inequality(lp);
243 			isl_seq_clr(lp->ineq[k], 1+dim*i);
244 			isl_seq_cpy(lp->ineq[k]+1+dim*i, set->p[i]->ineq[j], dim);
245 			isl_seq_clr(lp->ineq[k]+1+dim*(i+1), dim*(set->n-i-1));
246 		}
247 	}
248 	return lp;
249 }
250 
251 /* Given a facet "facet" of the convex hull of "set" and a facet "ridge"
252  * of that facet, compute the other facet of the convex hull that contains
253  * the ridge.
254  *
255  * We first transform the set such that the facet constraint becomes
256  *
257  *			x_1 >= 0
258  *
259  * I.e., the facet lies in
260  *
261  *			x_1 = 0
262  *
263  * and on that facet, the constraint that defines the ridge is
264  *
265  *			x_2 >= 0
266  *
267  * (This transformation is not strictly needed, all that is needed is
268  * that the ridge contains the origin.)
269  *
270  * Since the ridge contains the origin, the cone of the convex hull
271  * will be of the form
272  *
273  *			x_1 >= 0
274  *			x_2 >= a x_1
275  *
276  * with this second constraint defining the new facet.
277  * The constant a is obtained by settting x_1 in the cone of the
278  * convex hull to 1 and minimizing x_2.
279  * Now, each element in the cone of the convex hull is the sum
280  * of elements in the cones of the basic sets.
281  * If a_i is the dilation factor of basic set i, then the problem
282  * we need to solve is
283  *
284  *			min \sum_i x_{i,2}
285  *			st
286  *				\sum_i x_{i,1} = 1
287  *				    a_i   >= 0
288  *				  [ a_i ]
289  *				A [ x_i ] >= 0
290  *
291  * with
292  *				    [  1  ]
293  *				A_i [ x_i ] >= 0
294  *
295  * the constraints of each (transformed) basic set.
296  * If a = n/d, then the constraint defining the new facet (in the transformed
297  * space) is
298  *
299  *			-n x_1 + d x_2 >= 0
300  *
301  * In the original space, we need to take the same combination of the
302  * corresponding constraints "facet" and "ridge".
303  *
304  * If a = -infty = "-1/0", then we just return the original facet constraint.
305  * This means that the facet is unbounded, but has a bounded intersection
306  * with the union of sets.
307  */
isl_set_wrap_facet(__isl_keep isl_set * set,isl_int * facet,isl_int * ridge)308 isl_int *isl_set_wrap_facet(__isl_keep isl_set *set,
309 	isl_int *facet, isl_int *ridge)
310 {
311 	int i;
312 	isl_ctx *ctx;
313 	struct isl_mat *T = NULL;
314 	struct isl_basic_set *lp = NULL;
315 	struct isl_vec *obj;
316 	enum isl_lp_result res;
317 	isl_int num, den;
318 	isl_size dim;
319 
320 	dim = isl_set_dim(set, isl_dim_set);
321 	if (dim < 0)
322 		return NULL;
323 	ctx = set->ctx;
324 	set = isl_set_copy(set);
325 	set = isl_set_set_rational(set);
326 
327 	dim += 1;
328 	T = isl_mat_alloc(ctx, 3, dim);
329 	if (!T)
330 		goto error;
331 	isl_int_set_si(T->row[0][0], 1);
332 	isl_seq_clr(T->row[0]+1, dim - 1);
333 	isl_seq_cpy(T->row[1], facet, dim);
334 	isl_seq_cpy(T->row[2], ridge, dim);
335 	T = isl_mat_right_inverse(T);
336 	set = isl_set_preimage(set, T);
337 	T = NULL;
338 	if (!set)
339 		goto error;
340 	lp = wrap_constraints(set);
341 	obj = isl_vec_alloc(ctx, 1 + dim*set->n);
342 	if (!obj)
343 		goto error;
344 	isl_int_set_si(obj->block.data[0], 0);
345 	for (i = 0; i < set->n; ++i) {
346 		isl_seq_clr(obj->block.data + 1 + dim*i, 2);
347 		isl_int_set_si(obj->block.data[1 + dim*i+2], 1);
348 		isl_seq_clr(obj->block.data + 1 + dim*i+3, dim-3);
349 	}
350 	isl_int_init(num);
351 	isl_int_init(den);
352 	res = isl_basic_set_solve_lp(lp, 0,
353 			    obj->block.data, ctx->one, &num, &den, NULL);
354 	if (res == isl_lp_ok) {
355 		isl_int_neg(num, num);
356 		isl_seq_combine(facet, num, facet, den, ridge, dim);
357 		isl_seq_normalize(ctx, facet, dim);
358 	}
359 	isl_int_clear(num);
360 	isl_int_clear(den);
361 	isl_vec_free(obj);
362 	isl_basic_set_free(lp);
363 	isl_set_free(set);
364 	if (res == isl_lp_error)
365 		return NULL;
366 	isl_assert(ctx, res == isl_lp_ok || res == isl_lp_unbounded,
367 		   return NULL);
368 	return facet;
369 error:
370 	isl_basic_set_free(lp);
371 	isl_mat_free(T);
372 	isl_set_free(set);
373 	return NULL;
374 }
375 
376 /* Compute the constraint of a facet of "set".
377  *
378  * We first compute the intersection with a bounding constraint
379  * that is orthogonal to one of the coordinate axes.
380  * If the affine hull of this intersection has only one equality,
381  * we have found a facet.
382  * Otherwise, we wrap the current bounding constraint around
383  * one of the equalities of the face (one that is not equal to
384  * the current bounding constraint).
385  * This process continues until we have found a facet.
386  * The dimension of the intersection increases by at least
387  * one on each iteration, so termination is guaranteed.
388  */
initial_facet_constraint(__isl_keep isl_set * set)389 static __isl_give isl_mat *initial_facet_constraint(__isl_keep isl_set *set)
390 {
391 	struct isl_set *slice = NULL;
392 	struct isl_basic_set *face = NULL;
393 	int i;
394 	isl_size dim = isl_set_dim(set, isl_dim_set);
395 	isl_bool is_bound;
396 	isl_mat *bounds = NULL;
397 
398 	if (dim < 0)
399 		return NULL;
400 	isl_assert(set->ctx, set->n > 0, goto error);
401 	bounds = isl_mat_alloc(set->ctx, 1, 1 + dim);
402 	if (!bounds)
403 		return NULL;
404 
405 	isl_seq_clr(bounds->row[0], dim);
406 	isl_int_set_si(bounds->row[0][1 + dim - 1], 1);
407 	is_bound = uset_is_bound(set, bounds->row[0], 1 + dim);
408 	if (is_bound < 0)
409 		goto error;
410 	isl_assert(set->ctx, is_bound, goto error);
411 	isl_seq_normalize(set->ctx, bounds->row[0], 1 + dim);
412 	bounds->n_row = 1;
413 
414 	for (;;) {
415 		slice = isl_set_copy(set);
416 		slice = isl_set_add_basic_set_equality(slice, bounds->row[0]);
417 		face = isl_set_affine_hull(slice);
418 		if (!face)
419 			goto error;
420 		if (face->n_eq == 1) {
421 			isl_basic_set_free(face);
422 			break;
423 		}
424 		for (i = 0; i < face->n_eq; ++i)
425 			if (!isl_seq_eq(bounds->row[0], face->eq[i], 1 + dim) &&
426 			    !isl_seq_is_neg(bounds->row[0],
427 						face->eq[i], 1 + dim))
428 				break;
429 		isl_assert(set->ctx, i < face->n_eq, goto error);
430 		if (!isl_set_wrap_facet(set, bounds->row[0], face->eq[i]))
431 			goto error;
432 		isl_seq_normalize(set->ctx, bounds->row[0], bounds->n_col);
433 		isl_basic_set_free(face);
434 	}
435 
436 	return bounds;
437 error:
438 	isl_basic_set_free(face);
439 	isl_mat_free(bounds);
440 	return NULL;
441 }
442 
443 /* Given the bounding constraint "c" of a facet of the convex hull of "set",
444  * compute a hyperplane description of the facet, i.e., compute the facets
445  * of the facet.
446  *
447  * We compute an affine transformation that transforms the constraint
448  *
449  *			  [ 1 ]
450  *			c [ x ] = 0
451  *
452  * to the constraint
453  *
454  *			   z_1  = 0
455  *
456  * by computing the right inverse U of a matrix that starts with the rows
457  *
458  *			[ 1 0 ]
459  *			[  c  ]
460  *
461  * Then
462  *			[ 1 ]     [ 1 ]
463  *			[ x ] = U [ z ]
464  * and
465  *			[ 1 ]     [ 1 ]
466  *			[ z ] = Q [ x ]
467  *
468  * with Q = U^{-1}
469  * Since z_1 is zero, we can drop this variable as well as the corresponding
470  * column of U to obtain
471  *
472  *			[ 1 ]      [ 1  ]
473  *			[ x ] = U' [ z' ]
474  * and
475  *			[ 1  ]      [ 1 ]
476  *			[ z' ] = Q' [ x ]
477  *
478  * with Q' equal to Q, but without the corresponding row.
479  * After computing the facets of the facet in the z' space,
480  * we convert them back to the x space through Q.
481  */
compute_facet(__isl_keep isl_set * set,isl_int * c)482 static __isl_give isl_basic_set *compute_facet(__isl_keep isl_set *set,
483 	isl_int *c)
484 {
485 	struct isl_mat *m, *U, *Q;
486 	struct isl_basic_set *facet = NULL;
487 	struct isl_ctx *ctx;
488 	isl_size dim;
489 
490 	dim = isl_set_dim(set, isl_dim_set);
491 	if (dim < 0)
492 		return NULL;
493 	ctx = set->ctx;
494 	set = isl_set_copy(set);
495 	m = isl_mat_alloc(set->ctx, 2, 1 + dim);
496 	if (!m)
497 		goto error;
498 	isl_int_set_si(m->row[0][0], 1);
499 	isl_seq_clr(m->row[0]+1, dim);
500 	isl_seq_cpy(m->row[1], c, 1+dim);
501 	U = isl_mat_right_inverse(m);
502 	Q = isl_mat_right_inverse(isl_mat_copy(U));
503 	U = isl_mat_drop_cols(U, 1, 1);
504 	Q = isl_mat_drop_rows(Q, 1, 1);
505 	set = isl_set_preimage(set, U);
506 	facet = uset_convex_hull_wrap_bounded(set);
507 	facet = isl_basic_set_preimage(facet, Q);
508 	if (facet && facet->n_eq != 0)
509 		isl_die(ctx, isl_error_internal, "unexpected equality",
510 			return isl_basic_set_free(facet));
511 	return facet;
512 error:
513 	isl_basic_set_free(facet);
514 	isl_set_free(set);
515 	return NULL;
516 }
517 
518 /* Given an initial facet constraint, compute the remaining facets.
519  * We do this by running through all facets found so far and computing
520  * the adjacent facets through wrapping, adding those facets that we
521  * hadn't already found before.
522  *
523  * For each facet we have found so far, we first compute its facets
524  * in the resulting convex hull.  That is, we compute the ridges
525  * of the resulting convex hull contained in the facet.
526  * We also compute the corresponding facet in the current approximation
527  * of the convex hull.  There is no need to wrap around the ridges
528  * in this facet since that would result in a facet that is already
529  * present in the current approximation.
530  *
531  * This function can still be significantly optimized by checking which of
532  * the facets of the basic sets are also facets of the convex hull and
533  * using all the facets so far to help in constructing the facets of the
534  * facets
535  * and/or
536  * using the technique in section "3.1 Ridge Generation" of
537  * "Extended Convex Hull" by Fukuda et al.
538  */
extend(__isl_take isl_basic_set * hull,__isl_keep isl_set * set)539 static __isl_give isl_basic_set *extend(__isl_take isl_basic_set *hull,
540 	__isl_keep isl_set *set)
541 {
542 	int i, j, f;
543 	int k;
544 	struct isl_basic_set *facet = NULL;
545 	struct isl_basic_set *hull_facet = NULL;
546 	isl_size dim;
547 
548 	dim = isl_set_dim(set, isl_dim_set);
549 	if (dim < 0 || !hull)
550 		return isl_basic_set_free(hull);
551 
552 	isl_assert(set->ctx, set->n > 0, goto error);
553 
554 	for (i = 0; i < hull->n_ineq; ++i) {
555 		facet = compute_facet(set, hull->ineq[i]);
556 		facet = isl_basic_set_add_eq(facet, hull->ineq[i]);
557 		facet = isl_basic_set_gauss(facet, NULL);
558 		facet = isl_basic_set_normalize_constraints(facet);
559 		hull_facet = isl_basic_set_copy(hull);
560 		hull_facet = isl_basic_set_add_eq(hull_facet, hull->ineq[i]);
561 		hull_facet = isl_basic_set_gauss(hull_facet, NULL);
562 		hull_facet = isl_basic_set_normalize_constraints(hull_facet);
563 		if (!facet || !hull_facet)
564 			goto error;
565 		hull = isl_basic_set_cow(hull);
566 		hull = isl_basic_set_extend(hull, 0, 0, facet->n_ineq);
567 		if (!hull)
568 			goto error;
569 		for (j = 0; j < facet->n_ineq; ++j) {
570 			for (f = 0; f < hull_facet->n_ineq; ++f)
571 				if (isl_seq_eq(facet->ineq[j],
572 						hull_facet->ineq[f], 1 + dim))
573 					break;
574 			if (f < hull_facet->n_ineq)
575 				continue;
576 			k = isl_basic_set_alloc_inequality(hull);
577 			if (k < 0)
578 				goto error;
579 			isl_seq_cpy(hull->ineq[k], hull->ineq[i], 1+dim);
580 			if (!isl_set_wrap_facet(set, hull->ineq[k], facet->ineq[j]))
581 				goto error;
582 		}
583 		isl_basic_set_free(hull_facet);
584 		isl_basic_set_free(facet);
585 	}
586 	hull = isl_basic_set_simplify(hull);
587 	hull = isl_basic_set_finalize(hull);
588 	return hull;
589 error:
590 	isl_basic_set_free(hull_facet);
591 	isl_basic_set_free(facet);
592 	isl_basic_set_free(hull);
593 	return NULL;
594 }
595 
596 /* Special case for computing the convex hull of a one dimensional set.
597  * We simply collect the lower and upper bounds of each basic set
598  * and the biggest of those.
599  */
convex_hull_1d(__isl_take isl_set * set)600 static __isl_give isl_basic_set *convex_hull_1d(__isl_take isl_set *set)
601 {
602 	struct isl_mat *c = NULL;
603 	isl_int *lower = NULL;
604 	isl_int *upper = NULL;
605 	int i, j, k;
606 	isl_int a, b;
607 	struct isl_basic_set *hull;
608 
609 	for (i = 0; i < set->n; ++i) {
610 		set->p[i] = isl_basic_set_simplify(set->p[i]);
611 		if (!set->p[i])
612 			goto error;
613 	}
614 	set = isl_set_remove_empty_parts(set);
615 	if (!set)
616 		goto error;
617 	isl_assert(set->ctx, set->n > 0, goto error);
618 	c = isl_mat_alloc(set->ctx, 2, 2);
619 	if (!c)
620 		goto error;
621 
622 	if (set->p[0]->n_eq > 0) {
623 		isl_assert(set->ctx, set->p[0]->n_eq == 1, goto error);
624 		lower = c->row[0];
625 		upper = c->row[1];
626 		if (isl_int_is_pos(set->p[0]->eq[0][1])) {
627 			isl_seq_cpy(lower, set->p[0]->eq[0], 2);
628 			isl_seq_neg(upper, set->p[0]->eq[0], 2);
629 		} else {
630 			isl_seq_neg(lower, set->p[0]->eq[0], 2);
631 			isl_seq_cpy(upper, set->p[0]->eq[0], 2);
632 		}
633 	} else {
634 		for (j = 0; j < set->p[0]->n_ineq; ++j) {
635 			if (isl_int_is_pos(set->p[0]->ineq[j][1])) {
636 				lower = c->row[0];
637 				isl_seq_cpy(lower, set->p[0]->ineq[j], 2);
638 			} else {
639 				upper = c->row[1];
640 				isl_seq_cpy(upper, set->p[0]->ineq[j], 2);
641 			}
642 		}
643 	}
644 
645 	isl_int_init(a);
646 	isl_int_init(b);
647 	for (i = 0; i < set->n; ++i) {
648 		struct isl_basic_set *bset = set->p[i];
649 		int has_lower = 0;
650 		int has_upper = 0;
651 
652 		for (j = 0; j < bset->n_eq; ++j) {
653 			has_lower = 1;
654 			has_upper = 1;
655 			if (lower) {
656 				isl_int_mul(a, lower[0], bset->eq[j][1]);
657 				isl_int_mul(b, lower[1], bset->eq[j][0]);
658 				if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
659 					isl_seq_cpy(lower, bset->eq[j], 2);
660 				if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
661 					isl_seq_neg(lower, bset->eq[j], 2);
662 			}
663 			if (upper) {
664 				isl_int_mul(a, upper[0], bset->eq[j][1]);
665 				isl_int_mul(b, upper[1], bset->eq[j][0]);
666 				if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
667 					isl_seq_neg(upper, bset->eq[j], 2);
668 				if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
669 					isl_seq_cpy(upper, bset->eq[j], 2);
670 			}
671 		}
672 		for (j = 0; j < bset->n_ineq; ++j) {
673 			if (isl_int_is_pos(bset->ineq[j][1]))
674 				has_lower = 1;
675 			if (isl_int_is_neg(bset->ineq[j][1]))
676 				has_upper = 1;
677 			if (lower && isl_int_is_pos(bset->ineq[j][1])) {
678 				isl_int_mul(a, lower[0], bset->ineq[j][1]);
679 				isl_int_mul(b, lower[1], bset->ineq[j][0]);
680 				if (isl_int_lt(a, b))
681 					isl_seq_cpy(lower, bset->ineq[j], 2);
682 			}
683 			if (upper && isl_int_is_neg(bset->ineq[j][1])) {
684 				isl_int_mul(a, upper[0], bset->ineq[j][1]);
685 				isl_int_mul(b, upper[1], bset->ineq[j][0]);
686 				if (isl_int_gt(a, b))
687 					isl_seq_cpy(upper, bset->ineq[j], 2);
688 			}
689 		}
690 		if (!has_lower)
691 			lower = NULL;
692 		if (!has_upper)
693 			upper = NULL;
694 	}
695 	isl_int_clear(a);
696 	isl_int_clear(b);
697 
698 	hull = isl_basic_set_alloc(set->ctx, 0, 1, 0, 0, 2);
699 	hull = isl_basic_set_set_rational(hull);
700 	if (!hull)
701 		goto error;
702 	if (lower) {
703 		k = isl_basic_set_alloc_inequality(hull);
704 		isl_seq_cpy(hull->ineq[k], lower, 2);
705 	}
706 	if (upper) {
707 		k = isl_basic_set_alloc_inequality(hull);
708 		isl_seq_cpy(hull->ineq[k], upper, 2);
709 	}
710 	hull = isl_basic_set_finalize(hull);
711 	isl_set_free(set);
712 	isl_mat_free(c);
713 	return hull;
714 error:
715 	isl_set_free(set);
716 	isl_mat_free(c);
717 	return NULL;
718 }
719 
convex_hull_0d(__isl_take isl_set * set)720 static __isl_give isl_basic_set *convex_hull_0d(__isl_take isl_set *set)
721 {
722 	struct isl_basic_set *convex_hull;
723 
724 	if (!set)
725 		return NULL;
726 
727 	if (isl_set_is_empty(set))
728 		convex_hull = isl_basic_set_empty(isl_space_copy(set->dim));
729 	else
730 		convex_hull = isl_basic_set_universe(isl_space_copy(set->dim));
731 	isl_set_free(set);
732 	return convex_hull;
733 }
734 
735 /* Compute the convex hull of a pair of basic sets without any parameters or
736  * integer divisions using Fourier-Motzkin elimination.
737  * The convex hull is the set of all points that can be written as
738  * the sum of points from both basic sets (in homogeneous coordinates).
739  * We set up the constraints in a space with dimensions for each of
740  * the three sets and then project out the dimensions corresponding
741  * to the two original basic sets, retaining only those corresponding
742  * to the convex hull.
743  */
convex_hull_pair_elim(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)744 static __isl_give isl_basic_set *convex_hull_pair_elim(
745 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
746 {
747 	int i, j, k;
748 	struct isl_basic_set *bset[2];
749 	struct isl_basic_set *hull = NULL;
750 	isl_size dim;
751 
752 	dim = isl_basic_set_dim(bset1, isl_dim_set);
753 	if (dim < 0 || !bset2)
754 		goto error;
755 
756 	hull = isl_basic_set_alloc(bset1->ctx, 0, 2 + 3 * dim, 0,
757 				1 + dim + bset1->n_eq + bset2->n_eq,
758 				2 + bset1->n_ineq + bset2->n_ineq);
759 	bset[0] = bset1;
760 	bset[1] = bset2;
761 	for (i = 0; i < 2; ++i) {
762 		for (j = 0; j < bset[i]->n_eq; ++j) {
763 			k = isl_basic_set_alloc_equality(hull);
764 			if (k < 0)
765 				goto error;
766 			isl_seq_clr(hull->eq[k], (i+1) * (1+dim));
767 			isl_seq_clr(hull->eq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
768 			isl_seq_cpy(hull->eq[k]+(i+1)*(1+dim), bset[i]->eq[j],
769 					1+dim);
770 		}
771 		for (j = 0; j < bset[i]->n_ineq; ++j) {
772 			k = isl_basic_set_alloc_inequality(hull);
773 			if (k < 0)
774 				goto error;
775 			isl_seq_clr(hull->ineq[k], (i+1) * (1+dim));
776 			isl_seq_clr(hull->ineq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
777 			isl_seq_cpy(hull->ineq[k]+(i+1)*(1+dim),
778 					bset[i]->ineq[j], 1+dim);
779 		}
780 		k = isl_basic_set_alloc_inequality(hull);
781 		if (k < 0)
782 			goto error;
783 		isl_seq_clr(hull->ineq[k], 1+2+3*dim);
784 		isl_int_set_si(hull->ineq[k][(i+1)*(1+dim)], 1);
785 	}
786 	for (j = 0; j < 1+dim; ++j) {
787 		k = isl_basic_set_alloc_equality(hull);
788 		if (k < 0)
789 			goto error;
790 		isl_seq_clr(hull->eq[k], 1+2+3*dim);
791 		isl_int_set_si(hull->eq[k][j], -1);
792 		isl_int_set_si(hull->eq[k][1+dim+j], 1);
793 		isl_int_set_si(hull->eq[k][2*(1+dim)+j], 1);
794 	}
795 	hull = isl_basic_set_set_rational(hull);
796 	hull = isl_basic_set_remove_dims(hull, isl_dim_set, dim, 2*(1+dim));
797 	hull = isl_basic_set_remove_redundancies(hull);
798 	isl_basic_set_free(bset1);
799 	isl_basic_set_free(bset2);
800 	return hull;
801 error:
802 	isl_basic_set_free(bset1);
803 	isl_basic_set_free(bset2);
804 	isl_basic_set_free(hull);
805 	return NULL;
806 }
807 
808 /* Is the set bounded for each value of the parameters?
809  */
isl_basic_set_is_bounded(__isl_keep isl_basic_set * bset)810 isl_bool isl_basic_set_is_bounded(__isl_keep isl_basic_set *bset)
811 {
812 	struct isl_tab *tab;
813 	isl_bool bounded;
814 
815 	if (!bset)
816 		return isl_bool_error;
817 	if (isl_basic_set_plain_is_empty(bset))
818 		return isl_bool_true;
819 
820 	tab = isl_tab_from_recession_cone(bset, 1);
821 	bounded = isl_tab_cone_is_bounded(tab);
822 	isl_tab_free(tab);
823 	return bounded;
824 }
825 
826 /* Is the image bounded for each value of the parameters and
827  * the domain variables?
828  */
isl_basic_map_image_is_bounded(__isl_keep isl_basic_map * bmap)829 isl_bool isl_basic_map_image_is_bounded(__isl_keep isl_basic_map *bmap)
830 {
831 	isl_size nparam = isl_basic_map_dim(bmap, isl_dim_param);
832 	isl_size n_in = isl_basic_map_dim(bmap, isl_dim_in);
833 	isl_bool bounded;
834 
835 	if (nparam < 0 || n_in < 0)
836 		return isl_bool_error;
837 
838 	bmap = isl_basic_map_copy(bmap);
839 	bmap = isl_basic_map_cow(bmap);
840 	bmap = isl_basic_map_move_dims(bmap, isl_dim_param, nparam,
841 					isl_dim_in, 0, n_in);
842 	bounded = isl_basic_set_is_bounded(bset_from_bmap(bmap));
843 	isl_basic_map_free(bmap);
844 
845 	return bounded;
846 }
847 
848 /* Is the set bounded for each value of the parameters?
849  */
isl_set_is_bounded(__isl_keep isl_set * set)850 isl_bool isl_set_is_bounded(__isl_keep isl_set *set)
851 {
852 	int i;
853 
854 	if (!set)
855 		return isl_bool_error;
856 
857 	for (i = 0; i < set->n; ++i) {
858 		isl_bool bounded = isl_basic_set_is_bounded(set->p[i]);
859 		if (!bounded || bounded < 0)
860 			return bounded;
861 	}
862 	return isl_bool_true;
863 }
864 
865 /* Compute the lineality space of the convex hull of bset1 and bset2.
866  *
867  * We first compute the intersection of the recession cone of bset1
868  * with the negative of the recession cone of bset2 and then compute
869  * the linear hull of the resulting cone.
870  */
induced_lineality_space(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)871 static __isl_give isl_basic_set *induced_lineality_space(
872 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
873 {
874 	int i, k;
875 	struct isl_basic_set *lin = NULL;
876 	isl_size dim;
877 
878 	dim = isl_basic_set_dim(bset1, isl_dim_all);
879 	if (dim < 0 || !bset2)
880 		goto error;
881 
882 	lin = isl_basic_set_alloc_space(isl_basic_set_get_space(bset1), 0,
883 					bset1->n_eq + bset2->n_eq,
884 					bset1->n_ineq + bset2->n_ineq);
885 	lin = isl_basic_set_set_rational(lin);
886 	if (!lin)
887 		goto error;
888 	for (i = 0; i < bset1->n_eq; ++i) {
889 		k = isl_basic_set_alloc_equality(lin);
890 		if (k < 0)
891 			goto error;
892 		isl_int_set_si(lin->eq[k][0], 0);
893 		isl_seq_cpy(lin->eq[k] + 1, bset1->eq[i] + 1, dim);
894 	}
895 	for (i = 0; i < bset1->n_ineq; ++i) {
896 		k = isl_basic_set_alloc_inequality(lin);
897 		if (k < 0)
898 			goto error;
899 		isl_int_set_si(lin->ineq[k][0], 0);
900 		isl_seq_cpy(lin->ineq[k] + 1, bset1->ineq[i] + 1, dim);
901 	}
902 	for (i = 0; i < bset2->n_eq; ++i) {
903 		k = isl_basic_set_alloc_equality(lin);
904 		if (k < 0)
905 			goto error;
906 		isl_int_set_si(lin->eq[k][0], 0);
907 		isl_seq_neg(lin->eq[k] + 1, bset2->eq[i] + 1, dim);
908 	}
909 	for (i = 0; i < bset2->n_ineq; ++i) {
910 		k = isl_basic_set_alloc_inequality(lin);
911 		if (k < 0)
912 			goto error;
913 		isl_int_set_si(lin->ineq[k][0], 0);
914 		isl_seq_neg(lin->ineq[k] + 1, bset2->ineq[i] + 1, dim);
915 	}
916 
917 	isl_basic_set_free(bset1);
918 	isl_basic_set_free(bset2);
919 	return isl_basic_set_affine_hull(lin);
920 error:
921 	isl_basic_set_free(lin);
922 	isl_basic_set_free(bset1);
923 	isl_basic_set_free(bset2);
924 	return NULL;
925 }
926 
927 static __isl_give isl_basic_set *uset_convex_hull(__isl_take isl_set *set);
928 
929 /* Given a set and a linear space "lin" of dimension n > 0,
930  * project the linear space from the set, compute the convex hull
931  * and then map the set back to the original space.
932  *
933  * Let
934  *
935  *	M x = 0
936  *
937  * describe the linear space.  We first compute the Hermite normal
938  * form H = M U of M = H Q, to obtain
939  *
940  *	H Q x = 0
941  *
942  * The last n rows of H will be zero, so the last n variables of x' = Q x
943  * are the one we want to project out.  We do this by transforming each
944  * basic set A x >= b to A U x' >= b and then removing the last n dimensions.
945  * After computing the convex hull in x'_1, i.e., A' x'_1 >= b',
946  * we transform the hull back to the original space as A' Q_1 x >= b',
947  * with Q_1 all but the last n rows of Q.
948  */
modulo_lineality(__isl_take isl_set * set,__isl_take isl_basic_set * lin)949 static __isl_give isl_basic_set *modulo_lineality(__isl_take isl_set *set,
950 	__isl_take isl_basic_set *lin)
951 {
952 	isl_size total = isl_basic_set_dim(lin, isl_dim_all);
953 	unsigned lin_dim;
954 	struct isl_basic_set *hull;
955 	struct isl_mat *M, *U, *Q;
956 
957 	if (!set || total < 0)
958 		goto error;
959 	lin_dim = total - lin->n_eq;
960 	M = isl_mat_sub_alloc6(set->ctx, lin->eq, 0, lin->n_eq, 1, total);
961 	M = isl_mat_left_hermite(M, 0, &U, &Q);
962 	if (!M)
963 		goto error;
964 	isl_mat_free(M);
965 	isl_basic_set_free(lin);
966 
967 	Q = isl_mat_drop_rows(Q, Q->n_row - lin_dim, lin_dim);
968 
969 	U = isl_mat_lin_to_aff(U);
970 	Q = isl_mat_lin_to_aff(Q);
971 
972 	set = isl_set_preimage(set, U);
973 	set = isl_set_remove_dims(set, isl_dim_set, total - lin_dim, lin_dim);
974 	hull = uset_convex_hull(set);
975 	hull = isl_basic_set_preimage(hull, Q);
976 
977 	return hull;
978 error:
979 	isl_basic_set_free(lin);
980 	isl_set_free(set);
981 	return NULL;
982 }
983 
984 /* Given two polyhedra with as constraints h_{ij} x >= 0 in homegeneous space,
985  * set up an LP for solving
986  *
987  *	\sum_j \alpha_{1j} h_{1j} = \sum_j \alpha_{2j} h_{2j}
988  *
989  * \alpha{i0} corresponds to the (implicit) positivity constraint 1 >= 0
990  * The next \alpha{ij} correspond to the equalities and come in pairs.
991  * The final \alpha{ij} correspond to the inequalities.
992  */
valid_direction_lp(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)993 static __isl_give isl_basic_set *valid_direction_lp(
994 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
995 {
996 	isl_space *space;
997 	struct isl_basic_set *lp;
998 	unsigned d;
999 	int n;
1000 	int i, j, k;
1001 	isl_size total;
1002 
1003 	total = isl_basic_set_dim(bset1, isl_dim_all);
1004 	if (total < 0 || !bset2)
1005 		goto error;
1006 	d = 1 + total;
1007 	n = 2 +
1008 	    2 * bset1->n_eq + bset1->n_ineq + 2 * bset2->n_eq + bset2->n_ineq;
1009 	space = isl_space_set_alloc(bset1->ctx, 0, n);
1010 	lp = isl_basic_set_alloc_space(space, 0, d, n);
1011 	if (!lp)
1012 		goto error;
1013 	for (i = 0; i < n; ++i) {
1014 		k = isl_basic_set_alloc_inequality(lp);
1015 		if (k < 0)
1016 			goto error;
1017 		isl_seq_clr(lp->ineq[k] + 1, n);
1018 		isl_int_set_si(lp->ineq[k][0], -1);
1019 		isl_int_set_si(lp->ineq[k][1 + i], 1);
1020 	}
1021 	for (i = 0; i < d; ++i) {
1022 		k = isl_basic_set_alloc_equality(lp);
1023 		if (k < 0)
1024 			goto error;
1025 		n = 0;
1026 		isl_int_set_si(lp->eq[k][n], 0); n++;
1027 		/* positivity constraint 1 >= 0 */
1028 		isl_int_set_si(lp->eq[k][n], i == 0); n++;
1029 		for (j = 0; j < bset1->n_eq; ++j) {
1030 			isl_int_set(lp->eq[k][n], bset1->eq[j][i]); n++;
1031 			isl_int_neg(lp->eq[k][n], bset1->eq[j][i]); n++;
1032 		}
1033 		for (j = 0; j < bset1->n_ineq; ++j) {
1034 			isl_int_set(lp->eq[k][n], bset1->ineq[j][i]); n++;
1035 		}
1036 		/* positivity constraint 1 >= 0 */
1037 		isl_int_set_si(lp->eq[k][n], -(i == 0)); n++;
1038 		for (j = 0; j < bset2->n_eq; ++j) {
1039 			isl_int_neg(lp->eq[k][n], bset2->eq[j][i]); n++;
1040 			isl_int_set(lp->eq[k][n], bset2->eq[j][i]); n++;
1041 		}
1042 		for (j = 0; j < bset2->n_ineq; ++j) {
1043 			isl_int_neg(lp->eq[k][n], bset2->ineq[j][i]); n++;
1044 		}
1045 	}
1046 	lp = isl_basic_set_gauss(lp, NULL);
1047 	isl_basic_set_free(bset1);
1048 	isl_basic_set_free(bset2);
1049 	return lp;
1050 error:
1051 	isl_basic_set_free(bset1);
1052 	isl_basic_set_free(bset2);
1053 	return NULL;
1054 }
1055 
1056 /* Compute a vector s in the homogeneous space such that <s, r> > 0
1057  * for all rays in the homogeneous space of the two cones that correspond
1058  * to the input polyhedra bset1 and bset2.
1059  *
1060  * We compute s as a vector that satisfies
1061  *
1062  *	s = \sum_j \alpha_{ij} h_{ij}	for i = 1,2			(*)
1063  *
1064  * with h_{ij} the normals of the facets of polyhedron i
1065  * (including the "positivity constraint" 1 >= 0) and \alpha_{ij}
1066  * strictly positive numbers.  For simplicity we impose \alpha_{ij} >= 1.
1067  * We first set up an LP with as variables the \alpha{ij}.
1068  * In this formulation, for each polyhedron i,
1069  * the first constraint is the positivity constraint, followed by pairs
1070  * of variables for the equalities, followed by variables for the inequalities.
1071  * We then simply pick a feasible solution and compute s using (*).
1072  *
1073  * Note that we simply pick any valid direction and make no attempt
1074  * to pick a "good" or even the "best" valid direction.
1075  */
valid_direction(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)1076 static __isl_give isl_vec *valid_direction(
1077 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
1078 {
1079 	struct isl_basic_set *lp;
1080 	struct isl_tab *tab;
1081 	struct isl_vec *sample = NULL;
1082 	struct isl_vec *dir;
1083 	isl_size d;
1084 	int i;
1085 	int n;
1086 
1087 	if (!bset1 || !bset2)
1088 		goto error;
1089 	lp = valid_direction_lp(isl_basic_set_copy(bset1),
1090 				isl_basic_set_copy(bset2));
1091 	tab = isl_tab_from_basic_set(lp, 0);
1092 	sample = isl_tab_get_sample_value(tab);
1093 	isl_tab_free(tab);
1094 	isl_basic_set_free(lp);
1095 	if (!sample)
1096 		goto error;
1097 	d = isl_basic_set_dim(bset1, isl_dim_all);
1098 	if (d < 0)
1099 		goto error;
1100 	dir = isl_vec_alloc(bset1->ctx, 1 + d);
1101 	if (!dir)
1102 		goto error;
1103 	isl_seq_clr(dir->block.data + 1, dir->size - 1);
1104 	n = 1;
1105 	/* positivity constraint 1 >= 0 */
1106 	isl_int_set(dir->block.data[0], sample->block.data[n]); n++;
1107 	for (i = 0; i < bset1->n_eq; ++i) {
1108 		isl_int_sub(sample->block.data[n],
1109 			    sample->block.data[n], sample->block.data[n+1]);
1110 		isl_seq_combine(dir->block.data,
1111 				bset1->ctx->one, dir->block.data,
1112 				sample->block.data[n], bset1->eq[i], 1 + d);
1113 
1114 		n += 2;
1115 	}
1116 	for (i = 0; i < bset1->n_ineq; ++i)
1117 		isl_seq_combine(dir->block.data,
1118 				bset1->ctx->one, dir->block.data,
1119 				sample->block.data[n++], bset1->ineq[i], 1 + d);
1120 	isl_vec_free(sample);
1121 	isl_seq_normalize(bset1->ctx, dir->el, dir->size);
1122 	isl_basic_set_free(bset1);
1123 	isl_basic_set_free(bset2);
1124 	return dir;
1125 error:
1126 	isl_vec_free(sample);
1127 	isl_basic_set_free(bset1);
1128 	isl_basic_set_free(bset2);
1129 	return NULL;
1130 }
1131 
1132 /* Given a polyhedron b_i + A_i x >= 0 and a map T = S^{-1},
1133  * compute b_i' + A_i' x' >= 0, with
1134  *
1135  *	[ b_i A_i ]        [ y' ]		              [ y' ]
1136  *	[  1   0  ] S^{-1} [ x' ] >= 0	or	[ b_i' A_i' ] [ x' ] >= 0
1137  *
1138  * In particular, add the "positivity constraint" and then perform
1139  * the mapping.
1140  */
homogeneous_map(__isl_take isl_basic_set * bset,__isl_take isl_mat * T)1141 static __isl_give isl_basic_set *homogeneous_map(__isl_take isl_basic_set *bset,
1142 	__isl_take isl_mat *T)
1143 {
1144 	int k;
1145 	isl_size total;
1146 
1147 	total = isl_basic_set_dim(bset, isl_dim_all);
1148 	if (total < 0)
1149 		goto error;
1150 	bset = isl_basic_set_extend_constraints(bset, 0, 1);
1151 	k = isl_basic_set_alloc_inequality(bset);
1152 	if (k < 0)
1153 		goto error;
1154 	isl_seq_clr(bset->ineq[k] + 1, total);
1155 	isl_int_set_si(bset->ineq[k][0], 1);
1156 	bset = isl_basic_set_preimage(bset, T);
1157 	return bset;
1158 error:
1159 	isl_mat_free(T);
1160 	isl_basic_set_free(bset);
1161 	return NULL;
1162 }
1163 
1164 /* Compute the convex hull of a pair of basic sets without any parameters or
1165  * integer divisions, where the convex hull is known to be pointed,
1166  * but the basic sets may be unbounded.
1167  *
1168  * We turn this problem into the computation of a convex hull of a pair
1169  * _bounded_ polyhedra by "changing the direction of the homogeneous
1170  * dimension".  This idea is due to Matthias Koeppe.
1171  *
1172  * Consider the cones in homogeneous space that correspond to the
1173  * input polyhedra.  The rays of these cones are also rays of the
1174  * polyhedra if the coordinate that corresponds to the homogeneous
1175  * dimension is zero.  That is, if the inner product of the rays
1176  * with the homogeneous direction is zero.
1177  * The cones in the homogeneous space can also be considered to
1178  * correspond to other pairs of polyhedra by chosing a different
1179  * homogeneous direction.  To ensure that both of these polyhedra
1180  * are bounded, we need to make sure that all rays of the cones
1181  * correspond to vertices and not to rays.
1182  * Let s be a direction such that <s, r> > 0 for all rays r of both cones.
1183  * Then using s as a homogeneous direction, we obtain a pair of polytopes.
1184  * The vector s is computed in valid_direction.
1185  *
1186  * Note that we need to consider _all_ rays of the cones and not just
1187  * the rays that correspond to rays in the polyhedra.  If we were to
1188  * only consider those rays and turn them into vertices, then we
1189  * may inadvertently turn some vertices into rays.
1190  *
1191  * The standard homogeneous direction is the unit vector in the 0th coordinate.
1192  * We therefore transform the two polyhedra such that the selected
1193  * direction is mapped onto this standard direction and then proceed
1194  * with the normal computation.
1195  * Let S be a non-singular square matrix with s as its first row,
1196  * then we want to map the polyhedra to the space
1197  *
1198  *	[ y' ]     [ y ]		[ y ]          [ y' ]
1199  *	[ x' ] = S [ x ]	i.e.,	[ x ] = S^{-1} [ x' ]
1200  *
1201  * We take S to be the unimodular completion of s to limit the growth
1202  * of the coefficients in the following computations.
1203  *
1204  * Let b_i + A_i x >= 0 be the constraints of polyhedron i.
1205  * We first move to the homogeneous dimension
1206  *
1207  *	b_i y + A_i x >= 0		[ b_i A_i ] [ y ]    [ 0 ]
1208  *	    y         >= 0	or	[  1   0  ] [ x ] >= [ 0 ]
1209  *
1210  * Then we change directoin
1211  *
1212  *	[ b_i A_i ]        [ y' ]		              [ y' ]
1213  *	[  1   0  ] S^{-1} [ x' ] >= 0	or	[ b_i' A_i' ] [ x' ] >= 0
1214  *
1215  * Then we compute the convex hull of the polytopes b_i' + A_i' x' >= 0
1216  * resulting in b' + A' x' >= 0, which we then convert back
1217  *
1218  *	            [ y ]		        [ y ]
1219  *	[ b' A' ] S [ x ] >= 0	or	[ b A ] [ x ] >= 0
1220  *
1221  * The polyhedron b + A x >= 0 is then the convex hull of the input polyhedra.
1222  */
convex_hull_pair_pointed(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)1223 static __isl_give isl_basic_set *convex_hull_pair_pointed(
1224 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
1225 {
1226 	struct isl_ctx *ctx = NULL;
1227 	struct isl_vec *dir = NULL;
1228 	struct isl_mat *T = NULL;
1229 	struct isl_mat *T2 = NULL;
1230 	struct isl_basic_set *hull;
1231 	struct isl_set *set;
1232 
1233 	if (!bset1 || !bset2)
1234 		goto error;
1235 	ctx = isl_basic_set_get_ctx(bset1);
1236 	dir = valid_direction(isl_basic_set_copy(bset1),
1237 				isl_basic_set_copy(bset2));
1238 	if (!dir)
1239 		goto error;
1240 	T = isl_mat_alloc(ctx, dir->size, dir->size);
1241 	if (!T)
1242 		goto error;
1243 	isl_seq_cpy(T->row[0], dir->block.data, dir->size);
1244 	T = isl_mat_unimodular_complete(T, 1);
1245 	T2 = isl_mat_right_inverse(isl_mat_copy(T));
1246 
1247 	bset1 = homogeneous_map(bset1, isl_mat_copy(T2));
1248 	bset2 = homogeneous_map(bset2, T2);
1249 	set = isl_set_alloc_space(isl_basic_set_get_space(bset1), 2, 0);
1250 	set = isl_set_add_basic_set(set, bset1);
1251 	set = isl_set_add_basic_set(set, bset2);
1252 	hull = uset_convex_hull(set);
1253 	hull = isl_basic_set_preimage(hull, T);
1254 
1255 	isl_vec_free(dir);
1256 
1257 	return hull;
1258 error:
1259 	isl_vec_free(dir);
1260 	isl_basic_set_free(bset1);
1261 	isl_basic_set_free(bset2);
1262 	return NULL;
1263 }
1264 
1265 static __isl_give isl_basic_set *uset_convex_hull_wrap(__isl_take isl_set *set);
1266 static __isl_give isl_basic_set *modulo_affine_hull(
1267 	__isl_take isl_set *set, __isl_take isl_basic_set *affine_hull);
1268 
1269 /* Compute the convex hull of a pair of basic sets without any parameters or
1270  * integer divisions.
1271  *
1272  * This function is called from uset_convex_hull_unbounded, which
1273  * means that the complete convex hull is unbounded.  Some pairs
1274  * of basic sets may still be bounded, though.
1275  * They may even lie inside a lower dimensional space, in which
1276  * case they need to be handled inside their affine hull since
1277  * the main algorithm assumes that the result is full-dimensional.
1278  *
1279  * If the convex hull of the two basic sets would have a non-trivial
1280  * lineality space, we first project out this lineality space.
1281  */
convex_hull_pair(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)1282 static __isl_give isl_basic_set *convex_hull_pair(
1283 	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
1284 {
1285 	isl_basic_set *lin, *aff;
1286 	isl_bool bounded1, bounded2;
1287 	isl_size total;
1288 
1289 	if (bset1->ctx->opt->convex == ISL_CONVEX_HULL_FM)
1290 		return convex_hull_pair_elim(bset1, bset2);
1291 
1292 	aff = isl_set_affine_hull(isl_basic_set_union(isl_basic_set_copy(bset1),
1293 						    isl_basic_set_copy(bset2)));
1294 	if (!aff)
1295 		goto error;
1296 	if (aff->n_eq != 0)
1297 		return modulo_affine_hull(isl_basic_set_union(bset1, bset2), aff);
1298 	isl_basic_set_free(aff);
1299 
1300 	bounded1 = isl_basic_set_is_bounded(bset1);
1301 	bounded2 = isl_basic_set_is_bounded(bset2);
1302 
1303 	if (bounded1 < 0 || bounded2 < 0)
1304 		goto error;
1305 
1306 	if (bounded1 && bounded2)
1307 		return uset_convex_hull_wrap(isl_basic_set_union(bset1, bset2));
1308 
1309 	if (bounded1 || bounded2)
1310 		return convex_hull_pair_pointed(bset1, bset2);
1311 
1312 	lin = induced_lineality_space(isl_basic_set_copy(bset1),
1313 				      isl_basic_set_copy(bset2));
1314 	if (!lin)
1315 		goto error;
1316 	if (isl_basic_set_plain_is_universe(lin)) {
1317 		isl_basic_set_free(bset1);
1318 		isl_basic_set_free(bset2);
1319 		return lin;
1320 	}
1321 	total = isl_basic_set_dim(lin, isl_dim_all);
1322 	if (lin->n_eq < total) {
1323 		struct isl_set *set;
1324 		set = isl_set_alloc_space(isl_basic_set_get_space(bset1), 2, 0);
1325 		set = isl_set_add_basic_set(set, bset1);
1326 		set = isl_set_add_basic_set(set, bset2);
1327 		return modulo_lineality(set, lin);
1328 	}
1329 	isl_basic_set_free(lin);
1330 	if (total < 0)
1331 		goto error;
1332 
1333 	return convex_hull_pair_pointed(bset1, bset2);
1334 error:
1335 	isl_basic_set_free(bset1);
1336 	isl_basic_set_free(bset2);
1337 	return NULL;
1338 }
1339 
1340 /* Compute the lineality space of a basic set.
1341  * We basically just drop the constants and turn every inequality
1342  * into an equality.
1343  * Any explicit representations of local variables are removed
1344  * because they may no longer be valid representations
1345  * in the lineality space.
1346  */
isl_basic_set_lineality_space(__isl_take isl_basic_set * bset)1347 __isl_give isl_basic_set *isl_basic_set_lineality_space(
1348 	__isl_take isl_basic_set *bset)
1349 {
1350 	int i, k;
1351 	struct isl_basic_set *lin = NULL;
1352 	isl_size n_div, dim;
1353 
1354 	n_div = isl_basic_set_dim(bset, isl_dim_div);
1355 	dim = isl_basic_set_dim(bset, isl_dim_all);
1356 	if (n_div < 0 || dim < 0)
1357 		return isl_basic_set_free(bset);
1358 
1359 	lin = isl_basic_set_alloc_space(isl_basic_set_get_space(bset),
1360 					n_div, dim, 0);
1361 	for (i = 0; i < n_div; ++i)
1362 		if (isl_basic_set_alloc_div(lin) < 0)
1363 			goto error;
1364 	if (!lin)
1365 		goto error;
1366 	for (i = 0; i < bset->n_eq; ++i) {
1367 		k = isl_basic_set_alloc_equality(lin);
1368 		if (k < 0)
1369 			goto error;
1370 		isl_int_set_si(lin->eq[k][0], 0);
1371 		isl_seq_cpy(lin->eq[k] + 1, bset->eq[i] + 1, dim);
1372 	}
1373 	lin = isl_basic_set_gauss(lin, NULL);
1374 	if (!lin)
1375 		goto error;
1376 	for (i = 0; i < bset->n_ineq && lin->n_eq < dim; ++i) {
1377 		k = isl_basic_set_alloc_equality(lin);
1378 		if (k < 0)
1379 			goto error;
1380 		isl_int_set_si(lin->eq[k][0], 0);
1381 		isl_seq_cpy(lin->eq[k] + 1, bset->ineq[i] + 1, dim);
1382 		lin = isl_basic_set_gauss(lin, NULL);
1383 		if (!lin)
1384 			goto error;
1385 	}
1386 	isl_basic_set_free(bset);
1387 	return lin;
1388 error:
1389 	isl_basic_set_free(lin);
1390 	isl_basic_set_free(bset);
1391 	return NULL;
1392 }
1393 
1394 /* Compute the (linear) hull of the lineality spaces of the basic sets in the
1395  * set "set".
1396  */
isl_set_combined_lineality_space(__isl_take isl_set * set)1397 __isl_give isl_basic_set *isl_set_combined_lineality_space(
1398 	__isl_take isl_set *set)
1399 {
1400 	int i;
1401 	struct isl_set *lin = NULL;
1402 
1403 	if (!set)
1404 		return NULL;
1405 	if (set->n == 0) {
1406 		isl_space *space = isl_set_get_space(set);
1407 		isl_set_free(set);
1408 		return isl_basic_set_empty(space);
1409 	}
1410 
1411 	lin = isl_set_alloc_space(isl_set_get_space(set), set->n, 0);
1412 	for (i = 0; i < set->n; ++i)
1413 		lin = isl_set_add_basic_set(lin,
1414 		    isl_basic_set_lineality_space(isl_basic_set_copy(set->p[i])));
1415 	isl_set_free(set);
1416 	return isl_set_affine_hull(lin);
1417 }
1418 
1419 /* Compute the convex hull of a set without any parameters or
1420  * integer divisions.
1421  * In each step, we combined two basic sets until only one
1422  * basic set is left.
1423  * The input basic sets are assumed not to have a non-trivial
1424  * lineality space.  If any of the intermediate results has
1425  * a non-trivial lineality space, it is projected out.
1426  */
uset_convex_hull_unbounded(__isl_take isl_set * set)1427 static __isl_give isl_basic_set *uset_convex_hull_unbounded(
1428 	__isl_take isl_set *set)
1429 {
1430 	isl_basic_set_list *list;
1431 
1432 	list = isl_set_get_basic_set_list(set);
1433 	isl_set_free(set);
1434 
1435 	while (list) {
1436 		isl_size n, total;
1437 		struct isl_basic_set *t;
1438 		isl_basic_set *bset1, *bset2;
1439 
1440 		n = isl_basic_set_list_n_basic_set(list);
1441 		if (n < 0)
1442 			goto error;
1443 		if (n < 2)
1444 			isl_die(isl_basic_set_list_get_ctx(list),
1445 				isl_error_internal,
1446 				"expecting at least two elements", goto error);
1447 		bset1 = isl_basic_set_list_get_basic_set(list, n - 1);
1448 		bset2 = isl_basic_set_list_get_basic_set(list, n - 2);
1449 		bset1 = convex_hull_pair(bset1, bset2);
1450 		if (n == 2) {
1451 			isl_basic_set_list_free(list);
1452 			return bset1;
1453 		}
1454 		bset1 = isl_basic_set_underlying_set(bset1);
1455 		list = isl_basic_set_list_drop(list, n - 2, 2);
1456 		list = isl_basic_set_list_add(list, bset1);
1457 
1458 		t = isl_basic_set_list_get_basic_set(list, n - 2);
1459 		t = isl_basic_set_lineality_space(t);
1460 		if (!t)
1461 			goto error;
1462 		if (isl_basic_set_plain_is_universe(t)) {
1463 			isl_basic_set_list_free(list);
1464 			return t;
1465 		}
1466 		total = isl_basic_set_dim(t, isl_dim_all);
1467 		if (t->n_eq < total) {
1468 			set = isl_basic_set_list_union(list);
1469 			return modulo_lineality(set, t);
1470 		}
1471 		isl_basic_set_free(t);
1472 		if (total < 0)
1473 			goto error;
1474 	}
1475 
1476 	return NULL;
1477 error:
1478 	isl_basic_set_list_free(list);
1479 	return NULL;
1480 }
1481 
1482 /* Compute an initial hull for wrapping containing a single initial
1483  * facet.
1484  * This function assumes that the given set is bounded.
1485  */
initial_hull(__isl_take isl_basic_set * hull,__isl_keep isl_set * set)1486 static __isl_give isl_basic_set *initial_hull(__isl_take isl_basic_set *hull,
1487 	__isl_keep isl_set *set)
1488 {
1489 	struct isl_mat *bounds = NULL;
1490 	isl_size dim;
1491 	int k;
1492 
1493 	if (!hull)
1494 		goto error;
1495 	bounds = initial_facet_constraint(set);
1496 	if (!bounds)
1497 		goto error;
1498 	k = isl_basic_set_alloc_inequality(hull);
1499 	if (k < 0)
1500 		goto error;
1501 	dim = isl_set_dim(set, isl_dim_set);
1502 	if (dim < 0)
1503 		goto error;
1504 	isl_assert(set->ctx, 1 + dim == bounds->n_col, goto error);
1505 	isl_seq_cpy(hull->ineq[k], bounds->row[0], bounds->n_col);
1506 	isl_mat_free(bounds);
1507 
1508 	return hull;
1509 error:
1510 	isl_basic_set_free(hull);
1511 	isl_mat_free(bounds);
1512 	return NULL;
1513 }
1514 
1515 struct max_constraint {
1516 	struct isl_mat *c;
1517 	int	 	count;
1518 	int		ineq;
1519 };
1520 
max_constraint_equal(const void * entry,const void * val)1521 static isl_bool max_constraint_equal(const void *entry, const void *val)
1522 {
1523 	struct max_constraint *a = (struct max_constraint *)entry;
1524 	isl_int *b = (isl_int *)val;
1525 
1526 	return isl_bool_ok(isl_seq_eq(a->c->row[0] + 1, b, a->c->n_col - 1));
1527 }
1528 
update_constraint(struct isl_ctx * ctx,struct isl_hash_table * table,isl_int * con,unsigned len,int n,int ineq)1529 static isl_stat update_constraint(struct isl_ctx *ctx,
1530 	struct isl_hash_table *table,
1531 	isl_int *con, unsigned len, int n, int ineq)
1532 {
1533 	struct isl_hash_table_entry *entry;
1534 	struct max_constraint *c;
1535 	uint32_t c_hash;
1536 
1537 	c_hash = isl_seq_get_hash(con + 1, len);
1538 	entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
1539 			con + 1, 0);
1540 	if (!entry)
1541 		return isl_stat_error;
1542 	if (entry == isl_hash_table_entry_none)
1543 		return isl_stat_ok;
1544 	c = entry->data;
1545 	if (c->count < n) {
1546 		isl_hash_table_remove(ctx, table, entry);
1547 		return isl_stat_ok;
1548 	}
1549 	c->count++;
1550 	if (isl_int_gt(c->c->row[0][0], con[0]))
1551 		return isl_stat_ok;
1552 	if (isl_int_eq(c->c->row[0][0], con[0])) {
1553 		if (ineq)
1554 			c->ineq = ineq;
1555 		return isl_stat_ok;
1556 	}
1557 	c->c = isl_mat_cow(c->c);
1558 	isl_int_set(c->c->row[0][0], con[0]);
1559 	c->ineq = ineq;
1560 
1561 	return isl_stat_ok;
1562 }
1563 
1564 /* Check whether the constraint hash table "table" contains the constraint
1565  * "con".
1566  */
has_constraint(struct isl_ctx * ctx,struct isl_hash_table * table,isl_int * con,unsigned len,int n)1567 static isl_bool has_constraint(struct isl_ctx *ctx,
1568 	struct isl_hash_table *table, isl_int *con, unsigned len, int n)
1569 {
1570 	struct isl_hash_table_entry *entry;
1571 	struct max_constraint *c;
1572 	uint32_t c_hash;
1573 
1574 	c_hash = isl_seq_get_hash(con + 1, len);
1575 	entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
1576 			con + 1, 0);
1577 	if (!entry)
1578 		return isl_bool_error;
1579 	if (entry == isl_hash_table_entry_none)
1580 		return isl_bool_false;
1581 	c = entry->data;
1582 	if (c->count < n)
1583 		return isl_bool_false;
1584 	return isl_bool_ok(isl_int_eq(c->c->row[0][0], con[0]));
1585 }
1586 
1587 /* Are the constraints of "bset" known to be facets?
1588  * If there are any equality constraints, then they are not.
1589  * If there may be redundant constraints, then those
1590  * redundant constraints are not facets.
1591  */
has_facets(__isl_keep isl_basic_set * bset)1592 static isl_bool has_facets(__isl_keep isl_basic_set *bset)
1593 {
1594 	isl_size n_eq;
1595 
1596 	n_eq = isl_basic_set_n_equality(bset);
1597 	if (n_eq < 0)
1598 		return isl_bool_error;
1599 	if (n_eq != 0)
1600 		return isl_bool_false;
1601 	return ISL_F_ISSET(bset, ISL_BASIC_SET_NO_REDUNDANT);
1602 }
1603 
1604 /* Check for inequality constraints of a basic set without equalities
1605  * or redundant constraints
1606  * such that the same or more stringent copies of the constraint appear
1607  * in all of the basic sets.  Such constraints are necessarily facet
1608  * constraints of the convex hull.
1609  *
1610  * If the resulting basic set is by chance identical to one of
1611  * the basic sets in "set", then we know that this basic set contains
1612  * all other basic sets and is therefore the convex hull of set.
1613  * In this case we set *is_hull to 1.
1614  */
common_constraints(__isl_take isl_basic_set * hull,__isl_keep isl_set * set,int * is_hull)1615 static __isl_give isl_basic_set *common_constraints(
1616 	__isl_take isl_basic_set *hull, __isl_keep isl_set *set, int *is_hull)
1617 {
1618 	int i, j, s, n;
1619 	int min_constraints;
1620 	int best;
1621 	struct max_constraint *constraints = NULL;
1622 	struct isl_hash_table *table = NULL;
1623 	isl_size total;
1624 
1625 	*is_hull = 0;
1626 
1627 	for (i = 0; i < set->n; ++i) {
1628 		isl_bool facets = has_facets(set->p[i]);
1629 		if (facets < 0)
1630 			return isl_basic_set_free(hull);
1631 		if (facets)
1632 			break;
1633 	}
1634 	if (i >= set->n)
1635 		return hull;
1636 	min_constraints = set->p[i]->n_ineq;
1637 	best = i;
1638 	for (i = best + 1; i < set->n; ++i) {
1639 		isl_bool facets = has_facets(set->p[i]);
1640 		if (facets < 0)
1641 			return isl_basic_set_free(hull);
1642 		if (!facets)
1643 			continue;
1644 		if (set->p[i]->n_ineq >= min_constraints)
1645 			continue;
1646 		min_constraints = set->p[i]->n_ineq;
1647 		best = i;
1648 	}
1649 	constraints = isl_calloc_array(hull->ctx, struct max_constraint,
1650 					min_constraints);
1651 	if (!constraints)
1652 		return hull;
1653 	table = isl_alloc_type(hull->ctx, struct isl_hash_table);
1654 	if (isl_hash_table_init(hull->ctx, table, min_constraints))
1655 		goto error;
1656 
1657 	total = isl_set_dim(set, isl_dim_all);
1658 	if (total < 0)
1659 		goto error;
1660 	for (i = 0; i < set->p[best]->n_ineq; ++i) {
1661 		constraints[i].c = isl_mat_sub_alloc6(hull->ctx,
1662 			set->p[best]->ineq + i, 0, 1, 0, 1 + total);
1663 		if (!constraints[i].c)
1664 			goto error;
1665 		constraints[i].ineq = 1;
1666 	}
1667 	for (i = 0; i < min_constraints; ++i) {
1668 		struct isl_hash_table_entry *entry;
1669 		uint32_t c_hash;
1670 		c_hash = isl_seq_get_hash(constraints[i].c->row[0] + 1, total);
1671 		entry = isl_hash_table_find(hull->ctx, table, c_hash,
1672 			max_constraint_equal, constraints[i].c->row[0] + 1, 1);
1673 		if (!entry)
1674 			goto error;
1675 		isl_assert(hull->ctx, !entry->data, goto error);
1676 		entry->data = &constraints[i];
1677 	}
1678 
1679 	n = 0;
1680 	for (s = 0; s < set->n; ++s) {
1681 		if (s == best)
1682 			continue;
1683 
1684 		for (i = 0; i < set->p[s]->n_eq; ++i) {
1685 			isl_int *eq = set->p[s]->eq[i];
1686 			for (j = 0; j < 2; ++j) {
1687 				isl_seq_neg(eq, eq, 1 + total);
1688 				if (update_constraint(hull->ctx, table,
1689 						    eq, total, n, 0) < 0)
1690 					goto error;
1691 			}
1692 		}
1693 		for (i = 0; i < set->p[s]->n_ineq; ++i) {
1694 			isl_int *ineq = set->p[s]->ineq[i];
1695 			if (update_constraint(hull->ctx, table, ineq, total, n,
1696 					set->p[s]->n_eq == 0) < 0)
1697 				goto error;
1698 		}
1699 		++n;
1700 	}
1701 
1702 	for (i = 0; i < min_constraints; ++i) {
1703 		if (constraints[i].count < n)
1704 			continue;
1705 		if (!constraints[i].ineq)
1706 			continue;
1707 		j = isl_basic_set_alloc_inequality(hull);
1708 		if (j < 0)
1709 			goto error;
1710 		isl_seq_cpy(hull->ineq[j], constraints[i].c->row[0], 1 + total);
1711 	}
1712 
1713 	for (s = 0; s < set->n; ++s) {
1714 		if (set->p[s]->n_eq)
1715 			continue;
1716 		if (set->p[s]->n_ineq != hull->n_ineq)
1717 			continue;
1718 		for (i = 0; i < set->p[s]->n_ineq; ++i) {
1719 			isl_bool has;
1720 			isl_int *ineq = set->p[s]->ineq[i];
1721 			has = has_constraint(hull->ctx, table, ineq, total, n);
1722 			if (has < 0)
1723 				goto error;
1724 			if (!has)
1725 				break;
1726 		}
1727 		if (i == set->p[s]->n_ineq)
1728 			*is_hull = 1;
1729 	}
1730 
1731 	isl_hash_table_clear(table);
1732 	for (i = 0; i < min_constraints; ++i)
1733 		isl_mat_free(constraints[i].c);
1734 	free(constraints);
1735 	free(table);
1736 	return hull;
1737 error:
1738 	isl_hash_table_clear(table);
1739 	free(table);
1740 	if (constraints)
1741 		for (i = 0; i < min_constraints; ++i)
1742 			isl_mat_free(constraints[i].c);
1743 	free(constraints);
1744 	return hull;
1745 }
1746 
1747 /* Create a template for the convex hull of "set" and fill it up
1748  * obvious facet constraints, if any.  If the result happens to
1749  * be the convex hull of "set" then *is_hull is set to 1.
1750  */
proto_hull(__isl_keep isl_set * set,int * is_hull)1751 static __isl_give isl_basic_set *proto_hull(__isl_keep isl_set *set,
1752 	int *is_hull)
1753 {
1754 	struct isl_basic_set *hull;
1755 	unsigned n_ineq;
1756 	int i;
1757 
1758 	n_ineq = 1;
1759 	for (i = 0; i < set->n; ++i) {
1760 		n_ineq += set->p[i]->n_eq;
1761 		n_ineq += set->p[i]->n_ineq;
1762 	}
1763 	hull = isl_basic_set_alloc_space(isl_space_copy(set->dim), 0, 0, n_ineq);
1764 	hull = isl_basic_set_set_rational(hull);
1765 	if (!hull)
1766 		return NULL;
1767 	return common_constraints(hull, set, is_hull);
1768 }
1769 
uset_convex_hull_wrap(__isl_take isl_set * set)1770 static __isl_give isl_basic_set *uset_convex_hull_wrap(__isl_take isl_set *set)
1771 {
1772 	struct isl_basic_set *hull;
1773 	int is_hull;
1774 
1775 	hull = proto_hull(set, &is_hull);
1776 	if (hull && !is_hull) {
1777 		if (hull->n_ineq == 0)
1778 			hull = initial_hull(hull, set);
1779 		hull = extend(hull, set);
1780 	}
1781 	isl_set_free(set);
1782 
1783 	return hull;
1784 }
1785 
1786 /* Compute the convex hull of a set without any parameters or
1787  * integer divisions.  Depending on whether the set is bounded,
1788  * we pass control to the wrapping based convex hull or
1789  * the Fourier-Motzkin elimination based convex hull.
1790  * We also handle a few special cases before checking the boundedness.
1791  */
uset_convex_hull(__isl_take isl_set * set)1792 static __isl_give isl_basic_set *uset_convex_hull(__isl_take isl_set *set)
1793 {
1794 	isl_bool bounded;
1795 	isl_size dim;
1796 	struct isl_basic_set *convex_hull = NULL;
1797 	struct isl_basic_set *lin;
1798 
1799 	dim = isl_set_dim(set, isl_dim_all);
1800 	if (dim < 0)
1801 		goto error;
1802 	if (dim == 0)
1803 		return convex_hull_0d(set);
1804 
1805 	set = isl_set_coalesce(set);
1806 	set = isl_set_set_rational(set);
1807 
1808 	if (!set)
1809 		return NULL;
1810 	if (set->n == 1) {
1811 		convex_hull = isl_basic_set_copy(set->p[0]);
1812 		isl_set_free(set);
1813 		return convex_hull;
1814 	}
1815 	if (dim == 1)
1816 		return convex_hull_1d(set);
1817 
1818 	bounded = isl_set_is_bounded(set);
1819 	if (bounded < 0)
1820 		goto error;
1821 	if (bounded && set->ctx->opt->convex == ISL_CONVEX_HULL_WRAP)
1822 		return uset_convex_hull_wrap(set);
1823 
1824 	lin = isl_set_combined_lineality_space(isl_set_copy(set));
1825 	if (!lin)
1826 		goto error;
1827 	if (isl_basic_set_plain_is_universe(lin)) {
1828 		isl_set_free(set);
1829 		return lin;
1830 	}
1831 	if (lin->n_eq < dim)
1832 		return modulo_lineality(set, lin);
1833 	isl_basic_set_free(lin);
1834 
1835 	return uset_convex_hull_unbounded(set);
1836 error:
1837 	isl_set_free(set);
1838 	isl_basic_set_free(convex_hull);
1839 	return NULL;
1840 }
1841 
1842 /* This is the core procedure, where "set" is a "pure" set, i.e.,
1843  * without parameters or divs and where the convex hull of set is
1844  * known to be full-dimensional.
1845  */
uset_convex_hull_wrap_bounded(__isl_take isl_set * set)1846 static __isl_give isl_basic_set *uset_convex_hull_wrap_bounded(
1847 	__isl_take isl_set *set)
1848 {
1849 	struct isl_basic_set *convex_hull = NULL;
1850 	isl_size dim;
1851 
1852 	dim = isl_set_dim(set, isl_dim_all);
1853 	if (dim < 0)
1854 		goto error;
1855 
1856 	if (dim == 0) {
1857 		convex_hull = isl_basic_set_universe(isl_space_copy(set->dim));
1858 		isl_set_free(set);
1859 		convex_hull = isl_basic_set_set_rational(convex_hull);
1860 		return convex_hull;
1861 	}
1862 
1863 	set = isl_set_set_rational(set);
1864 	set = isl_set_coalesce(set);
1865 	if (!set)
1866 		goto error;
1867 	if (set->n == 1) {
1868 		convex_hull = isl_basic_set_copy(set->p[0]);
1869 		isl_set_free(set);
1870 		convex_hull = isl_basic_map_remove_redundancies(convex_hull);
1871 		return convex_hull;
1872 	}
1873 	if (dim == 1)
1874 		return convex_hull_1d(set);
1875 
1876 	return uset_convex_hull_wrap(set);
1877 error:
1878 	isl_set_free(set);
1879 	return NULL;
1880 }
1881 
1882 /* Compute the convex hull of set "set" with affine hull "affine_hull",
1883  * We first remove the equalities (transforming the set), compute the
1884  * convex hull of the transformed set and then add the equalities back
1885  * (after performing the inverse transformation.
1886  */
modulo_affine_hull(__isl_take isl_set * set,__isl_take isl_basic_set * affine_hull)1887 static __isl_give isl_basic_set *modulo_affine_hull(
1888 	__isl_take isl_set *set, __isl_take isl_basic_set *affine_hull)
1889 {
1890 	struct isl_mat *T;
1891 	struct isl_mat *T2;
1892 	struct isl_basic_set *dummy;
1893 	struct isl_basic_set *convex_hull;
1894 
1895 	dummy = isl_basic_set_remove_equalities(
1896 			isl_basic_set_copy(affine_hull), &T, &T2);
1897 	if (!dummy)
1898 		goto error;
1899 	isl_basic_set_free(dummy);
1900 	set = isl_set_preimage(set, T);
1901 	convex_hull = uset_convex_hull(set);
1902 	convex_hull = isl_basic_set_preimage(convex_hull, T2);
1903 	convex_hull = isl_basic_set_intersect(convex_hull, affine_hull);
1904 	return convex_hull;
1905 error:
1906 	isl_mat_free(T);
1907 	isl_mat_free(T2);
1908 	isl_basic_set_free(affine_hull);
1909 	isl_set_free(set);
1910 	return NULL;
1911 }
1912 
1913 /* Return an empty basic map living in the same space as "map".
1914  */
replace_map_by_empty_basic_map(__isl_take isl_map * map)1915 static __isl_give isl_basic_map *replace_map_by_empty_basic_map(
1916 	__isl_take isl_map *map)
1917 {
1918 	isl_space *space;
1919 
1920 	space = isl_map_get_space(map);
1921 	isl_map_free(map);
1922 	return isl_basic_map_empty(space);
1923 }
1924 
1925 /* Compute the convex hull of a map.
1926  *
1927  * The implementation was inspired by "Extended Convex Hull" by Fukuda et al.,
1928  * specifically, the wrapping of facets to obtain new facets.
1929  */
isl_map_convex_hull(__isl_take isl_map * map)1930 __isl_give isl_basic_map *isl_map_convex_hull(__isl_take isl_map *map)
1931 {
1932 	struct isl_basic_set *bset;
1933 	struct isl_basic_map *model = NULL;
1934 	struct isl_basic_set *affine_hull = NULL;
1935 	struct isl_basic_map *convex_hull = NULL;
1936 	struct isl_set *set = NULL;
1937 
1938 	map = isl_map_detect_equalities(map);
1939 	map = isl_map_align_divs_internal(map);
1940 	if (!map)
1941 		goto error;
1942 
1943 	if (map->n == 0)
1944 		return replace_map_by_empty_basic_map(map);
1945 
1946 	model = isl_basic_map_copy(map->p[0]);
1947 	set = isl_map_underlying_set(map);
1948 	if (!set)
1949 		goto error;
1950 
1951 	affine_hull = isl_set_affine_hull(isl_set_copy(set));
1952 	if (!affine_hull)
1953 		goto error;
1954 	if (affine_hull->n_eq != 0)
1955 		bset = modulo_affine_hull(set, affine_hull);
1956 	else {
1957 		isl_basic_set_free(affine_hull);
1958 		bset = uset_convex_hull(set);
1959 	}
1960 
1961 	convex_hull = isl_basic_map_overlying_set(bset, model);
1962 	if (!convex_hull)
1963 		return NULL;
1964 
1965 	ISL_F_SET(convex_hull, ISL_BASIC_MAP_NO_IMPLICIT);
1966 	ISL_F_SET(convex_hull, ISL_BASIC_MAP_ALL_EQUALITIES);
1967 	ISL_F_CLR(convex_hull, ISL_BASIC_MAP_RATIONAL);
1968 	return convex_hull;
1969 error:
1970 	isl_set_free(set);
1971 	isl_basic_map_free(model);
1972 	return NULL;
1973 }
1974 
isl_set_convex_hull(__isl_take isl_set * set)1975 __isl_give isl_basic_set *isl_set_convex_hull(__isl_take isl_set *set)
1976 {
1977 	return bset_from_bmap(isl_map_convex_hull(set_to_map(set)));
1978 }
1979 
isl_map_polyhedral_hull(__isl_take isl_map * map)1980 __isl_give isl_basic_map *isl_map_polyhedral_hull(__isl_take isl_map *map)
1981 {
1982 	isl_basic_map *hull;
1983 
1984 	hull = isl_map_convex_hull(map);
1985 	return isl_basic_map_remove_divs(hull);
1986 }
1987 
isl_set_polyhedral_hull(__isl_take isl_set * set)1988 __isl_give isl_basic_set *isl_set_polyhedral_hull(__isl_take isl_set *set)
1989 {
1990 	return bset_from_bmap(isl_map_polyhedral_hull(set_to_map(set)));
1991 }
1992 
1993 struct sh_data_entry {
1994 	struct isl_hash_table	*table;
1995 	struct isl_tab		*tab;
1996 };
1997 
1998 /* Holds the data needed during the simple hull computation.
1999  * In particular,
2000  *	n		the number of basic sets in the original set
2001  *	hull_table	a hash table of already computed constraints
2002  *			in the simple hull
2003  *	p		for each basic set,
2004  *		table		a hash table of the constraints
2005  *		tab		the tableau corresponding to the basic set
2006  */
2007 struct sh_data {
2008 	struct isl_ctx		*ctx;
2009 	unsigned		n;
2010 	struct isl_hash_table	*hull_table;
2011 	struct sh_data_entry	p[1];
2012 };
2013 
sh_data_free(struct sh_data * data)2014 static void sh_data_free(struct sh_data *data)
2015 {
2016 	int i;
2017 
2018 	if (!data)
2019 		return;
2020 	isl_hash_table_free(data->ctx, data->hull_table);
2021 	for (i = 0; i < data->n; ++i) {
2022 		isl_hash_table_free(data->ctx, data->p[i].table);
2023 		isl_tab_free(data->p[i].tab);
2024 	}
2025 	free(data);
2026 }
2027 
2028 struct ineq_cmp_data {
2029 	unsigned	len;
2030 	isl_int		*p;
2031 };
2032 
has_ineq(const void * entry,const void * val)2033 static isl_bool has_ineq(const void *entry, const void *val)
2034 {
2035 	isl_int *row = (isl_int *)entry;
2036 	struct ineq_cmp_data *v = (struct ineq_cmp_data *)val;
2037 
2038 	return isl_bool_ok(isl_seq_eq(row + 1, v->p + 1, v->len) ||
2039 			   isl_seq_is_neg(row + 1, v->p + 1, v->len));
2040 }
2041 
hash_ineq(struct isl_ctx * ctx,struct isl_hash_table * table,isl_int * ineq,unsigned len)2042 static int hash_ineq(struct isl_ctx *ctx, struct isl_hash_table *table,
2043 			isl_int *ineq, unsigned len)
2044 {
2045 	uint32_t c_hash;
2046 	struct ineq_cmp_data v;
2047 	struct isl_hash_table_entry *entry;
2048 
2049 	v.len = len;
2050 	v.p = ineq;
2051 	c_hash = isl_seq_get_hash(ineq + 1, len);
2052 	entry = isl_hash_table_find(ctx, table, c_hash, has_ineq, &v, 1);
2053 	if (!entry)
2054 		return - 1;
2055 	entry->data = ineq;
2056 	return 0;
2057 }
2058 
2059 /* Fill hash table "table" with the constraints of "bset".
2060  * Equalities are added as two inequalities.
2061  * The value in the hash table is a pointer to the (in)equality of "bset".
2062  */
hash_basic_set(struct isl_hash_table * table,__isl_keep isl_basic_set * bset)2063 static isl_stat hash_basic_set(struct isl_hash_table *table,
2064 	__isl_keep isl_basic_set *bset)
2065 {
2066 	int i, j;
2067 	isl_size dim = isl_basic_set_dim(bset, isl_dim_all);
2068 
2069 	if (dim < 0)
2070 		return isl_stat_error;
2071 	for (i = 0; i < bset->n_eq; ++i) {
2072 		for (j = 0; j < 2; ++j) {
2073 			isl_seq_neg(bset->eq[i], bset->eq[i], 1 + dim);
2074 			if (hash_ineq(bset->ctx, table, bset->eq[i], dim) < 0)
2075 				return isl_stat_error;
2076 		}
2077 	}
2078 	for (i = 0; i < bset->n_ineq; ++i) {
2079 		if (hash_ineq(bset->ctx, table, bset->ineq[i], dim) < 0)
2080 			return isl_stat_error;
2081 	}
2082 	return isl_stat_ok;
2083 }
2084 
sh_data_alloc(__isl_keep isl_set * set,unsigned n_ineq)2085 static struct sh_data *sh_data_alloc(__isl_keep isl_set *set, unsigned n_ineq)
2086 {
2087 	struct sh_data *data;
2088 	int i;
2089 
2090 	data = isl_calloc(set->ctx, struct sh_data,
2091 		sizeof(struct sh_data) +
2092 		(set->n - 1) * sizeof(struct sh_data_entry));
2093 	if (!data)
2094 		return NULL;
2095 	data->ctx = set->ctx;
2096 	data->n = set->n;
2097 	data->hull_table = isl_hash_table_alloc(set->ctx, n_ineq);
2098 	if (!data->hull_table)
2099 		goto error;
2100 	for (i = 0; i < set->n; ++i) {
2101 		data->p[i].table = isl_hash_table_alloc(set->ctx,
2102 				    2 * set->p[i]->n_eq + set->p[i]->n_ineq);
2103 		if (!data->p[i].table)
2104 			goto error;
2105 		if (hash_basic_set(data->p[i].table, set->p[i]) < 0)
2106 			goto error;
2107 	}
2108 	return data;
2109 error:
2110 	sh_data_free(data);
2111 	return NULL;
2112 }
2113 
2114 /* Check if inequality "ineq" is a bound for basic set "j" or if
2115  * it can be relaxed (by increasing the constant term) to become
2116  * a bound for that basic set.  In the latter case, the constant
2117  * term is updated.
2118  * Relaxation of the constant term is only allowed if "shift" is set.
2119  *
2120  * Return 1 if "ineq" is a bound
2121  *	  0 if "ineq" may attain arbitrarily small values on basic set "j"
2122  *	 -1 if some error occurred
2123  */
is_bound(struct sh_data * data,__isl_keep isl_set * set,int j,isl_int * ineq,int shift)2124 static int is_bound(struct sh_data *data, __isl_keep isl_set *set, int j,
2125 	isl_int *ineq, int shift)
2126 {
2127 	enum isl_lp_result res;
2128 	isl_int opt;
2129 
2130 	if (!data->p[j].tab) {
2131 		data->p[j].tab = isl_tab_from_basic_set(set->p[j], 0);
2132 		if (!data->p[j].tab)
2133 			return -1;
2134 	}
2135 
2136 	isl_int_init(opt);
2137 
2138 	res = isl_tab_min(data->p[j].tab, ineq, data->ctx->one,
2139 				&opt, NULL, 0);
2140 	if (res == isl_lp_ok && isl_int_is_neg(opt)) {
2141 		if (shift)
2142 			isl_int_sub(ineq[0], ineq[0], opt);
2143 		else
2144 			res = isl_lp_unbounded;
2145 	}
2146 
2147 	isl_int_clear(opt);
2148 
2149 	return (res == isl_lp_ok || res == isl_lp_empty) ? 1 :
2150 	       res == isl_lp_unbounded ? 0 : -1;
2151 }
2152 
2153 /* Set the constant term of "ineq" to the maximum of those of the constraints
2154  * in the basic sets of "set" following "i" that are parallel to "ineq".
2155  * That is, if any of the basic sets of "set" following "i" have a more
2156  * relaxed copy of "ineq", then replace "ineq" by the most relaxed copy.
2157  * "c_hash" is the hash value of the linear part of "ineq".
2158  * "v" has been set up for use by has_ineq.
2159  *
2160  * Note that the two inequality constraints corresponding to an equality are
2161  * represented by the same inequality constraint in data->p[j].table
2162  * (but with different hash values).  This means the constraint (or at
2163  * least its constant term) may need to be temporarily negated to get
2164  * the actually hashed constraint.
2165  */
set_max_constant_term(struct sh_data * data,__isl_keep isl_set * set,int i,isl_int * ineq,uint32_t c_hash,struct ineq_cmp_data * v)2166 static isl_stat set_max_constant_term(struct sh_data *data,
2167 	__isl_keep isl_set *set,
2168 	int i, isl_int *ineq, uint32_t c_hash, struct ineq_cmp_data *v)
2169 {
2170 	int j;
2171 	isl_ctx *ctx;
2172 	struct isl_hash_table_entry *entry;
2173 
2174 	ctx = isl_set_get_ctx(set);
2175 	for (j = i + 1; j < set->n; ++j) {
2176 		int neg;
2177 		isl_int *ineq_j;
2178 
2179 		entry = isl_hash_table_find(ctx, data->p[j].table,
2180 						c_hash, &has_ineq, v, 0);
2181 		if (!entry)
2182 			return isl_stat_error;
2183 		if (entry == isl_hash_table_entry_none)
2184 			continue;
2185 
2186 		ineq_j = entry->data;
2187 		neg = isl_seq_is_neg(ineq_j + 1, ineq + 1, v->len);
2188 		if (neg)
2189 			isl_int_neg(ineq_j[0], ineq_j[0]);
2190 		if (isl_int_gt(ineq_j[0], ineq[0]))
2191 			isl_int_set(ineq[0], ineq_j[0]);
2192 		if (neg)
2193 			isl_int_neg(ineq_j[0], ineq_j[0]);
2194 	}
2195 
2196 	return isl_stat_ok;
2197 }
2198 
2199 /* Check if inequality "ineq" from basic set "i" is or can be relaxed to
2200  * become a bound on the whole set.  If so, add the (relaxed) inequality
2201  * to "hull".  Relaxation is only allowed if "shift" is set.
2202  *
2203  * We first check if "hull" already contains a translate of the inequality.
2204  * If so, we are done.
2205  * Then, we check if any of the previous basic sets contains a translate
2206  * of the inequality.  If so, then we have already considered this
2207  * inequality and we are done.
2208  * Otherwise, for each basic set other than "i", we check if the inequality
2209  * is a bound on the basic set, but first replace the constant term
2210  * by the maximal value of any translate of the inequality in any
2211  * of the following basic sets.
2212  * For previous basic sets, we know that they do not contain a translate
2213  * of the inequality, so we directly call is_bound.
2214  * For following basic sets, we first check if a translate of the
2215  * inequality appears in its description.  If so, the constant term
2216  * of the inequality has already been updated with respect to this
2217  * translate and the inequality is therefore known to be a bound
2218  * of this basic set.
2219  */
add_bound(__isl_take isl_basic_set * hull,struct sh_data * data,__isl_keep isl_set * set,int i,isl_int * ineq,int shift)2220 static __isl_give isl_basic_set *add_bound(__isl_take isl_basic_set *hull,
2221 	struct sh_data *data, __isl_keep isl_set *set, int i, isl_int *ineq,
2222 	int shift)
2223 {
2224 	uint32_t c_hash;
2225 	struct ineq_cmp_data v;
2226 	struct isl_hash_table_entry *entry;
2227 	int j, k;
2228 	isl_size total;
2229 
2230 	total = isl_basic_set_dim(hull, isl_dim_all);
2231 	if (total < 0)
2232 		return isl_basic_set_free(hull);
2233 
2234 	v.len = total;
2235 	v.p = ineq;
2236 	c_hash = isl_seq_get_hash(ineq + 1, v.len);
2237 
2238 	entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
2239 					has_ineq, &v, 0);
2240 	if (!entry)
2241 		return isl_basic_set_free(hull);
2242 	if (entry != isl_hash_table_entry_none)
2243 		return hull;
2244 
2245 	for (j = 0; j < i; ++j) {
2246 		entry = isl_hash_table_find(hull->ctx, data->p[j].table,
2247 						c_hash, has_ineq, &v, 0);
2248 		if (!entry)
2249 			return isl_basic_set_free(hull);
2250 		if (entry != isl_hash_table_entry_none)
2251 			break;
2252 	}
2253 	if (j < i)
2254 		return hull;
2255 
2256 	k = isl_basic_set_alloc_inequality(hull);
2257 	if (k < 0)
2258 		goto error;
2259 	isl_seq_cpy(hull->ineq[k], ineq, 1 + v.len);
2260 
2261 	if (set_max_constant_term(data, set, i, hull->ineq[k], c_hash, &v) < 0)
2262 		goto error;
2263 	for (j = 0; j < i; ++j) {
2264 		int bound;
2265 		bound = is_bound(data, set, j, hull->ineq[k], shift);
2266 		if (bound < 0)
2267 			goto error;
2268 		if (!bound)
2269 			break;
2270 	}
2271 	if (j < i)
2272 		return isl_basic_set_free_inequality(hull, 1);
2273 
2274 	for (j = i + 1; j < set->n; ++j) {
2275 		int bound;
2276 		entry = isl_hash_table_find(hull->ctx, data->p[j].table,
2277 						c_hash, has_ineq, &v, 0);
2278 		if (!entry)
2279 			return isl_basic_set_free(hull);
2280 		if (entry != isl_hash_table_entry_none)
2281 			continue;
2282 		bound = is_bound(data, set, j, hull->ineq[k], shift);
2283 		if (bound < 0)
2284 			goto error;
2285 		if (!bound)
2286 			break;
2287 	}
2288 	if (j < set->n)
2289 		return isl_basic_set_free_inequality(hull, 1);
2290 
2291 	entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
2292 					has_ineq, &v, 1);
2293 	if (!entry)
2294 		goto error;
2295 	entry->data = hull->ineq[k];
2296 
2297 	return hull;
2298 error:
2299 	isl_basic_set_free(hull);
2300 	return NULL;
2301 }
2302 
2303 /* Check if any inequality from basic set "i" is or can be relaxed to
2304  * become a bound on the whole set.  If so, add the (relaxed) inequality
2305  * to "hull".  Relaxation is only allowed if "shift" is set.
2306  */
add_bounds(__isl_take isl_basic_set * bset,struct sh_data * data,__isl_keep isl_set * set,int i,int shift)2307 static __isl_give isl_basic_set *add_bounds(__isl_take isl_basic_set *bset,
2308 	struct sh_data *data, __isl_keep isl_set *set, int i, int shift)
2309 {
2310 	int j, k;
2311 	isl_size dim = isl_basic_set_dim(bset, isl_dim_all);
2312 
2313 	if (dim < 0)
2314 		return isl_basic_set_free(bset);
2315 
2316 	for (j = 0; j < set->p[i]->n_eq; ++j) {
2317 		for (k = 0; k < 2; ++k) {
2318 			isl_seq_neg(set->p[i]->eq[j], set->p[i]->eq[j], 1+dim);
2319 			bset = add_bound(bset, data, set, i, set->p[i]->eq[j],
2320 					    shift);
2321 		}
2322 	}
2323 	for (j = 0; j < set->p[i]->n_ineq; ++j)
2324 		bset = add_bound(bset, data, set, i, set->p[i]->ineq[j], shift);
2325 	return bset;
2326 }
2327 
2328 /* Compute a superset of the convex hull of set that is described
2329  * by only (translates of) the constraints in the constituents of set.
2330  * Translation is only allowed if "shift" is set.
2331  */
uset_simple_hull(__isl_take isl_set * set,int shift)2332 static __isl_give isl_basic_set *uset_simple_hull(__isl_take isl_set *set,
2333 	int shift)
2334 {
2335 	struct sh_data *data = NULL;
2336 	struct isl_basic_set *hull = NULL;
2337 	unsigned n_ineq;
2338 	int i;
2339 
2340 	if (!set)
2341 		return NULL;
2342 
2343 	n_ineq = 0;
2344 	for (i = 0; i < set->n; ++i) {
2345 		if (!set->p[i])
2346 			goto error;
2347 		n_ineq += 2 * set->p[i]->n_eq + set->p[i]->n_ineq;
2348 	}
2349 
2350 	hull = isl_basic_set_alloc_space(isl_space_copy(set->dim), 0, 0, n_ineq);
2351 	if (!hull)
2352 		goto error;
2353 
2354 	data = sh_data_alloc(set, n_ineq);
2355 	if (!data)
2356 		goto error;
2357 
2358 	for (i = 0; i < set->n; ++i)
2359 		hull = add_bounds(hull, data, set, i, shift);
2360 
2361 	sh_data_free(data);
2362 	isl_set_free(set);
2363 
2364 	return hull;
2365 error:
2366 	sh_data_free(data);
2367 	isl_basic_set_free(hull);
2368 	isl_set_free(set);
2369 	return NULL;
2370 }
2371 
2372 /* Compute a superset of the convex hull of map that is described
2373  * by only (translates of) the constraints in the constituents of map.
2374  * Handle trivial cases where map is NULL or contains at most one disjunct.
2375  */
map_simple_hull_trivial(__isl_take isl_map * map)2376 static __isl_give isl_basic_map *map_simple_hull_trivial(
2377 	__isl_take isl_map *map)
2378 {
2379 	isl_basic_map *hull;
2380 
2381 	if (!map)
2382 		return NULL;
2383 	if (map->n == 0)
2384 		return replace_map_by_empty_basic_map(map);
2385 
2386 	hull = isl_basic_map_copy(map->p[0]);
2387 	isl_map_free(map);
2388 	return hull;
2389 }
2390 
2391 /* Return a copy of the simple hull cached inside "map".
2392  * "shift" determines whether to return the cached unshifted or shifted
2393  * simple hull.
2394  */
cached_simple_hull(__isl_take isl_map * map,int shift)2395 static __isl_give isl_basic_map *cached_simple_hull(__isl_take isl_map *map,
2396 	int shift)
2397 {
2398 	isl_basic_map *hull;
2399 
2400 	hull = isl_basic_map_copy(map->cached_simple_hull[shift]);
2401 	isl_map_free(map);
2402 
2403 	return hull;
2404 }
2405 
2406 /* Compute a superset of the convex hull of map that is described
2407  * by only (translates of) the constraints in the constituents of map.
2408  * Translation is only allowed if "shift" is set.
2409  *
2410  * The constraints are sorted while removing redundant constraints
2411  * in order to indicate a preference of which constraints should
2412  * be preserved.  In particular, pairs of constraints that are
2413  * sorted together are preferred to either both be preserved
2414  * or both be removed.  The sorting is performed inside
2415  * isl_basic_map_remove_redundancies.
2416  *
2417  * The result of the computation is stored in map->cached_simple_hull[shift]
2418  * such that it can be reused in subsequent calls.  The cache is cleared
2419  * whenever the map is modified (in isl_map_cow).
2420  * Note that the results need to be stored in the input map for there
2421  * to be any chance that they may get reused.  In particular, they
2422  * are stored in a copy of the input map that is saved before
2423  * the integer division alignment.
2424  */
map_simple_hull(__isl_take isl_map * map,int shift)2425 static __isl_give isl_basic_map *map_simple_hull(__isl_take isl_map *map,
2426 	int shift)
2427 {
2428 	struct isl_set *set = NULL;
2429 	struct isl_basic_map *model = NULL;
2430 	struct isl_basic_map *hull;
2431 	struct isl_basic_map *affine_hull;
2432 	struct isl_basic_set *bset = NULL;
2433 	isl_map *input;
2434 
2435 	if (!map || map->n <= 1)
2436 		return map_simple_hull_trivial(map);
2437 
2438 	if (map->cached_simple_hull[shift])
2439 		return cached_simple_hull(map, shift);
2440 
2441 	map = isl_map_detect_equalities(map);
2442 	if (!map || map->n <= 1)
2443 		return map_simple_hull_trivial(map);
2444 	affine_hull = isl_map_affine_hull(isl_map_copy(map));
2445 	input = isl_map_copy(map);
2446 	map = isl_map_align_divs_internal(map);
2447 	model = map ? isl_basic_map_copy(map->p[0]) : NULL;
2448 
2449 	set = isl_map_underlying_set(map);
2450 
2451 	bset = uset_simple_hull(set, shift);
2452 
2453 	hull = isl_basic_map_overlying_set(bset, model);
2454 
2455 	hull = isl_basic_map_intersect(hull, affine_hull);
2456 	hull = isl_basic_map_remove_redundancies(hull);
2457 
2458 	if (hull) {
2459 		ISL_F_SET(hull, ISL_BASIC_MAP_NO_IMPLICIT);
2460 		ISL_F_SET(hull, ISL_BASIC_MAP_ALL_EQUALITIES);
2461 	}
2462 
2463 	hull = isl_basic_map_finalize(hull);
2464 	if (input)
2465 		input->cached_simple_hull[shift] = isl_basic_map_copy(hull);
2466 	isl_map_free(input);
2467 
2468 	return hull;
2469 }
2470 
2471 /* Compute a superset of the convex hull of map that is described
2472  * by only translates of the constraints in the constituents of map.
2473  */
isl_map_simple_hull(__isl_take isl_map * map)2474 __isl_give isl_basic_map *isl_map_simple_hull(__isl_take isl_map *map)
2475 {
2476 	return map_simple_hull(map, 1);
2477 }
2478 
isl_set_simple_hull(__isl_take isl_set * set)2479 __isl_give isl_basic_set *isl_set_simple_hull(__isl_take isl_set *set)
2480 {
2481 	return bset_from_bmap(isl_map_simple_hull(set_to_map(set)));
2482 }
2483 
2484 /* Compute a superset of the convex hull of map that is described
2485  * by only the constraints in the constituents of map.
2486  */
isl_map_unshifted_simple_hull(__isl_take isl_map * map)2487 __isl_give isl_basic_map *isl_map_unshifted_simple_hull(
2488 	__isl_take isl_map *map)
2489 {
2490 	return map_simple_hull(map, 0);
2491 }
2492 
isl_set_unshifted_simple_hull(__isl_take isl_set * set)2493 __isl_give isl_basic_set *isl_set_unshifted_simple_hull(
2494 	__isl_take isl_set *set)
2495 {
2496 	return isl_map_unshifted_simple_hull(set);
2497 }
2498 
2499 /* Drop all inequalities from "bmap1" that do not also appear in "bmap2".
2500  * A constraint that appears with different constant terms
2501  * in "bmap1" and "bmap2" is also kept, with the least restrictive
2502  * (i.e., greatest) constant term.
2503  * "bmap1" and "bmap2" are assumed to have the same (known)
2504  * integer divisions.
2505  * The constraints of both "bmap1" and "bmap2" are assumed
2506  * to have been sorted using isl_basic_map_sort_constraints.
2507  *
2508  * Run through the inequality constraints of "bmap1" and "bmap2"
2509  * in sorted order.
2510  * Each constraint of "bmap1" without a matching constraint in "bmap2"
2511  * is removed.
2512  * If a match is found, the constraint is kept.  If needed, the constant
2513  * term of the constraint is adjusted.
2514  */
select_shared_inequalities(__isl_take isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)2515 static __isl_give isl_basic_map *select_shared_inequalities(
2516 	__isl_take isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
2517 {
2518 	int i1, i2;
2519 
2520 	bmap1 = isl_basic_map_cow(bmap1);
2521 	if (!bmap1 || !bmap2)
2522 		return isl_basic_map_free(bmap1);
2523 
2524 	i1 = bmap1->n_ineq - 1;
2525 	i2 = bmap2->n_ineq - 1;
2526 	while (bmap1 && i1 >= 0 && i2 >= 0) {
2527 		int cmp;
2528 
2529 		cmp = isl_basic_map_constraint_cmp(bmap1, bmap1->ineq[i1],
2530 							bmap2->ineq[i2]);
2531 		if (cmp < 0) {
2532 			--i2;
2533 			continue;
2534 		}
2535 		if (cmp > 0) {
2536 			if (isl_basic_map_drop_inequality(bmap1, i1) < 0)
2537 				bmap1 = isl_basic_map_free(bmap1);
2538 			--i1;
2539 			continue;
2540 		}
2541 		if (isl_int_lt(bmap1->ineq[i1][0], bmap2->ineq[i2][0]))
2542 			isl_int_set(bmap1->ineq[i1][0], bmap2->ineq[i2][0]);
2543 		--i1;
2544 		--i2;
2545 	}
2546 	for (; i1 >= 0; --i1)
2547 		if (isl_basic_map_drop_inequality(bmap1, i1) < 0)
2548 			bmap1 = isl_basic_map_free(bmap1);
2549 
2550 	return bmap1;
2551 }
2552 
2553 /* Drop all equalities from "bmap1" that do not also appear in "bmap2".
2554  * "bmap1" and "bmap2" are assumed to have the same (known)
2555  * integer divisions.
2556  *
2557  * Run through the equality constraints of "bmap1" and "bmap2".
2558  * Each constraint of "bmap1" without a matching constraint in "bmap2"
2559  * is removed.
2560  */
select_shared_equalities(__isl_take isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)2561 static __isl_give isl_basic_map *select_shared_equalities(
2562 	__isl_take isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
2563 {
2564 	int i1, i2;
2565 	isl_size total;
2566 
2567 	bmap1 = isl_basic_map_cow(bmap1);
2568 	total = isl_basic_map_dim(bmap1, isl_dim_all);
2569 	if (total < 0 || !bmap2)
2570 		return isl_basic_map_free(bmap1);
2571 
2572 	i1 = bmap1->n_eq - 1;
2573 	i2 = bmap2->n_eq - 1;
2574 	while (bmap1 && i1 >= 0 && i2 >= 0) {
2575 		int last1, last2;
2576 
2577 		last1 = isl_seq_last_non_zero(bmap1->eq[i1] + 1, total);
2578 		last2 = isl_seq_last_non_zero(bmap2->eq[i2] + 1, total);
2579 		if (last1 > last2) {
2580 			--i2;
2581 			continue;
2582 		}
2583 		if (last1 < last2) {
2584 			if (isl_basic_map_drop_equality(bmap1, i1) < 0)
2585 				bmap1 = isl_basic_map_free(bmap1);
2586 			--i1;
2587 			continue;
2588 		}
2589 		if (!isl_seq_eq(bmap1->eq[i1], bmap2->eq[i2], 1 + total)) {
2590 			if (isl_basic_map_drop_equality(bmap1, i1) < 0)
2591 				bmap1 = isl_basic_map_free(bmap1);
2592 		}
2593 		--i1;
2594 		--i2;
2595 	}
2596 	for (; i1 >= 0; --i1)
2597 		if (isl_basic_map_drop_equality(bmap1, i1) < 0)
2598 			bmap1 = isl_basic_map_free(bmap1);
2599 
2600 	return bmap1;
2601 }
2602 
2603 /* Compute a superset of "bmap1" and "bmap2" that is described
2604  * by only the constraints that appear in both "bmap1" and "bmap2".
2605  *
2606  * First drop constraints that involve unknown integer divisions
2607  * since it is not trivial to check whether two such integer divisions
2608  * in different basic maps are the same.
2609  * Then align the remaining (known) divs and sort the constraints.
2610  * Finally drop all inequalities and equalities from "bmap1" that
2611  * do not also appear in "bmap2".
2612  */
isl_basic_map_plain_unshifted_simple_hull(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)2613 __isl_give isl_basic_map *isl_basic_map_plain_unshifted_simple_hull(
2614 	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
2615 {
2616 	if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
2617 		goto error;
2618 
2619 	bmap1 = isl_basic_map_drop_constraints_involving_unknown_divs(bmap1);
2620 	bmap2 = isl_basic_map_drop_constraints_involving_unknown_divs(bmap2);
2621 	bmap2 = isl_basic_map_align_divs(bmap2, bmap1);
2622 	bmap1 = isl_basic_map_align_divs(bmap1, bmap2);
2623 	bmap1 = isl_basic_map_sort_constraints(bmap1);
2624 	bmap2 = isl_basic_map_sort_constraints(bmap2);
2625 
2626 	bmap1 = select_shared_inequalities(bmap1, bmap2);
2627 	bmap1 = select_shared_equalities(bmap1, bmap2);
2628 
2629 	isl_basic_map_free(bmap2);
2630 	bmap1 = isl_basic_map_finalize(bmap1);
2631 	return bmap1;
2632 error:
2633 	isl_basic_map_free(bmap1);
2634 	isl_basic_map_free(bmap2);
2635 	return NULL;
2636 }
2637 
2638 /* Compute a superset of the convex hull of "map" that is described
2639  * by only the constraints in the constituents of "map".
2640  * In particular, the result is composed of constraints that appear
2641  * in each of the basic maps of "map"
2642  *
2643  * Constraints that involve unknown integer divisions are dropped
2644  * since it is not trivial to check whether two such integer divisions
2645  * in different basic maps are the same.
2646  *
2647  * The hull is initialized from the first basic map and then
2648  * updated with respect to the other basic maps in turn.
2649  */
isl_map_plain_unshifted_simple_hull(__isl_take isl_map * map)2650 __isl_give isl_basic_map *isl_map_plain_unshifted_simple_hull(
2651 	__isl_take isl_map *map)
2652 {
2653 	int i;
2654 	isl_basic_map *hull;
2655 
2656 	if (!map)
2657 		return NULL;
2658 	if (map->n <= 1)
2659 		return map_simple_hull_trivial(map);
2660 	map = isl_map_drop_constraints_involving_unknown_divs(map);
2661 	hull = isl_basic_map_copy(map->p[0]);
2662 	for (i = 1; i < map->n; ++i) {
2663 		isl_basic_map *bmap_i;
2664 
2665 		bmap_i = isl_basic_map_copy(map->p[i]);
2666 		hull = isl_basic_map_plain_unshifted_simple_hull(hull, bmap_i);
2667 	}
2668 
2669 	isl_map_free(map);
2670 	return hull;
2671 }
2672 
2673 /* Compute a superset of the convex hull of "set" that is described
2674  * by only the constraints in the constituents of "set".
2675  * In particular, the result is composed of constraints that appear
2676  * in each of the basic sets of "set"
2677  */
isl_set_plain_unshifted_simple_hull(__isl_take isl_set * set)2678 __isl_give isl_basic_set *isl_set_plain_unshifted_simple_hull(
2679 	__isl_take isl_set *set)
2680 {
2681 	return isl_map_plain_unshifted_simple_hull(set);
2682 }
2683 
2684 /* Check if "ineq" is a bound on "set" and, if so, add it to "hull".
2685  *
2686  * For each basic set in "set", we first check if the basic set
2687  * contains a translate of "ineq".  If this translate is more relaxed,
2688  * then we assume that "ineq" is not a bound on this basic set.
2689  * Otherwise, we know that it is a bound.
2690  * If the basic set does not contain a translate of "ineq", then
2691  * we call is_bound to perform the test.
2692  */
add_bound_from_constraint(__isl_take isl_basic_set * hull,struct sh_data * data,__isl_keep isl_set * set,isl_int * ineq)2693 static __isl_give isl_basic_set *add_bound_from_constraint(
2694 	__isl_take isl_basic_set *hull, struct sh_data *data,
2695 	__isl_keep isl_set *set, isl_int *ineq)
2696 {
2697 	int i, k;
2698 	isl_ctx *ctx;
2699 	uint32_t c_hash;
2700 	struct ineq_cmp_data v;
2701 	isl_size total;
2702 
2703 	total = isl_basic_set_dim(hull, isl_dim_all);
2704 	if (total < 0 || !set)
2705 		return isl_basic_set_free(hull);
2706 
2707 	v.len = total;
2708 	v.p = ineq;
2709 	c_hash = isl_seq_get_hash(ineq + 1, v.len);
2710 
2711 	ctx = isl_basic_set_get_ctx(hull);
2712 	for (i = 0; i < set->n; ++i) {
2713 		int bound;
2714 		struct isl_hash_table_entry *entry;
2715 
2716 		entry = isl_hash_table_find(ctx, data->p[i].table,
2717 						c_hash, &has_ineq, &v, 0);
2718 		if (!entry)
2719 			return isl_basic_set_free(hull);
2720 		if (entry != isl_hash_table_entry_none) {
2721 			isl_int *ineq_i = entry->data;
2722 			int neg, more_relaxed;
2723 
2724 			neg = isl_seq_is_neg(ineq_i + 1, ineq + 1, v.len);
2725 			if (neg)
2726 				isl_int_neg(ineq_i[0], ineq_i[0]);
2727 			more_relaxed = isl_int_gt(ineq_i[0], ineq[0]);
2728 			if (neg)
2729 				isl_int_neg(ineq_i[0], ineq_i[0]);
2730 			if (more_relaxed)
2731 				break;
2732 			else
2733 				continue;
2734 		}
2735 		bound = is_bound(data, set, i, ineq, 0);
2736 		if (bound < 0)
2737 			return isl_basic_set_free(hull);
2738 		if (!bound)
2739 			break;
2740 	}
2741 	if (i < set->n)
2742 		return hull;
2743 
2744 	k = isl_basic_set_alloc_inequality(hull);
2745 	if (k < 0)
2746 		return isl_basic_set_free(hull);
2747 	isl_seq_cpy(hull->ineq[k], ineq, 1 + v.len);
2748 
2749 	return hull;
2750 }
2751 
2752 /* Compute a superset of the convex hull of "set" that is described
2753  * by only some of the "n_ineq" constraints in the list "ineq", where "set"
2754  * has no parameters or integer divisions.
2755  *
2756  * The inequalities in "ineq" are assumed to have been sorted such
2757  * that constraints with the same linear part appear together and
2758  * that among constraints with the same linear part, those with
2759  * smaller constant term appear first.
2760  *
2761  * We reuse the same data structure that is used by uset_simple_hull,
2762  * but we do not need the hull table since we will not consider the
2763  * same constraint more than once.  We therefore allocate it with zero size.
2764  *
2765  * We run through the constraints and try to add them one by one,
2766  * skipping identical constraints.  If we have added a constraint and
2767  * the next constraint is a more relaxed translate, then we skip this
2768  * next constraint as well.
2769  */
uset_unshifted_simple_hull_from_constraints(__isl_take isl_set * set,int n_ineq,isl_int ** ineq)2770 static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_constraints(
2771 	__isl_take isl_set *set, int n_ineq, isl_int **ineq)
2772 {
2773 	int i;
2774 	int last_added = 0;
2775 	struct sh_data *data = NULL;
2776 	isl_basic_set *hull = NULL;
2777 	isl_size dim;
2778 
2779 	hull = isl_basic_set_alloc_space(isl_set_get_space(set), 0, 0, n_ineq);
2780 	if (!hull)
2781 		goto error;
2782 
2783 	data = sh_data_alloc(set, 0);
2784 	if (!data)
2785 		goto error;
2786 
2787 	dim = isl_set_dim(set, isl_dim_set);
2788 	if (dim < 0)
2789 		goto error;
2790 	for (i = 0; i < n_ineq; ++i) {
2791 		int hull_n_ineq = hull->n_ineq;
2792 		int parallel;
2793 
2794 		parallel = i > 0 && isl_seq_eq(ineq[i - 1] + 1, ineq[i] + 1,
2795 						dim);
2796 		if (parallel &&
2797 		    (last_added || isl_int_eq(ineq[i - 1][0], ineq[i][0])))
2798 			continue;
2799 		hull = add_bound_from_constraint(hull, data, set, ineq[i]);
2800 		if (!hull)
2801 			goto error;
2802 		last_added = hull->n_ineq > hull_n_ineq;
2803 	}
2804 
2805 	sh_data_free(data);
2806 	isl_set_free(set);
2807 	return hull;
2808 error:
2809 	sh_data_free(data);
2810 	isl_set_free(set);
2811 	isl_basic_set_free(hull);
2812 	return NULL;
2813 }
2814 
2815 /* Collect pointers to all the inequalities in the elements of "list"
2816  * in "ineq".  For equalities, store both a pointer to the equality and
2817  * a pointer to its opposite, which is first copied to "mat".
2818  * "ineq" and "mat" are assumed to have been preallocated to the right size
2819  * (the number of inequalities + 2 times the number of equalites and
2820  * the number of equalities, respectively).
2821  */
collect_inequalities(__isl_take isl_mat * mat,__isl_keep isl_basic_set_list * list,isl_int ** ineq)2822 static __isl_give isl_mat *collect_inequalities(__isl_take isl_mat *mat,
2823 	__isl_keep isl_basic_set_list *list, isl_int **ineq)
2824 {
2825 	int i, j, n_eq, n_ineq;
2826 	isl_size n;
2827 
2828 	n = isl_basic_set_list_n_basic_set(list);
2829 	if (!mat || n < 0)
2830 		return isl_mat_free(mat);
2831 
2832 	n_eq = 0;
2833 	n_ineq = 0;
2834 	for (i = 0; i < n; ++i) {
2835 		isl_basic_set *bset;
2836 		bset = isl_basic_set_list_get_basic_set(list, i);
2837 		if (!bset)
2838 			return isl_mat_free(mat);
2839 		for (j = 0; j < bset->n_eq; ++j) {
2840 			ineq[n_ineq++] = mat->row[n_eq];
2841 			ineq[n_ineq++] = bset->eq[j];
2842 			isl_seq_neg(mat->row[n_eq++], bset->eq[j], mat->n_col);
2843 		}
2844 		for (j = 0; j < bset->n_ineq; ++j)
2845 			ineq[n_ineq++] = bset->ineq[j];
2846 		isl_basic_set_free(bset);
2847 	}
2848 
2849 	return mat;
2850 }
2851 
2852 /* Comparison routine for use as an isl_sort callback.
2853  *
2854  * Constraints with the same linear part are sorted together and
2855  * among constraints with the same linear part, those with smaller
2856  * constant term are sorted first.
2857  */
cmp_ineq(const void * a,const void * b,void * arg)2858 static int cmp_ineq(const void *a, const void *b, void *arg)
2859 {
2860 	unsigned dim = *(unsigned *) arg;
2861 	isl_int * const *ineq1 = a;
2862 	isl_int * const *ineq2 = b;
2863 	int cmp;
2864 
2865 	cmp = isl_seq_cmp((*ineq1) + 1, (*ineq2) + 1, dim);
2866 	if (cmp != 0)
2867 		return cmp;
2868 	return isl_int_cmp((*ineq1)[0], (*ineq2)[0]);
2869 }
2870 
2871 /* Compute a superset of the convex hull of "set" that is described
2872  * by only constraints in the elements of "list", where "set" has
2873  * no parameters or integer divisions.
2874  *
2875  * We collect all the constraints in those elements and then
2876  * sort the constraints such that constraints with the same linear part
2877  * are sorted together and that those with smaller constant term are
2878  * sorted first.
2879  */
uset_unshifted_simple_hull_from_basic_set_list(__isl_take isl_set * set,__isl_take isl_basic_set_list * list)2880 static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_basic_set_list(
2881 	__isl_take isl_set *set, __isl_take isl_basic_set_list *list)
2882 {
2883 	int i, n_eq, n_ineq;
2884 	isl_size n;
2885 	isl_size dim;
2886 	isl_ctx *ctx;
2887 	isl_mat *mat = NULL;
2888 	isl_int **ineq = NULL;
2889 	isl_basic_set *hull;
2890 
2891 	n = isl_basic_set_list_n_basic_set(list);
2892 	if (!set || n < 0)
2893 		goto error;
2894 	ctx = isl_set_get_ctx(set);
2895 
2896 	n_eq = 0;
2897 	n_ineq = 0;
2898 	for (i = 0; i < n; ++i) {
2899 		isl_basic_set *bset;
2900 		bset = isl_basic_set_list_get_basic_set(list, i);
2901 		if (!bset)
2902 			goto error;
2903 		n_eq += bset->n_eq;
2904 		n_ineq += 2 * bset->n_eq + bset->n_ineq;
2905 		isl_basic_set_free(bset);
2906 	}
2907 
2908 	ineq = isl_alloc_array(ctx, isl_int *, n_ineq);
2909 	if (n_ineq > 0 && !ineq)
2910 		goto error;
2911 
2912 	dim = isl_set_dim(set, isl_dim_set);
2913 	if (dim < 0)
2914 		goto error;
2915 	mat = isl_mat_alloc(ctx, n_eq, 1 + dim);
2916 	mat = collect_inequalities(mat, list, ineq);
2917 	if (!mat)
2918 		goto error;
2919 
2920 	if (isl_sort(ineq, n_ineq, sizeof(ineq[0]), &cmp_ineq, &dim) < 0)
2921 		goto error;
2922 
2923 	hull = uset_unshifted_simple_hull_from_constraints(set, n_ineq, ineq);
2924 
2925 	isl_mat_free(mat);
2926 	free(ineq);
2927 	isl_basic_set_list_free(list);
2928 	return hull;
2929 error:
2930 	isl_mat_free(mat);
2931 	free(ineq);
2932 	isl_set_free(set);
2933 	isl_basic_set_list_free(list);
2934 	return NULL;
2935 }
2936 
2937 /* Compute a superset of the convex hull of "map" that is described
2938  * by only constraints in the elements of "list".
2939  *
2940  * If the list is empty, then we can only describe the universe set.
2941  * If the input map is empty, then all constraints are valid, so
2942  * we return the intersection of the elements in "list".
2943  *
2944  * Otherwise, we align all divs and temporarily treat them
2945  * as regular variables, computing the unshifted simple hull in
2946  * uset_unshifted_simple_hull_from_basic_set_list.
2947  */
map_unshifted_simple_hull_from_basic_map_list(__isl_take isl_map * map,__isl_take isl_basic_map_list * list)2948 static __isl_give isl_basic_map *map_unshifted_simple_hull_from_basic_map_list(
2949 	__isl_take isl_map *map, __isl_take isl_basic_map_list *list)
2950 {
2951 	isl_size n;
2952 	isl_basic_map *model;
2953 	isl_basic_map *hull;
2954 	isl_set *set;
2955 	isl_basic_set_list *bset_list;
2956 
2957 	n = isl_basic_map_list_n_basic_map(list);
2958 	if (!map || n < 0)
2959 		goto error;
2960 
2961 	if (n == 0) {
2962 		isl_space *space;
2963 
2964 		space = isl_map_get_space(map);
2965 		isl_map_free(map);
2966 		isl_basic_map_list_free(list);
2967 		return isl_basic_map_universe(space);
2968 	}
2969 	if (isl_map_plain_is_empty(map)) {
2970 		isl_map_free(map);
2971 		return isl_basic_map_list_intersect(list);
2972 	}
2973 
2974 	map = isl_map_align_divs_to_basic_map_list(map, list);
2975 	if (!map)
2976 		goto error;
2977 	list = isl_basic_map_list_align_divs_to_basic_map(list, map->p[0]);
2978 
2979 	model = isl_basic_map_list_get_basic_map(list, 0);
2980 
2981 	set = isl_map_underlying_set(map);
2982 	bset_list = isl_basic_map_list_underlying_set(list);
2983 
2984 	hull = uset_unshifted_simple_hull_from_basic_set_list(set, bset_list);
2985 	hull = isl_basic_map_overlying_set(hull, model);
2986 
2987 	return hull;
2988 error:
2989 	isl_map_free(map);
2990 	isl_basic_map_list_free(list);
2991 	return NULL;
2992 }
2993 
2994 /* Return a sequence of the basic maps that make up the maps in "list".
2995  */
collect_basic_maps(__isl_take isl_map_list * list)2996 static __isl_give isl_basic_map_list *collect_basic_maps(
2997 	__isl_take isl_map_list *list)
2998 {
2999 	int i;
3000 	isl_size n;
3001 	isl_ctx *ctx;
3002 	isl_basic_map_list *bmap_list;
3003 
3004 	if (!list)
3005 		return NULL;
3006 	n = isl_map_list_n_map(list);
3007 	ctx = isl_map_list_get_ctx(list);
3008 	bmap_list = isl_basic_map_list_alloc(ctx, 0);
3009 	if (n < 0)
3010 		bmap_list = isl_basic_map_list_free(bmap_list);
3011 
3012 	for (i = 0; i < n; ++i) {
3013 		isl_map *map;
3014 		isl_basic_map_list *list_i;
3015 
3016 		map = isl_map_list_get_map(list, i);
3017 		map = isl_map_compute_divs(map);
3018 		list_i = isl_map_get_basic_map_list(map);
3019 		isl_map_free(map);
3020 		bmap_list = isl_basic_map_list_concat(bmap_list, list_i);
3021 	}
3022 
3023 	isl_map_list_free(list);
3024 	return bmap_list;
3025 }
3026 
3027 /* Compute a superset of the convex hull of "map" that is described
3028  * by only constraints in the elements of "list".
3029  *
3030  * If "map" is the universe, then the convex hull (and therefore
3031  * any superset of the convexhull) is the universe as well.
3032  *
3033  * Otherwise, we collect all the basic maps in the map list and
3034  * continue with map_unshifted_simple_hull_from_basic_map_list.
3035  */
isl_map_unshifted_simple_hull_from_map_list(__isl_take isl_map * map,__isl_take isl_map_list * list)3036 __isl_give isl_basic_map *isl_map_unshifted_simple_hull_from_map_list(
3037 	__isl_take isl_map *map, __isl_take isl_map_list *list)
3038 {
3039 	isl_basic_map_list *bmap_list;
3040 	int is_universe;
3041 
3042 	is_universe = isl_map_plain_is_universe(map);
3043 	if (is_universe < 0)
3044 		map = isl_map_free(map);
3045 	if (is_universe < 0 || is_universe) {
3046 		isl_map_list_free(list);
3047 		return isl_map_unshifted_simple_hull(map);
3048 	}
3049 
3050 	bmap_list = collect_basic_maps(list);
3051 	return map_unshifted_simple_hull_from_basic_map_list(map, bmap_list);
3052 }
3053 
3054 /* Compute a superset of the convex hull of "set" that is described
3055  * by only constraints in the elements of "list".
3056  */
isl_set_unshifted_simple_hull_from_set_list(__isl_take isl_set * set,__isl_take isl_set_list * list)3057 __isl_give isl_basic_set *isl_set_unshifted_simple_hull_from_set_list(
3058 	__isl_take isl_set *set, __isl_take isl_set_list *list)
3059 {
3060 	return isl_map_unshifted_simple_hull_from_map_list(set, list);
3061 }
3062 
3063 /* Given a set "set", return parametric bounds on the dimension "dim".
3064  */
set_bounds(__isl_keep isl_set * set,int dim)3065 static __isl_give isl_basic_set *set_bounds(__isl_keep isl_set *set, int dim)
3066 {
3067 	isl_size set_dim = isl_set_dim(set, isl_dim_set);
3068 	if (set_dim < 0)
3069 		return NULL;
3070 	set = isl_set_copy(set);
3071 	set = isl_set_eliminate_dims(set, dim + 1, set_dim - (dim + 1));
3072 	set = isl_set_eliminate_dims(set, 0, dim);
3073 	return isl_set_convex_hull(set);
3074 }
3075 
3076 /* Computes a "simple hull" and then check if each dimension in the
3077  * resulting hull is bounded by a symbolic constant.  If not, the
3078  * hull is intersected with the corresponding bounds on the whole set.
3079  */
isl_set_bounded_simple_hull(__isl_take isl_set * set)3080 __isl_give isl_basic_set *isl_set_bounded_simple_hull(__isl_take isl_set *set)
3081 {
3082 	int i, j;
3083 	struct isl_basic_set *hull;
3084 	isl_size nparam, dim, total;
3085 	unsigned left;
3086 	int removed_divs = 0;
3087 
3088 	hull = isl_set_simple_hull(isl_set_copy(set));
3089 	nparam = isl_basic_set_dim(hull, isl_dim_param);
3090 	dim = isl_basic_set_dim(hull, isl_dim_set);
3091 	total = isl_basic_set_dim(hull, isl_dim_all);
3092 	if (nparam < 0 || dim < 0 || total < 0)
3093 		goto error;
3094 
3095 	for (i = 0; i < dim; ++i) {
3096 		int lower = 0, upper = 0;
3097 		struct isl_basic_set *bounds;
3098 
3099 		left = total - nparam - i - 1;
3100 		for (j = 0; j < hull->n_eq; ++j) {
3101 			if (isl_int_is_zero(hull->eq[j][1 + nparam + i]))
3102 				continue;
3103 			if (isl_seq_first_non_zero(hull->eq[j]+1+nparam+i+1,
3104 						    left) == -1)
3105 				break;
3106 		}
3107 		if (j < hull->n_eq)
3108 			continue;
3109 
3110 		for (j = 0; j < hull->n_ineq; ++j) {
3111 			if (isl_int_is_zero(hull->ineq[j][1 + nparam + i]))
3112 				continue;
3113 			if (isl_seq_first_non_zero(hull->ineq[j]+1+nparam+i+1,
3114 						    left) != -1 ||
3115 			    isl_seq_first_non_zero(hull->ineq[j]+1+nparam,
3116 						    i) != -1)
3117 				continue;
3118 			if (isl_int_is_pos(hull->ineq[j][1 + nparam + i]))
3119 				lower = 1;
3120 			else
3121 				upper = 1;
3122 			if (lower && upper)
3123 				break;
3124 		}
3125 
3126 		if (lower && upper)
3127 			continue;
3128 
3129 		if (!removed_divs) {
3130 			set = isl_set_remove_divs(set);
3131 			if (!set)
3132 				goto error;
3133 			removed_divs = 1;
3134 		}
3135 		bounds = set_bounds(set, i);
3136 		hull = isl_basic_set_intersect(hull, bounds);
3137 		if (!hull)
3138 			goto error;
3139 	}
3140 
3141 	isl_set_free(set);
3142 	return hull;
3143 error:
3144 	isl_set_free(set);
3145 	isl_basic_set_free(hull);
3146 	return NULL;
3147 }
3148