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 /* Return the space of "multi".
30 __isl_keep isl_space
*FN(MULTI(BASE
),peek_space
)(__isl_keep
MULTI(BASE
) *multi
)
32 return multi
? multi
->space
: NULL
;
35 __isl_give isl_space
*FN(MULTI(BASE
),get_space
)(__isl_keep
MULTI(BASE
) *multi
)
37 return isl_space_copy(FN(MULTI(BASE
),peek_space
)(multi
));
40 /* Return the position of the dimension of the given type and name
42 * Return -1 if no such dimension can be found.
44 int FN(MULTI(BASE
),find_dim_by_name
)(__isl_keep
MULTI(BASE
) *multi
,
45 enum isl_dim_type type
, const char *name
)
49 return isl_space_find_dim_by_name(multi
->space
, type
, name
);
52 __isl_give isl_space
*FN(MULTI(BASE
),get_domain_space
)(
53 __isl_keep
MULTI(BASE
) *multi
)
55 return multi
? isl_space_domain(isl_space_copy(multi
->space
)) : NULL
;
58 /* Allocate a multi expression living in "space".
60 * If the number of base expressions is zero, then make sure
61 * there is enough room in the structure for the explicit domain,
62 * in case the type supports such an explicit domain.
64 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),alloc
)(__isl_take isl_space
*space
)
73 ctx
= isl_space_get_ctx(space
);
74 n
= isl_space_dim(space
, isl_dim_out
);
76 multi
= isl_calloc(ctx
, MULTI(BASE
),
77 sizeof(MULTI(BASE
)) + (n
- 1) * sizeof(struct EL
*));
79 multi
= isl_calloc(ctx
, MULTI(BASE
), sizeof(MULTI(BASE
)));
86 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
87 multi
= FN(MULTI(BASE
),init_explicit_domain
)(multi
);
90 isl_space_free(space
);
94 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),dup
)(__isl_keep
MULTI(BASE
) *multi
)
102 dup
= FN(MULTI(BASE
),alloc
)(isl_space_copy(multi
->space
));
106 for (i
= 0; i
< multi
->n
; ++i
)
107 dup
= FN(FN(MULTI(BASE
),set
),BASE
)(dup
, i
,
108 FN(EL
,copy
)(multi
->u
.p
[i
]));
109 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
110 dup
= FN(MULTI(BASE
),copy_explicit_domain
)(dup
, multi
);
115 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),cow
)(__isl_take
MULTI(BASE
) *multi
)
124 return FN(MULTI(BASE
),dup
)(multi
);
127 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),copy
)(__isl_keep
MULTI(BASE
) *multi
)
136 __isl_null
MULTI(BASE
) *FN(MULTI(BASE
),free
)(__isl_take
MULTI(BASE
) *multi
)
143 if (--multi
->ref
> 0)
146 isl_space_free(multi
->space
);
147 for (i
= 0; i
< multi
->n
; ++i
)
148 FN(EL
,free
)(multi
->u
.p
[i
]);
149 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
150 FN(MULTI(BASE
),free_explicit_domain
)(multi
);
156 unsigned FN(MULTI(BASE
),dim
)(__isl_keep
MULTI(BASE
) *multi
,
157 enum isl_dim_type type
)
159 return multi
? isl_space_dim(multi
->space
, type
) : 0;
162 /* Return the position of the first dimension of "type" with id "id".
163 * Return -1 if there is no such dimension.
165 int FN(MULTI(BASE
),find_dim_by_id
)(__isl_keep
MULTI(BASE
) *multi
,
166 enum isl_dim_type type
, __isl_keep isl_id
*id
)
170 return isl_space_find_dim_by_id(multi
->space
, type
, id
);
173 /* Return the id of the given dimension.
175 __isl_give isl_id
*FN(MULTI(BASE
),get_dim_id
)(__isl_keep
MULTI(BASE
) *multi
,
176 enum isl_dim_type type
, unsigned pos
)
178 return multi
? isl_space_get_dim_id(multi
->space
, type
, pos
) : NULL
;
181 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_dim_name
)(
182 __isl_take
MULTI(BASE
) *multi
,
183 enum isl_dim_type type
, unsigned pos
, const char *s
)
187 multi
= FN(MULTI(BASE
),cow
)(multi
);
191 multi
->space
= isl_space_set_dim_name(multi
->space
, type
, pos
, s
);
193 return FN(MULTI(BASE
),free
)(multi
);
195 if (type
== isl_dim_out
)
197 for (i
= 0; i
< multi
->n
; ++i
) {
198 multi
->u
.p
[i
] = FN(EL
,set_dim_name
)(multi
->u
.p
[i
],
201 return FN(MULTI(BASE
),free
)(multi
);
207 const char *FN(MULTI(BASE
),get_tuple_name
)(__isl_keep
MULTI(BASE
) *multi
,
208 enum isl_dim_type type
)
210 return multi
? isl_space_get_tuple_name(multi
->space
, type
) : NULL
;
213 /* Does the specified tuple have an id?
215 isl_bool
FN(MULTI(BASE
),has_tuple_id
)(__isl_keep
MULTI(BASE
) *multi
,
216 enum isl_dim_type type
)
219 return isl_bool_error
;
220 return isl_space_has_tuple_id(multi
->space
, type
);
223 /* Return the id of the specified tuple.
225 __isl_give isl_id
*FN(MULTI(BASE
),get_tuple_id
)(__isl_keep
MULTI(BASE
) *multi
,
226 enum isl_dim_type type
)
228 return multi
? isl_space_get_tuple_id(multi
->space
, type
) : NULL
;
231 __isl_give EL
*FN(FN(MULTI(BASE
),get
),BASE
)(__isl_keep
MULTI(BASE
) *multi
,
238 ctx
= FN(MULTI(BASE
),get_ctx
)(multi
);
239 if (pos
< 0 || pos
>= multi
->n
)
240 isl_die(ctx
, isl_error_invalid
,
241 "index out of bounds", return NULL
);
242 return FN(EL
,copy
)(multi
->u
.p
[pos
]);
245 /* Set the element at position "pos" of "multi" to "el",
246 * where the position may be empty if "multi" has only a single reference.
248 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),restore
)(
249 __isl_take
MULTI(BASE
) *multi
, int pos
, __isl_take EL
*el
)
251 multi
= FN(MULTI(BASE
),cow
)(multi
);
255 if (pos
< 0 || pos
>= multi
->n
)
256 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
257 "index out of bounds", goto error
);
259 FN(EL
,free
)(multi
->u
.p
[pos
]);
260 multi
->u
.p
[pos
] = el
;
264 FN(MULTI(BASE
),free
)(multi
);
269 /* Set the element at position "pos" of "multi" to "el",
270 * where the position may be empty if "multi" has only a single reference.
271 * However, the space of "multi" is available and is checked
272 * for compatibility with "el".
274 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),restore_check_space
)(
275 __isl_take
MULTI(BASE
) *multi
, int pos
, __isl_take EL
*el
)
279 space
= FN(MULTI(BASE
),peek_space
)(multi
);
280 if (FN(EL
,check_match_domain_space
)(el
, space
) < 0)
281 multi
= FN(MULTI(BASE
),free
)(multi
);
282 return FN(MULTI(BASE
),restore
)(multi
, pos
, el
);
285 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),set
),BASE
)(
286 __isl_take
MULTI(BASE
) *multi
, int pos
, __isl_take EL
*el
)
288 isl_space
*multi_space
= NULL
;
289 isl_space
*el_space
= NULL
;
292 multi_space
= FN(MULTI(BASE
),get_space
)(multi
);
293 match
= FN(EL
,matching_params
)(el
, multi_space
);
297 multi
= FN(MULTI(BASE
),align_params
)(multi
,
298 FN(EL
,get_space
)(el
));
299 isl_space_free(multi_space
);
300 multi_space
= FN(MULTI(BASE
),get_space
)(multi
);
301 el
= FN(EL
,align_params
)(el
, isl_space_copy(multi_space
));
304 multi
= FN(MULTI(BASE
),restore_check_space
)(multi
, pos
, el
);
306 isl_space_free(multi_space
);
307 isl_space_free(el_space
);
311 FN(MULTI(BASE
),free
)(multi
);
313 isl_space_free(multi_space
);
314 isl_space_free(el_space
);
318 /* Reset the space of "multi". This function is called from isl_pw_templ.c
319 * and doesn't know if the space of an element object is represented
320 * directly or through its domain. It therefore passes along both,
321 * which we pass along to the element function since we don't know how
322 * that is represented either.
324 * If "multi" has an explicit domain, then the caller is expected
325 * to make sure that any modification that would change the dimensions
326 * of the explicit domain has bee applied before this function is called.
328 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_space_and_domain
)(
329 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*space
,
330 __isl_take isl_space
*domain
)
334 multi
= FN(MULTI(BASE
),cow
)(multi
);
335 if (!multi
|| !space
|| !domain
)
338 for (i
= 0; i
< multi
->n
; ++i
) {
339 multi
->u
.p
[i
] = FN(EL
,reset_domain_space
)(multi
->u
.p
[i
],
340 isl_space_copy(domain
));
344 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
)) {
345 multi
= FN(MULTI(BASE
),reset_explicit_domain_space
)(multi
,
346 isl_space_copy(domain
));
350 isl_space_free(domain
);
351 isl_space_free(multi
->space
);
352 multi
->space
= space
;
356 isl_space_free(domain
);
357 isl_space_free(space
);
358 FN(MULTI(BASE
),free
)(multi
);
362 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_domain_space
)(
363 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*domain
)
367 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
368 isl_space_copy(multi
->space
));
369 return FN(MULTI(BASE
),reset_space_and_domain
)(multi
, space
, domain
);
372 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_space
)(
373 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*space
)
377 domain
= isl_space_domain(isl_space_copy(space
));
378 return FN(MULTI(BASE
),reset_space_and_domain
)(multi
, space
, domain
);
381 /* Set the id of the given dimension of "multi" to "id".
383 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_dim_id
)(
384 __isl_take
MULTI(BASE
) *multi
,
385 enum isl_dim_type type
, unsigned pos
, __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_dim_id(space
, type
, pos
, id
);
396 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
399 FN(MULTI(BASE
),free
)(multi
);
403 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_tuple_name
)(
404 __isl_keep
MULTI(BASE
) *multi
, enum isl_dim_type type
,
409 multi
= FN(MULTI(BASE
),cow
)(multi
);
413 space
= FN(MULTI(BASE
),get_space
)(multi
);
414 space
= isl_space_set_tuple_name(space
, type
, s
);
416 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
419 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),set_tuple_id
)(
420 __isl_take
MULTI(BASE
) *multi
, enum isl_dim_type type
,
421 __isl_take isl_id
*id
)
425 multi
= FN(MULTI(BASE
),cow
)(multi
);
429 space
= FN(MULTI(BASE
),get_space
)(multi
);
430 space
= isl_space_set_tuple_id(space
, type
, id
);
432 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
438 /* Drop the id on the specified tuple.
440 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_tuple_id
)(
441 __isl_take
MULTI(BASE
) *multi
, enum isl_dim_type type
)
447 if (!FN(MULTI(BASE
),has_tuple_id
)(multi
, type
))
450 multi
= FN(MULTI(BASE
),cow
)(multi
);
454 space
= FN(MULTI(BASE
),get_space
)(multi
);
455 space
= isl_space_reset_tuple_id(space
, type
);
457 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
460 /* Reset the user pointer on all identifiers of parameters and tuples
461 * of the space of "multi".
463 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),reset_user
)(
464 __isl_take
MULTI(BASE
) *multi
)
468 space
= FN(MULTI(BASE
),get_space
)(multi
);
469 space
= isl_space_reset_user(space
);
471 return FN(MULTI(BASE
),reset_space
)(multi
, space
);
474 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),realign_domain
)(
475 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_reordering
*exp
)
480 multi
= FN(MULTI(BASE
),cow
)(multi
);
484 for (i
= 0; i
< multi
->n
; ++i
) {
485 multi
->u
.p
[i
] = FN(EL
,realign_domain
)(multi
->u
.p
[i
],
486 isl_reordering_copy(exp
));
491 space
= isl_reordering_get_space(exp
);
492 multi
= FN(MULTI(BASE
),reset_domain_space
)(multi
, space
);
494 isl_reordering_free(exp
);
497 isl_reordering_free(exp
);
498 FN(MULTI(BASE
),free
)(multi
);
502 /* Align the parameters of "multi" to those of "model".
504 * If "multi" has an explicit domain, then align the parameters
505 * of the domain first.
507 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),align_params
)(
508 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_space
*model
)
511 isl_bool equal_params
;
514 if (!multi
|| !model
)
517 equal_params
= isl_space_has_equal_params(multi
->space
, model
);
518 if (equal_params
< 0)
521 isl_space_free(model
);
525 ctx
= isl_space_get_ctx(model
);
526 if (!isl_space_has_named_params(model
))
527 isl_die(ctx
, isl_error_invalid
,
528 "model has unnamed parameters", goto error
);
529 if (!isl_space_has_named_params(multi
->space
))
530 isl_die(ctx
, isl_error_invalid
,
531 "input has unnamed parameters", goto error
);
533 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
)) {
534 multi
= FN(MULTI(BASE
),align_explicit_domain_params
)(multi
,
535 isl_space_copy(model
));
539 exp
= isl_parameter_alignment_reordering(multi
->space
, model
);
540 exp
= isl_reordering_extend_space(exp
,
541 FN(MULTI(BASE
),get_domain_space
)(multi
));
542 multi
= FN(MULTI(BASE
),realign_domain
)(multi
, exp
);
544 isl_space_free(model
);
547 isl_space_free(model
);
548 FN(MULTI(BASE
),free
)(multi
);
552 /* Create a multi expression in the given space with the elements of "list"
553 * as base expressions.
555 * Since isl_multi_*_restore_* assumes that the element and
556 * the multi expression have matching spaces, the alignment
557 * (if any) needs to be performed beforehand.
559 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),from
),LIST(BASE
))(
560 __isl_take isl_space
*space
, __isl_take
LIST(EL
) *list
)
570 ctx
= isl_space_get_ctx(space
);
571 n
= FN(FN(LIST(EL
),n
),BASE
)(list
);
572 if (n
!= isl_space_dim(space
, isl_dim_out
))
573 isl_die(ctx
, isl_error_invalid
,
574 "invalid number of elements in list", goto error
);
576 for (i
= 0; i
< n
; ++i
) {
577 EL
*el
= FN(LIST(EL
),peek
)(list
, i
);
578 space
= isl_space_align_params(space
, FN(EL
,get_space
)(el
));
580 multi
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
581 for (i
= 0; i
< n
; ++i
) {
582 EL
*el
= FN(FN(LIST(EL
),get
),BASE
)(list
, i
);
583 el
= FN(EL
,align_params
)(el
, isl_space_copy(space
));
584 multi
= FN(MULTI(BASE
),restore_check_space
)(multi
, i
, el
);
587 isl_space_free(space
);
588 FN(LIST(EL
),free
)(list
);
591 isl_space_free(space
);
592 FN(LIST(EL
),free
)(list
);
597 /* Construct a multi expression in the given space with value zero in
598 * each of the output dimensions.
600 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),zero
)(__isl_take isl_space
*space
)
608 n
= isl_space_dim(space
, isl_dim_out
);
609 multi
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
612 isl_space_free(space
);
618 space
= isl_space_domain(space
);
619 ls
= isl_local_space_from_space(space
);
620 el
= FN(EL
,zero_on_domain
)(ls
);
622 for (i
= 0; i
< n
; ++i
)
623 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, i
,
634 /* Create a multiple expression with a single output/set dimension
636 * For most multiple expression types, the base type has a single
637 * output/set dimension and the space of the result is therefore
638 * the same as the space of the input.
639 * In the case of isl_multi_union_pw_aff, however, the base type
640 * lives in a parameter space and we therefore need to add
641 * a single set dimension.
643 __isl_give
MULTI(BASE
) *FN(FN(MULTI(BASE
),from
),BASE
)(__isl_take EL
*el
)
648 space
= FN(EL
,get_space(el
));
649 if (isl_space_is_params(space
)) {
650 space
= isl_space_set_from_params(space
);
651 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
653 multi
= FN(MULTI(BASE
),alloc
)(space
);
654 multi
= FN(FN(MULTI(BASE
),set
),BASE
)(multi
, 0, el
);
660 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),drop_dims
)(
661 __isl_take
MULTI(BASE
) *multi
,
662 enum isl_dim_type type
, unsigned first
, unsigned n
)
667 multi
= FN(MULTI(BASE
),cow
)(multi
);
671 dim
= FN(MULTI(BASE
),dim
)(multi
, type
);
672 if (first
+ n
> dim
|| first
+ n
< first
)
673 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
674 "index out of bounds",
675 return FN(MULTI(BASE
),free
)(multi
));
677 multi
->space
= isl_space_drop_dims(multi
->space
, type
, first
, n
);
679 return FN(MULTI(BASE
),free
)(multi
);
681 if (type
== isl_dim_out
) {
682 for (i
= 0; i
< n
; ++i
)
683 FN(EL
,free
)(multi
->u
.p
[first
+ i
]);
684 for (i
= first
; i
+ n
< multi
->n
; ++i
)
685 multi
->u
.p
[i
] = multi
->u
.p
[i
+ n
];
687 if (n
> 0 && FN(MULTI(BASE
),has_explicit_domain
)(multi
))
688 multi
= FN(MULTI(BASE
),init_explicit_domain
)(multi
);
693 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
694 multi
= FN(MULTI(BASE
),drop_explicit_domain_dims
)(multi
,
699 for (i
= 0; i
< multi
->n
; ++i
) {
700 multi
->u
.p
[i
] = FN(EL
,drop_dims
)(multi
->u
.p
[i
], type
, first
, n
);
702 return FN(MULTI(BASE
),free
)(multi
);
708 /* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
710 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),align_params_multi_multi_and
)(
711 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
712 __isl_give
MULTI(BASE
) *(*fn
)(__isl_take
MULTI(BASE
) *multi1
,
713 __isl_take
MULTI(BASE
) *multi2
))
716 isl_bool equal_params
;
718 if (!multi1
|| !multi2
)
720 equal_params
= isl_space_has_equal_params(multi1
->space
, multi2
->space
);
721 if (equal_params
< 0)
724 return fn(multi1
, multi2
);
725 ctx
= FN(MULTI(BASE
),get_ctx
)(multi1
);
726 if (!isl_space_has_named_params(multi1
->space
) ||
727 !isl_space_has_named_params(multi2
->space
))
728 isl_die(ctx
, isl_error_invalid
,
729 "unaligned unnamed parameters", goto error
);
730 multi1
= FN(MULTI(BASE
),align_params
)(multi1
,
731 FN(MULTI(BASE
),get_space
)(multi2
));
732 multi2
= FN(MULTI(BASE
),align_params
)(multi2
,
733 FN(MULTI(BASE
),get_space
)(multi1
));
734 return fn(multi1
, multi2
);
736 FN(MULTI(BASE
),free
)(multi1
);
737 FN(MULTI(BASE
),free
)(multi2
);
741 /* Given two MULTI(BASE)s A -> B and C -> D,
742 * construct a MULTI(BASE) (A * C) -> [B -> D].
744 * The parameters are assumed to have been aligned.
746 * If "multi1" and/or "multi2" has an explicit domain, then
747 * intersect the domain of the result with these explicit domains.
749 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_product_aligned
)(
750 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
757 if (!multi1
|| !multi2
)
760 space
= isl_space_range_product(FN(MULTI(BASE
),get_space
)(multi1
),
761 FN(MULTI(BASE
),get_space
)(multi2
));
762 res
= FN(MULTI(BASE
),alloc
)(space
);
764 n1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
765 n2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_out
);
767 for (i
= 0; i
< n1
; ++i
) {
768 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi1
, i
);
769 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, i
, el
);
772 for (i
= 0; i
< n2
; ++i
) {
773 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi2
, i
);
774 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, n1
+ i
, el
);
777 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
))
778 res
= FN(MULTI(BASE
),intersect_explicit_domain
)(res
, multi1
);
779 if (FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
780 res
= FN(MULTI(BASE
),intersect_explicit_domain
)(res
, multi2
);
782 FN(MULTI(BASE
),free
)(multi1
);
783 FN(MULTI(BASE
),free
)(multi2
);
786 FN(MULTI(BASE
),free
)(multi1
);
787 FN(MULTI(BASE
),free
)(multi2
);
791 /* Given two MULTI(BASE)s A -> B and C -> D,
792 * construct a MULTI(BASE) (A * C) -> [B -> D].
794 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_product
)(
795 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
797 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
798 &FN(MULTI(BASE
),range_product_aligned
));
801 /* Is the range of "multi" a wrapped relation?
803 isl_bool
FN(MULTI(BASE
),range_is_wrapping
)(__isl_keep
MULTI(BASE
) *multi
)
806 return isl_bool_error
;
807 return isl_space_range_is_wrapping(multi
->space
);
810 /* Given a function A -> [B -> C], extract the function A -> B.
812 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_factor_domain
)(
813 __isl_take
MULTI(BASE
) *multi
)
820 if (!isl_space_range_is_wrapping(multi
->space
))
821 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
822 "range is not a product",
823 return FN(MULTI(BASE
),free
)(multi
));
825 space
= FN(MULTI(BASE
),get_space
)(multi
);
826 total
= isl_space_dim(space
, isl_dim_out
);
827 space
= isl_space_range_factor_domain(space
);
828 keep
= isl_space_dim(space
, isl_dim_out
);
829 multi
= FN(MULTI(BASE
),drop_dims
)(multi
,
830 isl_dim_out
, keep
, total
- keep
);
831 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
836 /* Given a function A -> [B -> C], extract the function A -> C.
838 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_factor_range
)(
839 __isl_take
MULTI(BASE
) *multi
)
846 if (!isl_space_range_is_wrapping(multi
->space
))
847 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
848 "range is not a product",
849 return FN(MULTI(BASE
),free
)(multi
));
851 space
= FN(MULTI(BASE
),get_space
)(multi
);
852 total
= isl_space_dim(space
, isl_dim_out
);
853 space
= isl_space_range_factor_range(space
);
854 keep
= isl_space_dim(space
, isl_dim_out
);
855 multi
= FN(MULTI(BASE
),drop_dims
)(multi
, isl_dim_out
, 0, total
- keep
);
856 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
861 /* Given a function [B -> C], extract the function C.
863 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),factor_range
)(
864 __isl_take
MULTI(BASE
) *multi
)
871 if (!isl_space_is_wrapping(multi
->space
))
872 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
873 "not a product", return FN(MULTI(BASE
),free
)(multi
));
875 space
= FN(MULTI(BASE
),get_space
)(multi
);
876 total
= isl_space_dim(space
, isl_dim_out
);
877 space
= isl_space_factor_range(space
);
878 keep
= isl_space_dim(space
, isl_dim_out
);
879 multi
= FN(MULTI(BASE
),drop_dims
)(multi
, isl_dim_out
, 0, total
- keep
);
880 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
886 /* Given two MULTI(BASE)s A -> B and C -> D,
887 * construct a MULTI(BASE) [A -> C] -> [B -> D].
889 * The parameters are assumed to have been aligned.
891 * If "multi1" and/or "multi2" has an explicit domain, then
892 * intersect the domain of the result with these explicit domains.
894 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),product_aligned
)(
895 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
901 int in1
, in2
, out1
, out2
;
903 in1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_in
);
904 in2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_in
);
905 out1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
906 out2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_out
);
907 space
= isl_space_product(FN(MULTI(BASE
),get_space
)(multi1
),
908 FN(MULTI(BASE
),get_space
)(multi2
));
909 res
= FN(MULTI(BASE
),alloc
)(isl_space_copy(space
));
910 space
= isl_space_domain(space
);
912 for (i
= 0; i
< out1
; ++i
) {
913 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi1
, i
);
914 el
= FN(EL
,insert_dims
)(el
, isl_dim_in
, in1
, in2
);
915 el
= FN(EL
,reset_domain_space
)(el
, isl_space_copy(space
));
916 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, i
, el
);
919 for (i
= 0; i
< out2
; ++i
) {
920 el
= FN(FN(MULTI(BASE
),get
),BASE
)(multi2
, i
);
921 el
= FN(EL
,insert_dims
)(el
, isl_dim_in
, 0, in1
);
922 el
= FN(EL
,reset_domain_space
)(el
, isl_space_copy(space
));
923 res
= FN(FN(MULTI(BASE
),set
),BASE
)(res
, out1
+ i
, el
);
926 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
) ||
927 FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
928 res
= FN(MULTI(BASE
),intersect_explicit_domain_product
)(res
,
931 isl_space_free(space
);
932 FN(MULTI(BASE
),free
)(multi1
);
933 FN(MULTI(BASE
),free
)(multi2
);
937 /* Given two MULTI(BASE)s A -> B and C -> D,
938 * construct a MULTI(BASE) [A -> C] -> [B -> D].
940 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),product
)(
941 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
943 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
944 &FN(MULTI(BASE
),product_aligned
));
948 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),flatten_range
)(
949 __isl_take
MULTI(BASE
) *multi
)
954 if (!multi
->space
->nested
[1])
957 multi
= FN(MULTI(BASE
),cow
)(multi
);
961 multi
->space
= isl_space_flatten_range(multi
->space
);
963 return FN(MULTI(BASE
),free
)(multi
);
968 /* Given two MULTI(BASE)s A -> B and C -> D,
969 * construct a MULTI(BASE) (A * C) -> (B, D).
971 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),flat_range_product
)(
972 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
976 multi
= FN(MULTI(BASE
),range_product
)(multi1
, multi2
);
977 multi
= FN(MULTI(BASE
),flatten_range
)(multi
);
981 /* Given two multi expressions, "multi1"
985 * where B2 starts at position "pos", and "multi2"
989 * return the multi expression
993 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),range_splice
)(
994 __isl_take
MULTI(BASE
) *multi1
, unsigned pos
,
995 __isl_take
MULTI(BASE
) *multi2
)
1000 if (!multi1
|| !multi2
)
1003 dim
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_out
);
1005 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1006 "index out of bounds", goto error
);
1008 res
= FN(MULTI(BASE
),copy
)(multi1
);
1009 res
= FN(MULTI(BASE
),drop_dims
)(res
, isl_dim_out
, pos
, dim
- pos
);
1010 multi1
= FN(MULTI(BASE
),drop_dims
)(multi1
, isl_dim_out
, 0, pos
);
1012 res
= FN(MULTI(BASE
),flat_range_product
)(res
, multi2
);
1013 res
= FN(MULTI(BASE
),flat_range_product
)(res
, multi1
);
1017 FN(MULTI(BASE
),free
)(multi1
);
1018 FN(MULTI(BASE
),free
)(multi2
);
1023 /* Given two multi expressions, "multi1"
1025 * [A1 A2] -> [B1 B2]
1027 * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
1032 * return the multi expression
1034 * [A1 C A2] -> [B1 D B2]
1036 * We first insert input dimensions to obtain
1038 * [A1 C A2] -> [B1 B2]
1044 * and then apply range_splice.
1046 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),splice
)(
1047 __isl_take
MULTI(BASE
) *multi1
, unsigned in_pos
, unsigned out_pos
,
1048 __isl_take
MULTI(BASE
) *multi2
)
1053 if (!multi1
|| !multi2
)
1056 n_in1
= FN(MULTI(BASE
),dim
)(multi1
, isl_dim_in
);
1058 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1059 "index out of bounds", goto error
);
1061 n_in2
= FN(MULTI(BASE
),dim
)(multi2
, isl_dim_in
);
1063 multi1
= FN(MULTI(BASE
),insert_dims
)(multi1
, isl_dim_in
, in_pos
, n_in2
);
1064 multi2
= FN(MULTI(BASE
),insert_dims
)(multi2
, isl_dim_in
, n_in2
,
1066 multi2
= FN(MULTI(BASE
),insert_dims
)(multi2
, isl_dim_in
, 0, in_pos
);
1068 return FN(MULTI(BASE
),range_splice
)(multi1
, out_pos
, multi2
);
1070 FN(MULTI(BASE
),free
)(multi1
);
1071 FN(MULTI(BASE
),free
)(multi2
);
1076 /* Check that "multi1" and "multi2" live in the same space,
1077 * reporting an error if they do not.
1079 static isl_stat
FN(MULTI(BASE
),check_equal_space
)(
1080 __isl_keep
MULTI(BASE
) *multi1
, __isl_keep
MULTI(BASE
) *multi2
)
1084 if (!multi1
|| !multi2
)
1085 return isl_stat_error
;
1087 equal
= isl_space_is_equal(multi1
->space
, multi2
->space
);
1089 return isl_stat_error
;
1091 isl_die(FN(MULTI(BASE
),get_ctx
)(multi1
), isl_error_invalid
,
1092 "spaces don't match", return isl_stat_error
);
1097 /* This function is currently only used from isl_aff.c
1099 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),bin_op
)(
1100 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
1101 __isl_give EL
*(*fn
)(__isl_take EL
*, __isl_take EL
*))
1102 __attribute__ ((unused
));
1104 /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
1105 * return the result.
1107 * If "multi2" has an explicit domain, then
1108 * intersect the domain of the result with this explicit domain.
1110 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),bin_op
)(
1111 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
,
1112 __isl_give EL
*(*fn
)(__isl_take EL
*, __isl_take EL
*))
1116 multi1
= FN(MULTI(BASE
),cow
)(multi1
);
1117 if (FN(MULTI(BASE
),check_equal_space
)(multi1
, multi2
) < 0)
1120 for (i
= 0; i
< multi1
->n
; ++i
) {
1121 multi1
->u
.p
[i
] = fn(multi1
->u
.p
[i
],
1122 FN(EL
,copy
)(multi2
->u
.p
[i
]));
1123 if (!multi1
->u
.p
[i
])
1127 if (FN(MULTI(BASE
),has_explicit_domain
)(multi2
))
1128 multi1
= FN(MULTI(BASE
),intersect_explicit_domain
)(multi1
,
1131 FN(MULTI(BASE
),free
)(multi2
);
1134 FN(MULTI(BASE
),free
)(multi1
);
1135 FN(MULTI(BASE
),free
)(multi2
);
1139 /* Add "multi2" to "multi1" and return the result.
1141 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1143 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),add_aligned
)(
1144 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
1146 return FN(MULTI(BASE
),bin_op
)(multi1
, multi2
, &FN(EL
,add
));
1149 /* Add "multi2" to "multi1" and return the result.
1151 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),add
)(__isl_take
MULTI(BASE
) *multi1
,
1152 __isl_take
MULTI(BASE
) *multi2
)
1154 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
1155 &FN(MULTI(BASE
),add_aligned
));
1158 /* Subtract "multi2" from "multi1" and return the result.
1160 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1162 static __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),sub_aligned
)(
1163 __isl_take
MULTI(BASE
) *multi1
, __isl_take
MULTI(BASE
) *multi2
)
1165 return FN(MULTI(BASE
),bin_op
)(multi1
, multi2
, &FN(EL
,sub
));
1168 /* Subtract "multi2" from "multi1" and return the result.
1170 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),sub
)(__isl_take
MULTI(BASE
) *multi1
,
1171 __isl_take
MULTI(BASE
) *multi2
)
1173 return FN(MULTI(BASE
),align_params_multi_multi_and
)(multi1
, multi2
,
1174 &FN(MULTI(BASE
),sub_aligned
));
1177 /* Multiply the elements of "multi" by "v" and return the result.
1179 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_val
)(__isl_take
MULTI(BASE
) *multi
,
1180 __isl_take isl_val
*v
)
1187 if (isl_val_is_one(v
)) {
1192 if (!isl_val_is_rat(v
))
1193 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1194 "expecting rational factor", goto error
);
1196 multi
= FN(MULTI(BASE
),cow
)(multi
);
1200 for (i
= 0; i
< multi
->n
; ++i
) {
1201 multi
->u
.p
[i
] = FN(EL
,scale_val
)(multi
->u
.p
[i
],
1211 return FN(MULTI(BASE
),free
)(multi
);
1214 /* Divide the elements of "multi" by "v" and return the result.
1216 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_down_val
)(
1217 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_val
*v
)
1224 if (isl_val_is_one(v
)) {
1229 if (!isl_val_is_rat(v
))
1230 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1231 "expecting rational factor", goto error
);
1232 if (isl_val_is_zero(v
))
1233 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1234 "cannot scale down by zero", goto error
);
1236 multi
= FN(MULTI(BASE
),cow
)(multi
);
1240 for (i
= 0; i
< multi
->n
; ++i
) {
1241 multi
->u
.p
[i
] = FN(EL
,scale_down_val
)(multi
->u
.p
[i
],
1251 return FN(MULTI(BASE
),free
)(multi
);
1254 /* Multiply the elements of "multi" by the corresponding element of "mv"
1255 * and return the result.
1257 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_multi_val
)(
1258 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1265 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1266 mv
->space
, isl_dim_set
))
1267 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1268 "spaces don't match", goto error
);
1270 multi
= FN(MULTI(BASE
),cow
)(multi
);
1274 for (i
= 0; i
< multi
->n
; ++i
) {
1277 v
= isl_multi_val_get_val(mv
, i
);
1278 multi
->u
.p
[i
] = FN(EL
,scale_val
)(multi
->u
.p
[i
], v
);
1283 isl_multi_val_free(mv
);
1286 isl_multi_val_free(mv
);
1287 return FN(MULTI(BASE
),free
)(multi
);
1290 /* Divide the elements of "multi" by the corresponding element of "mv"
1291 * and return the result.
1293 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),scale_down_multi_val
)(
1294 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1301 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1302 mv
->space
, isl_dim_set
))
1303 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1304 "spaces don't match", goto error
);
1306 multi
= FN(MULTI(BASE
),cow
)(multi
);
1310 for (i
= 0; i
< multi
->n
; ++i
) {
1313 v
= isl_multi_val_get_val(mv
, i
);
1314 multi
->u
.p
[i
] = FN(EL
,scale_down_val
)(multi
->u
.p
[i
], v
);
1319 isl_multi_val_free(mv
);
1322 isl_multi_val_free(mv
);
1323 return FN(MULTI(BASE
),free
)(multi
);
1326 /* Compute the residues of the elements of "multi" modulo
1327 * the corresponding element of "mv" and return the result.
1329 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),mod_multi_val
)(
1330 __isl_take
MULTI(BASE
) *multi
, __isl_take isl_multi_val
*mv
)
1337 if (!isl_space_tuple_is_equal(multi
->space
, isl_dim_out
,
1338 mv
->space
, isl_dim_set
))
1339 isl_die(isl_multi_val_get_ctx(mv
), isl_error_invalid
,
1340 "spaces don't match", goto error
);
1342 multi
= FN(MULTI(BASE
),cow
)(multi
);
1346 for (i
= 0; i
< multi
->n
; ++i
) {
1349 v
= isl_multi_val_get_val(mv
, i
);
1350 multi
->u
.p
[i
] = FN(EL
,mod_val
)(multi
->u
.p
[i
], v
);
1355 isl_multi_val_free(mv
);
1358 isl_multi_val_free(mv
);
1359 return FN(MULTI(BASE
),free
)(multi
);
1362 #ifndef NO_MOVE_DIMS
1363 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
1364 * to dimensions of "dst_type" at "dst_pos".
1366 * We only support moving input dimensions to parameters and vice versa.
1368 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),move_dims
)(__isl_take
MULTI(BASE
) *multi
,
1369 enum isl_dim_type dst_type
, unsigned dst_pos
,
1370 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1378 !isl_space_is_named_or_nested(multi
->space
, src_type
) &&
1379 !isl_space_is_named_or_nested(multi
->space
, dst_type
))
1382 if (dst_type
== isl_dim_out
|| src_type
== isl_dim_out
)
1383 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1384 "cannot move output/set dimension",
1385 return FN(MULTI(BASE
),free
)(multi
));
1386 if (dst_type
== isl_dim_div
|| src_type
== isl_dim_div
)
1387 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1389 return FN(MULTI(BASE
),free
)(multi
));
1390 if (src_pos
+ n
> isl_space_dim(multi
->space
, src_type
))
1391 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1392 "range out of bounds",
1393 return FN(MULTI(BASE
),free
)(multi
));
1394 if (dst_type
== src_type
)
1395 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_unsupported
,
1396 "moving dims within the same type not supported",
1397 return FN(MULTI(BASE
),free
)(multi
));
1399 multi
= FN(MULTI(BASE
),cow
)(multi
);
1403 multi
->space
= isl_space_move_dims(multi
->space
, dst_type
, dst_pos
,
1404 src_type
, src_pos
, n
);
1406 return FN(MULTI(BASE
),free
)(multi
);
1407 if (FN(MULTI(BASE
),has_explicit_domain
)(multi
))
1408 multi
= FN(MULTI(BASE
),move_explicit_domain_dims
)(multi
,
1409 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1413 for (i
= 0; i
< multi
->n
; ++i
) {
1414 multi
->u
.p
[i
] = FN(EL
,move_dims
)(multi
->u
.p
[i
],
1416 src_type
, src_pos
, n
);
1418 return FN(MULTI(BASE
),free
)(multi
);
1425 /* Convert a multiple expression defined over a parameter domain
1426 * into one that is defined over a zero-dimensional set.
1428 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),from_range
)(
1429 __isl_take
MULTI(BASE
) *multi
)
1435 if (!isl_space_is_set(multi
->space
))
1436 isl_die(FN(MULTI(BASE
),get_ctx
)(multi
), isl_error_invalid
,
1437 "not living in a set space",
1438 return FN(MULTI(BASE
),free
)(multi
));
1440 space
= FN(MULTI(BASE
),get_space
)(multi
);
1441 space
= isl_space_from_range(space
);
1442 multi
= FN(MULTI(BASE
),reset_space
)(multi
, space
);
1447 /* Are "multi1" and "multi2" obviously equal?
1449 isl_bool
FN(MULTI(BASE
),plain_is_equal
)(__isl_keep
MULTI(BASE
) *multi1
,
1450 __isl_keep
MULTI(BASE
) *multi2
)
1455 if (!multi1
|| !multi2
)
1456 return isl_bool_error
;
1457 if (multi1
->n
!= multi2
->n
)
1458 return isl_bool_false
;
1459 equal
= isl_space_is_equal(multi1
->space
, multi2
->space
);
1460 if (equal
< 0 || !equal
)
1463 for (i
= 0; i
< multi1
->n
; ++i
) {
1464 equal
= FN(EL
,plain_is_equal
)(multi1
->u
.p
[i
], multi2
->u
.p
[i
]);
1465 if (equal
< 0 || !equal
)
1469 if (FN(MULTI(BASE
),has_explicit_domain
)(multi1
) ||
1470 FN(MULTI(BASE
),has_explicit_domain
)(multi2
)) {
1471 equal
= FN(MULTI(BASE
),equal_explicit_domain
)(multi1
, multi2
);
1472 if (equal
< 0 || !equal
)
1476 return isl_bool_true
;
1479 /* Does "multi" involve any NaNs?
1481 isl_bool
FN(MULTI(BASE
),involves_nan
)(__isl_keep
MULTI(BASE
) *multi
)
1486 return isl_bool_error
;
1488 return isl_bool_false
;
1490 for (i
= 0; i
< multi
->n
; ++i
) {
1491 isl_bool has_nan
= FN(EL
,involves_nan
)(multi
->u
.p
[i
]);
1492 if (has_nan
< 0 || has_nan
)
1496 return isl_bool_false
;
1499 /* Return the opposite of "multi".
1501 __isl_give
MULTI(BASE
) *FN(MULTI(BASE
),neg
)(__isl_take
MULTI(BASE
) *multi
)
1505 multi
= FN(MULTI(BASE
),cow
)(multi
);
1509 for (i
= 0; i
< multi
->n
; ++i
) {
1510 multi
->u
.p
[i
] = FN(EL
,neg
)(multi
->u
.p
[i
]);
1512 return FN(MULTI(BASE
),free
)(multi
);