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
11 #include <isl_space_private.h>
13 #include <isl_reordering.h>
15 #include <isl_multi_macro.h>
17 #define MULTI_NAME(BASE) "isl_multi_" #BASE
18 #define xLIST(EL) EL ## _list
19 #define LIST(EL) xLIST(EL)
21 isl_ctx
*FN(MULTI(BASE
),get_ctx
)(__isl_keep
MULTI(BASE
) *multi
)
23 return multi
? isl_space_get_ctx(multi
->space
) : NULL
;
26 __isl_give isl_space
*FN(MULTI(BASE
),get_space
)(__isl_keep
MULTI(BASE
) *multi
)
28 return multi
? isl_space_copy(multi
->space
) : NULL
;
31 /* Return the position of the dimension of the given type and name
33 * Return -1 if no such dimension can be found.
35 int FN(MULTI(BASE
),find_dim_by_name
)(__isl_keep
MULTI(BASE
) *multi
,
36 enum isl_dim_type type
, const char *name
)
40 return isl_space_find_dim_by_name(multi
->space
, type
, name
);
43 __isl_give isl_space
*FN(MULTI(BASE
),get_domain_space
)(
44 __isl_keep
MULTI(BASE
) *multi
)
46 return multi
? isl_space_domain(isl_space_copy(multi
->space
)) : NULL
;
49 /* Allocate a multi expression living in "space".
51 * If the number of base expressions is zero, then make sure
52 * there is enough room in the structure for the explicit domain,
53 * in case the type supports such an explicit domain.
55 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),alloc
)(__isl_take isl_space
*space
)
64 ctx
= isl_space_get_ctx(space
);
65 n
= isl_space_dim(space
, isl_dim_out
);
67 multi
= isl_calloc(ctx
, MULTI(BASE
),
68 sizeof(MULTI(BASE
)) + (n
- 1) * sizeof(struct EL
*));
70 multi
= isl_calloc(ctx
, MULTI(BASE
), sizeof(MULTI(BASE
)));
77 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
78 multi
= FN(MULTI(BASE
),init_explicit_domain
)(multi
);
81 isl_space_free(space
);
85 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),dup
)(__isl_keep
MULTI(BASE
) *multi
)
93 dup
= FN(MULTI(BASE
),alloc
)(isl_space_copy(multi
->space
));
97 for (i
= 0; i
< multi
->n
; ++i
)
98 dup
= FN(FN(MULTI(BASE
),set
),BASE
)(dup
, i
,
99 FN(EL
,copy
)(multi
->u
.p
[i
]));
100 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
101 dup
= FN(MULTI(BASE
),copy_explicit_domain
)(dup
, multi
);
106 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),cow
)(__isl_take
MULTI(BASE
) *multi
)
115 return FN(MULTI(BASE
),dup
)(multi
);
118 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),copy
)(__isl_keep
MULTI(BASE
) *multi
)
127 __isl_null
MULTI(BASE
) *FN(MULTI(BASE
),free
)(__isl_take
MULTI(BASE
) *multi
)
134 if (--multi
->ref
> 0)
137 isl_space_free(multi
->space
);
138 for (i
= 0; i
< multi
->n
; ++i
)
139 FN(EL
,free
)(multi
->u
.p
[i
]);
140 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
141 FN(MULTI(BASE
),free_explicit_domain
)(multi
);
147 unsigned FN(MULTI(BASE
),dim
)(__isl_keep
MULTI(BASE
) *multi
,
148 enum isl_dim_type type
)
150 return multi
? isl_space_dim(multi
->space
, type
) : 0;
153 /* Return the position of the first dimension of "type" with id "id".
154 * Return -1 if there is no such dimension.
156 int FN(MULTI(BASE
),find_dim_by_id
)(__isl_keep
MULTI(BASE
) *multi
,
157 enum isl_dim_type type
, __isl_keep isl_id
*id
)
161 return isl_space_find_dim_by_id(multi
->space
, type
, id
);
164 /* Return the id of the given dimension.
166 __isl_give isl_id
*FN(MULTI(BASE
),get_dim_id
)(__isl_keep
MULTI(BASE
) *multi
,
167 enum isl_dim_type type
, unsigned pos
)
169 return multi
? isl_space_get_dim_id(multi
->space
, type
, pos
) : NULL
;
172 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_dim_name
)(
173 __isl_take
MULTI(BASE
) *multi
,
174 enum isl_dim_type type
, unsigned pos
, const char *s
)
178 multi
= FN(MULTI(BASE
),cow
)(multi
);
182 multi
->space
= isl_space_set_dim_name(multi
->space
, type
, pos
, s
);
184 return FN(MULTI(BASE
),free
)(multi
);
186 if (type
== isl_dim_out
)
188 for (i
= 0; i
< multi
->n
; ++i
) {
189 multi
->u
.p
[i
] = FN(EL
,set_dim_name
)(multi
->u
.p
[i
],
192 return FN(MULTI(BASE
),free
)(multi
);
198 const char *FN(MULTI(BASE
),get_tuple_name
)(__isl_keep
MULTI(BASE
) *multi
,
199 enum isl_dim_type type
)
201 return multi
? isl_space_get_tuple_name(multi
->space
, type
) : NULL
;
204 /* Does the specified tuple have an id?
206 isl_bool
FN(MULTI(BASE
),has_tuple_id
)(__isl_keep
MULTI(BASE
) *multi
,
207 enum isl_dim_type type
)
210 return isl_bool_error
;
211 return isl_space_has_tuple_id(multi
->space
, type
);
214 /* Return the id of the specified tuple.
216 __isl_give isl_id
*FN(MULTI(BASE
),get_tuple_id
)(__isl_keep
MULTI(BASE
) *multi
,
217 enum isl_dim_type type
)
219 return multi
? isl_space_get_tuple_id(multi
->space
, type
) : NULL
;
222 __isl_give EL
*FN(FN(MULTI(BASE
),get
),BASE
)(__isl_keep
MULTI(BASE
) *multi
,
229 ctx
= FN(MULTI(BASE
),get_ctx
)(multi
);
230 if (pos
< 0 || pos
>= multi
->n
)
231 isl_die(ctx
, isl_error_invalid
,
232 "index out of bounds", return NULL
);
233 return FN(EL
,copy
)(multi
->u
.p
[pos
]);
236 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),set
),BASE
)(
237 __isl_take
MULTI(BASE
) *multi
, int pos
, __isl_take EL
*el
)
239 isl_space
*multi_space
= NULL
;
240 isl_space
*el_space
= NULL
;
243 multi
= FN(MULTI(BASE
),cow
)(multi
);
247 multi_space
= FN(MULTI(BASE
),get_space
)(multi
);
248 match
= FN(EL
,matching_params
)(el
, multi_space
);
252 multi
= FN(MULTI(BASE
),align_params
)(multi
,
253 FN(EL
,get_space
)(el
));
254 isl_space_free(multi_space
);
255 multi_space
= FN(MULTI(BASE
),get_space
)(multi
);
256 el
= FN(EL
,align_params
)(el
, isl_space_copy(multi_space
));
258 if (FN(EL
,check_match_domain_space
)(el
, multi_space
) < 0)
261 if (pos
< 0 || pos
>= multi
->n
)
262 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
263 "index out of bounds", goto error
);
265 FN(EL
,free
)(multi
->u
.p
[pos
]);
266 multi
->u
.p
[pos
] = el
;
268 isl_space_free(multi_space
);
269 isl_space_free(el_space
);
273 FN(MULTI(BASE
),free
)(multi
);
275 isl_space_free(multi_space
);
276 isl_space_free(el_space
);
280 /* Reset the space of "multi". This function is called from isl_pw_templ.c
281 * and doesn't know if the space of an element object is represented
282 * directly or through its domain. It therefore passes along both,
283 * which we pass along to the element function since we don't know how
284 * that is represented either.
286 * If "multi" has an explicit domain, then the caller is expected
287 * to make sure that any modification that would change the dimensions
288 * of the explicit domain has bee applied before this function is called.
290 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_space_and_domain
)(
291 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*space
,
292 __isl_take isl_space
*domain
)
296 multi
= FN(MULTI(BASE
),cow
)(multi
);
297 if (!multi
|| !space
|| !domain
)
300 for (i
= 0; i
< multi
->n
; ++i
) {
301 multi
->u
.p
[i
] = FN(EL
,reset_domain_space
)(multi
->u
.p
[i
],
302 isl_space_copy(domain
));
306 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
)) {
307 multi
= FN(MULTI(BASE
),reset_explicit_domain_space
)(multi
,
308 isl_space_copy(domain
));
312 isl_space_free(domain
);
313 isl_space_free(multi
->space
);
314 multi
->space
= space
;
318 isl_space_free(domain
);
319 isl_space_free(space
);
320 FN(MULTI(BASE
),free
)(multi
);
324 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_domain_space
)(
325 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*domain
)
329 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
330 isl_space_copy(multi
->space
));
331 return FN(MULTI(BASE
),reset_space_and_domain
)(multi
, space
, domain
);
334 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_space
)(
335 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*space
)
339 domain
= isl_space_domain(isl_space_copy(space
));
340 return FN(MULTI(BASE
),reset_space_and_domain
)(multi
, space
, domain
);
343 /* Set the id of the given dimension of "multi" to "id".
345 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_dim_id
)(
346 __isl_take
MULTI(BASE
) *multi
,
347 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
351 multi
= FN(MULTI(BASE
),cow
)(multi
);
355 space
= FN(MULTI(BASE
),get_space
)(multi
);
356 space
= isl_space_set_dim_id(space
, type
, pos
, id
);
358 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
361 FN(MULTI(BASE
),free
)(multi
);
365 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_tuple_name
)(
366 __isl_keep
MULTI(BASE
) *multi
, enum isl_dim_type type
,
371 multi
= FN(MULTI(BASE
),cow
)(multi
);
375 space
= FN(MULTI(BASE
),get_space
)(multi
);
376 space
= isl_space_set_tuple_name(space
, type
, s
);
378 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
381 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_tuple_id
)(
382 __isl_take
MULTI(BASE
) *multi
, enum isl_dim_type type
,
383 __isl_take isl_id
*id
)
387 multi
= FN(MULTI(BASE
),cow
)(multi
);
391 space
= FN(MULTI(BASE
),get_space
)(multi
);
392 space
= isl_space_set_tuple_id(space
, type
, id
);
394 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
400 /* Drop the id on the specified tuple.
402 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_tuple_id
)(
403 __isl_take
MULTI(BASE
) *multi
, enum isl_dim_type type
)
409 if (!FN(MULTI(BASE
),has_tuple_id
)(multi
, type
))
412 multi
= FN(MULTI(BASE
),cow
)(multi
);
416 space
= FN(MULTI(BASE
),get_space
)(multi
);
417 space
= isl_space_reset_tuple_id(space
, type
);
419 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
422 /* Reset the user pointer on all identifiers of parameters and tuples
423 * of the space of "multi".
425 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_user
)(
426 __isl_take
MULTI(BASE
) *multi
)
430 space
= FN(MULTI(BASE
),get_space
)(multi
);
431 space
= isl_space_reset_user(space
);
433 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
436 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),realign_domain
)(
437 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_reordering
*exp
)
441 multi
= FN(MULTI(BASE
),cow
)(multi
);
445 for (i
= 0; i
< multi
->n
; ++i
) {
446 multi
->u
.p
[i
] = FN(EL
,realign_domain
)(multi
->u
.p
[i
],
447 isl_reordering_copy(exp
));
452 multi
= FN(MULTI(BASE
),reset_domain_space
)(multi
,
453 isl_space_copy(exp
->dim
));
455 isl_reordering_free(exp
);
458 isl_reordering_free(exp
);
459 FN(MULTI(BASE
),free
)(multi
);
463 /* Align the parameters of "multi" to those of "model".
465 * If "multi" has an explicit domain, then align the parameters
466 * of the domain first.
468 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),align_params
)(
469 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*model
)
472 isl_bool equal_params
;
475 if (!multi
|| !model
)
478 equal_params
= isl_space_has_equal_params(multi
->space
, model
);
479 if (equal_params
< 0)
482 isl_space_free(model
);
486 ctx
= isl_space_get_ctx(model
);
487 if (!isl_space_has_named_params(model
))
488 isl_die(ctx
, isl_error_invalid
,
489 "model has unnamed parameters", goto error
);
490 if (!isl_space_has_named_params(multi
->space
))
491 isl_die(ctx
, isl_error_invalid
,
492 "input has unnamed parameters", goto error
);
494 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
)) {
495 multi
= FN(MULTI(BASE
),align_explicit_domain_params
)(multi
,
496 isl_space_copy(model
));
500 model
= isl_space_params(model
);
501 exp
= isl_parameter_alignment_reordering(multi
->space
, model
);
502 exp
= isl_reordering_extend_space(exp
,
503 FN(MULTI(BASE
),get_domain_space
)(multi
));
504 multi
= FN(MULTI(BASE
),realign_domain
)(multi
, exp
);
506 isl_space_free(model
);
509 isl_space_free(model
);
510 FN(MULTI(BASE
),free
)(multi
);
514 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),from
),LIST(BASE
))(
515 __isl_take isl_space
*space
, __isl_take
LIST(EL
) *list
)
525 ctx
= isl_space_get_ctx(space
);
526 n
= FN(FN(LIST(EL
),n
),BASE
)(list
);
527 if (n
!= isl_space_dim(space
, isl_dim_out
))
528 isl_die(ctx
, isl_error_invalid
,
529 "invalid number of elements in list", goto error
);
531 multi
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
532 for (i
= 0; i
< n
; ++i
) {
533 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, i
,
534 FN(FN(LIST(EL
),get
),BASE
)(list
, i
));
537 isl_space_free(space
);
538 FN(LIST(EL
),free
)(list
);
541 isl_space_free(space
);
542 FN(LIST(EL
),free
)(list
);
547 /* Create a multi expression in the given space that maps each
548 * input dimension to the corresponding output dimension.
550 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),identity
)(__isl_take isl_space
*space
)
559 if (isl_space_is_set(space
))
560 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
561 "expecting map space", goto error
);
563 n
= isl_space_dim(space
, isl_dim_out
);
564 if (n
!= isl_space_dim(space
, isl_dim_in
))
565 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
566 "number of input and output dimensions needs to be "
567 "the same", goto error
);
569 multi
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
572 isl_space_free(space
);
576 space
= isl_space_domain(space
);
577 ls
= isl_local_space_from_space(space
);
579 for (i
= 0; i
< n
; ++i
) {
581 el
= FN(EL
,var_on_domain
)(isl_local_space_copy(ls
),
583 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, i
, el
);
586 isl_local_space_free(ls
);
590 isl_space_free(space
);
596 /* Construct a multi expression in the given space with value zero in
597 * each of the output dimensions.
599 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),zero
)(__isl_take isl_space
*space
)
607 n
= isl_space_dim(space
, isl_dim_out
);
608 multi
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
611 isl_space_free(space
);
617 space
= isl_space_domain(space
);
618 ls
= isl_local_space_from_space(space
);
619 el
= FN(EL
,zero_on_domain
)(ls
);
621 for (i
= 0; i
< n
; ++i
)
622 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, i
,
633 /* Create a multiple expression with a single output/set dimension
635 * For most multiple expression types, the base type has a single
636 * output/set dimension and the space of the result is therefore
637 * the same as the space of the input.
638 * In the case of isl_multi_union_pw_aff, however, the base type
639 * lives in a parameter space and we therefore need to add
640 * a single set dimension.
642 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),from
),BASE
)(__isl_take EL
*el
)
647 space
= FN(EL
,get_space(el
));
648 if (isl_space_is_params(space
)) {
649 space
= isl_space_set_from_params(space
);
650 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
652 multi
= FN(MULTI(BASE
),alloc
)(space
);
653 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, 0, el
);
659 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),drop_dims
)(
660 __isl_take
MULTI(BASE
) *multi
,
661 enum isl_dim_type type
, unsigned first
, unsigned n
)
666 multi
= FN(MULTI(BASE
),cow
)(multi
);
670 dim
= FN(MULTI(BASE
),dim
)(multi
, type
);
671 if (first
+ n
> dim
|| first
+ n
< first
)
672 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
673 "index out of bounds",
674 return FN(MULTI(BASE
),free
)(multi
));
676 multi
->space
= isl_space_drop_dims(multi
->space
, type
, first
, n
);
678 return FN(MULTI(BASE
),free
)(multi
);
680 if (type
== isl_dim_out
) {
681 for (i
= 0; i
< n
; ++i
)
682 FN(EL
,free
)(multi
->u
.p
[first
+ i
]);
683 for (i
= first
; i
+ n
< multi
->n
; ++i
)
684 multi
->u
.p
[i
] = multi
->u
.p
[i
+ n
];
686 if (n
> 0 && FN(MULTI(BASE
),has_explicit_domain
)(multi
))
687 multi
= FN(MULTI(BASE
),init_explicit_domain
)(multi
);
692 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
693 multi
= FN(MULTI(BASE
),drop_explicit_domain_dims
)(multi
,
698 for (i
= 0; i
< multi
->n
; ++i
) {
699 multi
->u
.p
[i
] = FN(EL
,drop_dims
)(multi
->u
.p
[i
], type
, first
, n
);
701 return FN(MULTI(BASE
),free
)(multi
);
707 /* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
709 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),align_params_multi_multi_and
)(
710 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
711 __isl_give
MULTI(BASE
) *(*fn
)(__isl_take
MULTI(BASE
) *multi1
,
712 __isl_take
MULTI(BASE
) *multi2
))
715 isl_bool equal_params
;
717 if (!multi1
|| !multi2
)
719 equal_params
= isl_space_has_equal_params(multi1
->space
, multi2
->space
);
720 if (equal_params
< 0)
723 return fn(multi1
, multi2
);
724 ctx
= FN(MULTI(BASE
),get_ctx
)(multi1
);
725 if (!isl_space_has_named_params(multi1
->space
) ||
726 !isl_space_has_named_params(multi2
->space
))
727 isl_die(ctx
, isl_error_invalid
,
728 "unaligned unnamed parameters", goto error
);
729 multi1
= FN(MULTI(BASE
),align_params
)(multi1
,
730 FN(MULTI(BASE
),get_space
)(multi2
));
731 multi2
= FN(MULTI(BASE
),align_params
)(multi2
,
732 FN(MULTI(BASE
),get_space
)(multi1
));
733 return fn(multi1
, multi2
);
735 FN(MULTI(BASE
),free
)(multi1
);
736 FN(MULTI(BASE
),free
)(multi2
);
740 /* Given two MULTI(BASE)s A -> B and C -> D,
741 * construct a MULTI(BASE) (A * C) -> [B -> D].
743 * The parameters are assumed to have been aligned.
745 * If "multi1" and/or "multi2" has an explicit domain, then
746 * intersect the domain of the result with these explicit domains.
748 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_product_aligned
)(
749 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
756 if (!multi1
|| !multi2
)
759 space
= isl_space_range_product(FN(MULTI(BASE
),get_space
)(multi1
),
760 FN(MULTI(BASE
),get_space
)(multi2
));
761 res
= FN(MULTI(BASE
),alloc
)(space
);
763 n1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
764 n2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_out
);
766 for (i
= 0; i
< n1
; ++i
) {
767 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi1
, i
);
768 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, i
, el
);
771 for (i
= 0; i
< n2
; ++i
) {
772 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi2
, i
);
773 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, n1
+ i
, el
);
776 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
))
777 res
= FN(MULTI(BASE
),intersect_explicit_domain
)(res
, multi1
);
778 if (FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
779 res
= FN(MULTI(BASE
),intersect_explicit_domain
)(res
, multi2
);
781 FN(MULTI(BASE
),free
)(multi1
);
782 FN(MULTI(BASE
),free
)(multi2
);
785 FN(MULTI(BASE
),free
)(multi1
);
786 FN(MULTI(BASE
),free
)(multi2
);
790 /* Given two MULTI(BASE)s A -> B and C -> D,
791 * construct a MULTI(BASE) (A * C) -> [B -> D].
793 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_product
)(
794 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
796 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
797 &FN(MULTI(BASE
),range_product_aligned
));
800 /* Is the range of "multi" a wrapped relation?
802 isl_bool
FN(MULTI(BASE
),range_is_wrapping
)(__isl_keep
MULTI(BASE
) *multi
)
805 return isl_bool_error
;
806 return isl_space_range_is_wrapping(multi
->space
);
809 /* Given a function A -> [B -> C], extract the function A -> B.
811 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_factor_domain
)(
812 __isl_take
MULTI(BASE
) *multi
)
819 if (!isl_space_range_is_wrapping(multi
->space
))
820 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
821 "range is not a product",
822 return FN(MULTI(BASE
),free
)(multi
));
824 space
= FN(MULTI(BASE
),get_space
)(multi
);
825 total
= isl_space_dim(space
, isl_dim_out
);
826 space
= isl_space_range_factor_domain(space
);
827 keep
= isl_space_dim(space
, isl_dim_out
);
828 multi
= FN(MULTI(BASE
),drop_dims
)(multi
,
829 isl_dim_out
, keep
, total
- keep
);
830 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
835 /* Given a function A -> [B -> C], extract the function A -> C.
837 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_factor_range
)(
838 __isl_take
MULTI(BASE
) *multi
)
845 if (!isl_space_range_is_wrapping(multi
->space
))
846 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
847 "range is not a product",
848 return FN(MULTI(BASE
),free
)(multi
));
850 space
= FN(MULTI(BASE
),get_space
)(multi
);
851 total
= isl_space_dim(space
, isl_dim_out
);
852 space
= isl_space_range_factor_range(space
);
853 keep
= isl_space_dim(space
, isl_dim_out
);
854 multi
= FN(MULTI(BASE
),drop_dims
)(multi
, isl_dim_out
, 0, total
- keep
);
855 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
860 /* Given a function [B -> C], extract the function C.
862 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),factor_range
)(
863 __isl_take
MULTI(BASE
) *multi
)
870 if (!isl_space_is_wrapping(multi
->space
))
871 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
872 "not a product", return FN(MULTI(BASE
),free
)(multi
));
874 space
= FN(MULTI(BASE
),get_space
)(multi
);
875 total
= isl_space_dim(space
, isl_dim_out
);
876 space
= isl_space_factor_range(space
);
877 keep
= isl_space_dim(space
, isl_dim_out
);
878 multi
= FN(MULTI(BASE
),drop_dims
)(multi
, isl_dim_out
, 0, total
- keep
);
879 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
885 /* Given two MULTI(BASE)s A -> B and C -> D,
886 * construct a MULTI(BASE) [A -> C] -> [B -> D].
888 * The parameters are assumed to have been aligned.
890 * If "multi1" and/or "multi2" has an explicit domain, then
891 * intersect the domain of the result with these explicit domains.
893 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),product_aligned
)(
894 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
900 int in1
, in2
, out1
, out2
;
902 in1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_in
);
903 in2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_in
);
904 out1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
905 out2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_out
);
906 space
= isl_space_product(FN(MULTI(BASE
),get_space
)(multi1
),
907 FN(MULTI(BASE
),get_space
)(multi2
));
908 res
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
909 space
= isl_space_domain(space
);
911 for (i
= 0; i
< out1
; ++i
) {
912 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi1
, i
);
913 el
= FN(EL
,insert_dims
)(el
, isl_dim_in
, in1
, in2
);
914 el
= FN(EL
,reset_domain_space
)(el
, isl_space_copy(space
));
915 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, i
, el
);
918 for (i
= 0; i
< out2
; ++i
) {
919 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi2
, i
);
920 el
= FN(EL
,insert_dims
)(el
, isl_dim_in
, 0, in1
);
921 el
= FN(EL
,reset_domain_space
)(el
, isl_space_copy(space
));
922 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, out1
+ i
, el
);
925 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
) ||
926 FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
927 res
= FN(MULTI(BASE
),intersect_explicit_domain_product
)(res
,
930 isl_space_free(space
);
931 FN(MULTI(BASE
),free
)(multi1
);
932 FN(MULTI(BASE
),free
)(multi2
);
936 /* Given two MULTI(BASE)s A -> B and C -> D,
937 * construct a MULTI(BASE) [A -> C] -> [B -> D].
939 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),product
)(
940 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
942 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
943 &FN(MULTI(BASE
),product_aligned
));
947 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),flatten_range
)(
948 __isl_take
MULTI(BASE
) *multi
)
953 if (!multi
->space
->nested
[1])
956 multi
= FN(MULTI(BASE
),cow
)(multi
);
960 multi
->space
= isl_space_flatten_range(multi
->space
);
962 return FN(MULTI(BASE
),free
)(multi
);
967 /* Given two MULTI(BASE)s A -> B and C -> D,
968 * construct a MULTI(BASE) (A * C) -> (B, D).
970 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),flat_range_product
)(
971 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
975 multi
= FN(MULTI(BASE
),range_product
)(multi1
, multi2
);
976 multi
= FN(MULTI(BASE
),flatten_range
)(multi
);
980 /* Given two multi expressions, "multi1"
984 * where B2 starts at position "pos", and "multi2"
988 * return the multi expression
992 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_splice
)(
993 __isl_take
MULTI(BASE
) *multi1
, unsigned pos
,
994 __isl_take
MULTI(BASE
) *multi2
)
999 if (!multi1
|| !multi2
)
1002 dim
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
1004 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1005 "index out of bounds", goto error
);
1007 res
= FN(MULTI(BASE
),copy
)(multi1
);
1008 res
= FN(MULTI(BASE
),drop_dims
)(res
, isl_dim_out
, pos
, dim
- pos
);
1009 multi1
= FN(MULTI(BASE
),drop_dims
)(multi1
, isl_dim_out
, 0, pos
);
1011 res
= FN(MULTI(BASE
),flat_range_product
)(res
, multi2
);
1012 res
= FN(MULTI(BASE
),flat_range_product
)(res
, multi1
);
1016 FN(MULTI(BASE
),free
)(multi1
);
1017 FN(MULTI(BASE
),free
)(multi2
);
1022 /* Given two multi expressions, "multi1"
1024 * [A1 A2] -> [B1 B2]
1026 * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
1031 * return the multi expression
1033 * [A1 C A2] -> [B1 D B2]
1035 * We first insert input dimensions to obtain
1037 * [A1 C A2] -> [B1 B2]
1043 * and then apply range_splice.
1045 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),splice
)(
1046 __isl_take
MULTI(BASE
) *multi1
, unsigned in_pos
, unsigned out_pos
,
1047 __isl_take
MULTI(BASE
) *multi2
)
1052 if (!multi1
|| !multi2
)
1055 n_in1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_in
);
1057 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1058 "index out of bounds", goto error
);
1060 n_in2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_in
);
1062 multi1
= FN(MULTI(BASE
),insert_dims
)(multi1
, isl_dim_in
, in_pos
, n_in2
);
1063 multi2
= FN(MULTI(BASE
),insert_dims
)(multi2
, isl_dim_in
, n_in2
,
1065 multi2
= FN(MULTI(BASE
),insert_dims
)(multi2
, isl_dim_in
, 0, in_pos
);
1067 return FN(MULTI(BASE
),range_splice
)(multi1
, out_pos
, multi2
);
1069 FN(MULTI(BASE
),free
)(multi1
);
1070 FN(MULTI(BASE
),free
)(multi2
);
1075 /* Check that "multi1" and "multi2" live in the same space,
1076 * reporting an error if they do not.
1078 static isl_stat
FN(MULTI(BASE
),check_equal_space
)(
1079 __isl_keep
MULTI(BASE
) *multi1
, __isl_keep
MULTI(BASE
) *multi2
)
1083 if (!multi1
|| !multi2
)
1084 return isl_stat_error
;
1086 equal
= isl_space_is_equal(multi1
->space
, multi2
->space
);
1088 return isl_stat_error
;
1090 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1091 "spaces don't match", return isl_stat_error
);
1096 /* This function is currently only used from isl_aff.c
1098 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),bin_op
)(
1099 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
1100 __isl_give EL
*(*fn
)(__isl_take EL
*, __isl_take EL
*))
1101 __attribute__ ((unused
));
1103 /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
1104 * return the result.
1106 * If "multi2" has an explicit domain, then
1107 * intersect the domain of the result with this explicit domain.
1109 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),bin_op
)(
1110 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
1111 __isl_give EL
*(*fn
)(__isl_take EL
*, __isl_take EL
*))
1115 multi1
= FN(MULTI(BASE
),cow
)(multi1
);
1116 if (FN(MULTI(BASE
),check_equal_space
)(multi1
, multi2
) < 0)
1119 for (i
= 0; i
< multi1
->n
; ++i
) {
1120 multi1
->u
.p
[i
] = fn(multi1
->u
.p
[i
],
1121 FN(EL
,copy
)(multi2
->u
.p
[i
]));
1122 if (!multi1
->u
.p
[i
])
1126 if (FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
1127 multi1
= FN(MULTI(BASE
),intersect_explicit_domain
)(multi1
,
1130 FN(MULTI(BASE
),free
)(multi2
);
1133 FN(MULTI(BASE
),free
)(multi1
);
1134 FN(MULTI(BASE
),free
)(multi2
);
1138 /* Add "multi2" from "multi1" and return the result.
1140 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1142 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),add_aligned
)(
1143 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
1145 return FN(MULTI(BASE
),bin_op
)(multi1
, multi2
, &FN(EL
,add
));
1148 /* Add "multi2" from "multi1" and return the result.
1150 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),add
)(__isl_take
MULTI(BASE
) *multi1
,
1151 __isl_take
MULTI(BASE
) *multi2
)
1153 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
1154 &FN(MULTI(BASE
),add_aligned
));
1157 /* Subtract "multi2" from "multi1" and return the result.
1159 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1161 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),sub_aligned
)(
1162 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
1164 return FN(MULTI(BASE
),bin_op
)(multi1
, multi2
, &FN(EL
,sub
));
1167 /* Subtract "multi2" from "multi1" and return the result.
1169 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),sub
)(__isl_take
MULTI(BASE
) *multi1
,
1170 __isl_take
MULTI(BASE
) *multi2
)
1172 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
1173 &FN(MULTI(BASE
),sub_aligned
));
1176 /* Multiply the elements of "multi" by "v" and return the result.
1178 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_val
)(__isl_take
MULTI(BASE
) *multi
,
1179 __isl_take isl_val
*v
)
1186 if (isl_val_is_one(v
)) {
1191 if (!isl_val_is_rat(v
))
1192 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1193 "expecting rational factor", goto error
);
1195 multi
= FN(MULTI(BASE
),cow
)(multi
);
1199 for (i
= 0; i
< multi
->n
; ++i
) {
1200 multi
->u
.p
[i
] = FN(EL
,scale_val
)(multi
->u
.p
[i
],
1210 return FN(MULTI(BASE
),free
)(multi
);
1213 /* Divide the elements of "multi" by "v" and return the result.
1215 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_down_val
)(
1216 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_val
*v
)
1223 if (isl_val_is_one(v
)) {
1228 if (!isl_val_is_rat(v
))
1229 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1230 "expecting rational factor", goto error
);
1231 if (isl_val_is_zero(v
))
1232 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1233 "cannot scale down by zero", goto error
);
1235 multi
= FN(MULTI(BASE
),cow
)(multi
);
1239 for (i
= 0; i
< multi
->n
; ++i
) {
1240 multi
->u
.p
[i
] = FN(EL
,scale_down_val
)(multi
->u
.p
[i
],
1250 return FN(MULTI(BASE
),free
)(multi
);
1253 /* Multiply the elements of "multi" by the corresponding element of "mv"
1254 * and return the result.
1256 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_multi_val
)(
1257 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1264 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1265 mv
->space
, isl_dim_set
))
1266 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1267 "spaces don't match", goto error
);
1269 multi
= FN(MULTI(BASE
),cow
)(multi
);
1273 for (i
= 0; i
< multi
->n
; ++i
) {
1276 v
= isl_multi_val_get_val(mv
, i
);
1277 multi
->u
.p
[i
] = FN(EL
,scale_val
)(multi
->u
.p
[i
], v
);
1282 isl_multi_val_free(mv
);
1285 isl_multi_val_free(mv
);
1286 return FN(MULTI(BASE
),free
)(multi
);
1289 /* Divide the elements of "multi" by the corresponding element of "mv"
1290 * and return the result.
1292 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_down_multi_val
)(
1293 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1300 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1301 mv
->space
, isl_dim_set
))
1302 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1303 "spaces don't match", goto error
);
1305 multi
= FN(MULTI(BASE
),cow
)(multi
);
1309 for (i
= 0; i
< multi
->n
; ++i
) {
1312 v
= isl_multi_val_get_val(mv
, i
);
1313 multi
->u
.p
[i
] = FN(EL
,scale_down_val
)(multi
->u
.p
[i
], v
);
1318 isl_multi_val_free(mv
);
1321 isl_multi_val_free(mv
);
1322 return FN(MULTI(BASE
),free
)(multi
);
1325 /* Compute the residues of the elements of "multi" modulo
1326 * the corresponding element of "mv" and return the result.
1328 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),mod_multi_val
)(
1329 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1336 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1337 mv
->space
, isl_dim_set
))
1338 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1339 "spaces don't match", goto error
);
1341 multi
= FN(MULTI(BASE
),cow
)(multi
);
1345 for (i
= 0; i
< multi
->n
; ++i
) {
1348 v
= isl_multi_val_get_val(mv
, i
);
1349 multi
->u
.p
[i
] = FN(EL
,mod_val
)(multi
->u
.p
[i
], v
);
1354 isl_multi_val_free(mv
);
1357 isl_multi_val_free(mv
);
1358 return FN(MULTI(BASE
),free
)(multi
);
1361 #ifndef NO_MOVE_DIMS
1362 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
1363 * to dimensions of "dst_type" at "dst_pos".
1365 * We only support moving input dimensions to parameters and vice versa.
1367 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),move_dims
)(__isl_take
MULTI(BASE
) *multi
,
1368 enum isl_dim_type dst_type
, unsigned dst_pos
,
1369 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1377 !isl_space_is_named_or_nested(multi
->space
, src_type
) &&
1378 !isl_space_is_named_or_nested(multi
->space
, dst_type
))
1381 if (dst_type
== isl_dim_out
|| src_type
== isl_dim_out
)
1382 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1383 "cannot move output/set dimension",
1384 return FN(MULTI(BASE
),free
)(multi
));
1385 if (dst_type
== isl_dim_div
|| src_type
== isl_dim_div
)
1386 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1388 return FN(MULTI(BASE
),free
)(multi
));
1389 if (src_pos
+ n
> isl_space_dim(multi
->space
, src_type
))
1390 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1391 "range out of bounds",
1392 return FN(MULTI(BASE
),free
)(multi
));
1393 if (dst_type
== src_type
)
1394 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_unsupported
,
1395 "moving dims within the same type not supported",
1396 return FN(MULTI(BASE
),free
)(multi
));
1398 multi
= FN(MULTI(BASE
),cow
)(multi
);
1402 multi
->space
= isl_space_move_dims(multi
->space
, dst_type
, dst_pos
,
1403 src_type
, src_pos
, n
);
1405 return FN(MULTI(BASE
),free
)(multi
);
1406 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
1407 multi
= FN(MULTI(BASE
),move_explicit_domain_dims
)(multi
,
1408 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1412 for (i
= 0; i
< multi
->n
; ++i
) {
1413 multi
->u
.p
[i
] = FN(EL
,move_dims
)(multi
->u
.p
[i
],
1415 src_type
, src_pos
, n
);
1417 return FN(MULTI(BASE
),free
)(multi
);
1424 /* Convert a multiple expression defined over a parameter domain
1425 * into one that is defined over a zero-dimensional set.
1427 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),from_range
)(
1428 __isl_take
MULTI(BASE
) *multi
)
1434 if (!isl_space_is_set(multi
->space
))
1435 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1436 "not living in a set space",
1437 return FN(MULTI(BASE
),free
)(multi
));
1439 space
= FN(MULTI(BASE
),get_space
)(multi
);
1440 space
= isl_space_from_range(space
);
1441 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
1446 /* Are "multi1" and "multi2" obviously equal?
1448 isl_bool
FN(MULTI(BASE
),plain_is_equal
)(__isl_keep
MULTI(BASE
) *multi1
,
1449 __isl_keep
MULTI(BASE
) *multi2
)
1454 if (!multi1
|| !multi2
)
1455 return isl_bool_error
;
1456 if (multi1
->n
!= multi2
->n
)
1457 return isl_bool_false
;
1458 equal
= isl_space_is_equal(multi1
->space
, multi2
->space
);
1459 if (equal
< 0 || !equal
)
1462 for (i
= 0; i
< multi1
->n
; ++i
) {
1463 equal
= FN(EL
,plain_is_equal
)(multi1
->u
.p
[i
], multi2
->u
.p
[i
]);
1464 if (equal
< 0 || !equal
)
1468 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
) ||
1469 FN(MULTI(BASE
),has_explicit_domain
)(multi2
)) {
1470 equal
= FN(MULTI(BASE
),equal_explicit_domain
)(multi1
, multi2
);
1471 if (equal
< 0 || !equal
)
1475 return isl_bool_true
;
1478 /* Does "multi" involve any NaNs?
1480 isl_bool
FN(MULTI(BASE
),involves_nan
)(__isl_keep
MULTI(BASE
) *multi
)
1485 return isl_bool_error
;
1487 return isl_bool_false
;
1489 for (i
= 0; i
< multi
->n
; ++i
) {
1490 isl_bool has_nan
= FN(EL
,involves_nan
)(multi
->u
.p
[i
]);
1491 if (has_nan
< 0 || has_nan
)
1495 return isl_bool_false
;
1499 /* Return the shared domain of the elements of "multi".
1501 * If "multi" has an explicit domain, then return this domain.
1503 __isl_give isl_set
*FN(MULTI(BASE
),domain
)(__isl_take
MULTI(BASE
) *multi
)
1511 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
)) {
1512 dom
= FN(MULTI(BASE
),get_explicit_domain
)(multi
);
1513 FN(MULTI(BASE
),free
)(multi
);
1517 dom
= isl_set_universe(FN(MULTI(BASE
),get_domain_space
)(multi
));
1518 for (i
= 0; i
< multi
->n
; ++i
) {
1521 dom_i
= FN(EL
,domain
)(FN(FN(MULTI(BASE
),get
),BASE
)(multi
, i
));
1522 dom
= isl_set_intersect(dom
, dom_i
);
1525 FN(MULTI(BASE
),free
)(multi
);
1531 /* Return the opposite of "multi".
1533 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),neg
)(__isl_take
MULTI(BASE
) *multi
)
1537 multi
= FN(MULTI(BASE
),cow
)(multi
);
1541 for (i
= 0; i
< multi
->n
; ++i
) {
1542 multi
->u
.p
[i
] = FN(EL
,neg
)(multi
->u
.p
[i
]);
1544 return FN(MULTI(BASE
),free
)(multi
);