isl_multi_templ.c: extract out isl_multi_identity_templ.c
[isl.git] / isl_multi_templ.c
blobdf27779556fbcd98b86e38bec56c6997f4991b76
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_ZERO
597 /* Construct a multi expression in the given space with value zero in
598 * each of the output dimensions.
600 __isl_give MULTI(BASE) *FN(MULTI(BASE),zero)(__isl_take isl_space *space)
602 int n;
603 MULTI(BASE) *multi;
605 if (!space)
606 return NULL;
608 n = isl_space_dim(space , isl_dim_out);
609 multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
611 if (!n)
612 isl_space_free(space);
613 else {
614 int i;
615 isl_local_space *ls;
616 EL *el;
618 space = isl_space_domain(space);
619 ls = isl_local_space_from_space(space);
620 el = FN(EL,zero_on_domain)(ls);
622 for (i = 0; i < n; ++i)
623 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
624 FN(EL,copy)(el));
626 FN(EL,free)(el);
629 return multi;
631 #endif
633 #ifndef NO_FROM_BASE
634 /* Create a multiple expression with a single output/set dimension
635 * equal to "el".
636 * For most multiple expression types, the base type has a single
637 * output/set dimension and the space of the result is therefore
638 * the same as the space of the input.
639 * In the case of isl_multi_union_pw_aff, however, the base type
640 * lives in a parameter space and we therefore need to add
641 * a single set dimension.
643 __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
645 isl_space *space;
646 MULTI(BASE) *multi;
648 space = FN(EL,get_space(el));
649 if (isl_space_is_params(space)) {
650 space = isl_space_set_from_params(space);
651 space = isl_space_add_dims(space, isl_dim_set, 1);
653 multi = FN(MULTI(BASE),alloc)(space);
654 multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
656 return multi;
658 #endif
660 __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
661 __isl_take MULTI(BASE) *multi,
662 enum isl_dim_type type, unsigned first, unsigned n)
664 int i;
665 unsigned dim;
667 multi = FN(MULTI(BASE),cow)(multi);
668 if (!multi)
669 return NULL;
671 dim = FN(MULTI(BASE),dim)(multi, type);
672 if (first + n > dim || first + n < first)
673 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
674 "index out of bounds",
675 return FN(MULTI(BASE),free)(multi));
677 multi->space = isl_space_drop_dims(multi->space, type, first, n);
678 if (!multi->space)
679 return FN(MULTI(BASE),free)(multi);
681 if (type == isl_dim_out) {
682 for (i = 0; i < n; ++i)
683 FN(EL,free)(multi->u.p[first + i]);
684 for (i = first; i + n < multi->n; ++i)
685 multi->u.p[i] = multi->u.p[i + n];
686 multi->n -= n;
687 if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi))
688 multi = FN(MULTI(BASE),init_explicit_domain)(multi);
690 return multi;
693 if (FN(MULTI(BASE),has_explicit_domain)(multi))
694 multi = FN(MULTI(BASE),drop_explicit_domain_dims)(multi,
695 type, first, n);
696 if (!multi)
697 return NULL;
699 for (i = 0; i < multi->n; ++i) {
700 multi->u.p[i] = FN(EL,drop_dims)(multi->u.p[i], type, first, n);
701 if (!multi->u.p[i])
702 return FN(MULTI(BASE),free)(multi);
705 return multi;
708 /* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
710 static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_multi_and)(
711 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
712 __isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi1,
713 __isl_take MULTI(BASE) *multi2))
715 isl_ctx *ctx;
716 isl_bool equal_params;
718 if (!multi1 || !multi2)
719 goto error;
720 equal_params = isl_space_has_equal_params(multi1->space, multi2->space);
721 if (equal_params < 0)
722 goto error;
723 if (equal_params)
724 return fn(multi1, multi2);
725 ctx = FN(MULTI(BASE),get_ctx)(multi1);
726 if (!isl_space_has_named_params(multi1->space) ||
727 !isl_space_has_named_params(multi2->space))
728 isl_die(ctx, isl_error_invalid,
729 "unaligned unnamed parameters", goto error);
730 multi1 = FN(MULTI(BASE),align_params)(multi1,
731 FN(MULTI(BASE),get_space)(multi2));
732 multi2 = FN(MULTI(BASE),align_params)(multi2,
733 FN(MULTI(BASE),get_space)(multi1));
734 return fn(multi1, multi2);
735 error:
736 FN(MULTI(BASE),free)(multi1);
737 FN(MULTI(BASE),free)(multi2);
738 return NULL;
741 /* Given two MULTI(BASE)s A -> B and C -> D,
742 * construct a MULTI(BASE) (A * C) -> [B -> D].
744 * The parameters are assumed to have been aligned.
746 * If "multi1" and/or "multi2" has an explicit domain, then
747 * intersect the domain of the result with these explicit domains.
749 static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
750 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
752 int i, n1, n2;
753 EL *el;
754 isl_space *space;
755 MULTI(BASE) *res;
757 if (!multi1 || !multi2)
758 goto error;
760 space = isl_space_range_product(FN(MULTI(BASE),get_space)(multi1),
761 FN(MULTI(BASE),get_space)(multi2));
762 res = FN(MULTI(BASE),alloc)(space);
764 n1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
765 n2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
767 for (i = 0; i < n1; ++i) {
768 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
769 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
772 for (i = 0; i < n2; ++i) {
773 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
774 res = FN(FN(MULTI(BASE),set),BASE)(res, n1 + i, el);
777 if (FN(MULTI(BASE),has_explicit_domain)(multi1))
778 res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi1);
779 if (FN(MULTI(BASE),has_explicit_domain)(multi2))
780 res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi2);
782 FN(MULTI(BASE),free)(multi1);
783 FN(MULTI(BASE),free)(multi2);
784 return res;
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 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)(
795 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
797 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
798 &FN(MULTI(BASE),range_product_aligned));
801 /* Is the range of "multi" a wrapped relation?
803 isl_bool FN(MULTI(BASE),range_is_wrapping)(__isl_keep MULTI(BASE) *multi)
805 if (!multi)
806 return isl_bool_error;
807 return isl_space_range_is_wrapping(multi->space);
810 /* Given a function A -> [B -> C], extract the function A -> B.
812 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_domain)(
813 __isl_take MULTI(BASE) *multi)
815 isl_space *space;
816 int total, keep;
818 if (!multi)
819 return NULL;
820 if (!isl_space_range_is_wrapping(multi->space))
821 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
822 "range is not a product",
823 return FN(MULTI(BASE),free)(multi));
825 space = FN(MULTI(BASE),get_space)(multi);
826 total = isl_space_dim(space, isl_dim_out);
827 space = isl_space_range_factor_domain(space);
828 keep = isl_space_dim(space, isl_dim_out);
829 multi = FN(MULTI(BASE),drop_dims)(multi,
830 isl_dim_out, keep, total - keep);
831 multi = FN(MULTI(BASE),reset_space)(multi, space);
833 return multi;
836 /* Given a function A -> [B -> C], extract the function A -> C.
838 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)(
839 __isl_take MULTI(BASE) *multi)
841 isl_space *space;
842 int total, keep;
844 if (!multi)
845 return NULL;
846 if (!isl_space_range_is_wrapping(multi->space))
847 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
848 "range is not a product",
849 return FN(MULTI(BASE),free)(multi));
851 space = FN(MULTI(BASE),get_space)(multi);
852 total = isl_space_dim(space, isl_dim_out);
853 space = isl_space_range_factor_range(space);
854 keep = isl_space_dim(space, isl_dim_out);
855 multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
856 multi = FN(MULTI(BASE),reset_space)(multi, space);
858 return multi;
861 /* Given a function [B -> C], extract the function C.
863 __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
864 __isl_take MULTI(BASE) *multi)
866 isl_space *space;
867 int total, keep;
869 if (!multi)
870 return NULL;
871 if (!isl_space_is_wrapping(multi->space))
872 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
873 "not a product", return FN(MULTI(BASE),free)(multi));
875 space = FN(MULTI(BASE),get_space)(multi);
876 total = isl_space_dim(space, isl_dim_out);
877 space = isl_space_factor_range(space);
878 keep = isl_space_dim(space, isl_dim_out);
879 multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
880 multi = FN(MULTI(BASE),reset_space)(multi, space);
882 return multi;
885 #ifndef NO_PRODUCT
886 /* Given two MULTI(BASE)s A -> B and C -> D,
887 * construct a MULTI(BASE) [A -> C] -> [B -> D].
889 * The parameters are assumed to have been aligned.
891 * If "multi1" and/or "multi2" has an explicit domain, then
892 * intersect the domain of the result with these explicit domains.
894 __isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
895 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
897 int i;
898 EL *el;
899 isl_space *space;
900 MULTI(BASE) *res;
901 int in1, in2, out1, out2;
903 in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
904 in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
905 out1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
906 out2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
907 space = isl_space_product(FN(MULTI(BASE),get_space)(multi1),
908 FN(MULTI(BASE),get_space)(multi2));
909 res = FN(MULTI(BASE),alloc)(isl_space_copy(space));
910 space = isl_space_domain(space);
912 for (i = 0; i < out1; ++i) {
913 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
914 el = FN(EL,insert_dims)(el, isl_dim_in, in1, in2);
915 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
916 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
919 for (i = 0; i < out2; ++i) {
920 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
921 el = FN(EL,insert_dims)(el, isl_dim_in, 0, in1);
922 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
923 res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
926 if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
927 FN(MULTI(BASE),has_explicit_domain)(multi2))
928 res = FN(MULTI(BASE),intersect_explicit_domain_product)(res,
929 multi1, multi2);
931 isl_space_free(space);
932 FN(MULTI(BASE),free)(multi1);
933 FN(MULTI(BASE),free)(multi2);
934 return res;
937 /* Given two MULTI(BASE)s A -> B and C -> D,
938 * construct a MULTI(BASE) [A -> C] -> [B -> D].
940 __isl_give MULTI(BASE) *FN(MULTI(BASE),product)(
941 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
943 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
944 &FN(MULTI(BASE),product_aligned));
946 #endif
948 __isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
949 __isl_take MULTI(BASE) *multi)
951 if (!multi)
952 return NULL;
954 if (!multi->space->nested[1])
955 return multi;
957 multi = FN(MULTI(BASE),cow)(multi);
958 if (!multi)
959 return NULL;
961 multi->space = isl_space_flatten_range(multi->space);
962 if (!multi->space)
963 return FN(MULTI(BASE),free)(multi);
965 return multi;
968 /* Given two MULTI(BASE)s A -> B and C -> D,
969 * construct a MULTI(BASE) (A * C) -> (B, D).
971 __isl_give MULTI(BASE) *FN(MULTI(BASE),flat_range_product)(
972 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
974 MULTI(BASE) *multi;
976 multi = FN(MULTI(BASE),range_product)(multi1, multi2);
977 multi = FN(MULTI(BASE),flatten_range)(multi);
978 return multi;
981 /* Given two multi expressions, "multi1"
983 * [A] -> [B1 B2]
985 * where B2 starts at position "pos", and "multi2"
987 * [A] -> [D]
989 * return the multi expression
991 * [A] -> [B1 D B2]
993 __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
994 __isl_take MULTI(BASE) *multi1, unsigned pos,
995 __isl_take MULTI(BASE) *multi2)
997 MULTI(BASE) *res;
998 unsigned dim;
1000 if (!multi1 || !multi2)
1001 goto error;
1003 dim = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
1004 if (pos > dim)
1005 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1006 "index out of bounds", goto error);
1008 res = FN(MULTI(BASE),copy)(multi1);
1009 res = FN(MULTI(BASE),drop_dims)(res, isl_dim_out, pos, dim - pos);
1010 multi1 = FN(MULTI(BASE),drop_dims)(multi1, isl_dim_out, 0, pos);
1012 res = FN(MULTI(BASE),flat_range_product)(res, multi2);
1013 res = FN(MULTI(BASE),flat_range_product)(res, multi1);
1015 return res;
1016 error:
1017 FN(MULTI(BASE),free)(multi1);
1018 FN(MULTI(BASE),free)(multi2);
1019 return NULL;
1022 #ifndef NO_SPLICE
1023 /* Given two multi expressions, "multi1"
1025 * [A1 A2] -> [B1 B2]
1027 * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
1028 * and "multi2"
1030 * [C] -> [D]
1032 * return the multi expression
1034 * [A1 C A2] -> [B1 D B2]
1036 * We first insert input dimensions to obtain
1038 * [A1 C A2] -> [B1 B2]
1040 * and
1042 * [A1 C A2] -> [D]
1044 * and then apply range_splice.
1046 __isl_give MULTI(BASE) *FN(MULTI(BASE),splice)(
1047 __isl_take MULTI(BASE) *multi1, unsigned in_pos, unsigned out_pos,
1048 __isl_take MULTI(BASE) *multi2)
1050 unsigned n_in1;
1051 unsigned n_in2;
1053 if (!multi1 || !multi2)
1054 goto error;
1056 n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
1057 if (in_pos > n_in1)
1058 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1059 "index out of bounds", goto error);
1061 n_in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
1063 multi1 = FN(MULTI(BASE),insert_dims)(multi1, isl_dim_in, in_pos, n_in2);
1064 multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, n_in2,
1065 n_in1 - in_pos);
1066 multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, 0, in_pos);
1068 return FN(MULTI(BASE),range_splice)(multi1, out_pos, multi2);
1069 error:
1070 FN(MULTI(BASE),free)(multi1);
1071 FN(MULTI(BASE),free)(multi2);
1072 return NULL;
1074 #endif
1076 /* Check that "multi1" and "multi2" live in the same space,
1077 * reporting an error if they do not.
1079 static isl_stat FN(MULTI(BASE),check_equal_space)(
1080 __isl_keep MULTI(BASE) *multi1, __isl_keep MULTI(BASE) *multi2)
1082 isl_bool equal;
1084 if (!multi1 || !multi2)
1085 return isl_stat_error;
1087 equal = isl_space_is_equal(multi1->space, multi2->space);
1088 if (equal < 0)
1089 return isl_stat_error;
1090 if (!equal)
1091 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
1092 "spaces don't match", return isl_stat_error);
1094 return isl_stat_ok;
1097 /* This function is currently only used from isl_aff.c
1099 static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
1100 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
1101 __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
1102 __attribute__ ((unused));
1104 /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
1105 * return the result.
1107 * If "multi2" has an explicit domain, then
1108 * intersect the domain of the result with this explicit domain.
1110 static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
1111 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
1112 __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
1114 int i;
1116 multi1 = FN(MULTI(BASE),cow)(multi1);
1117 if (FN(MULTI(BASE),check_equal_space)(multi1, multi2) < 0)
1118 goto error;
1120 for (i = 0; i < multi1->n; ++i) {
1121 multi1->u.p[i] = fn(multi1->u.p[i],
1122 FN(EL,copy)(multi2->u.p[i]));
1123 if (!multi1->u.p[i])
1124 goto error;
1127 if (FN(MULTI(BASE),has_explicit_domain)(multi2))
1128 multi1 = FN(MULTI(BASE),intersect_explicit_domain)(multi1,
1129 multi2);
1131 FN(MULTI(BASE),free)(multi2);
1132 return multi1;
1133 error:
1134 FN(MULTI(BASE),free)(multi1);
1135 FN(MULTI(BASE),free)(multi2);
1136 return NULL;
1139 /* Add "multi2" to "multi1" and return the result.
1141 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1143 static __isl_give MULTI(BASE) *FN(MULTI(BASE),add_aligned)(
1144 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1146 return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,add));
1149 /* Add "multi2" to "multi1" and return the result.
1151 __isl_give MULTI(BASE) *FN(MULTI(BASE),add)(__isl_take MULTI(BASE) *multi1,
1152 __isl_take MULTI(BASE) *multi2)
1154 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
1155 &FN(MULTI(BASE),add_aligned));
1158 /* Subtract "multi2" from "multi1" and return the result.
1160 * The parameters of "multi1" and "multi2" are assumed to have been aligned.
1162 static __isl_give MULTI(BASE) *FN(MULTI(BASE),sub_aligned)(
1163 __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
1165 return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
1168 /* Subtract "multi2" from "multi1" and return the result.
1170 __isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
1171 __isl_take MULTI(BASE) *multi2)
1173 return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
1174 &FN(MULTI(BASE),sub_aligned));
1177 /* Multiply the elements of "multi" by "v" and return the result.
1179 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
1180 __isl_take isl_val *v)
1182 int i;
1184 if (!multi || !v)
1185 goto error;
1187 if (isl_val_is_one(v)) {
1188 isl_val_free(v);
1189 return multi;
1192 if (!isl_val_is_rat(v))
1193 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1194 "expecting rational factor", goto error);
1196 multi = FN(MULTI(BASE),cow)(multi);
1197 if (!multi)
1198 return NULL;
1200 for (i = 0; i < multi->n; ++i) {
1201 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i],
1202 isl_val_copy(v));
1203 if (!multi->u.p[i])
1204 goto error;
1207 isl_val_free(v);
1208 return multi;
1209 error:
1210 isl_val_free(v);
1211 return FN(MULTI(BASE),free)(multi);
1214 /* Divide the elements of "multi" by "v" and return the result.
1216 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
1217 __isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
1219 int i;
1221 if (!multi || !v)
1222 goto error;
1224 if (isl_val_is_one(v)) {
1225 isl_val_free(v);
1226 return multi;
1229 if (!isl_val_is_rat(v))
1230 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1231 "expecting rational factor", goto error);
1232 if (isl_val_is_zero(v))
1233 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1234 "cannot scale down by zero", goto error);
1236 multi = FN(MULTI(BASE),cow)(multi);
1237 if (!multi)
1238 return NULL;
1240 for (i = 0; i < multi->n; ++i) {
1241 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i],
1242 isl_val_copy(v));
1243 if (!multi->u.p[i])
1244 goto error;
1247 isl_val_free(v);
1248 return multi;
1249 error:
1250 isl_val_free(v);
1251 return FN(MULTI(BASE),free)(multi);
1254 /* Multiply the elements of "multi" by the corresponding element of "mv"
1255 * and return the result.
1257 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
1258 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1260 int i;
1262 if (!multi || !mv)
1263 goto error;
1265 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1266 mv->space, isl_dim_set))
1267 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1268 "spaces don't match", goto error);
1270 multi = FN(MULTI(BASE),cow)(multi);
1271 if (!multi)
1272 goto error;
1274 for (i = 0; i < multi->n; ++i) {
1275 isl_val *v;
1277 v = isl_multi_val_get_val(mv, i);
1278 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i], v);
1279 if (!multi->u.p[i])
1280 goto error;
1283 isl_multi_val_free(mv);
1284 return multi;
1285 error:
1286 isl_multi_val_free(mv);
1287 return FN(MULTI(BASE),free)(multi);
1290 /* Divide the elements of "multi" by the corresponding element of "mv"
1291 * and return the result.
1293 __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
1294 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1296 int i;
1298 if (!multi || !mv)
1299 goto error;
1301 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1302 mv->space, isl_dim_set))
1303 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1304 "spaces don't match", goto error);
1306 multi = FN(MULTI(BASE),cow)(multi);
1307 if (!multi)
1308 return NULL;
1310 for (i = 0; i < multi->n; ++i) {
1311 isl_val *v;
1313 v = isl_multi_val_get_val(mv, i);
1314 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i], v);
1315 if (!multi->u.p[i])
1316 goto error;
1319 isl_multi_val_free(mv);
1320 return multi;
1321 error:
1322 isl_multi_val_free(mv);
1323 return FN(MULTI(BASE),free)(multi);
1326 /* Compute the residues of the elements of "multi" modulo
1327 * the corresponding element of "mv" and return the result.
1329 __isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
1330 __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
1332 int i;
1334 if (!multi || !mv)
1335 goto error;
1337 if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
1338 mv->space, isl_dim_set))
1339 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
1340 "spaces don't match", goto error);
1342 multi = FN(MULTI(BASE),cow)(multi);
1343 if (!multi)
1344 goto error;
1346 for (i = 0; i < multi->n; ++i) {
1347 isl_val *v;
1349 v = isl_multi_val_get_val(mv, i);
1350 multi->u.p[i] = FN(EL,mod_val)(multi->u.p[i], v);
1351 if (!multi->u.p[i])
1352 goto error;
1355 isl_multi_val_free(mv);
1356 return multi;
1357 error:
1358 isl_multi_val_free(mv);
1359 return FN(MULTI(BASE),free)(multi);
1362 #ifndef NO_MOVE_DIMS
1363 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
1364 * to dimensions of "dst_type" at "dst_pos".
1366 * We only support moving input dimensions to parameters and vice versa.
1368 __isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
1369 enum isl_dim_type dst_type, unsigned dst_pos,
1370 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1372 int i;
1374 if (!multi)
1375 return NULL;
1377 if (n == 0 &&
1378 !isl_space_is_named_or_nested(multi->space, src_type) &&
1379 !isl_space_is_named_or_nested(multi->space, dst_type))
1380 return multi;
1382 if (dst_type == isl_dim_out || src_type == isl_dim_out)
1383 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1384 "cannot move output/set dimension",
1385 return FN(MULTI(BASE),free)(multi));
1386 if (dst_type == isl_dim_div || src_type == isl_dim_div)
1387 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1388 "cannot move divs",
1389 return FN(MULTI(BASE),free)(multi));
1390 if (src_pos + n > isl_space_dim(multi->space, src_type))
1391 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1392 "range out of bounds",
1393 return FN(MULTI(BASE),free)(multi));
1394 if (dst_type == src_type)
1395 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_unsupported,
1396 "moving dims within the same type not supported",
1397 return FN(MULTI(BASE),free)(multi));
1399 multi = FN(MULTI(BASE),cow)(multi);
1400 if (!multi)
1401 return NULL;
1403 multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
1404 src_type, src_pos, n);
1405 if (!multi->space)
1406 return FN(MULTI(BASE),free)(multi);
1407 if (FN(MULTI(BASE),has_explicit_domain)(multi))
1408 multi = FN(MULTI(BASE),move_explicit_domain_dims)(multi,
1409 dst_type, dst_pos, src_type, src_pos, n);
1410 if (!multi)
1411 return NULL;
1413 for (i = 0; i < multi->n; ++i) {
1414 multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
1415 dst_type, dst_pos,
1416 src_type, src_pos, n);
1417 if (!multi->u.p[i])
1418 return FN(MULTI(BASE),free)(multi);
1421 return multi;
1423 #endif
1425 /* Convert a multiple expression defined over a parameter domain
1426 * into one that is defined over a zero-dimensional set.
1428 __isl_give MULTI(BASE) *FN(MULTI(BASE),from_range)(
1429 __isl_take MULTI(BASE) *multi)
1431 isl_space *space;
1433 if (!multi)
1434 return NULL;
1435 if (!isl_space_is_set(multi->space))
1436 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
1437 "not living in a set space",
1438 return FN(MULTI(BASE),free)(multi));
1440 space = FN(MULTI(BASE),get_space)(multi);
1441 space = isl_space_from_range(space);
1442 multi = FN(MULTI(BASE),reset_space)(multi, space);
1444 return multi;
1447 /* Are "multi1" and "multi2" obviously equal?
1449 isl_bool FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1,
1450 __isl_keep MULTI(BASE) *multi2)
1452 int i;
1453 isl_bool equal;
1455 if (!multi1 || !multi2)
1456 return isl_bool_error;
1457 if (multi1->n != multi2->n)
1458 return isl_bool_false;
1459 equal = isl_space_is_equal(multi1->space, multi2->space);
1460 if (equal < 0 || !equal)
1461 return equal;
1463 for (i = 0; i < multi1->n; ++i) {
1464 equal = FN(EL,plain_is_equal)(multi1->u.p[i], multi2->u.p[i]);
1465 if (equal < 0 || !equal)
1466 return equal;
1469 if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
1470 FN(MULTI(BASE),has_explicit_domain)(multi2)) {
1471 equal = FN(MULTI(BASE),equal_explicit_domain)(multi1, multi2);
1472 if (equal < 0 || !equal)
1473 return equal;
1476 return isl_bool_true;
1479 /* Does "multi" involve any NaNs?
1481 isl_bool FN(MULTI(BASE),involves_nan)(__isl_keep MULTI(BASE) *multi)
1483 int i;
1485 if (!multi)
1486 return isl_bool_error;
1487 if (multi->n == 0)
1488 return isl_bool_false;
1490 for (i = 0; i < multi->n; ++i) {
1491 isl_bool has_nan = FN(EL,involves_nan)(multi->u.p[i]);
1492 if (has_nan < 0 || has_nan)
1493 return has_nan;
1496 return isl_bool_false;
1499 /* Return the opposite of "multi".
1501 __isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
1503 int i;
1505 multi = FN(MULTI(BASE),cow)(multi);
1506 if (!multi)
1507 return NULL;
1509 for (i = 0; i < multi->n; ++i) {
1510 multi->u.p[i] = FN(EL,neg)(multi->u.p[i]);
1511 if (!multi->u.p[i])
1512 return FN(MULTI(BASE),free)(multi);
1515 return multi;