isl_pw_*_eval: rename "pnt_dim" variable to "pnt_space"
[isl.git] / isl_multi_templ.c
blobbc14033c881527b4b49d3b8932ae1f606e987a02
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 __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
32 * in "multi".
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)
38 if (!multi)
39 return -1;
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)
57 isl_ctx *ctx;
58 int n;
59 MULTI(BASE) *multi;
61 if (!space)
62 return NULL;
64 ctx = isl_space_get_ctx(space);
65 n = isl_space_dim(space, isl_dim_out);
66 if (n > 0)
67 multi = isl_calloc(ctx, MULTI(BASE),
68 sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *));
69 else
70 multi = isl_calloc(ctx, MULTI(BASE), sizeof(MULTI(BASE)));
71 if (!multi)
72 goto error;
74 multi->space = space;
75 multi->n = n;
76 multi->ref = 1;
77 if (FN(MULTI(BASE),has_explicit_domain)(multi))
78 multi = FN(MULTI(BASE),init_explicit_domain)(multi);
79 return multi;
80 error:
81 isl_space_free(space);
82 return NULL;
85 __isl_give MULTI(BASE) *FN(MULTI(BASE),dup)(__isl_keep MULTI(BASE) *multi)
87 int i;
88 MULTI(BASE) *dup;
90 if (!multi)
91 return NULL;
93 dup = FN(MULTI(BASE),alloc)(isl_space_copy(multi->space));
94 if (!dup)
95 return NULL;
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);
103 return dup;
106 __isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi)
108 if (!multi)
109 return NULL;
111 if (multi->ref == 1)
112 return multi;
114 multi->ref--;
115 return FN(MULTI(BASE),dup)(multi);
118 __isl_give MULTI(BASE) *FN(MULTI(BASE),copy)(__isl_keep MULTI(BASE) *multi)
120 if (!multi)
121 return NULL;
123 multi->ref++;
124 return multi;
127 __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
129 int i;
131 if (!multi)
132 return NULL;
134 if (--multi->ref > 0)
135 return NULL;
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);
142 free(multi);
144 return NULL;
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)
159 if (!multi)
160 return -1;
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)
176 int i;
178 multi = FN(MULTI(BASE),cow)(multi);
179 if (!multi)
180 return NULL;
182 multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
183 if (!multi->space)
184 return FN(MULTI(BASE),free)(multi);
186 if (type == isl_dim_out)
187 return multi;
188 for (i = 0; i < multi->n; ++i) {
189 multi->u.p[i] = FN(EL,set_dim_name)(multi->u.p[i],
190 type, pos, s);
191 if (!multi->u.p[i])
192 return FN(MULTI(BASE),free)(multi);
195 return 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)
209 if (!multi)
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,
223 int pos)
225 isl_ctx *ctx;
227 if (!multi)
228 return NULL;
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;
241 isl_bool match;
243 multi = FN(MULTI(BASE),cow)(multi);
244 if (!multi || !el)
245 goto error;
247 multi_space = FN(MULTI(BASE),get_space)(multi);
248 match = FN(EL,matching_params)(el, multi_space);
249 if (match < 0)
250 goto error;
251 if (!match) {
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)
259 goto error;
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);
271 return multi;
272 error:
273 FN(MULTI(BASE),free)(multi);
274 FN(EL,free)(el);
275 isl_space_free(multi_space);
276 isl_space_free(el_space);
277 return NULL;
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)
294 int i;
296 multi = FN(MULTI(BASE),cow)(multi);
297 if (!multi || !space || !domain)
298 goto error;
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));
303 if (!multi->u.p[i])
304 goto error;
306 if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
307 multi = FN(MULTI(BASE),reset_explicit_domain_space)(multi,
308 isl_space_copy(domain));
309 if (!multi)
310 goto error;
312 isl_space_free(domain);
313 isl_space_free(multi->space);
314 multi->space = space;
316 return multi;
317 error:
318 isl_space_free(domain);
319 isl_space_free(space);
320 FN(MULTI(BASE),free)(multi);
321 return NULL;
324 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_domain_space)(
325 __isl_take MULTI(BASE) *multi, __isl_take isl_space *domain)
327 isl_space *space;
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)
337 isl_space *domain;
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)
349 isl_space *space;
351 multi = FN(MULTI(BASE),cow)(multi);
352 if (!multi || !id)
353 goto error;
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);
359 error:
360 isl_id_free(id);
361 FN(MULTI(BASE),free)(multi);
362 return NULL;
365 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_name)(
366 __isl_keep MULTI(BASE) *multi, enum isl_dim_type type,
367 const char *s)
369 isl_space *space;
371 multi = FN(MULTI(BASE),cow)(multi);
372 if (!multi)
373 return NULL;
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)
385 isl_space *space;
387 multi = FN(MULTI(BASE),cow)(multi);
388 if (!multi)
389 goto error;
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);
395 error:
396 isl_id_free(id);
397 return NULL;
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)
405 isl_space *space;
407 if (!multi)
408 return NULL;
409 if (!FN(MULTI(BASE),has_tuple_id)(multi, type))
410 return multi;
412 multi = FN(MULTI(BASE),cow)(multi);
413 if (!multi)
414 return NULL;
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)
428 isl_space *space;
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)
439 int i;
441 multi = FN(MULTI(BASE),cow)(multi);
442 if (!multi || !exp)
443 goto error;
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));
448 if (!multi->u.p[i])
449 goto error;
452 multi = FN(MULTI(BASE),reset_domain_space)(multi,
453 isl_space_copy(exp->dim));
455 isl_reordering_free(exp);
456 return multi;
457 error:
458 isl_reordering_free(exp);
459 FN(MULTI(BASE),free)(multi);
460 return NULL;
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)
471 isl_ctx *ctx;
472 isl_bool equal_params;
473 isl_reordering *exp;
475 if (!multi || !model)
476 goto error;
478 equal_params = isl_space_has_equal_params(multi->space, model);
479 if (equal_params < 0)
480 goto error;
481 if (equal_params) {
482 isl_space_free(model);
483 return multi;
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));
497 if (!multi)
498 goto error;
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);
507 return multi;
508 error:
509 isl_space_free(model);
510 FN(MULTI(BASE),free)(multi);
511 return NULL;
514 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))(
515 __isl_take isl_space *space, __isl_take LIST(EL) *list)
517 int i;
518 int n;
519 isl_ctx *ctx;
520 MULTI(BASE) *multi;
522 if (!space || !list)
523 goto error;
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);
539 return multi;
540 error:
541 isl_space_free(space);
542 FN(LIST(EL),free)(list);
543 return NULL;
546 #ifndef NO_IDENTITY
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)
552 int i, n;
553 isl_local_space *ls;
554 MULTI(BASE) *multi;
556 if (!space)
557 return NULL;
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));
571 if (!n) {
572 isl_space_free(space);
573 return multi;
576 space = isl_space_domain(space);
577 ls = isl_local_space_from_space(space);
579 for (i = 0; i < n; ++i) {
580 EL *el;
581 el = FN(EL,var_on_domain)(isl_local_space_copy(ls),
582 isl_dim_set, i);
583 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i, el);
586 isl_local_space_free(ls);
588 return multi;
589 error:
590 isl_space_free(space);
591 return NULL;
593 #endif
595 #ifndef NO_ZERO
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)
601 int n;
602 MULTI(BASE) *multi;
604 if (!space)
605 return NULL;
607 n = isl_space_dim(space , isl_dim_out);
608 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
610 if (!n)
611 isl_space_free(space);
612 else {
613 int i;
614 isl_local_space *ls;
615 EL *el;
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,
623 FN(EL,copy)(el));
625 FN(EL,free)(el);
628 return multi;
630 #endif
632 #ifndef NO_FROM_BASE
633 /* Create a multiple expression with a single output/set dimension
634 * equal to "el".
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)
644 isl_space *space;
645 MULTI(BASE) *multi;
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);
655 return multi;
657 #endif
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)
663 int i;
664 unsigned dim;
666 multi = FN(MULTI(BASE),cow)(multi);
667 if (!multi)
668 return NULL;
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);
677 if (!multi->space)
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];
685 multi->n -= n;
686 if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi))
687 multi = FN(MULTI(BASE),init_explicit_domain)(multi);
689 return multi;
692 if (FN(MULTI(BASE),has_explicit_domain)(multi))
693 multi = FN(MULTI(BASE),drop_explicit_domain_dims)(multi,
694 type, first, n);
695 if (!multi)
696 return NULL;
698 for (i = 0; i < multi->n; ++i) {
699 multi->u.p[i] = FN(EL,drop_dims)(multi->u.p[i], type, first, n);
700 if (!multi->u.p[i])
701 return FN(MULTI(BASE),free)(multi);
704 return 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))
714 isl_ctx *ctx;
715 isl_bool equal_params;
717 if (!multi1 || !multi2)
718 goto error;
719 equal_params = isl_space_has_equal_params(multi1->space, multi2->space);
720 if (equal_params < 0)
721 goto error;
722 if (equal_params)
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);
734 error:
735 FN(MULTI(BASE),free)(multi1);
736 FN(MULTI(BASE),free)(multi2);
737 return NULL;
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)
751 int i, n1, n2;
752 EL *el;
753 isl_space *space;
754 MULTI(BASE) *res;
756 if (!multi1 || !multi2)
757 goto error;
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);
783 return res;
784 error:
785 FN(MULTI(BASE),free)(multi1);
786 FN(MULTI(BASE),free)(multi2);
787 return NULL;
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)
804 if (!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)
814 isl_space *space;
815 int total, keep;
817 if (!multi)
818 return NULL;
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);
832 return multi;
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)
840 isl_space *space;
841 int total, keep;
843 if (!multi)
844 return NULL;
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);
857 return multi;
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)
865 isl_space *space;
866 int total, keep;
868 if (!multi)
869 return NULL;
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);
881 return multi;
884 #ifndef NO_PRODUCT
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)
896 int i;
897 EL *el;
898 isl_space *space;
899 MULTI(BASE) *res;
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,
928 multi1, multi2);
930 isl_space_free(space);
931 FN(MULTI(BASE),free)(multi1);
932 FN(MULTI(BASE),free)(multi2);
933 return res;
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));
945 #endif
947 __isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
948 __isl_take MULTI(BASE) *multi)
950 if (!multi)
951 return NULL;
953 if (!multi->space->nested[1])
954 return multi;
956 multi = FN(MULTI(BASE),cow)(multi);
957 if (!multi)
958 return NULL;
960 multi->space = isl_space_flatten_range(multi->space);
961 if (!multi->space)
962 return FN(MULTI(BASE),free)(multi);
964 return 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)
973 MULTI(BASE) *multi;
975 multi = FN(MULTI(BASE),range_product)(multi1, multi2);
976 multi = FN(MULTI(BASE),flatten_range)(multi);
977 return multi;
980 /* Given two multi expressions, "multi1"
982 * [A] -> [B1 B2]
984 * where B2 starts at position "pos", and "multi2"
986 * [A] -> [D]
988 * return the multi expression
990 * [A] -> [B1 D B2]
992 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
993 __isl_take MULTI(BASE) *multi1, unsigned pos,
994 __isl_take MULTI(BASE) *multi2)
996 MULTI(BASE) *res;
997 unsigned dim;
999 if (!multi1 || !multi2)
1000 goto error;
1002 dim = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
1003 if (pos > dim)
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);
1014 return res;
1015 error:
1016 FN(MULTI(BASE),free)(multi1);
1017 FN(MULTI(BASE),free)(multi2);
1018 return NULL;
1021 #ifndef NO_SPLICE
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",
1027 * and "multi2"
1029 * [C] -> [D]
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]
1039 * and
1041 * [A1 C A2] -> [D]
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)
1049 unsigned n_in1;
1050 unsigned n_in2;
1052 if (!multi1 || !multi2)
1053 goto error;
1055 n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
1056 if (in_pos > n_in1)
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,
1064 n_in1 - in_pos);
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);
1068 error:
1069 FN(MULTI(BASE),free)(multi1);
1070 FN(MULTI(BASE),free)(multi2);
1071 return NULL;
1073 #endif
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)
1081 isl_bool equal;
1083 if (!multi1 || !multi2)
1084 return isl_stat_error;
1086 equal = isl_space_is_equal(multi1->space, multi2->space);
1087 if (equal < 0)
1088 return isl_stat_error;
1089 if (!equal)
1090 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1091 "spaces don't match", return isl_stat_error);
1093 return isl_stat_ok;
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 *))
1113 int i;
1115 multi1 = FN(MULTI(BASE),cow)(multi1);
1116 if (FN(MULTI(BASE),check_equal_space)(multi1, multi2) < 0)
1117 goto error;
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])
1123 goto error;
1126 if (FN(MULTI(BASE),has_explicit_domain)(multi2))
1127 multi1 = FN(MULTI(BASE),intersect_explicit_domain)(multi1,
1128 multi2);
1130 FN(MULTI(BASE),free)(multi2);
1131 return multi1;
1132 error:
1133 FN(MULTI(BASE),free)(multi1);
1134 FN(MULTI(BASE),free)(multi2);
1135 return NULL;
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)
1181 int i;
1183 if (!multi || !v)
1184 goto error;
1186 if (isl_val_is_one(v)) {
1187 isl_val_free(v);
1188 return multi;
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);
1196 if (!multi)
1197 return NULL;
1199 for (i = 0; i < multi->n; ++i) {
1200 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i],
1201 isl_val_copy(v));
1202 if (!multi->u.p[i])
1203 goto error;
1206 isl_val_free(v);
1207 return multi;
1208 error:
1209 isl_val_free(v);
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)
1218 int i;
1220 if (!multi || !v)
1221 goto error;
1223 if (isl_val_is_one(v)) {
1224 isl_val_free(v);
1225 return multi;
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);
1236 if (!multi)
1237 return NULL;
1239 for (i = 0; i < multi->n; ++i) {
1240 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i],
1241 isl_val_copy(v));
1242 if (!multi->u.p[i])
1243 goto error;
1246 isl_val_free(v);
1247 return multi;
1248 error:
1249 isl_val_free(v);
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)
1259 int i;
1261 if (!multi || !mv)
1262 goto error;
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);
1270 if (!multi)
1271 goto error;
1273 for (i = 0; i < multi->n; ++i) {
1274 isl_val *v;
1276 v = isl_multi_val_get_val(mv, i);
1277 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i], v);
1278 if (!multi->u.p[i])
1279 goto error;
1282 isl_multi_val_free(mv);
1283 return multi;
1284 error:
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)
1295 int i;
1297 if (!multi || !mv)
1298 goto error;
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);
1306 if (!multi)
1307 return NULL;
1309 for (i = 0; i < multi->n; ++i) {
1310 isl_val *v;
1312 v = isl_multi_val_get_val(mv, i);
1313 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i], v);
1314 if (!multi->u.p[i])
1315 goto error;
1318 isl_multi_val_free(mv);
1319 return multi;
1320 error:
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)
1331 int i;
1333 if (!multi || !mv)
1334 goto error;
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);
1342 if (!multi)
1343 goto error;
1345 for (i = 0; i < multi->n; ++i) {
1346 isl_val *v;
1348 v = isl_multi_val_get_val(mv, i);
1349 multi->u.p[i] = FN(EL,mod_val)(multi->u.p[i], v);
1350 if (!multi->u.p[i])
1351 goto error;
1354 isl_multi_val_free(mv);
1355 return multi;
1356 error:
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)
1371 int i;
1373 if (!multi)
1374 return NULL;
1376 if (n == 0 &&
1377 !isl_space_is_named_or_nested(multi->space, src_type) &&
1378 !isl_space_is_named_or_nested(multi->space, dst_type))
1379 return multi;
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,
1387 "cannot move divs",
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);
1399 if (!multi)
1400 return NULL;
1402 multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
1403 src_type, src_pos, n);
1404 if (!multi->space)
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);
1409 if (!multi)
1410 return NULL;
1412 for (i = 0; i < multi->n; ++i) {
1413 multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
1414 dst_type, dst_pos,
1415 src_type, src_pos, n);
1416 if (!multi->u.p[i])
1417 return FN(MULTI(BASE),free)(multi);
1420 return multi;
1422 #endif
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)
1430 isl_space *space;
1432 if (!multi)
1433 return NULL;
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);
1443 return multi;
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)
1451 int i;
1452 isl_bool equal;
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)
1460 return 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)
1465 return 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)
1472 return 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)
1482 int i;
1484 if (!multi)
1485 return isl_bool_error;
1486 if (multi->n == 0)
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)
1492 return has_nan;
1495 return isl_bool_false;
1498 #ifndef NO_DOMAIN
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)
1505 int i;
1506 isl_set *dom;
1508 if (!multi)
1509 return NULL;
1511 if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
1512 dom = FN(MULTI(BASE),get_explicit_domain)(multi);
1513 FN(MULTI(BASE),free)(multi);
1514 return dom;
1517 dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
1518 for (i = 0; i < multi->n; ++i) {
1519 isl_set *dom_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);
1526 return dom;
1528 #endif
1530 #ifndef NO_NEG
1531 /* Return the opposite of "multi".
1533 __isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
1535 int i;
1537 multi = FN(MULTI(BASE),cow)(multi);
1538 if (!multi)
1539 return NULL;
1541 for (i = 0; i < multi->n; ++i) {
1542 multi->u.p[i] = FN(EL,neg)(multi->u.p[i]);
1543 if (!multi->u.p[i])
1544 return FN(MULTI(BASE),free)(multi);
1547 return multi;
1549 #endif