2 * Copyright 2011 INRIA Saclay
3 * Copyright 2012-2014 Ecole Normale Superieure
4 * Copyright 2019 Cerebras Systems
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
9 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
12 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
15 #include <isl_ctx_private.h>
17 #include <isl_map_private.h>
18 #include <isl_local_space_private.h>
19 #include <isl_space_private.h>
20 #include <isl_mat_private.h>
21 #include <isl_aff_private.h>
22 #include <isl_vec_private.h>
23 #include <isl_point_private.h>
25 #include <isl_local.h>
27 isl_ctx
*isl_local_space_get_ctx(__isl_keep isl_local_space
*ls
)
29 return ls
? ls
->dim
->ctx
: NULL
;
32 /* Return a hash value that digests "ls".
34 uint32_t isl_local_space_get_hash(__isl_keep isl_local_space
*ls
)
36 uint32_t hash
, space_hash
, div_hash
;
41 hash
= isl_hash_init();
42 space_hash
= isl_space_get_full_hash(isl_local_space_peek_space(ls
));
43 isl_hash_hash(hash
, space_hash
);
44 div_hash
= isl_mat_get_hash(ls
->div
);
45 isl_hash_hash(hash
, div_hash
);
50 __isl_give isl_local_space
*isl_local_space_alloc_div(
51 __isl_take isl_space
*space
, __isl_take isl_mat
*div
)
54 isl_local_space
*ls
= NULL
;
59 ctx
= isl_space_get_ctx(space
);
60 ls
= isl_calloc_type(ctx
, struct isl_local_space
);
71 isl_space_free(space
);
72 isl_local_space_free(ls
);
76 __isl_give isl_local_space
*isl_local_space_alloc(__isl_take isl_space
*space
,
86 total
= isl_space_dim(space
, isl_dim_all
);
88 return isl_local_space_from_space(isl_space_free(space
));
90 ctx
= isl_space_get_ctx(space
);
91 div
= isl_mat_alloc(ctx
, n_div
, 1 + 1 + total
+ n_div
);
92 return isl_local_space_alloc_div(space
, div
);
95 __isl_give isl_local_space
*isl_local_space_from_space(
96 __isl_take isl_space
*space
)
98 return isl_local_space_alloc(space
, 0);
101 __isl_give isl_local_space
*isl_local_space_copy(__isl_keep isl_local_space
*ls
)
110 __isl_give isl_local_space
*isl_local_space_dup(__isl_keep isl_local_space
*ls
)
115 return isl_local_space_alloc_div(isl_space_copy(ls
->dim
),
116 isl_mat_copy(ls
->div
));
120 __isl_give isl_local_space
*isl_local_space_cow(__isl_take isl_local_space
*ls
)
128 return isl_local_space_dup(ls
);
131 __isl_null isl_local_space
*isl_local_space_free(
132 __isl_take isl_local_space
*ls
)
140 isl_space_free(ls
->dim
);
141 isl_mat_free(ls
->div
);
148 /* Is the local space that of a parameter domain?
150 isl_bool
isl_local_space_is_params(__isl_keep isl_local_space
*ls
)
153 return isl_bool_error
;
154 return isl_space_is_params(ls
->dim
);
157 /* Is the local space that of a set?
159 isl_bool
isl_local_space_is_set(__isl_keep isl_local_space
*ls
)
161 return ls
? isl_space_is_set(ls
->dim
) : isl_bool_error
;
165 #define TYPE isl_local_space
167 #include "isl_type_has_equal_space_bin_templ.c"
168 #include "isl_type_has_space_templ.c"
170 /* Check that the space of "ls" is equal to "space".
172 static isl_stat
isl_local_space_check_has_space(__isl_keep isl_local_space
*ls
,
173 __isl_keep isl_space
*space
)
177 ok
= isl_local_space_has_space(ls
, space
);
179 return isl_stat_error
;
181 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
182 "spaces don't match", return isl_stat_error
);
186 /* Return true if the two local spaces are identical, with identical
187 * expressions for the integer divisions.
189 isl_bool
isl_local_space_is_equal(__isl_keep isl_local_space
*ls1
,
190 __isl_keep isl_local_space
*ls2
)
194 equal
= isl_local_space_has_equal_space(ls1
, ls2
);
195 if (equal
< 0 || !equal
)
198 if (!isl_local_space_divs_known(ls1
))
199 return isl_bool_false
;
200 if (!isl_local_space_divs_known(ls2
))
201 return isl_bool_false
;
203 return isl_mat_is_equal(ls1
->div
, ls2
->div
);
206 /* Compare two isl_local_spaces.
208 * Return -1 if "ls1" is "smaller" than "ls2", 1 if "ls1" is "greater"
209 * than "ls2" and 0 if they are equal.
211 int isl_local_space_cmp(__isl_keep isl_local_space
*ls1
,
212 __isl_keep isl_local_space
*ls2
)
223 cmp
= isl_space_cmp(ls1
->dim
, ls2
->dim
);
227 return isl_local_cmp(ls1
->div
, ls2
->div
);
230 isl_size
isl_local_space_dim(__isl_keep isl_local_space
*ls
,
231 enum isl_dim_type type
)
234 return isl_size_error
;
235 if (type
== isl_dim_div
)
236 return ls
->div
->n_row
;
237 if (type
== isl_dim_all
) {
238 isl_size dim
= isl_space_dim(ls
->dim
, isl_dim_all
);
240 return isl_size_error
;
241 return dim
+ ls
->div
->n_row
;
243 return isl_space_dim(ls
->dim
, type
);
247 #define TYPE isl_local_space
248 #include "check_type_range_templ.c"
250 /* Return the position of the variables of the given type
251 * within the sequence of variables of "ls".
253 isl_size
isl_local_space_var_offset(__isl_keep isl_local_space
*ls
,
254 enum isl_dim_type type
)
258 space
= isl_local_space_peek_space(ls
);
262 case isl_dim_out
: return isl_space_offset(space
, type
);
263 case isl_dim_div
: return isl_space_dim(space
, isl_dim_all
);
266 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
267 "invalid dimension type", return isl_size_error
);
271 /* Return the position of the coefficients of the variables of the given type
272 * within the sequence of coefficients of "ls".
274 unsigned isl_local_space_offset(__isl_keep isl_local_space
*ls
,
275 enum isl_dim_type type
)
281 case isl_dim_cst
: return 0;
285 case isl_dim_div
: return 1 + isl_local_space_var_offset(ls
, type
);
290 /* Return the position of the dimension of the given type and name
292 * Return -1 if no such dimension can be found.
294 int isl_local_space_find_dim_by_name(__isl_keep isl_local_space
*ls
,
295 enum isl_dim_type type
, const char *name
)
299 if (type
== isl_dim_div
)
301 return isl_space_find_dim_by_name(ls
->dim
, type
, name
);
304 /* Does the given dimension have a name?
306 isl_bool
isl_local_space_has_dim_name(__isl_keep isl_local_space
*ls
,
307 enum isl_dim_type type
, unsigned pos
)
309 return ls
? isl_space_has_dim_name(ls
->dim
, type
, pos
) : isl_bool_error
;
312 const char *isl_local_space_get_dim_name(__isl_keep isl_local_space
*ls
,
313 enum isl_dim_type type
, unsigned pos
)
315 return ls
? isl_space_get_dim_name(ls
->dim
, type
, pos
) : NULL
;
318 isl_bool
isl_local_space_has_dim_id(__isl_keep isl_local_space
*ls
,
319 enum isl_dim_type type
, unsigned pos
)
321 return ls
? isl_space_has_dim_id(ls
->dim
, type
, pos
) : isl_bool_error
;
324 __isl_give isl_id
*isl_local_space_get_dim_id(__isl_keep isl_local_space
*ls
,
325 enum isl_dim_type type
, unsigned pos
)
327 return ls
? isl_space_get_dim_id(ls
->dim
, type
, pos
) : NULL
;
330 /* Return the argument of the integer division at position "pos" in "ls".
331 * All local variables in "ls" are known to have a (complete) explicit
334 static __isl_give isl_aff
*extract_div(__isl_keep isl_local_space
*ls
, int pos
)
338 aff
= isl_aff_alloc(isl_local_space_copy(ls
));
341 isl_seq_cpy(aff
->v
->el
, ls
->div
->row
[pos
], aff
->v
->size
);
345 /* Return the argument of the integer division at position "pos" in "ls".
346 * The integer division at that position is known to have a complete
347 * explicit representation, but some of the others do not.
348 * Remove them first because the domain of an isl_aff
349 * is not allowed to have unknown local variables.
351 static __isl_give isl_aff
*drop_unknown_divs_and_extract_div(
352 __isl_keep isl_local_space
*ls
, int pos
)
359 n
= isl_local_space_dim(ls
, isl_dim_div
);
362 ls
= isl_local_space_copy(ls
);
363 for (i
= n
- 1; i
>= 0; --i
) {
364 unknown
= isl_local_space_div_is_marked_unknown(ls
, i
);
366 ls
= isl_local_space_free(ls
);
369 ls
= isl_local_space_drop_dims(ls
, isl_dim_div
, i
, 1);
373 aff
= extract_div(ls
, pos
);
374 isl_local_space_free(ls
);
378 /* Return the argument of the integer division at position "pos" in "ls".
379 * The integer division is assumed to have a complete explicit
380 * representation. If some of the other integer divisions
381 * do not have an explicit representation, then they need
382 * to be removed first because the domain of an isl_aff
383 * is not allowed to have unknown local variables.
385 __isl_give isl_aff
*isl_local_space_get_div(__isl_keep isl_local_space
*ls
,
393 if (pos
< 0 || pos
>= ls
->div
->n_row
)
394 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
395 "index out of bounds", return NULL
);
397 known
= isl_local_space_div_is_known(ls
, pos
);
401 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
402 "expression of div unknown", return NULL
);
403 if (!isl_local_space_is_set(ls
))
404 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
405 "cannot represent divs of map spaces", return NULL
);
407 known
= isl_local_space_divs_known(ls
);
411 return extract_div(ls
, pos
);
413 return drop_unknown_divs_and_extract_div(ls
, pos
);
416 /* Return the space of "ls".
418 __isl_keep isl_space
*isl_local_space_peek_space(__isl_keep isl_local_space
*ls
)
426 __isl_give isl_space
*isl_local_space_get_space(__isl_keep isl_local_space
*ls
)
428 return isl_space_copy(isl_local_space_peek_space(ls
));
431 /* Return the space of "ls".
432 * This may be either a copy or the space itself
433 * if there is only one reference to "ls".
434 * This allows the space to be modified inplace
435 * if both the local space and its space have only a single reference.
436 * The caller is not allowed to modify "ls" between this call and
437 * a subsequent call to isl_local_space_restore_space.
438 * The only exception is that isl_local_space_free can be called instead.
440 __isl_give isl_space
*isl_local_space_take_space(__isl_keep isl_local_space
*ls
)
447 return isl_local_space_get_space(ls
);
453 /* Set the space of "ls" to "space", where the space of "ls" may be missing
454 * due to a preceding call to isl_local_space_take_space.
455 * However, in this case, "ls" only has a single reference and
456 * then the call to isl_local_space_cow has no effect.
458 __isl_give isl_local_space
*isl_local_space_restore_space(
459 __isl_take isl_local_space
*ls
, __isl_take isl_space
*space
)
464 if (ls
->dim
== space
) {
465 isl_space_free(space
);
469 ls
= isl_local_space_cow(ls
);
472 isl_space_free(ls
->dim
);
477 isl_local_space_free(ls
);
478 isl_space_free(space
);
482 /* Return the local variables of "ls".
484 __isl_keep isl_local
*isl_local_space_peek_local(__isl_keep isl_local_space
*ls
)
486 return ls
? ls
->div
: NULL
;
489 /* Return a copy of the local variables of "ls".
491 __isl_give isl_local
*isl_local_space_get_local(__isl_keep isl_local_space
*ls
)
493 return isl_local_copy(isl_local_space_peek_local(ls
));
496 /* Return the local variables of "ls".
497 * This may be either a copy or the local variables itself
498 * if there is only one reference to "ls".
499 * This allows the local variables to be modified inplace
500 * if both the local space and its local variables have only a single reference.
501 * The caller is not allowed to modify "ls" between this call and
502 * the subsequent call to isl_local_space_restore_local.
503 * The only exception is that isl_local_space_free can be called instead.
505 static __isl_give isl_local
*isl_local_space_take_local(
506 __isl_keep isl_local_space
*ls
)
513 return isl_local_space_get_local(ls
);
519 /* Set the local variables of "ls" to "local",
520 * where the local variables of "ls" may be missing
521 * due to a preceding call to isl_local_space_take_local.
522 * However, in this case, "ls" only has a single reference and
523 * then the call to isl_local_space_cow has no effect.
525 static __isl_give isl_local_space
*isl_local_space_restore_local(
526 __isl_take isl_local_space
*ls
, __isl_take isl_local
*local
)
531 if (ls
->div
== local
) {
532 isl_local_free(local
);
536 ls
= isl_local_space_cow(ls
);
539 isl_local_free(ls
->div
);
544 isl_local_space_free(ls
);
545 isl_local_free(local
);
549 /* Replace the identifier of the tuple of type "type" by "id".
551 __isl_give isl_local_space
*isl_local_space_set_tuple_id(
552 __isl_take isl_local_space
*ls
,
553 enum isl_dim_type type
, __isl_take isl_id
*id
)
555 ls
= isl_local_space_cow(ls
);
558 ls
->dim
= isl_space_set_tuple_id(ls
->dim
, type
, id
);
560 return isl_local_space_free(ls
);
567 __isl_give isl_local_space
*isl_local_space_set_dim_name(
568 __isl_take isl_local_space
*ls
,
569 enum isl_dim_type type
, unsigned pos
, const char *s
)
571 ls
= isl_local_space_cow(ls
);
574 ls
->dim
= isl_space_set_dim_name(ls
->dim
, type
, pos
, s
);
576 return isl_local_space_free(ls
);
581 __isl_give isl_local_space
*isl_local_space_set_dim_id(
582 __isl_take isl_local_space
*ls
,
583 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
585 ls
= isl_local_space_cow(ls
);
588 ls
->dim
= isl_space_set_dim_id(ls
->dim
, type
, pos
, id
);
590 return isl_local_space_free(ls
);
598 /* Construct a zero-dimensional local space with the given parameter domain.
600 __isl_give isl_local_space
*isl_local_space_set_from_params(
601 __isl_take isl_local_space
*ls
)
605 space
= isl_local_space_take_space(ls
);
606 space
= isl_space_set_from_params(space
);
607 ls
= isl_local_space_restore_space(ls
, space
);
612 __isl_give isl_local_space
*isl_local_space_reset_space(
613 __isl_take isl_local_space
*ls
, __isl_take isl_space
*space
)
615 ls
= isl_local_space_cow(ls
);
619 isl_space_free(ls
->dim
);
624 isl_local_space_free(ls
);
625 isl_space_free(space
);
629 /* Reorder the dimensions of "ls" according to the given reordering.
630 * The reordering r is assumed to have been extended with the local
631 * variables, leaving them in the same order.
633 __isl_give isl_local_space
*isl_local_space_realign(
634 __isl_take isl_local_space
*ls
, __isl_take isl_reordering
*r
)
638 local
= isl_local_space_take_local(ls
);
639 local
= isl_local_reorder(local
, isl_reordering_copy(r
));
640 ls
= isl_local_space_restore_local(ls
, local
);
642 ls
= isl_local_space_reset_space(ls
, isl_reordering_get_space(r
));
644 isl_reordering_free(r
);
648 __isl_give isl_local_space
*isl_local_space_add_div(
649 __isl_take isl_local_space
*ls
, __isl_take isl_vec
*div
)
651 ls
= isl_local_space_cow(ls
);
655 if (ls
->div
->n_col
!= div
->size
)
656 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
657 "incompatible dimensions", goto error
);
659 ls
->div
= isl_mat_add_zero_cols(ls
->div
, 1);
660 ls
->div
= isl_mat_add_rows(ls
->div
, 1);
664 isl_seq_cpy(ls
->div
->row
[ls
->div
->n_row
- 1], div
->el
, div
->size
);
665 isl_int_set_si(ls
->div
->row
[ls
->div
->n_row
- 1][div
->size
], 0);
670 isl_local_space_free(ls
);
675 __isl_give isl_local_space
*isl_local_space_replace_divs(
676 __isl_take isl_local_space
*ls
, __isl_take isl_mat
*div
)
678 ls
= isl_local_space_cow(ls
);
683 isl_mat_free(ls
->div
);
688 isl_local_space_free(ls
);
692 /* Copy row "s" of "src" to row "d" of "dst", applying the expansion
695 static void expand_row(__isl_keep isl_mat
*dst
, int d
,
696 __isl_keep isl_mat
*src
, int s
, int *exp
)
699 unsigned c
= src
->n_col
- src
->n_row
;
701 isl_seq_cpy(dst
->row
[d
], src
->row
[s
], c
);
702 isl_seq_clr(dst
->row
[d
] + c
, dst
->n_col
- c
);
704 for (i
= 0; i
< s
; ++i
)
705 isl_int_set(dst
->row
[d
][c
+ exp
[i
]], src
->row
[s
][c
+ i
]);
708 /* Compare (known) divs.
709 * Return non-zero if at least one of the two divs is unknown.
710 * In particular, if both divs are unknown, we respect their
711 * current order. Otherwise, we sort the known div after the unknown
712 * div only if the known div depends on the unknown div.
714 static int cmp_row(isl_int
*row_i
, isl_int
*row_j
, int i
, int j
,
715 unsigned n_row
, unsigned n_col
)
718 int unknown_i
, unknown_j
;
720 unknown_i
= isl_int_is_zero(row_i
[0]);
721 unknown_j
= isl_int_is_zero(row_j
[0]);
723 if (unknown_i
&& unknown_j
)
727 li
= n_col
- n_row
+ i
;
729 li
= isl_seq_last_non_zero(row_i
, n_col
);
731 lj
= n_col
- n_row
+ j
;
733 lj
= isl_seq_last_non_zero(row_j
, n_col
);
738 return isl_seq_cmp(row_i
, row_j
, n_col
);
741 /* Call cmp_row for divs in a matrix.
743 int isl_mat_cmp_div(__isl_keep isl_mat
*div
, int i
, int j
)
745 return cmp_row(div
->row
[i
], div
->row
[j
], i
, j
, div
->n_row
, div
->n_col
);
748 /* Call cmp_row for divs in a basic map.
750 static int bmap_cmp_row(__isl_keep isl_basic_map
*bmap
, int i
, int j
,
753 return cmp_row(bmap
->div
[i
], bmap
->div
[j
], i
, j
, bmap
->n_div
, total
);
756 /* Sort the divs in "bmap".
758 * We first make sure divs are placed after divs on which they depend.
759 * Then we perform a simple insertion sort based on the same ordering
760 * that is used in isl_merge_divs.
762 __isl_give isl_basic_map
*isl_basic_map_sort_divs(
763 __isl_take isl_basic_map
*bmap
)
768 bmap
= isl_basic_map_order_divs(bmap
);
771 if (bmap
->n_div
<= 1)
774 total
= isl_basic_map_dim(bmap
, isl_dim_all
);
776 return isl_basic_map_free(bmap
);
777 for (i
= 1; i
< bmap
->n_div
; ++i
) {
778 for (j
= i
- 1; j
>= 0; --j
) {
779 if (bmap_cmp_row(bmap
, j
, j
+ 1, 2 + total
) <= 0)
781 bmap
= isl_basic_map_swap_div(bmap
, j
, j
+ 1);
790 /* Sort the divs in the basic maps of "map".
792 __isl_give isl_map
*isl_map_sort_divs(__isl_take isl_map
*map
)
794 return isl_map_inline_foreach_basic_map(map
, &isl_basic_map_sort_divs
);
797 /* Combine the two lists of divs into a single list.
798 * For each row i in div1, exp1[i] is set to the position of the corresponding
799 * row in the result. Similarly for div2 and exp2.
800 * This function guarantees
802 * exp1[i+1] > exp1[i]
803 * For optimal merging, the two input list should have been sorted.
805 __isl_give isl_mat
*isl_merge_divs(__isl_keep isl_mat
*div1
,
806 __isl_keep isl_mat
*div2
, int *exp1
, int *exp2
)
815 d
= div1
->n_col
- div1
->n_row
;
816 div
= isl_mat_alloc(div1
->ctx
, 1 + div1
->n_row
+ div2
->n_row
,
817 d
+ div1
->n_row
+ div2
->n_row
);
821 for (i
= 0, j
= 0, k
= 0; i
< div1
->n_row
&& j
< div2
->n_row
; ++k
) {
824 expand_row(div
, k
, div1
, i
, exp1
);
825 expand_row(div
, k
+ 1, div2
, j
, exp2
);
827 cmp
= isl_mat_cmp_div(div
, k
, k
+ 1);
831 } else if (cmp
< 0) {
835 isl_seq_cpy(div
->row
[k
], div
->row
[k
+ 1], div
->n_col
);
838 for (; i
< div1
->n_row
; ++i
, ++k
) {
839 expand_row(div
, k
, div1
, i
, exp1
);
842 for (; j
< div2
->n_row
; ++j
, ++k
) {
843 expand_row(div
, k
, div2
, j
, exp2
);
853 /* Swap divs "a" and "b" in "ls".
855 __isl_give isl_local_space
*isl_local_space_swap_div(
856 __isl_take isl_local_space
*ls
, int a
, int b
)
860 ls
= isl_local_space_cow(ls
);
863 if (a
< 0 || a
>= ls
->div
->n_row
|| b
< 0 || b
>= ls
->div
->n_row
)
864 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
865 "index out of bounds", return isl_local_space_free(ls
));
866 offset
= ls
->div
->n_col
- ls
->div
->n_row
;
867 ls
->div
= isl_mat_swap_cols(ls
->div
, offset
+ a
, offset
+ b
);
868 ls
->div
= isl_mat_swap_rows(ls
->div
, a
, b
);
870 return isl_local_space_free(ls
);
874 /* Construct a local space that contains all the divs in either
877 __isl_give isl_local_space
*isl_local_space_intersect(
878 __isl_take isl_local_space
*ls1
, __isl_take isl_local_space
*ls2
)
889 ctx
= isl_local_space_get_ctx(ls1
);
890 if (!isl_space_is_equal(ls1
->dim
, ls2
->dim
))
891 isl_die(ctx
, isl_error_invalid
,
892 "spaces should be identical", goto error
);
894 if (ls2
->div
->n_row
== 0) {
895 isl_local_space_free(ls2
);
899 if (ls1
->div
->n_row
== 0) {
900 isl_local_space_free(ls1
);
904 exp1
= isl_alloc_array(ctx
, int, ls1
->div
->n_row
);
905 exp2
= isl_alloc_array(ctx
, int, ls2
->div
->n_row
);
909 div
= isl_merge_divs(ls1
->div
, ls2
->div
, exp1
, exp2
);
913 equal
= isl_mat_is_equal(ls1
->div
, div
);
917 ls1
= isl_local_space_cow(ls1
);
923 isl_local_space_free(ls2
);
924 isl_mat_free(ls1
->div
);
932 isl_local_space_free(ls1
);
933 isl_local_space_free(ls2
);
937 /* Is the local variable "div" of "ls" marked as not having
938 * an explicit representation?
939 * Note that even if this variable is not marked in this way and therefore
940 * does have an explicit representation, this representation may still
941 * depend (indirectly) on other local variables that do not
942 * have an explicit representation.
944 isl_bool
isl_local_space_div_is_marked_unknown(__isl_keep isl_local_space
*ls
,
948 return isl_bool_error
;
949 return isl_local_div_is_marked_unknown(ls
->div
, div
);
952 /* Does "ls" have a complete explicit representation for div "div"?
954 isl_bool
isl_local_space_div_is_known(__isl_keep isl_local_space
*ls
, int div
)
957 return isl_bool_error
;
958 return isl_local_div_is_known(ls
->div
, div
);
961 /* Does "ls" have an explicit representation for all local variables?
963 isl_bool
isl_local_space_divs_known(__isl_keep isl_local_space
*ls
)
966 return isl_bool_error
;
967 return isl_local_divs_known(ls
->div
);
970 __isl_give isl_local_space
*isl_local_space_domain(
971 __isl_take isl_local_space
*ls
)
975 n_out
= isl_local_space_dim(ls
, isl_dim_out
);
977 return isl_local_space_free(ls
);
978 ls
= isl_local_space_drop_dims(ls
, isl_dim_out
, 0, n_out
);
979 ls
= isl_local_space_cow(ls
);
982 ls
->dim
= isl_space_domain(ls
->dim
);
984 return isl_local_space_free(ls
);
988 __isl_give isl_local_space
*isl_local_space_range(
989 __isl_take isl_local_space
*ls
)
993 n_in
= isl_local_space_dim(ls
, isl_dim_in
);
995 return isl_local_space_free(ls
);
996 ls
= isl_local_space_drop_dims(ls
, isl_dim_in
, 0, n_in
);
997 ls
= isl_local_space_cow(ls
);
1001 ls
->dim
= isl_space_range(ls
->dim
);
1003 return isl_local_space_free(ls
);
1007 /* Construct a local space for a map that has the given local
1008 * space as domain and that has a zero-dimensional range.
1010 __isl_give isl_local_space
*isl_local_space_from_domain(
1011 __isl_take isl_local_space
*ls
)
1013 ls
= isl_local_space_cow(ls
);
1016 ls
->dim
= isl_space_from_domain(ls
->dim
);
1018 return isl_local_space_free(ls
);
1022 __isl_give isl_local_space
*isl_local_space_add_dims(
1023 __isl_take isl_local_space
*ls
, enum isl_dim_type type
, unsigned n
)
1027 pos
= isl_local_space_dim(ls
, type
);
1029 return isl_local_space_free(ls
);
1030 return isl_local_space_insert_dims(ls
, type
, pos
, n
);
1033 /* Lift the basic set "bset", living in the space of "ls"
1034 * to live in a space with extra coordinates corresponding
1035 * to the local variables of "ls".
1037 __isl_give isl_basic_set
*isl_local_space_lift_basic_set(
1038 __isl_take isl_local_space
*ls
, __isl_take isl_basic_set
*bset
)
1042 isl_basic_set
*ls_bset
;
1044 n_local
= isl_local_space_dim(ls
, isl_dim_div
);
1045 space
= isl_basic_set_peek_space(bset
);
1047 isl_local_space_check_has_space(ls
, space
) < 0)
1051 isl_local_space_free(ls
);
1055 bset
= isl_basic_set_add_dims(bset
, isl_dim_set
, n_local
);
1056 ls_bset
= isl_basic_set_from_local_space(ls
);
1057 ls_bset
= isl_basic_set_lift(ls_bset
);
1058 ls_bset
= isl_basic_set_flatten(ls_bset
);
1059 bset
= isl_basic_set_intersect(bset
, ls_bset
);
1063 isl_local_space_free(ls
);
1064 isl_basic_set_free(bset
);
1068 /* Lift the set "set", living in the space of "ls"
1069 * to live in a space with extra coordinates corresponding
1070 * to the local variables of "ls".
1072 __isl_give isl_set
*isl_local_space_lift_set(__isl_take isl_local_space
*ls
,
1073 __isl_take isl_set
*set
)
1076 isl_basic_set
*bset
;
1078 n_local
= isl_local_space_dim(ls
, isl_dim_div
);
1080 isl_local_space_check_has_space(ls
, isl_set_peek_space(set
)) < 0)
1084 isl_local_space_free(ls
);
1088 set
= isl_set_add_dims(set
, isl_dim_set
, n_local
);
1089 bset
= isl_basic_set_from_local_space(ls
);
1090 bset
= isl_basic_set_lift(bset
);
1091 bset
= isl_basic_set_flatten(bset
);
1092 set
= isl_set_intersect(set
, isl_set_from_basic_set(bset
));
1096 isl_local_space_free(ls
);
1101 /* Remove common factor of non-constant terms and denominator.
1103 static __isl_give isl_local_space
*normalize_div(
1104 __isl_take isl_local_space
*ls
, int div
)
1106 isl_ctx
*ctx
= ls
->div
->ctx
;
1107 unsigned total
= ls
->div
->n_col
- 2;
1109 isl_seq_gcd(ls
->div
->row
[div
] + 2, total
, &ctx
->normalize_gcd
);
1110 isl_int_gcd(ctx
->normalize_gcd
,
1111 ctx
->normalize_gcd
, ls
->div
->row
[div
][0]);
1112 if (isl_int_is_one(ctx
->normalize_gcd
))
1115 isl_seq_scale_down(ls
->div
->row
[div
] + 2, ls
->div
->row
[div
] + 2,
1116 ctx
->normalize_gcd
, total
);
1117 isl_int_divexact(ls
->div
->row
[div
][0], ls
->div
->row
[div
][0],
1118 ctx
->normalize_gcd
);
1119 isl_int_fdiv_q(ls
->div
->row
[div
][1], ls
->div
->row
[div
][1],
1120 ctx
->normalize_gcd
);
1125 /* Exploit the equalities in "eq" to simplify the expressions of
1126 * the integer divisions in "ls".
1127 * The integer divisions in "ls" are assumed to appear as regular
1128 * dimensions in "eq".
1130 __isl_give isl_local_space
*isl_local_space_substitute_equalities(
1131 __isl_take isl_local_space
*ls
, __isl_take isl_basic_set
*eq
)
1134 isl_size total
, dim
;
1140 total
= isl_space_dim(eq
->dim
, isl_dim_all
);
1141 dim
= isl_local_space_dim(ls
, isl_dim_all
);
1142 if (dim
< 0 || total
< 0)
1145 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
1146 "spaces don't match", goto error
);
1149 for (i
= 0; i
< eq
->n_eq
; ++i
) {
1150 j
= isl_seq_last_non_zero(eq
->eq
[i
], total
+ n_div
);
1151 if (j
< 0 || j
== 0 || j
>= total
)
1154 for (k
= 0; k
< ls
->div
->n_row
; ++k
) {
1155 if (isl_int_is_zero(ls
->div
->row
[k
][1 + j
]))
1157 ls
= isl_local_space_cow(ls
);
1160 ls
->div
= isl_mat_cow(ls
->div
);
1163 isl_seq_elim(ls
->div
->row
[k
] + 1, eq
->eq
[i
], j
, total
,
1164 &ls
->div
->row
[k
][0]);
1165 ls
= normalize_div(ls
, k
);
1171 isl_basic_set_free(eq
);
1174 isl_basic_set_free(eq
);
1175 isl_local_space_free(ls
);
1179 /* Plug in the affine expressions "subs" of length "subs_len" (including
1180 * the denominator and the constant term) into the variable at position "pos"
1181 * of the "n" div expressions starting at "first".
1183 * Let i be the dimension to replace and let "subs" be of the form
1187 * Any integer division starting at "first" with a non-zero coefficient for i,
1189 * floor((a i + g)/m)
1193 * floor((a f + d g)/(m d))
1195 __isl_give isl_local_space
*isl_local_space_substitute_seq(
1196 __isl_take isl_local_space
*ls
,
1197 enum isl_dim_type type
, unsigned pos
, isl_int
*subs
, int subs_len
,
1205 ls
= isl_local_space_cow(ls
);
1208 ls
->div
= isl_mat_cow(ls
->div
);
1210 return isl_local_space_free(ls
);
1212 if (first
+ n
> ls
->div
->n_row
)
1213 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
1214 "index out of bounds", return isl_local_space_free(ls
));
1216 pos
+= isl_local_space_offset(ls
, type
);
1219 for (i
= first
; i
< first
+ n
; ++i
) {
1220 if (isl_int_is_zero(ls
->div
->row
[i
][1 + pos
]))
1222 isl_seq_substitute(ls
->div
->row
[i
], pos
, subs
,
1223 ls
->div
->n_col
, subs_len
, v
);
1224 ls
= normalize_div(ls
, i
);
1233 /* Plug in "subs" for dimension "type", "pos" in the integer divisions
1236 * Let i be the dimension to replace and let "subs" be of the form
1240 * Any integer division with a non-zero coefficient for i,
1242 * floor((a i + g)/m)
1246 * floor((a f + d g)/(m d))
1248 __isl_give isl_local_space
*isl_local_space_substitute(
1249 __isl_take isl_local_space
*ls
,
1250 enum isl_dim_type type
, unsigned pos
, __isl_keep isl_aff
*subs
)
1254 ls
= isl_local_space_cow(ls
);
1256 return isl_local_space_free(ls
);
1258 if (!isl_space_is_equal(ls
->dim
, subs
->ls
->dim
))
1259 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
1260 "spaces don't match", return isl_local_space_free(ls
));
1261 n_div
= isl_local_space_dim(subs
->ls
, isl_dim_div
);
1263 return isl_local_space_free(ls
);
1265 isl_die(isl_local_space_get_ctx(ls
), isl_error_unsupported
,
1266 "cannot handle divs yet",
1267 return isl_local_space_free(ls
));
1269 return isl_local_space_substitute_seq(ls
, type
, pos
, subs
->v
->el
,
1270 subs
->v
->size
, 0, ls
->div
->n_row
);
1273 isl_bool
isl_local_space_is_named_or_nested(__isl_keep isl_local_space
*ls
,
1274 enum isl_dim_type type
)
1277 return isl_bool_error
;
1278 return isl_space_is_named_or_nested(ls
->dim
, type
);
1281 __isl_give isl_local_space
*isl_local_space_drop_dims(
1282 __isl_take isl_local_space
*ls
,
1283 enum isl_dim_type type
, unsigned first
, unsigned n
)
1287 if (n
== 0 && !isl_local_space_is_named_or_nested(ls
, type
))
1290 if (isl_local_space_check_range(ls
, type
, first
, n
) < 0)
1291 return isl_local_space_free(ls
);
1293 ls
= isl_local_space_cow(ls
);
1297 if (type
== isl_dim_div
) {
1298 ls
->div
= isl_mat_drop_rows(ls
->div
, first
, n
);
1300 ls
->dim
= isl_space_drop_dims(ls
->dim
, type
, first
, n
);
1302 return isl_local_space_free(ls
);
1305 first
+= 1 + isl_local_space_offset(ls
, type
);
1306 ls
->div
= isl_mat_drop_cols(ls
->div
, first
, n
);
1308 return isl_local_space_free(ls
);
1313 __isl_give isl_local_space
*isl_local_space_insert_dims(
1314 __isl_take isl_local_space
*ls
,
1315 enum isl_dim_type type
, unsigned first
, unsigned n
)
1319 if (n
== 0 && !isl_local_space_is_named_or_nested(ls
, type
))
1322 if (isl_local_space_check_range(ls
, type
, first
, 0) < 0)
1323 return isl_local_space_free(ls
);
1325 ls
= isl_local_space_cow(ls
);
1329 if (type
== isl_dim_div
) {
1330 ls
->div
= isl_mat_insert_zero_rows(ls
->div
, first
, n
);
1332 ls
->dim
= isl_space_insert_dims(ls
->dim
, type
, first
, n
);
1334 return isl_local_space_free(ls
);
1337 first
+= 1 + isl_local_space_offset(ls
, type
);
1338 ls
->div
= isl_mat_insert_zero_cols(ls
->div
, first
, n
);
1340 return isl_local_space_free(ls
);
1345 /* Does the linear part of "constraint" correspond to
1346 * integer division "div" in "ls"?
1348 * That is, given div = floor((c + f)/m), is the constraint of the form
1350 * f - m d + c' >= 0 [sign = 1]
1352 * -f + m d + c'' >= 0 [sign = -1]
1354 * If so, set *sign to the corresponding value.
1356 static isl_bool
is_linear_div_constraint(__isl_keep isl_local_space
*ls
,
1357 isl_int
*constraint
, unsigned div
, int *sign
)
1362 unknown
= isl_local_space_div_is_marked_unknown(ls
, div
);
1364 return isl_bool_error
;
1366 return isl_bool_false
;
1368 pos
= isl_local_space_offset(ls
, isl_dim_div
) + div
;
1370 if (isl_int_eq(constraint
[pos
], ls
->div
->row
[div
][0])) {
1372 if (!isl_seq_is_neg(constraint
+ 1,
1373 ls
->div
->row
[div
] + 2, pos
- 1))
1374 return isl_bool_false
;
1375 } else if (isl_int_abs_eq(constraint
[pos
], ls
->div
->row
[div
][0])) {
1377 if (!isl_seq_eq(constraint
+ 1, ls
->div
->row
[div
] + 2, pos
- 1))
1378 return isl_bool_false
;
1380 return isl_bool_false
;
1382 if (isl_seq_first_non_zero(constraint
+ pos
+ 1,
1383 ls
->div
->n_row
- div
- 1) != -1)
1384 return isl_bool_false
;
1385 return isl_bool_true
;
1388 /* Check if the constraints pointed to by "constraint" is a div
1389 * constraint corresponding to div "div" in "ls".
1391 * That is, if div = floor(f/m), then check if the constraint is
1395 * -(f-(m-1)) + m d >= 0
1397 * First check if the linear part is of the right form and
1398 * then check the constant term.
1400 isl_bool
isl_local_space_is_div_constraint(__isl_keep isl_local_space
*ls
,
1401 isl_int
*constraint
, unsigned div
)
1406 linear
= is_linear_div_constraint(ls
, constraint
, div
, &sign
);
1407 if (linear
< 0 || !linear
)
1412 isl_int_sub(ls
->div
->row
[div
][1],
1413 ls
->div
->row
[div
][1], ls
->div
->row
[div
][0]);
1414 isl_int_add_ui(ls
->div
->row
[div
][1], ls
->div
->row
[div
][1], 1);
1415 neg
= isl_seq_is_neg(constraint
, ls
->div
->row
[div
] + 1, 1);
1416 isl_int_sub_ui(ls
->div
->row
[div
][1], ls
->div
->row
[div
][1], 1);
1417 isl_int_add(ls
->div
->row
[div
][1],
1418 ls
->div
->row
[div
][1], ls
->div
->row
[div
][0]);
1420 return isl_bool_false
;
1422 if (!isl_int_eq(constraint
[0], ls
->div
->row
[div
][1]))
1423 return isl_bool_false
;
1426 return isl_bool_true
;
1429 /* Is the constraint pointed to by "constraint" one
1430 * of an equality that corresponds to integer division "div" in "ls"?
1432 * That is, given an integer division of the form
1434 * a = floor((f + c)/m)
1436 * is the equality of the form
1440 * Note that the constant term is not checked explicitly, but given
1441 * that this is a valid equality constraint, the constant c' necessarily
1442 * has a value close to -c.
1444 isl_bool
isl_local_space_is_div_equality(__isl_keep isl_local_space
*ls
,
1445 isl_int
*constraint
, unsigned div
)
1450 linear
= is_linear_div_constraint(ls
, constraint
, div
, &sign
);
1451 if (linear
< 0 || !linear
)
1454 return isl_bool_ok(sign
< 0);
1457 /* Return an array of integers, one for each variable of "ls",
1458 * with entry i set to 1 if the variable at position i is involved
1459 * in the linear expression "l". This includes variables that appear
1460 * in the definition of local variables that appear in "l".
1462 int *isl_local_space_get_active(__isl_keep isl_local_space
*ls
, isl_int
*l
)
1470 ctx
= isl_local_space_get_ctx(ls
);
1471 total
= isl_local_space_dim(ls
, isl_dim_all
);
1474 active
= isl_calloc_array(ctx
, int, total
);
1475 if (total
&& !active
)
1478 for (i
= 0; i
< total
; ++i
)
1479 active
[i
] = !isl_int_is_zero(l
[i
]);
1481 offset
= isl_local_space_offset(ls
, isl_dim_div
) - 1;
1482 for (i
= ls
->div
->n_row
- 1; i
>= 0; --i
) {
1483 if (!active
[offset
+ i
])
1485 for (j
= 0; j
< total
; ++j
)
1486 active
[j
] |= !isl_int_is_zero(ls
->div
->row
[i
][2 + j
]);
1492 /* Given a local space "ls" of a set, create a local space
1493 * for the lift of the set. In particular, the result
1494 * is of the form [dim -> local[..]], with ls->div->n_row variables in the
1495 * range of the wrapped map.
1497 __isl_give isl_local_space
*isl_local_space_lift(
1498 __isl_take isl_local_space
*ls
)
1500 ls
= isl_local_space_cow(ls
);
1504 ls
->dim
= isl_space_lift(ls
->dim
, ls
->div
->n_row
);
1505 ls
->div
= isl_mat_drop_rows(ls
->div
, 0, ls
->div
->n_row
);
1506 if (!ls
->dim
|| !ls
->div
)
1507 return isl_local_space_free(ls
);
1512 /* Construct a basic map that maps a set living in local space "ls"
1513 * to the corresponding lifted local space.
1515 __isl_give isl_basic_map
*isl_local_space_lifting(
1516 __isl_take isl_local_space
*ls
)
1518 isl_basic_map
*lifting
;
1519 isl_basic_set
*bset
;
1523 if (!isl_local_space_is_set(ls
))
1524 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
1525 "lifting only defined on set spaces", goto error
);
1527 bset
= isl_basic_set_from_local_space(ls
);
1528 lifting
= isl_basic_set_unwrap(isl_basic_set_lift(bset
));
1529 lifting
= isl_basic_map_domain_map(lifting
);
1530 lifting
= isl_basic_map_reverse(lifting
);
1534 isl_local_space_free(ls
);
1538 /* Compute the preimage of "ls" under the function represented by "ma".
1539 * In other words, plug in "ma" in "ls". The result is a local space
1540 * that is part of the domain space of "ma".
1542 * If the divs in "ls" are represented as
1544 * floor((a_i(p) + b_i x + c_i(divs))/n_i)
1546 * and ma is represented by
1548 * x = D(p) + F(y) + G(divs')
1550 * then the resulting divs are
1552 * floor((a_i(p) + b_i D(p) + b_i F(y) + B_i G(divs') + c_i(divs))/n_i)
1554 * We first copy over the divs from "ma" and then
1555 * we add the modified divs from "ls".
1557 __isl_give isl_local_space
*isl_local_space_preimage_multi_aff(
1558 __isl_take isl_local_space
*ls
, __isl_take isl_multi_aff
*ma
)
1562 isl_local_space
*res
= NULL
;
1563 isl_size n_div_ls
, n_div_ma
;
1564 isl_int f
, c1
, c2
, g
;
1566 ma
= isl_multi_aff_align_divs(ma
);
1569 if (!isl_space_is_range_internal(ls
->dim
, ma
->space
))
1570 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
1571 "spaces don't match", goto error
);
1573 n_div_ls
= isl_local_space_dim(ls
, isl_dim_div
);
1574 n_div_ma
= ma
->n
? isl_aff_dim(ma
->u
.p
[0], isl_dim_div
) : 0;
1575 if (n_div_ls
< 0 || n_div_ma
< 0)
1578 space
= isl_space_domain(isl_multi_aff_get_space(ma
));
1579 res
= isl_local_space_alloc(space
, n_div_ma
+ n_div_ls
);
1584 isl_mat_free(res
->div
);
1585 res
->div
= isl_mat_copy(ma
->u
.p
[0]->ls
->div
);
1586 res
->div
= isl_mat_add_zero_cols(res
->div
, n_div_ls
);
1587 res
->div
= isl_mat_add_rows(res
->div
, n_div_ls
);
1597 for (i
= 0; i
< ls
->div
->n_row
; ++i
) {
1598 if (isl_int_is_zero(ls
->div
->row
[i
][0])) {
1599 isl_int_set_si(res
->div
->row
[n_div_ma
+ i
][0], 0);
1602 if (isl_seq_preimage(res
->div
->row
[n_div_ma
+ i
],
1604 ma
, 0, 0, n_div_ma
, n_div_ls
, f
, c1
, c2
, g
, 1) < 0)
1605 res
= isl_local_space_free(res
);
1606 res
= normalize_div(res
, n_div_ma
+ i
);
1616 isl_local_space_free(ls
);
1617 isl_multi_aff_free(ma
);
1620 isl_local_space_free(ls
);
1621 isl_multi_aff_free(ma
);
1622 isl_local_space_free(res
);
1626 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "ls"
1627 * to dimensions of "dst_type" at "dst_pos".
1629 * Moving to/from local dimensions is not allowed.
1630 * We currently assume that the dimension type changes.
1632 __isl_give isl_local_space
*isl_local_space_move_dims(
1633 __isl_take isl_local_space
*ls
,
1634 enum isl_dim_type dst_type
, unsigned dst_pos
,
1635 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1639 isl_size v_src
, v_dst
;
1646 !isl_local_space_is_named_or_nested(ls
, src_type
) &&
1647 !isl_local_space_is_named_or_nested(ls
, dst_type
))
1650 if (isl_local_space_check_range(ls
, src_type
, src_pos
, n
) < 0)
1651 return isl_local_space_free(ls
);
1652 if (isl_local_space_check_range(ls
, dst_type
, dst_pos
, 0) < 0)
1653 return isl_local_space_free(ls
);
1654 if (src_type
== isl_dim_div
)
1655 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
1656 "cannot move divs", return isl_local_space_free(ls
));
1657 if (dst_type
== isl_dim_div
)
1658 isl_die(isl_local_space_get_ctx(ls
), isl_error_invalid
,
1659 "cannot move to divs", return isl_local_space_free(ls
));
1660 if (dst_type
== src_type
&& dst_pos
== src_pos
)
1662 if (dst_type
== src_type
)
1663 isl_die(isl_local_space_get_ctx(ls
), isl_error_unsupported
,
1664 "moving dims within the same type not supported",
1665 return isl_local_space_free(ls
));
1667 v_src
= isl_local_space_var_offset(ls
, src_type
);
1668 v_dst
= isl_local_space_var_offset(ls
, dst_type
);
1669 if (v_src
< 0 || v_dst
< 0)
1670 return isl_local_space_free(ls
);
1671 g_src_pos
= v_src
+ src_pos
;
1672 g_dst_pos
= v_dst
+ dst_pos
;
1673 if (dst_type
> src_type
)
1676 local
= isl_local_space_take_local(ls
);
1677 local
= isl_local_move_vars(local
, g_dst_pos
, g_src_pos
, n
);
1678 ls
= isl_local_space_restore_local(ls
, local
);
1680 space
= isl_local_space_take_space(ls
);
1681 space
= isl_space_move_dims(space
, dst_type
, dst_pos
,
1682 src_type
, src_pos
, n
);
1683 ls
= isl_local_space_restore_space(ls
, space
);
1688 /* Given a local space (A -> B), return the corresponding local space
1691 __isl_give isl_local_space
*isl_local_space_wrapped_reverse(
1692 __isl_take isl_local_space
*ls
)
1696 isl_size n_in
, n_out
;
1699 space
= isl_local_space_peek_space(ls
);
1700 offset
= isl_space_offset(space
, isl_dim_set
);
1701 n_in
= isl_space_wrapped_dim(space
, isl_dim_set
, isl_dim_in
);
1702 n_out
= isl_space_wrapped_dim(space
, isl_dim_set
, isl_dim_out
);
1703 if (offset
< 0 || n_in
< 0 || n_out
< 0)
1704 return isl_local_space_free(ls
);
1706 space
= isl_local_space_take_space(ls
);
1707 space
= isl_space_wrapped_reverse(space
);
1708 ls
= isl_local_space_restore_space(ls
, space
);
1710 local
= isl_local_space_take_local(ls
);
1711 local
= isl_local_move_vars(local
, offset
, offset
+ n_in
, n_out
);
1712 ls
= isl_local_space_restore_local(ls
, local
);
1717 /* Remove any internal structure of the domain of "ls".
1718 * If there is any such internal structure in the input,
1719 * then the name of the corresponding space is also removed.
1721 __isl_give isl_local_space
*isl_local_space_flatten_domain(
1722 __isl_take isl_local_space
*ls
)
1727 if (!ls
->dim
->nested
[0])
1730 ls
= isl_local_space_cow(ls
);
1734 ls
->dim
= isl_space_flatten_domain(ls
->dim
);
1736 return isl_local_space_free(ls
);
1741 /* Remove any internal structure of the range of "ls".
1742 * If there is any such internal structure in the input,
1743 * then the name of the corresponding space is also removed.
1745 __isl_give isl_local_space
*isl_local_space_flatten_range(
1746 __isl_take isl_local_space
*ls
)
1751 if (!ls
->dim
->nested
[1])
1754 ls
= isl_local_space_cow(ls
);
1758 ls
->dim
= isl_space_flatten_range(ls
->dim
);
1760 return isl_local_space_free(ls
);
1765 /* Given the local space "ls" of a map, return the local space of a set
1766 * that lives in a space that wraps the space of "ls" and that has
1769 __isl_give isl_local_space
*isl_local_space_wrap(__isl_take isl_local_space
*ls
)
1771 ls
= isl_local_space_cow(ls
);
1775 ls
->dim
= isl_space_wrap(ls
->dim
);
1777 return isl_local_space_free(ls
);
1782 /* Lift the point "pnt", living in the (set) space of "ls"
1783 * to live in a space with extra coordinates corresponding
1784 * to the local variables of "ls".
1786 __isl_give isl_point
*isl_local_space_lift_point(__isl_take isl_local_space
*ls
,
1787 __isl_take isl_point
*pnt
)
1794 if (isl_local_space_check_has_space(ls
, isl_point_peek_space(pnt
)) < 0)
1797 local
= isl_local_space_peek_local(ls
);
1798 n_local
= isl_local_space_dim(ls
, isl_dim_div
);
1802 space
= isl_point_take_space(pnt
);
1803 vec
= isl_point_take_vec(pnt
);
1805 space
= isl_space_lift(space
, n_local
);
1806 vec
= isl_local_extend_point_vec(local
, vec
);
1808 pnt
= isl_point_restore_vec(pnt
, vec
);
1809 pnt
= isl_point_restore_space(pnt
, space
);
1811 isl_local_space_free(ls
);
1815 isl_local_space_free(ls
);
1816 isl_point_free(pnt
);
1820 /* Do any of the local variables in "ls" depend on the specified dimensions?
1822 isl_bool
isl_local_space_involves_dims(__isl_keep isl_local_space
*ls
,
1823 enum isl_dim_type type
, unsigned first
, unsigned n
)
1828 off
= isl_local_space_var_offset(ls
, type
);
1829 if (off
< 0 || isl_local_space_check_range(ls
, type
, first
, n
) < 0)
1830 return isl_bool_error
;
1832 local
= isl_local_space_peek_local(ls
);
1833 return isl_local_involves_vars(local
, off
+ first
, n
);