isl_pw_*_un_op: use isl_pw_*_{take,restore}_base_at
[isl.git] / isl_local_space.c
blob1eebd447557544a2f63b9b5fd8197d8e1b177e96
1 /*
2 * Copyright 2011 INRIA Saclay
3 * Copyright 2012-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_ctx_private.h>
14 #include <isl/id.h>
15 #include <isl_map_private.h>
16 #include <isl_local_space_private.h>
17 #include <isl_space_private.h>
18 #include <isl_mat_private.h>
19 #include <isl_aff_private.h>
20 #include <isl_vec_private.h>
21 #include <isl_point_private.h>
22 #include <isl_seq.h>
23 #include <isl_local.h>
25 isl_ctx *isl_local_space_get_ctx(__isl_keep isl_local_space *ls)
27 return ls ? ls->dim->ctx : NULL;
30 /* Return a hash value that digests "ls".
32 uint32_t isl_local_space_get_hash(__isl_keep isl_local_space *ls)
34 uint32_t hash, space_hash, div_hash;
36 if (!ls)
37 return 0;
39 hash = isl_hash_init();
40 space_hash = isl_space_get_full_hash(isl_local_space_peek_space(ls));
41 isl_hash_hash(hash, space_hash);
42 div_hash = isl_mat_get_hash(ls->div);
43 isl_hash_hash(hash, div_hash);
45 return hash;
48 __isl_give isl_local_space *isl_local_space_alloc_div(
49 __isl_take isl_space *space, __isl_take isl_mat *div)
51 isl_ctx *ctx;
52 isl_local_space *ls = NULL;
54 if (!space || !div)
55 goto error;
57 ctx = isl_space_get_ctx(space);
58 ls = isl_calloc_type(ctx, struct isl_local_space);
59 if (!ls)
60 goto error;
62 ls->ref = 1;
63 ls->dim = space;
64 ls->div = div;
66 return ls;
67 error:
68 isl_mat_free(div);
69 isl_space_free(space);
70 isl_local_space_free(ls);
71 return NULL;
74 __isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *space,
75 unsigned n_div)
77 isl_ctx *ctx;
78 isl_mat *div;
79 isl_size total;
81 if (!space)
82 return NULL;
84 total = isl_space_dim(space, isl_dim_all);
85 if (total < 0)
86 return isl_local_space_from_space(isl_space_free(space));
88 ctx = isl_space_get_ctx(space);
89 div = isl_mat_alloc(ctx, n_div, 1 + 1 + total + n_div);
90 return isl_local_space_alloc_div(space, div);
93 __isl_give isl_local_space *isl_local_space_from_space(
94 __isl_take isl_space *space)
96 return isl_local_space_alloc(space, 0);
99 __isl_give isl_local_space *isl_local_space_copy(__isl_keep isl_local_space *ls)
101 if (!ls)
102 return NULL;
104 ls->ref++;
105 return ls;
108 __isl_give isl_local_space *isl_local_space_dup(__isl_keep isl_local_space *ls)
110 if (!ls)
111 return NULL;
113 return isl_local_space_alloc_div(isl_space_copy(ls->dim),
114 isl_mat_copy(ls->div));
118 __isl_give isl_local_space *isl_local_space_cow(__isl_take isl_local_space *ls)
120 if (!ls)
121 return NULL;
123 if (ls->ref == 1)
124 return ls;
125 ls->ref--;
126 return isl_local_space_dup(ls);
129 __isl_null isl_local_space *isl_local_space_free(
130 __isl_take isl_local_space *ls)
132 if (!ls)
133 return NULL;
135 if (--ls->ref > 0)
136 return NULL;
138 isl_space_free(ls->dim);
139 isl_mat_free(ls->div);
141 free(ls);
143 return NULL;
146 /* Is the local space that of a parameter domain?
148 isl_bool isl_local_space_is_params(__isl_keep isl_local_space *ls)
150 if (!ls)
151 return isl_bool_error;
152 return isl_space_is_params(ls->dim);
155 /* Is the local space that of a set?
157 isl_bool isl_local_space_is_set(__isl_keep isl_local_space *ls)
159 return ls ? isl_space_is_set(ls->dim) : isl_bool_error;
162 #undef TYPE
163 #define TYPE isl_local_space
165 #include "isl_type_has_equal_space_bin_templ.c"
166 #include "isl_type_has_space_templ.c"
168 /* Check that the space of "ls" is equal to "space".
170 static isl_stat isl_local_space_check_has_space(__isl_keep isl_local_space *ls,
171 __isl_keep isl_space *space)
173 isl_bool ok;
175 ok = isl_local_space_has_space(ls, space);
176 if (ok < 0)
177 return isl_stat_error;
178 if (!ok)
179 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
180 "spaces don't match", return isl_stat_error);
181 return isl_stat_ok;
184 /* Return true if the two local spaces are identical, with identical
185 * expressions for the integer divisions.
187 isl_bool isl_local_space_is_equal(__isl_keep isl_local_space *ls1,
188 __isl_keep isl_local_space *ls2)
190 isl_bool equal;
192 equal = isl_local_space_has_equal_space(ls1, ls2);
193 if (equal < 0 || !equal)
194 return equal;
196 if (!isl_local_space_divs_known(ls1))
197 return isl_bool_false;
198 if (!isl_local_space_divs_known(ls2))
199 return isl_bool_false;
201 return isl_mat_is_equal(ls1->div, ls2->div);
204 /* Compare two isl_local_spaces.
206 * Return -1 if "ls1" is "smaller" than "ls2", 1 if "ls1" is "greater"
207 * than "ls2" and 0 if they are equal.
209 int isl_local_space_cmp(__isl_keep isl_local_space *ls1,
210 __isl_keep isl_local_space *ls2)
212 int cmp;
214 if (ls1 == ls2)
215 return 0;
216 if (!ls1)
217 return -1;
218 if (!ls2)
219 return 1;
221 cmp = isl_space_cmp(ls1->dim, ls2->dim);
222 if (cmp != 0)
223 return cmp;
225 return isl_local_cmp(ls1->div, ls2->div);
228 isl_size isl_local_space_dim(__isl_keep isl_local_space *ls,
229 enum isl_dim_type type)
231 if (!ls)
232 return isl_size_error;
233 if (type == isl_dim_div)
234 return ls->div->n_row;
235 if (type == isl_dim_all) {
236 isl_size dim = isl_space_dim(ls->dim, isl_dim_all);
237 if (dim < 0)
238 return isl_size_error;
239 return dim + ls->div->n_row;
241 return isl_space_dim(ls->dim, type);
244 #undef TYPE
245 #define TYPE isl_local_space
246 #include "check_type_range_templ.c"
248 unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
249 enum isl_dim_type type)
251 isl_space *space;
253 if (!ls)
254 return 0;
256 space = ls->dim;
257 switch (type) {
258 case isl_dim_cst: return 0;
259 case isl_dim_param: return 1;
260 case isl_dim_in: return 1 + space->nparam;
261 case isl_dim_out: return 1 + space->nparam + space->n_in;
262 case isl_dim_div:
263 return 1 + space->nparam + space->n_in + space->n_out;
264 default: return 0;
268 /* Return the position of the dimension of the given type and name
269 * in "ls".
270 * Return -1 if no such dimension can be found.
272 int isl_local_space_find_dim_by_name(__isl_keep isl_local_space *ls,
273 enum isl_dim_type type, const char *name)
275 if (!ls)
276 return -1;
277 if (type == isl_dim_div)
278 return -1;
279 return isl_space_find_dim_by_name(ls->dim, type, name);
282 /* Does the given dimension have a name?
284 isl_bool isl_local_space_has_dim_name(__isl_keep isl_local_space *ls,
285 enum isl_dim_type type, unsigned pos)
287 return ls ? isl_space_has_dim_name(ls->dim, type, pos) : isl_bool_error;
290 const char *isl_local_space_get_dim_name(__isl_keep isl_local_space *ls,
291 enum isl_dim_type type, unsigned pos)
293 return ls ? isl_space_get_dim_name(ls->dim, type, pos) : NULL;
296 isl_bool isl_local_space_has_dim_id(__isl_keep isl_local_space *ls,
297 enum isl_dim_type type, unsigned pos)
299 return ls ? isl_space_has_dim_id(ls->dim, type, pos) : isl_bool_error;
302 __isl_give isl_id *isl_local_space_get_dim_id(__isl_keep isl_local_space *ls,
303 enum isl_dim_type type, unsigned pos)
305 return ls ? isl_space_get_dim_id(ls->dim, type, pos) : NULL;
308 /* Return the argument of the integer division at position "pos" in "ls".
309 * All local variables in "ls" are known to have a (complete) explicit
310 * representation.
312 static __isl_give isl_aff *extract_div(__isl_keep isl_local_space *ls, int pos)
314 isl_aff *aff;
316 aff = isl_aff_alloc(isl_local_space_copy(ls));
317 if (!aff)
318 return NULL;
319 isl_seq_cpy(aff->v->el, ls->div->row[pos], aff->v->size);
320 return aff;
323 /* Return the argument of the integer division at position "pos" in "ls".
324 * The integer division at that position is known to have a complete
325 * explicit representation, but some of the others do not.
326 * Remove them first because the domain of an isl_aff
327 * is not allowed to have unknown local variables.
329 static __isl_give isl_aff *drop_unknown_divs_and_extract_div(
330 __isl_keep isl_local_space *ls, int pos)
332 int i;
333 isl_size n;
334 isl_bool unknown;
335 isl_aff *aff;
337 n = isl_local_space_dim(ls, isl_dim_div);
338 if (n < 0)
339 return NULL;
340 ls = isl_local_space_copy(ls);
341 for (i = n - 1; i >= 0; --i) {
342 unknown = isl_local_space_div_is_marked_unknown(ls, i);
343 if (unknown < 0)
344 ls = isl_local_space_free(ls);
345 else if (!unknown)
346 continue;
347 ls = isl_local_space_drop_dims(ls, isl_dim_div, i, 1);
348 if (pos > i)
349 --pos;
351 aff = extract_div(ls, pos);
352 isl_local_space_free(ls);
353 return aff;
356 /* Return the argument of the integer division at position "pos" in "ls".
357 * The integer division is assumed to have a complete explicit
358 * representation. If some of the other integer divisions
359 * do not have an explicit representation, then they need
360 * to be removed first because the domain of an isl_aff
361 * is not allowed to have unknown local variables.
363 __isl_give isl_aff *isl_local_space_get_div(__isl_keep isl_local_space *ls,
364 int pos)
366 isl_bool known;
368 if (!ls)
369 return NULL;
371 if (pos < 0 || pos >= ls->div->n_row)
372 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
373 "index out of bounds", return NULL);
375 known = isl_local_space_div_is_known(ls, pos);
376 if (known < 0)
377 return NULL;
378 if (!known)
379 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
380 "expression of div unknown", return NULL);
381 if (!isl_local_space_is_set(ls))
382 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
383 "cannot represent divs of map spaces", return NULL);
385 known = isl_local_space_divs_known(ls);
386 if (known < 0)
387 return NULL;
388 if (known)
389 return extract_div(ls, pos);
390 else
391 return drop_unknown_divs_and_extract_div(ls, pos);
394 /* Return the space of "ls".
396 __isl_keep isl_space *isl_local_space_peek_space(__isl_keep isl_local_space *ls)
398 if (!ls)
399 return NULL;
401 return ls->dim;
404 __isl_give isl_space *isl_local_space_get_space(__isl_keep isl_local_space *ls)
406 return isl_space_copy(isl_local_space_peek_space(ls));
409 /* Return the space of "ls".
410 * This may be either a copy or the space itself
411 * if there is only one reference to "ls".
412 * This allows the space to be modified inplace
413 * if both the local space and its space have only a single reference.
414 * The caller is not allowed to modify "ls" between this call and
415 * a subsequent call to isl_local_space_restore_space.
416 * The only exception is that isl_local_space_free can be called instead.
418 __isl_give isl_space *isl_local_space_take_space(__isl_keep isl_local_space *ls)
420 isl_space *space;
422 if (!ls)
423 return NULL;
424 if (ls->ref != 1)
425 return isl_local_space_get_space(ls);
426 space = ls->dim;
427 ls->dim = NULL;
428 return space;
431 /* Set the space of "ls" to "space", where the space of "ls" may be missing
432 * due to a preceding call to isl_local_space_take_space.
433 * However, in this case, "ls" only has a single reference and
434 * then the call to isl_local_space_cow has no effect.
436 __isl_give isl_local_space *isl_local_space_restore_space(
437 __isl_take isl_local_space *ls, __isl_take isl_space *space)
439 if (!ls || !space)
440 goto error;
442 if (ls->dim == space) {
443 isl_space_free(space);
444 return ls;
447 ls = isl_local_space_cow(ls);
448 if (!ls)
449 goto error;
450 isl_space_free(ls->dim);
451 ls->dim = space;
453 return ls;
454 error:
455 isl_local_space_free(ls);
456 isl_space_free(space);
457 return NULL;
460 /* Return the local variables of "ls".
462 __isl_keep isl_local *isl_local_space_peek_local(__isl_keep isl_local_space *ls)
464 return ls ? ls->div : NULL;
467 /* Replace the identifier of the tuple of type "type" by "id".
469 __isl_give isl_local_space *isl_local_space_set_tuple_id(
470 __isl_take isl_local_space *ls,
471 enum isl_dim_type type, __isl_take isl_id *id)
473 ls = isl_local_space_cow(ls);
474 if (!ls)
475 goto error;
476 ls->dim = isl_space_set_tuple_id(ls->dim, type, id);
477 if (!ls->dim)
478 return isl_local_space_free(ls);
479 return ls;
480 error:
481 isl_id_free(id);
482 return NULL;
485 __isl_give isl_local_space *isl_local_space_set_dim_name(
486 __isl_take isl_local_space *ls,
487 enum isl_dim_type type, unsigned pos, const char *s)
489 ls = isl_local_space_cow(ls);
490 if (!ls)
491 return NULL;
492 ls->dim = isl_space_set_dim_name(ls->dim, type, pos, s);
493 if (!ls->dim)
494 return isl_local_space_free(ls);
496 return ls;
499 __isl_give isl_local_space *isl_local_space_set_dim_id(
500 __isl_take isl_local_space *ls,
501 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
503 ls = isl_local_space_cow(ls);
504 if (!ls)
505 goto error;
506 ls->dim = isl_space_set_dim_id(ls->dim, type, pos, id);
507 if (!ls->dim)
508 return isl_local_space_free(ls);
510 return ls;
511 error:
512 isl_id_free(id);
513 return NULL;
516 /* Construct a zero-dimensional local space with the given parameter domain.
518 __isl_give isl_local_space *isl_local_space_set_from_params(
519 __isl_take isl_local_space *ls)
521 isl_space *space;
523 space = isl_local_space_take_space(ls);
524 space = isl_space_set_from_params(space);
525 ls = isl_local_space_restore_space(ls, space);
527 return ls;
530 __isl_give isl_local_space *isl_local_space_reset_space(
531 __isl_take isl_local_space *ls, __isl_take isl_space *space)
533 ls = isl_local_space_cow(ls);
534 if (!ls || !space)
535 goto error;
537 isl_space_free(ls->dim);
538 ls->dim = space;
540 return ls;
541 error:
542 isl_local_space_free(ls);
543 isl_space_free(space);
544 return NULL;
547 /* Reorder the dimensions of "ls" according to the given reordering.
548 * The reordering r is assumed to have been extended with the local
549 * variables, leaving them in the same order.
551 __isl_give isl_local_space *isl_local_space_realign(
552 __isl_take isl_local_space *ls, __isl_take isl_reordering *r)
554 ls = isl_local_space_cow(ls);
555 if (!ls || !r)
556 goto error;
558 ls->div = isl_local_reorder(ls->div, isl_reordering_copy(r));
559 if (!ls->div)
560 goto error;
562 ls = isl_local_space_reset_space(ls, isl_reordering_get_space(r));
564 isl_reordering_free(r);
565 return ls;
566 error:
567 isl_local_space_free(ls);
568 isl_reordering_free(r);
569 return NULL;
572 __isl_give isl_local_space *isl_local_space_add_div(
573 __isl_take isl_local_space *ls, __isl_take isl_vec *div)
575 ls = isl_local_space_cow(ls);
576 if (!ls || !div)
577 goto error;
579 if (ls->div->n_col != div->size)
580 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
581 "incompatible dimensions", goto error);
583 ls->div = isl_mat_add_zero_cols(ls->div, 1);
584 ls->div = isl_mat_add_rows(ls->div, 1);
585 if (!ls->div)
586 goto error;
588 isl_seq_cpy(ls->div->row[ls->div->n_row - 1], div->el, div->size);
589 isl_int_set_si(ls->div->row[ls->div->n_row - 1][div->size], 0);
591 isl_vec_free(div);
592 return ls;
593 error:
594 isl_local_space_free(ls);
595 isl_vec_free(div);
596 return NULL;
599 __isl_give isl_local_space *isl_local_space_replace_divs(
600 __isl_take isl_local_space *ls, __isl_take isl_mat *div)
602 ls = isl_local_space_cow(ls);
604 if (!ls || !div)
605 goto error;
607 isl_mat_free(ls->div);
608 ls->div = div;
609 return ls;
610 error:
611 isl_mat_free(div);
612 isl_local_space_free(ls);
613 return NULL;
616 /* Copy row "s" of "src" to row "d" of "dst", applying the expansion
617 * defined by "exp".
619 static void expand_row(__isl_keep isl_mat *dst, int d,
620 __isl_keep isl_mat *src, int s, int *exp)
622 int i;
623 unsigned c = src->n_col - src->n_row;
625 isl_seq_cpy(dst->row[d], src->row[s], c);
626 isl_seq_clr(dst->row[d] + c, dst->n_col - c);
628 for (i = 0; i < s; ++i)
629 isl_int_set(dst->row[d][c + exp[i]], src->row[s][c + i]);
632 /* Compare (known) divs.
633 * Return non-zero if at least one of the two divs is unknown.
634 * In particular, if both divs are unknown, we respect their
635 * current order. Otherwise, we sort the known div after the unknown
636 * div only if the known div depends on the unknown div.
638 static int cmp_row(isl_int *row_i, isl_int *row_j, int i, int j,
639 unsigned n_row, unsigned n_col)
641 int li, lj;
642 int unknown_i, unknown_j;
644 unknown_i = isl_int_is_zero(row_i[0]);
645 unknown_j = isl_int_is_zero(row_j[0]);
647 if (unknown_i && unknown_j)
648 return i - j;
650 if (unknown_i)
651 li = n_col - n_row + i;
652 else
653 li = isl_seq_last_non_zero(row_i, n_col);
654 if (unknown_j)
655 lj = n_col - n_row + j;
656 else
657 lj = isl_seq_last_non_zero(row_j, n_col);
659 if (li != lj)
660 return li - lj;
662 return isl_seq_cmp(row_i, row_j, n_col);
665 /* Call cmp_row for divs in a matrix.
667 int isl_mat_cmp_div(__isl_keep isl_mat *div, int i, int j)
669 return cmp_row(div->row[i], div->row[j], i, j, div->n_row, div->n_col);
672 /* Call cmp_row for divs in a basic map.
674 static int bmap_cmp_row(__isl_keep isl_basic_map *bmap, int i, int j,
675 unsigned total)
677 return cmp_row(bmap->div[i], bmap->div[j], i, j, bmap->n_div, total);
680 /* Sort the divs in "bmap".
682 * We first make sure divs are placed after divs on which they depend.
683 * Then we perform a simple insertion sort based on the same ordering
684 * that is used in isl_merge_divs.
686 __isl_give isl_basic_map *isl_basic_map_sort_divs(
687 __isl_take isl_basic_map *bmap)
689 int i, j;
690 isl_size total;
692 bmap = isl_basic_map_order_divs(bmap);
693 if (!bmap)
694 return NULL;
695 if (bmap->n_div <= 1)
696 return bmap;
698 total = isl_basic_map_dim(bmap, isl_dim_all);
699 if (total < 0)
700 return isl_basic_map_free(bmap);
701 for (i = 1; i < bmap->n_div; ++i) {
702 for (j = i - 1; j >= 0; --j) {
703 if (bmap_cmp_row(bmap, j, j + 1, 2 + total) <= 0)
704 break;
705 bmap = isl_basic_map_swap_div(bmap, j, j + 1);
706 if (!bmap)
707 return NULL;
711 return bmap;
714 /* Sort the divs in the basic maps of "map".
716 __isl_give isl_map *isl_map_sort_divs(__isl_take isl_map *map)
718 return isl_map_inline_foreach_basic_map(map, &isl_basic_map_sort_divs);
721 /* Combine the two lists of divs into a single list.
722 * For each row i in div1, exp1[i] is set to the position of the corresponding
723 * row in the result. Similarly for div2 and exp2.
724 * This function guarantees
725 * exp1[i] >= i
726 * exp1[i+1] > exp1[i]
727 * For optimal merging, the two input list should have been sorted.
729 __isl_give isl_mat *isl_merge_divs(__isl_keep isl_mat *div1,
730 __isl_keep isl_mat *div2, int *exp1, int *exp2)
732 int i, j, k;
733 isl_mat *div = NULL;
734 unsigned d;
736 if (!div1 || !div2)
737 return NULL;
739 d = div1->n_col - div1->n_row;
740 div = isl_mat_alloc(div1->ctx, 1 + div1->n_row + div2->n_row,
741 d + div1->n_row + div2->n_row);
742 if (!div)
743 return NULL;
745 for (i = 0, j = 0, k = 0; i < div1->n_row && j < div2->n_row; ++k) {
746 int cmp;
748 expand_row(div, k, div1, i, exp1);
749 expand_row(div, k + 1, div2, j, exp2);
751 cmp = isl_mat_cmp_div(div, k, k + 1);
752 if (cmp == 0) {
753 exp1[i++] = k;
754 exp2[j++] = k;
755 } else if (cmp < 0) {
756 exp1[i++] = k;
757 } else {
758 exp2[j++] = k;
759 isl_seq_cpy(div->row[k], div->row[k + 1], div->n_col);
762 for (; i < div1->n_row; ++i, ++k) {
763 expand_row(div, k, div1, i, exp1);
764 exp1[i] = k;
766 for (; j < div2->n_row; ++j, ++k) {
767 expand_row(div, k, div2, j, exp2);
768 exp2[j] = k;
771 div->n_row = k;
772 div->n_col = d + k;
774 return div;
777 /* Swap divs "a" and "b" in "ls".
779 __isl_give isl_local_space *isl_local_space_swap_div(
780 __isl_take isl_local_space *ls, int a, int b)
782 int offset;
784 ls = isl_local_space_cow(ls);
785 if (!ls)
786 return NULL;
787 if (a < 0 || a >= ls->div->n_row || b < 0 || b >= ls->div->n_row)
788 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
789 "index out of bounds", return isl_local_space_free(ls));
790 offset = ls->div->n_col - ls->div->n_row;
791 ls->div = isl_mat_swap_cols(ls->div, offset + a, offset + b);
792 ls->div = isl_mat_swap_rows(ls->div, a, b);
793 if (!ls->div)
794 return isl_local_space_free(ls);
795 return ls;
798 /* Construct a local space that contains all the divs in either
799 * "ls1" or "ls2".
801 __isl_give isl_local_space *isl_local_space_intersect(
802 __isl_take isl_local_space *ls1, __isl_take isl_local_space *ls2)
804 isl_ctx *ctx;
805 int *exp1 = NULL;
806 int *exp2 = NULL;
807 isl_mat *div = NULL;
808 isl_bool equal;
810 if (!ls1 || !ls2)
811 goto error;
813 ctx = isl_local_space_get_ctx(ls1);
814 if (!isl_space_is_equal(ls1->dim, ls2->dim))
815 isl_die(ctx, isl_error_invalid,
816 "spaces should be identical", goto error);
818 if (ls2->div->n_row == 0) {
819 isl_local_space_free(ls2);
820 return ls1;
823 if (ls1->div->n_row == 0) {
824 isl_local_space_free(ls1);
825 return ls2;
828 exp1 = isl_alloc_array(ctx, int, ls1->div->n_row);
829 exp2 = isl_alloc_array(ctx, int, ls2->div->n_row);
830 if (!exp1 || !exp2)
831 goto error;
833 div = isl_merge_divs(ls1->div, ls2->div, exp1, exp2);
834 if (!div)
835 goto error;
837 equal = isl_mat_is_equal(ls1->div, div);
838 if (equal < 0)
839 goto error;
840 if (!equal)
841 ls1 = isl_local_space_cow(ls1);
842 if (!ls1)
843 goto error;
845 free(exp1);
846 free(exp2);
847 isl_local_space_free(ls2);
848 isl_mat_free(ls1->div);
849 ls1->div = div;
851 return ls1;
852 error:
853 free(exp1);
854 free(exp2);
855 isl_mat_free(div);
856 isl_local_space_free(ls1);
857 isl_local_space_free(ls2);
858 return NULL;
861 /* Is the local variable "div" of "ls" marked as not having
862 * an explicit representation?
863 * Note that even if this variable is not marked in this way and therefore
864 * does have an explicit representation, this representation may still
865 * depend (indirectly) on other local variables that do not
866 * have an explicit representation.
868 isl_bool isl_local_space_div_is_marked_unknown(__isl_keep isl_local_space *ls,
869 int div)
871 if (!ls)
872 return isl_bool_error;
873 return isl_local_div_is_marked_unknown(ls->div, div);
876 /* Does "ls" have a complete explicit representation for div "div"?
878 isl_bool isl_local_space_div_is_known(__isl_keep isl_local_space *ls, int div)
880 if (!ls)
881 return isl_bool_error;
882 return isl_local_div_is_known(ls->div, div);
885 /* Does "ls" have an explicit representation for all local variables?
887 isl_bool isl_local_space_divs_known(__isl_keep isl_local_space *ls)
889 if (!ls)
890 return isl_bool_error;
891 return isl_local_divs_known(ls->div);
894 __isl_give isl_local_space *isl_local_space_domain(
895 __isl_take isl_local_space *ls)
897 isl_size n_out;
899 n_out = isl_local_space_dim(ls, isl_dim_out);
900 if (n_out < 0)
901 return isl_local_space_free(ls);
902 ls = isl_local_space_drop_dims(ls, isl_dim_out, 0, n_out);
903 ls = isl_local_space_cow(ls);
904 if (!ls)
905 return NULL;
906 ls->dim = isl_space_domain(ls->dim);
907 if (!ls->dim)
908 return isl_local_space_free(ls);
909 return ls;
912 __isl_give isl_local_space *isl_local_space_range(
913 __isl_take isl_local_space *ls)
915 isl_size n_in;
917 n_in = isl_local_space_dim(ls, isl_dim_in);
918 if (n_in < 0)
919 return isl_local_space_free(ls);
920 ls = isl_local_space_drop_dims(ls, isl_dim_in, 0, n_in);
921 ls = isl_local_space_cow(ls);
922 if (!ls)
923 return NULL;
925 ls->dim = isl_space_range(ls->dim);
926 if (!ls->dim)
927 return isl_local_space_free(ls);
928 return ls;
931 /* Construct a local space for a map that has the given local
932 * space as domain and that has a zero-dimensional range.
934 __isl_give isl_local_space *isl_local_space_from_domain(
935 __isl_take isl_local_space *ls)
937 ls = isl_local_space_cow(ls);
938 if (!ls)
939 return NULL;
940 ls->dim = isl_space_from_domain(ls->dim);
941 if (!ls->dim)
942 return isl_local_space_free(ls);
943 return ls;
946 __isl_give isl_local_space *isl_local_space_add_dims(
947 __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned n)
949 isl_size pos;
951 pos = isl_local_space_dim(ls, type);
952 if (pos < 0)
953 return isl_local_space_free(ls);
954 return isl_local_space_insert_dims(ls, type, pos, n);
957 /* Lift the basic set "bset", living in the space of "ls"
958 * to live in a space with extra coordinates corresponding
959 * to the local variables of "ls".
961 __isl_give isl_basic_set *isl_local_space_lift_basic_set(
962 __isl_take isl_local_space *ls, __isl_take isl_basic_set *bset)
964 isl_size n_local;
965 isl_space *space;
966 isl_basic_set *ls_bset;
968 n_local = isl_local_space_dim(ls, isl_dim_div);
969 space = isl_basic_set_peek_space(bset);
970 if (n_local < 0 ||
971 isl_local_space_check_has_space(ls, space) < 0)
972 goto error;
974 if (n_local == 0) {
975 isl_local_space_free(ls);
976 return bset;
979 bset = isl_basic_set_add_dims(bset, isl_dim_set, n_local);
980 ls_bset = isl_basic_set_from_local_space(ls);
981 ls_bset = isl_basic_set_lift(ls_bset);
982 ls_bset = isl_basic_set_flatten(ls_bset);
983 bset = isl_basic_set_intersect(bset, ls_bset);
985 return bset;
986 error:
987 isl_local_space_free(ls);
988 isl_basic_set_free(bset);
989 return NULL;
992 /* Lift the set "set", living in the space of "ls"
993 * to live in a space with extra coordinates corresponding
994 * to the local variables of "ls".
996 __isl_give isl_set *isl_local_space_lift_set(__isl_take isl_local_space *ls,
997 __isl_take isl_set *set)
999 isl_size n_local;
1000 isl_basic_set *bset;
1002 n_local = isl_local_space_dim(ls, isl_dim_div);
1003 if (n_local < 0 ||
1004 isl_local_space_check_has_space(ls, isl_set_peek_space(set)) < 0)
1005 goto error;
1007 if (n_local == 0) {
1008 isl_local_space_free(ls);
1009 return set;
1012 set = isl_set_add_dims(set, isl_dim_set, n_local);
1013 bset = isl_basic_set_from_local_space(ls);
1014 bset = isl_basic_set_lift(bset);
1015 bset = isl_basic_set_flatten(bset);
1016 set = isl_set_intersect(set, isl_set_from_basic_set(bset));
1018 return set;
1019 error:
1020 isl_local_space_free(ls);
1021 isl_set_free(set);
1022 return NULL;
1025 /* Remove common factor of non-constant terms and denominator.
1027 static __isl_give isl_local_space *normalize_div(
1028 __isl_take isl_local_space *ls, int div)
1030 isl_ctx *ctx = ls->div->ctx;
1031 unsigned total = ls->div->n_col - 2;
1033 isl_seq_gcd(ls->div->row[div] + 2, total, &ctx->normalize_gcd);
1034 isl_int_gcd(ctx->normalize_gcd,
1035 ctx->normalize_gcd, ls->div->row[div][0]);
1036 if (isl_int_is_one(ctx->normalize_gcd))
1037 return ls;
1039 isl_seq_scale_down(ls->div->row[div] + 2, ls->div->row[div] + 2,
1040 ctx->normalize_gcd, total);
1041 isl_int_divexact(ls->div->row[div][0], ls->div->row[div][0],
1042 ctx->normalize_gcd);
1043 isl_int_fdiv_q(ls->div->row[div][1], ls->div->row[div][1],
1044 ctx->normalize_gcd);
1046 return ls;
1049 /* Exploit the equalities in "eq" to simplify the expressions of
1050 * the integer divisions in "ls".
1051 * The integer divisions in "ls" are assumed to appear as regular
1052 * dimensions in "eq".
1054 __isl_give isl_local_space *isl_local_space_substitute_equalities(
1055 __isl_take isl_local_space *ls, __isl_take isl_basic_set *eq)
1057 int i, j, k;
1058 isl_size total, dim;
1059 unsigned n_div;
1061 if (!ls || !eq)
1062 goto error;
1064 total = isl_space_dim(eq->dim, isl_dim_all);
1065 dim = isl_local_space_dim(ls, isl_dim_all);
1066 if (dim < 0 || total < 0)
1067 goto error;
1068 if (dim != total)
1069 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1070 "spaces don't match", goto error);
1071 total++;
1072 n_div = eq->n_div;
1073 for (i = 0; i < eq->n_eq; ++i) {
1074 j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
1075 if (j < 0 || j == 0 || j >= total)
1076 continue;
1078 for (k = 0; k < ls->div->n_row; ++k) {
1079 if (isl_int_is_zero(ls->div->row[k][1 + j]))
1080 continue;
1081 ls = isl_local_space_cow(ls);
1082 if (!ls)
1083 goto error;
1084 ls->div = isl_mat_cow(ls->div);
1085 if (!ls->div)
1086 goto error;
1087 isl_seq_elim(ls->div->row[k] + 1, eq->eq[i], j, total,
1088 &ls->div->row[k][0]);
1089 ls = normalize_div(ls, k);
1090 if (!ls)
1091 goto error;
1095 isl_basic_set_free(eq);
1096 return ls;
1097 error:
1098 isl_basic_set_free(eq);
1099 isl_local_space_free(ls);
1100 return NULL;
1103 /* Plug in the affine expressions "subs" of length "subs_len" (including
1104 * the denominator and the constant term) into the variable at position "pos"
1105 * of the "n" div expressions starting at "first".
1107 * Let i be the dimension to replace and let "subs" be of the form
1109 * f/d
1111 * Any integer division starting at "first" with a non-zero coefficient for i,
1113 * floor((a i + g)/m)
1115 * is replaced by
1117 * floor((a f + d g)/(m d))
1119 __isl_give isl_local_space *isl_local_space_substitute_seq(
1120 __isl_take isl_local_space *ls,
1121 enum isl_dim_type type, unsigned pos, isl_int *subs, int subs_len,
1122 int first, int n)
1124 int i;
1125 isl_int v;
1127 if (n == 0)
1128 return ls;
1129 ls = isl_local_space_cow(ls);
1130 if (!ls)
1131 return NULL;
1132 ls->div = isl_mat_cow(ls->div);
1133 if (!ls->div)
1134 return isl_local_space_free(ls);
1136 if (first + n > ls->div->n_row)
1137 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1138 "index out of bounds", return isl_local_space_free(ls));
1140 pos += isl_local_space_offset(ls, type);
1142 isl_int_init(v);
1143 for (i = first; i < first + n; ++i) {
1144 if (isl_int_is_zero(ls->div->row[i][1 + pos]))
1145 continue;
1146 isl_seq_substitute(ls->div->row[i], pos, subs,
1147 ls->div->n_col, subs_len, v);
1148 ls = normalize_div(ls, i);
1149 if (!ls)
1150 break;
1152 isl_int_clear(v);
1154 return ls;
1157 /* Plug in "subs" for dimension "type", "pos" in the integer divisions
1158 * of "ls".
1160 * Let i be the dimension to replace and let "subs" be of the form
1162 * f/d
1164 * Any integer division with a non-zero coefficient for i,
1166 * floor((a i + g)/m)
1168 * is replaced by
1170 * floor((a f + d g)/(m d))
1172 __isl_give isl_local_space *isl_local_space_substitute(
1173 __isl_take isl_local_space *ls,
1174 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
1176 isl_size n_div;
1178 ls = isl_local_space_cow(ls);
1179 if (!ls || !subs)
1180 return isl_local_space_free(ls);
1182 if (!isl_space_is_equal(ls->dim, subs->ls->dim))
1183 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1184 "spaces don't match", return isl_local_space_free(ls));
1185 n_div = isl_local_space_dim(subs->ls, isl_dim_div);
1186 if (n_div < 0)
1187 return isl_local_space_free(ls);
1188 if (n_div != 0)
1189 isl_die(isl_local_space_get_ctx(ls), isl_error_unsupported,
1190 "cannot handle divs yet",
1191 return isl_local_space_free(ls));
1193 return isl_local_space_substitute_seq(ls, type, pos, subs->v->el,
1194 subs->v->size, 0, ls->div->n_row);
1197 isl_bool isl_local_space_is_named_or_nested(__isl_keep isl_local_space *ls,
1198 enum isl_dim_type type)
1200 if (!ls)
1201 return isl_bool_error;
1202 return isl_space_is_named_or_nested(ls->dim, type);
1205 __isl_give isl_local_space *isl_local_space_drop_dims(
1206 __isl_take isl_local_space *ls,
1207 enum isl_dim_type type, unsigned first, unsigned n)
1209 if (!ls)
1210 return NULL;
1211 if (n == 0 && !isl_local_space_is_named_or_nested(ls, type))
1212 return ls;
1214 if (isl_local_space_check_range(ls, type, first, n) < 0)
1215 return isl_local_space_free(ls);
1217 ls = isl_local_space_cow(ls);
1218 if (!ls)
1219 return NULL;
1221 if (type == isl_dim_div) {
1222 ls->div = isl_mat_drop_rows(ls->div, first, n);
1223 } else {
1224 ls->dim = isl_space_drop_dims(ls->dim, type, first, n);
1225 if (!ls->dim)
1226 return isl_local_space_free(ls);
1229 first += 1 + isl_local_space_offset(ls, type);
1230 ls->div = isl_mat_drop_cols(ls->div, first, n);
1231 if (!ls->div)
1232 return isl_local_space_free(ls);
1234 return ls;
1237 __isl_give isl_local_space *isl_local_space_insert_dims(
1238 __isl_take isl_local_space *ls,
1239 enum isl_dim_type type, unsigned first, unsigned n)
1241 if (!ls)
1242 return NULL;
1243 if (n == 0 && !isl_local_space_is_named_or_nested(ls, type))
1244 return ls;
1246 if (isl_local_space_check_range(ls, type, first, 0) < 0)
1247 return isl_local_space_free(ls);
1249 ls = isl_local_space_cow(ls);
1250 if (!ls)
1251 return NULL;
1253 if (type == isl_dim_div) {
1254 ls->div = isl_mat_insert_zero_rows(ls->div, first, n);
1255 } else {
1256 ls->dim = isl_space_insert_dims(ls->dim, type, first, n);
1257 if (!ls->dim)
1258 return isl_local_space_free(ls);
1261 first += 1 + isl_local_space_offset(ls, type);
1262 ls->div = isl_mat_insert_zero_cols(ls->div, first, n);
1263 if (!ls->div)
1264 return isl_local_space_free(ls);
1266 return ls;
1269 /* Does the linear part of "constraint" correspond to
1270 * integer division "div" in "ls"?
1272 * That is, given div = floor((c + f)/m), is the constraint of the form
1274 * f - m d + c' >= 0 [sign = 1]
1275 * or
1276 * -f + m d + c'' >= 0 [sign = -1]
1278 * If so, set *sign to the corresponding value.
1280 static isl_bool is_linear_div_constraint(__isl_keep isl_local_space *ls,
1281 isl_int *constraint, unsigned div, int *sign)
1283 isl_bool unknown;
1284 unsigned pos;
1286 unknown = isl_local_space_div_is_marked_unknown(ls, div);
1287 if (unknown < 0)
1288 return isl_bool_error;
1289 if (unknown)
1290 return isl_bool_false;
1292 pos = isl_local_space_offset(ls, isl_dim_div) + div;
1294 if (isl_int_eq(constraint[pos], ls->div->row[div][0])) {
1295 *sign = -1;
1296 if (!isl_seq_is_neg(constraint + 1,
1297 ls->div->row[div] + 2, pos - 1))
1298 return isl_bool_false;
1299 } else if (isl_int_abs_eq(constraint[pos], ls->div->row[div][0])) {
1300 *sign = 1;
1301 if (!isl_seq_eq(constraint + 1, ls->div->row[div] + 2, pos - 1))
1302 return isl_bool_false;
1303 } else {
1304 return isl_bool_false;
1306 if (isl_seq_first_non_zero(constraint + pos + 1,
1307 ls->div->n_row - div - 1) != -1)
1308 return isl_bool_false;
1309 return isl_bool_true;
1312 /* Check if the constraints pointed to by "constraint" is a div
1313 * constraint corresponding to div "div" in "ls".
1315 * That is, if div = floor(f/m), then check if the constraint is
1317 * f - m d >= 0
1318 * or
1319 * -(f-(m-1)) + m d >= 0
1321 * First check if the linear part is of the right form and
1322 * then check the constant term.
1324 isl_bool isl_local_space_is_div_constraint(__isl_keep isl_local_space *ls,
1325 isl_int *constraint, unsigned div)
1327 int sign;
1328 isl_bool linear;
1330 linear = is_linear_div_constraint(ls, constraint, div, &sign);
1331 if (linear < 0 || !linear)
1332 return linear;
1334 if (sign < 0) {
1335 int neg;
1336 isl_int_sub(ls->div->row[div][1],
1337 ls->div->row[div][1], ls->div->row[div][0]);
1338 isl_int_add_ui(ls->div->row[div][1], ls->div->row[div][1], 1);
1339 neg = isl_seq_is_neg(constraint, ls->div->row[div] + 1, 1);
1340 isl_int_sub_ui(ls->div->row[div][1], ls->div->row[div][1], 1);
1341 isl_int_add(ls->div->row[div][1],
1342 ls->div->row[div][1], ls->div->row[div][0]);
1343 if (!neg)
1344 return isl_bool_false;
1345 } else {
1346 if (!isl_int_eq(constraint[0], ls->div->row[div][1]))
1347 return isl_bool_false;
1350 return isl_bool_true;
1353 /* Is the constraint pointed to by "constraint" one
1354 * of an equality that corresponds to integer division "div" in "ls"?
1356 * That is, given an integer division of the form
1358 * a = floor((f + c)/m)
1360 * is the equality of the form
1362 * -f + m d + c' = 0
1364 * Note that the constant term is not checked explicitly, but given
1365 * that this is a valid equality constraint, the constant c' necessarily
1366 * has a value close to -c.
1368 isl_bool isl_local_space_is_div_equality(__isl_keep isl_local_space *ls,
1369 isl_int *constraint, unsigned div)
1371 int sign;
1372 isl_bool linear;
1374 linear = is_linear_div_constraint(ls, constraint, div, &sign);
1375 if (linear < 0 || !linear)
1376 return linear;
1378 return isl_bool_ok(sign < 0);
1382 * Set active[i] to 1 if the dimension at position i is involved
1383 * in the linear expression l.
1385 int *isl_local_space_get_active(__isl_keep isl_local_space *ls, isl_int *l)
1387 int i, j;
1388 isl_ctx *ctx;
1389 int *active = NULL;
1390 isl_size total;
1391 unsigned offset;
1393 ctx = isl_local_space_get_ctx(ls);
1394 total = isl_local_space_dim(ls, isl_dim_all);
1395 if (total < 0)
1396 return NULL;
1397 active = isl_calloc_array(ctx, int, total);
1398 if (total && !active)
1399 return NULL;
1401 for (i = 0; i < total; ++i)
1402 active[i] = !isl_int_is_zero(l[i]);
1404 offset = isl_local_space_offset(ls, isl_dim_div) - 1;
1405 for (i = ls->div->n_row - 1; i >= 0; --i) {
1406 if (!active[offset + i])
1407 continue;
1408 for (j = 0; j < total; ++j)
1409 active[j] |= !isl_int_is_zero(ls->div->row[i][2 + j]);
1412 return active;
1415 /* Given a local space "ls" of a set, create a local space
1416 * for the lift of the set. In particular, the result
1417 * is of the form [dim -> local[..]], with ls->div->n_row variables in the
1418 * range of the wrapped map.
1420 __isl_give isl_local_space *isl_local_space_lift(
1421 __isl_take isl_local_space *ls)
1423 ls = isl_local_space_cow(ls);
1424 if (!ls)
1425 return NULL;
1427 ls->dim = isl_space_lift(ls->dim, ls->div->n_row);
1428 ls->div = isl_mat_drop_rows(ls->div, 0, ls->div->n_row);
1429 if (!ls->dim || !ls->div)
1430 return isl_local_space_free(ls);
1432 return ls;
1435 /* Construct a basic map that maps a set living in local space "ls"
1436 * to the corresponding lifted local space.
1438 __isl_give isl_basic_map *isl_local_space_lifting(
1439 __isl_take isl_local_space *ls)
1441 isl_basic_map *lifting;
1442 isl_basic_set *bset;
1444 if (!ls)
1445 return NULL;
1446 if (!isl_local_space_is_set(ls))
1447 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1448 "lifting only defined on set spaces", goto error);
1450 bset = isl_basic_set_from_local_space(ls);
1451 lifting = isl_basic_set_unwrap(isl_basic_set_lift(bset));
1452 lifting = isl_basic_map_domain_map(lifting);
1453 lifting = isl_basic_map_reverse(lifting);
1455 return lifting;
1456 error:
1457 isl_local_space_free(ls);
1458 return NULL;
1461 /* Compute the preimage of "ls" under the function represented by "ma".
1462 * In other words, plug in "ma" in "ls". The result is a local space
1463 * that is part of the domain space of "ma".
1465 * If the divs in "ls" are represented as
1467 * floor((a_i(p) + b_i x + c_i(divs))/n_i)
1469 * and ma is represented by
1471 * x = D(p) + F(y) + G(divs')
1473 * then the resulting divs are
1475 * floor((a_i(p) + b_i D(p) + b_i F(y) + B_i G(divs') + c_i(divs))/n_i)
1477 * We first copy over the divs from "ma" and then
1478 * we add the modified divs from "ls".
1480 __isl_give isl_local_space *isl_local_space_preimage_multi_aff(
1481 __isl_take isl_local_space *ls, __isl_take isl_multi_aff *ma)
1483 int i;
1484 isl_space *space;
1485 isl_local_space *res = NULL;
1486 isl_size n_div_ls, n_div_ma;
1487 isl_int f, c1, c2, g;
1489 ma = isl_multi_aff_align_divs(ma);
1490 if (!ls || !ma)
1491 goto error;
1492 if (!isl_space_is_range_internal(ls->dim, ma->space))
1493 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1494 "spaces don't match", goto error);
1496 n_div_ls = isl_local_space_dim(ls, isl_dim_div);
1497 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
1498 if (n_div_ls < 0 || n_div_ma < 0)
1499 goto error;
1501 space = isl_space_domain(isl_multi_aff_get_space(ma));
1502 res = isl_local_space_alloc(space, n_div_ma + n_div_ls);
1503 if (!res)
1504 goto error;
1506 if (n_div_ma) {
1507 isl_mat_free(res->div);
1508 res->div = isl_mat_copy(ma->u.p[0]->ls->div);
1509 res->div = isl_mat_add_zero_cols(res->div, n_div_ls);
1510 res->div = isl_mat_add_rows(res->div, n_div_ls);
1511 if (!res->div)
1512 goto error;
1515 isl_int_init(f);
1516 isl_int_init(c1);
1517 isl_int_init(c2);
1518 isl_int_init(g);
1520 for (i = 0; i < ls->div->n_row; ++i) {
1521 if (isl_int_is_zero(ls->div->row[i][0])) {
1522 isl_int_set_si(res->div->row[n_div_ma + i][0], 0);
1523 continue;
1525 if (isl_seq_preimage(res->div->row[n_div_ma + i],
1526 ls->div->row[i],
1527 ma, 0, 0, n_div_ma, n_div_ls, f, c1, c2, g, 1) < 0)
1528 res = isl_local_space_free(res);
1529 res = normalize_div(res, n_div_ma + i);
1530 if (!res)
1531 break;
1534 isl_int_clear(f);
1535 isl_int_clear(c1);
1536 isl_int_clear(c2);
1537 isl_int_clear(g);
1539 isl_local_space_free(ls);
1540 isl_multi_aff_free(ma);
1541 return res;
1542 error:
1543 isl_local_space_free(ls);
1544 isl_multi_aff_free(ma);
1545 isl_local_space_free(res);
1546 return NULL;
1549 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "ls"
1550 * to dimensions of "dst_type" at "dst_pos".
1552 * Moving to/from local dimensions is not allowed.
1553 * We currently assume that the dimension type changes.
1555 __isl_give isl_local_space *isl_local_space_move_dims(
1556 __isl_take isl_local_space *ls,
1557 enum isl_dim_type dst_type, unsigned dst_pos,
1558 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1560 unsigned g_dst_pos;
1561 unsigned g_src_pos;
1563 if (!ls)
1564 return NULL;
1565 if (n == 0 &&
1566 !isl_local_space_is_named_or_nested(ls, src_type) &&
1567 !isl_local_space_is_named_or_nested(ls, dst_type))
1568 return ls;
1570 if (isl_local_space_check_range(ls, src_type, src_pos, n) < 0)
1571 return isl_local_space_free(ls);
1572 if (isl_local_space_check_range(ls, dst_type, dst_pos, 0) < 0)
1573 return isl_local_space_free(ls);
1574 if (src_type == isl_dim_div)
1575 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1576 "cannot move divs", return isl_local_space_free(ls));
1577 if (dst_type == isl_dim_div)
1578 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1579 "cannot move to divs", return isl_local_space_free(ls));
1580 if (dst_type == src_type && dst_pos == src_pos)
1581 return ls;
1582 if (dst_type == src_type)
1583 isl_die(isl_local_space_get_ctx(ls), isl_error_unsupported,
1584 "moving dims within the same type not supported",
1585 return isl_local_space_free(ls));
1587 ls = isl_local_space_cow(ls);
1588 if (!ls)
1589 return NULL;
1591 g_src_pos = 1 + isl_local_space_offset(ls, src_type) + src_pos;
1592 g_dst_pos = 1 + isl_local_space_offset(ls, dst_type) + dst_pos;
1593 if (dst_type > src_type)
1594 g_dst_pos -= n;
1595 ls->div = isl_mat_move_cols(ls->div, g_dst_pos, g_src_pos, n);
1596 if (!ls->div)
1597 return isl_local_space_free(ls);
1598 ls->dim = isl_space_move_dims(ls->dim, dst_type, dst_pos,
1599 src_type, src_pos, n);
1600 if (!ls->dim)
1601 return isl_local_space_free(ls);
1603 return ls;
1606 /* Remove any internal structure of the domain of "ls".
1607 * If there is any such internal structure in the input,
1608 * then the name of the corresponding space is also removed.
1610 __isl_give isl_local_space *isl_local_space_flatten_domain(
1611 __isl_take isl_local_space *ls)
1613 if (!ls)
1614 return NULL;
1616 if (!ls->dim->nested[0])
1617 return ls;
1619 ls = isl_local_space_cow(ls);
1620 if (!ls)
1621 return NULL;
1623 ls->dim = isl_space_flatten_domain(ls->dim);
1624 if (!ls->dim)
1625 return isl_local_space_free(ls);
1627 return ls;
1630 /* Remove any internal structure of the range of "ls".
1631 * If there is any such internal structure in the input,
1632 * then the name of the corresponding space is also removed.
1634 __isl_give isl_local_space *isl_local_space_flatten_range(
1635 __isl_take isl_local_space *ls)
1637 if (!ls)
1638 return NULL;
1640 if (!ls->dim->nested[1])
1641 return ls;
1643 ls = isl_local_space_cow(ls);
1644 if (!ls)
1645 return NULL;
1647 ls->dim = isl_space_flatten_range(ls->dim);
1648 if (!ls->dim)
1649 return isl_local_space_free(ls);
1651 return ls;
1654 /* Given the local space "ls" of a map, return the local space of a set
1655 * that lives in a space that wraps the space of "ls" and that has
1656 * the same divs.
1658 __isl_give isl_local_space *isl_local_space_wrap(__isl_take isl_local_space *ls)
1660 ls = isl_local_space_cow(ls);
1661 if (!ls)
1662 return NULL;
1664 ls->dim = isl_space_wrap(ls->dim);
1665 if (!ls->dim)
1666 return isl_local_space_free(ls);
1668 return ls;
1671 /* Lift the point "pnt", living in the (set) space of "ls"
1672 * to live in a space with extra coordinates corresponding
1673 * to the local variables of "ls".
1675 __isl_give isl_point *isl_local_space_lift_point(__isl_take isl_local_space *ls,
1676 __isl_take isl_point *pnt)
1678 isl_size n_local;
1679 isl_space *space;
1680 isl_local *local;
1681 isl_vec *vec;
1683 if (isl_local_space_check_has_space(ls, isl_point_peek_space(pnt)) < 0)
1684 goto error;
1686 local = isl_local_space_peek_local(ls);
1687 n_local = isl_local_space_dim(ls, isl_dim_div);
1688 if (n_local < 0)
1689 goto error;
1691 space = isl_point_take_space(pnt);
1692 vec = isl_point_take_vec(pnt);
1694 space = isl_space_lift(space, n_local);
1695 vec = isl_local_extend_point_vec(local, vec);
1697 pnt = isl_point_restore_vec(pnt, vec);
1698 pnt = isl_point_restore_space(pnt, space);
1700 isl_local_space_free(ls);
1702 return pnt;
1703 error:
1704 isl_local_space_free(ls);
1705 isl_point_free(pnt);
1706 return NULL;