コード例 #1
0
ファイル: isl_morph.c プロジェクト: xin3liang/toolchain_cloog
/* Construct a morphism that first does morph2 and then morph1.
 */
__isl_give isl_morph *isl_morph_compose(__isl_take isl_morph *morph1,
	__isl_take isl_morph *morph2)
{
	isl_mat *map, *inv;
	isl_basic_set *dom, *ran;

	if (!morph1 || !morph2)
		goto error;

	map = isl_mat_product(isl_mat_copy(morph1->map), isl_mat_copy(morph2->map));
	inv = isl_mat_product(isl_mat_copy(morph2->inv), isl_mat_copy(morph1->inv));
	dom = isl_morph_basic_set(isl_morph_inverse(isl_morph_copy(morph2)),
				  isl_basic_set_copy(morph1->dom));
	dom = isl_basic_set_intersect(dom, isl_basic_set_copy(morph2->dom));
	ran = isl_morph_basic_set(isl_morph_copy(morph1),
				  isl_basic_set_copy(morph2->ran));
	ran = isl_basic_set_intersect(ran, isl_basic_set_copy(morph1->ran));

	isl_morph_free(morph1);
	isl_morph_free(morph2);

	return isl_morph_alloc(dom, ran, map, inv);
error:
	isl_morph_free(morph1);
	isl_morph_free(morph2);
	return NULL;
}
コード例 #2
0
ファイル: isl_morph.c プロジェクト: xin3liang/toolchain_cloog
__isl_give isl_morph *isl_morph_dup(__isl_keep isl_morph *morph)
{
	if (!morph)
		return NULL;

	return isl_morph_alloc(isl_basic_set_copy(morph->dom),
		isl_basic_set_copy(morph->ran),
		isl_mat_copy(morph->map), isl_mat_copy(morph->inv));
}
コード例 #3
0
int isl_basic_set_count_upto(__isl_keep isl_basic_set *bset,
	isl_int max, isl_int *count)
{
	struct isl_counter cnt = { { &increment_counter } };

	if (!bset)
		return -1;

	isl_int_init(cnt.count);
	isl_int_init(cnt.max);

	isl_int_set_si(cnt.count, 0);
	isl_int_set(cnt.max, max);
	if (isl_basic_set_scan(isl_basic_set_copy(bset), &cnt.callback) < 0 &&
	    isl_int_lt(cnt.count, cnt.max))
		goto error;

	isl_int_set(*count, cnt.count);
	isl_int_clear(cnt.max);
	isl_int_clear(cnt.count);

	return 0;
error:
	isl_int_clear(cnt.count);
	return -1;
}
コード例 #4
0
/* Look for all equalities satisfied by the integer points in bset,
 * which is assumed not to have any explicit equalities.
 *
 * The equalities are obtained by successively looking for
 * a point that is affinely independent of the points found so far.
 * In particular, for each equality satisfied by the points so far,
 * we check if there is any point on a hyperplane parallel to the
 * corresponding hyperplane shifted by at least one (in either direction).
 *
 * Before looking for any outside points, we first compute the recession
 * cone.  The directions of this recession cone will always be part
 * of the affine hull, so there is no need for looking for any points
 * in these directions.
 * In particular, if the recession cone is full-dimensional, then
 * the affine hull is simply the whole universe.
 */
static struct isl_basic_set *uset_affine_hull(struct isl_basic_set *bset)
{
	struct isl_basic_set *cone;

	if (isl_basic_set_plain_is_empty(bset))
		return bset;

	cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset));
	if (!cone)
		goto error;
	if (cone->n_eq == 0) {
		struct isl_basic_set *hull;
		isl_basic_set_free(cone);
		hull = isl_basic_set_universe_like(bset);
		isl_basic_set_free(bset);
		return hull;
	}

	if (cone->n_eq < isl_basic_set_total_dim(cone))
		return affine_hull_with_cone(bset, cone);

	isl_basic_set_free(cone);
	return uset_affine_hull_bounded(bset);
