isl_set_is_subset: properly handle identical integer divisions
[isl.git] / isl_multi_templ.c
blob32501f0b1d1c598f7c0ad82c0074ef5188fe9434
1 /*
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
9 */
11 #include <isl_space_private.h>
12 #include <isl/set.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 /* Return the space of "multi".
28 static __isl_keep isl_space *FN(MULTI(BASE),peek_space)(
29 __isl_keep MULTI(BASE) *multi)
31 return multi ? multi->space : NULL;
34 __isl_give isl_space *FN(MULTI(BASE),get_space)(__isl_keep MULTI(BASE) *multi)
36 return isl_space_copy(FN(MULTI(BASE),peek_space)(multi));
39 /* Return the position of the dimension of the given type and name
40 * in "multi".
41 * Return -1 if no such dimension can be found.
43 int FN(MULTI(BASE),find_dim_by_name)(__isl_keep MULTI(BASE) *multi,
44 enum isl_dim_type type, const char *name)
46 if (!multi)
47 return -1;
48 return isl_space_find_dim_by_name(multi->space, type, name);
51 __isl_give isl_space *FN(MULTI(BASE),get_domain_space)(
52 __isl_keep MULTI(BASE) *multi)
54 return multi ? isl_space_domain(isl_space_copy(multi->space)) : NULL;
57 __isl_give MULTI(BASE) *FN(MULTI(BASE),alloc)(__isl_take isl_space *space)
59 isl_ctx *ctx;
60 int n;
61 MULTI(BASE) *multi;
63 if (!space)
64 return NULL;
66 ctx = isl_space_get_ctx(space);
67 n = isl_space_dim(space, isl_dim_out);
68 multi = isl_calloc(ctx, MULTI(BASE),
69 sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *));
70 if (!multi)
71 goto error;
73 multi->space = space;
74 multi->n = n;
75 multi->ref = 1;
76 return multi;
77 error:
78 isl_space_free(space);
79 return NULL;
82 __isl_give MULTI(BASE) *FN(MULTI(BASE),dup)(__isl_keep MULTI(BASE) *multi)
84 int i;
85 MULTI(BASE) *dup;
87 if (!multi)
88 return NULL;
90 dup = FN(MULTI(BASE),alloc)(isl_space_copy(multi->space));
91 if (!dup)
92 return NULL;
94 for (i = 0; i < multi->n; ++i)
95 dup = FN(FN(MULTI(BASE),set),BASE)(dup, i,
96 FN(EL,copy)(multi->p[i]));
98 return dup;
101 __isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi)
103 if (!multi)
104 return NULL;
106 if (multi->ref == 1)
107 return multi;
109 multi->ref--;
110 return FN(MULTI(BASE),dup)(multi);
113 __isl_give MULTI(BASE) *FN(MULTI(BASE),copy)(__isl_keep MULTI(BASE) *multi)
115 if (!multi)
116 return NULL;
118 multi->ref++;
119 return multi;
122 __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
124 int i;
126 if (!multi)
127 return NULL;
129 if (--multi->ref > 0)
130 return NULL;
132 isl_space_free(multi->space);
133 for (i = 0; i < multi->n; ++i)
134 FN(EL,free)(multi->p[i]);
135 free(multi);
137 return NULL;
140 unsigned FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi,
141 enum isl_dim_type type)
143 return multi ? isl_space_dim(multi->space, type) : 0;
146 /* Return the position of the first dimension of "type" with id "id".
147 * Return -1 if there is no such dimension.
149 int FN(MULTI(BASE),find_dim_by_id)(__isl_keep MULTI(BASE) *multi,
150 enum isl_dim_type type, __isl_keep isl_id *id)
152 if (!multi)
153 return -1;
154 return isl_space_find_dim_by_id(multi->space, type, id);
157 /* Return the id of the given dimension.
159 __isl_give isl_id *FN(MULTI(BASE),get_dim_id)(__isl_keep MULTI(BASE) *multi,
160 enum isl_dim_type type, unsigned pos)
162 return multi ? isl_space_get_dim_id(multi->space, type, pos) : NULL;
165 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_name)(
166 __isl_take MULTI(BASE) *multi,
167 enum isl_dim_type type, unsigned pos, const char *s)
169 int i;
171 multi = FN(MULTI(BASE),cow)(multi);
172 if (!multi)
173 return NULL;
175 multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
176 if (!multi->space)
177 return FN(MULTI(BASE),free)(multi);
179 if (type == isl_dim_out)
180 return multi;
181 for (i = 0; i < multi->n; ++i) {
182 multi->p[i] = FN(EL,set_dim_name)(multi->p[i], type, pos, s);
183 if (!multi->p[i])
184 return FN(MULTI(BASE),free)(multi);
187 return multi;
190 const char *FN(MULTI(BASE),get_tuple_name)(__isl_keep MULTI(BASE) *multi,
191 enum isl_dim_type type)
193 return multi ? isl_space_get_tuple_name(multi->space, type) : NULL;
196 /* Does the specified tuple have an id?
198 isl_bool FN(MULTI(BASE),has_tuple_id)(__isl_keep MULTI(BASE) *multi,
199 enum isl_dim_type type)
201 if (!multi)
202 return isl_bool_error;
203 return isl_space_has_tuple_id(multi->space, type);
206 /* Return the id of the specified tuple.
208 __isl_give isl_id *FN(MULTI(BASE),get_tuple_id)(__isl_keep MULTI(BASE) *multi,
209 enum isl_dim_type type)
211 return multi ? isl_space_get_tuple_id(multi->space, type) : NULL;
214 __isl_give EL *FN(FN(MULTI(BASE),get),BASE)(__isl_keep MULTI(BASE) *multi,
215 int pos)
217 isl_ctx *ctx;
219 if (!multi)
220 return NULL;
221 ctx = FN(MULTI(BASE),get_ctx)(multi);
222 if (pos < 0 || pos >= multi->n)
223 isl_die(ctx, isl_error_invalid,
224 "index out of bounds", return NULL);
225 return FN(EL,copy)(multi->p[pos]);
228 /* Set the element at position "pos" of "multi" to "el",
229 * where the position may be empty if "multi" has only a single reference.
231 static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore)(
232 __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
234 multi = FN(MULTI(BASE),cow)(multi);
235 if (!multi || !el)
236 goto error;
238 if (pos < 0 || pos >= multi->n)
239 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
240 "index out of bounds", goto error);
242 FN(EL,free)(multi->p[pos]);
243 multi->p[pos] = el;
245 return multi;
246 error:
247 FN(MULTI(BASE),free)(multi);
248 FN(EL,free)(el);
249 return NULL;
252 /* Set the element at position "pos" of "multi" to "el",
253 * where the position may be empty if "multi" has only a single reference.
254 * However, the space of "multi" is available and is checked
255 * for compatibility with "el".
257 static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_check_space)(
258 __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
260 isl_space *space;
262 space = FN(MULTI(BASE),peek_space)(multi);
263 if (FN(EL,check_match_domain_space)(el, space) < 0)
264 multi = FN(MULTI(BASE),free)(multi);
265 return FN(MULTI(BASE),restore)(multi, pos, el);
268 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),set),BASE)(
269 __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
271 isl_space *multi_space = NULL;
272 isl_space *el_space = NULL;
273 isl_bool match;
275 multi_space = FN(MULTI(BASE),get_space)(multi);
276 match = FN(EL,matching_params)(el, multi_space);
277 if (match < 0)
278 goto error;
279 if (!match) {
280 multi = FN(MULTI(BASE),align_params)(multi,
281 FN(EL,get_space)(el));
282 isl_space_free(multi_space);
283 multi_space = FN(MULTI(BASE),get_space)(multi);
284 el = FN(EL,align_params)(el, isl_space_copy(multi_space));
287 multi = FN(MULTI(BASE),restore_check_space)(multi, pos, el);
289 isl_space_free(multi_space);
290 isl_space_free(el_space);
292 return multi;
293 error:
294 FN(MULTI(BASE),free)(multi);
295 FN(EL,free)(el);
296 isl_space_free(multi_space);
297 isl_space_free(el_space);
298 return NULL;
301 /* Reset the space of "multi". This function is called from isl_pw_templ.c
302 * and doesn't know if the space of an element object is represented
303 * directly or through its domain. It therefore passes along both,
304 * which we pass along to the element function since we don't know how
305 * that is represented either.
307 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space_and_domain)(
308 __isl_take MULTI(BASE) *multi, __isl_take isl_space *space,
309 __isl_take isl_space *domain)
311 int i;
313 multi = FN(MULTI(BASE),cow)(multi);
314 if (!multi || !space || !domain)
315 goto error;
317 for (i = 0; i < multi->n; ++i) {
318 multi->p[i] = FN(EL,reset_domain_space)(multi->p[i],
319 isl_space_copy(domain));
320 if (!multi->p[i])
321 goto error;
323 isl_space_free(domain);
324 isl_space_free(multi->space);
325 multi->space = space;
327 return multi;
328 error:
329 isl_space_free(domain);
330 isl_space_free(space);
331 FN(MULTI(BASE),free)(multi);
332 return NULL;
335 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_domain_space)(
336 __isl_take MULTI(BASE) *multi, __isl_take isl_space *domain)
338 isl_space *space;
340 space = isl_space_extend_domain_with_range(isl_space_copy(domain),
341 isl_space_copy(multi->space));
342 return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
345 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space)(
346 __isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
348 isl_space *domain;
350 domain = isl_space_domain(isl_space_copy(space));
351 return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
354 /* Set the id of the given dimension of "multi" to "id".
356 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_id)(
357 __isl_take MULTI(BASE) *multi,
358 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
360 isl_space *space;
362 multi = FN(MULTI(BASE),cow)(multi);
363 if (!multi || !id)
364 goto error;
366 space = FN(MULTI(BASE),get_space)(multi);
367 space = isl_space_set_dim_id(space, type, pos, id);
369 return FN(MULTI(BASE),reset_space)(multi, space);
370 error:
371 isl_id_free(id);
372 FN(MULTI(BASE),free)(multi);
373 return NULL;
376 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_name)(
377 __isl_keep MULTI(BASE) *multi, enum isl_dim_type type,
378 const char *s)
380 isl_space *space;
382 multi = FN(MULTI(BASE),cow)(multi);
383 if (!multi)
384 return NULL;
386 space = FN(MULTI(BASE),get_space)(multi);
387 space = isl_space_set_tuple_name(space, type, s);
389 return FN(MULTI(BASE),reset_space)(multi, space);
392 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_id)(
393 __isl_take MULTI(BASE) *multi, enum isl_dim_type type,
394 __isl_take isl_id *id)
396 isl_space *space;
398 multi = FN(MULTI(BASE),cow)(multi);
399 if (!multi)
400 goto error;
402 space = FN(MULTI(BASE),get_space)(multi);
403 space = isl_space_set_tuple_id(space, type, id);
405 return FN(MULTI(BASE),reset_space)(multi, space);
406 error:
407 isl_id_free(id);
408 return NULL;
411 /* Drop the id on the specified tuple.
413 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_tuple_id)(
414 __isl_take MULTI(BASE) *multi, enum isl_dim_type type)
416 isl_space *space;
418 if (!multi)
419 return NULL;
420 if (!FN(MULTI(BASE),has_tuple_id)(multi, type))
421 return multi;
423 multi = FN(MULTI(BASE),cow)(multi);
424 if (!multi)
425 return NULL;
427 space = FN(MULTI(BASE),get_space)(multi);
428 space = isl_space_reset_tuple_id(space, type);
430 return FN(MULTI(BASE),reset_space)(multi, space);
433 /* Reset the user pointer on all identifiers of parameters and tuples
434 * of the space of "multi".
436 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_user)(
437 __isl_take MULTI(BASE) *multi)
439 isl_space *space;
441 space = FN(MULTI(BASE),get_space)(multi);
442 space = isl_space_reset_user(space);
444 return FN(MULTI(BASE),reset_space)(multi, space);
447 __isl_give MULTI(BASE) *FN(MULTI(BASE),realign_domain)(
448 __isl_take MULTI(BASE) *multi, __isl_take isl_reordering *exp)
450 int i;
452 multi = FN(MULTI(BASE),cow)(multi);
453 if (!multi || !exp)
454 goto error;
456 for (i = 0; i < multi->n; ++i) {
457 multi->p[i] = FN(EL,realign_domain)(multi->p[i],
458 isl_reordering_copy(exp));
459 if (!multi->p[i])
460 goto error;
463 multi = FN(MULTI(BASE),reset_domain_space)(multi,
464 isl_space_copy(exp->dim));
466 isl_reordering_free(exp);
467 return multi;
468 error:
469 isl_reordering_free(exp);
470 FN(MULTI(BASE),free)(multi);
471 return NULL;
474 /* Align the parameters of "multi" to those of "model".
476 __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)(
477 __isl_take MULTI(BASE) *multi, __isl_take isl_space *model)
479 isl_ctx *ctx;
480 isl_bool equal_params;
481 isl_reordering *exp;
483 if (!multi || !model)
484 goto error;
486 equal_params = isl_space_has_equal_params(multi->space, model);
487 if (equal_params < 0)
488 goto error;
489 if (equal_params) {
490 isl_space_free(model);
491 return multi;
494 ctx = isl_space_get_ctx(model);
495 if (!isl_space_has_named_params(model))
496 isl_die(ctx, isl_error_invalid,
497 "model has unnamed parameters", goto error);
498 if (!isl_space_has_named_params(multi->space))
499 isl_die(ctx, isl_error_invalid,
500 "input has unnamed parameters", goto error);
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);
509 return multi;
510 error:
511 isl_space_free(model);
512 FN(MULTI(BASE),free)(multi);
513 return NULL;
516 /* Create a multi expression in the given space with the elements of "list"
517 * as base expressions.
519 * Since isl_multi_*_restore_* assumes that the element and
520 * the multi expression have matching spaces, the alignment
521 * (if any) needs to be performed beforehand.
523 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))(
524 __isl_take isl_space *space, __isl_take LIST(EL) *list)
526 int i;
527 int n;
528 isl_ctx *ctx;
529 MULTI(BASE) *multi;
531 if (!space || !list)
532 goto error;
534 ctx = isl_space_get_ctx(space);
535 n = FN(FN(LIST(EL),n),BASE)(list);
536 if (n != isl_space_dim(space, isl_dim_out))
537 isl_die(ctx, isl_error_invalid,
538 "invalid number of elements in list", goto error);
540 for (i = 0; i < n; ++i) {
541 EL *el = FN(LIST(EL),peek)(list, i);
542 space = isl_space_align_params(space, FN(EL,get_space)(el));
544 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
545 for (i = 0; i < n; ++i) {
546 EL *el = FN(FN(LIST(EL),get),BASE)(list, i);
547 el = FN(EL,align_params)(el, isl_space_copy(space));
548 multi = FN(MULTI(BASE),restore_check_space)(multi, i, el);
551 isl_space_free(space);
552 FN(LIST(EL),free)(list);
553 return multi;
554 error:
555 isl_space_free(space);
556 FN(LIST(EL),free)(list);
557 return NULL;
560 #ifndef NO_IDENTITY
561 /* Create a multi expression in the given space that maps each
562 * input dimension to the corresponding output dimension.
564 __isl_give MULTI(BASE) *FN(MULTI(BASE),identity)(__isl_take isl_space *space)
566 int i, n;
567 isl_local_space *ls;
568 MULTI(BASE) *multi;
570 if (!space)
571 return NULL;
573 if (isl_space_is_set(space))
574 isl_die(isl_space_get_ctx(space), isl_error_invalid,
575 "expecting map space", goto error);
577 n = isl_space_dim(space, isl_dim_out);
578 if (n != isl_space_dim(space, isl_dim_in))
579 isl_die(isl_space_get_ctx(space), isl_error_invalid,
580 "number of input and output dimensions needs to be "
581 "the same", goto error);
583 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
585 if (!n) {
586 isl_space_free(space);
587 return multi;
590 space = isl_space_domain(space);
591 ls = isl_local_space_from_space(space);
593 for (i = 0; i < n; ++i) {
594 EL *el;
595 el = FN(EL,var_on_domain)(isl_local_space_copy(ls),
596 isl_dim_set, i);
597 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i, el);
600 isl_local_space_free(ls);
602 return multi;
603 error:
604 isl_space_free(space);
605 return NULL;
607 #endif
609 #ifndef NO_ZERO
610 /* Construct a multi expression in the given space with value zero in
611 * each of the output dimensions.
613 __isl_give MULTI(BASE) *FN(MULTI(BASE),zero)(__isl_take isl_space *space)
615 int n;
616 MULTI(BASE) *multi;
618 if (!space)
619 return NULL;
621 n = isl_space_dim(space , isl_dim_out);
622 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
624 if (!n)
625 isl_space_free(space);
626 else {
627 int i;
628 isl_local_space *ls;
629 EL *el;
631 space = isl_space_domain(space);
632 ls = isl_local_space_from_space(space);
633 el = FN(EL,zero_on_domain)(ls);
635 for (i = 0; i < n; ++i)
636 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
637 FN(EL,copy)(el));
639 FN(EL,free)(el);
642 return multi;
644 #endif
646 #ifndef NO_FROM_BASE
647 /* Create a multiple expression with a single output/set dimension
648 * equal to "el".
649 * For most multiple expression types, the base type has a single
650 * output/set dimension and the space of the result is therefore
651 * the same as the space of the input.
652 * In the case of isl_multi_union_pw_aff, however, the base type
653 * lives in a parameter space and we therefore need to add
654 * a single set dimension.
656 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
658 isl_space *space;
659 MULTI(BASE) *multi;
661 space = FN(EL,get_space(el));
662 if (isl_space_is_params(space)) {
663 space = isl_space_set_from_params(space);
664 space = isl_space_add_dims(space, isl_dim_set, 1);
666 multi = FN(MULTI(BASE),alloc)(space);
667 multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
669 return multi;
671 #endif
673 __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
674 __isl_take MULTI(BASE) *multi,
675 enum isl_dim_type type, unsigned first, unsigned n)
677 int i;
678 unsigned dim;
680 multi = FN(MULTI(BASE),cow)(multi);
681 if (!multi)
682 return NULL;
684 dim = FN(MULTI(BASE),dim)(multi, type);
685 if (first + n > dim || first + n < first)
686 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
687 "index out of bounds",
688 return FN(MULTI(BASE),free)(multi));
690 multi->space = isl_space_drop_dims(multi->space, type, first, n);
691 if (!multi->space)
692 return FN(MULTI(BASE),free)(multi);
694 if (type == isl_dim_out) {
695 for (i = 0; i < n; ++i)
696 FN(EL,free)(multi->p[first + i]);
697 for (i = first; i + n < multi->n; ++i)
698 multi->p[i] = multi->p[i + n];
699 multi->n -= n;
701 return multi;
704 for (i = 0; i < multi->n; ++i) {
705 multi->p[i] = FN(EL,drop_dims)(multi->p[i], type, first, n);
706 if (!multi->p[i])
707 return FN(MULTI(BASE),free)(multi);
710 return multi;
713 /* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
715 static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_multi_and)(
716 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
717 __isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi1,
718 __isl_take MULTI(BASE) *multi2))
720 isl_ctx *ctx;
721 isl_bool equal_params;
723 if (!multi1 || !multi2)
724 goto error;
725 equal_params = isl_space_has_equal_params(multi1->space, multi2->space);
726 if (equal_params < 0)
727 goto error;
728 if (equal_params)
729 return fn(multi1, multi2);
730 ctx = FN(MULTI(BASE),get_ctx)(multi1);
731 if (!isl_space_has_named_params(multi1->space) ||
732 !isl_space_has_named_params(multi2->space))
733 isl_die(ctx, isl_error_invalid,
734 "unaligned unnamed parameters", goto error);
735 multi1 = FN(MULTI(BASE),align_params)(multi1,
736 FN(MULTI(BASE),get_space)(multi2));
737 multi2 = FN(MULTI(BASE),align_params)(multi2,
738 FN(MULTI(BASE),get_space)(multi1));
739 return fn(multi1, multi2);
740 error:
741 FN(MULTI(BASE),free)(multi1);
742 FN(MULTI(BASE),free)(multi2);
743 return NULL;
746 /* Given two MULTI(BASE)s A -> B and C -> D,
747 * construct a MULTI(BASE) (A * C) -> [B -> D].
749 * The parameters are assumed to have been aligned.
751 static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
752 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
754 int i, n1, n2;
755 EL *el;
756 isl_space *space;
757 MULTI(BASE) *res;
759 if (!multi1 || !multi2)
760 goto error;
762 space = isl_space_range_product(FN(MULTI(BASE),get_space)(multi1),
763 FN(MULTI(BASE),get_space)(multi2));
764 res = FN(MULTI(BASE),alloc)(space);
766 n1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
767 n2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
769 for (i = 0; i < n1; ++i) {
770 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
771 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
774 for (i = 0; i < n2; ++i) {
775 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
776 res = FN(FN(MULTI(BASE),set),BASE)(res, n1 + i, el);
779 FN(MULTI(BASE),free)(multi1);
780 FN(MULTI(BASE),free)(multi2);
781 return res;
782 error:
783 FN(MULTI(BASE),free)(multi1);
784 FN(MULTI(BASE),free)(multi2);
785 return NULL;
788 /* Given two MULTI(BASE)s A -> B and C -> D,
789 * construct a MULTI(BASE) (A * C) -> [B -> D].
791 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)(
792 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
794 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
795 &FN(MULTI(BASE),range_product_aligned));
798 /* Is the range of "multi" a wrapped relation?
800 isl_bool FN(MULTI(BASE),range_is_wrapping)(__isl_keep MULTI(BASE) *multi)
802 if (!multi)
803 return isl_bool_error;
804 return isl_space_range_is_wrapping(multi->space);
807 /* Given a function A -> [B -> C], extract the function A -> B.
809 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_domain)(
810 __isl_take MULTI(BASE) *multi)
812 isl_space *space;
813 int total, keep;
815 if (!multi)
816 return NULL;
817 if (!isl_space_range_is_wrapping(multi->space))
818 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
819 "range is not a product",
820 return FN(MULTI(BASE),free)(multi));
822 space = FN(MULTI(BASE),get_space)(multi);
823 total = isl_space_dim(space, isl_dim_out);
824 space = isl_space_range_factor_domain(space);
825 keep = isl_space_dim(space, isl_dim_out);
826 multi = FN(MULTI(BASE),drop_dims)(multi,
827 isl_dim_out, keep, total - keep);
828 multi = FN(MULTI(BASE),reset_space)(multi, space);
830 return multi;
833 /* Given a function A -> [B -> C], extract the function A -> C.
835 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)(
836 __isl_take MULTI(BASE) *multi)
838 isl_space *space;
839 int total, keep;
841 if (!multi)
842 return NULL;
843 if (!isl_space_range_is_wrapping(multi->space))
844 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
845 "range is not a product",
846 return FN(MULTI(BASE),free)(multi));
848 space = FN(MULTI(BASE),get_space)(multi);
849 total = isl_space_dim(space, isl_dim_out);
850 space = isl_space_range_factor_range(space);
851 keep = isl_space_dim(space, isl_dim_out);
852 multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
853 multi = FN(MULTI(BASE),reset_space)(multi, space);
855 return multi;
858 /* Given a function [B -> C], extract the function C.
860 __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
861 __isl_take MULTI(BASE) *multi)
863 isl_space *space;
864 int total, keep;
866 if (!multi)
867 return NULL;
868 if (!isl_space_is_wrapping(multi->space))
869 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
870 "not a product", return FN(MULTI(BASE),free)(multi));
872 space = FN(MULTI(BASE),get_space)(multi);
873 total = isl_space_dim(space, isl_dim_out);
874 space = isl_space_factor_range(space);
875 keep = isl_space_dim(space, isl_dim_out);
876 multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
877 multi = FN(MULTI(BASE),reset_space)(multi, space);
879 return multi;
882 #ifndef NO_PRODUCT
883 /* Given two MULTI(BASE)s A -> B and C -> D,
884 * construct a MULTI(BASE) [A -> C] -> [B -> D].
886 * The parameters are assumed to have been aligned.
888 __isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
889 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
891 int i;
892 EL *el;
893 isl_space *space;
894 MULTI(BASE) *res;
895 int in1, in2, out1, out2;
897 in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
898 in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
899 out1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
900 out2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
901 space = isl_space_product(FN(MULTI(BASE),get_space)(multi1),
902 FN(MULTI(BASE),get_space)(multi2));
903 res = FN(MULTI(BASE),alloc)(isl_space_copy(space));
904 space = isl_space_domain(space);
906 for (i = 0; i < out1; ++i) {
907 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
908 el = FN(EL,insert_dims)(el, isl_dim_in, in1, in2);
909 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
910 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
913 for (i = 0; i < out2; ++i) {
914 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
915 el = FN(EL,insert_dims)(el, isl_dim_in, 0, in1);
916 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
917 res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
920 isl_space_free(space);
921 FN(MULTI(BASE),free)(multi1);
922 FN(MULTI(BASE),free)(multi2);
923 return res;
926 /* Given two MULTI(BASE)s A -> B and C -> D,
927 * construct a MULTI(BASE) [A -> C] -> [B -> D].
929 __isl_give MULTI(BASE) *FN(MULTI(BASE),product)(
930 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
932 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
933 &FN(MULTI(BASE),product_aligned));
935 #endif
937 __isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
938 __isl_take MULTI(BASE) *multi)
940 if (!multi)
941 return NULL;
943 if (!multi->space->nested[1])
944 return multi;
946 multi = FN(MULTI(BASE),cow)(multi);
947 if (!multi)
948 return NULL;
950 multi->space = isl_space_flatten_range(multi->space);
951 if (!multi->space)
952 return FN(MULTI(BASE),free)(multi);
954 return multi;
957 /* Given two MULTI(BASE)s A -> B and C -> D,
958 * construct a MULTI(BASE) (A * C) -> (B, D).
960 __isl_give MULTI(BASE) *FN(MULTI(BASE),flat_range_product)(
961 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
963 MULTI(BASE) *multi;
965 multi = FN(MULTI(BASE),range_product)(multi1, multi2);
966 multi = FN(MULTI(BASE),flatten_range)(multi);
967 return multi;
970 /* Given two multi expressions, "multi1"
972 * [A] -> [B1 B2]
974 * where B2 starts at position "pos", and "multi2"
976 * [A] -> [D]
978 * return the multi expression
980 * [A] -> [B1 D B2]
982 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
983 __isl_take MULTI(BASE) *multi1, unsigned pos,
984 __isl_take MULTI(BASE) *multi2)
986 MULTI(BASE) *res;
987 unsigned dim;
989 if (!multi1 || !multi2)
990 goto error;
992 dim = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
993 if (pos > dim)
994 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
995 "index out of bounds", goto error);
997 res = FN(MULTI(BASE),copy)(multi1);
998 res = FN(MULTI(BASE),drop_dims)(res, isl_dim_out, pos, dim - pos);
999 multi1 = FN(MULTI(BASE),drop_dims)(multi1, isl_dim_out, 0, pos);
1001 res = FN(MULTI(BASE),flat_range_product)(res, multi2);
1002 res = FN(MULTI(BASE),flat_range_product)(res, multi1);
1004 return res;
1005 error:
1006 FN(MULTI(BASE),free)(multi1);
1007 FN(MULTI(BASE),free)(multi2);
1008 return NULL;
1011 #ifndef NO_SPLICE
1012 /* Given two multi expressions, "multi1"
1014 * [A1 A2] -> [B1 B2]
1016 * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
1017 * and "multi2"
1019 * [C] -> [D]
1021 * return the multi expression
1023 * [A1 C A2] -> [B1 D B2]
1025 * We first insert input dimensions to obtain
1027 * [A1 C A2] -> [B1 B2]
1029 * and
1031 * [A1 C A2] -> [D]
1033 * and then apply range_splice.
1035 __isl_give MULTI(BASE) *FN(MULTI(BASE),splice)(
1036 __isl_take MULTI(BASE) *multi1, unsigned in_pos, unsigned out_pos,
1037 __isl_take MULTI(BASE) *multi2)
1039 unsigned n_in1;
1040 unsigned n_in2;
1042 if (!multi1 || !multi2)
1043 goto error;
1045 n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
1046 if (in_pos > n_in1)
1047 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1048 "index out of bounds", goto error);
1050 n_in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
1052 multi1 = FN(MULTI(BASE),insert_dims)(multi1, isl_dim_in, in_pos, n_in2);
1053 multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, n_in2,
1054 n_in1 - in_pos);
1055 multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, 0, in_pos);
1057 return FN(MULTI(BASE),range_splice)(multi1, out_pos, multi2);
1058 error:
1059 FN(MULTI(BASE),free)(multi1);
1060 FN(MULTI(BASE),free)(multi2);
1061 return NULL;
1063 #endif
1065 /* This function is currently only used from isl_aff.c
1067 static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
1068 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
1069 __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
1070 __attribute__ ((unused));
1072 /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
1073 * return the result.
1075 static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
1076 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
1077 __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
1079 int i;
1080 isl_ctx *ctx;
1082 multi1 = FN(MULTI(BASE),cow)(multi1);
1083 if (!multi1 || !multi2)
1084 goto error;
1086 ctx = FN(MULTI(BASE),get_ctx)(multi1);
1087 if (!isl_space_is_equal(multi1->space, multi2->space))
1088 isl_die(ctx, isl_error_invalid,
1089 "spaces don't match", goto error);
1091 for (i = 0; i < multi1->n; ++i) {
1092 multi1->p[i] = fn(multi1->p[i], FN(EL,copy)(multi2->p[i]));
1093 if (!multi1->p[i])
1094 goto error;
1097 FN(MULTI(BASE),free)(multi2);
1098 return multi1;
1099 error:
1100 FN(MULTI(BASE),free)(multi1);
1101 FN(MULTI(BASE),free)(multi2);
1102 return NULL;
1105 /* Add "multi2" from "multi1" and return the result.
1107 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1109 static __isl_give MULTI(BASE) *FN(MULTI(BASE),add_aligned)(
1110 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1112 return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,add));
1115 /* Add "multi2" from "multi1" and return the result.
1117 __isl_give MULTI(BASE) *FN(MULTI(BASE),add)(__isl_take MULTI(BASE) *multi1,
1118 __isl_take MULTI(BASE) *multi2)
1120 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
1121 &FN(MULTI(BASE),add_aligned));
1124 /* Subtract "multi2" from "multi1" and return the result.
1126 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1128 static __isl_give MULTI(BASE) *FN(MULTI(BASE),sub_aligned)(
1129 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1131 return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
1134 /* Subtract "multi2" from "multi1" and return the result.
1136 __isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
1137 __isl_take MULTI(BASE) *multi2)
1139 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
1140 &FN(MULTI(BASE),sub_aligned));
1143 /* Multiply the elements of "multi" by "v" and return the result.
1145 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
1146 __isl_take isl_val *v)
1148 int i;
1150 if (!multi || !v)
1151 goto error;
1153 if (isl_val_is_one(v)) {
1154 isl_val_free(v);
1155 return multi;
1158 if (!isl_val_is_rat(v))
1159 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1160 "expecting rational factor", goto error);
1162 multi = FN(MULTI(BASE),cow)(multi);
1163 if (!multi)
1164 return NULL;
1166 for (i = 0; i < multi->n; ++i) {
1167 multi->p[i] = FN(EL,scale_val)(multi->p[i], isl_val_copy(v));
1168 if (!multi->p[i])
1169 goto error;
1172 isl_val_free(v);
1173 return multi;
1174 error:
1175 isl_val_free(v);
1176 return FN(MULTI(BASE),free)(multi);
1179 /* Divide the elements of "multi" by "v" and return the result.
1181 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
1182 __isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
1184 int i;
1186 if (!multi || !v)
1187 goto error;
1189 if (isl_val_is_one(v)) {
1190 isl_val_free(v);
1191 return multi;
1194 if (!isl_val_is_rat(v))
1195 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1196 "expecting rational factor", goto error);
1197 if (isl_val_is_zero(v))
1198 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1199 "cannot scale down by zero", goto error);
1201 multi = FN(MULTI(BASE),cow)(multi);
1202 if (!multi)
1203 return NULL;
1205 for (i = 0; i < multi->n; ++i) {
1206 multi->p[i] = FN(EL,scale_down_val)(multi->p[i],
1207 isl_val_copy(v));
1208 if (!multi->p[i])
1209 goto error;
1212 isl_val_free(v);
1213 return multi;
1214 error:
1215 isl_val_free(v);
1216 return FN(MULTI(BASE),free)(multi);
1219 /* Multiply the elements of "multi" by the corresponding element of "mv"
1220 * and return the result.
1222 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
1223 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1225 int i;
1227 if (!multi || !mv)
1228 goto error;
1230 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1231 mv->space, isl_dim_set))
1232 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1233 "spaces don't match", goto error);
1235 multi = FN(MULTI(BASE),cow)(multi);
1236 if (!multi)
1237 goto error;
1239 for (i = 0; i < multi->n; ++i) {
1240 isl_val *v;
1242 v = isl_multi_val_get_val(mv, i);
1243 multi->p[i] = FN(EL,scale_val)(multi->p[i], v);
1244 if (!multi->p[i])
1245 goto error;
1248 isl_multi_val_free(mv);
1249 return multi;
1250 error:
1251 isl_multi_val_free(mv);
1252 return FN(MULTI(BASE),free)(multi);
1255 /* Divide the elements of "multi" by the corresponding element of "mv"
1256 * and return the result.
1258 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
1259 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1261 int i;
1263 if (!multi || !mv)
1264 goto error;
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);
1272 if (!multi)
1273 return NULL;
1275 for (i = 0; i < multi->n; ++i) {
1276 isl_val *v;
1278 v = isl_multi_val_get_val(mv, i);
1279 multi->p[i] = FN(EL,scale_down_val)(multi->p[i], v);
1280 if (!multi->p[i])
1281 goto error;
1284 isl_multi_val_free(mv);
1285 return multi;
1286 error:
1287 isl_multi_val_free(mv);
1288 return FN(MULTI(BASE),free)(multi);
1291 /* Compute the residues of the elements of "multi" modulo
1292 * the corresponding element of "mv" and return the result.
1294 __isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
1295 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1297 int i;
1299 if (!multi || !mv)
1300 goto error;
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);
1308 if (!multi)
1309 goto error;
1311 for (i = 0; i < multi->n; ++i) {
1312 isl_val *v;
1314 v = isl_multi_val_get_val(mv, i);
1315 multi->p[i] = FN(EL,mod_val)(multi->p[i], v);
1316 if (!multi->p[i])
1317 goto error;
1320 isl_multi_val_free(mv);
1321 return multi;
1322 error:
1323 isl_multi_val_free(mv);
1324 return FN(MULTI(BASE),free)(multi);
1327 #ifndef NO_MOVE_DIMS
1328 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
1329 * to dimensions of "dst_type" at "dst_pos".
1331 * We only support moving input dimensions to parameters and vice versa.
1333 __isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
1334 enum isl_dim_type dst_type, unsigned dst_pos,
1335 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1337 int i;
1339 if (!multi)
1340 return NULL;
1342 if (n == 0 &&
1343 !isl_space_is_named_or_nested(multi->space, src_type) &&
1344 !isl_space_is_named_or_nested(multi->space, dst_type))
1345 return multi;
1347 if (dst_type == isl_dim_out || src_type == isl_dim_out)
1348 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1349 "cannot move output/set dimension",
1350 return FN(MULTI(BASE),free)(multi));
1351 if (dst_type == isl_dim_div || src_type == isl_dim_div)
1352 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1353 "cannot move divs",
1354 return FN(MULTI(BASE),free)(multi));
1355 if (src_pos + n > isl_space_dim(multi->space, src_type))
1356 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1357 "range out of bounds",
1358 return FN(MULTI(BASE),free)(multi));
1359 if (dst_type == src_type)
1360 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_unsupported,
1361 "moving dims within the same type not supported",
1362 return FN(MULTI(BASE),free)(multi));
1364 multi = FN(MULTI(BASE),cow)(multi);
1365 if (!multi)
1366 return NULL;
1368 multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
1369 src_type, src_pos, n);
1370 if (!multi->space)
1371 return FN(MULTI(BASE),free)(multi);
1373 for (i = 0; i < multi->n; ++i) {
1374 multi->p[i] = FN(EL,move_dims)(multi->p[i], dst_type, dst_pos,
1375 src_type, src_pos, n);
1376 if (!multi->p[i])
1377 return FN(MULTI(BASE),free)(multi);
1380 return multi;
1382 #endif
1384 /* Convert a multiple expression defined over a parameter domain
1385 * into one that is defined over a zero-dimensional set.
1387 __isl_give MULTI(BASE) *FN(MULTI(BASE),from_range)(
1388 __isl_take MULTI(BASE) *multi)
1390 isl_space *space;
1392 if (!multi)
1393 return NULL;
1394 if (!isl_space_is_set(multi->space))
1395 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1396 "not living in a set space",
1397 return FN(MULTI(BASE),free)(multi));
1399 space = FN(MULTI(BASE),get_space)(multi);
1400 space = isl_space_from_range(space);
1401 multi = FN(MULTI(BASE),reset_space)(multi, space);
1403 return multi;
1406 /* Are "multi1" and "multi2" obviously equal?
1408 isl_bool FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1,
1409 __isl_keep MULTI(BASE) *multi2)
1411 int i;
1412 isl_bool equal;
1414 if (!multi1 || !multi2)
1415 return isl_bool_error;
1416 if (multi1->n != multi2->n)
1417 return isl_bool_false;
1418 equal = isl_space_is_equal(multi1->space, multi2->space);
1419 if (equal < 0 || !equal)
1420 return equal;
1422 for (i = 0; i < multi1->n; ++i) {
1423 equal = FN(EL,plain_is_equal)(multi1->p[i], multi2->p[i]);
1424 if (equal < 0 || !equal)
1425 return equal;
1428 return isl_bool_true;
1431 /* Does "multi" involve any NaNs?
1433 isl_bool FN(MULTI(BASE),involves_nan)(__isl_keep MULTI(BASE) *multi)
1435 int i;
1437 if (!multi)
1438 return isl_bool_error;
1439 if (multi->n == 0)
1440 return isl_bool_false;
1442 for (i = 0; i < multi->n; ++i) {
1443 isl_bool has_nan = FN(EL,involves_nan)(multi->p[i]);
1444 if (has_nan < 0 || has_nan)
1445 return has_nan;
1448 return isl_bool_false;
1451 #ifndef NO_DOMAIN
1452 /* Return the shared domain of the elements of "multi".
1454 __isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
1456 int i;
1457 isl_set *dom;
1459 if (!multi)
1460 return NULL;
1462 dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
1463 for (i = 0; i < multi->n; ++i) {
1464 isl_set *dom_i;
1466 dom_i = FN(EL,domain)(FN(FN(MULTI(BASE),get),BASE)(multi, i));
1467 dom = isl_set_intersect(dom, dom_i);
1470 FN(MULTI(BASE),free)(multi);
1471 return dom;
1473 #endif
1475 #ifndef NO_NEG
1476 /* Return the opposite of "multi".
1478 __isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
1480 int i;
1482 multi = FN(MULTI(BASE),cow)(multi);
1483 if (!multi)
1484 return NULL;
1486 for (i = 0; i < multi->n; ++i) {
1487 multi->p[i] = FN(EL,neg)(multi->p[i]);
1488 if (!multi->p[i])
1489 return FN(MULTI(BASE),free)(multi);
1492 return multi;
1494 #endif