replace obsolete AC_PROG_LIBTOOL by LT_INIT
[isl.git] / isl_morph.c
blobf7b920b166d2ba9573a5e53c445cbb2913e1cb4a
1 /*
2 * Copyright 2010-2011 INRIA Saclay
3 * Copyright 2014 Ecole Normale Superieure
5 * Use of this software is governed by the MIT license
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, France
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>
24 isl_ctx *isl_morph_get_ctx(__isl_keep isl_morph *morph)
26 if (!morph)
27 return NULL;
28 return isl_basic_set_get_ctx(morph->dom);
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)
35 isl_morph *morph;
37 if (!dom || !ran || !map || !inv)
38 goto error;
40 morph = isl_alloc_type(dom->ctx, struct isl_morph);
41 if (!morph)
42 goto error;
44 morph->ref = 1;
45 morph->dom = dom;
46 morph->ran = ran;
47 morph->map = map;
48 morph->inv = inv;
50 return morph;
51 error:
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;
59 __isl_give isl_morph *isl_morph_copy(__isl_keep isl_morph *morph)
61 if (!morph)
62 return NULL;
64 morph->ref++;
65 return morph;
68 __isl_give isl_morph *isl_morph_dup(__isl_keep isl_morph *morph)
70 if (!morph)
71 return NULL;
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));
78 __isl_give isl_morph *isl_morph_cow(__isl_take isl_morph *morph)
80 if (!morph)
81 return NULL;
83 if (morph->ref == 1)
84 return morph;
85 morph->ref--;
86 return isl_morph_dup(morph);
89 __isl_null isl_morph *isl_morph_free(__isl_take isl_morph *morph)
91 if (!morph)
92 return NULL;
94 if (--morph->ref > 0)
95 return NULL;
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);
103 return NULL;
106 /* Is "morph" an identity on the parameters?
108 static isl_bool identity_on_parameters(__isl_keep isl_morph *morph)
110 isl_bool is_identity;
111 isl_size nparam, nparam_ran;
112 isl_mat *sub;
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);
126 return is_identity;
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".
132 * In order for the space manipulations to make sense, we require
133 * that the parameters are not modified by "morph".
135 __isl_give isl_multi_aff *isl_morph_get_var_multi_aff(
136 __isl_keep isl_morph *morph)
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;
145 if (!morph)
146 return NULL;
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);
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);
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;
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);
178 isl_local_space_free(ls);
179 return ma;
182 /* Return the domain space of "morph".
184 static __isl_keep isl_space *isl_morph_peek_dom_space(
185 __isl_keep isl_morph *morph)
187 if (!morph)
188 return NULL;
190 return isl_basic_set_peek_space(morph->dom);
193 /* Return a copy of the domain space of "morph".
195 __isl_give isl_space *isl_morph_get_dom_space(__isl_keep isl_morph *morph)
197 return isl_space_copy(isl_morph_peek_dom_space(morph));
200 /* Check that the match against "space" with result "match" was successful.
202 static isl_stat check_space_match(__isl_keep isl_space *space, isl_bool match)
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);
210 return isl_stat_ok;
213 /* Check that "morph" can be applied to the "space".
215 isl_stat isl_morph_check_applies(__isl_keep isl_morph *morph,
216 __isl_keep isl_space *space)
218 isl_space *dom_space;
219 isl_bool applies;
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);
226 __isl_give isl_space *isl_morph_get_ran_space(__isl_keep isl_morph *morph)
228 if (!morph)
229 return NULL;
231 return isl_space_copy(morph->ran->dim);
234 isl_size isl_morph_dom_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)
236 if (!morph)
237 return isl_size_error;
239 return isl_basic_set_dim(morph->dom, type);
242 isl_size isl_morph_ran_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)
244 if (!morph)
245 return isl_size_error;
247 return isl_basic_set_dim(morph->ran, type);
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)
253 unsigned dom_offset;
255 if (n == 0)
256 return morph;
258 morph = isl_morph_cow(morph);
259 if (!morph)
260 return NULL;
262 dom_offset = 1 + isl_space_offset(morph->dom->dim, type);
264 morph->dom = isl_basic_set_remove_dims(morph->dom, type, first, n);
266 morph->map = isl_mat_drop_cols(morph->map, dom_offset + first, n);
268 morph->inv = isl_mat_drop_rows(morph->inv, dom_offset + first, n);
270 if (morph->dom && morph->ran && morph->map && morph->inv)
271 return morph;
273 isl_morph_free(morph);
274 return NULL;
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)
280 unsigned ran_offset;
282 if (n == 0)
283 return morph;
285 morph = isl_morph_cow(morph);
286 if (!morph)
287 return NULL;
289 ran_offset = 1 + isl_space_offset(morph->ran->dim, type);
291 morph->ran = isl_basic_set_remove_dims(morph->ran, type, first, n);
293 morph->map = isl_mat_drop_rows(morph->map, ran_offset + first, n);
295 morph->inv = isl_mat_drop_cols(morph->inv, ran_offset + first, n);
297 if (morph->dom && morph->ran && morph->map && morph->inv)
298 return morph;
300 isl_morph_free(morph);
301 return NULL;
304 /* Project domain of morph onto its parameter domain.
306 __isl_give isl_morph *isl_morph_dom_params(__isl_take isl_morph *morph)
308 isl_size n;
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;
323 isl_morph_free(morph);
324 return NULL;
327 /* Project range of morph onto its parameter domain.
329 __isl_give isl_morph *isl_morph_ran_params(__isl_take isl_morph *morph)
331 isl_size n;
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;
346 isl_morph_free(morph);
347 return NULL;
350 /* Replace the identifier of the tuple of the range of the morph by "id".
352 static __isl_give isl_morph *isl_morph_set_ran_tuple_id(
353 __isl_take isl_morph *morph, __isl_keep isl_id *id)
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;
364 void isl_morph_print_internal(__isl_take isl_morph *morph, FILE *out)
366 if (!morph)
367 return;
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);
375 void isl_morph_dump(__isl_take isl_morph *morph)
377 isl_morph_print_internal(morph, stderr);
380 __isl_give isl_morph *isl_morph_identity(__isl_keep isl_basic_set *bset)
382 isl_mat *id;
383 isl_basic_set *universe;
384 isl_size total;
386 total = isl_basic_set_dim(bset, isl_dim_all);
387 if (total < 0)
388 return NULL;
390 id = isl_mat_identity(bset->ctx, 1 + total);
391 universe = isl_basic_set_universe(isl_space_copy(bset->dim));
393 return isl_morph_alloc(universe, isl_basic_set_copy(universe),
394 id, isl_mat_copy(id));
397 /* Create a(n identity) morphism between empty sets of the same dimension
398 * a "bset".
400 __isl_give isl_morph *isl_morph_empty(__isl_keep isl_basic_set *bset)
402 isl_mat *id;
403 isl_basic_set *empty;
404 isl_size total;
406 total = isl_basic_set_dim(bset, isl_dim_all);
407 if (total < 0)
408 return NULL;
410 id = isl_mat_identity(bset->ctx, 1 + total);
411 empty = isl_basic_set_empty(isl_space_copy(bset->dim));
413 return isl_morph_alloc(empty, isl_basic_set_copy(empty),
414 id, isl_mat_copy(id));
417 /* Construct a basic set described by the "n" equalities of "bset" starting
418 * at "first".
420 static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset,
421 unsigned first, unsigned n)
423 int i, k;
424 isl_basic_set *eq;
425 isl_size total;
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;
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);
441 return eq;
442 error:
443 isl_basic_set_free(eq);
444 return NULL;
447 /* Given a basic set, exploit the equalities in the basic set to construct
448 * a morphism that maps the basic set to a lower-dimensional space.
449 * Specifically, the morphism reduces the number of dimensions of type "type".
451 * We first select the equalities of interest, that is those that involve
452 * variables of type "type" and no later variables.
453 * Denote those equalities as
455 * -C(p) + M x = 0
457 * where C(p) depends on the parameters if type == isl_dim_set and
458 * is a constant if type == isl_dim_param.
460 * Use isl_mat_final_variable_compression to construct a compression
462 * x = T x'
464 * x' = Q x
466 * If T is a zero-column matrix, then the set of equality constraints
467 * do not admit a solution. In this case, an empty morphism is returned.
469 * Both matrices are extended to map the full original space to the full
470 * compressed space.
472 __isl_give isl_morph *isl_basic_set_variable_compression(
473 __isl_keep isl_basic_set *bset, enum isl_dim_type type)
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;
485 if (!bset)
486 return NULL;
488 if (isl_basic_set_plain_is_empty(bset))
489 return isl_morph_empty(bset);
491 if (isl_basic_set_check_no_locals(bset) < 0)
492 return NULL;
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);
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);
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);
521 Q = isl_mat_diagonal(Q, isl_mat_identity(bset->ctx, nrest));
522 C = isl_mat_diagonal(C, isl_mat_identity(bset->ctx, nrest));
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);
530 return isl_morph_alloc(dom, ran, Q, C);
533 /* Given a basic set, exploit the equalities in the basic set to construct
534 * a morphism that maps the basic set to a lower-dimensional space
535 * with identifier "id".
536 * Specifically, the morphism reduces the number of set dimensions.
538 __isl_give isl_morph *isl_basic_set_variable_compression_with_id(
539 __isl_keep isl_basic_set *bset, __isl_keep isl_id *id)
541 isl_morph *morph;
543 morph = isl_basic_set_variable_compression(bset, isl_dim_set);
544 morph = isl_morph_set_ran_tuple_id(morph, id);
545 return morph;
548 /* Construct a parameter compression for "bset".
549 * We basically just call isl_mat_parameter_compression with the right input
550 * and then extend the resulting matrix to include the variables.
552 * The implementation assumes that "bset" does not have any equalities
553 * that only involve the parameters and that isl_basic_set_gauss has
554 * been applied to "bset".
556 * Let the equalities be given as
558 * B(p) + A x = 0.
560 * We use isl_mat_parameter_compression_ext to compute the compression
562 * p = T p'.
564 __isl_give isl_morph *isl_basic_set_parameter_compression(
565 __isl_keep isl_basic_set *bset)
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;
575 if (!bset)
576 return NULL;
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);
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;
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);
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));
606 dom = isl_basic_set_universe(isl_space_copy(bset->dim));
607 ran = isl_basic_set_universe(isl_space_copy(bset->dim));
609 return isl_morph_alloc(dom, ran, map, inv);
612 /* Construct an isl_multi_aff that corresponds
613 * to the affine transformation matrix "mat" and
614 * that lives in an anonymous space.
616 static __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat_anonymous(
617 __isl_take isl_mat *mat)
619 isl_size n_row, n_col;
620 isl_ctx *ctx;
621 isl_space *space;
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 else
629 space = isl_space_alloc(ctx, 0, n_col - 1, n_row - 1);
631 return isl_multi_aff_from_aff_mat(space, mat);
634 /* Apply the morphism to the basic set.
635 * In particular, compute the preimage of "bset" under the inverse mapping
636 * 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 call
639 * to isl_basic_set_preimage_multi_aff.
641 __isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph,
642 __isl_take isl_basic_set *bset)
644 isl_size n_param;
645 isl_space *space;
646 isl_multi_aff *ma;
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;
654 ma = isl_multi_aff_from_aff_mat_anonymous(isl_mat_copy(morph->inv));
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));
663 isl_morph_free(morph);
664 return bset;
665 error:
666 isl_morph_free(morph);
667 isl_basic_set_free(bset);
668 return NULL;
671 /* Apply the morphism to the set.
672 * In particular, compute the preimage of "set" under the inverse mapping
673 * 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 call
676 * to isl_set_preimage_multi_aff.
678 __isl_give isl_set *isl_morph_set(__isl_take isl_morph *morph,
679 __isl_take isl_set *set)
681 isl_size n_param;
682 isl_space *space;
683 isl_multi_aff *ma;
684 isl_basic_set *ran;
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;
692 ma = isl_multi_aff_from_aff_mat_anonymous(isl_mat_copy(morph->inv));
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));
701 isl_morph_free(morph);
702 return set;
703 error:
704 isl_set_free(set);
705 isl_morph_free(morph);
706 return NULL;
709 /* Construct a morphism that first does morph2 and then morph1.
711 __isl_give isl_morph *isl_morph_compose(__isl_take isl_morph *morph1,
712 __isl_take isl_morph *morph2)
714 isl_mat *map, *inv;
715 isl_basic_set *dom, *ran;
717 if (!morph1 || !morph2)
718 goto error;
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));
729 isl_morph_free(morph1);
730 isl_morph_free(morph2);
732 return isl_morph_alloc(dom, ran, map, inv);
733 error:
734 isl_morph_free(morph1);
735 isl_morph_free(morph2);
736 return NULL;
739 __isl_give isl_morph *isl_morph_inverse(__isl_take isl_morph *morph)
741 isl_basic_set *bset;
742 isl_mat *mat;
744 morph = isl_morph_cow(morph);
745 if (!morph)
746 return NULL;
748 bset = morph->dom;
749 morph->dom = morph->ran;
750 morph->ran = bset;
752 mat = morph->map;
753 morph->map = morph->inv;
754 morph->inv = mat;
756 return morph;
759 /* We detect all the equalities first to avoid implicit equalities
760 * being discovered during the computations. In particular,
761 * the compression on the variables could expose additional stride
762 * constraints on the parameters. This would result in existentially
763 * quantified variables after applying the resulting morph, which
764 * in turn could break invariants of the calling functions.
766 __isl_give isl_morph *isl_basic_set_full_compression(
767 __isl_keep isl_basic_set *bset)
769 isl_morph *morph, *morph2;
771 bset = isl_basic_set_copy(bset);
772 bset = isl_basic_set_detect_equalities(bset);
774 morph = isl_basic_set_variable_compression(bset, isl_dim_param);
775 bset = isl_morph_basic_set(isl_morph_copy(morph), bset);
777 morph2 = isl_basic_set_parameter_compression(bset);
778 bset = isl_morph_basic_set(isl_morph_copy(morph2), bset);
780 morph = isl_morph_compose(morph2, morph);
782 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
783 isl_basic_set_free(bset);
785 morph = isl_morph_compose(morph2, morph);
787 return morph;
790 __isl_give isl_vec *isl_morph_vec(__isl_take isl_morph *morph,
791 __isl_take isl_vec *vec)
793 if (!morph)
794 goto error;
796 vec = isl_mat_vec_product(isl_mat_copy(morph->map), vec);
798 isl_morph_free(morph);
799 return vec;
800 error:
801 isl_morph_free(morph);
802 isl_vec_free(vec);
803 return NULL;