805 lines · c
1/*2 * Copyright 2010-2011 INRIA Saclay3 * Copyright 2014 Ecole Normale Superieure4 *5 * Use of this software is governed by the MIT license6 *7 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,8 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,9 * 91893 Orsay, France 10 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France11 */12 13#include <isl_map_private.h>14#include <isl_aff_private.h>15#include <isl_morph.h>16#include <isl_seq.h>17#include <isl_mat_private.h>18#include <isl_space_private.h>19#include <isl_equalities.h>20#include <isl_id_private.h>21#include <isl_aff_private.h>22#include <isl_vec_private.h>23 24isl_ctx *isl_morph_get_ctx(__isl_keep isl_morph *morph)25{26 if (!morph)27 return NULL;28 return isl_basic_set_get_ctx(morph->dom);29}30 31__isl_give isl_morph *isl_morph_alloc(32 __isl_take isl_basic_set *dom, __isl_take isl_basic_set *ran,33 __isl_take isl_mat *map, __isl_take isl_mat *inv)34{35 isl_morph *morph;36 37 if (!dom || !ran || !map || !inv)38 goto error;39 40 morph = isl_alloc_type(dom->ctx, struct isl_morph);41 if (!morph)42 goto error;43 44 morph->ref = 1;45 morph->dom = dom;46 morph->ran = ran;47 morph->map = map;48 morph->inv = inv;49 50 return morph;51error:52 isl_basic_set_free(dom);53 isl_basic_set_free(ran);54 isl_mat_free(map);55 isl_mat_free(inv);56 return NULL;57}58 59__isl_give isl_morph *isl_morph_copy(__isl_keep isl_morph *morph)60{61 if (!morph)62 return NULL;63 64 morph->ref++;65 return morph;66}67 68__isl_give isl_morph *isl_morph_dup(__isl_keep isl_morph *morph)69{70 if (!morph)71 return NULL;72 73 return isl_morph_alloc(isl_basic_set_copy(morph->dom),74 isl_basic_set_copy(morph->ran),75 isl_mat_copy(morph->map), isl_mat_copy(morph->inv));76}77 78__isl_give isl_morph *isl_morph_cow(__isl_take isl_morph *morph)79{80 if (!morph)81 return NULL;82 83 if (morph->ref == 1)84 return morph;85 morph->ref--;86 return isl_morph_dup(morph);87}88 89__isl_null isl_morph *isl_morph_free(__isl_take isl_morph *morph)90{91 if (!morph)92 return NULL;93 94 if (--morph->ref > 0)95 return NULL;96 97 isl_basic_set_free(morph->dom);98 isl_basic_set_free(morph->ran);99 isl_mat_free(morph->map);100 isl_mat_free(morph->inv);101 free(morph);102 103 return NULL;104}105 106/* Is "morph" an identity on the parameters?107 */108static isl_bool identity_on_parameters(__isl_keep isl_morph *morph)109{110 isl_bool is_identity;111 isl_size nparam, nparam_ran;112 isl_mat *sub;113 114 nparam = isl_morph_dom_dim(morph, isl_dim_param);115 nparam_ran = isl_morph_ran_dim(morph, isl_dim_param);116 if (nparam < 0 || nparam_ran < 0)117 return isl_bool_error;118 if (nparam != nparam_ran)119 return isl_bool_false;120 if (nparam == 0)121 return isl_bool_true;122 sub = isl_mat_sub_alloc(morph->map, 0, 1 + nparam, 0, 1 + nparam);123 is_identity = isl_mat_is_scaled_identity(sub);124 isl_mat_free(sub);125 126 return is_identity;127}128 129/* Return an affine expression of the variables of the range of "morph"130 * in terms of the parameters and the variables of the domain on "morph".131 *132 * In order for the space manipulations to make sense, we require133 * that the parameters are not modified by "morph".134 */135__isl_give isl_multi_aff *isl_morph_get_var_multi_aff(136 __isl_keep isl_morph *morph)137{138 isl_space *dom, *ran, *space;139 isl_local_space *ls;140 isl_multi_aff *ma;141 isl_size nparam, nvar;142 int i;143 isl_bool is_identity;144 145 if (!morph)146 return NULL;147 148 is_identity = identity_on_parameters(morph);149 if (is_identity < 0)150 return NULL;151 if (!is_identity)152 isl_die(isl_morph_get_ctx(morph), isl_error_invalid,153 "cannot handle parameter compression", return NULL);154 155 dom = isl_morph_get_dom_space(morph);156 ls = isl_local_space_from_space(isl_space_copy(dom));157 ran = isl_morph_get_ran_space(morph);158 space = isl_space_map_from_domain_and_range(dom, ran);159 ma = isl_multi_aff_zero(space);160 161 nparam = isl_multi_aff_dim(ma, isl_dim_param);162 nvar = isl_multi_aff_dim(ma, isl_dim_out);163 if (nparam < 0 || nvar < 0)164 ma = isl_multi_aff_free(ma);165 for (i = 0; i < nvar; ++i) {166 isl_val *val;167 isl_vec *v;168 isl_aff *aff;169 170 v = isl_mat_get_row(morph->map, 1 + nparam + i);171 v = isl_vec_insert_els(v, 0, 1);172 val = isl_mat_get_element_val(morph->map, 0, 0);173 v = isl_vec_set_element_val(v, 0, val);174 aff = isl_aff_alloc_vec(isl_local_space_copy(ls), v);175 ma = isl_multi_aff_set_aff(ma, i, aff);176 }177 178 isl_local_space_free(ls);179 return ma;180}181 182/* Return the domain space of "morph".183 */184static __isl_keep isl_space *isl_morph_peek_dom_space(185 __isl_keep isl_morph *morph)186{187 if (!morph)188 return NULL;189 190 return isl_basic_set_peek_space(morph->dom);191}192 193/* Return a copy of the domain space of "morph".194 */195__isl_give isl_space *isl_morph_get_dom_space(__isl_keep isl_morph *morph)196{197 return isl_space_copy(isl_morph_peek_dom_space(morph));198}199 200/* Check that the match against "space" with result "match" was successful.201 */202static isl_stat check_space_match(__isl_keep isl_space *space, isl_bool match)203{204 if (match < 0)205 return isl_stat_error;206 if (!match)207 isl_die(isl_space_get_ctx(space), isl_error_invalid,208 "spaces don't match", return isl_stat_error);209 210 return isl_stat_ok;211}212 213/* Check that "morph" can be applied to the "space".214 */215isl_stat isl_morph_check_applies(__isl_keep isl_morph *morph,216 __isl_keep isl_space *space)217{218 isl_space *dom_space;219 isl_bool applies;220 221 dom_space = isl_morph_peek_dom_space(morph);222 applies = isl_space_is_equal(dom_space, space);223 return check_space_match(space, applies);224}225 226__isl_give isl_space *isl_morph_get_ran_space(__isl_keep isl_morph *morph)227{228 if (!morph)229 return NULL;230 231 return isl_space_copy(morph->ran->dim);232}233 234isl_size isl_morph_dom_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)235{236 if (!morph)237 return isl_size_error;238 239 return isl_basic_set_dim(morph->dom, type);240}241 242isl_size isl_morph_ran_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)243{244 if (!morph)245 return isl_size_error;246 247 return isl_basic_set_dim(morph->ran, type);248}249 250__isl_give isl_morph *isl_morph_remove_dom_dims(__isl_take isl_morph *morph,251 enum isl_dim_type type, unsigned first, unsigned n)252{253 unsigned dom_offset;254 255 if (n == 0)256 return morph;257 258 morph = isl_morph_cow(morph);259 if (!morph)260 return NULL;261 262 dom_offset = 1 + isl_space_offset(morph->dom->dim, type);263 264 morph->dom = isl_basic_set_remove_dims(morph->dom, type, first, n);265 266 morph->map = isl_mat_drop_cols(morph->map, dom_offset + first, n);267 268 morph->inv = isl_mat_drop_rows(morph->inv, dom_offset + first, n);269 270 if (morph->dom && morph->ran && morph->map && morph->inv)271 return morph;272 273 isl_morph_free(morph);274 return NULL;275}276 277__isl_give isl_morph *isl_morph_remove_ran_dims(__isl_take isl_morph *morph,278 enum isl_dim_type type, unsigned first, unsigned n)279{280 unsigned ran_offset;281 282 if (n == 0)283 return morph;284 285 morph = isl_morph_cow(morph);286 if (!morph)287 return NULL;288 289 ran_offset = 1 + isl_space_offset(morph->ran->dim, type);290 291 morph->ran = isl_basic_set_remove_dims(morph->ran, type, first, n);292 293 morph->map = isl_mat_drop_rows(morph->map, ran_offset + first, n);294 295 morph->inv = isl_mat_drop_cols(morph->inv, ran_offset + first, n);296 297 if (morph->dom && morph->ran && morph->map && morph->inv)298 return morph;299 300 isl_morph_free(morph);301 return NULL;302}303 304/* Project domain of morph onto its parameter domain.305 */306__isl_give isl_morph *isl_morph_dom_params(__isl_take isl_morph *morph)307{308 isl_size n;309 310 morph = isl_morph_cow(morph);311 if (!morph)312 return NULL;313 n = isl_basic_set_dim(morph->dom, isl_dim_set);314 if (n < 0)315 return isl_morph_free(morph);316 morph = isl_morph_remove_dom_dims(morph, isl_dim_set, 0, n);317 if (!morph)318 return NULL;319 morph->dom = isl_basic_set_params(morph->dom);320 if (morph->dom)321 return morph;322 323 isl_morph_free(morph);324 return NULL;325}326 327/* Project range of morph onto its parameter domain.328 */329__isl_give isl_morph *isl_morph_ran_params(__isl_take isl_morph *morph)330{331 isl_size n;332 333 morph = isl_morph_cow(morph);334 if (!morph)335 return NULL;336 n = isl_basic_set_dim(morph->ran, isl_dim_set);337 if (n < 0)338 return isl_morph_free(morph);339 morph = isl_morph_remove_ran_dims(morph, isl_dim_set, 0, n);340 if (!morph)341 return NULL;342 morph->ran = isl_basic_set_params(morph->ran);343 if (morph->ran)344 return morph;345 346 isl_morph_free(morph);347 return NULL;348}349 350/* Replace the identifier of the tuple of the range of the morph by "id".351 */352static __isl_give isl_morph *isl_morph_set_ran_tuple_id(353 __isl_take isl_morph *morph, __isl_keep isl_id *id)354{355 morph = isl_morph_cow(morph);356 if (!morph)357 return NULL;358 morph->ran = isl_basic_set_set_tuple_id(morph->ran, isl_id_copy(id));359 if (!morph->ran)360 return isl_morph_free(morph);361 return morph;362}363 364void isl_morph_print_internal(__isl_take isl_morph *morph, FILE *out)365{366 if (!morph)367 return;368 369 isl_basic_set_dump(morph->dom);370 isl_basic_set_dump(morph->ran);371 isl_mat_print_internal(morph->map, out, 4);372 isl_mat_print_internal(morph->inv, out, 4);373}374 375void isl_morph_dump(__isl_take isl_morph *morph)376{377 isl_morph_print_internal(morph, stderr);378}379 380__isl_give isl_morph *isl_morph_identity(__isl_keep isl_basic_set *bset)381{382 isl_mat *id;383 isl_basic_set *universe;384 isl_size total;385 386 total = isl_basic_set_dim(bset, isl_dim_all);387 if (total < 0)388 return NULL;389 390 id = isl_mat_identity(bset->ctx, 1 + total);391 universe = isl_basic_set_universe(isl_space_copy(bset->dim));392 393 return isl_morph_alloc(universe, isl_basic_set_copy(universe),394 id, isl_mat_copy(id));395}396 397/* Create a(n identity) morphism between empty sets of the same dimension398 * a "bset".399 */400__isl_give isl_morph *isl_morph_empty(__isl_keep isl_basic_set *bset)401{402 isl_mat *id;403 isl_basic_set *empty;404 isl_size total;405 406 total = isl_basic_set_dim(bset, isl_dim_all);407 if (total < 0)408 return NULL;409 410 id = isl_mat_identity(bset->ctx, 1 + total);411 empty = isl_basic_set_empty(isl_space_copy(bset->dim));412 413 return isl_morph_alloc(empty, isl_basic_set_copy(empty),414 id, isl_mat_copy(id));415}416 417/* Construct a basic set described by the "n" equalities of "bset" starting418 * at "first".419 */420static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset,421 unsigned first, unsigned n)422{423 int i, k;424 isl_basic_set *eq;425 isl_size total;426 427 total = isl_basic_set_dim(bset, isl_dim_all);428 if (total < 0 || isl_basic_set_check_no_locals(bset) < 0)429 return NULL;430 431 eq = isl_basic_set_alloc_space(isl_basic_set_get_space(bset), 0, n, 0);432 if (!eq)433 return NULL;434 for (i = 0; i < n; ++i) {435 k = isl_basic_set_alloc_equality(eq);436 if (k < 0)437 goto error;438 isl_seq_cpy(eq->eq[k], bset->eq[first + i], 1 + total);439 }440 441 return eq;442error:443 isl_basic_set_free(eq);444 return NULL;445}446 447/* Given a basic set, exploit the equalities in the basic set to construct448 * a morphism that maps the basic set to a lower-dimensional space.449 * Specifically, the morphism reduces the number of dimensions of type "type".450 *451 * We first select the equalities of interest, that is those that involve452 * variables of type "type" and no later variables.453 * Denote those equalities as454 *455 * -C(p) + M x = 0456 *457 * where C(p) depends on the parameters if type == isl_dim_set and458 * is a constant if type == isl_dim_param.459 *460 * Use isl_mat_final_variable_compression to construct a compression461 *462 * x = T x'463 *464 * x' = Q x465 *466 * If T is a zero-column matrix, then the set of equality constraints467 * do not admit a solution. In this case, an empty morphism is returned.468 *469 * Both matrices are extended to map the full original space to the full470 * compressed space.471 */472__isl_give isl_morph *isl_basic_set_variable_compression(473 __isl_keep isl_basic_set *bset, enum isl_dim_type type)474{475 unsigned otype;476 isl_size ntype;477 unsigned orest;478 unsigned nrest;479 isl_size total;480 int f_eq, n_eq;481 isl_space *space;482 isl_mat *E, *Q, *C;483 isl_basic_set *dom, *ran;484 485 if (!bset)486 return NULL;487 488 if (isl_basic_set_plain_is_empty(bset))489 return isl_morph_empty(bset);490 491 if (isl_basic_set_check_no_locals(bset) < 0)492 return NULL;493 494 ntype = isl_basic_set_dim(bset, type);495 total = isl_basic_set_dim(bset, isl_dim_all);496 if (ntype < 0 || total < 0)497 return NULL;498 otype = isl_basic_set_offset(bset, type);499 orest = otype + ntype;500 nrest = total - (orest - 1);501 502 for (f_eq = 0; f_eq < bset->n_eq; ++f_eq)503 if (isl_seq_first_non_zero(bset->eq[f_eq] + orest, nrest) == -1)504 break;505 for (n_eq = 0; f_eq + n_eq < bset->n_eq; ++n_eq)506 if (isl_seq_first_non_zero(bset->eq[f_eq + n_eq] + otype, ntype) == -1)507 break;508 if (n_eq == 0)509 return isl_morph_identity(bset);510 511 E = isl_mat_sub_alloc6(bset->ctx, bset->eq, f_eq, n_eq, 0, orest);512 C = isl_mat_final_variable_compression(E, otype - 1, &Q);513 if (!Q)514 C = isl_mat_free(C);515 if (C && C->n_col == 0) {516 isl_mat_free(C);517 isl_mat_free(Q);518 return isl_morph_empty(bset);519 }520 521 Q = isl_mat_diagonal(Q, isl_mat_identity(bset->ctx, nrest));522 C = isl_mat_diagonal(C, isl_mat_identity(bset->ctx, nrest));523 524 space = isl_space_copy(bset->dim);525 space = isl_space_drop_dims(space, type, 0, ntype);526 space = isl_space_add_dims(space, type, ntype - n_eq);527 ran = isl_basic_set_universe(space);528 dom = copy_equalities(bset, f_eq, n_eq);529 530 return isl_morph_alloc(dom, ran, Q, C);531}532 533/* Given a basic set, exploit the equalities in the basic set to construct534 * a morphism that maps the basic set to a lower-dimensional space535 * with identifier "id".536 * Specifically, the morphism reduces the number of set dimensions.537 */538__isl_give isl_morph *isl_basic_set_variable_compression_with_id(539 __isl_keep isl_basic_set *bset, __isl_keep isl_id *id)540{541 isl_morph *morph;542 543 morph = isl_basic_set_variable_compression(bset, isl_dim_set);544 morph = isl_morph_set_ran_tuple_id(morph, id);545 return morph;546}547 548/* Construct a parameter compression for "bset".549 * We basically just call isl_mat_parameter_compression with the right input550 * and then extend the resulting matrix to include the variables.551 *552 * The implementation assumes that "bset" does not have any equalities553 * that only involve the parameters and that isl_basic_set_gauss has554 * been applied to "bset".555 *556 * Let the equalities be given as557 *558 * B(p) + A x = 0.559 *560 * We use isl_mat_parameter_compression_ext to compute the compression561 *562 * p = T p'.563 */564__isl_give isl_morph *isl_basic_set_parameter_compression(565 __isl_keep isl_basic_set *bset)566{567 isl_size nparam;568 isl_size nvar;569 isl_size n_div;570 int n_eq;571 isl_mat *H, *B;572 isl_mat *map, *inv;573 isl_basic_set *dom, *ran;574 575 if (!bset)576 return NULL;577 578 if (isl_basic_set_plain_is_empty(bset))579 return isl_morph_empty(bset);580 if (bset->n_eq == 0)581 return isl_morph_identity(bset);582 583 n_eq = bset->n_eq;584 nparam = isl_basic_set_dim(bset, isl_dim_param);585 nvar = isl_basic_set_dim(bset, isl_dim_set);586 n_div = isl_basic_set_dim(bset, isl_dim_div);587 if (nparam < 0 || nvar < 0 || n_div < 0)588 return NULL;589 590 if (isl_seq_first_non_zero(bset->eq[bset->n_eq - 1] + 1 + nparam,591 nvar + n_div) == -1)592 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,593 "input not allowed to have parameter equalities",594 return NULL);595 if (n_eq > nvar + n_div)596 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,597 "input not gaussed", return NULL);598 599 B = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, n_eq, 0, 1 + nparam);600 H = isl_mat_sub_alloc6(bset->ctx, bset->eq,601 0, n_eq, 1 + nparam, nvar + n_div);602 inv = isl_mat_parameter_compression_ext(B, H);603 inv = isl_mat_diagonal(inv, isl_mat_identity(bset->ctx, nvar));604 map = isl_mat_right_inverse(isl_mat_copy(inv));605 606 dom = isl_basic_set_universe(isl_space_copy(bset->dim));607 ran = isl_basic_set_universe(isl_space_copy(bset->dim));608 609 return isl_morph_alloc(dom, ran, map, inv);610}611 612/* Construct an isl_multi_aff that corresponds613 * to the affine transformation matrix "mat" and614 * that lives in an anonymous space.615 */616static __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat_anonymous(617 __isl_take isl_mat *mat)618{619 isl_size n_row, n_col;620 isl_ctx *ctx;621 isl_space *space;622 623 ctx = isl_mat_get_ctx(mat);624 n_row = isl_mat_rows(mat);625 n_col = isl_mat_cols(mat);626 if (n_row < 0 || n_col < 0)627 space = NULL;628 else629 space = isl_space_alloc(ctx, 0, n_col - 1, n_row - 1);630 631 return isl_multi_aff_from_aff_mat(space, mat);632}633 634/* Apply the morphism to the basic set.635 * In particular, compute the preimage of "bset" under the inverse mapping636 * in morph and intersect with the range of the morphism.637 * Note that the mapping in morph applies to both parameters and set dimensions,638 * so the parameters need to be treated as set dimensions during the call639 * to isl_basic_set_preimage_multi_aff.640 */641__isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph,642 __isl_take isl_basic_set *bset)643{644 isl_size n_param;645 isl_space *space;646 isl_multi_aff *ma;647 648 if (!morph || isl_basic_set_check_equal_space(bset, morph->dom) < 0)649 goto error;650 n_param = isl_basic_set_dim(morph->dom, isl_dim_param);651 if (n_param < 0)652 goto error;653 654 ma = isl_multi_aff_from_aff_mat_anonymous(isl_mat_copy(morph->inv));655 656 bset = isl_basic_set_move_dims(bset, isl_dim_set, 0,657 isl_dim_param, 0, n_param);658 bset = isl_basic_set_preimage_multi_aff(bset, ma);659 space = isl_basic_set_get_space(morph->ran);660 bset = isl_basic_set_reset_space(bset, space);661 bset = isl_basic_set_intersect(bset, isl_basic_set_copy(morph->ran));662 663 isl_morph_free(morph);664 return bset;665error:666 isl_morph_free(morph);667 isl_basic_set_free(bset);668 return NULL;669}670 671/* Apply the morphism to the set.672 * In particular, compute the preimage of "set" under the inverse mapping673 * in morph and intersect with the range of the morphism.674 * Note that the mapping in morph applies to both parameters and set dimensions,675 * so the parameters need to be treated as set dimensions during the call676 * to isl_set_preimage_multi_aff.677 */678__isl_give isl_set *isl_morph_set(__isl_take isl_morph *morph,679 __isl_take isl_set *set)680{681 isl_size n_param;682 isl_space *space;683 isl_multi_aff *ma;684 isl_basic_set *ran;685 686 if (!morph || isl_set_basic_set_check_equal_space(set, morph->dom) < 0)687 goto error;688 n_param = isl_basic_set_dim(morph->dom, isl_dim_param);689 if (n_param < 0)690 goto error;691 692 ma = isl_multi_aff_from_aff_mat_anonymous(isl_mat_copy(morph->inv));693 694 set = isl_set_move_dims(set, isl_dim_set, 0, isl_dim_param, 0, n_param);695 set = isl_set_preimage_multi_aff(set, ma);696 space = isl_basic_set_get_space(morph->ran);697 set = isl_set_reset_space(set, space);698 ran = isl_basic_set_copy(morph->ran);699 set = isl_set_intersect(set, isl_set_from_basic_set(ran));700 701 isl_morph_free(morph);702 return set;703error:704 isl_set_free(set);705 isl_morph_free(morph);706 return NULL;707}708 709/* Construct a morphism that first does morph2 and then morph1.710 */711__isl_give isl_morph *isl_morph_compose(__isl_take isl_morph *morph1,712 __isl_take isl_morph *morph2)713{714 isl_mat *map, *inv;715 isl_basic_set *dom, *ran;716 717 if (!morph1 || !morph2)718 goto error;719 720 map = isl_mat_product(isl_mat_copy(morph1->map), isl_mat_copy(morph2->map));721 inv = isl_mat_product(isl_mat_copy(morph2->inv), isl_mat_copy(morph1->inv));722 dom = isl_morph_basic_set(isl_morph_inverse(isl_morph_copy(morph2)),723 isl_basic_set_copy(morph1->dom));724 dom = isl_basic_set_intersect(dom, isl_basic_set_copy(morph2->dom));725 ran = isl_morph_basic_set(isl_morph_copy(morph1),726 isl_basic_set_copy(morph2->ran));727 ran = isl_basic_set_intersect(ran, isl_basic_set_copy(morph1->ran));728 729 isl_morph_free(morph1);730 isl_morph_free(morph2);731 732 return isl_morph_alloc(dom, ran, map, inv);733error:734 isl_morph_free(morph1);735 isl_morph_free(morph2);736 return NULL;737}738 739__isl_give isl_morph *isl_morph_inverse(__isl_take isl_morph *morph)740{741 isl_basic_set *bset;742 isl_mat *mat;743 744 morph = isl_morph_cow(morph);745 if (!morph)746 return NULL;747 748 bset = morph->dom;749 morph->dom = morph->ran;750 morph->ran = bset;751 752 mat = morph->map;753 morph->map = morph->inv;754 morph->inv = mat;755 756 return morph;757}758 759/* We detect all the equalities first to avoid implicit equalities760 * being discovered during the computations. In particular,761 * the compression on the variables could expose additional stride762 * constraints on the parameters. This would result in existentially763 * quantified variables after applying the resulting morph, which764 * in turn could break invariants of the calling functions.765 */766__isl_give isl_morph *isl_basic_set_full_compression(767 __isl_keep isl_basic_set *bset)768{769 isl_morph *morph, *morph2;770 771 bset = isl_basic_set_copy(bset);772 bset = isl_basic_set_detect_equalities(bset);773 774 morph = isl_basic_set_variable_compression(bset, isl_dim_param);775 bset = isl_morph_basic_set(isl_morph_copy(morph), bset);776 777 morph2 = isl_basic_set_parameter_compression(bset);778 bset = isl_morph_basic_set(isl_morph_copy(morph2), bset);779 780 morph = isl_morph_compose(morph2, morph);781 782 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);783 isl_basic_set_free(bset);784 785 morph = isl_morph_compose(morph2, morph);786 787 return morph;788}789 790__isl_give isl_vec *isl_morph_vec(__isl_take isl_morph *morph,791 __isl_take isl_vec *vec)792{793 if (!morph)794 goto error;795 796 vec = isl_mat_vec_product(isl_mat_copy(morph->map), vec);797 798 isl_morph_free(morph);799 return vec;800error:801 isl_morph_free(morph);802 isl_vec_free(vec);803 return NULL;804}805