From: Sven Verdoolaege Date: Wed, 12 May 2010 09:36:58 +0000 (+0200) Subject: add rudimentary isl_morph X-Git-Tag: isl-0.03~170 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2a410ae0874aee465eb49c8d1723a3dec6187ee9;p=platform%2Fupstream%2Fisl.git add rudimentary isl_morph --- diff --git a/Makefile.am b/Makefile.am index 4c932d3..ee14250 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,6 +60,8 @@ libisl_la_SOURCES = \ isl_map_private.h \ isl_map_piplib.h \ isl_mat.c \ + isl_morph.c \ + isl_morph.h \ isl_name.c \ isl_name.h \ isl_obj.c \ diff --git a/isl_morph.c b/isl_morph.c new file mode 100644 index 0000000..30f1154 --- /dev/null +++ b/isl_morph.c @@ -0,0 +1,697 @@ +/* + * Copyright 2010 INRIA Saclay + * + * Use of this software is governed by the GNU LGPLv2.1 license + * + * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, + * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, + * 91893 Orsay, France + */ + +#include +#include +#include +#include +#include + +static __isl_give isl_morph *isl_morph_alloc( + __isl_take isl_basic_set *dom, __isl_take isl_basic_set *ran, + __isl_take isl_mat *map, __isl_take isl_mat *inv) +{ + isl_morph *morph; + + if (!dom || !ran || !map || !inv) + goto error; + + morph = isl_alloc_type(in_dim->ctx, struct isl_morph); + if (!morph) + goto error; + + morph->ref = 1; + morph->dom = dom; + morph->ran = ran; + morph->map = map; + morph->inv = inv; + + return morph; +error: + isl_basic_set_free(dom); + isl_basic_set_free(ran); + isl_mat_free(map); + isl_mat_free(inv); + return NULL; +} + +__isl_give isl_morph *isl_morph_copy(__isl_keep isl_morph *morph) +{ + if (!morph) + return NULL; + + morph->ref++; + return morph; +} + +__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)); +} + +__isl_give isl_morph *isl_morph_cow(__isl_take isl_morph *morph) +{ + if (!morph) + return NULL; + + if (morph->ref == 1) + return morph; + morph->ref--; + return isl_morph_dup(morph); +} + +void isl_morph_free(__isl_take isl_morph *morph) +{ + if (!morph) + return; + + if (--morph->ref > 0) + return; + + isl_basic_set_free(morph->dom); + isl_basic_set_free(morph->ran); + isl_mat_free(morph->map); + isl_mat_free(morph->inv); + free(morph); +} + +__isl_give isl_dim *isl_morph_get_ran_dim(__isl_keep isl_morph *morph) +{ + if (!morph) + return NULL; + + return isl_dim_copy(morph->ran->dim); +} + +__isl_give isl_morph *isl_morph_drop_dims(__isl_take isl_morph *morph, + enum isl_dim_type type, unsigned first, unsigned n) +{ + unsigned dom_offset; + unsigned ran_offset; + + if (n == 0) + return morph; + + morph = isl_morph_cow(morph); + if (!morph) + return NULL; + + dom_offset = 1 + isl_dim_offset(morph->dom->dim, type); + ran_offset = 1 + isl_dim_offset(morph->ran->dim, type); + + morph->dom = isl_basic_set_drop(morph->dom, type, first, n); + morph->ran = isl_basic_set_drop(morph->ran, type, first, n); + + morph->map = isl_mat_drop_cols(morph->map, dom_offset + first, n); + morph->map = isl_mat_drop_rows(morph->map, ran_offset + first, n); + + morph->inv = isl_mat_drop_cols(morph->inv, ran_offset + first, n); + morph->inv = isl_mat_drop_rows(morph->inv, dom_offset + first, n); + + if (morph->dom && morph->ran && morph->map && morph->inv) + return morph; + + isl_morph_free(morph); + return NULL; +} + +void isl_morph_dump(__isl_take isl_morph *morph, FILE *out) +{ + if (!morph) + return; + + isl_basic_set_print(morph->dom, out, 0, "", "", ISL_FORMAT_ISL); + isl_basic_set_print(morph->ran, out, 0, "", "", ISL_FORMAT_ISL); + isl_mat_dump(morph->map, out, 4); + isl_mat_dump(morph->inv, out, 4); +} + +__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_dim_copy(bset->dim)); + + return isl_morph_alloc(universe, isl_basic_set_copy(universe), + id, isl_mat_copy(id)); +} + +/* 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_dim_copy(bset->dim)); + + return isl_morph_alloc(empty, isl_basic_set_copy(empty), + id, isl_mat_copy(id)); +} + +/* Given a matrix that maps a (possibly) parametric domain to + * a parametric domain, add in rows that map the "nparam" parameters onto + * themselves. + */ +static __isl_give isl_mat *insert_parameter_rows(__isl_take isl_mat *mat, + unsigned nparam) +{ + int i; + + if (nparam == 0) + return mat; + if (!mat) + return NULL; + + mat = isl_mat_insert_rows(mat, 1, nparam); + if (!mat) + return NULL; + + for (i = 0; i < nparam; ++i) { + isl_seq_clr(mat->row[1 + i], mat->n_col); + isl_int_set(mat->row[1 + i][1 + i], mat->row[0][0]); + } + + return mat; +} + +/* Construct a basic set described by the "n" equalities of "bset" starting + * at "first". + */ +static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset, + unsigned first, unsigned n) +{ + int i, k; + isl_basic_set *eq; + unsigned total; + + isl_assert(bset->ctx, bset->n_div == 0, return NULL); + + total = isl_basic_set_total_dim(bset); + eq = isl_basic_set_alloc_dim(isl_dim_copy(bset->dim), 0, n, 0); + if (!eq) + return NULL; + for (i = 0; i < n; ++i) { + k = isl_basic_set_alloc_equality(eq); + if (k < 0) + goto error; + isl_seq_cpy(eq->eq[k], bset->eq[first + k], 1 + total); + } + + return eq; +error: + isl_basic_set_free(eq); + return NULL; +} + +/* Given a basic set, exploit the equalties in the a basic set to construct + * a morphishm that maps the basic set to a lower-dimensional space. + * Specifically, the morphism reduces the number of dimensions of type "type". + * + * This function is a slight generalization of isl_mat_variable_compression + * in that it allows the input to be parametric and that it allows for the + * compression of either parameters or set variables. + * + * We first select the equalities of interest, that is those that involve + * variables of type "type" and no later variables. + * Denote those equalities as + * + * -C(p) + M x = 0 + * + * where C(p) depends on the parameters if type == isl_dim_set and + * is a constant if type == isl_dim_param. + * + * First compute the (left) Hermite normal form of M, + * + * M [U1 U2] = M U = H = [H1 0] + * or + * M = H Q = [H1 0] [Q1] + * [Q2] + * + * with U, Q unimodular, Q = U^{-1} (and H lower triangular). + * Define the transformed variables as + * + * x = [U1 U2] [ x1' ] = [U1 U2] [Q1] x + * [ x2' ] [Q2] + * + * The equalities then become + * + * -C(p) + H1 x1' = 0 or x1' = H1^{-1} C(p) = C'(p) + * + * If the denominator of the constant term does not divide the + * the common denominator of the parametric terms, then every + * integer point is mapped to a non-integer point and then the original set has no + * integer solutions (since the x' are a unimodular transformation + * of the x). In this case, an empty morphism is returned. + * Otherwise, the transformation is given by + * + * x = U1 H1^{-1} C(p) + U2 x2' + * + * The inverse transformation is simply + * + * x2' = Q2 x + * + * Both matrices are extended to map the full original space to the full + * compressed space. + */ +__isl_give isl_morph *isl_basic_set_variable_compression( + __isl_keep isl_basic_set *bset, enum isl_dim_type type) +{ + unsigned otype; + unsigned ntype; + unsigned orest; + unsigned nrest; + unsigned total; + int f_eq, n_eq; + isl_dim *dim; + isl_mat *H, *U, *Q, *C = NULL, *H1, *U1, *U2; + isl_basic_set *dom, *ran; + + if (!bset) + return NULL; + + if (isl_basic_set_fast_is_empty(bset)) + return isl_morph_empty(bset); + + isl_assert(bset->ctx, bset->n_div == 0, return NULL); + + otype = 1 + isl_dim_offset(bset->dim, type); + ntype = isl_basic_set_dim(bset, type); + orest = otype + ntype; + nrest = isl_basic_set_total_dim(bset) - (orest - 1); + + for (f_eq = 0; f_eq < bset->n_eq; ++f_eq) + if (isl_seq_first_non_zero(bset->eq[f_eq] + orest, nrest) == -1) + break; + for (n_eq = 0; f_eq + n_eq < bset->n_eq; ++n_eq) + if (isl_seq_first_non_zero(bset->eq[f_eq + n_eq] + otype, ntype) == -1) + break; + if (n_eq == 0) + return isl_morph_identity(bset); + + H = isl_mat_sub_alloc(bset->ctx, bset->eq, f_eq, n_eq, otype, ntype); + H = isl_mat_left_hermite(H, 0, &U, &Q); + if (!H || !U || !Q) + goto error; + Q = isl_mat_drop_rows(Q, 0, n_eq); + Q = isl_mat_diagonal(isl_mat_identity(bset->ctx, otype), Q); + Q = isl_mat_diagonal(Q, isl_mat_identity(bset->ctx, nrest)); + C = isl_mat_alloc(bset->ctx, 1 + n_eq, otype); + if (!C) + goto error; + isl_int_set_si(C->row[0][0], 1); + isl_seq_clr(C->row[0] + 1, otype - 1); + isl_mat_sub_neg(C->ctx, C->row + 1, bset->eq + f_eq, n_eq, 0, 0, otype); + H1 = isl_mat_sub_alloc(H->ctx, H->row, 0, H->n_row, 0, H->n_row); + H1 = isl_mat_lin_to_aff(H1); + C = isl_mat_inverse_product(H1, C); + if (!C) + goto error; + isl_mat_free(H); + + if (!isl_int_is_one(C->row[0][0])) { + int i; + isl_int g; + + isl_int_init(g); + for (i = 0; i < n_eq; ++i) { + isl_seq_gcd(C->row[1 + i] + 1, otype - 1, &g); + isl_int_gcd(g, g, C->row[0][0]); + if (!isl_int_is_divisible_by(C->row[1 + i][0], g)) + break; + } + isl_int_clear(g); + + if (i < n_eq) { + isl_mat_free(C); + isl_mat_free(U); + isl_mat_free(Q); + return isl_morph_empty(bset); + } + + C = isl_mat_normalize(C); + } + + U1 = isl_mat_sub_alloc(U->ctx, U->row, 0, U->n_row, 0, n_eq); + U1 = isl_mat_lin_to_aff(U1); + U2 = isl_mat_sub_alloc(U->ctx, U->row, 0, U->n_row, n_eq, U->n_row - n_eq); + U2 = isl_mat_lin_to_aff(U2); + isl_mat_free(U); + + C = isl_mat_product(U1, C); + C = isl_mat_aff_direct_sum(C, U2); + C = insert_parameter_rows(C, otype - 1); + C = isl_mat_diagonal(C, isl_mat_identity(bset->ctx, nrest)); + + dim = isl_dim_copy(bset->dim); + dim = isl_dim_drop(dim, type, 0, ntype); + dim = isl_dim_add(dim, type, ntype - n_eq); + ran = isl_basic_set_universe(dim); + dom = copy_equalities(bset, f_eq, n_eq); + + return isl_morph_alloc(dom, ran, Q, C); +error: + isl_mat_free(C); + isl_mat_free(H); + isl_mat_free(U); + isl_mat_free(Q); + return NULL; +} + +/* Construct a parameter compression for "bset". + * We basically just call isl_mat_parameter_compression with the right input + * and then extend the resulting matrix to include the variables. + * + * Let the equalities be given as + * + * B(p) + A x = 0 + * + * and let [H 0] be the Hermite Normal Form of A, then + * + * H^-1 B(p) + * + * needs to be integer, so we impose that each row is divisible by + * the denominator. + */ +__isl_give isl_morph *isl_basic_set_parameter_compression( + __isl_keep isl_basic_set *bset) +{ + unsigned nparam; + unsigned nvar; + int n_eq; + isl_mat *H, *B; + isl_vec *d; + isl_mat *map, *inv; + isl_basic_set *dom, *ran; + + if (!bset) + return NULL; + + if (isl_basic_set_fast_is_empty(bset)) + return isl_morph_empty(bset); + if (bset->n_eq == 0) + return isl_morph_identity(bset); + + isl_assert(bset->ctx, bset->n_div == 0, return NULL); + + n_eq = bset->n_eq; + nparam = isl_basic_set_dim(bset, isl_dim_param); + nvar = isl_basic_set_dim(bset, isl_dim_set); + + isl_assert(bset->ctx, n_eq <= nvar, return NULL); + + d = isl_vec_alloc(bset->ctx, n_eq); + B = isl_mat_sub_alloc(bset->ctx, bset->eq, 0, n_eq, 0, 1 + nparam); + H = isl_mat_sub_alloc(bset->ctx, bset->eq, 0, n_eq, 1 + nparam, nvar); + H = isl_mat_left_hermite(H, 0, NULL, NULL); + H = isl_mat_drop_cols(H, n_eq, nvar - n_eq); + H = isl_mat_lin_to_aff(H); + H = isl_mat_right_inverse(H); + if (!H || !d) + goto error; + isl_seq_set(d->el, H->row[0][0], d->size); + H = isl_mat_drop_rows(H, 0, 1); + H = isl_mat_drop_cols(H, 0, 1); + B = isl_mat_product(H, B); + inv = isl_mat_parameter_compression(B, d); + inv = isl_mat_diagonal(inv, isl_mat_identity(bset->ctx, nvar)); + map = isl_mat_right_inverse(isl_mat_copy(inv)); + + dom = isl_basic_set_universe(isl_dim_copy(bset->dim)); + ran = isl_basic_set_universe(isl_dim_copy(bset->dim)); + + return isl_morph_alloc(dom, ran, map, inv); +error: + isl_mat_free(H); + isl_mat_free(B); + isl_vec_free(d); + return NULL; +} + +/* Add stride constraints to "bset" based on the inverse mapping + * that was plugged in. In particular, if morph maps x' to x, + * the the constraints of the original input + * + * A x' + b >= 0 + * + * have been rewritten to + * + * A inv x + b >= 0 + * + * However, this substitution may loose information on the integrality of x', + * so we need to impose that + * + * inv x + * + * is integral. If inv = B/d, this means that we need to impose that + * + * B x = 0 mod d + * + * or + * + * exists alpha in Z^m: B x = d alpha + * + */ +static __isl_give isl_basic_set *add_strides(__isl_take isl_basic_set *bset, + __isl_keep isl_morph *morph) +{ + int i, div, k; + isl_int gcd; + + if (isl_int_is_one(morph->inv->row[0][0])) + return bset; + + isl_int_init(gcd); + + for (i = 0; 1 + i < morph->inv->n_row; ++i) { + isl_seq_gcd(morph->inv->row[1 + i], morph->inv->n_col, &gcd); + if (isl_int_is_divisible_by(gcd, morph->inv->row[0][0])) + continue; + div = isl_basic_set_alloc_div(bset); + if (div < 0) + goto error; + k = isl_basic_set_alloc_equality(bset); + if (k < 0) + goto error; + isl_seq_cpy(bset->eq[k], morph->inv->row[1 + i], + morph->inv->n_col); + isl_seq_clr(bset->eq[k] + morph->inv->n_col, bset->n_div); + isl_int_set(bset->eq[k][morph->inv->n_col + div], + morph->inv->row[0][0]); + } + + isl_int_clear(gcd); + + return bset; +error: + isl_int_clear(gcd); + isl_basic_set_free(bset); + return NULL; +} + +/* 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_dim_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_dim(isl_dim_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_alloc(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_alloc(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_alloc(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); + + 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; +} + +/* Apply the morphism to the set. + */ +__isl_give isl_set *isl_morph_set(__isl_take isl_morph *morph, + __isl_take isl_set *set) +{ + int i; + + if (!morph || !set) + goto error; + + isl_assert(set->ctx, isl_dim_equal(set->dim, morph->dom->dim), goto error); + + set = isl_set_cow(set); + if (!set) + goto error; + + isl_dim_free(set->dim); + set->dim = isl_dim_copy(morph->ran->dim); + if (!set->dim) + goto error; + + for (i = 0; i < set->n; ++i) { + set->p[i] = isl_morph_basic_set(isl_morph_copy(morph), set->p[i]); + if (!set->p[i]) + goto error; + } + + isl_morph_free(morph); + + ISL_F_CLR(set, ISL_SET_NORMALIZED); + + return set; +error: + isl_set_free(set); + isl_morph_free(morph); + return NULL; +} + +/* 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; +} + +__isl_give isl_morph *isl_morph_inverse(__isl_take isl_morph *morph) +{ + isl_basic_set *bset; + isl_mat *mat; + + morph = isl_morph_cow(morph); + if (!morph) + return NULL; + + bset = morph->dom; + morph->dom = morph->ran; + morph->ran = bset; + + mat = morph->map; + morph->map = morph->inv; + morph->inv = mat; + + return morph; +} diff --git a/isl_morph.h b/isl_morph.h new file mode 100644 index 0000000..37348ca --- /dev/null +++ b/isl_morph.h @@ -0,0 +1,66 @@ +/* + * Copyright 2010 INRIA Saclay + * + * Use of this software is governed by the GNU LGPLv2.1 license + * + * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, + * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, + * 91893 Orsay, France + */ + +#ifndef ISL_MORHP_H +#define ISL_MORHP_H + +#include +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* An isl_morph is a "morphism" on (basic) sets. + * "map" is an affine mapping from "dom" to "ran" + * and "inv" is the inverse mapping. + */ +struct isl_morph { + int ref; + + isl_basic_set *dom; + isl_basic_set *ran; + + isl_mat *map; + isl_mat *inv; +}; +typedef struct isl_morph isl_morph; + +__isl_give isl_morph *isl_morph_copy(__isl_keep isl_morph *morph); +void isl_morph_free(__isl_take isl_morph *morph); + +__isl_give isl_dim *isl_morph_get_ran_dim(__isl_keep isl_morph *morph); + +__isl_give isl_morph *isl_morph_drop_dims(__isl_take isl_morph *morph, + enum isl_dim_type type, unsigned first, unsigned n); + +__isl_give isl_morph *isl_morph_compose(__isl_take isl_morph *morph1, + __isl_take isl_morph *morph2); +__isl_give isl_morph *isl_morph_inverse(__isl_take isl_morph *morph); + +void isl_morph_dump(__isl_take isl_morph *morph, FILE *out); + +__isl_give isl_morph *isl_basic_set_variable_compression( + __isl_keep isl_basic_set *bset, enum isl_dim_type type); +__isl_give isl_morph *isl_basic_set_parameter_compression( + __isl_keep isl_basic_set *bset); + +__isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph, + __isl_take isl_basic_set *bset); +__isl_give isl_set *isl_morph_set(__isl_take isl_morph *morph, + __isl_take isl_set *set); + +#if defined(__cplusplus) +} +#endif + +#endif