error:
	isl_basic_set_free(bset);
	return NULL;
}
コード例 #5
0
ファイル: isl_point.c プロジェクト: xin3liang/toolchain_cloog
int isl_set_foreach_point(__isl_keep isl_set *set,
	int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
{
	struct isl_foreach_point fp = { { &foreach_point }, fn, user };
	int i;

	if (!set)
		return -1;

	fp.dim = isl_set_get_dim(set);
	if (!fp.dim)
		return -1;

	set = isl_set_copy(set);
	set = isl_set_cow(set);
	set = isl_set_make_disjoint(set);
	set = isl_set_compute_divs(set);
	if (!set)
		goto error;

	for (i = 0; i < set->n; ++i)
		if (isl_basic_set_scan(isl_basic_set_copy(set->p[i]),
					&fp.callback) < 0)
			goto error;

	isl_set_free(set);
	isl_dim_free(fp.dim);

	return 0;
error:
	isl_set_free(set);
	isl_dim_free(fp.dim);
	return -1;
}
コード例 #6
0
ファイル: isl_range.c プロジェクト: KangDroidSMProject/ISL
/* Check whether the polynomial "poly" has sign "sign" over "bset",
 * i.e., if sign == 1, check that the lower bound on the polynomial
 * is non-negative and if sign == -1, check that the upper bound on
 * the polynomial is non-positive.
 */
static int has_sign(__isl_keep isl_basic_set *bset,
	__isl_keep isl_qpolynomial *poly, int sign, int *signs)
{
	struct range_data data_m;
	unsigned nparam;
	isl_space *dim;
	isl_val *opt;
	int r;
	enum isl_fold type;

	nparam = isl_basic_set_dim(bset, isl_dim_param);

	bset = isl_basic_set_copy(bset);
	poly = isl_qpolynomial_copy(poly);

	bset = isl_basic_set_move_dims(bset, isl_dim_set, 0,
					isl_dim_param, 0, nparam);
	poly = isl_qpolynomial_move_dims(poly, isl_dim_in, 0,
					isl_dim_param, 0, nparam);

	dim = isl_qpolynomial_get_space(poly);
	dim = isl_space_params(dim);
	dim = isl_space_from_domain(dim);
	dim = isl_space_add_dims(dim, isl_dim_out, 1);

	data_m.test_monotonicity = 0;
	data_m.signs = signs;
	data_m.sign = -sign;
	type = data_m.sign < 0 ? isl_fold_min : isl_fold_max;
	data_m.pwf = isl_pw_qpolynomial_fold_zero(dim, type);
	data_m.tight = 0;
	data_m.pwf_tight = NULL;

	if (propagate_on_domain(bset, poly, &data_m) < 0)
		goto error;

	if (sign > 0)
		opt = isl_pw_qpolynomial_fold_min(data_m.pwf);
	else
		opt = isl_pw_qpolynomial_fold_max(data_m.pwf);

	if (!opt)
		r = -1;
	else if (isl_val_is_nan(opt) ||
		 isl_val_is_infty(opt) ||
		 isl_val_is_neginfty(opt))
		r = 0;
	else
		r = sign * isl_val_sgn(opt) >= 0;

	isl_val_free(opt);

	return r;
error:
	isl_pw_qpolynomial_fold_free(data_m.pwf);
	return -1;
}
コード例 #7
0
struct isl_basic_map *isl_map_affine_hull(struct isl_map *map)
{
	int i;
	struct isl_basic_map *model = NULL;
	struct isl_basic_map *hull = NULL;
	struct isl_set *set;

	map = isl_map_detect_equalities(map);
	map = isl_map_align_divs(map);

	if (!map)
		return NULL;

	if (map->n == 0) {
		hull = isl_basic_map_empty_like_map(map);
		isl_map_free(map);
		return hull;
	}

	model = isl_basic_map_copy(map->p[0]);
	set = isl_map_underlying_set(map);
	set = isl_set_cow(set);
	if (!set)
		goto error;

	for (i = 0; i < set->n; ++i) {
		set->p[i] = isl_basic_set_cow(set->p[i]);
		set->p[i] = isl_basic_set_affine_hull(set->p[i]);
		set->p[i] = isl_basic_set_gauss(set->p[i], NULL);
		if (!set->p[i])
			goto error;
	}
	set = isl_set_remove_empty_parts(set);
	if (set->n == 0) {
		hull = isl_basic_map_empty_like(model);
		isl_basic_map_free(model);
	} else {
		struct isl_basic_set *bset;
		while (set->n > 1) {
			set->p[0] = affine_hull(set->p[0], set->p[--set->n]);
			if (!set->p[0])
				goto error;
		}
		bset = isl_basic_set_copy(set->p[0]);
		hull = isl_basic_map_overlying_set(bset, model);
	}
	isl_set_free(set);
	hull = isl_basic_map_simplify(hull);
	return isl_basic_map_finalize(hull);
error:
	isl_basic_map_free(model);
	isl_set_free(set);
	return NULL;
}
コード例 #8
0
ファイル: isl_morph.c プロジェクト: xin3liang/toolchain_cloog
/* Create a(n identity) morphism between empty sets of the same dimension
 * a "bset".
 */
__isl_give isl_morph *isl_morph_empty(__isl_keep isl_basic_set *bset)
{
	isl_mat *id;
	isl_basic_set *empty;
	unsigned total;

	if (!bset)
		return NULL;

	total = isl_basic_set_total_dim(bset);
	id = isl_mat_identity(bset->ctx, 1 + total);
	empty = isl_basic_set_empty(isl_space_copy(bset->dim));

	return isl_morph_alloc(empty, isl_basic_set_copy(empty),
		id, isl_mat_copy(id));
}
コード例 #9
0
ファイル: isl_morph.c プロジェクト: xin3liang/toolchain_cloog
__isl_give isl_morph *isl_morph_identity(__isl_keep isl_basic_set *bset)
{
	isl_mat *id;
	isl_basic_set *universe;
	unsigned total;

	if (!bset)
		return NULL;

	total = isl_basic_set_total_dim(bset);
	id = isl_mat_identity(bset->ctx, 1 + total);
	universe = isl_basic_set_universe(isl_space_copy(bset->dim));

	return isl_morph_alloc(universe, isl_basic_set_copy(universe),
		id, isl_mat_copy(id));
}
コード例 #10
0
ファイル: isl_morph.c プロジェクト: xin3liang/toolchain_cloog
__isl_give isl_morph *isl_basic_set_full_compression(
	__isl_keep isl_basic_set *bset)
{
	isl_morph *morph, *morph2;

	bset = isl_basic_set_copy(bset);

	morph = isl_basic_set_variable_compression(bset, isl_dim_param);
	bset = isl_morph_basic_set(isl_morph_copy(morph), bset);

	morph2 = isl_basic_set_parameter_compression(bset);
	bset = isl_morph_basic_set(isl_morph_copy(morph2), bset);

	morph = isl_morph_compose(morph2, morph);

	morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
	isl_basic_set_free(bset);

	morph = isl_morph_compose(morph2, morph);

	return morph;
}
コード例 #11
0
int main(int argc, char **argv)
{
    struct isl_ctx *ctx = isl_ctx_alloc();
    struct isl_basic_set *bset;
    struct isl_vec *sample;
    isl_printer *p;

    bset = isl_basic_set_read_from_file(ctx, stdin);
    sample = isl_basic_set_sample_vec(isl_basic_set_copy(bset));
    p = isl_printer_to_file(ctx, stdout);
    p = isl_printer_print_vec(p, sample);
    p = isl_printer_end_line(p);
    isl_printer_free(p);
    assert(sample);
    if (sample->size > 0)
        assert(isl_basic_set_contains(bset, sample));
    isl_basic_set_free(bset);
    isl_vec_free(sample);
    isl_ctx_free(ctx);

    return 0;
}
コード例 #12
0
int isl_set_scan(__isl_take isl_set *set, struct isl_scan_callback *callback)
{
	int i;

	if (!set || !callback)
		goto error;

	set = isl_set_cow(set);
	set = isl_set_make_disjoint(set);
	set = isl_set_compute_divs(set);
	if (!set)
		goto error;

	for (i = 0; i < set->n; ++i)
		if (isl_basic_set_scan(isl_basic_set_copy(set->p[i]),
					callback) < 0)
			goto error;

	isl_set_free(set);
	return 0;
error:
	isl_set_free(set);
	return -1;
}
コード例 #13
0
ファイル: isl_morph.c プロジェクト: xin3liang/toolchain_cloog
/* Apply the morphism to the basic set.
 * We basically just compute the preimage of "bset" under the inverse mapping
 * in morph, add in stride constraints and intersect with the range
 * of the morphism.
 */
__isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph,
	__isl_take isl_basic_set *bset)
{
	isl_basic_set *res = NULL;
	isl_mat *mat = NULL;
	int i, k;
	int max_stride;

	if (!morph || !bset)
		goto error;

	isl_assert(bset->ctx, isl_space_is_equal(bset->dim, morph->dom->dim),
		    goto error);

	max_stride = morph->inv->n_row - 1;
	if (isl_int_is_one(morph->inv->row[0][0]))
		max_stride = 0;
	res = isl_basic_set_alloc_space(isl_space_copy(morph->ran->dim),
		bset->n_div + max_stride, bset->n_eq + max_stride, bset->n_ineq);

	for (i = 0; i < bset->n_div; ++i)
		if (isl_basic_set_alloc_div(res) < 0)
			goto error;

	mat = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq,
					0, morph->inv->n_row);
	mat = isl_mat_product(mat, isl_mat_copy(morph->inv));
	if (!mat)
		goto error;
	for (i = 0; i < bset->n_eq; ++i) {
		k = isl_basic_set_alloc_equality(res);
		if (k < 0)
			goto error;
		isl_seq_cpy(res->eq[k], mat->row[i], mat->n_col);
		isl_seq_scale(res->eq[k] + mat->n_col, bset->eq[i] + mat->n_col,
				morph->inv->row[0][0], bset->n_div);
	}
	isl_mat_free(mat);

	mat = isl_mat_sub_alloc6(bset->ctx, bset->ineq, 0, bset->n_ineq,
					0, morph->inv->n_row);
	mat = isl_mat_product(mat, isl_mat_copy(morph->inv));
	if (!mat)
		goto error;
	for (i = 0; i < bset->n_ineq; ++i) {
		k = isl_basic_set_alloc_inequality(res);
		if (k < 0)
			goto error;
		isl_seq_cpy(res->ineq[k], mat->row[i], mat->n_col);
		isl_seq_scale(res->ineq[k] + mat->n_col,
				bset->ineq[i] + mat->n_col,
				morph->inv->row[0][0], bset->n_div);
	}
	isl_mat_free(mat);

	mat = isl_mat_sub_alloc6(bset->ctx, bset->div, 0, bset->n_div,
					1, morph->inv->n_row);
	mat = isl_mat_product(mat, isl_mat_copy(morph->inv));
	if (!mat)
		goto error;
	for (i = 0; i < bset->n_div; ++i) {
		isl_int_mul(res->div[i][0],
				morph->inv->row[0][0], bset->div[i][0]);
		isl_seq_cpy(res->div[i] + 1, mat->row[i], mat->n_col);
		isl_seq_scale(res->div[i] + 1 + mat->n_col,
				bset->div[i] + 1 + mat->n_col,
				morph->inv->row[0][0], bset->n_div);
	}
	isl_mat_free(mat);

	res = add_strides(res, morph);

	if (isl_basic_set_is_rational(bset))
		res = isl_basic_set_set_rational(res);

	res = isl_basic_set_simplify(res);
	res = isl_basic_set_finalize(res);

	res = isl_basic_set_intersect(res, isl_basic_set_copy(morph->ran));

	isl_morph_free(morph);
	isl_basic_set_free(bset);
	return res;
