add isl_*_list_swap
[isl.git] / isl_multi_templ.c
blob3403c502e807a9551da4a599671913e7647feb6a
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/id.h>
12 #include <isl_space_private.h>
13 #include <isl_val_private.h>
14 #include <isl/set.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
41 * in "multi".
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)
47 if (!multi)
48 return -1;
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)
66 isl_ctx *ctx;
67 int n;
68 MULTI(BASE) *multi;
70 if (!space)
71 return NULL;
73 ctx = isl_space_get_ctx(space);
74 n = isl_space_dim(space, isl_dim_out);
75 if (n > 0)
76 multi = isl_calloc(ctx, MULTI(BASE),
77 sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *));
78 else
79 multi = isl_calloc(ctx, MULTI(BASE), sizeof(MULTI(BASE)));
80 if (!multi)
81 goto error;
83 multi->space = space;
84 multi->n = n;
85 multi->ref = 1;
86 if (FN(MULTI(BASE),has_explicit_domain)(multi))
87 multi = FN(MULTI(BASE),init_explicit_domain)(multi);
88 return multi;
89 error:
90 isl_space_free(space);
91 return NULL;
94 __isl_give MULTI(BASE) *FN(MULTI(BASE),dup)(__isl_keep MULTI(BASE) *multi)
96 int i;
97 MULTI(BASE) *dup;
99 if (!multi)
100 return NULL;
102 dup = FN(MULTI(BASE),alloc)(isl_space_copy(multi->space));
103 if (!dup)
104 return NULL;
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);
112 return dup;
115 __isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi)
117 if (!multi)
118 return NULL;
120 if (multi->ref == 1)
121 return multi;
123 multi->ref--;
124 return FN(MULTI(BASE),dup)(multi);
127 __isl_give MULTI(BASE) *FN(MULTI(BASE),copy)(__isl_keep MULTI(BASE) *multi)
129 if (!multi)
130 return NULL;
132 multi->ref++;
133 return multi;
136 __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
138 int i;
140 if (!multi)
141 return NULL;
143 if (--multi->ref > 0)
144 return NULL;
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);
151 free(multi);
153 return NULL;
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)
168 if (!multi)
169 return -1;
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)
185 int i;
187 multi = FN(MULTI(BASE),cow)(multi);
188 if (!multi)
189 return NULL;
191 multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
192 if (!multi->space)
193 return FN(MULTI(BASE),free)(multi);
195 if (type == isl_dim_out)
196 return multi;
197 for (i = 0; i < multi->n; ++i) {
198 multi->u.p[i] = FN(EL,set_dim_name)(multi->u.p[i],
199 type, pos, s);
200 if (!multi->u.p[i])
201 return FN(MULTI(BASE),free)(multi);
204 return 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)
218 if (!multi)
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,
232 int pos)
234 isl_ctx *ctx;
236 if (!multi)
237 return NULL;
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);
252 if (!multi || !el)
253 goto error;
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;
262 return multi;
263 error:
264 FN(MULTI(BASE),free)(multi);
265 FN(EL,free)(el);
266 return NULL;
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)
277 isl_space *space;
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;
290 isl_bool match;
292 multi_space = FN(MULTI(BASE),get_space)(multi);
293 match = FN(EL,matching_params)(el, multi_space);
294 if (match < 0)
295 goto error;
296 if (!match) {
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);
309 return multi;
310 error:
311 FN(MULTI(BASE),free)(multi);
312 FN(EL,free)(el);
313 isl_space_free(multi_space);
314 isl_space_free(el_space);
315 return NULL;
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)
332 int i;
334 multi = FN(MULTI(BASE),cow)(multi);
335 if (!multi || !space || !domain)
336 goto error;
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));
341 if (!multi->u.p[i])
342 goto error;
344 if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
345 multi = FN(MULTI(BASE),reset_explicit_domain_space)(multi,
346 isl_space_copy(domain));
347 if (!multi)
348 goto error;
350 isl_space_free(domain);
351 isl_space_free(multi->space);
352 multi->space = space;
354 return multi;
355 error:
356 isl_space_free(domain);
357 isl_space_free(space);
358 FN(MULTI(BASE),free)(multi);
359 return NULL;
362 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_domain_space)(
363 __isl_take MULTI(BASE) *multi, __isl_take isl_space *domain)
365 isl_space *space;
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)
375 isl_space *domain;
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)
387 isl_space *space;
389 multi = FN(MULTI(BASE),cow)(multi);
390 if (!multi || !id)
391 goto error;
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);
397 error:
398 isl_id_free(id);
399 FN(MULTI(BASE),free)(multi);
400 return NULL;
403 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_name)(
404 __isl_keep MULTI(BASE) *multi, enum isl_dim_type type,
405 const char *s)
407 isl_space *space;
409 multi = FN(MULTI(BASE),cow)(multi);
410 if (!multi)
411 return NULL;
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)
423 isl_space *space;
425 multi = FN(MULTI(BASE),cow)(multi);
426 if (!multi)
427 goto error;
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);
433 error:
434 isl_id_free(id);
435 return NULL;
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)
443 isl_space *space;
445 if (!multi)
446 return NULL;
447 if (!FN(MULTI(BASE),has_tuple_id)(multi, type))
448 return multi;
450 multi = FN(MULTI(BASE),cow)(multi);
451 if (!multi)
452 return NULL;
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)
466 isl_space *space;
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)
477 int i;
478 isl_space *space;
480 multi = FN(MULTI(BASE),cow)(multi);
481 if (!multi || !exp)
482 goto error;
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));
487 if (!multi->u.p[i])
488 goto error;
491 space = isl_reordering_get_space(exp);
492 multi = FN(MULTI(BASE),reset_domain_space)(multi, space);
494 isl_reordering_free(exp);
495 return multi;
496 error:
497 isl_reordering_free(exp);
498 FN(MULTI(BASE),free)(multi);
499 return NULL;
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)
510 isl_ctx *ctx;
511 isl_bool equal_params;
512 isl_reordering *exp;
514 if (!multi || !model)
515 goto error;
517 equal_params = isl_space_has_equal_params(multi->space, model);
518 if (equal_params < 0)
519 goto error;
520 if (equal_params) {
521 isl_space_free(model);
522 return multi;
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));
536 if (!multi)
537 goto error;
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);
545 return multi;
546 error:
547 isl_space_free(model);
548 FN(MULTI(BASE),free)(multi);
549 return NULL;
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)
562 int i;
563 int n;
564 isl_ctx *ctx;
565 MULTI(BASE) *multi;
567 if (!space || !list)
568 goto error;
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);
589 return multi;
590 error:
591 isl_space_free(space);
592 FN(LIST(EL),free)(list);
593 return NULL;
596 #ifndef NO_IDENTITY
597 /* Create a multi expression in the given space that maps each
598 * input dimension to the corresponding output dimension.
600 __isl_give MULTI(BASE) *FN(MULTI(BASE),identity)(__isl_take isl_space *space)
602 int i, n;
603 isl_local_space *ls;
604 MULTI(BASE) *multi;
606 if (!space)
607 return NULL;
609 if (isl_space_is_set(space))
610 isl_die(isl_space_get_ctx(space), isl_error_invalid,
611 "expecting map space", goto error);
613 n = isl_space_dim(space, isl_dim_out);
614 if (n != isl_space_dim(space, isl_dim_in))
615 isl_die(isl_space_get_ctx(space), isl_error_invalid,
616 "number of input and output dimensions needs to be "
617 "the same", goto error);
619 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
621 if (!n) {
622 isl_space_free(space);
623 return multi;
626 space = isl_space_domain(space);
627 ls = isl_local_space_from_space(space);
629 for (i = 0; i < n; ++i) {
630 EL *el;
631 el = FN(EL,var_on_domain)(isl_local_space_copy(ls),
632 isl_dim_set, i);
633 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i, el);
636 isl_local_space_free(ls);
638 return multi;
639 error:
640 isl_space_free(space);
641 return NULL;
643 #endif
645 #ifndef NO_ZERO
646 /* Construct a multi expression in the given space with value zero in
647 * each of the output dimensions.
649 __isl_give MULTI(BASE) *FN(MULTI(BASE),zero)(__isl_take isl_space *space)
651 int n;
652 MULTI(BASE) *multi;
654 if (!space)
655 return NULL;
657 n = isl_space_dim(space , isl_dim_out);
658 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
660 if (!n)
661 isl_space_free(space);
662 else {
663 int i;
664 isl_local_space *ls;
665 EL *el;
667 space = isl_space_domain(space);
668 ls = isl_local_space_from_space(space);
669 el = FN(EL,zero_on_domain)(ls);
671 for (i = 0; i < n; ++i)
672 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
673 FN(EL,copy)(el));
675 FN(EL,free)(el);
678 return multi;
680 #endif
682 #ifndef NO_FROM_BASE
683 /* Create a multiple expression with a single output/set dimension
684 * equal to "el".
685 * For most multiple expression types, the base type has a single
686 * output/set dimension and the space of the result is therefore
687 * the same as the space of the input.
688 * In the case of isl_multi_union_pw_aff, however, the base type
689 * lives in a parameter space and we therefore need to add
690 * a single set dimension.
692 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
694 isl_space *space;
695 MULTI(BASE) *multi;
697 space = FN(EL,get_space(el));
698 if (isl_space_is_params(space)) {
699 space = isl_space_set_from_params(space);
700 space = isl_space_add_dims(space, isl_dim_set, 1);
702 multi = FN(MULTI(BASE),alloc)(space);
703 multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
705 return multi;
707 #endif
709 __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
710 __isl_take MULTI(BASE) *multi,
711 enum isl_dim_type type, unsigned first, unsigned n)
713 int i;
714 unsigned dim;
716 multi = FN(MULTI(BASE),cow)(multi);
717 if (!multi)
718 return NULL;
720 dim = FN(MULTI(BASE),dim)(multi, type);
721 if (first + n > dim || first + n < first)
722 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
723 "index out of bounds",
724 return FN(MULTI(BASE),free)(multi));
726 multi->space = isl_space_drop_dims(multi->space, type, first, n);
727 if (!multi->space)
728 return FN(MULTI(BASE),free)(multi);
730 if (type == isl_dim_out) {
731 for (i = 0; i < n; ++i)
732 FN(EL,free)(multi->u.p[first + i]);
733 for (i = first; i + n < multi->n; ++i)
734 multi->u.p[i] = multi->u.p[i + n];
735 multi->n -= n;
736 if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi))
737 multi = FN(MULTI(BASE),init_explicit_domain)(multi);
739 return multi;
742 if (FN(MULTI(BASE),has_explicit_domain)(multi))
743 multi = FN(MULTI(BASE),drop_explicit_domain_dims)(multi,
744 type, first, n);
745 if (!multi)
746 return NULL;
748 for (i = 0; i < multi->n; ++i) {
749 multi->u.p[i] = FN(EL,drop_dims)(multi->u.p[i], type, first, n);
750 if (!multi->u.p[i])
751 return FN(MULTI(BASE),free)(multi);
754 return multi;
757 /* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
759 static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_multi_and)(
760 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
761 __isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi1,
762 __isl_take MULTI(BASE) *multi2))
764 isl_ctx *ctx;
765 isl_bool equal_params;
767 if (!multi1 || !multi2)
768 goto error;
769 equal_params = isl_space_has_equal_params(multi1->space, multi2->space);
770 if (equal_params < 0)
771 goto error;
772 if (equal_params)
773 return fn(multi1, multi2);
774 ctx = FN(MULTI(BASE),get_ctx)(multi1);
775 if (!isl_space_has_named_params(multi1->space) ||
776 !isl_space_has_named_params(multi2->space))
777 isl_die(ctx, isl_error_invalid,
778 "unaligned unnamed parameters", goto error);
779 multi1 = FN(MULTI(BASE),align_params)(multi1,
780 FN(MULTI(BASE),get_space)(multi2));
781 multi2 = FN(MULTI(BASE),align_params)(multi2,
782 FN(MULTI(BASE),get_space)(multi1));
783 return fn(multi1, multi2);
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 * The parameters are assumed to have been aligned.
795 * If "multi1" and/or "multi2" has an explicit domain, then
796 * intersect the domain of the result with these explicit domains.
798 static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
799 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
801 int i, n1, n2;
802 EL *el;
803 isl_space *space;
804 MULTI(BASE) *res;
806 if (!multi1 || !multi2)
807 goto error;
809 space = isl_space_range_product(FN(MULTI(BASE),get_space)(multi1),
810 FN(MULTI(BASE),get_space)(multi2));
811 res = FN(MULTI(BASE),alloc)(space);
813 n1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
814 n2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
816 for (i = 0; i < n1; ++i) {
817 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
818 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
821 for (i = 0; i < n2; ++i) {
822 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
823 res = FN(FN(MULTI(BASE),set),BASE)(res, n1 + i, el);
826 if (FN(MULTI(BASE),has_explicit_domain)(multi1))
827 res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi1);
828 if (FN(MULTI(BASE),has_explicit_domain)(multi2))
829 res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi2);
831 FN(MULTI(BASE),free)(multi1);
832 FN(MULTI(BASE),free)(multi2);
833 return res;
834 error:
835 FN(MULTI(BASE),free)(multi1);
836 FN(MULTI(BASE),free)(multi2);
837 return NULL;
840 /* Given two MULTI(BASE)s A -> B and C -> D,
841 * construct a MULTI(BASE) (A * C) -> [B -> D].
843 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)(
844 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
846 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
847 &FN(MULTI(BASE),range_product_aligned));
850 /* Is the range of "multi" a wrapped relation?
852 isl_bool FN(MULTI(BASE),range_is_wrapping)(__isl_keep MULTI(BASE) *multi)
854 if (!multi)
855 return isl_bool_error;
856 return isl_space_range_is_wrapping(multi->space);
859 /* Given a function A -> [B -> C], extract the function A -> B.
861 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_domain)(
862 __isl_take MULTI(BASE) *multi)
864 isl_space *space;
865 int total, keep;
867 if (!multi)
868 return NULL;
869 if (!isl_space_range_is_wrapping(multi->space))
870 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
871 "range is not a product",
872 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_range_factor_domain(space);
877 keep = isl_space_dim(space, isl_dim_out);
878 multi = FN(MULTI(BASE),drop_dims)(multi,
879 isl_dim_out, keep, total - keep);
880 multi = FN(MULTI(BASE),reset_space)(multi, space);
882 return multi;
885 /* Given a function A -> [B -> C], extract the function A -> C.
887 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)(
888 __isl_take MULTI(BASE) *multi)
890 isl_space *space;
891 int total, keep;
893 if (!multi)
894 return NULL;
895 if (!isl_space_range_is_wrapping(multi->space))
896 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
897 "range is not a product",
898 return FN(MULTI(BASE),free)(multi));
900 space = FN(MULTI(BASE),get_space)(multi);
901 total = isl_space_dim(space, isl_dim_out);
902 space = isl_space_range_factor_range(space);
903 keep = isl_space_dim(space, isl_dim_out);
904 multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
905 multi = FN(MULTI(BASE),reset_space)(multi, space);
907 return multi;
910 /* Given a function [B -> C], extract the function C.
912 __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
913 __isl_take MULTI(BASE) *multi)
915 isl_space *space;
916 int total, keep;
918 if (!multi)
919 return NULL;
920 if (!isl_space_is_wrapping(multi->space))
921 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
922 "not a product", return FN(MULTI(BASE),free)(multi));
924 space = FN(MULTI(BASE),get_space)(multi);
925 total = isl_space_dim(space, isl_dim_out);
926 space = isl_space_factor_range(space);
927 keep = isl_space_dim(space, isl_dim_out);
928 multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
929 multi = FN(MULTI(BASE),reset_space)(multi, space);
931 return multi;
934 #ifndef NO_PRODUCT
935 /* Given two MULTI(BASE)s A -> B and C -> D,
936 * construct a MULTI(BASE) [A -> C] -> [B -> D].
938 * The parameters are assumed to have been aligned.
940 * If "multi1" and/or "multi2" has an explicit domain, then
941 * intersect the domain of the result with these explicit domains.
943 __isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
944 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
946 int i;
947 EL *el;
948 isl_space *space;
949 MULTI(BASE) *res;
950 int in1, in2, out1, out2;
952 in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
953 in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
954 out1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
955 out2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
956 space = isl_space_product(FN(MULTI(BASE),get_space)(multi1),
957 FN(MULTI(BASE),get_space)(multi2));
958 res = FN(MULTI(BASE),alloc)(isl_space_copy(space));
959 space = isl_space_domain(space);
961 for (i = 0; i < out1; ++i) {
962 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
963 el = FN(EL,insert_dims)(el, isl_dim_in, in1, in2);
964 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
965 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
968 for (i = 0; i < out2; ++i) {
969 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
970 el = FN(EL,insert_dims)(el, isl_dim_in, 0, in1);
971 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
972 res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
975 if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
976 FN(MULTI(BASE),has_explicit_domain)(multi2))
977 res = FN(MULTI(BASE),intersect_explicit_domain_product)(res,
978 multi1, multi2);
980 isl_space_free(space);
981 FN(MULTI(BASE),free)(multi1);
982 FN(MULTI(BASE),free)(multi2);
983 return res;
986 /* Given two MULTI(BASE)s A -> B and C -> D,
987 * construct a MULTI(BASE) [A -> C] -> [B -> D].
989 __isl_give MULTI(BASE) *FN(MULTI(BASE),product)(
990 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
992 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
993 &FN(MULTI(BASE),product_aligned));
995 #endif
997 __isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
998 __isl_take MULTI(BASE) *multi)
1000 if (!multi)
1001 return NULL;
1003 if (!multi->space->nested[1])
1004 return multi;
1006 multi = FN(MULTI(BASE),cow)(multi);
1007 if (!multi)
1008 return NULL;
1010 multi->space = isl_space_flatten_range(multi->space);
1011 if (!multi->space)
1012 return FN(MULTI(BASE),free)(multi);
1014 return multi;
1017 /* Given two MULTI(BASE)s A -> B and C -> D,
1018 * construct a MULTI(BASE) (A * C) -> (B, D).
1020 __isl_give MULTI(BASE) *FN(MULTI(BASE),flat_range_product)(
1021 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1023 MULTI(BASE) *multi;
1025 multi = FN(MULTI(BASE),range_product)(multi1, multi2);
1026 multi = FN(MULTI(BASE),flatten_range)(multi);
1027 return multi;
1030 /* Given two multi expressions, "multi1"
1032 * [A] -> [B1 B2]
1034 * where B2 starts at position "pos", and "multi2"
1036 * [A] -> [D]
1038 * return the multi expression
1040 * [A] -> [B1 D B2]
1042 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
1043 __isl_take MULTI(BASE) *multi1, unsigned pos,
1044 __isl_take MULTI(BASE) *multi2)
1046 MULTI(BASE) *res;
1047 unsigned dim;
1049 if (!multi1 || !multi2)
1050 goto error;
1052 dim = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
1053 if (pos > dim)
1054 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1055 "index out of bounds", goto error);
1057 res = FN(MULTI(BASE),copy)(multi1);
1058 res = FN(MULTI(BASE),drop_dims)(res, isl_dim_out, pos, dim - pos);
1059 multi1 = FN(MULTI(BASE),drop_dims)(multi1, isl_dim_out, 0, pos);
1061 res = FN(MULTI(BASE),flat_range_product)(res, multi2);
1062 res = FN(MULTI(BASE),flat_range_product)(res, multi1);
1064 return res;
1065 error:
1066 FN(MULTI(BASE),free)(multi1);
1067 FN(MULTI(BASE),free)(multi2);
1068 return NULL;
1071 #ifndef NO_SPLICE
1072 /* Given two multi expressions, "multi1"
1074 * [A1 A2] -> [B1 B2]
1076 * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
1077 * and "multi2"
1079 * [C] -> [D]
1081 * return the multi expression
1083 * [A1 C A2] -> [B1 D B2]
1085 * We first insert input dimensions to obtain
1087 * [A1 C A2] -> [B1 B2]
1089 * and
1091 * [A1 C A2] -> [D]
1093 * and then apply range_splice.
1095 __isl_give MULTI(BASE) *FN(MULTI(BASE),splice)(
1096 __isl_take MULTI(BASE) *multi1, unsigned in_pos, unsigned out_pos,
1097 __isl_take MULTI(BASE) *multi2)
1099 unsigned n_in1;
1100 unsigned n_in2;
1102 if (!multi1 || !multi2)
1103 goto error;
1105 n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
1106 if (in_pos > n_in1)
1107 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1108 "index out of bounds", goto error);
1110 n_in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
1112 multi1 = FN(MULTI(BASE),insert_dims)(multi1, isl_dim_in, in_pos, n_in2);
1113 multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, n_in2,
1114 n_in1 - in_pos);
1115 multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, 0, in_pos);
1117 return FN(MULTI(BASE),range_splice)(multi1, out_pos, multi2);
1118 error:
1119 FN(MULTI(BASE),free)(multi1);
1120 FN(MULTI(BASE),free)(multi2);
1121 return NULL;
1123 #endif
1125 /* Check that "multi1" and "multi2" live in the same space,
1126 * reporting an error if they do not.
1128 static isl_stat FN(MULTI(BASE),check_equal_space)(
1129 __isl_keep MULTI(BASE) *multi1, __isl_keep MULTI(BASE) *multi2)
1131 isl_bool equal;
1133 if (!multi1 || !multi2)
1134 return isl_stat_error;
1136 equal = isl_space_is_equal(multi1->space, multi2->space);
1137 if (equal < 0)
1138 return isl_stat_error;
1139 if (!equal)
1140 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1141 "spaces don't match", return isl_stat_error);
1143 return isl_stat_ok;
1146 /* This function is currently only used from isl_aff.c
1148 static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
1149 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
1150 __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
1151 __attribute__ ((unused));
1153 /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
1154 * return the result.
1156 * If "multi2" has an explicit domain, then
1157 * intersect the domain of the result with this explicit domain.
1159 static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
1160 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
1161 __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
1163 int i;
1165 multi1 = FN(MULTI(BASE),cow)(multi1);
1166 if (FN(MULTI(BASE),check_equal_space)(multi1, multi2) < 0)
1167 goto error;
1169 for (i = 0; i < multi1->n; ++i) {
1170 multi1->u.p[i] = fn(multi1->u.p[i],
1171 FN(EL,copy)(multi2->u.p[i]));
1172 if (!multi1->u.p[i])
1173 goto error;
1176 if (FN(MULTI(BASE),has_explicit_domain)(multi2))
1177 multi1 = FN(MULTI(BASE),intersect_explicit_domain)(multi1,
1178 multi2);
1180 FN(MULTI(BASE),free)(multi2);
1181 return multi1;
1182 error:
1183 FN(MULTI(BASE),free)(multi1);
1184 FN(MULTI(BASE),free)(multi2);
1185 return NULL;
1188 /* Add "multi2" from "multi1" and return the result.
1190 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1192 static __isl_give MULTI(BASE) *FN(MULTI(BASE),add_aligned)(
1193 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1195 return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,add));
1198 /* Add "multi2" from "multi1" and return the result.
1200 __isl_give MULTI(BASE) *FN(MULTI(BASE),add)(__isl_take MULTI(BASE) *multi1,
1201 __isl_take MULTI(BASE) *multi2)
1203 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
1204 &FN(MULTI(BASE),add_aligned));
1207 /* Subtract "multi2" from "multi1" and return the result.
1209 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1211 static __isl_give MULTI(BASE) *FN(MULTI(BASE),sub_aligned)(
1212 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1214 return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
1217 /* Subtract "multi2" from "multi1" and return the result.
1219 __isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
1220 __isl_take MULTI(BASE) *multi2)
1222 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
1223 &FN(MULTI(BASE),sub_aligned));
1226 /* Multiply the elements of "multi" by "v" and return the result.
1228 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
1229 __isl_take isl_val *v)
1231 int i;
1233 if (!multi || !v)
1234 goto error;
1236 if (isl_val_is_one(v)) {
1237 isl_val_free(v);
1238 return multi;
1241 if (!isl_val_is_rat(v))
1242 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1243 "expecting rational factor", goto error);
1245 multi = FN(MULTI(BASE),cow)(multi);
1246 if (!multi)
1247 return NULL;
1249 for (i = 0; i < multi->n; ++i) {
1250 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i],
1251 isl_val_copy(v));
1252 if (!multi->u.p[i])
1253 goto error;
1256 isl_val_free(v);
1257 return multi;
1258 error:
1259 isl_val_free(v);
1260 return FN(MULTI(BASE),free)(multi);
1263 /* Divide the elements of "multi" by "v" and return the result.
1265 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
1266 __isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
1268 int i;
1270 if (!multi || !v)
1271 goto error;
1273 if (isl_val_is_one(v)) {
1274 isl_val_free(v);
1275 return multi;
1278 if (!isl_val_is_rat(v))
1279 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1280 "expecting rational factor", goto error);
1281 if (isl_val_is_zero(v))
1282 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1283 "cannot scale down by zero", goto error);
1285 multi = FN(MULTI(BASE),cow)(multi);
1286 if (!multi)
1287 return NULL;
1289 for (i = 0; i < multi->n; ++i) {
1290 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i],
1291 isl_val_copy(v));
1292 if (!multi->u.p[i])
1293 goto error;
1296 isl_val_free(v);
1297 return multi;
1298 error:
1299 isl_val_free(v);
1300 return FN(MULTI(BASE),free)(multi);
1303 /* Multiply the elements of "multi" by the corresponding element of "mv"
1304 * and return the result.
1306 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
1307 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1309 int i;
1311 if (!multi || !mv)
1312 goto error;
1314 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1315 mv->space, isl_dim_set))
1316 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1317 "spaces don't match", goto error);
1319 multi = FN(MULTI(BASE),cow)(multi);
1320 if (!multi)
1321 goto error;
1323 for (i = 0; i < multi->n; ++i) {
1324 isl_val *v;
1326 v = isl_multi_val_get_val(mv, i);
1327 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i], v);
1328 if (!multi->u.p[i])
1329 goto error;
1332 isl_multi_val_free(mv);
1333 return multi;
1334 error:
1335 isl_multi_val_free(mv);
1336 return FN(MULTI(BASE),free)(multi);
1339 /* Divide the elements of "multi" by the corresponding element of "mv"
1340 * and return the result.
1342 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
1343 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1345 int i;
1347 if (!multi || !mv)
1348 goto error;
1350 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1351 mv->space, isl_dim_set))
1352 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1353 "spaces don't match", goto error);
1355 multi = FN(MULTI(BASE),cow)(multi);
1356 if (!multi)
1357 return NULL;
1359 for (i = 0; i < multi->n; ++i) {
1360 isl_val *v;
1362 v = isl_multi_val_get_val(mv, i);
1363 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i], v);
1364 if (!multi->u.p[i])
1365 goto error;
1368 isl_multi_val_free(mv);
1369 return multi;
1370 error:
1371 isl_multi_val_free(mv);
1372 return FN(MULTI(BASE),free)(multi);
1375 /* Compute the residues of the elements of "multi" modulo
1376 * the corresponding element of "mv" and return the result.
1378 __isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
1379 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1381 int i;
1383 if (!multi || !mv)
1384 goto error;
1386 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1387 mv->space, isl_dim_set))
1388 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1389 "spaces don't match", goto error);
1391 multi = FN(MULTI(BASE),cow)(multi);
1392 if (!multi)
1393 goto error;
1395 for (i = 0; i < multi->n; ++i) {
1396 isl_val *v;
1398 v = isl_multi_val_get_val(mv, i);
1399 multi->u.p[i] = FN(EL,mod_val)(multi->u.p[i], v);
1400 if (!multi->u.p[i])
1401 goto error;
1404 isl_multi_val_free(mv);
1405 return multi;
1406 error:
1407 isl_multi_val_free(mv);
1408 return FN(MULTI(BASE),free)(multi);
1411 #ifndef NO_MOVE_DIMS
1412 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
1413 * to dimensions of "dst_type" at "dst_pos".
1415 * We only support moving input dimensions to parameters and vice versa.
1417 __isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
1418 enum isl_dim_type dst_type, unsigned dst_pos,
1419 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1421 int i;
1423 if (!multi)
1424 return NULL;
1426 if (n == 0 &&
1427 !isl_space_is_named_or_nested(multi->space, src_type) &&
1428 !isl_space_is_named_or_nested(multi->space, dst_type))
1429 return multi;
1431 if (dst_type == isl_dim_out || src_type == isl_dim_out)
1432 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1433 "cannot move output/set dimension",
1434 return FN(MULTI(BASE),free)(multi));
1435 if (dst_type == isl_dim_div || src_type == isl_dim_div)
1436 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1437 "cannot move divs",
1438 return FN(MULTI(BASE),free)(multi));
1439 if (src_pos + n > isl_space_dim(multi->space, src_type))
1440 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1441 "range out of bounds",
1442 return FN(MULTI(BASE),free)(multi));
1443 if (dst_type == src_type)
1444 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_unsupported,
1445 "moving dims within the same type not supported",
1446 return FN(MULTI(BASE),free)(multi));
1448 multi = FN(MULTI(BASE),cow)(multi);
1449 if (!multi)
1450 return NULL;
1452 multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
1453 src_type, src_pos, n);
1454 if (!multi->space)
1455 return FN(MULTI(BASE),free)(multi);
1456 if (FN(MULTI(BASE),has_explicit_domain)(multi))
1457 multi = FN(MULTI(BASE),move_explicit_domain_dims)(multi,
1458 dst_type, dst_pos, src_type, src_pos, n);
1459 if (!multi)
1460 return NULL;
1462 for (i = 0; i < multi->n; ++i) {
1463 multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
1464 dst_type, dst_pos,
1465 src_type, src_pos, n);
1466 if (!multi->u.p[i])
1467 return FN(MULTI(BASE),free)(multi);
1470 return multi;
1472 #endif
1474 /* Convert a multiple expression defined over a parameter domain
1475 * into one that is defined over a zero-dimensional set.
1477 __isl_give MULTI(BASE) *FN(MULTI(BASE),from_range)(
1478 __isl_take MULTI(BASE) *multi)
1480 isl_space *space;
1482 if (!multi)
1483 return NULL;
1484 if (!isl_space_is_set(multi->space))
1485 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1486 "not living in a set space",
1487 return FN(MULTI(BASE),free)(multi));
1489 space = FN(MULTI(BASE),get_space)(multi);
1490 space = isl_space_from_range(space);
1491 multi = FN(MULTI(BASE),reset_space)(multi, space);
1493 return multi;
1496 /* Are "multi1" and "multi2" obviously equal?
1498 isl_bool FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1,
1499 __isl_keep MULTI(BASE) *multi2)
1501 int i;
1502 isl_bool equal;
1504 if (!multi1 || !multi2)
1505 return isl_bool_error;
1506 if (multi1->n != multi2->n)
1507 return isl_bool_false;
1508 equal = isl_space_is_equal(multi1->space, multi2->space);
1509 if (equal < 0 || !equal)
1510 return equal;
1512 for (i = 0; i < multi1->n; ++i) {
1513 equal = FN(EL,plain_is_equal)(multi1->u.p[i], multi2->u.p[i]);
1514 if (equal < 0 || !equal)
1515 return equal;
1518 if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
1519 FN(MULTI(BASE),has_explicit_domain)(multi2)) {
1520 equal = FN(MULTI(BASE),equal_explicit_domain)(multi1, multi2);
1521 if (equal < 0 || !equal)
1522 return equal;
1525 return isl_bool_true;
1528 /* Does "multi" involve any NaNs?
1530 isl_bool FN(MULTI(BASE),involves_nan)(__isl_keep MULTI(BASE) *multi)
1532 int i;
1534 if (!multi)
1535 return isl_bool_error;
1536 if (multi->n == 0)
1537 return isl_bool_false;
1539 for (i = 0; i < multi->n; ++i) {
1540 isl_bool has_nan = FN(EL,involves_nan)(multi->u.p[i]);
1541 if (has_nan < 0 || has_nan)
1542 return has_nan;
1545 return isl_bool_false;
1548 #ifndef NO_DOMAIN
1549 /* Return the shared domain of the elements of "multi".
1551 * If "multi" has an explicit domain, then return this domain.
1553 __isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
1555 int i;
1556 isl_set *dom;
1558 if (!multi)
1559 return NULL;
1561 if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
1562 dom = FN(MULTI(BASE),get_explicit_domain)(multi);
1563 FN(MULTI(BASE),free)(multi);
1564 return dom;
1567 dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
1568 for (i = 0; i < multi->n; ++i) {
1569 isl_set *dom_i;
1571 dom_i = FN(EL,domain)(FN(FN(MULTI(BASE),get),BASE)(multi, i));
1572 dom = isl_set_intersect(dom, dom_i);
1575 FN(MULTI(BASE),free)(multi);
1576 return dom;
1578 #endif
1580 #ifndef NO_NEG
1581 /* Return the opposite of "multi".
1583 __isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
1585 int i;
1587 multi = FN(MULTI(BASE),cow)(multi);
1588 if (!multi)
1589 return NULL;
1591 for (i = 0; i < multi->n; ++i) {
1592 multi->u.p[i] = FN(EL,neg)(multi->u.p[i]);
1593 if (!multi->u.p[i])
1594 return FN(MULTI(BASE),free)(multi);
1597 return multi;
1599 #endif