isl_pw_*_eval: rename "pnt_dim" variable to "pnt_space"
[isl.git] / isl_local_space.c
blob06e4756690f5da3b51d63482b9d42037488f96a5
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_map_private.h>
15 #include <isl_local_space_private.h>
16 #include <isl_space_private.h>
17 #include <isl_mat_private.h>
18 #include <isl_aff_private.h>
19 #include <isl_vec_private.h>
20 #include <isl_point_private.h>
21 #include <isl_seq.h>
22 #include <isl_local.h>
24 isl_ctx *isl_local_space_get_ctx(__isl_keep isl_local_space *ls)
26 return ls ? ls->dim->ctx : NULL;
29 /* Return a hash value that digests "ls".
31 uint32_t isl_local_space_get_hash(__isl_keep isl_local_space *ls)
33 uint32_t hash, space_hash, div_hash;
35 if (!ls)
36 return 0;
38 hash = isl_hash_init();
39 space_hash = isl_space_get_hash(ls->dim);
40 isl_hash_hash(hash, space_hash);
41 div_hash = isl_mat_get_hash(ls->div);
42 isl_hash_hash(hash, div_hash);
44 return hash;
47 __isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_space *dim,
48 __isl_take isl_mat *div)
50 isl_ctx *ctx;
51 isl_local_space *ls = NULL;
53 if (!dim || !div)
54 goto error;
56 ctx = isl_space_get_ctx(dim);
57 ls = isl_calloc_type(ctx, struct isl_local_space);
58 if (!ls)
59 goto error;
61 ls->ref = 1;
62 ls->dim = dim;
63 ls->div = div;
65 return ls;
66 error:
67 isl_mat_free(div);
68 isl_space_free(dim);
69 isl_local_space_free(ls);
70 return NULL;
73 __isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *dim,
74 unsigned n_div)
76 isl_ctx *ctx;
77 isl_mat *div;
78 unsigned total;
80 if (!dim)
81 return NULL;
83 total = isl_space_dim(dim, isl_dim_all);
85 ctx = isl_space_get_ctx(dim);
86 div = isl_mat_alloc(ctx, n_div, 1 + 1 + total + n_div);
87 return isl_local_space_alloc_div(dim, div);
90 __isl_give isl_local_space *isl_local_space_from_space(__isl_take isl_space *dim)
92 return isl_local_space_alloc(dim, 0);
95 __isl_give isl_local_space *isl_local_space_copy(__isl_keep isl_local_space *ls)
97 if (!ls)
98 return NULL;
100 ls->ref++;
101 return ls;
104 __isl_give isl_local_space *isl_local_space_dup(__isl_keep isl_local_space *ls)
106 if (!ls)
107 return NULL;
109 return isl_local_space_alloc_div(isl_space_copy(ls->dim),
110 isl_mat_copy(ls->div));
114 __isl_give isl_local_space *isl_local_space_cow(__isl_take isl_local_space *ls)
116 if (!ls)
117 return NULL;
119 if (ls->ref == 1)
120 return ls;
121 ls->ref--;
122 return isl_local_space_dup(ls);
125 __isl_null isl_local_space *isl_local_space_free(
126 __isl_take isl_local_space *ls)
128 if (!ls)
129 return NULL;
131 if (--ls->ref > 0)
132 return NULL;
134 isl_space_free(ls->dim);
135 isl_mat_free(ls->div);
137 free(ls);
139 return NULL;
142 /* Is the local space that of a parameter domain?
144 isl_bool isl_local_space_is_params(__isl_keep isl_local_space *ls)
146 if (!ls)
147 return isl_bool_error;
148 return isl_space_is_params(ls->dim);
151 /* Is the local space that of a set?
153 isl_bool isl_local_space_is_set(__isl_keep isl_local_space *ls)
155 return ls ? isl_space_is_set(ls->dim) : isl_bool_error;
158 /* Do "ls1" and "ls2" have the same space?
160 isl_bool isl_local_space_has_equal_space(__isl_keep isl_local_space *ls1,
161 __isl_keep isl_local_space *ls2)
163 if (!ls1 || !ls2)
164 return isl_bool_error;
166 return isl_space_is_equal(ls1->dim, ls2->dim);
169 /* Is the space of "ls" equal to "space"?
171 isl_bool isl_local_space_has_space(__isl_keep isl_local_space *ls,
172 __isl_keep isl_space *space)
174 return isl_space_is_equal(isl_local_space_peek_space(ls), space);
177 /* Check that the space of "ls" is equal to "space".
179 static isl_stat isl_local_space_check_has_space(__isl_keep isl_local_space *ls,
180 __isl_keep isl_space *space)
182 isl_bool ok;
184 ok = isl_local_space_has_space(ls, space);
185 if (ok < 0)
186 return isl_stat_error;
187 if (!ok)
188 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
189 "spaces don't match", return isl_stat_error);
190 return isl_stat_ok;
193 /* Return true if the two local spaces are identical, with identical
194 * expressions for the integer divisions.
196 isl_bool isl_local_space_is_equal(__isl_keep isl_local_space *ls1,
197 __isl_keep isl_local_space *ls2)
199 isl_bool equal;
201 equal = isl_local_space_has_equal_space(ls1, ls2);
202 if (equal < 0 || !equal)
203 return equal;
205 if (!isl_local_space_divs_known(ls1))
206 return isl_bool_false;
207 if (!isl_local_space_divs_known(ls2))
208 return isl_bool_false;
210 return isl_mat_is_equal(ls1->div, ls2->div);
213 /* Compare two isl_local_spaces.
215 * Return -1 if "ls1" is "smaller" than "ls2", 1 if "ls1" is "greater"
216 * than "ls2" and 0 if they are equal.
218 int isl_local_space_cmp(__isl_keep isl_local_space *ls1,
219 __isl_keep isl_local_space *ls2)
221 int cmp;
223 if (ls1 == ls2)
224 return 0;
225 if (!ls1)
226 return -1;
227 if (!ls2)
228 return 1;
230 cmp = isl_space_cmp(ls1->dim, ls2->dim);
231 if (cmp != 0)
232 return cmp;
234 return isl_local_cmp(ls1->div, ls2->div);
237 int isl_local_space_dim(__isl_keep isl_local_space *ls,
238 enum isl_dim_type type)
240 if (!ls)
241 return 0;
242 if (type == isl_dim_div)
243 return ls->div->n_row;
244 if (type == isl_dim_all)
245 return isl_space_dim(ls->dim, isl_dim_all) + ls->div->n_row;
246 return isl_space_dim(ls->dim, type);
249 unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
250 enum isl_dim_type type)
252 isl_space *dim;
254 if (!ls)
255 return 0;
257 dim = ls->dim;
258 switch (type) {
259 case isl_dim_cst: return 0;
260 case isl_dim_param: return 1;
261 case isl_dim_in: return 1 + dim->nparam;
262 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
263 case isl_dim_div: return 1 + dim->nparam + dim->n_in + dim->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, n;
333 isl_bool unknown;
334 isl_aff *aff;
336 ls = isl_local_space_copy(ls);
337 n = isl_local_space_dim(ls, isl_dim_div);
338 for (i = n - 1; i >= 0; --i) {
339 unknown = isl_local_space_div_is_marked_unknown(ls, i);
340 if (unknown < 0)
341 ls = isl_local_space_free(ls);
342 else if (!unknown)
343 continue;
344 ls = isl_local_space_drop_dims(ls, isl_dim_div, i, 1);
345 if (pos > i)
346 --pos;
348 aff = extract_div(ls, pos);
349 isl_local_space_free(ls);
350 return aff;
353 /* Return the argument of the integer division at position "pos" in "ls".
354 * The integer division is assumed to have a complete explicit
355 * representation. If some of the other integer divisions
356 * do not have an explicit representation, then they need
357 * to be removed first because the domain of an isl_aff
358 * is not allowed to have unknown local variables.
360 __isl_give isl_aff *isl_local_space_get_div(__isl_keep isl_local_space *ls,
361 int pos)
363 isl_bool known;
365 if (!ls)
366 return NULL;
368 if (pos < 0 || pos >= ls->div->n_row)
369 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
370 "index out of bounds", return NULL);
372 known = isl_local_space_div_is_known(ls, pos);
373 if (known < 0)
374 return NULL;
375 if (!known)
376 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
377 "expression of div unknown", return NULL);
378 if (!isl_local_space_is_set(ls))
379 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
380 "cannot represent divs of map spaces", return NULL);
382 known = isl_local_space_divs_known(ls);
383 if (known < 0)
384 return NULL;
385 if (known)
386 return extract_div(ls, pos);
387 else
388 return drop_unknown_divs_and_extract_div(ls, pos);
391 /* Return the space of "ls".
393 __isl_keep isl_space *isl_local_space_peek_space(__isl_keep isl_local_space *ls)
395 if (!ls)
396 return NULL;
398 return ls->dim;
401 __isl_give isl_space *isl_local_space_get_space(__isl_keep isl_local_space *ls)
403 return isl_space_copy(isl_local_space_peek_space(ls));
406 /* Return the space of "ls".
407 * This may be either a copy or the space itself
408 * if there is only one reference to "ls".
409 * This allows the space to be modified inplace
410 * if both the local space and its space have only a single reference.
411 * The caller is not allowed to modify "ls" between this call and
412 * a subsequent call to isl_local_space_restore_space.
413 * The only exception is that isl_local_space_free can be called instead.
415 __isl_give isl_space *isl_local_space_take_space(__isl_keep isl_local_space *ls)
417 isl_space *space;
419 if (!ls)
420 return NULL;
421 if (ls->ref != 1)
422 return isl_local_space_get_space(ls);
423 space = ls->dim;
424 ls->dim = NULL;
425 return space;
428 /* Set the space of "ls" to "space", where the space of "ls" may be missing
429 * due to a preceding call to isl_local_space_take_space.
430 * However, in this case, "ls" only has a single reference and
431 * then the call to isl_local_space_cow has no effect.
433 __isl_give isl_local_space *isl_local_space_restore_space(
434 __isl_take isl_local_space *ls, __isl_take isl_space *space)
436 if (!ls || !space)
437 goto error;
439 if (ls->dim == space) {
440 isl_space_free(space);
441 return ls;
444 ls = isl_local_space_cow(ls);
445 if (!ls)
446 goto error;
447 isl_space_free(ls->dim);
448 ls->dim = space;
450 return ls;
451 error:
452 isl_local_space_free(ls);
453 isl_space_free(space);
454 return NULL;
457 /* Return the local variables of "ls".
459 __isl_keep isl_local *isl_local_space_peek_local(__isl_keep isl_local_space *ls)
461 return ls ? ls->div : NULL;
464 /* Replace the identifier of the tuple of type "type" by "id".
466 __isl_give isl_local_space *isl_local_space_set_tuple_id(
467 __isl_take isl_local_space *ls,
468 enum isl_dim_type type, __isl_take isl_id *id)
470 ls = isl_local_space_cow(ls);
471 if (!ls)
472 goto error;
473 ls->dim = isl_space_set_tuple_id(ls->dim, type, id);
474 if (!ls->dim)
475 return isl_local_space_free(ls);
476 return ls;
477 error:
478 isl_id_free(id);
479 return NULL;
482 __isl_give isl_local_space *isl_local_space_set_dim_name(
483 __isl_take isl_local_space *ls,
484 enum isl_dim_type type, unsigned pos, const char *s)
486 ls = isl_local_space_cow(ls);
487 if (!ls)
488 return NULL;
489 ls->dim = isl_space_set_dim_name(ls->dim, type, pos, s);
490 if (!ls->dim)
491 return isl_local_space_free(ls);
493 return ls;
496 __isl_give isl_local_space *isl_local_space_set_dim_id(
497 __isl_take isl_local_space *ls,
498 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
500 ls = isl_local_space_cow(ls);
501 if (!ls)
502 goto error;
503 ls->dim = isl_space_set_dim_id(ls->dim, type, pos, id);
504 if (!ls->dim)
505 return isl_local_space_free(ls);
507 return ls;
508 error:
509 isl_id_free(id);
510 return NULL;
513 /* Construct a zero-dimensional local space with the given parameter domain.
515 __isl_give isl_local_space *isl_local_space_set_from_params(
516 __isl_take isl_local_space *ls)
518 isl_space *space;
520 space = isl_local_space_take_space(ls);
521 space = isl_space_set_from_params(space);
522 ls = isl_local_space_restore_space(ls, space);
524 return ls;
527 __isl_give isl_local_space *isl_local_space_reset_space(
528 __isl_take isl_local_space *ls, __isl_take isl_space *dim)
530 ls = isl_local_space_cow(ls);
531 if (!ls || !dim)
532 goto error;
534 isl_space_free(ls->dim);
535 ls->dim = dim;
537 return ls;
538 error:
539 isl_local_space_free(ls);
540 isl_space_free(dim);
541 return NULL;
544 /* Reorder the columns of the given div definitions according to the
545 * given reordering.
546 * The order of the divs themselves is assumed not to change.
548 static __isl_give isl_mat *reorder_divs(__isl_take isl_mat *div,
549 __isl_take isl_reordering *r)
551 int i, j;
552 isl_mat *mat;
553 int extra;
555 if (!div || !r)
556 goto error;
558 extra = isl_space_dim(r->dim, isl_dim_all) + div->n_row - r->len;
559 mat = isl_mat_alloc(div->ctx, div->n_row, div->n_col + extra);
560 if (!mat)
561 goto error;
563 for (i = 0; i < div->n_row; ++i) {
564 isl_seq_cpy(mat->row[i], div->row[i], 2);
565 isl_seq_clr(mat->row[i] + 2, mat->n_col - 2);
566 for (j = 0; j < r->len; ++j)
567 isl_int_set(mat->row[i][2 + r->pos[j]],
568 div->row[i][2 + j]);
571 isl_reordering_free(r);
572 isl_mat_free(div);
573 return mat;
574 error:
575 isl_reordering_free(r);
576 isl_mat_free(div);
577 return NULL;
580 /* Reorder the dimensions of "ls" according to the given reordering.
581 * The reordering r is assumed to have been extended with the local
582 * variables, leaving them in the same order.
584 __isl_give isl_local_space *isl_local_space_realign(
585 __isl_take isl_local_space *ls, __isl_take isl_reordering *r)
587 ls = isl_local_space_cow(ls);
588 if (!ls || !r)
589 goto error;
591 ls->div = reorder_divs(ls->div, isl_reordering_copy(r));
592 if (!ls->div)
593 goto error;
595 ls = isl_local_space_reset_space(ls, isl_space_copy(r->dim));
597 isl_reordering_free(r);
598 return ls;
599 error:
600 isl_local_space_free(ls);
601 isl_reordering_free(r);
602 return NULL;
605 __isl_give isl_local_space *isl_local_space_add_div(
606 __isl_take isl_local_space *ls, __isl_take isl_vec *div)
608 ls = isl_local_space_cow(ls);
609 if (!ls || !div)
610 goto error;
612 if (ls->div->n_col != div->size)
613 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
614 "incompatible dimensions", goto error);
616 ls->div = isl_mat_add_zero_cols(ls->div, 1);
617 ls->div = isl_mat_add_rows(ls->div, 1);
618 if (!ls->div)
619 goto error;
621 isl_seq_cpy(ls->div->row[ls->div->n_row - 1], div->el, div->size);
622 isl_int_set_si(ls->div->row[ls->div->n_row - 1][div->size], 0);
624 isl_vec_free(div);
625 return ls;
626 error:
627 isl_local_space_free(ls);
628 isl_vec_free(div);
629 return NULL;
632 __isl_give isl_local_space *isl_local_space_replace_divs(
633 __isl_take isl_local_space *ls, __isl_take isl_mat *div)
635 ls = isl_local_space_cow(ls);
637 if (!ls || !div)
638 goto error;
640 isl_mat_free(ls->div);
641 ls->div = div;
642 return ls;
643 error:
644 isl_mat_free(div);
645 isl_local_space_free(ls);
646 return NULL;
649 /* Copy row "s" of "src" to row "d" of "dst", applying the expansion
650 * defined by "exp".
652 static void expand_row(__isl_keep isl_mat *dst, int d,
653 __isl_keep isl_mat *src, int s, int *exp)
655 int i;
656 unsigned c = src->n_col - src->n_row;
658 isl_seq_cpy(dst->row[d], src->row[s], c);
659 isl_seq_clr(dst->row[d] + c, dst->n_col - c);
661 for (i = 0; i < s; ++i)
662 isl_int_set(dst->row[d][c + exp[i]], src->row[s][c + i]);
665 /* Compare (known) divs.
666 * Return non-zero if at least one of the two divs is unknown.
667 * In particular, if both divs are unknown, we respect their
668 * current order. Otherwise, we sort the known div after the unknown
669 * div only if the known div depends on the unknown div.
671 static int cmp_row(isl_int *row_i, isl_int *row_j, int i, int j,
672 unsigned n_row, unsigned n_col)
674 int li, lj;
675 int unknown_i, unknown_j;
677 unknown_i = isl_int_is_zero(row_i[0]);
678 unknown_j = isl_int_is_zero(row_j[0]);
680 if (unknown_i && unknown_j)
681 return i - j;
683 if (unknown_i)
684 li = n_col - n_row + i;
685 else
686 li = isl_seq_last_non_zero(row_i, n_col);
687 if (unknown_j)
688 lj = n_col - n_row + j;
689 else
690 lj = isl_seq_last_non_zero(row_j, n_col);
692 if (li != lj)
693 return li - lj;
695 return isl_seq_cmp(row_i, row_j, n_col);
698 /* Call cmp_row for divs in a matrix.
700 int isl_mat_cmp_div(__isl_keep isl_mat *div, int i, int j)
702 return cmp_row(div->row[i], div->row[j], i, j, div->n_row, div->n_col);
705 /* Call cmp_row for divs in a basic map.
707 static int bmap_cmp_row(__isl_keep isl_basic_map *bmap, int i, int j,
708 unsigned total)
710 return cmp_row(bmap->div[i], bmap->div[j], i, j, bmap->n_div, total);
713 /* Sort the divs in "bmap".
715 * We first make sure divs are placed after divs on which they depend.
716 * Then we perform a simple insertion sort based on the same ordering
717 * that is used in isl_merge_divs.
719 __isl_give isl_basic_map *isl_basic_map_sort_divs(
720 __isl_take isl_basic_map *bmap)
722 int i, j;
723 unsigned total;
725 bmap = isl_basic_map_order_divs(bmap);
726 if (!bmap)
727 return NULL;
728 if (bmap->n_div <= 1)
729 return bmap;
731 total = 2 + isl_basic_map_total_dim(bmap);
732 for (i = 1; i < bmap->n_div; ++i) {
733 for (j = i - 1; j >= 0; --j) {
734 if (bmap_cmp_row(bmap, j, j + 1, total) <= 0)
735 break;
736 isl_basic_map_swap_div(bmap, j, j + 1);
740 return bmap;
743 /* Sort the divs in the basic maps of "map".
745 __isl_give isl_map *isl_map_sort_divs(__isl_take isl_map *map)
747 return isl_map_inline_foreach_basic_map(map, &isl_basic_map_sort_divs);
750 /* Combine the two lists of divs into a single list.
751 * For each row i in div1, exp1[i] is set to the position of the corresponding
752 * row in the result. Similarly for div2 and exp2.
753 * This function guarantees
754 * exp1[i] >= i
755 * exp1[i+1] > exp1[i]
756 * For optimal merging, the two input list should have been sorted.
758 __isl_give isl_mat *isl_merge_divs(__isl_keep isl_mat *div1,
759 __isl_keep isl_mat *div2, int *exp1, int *exp2)
761 int i, j, k;
762 isl_mat *div = NULL;
763 unsigned d;
765 if (!div1 || !div2)
766 return NULL;
768 d = div1->n_col - div1->n_row;
769 div = isl_mat_alloc(div1->ctx, 1 + div1->n_row + div2->n_row,
770 d + div1->n_row + div2->n_row);
771 if (!div)
772 return NULL;
774 for (i = 0, j = 0, k = 0; i < div1->n_row && j < div2->n_row; ++k) {
775 int cmp;
777 expand_row(div, k, div1, i, exp1);
778 expand_row(div, k + 1, div2, j, exp2);
780 cmp = isl_mat_cmp_div(div, k, k + 1);
781 if (cmp == 0) {
782 exp1[i++] = k;
783 exp2[j++] = k;
784 } else if (cmp < 0) {
785 exp1[i++] = k;
786 } else {
787 exp2[j++] = k;
788 isl_seq_cpy(div->row[k], div->row[k + 1], div->n_col);
791 for (; i < div1->n_row; ++i, ++k) {
792 expand_row(div, k, div1, i, exp1);
793 exp1[i] = k;
795 for (; j < div2->n_row; ++j, ++k) {
796 expand_row(div, k, div2, j, exp2);
797 exp2[j] = k;
800 div->n_row = k;
801 div->n_col = d + k;
803 return div;
806 /* Swap divs "a" and "b" in "ls".
808 __isl_give isl_local_space *isl_local_space_swap_div(
809 __isl_take isl_local_space *ls, int a, int b)
811 int offset;
813 ls = isl_local_space_cow(ls);
814 if (!ls)
815 return NULL;
816 if (a < 0 || a >= ls->div->n_row || b < 0 || b >= ls->div->n_row)
817 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
818 "index out of bounds", return isl_local_space_free(ls));
819 offset = ls->div->n_col - ls->div->n_row;
820 ls->div = isl_mat_swap_cols(ls->div, offset + a, offset + b);
821 ls->div = isl_mat_swap_rows(ls->div, a, b);
822 if (!ls->div)
823 return isl_local_space_free(ls);
824 return ls;
827 /* Construct a local space that contains all the divs in either
828 * "ls1" or "ls2".
830 __isl_give isl_local_space *isl_local_space_intersect(
831 __isl_take isl_local_space *ls1, __isl_take isl_local_space *ls2)
833 isl_ctx *ctx;
834 int *exp1 = NULL;
835 int *exp2 = NULL;
836 isl_mat *div = NULL;
837 isl_bool equal;
839 if (!ls1 || !ls2)
840 goto error;
842 ctx = isl_local_space_get_ctx(ls1);
843 if (!isl_space_is_equal(ls1->dim, ls2->dim))
844 isl_die(ctx, isl_error_invalid,
845 "spaces should be identical", goto error);
847 if (ls2->div->n_row == 0) {
848 isl_local_space_free(ls2);
849 return ls1;
852 if (ls1->div->n_row == 0) {
853 isl_local_space_free(ls1);
854 return ls2;
857 exp1 = isl_alloc_array(ctx, int, ls1->div->n_row);
858 exp2 = isl_alloc_array(ctx, int, ls2->div->n_row);
859 if (!exp1 || !exp2)
860 goto error;
862 div = isl_merge_divs(ls1->div, ls2->div, exp1, exp2);
863 if (!div)
864 goto error;
866 equal = isl_mat_is_equal(ls1->div, div);
867 if (equal < 0)
868 goto error;
869 if (!equal)
870 ls1 = isl_local_space_cow(ls1);
871 if (!ls1)
872 goto error;
874 free(exp1);
875 free(exp2);
876 isl_local_space_free(ls2);
877 isl_mat_free(ls1->div);
878 ls1->div = div;
880 return ls1;
881 error:
882 free(exp1);
883 free(exp2);
884 isl_mat_free(div);
885 isl_local_space_free(ls1);
886 isl_local_space_free(ls2);
887 return NULL;
890 /* Is the local variable "div" of "ls" marked as not having
891 * an explicit representation?
892 * Note that even if this variable is not marked in this way and therefore
893 * does have an explicit representation, this representation may still
894 * depend (indirectly) on other local variables that do not
895 * have an explicit representation.
897 isl_bool isl_local_space_div_is_marked_unknown(__isl_keep isl_local_space *ls,
898 int div)
900 if (!ls)
901 return isl_bool_error;
902 return isl_local_div_is_marked_unknown(ls->div, div);
905 /* Does "ls" have a complete explicit representation for div "div"?
907 isl_bool isl_local_space_div_is_known(__isl_keep isl_local_space *ls, int div)
909 if (!ls)
910 return isl_bool_error;
911 return isl_local_div_is_known(ls->div, div);
914 /* Does "ls" have an explicit representation for all local variables?
916 isl_bool isl_local_space_divs_known(__isl_keep isl_local_space *ls)
918 if (!ls)
919 return isl_bool_error;
920 return isl_local_divs_known(ls->div);
923 __isl_give isl_local_space *isl_local_space_domain(
924 __isl_take isl_local_space *ls)
926 ls = isl_local_space_drop_dims(ls, isl_dim_out,
927 0, isl_local_space_dim(ls, isl_dim_out));
928 ls = isl_local_space_cow(ls);
929 if (!ls)
930 return NULL;
931 ls->dim = isl_space_domain(ls->dim);
932 if (!ls->dim)
933 return isl_local_space_free(ls);
934 return ls;
937 __isl_give isl_local_space *isl_local_space_range(
938 __isl_take isl_local_space *ls)
940 ls = isl_local_space_drop_dims(ls, isl_dim_in,
941 0, isl_local_space_dim(ls, isl_dim_in));
942 ls = isl_local_space_cow(ls);
943 if (!ls)
944 return NULL;
946 ls->dim = isl_space_range(ls->dim);
947 if (!ls->dim)
948 return isl_local_space_free(ls);
949 return ls;
952 /* Construct a local space for a map that has the given local
953 * space as domain and that has a zero-dimensional range.
955 __isl_give isl_local_space *isl_local_space_from_domain(
956 __isl_take isl_local_space *ls)
958 ls = isl_local_space_cow(ls);
959 if (!ls)
960 return NULL;
961 ls->dim = isl_space_from_domain(ls->dim);
962 if (!ls->dim)
963 return isl_local_space_free(ls);
964 return ls;
967 __isl_give isl_local_space *isl_local_space_add_dims(
968 __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned n)
970 int pos;
972 if (!ls)
973 return NULL;
974 pos = isl_local_space_dim(ls, type);
975 return isl_local_space_insert_dims(ls, type, pos, n);
978 /* Remove common factor of non-constant terms and denominator.
980 static void normalize_div(__isl_keep isl_local_space *ls, int div)
982 isl_ctx *ctx = ls->div->ctx;
983 unsigned total = ls->div->n_col - 2;
985 isl_seq_gcd(ls->div->row[div] + 2, total, &ctx->normalize_gcd);
986 isl_int_gcd(ctx->normalize_gcd,
987 ctx->normalize_gcd, ls->div->row[div][0]);
988 if (isl_int_is_one(ctx->normalize_gcd))
989 return;
991 isl_seq_scale_down(ls->div->row[div] + 2, ls->div->row[div] + 2,
992 ctx->normalize_gcd, total);
993 isl_int_divexact(ls->div->row[div][0], ls->div->row[div][0],
994 ctx->normalize_gcd);
995 isl_int_fdiv_q(ls->div->row[div][1], ls->div->row[div][1],
996 ctx->normalize_gcd);
999 /* Exploit the equalities in "eq" to simplify the expressions of
1000 * the integer divisions in "ls".
1001 * The integer divisions in "ls" are assumed to appear as regular
1002 * dimensions in "eq".
1004 __isl_give isl_local_space *isl_local_space_substitute_equalities(
1005 __isl_take isl_local_space *ls, __isl_take isl_basic_set *eq)
1007 int i, j, k;
1008 unsigned total;
1009 unsigned n_div;
1011 if (!ls || !eq)
1012 goto error;
1014 total = isl_space_dim(eq->dim, isl_dim_all);
1015 if (isl_local_space_dim(ls, isl_dim_all) != total)
1016 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1017 "spaces don't match", goto error);
1018 total++;
1019 n_div = eq->n_div;
1020 for (i = 0; i < eq->n_eq; ++i) {
1021 j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
1022 if (j < 0 || j == 0 || j >= total)
1023 continue;
1025 for (k = 0; k < ls->div->n_row; ++k) {
1026 if (isl_int_is_zero(ls->div->row[k][1 + j]))
1027 continue;
1028 ls = isl_local_space_cow(ls);
1029 if (!ls)
1030 goto error;
1031 ls->div = isl_mat_cow(ls->div);
1032 if (!ls->div)
1033 goto error;
1034 isl_seq_elim(ls->div->row[k] + 1, eq->eq[i], j, total,
1035 &ls->div->row[k][0]);
1036 normalize_div(ls, k);
1040 isl_basic_set_free(eq);
1041 return ls;
1042 error:
1043 isl_basic_set_free(eq);
1044 isl_local_space_free(ls);
1045 return NULL;
1048 /* Plug in the affine expressions "subs" of length "subs_len" (including
1049 * the denominator and the constant term) into the variable at position "pos"
1050 * of the "n" div expressions starting at "first".
1052 * Let i be the dimension to replace and let "subs" be of the form
1054 * f/d
1056 * Any integer division starting at "first" with a non-zero coefficient for i,
1058 * floor((a i + g)/m)
1060 * is replaced by
1062 * floor((a f + d g)/(m d))
1064 __isl_give isl_local_space *isl_local_space_substitute_seq(
1065 __isl_take isl_local_space *ls,
1066 enum isl_dim_type type, unsigned pos, isl_int *subs, int subs_len,
1067 int first, int n)
1069 int i;
1070 isl_int v;
1072 if (n == 0)
1073 return ls;
1074 ls = isl_local_space_cow(ls);
1075 if (!ls)
1076 return NULL;
1077 ls->div = isl_mat_cow(ls->div);
1078 if (!ls->div)
1079 return isl_local_space_free(ls);
1081 if (first + n > ls->div->n_row)
1082 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1083 "index out of bounds", return isl_local_space_free(ls));
1085 pos += isl_local_space_offset(ls, type);
1087 isl_int_init(v);
1088 for (i = first; i < first + n; ++i) {
1089 if (isl_int_is_zero(ls->div->row[i][1 + pos]))
1090 continue;
1091 isl_seq_substitute(ls->div->row[i], pos, subs,
1092 ls->div->n_col, subs_len, v);
1093 normalize_div(ls, i);
1095 isl_int_clear(v);
1097 return ls;
1100 /* Plug in "subs" for dimension "type", "pos" in the integer divisions
1101 * of "ls".
1103 * Let i be the dimension to replace and let "subs" be of the form
1105 * f/d
1107 * Any integer division with a non-zero coefficient for i,
1109 * floor((a i + g)/m)
1111 * is replaced by
1113 * floor((a f + d g)/(m d))
1115 __isl_give isl_local_space *isl_local_space_substitute(
1116 __isl_take isl_local_space *ls,
1117 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
1119 ls = isl_local_space_cow(ls);
1120 if (!ls || !subs)
1121 return isl_local_space_free(ls);
1123 if (!isl_space_is_equal(ls->dim, subs->ls->dim))
1124 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1125 "spaces don't match", return isl_local_space_free(ls));
1126 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
1127 isl_die(isl_local_space_get_ctx(ls), isl_error_unsupported,
1128 "cannot handle divs yet",
1129 return isl_local_space_free(ls));
1131 return isl_local_space_substitute_seq(ls, type, pos, subs->v->el,
1132 subs->v->size, 0, ls->div->n_row);
1135 isl_bool isl_local_space_is_named_or_nested(__isl_keep isl_local_space *ls,
1136 enum isl_dim_type type)
1138 if (!ls)
1139 return isl_bool_error;
1140 return isl_space_is_named_or_nested(ls->dim, type);
1143 __isl_give isl_local_space *isl_local_space_drop_dims(
1144 __isl_take isl_local_space *ls,
1145 enum isl_dim_type type, unsigned first, unsigned n)
1147 isl_ctx *ctx;
1149 if (!ls)
1150 return NULL;
1151 if (n == 0 && !isl_local_space_is_named_or_nested(ls, type))
1152 return ls;
1154 ctx = isl_local_space_get_ctx(ls);
1155 if (first + n > isl_local_space_dim(ls, type))
1156 isl_die(ctx, isl_error_invalid, "range out of bounds",
1157 return isl_local_space_free(ls));
1159 ls = isl_local_space_cow(ls);
1160 if (!ls)
1161 return NULL;
1163 if (type == isl_dim_div) {
1164 ls->div = isl_mat_drop_rows(ls->div, first, n);
1165 } else {
1166 ls->dim = isl_space_drop_dims(ls->dim, type, first, n);
1167 if (!ls->dim)
1168 return isl_local_space_free(ls);
1171 first += 1 + isl_local_space_offset(ls, type);
1172 ls->div = isl_mat_drop_cols(ls->div, first, n);
1173 if (!ls->div)
1174 return isl_local_space_free(ls);
1176 return ls;
1179 __isl_give isl_local_space *isl_local_space_insert_dims(
1180 __isl_take isl_local_space *ls,
1181 enum isl_dim_type type, unsigned first, unsigned n)
1183 isl_ctx *ctx;
1185 if (!ls)
1186 return NULL;
1187 if (n == 0 && !isl_local_space_is_named_or_nested(ls, type))
1188 return ls;
1190 ctx = isl_local_space_get_ctx(ls);
1191 if (first > isl_local_space_dim(ls, type))
1192 isl_die(ctx, isl_error_invalid, "position out of bounds",
1193 return isl_local_space_free(ls));
1195 ls = isl_local_space_cow(ls);
1196 if (!ls)
1197 return NULL;
1199 if (type == isl_dim_div) {
1200 ls->div = isl_mat_insert_zero_rows(ls->div, first, n);
1201 } else {
1202 ls->dim = isl_space_insert_dims(ls->dim, type, first, n);
1203 if (!ls->dim)
1204 return isl_local_space_free(ls);
1207 first += 1 + isl_local_space_offset(ls, type);
1208 ls->div = isl_mat_insert_zero_cols(ls->div, first, n);
1209 if (!ls->div)
1210 return isl_local_space_free(ls);
1212 return ls;
1215 /* Check if the constraints pointed to by "constraint" is a div
1216 * constraint corresponding to div "div" in "ls".
1218 * That is, if div = floor(f/m), then check if the constraint is
1220 * f - m d >= 0
1221 * or
1222 * -(f-(m-1)) + m d >= 0
1224 isl_bool isl_local_space_is_div_constraint(__isl_keep isl_local_space *ls,
1225 isl_int *constraint, unsigned div)
1227 unsigned pos;
1229 if (!ls)
1230 return isl_bool_error;
1232 if (isl_int_is_zero(ls->div->row[div][0]))
1233 return isl_bool_false;
1235 pos = isl_local_space_offset(ls, isl_dim_div) + div;
1237 if (isl_int_eq(constraint[pos], ls->div->row[div][0])) {
1238 int neg;
1239 isl_int_sub(ls->div->row[div][1],
1240 ls->div->row[div][1], ls->div->row[div][0]);
1241 isl_int_add_ui(ls->div->row[div][1], ls->div->row[div][1], 1);
1242 neg = isl_seq_is_neg(constraint, ls->div->row[div]+1, pos);
1243 isl_int_sub_ui(ls->div->row[div][1], ls->div->row[div][1], 1);
1244 isl_int_add(ls->div->row[div][1],
1245 ls->div->row[div][1], ls->div->row[div][0]);
1246 if (!neg)
1247 return isl_bool_false;
1248 if (isl_seq_first_non_zero(constraint+pos+1,
1249 ls->div->n_row-div-1) != -1)
1250 return isl_bool_false;
1251 } else if (isl_int_abs_eq(constraint[pos], ls->div->row[div][0])) {
1252 if (!isl_seq_eq(constraint, ls->div->row[div]+1, pos))
1253 return isl_bool_false;
1254 if (isl_seq_first_non_zero(constraint+pos+1,
1255 ls->div->n_row-div-1) != -1)
1256 return isl_bool_false;
1257 } else
1258 return isl_bool_false;
1260 return isl_bool_true;
1264 * Set active[i] to 1 if the dimension at position i is involved
1265 * in the linear expression l.
1267 int *isl_local_space_get_active(__isl_keep isl_local_space *ls, isl_int *l)
1269 int i, j;
1270 isl_ctx *ctx;
1271 int *active = NULL;
1272 unsigned total;
1273 unsigned offset;
1275 ctx = isl_local_space_get_ctx(ls);
1276 total = isl_local_space_dim(ls, isl_dim_all);
1277 active = isl_calloc_array(ctx, int, total);
1278 if (total && !active)
1279 return NULL;
1281 for (i = 0; i < total; ++i)
1282 active[i] = !isl_int_is_zero(l[i]);
1284 offset = isl_local_space_offset(ls, isl_dim_div) - 1;
1285 for (i = ls->div->n_row - 1; i >= 0; --i) {
1286 if (!active[offset + i])
1287 continue;
1288 for (j = 0; j < total; ++j)
1289 active[j] |= !isl_int_is_zero(ls->div->row[i][2 + j]);
1292 return active;
1295 /* Given a local space "ls" of a set, create a local space
1296 * for the lift of the set. In particular, the result
1297 * is of the form [dim -> local[..]], with ls->div->n_row variables in the
1298 * range of the wrapped map.
1300 __isl_give isl_local_space *isl_local_space_lift(
1301 __isl_take isl_local_space *ls)
1303 ls = isl_local_space_cow(ls);
1304 if (!ls)
1305 return NULL;
1307 ls->dim = isl_space_lift(ls->dim, ls->div->n_row);
1308 ls->div = isl_mat_drop_rows(ls->div, 0, ls->div->n_row);
1309 if (!ls->dim || !ls->div)
1310 return isl_local_space_free(ls);
1312 return ls;
1315 /* Construct a basic map that maps a set living in local space "ls"
1316 * to the corresponding lifted local space.
1318 __isl_give isl_basic_map *isl_local_space_lifting(
1319 __isl_take isl_local_space *ls)
1321 isl_basic_map *lifting;
1322 isl_basic_set *bset;
1324 if (!ls)
1325 return NULL;
1326 if (!isl_local_space_is_set(ls))
1327 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1328 "lifting only defined on set spaces", goto error);
1330 bset = isl_basic_set_from_local_space(ls);
1331 lifting = isl_basic_set_unwrap(isl_basic_set_lift(bset));
1332 lifting = isl_basic_map_domain_map(lifting);
1333 lifting = isl_basic_map_reverse(lifting);
1335 return lifting;
1336 error:
1337 isl_local_space_free(ls);
1338 return NULL;
1341 /* Compute the preimage of "ls" under the function represented by "ma".
1342 * In other words, plug in "ma" in "ls". The result is a local space
1343 * that is part of the domain space of "ma".
1345 * If the divs in "ls" are represented as
1347 * floor((a_i(p) + b_i x + c_i(divs))/n_i)
1349 * and ma is represented by
1351 * x = D(p) + F(y) + G(divs')
1353 * then the resulting divs are
1355 * floor((a_i(p) + b_i D(p) + b_i F(y) + B_i G(divs') + c_i(divs))/n_i)
1357 * We first copy over the divs from "ma" and then
1358 * we add the modified divs from "ls".
1360 __isl_give isl_local_space *isl_local_space_preimage_multi_aff(
1361 __isl_take isl_local_space *ls, __isl_take isl_multi_aff *ma)
1363 int i;
1364 isl_space *space;
1365 isl_local_space *res = NULL;
1366 int n_div_ls, n_div_ma;
1367 isl_int f, c1, c2, g;
1369 ma = isl_multi_aff_align_divs(ma);
1370 if (!ls || !ma)
1371 goto error;
1372 if (!isl_space_is_range_internal(ls->dim, ma->space))
1373 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1374 "spaces don't match", goto error);
1376 n_div_ls = isl_local_space_dim(ls, isl_dim_div);
1377 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
1379 space = isl_space_domain(isl_multi_aff_get_space(ma));
1380 res = isl_local_space_alloc(space, n_div_ma + n_div_ls);
1381 if (!res)
1382 goto error;
1384 if (n_div_ma) {
1385 isl_mat_free(res->div);
1386 res->div = isl_mat_copy(ma->u.p[0]->ls->div);
1387 res->div = isl_mat_add_zero_cols(res->div, n_div_ls);
1388 res->div = isl_mat_add_rows(res->div, n_div_ls);
1389 if (!res->div)
1390 goto error;
1393 isl_int_init(f);
1394 isl_int_init(c1);
1395 isl_int_init(c2);
1396 isl_int_init(g);
1398 for (i = 0; i < ls->div->n_row; ++i) {
1399 if (isl_int_is_zero(ls->div->row[i][0])) {
1400 isl_int_set_si(res->div->row[n_div_ma + i][0], 0);
1401 continue;
1403 isl_seq_preimage(res->div->row[n_div_ma + i], ls->div->row[i],
1404 ma, 0, 0, n_div_ma, n_div_ls, f, c1, c2, g, 1);
1405 normalize_div(res, n_div_ma + i);
1408 isl_int_clear(f);
1409 isl_int_clear(c1);
1410 isl_int_clear(c2);
1411 isl_int_clear(g);
1413 isl_local_space_free(ls);
1414 isl_multi_aff_free(ma);
1415 return res;
1416 error:
1417 isl_local_space_free(ls);
1418 isl_multi_aff_free(ma);
1419 isl_local_space_free(res);
1420 return NULL;
1423 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "ls"
1424 * to dimensions of "dst_type" at "dst_pos".
1426 * Moving to/from local dimensions is not allowed.
1427 * We currently assume that the dimension type changes.
1429 __isl_give isl_local_space *isl_local_space_move_dims(
1430 __isl_take isl_local_space *ls,
1431 enum isl_dim_type dst_type, unsigned dst_pos,
1432 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1434 unsigned g_dst_pos;
1435 unsigned g_src_pos;
1437 if (!ls)
1438 return NULL;
1439 if (n == 0 &&
1440 !isl_local_space_is_named_or_nested(ls, src_type) &&
1441 !isl_local_space_is_named_or_nested(ls, dst_type))
1442 return ls;
1444 if (src_pos + n > isl_local_space_dim(ls, src_type))
1445 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1446 "range out of bounds", return isl_local_space_free(ls));
1447 if (dst_pos > isl_local_space_dim(ls, dst_type))
1448 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1449 "position out of bounds",
1450 return isl_local_space_free(ls));
1451 if (src_type == isl_dim_div)
1452 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1453 "cannot move divs", return isl_local_space_free(ls));
1454 if (dst_type == isl_dim_div)
1455 isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
1456 "cannot move to divs", return isl_local_space_free(ls));
1457 if (dst_type == src_type && dst_pos == src_pos)
1458 return ls;
1459 if (dst_type == src_type)
1460 isl_die(isl_local_space_get_ctx(ls), isl_error_unsupported,
1461 "moving dims within the same type not supported",
1462 return isl_local_space_free(ls));
1464 ls = isl_local_space_cow(ls);
1465 if (!ls)
1466 return NULL;
1468 g_src_pos = 1 + isl_local_space_offset(ls, src_type) + src_pos;
1469 g_dst_pos = 1 + isl_local_space_offset(ls, dst_type) + dst_pos;
1470 if (dst_type > src_type)
1471 g_dst_pos -= n;
1472 ls->div = isl_mat_move_cols(ls->div, g_dst_pos, g_src_pos, n);
1473 if (!ls->div)
1474 return isl_local_space_free(ls);
1475 ls->dim = isl_space_move_dims(ls->dim, dst_type, dst_pos,
1476 src_type, src_pos, n);
1477 if (!ls->dim)
1478 return isl_local_space_free(ls);
1480 return ls;
1483 /* Remove any internal structure of the domain of "ls".
1484 * If there is any such internal structure in the input,
1485 * then the name of the corresponding space is also removed.
1487 __isl_give isl_local_space *isl_local_space_flatten_domain(
1488 __isl_take isl_local_space *ls)
1490 if (!ls)
1491 return NULL;
1493 if (!ls->dim->nested[0])
1494 return ls;
1496 ls = isl_local_space_cow(ls);
1497 if (!ls)
1498 return NULL;
1500 ls->dim = isl_space_flatten_domain(ls->dim);
1501 if (!ls->dim)
1502 return isl_local_space_free(ls);
1504 return ls;
1507 /* Remove any internal structure of the range of "ls".
1508 * If there is any such internal structure in the input,
1509 * then the name of the corresponding space is also removed.
1511 __isl_give isl_local_space *isl_local_space_flatten_range(
1512 __isl_take isl_local_space *ls)
1514 if (!ls)
1515 return NULL;
1517 if (!ls->dim->nested[1])
1518 return ls;
1520 ls = isl_local_space_cow(ls);
1521 if (!ls)
1522 return NULL;
1524 ls->dim = isl_space_flatten_range(ls->dim);
1525 if (!ls->dim)
1526 return isl_local_space_free(ls);
1528 return ls;
1531 /* Given the local space "ls" of a map, return the local space of a set
1532 * that lives in a space that wraps the space of "ls" and that has
1533 * the same divs.
1535 __isl_give isl_local_space *isl_local_space_wrap(__isl_take isl_local_space *ls)
1537 ls = isl_local_space_cow(ls);
1538 if (!ls)
1539 return NULL;
1541 ls->dim = isl_space_wrap(ls->dim);
1542 if (!ls->dim)
1543 return isl_local_space_free(ls);
1545 return ls;
1548 /* Lift the point "pnt", living in the space of "ls"
1549 * to live in a space with extra coordinates corresponding
1550 * to the local variables of "ls".
1552 __isl_give isl_point *isl_local_space_lift_point(__isl_take isl_local_space *ls,
1553 __isl_take isl_point *pnt)
1555 unsigned n_local;
1556 isl_space *space;
1557 isl_local *local;
1558 isl_vec *vec;
1560 if (isl_local_space_check_has_space(ls, isl_point_peek_space(pnt)) < 0)
1561 goto error;
1563 local = isl_local_space_peek_local(ls);
1564 n_local = isl_local_space_dim(ls, isl_dim_div);
1566 space = isl_point_take_space(pnt);
1567 vec = isl_point_take_vec(pnt);
1569 space = isl_space_lift(space, n_local);
1570 vec = isl_local_extend_point_vec(local, vec);
1572 pnt = isl_point_restore_vec(pnt, vec);
1573 pnt = isl_point_restore_space(pnt, space);
1575 isl_local_space_free(ls);
1577 return pnt;
1578 error:
1579 isl_local_space_free(ls);
1580 isl_point_free(pnt);
1581 return NULL;