error:
	isl_mat_free(mat);
	isl_morph_free(morph);
	isl_basic_set_free(bset);
	isl_basic_set_free(res);
	return NULL;
}
コード例 #14
0
ファイル: isl_equalities.c プロジェクト: eva-oss/isl
/* Check if dimension dim belongs to a residue class
 *		i_dim \equiv r mod m
 * with m != 1 and if so return m in *modulo and r in *residue.
 * As a special case, when i_dim has a fixed value v, then
 * *modulo is set to 0 and *residue to v.
 *
 * If i_dim does not belong to such a residue class, then *modulo
 * is set to 1 and *residue is set to 0.
 */
int isl_basic_set_dim_residue_class(struct isl_basic_set *bset,
	int pos, isl_int *modulo, isl_int *residue)
{
	struct isl_ctx *ctx;
	struct isl_mat *H = NULL, *U = NULL, *C, *H1, *U1;
	unsigned total;
	unsigned nparam;

	if (!bset || !modulo || !residue)
		return -1;

	if (isl_basic_set_plain_dim_is_fixed(bset, pos, residue)) {
		isl_int_set_si(*modulo, 0);
		return 0;
	}

	ctx = isl_basic_set_get_ctx(bset);
	total = isl_basic_set_total_dim(bset);
	nparam = isl_basic_set_n_param(bset);
	H = isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 1, total);
	H = isl_mat_left_hermite(H, 0, &U, NULL);
	if (!H)
		return -1;

	isl_seq_gcd(U->row[nparam + pos]+bset->n_eq,
			total-bset->n_eq, modulo);
	if (isl_int_is_zero(*modulo))
		isl_int_set_si(*modulo, 1);
	if (isl_int_is_one(*modulo)) {
		isl_int_set_si(*residue, 0);
		isl_mat_free(H);
		isl_mat_free(U);
		return 0;
	}

	C = isl_mat_alloc(ctx, 1 + bset->n_eq, 1);
	if (!C)
		goto error;
	isl_int_set_si(C->row[0][0], 1);
	isl_mat_sub_neg(ctx, C->row + 1, bset->eq, bset->n_eq, 0, 0, 1);
	H1 = isl_mat_sub_alloc(H, 0, H->n_row, 0, H->n_row);
	H1 = isl_mat_lin_to_aff(H1);
	C = isl_mat_inverse_product(H1, C);
	isl_mat_free(H);
	U1 = isl_mat_sub_alloc(U, nparam+pos, 1, 0, bset->n_eq);
	U1 = isl_mat_lin_to_aff(U1);
	isl_mat_free(U);
	C = isl_mat_product(U1, C);
	if (!C)
		return -1;
	if (!isl_int_is_divisible_by(C->row[1][0], C->row[0][0])) {
		bset = isl_basic_set_copy(bset);
		bset = isl_basic_set_set_to_empty(bset);
		isl_basic_set_free(bset);
		isl_int_set_si(*modulo, 1);
		isl_int_set_si(*residue, 0);
		return 0;
	}
	isl_int_divexact(*residue, C->row[1][0], C->row[0][0]);
	isl_int_fdiv_r(*residue, *residue, *modulo);
	isl_mat_free(C);
	return 0;
