2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2013-2014 Ecole Normale Superieure
5 * Copyright 2018-2019 Cerebras Systems
7 * Use of this software is governed by the MIT license
9 * Written by Sven Verdoolaege, K.U.Leuven, Departement
10 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
11 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
12 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
13 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
14 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
19 #include <isl_space_private.h>
20 #include <isl_id_private.h>
21 #include <isl_reordering.h>
23 isl_ctx
*isl_space_get_ctx(__isl_keep isl_space
*space
)
25 return space
? space
->ctx
: NULL
;
28 __isl_give isl_space
*isl_space_alloc(isl_ctx
*ctx
,
29 unsigned nparam
, unsigned n_in
, unsigned n_out
)
33 space
= isl_alloc_type(ctx
, struct isl_space
);
40 space
->nparam
= nparam
;
44 space
->tuple_id
[0] = NULL
;
45 space
->tuple_id
[1] = NULL
;
47 space
->nested
[0] = NULL
;
48 space
->nested
[1] = NULL
;
56 /* Mark the space as being that of a set, by setting the domain tuple
59 static __isl_give isl_space
*mark_as_set(__isl_take isl_space
*space
)
61 space
= isl_space_cow(space
);
64 space
= isl_space_set_tuple_id(space
, isl_dim_in
, &isl_id_none
);
68 /* Is the space that of a set?
70 isl_bool
isl_space_is_set(__isl_keep isl_space
*space
)
73 return isl_bool_error
;
74 if (space
->n_in
!= 0 || space
->nested
[0])
75 return isl_bool_false
;
76 if (space
->tuple_id
[0] != &isl_id_none
)
77 return isl_bool_false
;
81 /* Check that "space" is a set space.
83 isl_stat
isl_space_check_is_set(__isl_keep isl_space
*space
)
87 is_set
= isl_space_is_set(space
);
89 return isl_stat_error
;
91 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
92 "space is not a set", return isl_stat_error
);
96 /* Check that "space" is a proper set space,
97 * i.e., the space of a set that is not a parameter domain.
99 isl_stat
isl_space_check_is_proper_set(__isl_keep isl_space
*space
)
101 isl_bool is_params
, is_set
;
103 is_params
= isl_space_is_params(space
);
104 is_set
= isl_space_is_set(space
);
105 if (is_params
< 0 || is_set
< 0)
106 return isl_stat_error
;
107 if (is_params
|| !is_set
)
108 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
109 "space is not a proper set", return isl_stat_error
);
113 /* Is the given space that of a map?
115 isl_bool
isl_space_is_map(__isl_keep isl_space
*space
)
120 return isl_bool_error
;
121 r
= space
->tuple_id
[0] != &isl_id_none
&&
122 space
->tuple_id
[1] != &isl_id_none
;
123 return isl_bool_ok(r
);
126 /* Check that "space" is the space of a map.
128 static isl_stat
isl_space_check_is_map(__isl_keep isl_space
*space
)
132 is_space
= isl_space_is_map(space
);
134 return isl_stat_error
;
136 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
137 "expecting map space", return isl_stat_error
);
141 /* Check that "space" is the space of a set wrapping a map space.
143 isl_stat
isl_space_check_is_wrapping(__isl_keep isl_space
*space
)
147 wrapping
= isl_space_is_wrapping(space
);
149 return isl_stat_error
;
151 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
152 "not a product", return isl_stat_error
);
156 /* Check that "space" is the space of a map
157 * where the domain is a wrapped map space.
159 isl_stat
isl_space_check_domain_is_wrapping(__isl_keep isl_space
*space
)
163 wrapping
= isl_space_domain_is_wrapping(space
);
165 return isl_stat_error
;
167 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
168 "domain not a product", return isl_stat_error
);
172 /* Check that "space" is the space of a map
173 * where the range is a wrapped map space.
175 isl_stat
isl_space_check_range_is_wrapping(__isl_keep isl_space
*space
)
179 wrapping
= isl_space_range_is_wrapping(space
);
181 return isl_stat_error
;
183 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
184 "range not a product", return isl_stat_error
);
188 __isl_give isl_space
*isl_space_set_alloc(isl_ctx
*ctx
,
189 unsigned nparam
, unsigned dim
)
192 space
= isl_space_alloc(ctx
, nparam
, 0, dim
);
193 space
= mark_as_set(space
);
197 /* Mark the space as being that of a parameter domain, by setting
198 * both tuples to isl_id_none.
200 static __isl_give isl_space
*mark_as_params(isl_space
*space
)
204 space
= isl_space_set_tuple_id(space
, isl_dim_in
, &isl_id_none
);
205 space
= isl_space_set_tuple_id(space
, isl_dim_out
, &isl_id_none
);
209 /* Is the space that of a parameter domain?
211 isl_bool
isl_space_is_params(__isl_keep isl_space
*space
)
214 return isl_bool_error
;
215 if (space
->n_in
!= 0 || space
->nested
[0] ||
216 space
->n_out
!= 0 || space
->nested
[1])
217 return isl_bool_false
;
218 if (space
->tuple_id
[0] != &isl_id_none
)
219 return isl_bool_false
;
220 if (space
->tuple_id
[1] != &isl_id_none
)
221 return isl_bool_false
;
222 return isl_bool_true
;
225 /* Create a space for a parameter domain.
227 __isl_give isl_space
*isl_space_params_alloc(isl_ctx
*ctx
, unsigned nparam
)
230 space
= isl_space_alloc(ctx
, nparam
, 0, 0);
231 space
= mark_as_params(space
);
235 /* Create a space for a parameter domain, without any parameters.
237 __isl_give isl_space
*isl_space_unit(isl_ctx
*ctx
)
239 return isl_space_params_alloc(ctx
, 0);
242 static isl_size
global_pos(__isl_keep isl_space
*space
,
243 enum isl_dim_type type
, unsigned pos
)
245 if (isl_space_check_range(space
, type
, pos
, 1) < 0)
246 return isl_size_error
;
252 return pos
+ space
->nparam
;
254 return pos
+ space
->nparam
+ space
->n_in
;
256 isl_assert(isl_space_get_ctx(space
), 0, return isl_size_error
);
258 return isl_size_error
;
261 /* Extend length of ids array to the total number of dimensions.
263 static __isl_give isl_space
*extend_ids(__isl_take isl_space
*space
)
269 dim
= isl_space_dim(space
, isl_dim_all
);
271 return isl_space_free(space
);
272 if (dim
<= space
->n_id
)
276 space
->ids
= isl_calloc_array(space
->ctx
, isl_id
*, dim
);
280 ids
= isl_realloc_array(space
->ctx
, space
->ids
, isl_id
*, dim
);
284 for (i
= space
->n_id
; i
< dim
; ++i
)
285 space
->ids
[i
] = NULL
;
292 isl_space_free(space
);
296 static __isl_give isl_space
*set_id(__isl_take isl_space
*space
,
297 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
301 space
= isl_space_cow(space
);
303 gpos
= global_pos(space
, type
, pos
);
307 if (gpos
>= space
->n_id
) {
310 space
= extend_ids(space
);
315 space
->ids
[gpos
] = id
;
320 isl_space_free(space
);
324 static __isl_keep isl_id
*get_id(__isl_keep isl_space
*space
,
325 enum isl_dim_type type
, unsigned pos
)
329 gpos
= global_pos(space
, type
, pos
);
332 if (gpos
>= space
->n_id
)
334 return space
->ids
[gpos
];
337 /* Return the nested space at the given position.
339 static __isl_keep isl_space
*isl_space_peek_nested(__isl_keep isl_space
*space
,
344 if (!space
->nested
[pos
])
345 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
346 "no nested space", return NULL
);
347 return space
->nested
[pos
];
350 static unsigned offset(__isl_keep isl_space
*space
, enum isl_dim_type type
)
353 case isl_dim_param
: return 0;
354 case isl_dim_in
: return space
->nparam
;
355 case isl_dim_out
: return space
->nparam
+ space
->n_in
;
360 static unsigned n(__isl_keep isl_space
*space
, enum isl_dim_type type
)
363 case isl_dim_param
: return space
->nparam
;
364 case isl_dim_in
: return space
->n_in
;
365 case isl_dim_out
: return space
->n_out
;
367 return space
->nparam
+ space
->n_in
+ space
->n_out
;
372 isl_size
isl_space_dim(__isl_keep isl_space
*space
, enum isl_dim_type type
)
375 return isl_size_error
;
376 return n(space
, type
);
379 /* Return the dimensionality of tuple "inner" within the wrapped relation
380 * inside tuple "outer".
382 isl_size
isl_space_wrapped_dim(__isl_keep isl_space
*space
,
383 enum isl_dim_type outer
, enum isl_dim_type inner
)
388 return isl_size_error
;
389 if (outer
!= isl_dim_in
&& outer
!= isl_dim_out
)
390 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
391 "only input, output and set tuples "
392 "can have nested relations", return isl_size_error
);
393 pos
= outer
- isl_dim_in
;
394 return isl_space_dim(isl_space_peek_nested(space
, pos
), inner
);
397 isl_size
isl_space_offset(__isl_keep isl_space
*space
, enum isl_dim_type type
)
400 return isl_size_error
;
401 return offset(space
, type
);
404 static __isl_give isl_space
*copy_ids(__isl_take isl_space
*dst
,
405 enum isl_dim_type dst_type
, unsigned offset
, __isl_keep isl_space
*src
,
406 enum isl_dim_type src_type
)
414 for (i
= 0; i
< n(src
, src_type
); ++i
) {
415 id
= get_id(src
, src_type
, i
);
418 isl_id_free(get_id(dst
, dst_type
, offset
+ i
));
419 dst
= set_id(dst
, dst_type
, offset
+ i
, isl_id_copy(id
));
426 __isl_give isl_space
*isl_space_dup(__isl_keep isl_space
*space
)
431 dup
= isl_space_alloc(space
->ctx
,
432 space
->nparam
, space
->n_in
, space
->n_out
);
435 if (space
->tuple_id
[0] &&
436 !(dup
->tuple_id
[0] = isl_id_copy(space
->tuple_id
[0])))
438 if (space
->tuple_id
[1] &&
439 !(dup
->tuple_id
[1] = isl_id_copy(space
->tuple_id
[1])))
441 if (space
->nested
[0] &&
442 !(dup
->nested
[0] = isl_space_copy(space
->nested
[0])))
444 if (space
->nested
[1] &&
445 !(dup
->nested
[1] = isl_space_copy(space
->nested
[1])))
449 dup
= copy_ids(dup
, isl_dim_param
, 0, space
, isl_dim_param
);
450 dup
= copy_ids(dup
, isl_dim_in
, 0, space
, isl_dim_in
);
451 dup
= copy_ids(dup
, isl_dim_out
, 0, space
, isl_dim_out
);
458 __isl_give isl_space
*isl_space_cow(__isl_take isl_space
*space
)
466 return isl_space_dup(space
);
469 __isl_give isl_space
*isl_space_copy(__isl_keep isl_space
*space
)
478 __isl_null isl_space
*isl_space_free(__isl_take isl_space
*space
)
485 if (--space
->ref
> 0)
488 isl_id_free(space
->tuple_id
[0]);
489 isl_id_free(space
->tuple_id
[1]);
491 isl_space_free(space
->nested
[0]);
492 isl_space_free(space
->nested
[1]);
494 for (i
= 0; i
< space
->n_id
; ++i
)
495 isl_id_free(space
->ids
[i
]);
497 isl_ctx_deref(space
->ctx
);
504 /* Check if "s" is a valid dimension or tuple name.
505 * We currently only forbid names that look like a number.
507 * s is assumed to be non-NULL.
509 static int name_ok(isl_ctx
*ctx
, const char *s
)
515 isl_die(ctx
, isl_error_invalid
, "name looks like a number",
521 /* Return a copy of the nested space at the given position.
523 static __isl_keep isl_space
*isl_space_get_nested(__isl_keep isl_space
*space
,
526 return isl_space_copy(isl_space_peek_nested(space
, pos
));
529 /* Return the nested space at the given position.
530 * This may be either a copy or the nested space itself
531 * if there is only one reference to "space".
532 * This allows the nested space to be modified inplace
533 * if both "space" and the nested space have only a single reference.
534 * The caller is not allowed to modify "space" between this call and
535 * a subsequent call to isl_space_restore_nested.
536 * The only exception is that isl_space_free can be called instead.
538 static __isl_give isl_space
*isl_space_take_nested(__isl_keep isl_space
*space
,
546 return isl_space_get_nested(space
, pos
);
547 nested
= space
->nested
[pos
];
548 space
->nested
[pos
] = NULL
;
552 /* Replace the nested space at the given position by "nested",
553 * where this nested space of "space" may be missing
554 * due to a preceding call to isl_space_take_nested.
555 * However, in this case, "space" only has a single reference and
556 * then the call to isl_space_cow has no effect.
558 static __isl_give isl_space
*isl_space_restore_nested(
559 __isl_take isl_space
*space
, int pos
, __isl_take isl_space
*nested
)
561 if (!space
|| !nested
)
564 if (space
->nested
[pos
] == nested
) {
565 isl_space_free(nested
);
569 space
= isl_space_cow(space
);
572 isl_space_free(space
->nested
[pos
]);
573 space
->nested
[pos
] = nested
;
577 isl_space_free(space
);
578 isl_space_free(nested
);
582 /* Is it possible for the given dimension type to have a tuple id?
584 static int space_can_have_id(__isl_keep isl_space
*space
,
585 enum isl_dim_type type
)
589 if (isl_space_is_params(space
))
590 isl_die(space
->ctx
, isl_error_invalid
,
591 "parameter spaces don't have tuple ids", return 0);
592 if (isl_space_is_set(space
) && type
!= isl_dim_set
)
593 isl_die(space
->ctx
, isl_error_invalid
,
594 "set spaces can only have a set id", return 0);
595 if (type
!= isl_dim_in
&& type
!= isl_dim_out
)
596 isl_die(space
->ctx
, isl_error_invalid
,
597 "only input, output and set tuples can have ids",
603 /* Does the tuple have an id?
605 isl_bool
isl_space_has_tuple_id(__isl_keep isl_space
*space
,
606 enum isl_dim_type type
)
608 if (!space_can_have_id(space
, type
))
609 return isl_bool_error
;
610 return isl_bool_ok(space
->tuple_id
[type
- isl_dim_in
] != NULL
);
613 /* Does the domain tuple of the map space "space" have an identifier?
615 isl_bool
isl_space_has_domain_tuple_id(__isl_keep isl_space
*space
)
617 if (isl_space_check_is_map(space
) < 0)
618 return isl_bool_error
;
619 return isl_space_has_tuple_id(space
, isl_dim_in
);
622 /* Does the range tuple of the map space "space" have an identifier?
624 isl_bool
isl_space_has_range_tuple_id(__isl_keep isl_space
*space
)
626 if (isl_space_check_is_map(space
) < 0)
627 return isl_bool_error
;
628 return isl_space_has_tuple_id(space
, isl_dim_out
);
631 __isl_give isl_id
*isl_space_get_tuple_id(__isl_keep isl_space
*space
,
632 enum isl_dim_type type
)
638 has_id
= isl_space_has_tuple_id(space
, type
);
642 isl_die(space
->ctx
, isl_error_invalid
,
643 "tuple has no id", return NULL
);
644 return isl_id_copy(space
->tuple_id
[type
- isl_dim_in
]);
647 /* Return the identifier of the domain tuple of the map space "space",
648 * assuming it has one.
650 __isl_give isl_id
*isl_space_get_domain_tuple_id(
651 __isl_keep isl_space
*space
)
653 if (isl_space_check_is_map(space
) < 0)
655 return isl_space_get_tuple_id(space
, isl_dim_in
);
658 /* Return the identifier of the range tuple of the map space "space",
659 * assuming it has one.
661 __isl_give isl_id
*isl_space_get_range_tuple_id(
662 __isl_keep isl_space
*space
)
664 if (isl_space_check_is_map(space
) < 0)
666 return isl_space_get_tuple_id(space
, isl_dim_out
);
669 __isl_give isl_space
*isl_space_set_tuple_id(__isl_take isl_space
*space
,
670 enum isl_dim_type type
, __isl_take isl_id
*id
)
672 space
= isl_space_cow(space
);
675 if (type
!= isl_dim_in
&& type
!= isl_dim_out
)
676 isl_die(space
->ctx
, isl_error_invalid
,
677 "only input, output and set tuples can have names",
680 isl_id_free(space
->tuple_id
[type
- isl_dim_in
]);
681 space
->tuple_id
[type
- isl_dim_in
] = id
;
686 isl_space_free(space
);
690 /* Replace the identifier of the domain tuple of the map space "space"
693 __isl_give isl_space
*isl_space_set_domain_tuple_id(
694 __isl_take isl_space
*space
, __isl_take isl_id
*id
)
696 if (isl_space_check_is_map(space
) < 0)
697 space
= isl_space_free(space
);
698 return isl_space_set_tuple_id(space
, isl_dim_in
, id
);
701 /* Replace the identifier of the range tuple of the map space "space"
704 __isl_give isl_space
*isl_space_set_range_tuple_id(
705 __isl_take isl_space
*space
, __isl_take isl_id
*id
)
707 if (isl_space_check_is_map(space
) < 0)
708 space
= isl_space_free(space
);
709 return isl_space_set_tuple_id(space
, isl_dim_out
, id
);
712 __isl_give isl_space
*isl_space_reset_tuple_id(__isl_take isl_space
*space
,
713 enum isl_dim_type type
)
715 space
= isl_space_cow(space
);
718 if (type
!= isl_dim_in
&& type
!= isl_dim_out
)
719 isl_die(space
->ctx
, isl_error_invalid
,
720 "only input, output and set tuples can have names",
723 isl_id_free(space
->tuple_id
[type
- isl_dim_in
]);
724 space
->tuple_id
[type
- isl_dim_in
] = NULL
;
728 isl_space_free(space
);
732 /* Set the id of the given dimension of "space" to "id".
733 * If the dimension already has an id, then it is replaced.
734 * If the dimension is a parameter, then we need to change it
735 * in the nested spaces (if any) as well.
737 __isl_give isl_space
*isl_space_set_dim_id(__isl_take isl_space
*space
,
738 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
740 space
= isl_space_cow(space
);
744 if (type
== isl_dim_param
) {
747 for (i
= 0; i
< 2; ++i
) {
748 if (!space
->nested
[i
])
751 isl_space_set_dim_id(space
->nested
[i
],
752 type
, pos
, isl_id_copy(id
));
753 if (!space
->nested
[i
])
758 isl_id_free(get_id(space
, type
, pos
));
759 return set_id(space
, type
, pos
, id
);
762 isl_space_free(space
);
766 /* Reset the id of the given dimension of "space".
767 * If the dimension already has an id, then it is removed.
768 * If the dimension is a parameter, then we need to reset it
769 * in the nested spaces (if any) as well.
771 __isl_give isl_space
*isl_space_reset_dim_id(__isl_take isl_space
*space
,
772 enum isl_dim_type type
, unsigned pos
)
774 space
= isl_space_cow(space
);
778 if (type
== isl_dim_param
) {
781 for (i
= 0; i
< 2; ++i
) {
782 if (!space
->nested
[i
])
785 isl_space_reset_dim_id(space
->nested
[i
],
787 if (!space
->nested
[i
])
792 isl_id_free(get_id(space
, type
, pos
));
793 return set_id(space
, type
, pos
, NULL
);
795 isl_space_free(space
);
799 isl_bool
isl_space_has_dim_id(__isl_keep isl_space
*space
,
800 enum isl_dim_type type
, unsigned pos
)
803 return isl_bool_error
;
804 return isl_bool_ok(get_id(space
, type
, pos
) != NULL
);
807 __isl_give isl_id
*isl_space_get_dim_id(__isl_keep isl_space
*space
,
808 enum isl_dim_type type
, unsigned pos
)
812 if (!get_id(space
, type
, pos
))
813 isl_die(space
->ctx
, isl_error_invalid
,
814 "dim has no id", return NULL
);
815 return isl_id_copy(get_id(space
, type
, pos
));
818 __isl_give isl_space
*isl_space_set_tuple_name(__isl_take isl_space
*space
,
819 enum isl_dim_type type
, const char *s
)
827 return isl_space_reset_tuple_id(space
, type
);
829 if (!name_ok(space
->ctx
, s
))
832 id
= isl_id_alloc(space
->ctx
, s
, NULL
);
833 return isl_space_set_tuple_id(space
, type
, id
);
835 isl_space_free(space
);
839 /* Does the tuple have a name?
841 isl_bool
isl_space_has_tuple_name(__isl_keep isl_space
*space
,
842 enum isl_dim_type type
)
846 if (!space_can_have_id(space
, type
))
847 return isl_bool_error
;
848 id
= space
->tuple_id
[type
- isl_dim_in
];
849 return isl_bool_ok(id
&& id
->name
);
852 __isl_keep
const char *isl_space_get_tuple_name(__isl_keep isl_space
*space
,
853 enum isl_dim_type type
)
858 if (type
!= isl_dim_in
&& type
!= isl_dim_out
)
860 id
= space
->tuple_id
[type
- isl_dim_in
];
861 return id
? id
->name
: NULL
;
864 __isl_give isl_space
*isl_space_set_dim_name(__isl_take isl_space
*space
,
865 enum isl_dim_type type
, unsigned pos
,
873 return isl_space_reset_dim_id(space
, type
, pos
);
874 if (!name_ok(space
->ctx
, s
))
876 id
= isl_id_alloc(space
->ctx
, s
, NULL
);
877 return isl_space_set_dim_id(space
, type
, pos
, id
);
879 isl_space_free(space
);
883 /* Does the given dimension have a name?
885 isl_bool
isl_space_has_dim_name(__isl_keep isl_space
*space
,
886 enum isl_dim_type type
, unsigned pos
)
891 return isl_bool_error
;
892 id
= get_id(space
, type
, pos
);
893 return isl_bool_ok(id
&& id
->name
);
896 __isl_keep
const char *isl_space_get_dim_name(__isl_keep isl_space
*space
,
897 enum isl_dim_type type
, unsigned pos
)
899 isl_id
*id
= get_id(space
, type
, pos
);
900 return id
? id
->name
: NULL
;
903 int isl_space_find_dim_by_id(__isl_keep isl_space
*space
,
904 enum isl_dim_type type
, __isl_keep isl_id
*id
)
910 n
= isl_space_dim(space
, type
);
911 offset
= isl_space_offset(space
, type
);
912 if (n
< 0 || offset
< 0 || !id
)
915 for (i
= 0; i
< n
&& offset
+ i
< space
->n_id
; ++i
)
916 if (space
->ids
[offset
+ i
] == id
)
922 int isl_space_find_dim_by_name(__isl_keep isl_space
*space
,
923 enum isl_dim_type type
, const char *name
)
929 n
= isl_space_dim(space
, type
);
930 offset
= isl_space_offset(space
, type
);
931 if (n
< 0 || offset
< 0 || !name
)
934 for (i
= 0; i
< n
&& offset
+ i
< space
->n_id
; ++i
) {
935 isl_id
*id
= get_id(space
, type
, i
);
936 if (id
&& id
->name
&& !strcmp(id
->name
, name
))
943 /* Reset the user pointer on all identifiers of parameters and tuples
946 __isl_give isl_space
*isl_space_reset_user(__isl_take isl_space
*space
)
956 ctx
= isl_space_get_ctx(space
);
958 for (i
= 0; i
< space
->nparam
&& i
< space
->n_id
; ++i
) {
959 if (!isl_id_get_user(space
->ids
[i
]))
961 space
= isl_space_cow(space
);
964 name
= isl_id_get_name(space
->ids
[i
]);
965 id
= isl_id_alloc(ctx
, name
, NULL
);
966 isl_id_free(space
->ids
[i
]);
969 return isl_space_free(space
);
972 for (i
= 0; i
< 2; ++i
) {
973 if (!space
->tuple_id
[i
])
975 if (!isl_id_get_user(space
->tuple_id
[i
]))
977 space
= isl_space_cow(space
);
980 name
= isl_id_get_name(space
->tuple_id
[i
]);
981 id
= isl_id_alloc(ctx
, name
, NULL
);
982 isl_id_free(space
->tuple_id
[i
]);
983 space
->tuple_id
[i
] = id
;
985 return isl_space_free(space
);
988 for (i
= 0; i
< 2; ++i
) {
991 if (!space
->nested
[i
])
993 nested
= isl_space_take_nested(space
, i
);
994 nested
= isl_space_reset_user(nested
);
995 space
= isl_space_restore_nested(space
, i
, nested
);
1003 static __isl_keep isl_id
*tuple_id(__isl_keep isl_space
*space
,
1004 enum isl_dim_type type
)
1008 if (type
== isl_dim_in
)
1009 return space
->tuple_id
[0];
1010 if (type
== isl_dim_out
)
1011 return space
->tuple_id
[1];
1015 static __isl_keep isl_space
*nested(__isl_keep isl_space
*space
,
1016 enum isl_dim_type type
)
1020 if (type
== isl_dim_in
)
1021 return space
->nested
[0];
1022 if (type
== isl_dim_out
)
1023 return space
->nested
[1];
1027 /* Are the two spaces the same, apart from positions and names of parameters?
1029 isl_bool
isl_space_has_equal_tuples(__isl_keep isl_space
*space1
,
1030 __isl_keep isl_space
*space2
)
1032 if (!space1
|| !space2
)
1033 return isl_bool_error
;
1034 if (space1
== space2
)
1035 return isl_bool_true
;
1036 return isl_space_tuple_is_equal(space1
, isl_dim_in
,
1037 space2
, isl_dim_in
) &&
1038 isl_space_tuple_is_equal(space1
, isl_dim_out
,
1039 space2
, isl_dim_out
);
1042 /* Check that a match involving "space" was successful.
1043 * That is, check that "match" is equal to isl_bool_true.
1045 static isl_stat
check_match(__isl_keep isl_space
*space
, isl_bool match
)
1048 return isl_stat_error
;
1050 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
1051 "incompatible spaces", return isl_stat_error
);
1056 /* Check that the two spaces are the same,
1057 * apart from positions and names of parameters.
1059 isl_stat
isl_space_check_equal_tuples(__isl_keep isl_space
*space1
,
1060 __isl_keep isl_space
*space2
)
1064 is_equal
= isl_space_has_equal_tuples(space1
, space2
);
1065 return check_match(space1
, is_equal
);
1068 /* Check if the tuple of type "type1" of "space1" is the same as
1069 * the tuple of type "type2" of "space2".
1071 * That is, check if the tuples have the same identifier, the same dimension
1072 * and the same internal structure.
1073 * The identifiers of the dimensions inside the tuples do not affect the result.
1075 * Note that this function only checks the tuples themselves.
1076 * If nested tuples are involved, then we need to be careful not
1077 * to have result affected by possibly differing parameters
1078 * in those nested tuples.
1080 isl_bool
isl_space_tuple_is_equal(__isl_keep isl_space
*space1
,
1081 enum isl_dim_type type1
, __isl_keep isl_space
*space2
,
1082 enum isl_dim_type type2
)
1085 isl_space
*nested1
, *nested2
;
1087 if (!space1
|| !space2
)
1088 return isl_bool_error
;
1090 if (space1
== space2
&& type1
== type2
)
1091 return isl_bool_true
;
1093 if (n(space1
, type1
) != n(space2
, type2
))
1094 return isl_bool_false
;
1095 id1
= tuple_id(space1
, type1
);
1096 id2
= tuple_id(space2
, type2
);
1098 return isl_bool_false
;
1099 if (id1
&& id1
!= id2
)
1100 return isl_bool_false
;
1101 nested1
= nested(space1
, type1
);
1102 nested2
= nested(space2
, type2
);
1103 if (!nested1
^ !nested2
)
1104 return isl_bool_false
;
1105 if (nested1
&& !isl_space_has_equal_tuples(nested1
, nested2
))
1106 return isl_bool_false
;
1107 return isl_bool_true
;
1110 /* Is the tuple "inner" within the wrapped relation inside tuple "outer"
1111 * of "space1" equal to tuple "type2" of "space2"?
1113 isl_bool
isl_space_wrapped_tuple_is_equal(__isl_keep isl_space
*space1
,
1114 enum isl_dim_type outer
, enum isl_dim_type inner
,
1115 __isl_keep isl_space
*space2
, enum isl_dim_type type2
)
1121 return isl_bool_error
;
1122 if (outer
!= isl_dim_in
&& outer
!= isl_dim_out
)
1123 isl_die(isl_space_get_ctx(space1
), isl_error_invalid
,
1124 "only input, output and set tuples "
1125 "can have nested relations", return isl_bool_error
);
1126 pos
= outer
- isl_dim_in
;
1127 nested
= isl_space_peek_nested(space1
, pos
);
1128 return isl_space_tuple_is_equal(nested
, inner
, space2
, type2
);
1131 /* Check that the tuple "inner" within the wrapped relation inside tuple "outer"
1132 * of "space1" is equal to tuple "type2" of "space2".
1134 isl_stat
isl_space_check_wrapped_tuple_is_equal(__isl_keep isl_space
*space1
,
1135 enum isl_dim_type outer
, enum isl_dim_type inner
,
1136 __isl_keep isl_space
*space2
, enum isl_dim_type type2
)
1140 is_equal
= isl_space_wrapped_tuple_is_equal(space1
, outer
, inner
,
1142 return check_match(space1
, is_equal
);
1145 static isl_bool
match(__isl_keep isl_space
*space1
, enum isl_dim_type type1
,
1146 __isl_keep isl_space
*space2
, enum isl_dim_type type2
)
1151 if (!space1
|| !space2
)
1152 return isl_bool_error
;
1154 if (space1
== space2
&& type1
== type2
)
1155 return isl_bool_true
;
1157 equal
= isl_space_tuple_is_equal(space1
, type1
, space2
, type2
);
1158 if (equal
< 0 || !equal
)
1161 if (!space1
->ids
&& !space2
->ids
)
1162 return isl_bool_true
;
1164 for (i
= 0; i
< n(space1
, type1
); ++i
) {
1165 if (get_id(space1
, type1
, i
) != get_id(space2
, type2
, i
))
1166 return isl_bool_false
;
1168 return isl_bool_true
;
1171 /* Do "space1" and "space2" have the same parameters?
1173 isl_bool
isl_space_has_equal_params(__isl_keep isl_space
*space1
,
1174 __isl_keep isl_space
*space2
)
1176 return match(space1
, isl_dim_param
, space2
, isl_dim_param
);
1179 /* Do "space1" and "space2" have the same identifiers for all
1180 * the tuple variables?
1182 isl_bool
isl_space_has_equal_ids(__isl_keep isl_space
*space1
,
1183 __isl_keep isl_space
*space2
)
1187 equal
= match(space1
, isl_dim_in
, space2
, isl_dim_in
);
1188 if (equal
< 0 || !equal
)
1190 return match(space1
, isl_dim_out
, space2
, isl_dim_out
);
1193 isl_bool
isl_space_match(__isl_keep isl_space
*space1
, enum isl_dim_type type1
,
1194 __isl_keep isl_space
*space2
, enum isl_dim_type type2
)
1196 return match(space1
, type1
, space2
, type2
);
1199 static void get_ids(__isl_keep isl_space
*space
, enum isl_dim_type type
,
1200 unsigned first
, unsigned n
, __isl_keep isl_id
**ids
)
1204 for (i
= 0; i
< n
; ++i
)
1205 ids
[i
] = get_id(space
, type
, first
+ i
);
1208 static __isl_give isl_space
*space_extend(__isl_take isl_space
*space
,
1209 unsigned nparam
, unsigned n_in
, unsigned n_out
)
1211 isl_id
**ids
= NULL
;
1215 if (space
->nparam
== nparam
&&
1216 space
->n_in
== n_in
&& space
->n_out
== n_out
)
1219 isl_assert(space
->ctx
, space
->nparam
<= nparam
, goto error
);
1220 isl_assert(space
->ctx
, space
->n_in
<= n_in
, goto error
);
1221 isl_assert(space
->ctx
, space
->n_out
<= n_out
, goto error
);
1223 space
= isl_space_cow(space
);
1229 n
= nparam
+ n_in
+ n_out
;
1230 if (n
< nparam
|| n
< n_in
|| n
< n_out
)
1231 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
1232 "overflow in total number of dimensions",
1234 ids
= isl_calloc_array(space
->ctx
, isl_id
*, n
);
1237 get_ids(space
, isl_dim_param
, 0, space
->nparam
, ids
);
1238 get_ids(space
, isl_dim_in
, 0, space
->n_in
, ids
+ nparam
);
1239 get_ids(space
, isl_dim_out
, 0, space
->n_out
,
1240 ids
+ nparam
+ n_in
);
1243 space
->n_id
= nparam
+ n_in
+ n_out
;
1245 space
->nparam
= nparam
;
1247 space
->n_out
= n_out
;
1252 isl_space_free(space
);
1256 __isl_give isl_space
*isl_space_extend(__isl_take isl_space
*space
,
1257 unsigned nparam
, unsigned n_in
, unsigned n_out
)
1259 return space_extend(space
, nparam
, n_in
, n_out
);
1262 __isl_give isl_space
*isl_space_add_dims(__isl_take isl_space
*space
,
1263 enum isl_dim_type type
, unsigned n
)
1265 space
= isl_space_reset(space
, type
);
1270 space
= space_extend(space
,
1271 space
->nparam
+ n
, space
->n_in
, space
->n_out
);
1272 if (space
&& space
->nested
[0] &&
1273 !(space
->nested
[0] = isl_space_add_dims(space
->nested
[0],
1276 if (space
&& space
->nested
[1] &&
1277 !(space
->nested
[1] = isl_space_add_dims(space
->nested
[1],
1282 return space_extend(space
,
1283 space
->nparam
, space
->n_in
+ n
, space
->n_out
);
1285 return space_extend(space
,
1286 space
->nparam
, space
->n_in
, space
->n_out
+ n
);
1288 isl_die(space
->ctx
, isl_error_invalid
,
1289 "cannot add dimensions of specified type", goto error
);
1292 isl_space_free(space
);
1296 /* Add a parameter with identifier "id" to "space", provided
1297 * it does not already appear in "space".
1299 __isl_give isl_space
*isl_space_add_param_id(__isl_take isl_space
*space
,
1300 __isl_take isl_id
*id
)
1307 if (isl_space_find_dim_by_id(space
, isl_dim_param
, id
) >= 0) {
1312 pos
= isl_space_dim(space
, isl_dim_param
);
1315 space
= isl_space_add_dims(space
, isl_dim_param
, 1);
1316 space
= isl_space_set_dim_id(space
, isl_dim_param
, pos
, id
);
1320 isl_space_free(space
);
1325 static int valid_dim_type(enum isl_dim_type type
)
1338 #define TYPE isl_space
1339 #include "check_type_range_templ.c"
1341 /* Insert "n" dimensions of type "type" at position "pos".
1342 * If we are inserting parameters, then they are also inserted in
1343 * any nested spaces.
1345 __isl_give isl_space
*isl_space_insert_dims(__isl_take isl_space
*space
,
1346 enum isl_dim_type type
, unsigned pos
, unsigned n
)
1349 isl_id
**ids
= NULL
;
1354 return isl_space_reset(space
, type
);
1356 ctx
= isl_space_get_ctx(space
);
1357 if (!valid_dim_type(type
))
1358 isl_die(ctx
, isl_error_invalid
,
1359 "cannot insert dimensions of specified type",
1362 if (isl_space_check_range(space
, type
, pos
, 0) < 0)
1363 return isl_space_free(space
);
1365 space
= isl_space_cow(space
);
1370 enum isl_dim_type t
, o
= isl_dim_param
;
1373 ids
= isl_calloc_array(ctx
, isl_id
*,
1374 space
->nparam
+ space
->n_in
+ space
->n_out
+ n
);
1378 s
[isl_dim_param
- o
] = space
->nparam
;
1379 s
[isl_dim_in
- o
] = space
->n_in
;
1380 s
[isl_dim_out
- o
] = space
->n_out
;
1381 for (t
= isl_dim_param
; t
<= isl_dim_out
; ++t
) {
1383 get_ids(space
, t
, 0, s
[t
- o
], ids
+ off
);
1386 get_ids(space
, t
, 0, pos
, ids
+ off
);
1388 get_ids(space
, t
, pos
, s
[t
- o
] - pos
,
1390 off
+= s
[t
- o
] - pos
;
1395 space
->n_id
= space
->nparam
+ space
->n_in
+ space
->n_out
+ n
;
1398 case isl_dim_param
: space
->nparam
+= n
; break;
1399 case isl_dim_in
: space
->n_in
+= n
; break;
1400 case isl_dim_out
: space
->n_out
+= n
; break;
1403 space
= isl_space_reset(space
, type
);
1405 if (type
== isl_dim_param
) {
1406 if (space
&& space
->nested
[0] &&
1407 !(space
->nested
[0] = isl_space_insert_dims(space
->nested
[0],
1408 isl_dim_param
, pos
, n
)))
1410 if (space
&& space
->nested
[1] &&
1411 !(space
->nested
[1] = isl_space_insert_dims(space
->nested
[1],
1412 isl_dim_param
, pos
, n
)))
1418 isl_space_free(space
);
1422 __isl_give isl_space
*isl_space_move_dims(__isl_take isl_space
*space
,
1423 enum isl_dim_type dst_type
, unsigned dst_pos
,
1424 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1428 space
= isl_space_reset(space
, src_type
);
1429 space
= isl_space_reset(space
, dst_type
);
1435 if (isl_space_check_range(space
, src_type
, src_pos
, n
) < 0)
1436 return isl_space_free(space
);
1438 if (dst_type
== src_type
&& dst_pos
== src_pos
)
1441 isl_assert(space
->ctx
, dst_type
!= src_type
, goto error
);
1443 space
= isl_space_cow(space
);
1449 enum isl_dim_type t
, o
= isl_dim_param
;
1452 ids
= isl_calloc_array(space
->ctx
, isl_id
*,
1453 space
->nparam
+ space
->n_in
+ space
->n_out
);
1457 s
[isl_dim_param
- o
] = space
->nparam
;
1458 s
[isl_dim_in
- o
] = space
->n_in
;
1459 s
[isl_dim_out
- o
] = space
->n_out
;
1460 for (t
= isl_dim_param
; t
<= isl_dim_out
; ++t
) {
1461 if (t
== dst_type
) {
1462 get_ids(space
, t
, 0, dst_pos
, ids
+ off
);
1464 get_ids(space
, src_type
, src_pos
, n
, ids
+ off
);
1466 get_ids(space
, t
, dst_pos
, s
[t
- o
] - dst_pos
,
1468 off
+= s
[t
- o
] - dst_pos
;
1469 } else if (t
== src_type
) {
1470 get_ids(space
, t
, 0, src_pos
, ids
+ off
);
1472 get_ids(space
, t
, src_pos
+ n
,
1473 s
[t
- o
] - src_pos
- n
, ids
+ off
);
1474 off
+= s
[t
- o
] - src_pos
- n
;
1476 get_ids(space
, t
, 0, s
[t
- o
], ids
+ off
);
1482 space
->n_id
= space
->nparam
+ space
->n_in
+ space
->n_out
;
1486 case isl_dim_param
: space
->nparam
+= n
; break;
1487 case isl_dim_in
: space
->n_in
+= n
; break;
1488 case isl_dim_out
: space
->n_out
+= n
; break;
1493 case isl_dim_param
: space
->nparam
-= n
; break;
1494 case isl_dim_in
: space
->n_in
-= n
; break;
1495 case isl_dim_out
: space
->n_out
-= n
; break;
1499 if (dst_type
!= isl_dim_param
&& src_type
!= isl_dim_param
)
1502 for (i
= 0; i
< 2; ++i
) {
1505 if (!space
->nested
[i
])
1507 nested
= isl_space_take_nested(space
, i
);
1508 nested
= isl_space_replace_params(nested
, space
);
1509 space
= isl_space_restore_nested(space
, i
, nested
);
1516 isl_space_free(space
);
1520 /* Check that "space1" and "space2" have the same parameters,
1521 * reporting an error if they do not.
1523 isl_stat
isl_space_check_equal_params(__isl_keep isl_space
*space1
,
1524 __isl_keep isl_space
*space2
)
1528 equal
= isl_space_has_equal_params(space1
, space2
);
1530 return isl_stat_error
;
1532 isl_die(isl_space_get_ctx(space1
), isl_error_invalid
,
1533 "parameters need to match", return isl_stat_error
);
1537 __isl_give isl_space
*isl_space_join(__isl_take isl_space
*left
,
1538 __isl_take isl_space
*right
)
1542 if (isl_space_check_equal_params(left
, right
) < 0)
1545 isl_assert(left
->ctx
,
1546 isl_space_tuple_is_equal(left
, isl_dim_out
, right
, isl_dim_in
),
1549 space
= isl_space_alloc(left
->ctx
,
1550 left
->nparam
, left
->n_in
, right
->n_out
);
1554 space
= copy_ids(space
, isl_dim_param
, 0, left
, isl_dim_param
);
1555 space
= copy_ids(space
, isl_dim_in
, 0, left
, isl_dim_in
);
1556 space
= copy_ids(space
, isl_dim_out
, 0, right
, isl_dim_out
);
1558 if (space
&& left
->tuple_id
[0] &&
1559 !(space
->tuple_id
[0] = isl_id_copy(left
->tuple_id
[0])))
1561 if (space
&& right
->tuple_id
[1] &&
1562 !(space
->tuple_id
[1] = isl_id_copy(right
->tuple_id
[1])))
1564 if (space
&& left
->nested
[0] &&
1565 !(space
->nested
[0] = isl_space_copy(left
->nested
[0])))
1567 if (space
&& right
->nested
[1] &&
1568 !(space
->nested
[1] = isl_space_copy(right
->nested
[1])))
1571 isl_space_free(left
);
1572 isl_space_free(right
);
1576 isl_space_free(left
);
1577 isl_space_free(right
);
1581 /* Given two map spaces { A -> C } and { B -> D }, construct the space
1582 * { [A -> B] -> [C -> D] }.
1583 * Given two set spaces { A } and { B }, construct the space { [A -> B] }.
1585 __isl_give isl_space
*isl_space_product(__isl_take isl_space
*left
,
1586 __isl_take isl_space
*right
)
1588 isl_space
*dom1
, *dom2
, *nest1
, *nest2
;
1591 if (!left
|| !right
)
1594 is_set
= isl_space_is_set(left
);
1595 if (is_set
!= isl_space_is_set(right
))
1596 isl_die(isl_space_get_ctx(left
), isl_error_invalid
,
1597 "expecting either two set spaces or two map spaces",
1600 return isl_space_range_product(left
, right
);
1602 if (isl_space_check_equal_params(left
, right
) < 0)
1605 dom1
= isl_space_domain(isl_space_copy(left
));
1606 dom2
= isl_space_domain(isl_space_copy(right
));
1607 nest1
= isl_space_wrap(isl_space_join(isl_space_reverse(dom1
), dom2
));
1609 dom1
= isl_space_range(left
);
1610 dom2
= isl_space_range(right
);
1611 nest2
= isl_space_wrap(isl_space_join(isl_space_reverse(dom1
), dom2
));
1613 return isl_space_join(isl_space_reverse(nest1
), nest2
);
1615 isl_space_free(left
);
1616 isl_space_free(right
);
1620 /* Given two spaces { A -> C } and { B -> C }, construct the space
1623 __isl_give isl_space
*isl_space_domain_product(__isl_take isl_space
*left
,
1624 __isl_take isl_space
*right
)
1626 isl_space
*ran
, *dom1
, *dom2
, *nest
;
1628 if (isl_space_check_equal_params(left
, right
) < 0)
1631 if (!isl_space_tuple_is_equal(left
, isl_dim_out
, right
, isl_dim_out
))
1632 isl_die(left
->ctx
, isl_error_invalid
,
1633 "ranges need to match", goto error
);
1635 ran
= isl_space_range(isl_space_copy(left
));
1637 dom1
= isl_space_domain(left
);
1638 dom2
= isl_space_domain(right
);
1639 nest
= isl_space_wrap(isl_space_join(isl_space_reverse(dom1
), dom2
));
1641 return isl_space_join(isl_space_reverse(nest
), ran
);
1643 isl_space_free(left
);
1644 isl_space_free(right
);
1648 __isl_give isl_space
*isl_space_range_product(__isl_take isl_space
*left
,
1649 __isl_take isl_space
*right
)
1651 isl_space
*dom
, *ran1
, *ran2
, *nest
;
1653 if (isl_space_check_equal_params(left
, right
) < 0)
1656 if (!isl_space_tuple_is_equal(left
, isl_dim_in
, right
, isl_dim_in
))
1657 isl_die(left
->ctx
, isl_error_invalid
,
1658 "domains need to match", goto error
);
1660 dom
= isl_space_domain(isl_space_copy(left
));
1662 ran1
= isl_space_range(left
);
1663 ran2
= isl_space_range(right
);
1664 nest
= isl_space_wrap(isl_space_join(isl_space_reverse(ran1
), ran2
));
1666 return isl_space_join(isl_space_reverse(dom
), nest
);
1668 isl_space_free(left
);
1669 isl_space_free(right
);
1673 /* Given a space of the form [A -> B] -> C, return the space A -> C.
1675 __isl_give isl_space
*isl_space_domain_factor_domain(
1676 __isl_take isl_space
*space
)
1681 if (isl_space_check_domain_is_wrapping(space
) < 0)
1682 return isl_space_free(space
);
1684 nested
= space
->nested
[0];
1685 domain
= isl_space_copy(space
);
1686 domain
= isl_space_drop_dims(domain
, isl_dim_in
,
1687 nested
->n_in
, nested
->n_out
);
1689 return isl_space_free(space
);
1690 if (nested
->tuple_id
[0]) {
1691 domain
->tuple_id
[0] = isl_id_copy(nested
->tuple_id
[0]);
1692 if (!domain
->tuple_id
[0])
1695 if (nested
->nested
[0]) {
1696 domain
->nested
[0] = isl_space_copy(nested
->nested
[0]);
1697 if (!domain
->nested
[0])
1701 isl_space_free(space
);
1704 isl_space_free(space
);
1705 isl_space_free(domain
);
1709 /* Given a space of the form [A -> B] -> C, return the space B -> C.
1711 __isl_give isl_space
*isl_space_domain_factor_range(
1712 __isl_take isl_space
*space
)
1717 if (isl_space_check_domain_is_wrapping(space
) < 0)
1718 return isl_space_free(space
);
1720 nested
= space
->nested
[0];
1721 range
= isl_space_copy(space
);
1722 range
= isl_space_drop_dims(range
, isl_dim_in
, 0, nested
->n_in
);
1724 return isl_space_free(space
);
1725 if (nested
->tuple_id
[1]) {
1726 range
->tuple_id
[0] = isl_id_copy(nested
->tuple_id
[1]);
1727 if (!range
->tuple_id
[0])
1730 if (nested
->nested
[1]) {
1731 range
->nested
[0] = isl_space_copy(nested
->nested
[1]);
1732 if (!range
->nested
[0])
1736 isl_space_free(space
);
1739 isl_space_free(space
);
1740 isl_space_free(range
);
1744 /* Internal function that selects the domain of the map that is
1745 * embedded in either a set space or the range of a map space.
1746 * In particular, given a space of the form [A -> B], return the space A.
1747 * Given a space of the form A -> [B -> C], return the space A -> B.
1749 static __isl_give isl_space
*range_factor_domain(__isl_take isl_space
*space
)
1757 nested
= space
->nested
[1];
1758 domain
= isl_space_copy(space
);
1759 domain
= isl_space_drop_dims(domain
, isl_dim_out
,
1760 nested
->n_in
, nested
->n_out
);
1762 return isl_space_free(space
);
1763 if (nested
->tuple_id
[0]) {
1764 domain
->tuple_id
[1] = isl_id_copy(nested
->tuple_id
[0]);
1765 if (!domain
->tuple_id
[1])
1768 if (nested
->nested
[0]) {
1769 domain
->nested
[1] = isl_space_copy(nested
->nested
[0]);
1770 if (!domain
->nested
[1])
1774 isl_space_free(space
);
1777 isl_space_free(space
);
1778 isl_space_free(domain
);
1782 /* Given a space of the form A -> [B -> C], return the space A -> B.
1784 __isl_give isl_space
*isl_space_range_factor_domain(
1785 __isl_take isl_space
*space
)
1787 if (isl_space_check_range_is_wrapping(space
) < 0)
1788 return isl_space_free(space
);
1790 return range_factor_domain(space
);
1793 /* Given a space of the form [A -> B], return the space A.
1795 static __isl_give isl_space
*set_factor_domain(__isl_take isl_space
*space
)
1799 if (!isl_space_is_wrapping(space
))
1800 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
1801 "not a product", return isl_space_free(space
));
1803 return range_factor_domain(space
);
1806 /* Given a space of the form [A -> B] -> [C -> D], return the space A -> C.
1807 * Given a space of the form [A -> B], return the space A.
1809 __isl_give isl_space
*isl_space_factor_domain(__isl_take isl_space
*space
)
1813 if (isl_space_is_set(space
))
1814 return set_factor_domain(space
);
1815 space
= isl_space_domain_factor_domain(space
);
1816 space
= isl_space_range_factor_domain(space
);
1820 /* Internal function that selects the range of the map that is
1821 * embedded in either a set space or the range of a map space.
1822 * In particular, given a space of the form [A -> B], return the space B.
1823 * Given a space of the form A -> [B -> C], return the space A -> C.
1825 static __isl_give isl_space
*range_factor_range(__isl_take isl_space
*space
)
1833 nested
= space
->nested
[1];
1834 range
= isl_space_copy(space
);
1835 range
= isl_space_drop_dims(range
, isl_dim_out
, 0, nested
->n_in
);
1837 return isl_space_free(space
);
1838 if (nested
->tuple_id
[1]) {
1839 range
->tuple_id
[1] = isl_id_copy(nested
->tuple_id
[1]);
1840 if (!range
->tuple_id
[1])
1843 if (nested
->nested
[1]) {
1844 range
->nested
[1] = isl_space_copy(nested
->nested
[1]);
1845 if (!range
->nested
[1])
1849 isl_space_free(space
);
1852 isl_space_free(space
);
1853 isl_space_free(range
);
1857 /* Given a space of the form A -> [B -> C], return the space A -> C.
1859 __isl_give isl_space
*isl_space_range_factor_range(
1860 __isl_take isl_space
*space
)
1862 if (isl_space_check_range_is_wrapping(space
) < 0)
1863 return isl_space_free(space
);
1865 return range_factor_range(space
);
1868 /* Given a space of the form [A -> B], return the space B.
1870 static __isl_give isl_space
*set_factor_range(__isl_take isl_space
*space
)
1874 if (!isl_space_is_wrapping(space
))
1875 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
1876 "not a product", return isl_space_free(space
));
1878 return range_factor_range(space
);
1881 /* Given a space of the form [A -> B] -> [C -> D], return the space B -> D.
1882 * Given a space of the form [A -> B], return the space B.
1884 __isl_give isl_space
*isl_space_factor_range(__isl_take isl_space
*space
)
1888 if (isl_space_is_set(space
))
1889 return set_factor_range(space
);
1890 space
= isl_space_domain_factor_range(space
);
1891 space
= isl_space_range_factor_range(space
);
1895 /* Given a space of the form [A -> B] -> C, return the space A.
1897 __isl_give isl_space
*isl_space_domain_wrapped_domain(
1898 __isl_take isl_space
*space
)
1900 return isl_space_factor_domain(isl_space_domain(space
));
1903 /* Given a space of the form [A -> B] -> C, return the space B.
1905 __isl_give isl_space
*isl_space_domain_wrapped_range(
1906 __isl_take isl_space
*space
)
1908 return isl_space_factor_range(isl_space_domain(space
));
1911 /* Given a space of the form A -> [B -> C], return the space B.
1913 __isl_give isl_space
*isl_space_range_wrapped_domain(
1914 __isl_take isl_space
*space
)
1916 return isl_space_factor_domain(isl_space_range(space
));
1919 /* Given a space of the form A -> [B -> C], return the space C.
1921 __isl_give isl_space
*isl_space_range_wrapped_range(
1922 __isl_take isl_space
*space
)
1924 return isl_space_factor_range(isl_space_range(space
));
1927 __isl_give isl_space
*isl_space_map_from_set(__isl_take isl_space
*space
)
1930 isl_id
**ids
= NULL
;
1935 ctx
= isl_space_get_ctx(space
);
1936 if (!isl_space_is_set(space
))
1937 isl_die(ctx
, isl_error_invalid
, "not a set space", goto error
);
1938 space
= isl_space_cow(space
);
1941 n_id
= space
->nparam
+ space
->n_out
+ space
->n_out
;
1942 if (n_id
> 0 && space
->ids
) {
1943 ids
= isl_calloc_array(space
->ctx
, isl_id
*, n_id
);
1946 get_ids(space
, isl_dim_param
, 0, space
->nparam
, ids
);
1947 get_ids(space
, isl_dim_out
, 0, space
->n_out
,
1948 ids
+ space
->nparam
);
1950 space
->n_in
= space
->n_out
;
1955 space
= copy_ids(space
, isl_dim_out
, 0, space
, isl_dim_in
);
1957 isl_id_free(space
->tuple_id
[0]);
1958 space
->tuple_id
[0] = isl_id_copy(space
->tuple_id
[1]);
1959 isl_space_free(space
->nested
[0]);
1960 space
->nested
[0] = isl_space_copy(space
->nested
[1]);
1963 isl_space_free(space
);
1967 __isl_give isl_space
*isl_space_map_from_domain_and_range(
1968 __isl_take isl_space
*domain
, __isl_take isl_space
*range
)
1970 if (!domain
|| !range
)
1972 if (!isl_space_is_set(domain
))
1973 isl_die(isl_space_get_ctx(domain
), isl_error_invalid
,
1974 "domain is not a set space", goto error
);
1975 if (!isl_space_is_set(range
))
1976 isl_die(isl_space_get_ctx(range
), isl_error_invalid
,
1977 "range is not a set space", goto error
);
1978 return isl_space_join(isl_space_reverse(domain
), range
);
1980 isl_space_free(domain
);
1981 isl_space_free(range
);
1985 static __isl_give isl_space
*set_ids(__isl_take isl_space
*space
,
1986 enum isl_dim_type type
,
1987 unsigned first
, unsigned n
, __isl_take isl_id
**ids
)
1991 for (i
= 0; i
< n
; ++i
)
1992 space
= set_id(space
, type
, first
+ i
, ids
[i
]);
1997 __isl_give isl_space
*isl_space_reverse(__isl_take isl_space
*space
)
2002 isl_id
**ids
= NULL
;
2005 equal
= match(space
, isl_dim_in
, space
, isl_dim_out
);
2007 return isl_space_free(space
);
2011 space
= isl_space_cow(space
);
2015 id
= space
->tuple_id
[0];
2016 space
->tuple_id
[0] = space
->tuple_id
[1];
2017 space
->tuple_id
[1] = id
;
2019 nested
= space
->nested
[0];
2020 space
->nested
[0] = space
->nested
[1];
2021 space
->nested
[1] = nested
;
2024 int n_id
= space
->n_in
+ space
->n_out
;
2025 ids
= isl_alloc_array(space
->ctx
, isl_id
*, n_id
);
2028 get_ids(space
, isl_dim_in
, 0, space
->n_in
, ids
);
2029 get_ids(space
, isl_dim_out
, 0, space
->n_out
, ids
+ space
->n_in
);
2033 space
->n_in
= space
->n_out
;
2037 space
= set_ids(space
, isl_dim_out
, 0, space
->n_out
, ids
);
2038 space
= set_ids(space
, isl_dim_in
, 0, space
->n_in
,
2039 ids
+ space
->n_out
);
2046 isl_space_free(space
);
2050 /* Given a space where the tuple of type "type" is a wrapped map space,
2051 * swap domain and range of that wrapped space.
2053 * If the tuple is named, then the name is only preserved
2054 * if the nested tuples are equal, in which case the output
2055 * of this function is identical to the input, except possibly
2056 * for the dimension identifiers.
2058 * Make a reasonable attempt at moving the dimension identifiers
2059 * along with the tuples.
2061 __isl_give isl_space
*isl_space_reverse_wrapped(__isl_take isl_space
*space
,
2062 enum isl_dim_type type
)
2064 int pos
= type
- isl_dim_in
;
2069 nested
= isl_space_peek_nested(space
, pos
);
2070 equal
= isl_space_tuple_is_equal(nested
, isl_dim_in
,
2071 nested
, isl_dim_out
);
2073 return isl_space_free(space
);
2075 nested
= isl_space_take_nested(space
, pos
);
2076 nested
= isl_space_reverse(nested
);
2077 space
= isl_space_restore_nested(space
, pos
, nested
);
2079 space
= isl_space_reset_tuple_id(space
, type
);
2080 nested
= isl_space_peek_nested(space
, pos
);
2081 n_in
= isl_space_dim(nested
, isl_dim_in
);
2083 return isl_space_free(space
);
2084 space
= copy_ids(space
, type
, 0, nested
, isl_dim_in
);
2085 space
= copy_ids(space
, type
, n_in
, nested
, isl_dim_out
);
2090 /* Given a space (A -> B), return the corresponding space
2093 * If the domain tuple is named, then the name is only preserved
2094 * if A and B are equal tuples, in which case the output
2095 * of this function is identical to the input, except possibly
2096 * for the dimension identifiers.
2098 __isl_give isl_space
*isl_space_wrapped_reverse(__isl_take isl_space
*space
)
2100 if (isl_space_check_is_wrapping(space
) < 0)
2101 return isl_space_free(space
);
2102 space
= isl_space_reverse_wrapped(space
, isl_dim_set
);
2107 /* Given a space (A -> B) -> C, return the corresponding space
2110 * If the domain tuple is named, then the name is only preserved
2111 * if A and B are equal tuples, in which case the output
2112 * of this function is identical to the input, except possibly
2113 * for the dimension identifiers.
2115 __isl_give isl_space
*isl_space_domain_reverse(__isl_take isl_space
*space
)
2117 if (isl_space_check_domain_is_wrapping(space
) < 0)
2118 return isl_space_free(space
);
2119 space
= isl_space_reverse_wrapped(space
, isl_dim_in
);
2124 /* Given a space A -> (B -> C), return the corresponding space
2127 * If the range tuple is named, then the name is only preserved
2128 * if B and C are equal tuples, in which case the output
2129 * of this function is identical to the input, except possibly
2130 * for the dimension identifiers.
2132 __isl_give isl_space
*isl_space_range_reverse(__isl_take isl_space
*space
)
2134 if (isl_space_check_range_is_wrapping(space
) < 0)
2135 return isl_space_free(space
);
2136 space
= isl_space_reverse_wrapped(space
, isl_dim_out
);
2141 __isl_give isl_space
*isl_space_drop_dims(__isl_take isl_space
*space
,
2142 enum isl_dim_type type
, unsigned first
, unsigned num
)
2150 return isl_space_reset(space
, type
);
2152 if (!valid_dim_type(type
))
2153 isl_die(space
->ctx
, isl_error_invalid
,
2154 "cannot drop dimensions of specified type", goto error
);
2156 if (isl_space_check_range(space
, type
, first
, num
) < 0)
2157 return isl_space_free(space
);
2158 space
= isl_space_cow(space
);
2162 space
= extend_ids(space
);
2165 for (i
= 0; i
< num
; ++i
)
2166 isl_id_free(get_id(space
, type
, first
+ i
));
2167 for (i
= first
+num
; i
< n(space
, type
); ++i
)
2168 set_id(space
, type
, i
- num
, get_id(space
, type
, i
));
2171 get_ids(space
, isl_dim_in
, 0, space
->n_in
,
2172 space
->ids
+ offset(space
, isl_dim_in
) - num
);
2174 get_ids(space
, isl_dim_out
, 0, space
->n_out
,
2175 space
->ids
+ offset(space
, isl_dim_out
) - num
);
2182 case isl_dim_param
: space
->nparam
-= num
; break;
2183 case isl_dim_in
: space
->n_in
-= num
; break;
2184 case isl_dim_out
: space
->n_out
-= num
; break;
2187 space
= isl_space_reset(space
, type
);
2188 if (type
== isl_dim_param
) {
2189 if (space
&& space
->nested
[0] &&
2190 !(space
->nested
[0] = isl_space_drop_dims(space
->nested
[0],
2191 isl_dim_param
, first
, num
)))
2193 if (space
&& space
->nested
[1] &&
2194 !(space
->nested
[1] = isl_space_drop_dims(space
->nested
[1],
2195 isl_dim_param
, first
, num
)))
2200 isl_space_free(space
);
2204 __isl_give isl_space
*isl_space_drop_inputs(__isl_take isl_space
*space
,
2205 unsigned first
, unsigned n
)
2209 return isl_space_drop_dims(space
, isl_dim_in
, first
, n
);
2212 __isl_give isl_space
*isl_space_drop_outputs(__isl_take isl_space
*space
,
2213 unsigned first
, unsigned n
)
2217 return isl_space_drop_dims(space
, isl_dim_out
, first
, n
);
2220 /* Remove all parameters from "space".
2222 __isl_give isl_space
*isl_space_drop_all_params(__isl_take isl_space
*space
)
2226 nparam
= isl_space_dim(space
, isl_dim_param
);
2228 return isl_space_free(space
);
2229 return isl_space_drop_dims(space
, isl_dim_param
, 0, nparam
);
2232 __isl_give isl_space
*isl_space_domain(__isl_take isl_space
*space
)
2236 space
= isl_space_drop_dims(space
, isl_dim_out
, 0, space
->n_out
);
2237 space
= isl_space_reverse(space
);
2238 space
= mark_as_set(space
);
2242 __isl_give isl_space
*isl_space_from_domain(__isl_take isl_space
*space
)
2246 if (!isl_space_is_set(space
))
2247 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
2248 "not a set space", goto error
);
2249 space
= isl_space_reverse(space
);
2250 space
= isl_space_reset(space
, isl_dim_out
);
2253 isl_space_free(space
);
2257 __isl_give isl_space
*isl_space_range(__isl_take isl_space
*space
)
2261 space
= isl_space_drop_dims(space
, isl_dim_in
, 0, space
->n_in
);
2262 space
= mark_as_set(space
);
2266 __isl_give isl_space
*isl_space_from_range(__isl_take isl_space
*space
)
2270 if (!isl_space_is_set(space
))
2271 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
2272 "not a set space", goto error
);
2273 return isl_space_reset(space
, isl_dim_in
);
2275 isl_space_free(space
);
2279 /* Given a map space A -> B, return the map space [A -> B] -> A.
2281 __isl_give isl_space
*isl_space_domain_map(__isl_take isl_space
*space
)
2285 domain
= isl_space_from_range(isl_space_domain(isl_space_copy(space
)));
2286 space
= isl_space_from_domain(isl_space_wrap(space
));
2287 space
= isl_space_join(space
, domain
);
2292 /* Given a map space A -> B, return the map space [A -> B] -> B.
2294 __isl_give isl_space
*isl_space_range_map(__isl_take isl_space
*space
)
2298 range
= isl_space_from_range(isl_space_range(isl_space_copy(space
)));
2299 space
= isl_space_from_domain(isl_space_wrap(space
));
2300 space
= isl_space_join(space
, range
);
2305 __isl_give isl_space
*isl_space_params(__isl_take isl_space
*space
)
2307 isl_size n_in
, n_out
;
2309 if (isl_space_is_params(space
))
2311 n_in
= isl_space_dim(space
, isl_dim_in
);
2312 n_out
= isl_space_dim(space
, isl_dim_out
);
2313 if (n_in
< 0 || n_out
< 0)
2314 return isl_space_free(space
);
2315 space
= isl_space_drop_dims(space
, isl_dim_in
, 0, n_in
);
2316 space
= isl_space_drop_dims(space
, isl_dim_out
, 0, n_out
);
2317 space
= mark_as_params(space
);
2321 __isl_give isl_space
*isl_space_set_from_params(__isl_take isl_space
*space
)
2325 if (!isl_space_is_params(space
))
2326 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
2327 "not a parameter space", goto error
);
2328 return isl_space_reset(space
, isl_dim_set
);
2330 isl_space_free(space
);
2334 /* Add an unnamed tuple of dimension "dim" to "space".
2335 * This requires "space" to be a parameter or set space.
2337 * In particular, if "space" is a parameter space, then return
2338 * a set space with the given dimension.
2339 * If "space" is a set space, then return a map space
2340 * with "space" as domain and a range of the given dimension.
2342 __isl_give isl_space
*isl_space_add_unnamed_tuple_ui(
2343 __isl_take isl_space
*space
, unsigned dim
)
2345 isl_bool is_params
, is_set
;
2347 is_params
= isl_space_is_params(space
);
2348 is_set
= isl_space_is_set(space
);
2349 if (is_params
< 0 || is_set
< 0)
2350 return isl_space_free(space
);
2351 if (!is_params
&& !is_set
)
2352 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
2353 "cannot add tuple to map space",
2354 return isl_space_free(space
));
2356 space
= isl_space_set_from_params(space
);
2358 space
= isl_space_from_domain(space
);
2359 space
= isl_space_add_dims(space
, isl_dim_out
, dim
);
2363 /* Add a tuple of dimension "dim" and with tuple identifier "tuple_id"
2365 * This requires "space" to be a parameter or set space.
2367 __isl_give isl_space
*isl_space_add_named_tuple_id_ui(
2368 __isl_take isl_space
*space
, __isl_take isl_id
*tuple_id
, unsigned dim
)
2370 space
= isl_space_add_unnamed_tuple_ui(space
, dim
);
2371 space
= isl_space_set_tuple_id(space
, isl_dim_out
, tuple_id
);
2375 /* Check that the identifiers in "tuple" do not appear as parameters
2378 static isl_stat
check_fresh_params(__isl_keep isl_space
*space
,
2379 __isl_keep isl_multi_id
*tuple
)
2384 n
= isl_multi_id_size(tuple
);
2386 return isl_stat_error
;
2387 for (i
= 0; i
< n
; ++i
) {
2391 id
= isl_multi_id_get_at(tuple
, i
);
2393 return isl_stat_error
;
2394 pos
= isl_space_find_dim_by_id(space
, isl_dim_param
, id
);
2397 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
2398 "parameters not unique", return isl_stat_error
);
2404 /* Add the identifiers in "tuple" as parameters of "space"
2405 * that are known to be fresh.
2407 static __isl_give isl_space
*add_bind_params(__isl_take isl_space
*space
,
2408 __isl_keep isl_multi_id
*tuple
)
2413 first
= isl_space_dim(space
, isl_dim_param
);
2414 n
= isl_multi_id_size(tuple
);
2415 if (first
< 0 || n
< 0)
2416 return isl_space_free(space
);
2417 space
= isl_space_add_dims(space
, isl_dim_param
, n
);
2418 for (i
= 0; i
< n
; ++i
) {
2421 id
= isl_multi_id_get_at(tuple
, i
);
2422 space
= isl_space_set_dim_id(space
,
2423 isl_dim_param
, first
+ i
, id
);
2429 /* Internal function that removes the set tuple of "space",
2430 * which is assumed to correspond to the range space of "tuple", and
2431 * adds the identifiers in "tuple" as fresh parameters.
2432 * In other words, the set dimensions of "space" are reinterpreted
2433 * as parameters, but stay in the same global positions.
2435 __isl_give isl_space
*isl_space_bind_set(__isl_take isl_space
*space
,
2436 __isl_keep isl_multi_id
*tuple
)
2438 isl_space
*tuple_space
;
2440 if (isl_space_check_is_proper_set(space
) < 0)
2441 return isl_space_free(space
);
2442 tuple_space
= isl_multi_id_peek_space(tuple
);
2443 if (isl_space_check_equal_tuples(tuple_space
, space
) < 0)
2444 return isl_space_free(space
);
2445 if (check_fresh_params(space
, tuple
) < 0)
2446 return isl_space_free(space
);
2447 space
= isl_space_params(space
);
2448 space
= add_bind_params(space
, tuple
);
2452 /* Internal function that removes the domain tuple of the map space "space",
2453 * which is assumed to correspond to the range space of "tuple", and
2454 * adds the identifiers in "tuple" as fresh parameters.
2455 * In other words, the domain dimensions of "space" are reinterpreted
2456 * as parameters, but stay in the same global positions.
2458 __isl_give isl_space
*isl_space_bind_map_domain(__isl_take isl_space
*space
,
2459 __isl_keep isl_multi_id
*tuple
)
2461 isl_space
*tuple_space
;
2463 if (isl_space_check_is_map(space
) < 0)
2464 return isl_space_free(space
);
2465 tuple_space
= isl_multi_id_peek_space(tuple
);
2466 if (isl_space_check_domain_tuples(tuple_space
, space
) < 0)
2467 return isl_space_free(space
);
2468 if (check_fresh_params(space
, tuple
) < 0)
2469 return isl_space_free(space
);
2470 space
= isl_space_range(space
);
2471 space
= add_bind_params(space
, tuple
);
2475 /* Internal function that, given a space of the form [A -> B] -> C and
2476 * a tuple of identifiers in A, returns a space B -> C with
2477 * the identifiers in "tuple" added as fresh parameters.
2478 * In other words, the domain dimensions of the wrapped relation
2479 * in the domain of "space" are reinterpreted
2480 * as parameters, but stay in the same global positions.
2482 __isl_give isl_space
*isl_space_bind_domain_wrapped_domain(
2483 __isl_take isl_space
*space
, __isl_keep isl_multi_id
*tuple
)
2485 isl_space
*tuple_space
;
2487 if (isl_space_check_is_map(space
) < 0)
2488 return isl_space_free(space
);
2489 tuple_space
= isl_multi_id_peek_space(tuple
);
2490 if (isl_space_check_domain_wrapped_domain_tuples(tuple_space
,
2492 return isl_space_free(space
);
2493 if (check_fresh_params(space
, tuple
) < 0)
2494 return isl_space_free(space
);
2495 space
= isl_space_domain_factor_range(space
);
2496 space
= add_bind_params(space
, tuple
);
2500 /* Insert a domain tuple in "space" corresponding to the set space "domain".
2501 * In particular, if "space" is a parameter space, then the result
2502 * is the set space "domain" combined with the parameters of "space".
2503 * If "space" is a set space, then the result
2504 * is a map space with "domain" as domain and the original space as range.
2506 static __isl_give isl_space
*isl_space_insert_domain(
2507 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
2511 domain
= isl_space_replace_params(domain
, space
);
2513 is_params
= isl_space_is_params(space
);
2514 if (is_params
< 0) {
2515 isl_space_free(domain
);
2516 space
= isl_space_free(space
);
2517 } else if (is_params
) {
2518 isl_space_free(space
);
2521 space
= isl_space_map_from_domain_and_range(domain
, space
);
2526 /* Internal function that introduces a domain in "space"
2527 * corresponding to the range space of "tuple".
2528 * In particular, if "space" is a parameter space, then the result
2529 * is a set space. If "space" is a set space, then the result
2530 * is a map space with the original space as range.
2531 * Parameters that correspond to the identifiers in "tuple" are removed.
2533 * The parameters are removed in reverse order (under the assumption
2534 * that they appear in the same order in "multi") because
2535 * it is slightly more efficient to remove parameters at the end.
2537 * For pretty-printing purposes, the identifiers of the set dimensions
2538 * of the introduced domain are set to the identifiers in "tuple".
2540 __isl_give isl_space
*isl_space_unbind_params_insert_domain(
2541 __isl_take isl_space
*space
, __isl_keep isl_multi_id
*tuple
)
2545 isl_space
*tuple_space
;
2547 n
= isl_multi_id_size(tuple
);
2548 if (!space
|| n
< 0)
2549 return isl_space_free(space
);
2550 for (i
= n
- 1; i
>= 0; --i
) {
2554 id
= isl_multi_id_get_id(tuple
, i
);
2556 return isl_space_free(space
);
2557 pos
= isl_space_find_dim_by_id(space
, isl_dim_param
, id
);
2561 space
= isl_space_drop_dims(space
, isl_dim_param
, pos
, 1);
2563 tuple_space
= isl_multi_id_get_space(tuple
);
2564 for (i
= 0; i
< n
; ++i
) {
2567 id
= isl_multi_id_get_id(tuple
, i
);
2568 tuple_space
= isl_space_set_dim_id(tuple_space
,
2569 isl_dim_set
, i
, id
);
2571 return isl_space_insert_domain(space
, tuple_space
);
2574 __isl_give isl_space
*isl_space_underlying(__isl_take isl_space
*space
,
2580 is_set
= isl_space_is_set(space
);
2582 return isl_space_free(space
);
2583 if (n_div
== 0 && is_set
&&
2584 space
->nparam
== 0 && space
->n_in
== 0 && space
->n_id
== 0)
2585 return isl_space_reset(space
, isl_dim_out
);
2586 space
= isl_space_cow(space
);
2589 space
->n_out
+= space
->nparam
+ space
->n_in
+ n_div
;
2593 for (i
= 0; i
< space
->n_id
; ++i
)
2594 isl_id_free(get_id(space
, isl_dim_out
, i
));
2596 space
= isl_space_reset(space
, isl_dim_in
);
2597 space
= isl_space_reset(space
, isl_dim_out
);
2598 space
= mark_as_set(space
);
2603 /* Are the two spaces the same, including positions and names of parameters?
2605 isl_bool
isl_space_is_equal(__isl_keep isl_space
*space1
,
2606 __isl_keep isl_space
*space2
)
2610 if (!space1
|| !space2
)
2611 return isl_bool_error
;
2612 if (space1
== space2
)
2613 return isl_bool_true
;
2614 equal
= isl_space_has_equal_params(space1
, space2
);
2615 if (equal
< 0 || !equal
)
2617 return isl_space_has_equal_tuples(space1
, space2
);
2620 /* Do the tuples of "space1" correspond to those of the domain of "space2"?
2621 * That is, is "space1" equal to the domain of "space2", ignoring parameters.
2623 * "space2" is allowed to be a set space, in which case "space1"
2624 * should be a parameter space.
2626 isl_bool
isl_space_has_domain_tuples(__isl_keep isl_space
*space1
,
2627 __isl_keep isl_space
*space2
)
2631 is_set
= isl_space_is_set(space1
);
2632 if (is_set
< 0 || !is_set
)
2634 return isl_space_tuple_is_equal(space1
, isl_dim_set
,
2635 space2
, isl_dim_in
);
2638 /* Do the tuples of "space1" correspond to those of the range of "space2"?
2639 * That is, is "space1" equal to the range of "space2", ignoring parameters.
2641 * "space2" is allowed to be the space of a set,
2642 * in which case it should be equal to "space1", ignoring parameters.
2644 isl_bool
isl_space_has_range_tuples(__isl_keep isl_space
*space1
,
2645 __isl_keep isl_space
*space2
)
2649 is_set
= isl_space_is_set(space1
);
2650 if (is_set
< 0 || !is_set
)
2652 return isl_space_tuple_is_equal(space1
, isl_dim_set
,
2653 space2
, isl_dim_out
);
2656 /* Check that the tuples of "space1" correspond to those
2657 * of the domain of "space2".
2658 * That is, check that "space1" is equal to the domain of "space2",
2659 * ignoring parameters.
2661 isl_stat
isl_space_check_domain_tuples(__isl_keep isl_space
*space1
,
2662 __isl_keep isl_space
*space2
)
2666 is_equal
= isl_space_has_domain_tuples(space1
, space2
);
2667 return check_match(space1
, is_equal
);
2670 /* Check that the tuples of "space1" correspond to those
2671 * of the domain of the wrapped relation in the domain of "space2".
2672 * That is, check that "space1" is equal to this domain,
2673 * ignoring parameters.
2675 isl_stat
isl_space_check_domain_wrapped_domain_tuples(
2676 __isl_keep isl_space
*space1
, __isl_keep isl_space
*space2
)
2681 domain
= isl_space_unwrap(isl_space_domain(isl_space_copy(space2
)));
2682 r
= isl_space_check_domain_tuples(space1
, domain
);
2683 isl_space_free(domain
);
2688 /* Is space1 equal to the domain of space2?
2690 * In the internal version we also allow space2 to be the space of a set,
2691 * provided space1 is a parameter space.
2693 isl_bool
isl_space_is_domain_internal(__isl_keep isl_space
*space1
,
2694 __isl_keep isl_space
*space2
)
2696 isl_bool equal_params
;
2698 if (!space1
|| !space2
)
2699 return isl_bool_error
;
2700 equal_params
= isl_space_has_equal_params(space1
, space2
);
2701 if (equal_params
< 0 || !equal_params
)
2702 return equal_params
;
2703 return isl_space_has_domain_tuples(space1
, space2
);
2706 /* Is space1 equal to the domain of space2?
2708 isl_bool
isl_space_is_domain(__isl_keep isl_space
*space1
,
2709 __isl_keep isl_space
*space2
)
2712 return isl_bool_error
;
2713 if (!isl_space_is_map(space2
))
2714 return isl_bool_false
;
2715 return isl_space_is_domain_internal(space1
, space2
);
2718 /* Is space1 equal to the range of space2?
2720 * In the internal version, space2 is allowed to be the space of a set,
2721 * in which case it should be equal to space1.
2723 isl_bool
isl_space_is_range_internal(__isl_keep isl_space
*space1
,
2724 __isl_keep isl_space
*space2
)
2726 isl_bool equal_params
;
2728 if (!space1
|| !space2
)
2729 return isl_bool_error
;
2730 equal_params
= isl_space_has_equal_params(space1
, space2
);
2731 if (equal_params
< 0 || !equal_params
)
2732 return equal_params
;
2733 return isl_space_has_range_tuples(space1
, space2
);
2736 /* Is space1 equal to the range of space2?
2738 isl_bool
isl_space_is_range(__isl_keep isl_space
*space1
,
2739 __isl_keep isl_space
*space2
)
2742 return isl_bool_error
;
2743 if (!isl_space_is_map(space2
))
2744 return isl_bool_false
;
2745 return isl_space_is_range_internal(space1
, space2
);
2748 /* Update "hash" by hashing in the parameters of "space".
2750 static uint32_t isl_hash_params(uint32_t hash
, __isl_keep isl_space
*space
)
2758 isl_hash_byte(hash
, space
->nparam
% 256);
2760 for (i
= 0; i
< space
->nparam
; ++i
) {
2761 id
= get_id(space
, isl_dim_param
, i
);
2762 hash
= isl_hash_id(hash
, id
);
2768 /* Update "hash" by hashing in the tuples of "space".
2769 * Changes in this function should be reflected in isl_hash_tuples_domain.
2771 static uint32_t isl_hash_tuples(uint32_t hash
, __isl_keep isl_space
*space
)
2778 isl_hash_byte(hash
, space
->n_in
% 256);
2779 isl_hash_byte(hash
, space
->n_out
% 256);
2781 id
= tuple_id(space
, isl_dim_in
);
2782 hash
= isl_hash_id(hash
, id
);
2783 id
= tuple_id(space
, isl_dim_out
);
2784 hash
= isl_hash_id(hash
, id
);
2786 hash
= isl_hash_tuples(hash
, space
->nested
[0]);
2787 hash
= isl_hash_tuples(hash
, space
->nested
[1]);
2792 /* Update "hash" by hashing in the domain tuple of "space".
2793 * The result of this function is equal to the result of applying
2794 * isl_hash_tuples to the domain of "space".
2796 static uint32_t isl_hash_tuples_domain(uint32_t hash
,
2797 __isl_keep isl_space
*space
)
2804 isl_hash_byte(hash
, 0);
2805 isl_hash_byte(hash
, space
->n_in
% 256);
2807 hash
= isl_hash_id(hash
, &isl_id_none
);
2808 id
= tuple_id(space
, isl_dim_in
);
2809 hash
= isl_hash_id(hash
, id
);
2811 hash
= isl_hash_tuples(hash
, space
->nested
[0]);
2816 /* Return a hash value that digests the tuples of "space",
2817 * i.e., that ignores the parameters.
2818 * Changes in this function should be reflected
2819 * in isl_space_get_tuple_domain_hash.
2821 uint32_t isl_space_get_tuple_hash(__isl_keep isl_space
*space
)
2828 hash
= isl_hash_init();
2829 hash
= isl_hash_tuples(hash
, space
);
2834 /* Return the hash value of "space".
2836 uint32_t isl_space_get_full_hash(__isl_keep isl_space
*space
)
2843 hash
= isl_hash_init();
2844 hash
= isl_hash_params(hash
, space
);
2845 hash
= isl_hash_tuples(hash
, space
);
2850 /* Return the hash value of the domain tuple of "space".
2851 * That is, isl_space_get_tuple_domain_hash(space) is equal to
2852 * isl_space_get_tuple_hash(isl_space_domain(space)).
2854 uint32_t isl_space_get_tuple_domain_hash(__isl_keep isl_space
*space
)
2861 hash
= isl_hash_init();
2862 hash
= isl_hash_tuples_domain(hash
, space
);
2867 /* Is "space" the space of a set wrapping a map space?
2869 isl_bool
isl_space_is_wrapping(__isl_keep isl_space
*space
)
2872 return isl_bool_error
;
2874 if (!isl_space_is_set(space
))
2875 return isl_bool_false
;
2877 return isl_bool_ok(space
->nested
[1] != NULL
);
2880 /* Is "space" the space of a map where the domain is a wrapped map space?
2882 isl_bool
isl_space_domain_is_wrapping(__isl_keep isl_space
*space
)
2885 return isl_bool_error
;
2887 if (isl_space_is_set(space
))
2888 return isl_bool_false
;
2890 return isl_bool_ok(space
->nested
[0] != NULL
);
2893 /* Is "space" the space of a map where the range is a wrapped map space?
2895 isl_bool
isl_space_range_is_wrapping(__isl_keep isl_space
*space
)
2898 return isl_bool_error
;
2900 if (isl_space_is_set(space
))
2901 return isl_bool_false
;
2903 return isl_bool_ok(space
->nested
[1] != NULL
);
2906 /* Is "space" a product of two spaces?
2907 * That is, is it a wrapping set space or a map space
2908 * with wrapping domain and range?
2910 isl_bool
isl_space_is_product(__isl_keep isl_space
*space
)
2913 isl_bool is_product
;
2915 is_set
= isl_space_is_set(space
);
2917 return isl_bool_error
;
2919 return isl_space_is_wrapping(space
);
2920 is_product
= isl_space_domain_is_wrapping(space
);
2921 if (is_product
< 0 || !is_product
)
2923 return isl_space_range_is_wrapping(space
);
2926 __isl_give isl_space
*isl_space_wrap(__isl_take isl_space
*space
)
2933 wrap
= isl_space_set_alloc(space
->ctx
,
2934 space
->nparam
, space
->n_in
+ space
->n_out
);
2936 wrap
= copy_ids(wrap
, isl_dim_param
, 0, space
, isl_dim_param
);
2937 wrap
= copy_ids(wrap
, isl_dim_set
, 0, space
, isl_dim_in
);
2938 wrap
= copy_ids(wrap
, isl_dim_set
, space
->n_in
, space
, isl_dim_out
);
2943 wrap
->nested
[1] = space
;
2947 isl_space_free(space
);
2951 __isl_give isl_space
*isl_space_unwrap(__isl_take isl_space
*space
)
2958 if (!isl_space_is_wrapping(space
))
2959 isl_die(space
->ctx
, isl_error_invalid
, "not a wrapping space",
2962 unwrap
= isl_space_copy(space
->nested
[1]);
2963 isl_space_free(space
);
2967 isl_space_free(space
);
2971 isl_bool
isl_space_is_named_or_nested(__isl_keep isl_space
*space
,
2972 enum isl_dim_type type
)
2974 if (type
!= isl_dim_in
&& type
!= isl_dim_out
)
2975 return isl_bool_false
;
2977 return isl_bool_error
;
2978 if (space
->tuple_id
[type
- isl_dim_in
])
2979 return isl_bool_true
;
2980 if (space
->nested
[type
- isl_dim_in
])
2981 return isl_bool_true
;
2982 return isl_bool_false
;
2985 isl_bool
isl_space_may_be_set(__isl_keep isl_space
*space
)
2991 return isl_bool_error
;
2992 if (isl_space_is_set(space
))
2993 return isl_bool_true
;
2994 n_in
= isl_space_dim(space
, isl_dim_in
);
2996 return isl_bool_error
;
2998 return isl_bool_false
;
2999 nested
= isl_space_is_named_or_nested(space
, isl_dim_in
);
3000 if (nested
< 0 || nested
)
3001 return isl_bool_not(nested
);
3002 return isl_bool_true
;
3005 __isl_give isl_space
*isl_space_reset(__isl_take isl_space
*space
,
3006 enum isl_dim_type type
)
3008 if (!isl_space_is_named_or_nested(space
, type
))
3011 space
= isl_space_cow(space
);
3015 isl_id_free(space
->tuple_id
[type
- isl_dim_in
]);
3016 space
->tuple_id
[type
- isl_dim_in
] = NULL
;
3017 isl_space_free(space
->nested
[type
- isl_dim_in
]);
3018 space
->nested
[type
- isl_dim_in
] = NULL
;
3023 __isl_give isl_space
*isl_space_flatten(__isl_take isl_space
*space
)
3027 if (!space
->nested
[0] && !space
->nested
[1])
3030 if (space
->nested
[0])
3031 space
= isl_space_reset(space
, isl_dim_in
);
3032 if (space
&& space
->nested
[1])
3033 space
= isl_space_reset(space
, isl_dim_out
);
3038 __isl_give isl_space
*isl_space_flatten_domain(__isl_take isl_space
*space
)
3042 if (!space
->nested
[0])
3045 return isl_space_reset(space
, isl_dim_in
);
3048 __isl_give isl_space
*isl_space_flatten_range(__isl_take isl_space
*space
)
3052 if (!space
->nested
[1])
3055 return isl_space_reset(space
, isl_dim_out
);
3058 /* Replace the parameters of dst by those of src.
3060 __isl_give isl_space
*isl_space_replace_params(__isl_take isl_space
*dst
,
3061 __isl_keep isl_space
*src
)
3063 isl_size dst_dim
, src_dim
;
3064 isl_bool equal_params
;
3065 enum isl_dim_type type
= isl_dim_param
;
3067 equal_params
= isl_space_has_equal_params(dst
, src
);
3068 if (equal_params
< 0)
3069 return isl_space_free(dst
);
3073 dst
= isl_space_cow(dst
);
3075 dst_dim
= isl_space_dim(dst
, type
);
3076 src_dim
= isl_space_dim(src
, type
);
3077 if (dst_dim
< 0 || src_dim
< 0)
3080 dst
= isl_space_drop_dims(dst
, type
, 0, dst_dim
);
3081 dst
= isl_space_add_dims(dst
, type
, src_dim
);
3082 dst
= copy_ids(dst
, type
, 0, src
, type
);
3086 for (i
= 0; i
<= 1; ++i
) {
3089 if (!dst
->nested
[i
])
3091 nested
= isl_space_take_nested(dst
, i
);
3092 nested
= isl_space_replace_params(nested
, src
);
3093 dst
= isl_space_restore_nested(dst
, i
, nested
);
3101 isl_space_free(dst
);
3105 /* Given two tuples ("dst_type" in "dst" and "src_type" in "src")
3106 * of the same size, check if any of the dimensions in the "dst" tuple
3107 * have no identifier, while the corresponding dimensions in "src"
3108 * does have an identifier,
3109 * If so, copy the identifier over to "dst".
3111 __isl_give isl_space
*isl_space_copy_ids_if_unset(__isl_take isl_space
*dst
,
3112 enum isl_dim_type dst_type
, __isl_keep isl_space
*src
,
3113 enum isl_dim_type src_type
)
3118 n
= isl_space_dim(dst
, dst_type
);
3120 return isl_space_free(dst
);
3121 for (i
= 0; i
< n
; ++i
) {
3125 set
= isl_space_has_dim_id(dst
, dst_type
, i
);
3127 return isl_space_free(dst
);
3131 set
= isl_space_has_dim_id(src
, src_type
, i
);
3133 return isl_space_free(dst
);
3137 id
= isl_space_get_dim_id(src
, src_type
, i
);
3138 dst
= isl_space_set_dim_id(dst
, dst_type
, i
, id
);
3144 /* Given a space "space" of a set, create a space
3145 * for the lift of the set. In particular, the result
3146 * is of the form lifted[space -> local[..]], with n_local variables in the
3147 * range of the wrapped map.
3149 __isl_give isl_space
*isl_space_lift(__isl_take isl_space
*space
,
3152 isl_space
*local_space
;
3157 local_space
= isl_space_dup(space
);
3158 local_space
= isl_space_drop_dims(local_space
, isl_dim_set
, 0,
3160 local_space
= isl_space_add_dims(local_space
, isl_dim_set
, n_local
);
3161 local_space
= isl_space_set_tuple_name(local_space
,
3162 isl_dim_set
, "local");
3163 space
= isl_space_join(isl_space_from_domain(space
),
3164 isl_space_from_range(local_space
));
3165 space
= isl_space_wrap(space
);
3166 space
= isl_space_set_tuple_name(space
, isl_dim_set
, "lifted");
3171 isl_bool
isl_space_can_zip(__isl_keep isl_space
*space
)
3175 is_set
= isl_space_is_set(space
);
3177 return isl_bool_error
;
3179 return isl_bool_false
;
3180 return isl_space_is_product(space
);
3183 __isl_give isl_space
*isl_space_zip(__isl_take isl_space
*space
)
3185 isl_space
*dom
, *ran
;
3186 isl_space
*dom_dom
, *dom_ran
, *ran_dom
, *ran_ran
;
3188 if (!isl_space_can_zip(space
))
3189 isl_die(space
->ctx
, isl_error_invalid
, "space cannot be zipped",
3194 dom
= isl_space_unwrap(isl_space_domain(isl_space_copy(space
)));
3195 ran
= isl_space_unwrap(isl_space_range(space
));
3196 dom_dom
= isl_space_domain(isl_space_copy(dom
));
3197 dom_ran
= isl_space_range(dom
);
3198 ran_dom
= isl_space_domain(isl_space_copy(ran
));
3199 ran_ran
= isl_space_range(ran
);
3200 dom
= isl_space_join(isl_space_from_domain(dom_dom
),
3201 isl_space_from_range(ran_dom
));
3202 ran
= isl_space_join(isl_space_from_domain(dom_ran
),
3203 isl_space_from_range(ran_ran
));
3204 return isl_space_join(isl_space_from_domain(isl_space_wrap(dom
)),
3205 isl_space_from_range(isl_space_wrap(ran
)));
3207 isl_space_free(space
);
3211 /* Can we apply isl_space_curry to "space"?
3212 * That is, does is it have a map space with a nested relation in its domain?
3214 isl_bool
isl_space_can_curry(__isl_keep isl_space
*space
)
3216 return isl_space_domain_is_wrapping(space
);
3219 /* Given a space (A -> B) -> C, return the corresponding space
3222 __isl_give isl_space
*isl_space_curry(__isl_take isl_space
*space
)
3224 isl_space
*dom
, *ran
;
3225 isl_space
*dom_dom
, *dom_ran
;
3230 if (!isl_space_can_curry(space
))
3231 isl_die(space
->ctx
, isl_error_invalid
,
3232 "space cannot be curried", goto error
);
3234 dom
= isl_space_unwrap(isl_space_domain(isl_space_copy(space
)));
3235 ran
= isl_space_range(space
);
3236 dom_dom
= isl_space_domain(isl_space_copy(dom
));
3237 dom_ran
= isl_space_range(dom
);
3238 ran
= isl_space_join(isl_space_from_domain(dom_ran
),
3239 isl_space_from_range(ran
));
3240 return isl_space_join(isl_space_from_domain(dom_dom
),
3241 isl_space_from_range(isl_space_wrap(ran
)));
3243 isl_space_free(space
);
3247 /* Can isl_space_range_curry be applied to "space"?
3248 * That is, does it have a nested relation in its range,
3249 * the domain of which is itself a nested relation?
3251 isl_bool
isl_space_can_range_curry(__isl_keep isl_space
*space
)
3256 return isl_bool_error
;
3257 can
= isl_space_range_is_wrapping(space
);
3258 if (can
< 0 || !can
)
3260 return isl_space_can_curry(space
->nested
[1]);
3263 /* Given a space A -> ((B -> C) -> D), return the corresponding space
3264 * A -> (B -> (C -> D)).
3266 __isl_give isl_space
*isl_space_range_curry(__isl_take isl_space
*space
)
3273 if (!isl_space_can_range_curry(space
))
3274 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
3275 "space range cannot be curried",
3276 return isl_space_free(space
));
3278 nested
= isl_space_take_nested(space
, 1);
3279 nested
= isl_space_curry(nested
);
3280 space
= isl_space_restore_nested(space
, 1, nested
);
3285 /* Can we apply isl_space_uncurry to "space"?
3286 * That is, does it have a map space with a nested relation in its range?
3288 isl_bool
isl_space_can_uncurry(__isl_keep isl_space
*space
)
3290 return isl_space_range_is_wrapping(space
);
3293 /* Given a space A -> (B -> C), return the corresponding space
3296 __isl_give isl_space
*isl_space_uncurry(__isl_take isl_space
*space
)
3298 isl_space
*dom
, *ran
;
3299 isl_space
*ran_dom
, *ran_ran
;
3304 if (!isl_space_can_uncurry(space
))
3305 isl_die(space
->ctx
, isl_error_invalid
,
3306 "space cannot be uncurried",
3307 return isl_space_free(space
));
3309 dom
= isl_space_domain(isl_space_copy(space
));
3310 ran
= isl_space_unwrap(isl_space_range(space
));
3311 ran_dom
= isl_space_domain(isl_space_copy(ran
));
3312 ran_ran
= isl_space_range(ran
);
3313 dom
= isl_space_join(isl_space_from_domain(dom
),
3314 isl_space_from_range(ran_dom
));
3315 return isl_space_join(isl_space_from_domain(isl_space_wrap(dom
)),
3316 isl_space_from_range(ran_ran
));
3319 isl_bool
isl_space_has_named_params(__isl_keep isl_space
*space
)
3325 return isl_bool_error
;
3326 if (space
->nparam
== 0)
3327 return isl_bool_true
;
3328 off
= isl_space_offset(space
, isl_dim_param
);
3330 return isl_bool_error
;
3331 if (off
+ space
->nparam
> space
->n_id
)
3332 return isl_bool_false
;
3333 for (i
= 0; i
< space
->nparam
; ++i
)
3334 if (!space
->ids
[off
+ i
])
3335 return isl_bool_false
;
3336 return isl_bool_true
;
3339 /* Check that "space" has only named parameters, reporting an error
3342 isl_stat
isl_space_check_named_params(__isl_keep isl_space
*space
)
3346 named
= isl_space_has_named_params(space
);
3348 return isl_stat_error
;
3350 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
3351 "unexpected unnamed parameters", return isl_stat_error
);
3356 /* Align the initial parameters of space1 to match the order in space2.
3358 __isl_give isl_space
*isl_space_align_params(__isl_take isl_space
*space1
,
3359 __isl_take isl_space
*space2
)
3361 isl_reordering
*exp
;
3363 if (isl_space_check_named_params(space1
) < 0 ||
3364 isl_space_check_named_params(space2
) < 0)
3367 exp
= isl_parameter_alignment_reordering(space1
, space2
);
3368 isl_space_free(space1
);
3369 isl_space_free(space2
);
3370 space1
= isl_reordering_get_space(exp
);
3371 isl_reordering_free(exp
);
3374 isl_space_free(space1
);
3375 isl_space_free(space2
);
3379 /* Given the space of set (domain), construct a space for a map
3380 * with as domain the given space and as range the range of "model".
3382 __isl_give isl_space
*isl_space_extend_domain_with_range(
3383 __isl_take isl_space
*space
, __isl_take isl_space
*model
)
3390 space
= isl_space_from_domain(space
);
3391 n_out
= isl_space_dim(model
, isl_dim_out
);
3394 space
= isl_space_add_dims(space
, isl_dim_out
, n_out
);
3395 if (isl_space_has_tuple_id(model
, isl_dim_out
))
3396 space
= isl_space_set_tuple_id(space
, isl_dim_out
,
3397 isl_space_get_tuple_id(model
, isl_dim_out
));
3400 if (model
->nested
[1]) {
3401 isl_space
*nested
= isl_space_copy(model
->nested
[1]);
3402 isl_size n_nested
, n_space
;
3403 nested
= isl_space_align_params(nested
, isl_space_copy(space
));
3404 n_nested
= isl_space_dim(nested
, isl_dim_param
);
3405 n_space
= isl_space_dim(space
, isl_dim_param
);
3406 if (n_nested
< 0 || n_space
< 0)
3408 if (n_nested
> n_space
)
3409 nested
= isl_space_drop_dims(nested
, isl_dim_param
,
3410 n_space
, n_nested
- n_space
);
3413 space
->nested
[1] = nested
;
3415 isl_space_free(model
);
3418 isl_space_free(model
);
3419 isl_space_free(space
);
3423 /* Compare the "type" dimensions of two isl_spaces.
3425 * The order is fairly arbitrary.
3427 static int isl_space_cmp_type(__isl_keep isl_space
*space1
,
3428 __isl_keep isl_space
*space2
, enum isl_dim_type type
)
3431 isl_size dim1
, dim2
;
3432 isl_space
*nested1
, *nested2
;
3434 dim1
= isl_space_dim(space1
, type
);
3435 dim2
= isl_space_dim(space2
, type
);
3436 if (dim1
< 0 || dim2
< 0)
3441 cmp
= isl_id_cmp(tuple_id(space1
, type
), tuple_id(space2
, type
));
3445 nested1
= nested(space1
, type
);
3446 nested2
= nested(space2
, type
);
3447 if (!nested1
!= !nested2
)
3448 return !nested1
- !nested2
;
3451 return isl_space_cmp(nested1
, nested2
);
3456 /* Compare two isl_spaces.
3458 * The order is fairly arbitrary.
3460 int isl_space_cmp(__isl_keep isl_space
*space1
, __isl_keep isl_space
*space2
)
3465 if (space1
== space2
)
3472 cmp
= isl_space_cmp_type(space1
, space2
, isl_dim_param
);
3475 cmp
= isl_space_cmp_type(space1
, space2
, isl_dim_in
);
3478 cmp
= isl_space_cmp_type(space1
, space2
, isl_dim_out
);
3482 if (!space1
->ids
&& !space2
->ids
)
3485 for (i
= 0; i
< n(space1
, isl_dim_param
); ++i
) {
3486 cmp
= isl_id_cmp(get_id(space1
, isl_dim_param
, i
),
3487 get_id(space2
, isl_dim_param
, i
));