2 * Copyright 2011 Sven Verdoolaege
3 * Copyright 2012-2013 Ecole Normale Superieure
5 * Use of this software is governed by the MIT license
7 * Written by Sven Verdoolaege,
8 * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
12 #include <isl_space_private.h>
13 #include <isl_val_private.h>
15 #include <isl_reordering.h>
17 #include <isl_multi_macro.h>
19 #define MULTI_NAME(BASE) "isl_multi_" #BASE
20 #define xLIST(EL) EL ## _list
21 #define LIST(EL) xLIST(EL)
23 isl_ctx
*FN(MULTI(BASE
),get_ctx
)(__isl_keep
MULTI(BASE
) *multi
)
25 return multi
? isl_space_get_ctx(multi
->space
) : NULL
;
28 __isl_give isl_space
*FN(MULTI(BASE
),get_space
)(__isl_keep
MULTI(BASE
) *multi
)
30 return multi
? isl_space_copy(multi
->space
) : NULL
;
33 /* Return the position of the dimension of the given type and name
35 * Return -1 if no such dimension can be found.
37 int FN(MULTI(BASE
),find_dim_by_name
)(__isl_keep
MULTI(BASE
) *multi
,
38 enum isl_dim_type type
, const char *name
)
42 return isl_space_find_dim_by_name(multi
->space
, type
, name
);
45 __isl_give isl_space
*FN(MULTI(BASE
),get_domain_space
)(
46 __isl_keep
MULTI(BASE
) *multi
)
48 return multi
? isl_space_domain(isl_space_copy(multi
->space
)) : NULL
;
51 /* Allocate a multi expression living in "space".
53 * If the number of base expressions is zero, then make sure
54 * there is enough room in the structure for the explicit domain,
55 * in case the type supports such an explicit domain.
57 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),alloc
)(__isl_take isl_space
*space
)
66 ctx
= isl_space_get_ctx(space
);
67 n
= isl_space_dim(space
, isl_dim_out
);
69 multi
= isl_calloc(ctx
, MULTI(BASE
),
70 sizeof(MULTI(BASE
)) + (n
- 1) * sizeof(struct EL
*));
72 multi
= isl_calloc(ctx
, MULTI(BASE
), sizeof(MULTI(BASE
)));
79 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
80 multi
= FN(MULTI(BASE
),init_explicit_domain
)(multi
);
83 isl_space_free(space
);
87 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),dup
)(__isl_keep
MULTI(BASE
) *multi
)
95 dup
= FN(MULTI(BASE
),alloc
)(isl_space_copy(multi
->space
));
99 for (i
= 0; i
< multi
->n
; ++i
)
100 dup
= FN(FN(MULTI(BASE
),set
),BASE
)(dup
, i
,
101 FN(EL
,copy
)(multi
->u
.p
[i
]));
102 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
103 dup
= FN(MULTI(BASE
),copy_explicit_domain
)(dup
, multi
);
108 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),cow
)(__isl_take
MULTI(BASE
) *multi
)
117 return FN(MULTI(BASE
),dup
)(multi
);
120 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),copy
)(__isl_keep
MULTI(BASE
) *multi
)
129 __isl_null
MULTI(BASE
) *FN(MULTI(BASE
),free
)(__isl_take
MULTI(BASE
) *multi
)
136 if (--multi
->ref
> 0)
139 isl_space_free(multi
->space
);
140 for (i
= 0; i
< multi
->n
; ++i
)
141 FN(EL
,free
)(multi
->u
.p
[i
]);
142 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
143 FN(MULTI(BASE
),free_explicit_domain
)(multi
);
149 unsigned FN(MULTI(BASE
),dim
)(__isl_keep
MULTI(BASE
) *multi
,
150 enum isl_dim_type type
)
152 return multi
? isl_space_dim(multi
->space
, type
) : 0;
155 /* Return the position of the first dimension of "type" with id "id".
156 * Return -1 if there is no such dimension.
158 int FN(MULTI(BASE
),find_dim_by_id
)(__isl_keep
MULTI(BASE
) *multi
,
159 enum isl_dim_type type
, __isl_keep isl_id
*id
)
163 return isl_space_find_dim_by_id(multi
->space
, type
, id
);
166 /* Return the id of the given dimension.
168 __isl_give isl_id
*FN(MULTI(BASE
),get_dim_id
)(__isl_keep
MULTI(BASE
) *multi
,
169 enum isl_dim_type type
, unsigned pos
)
171 return multi
? isl_space_get_dim_id(multi
->space
, type
, pos
) : NULL
;
174 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_dim_name
)(
175 __isl_take
MULTI(BASE
) *multi
,
176 enum isl_dim_type type
, unsigned pos
, const char *s
)
180 multi
= FN(MULTI(BASE
),cow
)(multi
);
184 multi
->space
= isl_space_set_dim_name(multi
->space
, type
, pos
, s
);
186 return FN(MULTI(BASE
),free
)(multi
);
188 if (type
== isl_dim_out
)
190 for (i
= 0; i
< multi
->n
; ++i
) {
191 multi
->u
.p
[i
] = FN(EL
,set_dim_name
)(multi
->u
.p
[i
],
194 return FN(MULTI(BASE
),free
)(multi
);
200 const char *FN(MULTI(BASE
),get_tuple_name
)(__isl_keep
MULTI(BASE
) *multi
,
201 enum isl_dim_type type
)
203 return multi
? isl_space_get_tuple_name(multi
->space
, type
) : NULL
;
206 /* Does the specified tuple have an id?
208 isl_bool
FN(MULTI(BASE
),has_tuple_id
)(__isl_keep
MULTI(BASE
) *multi
,
209 enum isl_dim_type type
)
212 return isl_bool_error
;
213 return isl_space_has_tuple_id(multi
->space
, type
);
216 /* Return the id of the specified tuple.
218 __isl_give isl_id
*FN(MULTI(BASE
),get_tuple_id
)(__isl_keep
MULTI(BASE
) *multi
,
219 enum isl_dim_type type
)
221 return multi
? isl_space_get_tuple_id(multi
->space
, type
) : NULL
;
224 __isl_give EL
*FN(FN(MULTI(BASE
),get
),BASE
)(__isl_keep
MULTI(BASE
) *multi
,
231 ctx
= FN(MULTI(BASE
),get_ctx
)(multi
);
232 if (pos
< 0 || pos
>= multi
->n
)
233 isl_die(ctx
, isl_error_invalid
,
234 "index out of bounds", return NULL
);
235 return FN(EL
,copy
)(multi
->u
.p
[pos
]);
238 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),set
),BASE
)(
239 __isl_take
MULTI(BASE
) *multi
, int pos
, __isl_take EL
*el
)
241 isl_space
*multi_space
= NULL
;
242 isl_space
*el_space
= NULL
;
245 multi
= FN(MULTI(BASE
),cow
)(multi
);
249 multi_space
= FN(MULTI(BASE
),get_space
)(multi
);
250 match
= FN(EL
,matching_params
)(el
, multi_space
);
254 multi
= FN(MULTI(BASE
),align_params
)(multi
,
255 FN(EL
,get_space
)(el
));
256 isl_space_free(multi_space
);
257 multi_space
= FN(MULTI(BASE
),get_space
)(multi
);
258 el
= FN(EL
,align_params
)(el
, isl_space_copy(multi_space
));
260 if (FN(EL
,check_match_domain_space
)(el
, multi_space
) < 0)
263 if (pos
< 0 || pos
>= multi
->n
)
264 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
265 "index out of bounds", goto error
);
267 FN(EL
,free
)(multi
->u
.p
[pos
]);
268 multi
->u
.p
[pos
] = el
;
270 isl_space_free(multi_space
);
271 isl_space_free(el_space
);
275 FN(MULTI(BASE
),free
)(multi
);
277 isl_space_free(multi_space
);
278 isl_space_free(el_space
);
282 /* Reset the space of "multi". This function is called from isl_pw_templ.c
283 * and doesn't know if the space of an element object is represented
284 * directly or through its domain. It therefore passes along both,
285 * which we pass along to the element function since we don't know how
286 * that is represented either.
288 * If "multi" has an explicit domain, then the caller is expected
289 * to make sure that any modification that would change the dimensions
290 * of the explicit domain has bee applied before this function is called.
292 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_space_and_domain
)(
293 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*space
,
294 __isl_take isl_space
*domain
)
298 multi
= FN(MULTI(BASE
),cow
)(multi
);
299 if (!multi
|| !space
|| !domain
)
302 for (i
= 0; i
< multi
->n
; ++i
) {
303 multi
->u
.p
[i
] = FN(EL
,reset_domain_space
)(multi
->u
.p
[i
],
304 isl_space_copy(domain
));
308 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
)) {
309 multi
= FN(MULTI(BASE
),reset_explicit_domain_space
)(multi
,
310 isl_space_copy(domain
));
314 isl_space_free(domain
);
315 isl_space_free(multi
->space
);
316 multi
->space
= space
;
320 isl_space_free(domain
);
321 isl_space_free(space
);
322 FN(MULTI(BASE
),free
)(multi
);
326 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_domain_space
)(
327 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*domain
)
331 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
332 isl_space_copy(multi
->space
));
333 return FN(MULTI(BASE
),reset_space_and_domain
)(multi
, space
, domain
);
336 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_space
)(
337 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*space
)
341 domain
= isl_space_domain(isl_space_copy(space
));
342 return FN(MULTI(BASE
),reset_space_and_domain
)(multi
, space
, domain
);
345 /* Set the id of the given dimension of "multi" to "id".
347 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_dim_id
)(
348 __isl_take
MULTI(BASE
) *multi
,
349 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
353 multi
= FN(MULTI(BASE
),cow
)(multi
);
357 space
= FN(MULTI(BASE
),get_space
)(multi
);
358 space
= isl_space_set_dim_id(space
, type
, pos
, id
);
360 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
363 FN(MULTI(BASE
),free
)(multi
);
367 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_tuple_name
)(
368 __isl_keep
MULTI(BASE
) *multi
, enum isl_dim_type type
,
373 multi
= FN(MULTI(BASE
),cow
)(multi
);
377 space
= FN(MULTI(BASE
),get_space
)(multi
);
378 space
= isl_space_set_tuple_name(space
, type
, s
);
380 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
383 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_tuple_id
)(
384 __isl_take
MULTI(BASE
) *multi
, enum isl_dim_type type
,
385 __isl_take isl_id
*id
)
389 multi
= FN(MULTI(BASE
),cow
)(multi
);
393 space
= FN(MULTI(BASE
),get_space
)(multi
);
394 space
= isl_space_set_tuple_id(space
, type
, id
);
396 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
402 /* Drop the id on the specified tuple.
404 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_tuple_id
)(
405 __isl_take
MULTI(BASE
) *multi
, enum isl_dim_type type
)
411 if (!FN(MULTI(BASE
),has_tuple_id
)(multi
, type
))
414 multi
= FN(MULTI(BASE
),cow
)(multi
);
418 space
= FN(MULTI(BASE
),get_space
)(multi
);
419 space
= isl_space_reset_tuple_id(space
, type
);
421 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
424 /* Reset the user pointer on all identifiers of parameters and tuples
425 * of the space of "multi".
427 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_user
)(
428 __isl_take
MULTI(BASE
) *multi
)
432 space
= FN(MULTI(BASE
),get_space
)(multi
);
433 space
= isl_space_reset_user(space
);
435 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
438 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),realign_domain
)(
439 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_reordering
*exp
)
443 multi
= FN(MULTI(BASE
),cow
)(multi
);
447 for (i
= 0; i
< multi
->n
; ++i
) {
448 multi
->u
.p
[i
] = FN(EL
,realign_domain
)(multi
->u
.p
[i
],
449 isl_reordering_copy(exp
));
454 multi
= FN(MULTI(BASE
),reset_domain_space
)(multi
,
455 isl_space_copy(exp
->dim
));
457 isl_reordering_free(exp
);
460 isl_reordering_free(exp
);
461 FN(MULTI(BASE
),free
)(multi
);
465 /* Align the parameters of "multi" to those of "model".
467 * If "multi" has an explicit domain, then align the parameters
468 * of the domain first.
470 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),align_params
)(
471 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*model
)
474 isl_bool equal_params
;
477 if (!multi
|| !model
)
480 equal_params
= isl_space_has_equal_params(multi
->space
, model
);
481 if (equal_params
< 0)
484 isl_space_free(model
);
488 ctx
= isl_space_get_ctx(model
);
489 if (!isl_space_has_named_params(model
))
490 isl_die(ctx
, isl_error_invalid
,
491 "model has unnamed parameters", goto error
);
492 if (!isl_space_has_named_params(multi
->space
))
493 isl_die(ctx
, isl_error_invalid
,
494 "input has unnamed parameters", goto error
);
496 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
)) {
497 multi
= FN(MULTI(BASE
),align_explicit_domain_params
)(multi
,
498 isl_space_copy(model
));
502 model
= isl_space_params(model
);
503 exp
= isl_parameter_alignment_reordering(multi
->space
, model
);
504 exp
= isl_reordering_extend_space(exp
,
505 FN(MULTI(BASE
),get_domain_space
)(multi
));
506 multi
= FN(MULTI(BASE
),realign_domain
)(multi
, exp
);
508 isl_space_free(model
);
511 isl_space_free(model
);
512 FN(MULTI(BASE
),free
)(multi
);
516 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),from
),LIST(BASE
))(
517 __isl_take isl_space
*space
, __isl_take
LIST(EL
) *list
)
527 ctx
= isl_space_get_ctx(space
);
528 n
= FN(FN(LIST(EL
),n
),BASE
)(list
);
529 if (n
!= isl_space_dim(space
, isl_dim_out
))
530 isl_die(ctx
, isl_error_invalid
,
531 "invalid number of elements in list", goto error
);
533 multi
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
534 for (i
= 0; i
< n
; ++i
) {
535 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, i
,
536 FN(FN(LIST(EL
),get
),BASE
)(list
, i
));
539 isl_space_free(space
);
540 FN(LIST(EL
),free
)(list
);
543 isl_space_free(space
);
544 FN(LIST(EL
),free
)(list
);
549 /* Create a multi expression in the given space that maps each
550 * input dimension to the corresponding output dimension.
552 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),identity
)(__isl_take isl_space
*space
)
561 if (isl_space_is_set(space
))
562 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
563 "expecting map space", goto error
);
565 n
= isl_space_dim(space
, isl_dim_out
);
566 if (n
!= isl_space_dim(space
, isl_dim_in
))
567 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
568 "number of input and output dimensions needs to be "
569 "the same", goto error
);
571 multi
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
574 isl_space_free(space
);
578 space
= isl_space_domain(space
);
579 ls
= isl_local_space_from_space(space
);
581 for (i
= 0; i
< n
; ++i
) {
583 el
= FN(EL
,var_on_domain
)(isl_local_space_copy(ls
),
585 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, i
, el
);
588 isl_local_space_free(ls
);
592 isl_space_free(space
);
598 /* Construct a multi expression in the given space with value zero in
599 * each of the output dimensions.
601 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),zero
)(__isl_take isl_space
*space
)
609 n
= isl_space_dim(space
, isl_dim_out
);
610 multi
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
613 isl_space_free(space
);
619 space
= isl_space_domain(space
);
620 ls
= isl_local_space_from_space(space
);
621 el
= FN(EL
,zero_on_domain
)(ls
);
623 for (i
= 0; i
< n
; ++i
)
624 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, i
,
635 /* Create a multiple expression with a single output/set dimension
637 * For most multiple expression types, the base type has a single
638 * output/set dimension and the space of the result is therefore
639 * the same as the space of the input.
640 * In the case of isl_multi_union_pw_aff, however, the base type
641 * lives in a parameter space and we therefore need to add
642 * a single set dimension.
644 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),from
),BASE
)(__isl_take EL
*el
)
649 space
= FN(EL
,get_space(el
));
650 if (isl_space_is_params(space
)) {
651 space
= isl_space_set_from_params(space
);
652 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
654 multi
= FN(MULTI(BASE
),alloc
)(space
);
655 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, 0, el
);
661 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),drop_dims
)(
662 __isl_take
MULTI(BASE
) *multi
,
663 enum isl_dim_type type
, unsigned first
, unsigned n
)
668 multi
= FN(MULTI(BASE
),cow
)(multi
);
672 dim
= FN(MULTI(BASE
),dim
)(multi
, type
);
673 if (first
+ n
> dim
|| first
+ n
< first
)
674 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
675 "index out of bounds",
676 return FN(MULTI(BASE
),free
)(multi
));
678 multi
->space
= isl_space_drop_dims(multi
->space
, type
, first
, n
);
680 return FN(MULTI(BASE
),free
)(multi
);
682 if (type
== isl_dim_out
) {
683 for (i
= 0; i
< n
; ++i
)
684 FN(EL
,free
)(multi
->u
.p
[first
+ i
]);
685 for (i
= first
; i
+ n
< multi
->n
; ++i
)
686 multi
->u
.p
[i
] = multi
->u
.p
[i
+ n
];
688 if (n
> 0 && FN(MULTI(BASE
),has_explicit_domain
)(multi
))
689 multi
= FN(MULTI(BASE
),init_explicit_domain
)(multi
);
694 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
695 multi
= FN(MULTI(BASE
),drop_explicit_domain_dims
)(multi
,
700 for (i
= 0; i
< multi
->n
; ++i
) {
701 multi
->u
.p
[i
] = FN(EL
,drop_dims
)(multi
->u
.p
[i
], type
, first
, n
);
703 return FN(MULTI(BASE
),free
)(multi
);
709 /* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
711 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),align_params_multi_multi_and
)(
712 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
713 __isl_give
MULTI(BASE
) *(*fn
)(__isl_take
MULTI(BASE
) *multi1
,
714 __isl_take
MULTI(BASE
) *multi2
))
717 isl_bool equal_params
;
719 if (!multi1
|| !multi2
)
721 equal_params
= isl_space_has_equal_params(multi1
->space
, multi2
->space
);
722 if (equal_params
< 0)
725 return fn(multi1
, multi2
);
726 ctx
= FN(MULTI(BASE
),get_ctx
)(multi1
);
727 if (!isl_space_has_named_params(multi1
->space
) ||
728 !isl_space_has_named_params(multi2
->space
))
729 isl_die(ctx
, isl_error_invalid
,
730 "unaligned unnamed parameters", goto error
);
731 multi1
= FN(MULTI(BASE
),align_params
)(multi1
,
732 FN(MULTI(BASE
),get_space
)(multi2
));
733 multi2
= FN(MULTI(BASE
),align_params
)(multi2
,
734 FN(MULTI(BASE
),get_space
)(multi1
));
735 return fn(multi1
, multi2
);
737 FN(MULTI(BASE
),free
)(multi1
);
738 FN(MULTI(BASE
),free
)(multi2
);
742 /* Given two MULTI(BASE)s A -> B and C -> D,
743 * construct a MULTI(BASE) (A * C) -> [B -> D].
745 * The parameters are assumed to have been aligned.
747 * If "multi1" and/or "multi2" has an explicit domain, then
748 * intersect the domain of the result with these explicit domains.
750 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_product_aligned
)(
751 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
758 if (!multi1
|| !multi2
)
761 space
= isl_space_range_product(FN(MULTI(BASE
),get_space
)(multi1
),
762 FN(MULTI(BASE
),get_space
)(multi2
));
763 res
= FN(MULTI(BASE
),alloc
)(space
);
765 n1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
766 n2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_out
);
768 for (i
= 0; i
< n1
; ++i
) {
769 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi1
, i
);
770 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, i
, el
);
773 for (i
= 0; i
< n2
; ++i
) {
774 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi2
, i
);
775 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, n1
+ i
, el
);
778 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
))
779 res
= FN(MULTI(BASE
),intersect_explicit_domain
)(res
, multi1
);
780 if (FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
781 res
= FN(MULTI(BASE
),intersect_explicit_domain
)(res
, multi2
);
783 FN(MULTI(BASE
),free
)(multi1
);
784 FN(MULTI(BASE
),free
)(multi2
);
787 FN(MULTI(BASE
),free
)(multi1
);
788 FN(MULTI(BASE
),free
)(multi2
);
792 /* Given two MULTI(BASE)s A -> B and C -> D,
793 * construct a MULTI(BASE) (A * C) -> [B -> D].
795 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_product
)(
796 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
798 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
799 &FN(MULTI(BASE
),range_product_aligned
));
802 /* Is the range of "multi" a wrapped relation?
804 isl_bool
FN(MULTI(BASE
),range_is_wrapping
)(__isl_keep
MULTI(BASE
) *multi
)
807 return isl_bool_error
;
808 return isl_space_range_is_wrapping(multi
->space
);
811 /* Given a function A -> [B -> C], extract the function A -> B.
813 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_factor_domain
)(
814 __isl_take
MULTI(BASE
) *multi
)
821 if (!isl_space_range_is_wrapping(multi
->space
))
822 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
823 "range is not a product",
824 return FN(MULTI(BASE
),free
)(multi
));
826 space
= FN(MULTI(BASE
),get_space
)(multi
);
827 total
= isl_space_dim(space
, isl_dim_out
);
828 space
= isl_space_range_factor_domain(space
);
829 keep
= isl_space_dim(space
, isl_dim_out
);
830 multi
= FN(MULTI(BASE
),drop_dims
)(multi
,
831 isl_dim_out
, keep
, total
- keep
);
832 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
837 /* Given a function A -> [B -> C], extract the function A -> C.
839 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_factor_range
)(
840 __isl_take
MULTI(BASE
) *multi
)
847 if (!isl_space_range_is_wrapping(multi
->space
))
848 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
849 "range is not a product",
850 return FN(MULTI(BASE
),free
)(multi
));
852 space
= FN(MULTI(BASE
),get_space
)(multi
);
853 total
= isl_space_dim(space
, isl_dim_out
);
854 space
= isl_space_range_factor_range(space
);
855 keep
= isl_space_dim(space
, isl_dim_out
);
856 multi
= FN(MULTI(BASE
),drop_dims
)(multi
, isl_dim_out
, 0, total
- keep
);
857 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
862 /* Given a function [B -> C], extract the function C.
864 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),factor_range
)(
865 __isl_take
MULTI(BASE
) *multi
)
872 if (!isl_space_is_wrapping(multi
->space
))
873 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
874 "not a product", return FN(MULTI(BASE
),free
)(multi
));
876 space
= FN(MULTI(BASE
),get_space
)(multi
);
877 total
= isl_space_dim(space
, isl_dim_out
);
878 space
= isl_space_factor_range(space
);
879 keep
= isl_space_dim(space
, isl_dim_out
);
880 multi
= FN(MULTI(BASE
),drop_dims
)(multi
, isl_dim_out
, 0, total
- keep
);
881 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
887 /* Given two MULTI(BASE)s A -> B and C -> D,
888 * construct a MULTI(BASE) [A -> C] -> [B -> D].
890 * The parameters are assumed to have been aligned.
892 * If "multi1" and/or "multi2" has an explicit domain, then
893 * intersect the domain of the result with these explicit domains.
895 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),product_aligned
)(
896 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
902 int in1
, in2
, out1
, out2
;
904 in1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_in
);
905 in2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_in
);
906 out1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
907 out2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_out
);
908 space
= isl_space_product(FN(MULTI(BASE
),get_space
)(multi1
),
909 FN(MULTI(BASE
),get_space
)(multi2
));
910 res
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
911 space
= isl_space_domain(space
);
913 for (i
= 0; i
< out1
; ++i
) {
914 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi1
, i
);
915 el
= FN(EL
,insert_dims
)(el
, isl_dim_in
, in1
, in2
);
916 el
= FN(EL
,reset_domain_space
)(el
, isl_space_copy(space
));
917 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, i
, el
);
920 for (i
= 0; i
< out2
; ++i
) {
921 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi2
, i
);
922 el
= FN(EL
,insert_dims
)(el
, isl_dim_in
, 0, in1
);
923 el
= FN(EL
,reset_domain_space
)(el
, isl_space_copy(space
));
924 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, out1
+ i
, el
);
927 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
) ||
928 FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
929 res
= FN(MULTI(BASE
),intersect_explicit_domain_product
)(res
,
932 isl_space_free(space
);
933 FN(MULTI(BASE
),free
)(multi1
);
934 FN(MULTI(BASE
),free
)(multi2
);
938 /* Given two MULTI(BASE)s A -> B and C -> D,
939 * construct a MULTI(BASE) [A -> C] -> [B -> D].
941 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),product
)(
942 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
944 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
945 &FN(MULTI(BASE
),product_aligned
));
949 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),flatten_range
)(
950 __isl_take
MULTI(BASE
) *multi
)
955 if (!multi
->space
->nested
[1])
958 multi
= FN(MULTI(BASE
),cow
)(multi
);
962 multi
->space
= isl_space_flatten_range(multi
->space
);
964 return FN(MULTI(BASE
),free
)(multi
);
969 /* Given two MULTI(BASE)s A -> B and C -> D,
970 * construct a MULTI(BASE) (A * C) -> (B, D).
972 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),flat_range_product
)(
973 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
977 multi
= FN(MULTI(BASE
),range_product
)(multi1
, multi2
);
978 multi
= FN(MULTI(BASE
),flatten_range
)(multi
);
982 /* Given two multi expressions, "multi1"
986 * where B2 starts at position "pos", and "multi2"
990 * return the multi expression
994 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_splice
)(
995 __isl_take
MULTI(BASE
) *multi1
, unsigned pos
,
996 __isl_take
MULTI(BASE
) *multi2
)
1001 if (!multi1
|| !multi2
)
1004 dim
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
1006 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1007 "index out of bounds", goto error
);
1009 res
= FN(MULTI(BASE
),copy
)(multi1
);
1010 res
= FN(MULTI(BASE
),drop_dims
)(res
, isl_dim_out
, pos
, dim
- pos
);
1011 multi1
= FN(MULTI(BASE
),drop_dims
)(multi1
, isl_dim_out
, 0, pos
);
1013 res
= FN(MULTI(BASE
),flat_range_product
)(res
, multi2
);
1014 res
= FN(MULTI(BASE
),flat_range_product
)(res
, multi1
);
1018 FN(MULTI(BASE
),free
)(multi1
);
1019 FN(MULTI(BASE
),free
)(multi2
);
1024 /* Given two multi expressions, "multi1"
1026 * [A1 A2] -> [B1 B2]
1028 * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
1033 * return the multi expression
1035 * [A1 C A2] -> [B1 D B2]
1037 * We first insert input dimensions to obtain
1039 * [A1 C A2] -> [B1 B2]
1045 * and then apply range_splice.
1047 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),splice
)(
1048 __isl_take
MULTI(BASE
) *multi1
, unsigned in_pos
, unsigned out_pos
,
1049 __isl_take
MULTI(BASE
) *multi2
)
1054 if (!multi1
|| !multi2
)
1057 n_in1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_in
);
1059 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1060 "index out of bounds", goto error
);
1062 n_in2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_in
);
1064 multi1
= FN(MULTI(BASE
),insert_dims
)(multi1
, isl_dim_in
, in_pos
, n_in2
);
1065 multi2
= FN(MULTI(BASE
),insert_dims
)(multi2
, isl_dim_in
, n_in2
,
1067 multi2
= FN(MULTI(BASE
),insert_dims
)(multi2
, isl_dim_in
, 0, in_pos
);
1069 return FN(MULTI(BASE
),range_splice
)(multi1
, out_pos
, multi2
);
1071 FN(MULTI(BASE
),free
)(multi1
);
1072 FN(MULTI(BASE
),free
)(multi2
);
1077 /* Check that "multi1" and "multi2" live in the same space,
1078 * reporting an error if they do not.
1080 static isl_stat
FN(MULTI(BASE
),check_equal_space
)(
1081 __isl_keep
MULTI(BASE
) *multi1
, __isl_keep
MULTI(BASE
) *multi2
)
1085 if (!multi1
|| !multi2
)
1086 return isl_stat_error
;
1088 equal
= isl_space_is_equal(multi1
->space
, multi2
->space
);
1090 return isl_stat_error
;
1092 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1093 "spaces don't match", return isl_stat_error
);
1098 /* This function is currently only used from isl_aff.c
1100 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),bin_op
)(
1101 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
1102 __isl_give EL
*(*fn
)(__isl_take EL
*, __isl_take EL
*))
1103 __attribute__ ((unused
));
1105 /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
1106 * return the result.
1108 * If "multi2" has an explicit domain, then
1109 * intersect the domain of the result with this explicit domain.
1111 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),bin_op
)(
1112 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
1113 __isl_give EL
*(*fn
)(__isl_take EL
*, __isl_take EL
*))
1117 multi1
= FN(MULTI(BASE
),cow
)(multi1
);
1118 if (FN(MULTI(BASE
),check_equal_space
)(multi1
, multi2
) < 0)
1121 for (i
= 0; i
< multi1
->n
; ++i
) {
1122 multi1
->u
.p
[i
] = fn(multi1
->u
.p
[i
],
1123 FN(EL
,copy
)(multi2
->u
.p
[i
]));
1124 if (!multi1
->u
.p
[i
])
1128 if (FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
1129 multi1
= FN(MULTI(BASE
),intersect_explicit_domain
)(multi1
,
1132 FN(MULTI(BASE
),free
)(multi2
);
1135 FN(MULTI(BASE
),free
)(multi1
);
1136 FN(MULTI(BASE
),free
)(multi2
);
1140 /* Add "multi2" from "multi1" and return the result.
1142 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1144 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),add_aligned
)(
1145 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
1147 return FN(MULTI(BASE
),bin_op
)(multi1
, multi2
, &FN(EL
,add
));
1150 /* Add "multi2" from "multi1" and return the result.
1152 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),add
)(__isl_take
MULTI(BASE
) *multi1
,
1153 __isl_take
MULTI(BASE
) *multi2
)
1155 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
1156 &FN(MULTI(BASE
),add_aligned
));
1159 /* Subtract "multi2" from "multi1" and return the result.
1161 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1163 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),sub_aligned
)(
1164 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
1166 return FN(MULTI(BASE
),bin_op
)(multi1
, multi2
, &FN(EL
,sub
));
1169 /* Subtract "multi2" from "multi1" and return the result.
1171 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),sub
)(__isl_take
MULTI(BASE
) *multi1
,
1172 __isl_take
MULTI(BASE
) *multi2
)
1174 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
1175 &FN(MULTI(BASE
),sub_aligned
));
1178 /* Multiply the elements of "multi" by "v" and return the result.
1180 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_val
)(__isl_take
MULTI(BASE
) *multi
,
1181 __isl_take isl_val
*v
)
1188 if (isl_val_is_one(v
)) {
1193 if (!isl_val_is_rat(v
))
1194 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1195 "expecting rational factor", goto error
);
1197 multi
= FN(MULTI(BASE
),cow
)(multi
);
1201 for (i
= 0; i
< multi
->n
; ++i
) {
1202 multi
->u
.p
[i
] = FN(EL
,scale_val
)(multi
->u
.p
[i
],
1212 return FN(MULTI(BASE
),free
)(multi
);
1215 /* Divide the elements of "multi" by "v" and return the result.
1217 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_down_val
)(
1218 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_val
*v
)
1225 if (isl_val_is_one(v
)) {
1230 if (!isl_val_is_rat(v
))
1231 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1232 "expecting rational factor", goto error
);
1233 if (isl_val_is_zero(v
))
1234 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1235 "cannot scale down by zero", goto error
);
1237 multi
= FN(MULTI(BASE
),cow
)(multi
);
1241 for (i
= 0; i
< multi
->n
; ++i
) {
1242 multi
->u
.p
[i
] = FN(EL
,scale_down_val
)(multi
->u
.p
[i
],
1252 return FN(MULTI(BASE
),free
)(multi
);
1255 /* Multiply the elements of "multi" by the corresponding element of "mv"
1256 * and return the result.
1258 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_multi_val
)(
1259 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1266 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1267 mv
->space
, isl_dim_set
))
1268 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1269 "spaces don't match", goto error
);
1271 multi
= FN(MULTI(BASE
),cow
)(multi
);
1275 for (i
= 0; i
< multi
->n
; ++i
) {
1278 v
= isl_multi_val_get_val(mv
, i
);
1279 multi
->u
.p
[i
] = FN(EL
,scale_val
)(multi
->u
.p
[i
], v
);
1284 isl_multi_val_free(mv
);
1287 isl_multi_val_free(mv
);
1288 return FN(MULTI(BASE
),free
)(multi
);
1291 /* Divide the elements of "multi" by the corresponding element of "mv"
1292 * and return the result.
1294 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_down_multi_val
)(
1295 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1302 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1303 mv
->space
, isl_dim_set
))
1304 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1305 "spaces don't match", goto error
);
1307 multi
= FN(MULTI(BASE
),cow
)(multi
);
1311 for (i
= 0; i
< multi
->n
; ++i
) {
1314 v
= isl_multi_val_get_val(mv
, i
);
1315 multi
->u
.p
[i
] = FN(EL
,scale_down_val
)(multi
->u
.p
[i
], v
);
1320 isl_multi_val_free(mv
);
1323 isl_multi_val_free(mv
);
1324 return FN(MULTI(BASE
),free
)(multi
);
1327 /* Compute the residues of the elements of "multi" modulo
1328 * the corresponding element of "mv" and return the result.
1330 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),mod_multi_val
)(
1331 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1338 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1339 mv
->space
, isl_dim_set
))
1340 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1341 "spaces don't match", goto error
);
1343 multi
= FN(MULTI(BASE
),cow
)(multi
);
1347 for (i
= 0; i
< multi
->n
; ++i
) {
1350 v
= isl_multi_val_get_val(mv
, i
);
1351 multi
->u
.p
[i
] = FN(EL
,mod_val
)(multi
->u
.p
[i
], v
);
1356 isl_multi_val_free(mv
);
1359 isl_multi_val_free(mv
);
1360 return FN(MULTI(BASE
),free
)(multi
);
1363 #ifndef NO_MOVE_DIMS
1364 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
1365 * to dimensions of "dst_type" at "dst_pos".
1367 * We only support moving input dimensions to parameters and vice versa.
1369 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),move_dims
)(__isl_take
MULTI(BASE
) *multi
,
1370 enum isl_dim_type dst_type
, unsigned dst_pos
,
1371 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1379 !isl_space_is_named_or_nested(multi
->space
, src_type
) &&
1380 !isl_space_is_named_or_nested(multi
->space
, dst_type
))
1383 if (dst_type
== isl_dim_out
|| src_type
== isl_dim_out
)
1384 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1385 "cannot move output/set dimension",
1386 return FN(MULTI(BASE
),free
)(multi
));
1387 if (dst_type
== isl_dim_div
|| src_type
== isl_dim_div
)
1388 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1390 return FN(MULTI(BASE
),free
)(multi
));
1391 if (src_pos
+ n
> isl_space_dim(multi
->space
, src_type
))
1392 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1393 "range out of bounds",
1394 return FN(MULTI(BASE
),free
)(multi
));
1395 if (dst_type
== src_type
)
1396 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_unsupported
,
1397 "moving dims within the same type not supported",
1398 return FN(MULTI(BASE
),free
)(multi
));
1400 multi
= FN(MULTI(BASE
),cow
)(multi
);
1404 multi
->space
= isl_space_move_dims(multi
->space
, dst_type
, dst_pos
,
1405 src_type
, src_pos
, n
);
1407 return FN(MULTI(BASE
),free
)(multi
);
1408 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
1409 multi
= FN(MULTI(BASE
),move_explicit_domain_dims
)(multi
,
1410 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1414 for (i
= 0; i
< multi
->n
; ++i
) {
1415 multi
->u
.p
[i
] = FN(EL
,move_dims
)(multi
->u
.p
[i
],
1417 src_type
, src_pos
, n
);
1419 return FN(MULTI(BASE
),free
)(multi
);
1426 /* Convert a multiple expression defined over a parameter domain
1427 * into one that is defined over a zero-dimensional set.
1429 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),from_range
)(
1430 __isl_take
MULTI(BASE
) *multi
)
1436 if (!isl_space_is_set(multi
->space
))
1437 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1438 "not living in a set space",
1439 return FN(MULTI(BASE
),free
)(multi
));
1441 space
= FN(MULTI(BASE
),get_space
)(multi
);
1442 space
= isl_space_from_range(space
);
1443 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
1448 /* Are "multi1" and "multi2" obviously equal?
1450 isl_bool
FN(MULTI(BASE
),plain_is_equal
)(__isl_keep
MULTI(BASE
) *multi1
,
1451 __isl_keep
MULTI(BASE
) *multi2
)
1456 if (!multi1
|| !multi2
)
1457 return isl_bool_error
;
1458 if (multi1
->n
!= multi2
->n
)
1459 return isl_bool_false
;
1460 equal
= isl_space_is_equal(multi1
->space
, multi2
->space
);
1461 if (equal
< 0 || !equal
)
1464 for (i
= 0; i
< multi1
->n
; ++i
) {
1465 equal
= FN(EL
,plain_is_equal
)(multi1
->u
.p
[i
], multi2
->u
.p
[i
]);
1466 if (equal
< 0 || !equal
)
1470 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
) ||
1471 FN(MULTI(BASE
),has_explicit_domain
)(multi2
)) {
1472 equal
= FN(MULTI(BASE
),equal_explicit_domain
)(multi1
, multi2
);
1473 if (equal
< 0 || !equal
)
1477 return isl_bool_true
;
1480 /* Does "multi" involve any NaNs?
1482 isl_bool
FN(MULTI(BASE
),involves_nan
)(__isl_keep
MULTI(BASE
) *multi
)
1487 return isl_bool_error
;
1489 return isl_bool_false
;
1491 for (i
= 0; i
< multi
->n
; ++i
) {
1492 isl_bool has_nan
= FN(EL
,involves_nan
)(multi
->u
.p
[i
]);
1493 if (has_nan
< 0 || has_nan
)
1497 return isl_bool_false
;
1501 /* Return the shared domain of the elements of "multi".
1503 * If "multi" has an explicit domain, then return this domain.
1505 __isl_give isl_set
*FN(MULTI(BASE
),domain
)(__isl_take
MULTI(BASE
) *multi
)
1513 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
)) {
1514 dom
= FN(MULTI(BASE
),get_explicit_domain
)(multi
);
1515 FN(MULTI(BASE
),free
)(multi
);
1519 dom
= isl_set_universe(FN(MULTI(BASE
),get_domain_space
)(multi
));
1520 for (i
= 0; i
< multi
->n
; ++i
) {
1523 dom_i
= FN(EL
,domain
)(FN(FN(MULTI(BASE
),get
),BASE
)(multi
, i
));
1524 dom
= isl_set_intersect(dom
, dom_i
);
1527 FN(MULTI(BASE
),free
)(multi
);
1533 /* Return the opposite of "multi".
1535 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),neg
)(__isl_take
MULTI(BASE
) *multi
)
1539 multi
= FN(MULTI(BASE
),cow
)(multi
);
1543 for (i
= 0; i
< multi
->n
; ++i
) {
1544 multi
->u
.p
[i
] = FN(EL
,neg
)(multi
->u
.p
[i
]);
1546 return FN(MULTI(BASE
),free
)(multi
);