error:
	isl_mat_free(H);
	isl_mat_free(U);
	return -1;
}
コード例 #15
0
/**
 * Reduce the modulo guard expressed by "constraints" using equalities
 * found in outer nesting levels (stored in "equal").
 * The modulo guard may be an equality or a pair of inequalities.
 * In case of a pair of inequalities, *bound contains the bound on the
 * corresponding modulo expression.  If any reduction is performed
 * then this bound is recomputed.
 *
 * "level" may not correspond to an existentially quantified variable.
 *
 * We first check if there are any equalities we can use.  If not,
 * there is again nothing to reduce.
 * For the actual reduction, we use isl_basic_set_gist, but this
 * function will only perform the reduction we want here if the
 * the variable that imposes the modulo constraint has been projected
 * out (i.e., turned into an existentially quantified variable).
 * After the call to isl_basic_set_gist, we need to move the
 * existential variable back into the position where the calling
 * function expects it (assuming there are any constraints left).
 * We do this by adding an equality between the given dimension and
 * the existentially quantified variable.
 *
 * If there are no existentially quantified variables left, then
 * we don't need to add this equality.
 * If, on the other hand, the resulting basic set involves more
 * than one existentially quantified variable, then the caller
 * will not be able to handle the result, so we just return the
 * original input instead.
 */
