Update isl to isl-0.19-185-g8e9f55ce
[polly-mirror.git] / lib / External / isl / isl_multi_templ.c
blob076936008ce62070669ad19bab020b3104b518b5
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 static __isl_keep isl_space *FN(MULTI(BASE),peek_space)(
31 __isl_keep MULTI(BASE) *multi)
33 return multi ? multi->space : NULL;
36 __isl_give isl_space *FN(MULTI(BASE),get_space)(__isl_keep MULTI(BASE) *multi)
38 return isl_space_copy(FN(MULTI(BASE),peek_space)(multi));
41 /* Return the position of the dimension of the given type and name
42 * in "multi".
43 * Return -1 if no such dimension can be found.
45 int FN(MULTI(BASE),find_dim_by_name)(__isl_keep MULTI(BASE) *multi,
46 enum isl_dim_type type, const char *name)
48 if (!multi)
49 return -1;
50 return isl_space_find_dim_by_name(multi->space, type, name);
53 __isl_give isl_space *FN(MULTI(BASE),get_domain_space)(
54 __isl_keep MULTI(BASE) *multi)
56 return multi ? isl_space_domain(isl_space_copy(multi->space)) : NULL;
59 /* Allocate a multi expression living in "space".
61 * If the number of base expressions is zero, then make sure
62 * there is enough room in the structure for the explicit domain,
63 * in case the type supports such an explicit domain.
65 __isl_give MULTI(BASE) *FN(MULTI(BASE),alloc)(__isl_take isl_space *space)
67 isl_ctx *ctx;
68 int n;
69 MULTI(BASE) *multi;
71 if (!space)
72 return NULL;
74 ctx = isl_space_get_ctx(space);
75 n = isl_space_dim(space, isl_dim_out);
76 if (n > 0)
77 multi = isl_calloc(ctx, MULTI(BASE),
78 sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *));
79 else
80 multi = isl_calloc(ctx, MULTI(BASE), sizeof(MULTI(BASE)));
81 if (!multi)
82 goto error;
84 multi->space = space;
85 multi->n = n;
86 multi->ref = 1;
87 if (FN(MULTI(BASE),has_explicit_domain)(multi))
88 multi = FN(MULTI(BASE),init_explicit_domain)(multi);
89 return multi;
90 error:
91 isl_space_free(space);
92 return NULL;
95 __isl_give MULTI(BASE) *FN(MULTI(BASE),dup)(__isl_keep MULTI(BASE) *multi)
97 int i;
98 MULTI(BASE) *dup;
100 if (!multi)
101 return NULL;
103 dup = FN(MULTI(BASE),alloc)(isl_space_copy(multi->space));
104 if (!dup)
105 return NULL;
107 for (i = 0; i < multi->n; ++i)
108 dup = FN(FN(MULTI(BASE),set),BASE)(dup, i,
109 FN(EL,copy)(multi->u.p[i]));
110 if (FN(MULTI(BASE),has_explicit_domain)(multi))
111 dup = FN(MULTI(BASE),copy_explicit_domain)(dup, multi);
113 return dup;
116 __isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi)
118 if (!multi)
119 return NULL;
121 if (multi->ref == 1)
122 return multi;
124 multi->ref--;
125 return FN(MULTI(BASE),dup)(multi);
128 __isl_give MULTI(BASE) *FN(MULTI(BASE),copy)(__isl_keep MULTI(BASE) *multi)
130 if (!multi)
131 return NULL;
133 multi->ref++;
134 return multi;
137 __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
139 int i;
141 if (!multi)
142 return NULL;
144 if (--multi->ref > 0)
145 return NULL;
147 isl_space_free(multi->space);
148 for (i = 0; i < multi->n; ++i)
149 FN(EL,free)(multi->u.p[i]);
150 if (FN(MULTI(BASE),has_explicit_domain)(multi))
151 FN(MULTI(BASE),free_explicit_domain)(multi);
152 free(multi);
154 return NULL;
157 unsigned FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi,
158 enum isl_dim_type type)
160 return multi ? isl_space_dim(multi->space, type) : 0;
163 /* Return the position of the first dimension of "type" with id "id".
164 * Return -1 if there is no such dimension.
166 int FN(MULTI(BASE),find_dim_by_id)(__isl_keep MULTI(BASE) *multi,
167 enum isl_dim_type type, __isl_keep isl_id *id)
169 if (!multi)
170 return -1;
171 return isl_space_find_dim_by_id(multi->space, type, id);
174 /* Return the id of the given dimension.
176 __isl_give isl_id *FN(MULTI(BASE),get_dim_id)(__isl_keep MULTI(BASE) *multi,
177 enum isl_dim_type type, unsigned pos)
179 return multi ? isl_space_get_dim_id(multi->space, type, pos) : NULL;
182 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_name)(
183 __isl_take MULTI(BASE) *multi,
184 enum isl_dim_type type, unsigned pos, const char *s)
186 int i;
188 multi = FN(MULTI(BASE),cow)(multi);
189 if (!multi)
190 return NULL;
192 multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
193 if (!multi->space)
194 return FN(MULTI(BASE),free)(multi);
196 if (type == isl_dim_out)
197 return multi;
198 for (i = 0; i < multi->n; ++i) {
199 multi->u.p[i] = FN(EL,set_dim_name)(multi->u.p[i],
200 type, pos, s);
201 if (!multi->u.p[i])
202 return FN(MULTI(BASE),free)(multi);
205 return multi;
208 const char *FN(MULTI(BASE),get_tuple_name)(__isl_keep MULTI(BASE) *multi,
209 enum isl_dim_type type)
211 return multi ? isl_space_get_tuple_name(multi->space, type) : NULL;
214 /* Does the specified tuple have an id?
216 isl_bool FN(MULTI(BASE),has_tuple_id)(__isl_keep MULTI(BASE) *multi,
217 enum isl_dim_type type)
219 if (!multi)
220 return isl_bool_error;
221 return isl_space_has_tuple_id(multi->space, type);
224 /* Return the id of the specified tuple.
226 __isl_give isl_id *FN(MULTI(BASE),get_tuple_id)(__isl_keep MULTI(BASE) *multi,
227 enum isl_dim_type type)
229 return multi ? isl_space_get_tuple_id(multi->space, type) : NULL;
232 __isl_give EL *FN(FN(MULTI(BASE),get),BASE)(__isl_keep MULTI(BASE) *multi,
233 int pos)
235 isl_ctx *ctx;
237 if (!multi)
238 return NULL;
239 ctx = FN(MULTI(BASE),get_ctx)(multi);
240 if (pos < 0 || pos >= multi->n)
241 isl_die(ctx, isl_error_invalid,
242 "index out of bounds", return NULL);
243 return FN(EL,copy)(multi->u.p[pos]);
246 /* Set the element at position "pos" of "multi" to "el",
247 * where the position may be empty if "multi" has only a single reference.
249 static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore)(
250 __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
252 multi = FN(MULTI(BASE),cow)(multi);
253 if (!multi || !el)
254 goto error;
256 if (pos < 0 || pos >= multi->n)
257 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
258 "index out of bounds", goto error);
260 FN(EL,free)(multi->u.p[pos]);
261 multi->u.p[pos] = el;
263 return multi;
264 error:
265 FN(MULTI(BASE),free)(multi);
266 FN(EL,free)(el);
267 return NULL;
270 /* Set the element at position "pos" of "multi" to "el",
271 * where the position may be empty if "multi" has only a single reference.
272 * However, the space of "multi" is available and is checked
273 * for compatibility with "el".
275 static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_check_space)(
276 __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
278 isl_space *space;
280 space = FN(MULTI(BASE),peek_space)(multi);
281 if (FN(EL,check_match_domain_space)(el, space) < 0)
282 multi = FN(MULTI(BASE),free)(multi);
283 return FN(MULTI(BASE),restore)(multi, pos, el);
286 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),set),BASE)(
287 __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
289 isl_space *multi_space = NULL;
290 isl_space *el_space = NULL;
291 isl_bool match;
293 multi_space = FN(MULTI(BASE),get_space)(multi);
294 match = FN(EL,matching_params)(el, multi_space);
295 if (match < 0)
296 goto error;
297 if (!match) {
298 multi = FN(MULTI(BASE),align_params)(multi,
299 FN(EL,get_space)(el));
300 isl_space_free(multi_space);
301 multi_space = FN(MULTI(BASE),get_space)(multi);
302 el = FN(EL,align_params)(el, isl_space_copy(multi_space));
305 multi = FN(MULTI(BASE),restore_check_space)(multi, pos, el);
307 isl_space_free(multi_space);
308 isl_space_free(el_space);
310 return multi;
311 error:
312 FN(MULTI(BASE),free)(multi);
313 FN(EL,free)(el);
314 isl_space_free(multi_space);
315 isl_space_free(el_space);
316 return NULL;
319 /* Reset the space of "multi". This function is called from isl_pw_templ.c
320 * and doesn't know if the space of an element object is represented
321 * directly or through its domain. It therefore passes along both,
322 * which we pass along to the element function since we don't know how
323 * that is represented either.
325 * If "multi" has an explicit domain, then the caller is expected
326 * to make sure that any modification that would change the dimensions
327 * of the explicit domain has bee applied before this function is called.
329 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space_and_domain)(
330 __isl_take MULTI(BASE) *multi, __isl_take isl_space *space,
331 __isl_take isl_space *domain)
333 int i;
335 multi = FN(MULTI(BASE),cow)(multi);
336 if (!multi || !space || !domain)
337 goto error;
339 for (i = 0; i < multi->n; ++i) {
340 multi->u.p[i] = FN(EL,reset_domain_space)(multi->u.p[i],
341 isl_space_copy(domain));
342 if (!multi->u.p[i])
343 goto error;
345 if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
346 multi = FN(MULTI(BASE),reset_explicit_domain_space)(multi,
347 isl_space_copy(domain));
348 if (!multi)
349 goto error;
351 isl_space_free(domain);
352 isl_space_free(multi->space);
353 multi->space = space;
355 return multi;
356 error:
357 isl_space_free(domain);
358 isl_space_free(space);
359 FN(MULTI(BASE),free)(multi);
360 return NULL;
363 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_domain_space)(
364 __isl_take MULTI(BASE) *multi, __isl_take isl_space *domain)
366 isl_space *space;
368 space = isl_space_extend_domain_with_range(isl_space_copy(domain),
369 isl_space_copy(multi->space));
370 return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
373 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space)(
374 __isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
376 isl_space *domain;
378 domain = isl_space_domain(isl_space_copy(space));
379 return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
382 /* Set the id of the given dimension of "multi" to "id".
384 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_id)(
385 __isl_take MULTI(BASE) *multi,
386 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
388 isl_space *space;
390 multi = FN(MULTI(BASE),cow)(multi);
391 if (!multi || !id)
392 goto error;
394 space = FN(MULTI(BASE),get_space)(multi);
395 space = isl_space_set_dim_id(space, type, pos, id);
397 return FN(MULTI(BASE),reset_space)(multi, space);
398 error:
399 isl_id_free(id);
400 FN(MULTI(BASE),free)(multi);
401 return NULL;
404 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_name)(
405 __isl_keep MULTI(BASE) *multi, enum isl_dim_type type,
406 const char *s)
408 isl_space *space;
410 multi = FN(MULTI(BASE),cow)(multi);
411 if (!multi)
412 return NULL;
414 space = FN(MULTI(BASE),get_space)(multi);
415 space = isl_space_set_tuple_name(space, type, s);
417 return FN(MULTI(BASE),reset_space)(multi, space);
420 __isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_id)(
421 __isl_take MULTI(BASE) *multi, enum isl_dim_type type,
422 __isl_take isl_id *id)
424 isl_space *space;
426 multi = FN(MULTI(BASE),cow)(multi);
427 if (!multi)
428 goto error;
430 space = FN(MULTI(BASE),get_space)(multi);
431 space = isl_space_set_tuple_id(space, type, id);
433 return FN(MULTI(BASE),reset_space)(multi, space);
434 error:
435 isl_id_free(id);
436 return NULL;
439 /* Drop the id on the specified tuple.
441 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_tuple_id)(
442 __isl_take MULTI(BASE) *multi, enum isl_dim_type type)
444 isl_space *space;
446 if (!multi)
447 return NULL;
448 if (!FN(MULTI(BASE),has_tuple_id)(multi, type))
449 return multi;
451 multi = FN(MULTI(BASE),cow)(multi);
452 if (!multi)
453 return NULL;
455 space = FN(MULTI(BASE),get_space)(multi);
456 space = isl_space_reset_tuple_id(space, type);
458 return FN(MULTI(BASE),reset_space)(multi, space);
461 /* Reset the user pointer on all identifiers of parameters and tuples
462 * of the space of "multi".
464 __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_user)(
465 __isl_take MULTI(BASE) *multi)
467 isl_space *space;
469 space = FN(MULTI(BASE),get_space)(multi);
470 space = isl_space_reset_user(space);
472 return FN(MULTI(BASE),reset_space)(multi, space);
475 __isl_give MULTI(BASE) *FN(MULTI(BASE),realign_domain)(
476 __isl_take MULTI(BASE) *multi, __isl_take isl_reordering *exp)
478 int i;
479 isl_space *space;
481 multi = FN(MULTI(BASE),cow)(multi);
482 if (!multi || !exp)
483 goto error;
485 for (i = 0; i < multi->n; ++i) {
486 multi->u.p[i] = FN(EL,realign_domain)(multi->u.p[i],
487 isl_reordering_copy(exp));
488 if (!multi->u.p[i])
489 goto error;
492 space = isl_reordering_get_space(exp);
493 multi = FN(MULTI(BASE),reset_domain_space)(multi, space);
495 isl_reordering_free(exp);
496 return multi;
497 error:
498 isl_reordering_free(exp);
499 FN(MULTI(BASE),free)(multi);
500 return NULL;
503 /* Align the parameters of "multi" to those of "model".
505 * If "multi" has an explicit domain, then align the parameters
506 * of the domain first.
508 __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)(
509 __isl_take MULTI(BASE) *multi, __isl_take isl_space *model)
511 isl_ctx *ctx;
512 isl_bool equal_params;
513 isl_reordering *exp;
515 if (!multi || !model)
516 goto error;
518 equal_params = isl_space_has_equal_params(multi->space, model);
519 if (equal_params < 0)
520 goto error;
521 if (equal_params) {
522 isl_space_free(model);
523 return multi;
526 ctx = isl_space_get_ctx(model);
527 if (!isl_space_has_named_params(model))
528 isl_die(ctx, isl_error_invalid,
529 "model has unnamed parameters", goto error);
530 if (!isl_space_has_named_params(multi->space))
531 isl_die(ctx, isl_error_invalid,
532 "input has unnamed parameters", goto error);
534 if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
535 multi = FN(MULTI(BASE),align_explicit_domain_params)(multi,
536 isl_space_copy(model));
537 if (!multi)
538 goto error;
540 exp = isl_parameter_alignment_reordering(multi->space, model);
541 exp = isl_reordering_extend_space(exp,
542 FN(MULTI(BASE),get_domain_space)(multi));
543 multi = FN(MULTI(BASE),realign_domain)(multi, exp);
545 isl_space_free(model);
546 return multi;
547 error:
548 isl_space_free(model);
549 FN(MULTI(BASE),free)(multi);
550 return NULL;
553 /* Create a multi expression in the given space with the elements of "list"
554 * as base expressions.
556 * Since isl_multi_*_restore_* assumes that the element and
557 * the multi expression have matching spaces, the alignment
558 * (if any) needs to be performed beforehand.
560 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))(
561 __isl_take isl_space *space, __isl_take LIST(EL) *list)
563 int i;
564 int n;
565 isl_ctx *ctx;
566 MULTI(BASE) *multi;
568 if (!space || !list)
569 goto error;
571 ctx = isl_space_get_ctx(space);
572 n = FN(FN(LIST(EL),n),BASE)(list);
573 if (n != isl_space_dim(space, isl_dim_out))
574 isl_die(ctx, isl_error_invalid,
575 "invalid number of elements in list", goto error);
577 for (i = 0; i < n; ++i) {
578 EL *el = FN(LIST(EL),peek)(list, i);
579 space = isl_space_align_params(space, FN(EL,get_space)(el));
581 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
582 for (i = 0; i < n; ++i) {
583 EL *el = FN(FN(LIST(EL),get),BASE)(list, i);
584 el = FN(EL,align_params)(el, isl_space_copy(space));
585 multi = FN(MULTI(BASE),restore_check_space)(multi, i, el);
588 isl_space_free(space);
589 FN(LIST(EL),free)(list);
590 return multi;
591 error:
592 isl_space_free(space);
593 FN(LIST(EL),free)(list);
594 return NULL;
597 #ifndef NO_IDENTITY
598 /* Create a multi expression in the given space that maps each
599 * input dimension to the corresponding output dimension.
601 __isl_give MULTI(BASE) *FN(MULTI(BASE),identity)(__isl_take isl_space *space)
603 int i, n;
604 isl_local_space *ls;
605 MULTI(BASE) *multi;
607 if (!space)
608 return NULL;
610 if (isl_space_is_set(space))
611 isl_die(isl_space_get_ctx(space), isl_error_invalid,
612 "expecting map space", goto error);
614 n = isl_space_dim(space, isl_dim_out);
615 if (n != isl_space_dim(space, isl_dim_in))
616 isl_die(isl_space_get_ctx(space), isl_error_invalid,
617 "number of input and output dimensions needs to be "
618 "the same", goto error);
620 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
622 if (!n) {
623 isl_space_free(space);
624 return multi;
627 space = isl_space_domain(space);
628 ls = isl_local_space_from_space(space);
630 for (i = 0; i < n; ++i) {
631 EL *el;
632 el = FN(EL,var_on_domain)(isl_local_space_copy(ls),
633 isl_dim_set, i);
634 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i, el);
637 isl_local_space_free(ls);
639 return multi;
640 error:
641 isl_space_free(space);
642 return NULL;
644 #endif
646 #ifndef NO_ZERO
647 /* Construct a multi expression in the given space with value zero in
648 * each of the output dimensions.
650 __isl_give MULTI(BASE) *FN(MULTI(BASE),zero)(__isl_take isl_space *space)
652 int n;
653 MULTI(BASE) *multi;
655 if (!space)
656 return NULL;
658 n = isl_space_dim(space , isl_dim_out);
659 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
661 if (!n)
662 isl_space_free(space);
663 else {
664 int i;
665 isl_local_space *ls;
666 EL *el;
668 space = isl_space_domain(space);
669 ls = isl_local_space_from_space(space);
670 el = FN(EL,zero_on_domain)(ls);
672 for (i = 0; i < n; ++i)
673 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
674 FN(EL,copy)(el));
676 FN(EL,free)(el);
679 return multi;
681 #endif
683 #ifndef NO_FROM_BASE
684 /* Create a multiple expression with a single output/set dimension
685 * equal to "el".
686 * For most multiple expression types, the base type has a single
687 * output/set dimension and the space of the result is therefore
688 * the same as the space of the input.
689 * In the case of isl_multi_union_pw_aff, however, the base type
690 * lives in a parameter space and we therefore need to add
691 * a single set dimension.
693 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
695 isl_space *space;
696 MULTI(BASE) *multi;
698 space = FN(EL,get_space(el));
699 if (isl_space_is_params(space)) {
700 space = isl_space_set_from_params(space);
701 space = isl_space_add_dims(space, isl_dim_set, 1);
703 multi = FN(MULTI(BASE),alloc)(space);
704 multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
706 return multi;
708 #endif
710 __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
711 __isl_take MULTI(BASE) *multi,
712 enum isl_dim_type type, unsigned first, unsigned n)
714 int i;
715 unsigned dim;
717 multi = FN(MULTI(BASE),cow)(multi);
718 if (!multi)
719 return NULL;
721 dim = FN(MULTI(BASE),dim)(multi, type);
722 if (first + n > dim || first + n < first)
723 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
724 "index out of bounds",
725 return FN(MULTI(BASE),free)(multi));
727 multi->space = isl_space_drop_dims(multi->space, type, first, n);
728 if (!multi->space)
729 return FN(MULTI(BASE),free)(multi);
731 if (type == isl_dim_out) {
732 for (i = 0; i < n; ++i)
733 FN(EL,free)(multi->u.p[first + i]);
734 for (i = first; i + n < multi->n; ++i)
735 multi->u.p[i] = multi->u.p[i + n];
736 multi->n -= n;
737 if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi))
738 multi = FN(MULTI(BASE),init_explicit_domain)(multi);
740 return multi;
743 if (FN(MULTI(BASE),has_explicit_domain)(multi))
744 multi = FN(MULTI(BASE),drop_explicit_domain_dims)(multi,
745 type, first, n);
746 if (!multi)
747 return NULL;
749 for (i = 0; i < multi->n; ++i) {
750 multi->u.p[i] = FN(EL,drop_dims)(multi->u.p[i], type, first, n);
751 if (!multi->u.p[i])
752 return FN(MULTI(BASE),free)(multi);
755 return multi;
758 /* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
760 static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_multi_and)(
761 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
762 __isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi1,
763 __isl_take MULTI(BASE) *multi2))
765 isl_ctx *ctx;
766 isl_bool equal_params;
768 if (!multi1 || !multi2)
769 goto error;
770 equal_params = isl_space_has_equal_params(multi1->space, multi2->space);
771 if (equal_params < 0)
772 goto error;
773 if (equal_params)
774 return fn(multi1, multi2);
775 ctx = FN(MULTI(BASE),get_ctx)(multi1);
776 if (!isl_space_has_named_params(multi1->space) ||
777 !isl_space_has_named_params(multi2->space))
778 isl_die(ctx, isl_error_invalid,
779 "unaligned unnamed parameters", goto error);
780 multi1 = FN(MULTI(BASE),align_params)(multi1,
781 FN(MULTI(BASE),get_space)(multi2));
782 multi2 = FN(MULTI(BASE),align_params)(multi2,
783 FN(MULTI(BASE),get_space)(multi1));
784 return fn(multi1, multi2);
785 error:
786 FN(MULTI(BASE),free)(multi1);
787 FN(MULTI(BASE),free)(multi2);
788 return NULL;
791 /* Given two MULTI(BASE)s A -> B and C -> D,
792 * construct a MULTI(BASE) (A * C) -> [B -> D].
794 * The parameters are assumed to have been aligned.
796 * If "multi1" and/or "multi2" has an explicit domain, then
797 * intersect the domain of the result with these explicit domains.
799 static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
800 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
802 int i, n1, n2;
803 EL *el;
804 isl_space *space;
805 MULTI(BASE) *res;
807 if (!multi1 || !multi2)
808 goto error;
810 space = isl_space_range_product(FN(MULTI(BASE),get_space)(multi1),
811 FN(MULTI(BASE),get_space)(multi2));
812 res = FN(MULTI(BASE),alloc)(space);
814 n1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
815 n2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
817 for (i = 0; i < n1; ++i) {
818 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
819 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
822 for (i = 0; i < n2; ++i) {
823 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
824 res = FN(FN(MULTI(BASE),set),BASE)(res, n1 + i, el);
827 if (FN(MULTI(BASE),has_explicit_domain)(multi1))
828 res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi1);
829 if (FN(MULTI(BASE),has_explicit_domain)(multi2))
830 res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi2);
832 FN(MULTI(BASE),free)(multi1);
833 FN(MULTI(BASE),free)(multi2);
834 return res;
835 error:
836 FN(MULTI(BASE),free)(multi1);
837 FN(MULTI(BASE),free)(multi2);
838 return NULL;
841 /* Given two MULTI(BASE)s A -> B and C -> D,
842 * construct a MULTI(BASE) (A * C) -> [B -> D].
844 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)(
845 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
847 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
848 &FN(MULTI(BASE),range_product_aligned));
851 /* Is the range of "multi" a wrapped relation?
853 isl_bool FN(MULTI(BASE),range_is_wrapping)(__isl_keep MULTI(BASE) *multi)
855 if (!multi)
856 return isl_bool_error;
857 return isl_space_range_is_wrapping(multi->space);
860 /* Given a function A -> [B -> C], extract the function A -> B.
862 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_domain)(
863 __isl_take MULTI(BASE) *multi)
865 isl_space *space;
866 int total, keep;
868 if (!multi)
869 return NULL;
870 if (!isl_space_range_is_wrapping(multi->space))
871 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
872 "range is not a product",
873 return FN(MULTI(BASE),free)(multi));
875 space = FN(MULTI(BASE),get_space)(multi);
876 total = isl_space_dim(space, isl_dim_out);
877 space = isl_space_range_factor_domain(space);
878 keep = isl_space_dim(space, isl_dim_out);
879 multi = FN(MULTI(BASE),drop_dims)(multi,
880 isl_dim_out, keep, total - keep);
881 multi = FN(MULTI(BASE),reset_space)(multi, space);
883 return multi;
886 /* Given a function A -> [B -> C], extract the function A -> C.
888 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)(
889 __isl_take MULTI(BASE) *multi)
891 isl_space *space;
892 int total, keep;
894 if (!multi)
895 return NULL;
896 if (!isl_space_range_is_wrapping(multi->space))
897 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
898 "range is not a product",
899 return FN(MULTI(BASE),free)(multi));
901 space = FN(MULTI(BASE),get_space)(multi);
902 total = isl_space_dim(space, isl_dim_out);
903 space = isl_space_range_factor_range(space);
904 keep = isl_space_dim(space, isl_dim_out);
905 multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
906 multi = FN(MULTI(BASE),reset_space)(multi, space);
908 return multi;
911 /* Given a function [B -> C], extract the function C.
913 __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
914 __isl_take MULTI(BASE) *multi)
916 isl_space *space;
917 int total, keep;
919 if (!multi)
920 return NULL;
921 if (!isl_space_is_wrapping(multi->space))
922 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
923 "not a product", return FN(MULTI(BASE),free)(multi));
925 space = FN(MULTI(BASE),get_space)(multi);
926 total = isl_space_dim(space, isl_dim_out);
927 space = isl_space_factor_range(space);
928 keep = isl_space_dim(space, isl_dim_out);
929 multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
930 multi = FN(MULTI(BASE),reset_space)(multi, space);
932 return multi;
935 #ifndef NO_PRODUCT
936 /* Given two MULTI(BASE)s A -> B and C -> D,
937 * construct a MULTI(BASE) [A -> C] -> [B -> D].
939 * The parameters are assumed to have been aligned.
941 * If "multi1" and/or "multi2" has an explicit domain, then
942 * intersect the domain of the result with these explicit domains.
944 __isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
945 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
947 int i;
948 EL *el;
949 isl_space *space;
950 MULTI(BASE) *res;
951 int in1, in2, out1, out2;
953 in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
954 in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
955 out1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
956 out2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
957 space = isl_space_product(FN(MULTI(BASE),get_space)(multi1),
958 FN(MULTI(BASE),get_space)(multi2));
959 res = FN(MULTI(BASE),alloc)(isl_space_copy(space));
960 space = isl_space_domain(space);
962 for (i = 0; i < out1; ++i) {
963 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
964 el = FN(EL,insert_dims)(el, isl_dim_in, in1, in2);
965 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
966 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
969 for (i = 0; i < out2; ++i) {
970 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
971 el = FN(EL,insert_dims)(el, isl_dim_in, 0, in1);
972 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
973 res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
976 if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
977 FN(MULTI(BASE),has_explicit_domain)(multi2))
978 res = FN(MULTI(BASE),intersect_explicit_domain_product)(res,
979 multi1, multi2);
981 isl_space_free(space);
982 FN(MULTI(BASE),free)(multi1);
983 FN(MULTI(BASE),free)(multi2);
984 return res;
987 /* Given two MULTI(BASE)s A -> B and C -> D,
988 * construct a MULTI(BASE) [A -> C] -> [B -> D].
990 __isl_give MULTI(BASE) *FN(MULTI(BASE),product)(
991 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
993 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
994 &FN(MULTI(BASE),product_aligned));
996 #endif
998 __isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
999 __isl_take MULTI(BASE) *multi)
1001 if (!multi)
1002 return NULL;
1004 if (!multi->space->nested[1])
1005 return multi;
1007 multi = FN(MULTI(BASE),cow)(multi);
1008 if (!multi)
1009 return NULL;
1011 multi->space = isl_space_flatten_range(multi->space);
1012 if (!multi->space)
1013 return FN(MULTI(BASE),free)(multi);
1015 return multi;
1018 /* Given two MULTI(BASE)s A -> B and C -> D,
1019 * construct a MULTI(BASE) (A * C) -> (B, D).
1021 __isl_give MULTI(BASE) *FN(MULTI(BASE),flat_range_product)(
1022 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1024 MULTI(BASE) *multi;
1026 multi = FN(MULTI(BASE),range_product)(multi1, multi2);
1027 multi = FN(MULTI(BASE),flatten_range)(multi);
1028 return multi;
1031 /* Given two multi expressions, "multi1"
1033 * [A] -> [B1 B2]
1035 * where B2 starts at position "pos", and "multi2"
1037 * [A] -> [D]
1039 * return the multi expression
1041 * [A] -> [B1 D B2]
1043 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
1044 __isl_take MULTI(BASE) *multi1, unsigned pos,
1045 __isl_take MULTI(BASE) *multi2)
1047 MULTI(BASE) *res;
1048 unsigned dim;
1050 if (!multi1 || !multi2)
1051 goto error;
1053 dim = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
1054 if (pos > dim)
1055 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1056 "index out of bounds", goto error);
1058 res = FN(MULTI(BASE),copy)(multi1);
1059 res = FN(MULTI(BASE),drop_dims)(res, isl_dim_out, pos, dim - pos);
1060 multi1 = FN(MULTI(BASE),drop_dims)(multi1, isl_dim_out, 0, pos);
1062 res = FN(MULTI(BASE),flat_range_product)(res, multi2);
1063 res = FN(MULTI(BASE),flat_range_product)(res, multi1);
1065 return res;
1066 error:
1067 FN(MULTI(BASE),free)(multi1);
1068 FN(MULTI(BASE),free)(multi2);
1069 return NULL;
1072 #ifndef NO_SPLICE
1073 /* Given two multi expressions, "multi1"
1075 * [A1 A2] -> [B1 B2]
1077 * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
1078 * and "multi2"
1080 * [C] -> [D]
1082 * return the multi expression
1084 * [A1 C A2] -> [B1 D B2]
1086 * We first insert input dimensions to obtain
1088 * [A1 C A2] -> [B1 B2]
1090 * and
1092 * [A1 C A2] -> [D]
1094 * and then apply range_splice.
1096 __isl_give MULTI(BASE) *FN(MULTI(BASE),splice)(
1097 __isl_take MULTI(BASE) *multi1, unsigned in_pos, unsigned out_pos,
1098 __isl_take MULTI(BASE) *multi2)
1100 unsigned n_in1;
1101 unsigned n_in2;
1103 if (!multi1 || !multi2)
1104 goto error;
1106 n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
1107 if (in_pos > n_in1)
1108 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1109 "index out of bounds", goto error);
1111 n_in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
1113 multi1 = FN(MULTI(BASE),insert_dims)(multi1, isl_dim_in, in_pos, n_in2);
1114 multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, n_in2,
1115 n_in1 - in_pos);
1116 multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, 0, in_pos);
1118 return FN(MULTI(BASE),range_splice)(multi1, out_pos, multi2);
1119 error:
1120 FN(MULTI(BASE),free)(multi1);
1121 FN(MULTI(BASE),free)(multi2);
1122 return NULL;
1124 #endif
1126 /* Check that "multi1" and "multi2" live in the same space,
1127 * reporting an error if they do not.
1129 static isl_stat FN(MULTI(BASE),check_equal_space)(
1130 __isl_keep MULTI(BASE) *multi1, __isl_keep MULTI(BASE) *multi2)
1132 isl_bool equal;
1134 if (!multi1 || !multi2)
1135 return isl_stat_error;
1137 equal = isl_space_is_equal(multi1->space, multi2->space);
1138 if (equal < 0)
1139 return isl_stat_error;
1140 if (!equal)
1141 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1142 "spaces don't match", return isl_stat_error);
1144 return isl_stat_ok;
1147 /* This function is currently only used from isl_aff.c
1149 static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
1150 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
1151 __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
1152 __attribute__ ((unused));
1154 /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
1155 * return the result.
1157 * If "multi2" has an explicit domain, then
1158 * intersect the domain of the result with this explicit domain.
1160 static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
1161 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
1162 __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
1164 int i;
1166 multi1 = FN(MULTI(BASE),cow)(multi1);
1167 if (FN(MULTI(BASE),check_equal_space)(multi1, multi2) < 0)
1168 goto error;
1170 for (i = 0; i < multi1->n; ++i) {
1171 multi1->u.p[i] = fn(multi1->u.p[i],
1172 FN(EL,copy)(multi2->u.p[i]));
1173 if (!multi1->u.p[i])
1174 goto error;
1177 if (FN(MULTI(BASE),has_explicit_domain)(multi2))
1178 multi1 = FN(MULTI(BASE),intersect_explicit_domain)(multi1,
1179 multi2);
1181 FN(MULTI(BASE),free)(multi2);
1182 return multi1;
1183 error:
1184 FN(MULTI(BASE),free)(multi1);
1185 FN(MULTI(BASE),free)(multi2);
1186 return NULL;
1189 /* Add "multi2" from "multi1" and return the result.
1191 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1193 static __isl_give MULTI(BASE) *FN(MULTI(BASE),add_aligned)(
1194 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1196 return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,add));
1199 /* Add "multi2" from "multi1" and return the result.
1201 __isl_give MULTI(BASE) *FN(MULTI(BASE),add)(__isl_take MULTI(BASE) *multi1,
1202 __isl_take MULTI(BASE) *multi2)
1204 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
1205 &FN(MULTI(BASE),add_aligned));
1208 /* Subtract "multi2" from "multi1" and return the result.
1210 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1212 static __isl_give MULTI(BASE) *FN(MULTI(BASE),sub_aligned)(
1213 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1215 return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
1218 /* Subtract "multi2" from "multi1" and return the result.
1220 __isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
1221 __isl_take MULTI(BASE) *multi2)
1223 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
1224 &FN(MULTI(BASE),sub_aligned));
1227 /* Multiply the elements of "multi" by "v" and return the result.
1229 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
1230 __isl_take isl_val *v)
1232 int i;
1234 if (!multi || !v)
1235 goto error;
1237 if (isl_val_is_one(v)) {
1238 isl_val_free(v);
1239 return multi;
1242 if (!isl_val_is_rat(v))
1243 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1244 "expecting rational factor", goto error);
1246 multi = FN(MULTI(BASE),cow)(multi);
1247 if (!multi)
1248 return NULL;
1250 for (i = 0; i < multi->n; ++i) {
1251 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i],
1252 isl_val_copy(v));
1253 if (!multi->u.p[i])
1254 goto error;
1257 isl_val_free(v);
1258 return multi;
1259 error:
1260 isl_val_free(v);
1261 return FN(MULTI(BASE),free)(multi);
1264 /* Divide the elements of "multi" by "v" and return the result.
1266 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
1267 __isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
1269 int i;
1271 if (!multi || !v)
1272 goto error;
1274 if (isl_val_is_one(v)) {
1275 isl_val_free(v);
1276 return multi;
1279 if (!isl_val_is_rat(v))
1280 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1281 "expecting rational factor", goto error);
1282 if (isl_val_is_zero(v))
1283 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1284 "cannot scale down by zero", goto error);
1286 multi = FN(MULTI(BASE),cow)(multi);
1287 if (!multi)
1288 return NULL;
1290 for (i = 0; i < multi->n; ++i) {
1291 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i],
1292 isl_val_copy(v));
1293 if (!multi->u.p[i])
1294 goto error;
1297 isl_val_free(v);
1298 return multi;
1299 error:
1300 isl_val_free(v);
1301 return FN(MULTI(BASE),free)(multi);
1304 /* Multiply the elements of "multi" by the corresponding element of "mv"
1305 * and return the result.
1307 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
1308 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1310 int i;
1312 if (!multi || !mv)
1313 goto error;
1315 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1316 mv->space, isl_dim_set))
1317 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1318 "spaces don't match", goto error);
1320 multi = FN(MULTI(BASE),cow)(multi);
1321 if (!multi)
1322 goto error;
1324 for (i = 0; i < multi->n; ++i) {
1325 isl_val *v;
1327 v = isl_multi_val_get_val(mv, i);
1328 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i], v);
1329 if (!multi->u.p[i])
1330 goto error;
1333 isl_multi_val_free(mv);
1334 return multi;
1335 error:
1336 isl_multi_val_free(mv);
1337 return FN(MULTI(BASE),free)(multi);
1340 /* Divide the elements of "multi" by the corresponding element of "mv"
1341 * and return the result.
1343 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
1344 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1346 int i;
1348 if (!multi || !mv)
1349 goto error;
1351 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1352 mv->space, isl_dim_set))
1353 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1354 "spaces don't match", goto error);
1356 multi = FN(MULTI(BASE),cow)(multi);
1357 if (!multi)
1358 return NULL;
1360 for (i = 0; i < multi->n; ++i) {
1361 isl_val *v;
1363 v = isl_multi_val_get_val(mv, i);
1364 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i], v);
1365 if (!multi->u.p[i])
1366 goto error;
1369 isl_multi_val_free(mv);
1370 return multi;
1371 error:
1372 isl_multi_val_free(mv);
1373 return FN(MULTI(BASE),free)(multi);
1376 /* Compute the residues of the elements of "multi" modulo
1377 * the corresponding element of "mv" and return the result.
1379 __isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
1380 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1382 int i;
1384 if (!multi || !mv)
1385 goto error;
1387 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1388 mv->space, isl_dim_set))
1389 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1390 "spaces don't match", goto error);
1392 multi = FN(MULTI(BASE),cow)(multi);
1393 if (!multi)
1394 goto error;
1396 for (i = 0; i < multi->n; ++i) {
1397 isl_val *v;
1399 v = isl_multi_val_get_val(mv, i);
1400 multi->u.p[i] = FN(EL,mod_val)(multi->u.p[i], v);
1401 if (!multi->u.p[i])
1402 goto error;
1405 isl_multi_val_free(mv);
1406 return multi;
1407 error:
1408 isl_multi_val_free(mv);
1409 return FN(MULTI(BASE),free)(multi);
1412 #ifndef NO_MOVE_DIMS
1413 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
1414 * to dimensions of "dst_type" at "dst_pos".
1416 * We only support moving input dimensions to parameters and vice versa.
1418 __isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
1419 enum isl_dim_type dst_type, unsigned dst_pos,
1420 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1422 int i;
1424 if (!multi)
1425 return NULL;
1427 if (n == 0 &&
1428 !isl_space_is_named_or_nested(multi->space, src_type) &&
1429 !isl_space_is_named_or_nested(multi->space, dst_type))
1430 return multi;
1432 if (dst_type == isl_dim_out || src_type == isl_dim_out)
1433 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1434 "cannot move output/set dimension",
1435 return FN(MULTI(BASE),free)(multi));
1436 if (dst_type == isl_dim_div || src_type == isl_dim_div)
1437 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1438 "cannot move divs",
1439 return FN(MULTI(BASE),free)(multi));
1440 if (src_pos + n > isl_space_dim(multi->space, src_type))
1441 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1442 "range out of bounds",
1443 return FN(MULTI(BASE),free)(multi));
1444 if (dst_type == src_type)
1445 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_unsupported,
1446 "moving dims within the same type not supported",
1447 return FN(MULTI(BASE),free)(multi));
1449 multi = FN(MULTI(BASE),cow)(multi);
1450 if (!multi)
1451 return NULL;
1453 multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
1454 src_type, src_pos, n);
1455 if (!multi->space)
1456 return FN(MULTI(BASE),free)(multi);
1457 if (FN(MULTI(BASE),has_explicit_domain)(multi))
1458 multi = FN(MULTI(BASE),move_explicit_domain_dims)(multi,
1459 dst_type, dst_pos, src_type, src_pos, n);
1460 if (!multi)
1461 return NULL;
1463 for (i = 0; i < multi->n; ++i) {
1464 multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
1465 dst_type, dst_pos,
1466 src_type, src_pos, n);
1467 if (!multi->u.p[i])
1468 return FN(MULTI(BASE),free)(multi);
1471 return multi;
1473 #endif
1475 /* Convert a multiple expression defined over a parameter domain
1476 * into one that is defined over a zero-dimensional set.
1478 __isl_give MULTI(BASE) *FN(MULTI(BASE),from_range)(
1479 __isl_take MULTI(BASE) *multi)
1481 isl_space *space;
1483 if (!multi)
1484 return NULL;
1485 if (!isl_space_is_set(multi->space))
1486 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1487 "not living in a set space",
1488 return FN(MULTI(BASE),free)(multi));
1490 space = FN(MULTI(BASE),get_space)(multi);
1491 space = isl_space_from_range(space);
1492 multi = FN(MULTI(BASE),reset_space)(multi, space);
1494 return multi;
1497 /* Are "multi1" and "multi2" obviously equal?
1499 isl_bool FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1,
1500 __isl_keep MULTI(BASE) *multi2)
1502 int i;
1503 isl_bool equal;
1505 if (!multi1 || !multi2)
1506 return isl_bool_error;
1507 if (multi1->n != multi2->n)
1508 return isl_bool_false;
1509 equal = isl_space_is_equal(multi1->space, multi2->space);
1510 if (equal < 0 || !equal)
1511 return equal;
1513 for (i = 0; i < multi1->n; ++i) {
1514 equal = FN(EL,plain_is_equal)(multi1->u.p[i], multi2->u.p[i]);
1515 if (equal < 0 || !equal)
1516 return equal;
1519 if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
1520 FN(MULTI(BASE),has_explicit_domain)(multi2)) {
1521 equal = FN(MULTI(BASE),equal_explicit_domain)(multi1, multi2);
1522 if (equal < 0 || !equal)
1523 return equal;
1526 return isl_bool_true;
1529 /* Does "multi" involve any NaNs?
1531 isl_bool FN(MULTI(BASE),involves_nan)(__isl_keep MULTI(BASE) *multi)
1533 int i;
1535 if (!multi)
1536 return isl_bool_error;
1537 if (multi->n == 0)
1538 return isl_bool_false;
1540 for (i = 0; i < multi->n; ++i) {
1541 isl_bool has_nan = FN(EL,involves_nan)(multi->u.p[i]);
1542 if (has_nan < 0 || has_nan)
1543 return has_nan;
1546 return isl_bool_false;
1549 #ifndef NO_DOMAIN
1550 /* Return the shared domain of the elements of "multi".
1552 * If "multi" has an explicit domain, then return this domain.
1554 __isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
1556 int i;
1557 isl_set *dom;
1559 if (!multi)
1560 return NULL;
1562 if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
1563 dom = FN(MULTI(BASE),get_explicit_domain)(multi);
1564 FN(MULTI(BASE),free)(multi);
1565 return dom;
1568 dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
1569 for (i = 0; i < multi->n; ++i) {
1570 isl_set *dom_i;
1572 dom_i = FN(EL,domain)(FN(FN(MULTI(BASE),get),BASE)(multi, i));
1573 dom = isl_set_intersect(dom, dom_i);
1576 FN(MULTI(BASE),free)(multi);
1577 return dom;
1579 #endif
1581 #ifndef NO_NEG
1582 /* Return the opposite of "multi".
1584 __isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
1586 int i;
1588 multi = FN(MULTI(BASE),cow)(multi);
1589 if (!multi)
1590 return NULL;
1592 for (i = 0; i < multi->n; ++i) {
1593 multi->u.p[i] = FN(EL,neg)(multi->u.p[i]);
1594 if (!multi->u.p[i])
1595 return FN(MULTI(BASE),free)(multi);
1598 return multi;
1600 #endif