CloogConstraintSet *cloog_constraint_set_reduce(CloogConstraintSet *constraints,
	int level, CloogEqualities *equal, int nb_par, cloog_int_t *bound)
{
	int j;
	isl_space *idim;
	struct isl_basic_set *eq;
	struct isl_basic_map *id;
	struct cloog_isl_dim dim;
	struct isl_constraint *c;
	unsigned constraints_dim;
	unsigned n_div;
	isl_basic_set *bset, *orig;

	bset = cloog_constraints_set_to_isl(constraints);
	orig = isl_basic_set_copy(bset);
	dim = set_cloog_dim_to_isl_dim(constraints, level - 1);
	assert(dim.type == isl_dim_set);

	eq = NULL;
	for (j = 0; j < level - 1; ++j) {
		isl_basic_set *bset_j;
		if (equal->types[j] != EQTYPE_EXAFFINE)
			continue;
		bset_j = equality_to_basic_set(equal, j);
		if (!eq)
			eq = bset_j;
		else
			eq = isl_basic_set_intersect(eq, bset_j);
	}
	if (!eq) {
		isl_basic_set_free(orig);
		return cloog_constraint_set_from_isl_basic_set(bset);
	}

	idim = isl_space_map_from_set(isl_basic_set_get_space(bset));
	id = isl_basic_map_identity(idim);
	id = isl_basic_map_remove_dims(id, isl_dim_out, dim.pos, 1);
	bset = isl_basic_set_apply(bset, isl_basic_map_copy(id));
	bset = isl_basic_set_apply(bset, isl_basic_map_reverse(id));

	constraints_dim = isl_basic_set_dim(bset, isl_dim_set);
	eq = isl_basic_set_remove_dims(eq, isl_dim_set, constraints_dim,
			isl_basic_set_dim(eq, isl_dim_set) - constraints_dim);
	bset = isl_basic_set_gist(bset, eq);
	n_div = isl_basic_set_dim(bset, isl_dim_div);
	if (n_div > 1) {
		isl_basic_set_free(bset);
		return cloog_constraint_set_from_isl_basic_set(orig);
	}
	if (n_div < 1) {
		isl_basic_set_free(orig);
		return cloog_constraint_set_from_isl_basic_set(bset);
	}

	c = isl_equality_alloc(isl_basic_set_get_local_space(bset));
	c = isl_constraint_set_coefficient_si(c, isl_dim_div, 0, 1);
	c = isl_constraint_set_coefficient_si(c, isl_dim_set, dim.pos, -1);
	bset = isl_basic_set_add_constraint(bset, c);

	isl_int_set_si(*bound, 0);
	constraints = cloog_constraint_set_from_isl_basic_set(bset);
	cloog_constraint_set_foreach_constraint(constraints,
						add_constant_term, bound);

	isl_basic_set_free(orig);
	return cloog_constraint_set_from_isl_basic_set(bset);
}
コード例 #16
0
/* Look for all equalities satisfied by the integer points in bset,
 * which is assumed to be bounded.
 *
 * The equalities are obtained by successively looking for
 * a point that is affinely independent of the points found so far.
 * In particular, for each equality satisfied by the points so far,
 * we check if there is any point on a hyperplane parallel to the
 * corresponding hyperplane shifted by at least one (in either direction).
 */
static struct isl_basic_set *uset_affine_hull_bounded(struct isl_basic_set *bset)
{
	struct isl_vec *sample = NULL;
	struct isl_basic_set *hull;
	struct isl_tab *tab = NULL;
	unsigned dim;

	if (isl_basic_set_plain_is_empty(bset))
		return bset;

	dim = isl_basic_set_n_dim(bset);

	if (bset->sample && bset->sample->size == 1 + dim) {
		int contains = isl_basic_set_contains(bset, bset->sample);
		if (contains < 0)
			goto error;
		if (contains) {
			if (dim == 0)
				return bset;
			sample = isl_vec_copy(bset->sample);
		} else {
			isl_vec_free(bset->sample);
			bset->sample = NULL;
		}
	}

	tab = isl_tab_from_basic_set(bset);
	if (!tab)
		goto error;
	if (tab->empty) {
		isl_tab_free(tab);
		isl_vec_free(sample);
		return isl_basic_set_set_to_empty(bset);
	}
	if (isl_tab_track_bset(tab, isl_basic_set_copy(bset)) < 0)
		goto error;

	if (!sample) {
		struct isl_tab_undo *snap;
		snap = isl_tab_snap(tab);
		sample = isl_tab_sample(tab);
		if (isl_tab_rollback(tab, snap) < 0)
			goto error;
		isl_vec_free(tab->bmap->sample);
		tab->bmap->sample = isl_vec_copy(sample);
	}

	if (!sample)
		goto error;
	if (sample->size == 0) {
		isl_tab_free(tab);
		isl_vec_free(sample);
		return isl_basic_set_set_to_empty(bset);
	}

	hull = isl_basic_set_from_vec(sample);

	isl_basic_set_free(bset);
	hull = extend_affine_hull(tab, hull);
	isl_tab_free(tab);

	return hull;
error:
	isl_vec_free(sample);
	isl_tab_free(tab);
	isl_basic_set_free(bset);
	return NULL;
}