Update isl to isl-0.18-395-g77701b3
[polly-mirror.git] / lib / External / isl / isl_aff.c
blob8a6a715b974a19bafab4e12c435504f2bff7ce9b
1 /*
2 * Copyright 2011 INRIA Saclay
3 * Copyright 2011 Sven Verdoolaege
4 * Copyright 2012-2014 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
7 * Use of this software is governed by the MIT license
9 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
10 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 * 91893 Orsay, France
12 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
13 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
14 * B.P. 105 - 78153 Le Chesnay, France
17 #include <isl_ctx_private.h>
18 #define ISL_DIM_H
19 #include <isl_map_private.h>
20 #include <isl_union_map_private.h>
21 #include <isl_aff_private.h>
22 #include <isl_space_private.h>
23 #include <isl_local_space_private.h>
24 #include <isl_vec_private.h>
25 #include <isl_mat_private.h>
26 #include <isl/constraint.h>
27 #include <isl_seq.h>
28 #include <isl/set.h>
29 #include <isl_val_private.h>
30 #include <isl/deprecated/aff_int.h>
31 #include <isl_config.h>
33 #undef BASE
34 #define BASE aff
36 #include <isl_list_templ.c>
38 #undef BASE
39 #define BASE pw_aff
41 #include <isl_list_templ.c>
43 #undef BASE
44 #define BASE union_pw_aff
46 #include <isl_list_templ.c>
48 #undef BASE
49 #define BASE union_pw_multi_aff
51 #include <isl_list_templ.c>
53 __isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
54 __isl_take isl_vec *v)
56 isl_aff *aff;
58 if (!ls || !v)
59 goto error;
61 aff = isl_calloc_type(v->ctx, struct isl_aff);
62 if (!aff)
63 goto error;
65 aff->ref = 1;
66 aff->ls = ls;
67 aff->v = v;
69 return aff;
70 error:
71 isl_local_space_free(ls);
72 isl_vec_free(v);
73 return NULL;
76 __isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls)
78 isl_ctx *ctx;
79 isl_vec *v;
80 unsigned total;
82 if (!ls)
83 return NULL;
85 ctx = isl_local_space_get_ctx(ls);
86 if (!isl_local_space_divs_known(ls))
87 isl_die(ctx, isl_error_invalid, "local space has unknown divs",
88 goto error);
89 if (!isl_local_space_is_set(ls))
90 isl_die(ctx, isl_error_invalid,
91 "domain of affine expression should be a set",
92 goto error);
94 total = isl_local_space_dim(ls, isl_dim_all);
95 v = isl_vec_alloc(ctx, 1 + 1 + total);
96 return isl_aff_alloc_vec(ls, v);
97 error:
98 isl_local_space_free(ls);
99 return NULL;
102 __isl_give isl_aff *isl_aff_zero_on_domain(__isl_take isl_local_space *ls)
104 isl_aff *aff;
106 aff = isl_aff_alloc(ls);
107 if (!aff)
108 return NULL;
110 isl_int_set_si(aff->v->el[0], 1);
111 isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
113 return aff;
116 /* Return a piecewise affine expression defined on the specified domain
117 * that is equal to zero.
119 __isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(__isl_take isl_local_space *ls)
121 return isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls));
124 /* Return an affine expression defined on the specified domain
125 * that represents NaN.
127 __isl_give isl_aff *isl_aff_nan_on_domain(__isl_take isl_local_space *ls)
129 isl_aff *aff;
131 aff = isl_aff_alloc(ls);
132 if (!aff)
133 return NULL;
135 isl_seq_clr(aff->v->el, aff->v->size);
137 return aff;
140 /* Return a piecewise affine expression defined on the specified domain
141 * that represents NaN.
143 __isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls)
145 return isl_pw_aff_from_aff(isl_aff_nan_on_domain(ls));
148 /* Return an affine expression that is equal to "val" on
149 * domain local space "ls".
151 __isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls,
152 __isl_take isl_val *val)
154 isl_aff *aff;
156 if (!ls || !val)
157 goto error;
158 if (!isl_val_is_rat(val))
159 isl_die(isl_val_get_ctx(val), isl_error_invalid,
160 "expecting rational value", goto error);
162 aff = isl_aff_alloc(isl_local_space_copy(ls));
163 if (!aff)
164 goto error;
166 isl_seq_clr(aff->v->el + 2, aff->v->size - 2);
167 isl_int_set(aff->v->el[1], val->n);
168 isl_int_set(aff->v->el[0], val->d);
170 isl_local_space_free(ls);
171 isl_val_free(val);
172 return aff;
173 error:
174 isl_local_space_free(ls);
175 isl_val_free(val);
176 return NULL;
179 /* Return an affine expression that is equal to the specified dimension
180 * in "ls".
182 __isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls,
183 enum isl_dim_type type, unsigned pos)
185 isl_space *space;
186 isl_aff *aff;
188 if (!ls)
189 return NULL;
191 space = isl_local_space_get_space(ls);
192 if (!space)
193 goto error;
194 if (isl_space_is_map(space))
195 isl_die(isl_space_get_ctx(space), isl_error_invalid,
196 "expecting (parameter) set space", goto error);
197 if (pos >= isl_local_space_dim(ls, type))
198 isl_die(isl_space_get_ctx(space), isl_error_invalid,
199 "position out of bounds", goto error);
201 isl_space_free(space);
202 aff = isl_aff_alloc(ls);
203 if (!aff)
204 return NULL;
206 pos += isl_local_space_offset(aff->ls, type);
208 isl_int_set_si(aff->v->el[0], 1);
209 isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
210 isl_int_set_si(aff->v->el[1 + pos], 1);
212 return aff;
213 error:
214 isl_local_space_free(ls);
215 isl_space_free(space);
216 return NULL;
219 /* Return a piecewise affine expression that is equal to
220 * the specified dimension in "ls".
222 __isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls,
223 enum isl_dim_type type, unsigned pos)
225 return isl_pw_aff_from_aff(isl_aff_var_on_domain(ls, type, pos));
228 __isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff)
230 if (!aff)
231 return NULL;
233 aff->ref++;
234 return aff;
237 __isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff)
239 if (!aff)
240 return NULL;
242 return isl_aff_alloc_vec(isl_local_space_copy(aff->ls),
243 isl_vec_copy(aff->v));
246 __isl_give isl_aff *isl_aff_cow(__isl_take isl_aff *aff)
248 if (!aff)
249 return NULL;
251 if (aff->ref == 1)
252 return aff;
253 aff->ref--;
254 return isl_aff_dup(aff);
257 __isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff)
259 if (!aff)
260 return NULL;
262 if (--aff->ref > 0)
263 return NULL;
265 isl_local_space_free(aff->ls);
266 isl_vec_free(aff->v);
268 free(aff);
270 return NULL;
273 isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff)
275 return aff ? isl_local_space_get_ctx(aff->ls) : NULL;
278 /* Return a hash value that digests "aff".
280 uint32_t isl_aff_get_hash(__isl_keep isl_aff *aff)
282 uint32_t hash, ls_hash, v_hash;
284 if (!aff)
285 return 0;
287 hash = isl_hash_init();
288 ls_hash = isl_local_space_get_hash(aff->ls);
289 isl_hash_hash(hash, ls_hash);
290 v_hash = isl_vec_get_hash(aff->v);
291 isl_hash_hash(hash, v_hash);
293 return hash;
296 /* Externally, an isl_aff has a map space, but internally, the
297 * ls field corresponds to the domain of that space.
299 int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type)
301 if (!aff)
302 return 0;
303 if (type == isl_dim_out)
304 return 1;
305 if (type == isl_dim_in)
306 type = isl_dim_set;
307 return isl_local_space_dim(aff->ls, type);
310 /* Return the position of the dimension of the given type and name
311 * in "aff".
312 * Return -1 if no such dimension can be found.
314 int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff, enum isl_dim_type type,
315 const char *name)
317 if (!aff)
318 return -1;
319 if (type == isl_dim_out)
320 return -1;
321 if (type == isl_dim_in)
322 type = isl_dim_set;
323 return isl_local_space_find_dim_by_name(aff->ls, type, name);
326 __isl_give isl_space *isl_aff_get_domain_space(__isl_keep isl_aff *aff)
328 return aff ? isl_local_space_get_space(aff->ls) : NULL;
331 __isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff)
333 isl_space *space;
334 if (!aff)
335 return NULL;
336 space = isl_local_space_get_space(aff->ls);
337 space = isl_space_from_domain(space);
338 space = isl_space_add_dims(space, isl_dim_out, 1);
339 return space;
342 __isl_give isl_local_space *isl_aff_get_domain_local_space(
343 __isl_keep isl_aff *aff)
345 return aff ? isl_local_space_copy(aff->ls) : NULL;
348 __isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff)
350 isl_local_space *ls;
351 if (!aff)
352 return NULL;
353 ls = isl_local_space_copy(aff->ls);
354 ls = isl_local_space_from_domain(ls);
355 ls = isl_local_space_add_dims(ls, isl_dim_out, 1);
356 return ls;
359 /* Externally, an isl_aff has a map space, but internally, the
360 * ls field corresponds to the domain of that space.
362 const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
363 enum isl_dim_type type, unsigned pos)
365 if (!aff)
366 return NULL;
367 if (type == isl_dim_out)
368 return NULL;
369 if (type == isl_dim_in)
370 type = isl_dim_set;
371 return isl_local_space_get_dim_name(aff->ls, type, pos);
374 __isl_give isl_aff *isl_aff_reset_domain_space(__isl_take isl_aff *aff,
375 __isl_take isl_space *dim)
377 aff = isl_aff_cow(aff);
378 if (!aff || !dim)
379 goto error;
381 aff->ls = isl_local_space_reset_space(aff->ls, dim);
382 if (!aff->ls)
383 return isl_aff_free(aff);
385 return aff;
386 error:
387 isl_aff_free(aff);
388 isl_space_free(dim);
389 return NULL;
392 /* Reset the space of "aff". This function is called from isl_pw_templ.c
393 * and doesn't know if the space of an element object is represented
394 * directly or through its domain. It therefore passes along both.
396 __isl_give isl_aff *isl_aff_reset_space_and_domain(__isl_take isl_aff *aff,
397 __isl_take isl_space *space, __isl_take isl_space *domain)
399 isl_space_free(space);
400 return isl_aff_reset_domain_space(aff, domain);
403 /* Reorder the coefficients of the affine expression based
404 * on the given reordering.
405 * The reordering r is assumed to have been extended with the local
406 * variables.
408 static __isl_give isl_vec *vec_reorder(__isl_take isl_vec *vec,
409 __isl_take isl_reordering *r, int n_div)
411 isl_vec *res;
412 int i;
414 if (!vec || !r)
415 goto error;
417 res = isl_vec_alloc(vec->ctx,
418 2 + isl_space_dim(r->dim, isl_dim_all) + n_div);
419 if (!res)
420 goto error;
421 isl_seq_cpy(res->el, vec->el, 2);
422 isl_seq_clr(res->el + 2, res->size - 2);
423 for (i = 0; i < r->len; ++i)
424 isl_int_set(res->el[2 + r->pos[i]], vec->el[2 + i]);
426 isl_reordering_free(r);
427 isl_vec_free(vec);
428 return res;
429 error:
430 isl_vec_free(vec);
431 isl_reordering_free(r);
432 return NULL;
435 /* Reorder the dimensions of the domain of "aff" according
436 * to the given reordering.
438 __isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff,
439 __isl_take isl_reordering *r)
441 aff = isl_aff_cow(aff);
442 if (!aff)
443 goto error;
445 r = isl_reordering_extend(r, aff->ls->div->n_row);
446 aff->v = vec_reorder(aff->v, isl_reordering_copy(r),
447 aff->ls->div->n_row);
448 aff->ls = isl_local_space_realign(aff->ls, r);
450 if (!aff->v || !aff->ls)
451 return isl_aff_free(aff);
453 return aff;
454 error:
455 isl_aff_free(aff);
456 isl_reordering_free(r);
457 return NULL;
460 __isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
461 __isl_take isl_space *model)
463 isl_bool equal_params;
465 if (!aff || !model)
466 goto error;
468 equal_params = isl_space_has_equal_params(aff->ls->dim, model);
469 if (equal_params < 0)
470 goto error;
471 if (!equal_params) {
472 isl_reordering *exp;
474 model = isl_space_drop_dims(model, isl_dim_in,
475 0, isl_space_dim(model, isl_dim_in));
476 model = isl_space_drop_dims(model, isl_dim_out,
477 0, isl_space_dim(model, isl_dim_out));
478 exp = isl_parameter_alignment_reordering(aff->ls->dim, model);
479 exp = isl_reordering_extend_space(exp,
480 isl_aff_get_domain_space(aff));
481 aff = isl_aff_realign_domain(aff, exp);
484 isl_space_free(model);
485 return aff;
486 error:
487 isl_space_free(model);
488 isl_aff_free(aff);
489 return NULL;
492 /* Is "aff" obviously equal to zero?
494 * If the denominator is zero, then "aff" is not equal to zero.
496 isl_bool isl_aff_plain_is_zero(__isl_keep isl_aff *aff)
498 if (!aff)
499 return isl_bool_error;
501 if (isl_int_is_zero(aff->v->el[0]))
502 return isl_bool_false;
503 return isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1) < 0;
506 /* Does "aff" represent NaN?
508 isl_bool isl_aff_is_nan(__isl_keep isl_aff *aff)
510 if (!aff)
511 return isl_bool_error;
513 return isl_seq_first_non_zero(aff->v->el, 2) < 0;
516 /* Are "aff1" and "aff2" obviously equal?
518 * NaN is not equal to anything, not even to another NaN.
520 isl_bool isl_aff_plain_is_equal(__isl_keep isl_aff *aff1,
521 __isl_keep isl_aff *aff2)
523 isl_bool equal;
525 if (!aff1 || !aff2)
526 return isl_bool_error;
528 if (isl_aff_is_nan(aff1) || isl_aff_is_nan(aff2))
529 return isl_bool_false;
531 equal = isl_local_space_is_equal(aff1->ls, aff2->ls);
532 if (equal < 0 || !equal)
533 return equal;
535 return isl_vec_is_equal(aff1->v, aff2->v);
538 /* Return the common denominator of "aff" in "v".
540 * We cannot return anything meaningful in case of a NaN.
542 isl_stat isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
544 if (!aff)
545 return isl_stat_error;
546 if (isl_aff_is_nan(aff))
547 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
548 "cannot get denominator of NaN", return isl_stat_error);
549 isl_int_set(*v, aff->v->el[0]);
550 return isl_stat_ok;
553 /* Return the common denominator of "aff".
555 __isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff)
557 isl_ctx *ctx;
559 if (!aff)
560 return NULL;
562 ctx = isl_aff_get_ctx(aff);
563 if (isl_aff_is_nan(aff))
564 return isl_val_nan(ctx);
565 return isl_val_int_from_isl_int(ctx, aff->v->el[0]);
568 /* Return the constant term of "aff" in "v".
570 * We cannot return anything meaningful in case of a NaN.
572 int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
574 if (!aff)
575 return -1;
576 if (isl_aff_is_nan(aff))
577 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
578 "cannot get constant term of NaN", return -1);
579 isl_int_set(*v, aff->v->el[1]);
580 return 0;
583 /* Return the constant term of "aff".
585 __isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff)
587 isl_ctx *ctx;
588 isl_val *v;
590 if (!aff)
591 return NULL;
593 ctx = isl_aff_get_ctx(aff);
594 if (isl_aff_is_nan(aff))
595 return isl_val_nan(ctx);
596 v = isl_val_rat_from_isl_int(ctx, aff->v->el[1], aff->v->el[0]);
597 return isl_val_normalize(v);
600 /* Return the coefficient of the variable of type "type" at position "pos"
601 * of "aff" in "v".
603 * We cannot return anything meaningful in case of a NaN.
605 int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
606 enum isl_dim_type type, int pos, isl_int *v)
608 if (!aff)
609 return -1;
611 if (type == isl_dim_out)
612 isl_die(aff->v->ctx, isl_error_invalid,
613 "output/set dimension does not have a coefficient",
614 return -1);
615 if (type == isl_dim_in)
616 type = isl_dim_set;
618 if (pos >= isl_local_space_dim(aff->ls, type))
619 isl_die(aff->v->ctx, isl_error_invalid,
620 "position out of bounds", return -1);
622 if (isl_aff_is_nan(aff))
623 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
624 "cannot get coefficient of NaN", return -1);
625 pos += isl_local_space_offset(aff->ls, type);
626 isl_int_set(*v, aff->v->el[1 + pos]);
628 return 0;
631 /* Return the coefficient of the variable of type "type" at position "pos"
632 * of "aff".
634 __isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
635 enum isl_dim_type type, int pos)
637 isl_ctx *ctx;
638 isl_val *v;
640 if (!aff)
641 return NULL;
643 ctx = isl_aff_get_ctx(aff);
644 if (type == isl_dim_out)
645 isl_die(ctx, isl_error_invalid,
646 "output/set dimension does not have a coefficient",
647 return NULL);
648 if (type == isl_dim_in)
649 type = isl_dim_set;
651 if (pos >= isl_local_space_dim(aff->ls, type))
652 isl_die(ctx, isl_error_invalid,
653 "position out of bounds", return NULL);
655 if (isl_aff_is_nan(aff))
656 return isl_val_nan(ctx);
657 pos += isl_local_space_offset(aff->ls, type);
658 v = isl_val_rat_from_isl_int(ctx, aff->v->el[1 + pos], aff->v->el[0]);
659 return isl_val_normalize(v);
662 /* Return the sign of the coefficient of the variable of type "type"
663 * at position "pos" of "aff".
665 int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type,
666 int pos)
668 isl_ctx *ctx;
670 if (!aff)
671 return 0;
673 ctx = isl_aff_get_ctx(aff);
674 if (type == isl_dim_out)
675 isl_die(ctx, isl_error_invalid,
676 "output/set dimension does not have a coefficient",
677 return 0);
678 if (type == isl_dim_in)
679 type = isl_dim_set;
681 if (pos >= isl_local_space_dim(aff->ls, type))
682 isl_die(ctx, isl_error_invalid,
683 "position out of bounds", return 0);
685 pos += isl_local_space_offset(aff->ls, type);
686 return isl_int_sgn(aff->v->el[1 + pos]);
689 /* Replace the denominator of "aff" by "v".
691 * A NaN is unaffected by this operation.
693 __isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v)
695 if (!aff)
696 return NULL;
697 if (isl_aff_is_nan(aff))
698 return aff;
699 aff = isl_aff_cow(aff);
700 if (!aff)
701 return NULL;
703 aff->v = isl_vec_cow(aff->v);
704 if (!aff->v)
705 return isl_aff_free(aff);
707 isl_int_set(aff->v->el[0], v);
709 return aff;
712 /* Replace the numerator of the constant term of "aff" by "v".
714 * A NaN is unaffected by this operation.
716 __isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
718 if (!aff)
719 return NULL;
720 if (isl_aff_is_nan(aff))
721 return aff;
722 aff = isl_aff_cow(aff);
723 if (!aff)
724 return NULL;
726 aff->v = isl_vec_cow(aff->v);
727 if (!aff->v)
728 return isl_aff_free(aff);
730 isl_int_set(aff->v->el[1], v);
732 return aff;
735 /* Replace the constant term of "aff" by "v".
737 * A NaN is unaffected by this operation.
739 __isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
740 __isl_take isl_val *v)
742 if (!aff || !v)
743 goto error;
745 if (isl_aff_is_nan(aff)) {
746 isl_val_free(v);
747 return aff;
750 if (!isl_val_is_rat(v))
751 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
752 "expecting rational value", goto error);
754 if (isl_int_eq(aff->v->el[1], v->n) &&
755 isl_int_eq(aff->v->el[0], v->d)) {
756 isl_val_free(v);
757 return aff;
760 aff = isl_aff_cow(aff);
761 if (!aff)
762 goto error;
763 aff->v = isl_vec_cow(aff->v);
764 if (!aff->v)
765 goto error;
767 if (isl_int_eq(aff->v->el[0], v->d)) {
768 isl_int_set(aff->v->el[1], v->n);
769 } else if (isl_int_is_one(v->d)) {
770 isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
771 } else {
772 isl_seq_scale(aff->v->el + 1,
773 aff->v->el + 1, v->d, aff->v->size - 1);
774 isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
775 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
776 aff->v = isl_vec_normalize(aff->v);
777 if (!aff->v)
778 goto error;
781 isl_val_free(v);
782 return aff;
783 error:
784 isl_aff_free(aff);
785 isl_val_free(v);
786 return NULL;
789 /* Add "v" to the constant term of "aff".
791 * A NaN is unaffected by this operation.
793 __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
795 if (isl_int_is_zero(v))
796 return aff;
798 if (!aff)
799 return NULL;
800 if (isl_aff_is_nan(aff))
801 return aff;
802 aff = isl_aff_cow(aff);
803 if (!aff)
804 return NULL;
806 aff->v = isl_vec_cow(aff->v);
807 if (!aff->v)
808 return isl_aff_free(aff);
810 isl_int_addmul(aff->v->el[1], aff->v->el[0], v);
812 return aff;
815 /* Add "v" to the constant term of "aff".
817 * A NaN is unaffected by this operation.
819 __isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff,
820 __isl_take isl_val *v)
822 if (!aff || !v)
823 goto error;
825 if (isl_aff_is_nan(aff) || isl_val_is_zero(v)) {
826 isl_val_free(v);
827 return aff;
830 if (!isl_val_is_rat(v))
831 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
832 "expecting rational value", goto error);
834 aff = isl_aff_cow(aff);
835 if (!aff)
836 goto error;
838 aff->v = isl_vec_cow(aff->v);
839 if (!aff->v)
840 goto error;
842 if (isl_int_is_one(v->d)) {
843 isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
844 } else if (isl_int_eq(aff->v->el[0], v->d)) {
845 isl_int_add(aff->v->el[1], aff->v->el[1], v->n);
846 aff->v = isl_vec_normalize(aff->v);
847 if (!aff->v)
848 goto error;
849 } else {
850 isl_seq_scale(aff->v->el + 1,
851 aff->v->el + 1, v->d, aff->v->size - 1);
852 isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
853 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
854 aff->v = isl_vec_normalize(aff->v);
855 if (!aff->v)
856 goto error;
859 isl_val_free(v);
860 return aff;
861 error:
862 isl_aff_free(aff);
863 isl_val_free(v);
864 return NULL;
867 __isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v)
869 isl_int t;
871 isl_int_init(t);
872 isl_int_set_si(t, v);
873 aff = isl_aff_add_constant(aff, t);
874 isl_int_clear(t);
876 return aff;
879 /* Add "v" to the numerator of the constant term of "aff".
881 * A NaN is unaffected by this operation.
883 __isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff, isl_int v)
885 if (isl_int_is_zero(v))
886 return aff;
888 if (!aff)
889 return NULL;
890 if (isl_aff_is_nan(aff))
891 return aff;
892 aff = isl_aff_cow(aff);
893 if (!aff)
894 return NULL;
896 aff->v = isl_vec_cow(aff->v);
897 if (!aff->v)
898 return isl_aff_free(aff);
900 isl_int_add(aff->v->el[1], aff->v->el[1], v);
902 return aff;
905 /* Add "v" to the numerator of the constant term of "aff".
907 * A NaN is unaffected by this operation.
909 __isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v)
911 isl_int t;
913 if (v == 0)
914 return aff;
916 isl_int_init(t);
917 isl_int_set_si(t, v);
918 aff = isl_aff_add_constant_num(aff, t);
919 isl_int_clear(t);
921 return aff;
924 /* Replace the numerator of the constant term of "aff" by "v".
926 * A NaN is unaffected by this operation.
928 __isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v)
930 if (!aff)
931 return NULL;
932 if (isl_aff_is_nan(aff))
933 return aff;
934 aff = isl_aff_cow(aff);
935 if (!aff)
936 return NULL;
938 aff->v = isl_vec_cow(aff->v);
939 if (!aff->v)
940 return isl_aff_free(aff);
942 isl_int_set_si(aff->v->el[1], v);
944 return aff;
947 /* Replace the numerator of the coefficient of the variable of type "type"
948 * at position "pos" of "aff" by "v".
950 * A NaN is unaffected by this operation.
952 __isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
953 enum isl_dim_type type, int pos, isl_int v)
955 if (!aff)
956 return NULL;
958 if (type == isl_dim_out)
959 isl_die(aff->v->ctx, isl_error_invalid,
960 "output/set dimension does not have a coefficient",
961 return isl_aff_free(aff));
962 if (type == isl_dim_in)
963 type = isl_dim_set;
965 if (pos >= isl_local_space_dim(aff->ls, type))
966 isl_die(aff->v->ctx, isl_error_invalid,
967 "position out of bounds", return isl_aff_free(aff));
969 if (isl_aff_is_nan(aff))
970 return aff;
971 aff = isl_aff_cow(aff);
972 if (!aff)
973 return NULL;
975 aff->v = isl_vec_cow(aff->v);
976 if (!aff->v)
977 return isl_aff_free(aff);
979 pos += isl_local_space_offset(aff->ls, type);
980 isl_int_set(aff->v->el[1 + pos], v);
982 return aff;
985 /* Replace the numerator of the coefficient of the variable of type "type"
986 * at position "pos" of "aff" by "v".
988 * A NaN is unaffected by this operation.
990 __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
991 enum isl_dim_type type, int pos, int v)
993 if (!aff)
994 return NULL;
996 if (type == isl_dim_out)
997 isl_die(aff->v->ctx, isl_error_invalid,
998 "output/set dimension does not have a coefficient",
999 return isl_aff_free(aff));
1000 if (type == isl_dim_in)
1001 type = isl_dim_set;
1003 if (pos < 0 || pos >= isl_local_space_dim(aff->ls, type))
1004 isl_die(aff->v->ctx, isl_error_invalid,
1005 "position out of bounds", return isl_aff_free(aff));
1007 if (isl_aff_is_nan(aff))
1008 return aff;
1009 pos += isl_local_space_offset(aff->ls, type);
1010 if (isl_int_cmp_si(aff->v->el[1 + pos], v) == 0)
1011 return aff;
1013 aff = isl_aff_cow(aff);
1014 if (!aff)
1015 return NULL;
1017 aff->v = isl_vec_cow(aff->v);
1018 if (!aff->v)
1019 return isl_aff_free(aff);
1021 isl_int_set_si(aff->v->el[1 + pos], v);
1023 return aff;
1026 /* Replace the coefficient of the variable of type "type" at position "pos"
1027 * of "aff" by "v".
1029 * A NaN is unaffected by this operation.
1031 __isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
1032 enum isl_dim_type type, int pos, __isl_take isl_val *v)
1034 if (!aff || !v)
1035 goto error;
1037 if (type == isl_dim_out)
1038 isl_die(aff->v->ctx, isl_error_invalid,
1039 "output/set dimension does not have a coefficient",
1040 goto error);
1041 if (type == isl_dim_in)
1042 type = isl_dim_set;
1044 if (pos >= isl_local_space_dim(aff->ls, type))
1045 isl_die(aff->v->ctx, isl_error_invalid,
1046 "position out of bounds", goto error);
1048 if (isl_aff_is_nan(aff)) {
1049 isl_val_free(v);
1050 return aff;
1052 if (!isl_val_is_rat(v))
1053 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1054 "expecting rational value", goto error);
1056 pos += isl_local_space_offset(aff->ls, type);
1057 if (isl_int_eq(aff->v->el[1 + pos], v->n) &&
1058 isl_int_eq(aff->v->el[0], v->d)) {
1059 isl_val_free(v);
1060 return aff;
1063 aff = isl_aff_cow(aff);
1064 if (!aff)
1065 goto error;
1066 aff->v = isl_vec_cow(aff->v);
1067 if (!aff->v)
1068 goto error;
1070 if (isl_int_eq(aff->v->el[0], v->d)) {
1071 isl_int_set(aff->v->el[1 + pos], v->n);
1072 } else if (isl_int_is_one(v->d)) {
1073 isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1074 } else {
1075 isl_seq_scale(aff->v->el + 1,
1076 aff->v->el + 1, v->d, aff->v->size - 1);
1077 isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1078 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
1079 aff->v = isl_vec_normalize(aff->v);
1080 if (!aff->v)
1081 goto error;
1084 isl_val_free(v);
1085 return aff;
1086 error:
1087 isl_aff_free(aff);
1088 isl_val_free(v);
1089 return NULL;
1092 /* Add "v" to the coefficient of the variable of type "type"
1093 * at position "pos" of "aff".
1095 * A NaN is unaffected by this operation.
1097 __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
1098 enum isl_dim_type type, int pos, isl_int v)
1100 if (!aff)
1101 return NULL;
1103 if (type == isl_dim_out)
1104 isl_die(aff->v->ctx, isl_error_invalid,
1105 "output/set dimension does not have a coefficient",
1106 return isl_aff_free(aff));
1107 if (type == isl_dim_in)
1108 type = isl_dim_set;
1110 if (pos >= isl_local_space_dim(aff->ls, type))
1111 isl_die(aff->v->ctx, isl_error_invalid,
1112 "position out of bounds", return isl_aff_free(aff));
1114 if (isl_aff_is_nan(aff))
1115 return aff;
1116 aff = isl_aff_cow(aff);
1117 if (!aff)
1118 return NULL;
1120 aff->v = isl_vec_cow(aff->v);
1121 if (!aff->v)
1122 return isl_aff_free(aff);
1124 pos += isl_local_space_offset(aff->ls, type);
1125 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v);
1127 return aff;
1130 /* Add "v" to the coefficient of the variable of type "type"
1131 * at position "pos" of "aff".
1133 * A NaN is unaffected by this operation.
1135 __isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff,
1136 enum isl_dim_type type, int pos, __isl_take isl_val *v)
1138 if (!aff || !v)
1139 goto error;
1141 if (isl_val_is_zero(v)) {
1142 isl_val_free(v);
1143 return aff;
1146 if (type == isl_dim_out)
1147 isl_die(aff->v->ctx, isl_error_invalid,
1148 "output/set dimension does not have a coefficient",
1149 goto error);
1150 if (type == isl_dim_in)
1151 type = isl_dim_set;
1153 if (pos >= isl_local_space_dim(aff->ls, type))
1154 isl_die(aff->v->ctx, isl_error_invalid,
1155 "position out of bounds", goto error);
1157 if (isl_aff_is_nan(aff)) {
1158 isl_val_free(v);
1159 return aff;
1161 if (!isl_val_is_rat(v))
1162 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1163 "expecting rational value", goto error);
1165 aff = isl_aff_cow(aff);
1166 if (!aff)
1167 goto error;
1169 aff->v = isl_vec_cow(aff->v);
1170 if (!aff->v)
1171 goto error;
1173 pos += isl_local_space_offset(aff->ls, type);
1174 if (isl_int_is_one(v->d)) {
1175 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1176 } else if (isl_int_eq(aff->v->el[0], v->d)) {
1177 isl_int_add(aff->v->el[1 + pos], aff->v->el[1 + pos], v->n);
1178 aff->v = isl_vec_normalize(aff->v);
1179 if (!aff->v)
1180 goto error;
1181 } else {
1182 isl_seq_scale(aff->v->el + 1,
1183 aff->v->el + 1, v->d, aff->v->size - 1);
1184 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1185 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
1186 aff->v = isl_vec_normalize(aff->v);
1187 if (!aff->v)
1188 goto error;
1191 isl_val_free(v);
1192 return aff;
1193 error:
1194 isl_aff_free(aff);
1195 isl_val_free(v);
1196 return NULL;
1199 __isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
1200 enum isl_dim_type type, int pos, int v)
1202 isl_int t;
1204 isl_int_init(t);
1205 isl_int_set_si(t, v);
1206 aff = isl_aff_add_coefficient(aff, type, pos, t);
1207 isl_int_clear(t);
1209 return aff;
1212 __isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos)
1214 if (!aff)
1215 return NULL;
1217 return isl_local_space_get_div(aff->ls, pos);
1220 /* Return the negation of "aff".
1222 * As a special case, -NaN = NaN.
1224 __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
1226 if (!aff)
1227 return NULL;
1228 if (isl_aff_is_nan(aff))
1229 return aff;
1230 aff = isl_aff_cow(aff);
1231 if (!aff)
1232 return NULL;
1233 aff->v = isl_vec_cow(aff->v);
1234 if (!aff->v)
1235 return isl_aff_free(aff);
1237 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
1239 return aff;
1242 /* Remove divs from the local space that do not appear in the affine
1243 * expression.
1244 * We currently only remove divs at the end.
1245 * Some intermediate divs may also not appear directly in the affine
1246 * expression, but we would also need to check that no other divs are
1247 * defined in terms of them.
1249 __isl_give isl_aff *isl_aff_remove_unused_divs(__isl_take isl_aff *aff)
1251 int pos;
1252 int off;
1253 int n;
1255 if (!aff)
1256 return NULL;
1258 n = isl_local_space_dim(aff->ls, isl_dim_div);
1259 off = isl_local_space_offset(aff->ls, isl_dim_div);
1261 pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1;
1262 if (pos == n)
1263 return aff;
1265 aff = isl_aff_cow(aff);
1266 if (!aff)
1267 return NULL;
1269 aff->ls = isl_local_space_drop_dims(aff->ls, isl_dim_div, pos, n - pos);
1270 aff->v = isl_vec_drop_els(aff->v, 1 + off + pos, n - pos);
1271 if (!aff->ls || !aff->v)
1272 return isl_aff_free(aff);
1274 return aff;
1277 /* Given two affine expressions "p" of length p_len (including the
1278 * denominator and the constant term) and "subs" of length subs_len,
1279 * plug in "subs" for the variable at position "pos".
1280 * The variables of "subs" and "p" are assumed to match up to subs_len,
1281 * but "p" may have additional variables.
1282 * "v" is an initialized isl_int that can be used internally.
1284 * In particular, if "p" represents the expression
1286 * (a i + g)/m
1288 * with i the variable at position "pos" and "subs" represents the expression
1290 * f/d
1292 * then the result represents the expression
1294 * (a f + d g)/(m d)
1297 void isl_seq_substitute(isl_int *p, int pos, isl_int *subs,
1298 int p_len, int subs_len, isl_int v)
1300 isl_int_set(v, p[1 + pos]);
1301 isl_int_set_si(p[1 + pos], 0);
1302 isl_seq_combine(p + 1, subs[0], p + 1, v, subs + 1, subs_len - 1);
1303 isl_seq_scale(p + subs_len, p + subs_len, subs[0], p_len - subs_len);
1304 isl_int_mul(p[0], p[0], subs[0]);
1307 /* Look for any divs in the aff->ls with a denominator equal to one
1308 * and plug them into the affine expression and any subsequent divs
1309 * that may reference the div.
1311 static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff)
1313 int i, n;
1314 int len;
1315 isl_int v;
1316 isl_vec *vec;
1317 isl_local_space *ls;
1318 unsigned pos;
1320 if (!aff)
1321 return NULL;
1323 n = isl_local_space_dim(aff->ls, isl_dim_div);
1324 len = aff->v->size;
1325 for (i = 0; i < n; ++i) {
1326 if (!isl_int_is_one(aff->ls->div->row[i][0]))
1327 continue;
1328 ls = isl_local_space_copy(aff->ls);
1329 ls = isl_local_space_substitute_seq(ls, isl_dim_div, i,
1330 aff->ls->div->row[i], len, i + 1, n - (i + 1));
1331 vec = isl_vec_copy(aff->v);
1332 vec = isl_vec_cow(vec);
1333 if (!ls || !vec)
1334 goto error;
1336 isl_int_init(v);
1338 pos = isl_local_space_offset(aff->ls, isl_dim_div) + i;
1339 isl_seq_substitute(vec->el, pos, aff->ls->div->row[i],
1340 len, len, v);
1342 isl_int_clear(v);
1344 isl_vec_free(aff->v);
1345 aff->v = vec;
1346 isl_local_space_free(aff->ls);
1347 aff->ls = ls;
1350 return aff;
1351 error:
1352 isl_vec_free(vec);
1353 isl_local_space_free(ls);
1354 return isl_aff_free(aff);
1357 /* Look for any divs j that appear with a unit coefficient inside
1358 * the definitions of other divs i and plug them into the definitions
1359 * of the divs i.
1361 * In particular, an expression of the form
1363 * floor((f(..) + floor(g(..)/n))/m)
1365 * is simplified to
1367 * floor((n * f(..) + g(..))/(n * m))
1369 * This simplification is correct because we can move the expression
1370 * f(..) into the inner floor in the original expression to obtain
1372 * floor(floor((n * f(..) + g(..))/n)/m)
1374 * from which we can derive the simplified expression.
1376 static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff)
1378 int i, j, n;
1379 int off;
1381 if (!aff)
1382 return NULL;
1384 n = isl_local_space_dim(aff->ls, isl_dim_div);
1385 off = isl_local_space_offset(aff->ls, isl_dim_div);
1386 for (i = 1; i < n; ++i) {
1387 for (j = 0; j < i; ++j) {
1388 if (!isl_int_is_one(aff->ls->div->row[i][1 + off + j]))
1389 continue;
1390 aff->ls = isl_local_space_substitute_seq(aff->ls,
1391 isl_dim_div, j, aff->ls->div->row[j],
1392 aff->v->size, i, 1);
1393 if (!aff->ls)
1394 return isl_aff_free(aff);
1398 return aff;
1401 /* Swap divs "a" and "b" in "aff", which is assumed to be non-NULL.
1403 * Even though this function is only called on isl_affs with a single
1404 * reference, we are careful to only change aff->v and aff->ls together.
1406 static __isl_give isl_aff *swap_div(__isl_take isl_aff *aff, int a, int b)
1408 unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
1409 isl_local_space *ls;
1410 isl_vec *v;
1412 ls = isl_local_space_copy(aff->ls);
1413 ls = isl_local_space_swap_div(ls, a, b);
1414 v = isl_vec_copy(aff->v);
1415 v = isl_vec_cow(v);
1416 if (!ls || !v)
1417 goto error;
1419 isl_int_swap(v->el[1 + off + a], v->el[1 + off + b]);
1420 isl_vec_free(aff->v);
1421 aff->v = v;
1422 isl_local_space_free(aff->ls);
1423 aff->ls = ls;
1425 return aff;
1426 error:
1427 isl_vec_free(v);
1428 isl_local_space_free(ls);
1429 return isl_aff_free(aff);
1432 /* Merge divs "a" and "b" in "aff", which is assumed to be non-NULL.
1434 * We currently do not actually remove div "b", but simply add its
1435 * coefficient to that of "a" and then zero it out.
1437 static __isl_give isl_aff *merge_divs(__isl_take isl_aff *aff, int a, int b)
1439 unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
1441 if (isl_int_is_zero(aff->v->el[1 + off + b]))
1442 return aff;
1444 aff->v = isl_vec_cow(aff->v);
1445 if (!aff->v)
1446 return isl_aff_free(aff);
1448 isl_int_add(aff->v->el[1 + off + a],
1449 aff->v->el[1 + off + a], aff->v->el[1 + off + b]);
1450 isl_int_set_si(aff->v->el[1 + off + b], 0);
1452 return aff;
1455 /* Sort the divs in the local space of "aff" according to
1456 * the comparison function "cmp_row" in isl_local_space.c,
1457 * combining the coefficients of identical divs.
1459 * Reordering divs does not change the semantics of "aff",
1460 * so there is no need to call isl_aff_cow.
1461 * Moreover, this function is currently only called on isl_affs
1462 * with a single reference.
1464 static __isl_give isl_aff *sort_divs(__isl_take isl_aff *aff)
1466 int i, j, n;
1468 if (!aff)
1469 return NULL;
1471 n = isl_aff_dim(aff, isl_dim_div);
1472 for (i = 1; i < n; ++i) {
1473 for (j = i - 1; j >= 0; --j) {
1474 int cmp = isl_mat_cmp_div(aff->ls->div, j, j + 1);
1475 if (cmp < 0)
1476 break;
1477 if (cmp == 0)
1478 aff = merge_divs(aff, j, j + 1);
1479 else
1480 aff = swap_div(aff, j, j + 1);
1481 if (!aff)
1482 return NULL;
1486 return aff;
1489 /* Normalize the representation of "aff".
1491 * This function should only be called of "new" isl_affs, i.e.,
1492 * with only a single reference. We therefore do not need to
1493 * worry about affecting other instances.
1495 __isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff)
1497 if (!aff)
1498 return NULL;
1499 aff->v = isl_vec_normalize(aff->v);
1500 if (!aff->v)
1501 return isl_aff_free(aff);
1502 aff = plug_in_integral_divs(aff);
1503 aff = plug_in_unit_divs(aff);
1504 aff = sort_divs(aff);
1505 aff = isl_aff_remove_unused_divs(aff);
1506 return aff;
1509 /* Given f, return floor(f).
1510 * If f is an integer expression, then just return f.
1511 * If f is a constant, then return the constant floor(f).
1512 * Otherwise, if f = g/m, write g = q m + r,
1513 * create a new div d = [r/m] and return the expression q + d.
1514 * The coefficients in r are taken to lie between -m/2 and m/2.
1516 * reduce_div_coefficients performs the same normalization.
1518 * As a special case, floor(NaN) = NaN.
1520 __isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff)
1522 int i;
1523 int size;
1524 isl_ctx *ctx;
1525 isl_vec *div;
1527 if (!aff)
1528 return NULL;
1530 if (isl_aff_is_nan(aff))
1531 return aff;
1532 if (isl_int_is_one(aff->v->el[0]))
1533 return aff;
1535 aff = isl_aff_cow(aff);
1536 if (!aff)
1537 return NULL;
1539 aff->v = isl_vec_cow(aff->v);
1540 if (!aff->v)
1541 return isl_aff_free(aff);
1543 if (isl_aff_is_cst(aff)) {
1544 isl_int_fdiv_q(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
1545 isl_int_set_si(aff->v->el[0], 1);
1546 return aff;
1549 div = isl_vec_copy(aff->v);
1550 div = isl_vec_cow(div);
1551 if (!div)
1552 return isl_aff_free(aff);
1554 ctx = isl_aff_get_ctx(aff);
1555 isl_int_fdiv_q(aff->v->el[0], aff->v->el[0], ctx->two);
1556 for (i = 1; i < aff->v->size; ++i) {
1557 isl_int_fdiv_r(div->el[i], div->el[i], div->el[0]);
1558 isl_int_fdiv_q(aff->v->el[i], aff->v->el[i], div->el[0]);
1559 if (isl_int_gt(div->el[i], aff->v->el[0])) {
1560 isl_int_sub(div->el[i], div->el[i], div->el[0]);
1561 isl_int_add_ui(aff->v->el[i], aff->v->el[i], 1);
1565 aff->ls = isl_local_space_add_div(aff->ls, div);
1566 if (!aff->ls)
1567 return isl_aff_free(aff);
1569 size = aff->v->size;
1570 aff->v = isl_vec_extend(aff->v, size + 1);
1571 if (!aff->v)
1572 return isl_aff_free(aff);
1573 isl_int_set_si(aff->v->el[0], 1);
1574 isl_int_set_si(aff->v->el[size], 1);
1576 aff = isl_aff_normalize(aff);
1578 return aff;
1581 /* Compute
1583 * aff mod m = aff - m * floor(aff/m)
1585 __isl_give isl_aff *isl_aff_mod(__isl_take isl_aff *aff, isl_int m)
1587 isl_aff *res;
1589 res = isl_aff_copy(aff);
1590 aff = isl_aff_scale_down(aff, m);
1591 aff = isl_aff_floor(aff);
1592 aff = isl_aff_scale(aff, m);
1593 res = isl_aff_sub(res, aff);
1595 return res;
1598 /* Compute
1600 * aff mod m = aff - m * floor(aff/m)
1602 * with m an integer value.
1604 __isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
1605 __isl_take isl_val *m)
1607 isl_aff *res;
1609 if (!aff || !m)
1610 goto error;
1612 if (!isl_val_is_int(m))
1613 isl_die(isl_val_get_ctx(m), isl_error_invalid,
1614 "expecting integer modulo", goto error);
1616 res = isl_aff_copy(aff);
1617 aff = isl_aff_scale_down_val(aff, isl_val_copy(m));
1618 aff = isl_aff_floor(aff);
1619 aff = isl_aff_scale_val(aff, m);
1620 res = isl_aff_sub(res, aff);
1622 return res;
1623 error:
1624 isl_aff_free(aff);
1625 isl_val_free(m);
1626 return NULL;
1629 /* Compute
1631 * pwaff mod m = pwaff - m * floor(pwaff/m)
1633 __isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m)
1635 isl_pw_aff *res;
1637 res = isl_pw_aff_copy(pwaff);
1638 pwaff = isl_pw_aff_scale_down(pwaff, m);
1639 pwaff = isl_pw_aff_floor(pwaff);
1640 pwaff = isl_pw_aff_scale(pwaff, m);
1641 res = isl_pw_aff_sub(res, pwaff);
1643 return res;
1646 /* Compute
1648 * pa mod m = pa - m * floor(pa/m)
1650 * with m an integer value.
1652 __isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa,
1653 __isl_take isl_val *m)
1655 if (!pa || !m)
1656 goto error;
1657 if (!isl_val_is_int(m))
1658 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
1659 "expecting integer modulo", goto error);
1660 pa = isl_pw_aff_mod(pa, m->n);
1661 isl_val_free(m);
1662 return pa;
1663 error:
1664 isl_pw_aff_free(pa);
1665 isl_val_free(m);
1666 return NULL;
1669 /* Given f, return ceil(f).
1670 * If f is an integer expression, then just return f.
1671 * Otherwise, let f be the expression
1673 * e/m
1675 * then return
1677 * floor((e + m - 1)/m)
1679 * As a special case, ceil(NaN) = NaN.
1681 __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff)
1683 if (!aff)
1684 return NULL;
1686 if (isl_aff_is_nan(aff))
1687 return aff;
1688 if (isl_int_is_one(aff->v->el[0]))
1689 return aff;
1691 aff = isl_aff_cow(aff);
1692 if (!aff)
1693 return NULL;
1694 aff->v = isl_vec_cow(aff->v);
1695 if (!aff->v)
1696 return isl_aff_free(aff);
1698 isl_int_add(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
1699 isl_int_sub_ui(aff->v->el[1], aff->v->el[1], 1);
1700 aff = isl_aff_floor(aff);
1702 return aff;
1705 /* Apply the expansion computed by isl_merge_divs.
1706 * The expansion itself is given by "exp" while the resulting
1707 * list of divs is given by "div".
1709 __isl_give isl_aff *isl_aff_expand_divs(__isl_take isl_aff *aff,
1710 __isl_take isl_mat *div, int *exp)
1712 int old_n_div;
1713 int new_n_div;
1714 int offset;
1716 aff = isl_aff_cow(aff);
1717 if (!aff || !div)
1718 goto error;
1720 old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
1721 new_n_div = isl_mat_rows(div);
1722 offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
1724 aff->v = isl_vec_expand(aff->v, offset, old_n_div, exp, new_n_div);
1725 aff->ls = isl_local_space_replace_divs(aff->ls, div);
1726 if (!aff->v || !aff->ls)
1727 return isl_aff_free(aff);
1728 return aff;
1729 error:
1730 isl_aff_free(aff);
1731 isl_mat_free(div);
1732 return NULL;
1735 /* Add two affine expressions that live in the same local space.
1737 static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1,
1738 __isl_take isl_aff *aff2)
1740 isl_int gcd, f;
1742 aff1 = isl_aff_cow(aff1);
1743 if (!aff1 || !aff2)
1744 goto error;
1746 aff1->v = isl_vec_cow(aff1->v);
1747 if (!aff1->v)
1748 goto error;
1750 isl_int_init(gcd);
1751 isl_int_init(f);
1752 isl_int_gcd(gcd, aff1->v->el[0], aff2->v->el[0]);
1753 isl_int_divexact(f, aff2->v->el[0], gcd);
1754 isl_seq_scale(aff1->v->el + 1, aff1->v->el + 1, f, aff1->v->size - 1);
1755 isl_int_divexact(f, aff1->v->el[0], gcd);
1756 isl_seq_addmul(aff1->v->el + 1, f, aff2->v->el + 1, aff1->v->size - 1);
1757 isl_int_divexact(f, aff2->v->el[0], gcd);
1758 isl_int_mul(aff1->v->el[0], aff1->v->el[0], f);
1759 isl_int_clear(f);
1760 isl_int_clear(gcd);
1762 isl_aff_free(aff2);
1763 return aff1;
1764 error:
1765 isl_aff_free(aff1);
1766 isl_aff_free(aff2);
1767 return NULL;
1770 /* Return the sum of "aff1" and "aff2".
1772 * If either of the two is NaN, then the result is NaN.
1774 __isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
1775 __isl_take isl_aff *aff2)
1777 isl_ctx *ctx;
1778 int *exp1 = NULL;
1779 int *exp2 = NULL;
1780 isl_mat *div;
1781 int n_div1, n_div2;
1783 if (!aff1 || !aff2)
1784 goto error;
1786 ctx = isl_aff_get_ctx(aff1);
1787 if (!isl_space_is_equal(aff1->ls->dim, aff2->ls->dim))
1788 isl_die(ctx, isl_error_invalid,
1789 "spaces don't match", goto error);
1791 if (isl_aff_is_nan(aff1)) {
1792 isl_aff_free(aff2);
1793 return aff1;
1795 if (isl_aff_is_nan(aff2)) {
1796 isl_aff_free(aff1);
1797 return aff2;
1800 n_div1 = isl_aff_dim(aff1, isl_dim_div);
1801 n_div2 = isl_aff_dim(aff2, isl_dim_div);
1802 if (n_div1 == 0 && n_div2 == 0)
1803 return add_expanded(aff1, aff2);
1805 exp1 = isl_alloc_array(ctx, int, n_div1);
1806 exp2 = isl_alloc_array(ctx, int, n_div2);
1807 if ((n_div1 && !exp1) || (n_div2 && !exp2))
1808 goto error;
1810 div = isl_merge_divs(aff1->ls->div, aff2->ls->div, exp1, exp2);
1811 aff1 = isl_aff_expand_divs(aff1, isl_mat_copy(div), exp1);
1812 aff2 = isl_aff_expand_divs(aff2, div, exp2);
1813 free(exp1);
1814 free(exp2);
1816 return add_expanded(aff1, aff2);
1817 error:
1818 free(exp1);
1819 free(exp2);
1820 isl_aff_free(aff1);
1821 isl_aff_free(aff2);
1822 return NULL;
1825 __isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
1826 __isl_take isl_aff *aff2)
1828 return isl_aff_add(aff1, isl_aff_neg(aff2));
1831 /* Return the result of scaling "aff" by a factor of "f".
1833 * As a special case, f * NaN = NaN.
1835 __isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f)
1837 isl_int gcd;
1839 if (!aff)
1840 return NULL;
1841 if (isl_aff_is_nan(aff))
1842 return aff;
1844 if (isl_int_is_one(f))
1845 return aff;
1847 aff = isl_aff_cow(aff);
1848 if (!aff)
1849 return NULL;
1850 aff->v = isl_vec_cow(aff->v);
1851 if (!aff->v)
1852 return isl_aff_free(aff);
1854 if (isl_int_is_pos(f) && isl_int_is_divisible_by(aff->v->el[0], f)) {
1855 isl_int_divexact(aff->v->el[0], aff->v->el[0], f);
1856 return aff;
1859 isl_int_init(gcd);
1860 isl_int_gcd(gcd, aff->v->el[0], f);
1861 isl_int_divexact(aff->v->el[0], aff->v->el[0], gcd);
1862 isl_int_divexact(gcd, f, gcd);
1863 isl_seq_scale(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
1864 isl_int_clear(gcd);
1866 return aff;
1869 /* Multiple "aff" by "v".
1871 __isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
1872 __isl_take isl_val *v)
1874 if (!aff || !v)
1875 goto error;
1877 if (isl_val_is_one(v)) {
1878 isl_val_free(v);
1879 return aff;
1882 if (!isl_val_is_rat(v))
1883 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1884 "expecting rational factor", goto error);
1886 aff = isl_aff_scale(aff, v->n);
1887 aff = isl_aff_scale_down(aff, v->d);
1889 isl_val_free(v);
1890 return aff;
1891 error:
1892 isl_aff_free(aff);
1893 isl_val_free(v);
1894 return NULL;
1897 /* Return the result of scaling "aff" down by a factor of "f".
1899 * As a special case, NaN/f = NaN.
1901 __isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f)
1903 isl_int gcd;
1905 if (!aff)
1906 return NULL;
1907 if (isl_aff_is_nan(aff))
1908 return aff;
1910 if (isl_int_is_one(f))
1911 return aff;
1913 aff = isl_aff_cow(aff);
1914 if (!aff)
1915 return NULL;
1917 if (isl_int_is_zero(f))
1918 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1919 "cannot scale down by zero", return isl_aff_free(aff));
1921 aff->v = isl_vec_cow(aff->v);
1922 if (!aff->v)
1923 return isl_aff_free(aff);
1925 isl_int_init(gcd);
1926 isl_seq_gcd(aff->v->el + 1, aff->v->size - 1, &gcd);
1927 isl_int_gcd(gcd, gcd, f);
1928 isl_seq_scale_down(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
1929 isl_int_divexact(gcd, f, gcd);
1930 isl_int_mul(aff->v->el[0], aff->v->el[0], gcd);
1931 isl_int_clear(gcd);
1933 return aff;
1936 /* Divide "aff" by "v".
1938 __isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff,
1939 __isl_take isl_val *v)
1941 if (!aff || !v)
1942 goto error;
1944 if (isl_val_is_one(v)) {
1945 isl_val_free(v);
1946 return aff;
1949 if (!isl_val_is_rat(v))
1950 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1951 "expecting rational factor", goto error);
1952 if (!isl_val_is_pos(v))
1953 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1954 "factor needs to be positive", goto error);
1956 aff = isl_aff_scale(aff, v->d);
1957 aff = isl_aff_scale_down(aff, v->n);
1959 isl_val_free(v);
1960 return aff;
1961 error:
1962 isl_aff_free(aff);
1963 isl_val_free(v);
1964 return NULL;
1967 __isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f)
1969 isl_int v;
1971 if (f == 1)
1972 return aff;
1974 isl_int_init(v);
1975 isl_int_set_ui(v, f);
1976 aff = isl_aff_scale_down(aff, v);
1977 isl_int_clear(v);
1979 return aff;
1982 __isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff,
1983 enum isl_dim_type type, unsigned pos, const char *s)
1985 aff = isl_aff_cow(aff);
1986 if (!aff)
1987 return NULL;
1988 if (type == isl_dim_out)
1989 isl_die(aff->v->ctx, isl_error_invalid,
1990 "cannot set name of output/set dimension",
1991 return isl_aff_free(aff));
1992 if (type == isl_dim_in)
1993 type = isl_dim_set;
1994 aff->ls = isl_local_space_set_dim_name(aff->ls, type, pos, s);
1995 if (!aff->ls)
1996 return isl_aff_free(aff);
1998 return aff;
2001 __isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff,
2002 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
2004 aff = isl_aff_cow(aff);
2005 if (!aff)
2006 goto error;
2007 if (type == isl_dim_out)
2008 isl_die(aff->v->ctx, isl_error_invalid,
2009 "cannot set name of output/set dimension",
2010 goto error);
2011 if (type == isl_dim_in)
2012 type = isl_dim_set;
2013 aff->ls = isl_local_space_set_dim_id(aff->ls, type, pos, id);
2014 if (!aff->ls)
2015 return isl_aff_free(aff);
2017 return aff;
2018 error:
2019 isl_id_free(id);
2020 isl_aff_free(aff);
2021 return NULL;
2024 /* Replace the identifier of the input tuple of "aff" by "id".
2025 * type is currently required to be equal to isl_dim_in
2027 __isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff,
2028 enum isl_dim_type type, __isl_take isl_id *id)
2030 aff = isl_aff_cow(aff);
2031 if (!aff)
2032 goto error;
2033 if (type != isl_dim_out)
2034 isl_die(aff->v->ctx, isl_error_invalid,
2035 "cannot only set id of input tuple", goto error);
2036 aff->ls = isl_local_space_set_tuple_id(aff->ls, isl_dim_set, id);
2037 if (!aff->ls)
2038 return isl_aff_free(aff);
2040 return aff;
2041 error:
2042 isl_id_free(id);
2043 isl_aff_free(aff);
2044 return NULL;
2047 /* Exploit the equalities in "eq" to simplify the affine expression
2048 * and the expressions of the integer divisions in the local space.
2049 * The integer divisions in this local space are assumed to appear
2050 * as regular dimensions in "eq".
2052 static __isl_give isl_aff *isl_aff_substitute_equalities_lifted(
2053 __isl_take isl_aff *aff, __isl_take isl_basic_set *eq)
2055 int i, j;
2056 unsigned total;
2057 unsigned n_div;
2059 if (!eq)
2060 goto error;
2061 if (eq->n_eq == 0) {
2062 isl_basic_set_free(eq);
2063 return aff;
2066 aff = isl_aff_cow(aff);
2067 if (!aff)
2068 goto error;
2070 aff->ls = isl_local_space_substitute_equalities(aff->ls,
2071 isl_basic_set_copy(eq));
2072 aff->v = isl_vec_cow(aff->v);
2073 if (!aff->ls || !aff->v)
2074 goto error;
2076 total = 1 + isl_space_dim(eq->dim, isl_dim_all);
2077 n_div = eq->n_div;
2078 for (i = 0; i < eq->n_eq; ++i) {
2079 j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
2080 if (j < 0 || j == 0 || j >= total)
2081 continue;
2083 isl_seq_elim(aff->v->el + 1, eq->eq[i], j, total,
2084 &aff->v->el[0]);
2087 isl_basic_set_free(eq);
2088 aff = isl_aff_normalize(aff);
2089 return aff;
2090 error:
2091 isl_basic_set_free(eq);
2092 isl_aff_free(aff);
2093 return NULL;
2096 /* Exploit the equalities in "eq" to simplify the affine expression
2097 * and the expressions of the integer divisions in the local space.
2099 __isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff,
2100 __isl_take isl_basic_set *eq)
2102 int n_div;
2104 if (!aff || !eq)
2105 goto error;
2106 n_div = isl_local_space_dim(aff->ls, isl_dim_div);
2107 if (n_div > 0)
2108 eq = isl_basic_set_add_dims(eq, isl_dim_set, n_div);
2109 return isl_aff_substitute_equalities_lifted(aff, eq);
2110 error:
2111 isl_basic_set_free(eq);
2112 isl_aff_free(aff);
2113 return NULL;
2116 /* Look for equalities among the variables shared by context and aff
2117 * and the integer divisions of aff, if any.
2118 * The equalities are then used to eliminate coefficients and/or integer
2119 * divisions from aff.
2121 __isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
2122 __isl_take isl_set *context)
2124 isl_basic_set *hull;
2125 int n_div;
2127 if (!aff)
2128 goto error;
2129 n_div = isl_local_space_dim(aff->ls, isl_dim_div);
2130 if (n_div > 0) {
2131 isl_basic_set *bset;
2132 isl_local_space *ls;
2133 context = isl_set_add_dims(context, isl_dim_set, n_div);
2134 ls = isl_aff_get_domain_local_space(aff);
2135 bset = isl_basic_set_from_local_space(ls);
2136 bset = isl_basic_set_lift(bset);
2137 bset = isl_basic_set_flatten(bset);
2138 context = isl_set_intersect(context,
2139 isl_set_from_basic_set(bset));
2142 hull = isl_set_affine_hull(context);
2143 return isl_aff_substitute_equalities_lifted(aff, hull);
2144 error:
2145 isl_aff_free(aff);
2146 isl_set_free(context);
2147 return NULL;
2150 __isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
2151 __isl_take isl_set *context)
2153 isl_set *dom_context = isl_set_universe(isl_aff_get_domain_space(aff));
2154 dom_context = isl_set_intersect_params(dom_context, context);
2155 return isl_aff_gist(aff, dom_context);
2158 /* Return a basic set containing those elements in the space
2159 * of aff where it is positive. "rational" should not be set.
2161 * If "aff" is NaN, then it is not positive.
2163 static __isl_give isl_basic_set *aff_pos_basic_set(__isl_take isl_aff *aff,
2164 int rational)
2166 isl_constraint *ineq;
2167 isl_basic_set *bset;
2168 isl_val *c;
2170 if (!aff)
2171 return NULL;
2172 if (isl_aff_is_nan(aff)) {
2173 isl_space *space = isl_aff_get_domain_space(aff);
2174 isl_aff_free(aff);
2175 return isl_basic_set_empty(space);
2177 if (rational)
2178 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
2179 "rational sets not supported", goto error);
2181 ineq = isl_inequality_from_aff(aff);
2182 c = isl_constraint_get_constant_val(ineq);
2183 c = isl_val_sub_ui(c, 1);
2184 ineq = isl_constraint_set_constant_val(ineq, c);
2186 bset = isl_basic_set_from_constraint(ineq);
2187 bset = isl_basic_set_simplify(bset);
2188 return bset;
2189 error:
2190 isl_aff_free(aff);
2191 return NULL;
2194 /* Return a basic set containing those elements in the space
2195 * of aff where it is non-negative.
2196 * If "rational" is set, then return a rational basic set.
2198 * If "aff" is NaN, then it is not non-negative (it's not negative either).
2200 static __isl_give isl_basic_set *aff_nonneg_basic_set(
2201 __isl_take isl_aff *aff, int rational)
2203 isl_constraint *ineq;
2204 isl_basic_set *bset;
2206 if (!aff)
2207 return NULL;
2208 if (isl_aff_is_nan(aff)) {
2209 isl_space *space = isl_aff_get_domain_space(aff);
2210 isl_aff_free(aff);
2211 return isl_basic_set_empty(space);
2214 ineq = isl_inequality_from_aff(aff);
2216 bset = isl_basic_set_from_constraint(ineq);
2217 if (rational)
2218 bset = isl_basic_set_set_rational(bset);
2219 bset = isl_basic_set_simplify(bset);
2220 return bset;
2223 /* Return a basic set containing those elements in the space
2224 * of aff where it is non-negative.
2226 __isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff)
2228 return aff_nonneg_basic_set(aff, 0);
2231 /* Return a basic set containing those elements in the domain space
2232 * of "aff" where it is positive.
2234 __isl_give isl_basic_set *isl_aff_pos_basic_set(__isl_take isl_aff *aff)
2236 aff = isl_aff_add_constant_num_si(aff, -1);
2237 return isl_aff_nonneg_basic_set(aff);
2240 /* Return a basic set containing those elements in the domain space
2241 * of aff where it is negative.
2243 __isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff)
2245 aff = isl_aff_neg(aff);
2246 return isl_aff_pos_basic_set(aff);
2249 /* Return a basic set containing those elements in the space
2250 * of aff where it is zero.
2251 * If "rational" is set, then return a rational basic set.
2253 * If "aff" is NaN, then it is not zero.
2255 static __isl_give isl_basic_set *aff_zero_basic_set(__isl_take isl_aff *aff,
2256 int rational)
2258 isl_constraint *ineq;
2259 isl_basic_set *bset;
2261 if (!aff)
2262 return NULL;
2263 if (isl_aff_is_nan(aff)) {
2264 isl_space *space = isl_aff_get_domain_space(aff);
2265 isl_aff_free(aff);
2266 return isl_basic_set_empty(space);
2269 ineq = isl_equality_from_aff(aff);
2271 bset = isl_basic_set_from_constraint(ineq);
2272 if (rational)
2273 bset = isl_basic_set_set_rational(bset);
2274 bset = isl_basic_set_simplify(bset);
2275 return bset;
2278 /* Return a basic set containing those elements in the space
2279 * of aff where it is zero.
2281 __isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff)
2283 return aff_zero_basic_set(aff, 0);
2286 /* Return a basic set containing those elements in the shared space
2287 * of aff1 and aff2 where aff1 is greater than or equal to aff2.
2289 __isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1,
2290 __isl_take isl_aff *aff2)
2292 aff1 = isl_aff_sub(aff1, aff2);
2294 return isl_aff_nonneg_basic_set(aff1);
2297 /* Return a basic set containing those elements in the shared domain space
2298 * of "aff1" and "aff2" where "aff1" is greater than "aff2".
2300 __isl_give isl_basic_set *isl_aff_gt_basic_set(__isl_take isl_aff *aff1,
2301 __isl_take isl_aff *aff2)
2303 aff1 = isl_aff_sub(aff1, aff2);
2305 return isl_aff_pos_basic_set(aff1);
2308 /* Return a set containing those elements in the shared space
2309 * of aff1 and aff2 where aff1 is greater than or equal to aff2.
2311 __isl_give isl_set *isl_aff_ge_set(__isl_take isl_aff *aff1,
2312 __isl_take isl_aff *aff2)
2314 return isl_set_from_basic_set(isl_aff_ge_basic_set(aff1, aff2));
2317 /* Return a basic set containing those elements in the shared space
2318 * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
2320 __isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1,
2321 __isl_take isl_aff *aff2)
2323 return isl_aff_ge_basic_set(aff2, aff1);
2326 /* Return a basic set containing those elements in the shared domain space
2327 * of "aff1" and "aff2" where "aff1" is smaller than "aff2".
2329 __isl_give isl_basic_set *isl_aff_lt_basic_set(__isl_take isl_aff *aff1,
2330 __isl_take isl_aff *aff2)
2332 return isl_aff_gt_basic_set(aff2, aff1);
2335 /* Return a set containing those elements in the shared space
2336 * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
2338 __isl_give isl_set *isl_aff_le_set(__isl_take isl_aff *aff1,
2339 __isl_take isl_aff *aff2)
2341 return isl_aff_ge_set(aff2, aff1);
2344 /* Return a set containing those elements in the shared domain space
2345 * of "aff1" and "aff2" where "aff1" is smaller than "aff2".
2347 __isl_give isl_set *isl_aff_lt_set(__isl_take isl_aff *aff1,
2348 __isl_take isl_aff *aff2)
2350 return isl_set_from_basic_set(isl_aff_lt_basic_set(aff1, aff2));
2353 /* Return a basic set containing those elements in the shared space
2354 * of aff1 and aff2 where aff1 and aff2 are equal.
2356 __isl_give isl_basic_set *isl_aff_eq_basic_set(__isl_take isl_aff *aff1,
2357 __isl_take isl_aff *aff2)
2359 aff1 = isl_aff_sub(aff1, aff2);
2361 return isl_aff_zero_basic_set(aff1);
2364 /* Return a set containing those elements in the shared space
2365 * of aff1 and aff2 where aff1 and aff2 are equal.
2367 __isl_give isl_set *isl_aff_eq_set(__isl_take isl_aff *aff1,
2368 __isl_take isl_aff *aff2)
2370 return isl_set_from_basic_set(isl_aff_eq_basic_set(aff1, aff2));
2373 __isl_give isl_aff *isl_aff_add_on_domain(__isl_keep isl_set *dom,
2374 __isl_take isl_aff *aff1, __isl_take isl_aff *aff2)
2376 aff1 = isl_aff_add(aff1, aff2);
2377 aff1 = isl_aff_gist(aff1, isl_set_copy(dom));
2378 return aff1;
2381 int isl_aff_is_empty(__isl_keep isl_aff *aff)
2383 if (!aff)
2384 return -1;
2386 return 0;
2389 /* Check whether the given affine expression has non-zero coefficient
2390 * for any dimension in the given range or if any of these dimensions
2391 * appear with non-zero coefficients in any of the integer divisions
2392 * involved in the affine expression.
2394 isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff,
2395 enum isl_dim_type type, unsigned first, unsigned n)
2397 int i;
2398 isl_ctx *ctx;
2399 int *active = NULL;
2400 isl_bool involves = isl_bool_false;
2402 if (!aff)
2403 return isl_bool_error;
2404 if (n == 0)
2405 return isl_bool_false;
2407 ctx = isl_aff_get_ctx(aff);
2408 if (first + n > isl_aff_dim(aff, type))
2409 isl_die(ctx, isl_error_invalid,
2410 "range out of bounds", return isl_bool_error);
2412 active = isl_local_space_get_active(aff->ls, aff->v->el + 2);
2413 if (!active)
2414 goto error;
2416 first += isl_local_space_offset(aff->ls, type) - 1;
2417 for (i = 0; i < n; ++i)
2418 if (active[first + i]) {
2419 involves = isl_bool_true;
2420 break;
2423 free(active);
2425 return involves;
2426 error:
2427 free(active);
2428 return isl_bool_error;
2431 __isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
2432 enum isl_dim_type type, unsigned first, unsigned n)
2434 isl_ctx *ctx;
2436 if (!aff)
2437 return NULL;
2438 if (type == isl_dim_out)
2439 isl_die(aff->v->ctx, isl_error_invalid,
2440 "cannot drop output/set dimension",
2441 return isl_aff_free(aff));
2442 if (type == isl_dim_in)
2443 type = isl_dim_set;
2444 if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
2445 return aff;
2447 ctx = isl_aff_get_ctx(aff);
2448 if (first + n > isl_local_space_dim(aff->ls, type))
2449 isl_die(ctx, isl_error_invalid, "range out of bounds",
2450 return isl_aff_free(aff));
2452 aff = isl_aff_cow(aff);
2453 if (!aff)
2454 return NULL;
2456 aff->ls = isl_local_space_drop_dims(aff->ls, type, first, n);
2457 if (!aff->ls)
2458 return isl_aff_free(aff);
2460 first += 1 + isl_local_space_offset(aff->ls, type);
2461 aff->v = isl_vec_drop_els(aff->v, first, n);
2462 if (!aff->v)
2463 return isl_aff_free(aff);
2465 return aff;
2468 /* Project the domain of the affine expression onto its parameter space.
2469 * The affine expression may not involve any of the domain dimensions.
2471 __isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff)
2473 isl_space *space;
2474 unsigned n;
2475 int involves;
2477 n = isl_aff_dim(aff, isl_dim_in);
2478 involves = isl_aff_involves_dims(aff, isl_dim_in, 0, n);
2479 if (involves < 0)
2480 return isl_aff_free(aff);
2481 if (involves)
2482 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2483 "affine expression involves some of the domain dimensions",
2484 return isl_aff_free(aff));
2485 aff = isl_aff_drop_dims(aff, isl_dim_in, 0, n);
2486 space = isl_aff_get_domain_space(aff);
2487 space = isl_space_params(space);
2488 aff = isl_aff_reset_domain_space(aff, space);
2489 return aff;
2492 __isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
2493 enum isl_dim_type type, unsigned first, unsigned n)
2495 isl_ctx *ctx;
2497 if (!aff)
2498 return NULL;
2499 if (type == isl_dim_out)
2500 isl_die(aff->v->ctx, isl_error_invalid,
2501 "cannot insert output/set dimensions",
2502 return isl_aff_free(aff));
2503 if (type == isl_dim_in)
2504 type = isl_dim_set;
2505 if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
2506 return aff;
2508 ctx = isl_aff_get_ctx(aff);
2509 if (first > isl_local_space_dim(aff->ls, type))
2510 isl_die(ctx, isl_error_invalid, "position out of bounds",
2511 return isl_aff_free(aff));
2513 aff = isl_aff_cow(aff);
2514 if (!aff)
2515 return NULL;
2517 aff->ls = isl_local_space_insert_dims(aff->ls, type, first, n);
2518 if (!aff->ls)
2519 return isl_aff_free(aff);
2521 first += 1 + isl_local_space_offset(aff->ls, type);
2522 aff->v = isl_vec_insert_zero_els(aff->v, first, n);
2523 if (!aff->v)
2524 return isl_aff_free(aff);
2526 return aff;
2529 __isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
2530 enum isl_dim_type type, unsigned n)
2532 unsigned pos;
2534 pos = isl_aff_dim(aff, type);
2536 return isl_aff_insert_dims(aff, type, pos, n);
2539 __isl_give isl_pw_aff *isl_pw_aff_add_dims(__isl_take isl_pw_aff *pwaff,
2540 enum isl_dim_type type, unsigned n)
2542 unsigned pos;
2544 pos = isl_pw_aff_dim(pwaff, type);
2546 return isl_pw_aff_insert_dims(pwaff, type, pos, n);
2549 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "aff"
2550 * to dimensions of "dst_type" at "dst_pos".
2552 * We only support moving input dimensions to parameters and vice versa.
2554 __isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
2555 enum isl_dim_type dst_type, unsigned dst_pos,
2556 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
2558 unsigned g_dst_pos;
2559 unsigned g_src_pos;
2561 if (!aff)
2562 return NULL;
2563 if (n == 0 &&
2564 !isl_local_space_is_named_or_nested(aff->ls, src_type) &&
2565 !isl_local_space_is_named_or_nested(aff->ls, dst_type))
2566 return aff;
2568 if (dst_type == isl_dim_out || src_type == isl_dim_out)
2569 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2570 "cannot move output/set dimension",
2571 return isl_aff_free(aff));
2572 if (dst_type == isl_dim_div || src_type == isl_dim_div)
2573 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2574 "cannot move divs", return isl_aff_free(aff));
2575 if (dst_type == isl_dim_in)
2576 dst_type = isl_dim_set;
2577 if (src_type == isl_dim_in)
2578 src_type = isl_dim_set;
2580 if (src_pos + n > isl_local_space_dim(aff->ls, src_type))
2581 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2582 "range out of bounds", return isl_aff_free(aff));
2583 if (dst_type == src_type)
2584 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
2585 "moving dims within the same type not supported",
2586 return isl_aff_free(aff));
2588 aff = isl_aff_cow(aff);
2589 if (!aff)
2590 return NULL;
2592 g_src_pos = 1 + isl_local_space_offset(aff->ls, src_type) + src_pos;
2593 g_dst_pos = 1 + isl_local_space_offset(aff->ls, dst_type) + dst_pos;
2594 if (dst_type > src_type)
2595 g_dst_pos -= n;
2597 aff->v = isl_vec_move_els(aff->v, g_dst_pos, g_src_pos, n);
2598 aff->ls = isl_local_space_move_dims(aff->ls, dst_type, dst_pos,
2599 src_type, src_pos, n);
2600 if (!aff->v || !aff->ls)
2601 return isl_aff_free(aff);
2603 aff = sort_divs(aff);
2605 return aff;
2608 __isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
2610 isl_set *dom = isl_set_universe(isl_aff_get_domain_space(aff));
2611 return isl_pw_aff_alloc(dom, aff);
2614 #define isl_aff_involves_nan isl_aff_is_nan
2616 #undef PW
2617 #define PW isl_pw_aff
2618 #undef EL
2619 #define EL isl_aff
2620 #undef EL_IS_ZERO
2621 #define EL_IS_ZERO is_empty
2622 #undef ZERO
2623 #define ZERO empty
2624 #undef IS_ZERO
2625 #define IS_ZERO is_empty
2626 #undef FIELD
2627 #define FIELD aff
2628 #undef DEFAULT_IS_ZERO
2629 #define DEFAULT_IS_ZERO 0
2631 #define NO_EVAL
2632 #define NO_OPT
2633 #define NO_LIFT
2634 #define NO_MORPH
2636 #include <isl_pw_templ.c>
2637 #include <isl_pw_hash.c>
2638 #include <isl_pw_union_opt.c>
2640 #undef UNION
2641 #define UNION isl_union_pw_aff
2642 #undef PART
2643 #define PART isl_pw_aff
2644 #undef PARTS
2645 #define PARTS pw_aff
2647 #include <isl_union_single.c>
2648 #include <isl_union_neg.c>
2650 static __isl_give isl_set *align_params_pw_pw_set_and(
2651 __isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2,
2652 __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
2653 __isl_take isl_pw_aff *pwaff2))
2655 isl_bool equal_params;
2657 if (!pwaff1 || !pwaff2)
2658 goto error;
2659 equal_params = isl_space_has_equal_params(pwaff1->dim, pwaff2->dim);
2660 if (equal_params < 0)
2661 goto error;
2662 if (equal_params)
2663 return fn(pwaff1, pwaff2);
2664 if (!isl_space_has_named_params(pwaff1->dim) ||
2665 !isl_space_has_named_params(pwaff2->dim))
2666 isl_die(isl_pw_aff_get_ctx(pwaff1), isl_error_invalid,
2667 "unaligned unnamed parameters", goto error);
2668 pwaff1 = isl_pw_aff_align_params(pwaff1, isl_pw_aff_get_space(pwaff2));
2669 pwaff2 = isl_pw_aff_align_params(pwaff2, isl_pw_aff_get_space(pwaff1));
2670 return fn(pwaff1, pwaff2);
2671 error:
2672 isl_pw_aff_free(pwaff1);
2673 isl_pw_aff_free(pwaff2);
2674 return NULL;
2677 /* Align the parameters of the to isl_pw_aff arguments and
2678 * then apply a function "fn" on them that returns an isl_map.
2680 static __isl_give isl_map *align_params_pw_pw_map_and(
2681 __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
2682 __isl_give isl_map *(*fn)(__isl_take isl_pw_aff *pa1,
2683 __isl_take isl_pw_aff *pa2))
2685 isl_bool equal_params;
2687 if (!pa1 || !pa2)
2688 goto error;
2689 equal_params = isl_space_has_equal_params(pa1->dim, pa2->dim);
2690 if (equal_params < 0)
2691 goto error;
2692 if (equal_params)
2693 return fn(pa1, pa2);
2694 if (!isl_space_has_named_params(pa1->dim) ||
2695 !isl_space_has_named_params(pa2->dim))
2696 isl_die(isl_pw_aff_get_ctx(pa1), isl_error_invalid,
2697 "unaligned unnamed parameters", goto error);
2698 pa1 = isl_pw_aff_align_params(pa1, isl_pw_aff_get_space(pa2));
2699 pa2 = isl_pw_aff_align_params(pa2, isl_pw_aff_get_space(pa1));
2700 return fn(pa1, pa2);
2701 error:
2702 isl_pw_aff_free(pa1);
2703 isl_pw_aff_free(pa2);
2704 return NULL;
2707 /* Compute a piecewise quasi-affine expression with a domain that
2708 * is the union of those of pwaff1 and pwaff2 and such that on each
2709 * cell, the quasi-affine expression is the maximum of those of pwaff1
2710 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
2711 * cell, then the associated expression is the defined one.
2713 static __isl_give isl_pw_aff *pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
2714 __isl_take isl_pw_aff *pwaff2)
2716 return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_ge_set);
2719 __isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
2720 __isl_take isl_pw_aff *pwaff2)
2722 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
2723 &pw_aff_union_max);
2726 /* Compute a piecewise quasi-affine expression with a domain that
2727 * is the union of those of pwaff1 and pwaff2 and such that on each
2728 * cell, the quasi-affine expression is the minimum of those of pwaff1
2729 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
2730 * cell, then the associated expression is the defined one.
2732 static __isl_give isl_pw_aff *pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
2733 __isl_take isl_pw_aff *pwaff2)
2735 return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_le_set);
2738 __isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
2739 __isl_take isl_pw_aff *pwaff2)
2741 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
2742 &pw_aff_union_min);
2745 __isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
2746 __isl_take isl_pw_aff *pwaff2, int max)
2748 if (max)
2749 return isl_pw_aff_union_max(pwaff1, pwaff2);
2750 else
2751 return isl_pw_aff_union_min(pwaff1, pwaff2);
2754 /* Construct a map with as domain the domain of pwaff and
2755 * one-dimensional range corresponding to the affine expressions.
2757 static __isl_give isl_map *map_from_pw_aff(__isl_take isl_pw_aff *pwaff)
2759 int i;
2760 isl_space *dim;
2761 isl_map *map;
2763 if (!pwaff)
2764 return NULL;
2766 dim = isl_pw_aff_get_space(pwaff);
2767 map = isl_map_empty(dim);
2769 for (i = 0; i < pwaff->n; ++i) {
2770 isl_basic_map *bmap;
2771 isl_map *map_i;
2773 bmap = isl_basic_map_from_aff(isl_aff_copy(pwaff->p[i].aff));
2774 map_i = isl_map_from_basic_map(bmap);
2775 map_i = isl_map_intersect_domain(map_i,
2776 isl_set_copy(pwaff->p[i].set));
2777 map = isl_map_union_disjoint(map, map_i);
2780 isl_pw_aff_free(pwaff);
2782 return map;
2785 /* Construct a map with as domain the domain of pwaff and
2786 * one-dimensional range corresponding to the affine expressions.
2788 __isl_give isl_map *isl_map_from_pw_aff(__isl_take isl_pw_aff *pwaff)
2790 if (!pwaff)
2791 return NULL;
2792 if (isl_space_is_set(pwaff->dim))
2793 isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
2794 "space of input is not a map", goto error);
2795 return map_from_pw_aff(pwaff);
2796 error:
2797 isl_pw_aff_free(pwaff);
2798 return NULL;
2801 /* Construct a one-dimensional set with as parameter domain
2802 * the domain of pwaff and the single set dimension
2803 * corresponding to the affine expressions.
2805 __isl_give isl_set *isl_set_from_pw_aff(__isl_take isl_pw_aff *pwaff)
2807 if (!pwaff)
2808 return NULL;
2809 if (!isl_space_is_set(pwaff->dim))
2810 isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
2811 "space of input is not a set", goto error);
2812 return map_from_pw_aff(pwaff);
2813 error:
2814 isl_pw_aff_free(pwaff);
2815 return NULL;
2818 /* Return a set containing those elements in the domain
2819 * of "pwaff" where it satisfies "fn" (if complement is 0) or
2820 * does not satisfy "fn" (if complement is 1).
2822 * The pieces with a NaN never belong to the result since
2823 * NaN does not satisfy any property.
2825 static __isl_give isl_set *pw_aff_locus(__isl_take isl_pw_aff *pwaff,
2826 __isl_give isl_basic_set *(*fn)(__isl_take isl_aff *aff, int rational),
2827 int complement)
2829 int i;
2830 isl_set *set;
2832 if (!pwaff)
2833 return NULL;
2835 set = isl_set_empty(isl_pw_aff_get_domain_space(pwaff));
2837 for (i = 0; i < pwaff->n; ++i) {
2838 isl_basic_set *bset;
2839 isl_set *set_i, *locus;
2840 isl_bool rational;
2842 if (isl_aff_is_nan(pwaff->p[i].aff))
2843 continue;
2845 rational = isl_set_has_rational(pwaff->p[i].set);
2846 bset = fn(isl_aff_copy(pwaff->p[i].aff), rational);
2847 locus = isl_set_from_basic_set(bset);
2848 set_i = isl_set_copy(pwaff->p[i].set);
2849 if (complement)
2850 set_i = isl_set_subtract(set_i, locus);
2851 else
2852 set_i = isl_set_intersect(set_i, locus);
2853 set = isl_set_union_disjoint(set, set_i);
2856 isl_pw_aff_free(pwaff);
2858 return set;
2861 /* Return a set containing those elements in the domain
2862 * of "pa" where it is positive.
2864 __isl_give isl_set *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa)
2866 return pw_aff_locus(pa, &aff_pos_basic_set, 0);
2869 /* Return a set containing those elements in the domain
2870 * of pwaff where it is non-negative.
2872 __isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff)
2874 return pw_aff_locus(pwaff, &aff_nonneg_basic_set, 0);
2877 /* Return a set containing those elements in the domain
2878 * of pwaff where it is zero.
2880 __isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff)
2882 return pw_aff_locus(pwaff, &aff_zero_basic_set, 0);
2885 /* Return a set containing those elements in the domain
2886 * of pwaff where it is not zero.
2888 __isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff)
2890 return pw_aff_locus(pwaff, &aff_zero_basic_set, 1);
2893 /* Return a set containing those elements in the shared domain
2894 * of pwaff1 and pwaff2 where pwaff1 is greater than (or equal) to pwaff2.
2896 * We compute the difference on the shared domain and then construct
2897 * the set of values where this difference is non-negative.
2898 * If strict is set, we first subtract 1 from the difference.
2899 * If equal is set, we only return the elements where pwaff1 and pwaff2
2900 * are equal.
2902 static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1,
2903 __isl_take isl_pw_aff *pwaff2, int strict, int equal)
2905 isl_set *set1, *set2;
2907 set1 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff1));
2908 set2 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff2));
2909 set1 = isl_set_intersect(set1, set2);
2910 pwaff1 = isl_pw_aff_intersect_domain(pwaff1, isl_set_copy(set1));
2911 pwaff2 = isl_pw_aff_intersect_domain(pwaff2, isl_set_copy(set1));
2912 pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_neg(pwaff2));
2914 if (strict) {
2915 isl_space *dim = isl_set_get_space(set1);
2916 isl_aff *aff;
2917 aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
2918 aff = isl_aff_add_constant_si(aff, -1);
2919 pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_alloc(set1, aff));
2920 } else
2921 isl_set_free(set1);
2923 if (equal)
2924 return isl_pw_aff_zero_set(pwaff1);
2925 return isl_pw_aff_nonneg_set(pwaff1);
2928 /* Return a set containing those elements in the shared domain
2929 * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2.
2931 static __isl_give isl_set *pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
2932 __isl_take isl_pw_aff *pwaff2)
2934 return pw_aff_gte_set(pwaff1, pwaff2, 0, 1);
2937 __isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
2938 __isl_take isl_pw_aff *pwaff2)
2940 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_eq_set);
2943 /* Return a set containing those elements in the shared domain
2944 * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2.
2946 static __isl_give isl_set *pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
2947 __isl_take isl_pw_aff *pwaff2)
2949 return pw_aff_gte_set(pwaff1, pwaff2, 0, 0);
2952 __isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
2953 __isl_take isl_pw_aff *pwaff2)
2955 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ge_set);
2958 /* Return a set containing those elements in the shared domain
2959 * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2.
2961 static __isl_give isl_set *pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
2962 __isl_take isl_pw_aff *pwaff2)
2964 return pw_aff_gte_set(pwaff1, pwaff2, 1, 0);
2967 __isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
2968 __isl_take isl_pw_aff *pwaff2)
2970 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_gt_set);
2973 __isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
2974 __isl_take isl_pw_aff *pwaff2)
2976 return isl_pw_aff_ge_set(pwaff2, pwaff1);
2979 __isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
2980 __isl_take isl_pw_aff *pwaff2)
2982 return isl_pw_aff_gt_set(pwaff2, pwaff1);
2985 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
2986 * where the function values are ordered in the same way as "order",
2987 * which returns a set in the shared domain of its two arguments.
2988 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
2990 * Let "pa1" and "pa2" be defined on domains A and B respectively.
2991 * We first pull back the two functions such that they are defined on
2992 * the domain [A -> B]. Then we apply "order", resulting in a set
2993 * in the space [A -> B]. Finally, we unwrap this set to obtain
2994 * a map in the space A -> B.
2996 static __isl_give isl_map *isl_pw_aff_order_map_aligned(
2997 __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
2998 __isl_give isl_set *(*order)(__isl_take isl_pw_aff *pa1,
2999 __isl_take isl_pw_aff *pa2))
3001 isl_space *space1, *space2;
3002 isl_multi_aff *ma;
3003 isl_set *set;
3005 space1 = isl_space_domain(isl_pw_aff_get_space(pa1));
3006 space2 = isl_space_domain(isl_pw_aff_get_space(pa2));
3007 space1 = isl_space_map_from_domain_and_range(space1, space2);
3008 ma = isl_multi_aff_domain_map(isl_space_copy(space1));
3009 pa1 = isl_pw_aff_pullback_multi_aff(pa1, ma);
3010 ma = isl_multi_aff_range_map(space1);
3011 pa2 = isl_pw_aff_pullback_multi_aff(pa2, ma);
3012 set = order(pa1, pa2);
3014 return isl_set_unwrap(set);
3017 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3018 * where the function values are equal.
3019 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3021 static __isl_give isl_map *isl_pw_aff_eq_map_aligned(__isl_take isl_pw_aff *pa1,
3022 __isl_take isl_pw_aff *pa2)
3024 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_eq_set);
3027 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3028 * where the function values are equal.
3030 __isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1,
3031 __isl_take isl_pw_aff *pa2)
3033 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_eq_map_aligned);
3036 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3037 * where the function value of "pa1" is less than the function value of "pa2".
3038 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3040 static __isl_give isl_map *isl_pw_aff_lt_map_aligned(__isl_take isl_pw_aff *pa1,
3041 __isl_take isl_pw_aff *pa2)
3043 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_lt_set);
3046 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3047 * where the function value of "pa1" is less than the function value of "pa2".
3049 __isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1,
3050 __isl_take isl_pw_aff *pa2)
3052 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_lt_map_aligned);
3055 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3056 * where the function value of "pa1" is greater than the function value
3057 * of "pa2".
3058 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3060 static __isl_give isl_map *isl_pw_aff_gt_map_aligned(__isl_take isl_pw_aff *pa1,
3061 __isl_take isl_pw_aff *pa2)
3063 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_gt_set);
3066 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3067 * where the function value of "pa1" is greater than the function value
3068 * of "pa2".
3070 __isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1,
3071 __isl_take isl_pw_aff *pa2)
3073 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_gt_map_aligned);
3076 /* Return a set containing those elements in the shared domain
3077 * of the elements of list1 and list2 where each element in list1
3078 * has the relation specified by "fn" with each element in list2.
3080 static __isl_give isl_set *pw_aff_list_set(__isl_take isl_pw_aff_list *list1,
3081 __isl_take isl_pw_aff_list *list2,
3082 __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
3083 __isl_take isl_pw_aff *pwaff2))
3085 int i, j;
3086 isl_ctx *ctx;
3087 isl_set *set;
3089 if (!list1 || !list2)
3090 goto error;
3092 ctx = isl_pw_aff_list_get_ctx(list1);
3093 if (list1->n < 1 || list2->n < 1)
3094 isl_die(ctx, isl_error_invalid,
3095 "list should contain at least one element", goto error);
3097 set = isl_set_universe(isl_pw_aff_get_domain_space(list1->p[0]));
3098 for (i = 0; i < list1->n; ++i)
3099 for (j = 0; j < list2->n; ++j) {
3100 isl_set *set_ij;
3102 set_ij = fn(isl_pw_aff_copy(list1->p[i]),
3103 isl_pw_aff_copy(list2->p[j]));
3104 set = isl_set_intersect(set, set_ij);
3107 isl_pw_aff_list_free(list1);
3108 isl_pw_aff_list_free(list2);
3109 return set;
3110 error:
3111 isl_pw_aff_list_free(list1);
3112 isl_pw_aff_list_free(list2);
3113 return NULL;
3116 /* Return a set containing those elements in the shared domain
3117 * of the elements of list1 and list2 where each element in list1
3118 * is equal to each element in list2.
3120 __isl_give isl_set *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1,
3121 __isl_take isl_pw_aff_list *list2)
3123 return pw_aff_list_set(list1, list2, &isl_pw_aff_eq_set);
3126 __isl_give isl_set *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1,
3127 __isl_take isl_pw_aff_list *list2)
3129 return pw_aff_list_set(list1, list2, &isl_pw_aff_ne_set);
3132 /* Return a set containing those elements in the shared domain
3133 * of the elements of list1 and list2 where each element in list1
3134 * is less than or equal to each element in list2.
3136 __isl_give isl_set *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1,
3137 __isl_take isl_pw_aff_list *list2)
3139 return pw_aff_list_set(list1, list2, &isl_pw_aff_le_set);
3142 __isl_give isl_set *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1,
3143 __isl_take isl_pw_aff_list *list2)
3145 return pw_aff_list_set(list1, list2, &isl_pw_aff_lt_set);
3148 __isl_give isl_set *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1,
3149 __isl_take isl_pw_aff_list *list2)
3151 return pw_aff_list_set(list1, list2, &isl_pw_aff_ge_set);
3154 __isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1,
3155 __isl_take isl_pw_aff_list *list2)
3157 return pw_aff_list_set(list1, list2, &isl_pw_aff_gt_set);
3161 /* Return a set containing those elements in the shared domain
3162 * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2.
3164 static __isl_give isl_set *pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
3165 __isl_take isl_pw_aff *pwaff2)
3167 isl_set *set_lt, *set_gt;
3169 set_lt = isl_pw_aff_lt_set(isl_pw_aff_copy(pwaff1),
3170 isl_pw_aff_copy(pwaff2));
3171 set_gt = isl_pw_aff_gt_set(pwaff1, pwaff2);
3172 return isl_set_union_disjoint(set_lt, set_gt);
3175 __isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
3176 __isl_take isl_pw_aff *pwaff2)
3178 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ne_set);
3181 __isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
3182 isl_int v)
3184 int i;
3186 if (isl_int_is_one(v))
3187 return pwaff;
3188 if (!isl_int_is_pos(v))
3189 isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
3190 "factor needs to be positive",
3191 return isl_pw_aff_free(pwaff));
3192 pwaff = isl_pw_aff_cow(pwaff);
3193 if (!pwaff)
3194 return NULL;
3195 if (pwaff->n == 0)
3196 return pwaff;
3198 for (i = 0; i < pwaff->n; ++i) {
3199 pwaff->p[i].aff = isl_aff_scale_down(pwaff->p[i].aff, v);
3200 if (!pwaff->p[i].aff)
3201 return isl_pw_aff_free(pwaff);
3204 return pwaff;
3207 __isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff)
3209 int i;
3211 pwaff = isl_pw_aff_cow(pwaff);
3212 if (!pwaff)
3213 return NULL;
3214 if (pwaff->n == 0)
3215 return pwaff;
3217 for (i = 0; i < pwaff->n; ++i) {
3218 pwaff->p[i].aff = isl_aff_floor(pwaff->p[i].aff);
3219 if (!pwaff->p[i].aff)
3220 return isl_pw_aff_free(pwaff);
3223 return pwaff;
3226 __isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff)
3228 int i;
3230 pwaff = isl_pw_aff_cow(pwaff);
3231 if (!pwaff)
3232 return NULL;
3233 if (pwaff->n == 0)
3234 return pwaff;
3236 for (i = 0; i < pwaff->n; ++i) {
3237 pwaff->p[i].aff = isl_aff_ceil(pwaff->p[i].aff);
3238 if (!pwaff->p[i].aff)
3239 return isl_pw_aff_free(pwaff);
3242 return pwaff;
3245 /* Assuming that "cond1" and "cond2" are disjoint,
3246 * return an affine expression that is equal to pwaff1 on cond1
3247 * and to pwaff2 on cond2.
3249 static __isl_give isl_pw_aff *isl_pw_aff_select(
3250 __isl_take isl_set *cond1, __isl_take isl_pw_aff *pwaff1,
3251 __isl_take isl_set *cond2, __isl_take isl_pw_aff *pwaff2)
3253 pwaff1 = isl_pw_aff_intersect_domain(pwaff1, cond1);
3254 pwaff2 = isl_pw_aff_intersect_domain(pwaff2, cond2);
3256 return isl_pw_aff_add_disjoint(pwaff1, pwaff2);
3259 /* Return an affine expression that is equal to pwaff_true for elements
3260 * where "cond" is non-zero and to pwaff_false for elements where "cond"
3261 * is zero.
3262 * That is, return cond ? pwaff_true : pwaff_false;
3264 * If "cond" involves and NaN, then we conservatively return a NaN
3265 * on its entire domain. In principle, we could consider the pieces
3266 * where it is NaN separately from those where it is not.
3268 * If "pwaff_true" and "pwaff_false" are obviously equal to each other,
3269 * then only use the domain of "cond" to restrict the domain.
3271 __isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond,
3272 __isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false)
3274 isl_set *cond_true, *cond_false;
3275 isl_bool equal;
3277 if (!cond)
3278 goto error;
3279 if (isl_pw_aff_involves_nan(cond)) {
3280 isl_space *space = isl_pw_aff_get_domain_space(cond);
3281 isl_local_space *ls = isl_local_space_from_space(space);
3282 isl_pw_aff_free(cond);
3283 isl_pw_aff_free(pwaff_true);
3284 isl_pw_aff_free(pwaff_false);
3285 return isl_pw_aff_nan_on_domain(ls);
3288 pwaff_true = isl_pw_aff_align_params(pwaff_true,
3289 isl_pw_aff_get_space(pwaff_false));
3290 pwaff_false = isl_pw_aff_align_params(pwaff_false,
3291 isl_pw_aff_get_space(pwaff_true));
3292 equal = isl_pw_aff_plain_is_equal(pwaff_true, pwaff_false);
3293 if (equal < 0)
3294 goto error;
3295 if (equal) {
3296 isl_set *dom;
3298 dom = isl_set_coalesce(isl_pw_aff_domain(cond));
3299 isl_pw_aff_free(pwaff_false);
3300 return isl_pw_aff_intersect_domain(pwaff_true, dom);
3303 cond_true = isl_pw_aff_non_zero_set(isl_pw_aff_copy(cond));
3304 cond_false = isl_pw_aff_zero_set(cond);
3305 return isl_pw_aff_select(cond_true, pwaff_true,
3306 cond_false, pwaff_false);
3307 error:
3308 isl_pw_aff_free(cond);
3309 isl_pw_aff_free(pwaff_true);
3310 isl_pw_aff_free(pwaff_false);
3311 return NULL;
3314 isl_bool isl_aff_is_cst(__isl_keep isl_aff *aff)
3316 if (!aff)
3317 return isl_bool_error;
3319 return isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2) == -1;
3322 /* Check whether pwaff is a piecewise constant.
3324 isl_bool isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff)
3326 int i;
3328 if (!pwaff)
3329 return isl_bool_error;
3331 for (i = 0; i < pwaff->n; ++i) {
3332 isl_bool is_cst = isl_aff_is_cst(pwaff->p[i].aff);
3333 if (is_cst < 0 || !is_cst)
3334 return is_cst;
3337 return isl_bool_true;
3340 /* Are all elements of "mpa" piecewise constants?
3342 isl_bool isl_multi_pw_aff_is_cst(__isl_keep isl_multi_pw_aff *mpa)
3344 int i;
3346 if (!mpa)
3347 return isl_bool_error;
3349 for (i = 0; i < mpa->n; ++i) {
3350 isl_bool is_cst = isl_pw_aff_is_cst(mpa->p[i]);
3351 if (is_cst < 0 || !is_cst)
3352 return is_cst;
3355 return isl_bool_true;
3358 /* Return the product of "aff1" and "aff2".
3360 * If either of the two is NaN, then the result is NaN.
3362 * Otherwise, at least one of "aff1" or "aff2" needs to be a constant.
3364 __isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1,
3365 __isl_take isl_aff *aff2)
3367 if (!aff1 || !aff2)
3368 goto error;
3370 if (isl_aff_is_nan(aff1)) {
3371 isl_aff_free(aff2);
3372 return aff1;
3374 if (isl_aff_is_nan(aff2)) {
3375 isl_aff_free(aff1);
3376 return aff2;
3379 if (!isl_aff_is_cst(aff2) && isl_aff_is_cst(aff1))
3380 return isl_aff_mul(aff2, aff1);
3382 if (!isl_aff_is_cst(aff2))
3383 isl_die(isl_aff_get_ctx(aff1), isl_error_invalid,
3384 "at least one affine expression should be constant",
3385 goto error);
3387 aff1 = isl_aff_cow(aff1);
3388 if (!aff1 || !aff2)
3389 goto error;
3391 aff1 = isl_aff_scale(aff1, aff2->v->el[1]);
3392 aff1 = isl_aff_scale_down(aff1, aff2->v->el[0]);
3394 isl_aff_free(aff2);
3395 return aff1;
3396 error:
3397 isl_aff_free(aff1);
3398 isl_aff_free(aff2);
3399 return NULL;
3402 /* Divide "aff1" by "aff2", assuming "aff2" is a constant.
3404 * If either of the two is NaN, then the result is NaN.
3406 __isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
3407 __isl_take isl_aff *aff2)
3409 int is_cst;
3410 int neg;
3412 if (!aff1 || !aff2)
3413 goto error;
3415 if (isl_aff_is_nan(aff1)) {
3416 isl_aff_free(aff2);
3417 return aff1;
3419 if (isl_aff_is_nan(aff2)) {
3420 isl_aff_free(aff1);
3421 return aff2;
3424 is_cst = isl_aff_is_cst(aff2);
3425 if (is_cst < 0)
3426 goto error;
3427 if (!is_cst)
3428 isl_die(isl_aff_get_ctx(aff2), isl_error_invalid,
3429 "second argument should be a constant", goto error);
3431 if (!aff2)
3432 goto error;
3434 neg = isl_int_is_neg(aff2->v->el[1]);
3435 if (neg) {
3436 isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
3437 isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
3440 aff1 = isl_aff_scale(aff1, aff2->v->el[0]);
3441 aff1 = isl_aff_scale_down(aff1, aff2->v->el[1]);
3443 if (neg) {
3444 isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
3445 isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
3448 isl_aff_free(aff2);
3449 return aff1;
3450 error:
3451 isl_aff_free(aff1);
3452 isl_aff_free(aff2);
3453 return NULL;
3456 static __isl_give isl_pw_aff *pw_aff_add(__isl_take isl_pw_aff *pwaff1,
3457 __isl_take isl_pw_aff *pwaff2)
3459 return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_add);
3462 __isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1,
3463 __isl_take isl_pw_aff *pwaff2)
3465 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_add);
3468 __isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
3469 __isl_take isl_pw_aff *pwaff2)
3471 return isl_pw_aff_union_add_(pwaff1, pwaff2);
3474 static __isl_give isl_pw_aff *pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
3475 __isl_take isl_pw_aff *pwaff2)
3477 return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_mul);
3480 __isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
3481 __isl_take isl_pw_aff *pwaff2)
3483 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_mul);
3486 static __isl_give isl_pw_aff *pw_aff_div(__isl_take isl_pw_aff *pa1,
3487 __isl_take isl_pw_aff *pa2)
3489 return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div);
3492 /* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant.
3494 __isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
3495 __isl_take isl_pw_aff *pa2)
3497 int is_cst;
3499 is_cst = isl_pw_aff_is_cst(pa2);
3500 if (is_cst < 0)
3501 goto error;
3502 if (!is_cst)
3503 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3504 "second argument should be a piecewise constant",
3505 goto error);
3506 return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_div);
3507 error:
3508 isl_pw_aff_free(pa1);
3509 isl_pw_aff_free(pa2);
3510 return NULL;
3513 /* Compute the quotient of the integer division of "pa1" by "pa2"
3514 * with rounding towards zero.
3515 * "pa2" is assumed to be a piecewise constant.
3517 * In particular, return
3519 * pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)
3522 __isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1,
3523 __isl_take isl_pw_aff *pa2)
3525 int is_cst;
3526 isl_set *cond;
3527 isl_pw_aff *f, *c;
3529 is_cst = isl_pw_aff_is_cst(pa2);
3530 if (is_cst < 0)
3531 goto error;
3532 if (!is_cst)
3533 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3534 "second argument should be a piecewise constant",
3535 goto error);
3537 pa1 = isl_pw_aff_div(pa1, pa2);
3539 cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1));
3540 f = isl_pw_aff_floor(isl_pw_aff_copy(pa1));
3541 c = isl_pw_aff_ceil(pa1);
3542 return isl_pw_aff_cond(isl_set_indicator_function(cond), f, c);
3543 error:
3544 isl_pw_aff_free(pa1);
3545 isl_pw_aff_free(pa2);
3546 return NULL;
3549 /* Compute the remainder of the integer division of "pa1" by "pa2"
3550 * with rounding towards zero.
3551 * "pa2" is assumed to be a piecewise constant.
3553 * In particular, return
3555 * pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2))
3558 __isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
3559 __isl_take isl_pw_aff *pa2)
3561 int is_cst;
3562 isl_pw_aff *res;
3564 is_cst = isl_pw_aff_is_cst(pa2);
3565 if (is_cst < 0)
3566 goto error;
3567 if (!is_cst)
3568 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3569 "second argument should be a piecewise constant",
3570 goto error);
3571 res = isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1), isl_pw_aff_copy(pa2));
3572 res = isl_pw_aff_mul(pa2, res);
3573 res = isl_pw_aff_sub(pa1, res);
3574 return res;
3575 error:
3576 isl_pw_aff_free(pa1);
3577 isl_pw_aff_free(pa2);
3578 return NULL;
3581 /* Does either of "pa1" or "pa2" involve any NaN2?
3583 static isl_bool either_involves_nan(__isl_keep isl_pw_aff *pa1,
3584 __isl_keep isl_pw_aff *pa2)
3586 isl_bool has_nan;
3588 has_nan = isl_pw_aff_involves_nan(pa1);
3589 if (has_nan < 0 || has_nan)
3590 return has_nan;
3591 return isl_pw_aff_involves_nan(pa2);
3594 /* Replace "pa1" and "pa2" (at least one of which involves a NaN)
3595 * by a NaN on their shared domain.
3597 * In principle, the result could be refined to only being NaN
3598 * on the parts of this domain where at least one of "pa1" or "pa2" is NaN.
3600 static __isl_give isl_pw_aff *replace_by_nan(__isl_take isl_pw_aff *pa1,
3601 __isl_take isl_pw_aff *pa2)
3603 isl_local_space *ls;
3604 isl_set *dom;
3605 isl_pw_aff *pa;
3607 dom = isl_set_intersect(isl_pw_aff_domain(pa1), isl_pw_aff_domain(pa2));
3608 ls = isl_local_space_from_space(isl_set_get_space(dom));
3609 pa = isl_pw_aff_nan_on_domain(ls);
3610 pa = isl_pw_aff_intersect_domain(pa, dom);
3612 return pa;
3615 static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1,
3616 __isl_take isl_pw_aff *pwaff2)
3618 isl_set *le;
3619 isl_set *dom;
3621 dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
3622 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
3623 le = isl_pw_aff_le_set(isl_pw_aff_copy(pwaff1),
3624 isl_pw_aff_copy(pwaff2));
3625 dom = isl_set_subtract(dom, isl_set_copy(le));
3626 return isl_pw_aff_select(le, pwaff1, dom, pwaff2);
3629 static __isl_give isl_pw_aff *pw_aff_max(__isl_take isl_pw_aff *pwaff1,
3630 __isl_take isl_pw_aff *pwaff2)
3632 isl_set *ge;
3633 isl_set *dom;
3635 dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
3636 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
3637 ge = isl_pw_aff_ge_set(isl_pw_aff_copy(pwaff1),
3638 isl_pw_aff_copy(pwaff2));
3639 dom = isl_set_subtract(dom, isl_set_copy(ge));
3640 return isl_pw_aff_select(ge, pwaff1, dom, pwaff2);
3643 /* Return an expression for the minimum (if "max" is not set) or
3644 * the maximum (if "max" is set) of "pa1" and "pa2".
3645 * If either expression involves any NaN, then return a NaN
3646 * on the shared domain as result.
3648 static __isl_give isl_pw_aff *pw_aff_min_max(__isl_take isl_pw_aff *pa1,
3649 __isl_take isl_pw_aff *pa2, int max)
3651 isl_bool has_nan;
3653 has_nan = either_involves_nan(pa1, pa2);
3654 if (has_nan < 0)
3655 pa1 = isl_pw_aff_free(pa1);
3656 else if (has_nan)
3657 return replace_by_nan(pa1, pa2);
3659 if (max)
3660 return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_max);
3661 else
3662 return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_min);
3665 /* Return an expression for the minimum of "pwaff1" and "pwaff2".
3667 __isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
3668 __isl_take isl_pw_aff *pwaff2)
3670 return pw_aff_min_max(pwaff1, pwaff2, 0);
3673 /* Return an expression for the maximum of "pwaff1" and "pwaff2".
3675 __isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
3676 __isl_take isl_pw_aff *pwaff2)
3678 return pw_aff_min_max(pwaff1, pwaff2, 1);
3681 static __isl_give isl_pw_aff *pw_aff_list_reduce(
3682 __isl_take isl_pw_aff_list *list,
3683 __isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pwaff1,
3684 __isl_take isl_pw_aff *pwaff2))
3686 int i;
3687 isl_ctx *ctx;
3688 isl_pw_aff *res;
3690 if (!list)
3691 return NULL;
3693 ctx = isl_pw_aff_list_get_ctx(list);
3694 if (list->n < 1)
3695 isl_die(ctx, isl_error_invalid,
3696 "list should contain at least one element", goto error);
3698 res = isl_pw_aff_copy(list->p[0]);
3699 for (i = 1; i < list->n; ++i)
3700 res = fn(res, isl_pw_aff_copy(list->p[i]));
3702 isl_pw_aff_list_free(list);
3703 return res;
3704 error:
3705 isl_pw_aff_list_free(list);
3706 return NULL;
3709 /* Return an isl_pw_aff that maps each element in the intersection of the
3710 * domains of the elements of list to the minimal corresponding affine
3711 * expression.
3713 __isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list)
3715 return pw_aff_list_reduce(list, &isl_pw_aff_min);
3718 /* Return an isl_pw_aff that maps each element in the intersection of the
3719 * domains of the elements of list to the maximal corresponding affine
3720 * expression.
3722 __isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list)
3724 return pw_aff_list_reduce(list, &isl_pw_aff_max);
3727 /* Mark the domains of "pwaff" as rational.
3729 __isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff)
3731 int i;
3733 pwaff = isl_pw_aff_cow(pwaff);
3734 if (!pwaff)
3735 return NULL;
3736 if (pwaff->n == 0)
3737 return pwaff;
3739 for (i = 0; i < pwaff->n; ++i) {
3740 pwaff->p[i].set = isl_set_set_rational(pwaff->p[i].set);
3741 if (!pwaff->p[i].set)
3742 return isl_pw_aff_free(pwaff);
3745 return pwaff;
3748 /* Mark the domains of the elements of "list" as rational.
3750 __isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational(
3751 __isl_take isl_pw_aff_list *list)
3753 int i, n;
3755 if (!list)
3756 return NULL;
3757 if (list->n == 0)
3758 return list;
3760 n = list->n;
3761 for (i = 0; i < n; ++i) {
3762 isl_pw_aff *pa;
3764 pa = isl_pw_aff_list_get_pw_aff(list, i);
3765 pa = isl_pw_aff_set_rational(pa);
3766 list = isl_pw_aff_list_set_pw_aff(list, i, pa);
3769 return list;
3772 /* Do the parameters of "aff" match those of "space"?
3774 isl_bool isl_aff_matching_params(__isl_keep isl_aff *aff,
3775 __isl_keep isl_space *space)
3777 isl_space *aff_space;
3778 isl_bool match;
3780 if (!aff || !space)
3781 return isl_bool_error;
3783 aff_space = isl_aff_get_domain_space(aff);
3785 match = isl_space_has_equal_params(space, aff_space);
3787 isl_space_free(aff_space);
3788 return match;
3791 /* Check that the domain space of "aff" matches "space".
3793 isl_stat isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
3794 __isl_keep isl_space *space)
3796 isl_space *aff_space;
3797 isl_bool match;
3799 if (!aff || !space)
3800 return isl_stat_error;
3802 aff_space = isl_aff_get_domain_space(aff);
3804 match = isl_space_has_equal_params(space, aff_space);
3805 if (match < 0)
3806 goto error;
3807 if (!match)
3808 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
3809 "parameters don't match", goto error);
3810 match = isl_space_tuple_is_equal(space, isl_dim_in,
3811 aff_space, isl_dim_set);
3812 if (match < 0)
3813 goto error;
3814 if (!match)
3815 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
3816 "domains don't match", goto error);
3817 isl_space_free(aff_space);
3818 return isl_stat_ok;
3819 error:
3820 isl_space_free(aff_space);
3821 return isl_stat_error;
3824 #undef BASE
3825 #define BASE aff
3826 #undef DOMBASE
3827 #define DOMBASE set
3828 #define NO_DOMAIN
3830 #include <isl_multi_templ.c>
3831 #include <isl_multi_apply_set.c>
3832 #include <isl_multi_cmp.c>
3833 #include <isl_multi_floor.c>
3834 #include <isl_multi_gist.c>
3836 #undef NO_DOMAIN
3838 /* Remove any internal structure of the domain of "ma".
3839 * If there is any such internal structure in the input,
3840 * then the name of the corresponding space is also removed.
3842 __isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
3843 __isl_take isl_multi_aff *ma)
3845 isl_space *space;
3847 if (!ma)
3848 return NULL;
3850 if (!ma->space->nested[0])
3851 return ma;
3853 space = isl_multi_aff_get_space(ma);
3854 space = isl_space_flatten_domain(space);
3855 ma = isl_multi_aff_reset_space(ma, space);
3857 return ma;
3860 /* Given a map space, return an isl_multi_aff that maps a wrapped copy
3861 * of the space to its domain.
3863 __isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space)
3865 int i, n_in;
3866 isl_local_space *ls;
3867 isl_multi_aff *ma;
3869 if (!space)
3870 return NULL;
3871 if (!isl_space_is_map(space))
3872 isl_die(isl_space_get_ctx(space), isl_error_invalid,
3873 "not a map space", goto error);
3875 n_in = isl_space_dim(space, isl_dim_in);
3876 space = isl_space_domain_map(space);
3878 ma = isl_multi_aff_alloc(isl_space_copy(space));
3879 if (n_in == 0) {
3880 isl_space_free(space);
3881 return ma;
3884 space = isl_space_domain(space);
3885 ls = isl_local_space_from_space(space);
3886 for (i = 0; i < n_in; ++i) {
3887 isl_aff *aff;
3889 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
3890 isl_dim_set, i);
3891 ma = isl_multi_aff_set_aff(ma, i, aff);
3893 isl_local_space_free(ls);
3894 return ma;
3895 error:
3896 isl_space_free(space);
3897 return NULL;
3900 /* Given a map space, return an isl_multi_aff that maps a wrapped copy
3901 * of the space to its range.
3903 __isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space)
3905 int i, n_in, n_out;
3906 isl_local_space *ls;
3907 isl_multi_aff *ma;
3909 if (!space)
3910 return NULL;
3911 if (!isl_space_is_map(space))
3912 isl_die(isl_space_get_ctx(space), isl_error_invalid,
3913 "not a map space", goto error);
3915 n_in = isl_space_dim(space, isl_dim_in);
3916 n_out = isl_space_dim(space, isl_dim_out);
3917 space = isl_space_range_map(space);
3919 ma = isl_multi_aff_alloc(isl_space_copy(space));
3920 if (n_out == 0) {
3921 isl_space_free(space);
3922 return ma;
3925 space = isl_space_domain(space);
3926 ls = isl_local_space_from_space(space);
3927 for (i = 0; i < n_out; ++i) {
3928 isl_aff *aff;
3930 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
3931 isl_dim_set, n_in + i);
3932 ma = isl_multi_aff_set_aff(ma, i, aff);
3934 isl_local_space_free(ls);
3935 return ma;
3936 error:
3937 isl_space_free(space);
3938 return NULL;
3941 /* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy
3942 * of the space to its range.
3944 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map(
3945 __isl_take isl_space *space)
3947 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_range_map(space));
3950 /* Given the space of a set and a range of set dimensions,
3951 * construct an isl_multi_aff that projects out those dimensions.
3953 __isl_give isl_multi_aff *isl_multi_aff_project_out_map(
3954 __isl_take isl_space *space, enum isl_dim_type type,
3955 unsigned first, unsigned n)
3957 int i, dim;
3958 isl_local_space *ls;
3959 isl_multi_aff *ma;
3961 if (!space)
3962 return NULL;
3963 if (!isl_space_is_set(space))
3964 isl_die(isl_space_get_ctx(space), isl_error_unsupported,
3965 "expecting set space", goto error);
3966 if (type != isl_dim_set)
3967 isl_die(isl_space_get_ctx(space), isl_error_invalid,
3968 "only set dimensions can be projected out", goto error);
3970 dim = isl_space_dim(space, isl_dim_set);
3971 if (first + n > dim)
3972 isl_die(isl_space_get_ctx(space), isl_error_invalid,
3973 "range out of bounds", goto error);
3975 space = isl_space_from_domain(space);
3976 space = isl_space_add_dims(space, isl_dim_out, dim - n);
3978 if (dim == n)
3979 return isl_multi_aff_alloc(space);
3981 ma = isl_multi_aff_alloc(isl_space_copy(space));
3982 space = isl_space_domain(space);
3983 ls = isl_local_space_from_space(space);
3985 for (i = 0; i < first; ++i) {
3986 isl_aff *aff;
3988 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
3989 isl_dim_set, i);
3990 ma = isl_multi_aff_set_aff(ma, i, aff);
3993 for (i = 0; i < dim - (first + n); ++i) {
3994 isl_aff *aff;
3996 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
3997 isl_dim_set, first + n + i);
3998 ma = isl_multi_aff_set_aff(ma, first + i, aff);
4001 isl_local_space_free(ls);
4002 return ma;
4003 error:
4004 isl_space_free(space);
4005 return NULL;
4008 /* Given the space of a set and a range of set dimensions,
4009 * construct an isl_pw_multi_aff that projects out those dimensions.
4011 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out_map(
4012 __isl_take isl_space *space, enum isl_dim_type type,
4013 unsigned first, unsigned n)
4015 isl_multi_aff *ma;
4017 ma = isl_multi_aff_project_out_map(space, type, first, n);
4018 return isl_pw_multi_aff_from_multi_aff(ma);
4021 /* Create an isl_pw_multi_aff with the given isl_multi_aff on a universe
4022 * domain.
4024 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_aff(
4025 __isl_take isl_multi_aff *ma)
4027 isl_set *dom = isl_set_universe(isl_multi_aff_get_domain_space(ma));
4028 return isl_pw_multi_aff_alloc(dom, ma);
4031 /* Create a piecewise multi-affine expression in the given space that maps each
4032 * input dimension to the corresponding output dimension.
4034 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
4035 __isl_take isl_space *space)
4037 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_identity(space));
4040 /* Exploit the equalities in "eq" to simplify the affine expressions.
4042 static __isl_give isl_multi_aff *isl_multi_aff_substitute_equalities(
4043 __isl_take isl_multi_aff *maff, __isl_take isl_basic_set *eq)
4045 int i;
4047 maff = isl_multi_aff_cow(maff);
4048 if (!maff || !eq)
4049 goto error;
4051 for (i = 0; i < maff->n; ++i) {
4052 maff->p[i] = isl_aff_substitute_equalities(maff->p[i],
4053 isl_basic_set_copy(eq));
4054 if (!maff->p[i])
4055 goto error;
4058 isl_basic_set_free(eq);
4059 return maff;
4060 error:
4061 isl_basic_set_free(eq);
4062 isl_multi_aff_free(maff);
4063 return NULL;
4066 __isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff,
4067 isl_int f)
4069 int i;
4071 maff = isl_multi_aff_cow(maff);
4072 if (!maff)
4073 return NULL;
4075 for (i = 0; i < maff->n; ++i) {
4076 maff->p[i] = isl_aff_scale(maff->p[i], f);
4077 if (!maff->p[i])
4078 return isl_multi_aff_free(maff);
4081 return maff;
4084 __isl_give isl_multi_aff *isl_multi_aff_add_on_domain(__isl_keep isl_set *dom,
4085 __isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2)
4087 maff1 = isl_multi_aff_add(maff1, maff2);
4088 maff1 = isl_multi_aff_gist(maff1, isl_set_copy(dom));
4089 return maff1;
4092 int isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff)
4094 if (!maff)
4095 return -1;
4097 return 0;
4100 /* Return the set of domain elements where "ma1" is lexicographically
4101 * smaller than or equal to "ma2".
4103 __isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1,
4104 __isl_take isl_multi_aff *ma2)
4106 return isl_multi_aff_lex_ge_set(ma2, ma1);
4109 /* Return the set of domain elements where "ma1" is lexicographically
4110 * smaller than "ma2".
4112 __isl_give isl_set *isl_multi_aff_lex_lt_set(__isl_take isl_multi_aff *ma1,
4113 __isl_take isl_multi_aff *ma2)
4115 return isl_multi_aff_lex_gt_set(ma2, ma1);
4118 /* Return the set of domain elements where "ma1" and "ma2"
4119 * satisfy "order".
4121 static __isl_give isl_set *isl_multi_aff_order_set(
4122 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2,
4123 __isl_give isl_map *order(__isl_take isl_space *set_space))
4125 isl_space *space;
4126 isl_map *map1, *map2;
4127 isl_map *map, *ge;
4129 map1 = isl_map_from_multi_aff(ma1);
4130 map2 = isl_map_from_multi_aff(ma2);
4131 map = isl_map_range_product(map1, map2);
4132 space = isl_space_range(isl_map_get_space(map));
4133 space = isl_space_domain(isl_space_unwrap(space));
4134 ge = order(space);
4135 map = isl_map_intersect_range(map, isl_map_wrap(ge));
4137 return isl_map_domain(map);
4140 /* Return the set of domain elements where "ma1" is lexicographically
4141 * greater than or equal to "ma2".
4143 __isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
4144 __isl_take isl_multi_aff *ma2)
4146 return isl_multi_aff_order_set(ma1, ma2, &isl_map_lex_ge);
4149 /* Return the set of domain elements where "ma1" is lexicographically
4150 * greater than "ma2".
4152 __isl_give isl_set *isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff *ma1,
4153 __isl_take isl_multi_aff *ma2)
4155 return isl_multi_aff_order_set(ma1, ma2, &isl_map_lex_gt);
4158 #undef PW
4159 #define PW isl_pw_multi_aff
4160 #undef EL
4161 #define EL isl_multi_aff
4162 #undef EL_IS_ZERO
4163 #define EL_IS_ZERO is_empty
4164 #undef ZERO
4165 #define ZERO empty
4166 #undef IS_ZERO
4167 #define IS_ZERO is_empty
4168 #undef FIELD
4169 #define FIELD maff
4170 #undef DEFAULT_IS_ZERO
4171 #define DEFAULT_IS_ZERO 0
4173 #define NO_SUB
4174 #define NO_EVAL
4175 #define NO_OPT
4176 #define NO_INVOLVES_DIMS
4177 #define NO_INSERT_DIMS
4178 #define NO_LIFT
4179 #define NO_MORPH
4181 #include <isl_pw_templ.c>
4182 #include <isl_pw_union_opt.c>
4184 #undef NO_SUB
4186 #undef UNION
4187 #define UNION isl_union_pw_multi_aff
4188 #undef PART
4189 #define PART isl_pw_multi_aff
4190 #undef PARTS
4191 #define PARTS pw_multi_aff
4193 #include <isl_union_multi.c>
4194 #include <isl_union_neg.c>
4196 static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmax(
4197 __isl_take isl_pw_multi_aff *pma1,
4198 __isl_take isl_pw_multi_aff *pma2)
4200 return isl_pw_multi_aff_union_opt_cmp(pma1, pma2,
4201 &isl_multi_aff_lex_ge_set);
4204 /* Given two piecewise multi affine expressions, return a piecewise
4205 * multi-affine expression defined on the union of the definition domains
4206 * of the inputs that is equal to the lexicographic maximum of the two
4207 * inputs on each cell. If only one of the two inputs is defined on
4208 * a given cell, then it is considered to be the maximum.
4210 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
4211 __isl_take isl_pw_multi_aff *pma1,
4212 __isl_take isl_pw_multi_aff *pma2)
4214 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4215 &pw_multi_aff_union_lexmax);
4218 static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmin(
4219 __isl_take isl_pw_multi_aff *pma1,
4220 __isl_take isl_pw_multi_aff *pma2)
4222 return isl_pw_multi_aff_union_opt_cmp(pma1, pma2,
4223 &isl_multi_aff_lex_le_set);
4226 /* Given two piecewise multi affine expressions, return a piecewise
4227 * multi-affine expression defined on the union of the definition domains
4228 * of the inputs that is equal to the lexicographic minimum of the two
4229 * inputs on each cell. If only one of the two inputs is defined on
4230 * a given cell, then it is considered to be the minimum.
4232 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
4233 __isl_take isl_pw_multi_aff *pma1,
4234 __isl_take isl_pw_multi_aff *pma2)
4236 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4237 &pw_multi_aff_union_lexmin);
4240 static __isl_give isl_pw_multi_aff *pw_multi_aff_add(
4241 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4243 return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
4244 &isl_multi_aff_add);
4247 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_add(
4248 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4250 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4251 &pw_multi_aff_add);
4254 static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
4255 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4257 return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
4258 &isl_multi_aff_sub);
4261 /* Subtract "pma2" from "pma1" and return the result.
4263 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
4264 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4266 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4267 &pw_multi_aff_sub);
4270 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
4271 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4273 return isl_pw_multi_aff_union_add_(pma1, pma2);
4276 /* Compute the sum of "upa1" and "upa2" on the union of their domains,
4277 * with the actual sum on the shared domain and
4278 * the defined expression on the symmetric difference of the domains.
4280 __isl_give isl_union_pw_aff *isl_union_pw_aff_union_add(
4281 __isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2)
4283 return isl_union_pw_aff_union_add_(upa1, upa2);
4286 /* Compute the sum of "upma1" and "upma2" on the union of their domains,
4287 * with the actual sum on the shared domain and
4288 * the defined expression on the symmetric difference of the domains.
4290 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_union_add(
4291 __isl_take isl_union_pw_multi_aff *upma1,
4292 __isl_take isl_union_pw_multi_aff *upma2)
4294 return isl_union_pw_multi_aff_union_add_(upma1, upma2);
4297 /* Given two piecewise multi-affine expressions A -> B and C -> D,
4298 * construct a piecewise multi-affine expression [A -> C] -> [B -> D].
4300 static __isl_give isl_pw_multi_aff *pw_multi_aff_product(
4301 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4303 int i, j, n;
4304 isl_space *space;
4305 isl_pw_multi_aff *res;
4307 if (!pma1 || !pma2)
4308 goto error;
4310 n = pma1->n * pma2->n;
4311 space = isl_space_product(isl_space_copy(pma1->dim),
4312 isl_space_copy(pma2->dim));
4313 res = isl_pw_multi_aff_alloc_size(space, n);
4315 for (i = 0; i < pma1->n; ++i) {
4316 for (j = 0; j < pma2->n; ++j) {
4317 isl_set *domain;
4318 isl_multi_aff *ma;
4320 domain = isl_set_product(isl_set_copy(pma1->p[i].set),
4321 isl_set_copy(pma2->p[j].set));
4322 ma = isl_multi_aff_product(
4323 isl_multi_aff_copy(pma1->p[i].maff),
4324 isl_multi_aff_copy(pma2->p[j].maff));
4325 res = isl_pw_multi_aff_add_piece(res, domain, ma);
4329 isl_pw_multi_aff_free(pma1);
4330 isl_pw_multi_aff_free(pma2);
4331 return res;
4332 error:
4333 isl_pw_multi_aff_free(pma1);
4334 isl_pw_multi_aff_free(pma2);
4335 return NULL;
4338 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_product(
4339 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4341 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4342 &pw_multi_aff_product);
4345 /* Construct a map mapping the domain of the piecewise multi-affine expression
4346 * to its range, with each dimension in the range equated to the
4347 * corresponding affine expression on its cell.
4349 * If the domain of "pma" is rational, then so is the constructed "map".
4351 __isl_give isl_map *isl_map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma)
4353 int i;
4354 isl_map *map;
4356 if (!pma)
4357 return NULL;
4359 map = isl_map_empty(isl_pw_multi_aff_get_space(pma));
4361 for (i = 0; i < pma->n; ++i) {
4362 isl_bool rational;
4363 isl_multi_aff *maff;
4364 isl_basic_map *bmap;
4365 isl_map *map_i;
4367 rational = isl_set_is_rational(pma->p[i].set);
4368 if (rational < 0)
4369 map = isl_map_free(map);
4370 maff = isl_multi_aff_copy(pma->p[i].maff);
4371 bmap = isl_basic_map_from_multi_aff2(maff, rational);
4372 map_i = isl_map_from_basic_map(bmap);
4373 map_i = isl_map_intersect_domain(map_i,
4374 isl_set_copy(pma->p[i].set));
4375 map = isl_map_union_disjoint(map, map_i);
4378 isl_pw_multi_aff_free(pma);
4379 return map;
4382 __isl_give isl_set *isl_set_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma)
4384 if (!pma)
4385 return NULL;
4387 if (!isl_space_is_set(pma->dim))
4388 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
4389 "isl_pw_multi_aff cannot be converted into an isl_set",
4390 goto error);
4392 return isl_map_from_pw_multi_aff(pma);
4393 error:
4394 isl_pw_multi_aff_free(pma);
4395 return NULL;
4398 /* Subtract the initial "n" elements in "ma" with coefficients in "c" and
4399 * denominator "denom".
4400 * "denom" is allowed to be negative, in which case the actual denominator
4401 * is -denom and the expressions are added instead.
4403 static __isl_give isl_aff *subtract_initial(__isl_take isl_aff *aff,
4404 __isl_keep isl_multi_aff *ma, int n, isl_int *c, isl_int denom)
4406 int i, first;
4407 int sign;
4408 isl_int d;
4410 first = isl_seq_first_non_zero(c, n);
4411 if (first == -1)
4412 return aff;
4414 sign = isl_int_sgn(denom);
4415 isl_int_init(d);
4416 isl_int_abs(d, denom);
4417 for (i = first; i < n; ++i) {
4418 isl_aff *aff_i;
4420 if (isl_int_is_zero(c[i]))
4421 continue;
4422 aff_i = isl_multi_aff_get_aff(ma, i);
4423 aff_i = isl_aff_scale(aff_i, c[i]);
4424 aff_i = isl_aff_scale_down(aff_i, d);
4425 if (sign >= 0)
4426 aff = isl_aff_sub(aff, aff_i);
4427 else
4428 aff = isl_aff_add(aff, aff_i);
4430 isl_int_clear(d);
4432 return aff;
4435 /* Extract an affine expression that expresses the output dimension "pos"
4436 * of "bmap" in terms of the parameters and input dimensions from
4437 * equality "eq".
4438 * Note that this expression may involve integer divisions defined
4439 * in terms of parameters and input dimensions.
4440 * The equality may also involve references to earlier (but not later)
4441 * output dimensions. These are replaced by the corresponding elements
4442 * in "ma".
4444 * If the equality is of the form
4446 * f(i) + h(j) + a x + g(i) = 0,
4448 * with f(i) a linear combinations of the parameters and input dimensions,
4449 * g(i) a linear combination of integer divisions defined in terms of the same
4450 * and h(j) a linear combinations of earlier output dimensions,
4451 * then the affine expression is
4453 * (-f(i) - g(i))/a - h(j)/a
4455 * If the equality is of the form
4457 * f(i) + h(j) - a x + g(i) = 0,
4459 * then the affine expression is
4461 * (f(i) + g(i))/a - h(j)/(-a)
4464 * If "div" refers to an integer division (i.e., it is smaller than
4465 * the number of integer divisions), then the equality constraint
4466 * does involve an integer division (the one at position "div") that
4467 * is defined in terms of output dimensions. However, this integer
4468 * division can be eliminated by exploiting a pair of constraints
4469 * x >= l and x <= l + n, with n smaller than the coefficient of "div"
4470 * in the equality constraint. "ineq" refers to inequality x >= l, i.e.,
4471 * -l + x >= 0.
4472 * In particular, let
4474 * x = e(i) + m floor(...)
4476 * with e(i) the expression derived above and floor(...) the integer
4477 * division involving output dimensions.
4478 * From
4480 * l <= x <= l + n,
4482 * we have
4484 * 0 <= x - l <= n
4486 * This means
4488 * e(i) + m floor(...) - l = (e(i) + m floor(...) - l) mod m
4489 * = (e(i) - l) mod m
4491 * Therefore,
4493 * x - l = (e(i) - l) mod m
4495 * or
4497 * x = ((e(i) - l) mod m) + l
4499 * The variable "shift" below contains the expression -l, which may
4500 * also involve a linear combination of earlier output dimensions.
4502 static __isl_give isl_aff *extract_aff_from_equality(
4503 __isl_keep isl_basic_map *bmap, int pos, int eq, int div, int ineq,
4504 __isl_keep isl_multi_aff *ma)
4506 unsigned o_out;
4507 unsigned n_div, n_out;
4508 isl_ctx *ctx;
4509 isl_local_space *ls;
4510 isl_aff *aff, *shift;
4511 isl_val *mod;
4513 ctx = isl_basic_map_get_ctx(bmap);
4514 ls = isl_basic_map_get_local_space(bmap);
4515 ls = isl_local_space_domain(ls);
4516 aff = isl_aff_alloc(isl_local_space_copy(ls));
4517 if (!aff)
4518 goto error;
4519 o_out = isl_basic_map_offset(bmap, isl_dim_out);
4520 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4521 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4522 if (isl_int_is_neg(bmap->eq[eq][o_out + pos])) {
4523 isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], o_out);
4524 isl_seq_cpy(aff->v->el + 1 + o_out,
4525 bmap->eq[eq] + o_out + n_out, n_div);
4526 } else {
4527 isl_seq_neg(aff->v->el + 1, bmap->eq[eq], o_out);
4528 isl_seq_neg(aff->v->el + 1 + o_out,
4529 bmap->eq[eq] + o_out + n_out, n_div);
4531 if (div < n_div)
4532 isl_int_set_si(aff->v->el[1 + o_out + div], 0);
4533 isl_int_abs(aff->v->el[0], bmap->eq[eq][o_out + pos]);
4534 aff = subtract_initial(aff, ma, pos, bmap->eq[eq] + o_out,
4535 bmap->eq[eq][o_out + pos]);
4536 if (div < n_div) {
4537 shift = isl_aff_alloc(isl_local_space_copy(ls));
4538 if (!shift)
4539 goto error;
4540 isl_seq_cpy(shift->v->el + 1, bmap->ineq[ineq], o_out);
4541 isl_seq_cpy(shift->v->el + 1 + o_out,
4542 bmap->ineq[ineq] + o_out + n_out, n_div);
4543 isl_int_set_si(shift->v->el[0], 1);
4544 shift = subtract_initial(shift, ma, pos,
4545 bmap->ineq[ineq] + o_out, ctx->negone);
4546 aff = isl_aff_add(aff, isl_aff_copy(shift));
4547 mod = isl_val_int_from_isl_int(ctx,
4548 bmap->eq[eq][o_out + n_out + div]);
4549 mod = isl_val_abs(mod);
4550 aff = isl_aff_mod_val(aff, mod);
4551 aff = isl_aff_sub(aff, shift);
4554 isl_local_space_free(ls);
4555 return aff;
4556 error:
4557 isl_local_space_free(ls);
4558 isl_aff_free(aff);
4559 return NULL;
4562 /* Given a basic map with output dimensions defined
4563 * in terms of the parameters input dimensions and earlier
4564 * output dimensions using an equality (and possibly a pair on inequalities),
4565 * extract an isl_aff that expresses output dimension "pos" in terms
4566 * of the parameters and input dimensions.
4567 * Note that this expression may involve integer divisions defined
4568 * in terms of parameters and input dimensions.
4569 * "ma" contains the expressions corresponding to earlier output dimensions.
4571 * This function shares some similarities with
4572 * isl_basic_map_has_defining_equality and isl_constraint_get_bound.
4574 static __isl_give isl_aff *extract_isl_aff_from_basic_map(
4575 __isl_keep isl_basic_map *bmap, int pos, __isl_keep isl_multi_aff *ma)
4577 int eq, div, ineq;
4578 isl_aff *aff;
4580 if (!bmap)
4581 return NULL;
4582 eq = isl_basic_map_output_defining_equality(bmap, pos, &div, &ineq);
4583 if (eq >= bmap->n_eq)
4584 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4585 "unable to find suitable equality", return NULL);
4586 aff = extract_aff_from_equality(bmap, pos, eq, div, ineq, ma);
4588 aff = isl_aff_remove_unused_divs(aff);
4589 return aff;
4592 /* Given a basic map where each output dimension is defined
4593 * in terms of the parameters and input dimensions using an equality,
4594 * extract an isl_multi_aff that expresses the output dimensions in terms
4595 * of the parameters and input dimensions.
4597 static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map(
4598 __isl_take isl_basic_map *bmap)
4600 int i;
4601 unsigned n_out;
4602 isl_multi_aff *ma;
4604 if (!bmap)
4605 return NULL;
4607 ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap));
4608 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4610 for (i = 0; i < n_out; ++i) {
4611 isl_aff *aff;
4613 aff = extract_isl_aff_from_basic_map(bmap, i, ma);
4614 ma = isl_multi_aff_set_aff(ma, i, aff);
4617 isl_basic_map_free(bmap);
4619 return ma;
4622 /* Given a basic set where each set dimension is defined
4623 * in terms of the parameters using an equality,
4624 * extract an isl_multi_aff that expresses the set dimensions in terms
4625 * of the parameters.
4627 __isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities(
4628 __isl_take isl_basic_set *bset)
4630 return extract_isl_multi_aff_from_basic_map(bset);
4633 /* Create an isl_pw_multi_aff that is equivalent to
4634 * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain).
4635 * The given basic map is such that each output dimension is defined
4636 * in terms of the parameters and input dimensions using an equality.
4638 * Since some applications expect the result of isl_pw_multi_aff_from_map
4639 * to only contain integer affine expressions, we compute the floor
4640 * of the expression before returning.
4642 * Remove all constraints involving local variables without
4643 * an explicit representation (resulting in the removal of those
4644 * local variables) prior to the actual extraction to ensure
4645 * that the local spaces in which the resulting affine expressions
4646 * are created do not contain any unknown local variables.
4647 * Removing such constraints is safe because constraints involving
4648 * unknown local variables are not used to determine whether
4649 * a basic map is obviously single-valued.
4651 static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map(
4652 __isl_take isl_set *domain, __isl_take isl_basic_map *bmap)
4654 isl_multi_aff *ma;
4656 bmap = isl_basic_map_drop_constraint_involving_unknown_divs(bmap);
4657 ma = extract_isl_multi_aff_from_basic_map(bmap);
4658 ma = isl_multi_aff_floor(ma);
4659 return isl_pw_multi_aff_alloc(domain, ma);
4662 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
4663 * This obviously only works if the input "map" is single-valued.
4664 * If so, we compute the lexicographic minimum of the image in the form
4665 * of an isl_pw_multi_aff. Since the image is unique, it is equal
4666 * to its lexicographic minimum.
4667 * If the input is not single-valued, we produce an error.
4669 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_base(
4670 __isl_take isl_map *map)
4672 int i;
4673 int sv;
4674 isl_pw_multi_aff *pma;
4676 sv = isl_map_is_single_valued(map);
4677 if (sv < 0)
4678 goto error;
4679 if (!sv)
4680 isl_die(isl_map_get_ctx(map), isl_error_invalid,
4681 "map is not single-valued", goto error);
4682 map = isl_map_make_disjoint(map);
4683 if (!map)
4684 return NULL;
4686 pma = isl_pw_multi_aff_empty(isl_map_get_space(map));
4688 for (i = 0; i < map->n; ++i) {
4689 isl_pw_multi_aff *pma_i;
4690 isl_basic_map *bmap;
4691 bmap = isl_basic_map_copy(map->p[i]);
4692 pma_i = isl_basic_map_lexmin_pw_multi_aff(bmap);
4693 pma = isl_pw_multi_aff_add_disjoint(pma, pma_i);
4696 isl_map_free(map);
4697 return pma;
4698 error:
4699 isl_map_free(map);
4700 return NULL;
4703 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
4704 * taking into account that the output dimension at position "d"
4705 * can be represented as
4707 * x = floor((e(...) + c1) / m)
4709 * given that constraint "i" is of the form
4711 * e(...) + c1 - m x >= 0
4714 * Let "map" be of the form
4716 * A -> B
4718 * We construct a mapping
4720 * A -> [A -> x = floor(...)]
4722 * apply that to the map, obtaining
4724 * [A -> x = floor(...)] -> B
4726 * and equate dimension "d" to x.
4727 * We then compute a isl_pw_multi_aff representation of the resulting map
4728 * and plug in the mapping above.
4730 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div(
4731 __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i)
4733 isl_ctx *ctx;
4734 isl_space *space;
4735 isl_local_space *ls;
4736 isl_multi_aff *ma;
4737 isl_aff *aff;
4738 isl_vec *v;
4739 isl_map *insert;
4740 int offset;
4741 int n;
4742 int n_in;
4743 isl_pw_multi_aff *pma;
4744 isl_bool is_set;
4746 is_set = isl_map_is_set(map);
4747 if (is_set < 0)
4748 goto error;
4750 offset = isl_basic_map_offset(hull, isl_dim_out);
4751 ctx = isl_map_get_ctx(map);
4752 space = isl_space_domain(isl_map_get_space(map));
4753 n_in = isl_space_dim(space, isl_dim_set);
4754 n = isl_space_dim(space, isl_dim_all);
4756 v = isl_vec_alloc(ctx, 1 + 1 + n);
4757 if (v) {
4758 isl_int_neg(v->el[0], hull->ineq[i][offset + d]);
4759 isl_seq_cpy(v->el + 1, hull->ineq[i], 1 + n);
4761 isl_basic_map_free(hull);
4763 ls = isl_local_space_from_space(isl_space_copy(space));
4764 aff = isl_aff_alloc_vec(ls, v);
4765 aff = isl_aff_floor(aff);
4766 if (is_set) {
4767 isl_space_free(space);
4768 ma = isl_multi_aff_from_aff(aff);
4769 } else {
4770 ma = isl_multi_aff_identity(isl_space_map_from_set(space));
4771 ma = isl_multi_aff_range_product(ma,
4772 isl_multi_aff_from_aff(aff));
4775 insert = isl_map_from_multi_aff(isl_multi_aff_copy(ma));
4776 map = isl_map_apply_domain(map, insert);
4777 map = isl_map_equate(map, isl_dim_in, n_in, isl_dim_out, d);
4778 pma = isl_pw_multi_aff_from_map(map);
4779 pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma);
4781 return pma;
4782 error:
4783 isl_map_free(map);
4784 isl_basic_map_free(hull);
4785 return NULL;
4788 /* Is constraint "c" of the form
4790 * e(...) + c1 - m x >= 0
4792 * or
4794 * -e(...) + c2 + m x >= 0
4796 * where m > 1 and e only depends on parameters and input dimemnsions?
4798 * "offset" is the offset of the output dimensions
4799 * "pos" is the position of output dimension x.
4801 static int is_potential_div_constraint(isl_int *c, int offset, int d, int total)
4803 if (isl_int_is_zero(c[offset + d]))
4804 return 0;
4805 if (isl_int_is_one(c[offset + d]))
4806 return 0;
4807 if (isl_int_is_negone(c[offset + d]))
4808 return 0;
4809 if (isl_seq_first_non_zero(c + offset, d) != -1)
4810 return 0;
4811 if (isl_seq_first_non_zero(c + offset + d + 1,
4812 total - (offset + d + 1)) != -1)
4813 return 0;
4814 return 1;
4817 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
4819 * As a special case, we first check if there is any pair of constraints,
4820 * shared by all the basic maps in "map" that force a given dimension
4821 * to be equal to the floor of some affine combination of the input dimensions.
4823 * In particular, if we can find two constraints
4825 * e(...) + c1 - m x >= 0 i.e., m x <= e(...) + c1
4827 * and
4829 * -e(...) + c2 + m x >= 0 i.e., m x >= e(...) - c2
4831 * where m > 1 and e only depends on parameters and input dimemnsions,
4832 * and such that
4834 * c1 + c2 < m i.e., -c2 >= c1 - (m - 1)
4836 * then we know that we can take
4838 * x = floor((e(...) + c1) / m)
4840 * without having to perform any computation.
4842 * Note that we know that
4844 * c1 + c2 >= 1
4846 * If c1 + c2 were 0, then we would have detected an equality during
4847 * simplification. If c1 + c2 were negative, then we would have detected
4848 * a contradiction.
4850 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_div(
4851 __isl_take isl_map *map)
4853 int d, dim;
4854 int i, j, n;
4855 int offset, total;
4856 isl_int sum;
4857 isl_basic_map *hull;
4859 hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
4860 if (!hull)
4861 goto error;
4863 isl_int_init(sum);
4864 dim = isl_map_dim(map, isl_dim_out);
4865 offset = isl_basic_map_offset(hull, isl_dim_out);
4866 total = 1 + isl_basic_map_total_dim(hull);
4867 n = hull->n_ineq;
4868 for (d = 0; d < dim; ++d) {
4869 for (i = 0; i < n; ++i) {
4870 if (!is_potential_div_constraint(hull->ineq[i],
4871 offset, d, total))
4872 continue;
4873 for (j = i + 1; j < n; ++j) {
4874 if (!isl_seq_is_neg(hull->ineq[i] + 1,
4875 hull->ineq[j] + 1, total - 1))
4876 continue;
4877 isl_int_add(sum, hull->ineq[i][0],
4878 hull->ineq[j][0]);
4879 if (isl_int_abs_lt(sum,
4880 hull->ineq[i][offset + d]))
4881 break;
4884 if (j >= n)
4885 continue;
4886 isl_int_clear(sum);
4887 if (isl_int_is_pos(hull->ineq[j][offset + d]))
4888 j = i;
4889 return pw_multi_aff_from_map_div(map, hull, d, j);
4892 isl_int_clear(sum);
4893 isl_basic_map_free(hull);
4894 return pw_multi_aff_from_map_base(map);
4895 error:
4896 isl_map_free(map);
4897 isl_basic_map_free(hull);
4898 return NULL;
4901 /* Given an affine expression
4903 * [A -> B] -> f(A,B)
4905 * construct an isl_multi_aff
4907 * [A -> B] -> B'
4909 * such that dimension "d" in B' is set to "aff" and the remaining
4910 * dimensions are set equal to the corresponding dimensions in B.
4911 * "n_in" is the dimension of the space A.
4912 * "n_out" is the dimension of the space B.
4914 * If "is_set" is set, then the affine expression is of the form
4916 * [B] -> f(B)
4918 * and we construct an isl_multi_aff
4920 * B -> B'
4922 static __isl_give isl_multi_aff *range_map(__isl_take isl_aff *aff, int d,
4923 unsigned n_in, unsigned n_out, int is_set)
4925 int i;
4926 isl_multi_aff *ma;
4927 isl_space *space, *space2;
4928 isl_local_space *ls;
4930 space = isl_aff_get_domain_space(aff);
4931 ls = isl_local_space_from_space(isl_space_copy(space));
4932 space2 = isl_space_copy(space);
4933 if (!is_set)
4934 space2 = isl_space_range(isl_space_unwrap(space2));
4935 space = isl_space_map_from_domain_and_range(space, space2);
4936 ma = isl_multi_aff_alloc(space);
4937 ma = isl_multi_aff_set_aff(ma, d, aff);
4939 for (i = 0; i < n_out; ++i) {
4940 if (i == d)
4941 continue;
4942 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
4943 isl_dim_set, n_in + i);
4944 ma = isl_multi_aff_set_aff(ma, i, aff);
4947 isl_local_space_free(ls);
4949 return ma;
4952 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
4953 * taking into account that the dimension at position "d" can be written as
4955 * x = m a + f(..) (1)
4957 * where m is equal to "gcd".
4958 * "i" is the index of the equality in "hull" that defines f(..).
4959 * In particular, the equality is of the form
4961 * f(..) - x + m g(existentials) = 0
4963 * or
4965 * -f(..) + x + m g(existentials) = 0
4967 * We basically plug (1) into "map", resulting in a map with "a"
4968 * in the range instead of "x". The corresponding isl_pw_multi_aff
4969 * defining "a" is then plugged back into (1) to obtain a definition for "x".
4971 * Specifically, given the input map
4973 * A -> B
4975 * We first wrap it into a set
4977 * [A -> B]
4979 * and define (1) on top of the corresponding space, resulting in "aff".
4980 * We use this to create an isl_multi_aff that maps the output position "d"
4981 * from "a" to "x", leaving all other (intput and output) dimensions unchanged.
4982 * We plug this into the wrapped map, unwrap the result and compute the
4983 * corresponding isl_pw_multi_aff.
4984 * The result is an expression
4986 * A -> T(A)
4988 * We adjust that to
4990 * A -> [A -> T(A)]
4992 * so that we can plug that into "aff", after extending the latter to
4993 * a mapping
4995 * [A -> B] -> B'
4998 * If "map" is actually a set, then there is no "A" space, meaning
4999 * that we do not need to perform any wrapping, and that the result
5000 * of the recursive call is of the form
5002 * [T]
5004 * which is plugged into a mapping of the form
5006 * B -> B'
5008 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
5009 __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i,
5010 isl_int gcd)
5012 isl_set *set;
5013 isl_space *space;
5014 isl_local_space *ls;
5015 isl_aff *aff;
5016 isl_multi_aff *ma;
5017 isl_pw_multi_aff *pma, *id;
5018 unsigned n_in;
5019 unsigned o_out;
5020 unsigned n_out;
5021 isl_bool is_set;
5023 is_set = isl_map_is_set(map);
5024 if (is_set < 0)
5025 goto error;
5027 n_in = isl_basic_map_dim(hull, isl_dim_in);
5028 n_out = isl_basic_map_dim(hull, isl_dim_out);
5029 o_out = isl_basic_map_offset(hull, isl_dim_out);
5031 if (is_set)
5032 set = map;
5033 else
5034 set = isl_map_wrap(map);
5035 space = isl_space_map_from_set(isl_set_get_space(set));
5036 ma = isl_multi_aff_identity(space);
5037 ls = isl_local_space_from_space(isl_set_get_space(set));
5038 aff = isl_aff_alloc(ls);
5039 if (aff) {
5040 isl_int_set_si(aff->v->el[0], 1);
5041 if (isl_int_is_one(hull->eq[i][o_out + d]))
5042 isl_seq_neg(aff->v->el + 1, hull->eq[i],
5043 aff->v->size - 1);
5044 else
5045 isl_seq_cpy(aff->v->el + 1, hull->eq[i],
5046 aff->v->size - 1);
5047 isl_int_set(aff->v->el[1 + o_out + d], gcd);
5049 ma = isl_multi_aff_set_aff(ma, n_in + d, isl_aff_copy(aff));
5050 set = isl_set_preimage_multi_aff(set, ma);
5052 ma = range_map(aff, d, n_in, n_out, is_set);
5054 if (is_set)
5055 map = set;
5056 else
5057 map = isl_set_unwrap(set);
5058 pma = isl_pw_multi_aff_from_map(map);
5060 if (!is_set) {
5061 space = isl_pw_multi_aff_get_domain_space(pma);
5062 space = isl_space_map_from_set(space);
5063 id = isl_pw_multi_aff_identity(space);
5064 pma = isl_pw_multi_aff_range_product(id, pma);
5066 id = isl_pw_multi_aff_from_multi_aff(ma);
5067 pma = isl_pw_multi_aff_pullback_pw_multi_aff(id, pma);
5069 isl_basic_map_free(hull);
5070 return pma;
5071 error:
5072 isl_map_free(map);
5073 isl_basic_map_free(hull);
5074 return NULL;
5077 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5078 * "hull" contains the equalities valid for "map".
5080 * Check if any of the output dimensions is "strided".
5081 * That is, we check if it can be written as
5083 * x = m a + f(..)
5085 * with m greater than 1, a some combination of existentially quantified
5086 * variables and f an expression in the parameters and input dimensions.
5087 * If so, we remove the stride in pw_multi_aff_from_map_stride.
5089 * Otherwise, we continue with pw_multi_aff_from_map_check_div for a further
5090 * special case.
5092 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_strides(
5093 __isl_take isl_map *map, __isl_take isl_basic_map *hull)
5095 int i, j;
5096 unsigned n_out;
5097 unsigned o_out;
5098 unsigned n_div;
5099 unsigned o_div;
5100 isl_int gcd;
5102 n_div = isl_basic_map_dim(hull, isl_dim_div);
5103 o_div = isl_basic_map_offset(hull, isl_dim_div);
5105 if (n_div == 0) {
5106 isl_basic_map_free(hull);
5107 return pw_multi_aff_from_map_check_div(map);
5110 isl_int_init(gcd);
5112 n_out = isl_basic_map_dim(hull, isl_dim_out);
5113 o_out = isl_basic_map_offset(hull, isl_dim_out);
5115 for (i = 0; i < n_out; ++i) {
5116 for (j = 0; j < hull->n_eq; ++j) {
5117 isl_int *eq = hull->eq[j];
5118 isl_pw_multi_aff *res;
5120 if (!isl_int_is_one(eq[o_out + i]) &&
5121 !isl_int_is_negone(eq[o_out + i]))
5122 continue;
5123 if (isl_seq_first_non_zero(eq + o_out, i) != -1)
5124 continue;
5125 if (isl_seq_first_non_zero(eq + o_out + i + 1,
5126 n_out - (i + 1)) != -1)
5127 continue;
5128 isl_seq_gcd(eq + o_div, n_div, &gcd);
5129 if (isl_int_is_zero(gcd))
5130 continue;
5131 if (isl_int_is_one(gcd))
5132 continue;
5134 res = pw_multi_aff_from_map_stride(map, hull,
5135 i, j, gcd);
5136 isl_int_clear(gcd);
5137 return res;
5141 isl_int_clear(gcd);
5142 isl_basic_map_free(hull);
5143 return pw_multi_aff_from_map_check_div(map);
5146 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5148 * As a special case, we first check if all output dimensions are uniquely
5149 * defined in terms of the parameters and input dimensions over the entire
5150 * domain. If so, we extract the desired isl_pw_multi_aff directly
5151 * from the affine hull of "map" and its domain.
5153 * Otherwise, continue with pw_multi_aff_from_map_check_strides for more
5154 * special cases.
5156 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
5158 isl_bool sv;
5159 isl_basic_map *hull;
5161 if (!map)
5162 return NULL;
5164 if (isl_map_n_basic_map(map) == 1) {
5165 hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
5166 hull = isl_basic_map_plain_affine_hull(hull);
5167 sv = isl_basic_map_plain_is_single_valued(hull);
5168 if (sv >= 0 && sv)
5169 return plain_pw_multi_aff_from_map(isl_map_domain(map),
5170 hull);
5171 isl_basic_map_free(hull);
5173 map = isl_map_detect_equalities(map);
5174 hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
5175 sv = isl_basic_map_plain_is_single_valued(hull);
5176 if (sv >= 0 && sv)
5177 return plain_pw_multi_aff_from_map(isl_map_domain(map), hull);
5178 if (sv >= 0)
5179 return pw_multi_aff_from_map_check_strides(map, hull);
5180 isl_basic_map_free(hull);
5181 isl_map_free(map);
5182 return NULL;
5185 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(__isl_take isl_set *set)
5187 return isl_pw_multi_aff_from_map(set);
5190 /* Convert "map" into an isl_pw_multi_aff (if possible) and
5191 * add it to *user.
5193 static isl_stat pw_multi_aff_from_map(__isl_take isl_map *map, void *user)
5195 isl_union_pw_multi_aff **upma = user;
5196 isl_pw_multi_aff *pma;
5198 pma = isl_pw_multi_aff_from_map(map);
5199 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
5201 return *upma ? isl_stat_ok : isl_stat_error;
5204 /* Create an isl_union_pw_multi_aff with the given isl_aff on a universe
5205 * domain.
5207 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff(
5208 __isl_take isl_aff *aff)
5210 isl_multi_aff *ma;
5211 isl_pw_multi_aff *pma;
5213 ma = isl_multi_aff_from_aff(aff);
5214 pma = isl_pw_multi_aff_from_multi_aff(ma);
5215 return isl_union_pw_multi_aff_from_pw_multi_aff(pma);
5218 /* Try and create an isl_union_pw_multi_aff that is equivalent
5219 * to the given isl_union_map.
5220 * The isl_union_map is required to be single-valued in each space.
5221 * Otherwise, an error is produced.
5223 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map(
5224 __isl_take isl_union_map *umap)
5226 isl_space *space;
5227 isl_union_pw_multi_aff *upma;
5229 space = isl_union_map_get_space(umap);
5230 upma = isl_union_pw_multi_aff_empty(space);
5231 if (isl_union_map_foreach_map(umap, &pw_multi_aff_from_map, &upma) < 0)
5232 upma = isl_union_pw_multi_aff_free(upma);
5233 isl_union_map_free(umap);
5235 return upma;
5238 /* Try and create an isl_union_pw_multi_aff that is equivalent
5239 * to the given isl_union_set.
5240 * The isl_union_set is required to be a singleton in each space.
5241 * Otherwise, an error is produced.
5243 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set(
5244 __isl_take isl_union_set *uset)
5246 return isl_union_pw_multi_aff_from_union_map(uset);
5249 /* Return the piecewise affine expression "set ? 1 : 0".
5251 __isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set)
5253 isl_pw_aff *pa;
5254 isl_space *space = isl_set_get_space(set);
5255 isl_local_space *ls = isl_local_space_from_space(space);
5256 isl_aff *zero = isl_aff_zero_on_domain(isl_local_space_copy(ls));
5257 isl_aff *one = isl_aff_zero_on_domain(ls);
5259 one = isl_aff_add_constant_si(one, 1);
5260 pa = isl_pw_aff_alloc(isl_set_copy(set), one);
5261 set = isl_set_complement(set);
5262 pa = isl_pw_aff_add_disjoint(pa, isl_pw_aff_alloc(set, zero));
5264 return pa;
5267 /* Plug in "subs" for dimension "type", "pos" of "aff".
5269 * Let i be the dimension to replace and let "subs" be of the form
5271 * f/d
5273 * and "aff" of the form
5275 * (a i + g)/m
5277 * The result is
5279 * (a f + d g')/(m d)
5281 * where g' is the result of plugging in "subs" in each of the integer
5282 * divisions in g.
5284 __isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *aff,
5285 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
5287 isl_ctx *ctx;
5288 isl_int v;
5290 aff = isl_aff_cow(aff);
5291 if (!aff || !subs)
5292 return isl_aff_free(aff);
5294 ctx = isl_aff_get_ctx(aff);
5295 if (!isl_space_is_equal(aff->ls->dim, subs->ls->dim))
5296 isl_die(ctx, isl_error_invalid,
5297 "spaces don't match", return isl_aff_free(aff));
5298 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
5299 isl_die(ctx, isl_error_unsupported,
5300 "cannot handle divs yet", return isl_aff_free(aff));
5302 aff->ls = isl_local_space_substitute(aff->ls, type, pos, subs);
5303 if (!aff->ls)
5304 return isl_aff_free(aff);
5306 aff->v = isl_vec_cow(aff->v);
5307 if (!aff->v)
5308 return isl_aff_free(aff);
5310 pos += isl_local_space_offset(aff->ls, type);
5312 isl_int_init(v);
5313 isl_seq_substitute(aff->v->el, pos, subs->v->el,
5314 aff->v->size, subs->v->size, v);
5315 isl_int_clear(v);
5317 return aff;
5320 /* Plug in "subs" for dimension "type", "pos" in each of the affine
5321 * expressions in "maff".
5323 __isl_give isl_multi_aff *isl_multi_aff_substitute(
5324 __isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos,
5325 __isl_keep isl_aff *subs)
5327 int i;
5329 maff = isl_multi_aff_cow(maff);
5330 if (!maff || !subs)
5331 return isl_multi_aff_free(maff);
5333 if (type == isl_dim_in)
5334 type = isl_dim_set;
5336 for (i = 0; i < maff->n; ++i) {
5337 maff->p[i] = isl_aff_substitute(maff->p[i], type, pos, subs);
5338 if (!maff->p[i])
5339 return isl_multi_aff_free(maff);
5342 return maff;
5345 /* Plug in "subs" for dimension "type", "pos" of "pma".
5347 * pma is of the form
5349 * A_i(v) -> M_i(v)
5351 * while subs is of the form
5353 * v' = B_j(v) -> S_j
5355 * Each pair i,j such that C_ij = A_i \cap B_i is non-empty
5356 * has a contribution in the result, in particular
5358 * C_ij(S_j) -> M_i(S_j)
5360 * Note that plugging in S_j in C_ij may also result in an empty set
5361 * and this contribution should simply be discarded.
5363 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute(
5364 __isl_take isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned pos,
5365 __isl_keep isl_pw_aff *subs)
5367 int i, j, n;
5368 isl_pw_multi_aff *res;
5370 if (!pma || !subs)
5371 return isl_pw_multi_aff_free(pma);
5373 n = pma->n * subs->n;
5374 res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma->dim), n);
5376 for (i = 0; i < pma->n; ++i) {
5377 for (j = 0; j < subs->n; ++j) {
5378 isl_set *common;
5379 isl_multi_aff *res_ij;
5380 int empty;
5382 common = isl_set_intersect(
5383 isl_set_copy(pma->p[i].set),
5384 isl_set_copy(subs->p[j].set));
5385 common = isl_set_substitute(common,
5386 type, pos, subs->p[j].aff);
5387 empty = isl_set_plain_is_empty(common);
5388 if (empty < 0 || empty) {
5389 isl_set_free(common);
5390 if (empty < 0)
5391 goto error;
5392 continue;
5395 res_ij = isl_multi_aff_substitute(
5396 isl_multi_aff_copy(pma->p[i].maff),
5397 type, pos, subs->p[j].aff);
5399 res = isl_pw_multi_aff_add_piece(res, common, res_ij);
5403 isl_pw_multi_aff_free(pma);
5404 return res;
5405 error:
5406 isl_pw_multi_aff_free(pma);
5407 isl_pw_multi_aff_free(res);
5408 return NULL;
5411 /* Compute the preimage of a range of dimensions in the affine expression "src"
5412 * under "ma" and put the result in "dst". The number of dimensions in "src"
5413 * that precede the range is given by "n_before". The number of dimensions
5414 * in the range is given by the number of output dimensions of "ma".
5415 * The number of dimensions that follow the range is given by "n_after".
5416 * If "has_denom" is set (to one),
5417 * then "src" and "dst" have an extra initial denominator.
5418 * "n_div_ma" is the number of existentials in "ma"
5419 * "n_div_bset" is the number of existentials in "src"
5420 * The resulting "dst" (which is assumed to have been allocated by
5421 * the caller) contains coefficients for both sets of existentials,
5422 * first those in "ma" and then those in "src".
5423 * f, c1, c2 and g are temporary objects that have been initialized
5424 * by the caller.
5426 * Let src represent the expression
5428 * (a(p) + f_u u + b v + f_w w + c(divs))/d
5430 * and let ma represent the expressions
5432 * v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i
5434 * We start out with the following expression for dst:
5436 * (a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d
5438 * with the multiplication factor f initially equal to 1
5439 * and f \sum_i b_i v_i kept separately.
5440 * For each x_i that we substitute, we multiply the numerator
5441 * (and denominator) of dst by c_1 = m_i and add the numerator
5442 * of the x_i expression multiplied by c_2 = f b_i,
5443 * after removing the common factors of c_1 and c_2.
5444 * The multiplication factor f also needs to be multiplied by c_1
5445 * for the next x_j, j > i.
5447 void isl_seq_preimage(isl_int *dst, isl_int *src,
5448 __isl_keep isl_multi_aff *ma, int n_before, int n_after,
5449 int n_div_ma, int n_div_bmap,
5450 isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom)
5452 int i;
5453 int n_param, n_in, n_out;
5454 int o_dst, o_src;
5456 n_param = isl_multi_aff_dim(ma, isl_dim_param);
5457 n_in = isl_multi_aff_dim(ma, isl_dim_in);
5458 n_out = isl_multi_aff_dim(ma, isl_dim_out);
5460 isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before);
5461 o_dst = o_src = has_denom + 1 + n_param + n_before;
5462 isl_seq_clr(dst + o_dst, n_in);
5463 o_dst += n_in;
5464 o_src += n_out;
5465 isl_seq_cpy(dst + o_dst, src + o_src, n_after);
5466 o_dst += n_after;
5467 o_src += n_after;
5468 isl_seq_clr(dst + o_dst, n_div_ma);
5469 o_dst += n_div_ma;
5470 isl_seq_cpy(dst + o_dst, src + o_src, n_div_bmap);
5472 isl_int_set_si(f, 1);
5474 for (i = 0; i < n_out; ++i) {
5475 int offset = has_denom + 1 + n_param + n_before + i;
5477 if (isl_int_is_zero(src[offset]))
5478 continue;
5479 isl_int_set(c1, ma->p[i]->v->el[0]);
5480 isl_int_mul(c2, f, src[offset]);
5481 isl_int_gcd(g, c1, c2);
5482 isl_int_divexact(c1, c1, g);
5483 isl_int_divexact(c2, c2, g);
5485 isl_int_mul(f, f, c1);
5486 o_dst = has_denom;
5487 o_src = 1;
5488 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5489 c2, ma->p[i]->v->el + o_src, 1 + n_param);
5490 o_dst += 1 + n_param;
5491 o_src += 1 + n_param;
5492 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_before);
5493 o_dst += n_before;
5494 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5495 c2, ma->p[i]->v->el + o_src, n_in);
5496 o_dst += n_in;
5497 o_src += n_in;
5498 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_after);
5499 o_dst += n_after;
5500 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5501 c2, ma->p[i]->v->el + o_src, n_div_ma);
5502 o_dst += n_div_ma;
5503 o_src += n_div_ma;
5504 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_div_bmap);
5505 if (has_denom)
5506 isl_int_mul(dst[0], dst[0], c1);
5510 /* Compute the pullback of "aff" by the function represented by "ma".
5511 * In other words, plug in "ma" in "aff". The result is an affine expression
5512 * defined over the domain space of "ma".
5514 * If "aff" is represented by
5516 * (a(p) + b x + c(divs))/d
5518 * and ma is represented by
5520 * x = D(p) + F(y) + G(divs')
5522 * then the result is
5524 * (a(p) + b D(p) + b F(y) + b G(divs') + c(divs))/d
5526 * The divs in the local space of the input are similarly adjusted
5527 * through a call to isl_local_space_preimage_multi_aff.
5529 __isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
5530 __isl_take isl_multi_aff *ma)
5532 isl_aff *res = NULL;
5533 isl_local_space *ls;
5534 int n_div_aff, n_div_ma;
5535 isl_int f, c1, c2, g;
5537 ma = isl_multi_aff_align_divs(ma);
5538 if (!aff || !ma)
5539 goto error;
5541 n_div_aff = isl_aff_dim(aff, isl_dim_div);
5542 n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
5544 ls = isl_aff_get_domain_local_space(aff);
5545 ls = isl_local_space_preimage_multi_aff(ls, isl_multi_aff_copy(ma));
5546 res = isl_aff_alloc(ls);
5547 if (!res)
5548 goto error;
5550 isl_int_init(f);
5551 isl_int_init(c1);
5552 isl_int_init(c2);
5553 isl_int_init(g);
5555 isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0, n_div_ma, n_div_aff,
5556 f, c1, c2, g, 1);
5558 isl_int_clear(f);
5559 isl_int_clear(c1);
5560 isl_int_clear(c2);
5561 isl_int_clear(g);
5563 isl_aff_free(aff);
5564 isl_multi_aff_free(ma);
5565 res = isl_aff_normalize(res);
5566 return res;
5567 error:
5568 isl_aff_free(aff);
5569 isl_multi_aff_free(ma);
5570 isl_aff_free(res);
5571 return NULL;
5574 /* Compute the pullback of "aff1" by the function represented by "aff2".
5575 * In other words, plug in "aff2" in "aff1". The result is an affine expression
5576 * defined over the domain space of "aff1".
5578 * The domain of "aff1" should match the range of "aff2", which means
5579 * that it should be single-dimensional.
5581 __isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
5582 __isl_take isl_aff *aff2)
5584 isl_multi_aff *ma;
5586 ma = isl_multi_aff_from_aff(aff2);
5587 return isl_aff_pullback_multi_aff(aff1, ma);
5590 /* Compute the pullback of "ma1" by the function represented by "ma2".
5591 * In other words, plug in "ma2" in "ma1".
5593 * The parameters of "ma1" and "ma2" are assumed to have been aligned.
5595 static __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff_aligned(
5596 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
5598 int i;
5599 isl_space *space = NULL;
5601 ma2 = isl_multi_aff_align_divs(ma2);
5602 ma1 = isl_multi_aff_cow(ma1);
5603 if (!ma1 || !ma2)
5604 goto error;
5606 space = isl_space_join(isl_multi_aff_get_space(ma2),
5607 isl_multi_aff_get_space(ma1));
5609 for (i = 0; i < ma1->n; ++i) {
5610 ma1->p[i] = isl_aff_pullback_multi_aff(ma1->p[i],
5611 isl_multi_aff_copy(ma2));
5612 if (!ma1->p[i])
5613 goto error;
5616 ma1 = isl_multi_aff_reset_space(ma1, space);
5617 isl_multi_aff_free(ma2);
5618 return ma1;
5619 error:
5620 isl_space_free(space);
5621 isl_multi_aff_free(ma2);
5622 isl_multi_aff_free(ma1);
5623 return NULL;
5626 /* Compute the pullback of "ma1" by the function represented by "ma2".
5627 * In other words, plug in "ma2" in "ma1".
5629 __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
5630 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
5632 return isl_multi_aff_align_params_multi_multi_and(ma1, ma2,
5633 &isl_multi_aff_pullback_multi_aff_aligned);
5636 /* Extend the local space of "dst" to include the divs
5637 * in the local space of "src".
5639 * If "src" does not have any divs or if the local spaces of "dst" and
5640 * "src" are the same, then no extension is required.
5642 __isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst,
5643 __isl_keep isl_aff *src)
5645 isl_ctx *ctx;
5646 int src_n_div, dst_n_div;
5647 int *exp1 = NULL;
5648 int *exp2 = NULL;
5649 isl_bool equal;
5650 isl_mat *div;
5652 if (!src || !dst)
5653 return isl_aff_free(dst);
5655 ctx = isl_aff_get_ctx(src);
5656 equal = isl_local_space_has_equal_space(src->ls, dst->ls);
5657 if (equal < 0)
5658 return isl_aff_free(dst);
5659 if (!equal)
5660 isl_die(ctx, isl_error_invalid,
5661 "spaces don't match", goto error);
5663 src_n_div = isl_local_space_dim(src->ls, isl_dim_div);
5664 if (src_n_div == 0)
5665 return dst;
5666 equal = isl_local_space_is_equal(src->ls, dst->ls);
5667 if (equal < 0)
5668 return isl_aff_free(dst);
5669 if (equal)
5670 return dst;
5672 dst_n_div = isl_local_space_dim(dst->ls, isl_dim_div);
5673 exp1 = isl_alloc_array(ctx, int, src_n_div);
5674 exp2 = isl_alloc_array(ctx, int, dst_n_div);
5675 if (!exp1 || (dst_n_div && !exp2))
5676 goto error;
5678 div = isl_merge_divs(src->ls->div, dst->ls->div, exp1, exp2);
5679 dst = isl_aff_expand_divs(dst, div, exp2);
5680 free(exp1);
5681 free(exp2);
5683 return dst;
5684 error:
5685 free(exp1);
5686 free(exp2);
5687 return isl_aff_free(dst);
5690 /* Adjust the local spaces of the affine expressions in "maff"
5691 * such that they all have the save divs.
5693 __isl_give isl_multi_aff *isl_multi_aff_align_divs(
5694 __isl_take isl_multi_aff *maff)
5696 int i;
5698 if (!maff)
5699 return NULL;
5700 if (maff->n == 0)
5701 return maff;
5702 maff = isl_multi_aff_cow(maff);
5703 if (!maff)
5704 return NULL;
5706 for (i = 1; i < maff->n; ++i)
5707 maff->p[0] = isl_aff_align_divs(maff->p[0], maff->p[i]);
5708 for (i = 1; i < maff->n; ++i) {
5709 maff->p[i] = isl_aff_align_divs(maff->p[i], maff->p[0]);
5710 if (!maff->p[i])
5711 return isl_multi_aff_free(maff);
5714 return maff;
5717 __isl_give isl_aff *isl_aff_lift(__isl_take isl_aff *aff)
5719 aff = isl_aff_cow(aff);
5720 if (!aff)
5721 return NULL;
5723 aff->ls = isl_local_space_lift(aff->ls);
5724 if (!aff->ls)
5725 return isl_aff_free(aff);
5727 return aff;
5730 /* Lift "maff" to a space with extra dimensions such that the result
5731 * has no more existentially quantified variables.
5732 * If "ls" is not NULL, then *ls is assigned the local space that lies
5733 * at the basis of the lifting applied to "maff".
5735 __isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
5736 __isl_give isl_local_space **ls)
5738 int i;
5739 isl_space *space;
5740 unsigned n_div;
5742 if (ls)
5743 *ls = NULL;
5745 if (!maff)
5746 return NULL;
5748 if (maff->n == 0) {
5749 if (ls) {
5750 isl_space *space = isl_multi_aff_get_domain_space(maff);
5751 *ls = isl_local_space_from_space(space);
5752 if (!*ls)
5753 return isl_multi_aff_free(maff);
5755 return maff;
5758 maff = isl_multi_aff_cow(maff);
5759 maff = isl_multi_aff_align_divs(maff);
5760 if (!maff)
5761 return NULL;
5763 n_div = isl_aff_dim(maff->p[0], isl_dim_div);
5764 space = isl_multi_aff_get_space(maff);
5765 space = isl_space_lift(isl_space_domain(space), n_div);
5766 space = isl_space_extend_domain_with_range(space,
5767 isl_multi_aff_get_space(maff));
5768 if (!space)
5769 return isl_multi_aff_free(maff);
5770 isl_space_free(maff->space);
5771 maff->space = space;
5773 if (ls) {
5774 *ls = isl_aff_get_domain_local_space(maff->p[0]);
5775 if (!*ls)
5776 return isl_multi_aff_free(maff);
5779 for (i = 0; i < maff->n; ++i) {
5780 maff->p[i] = isl_aff_lift(maff->p[i]);
5781 if (!maff->p[i])
5782 goto error;
5785 return maff;
5786 error:
5787 if (ls)
5788 isl_local_space_free(*ls);
5789 return isl_multi_aff_free(maff);
5793 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma".
5795 __isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
5796 __isl_keep isl_pw_multi_aff *pma, int pos)
5798 int i;
5799 int n_out;
5800 isl_space *space;
5801 isl_pw_aff *pa;
5803 if (!pma)
5804 return NULL;
5806 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
5807 if (pos < 0 || pos >= n_out)
5808 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
5809 "index out of bounds", return NULL);
5811 space = isl_pw_multi_aff_get_space(pma);
5812 space = isl_space_drop_dims(space, isl_dim_out,
5813 pos + 1, n_out - pos - 1);
5814 space = isl_space_drop_dims(space, isl_dim_out, 0, pos);
5816 pa = isl_pw_aff_alloc_size(space, pma->n);
5817 for (i = 0; i < pma->n; ++i) {
5818 isl_aff *aff;
5819 aff = isl_multi_aff_get_aff(pma->p[i].maff, pos);
5820 pa = isl_pw_aff_add_piece(pa, isl_set_copy(pma->p[i].set), aff);
5823 return pa;
5826 /* Return an isl_pw_multi_aff with the given "set" as domain and
5827 * an unnamed zero-dimensional range.
5829 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
5830 __isl_take isl_set *set)
5832 isl_multi_aff *ma;
5833 isl_space *space;
5835 space = isl_set_get_space(set);
5836 space = isl_space_from_domain(space);
5837 ma = isl_multi_aff_zero(space);
5838 return isl_pw_multi_aff_alloc(set, ma);
5841 /* Add an isl_pw_multi_aff with the given "set" as domain and
5842 * an unnamed zero-dimensional range to *user.
5844 static isl_stat add_pw_multi_aff_from_domain(__isl_take isl_set *set,
5845 void *user)
5847 isl_union_pw_multi_aff **upma = user;
5848 isl_pw_multi_aff *pma;
5850 pma = isl_pw_multi_aff_from_domain(set);
5851 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
5853 return isl_stat_ok;
5856 /* Return an isl_union_pw_multi_aff with the given "uset" as domain and
5857 * an unnamed zero-dimensional range.
5859 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
5860 __isl_take isl_union_set *uset)
5862 isl_space *space;
5863 isl_union_pw_multi_aff *upma;
5865 if (!uset)
5866 return NULL;
5868 space = isl_union_set_get_space(uset);
5869 upma = isl_union_pw_multi_aff_empty(space);
5871 if (isl_union_set_foreach_set(uset,
5872 &add_pw_multi_aff_from_domain, &upma) < 0)
5873 goto error;
5875 isl_union_set_free(uset);
5876 return upma;
5877 error:
5878 isl_union_set_free(uset);
5879 isl_union_pw_multi_aff_free(upma);
5880 return NULL;
5883 /* Convert "pma" to an isl_map and add it to *umap.
5885 static isl_stat map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma,
5886 void *user)
5888 isl_union_map **umap = user;
5889 isl_map *map;
5891 map = isl_map_from_pw_multi_aff(pma);
5892 *umap = isl_union_map_add_map(*umap, map);
5894 return isl_stat_ok;
5897 /* Construct a union map mapping the domain of the union
5898 * piecewise multi-affine expression to its range, with each dimension
5899 * in the range equated to the corresponding affine expression on its cell.
5901 __isl_give isl_union_map *isl_union_map_from_union_pw_multi_aff(
5902 __isl_take isl_union_pw_multi_aff *upma)
5904 isl_space *space;
5905 isl_union_map *umap;
5907 if (!upma)
5908 return NULL;
5910 space = isl_union_pw_multi_aff_get_space(upma);
5911 umap = isl_union_map_empty(space);
5913 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
5914 &map_from_pw_multi_aff, &umap) < 0)
5915 goto error;
5917 isl_union_pw_multi_aff_free(upma);
5918 return umap;
5919 error:
5920 isl_union_pw_multi_aff_free(upma);
5921 isl_union_map_free(umap);
5922 return NULL;
5925 /* Local data for bin_entry and the callback "fn".
5927 struct isl_union_pw_multi_aff_bin_data {
5928 isl_union_pw_multi_aff *upma2;
5929 isl_union_pw_multi_aff *res;
5930 isl_pw_multi_aff *pma;
5931 isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user);
5934 /* Given an isl_pw_multi_aff from upma1, store it in data->pma
5935 * and call data->fn for each isl_pw_multi_aff in data->upma2.
5937 static isl_stat bin_entry(__isl_take isl_pw_multi_aff *pma, void *user)
5939 struct isl_union_pw_multi_aff_bin_data *data = user;
5940 isl_stat r;
5942 data->pma = pma;
5943 r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma2,
5944 data->fn, data);
5945 isl_pw_multi_aff_free(pma);
5947 return r;
5950 /* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
5951 * The isl_pw_multi_aff from upma1 is stored in data->pma (where data is
5952 * passed as user field) and the isl_pw_multi_aff from upma2 is available
5953 * as *entry. The callback should adjust data->res if desired.
5955 static __isl_give isl_union_pw_multi_aff *bin_op(
5956 __isl_take isl_union_pw_multi_aff *upma1,
5957 __isl_take isl_union_pw_multi_aff *upma2,
5958 isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user))
5960 isl_space *space;
5961 struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn };
5963 space = isl_union_pw_multi_aff_get_space(upma2);
5964 upma1 = isl_union_pw_multi_aff_align_params(upma1, space);
5965 space = isl_union_pw_multi_aff_get_space(upma1);
5966 upma2 = isl_union_pw_multi_aff_align_params(upma2, space);
5968 if (!upma1 || !upma2)
5969 goto error;
5971 data.upma2 = upma2;
5972 data.res = isl_union_pw_multi_aff_alloc_same_size(upma1);
5973 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1,
5974 &bin_entry, &data) < 0)
5975 goto error;
5977 isl_union_pw_multi_aff_free(upma1);
5978 isl_union_pw_multi_aff_free(upma2);
5979 return data.res;
5980 error:
5981 isl_union_pw_multi_aff_free(upma1);
5982 isl_union_pw_multi_aff_free(upma2);
5983 isl_union_pw_multi_aff_free(data.res);
5984 return NULL;
5987 /* Given two aligned isl_pw_multi_affs A -> B and C -> D,
5988 * construct an isl_pw_multi_aff (A * C) -> [B -> D].
5990 static __isl_give isl_pw_multi_aff *pw_multi_aff_range_product(
5991 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
5993 isl_space *space;
5995 space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
5996 isl_pw_multi_aff_get_space(pma2));
5997 return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
5998 &isl_multi_aff_range_product);
6001 /* Given two isl_pw_multi_affs A -> B and C -> D,
6002 * construct an isl_pw_multi_aff (A * C) -> [B -> D].
6004 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_product(
6005 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6007 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
6008 &pw_multi_aff_range_product);
6011 /* Given two aligned isl_pw_multi_affs A -> B and C -> D,
6012 * construct an isl_pw_multi_aff (A * C) -> (B, D).
6014 static __isl_give isl_pw_multi_aff *pw_multi_aff_flat_range_product(
6015 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6017 isl_space *space;
6019 space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
6020 isl_pw_multi_aff_get_space(pma2));
6021 space = isl_space_flatten_range(space);
6022 return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
6023 &isl_multi_aff_flat_range_product);
6026 /* Given two isl_pw_multi_affs A -> B and C -> D,
6027 * construct an isl_pw_multi_aff (A * C) -> (B, D).
6029 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
6030 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6032 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
6033 &pw_multi_aff_flat_range_product);
6036 /* If data->pma and "pma2" have the same domain space, then compute
6037 * their flat range product and the result to data->res.
6039 static isl_stat flat_range_product_entry(__isl_take isl_pw_multi_aff *pma2,
6040 void *user)
6042 struct isl_union_pw_multi_aff_bin_data *data = user;
6044 if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
6045 pma2->dim, isl_dim_in)) {
6046 isl_pw_multi_aff_free(pma2);
6047 return isl_stat_ok;
6050 pma2 = isl_pw_multi_aff_flat_range_product(
6051 isl_pw_multi_aff_copy(data->pma), pma2);
6053 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
6055 return isl_stat_ok;
6058 /* Given two isl_union_pw_multi_affs A -> B and C -> D,
6059 * construct an isl_union_pw_multi_aff (A * C) -> (B, D).
6061 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_flat_range_product(
6062 __isl_take isl_union_pw_multi_aff *upma1,
6063 __isl_take isl_union_pw_multi_aff *upma2)
6065 return bin_op(upma1, upma2, &flat_range_product_entry);
6068 /* Replace the affine expressions at position "pos" in "pma" by "pa".
6069 * The parameters are assumed to have been aligned.
6071 * The implementation essentially performs an isl_pw_*_on_shared_domain,
6072 * except that it works on two different isl_pw_* types.
6074 static __isl_give isl_pw_multi_aff *pw_multi_aff_set_pw_aff(
6075 __isl_take isl_pw_multi_aff *pma, unsigned pos,
6076 __isl_take isl_pw_aff *pa)
6078 int i, j, n;
6079 isl_pw_multi_aff *res = NULL;
6081 if (!pma || !pa)
6082 goto error;
6084 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_in,
6085 pa->dim, isl_dim_in))
6086 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6087 "domains don't match", goto error);
6088 if (pos >= isl_pw_multi_aff_dim(pma, isl_dim_out))
6089 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6090 "index out of bounds", goto error);
6092 n = pma->n * pa->n;
6093 res = isl_pw_multi_aff_alloc_size(isl_pw_multi_aff_get_space(pma), n);
6095 for (i = 0; i < pma->n; ++i) {
6096 for (j = 0; j < pa->n; ++j) {
6097 isl_set *common;
6098 isl_multi_aff *res_ij;
6099 int empty;
6101 common = isl_set_intersect(isl_set_copy(pma->p[i].set),
6102 isl_set_copy(pa->p[j].set));
6103 empty = isl_set_plain_is_empty(common);
6104 if (empty < 0 || empty) {
6105 isl_set_free(common);
6106 if (empty < 0)
6107 goto error;
6108 continue;
6111 res_ij = isl_multi_aff_set_aff(
6112 isl_multi_aff_copy(pma->p[i].maff), pos,
6113 isl_aff_copy(pa->p[j].aff));
6114 res_ij = isl_multi_aff_gist(res_ij,
6115 isl_set_copy(common));
6117 res = isl_pw_multi_aff_add_piece(res, common, res_ij);
6121 isl_pw_multi_aff_free(pma);
6122 isl_pw_aff_free(pa);
6123 return res;
6124 error:
6125 isl_pw_multi_aff_free(pma);
6126 isl_pw_aff_free(pa);
6127 return isl_pw_multi_aff_free(res);
6130 /* Replace the affine expressions at position "pos" in "pma" by "pa".
6132 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
6133 __isl_take isl_pw_multi_aff *pma, unsigned pos,
6134 __isl_take isl_pw_aff *pa)
6136 isl_bool equal_params;
6138 if (!pma || !pa)
6139 goto error;
6140 equal_params = isl_space_has_equal_params(pma->dim, pa->dim);
6141 if (equal_params < 0)
6142 goto error;
6143 if (equal_params)
6144 return pw_multi_aff_set_pw_aff(pma, pos, pa);
6145 if (!isl_space_has_named_params(pma->dim) ||
6146 !isl_space_has_named_params(pa->dim))
6147 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6148 "unaligned unnamed parameters", goto error);
6149 pma = isl_pw_multi_aff_align_params(pma, isl_pw_aff_get_space(pa));
6150 pa = isl_pw_aff_align_params(pa, isl_pw_multi_aff_get_space(pma));
6151 return pw_multi_aff_set_pw_aff(pma, pos, pa);
6152 error:
6153 isl_pw_multi_aff_free(pma);
6154 isl_pw_aff_free(pa);
6155 return NULL;
6158 /* Do the parameters of "pa" match those of "space"?
6160 isl_bool isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa,
6161 __isl_keep isl_space *space)
6163 isl_space *pa_space;
6164 isl_bool match;
6166 if (!pa || !space)
6167 return isl_bool_error;
6169 pa_space = isl_pw_aff_get_space(pa);
6171 match = isl_space_has_equal_params(space, pa_space);
6173 isl_space_free(pa_space);
6174 return match;
6177 /* Check that the domain space of "pa" matches "space".
6179 isl_stat isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
6180 __isl_keep isl_space *space)
6182 isl_space *pa_space;
6183 isl_bool match;
6185 if (!pa || !space)
6186 return isl_stat_error;
6188 pa_space = isl_pw_aff_get_space(pa);
6190 match = isl_space_has_equal_params(space, pa_space);
6191 if (match < 0)
6192 goto error;
6193 if (!match)
6194 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
6195 "parameters don't match", goto error);
6196 match = isl_space_tuple_is_equal(space, isl_dim_in,
6197 pa_space, isl_dim_in);
6198 if (match < 0)
6199 goto error;
6200 if (!match)
6201 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
6202 "domains don't match", goto error);
6203 isl_space_free(pa_space);
6204 return isl_stat_ok;
6205 error:
6206 isl_space_free(pa_space);
6207 return isl_stat_error;
6210 #undef BASE
6211 #define BASE pw_aff
6212 #undef DOMBASE
6213 #define DOMBASE set
6215 #include <isl_multi_templ.c>
6216 #include <isl_multi_apply_set.c>
6217 #include <isl_multi_coalesce.c>
6218 #include <isl_multi_gist.c>
6219 #include <isl_multi_hash.c>
6220 #include <isl_multi_intersect.c>
6222 /* Scale the elements of "pma" by the corresponding elements of "mv".
6224 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
6225 __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv)
6227 int i;
6228 isl_bool equal_params;
6230 pma = isl_pw_multi_aff_cow(pma);
6231 if (!pma || !mv)
6232 goto error;
6233 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
6234 mv->space, isl_dim_set))
6235 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6236 "spaces don't match", goto error);
6237 equal_params = isl_space_has_equal_params(pma->dim, mv->space);
6238 if (equal_params < 0)
6239 goto error;
6240 if (!equal_params) {
6241 pma = isl_pw_multi_aff_align_params(pma,
6242 isl_multi_val_get_space(mv));
6243 mv = isl_multi_val_align_params(mv,
6244 isl_pw_multi_aff_get_space(pma));
6245 if (!pma || !mv)
6246 goto error;
6249 for (i = 0; i < pma->n; ++i) {
6250 pma->p[i].maff = isl_multi_aff_scale_multi_val(pma->p[i].maff,
6251 isl_multi_val_copy(mv));
6252 if (!pma->p[i].maff)
6253 goto error;
6256 isl_multi_val_free(mv);
6257 return pma;
6258 error:
6259 isl_multi_val_free(mv);
6260 isl_pw_multi_aff_free(pma);
6261 return NULL;
6264 /* This function is called for each entry of an isl_union_pw_multi_aff.
6265 * If the space of the entry matches that of data->mv,
6266 * then apply isl_pw_multi_aff_scale_multi_val and return the result.
6267 * Otherwise, return an empty isl_pw_multi_aff.
6269 static __isl_give isl_pw_multi_aff *union_pw_multi_aff_scale_multi_val_entry(
6270 __isl_take isl_pw_multi_aff *pma, void *user)
6272 isl_multi_val *mv = user;
6274 if (!pma)
6275 return NULL;
6276 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
6277 mv->space, isl_dim_set)) {
6278 isl_space *space = isl_pw_multi_aff_get_space(pma);
6279 isl_pw_multi_aff_free(pma);
6280 return isl_pw_multi_aff_empty(space);
6283 return isl_pw_multi_aff_scale_multi_val(pma, isl_multi_val_copy(mv));
6286 /* Scale the elements of "upma" by the corresponding elements of "mv",
6287 * for those entries that match the space of "mv".
6289 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
6290 __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv)
6292 upma = isl_union_pw_multi_aff_align_params(upma,
6293 isl_multi_val_get_space(mv));
6294 mv = isl_multi_val_align_params(mv,
6295 isl_union_pw_multi_aff_get_space(upma));
6296 if (!upma || !mv)
6297 goto error;
6299 return isl_union_pw_multi_aff_transform(upma,
6300 &union_pw_multi_aff_scale_multi_val_entry, mv);
6302 isl_multi_val_free(mv);
6303 return upma;
6304 error:
6305 isl_multi_val_free(mv);
6306 isl_union_pw_multi_aff_free(upma);
6307 return NULL;
6310 /* Construct and return a piecewise multi affine expression
6311 * in the given space with value zero in each of the output dimensions and
6312 * a universe domain.
6314 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(__isl_take isl_space *space)
6316 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_zero(space));
6319 /* Construct and return a piecewise multi affine expression
6320 * that is equal to the given piecewise affine expression.
6322 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff(
6323 __isl_take isl_pw_aff *pa)
6325 int i;
6326 isl_space *space;
6327 isl_pw_multi_aff *pma;
6329 if (!pa)
6330 return NULL;
6332 space = isl_pw_aff_get_space(pa);
6333 pma = isl_pw_multi_aff_alloc_size(space, pa->n);
6335 for (i = 0; i < pa->n; ++i) {
6336 isl_set *set;
6337 isl_multi_aff *ma;
6339 set = isl_set_copy(pa->p[i].set);
6340 ma = isl_multi_aff_from_aff(isl_aff_copy(pa->p[i].aff));
6341 pma = isl_pw_multi_aff_add_piece(pma, set, ma);
6344 isl_pw_aff_free(pa);
6345 return pma;
6348 /* Construct a set or map mapping the shared (parameter) domain
6349 * of the piecewise affine expressions to the range of "mpa"
6350 * with each dimension in the range equated to the
6351 * corresponding piecewise affine expression.
6353 static __isl_give isl_map *map_from_multi_pw_aff(
6354 __isl_take isl_multi_pw_aff *mpa)
6356 int i;
6357 isl_space *space;
6358 isl_map *map;
6360 if (!mpa)
6361 return NULL;
6363 if (isl_space_dim(mpa->space, isl_dim_out) != mpa->n)
6364 isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
6365 "invalid space", goto error);
6367 space = isl_multi_pw_aff_get_domain_space(mpa);
6368 map = isl_map_universe(isl_space_from_domain(space));
6370 for (i = 0; i < mpa->n; ++i) {
6371 isl_pw_aff *pa;
6372 isl_map *map_i;
6374 pa = isl_pw_aff_copy(mpa->p[i]);
6375 map_i = map_from_pw_aff(pa);
6377 map = isl_map_flat_range_product(map, map_i);
6380 map = isl_map_reset_space(map, isl_multi_pw_aff_get_space(mpa));
6382 isl_multi_pw_aff_free(mpa);
6383 return map;
6384 error:
6385 isl_multi_pw_aff_free(mpa);
6386 return NULL;
6389 /* Construct a map mapping the shared domain
6390 * of the piecewise affine expressions to the range of "mpa"
6391 * with each dimension in the range equated to the
6392 * corresponding piecewise affine expression.
6394 __isl_give isl_map *isl_map_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa)
6396 if (!mpa)
6397 return NULL;
6398 if (isl_space_is_set(mpa->space))
6399 isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
6400 "space of input is not a map", goto error);
6402 return map_from_multi_pw_aff(mpa);
6403 error:
6404 isl_multi_pw_aff_free(mpa);
6405 return NULL;
6408 /* Construct a set mapping the shared parameter domain
6409 * of the piecewise affine expressions to the space of "mpa"
6410 * with each dimension in the range equated to the
6411 * corresponding piecewise affine expression.
6413 __isl_give isl_set *isl_set_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa)
6415 if (!mpa)
6416 return NULL;
6417 if (!isl_space_is_set(mpa->space))
6418 isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
6419 "space of input is not a set", goto error);
6421 return map_from_multi_pw_aff(mpa);
6422 error:
6423 isl_multi_pw_aff_free(mpa);
6424 return NULL;
6427 /* Construct and return a piecewise multi affine expression
6428 * that is equal to the given multi piecewise affine expression
6429 * on the shared domain of the piecewise affine expressions.
6431 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff(
6432 __isl_take isl_multi_pw_aff *mpa)
6434 int i;
6435 isl_space *space;
6436 isl_pw_aff *pa;
6437 isl_pw_multi_aff *pma;
6439 if (!mpa)
6440 return NULL;
6442 space = isl_multi_pw_aff_get_space(mpa);
6444 if (mpa->n == 0) {
6445 isl_multi_pw_aff_free(mpa);
6446 return isl_pw_multi_aff_zero(space);
6449 pa = isl_multi_pw_aff_get_pw_aff(mpa, 0);
6450 pma = isl_pw_multi_aff_from_pw_aff(pa);
6452 for (i = 1; i < mpa->n; ++i) {
6453 isl_pw_multi_aff *pma_i;
6455 pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
6456 pma_i = isl_pw_multi_aff_from_pw_aff(pa);
6457 pma = isl_pw_multi_aff_range_product(pma, pma_i);
6460 pma = isl_pw_multi_aff_reset_space(pma, space);
6462 isl_multi_pw_aff_free(mpa);
6463 return pma;
6466 /* Construct and return a multi piecewise affine expression
6467 * that is equal to the given multi affine expression.
6469 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
6470 __isl_take isl_multi_aff *ma)
6472 int i, n;
6473 isl_multi_pw_aff *mpa;
6475 if (!ma)
6476 return NULL;
6478 n = isl_multi_aff_dim(ma, isl_dim_out);
6479 mpa = isl_multi_pw_aff_alloc(isl_multi_aff_get_space(ma));
6481 for (i = 0; i < n; ++i) {
6482 isl_pw_aff *pa;
6484 pa = isl_pw_aff_from_aff(isl_multi_aff_get_aff(ma, i));
6485 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
6488 isl_multi_aff_free(ma);
6489 return mpa;
6492 /* Construct and return a multi piecewise affine expression
6493 * that is equal to the given piecewise multi affine expression.
6495 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
6496 __isl_take isl_pw_multi_aff *pma)
6498 int i, n;
6499 isl_space *space;
6500 isl_multi_pw_aff *mpa;
6502 if (!pma)
6503 return NULL;
6505 n = isl_pw_multi_aff_dim(pma, isl_dim_out);
6506 space = isl_pw_multi_aff_get_space(pma);
6507 mpa = isl_multi_pw_aff_alloc(space);
6509 for (i = 0; i < n; ++i) {
6510 isl_pw_aff *pa;
6512 pa = isl_pw_multi_aff_get_pw_aff(pma, i);
6513 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
6516 isl_pw_multi_aff_free(pma);
6517 return mpa;
6520 /* Do "pa1" and "pa2" represent the same function?
6522 * We first check if they are obviously equal.
6523 * If not, we convert them to maps and check if those are equal.
6525 * If "pa1" or "pa2" contain any NaNs, then they are considered
6526 * not to be the same. A NaN is not equal to anything, not even
6527 * to another NaN.
6529 isl_bool isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1,
6530 __isl_keep isl_pw_aff *pa2)
6532 isl_bool equal;
6533 isl_bool has_nan;
6534 isl_map *map1, *map2;
6536 if (!pa1 || !pa2)
6537 return isl_bool_error;
6539 equal = isl_pw_aff_plain_is_equal(pa1, pa2);
6540 if (equal < 0 || equal)
6541 return equal;
6542 has_nan = either_involves_nan(pa1, pa2);
6543 if (has_nan < 0)
6544 return isl_bool_error;
6545 if (has_nan)
6546 return isl_bool_false;
6548 map1 = map_from_pw_aff(isl_pw_aff_copy(pa1));
6549 map2 = map_from_pw_aff(isl_pw_aff_copy(pa2));
6550 equal = isl_map_is_equal(map1, map2);
6551 isl_map_free(map1);
6552 isl_map_free(map2);
6554 return equal;
6557 /* Do "mpa1" and "mpa2" represent the same function?
6559 * Note that we cannot convert the entire isl_multi_pw_aff
6560 * to a map because the domains of the piecewise affine expressions
6561 * may not be the same.
6563 isl_bool isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
6564 __isl_keep isl_multi_pw_aff *mpa2)
6566 int i;
6567 isl_bool equal, equal_params;
6569 if (!mpa1 || !mpa2)
6570 return isl_bool_error;
6572 equal_params = isl_space_has_equal_params(mpa1->space, mpa2->space);
6573 if (equal_params < 0)
6574 return isl_bool_error;
6575 if (!equal_params) {
6576 if (!isl_space_has_named_params(mpa1->space))
6577 return isl_bool_false;
6578 if (!isl_space_has_named_params(mpa2->space))
6579 return isl_bool_false;
6580 mpa1 = isl_multi_pw_aff_copy(mpa1);
6581 mpa2 = isl_multi_pw_aff_copy(mpa2);
6582 mpa1 = isl_multi_pw_aff_align_params(mpa1,
6583 isl_multi_pw_aff_get_space(mpa2));
6584 mpa2 = isl_multi_pw_aff_align_params(mpa2,
6585 isl_multi_pw_aff_get_space(mpa1));
6586 equal = isl_multi_pw_aff_is_equal(mpa1, mpa2);
6587 isl_multi_pw_aff_free(mpa1);
6588 isl_multi_pw_aff_free(mpa2);
6589 return equal;
6592 equal = isl_space_is_equal(mpa1->space, mpa2->space);
6593 if (equal < 0 || !equal)
6594 return equal;
6596 for (i = 0; i < mpa1->n; ++i) {
6597 equal = isl_pw_aff_is_equal(mpa1->p[i], mpa2->p[i]);
6598 if (equal < 0 || !equal)
6599 return equal;
6602 return isl_bool_true;
6605 /* Do "pma1" and "pma2" represent the same function?
6607 * First check if they are obviously equal.
6608 * If not, then convert them to maps and check if those are equal.
6610 * If "pa1" or "pa2" contain any NaNs, then they are considered
6611 * not to be the same. A NaN is not equal to anything, not even
6612 * to another NaN.
6614 isl_bool isl_pw_multi_aff_is_equal(__isl_keep isl_pw_multi_aff *pma1,
6615 __isl_keep isl_pw_multi_aff *pma2)
6617 isl_bool equal;
6618 isl_bool has_nan;
6619 isl_map *map1, *map2;
6621 if (!pma1 || !pma2)
6622 return isl_bool_error;
6624 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
6625 if (equal < 0 || equal)
6626 return equal;
6627 has_nan = isl_pw_multi_aff_involves_nan(pma1);
6628 if (has_nan >= 0 && !has_nan)
6629 has_nan = isl_pw_multi_aff_involves_nan(pma2);
6630 if (has_nan < 0 || has_nan)
6631 return isl_bool_not(has_nan);
6633 map1 = isl_map_from_pw_multi_aff(isl_pw_multi_aff_copy(pma1));
6634 map2 = isl_map_from_pw_multi_aff(isl_pw_multi_aff_copy(pma2));
6635 equal = isl_map_is_equal(map1, map2);
6636 isl_map_free(map1);
6637 isl_map_free(map2);
6639 return equal;
6642 /* Compute the pullback of "mpa" by the function represented by "ma".
6643 * In other words, plug in "ma" in "mpa".
6645 * The parameters of "mpa" and "ma" are assumed to have been aligned.
6647 static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff_aligned(
6648 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
6650 int i;
6651 isl_space *space = NULL;
6653 mpa = isl_multi_pw_aff_cow(mpa);
6654 if (!mpa || !ma)
6655 goto error;
6657 space = isl_space_join(isl_multi_aff_get_space(ma),
6658 isl_multi_pw_aff_get_space(mpa));
6659 if (!space)
6660 goto error;
6662 for (i = 0; i < mpa->n; ++i) {
6663 mpa->p[i] = isl_pw_aff_pullback_multi_aff(mpa->p[i],
6664 isl_multi_aff_copy(ma));
6665 if (!mpa->p[i])
6666 goto error;
6669 isl_multi_aff_free(ma);
6670 isl_space_free(mpa->space);
6671 mpa->space = space;
6672 return mpa;
6673 error:
6674 isl_space_free(space);
6675 isl_multi_pw_aff_free(mpa);
6676 isl_multi_aff_free(ma);
6677 return NULL;
6680 /* Compute the pullback of "mpa" by the function represented by "ma".
6681 * In other words, plug in "ma" in "mpa".
6683 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff(
6684 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
6686 isl_bool equal_params;
6688 if (!mpa || !ma)
6689 goto error;
6690 equal_params = isl_space_has_equal_params(mpa->space, ma->space);
6691 if (equal_params < 0)
6692 goto error;
6693 if (equal_params)
6694 return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
6695 mpa = isl_multi_pw_aff_align_params(mpa, isl_multi_aff_get_space(ma));
6696 ma = isl_multi_aff_align_params(ma, isl_multi_pw_aff_get_space(mpa));
6697 return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
6698 error:
6699 isl_multi_pw_aff_free(mpa);
6700 isl_multi_aff_free(ma);
6701 return NULL;
6704 /* Compute the pullback of "mpa" by the function represented by "pma".
6705 * In other words, plug in "pma" in "mpa".
6707 * The parameters of "mpa" and "mpa" are assumed to have been aligned.
6709 static __isl_give isl_multi_pw_aff *
6710 isl_multi_pw_aff_pullback_pw_multi_aff_aligned(
6711 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
6713 int i;
6714 isl_space *space = NULL;
6716 mpa = isl_multi_pw_aff_cow(mpa);
6717 if (!mpa || !pma)
6718 goto error;
6720 space = isl_space_join(isl_pw_multi_aff_get_space(pma),
6721 isl_multi_pw_aff_get_space(mpa));
6723 for (i = 0; i < mpa->n; ++i) {
6724 mpa->p[i] = isl_pw_aff_pullback_pw_multi_aff_aligned(mpa->p[i],
6725 isl_pw_multi_aff_copy(pma));
6726 if (!mpa->p[i])
6727 goto error;
6730 isl_pw_multi_aff_free(pma);
6731 isl_space_free(mpa->space);
6732 mpa->space = space;
6733 return mpa;
6734 error:
6735 isl_space_free(space);
6736 isl_multi_pw_aff_free(mpa);
6737 isl_pw_multi_aff_free(pma);
6738 return NULL;
6741 /* Compute the pullback of "mpa" by the function represented by "pma".
6742 * In other words, plug in "pma" in "mpa".
6744 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_pw_multi_aff(
6745 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
6747 isl_bool equal_params;
6749 if (!mpa || !pma)
6750 goto error;
6751 equal_params = isl_space_has_equal_params(mpa->space, pma->dim);
6752 if (equal_params < 0)
6753 goto error;
6754 if (equal_params)
6755 return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
6756 mpa = isl_multi_pw_aff_align_params(mpa,
6757 isl_pw_multi_aff_get_space(pma));
6758 pma = isl_pw_multi_aff_align_params(pma,
6759 isl_multi_pw_aff_get_space(mpa));
6760 return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
6761 error:
6762 isl_multi_pw_aff_free(mpa);
6763 isl_pw_multi_aff_free(pma);
6764 return NULL;
6767 /* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
6768 * with the domain of "aff". The domain of the result is the same
6769 * as that of "mpa".
6770 * "mpa" and "aff" are assumed to have been aligned.
6772 * We first extract the parametric constant from "aff", defined
6773 * over the correct domain.
6774 * Then we add the appropriate combinations of the members of "mpa".
6775 * Finally, we add the integer divisions through recursive calls.
6777 static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff_aligned(
6778 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
6780 int i, n_in, n_div;
6781 isl_space *space;
6782 isl_val *v;
6783 isl_pw_aff *pa;
6784 isl_aff *tmp;
6786 n_in = isl_aff_dim(aff, isl_dim_in);
6787 n_div = isl_aff_dim(aff, isl_dim_div);
6789 space = isl_space_domain(isl_multi_pw_aff_get_space(mpa));
6790 tmp = isl_aff_copy(aff);
6791 tmp = isl_aff_drop_dims(tmp, isl_dim_div, 0, n_div);
6792 tmp = isl_aff_drop_dims(tmp, isl_dim_in, 0, n_in);
6793 tmp = isl_aff_add_dims(tmp, isl_dim_in,
6794 isl_space_dim(space, isl_dim_set));
6795 tmp = isl_aff_reset_domain_space(tmp, space);
6796 pa = isl_pw_aff_from_aff(tmp);
6798 for (i = 0; i < n_in; ++i) {
6799 isl_pw_aff *pa_i;
6801 if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
6802 continue;
6803 v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
6804 pa_i = isl_multi_pw_aff_get_pw_aff(mpa, i);
6805 pa_i = isl_pw_aff_scale_val(pa_i, v);
6806 pa = isl_pw_aff_add(pa, pa_i);
6809 for (i = 0; i < n_div; ++i) {
6810 isl_aff *div;
6811 isl_pw_aff *pa_i;
6813 if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
6814 continue;
6815 div = isl_aff_get_div(aff, i);
6816 pa_i = isl_multi_pw_aff_apply_aff_aligned(
6817 isl_multi_pw_aff_copy(mpa), div);
6818 pa_i = isl_pw_aff_floor(pa_i);
6819 v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
6820 pa_i = isl_pw_aff_scale_val(pa_i, v);
6821 pa = isl_pw_aff_add(pa, pa_i);
6824 isl_multi_pw_aff_free(mpa);
6825 isl_aff_free(aff);
6827 return pa;
6830 /* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
6831 * with the domain of "aff". The domain of the result is the same
6832 * as that of "mpa".
6834 __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff(
6835 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
6837 isl_bool equal_params;
6839 if (!aff || !mpa)
6840 goto error;
6841 equal_params = isl_space_has_equal_params(aff->ls->dim, mpa->space);
6842 if (equal_params < 0)
6843 goto error;
6844 if (equal_params)
6845 return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
6847 aff = isl_aff_align_params(aff, isl_multi_pw_aff_get_space(mpa));
6848 mpa = isl_multi_pw_aff_align_params(mpa, isl_aff_get_space(aff));
6850 return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
6851 error:
6852 isl_aff_free(aff);
6853 isl_multi_pw_aff_free(mpa);
6854 return NULL;
6857 /* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
6858 * with the domain of "pa". The domain of the result is the same
6859 * as that of "mpa".
6860 * "mpa" and "pa" are assumed to have been aligned.
6862 * We consider each piece in turn. Note that the domains of the
6863 * pieces are assumed to be disjoint and they remain disjoint
6864 * after taking the preimage (over the same function).
6866 static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff_aligned(
6867 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
6869 isl_space *space;
6870 isl_pw_aff *res;
6871 int i;
6873 if (!mpa || !pa)
6874 goto error;
6876 space = isl_space_join(isl_multi_pw_aff_get_space(mpa),
6877 isl_pw_aff_get_space(pa));
6878 res = isl_pw_aff_empty(space);
6880 for (i = 0; i < pa->n; ++i) {
6881 isl_pw_aff *pa_i;
6882 isl_set *domain;
6884 pa_i = isl_multi_pw_aff_apply_aff_aligned(
6885 isl_multi_pw_aff_copy(mpa),
6886 isl_aff_copy(pa->p[i].aff));
6887 domain = isl_set_copy(pa->p[i].set);
6888 domain = isl_set_preimage_multi_pw_aff(domain,
6889 isl_multi_pw_aff_copy(mpa));
6890 pa_i = isl_pw_aff_intersect_domain(pa_i, domain);
6891 res = isl_pw_aff_add_disjoint(res, pa_i);
6894 isl_pw_aff_free(pa);
6895 isl_multi_pw_aff_free(mpa);
6896 return res;
6897 error:
6898 isl_pw_aff_free(pa);
6899 isl_multi_pw_aff_free(mpa);
6900 return NULL;
6903 /* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
6904 * with the domain of "pa". The domain of the result is the same
6905 * as that of "mpa".
6907 __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff(
6908 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
6910 isl_bool equal_params;
6912 if (!pa || !mpa)
6913 goto error;
6914 equal_params = isl_space_has_equal_params(pa->dim, mpa->space);
6915 if (equal_params < 0)
6916 goto error;
6917 if (equal_params)
6918 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
6920 pa = isl_pw_aff_align_params(pa, isl_multi_pw_aff_get_space(mpa));
6921 mpa = isl_multi_pw_aff_align_params(mpa, isl_pw_aff_get_space(pa));
6923 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
6924 error:
6925 isl_pw_aff_free(pa);
6926 isl_multi_pw_aff_free(mpa);
6927 return NULL;
6930 /* Compute the pullback of "pa" by the function represented by "mpa".
6931 * In other words, plug in "mpa" in "pa".
6932 * "pa" and "mpa" are assumed to have been aligned.
6934 * The pullback is computed by applying "pa" to "mpa".
6936 static __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff_aligned(
6937 __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
6939 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
6942 /* Compute the pullback of "pa" by the function represented by "mpa".
6943 * In other words, plug in "mpa" in "pa".
6945 * The pullback is computed by applying "pa" to "mpa".
6947 __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
6948 __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
6950 return isl_multi_pw_aff_apply_pw_aff(mpa, pa);
6953 /* Compute the pullback of "mpa1" by the function represented by "mpa2".
6954 * In other words, plug in "mpa2" in "mpa1".
6956 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
6958 * We pullback each member of "mpa1" in turn.
6960 static __isl_give isl_multi_pw_aff *
6961 isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
6962 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
6964 int i;
6965 isl_space *space = NULL;
6967 mpa1 = isl_multi_pw_aff_cow(mpa1);
6968 if (!mpa1 || !mpa2)
6969 goto error;
6971 space = isl_space_join(isl_multi_pw_aff_get_space(mpa2),
6972 isl_multi_pw_aff_get_space(mpa1));
6974 for (i = 0; i < mpa1->n; ++i) {
6975 mpa1->p[i] = isl_pw_aff_pullback_multi_pw_aff_aligned(
6976 mpa1->p[i], isl_multi_pw_aff_copy(mpa2));
6977 if (!mpa1->p[i])
6978 goto error;
6981 mpa1 = isl_multi_pw_aff_reset_space(mpa1, space);
6983 isl_multi_pw_aff_free(mpa2);
6984 return mpa1;
6985 error:
6986 isl_space_free(space);
6987 isl_multi_pw_aff_free(mpa1);
6988 isl_multi_pw_aff_free(mpa2);
6989 return NULL;
6992 /* Compute the pullback of "mpa1" by the function represented by "mpa2".
6993 * In other words, plug in "mpa2" in "mpa1".
6995 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_pw_aff(
6996 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
6998 return isl_multi_pw_aff_align_params_multi_multi_and(mpa1, mpa2,
6999 &isl_multi_pw_aff_pullback_multi_pw_aff_aligned);
7002 /* Align the parameters of "mpa1" and "mpa2", check that the ranges
7003 * of "mpa1" and "mpa2" live in the same space, construct map space
7004 * between the domain spaces of "mpa1" and "mpa2" and call "order"
7005 * with this map space as extract argument.
7007 static __isl_give isl_map *isl_multi_pw_aff_order_map(
7008 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
7009 __isl_give isl_map *(*order)(__isl_keep isl_multi_pw_aff *mpa1,
7010 __isl_keep isl_multi_pw_aff *mpa2, __isl_take isl_space *space))
7012 int match;
7013 isl_space *space1, *space2;
7014 isl_map *res;
7016 mpa1 = isl_multi_pw_aff_align_params(mpa1,
7017 isl_multi_pw_aff_get_space(mpa2));
7018 mpa2 = isl_multi_pw_aff_align_params(mpa2,
7019 isl_multi_pw_aff_get_space(mpa1));
7020 if (!mpa1 || !mpa2)
7021 goto error;
7022 match = isl_space_tuple_is_equal(mpa1->space, isl_dim_out,
7023 mpa2->space, isl_dim_out);
7024 if (match < 0)
7025 goto error;
7026 if (!match)
7027 isl_die(isl_multi_pw_aff_get_ctx(mpa1), isl_error_invalid,
7028 "range spaces don't match", goto error);
7029 space1 = isl_space_domain(isl_multi_pw_aff_get_space(mpa1));
7030 space2 = isl_space_domain(isl_multi_pw_aff_get_space(mpa2));
7031 space1 = isl_space_map_from_domain_and_range(space1, space2);
7033 res = order(mpa1, mpa2, space1);
7034 isl_multi_pw_aff_free(mpa1);
7035 isl_multi_pw_aff_free(mpa2);
7036 return res;
7037 error:
7038 isl_multi_pw_aff_free(mpa1);
7039 isl_multi_pw_aff_free(mpa2);
7040 return NULL;
7043 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7044 * where the function values are equal. "space" is the space of the result.
7045 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7047 * "mpa1" and "mpa2" are equal when each of the pairs of elements
7048 * in the sequences are equal.
7050 static __isl_give isl_map *isl_multi_pw_aff_eq_map_on_space(
7051 __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2,
7052 __isl_take isl_space *space)
7054 int i, n;
7055 isl_map *res;
7057 res = isl_map_universe(space);
7059 n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
7060 for (i = 0; i < n; ++i) {
7061 isl_pw_aff *pa1, *pa2;
7062 isl_map *map;
7064 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7065 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7066 map = isl_pw_aff_eq_map(pa1, pa2);
7067 res = isl_map_intersect(res, map);
7070 return res;
7073 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7074 * where the function values are equal.
7076 __isl_give isl_map *isl_multi_pw_aff_eq_map(__isl_take isl_multi_pw_aff *mpa1,
7077 __isl_take isl_multi_pw_aff *mpa2)
7079 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7080 &isl_multi_pw_aff_eq_map_on_space);
7083 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7084 * where the function values of "mpa1" is lexicographically satisfies "base"
7085 * compared to that of "mpa2". "space" is the space of the result.
7086 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7088 * "mpa1" lexicographically satisfies "base" compared to "mpa2"
7089 * if its i-th element satisfies "base" when compared to
7090 * the i-th element of "mpa2" while all previous elements are
7091 * pairwise equal.
7093 static __isl_give isl_map *isl_multi_pw_aff_lex_map_on_space(
7094 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
7095 __isl_give isl_map *(*base)(__isl_take isl_pw_aff *pa1,
7096 __isl_take isl_pw_aff *pa2),
7097 __isl_take isl_space *space)
7099 int i, n;
7100 isl_map *res, *rest;
7102 res = isl_map_empty(isl_space_copy(space));
7103 rest = isl_map_universe(space);
7105 n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
7106 for (i = 0; i < n; ++i) {
7107 isl_pw_aff *pa1, *pa2;
7108 isl_map *map;
7110 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7111 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7112 map = base(pa1, pa2);
7113 map = isl_map_intersect(map, isl_map_copy(rest));
7114 res = isl_map_union(res, map);
7116 if (i == n - 1)
7117 continue;
7119 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7120 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7121 map = isl_pw_aff_eq_map(pa1, pa2);
7122 rest = isl_map_intersect(rest, map);
7125 isl_map_free(rest);
7126 return res;
7129 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7130 * where the function value of "mpa1" is lexicographically less than that
7131 * of "mpa2". "space" is the space of the result.
7132 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7134 * "mpa1" is less than "mpa2" if its i-th element is smaller
7135 * than the i-th element of "mpa2" while all previous elements are
7136 * pairwise equal.
7138 __isl_give isl_map *isl_multi_pw_aff_lex_lt_map_on_space(
7139 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
7140 __isl_take isl_space *space)
7142 return isl_multi_pw_aff_lex_map_on_space(mpa1, mpa2,
7143 &isl_pw_aff_lt_map, space);
7146 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7147 * where the function value of "mpa1" is lexicographically less than that
7148 * of "mpa2".
7150 __isl_give isl_map *isl_multi_pw_aff_lex_lt_map(
7151 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
7153 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7154 &isl_multi_pw_aff_lex_lt_map_on_space);
7157 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7158 * where the function value of "mpa1" is lexicographically greater than that
7159 * of "mpa2". "space" is the space of the result.
7160 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7162 * "mpa1" is greater than "mpa2" if its i-th element is greater
7163 * than the i-th element of "mpa2" while all previous elements are
7164 * pairwise equal.
7166 __isl_give isl_map *isl_multi_pw_aff_lex_gt_map_on_space(
7167 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
7168 __isl_take isl_space *space)
7170 return isl_multi_pw_aff_lex_map_on_space(mpa1, mpa2,
7171 &isl_pw_aff_gt_map, space);
7174 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7175 * where the function value of "mpa1" is lexicographically greater than that
7176 * of "mpa2".
7178 __isl_give isl_map *isl_multi_pw_aff_lex_gt_map(
7179 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
7181 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7182 &isl_multi_pw_aff_lex_gt_map_on_space);
7185 /* Compare two isl_affs.
7187 * Return -1 if "aff1" is "smaller" than "aff2", 1 if "aff1" is "greater"
7188 * than "aff2" and 0 if they are equal.
7190 * The order is fairly arbitrary. We do consider expressions that only involve
7191 * earlier dimensions as "smaller".
7193 int isl_aff_plain_cmp(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2)
7195 int cmp;
7196 int last1, last2;
7198 if (aff1 == aff2)
7199 return 0;
7201 if (!aff1)
7202 return -1;
7203 if (!aff2)
7204 return 1;
7206 cmp = isl_local_space_cmp(aff1->ls, aff2->ls);
7207 if (cmp != 0)
7208 return cmp;
7210 last1 = isl_seq_last_non_zero(aff1->v->el + 1, aff1->v->size - 1);
7211 last2 = isl_seq_last_non_zero(aff2->v->el + 1, aff1->v->size - 1);
7212 if (last1 != last2)
7213 return last1 - last2;
7215 return isl_seq_cmp(aff1->v->el, aff2->v->el, aff1->v->size);
7218 /* Compare two isl_pw_affs.
7220 * Return -1 if "pa1" is "smaller" than "pa2", 1 if "pa1" is "greater"
7221 * than "pa2" and 0 if they are equal.
7223 * The order is fairly arbitrary. We do consider expressions that only involve
7224 * earlier dimensions as "smaller".
7226 int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1,
7227 __isl_keep isl_pw_aff *pa2)
7229 int i;
7230 int cmp;
7232 if (pa1 == pa2)
7233 return 0;
7235 if (!pa1)
7236 return -1;
7237 if (!pa2)
7238 return 1;
7240 cmp = isl_space_cmp(pa1->dim, pa2->dim);
7241 if (cmp != 0)
7242 return cmp;
7244 if (pa1->n != pa2->n)
7245 return pa1->n - pa2->n;
7247 for (i = 0; i < pa1->n; ++i) {
7248 cmp = isl_set_plain_cmp(pa1->p[i].set, pa2->p[i].set);
7249 if (cmp != 0)
7250 return cmp;
7251 cmp = isl_aff_plain_cmp(pa1->p[i].aff, pa2->p[i].aff);
7252 if (cmp != 0)
7253 return cmp;
7256 return 0;
7259 /* Return a piecewise affine expression that is equal to "v" on "domain".
7261 __isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
7262 __isl_take isl_val *v)
7264 isl_space *space;
7265 isl_local_space *ls;
7266 isl_aff *aff;
7268 space = isl_set_get_space(domain);
7269 ls = isl_local_space_from_space(space);
7270 aff = isl_aff_val_on_domain(ls, v);
7272 return isl_pw_aff_alloc(domain, aff);
7275 /* Return a multi affine expression that is equal to "mv" on domain
7276 * space "space".
7278 __isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
7279 __isl_take isl_space *space, __isl_take isl_multi_val *mv)
7281 int i, n;
7282 isl_space *space2;
7283 isl_local_space *ls;
7284 isl_multi_aff *ma;
7286 if (!space || !mv)
7287 goto error;
7289 n = isl_multi_val_dim(mv, isl_dim_set);
7290 space2 = isl_multi_val_get_space(mv);
7291 space2 = isl_space_align_params(space2, isl_space_copy(space));
7292 space = isl_space_align_params(space, isl_space_copy(space2));
7293 space = isl_space_map_from_domain_and_range(space, space2);
7294 ma = isl_multi_aff_alloc(isl_space_copy(space));
7295 ls = isl_local_space_from_space(isl_space_domain(space));
7296 for (i = 0; i < n; ++i) {
7297 isl_val *v;
7298 isl_aff *aff;
7300 v = isl_multi_val_get_val(mv, i);
7301 aff = isl_aff_val_on_domain(isl_local_space_copy(ls), v);
7302 ma = isl_multi_aff_set_aff(ma, i, aff);
7304 isl_local_space_free(ls);
7306 isl_multi_val_free(mv);
7307 return ma;
7308 error:
7309 isl_space_free(space);
7310 isl_multi_val_free(mv);
7311 return NULL;
7314 /* Return a piecewise multi-affine expression
7315 * that is equal to "mv" on "domain".
7317 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_multi_val_on_domain(
7318 __isl_take isl_set *domain, __isl_take isl_multi_val *mv)
7320 isl_space *space;
7321 isl_multi_aff *ma;
7323 space = isl_set_get_space(domain);
7324 ma = isl_multi_aff_multi_val_on_space(space, mv);
7326 return isl_pw_multi_aff_alloc(domain, ma);
7329 /* Internal data structure for isl_union_pw_multi_aff_multi_val_on_domain.
7330 * mv is the value that should be attained on each domain set
7331 * res collects the results
7333 struct isl_union_pw_multi_aff_multi_val_on_domain_data {
7334 isl_multi_val *mv;
7335 isl_union_pw_multi_aff *res;
7338 /* Create an isl_pw_multi_aff equal to data->mv on "domain"
7339 * and add it to data->res.
7341 static isl_stat pw_multi_aff_multi_val_on_domain(__isl_take isl_set *domain,
7342 void *user)
7344 struct isl_union_pw_multi_aff_multi_val_on_domain_data *data = user;
7345 isl_pw_multi_aff *pma;
7346 isl_multi_val *mv;
7348 mv = isl_multi_val_copy(data->mv);
7349 pma = isl_pw_multi_aff_multi_val_on_domain(domain, mv);
7350 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
7352 return data->res ? isl_stat_ok : isl_stat_error;
7355 /* Return a union piecewise multi-affine expression
7356 * that is equal to "mv" on "domain".
7358 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_multi_val_on_domain(
7359 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
7361 struct isl_union_pw_multi_aff_multi_val_on_domain_data data;
7362 isl_space *space;
7364 space = isl_union_set_get_space(domain);
7365 data.res = isl_union_pw_multi_aff_empty(space);
7366 data.mv = mv;
7367 if (isl_union_set_foreach_set(domain,
7368 &pw_multi_aff_multi_val_on_domain, &data) < 0)
7369 data.res = isl_union_pw_multi_aff_free(data.res);
7370 isl_union_set_free(domain);
7371 isl_multi_val_free(mv);
7372 return data.res;
7375 /* Compute the pullback of data->pma by the function represented by "pma2",
7376 * provided the spaces match, and add the results to data->res.
7378 static isl_stat pullback_entry(__isl_take isl_pw_multi_aff *pma2, void *user)
7380 struct isl_union_pw_multi_aff_bin_data *data = user;
7382 if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
7383 pma2->dim, isl_dim_out)) {
7384 isl_pw_multi_aff_free(pma2);
7385 return isl_stat_ok;
7388 pma2 = isl_pw_multi_aff_pullback_pw_multi_aff(
7389 isl_pw_multi_aff_copy(data->pma), pma2);
7391 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
7392 if (!data->res)
7393 return isl_stat_error;
7395 return isl_stat_ok;
7398 /* Compute the pullback of "upma1" by the function represented by "upma2".
7400 __isl_give isl_union_pw_multi_aff *
7401 isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
7402 __isl_take isl_union_pw_multi_aff *upma1,
7403 __isl_take isl_union_pw_multi_aff *upma2)
7405 return bin_op(upma1, upma2, &pullback_entry);
7408 /* Check that the domain space of "upa" matches "space".
7410 * This function is called from isl_multi_union_pw_aff_set_union_pw_aff and
7411 * can in principle never fail since the space "space" is that
7412 * of the isl_multi_union_pw_aff and is a set space such that
7413 * there is no domain space to match.
7415 * We check the parameters and double-check that "space" is
7416 * indeed that of a set.
7418 static isl_stat isl_union_pw_aff_check_match_domain_space(
7419 __isl_keep isl_union_pw_aff *upa, __isl_keep isl_space *space)
7421 isl_space *upa_space;
7422 isl_bool match;
7424 if (!upa || !space)
7425 return isl_stat_error;
7427 match = isl_space_is_set(space);
7428 if (match < 0)
7429 return isl_stat_error;
7430 if (!match)
7431 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7432 "expecting set space", return -1);
7434 upa_space = isl_union_pw_aff_get_space(upa);
7435 match = isl_space_has_equal_params(space, upa_space);
7436 if (match < 0)
7437 goto error;
7438 if (!match)
7439 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7440 "parameters don't match", goto error);
7442 isl_space_free(upa_space);
7443 return isl_stat_ok;
7444 error:
7445 isl_space_free(upa_space);
7446 return isl_stat_error;
7449 /* Do the parameters of "upa" match those of "space"?
7451 static isl_bool isl_union_pw_aff_matching_params(
7452 __isl_keep isl_union_pw_aff *upa, __isl_keep isl_space *space)
7454 isl_space *upa_space;
7455 isl_bool match;
7457 if (!upa || !space)
7458 return isl_bool_error;
7460 upa_space = isl_union_pw_aff_get_space(upa);
7462 match = isl_space_has_equal_params(space, upa_space);
7464 isl_space_free(upa_space);
7465 return match;
7468 /* Internal data structure for isl_union_pw_aff_reset_domain_space.
7469 * space represents the new parameters.
7470 * res collects the results.
7472 struct isl_union_pw_aff_reset_params_data {
7473 isl_space *space;
7474 isl_union_pw_aff *res;
7477 /* Replace the parameters of "pa" by data->space and
7478 * add the result to data->res.
7480 static isl_stat reset_params(__isl_take isl_pw_aff *pa, void *user)
7482 struct isl_union_pw_aff_reset_params_data *data = user;
7483 isl_space *space;
7485 space = isl_pw_aff_get_space(pa);
7486 space = isl_space_replace(space, isl_dim_param, data->space);
7487 pa = isl_pw_aff_reset_space(pa, space);
7488 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7490 return data->res ? isl_stat_ok : isl_stat_error;
7493 /* Replace the domain space of "upa" by "space".
7494 * Since a union expression does not have a (single) domain space,
7495 * "space" is necessarily a parameter space.
7497 * Since the order and the names of the parameters determine
7498 * the hash value, we need to create a new hash table.
7500 static __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_domain_space(
7501 __isl_take isl_union_pw_aff *upa, __isl_take isl_space *space)
7503 struct isl_union_pw_aff_reset_params_data data = { space };
7504 isl_bool match;
7506 match = isl_union_pw_aff_matching_params(upa, space);
7507 if (match < 0)
7508 upa = isl_union_pw_aff_free(upa);
7509 else if (match) {
7510 isl_space_free(space);
7511 return upa;
7514 data.res = isl_union_pw_aff_empty(isl_space_copy(space));
7515 if (isl_union_pw_aff_foreach_pw_aff(upa, &reset_params, &data) < 0)
7516 data.res = isl_union_pw_aff_free(data.res);
7518 isl_union_pw_aff_free(upa);
7519 isl_space_free(space);
7520 return data.res;
7523 /* Return the floor of "pa".
7525 static __isl_give isl_pw_aff *floor_entry(__isl_take isl_pw_aff *pa, void *user)
7527 return isl_pw_aff_floor(pa);
7530 /* Given f, return floor(f).
7532 __isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
7533 __isl_take isl_union_pw_aff *upa)
7535 return isl_union_pw_aff_transform_inplace(upa, &floor_entry, NULL);
7538 /* Compute
7540 * upa mod m = upa - m * floor(upa/m)
7542 * with m an integer value.
7544 __isl_give isl_union_pw_aff *isl_union_pw_aff_mod_val(
7545 __isl_take isl_union_pw_aff *upa, __isl_take isl_val *m)
7547 isl_union_pw_aff *res;
7549 if (!upa || !m)
7550 goto error;
7552 if (!isl_val_is_int(m))
7553 isl_die(isl_val_get_ctx(m), isl_error_invalid,
7554 "expecting integer modulo", goto error);
7555 if (!isl_val_is_pos(m))
7556 isl_die(isl_val_get_ctx(m), isl_error_invalid,
7557 "expecting positive modulo", goto error);
7559 res = isl_union_pw_aff_copy(upa);
7560 upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(m));
7561 upa = isl_union_pw_aff_floor(upa);
7562 upa = isl_union_pw_aff_scale_val(upa, m);
7563 res = isl_union_pw_aff_sub(res, upa);
7565 return res;
7566 error:
7567 isl_val_free(m);
7568 isl_union_pw_aff_free(upa);
7569 return NULL;
7572 /* Internal data structure for isl_union_pw_aff_aff_on_domain.
7573 * "aff" is the symbolic value that the resulting isl_union_pw_aff
7574 * needs to attain.
7575 * "res" collects the results.
7577 struct isl_union_pw_aff_aff_on_domain_data {
7578 isl_aff *aff;
7579 isl_union_pw_aff *res;
7582 /* Construct a piecewise affine expression that is equal to data->aff
7583 * on "domain" and add the result to data->res.
7585 static isl_stat pw_aff_aff_on_domain(__isl_take isl_set *domain, void *user)
7587 struct isl_union_pw_aff_aff_on_domain_data *data = user;
7588 isl_pw_aff *pa;
7589 isl_aff *aff;
7590 int dim;
7592 aff = isl_aff_copy(data->aff);
7593 dim = isl_set_dim(domain, isl_dim_set);
7594 aff = isl_aff_add_dims(aff, isl_dim_in, dim);
7595 aff = isl_aff_reset_domain_space(aff, isl_set_get_space(domain));
7596 pa = isl_pw_aff_alloc(domain, aff);
7597 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7599 return data->res ? isl_stat_ok : isl_stat_error;
7602 /* Internal data structure for isl_union_pw_multi_aff_get_union_pw_aff.
7603 * pos is the output position that needs to be extracted.
7604 * res collects the results.
7606 struct isl_union_pw_multi_aff_get_union_pw_aff_data {
7607 int pos;
7608 isl_union_pw_aff *res;
7611 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma"
7612 * (assuming it has such a dimension) and add it to data->res.
7614 static isl_stat get_union_pw_aff(__isl_take isl_pw_multi_aff *pma, void *user)
7616 struct isl_union_pw_multi_aff_get_union_pw_aff_data *data = user;
7617 int n_out;
7618 isl_pw_aff *pa;
7620 if (!pma)
7621 return isl_stat_error;
7623 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
7624 if (data->pos >= n_out) {
7625 isl_pw_multi_aff_free(pma);
7626 return isl_stat_ok;
7629 pa = isl_pw_multi_aff_get_pw_aff(pma, data->pos);
7630 isl_pw_multi_aff_free(pma);
7632 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7634 return data->res ? isl_stat_ok : isl_stat_error;
7637 /* Extract an isl_union_pw_aff corresponding to
7638 * output dimension "pos" of "upma".
7640 __isl_give isl_union_pw_aff *isl_union_pw_multi_aff_get_union_pw_aff(
7641 __isl_keep isl_union_pw_multi_aff *upma, int pos)
7643 struct isl_union_pw_multi_aff_get_union_pw_aff_data data;
7644 isl_space *space;
7646 if (!upma)
7647 return NULL;
7649 if (pos < 0)
7650 isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
7651 "cannot extract at negative position", return NULL);
7653 space = isl_union_pw_multi_aff_get_space(upma);
7654 data.res = isl_union_pw_aff_empty(space);
7655 data.pos = pos;
7656 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
7657 &get_union_pw_aff, &data) < 0)
7658 data.res = isl_union_pw_aff_free(data.res);
7660 return data.res;
7663 /* Return a union piecewise affine expression
7664 * that is equal to "aff" on "domain".
7666 * Construct an isl_pw_aff on each of the sets in "domain" and
7667 * collect the results.
7669 __isl_give isl_union_pw_aff *isl_union_pw_aff_aff_on_domain(
7670 __isl_take isl_union_set *domain, __isl_take isl_aff *aff)
7672 struct isl_union_pw_aff_aff_on_domain_data data;
7673 isl_space *space;
7675 if (!domain || !aff)
7676 goto error;
7677 if (!isl_local_space_is_params(aff->ls))
7678 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
7679 "expecting parametric expression", goto error);
7681 space = isl_union_set_get_space(domain);
7682 data.res = isl_union_pw_aff_empty(space);
7683 data.aff = aff;
7684 if (isl_union_set_foreach_set(domain, &pw_aff_aff_on_domain, &data) < 0)
7685 data.res = isl_union_pw_aff_free(data.res);
7686 isl_union_set_free(domain);
7687 isl_aff_free(aff);
7688 return data.res;
7689 error:
7690 isl_union_set_free(domain);
7691 isl_aff_free(aff);
7692 return NULL;
7695 /* Internal data structure for isl_union_pw_aff_val_on_domain.
7696 * "v" is the value that the resulting isl_union_pw_aff needs to attain.
7697 * "res" collects the results.
7699 struct isl_union_pw_aff_val_on_domain_data {
7700 isl_val *v;
7701 isl_union_pw_aff *res;
7704 /* Construct a piecewise affine expression that is equal to data->v
7705 * on "domain" and add the result to data->res.
7707 static isl_stat pw_aff_val_on_domain(__isl_take isl_set *domain, void *user)
7709 struct isl_union_pw_aff_val_on_domain_data *data = user;
7710 isl_pw_aff *pa;
7711 isl_val *v;
7713 v = isl_val_copy(data->v);
7714 pa = isl_pw_aff_val_on_domain(domain, v);
7715 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7717 return data->res ? isl_stat_ok : isl_stat_error;
7720 /* Return a union piecewise affine expression
7721 * that is equal to "v" on "domain".
7723 * Construct an isl_pw_aff on each of the sets in "domain" and
7724 * collect the results.
7726 __isl_give isl_union_pw_aff *isl_union_pw_aff_val_on_domain(
7727 __isl_take isl_union_set *domain, __isl_take isl_val *v)
7729 struct isl_union_pw_aff_val_on_domain_data data;
7730 isl_space *space;
7732 space = isl_union_set_get_space(domain);
7733 data.res = isl_union_pw_aff_empty(space);
7734 data.v = v;
7735 if (isl_union_set_foreach_set(domain, &pw_aff_val_on_domain, &data) < 0)
7736 data.res = isl_union_pw_aff_free(data.res);
7737 isl_union_set_free(domain);
7738 isl_val_free(v);
7739 return data.res;
7742 /* Construct a piecewise multi affine expression
7743 * that is equal to "pa" and add it to upma.
7745 static isl_stat pw_multi_aff_from_pw_aff_entry(__isl_take isl_pw_aff *pa,
7746 void *user)
7748 isl_union_pw_multi_aff **upma = user;
7749 isl_pw_multi_aff *pma;
7751 pma = isl_pw_multi_aff_from_pw_aff(pa);
7752 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
7754 return *upma ? isl_stat_ok : isl_stat_error;
7757 /* Construct and return a union piecewise multi affine expression
7758 * that is equal to the given union piecewise affine expression.
7760 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_pw_aff(
7761 __isl_take isl_union_pw_aff *upa)
7763 isl_space *space;
7764 isl_union_pw_multi_aff *upma;
7766 if (!upa)
7767 return NULL;
7769 space = isl_union_pw_aff_get_space(upa);
7770 upma = isl_union_pw_multi_aff_empty(space);
7772 if (isl_union_pw_aff_foreach_pw_aff(upa,
7773 &pw_multi_aff_from_pw_aff_entry, &upma) < 0)
7774 upma = isl_union_pw_multi_aff_free(upma);
7776 isl_union_pw_aff_free(upa);
7777 return upma;
7780 /* Compute the set of elements in the domain of "pa" where it is zero and
7781 * add this set to "uset".
7783 static isl_stat zero_union_set(__isl_take isl_pw_aff *pa, void *user)
7785 isl_union_set **uset = (isl_union_set **)user;
7787 *uset = isl_union_set_add_set(*uset, isl_pw_aff_zero_set(pa));
7789 return *uset ? isl_stat_ok : isl_stat_error;
7792 /* Return a union set containing those elements in the domain
7793 * of "upa" where it is zero.
7795 __isl_give isl_union_set *isl_union_pw_aff_zero_union_set(
7796 __isl_take isl_union_pw_aff *upa)
7798 isl_union_set *zero;
7800 zero = isl_union_set_empty(isl_union_pw_aff_get_space(upa));
7801 if (isl_union_pw_aff_foreach_pw_aff(upa, &zero_union_set, &zero) < 0)
7802 zero = isl_union_set_free(zero);
7804 isl_union_pw_aff_free(upa);
7805 return zero;
7808 /* Convert "pa" to an isl_map and add it to *umap.
7810 static isl_stat map_from_pw_aff_entry(__isl_take isl_pw_aff *pa, void *user)
7812 isl_union_map **umap = user;
7813 isl_map *map;
7815 map = isl_map_from_pw_aff(pa);
7816 *umap = isl_union_map_add_map(*umap, map);
7818 return *umap ? isl_stat_ok : isl_stat_error;
7821 /* Construct a union map mapping the domain of the union
7822 * piecewise affine expression to its range, with the single output dimension
7823 * equated to the corresponding affine expressions on their cells.
7825 __isl_give isl_union_map *isl_union_map_from_union_pw_aff(
7826 __isl_take isl_union_pw_aff *upa)
7828 isl_space *space;
7829 isl_union_map *umap;
7831 if (!upa)
7832 return NULL;
7834 space = isl_union_pw_aff_get_space(upa);
7835 umap = isl_union_map_empty(space);
7837 if (isl_union_pw_aff_foreach_pw_aff(upa, &map_from_pw_aff_entry,
7838 &umap) < 0)
7839 umap = isl_union_map_free(umap);
7841 isl_union_pw_aff_free(upa);
7842 return umap;
7845 /* Internal data structure for isl_union_pw_aff_pullback_union_pw_multi_aff.
7846 * upma is the function that is plugged in.
7847 * pa is the current part of the function in which upma is plugged in.
7848 * res collects the results.
7850 struct isl_union_pw_aff_pullback_upma_data {
7851 isl_union_pw_multi_aff *upma;
7852 isl_pw_aff *pa;
7853 isl_union_pw_aff *res;
7856 /* Check if "pma" can be plugged into data->pa.
7857 * If so, perform the pullback and add the result to data->res.
7859 static isl_stat pa_pb_pma(__isl_take isl_pw_multi_aff *pma, void *user)
7861 struct isl_union_pw_aff_pullback_upma_data *data = user;
7862 isl_pw_aff *pa;
7864 if (!isl_space_tuple_is_equal(data->pa->dim, isl_dim_in,
7865 pma->dim, isl_dim_out)) {
7866 isl_pw_multi_aff_free(pma);
7867 return isl_stat_ok;
7870 pa = isl_pw_aff_copy(data->pa);
7871 pa = isl_pw_aff_pullback_pw_multi_aff(pa, pma);
7873 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7875 return data->res ? isl_stat_ok : isl_stat_error;
7878 /* Check if any of the elements of data->upma can be plugged into pa,
7879 * add if so add the result to data->res.
7881 static isl_stat upa_pb_upma(__isl_take isl_pw_aff *pa, void *user)
7883 struct isl_union_pw_aff_pullback_upma_data *data = user;
7884 isl_stat r;
7886 data->pa = pa;
7887 r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma,
7888 &pa_pb_pma, data);
7889 isl_pw_aff_free(pa);
7891 return r;
7894 /* Compute the pullback of "upa" by the function represented by "upma".
7895 * In other words, plug in "upma" in "upa". The result contains
7896 * expressions defined over the domain space of "upma".
7898 * Run over all pairs of elements in "upa" and "upma", perform
7899 * the pullback when appropriate and collect the results.
7900 * If the hash value were based on the domain space rather than
7901 * the function space, then we could run through all elements
7902 * of "upma" and directly pick out the corresponding element of "upa".
7904 __isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
7905 __isl_take isl_union_pw_aff *upa,
7906 __isl_take isl_union_pw_multi_aff *upma)
7908 struct isl_union_pw_aff_pullback_upma_data data = { NULL, NULL };
7909 isl_space *space;
7911 space = isl_union_pw_multi_aff_get_space(upma);
7912 upa = isl_union_pw_aff_align_params(upa, space);
7913 space = isl_union_pw_aff_get_space(upa);
7914 upma = isl_union_pw_multi_aff_align_params(upma, space);
7916 if (!upa || !upma)
7917 goto error;
7919 data.upma = upma;
7920 data.res = isl_union_pw_aff_alloc_same_size(upa);
7921 if (isl_union_pw_aff_foreach_pw_aff(upa, &upa_pb_upma, &data) < 0)
7922 data.res = isl_union_pw_aff_free(data.res);
7924 isl_union_pw_aff_free(upa);
7925 isl_union_pw_multi_aff_free(upma);
7926 return data.res;
7927 error:
7928 isl_union_pw_aff_free(upa);
7929 isl_union_pw_multi_aff_free(upma);
7930 return NULL;
7933 #undef BASE
7934 #define BASE union_pw_aff
7935 #undef DOMBASE
7936 #define DOMBASE union_set
7938 #define NO_MOVE_DIMS
7939 #define NO_DIMS
7940 #define NO_DOMAIN
7941 #define NO_PRODUCT
7942 #define NO_SPLICE
7943 #define NO_ZERO
7944 #define NO_IDENTITY
7945 #define NO_GIST
7947 #include <isl_multi_templ.c>
7948 #include <isl_multi_apply_set.c>
7949 #include <isl_multi_apply_union_set.c>
7950 #include <isl_multi_coalesce.c>
7951 #include <isl_multi_floor.c>
7952 #include <isl_multi_gist.c>
7953 #include <isl_multi_intersect.c>
7955 /* Construct a multiple union piecewise affine expression
7956 * in the given space with value zero in each of the output dimensions.
7958 * Since there is no canonical zero value for
7959 * a union piecewise affine expression, we can only construct
7960 * zero-dimensional "zero" value.
7962 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_zero(
7963 __isl_take isl_space *space)
7965 if (!space)
7966 return NULL;
7968 if (!isl_space_is_set(space))
7969 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7970 "expecting set space", goto error);
7971 if (isl_space_dim(space , isl_dim_out) != 0)
7972 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7973 "expecting 0D space", goto error);
7975 return isl_multi_union_pw_aff_alloc(space);
7976 error:
7977 isl_space_free(space);
7978 return NULL;
7981 /* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
7982 * with the actual sum on the shared domain and
7983 * the defined expression on the symmetric difference of the domains.
7985 * We simply iterate over the elements in both arguments and
7986 * call isl_union_pw_aff_union_add on each of them.
7988 static __isl_give isl_multi_union_pw_aff *
7989 isl_multi_union_pw_aff_union_add_aligned(
7990 __isl_take isl_multi_union_pw_aff *mupa1,
7991 __isl_take isl_multi_union_pw_aff *mupa2)
7993 return isl_multi_union_pw_aff_bin_op(mupa1, mupa2,
7994 &isl_union_pw_aff_union_add);
7997 /* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
7998 * with the actual sum on the shared domain and
7999 * the defined expression on the symmetric difference of the domains.
8001 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_union_add(
8002 __isl_take isl_multi_union_pw_aff *mupa1,
8003 __isl_take isl_multi_union_pw_aff *mupa2)
8005 return isl_multi_union_pw_aff_align_params_multi_multi_and(mupa1, mupa2,
8006 &isl_multi_union_pw_aff_union_add_aligned);
8009 /* Construct and return a multi union piecewise affine expression
8010 * that is equal to the given multi affine expression.
8012 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff(
8013 __isl_take isl_multi_aff *ma)
8015 isl_multi_pw_aff *mpa;
8017 mpa = isl_multi_pw_aff_from_multi_aff(ma);
8018 return isl_multi_union_pw_aff_from_multi_pw_aff(mpa);
8021 /* Construct and return a multi union piecewise affine expression
8022 * that is equal to the given multi piecewise affine expression.
8024 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff(
8025 __isl_take isl_multi_pw_aff *mpa)
8027 int i, n;
8028 isl_space *space;
8029 isl_multi_union_pw_aff *mupa;
8031 if (!mpa)
8032 return NULL;
8034 space = isl_multi_pw_aff_get_space(mpa);
8035 space = isl_space_range(space);
8036 mupa = isl_multi_union_pw_aff_alloc(space);
8038 n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
8039 for (i = 0; i < n; ++i) {
8040 isl_pw_aff *pa;
8041 isl_union_pw_aff *upa;
8043 pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
8044 upa = isl_union_pw_aff_from_pw_aff(pa);
8045 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8048 isl_multi_pw_aff_free(mpa);
8050 return mupa;
8053 /* Extract the range space of "pma" and assign it to *space.
8054 * If *space has already been set (through a previous call to this function),
8055 * then check that the range space is the same.
8057 static isl_stat extract_space(__isl_take isl_pw_multi_aff *pma, void *user)
8059 isl_space **space = user;
8060 isl_space *pma_space;
8061 isl_bool equal;
8063 pma_space = isl_space_range(isl_pw_multi_aff_get_space(pma));
8064 isl_pw_multi_aff_free(pma);
8066 if (!pma_space)
8067 return isl_stat_error;
8068 if (!*space) {
8069 *space = pma_space;
8070 return isl_stat_ok;
8073 equal = isl_space_is_equal(pma_space, *space);
8074 isl_space_free(pma_space);
8076 if (equal < 0)
8077 return isl_stat_error;
8078 if (!equal)
8079 isl_die(isl_space_get_ctx(*space), isl_error_invalid,
8080 "range spaces not the same", return isl_stat_error);
8081 return isl_stat_ok;
8084 /* Construct and return a multi union piecewise affine expression
8085 * that is equal to the given union piecewise multi affine expression.
8087 * In order to be able to perform the conversion, the input
8088 * needs to be non-empty and may only involve a single range space.
8090 __isl_give isl_multi_union_pw_aff *
8091 isl_multi_union_pw_aff_from_union_pw_multi_aff(
8092 __isl_take isl_union_pw_multi_aff *upma)
8094 isl_space *space = NULL;
8095 isl_multi_union_pw_aff *mupa;
8096 int i, n;
8098 if (!upma)
8099 return NULL;
8100 if (isl_union_pw_multi_aff_n_pw_multi_aff(upma) == 0)
8101 isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
8102 "cannot extract range space from empty input",
8103 goto error);
8104 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, &extract_space,
8105 &space) < 0)
8106 goto error;
8108 if (!space)
8109 goto error;
8111 n = isl_space_dim(space, isl_dim_set);
8112 mupa = isl_multi_union_pw_aff_alloc(space);
8114 for (i = 0; i < n; ++i) {
8115 isl_union_pw_aff *upa;
8117 upa = isl_union_pw_multi_aff_get_union_pw_aff(upma, i);
8118 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8121 isl_union_pw_multi_aff_free(upma);
8122 return mupa;
8123 error:
8124 isl_space_free(space);
8125 isl_union_pw_multi_aff_free(upma);
8126 return NULL;
8129 /* Try and create an isl_multi_union_pw_aff that is equivalent
8130 * to the given isl_union_map.
8131 * The isl_union_map is required to be single-valued in each space.
8132 * Moreover, it cannot be empty and all range spaces need to be the same.
8133 * Otherwise, an error is produced.
8135 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_map(
8136 __isl_take isl_union_map *umap)
8138 isl_union_pw_multi_aff *upma;
8140 upma = isl_union_pw_multi_aff_from_union_map(umap);
8141 return isl_multi_union_pw_aff_from_union_pw_multi_aff(upma);
8144 /* Return a multiple union piecewise affine expression
8145 * that is equal to "mv" on "domain", assuming "domain" and "mv"
8146 * have been aligned.
8148 static __isl_give isl_multi_union_pw_aff *
8149 isl_multi_union_pw_aff_multi_val_on_domain_aligned(
8150 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
8152 int i, n;
8153 isl_space *space;
8154 isl_multi_union_pw_aff *mupa;
8156 if (!domain || !mv)
8157 goto error;
8159 n = isl_multi_val_dim(mv, isl_dim_set);
8160 space = isl_multi_val_get_space(mv);
8161 mupa = isl_multi_union_pw_aff_alloc(space);
8162 for (i = 0; i < n; ++i) {
8163 isl_val *v;
8164 isl_union_pw_aff *upa;
8166 v = isl_multi_val_get_val(mv, i);
8167 upa = isl_union_pw_aff_val_on_domain(isl_union_set_copy(domain),
8169 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8172 isl_union_set_free(domain);
8173 isl_multi_val_free(mv);
8174 return mupa;
8175 error:
8176 isl_union_set_free(domain);
8177 isl_multi_val_free(mv);
8178 return NULL;
8181 /* Return a multiple union piecewise affine expression
8182 * that is equal to "mv" on "domain".
8184 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_val_on_domain(
8185 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
8187 isl_bool equal_params;
8189 if (!domain || !mv)
8190 goto error;
8191 equal_params = isl_space_has_equal_params(domain->dim, mv->space);
8192 if (equal_params < 0)
8193 goto error;
8194 if (equal_params)
8195 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(
8196 domain, mv);
8197 domain = isl_union_set_align_params(domain,
8198 isl_multi_val_get_space(mv));
8199 mv = isl_multi_val_align_params(mv, isl_union_set_get_space(domain));
8200 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(domain, mv);
8201 error:
8202 isl_union_set_free(domain);
8203 isl_multi_val_free(mv);
8204 return NULL;
8207 /* Return a multiple union piecewise affine expression
8208 * that is equal to "ma" on "domain", assuming "domain" and "ma"
8209 * have been aligned.
8211 static __isl_give isl_multi_union_pw_aff *
8212 isl_multi_union_pw_aff_multi_aff_on_domain_aligned(
8213 __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma)
8215 int i, n;
8216 isl_space *space;
8217 isl_multi_union_pw_aff *mupa;
8219 if (!domain || !ma)
8220 goto error;
8222 n = isl_multi_aff_dim(ma, isl_dim_set);
8223 space = isl_multi_aff_get_space(ma);
8224 mupa = isl_multi_union_pw_aff_alloc(space);
8225 for (i = 0; i < n; ++i) {
8226 isl_aff *aff;
8227 isl_union_pw_aff *upa;
8229 aff = isl_multi_aff_get_aff(ma, i);
8230 upa = isl_union_pw_aff_aff_on_domain(isl_union_set_copy(domain),
8231 aff);
8232 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8235 isl_union_set_free(domain);
8236 isl_multi_aff_free(ma);
8237 return mupa;
8238 error:
8239 isl_union_set_free(domain);
8240 isl_multi_aff_free(ma);
8241 return NULL;
8244 /* Return a multiple union piecewise affine expression
8245 * that is equal to "ma" on "domain".
8247 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_aff_on_domain(
8248 __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma)
8250 isl_bool equal_params;
8252 if (!domain || !ma)
8253 goto error;
8254 equal_params = isl_space_has_equal_params(domain->dim, ma->space);
8255 if (equal_params < 0)
8256 goto error;
8257 if (equal_params)
8258 return isl_multi_union_pw_aff_multi_aff_on_domain_aligned(
8259 domain, ma);
8260 domain = isl_union_set_align_params(domain,
8261 isl_multi_aff_get_space(ma));
8262 ma = isl_multi_aff_align_params(ma, isl_union_set_get_space(domain));
8263 return isl_multi_union_pw_aff_multi_aff_on_domain_aligned(domain, ma);
8264 error:
8265 isl_union_set_free(domain);
8266 isl_multi_aff_free(ma);
8267 return NULL;
8270 /* Return a union set containing those elements in the domains
8271 * of the elements of "mupa" where they are all zero.
8273 __isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
8274 __isl_take isl_multi_union_pw_aff *mupa)
8276 int i, n;
8277 isl_union_pw_aff *upa;
8278 isl_union_set *zero;
8280 if (!mupa)
8281 return NULL;
8283 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8284 if (n == 0)
8285 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8286 "cannot determine zero set "
8287 "of zero-dimensional function", goto error);
8289 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8290 zero = isl_union_pw_aff_zero_union_set(upa);
8292 for (i = 1; i < n; ++i) {
8293 isl_union_set *zero_i;
8295 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8296 zero_i = isl_union_pw_aff_zero_union_set(upa);
8298 zero = isl_union_set_intersect(zero, zero_i);
8301 isl_multi_union_pw_aff_free(mupa);
8302 return zero;
8303 error:
8304 isl_multi_union_pw_aff_free(mupa);
8305 return NULL;
8308 /* Construct a union map mapping the shared domain
8309 * of the union piecewise affine expressions to the range of "mupa"
8310 * with each dimension in the range equated to the
8311 * corresponding union piecewise affine expression.
8313 * The input cannot be zero-dimensional as there is
8314 * no way to extract a domain from a zero-dimensional isl_multi_union_pw_aff.
8316 __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
8317 __isl_take isl_multi_union_pw_aff *mupa)
8319 int i, n;
8320 isl_space *space;
8321 isl_union_map *umap;
8322 isl_union_pw_aff *upa;
8324 if (!mupa)
8325 return NULL;
8327 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8328 if (n == 0)
8329 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8330 "cannot determine domain of zero-dimensional "
8331 "isl_multi_union_pw_aff", goto error);
8333 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8334 umap = isl_union_map_from_union_pw_aff(upa);
8336 for (i = 1; i < n; ++i) {
8337 isl_union_map *umap_i;
8339 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8340 umap_i = isl_union_map_from_union_pw_aff(upa);
8341 umap = isl_union_map_flat_range_product(umap, umap_i);
8344 space = isl_multi_union_pw_aff_get_space(mupa);
8345 umap = isl_union_map_reset_range_space(umap, space);
8347 isl_multi_union_pw_aff_free(mupa);
8348 return umap;
8349 error:
8350 isl_multi_union_pw_aff_free(mupa);
8351 return NULL;
8354 /* Internal data structure for isl_union_pw_multi_aff_reset_range_space.
8355 * "range" is the space from which to set the range space.
8356 * "res" collects the results.
8358 struct isl_union_pw_multi_aff_reset_range_space_data {
8359 isl_space *range;
8360 isl_union_pw_multi_aff *res;
8363 /* Replace the range space of "pma" by the range space of data->range and
8364 * add the result to data->res.
8366 static isl_stat reset_range_space(__isl_take isl_pw_multi_aff *pma, void *user)
8368 struct isl_union_pw_multi_aff_reset_range_space_data *data = user;
8369 isl_space *space;
8371 space = isl_pw_multi_aff_get_space(pma);
8372 space = isl_space_domain(space);
8373 space = isl_space_extend_domain_with_range(space,
8374 isl_space_copy(data->range));
8375 pma = isl_pw_multi_aff_reset_space(pma, space);
8376 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
8378 return data->res ? isl_stat_ok : isl_stat_error;
8381 /* Replace the range space of all the piecewise affine expressions in "upma" by
8382 * the range space of "space".
8384 * This assumes that all these expressions have the same output dimension.
8386 * Since the spaces of the expressions change, so do their hash values.
8387 * We therefore need to create a new isl_union_pw_multi_aff.
8388 * Note that the hash value is currently computed based on the entire
8389 * space even though there can only be a single expression with a given
8390 * domain space.
8392 static __isl_give isl_union_pw_multi_aff *
8393 isl_union_pw_multi_aff_reset_range_space(
8394 __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *space)
8396 struct isl_union_pw_multi_aff_reset_range_space_data data = { space };
8397 isl_space *space_upma;
8399 space_upma = isl_union_pw_multi_aff_get_space(upma);
8400 data.res = isl_union_pw_multi_aff_empty(space_upma);
8401 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
8402 &reset_range_space, &data) < 0)
8403 data.res = isl_union_pw_multi_aff_free(data.res);
8405 isl_space_free(space);
8406 isl_union_pw_multi_aff_free(upma);
8407 return data.res;
8410 /* Construct and return a union piecewise multi affine expression
8411 * that is equal to the given multi union piecewise affine expression.
8413 * In order to be able to perform the conversion, the input
8414 * needs to have a least one output dimension.
8416 __isl_give isl_union_pw_multi_aff *
8417 isl_union_pw_multi_aff_from_multi_union_pw_aff(
8418 __isl_take isl_multi_union_pw_aff *mupa)
8420 int i, n;
8421 isl_space *space;
8422 isl_union_pw_multi_aff *upma;
8423 isl_union_pw_aff *upa;
8425 if (!mupa)
8426 return NULL;
8428 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8429 if (n == 0)
8430 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8431 "cannot determine domain of zero-dimensional "
8432 "isl_multi_union_pw_aff", goto error);
8434 space = isl_multi_union_pw_aff_get_space(mupa);
8435 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8436 upma = isl_union_pw_multi_aff_from_union_pw_aff(upa);
8438 for (i = 1; i < n; ++i) {
8439 isl_union_pw_multi_aff *upma_i;
8441 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8442 upma_i = isl_union_pw_multi_aff_from_union_pw_aff(upa);
8443 upma = isl_union_pw_multi_aff_flat_range_product(upma, upma_i);
8446 upma = isl_union_pw_multi_aff_reset_range_space(upma, space);
8448 isl_multi_union_pw_aff_free(mupa);
8449 return upma;
8450 error:
8451 isl_multi_union_pw_aff_free(mupa);
8452 return NULL;
8455 /* Intersect the range of "mupa" with "range".
8456 * That is, keep only those domain elements that have a function value
8457 * in "range".
8459 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
8460 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *range)
8462 isl_union_pw_multi_aff *upma;
8463 isl_union_set *domain;
8464 isl_space *space;
8465 int n;
8466 int match;
8468 if (!mupa || !range)
8469 goto error;
8471 space = isl_set_get_space(range);
8472 match = isl_space_tuple_is_equal(mupa->space, isl_dim_set,
8473 space, isl_dim_set);
8474 isl_space_free(space);
8475 if (match < 0)
8476 goto error;
8477 if (!match)
8478 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8479 "space don't match", goto error);
8480 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8481 if (n == 0)
8482 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8483 "cannot intersect range of zero-dimensional "
8484 "isl_multi_union_pw_aff", goto error);
8486 upma = isl_union_pw_multi_aff_from_multi_union_pw_aff(
8487 isl_multi_union_pw_aff_copy(mupa));
8488 domain = isl_union_set_from_set(range);
8489 domain = isl_union_set_preimage_union_pw_multi_aff(domain, upma);
8490 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, domain);
8492 return mupa;
8493 error:
8494 isl_multi_union_pw_aff_free(mupa);
8495 isl_set_free(range);
8496 return NULL;
8499 /* Return the shared domain of the elements of "mupa".
8501 __isl_give isl_union_set *isl_multi_union_pw_aff_domain(
8502 __isl_take isl_multi_union_pw_aff *mupa)
8504 int i, n;
8505 isl_union_pw_aff *upa;
8506 isl_union_set *dom;
8508 if (!mupa)
8509 return NULL;
8511 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8512 if (n == 0)
8513 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8514 "cannot determine domain", goto error);
8516 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8517 dom = isl_union_pw_aff_domain(upa);
8518 for (i = 1; i < n; ++i) {
8519 isl_union_set *dom_i;
8521 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8522 dom_i = isl_union_pw_aff_domain(upa);
8523 dom = isl_union_set_intersect(dom, dom_i);
8526 isl_multi_union_pw_aff_free(mupa);
8527 return dom;
8528 error:
8529 isl_multi_union_pw_aff_free(mupa);
8530 return NULL;
8533 /* Apply "aff" to "mupa". The space of "mupa" is equal to the domain of "aff".
8534 * In particular, the spaces have been aligned.
8535 * The result is defined over the shared domain of the elements of "mupa"
8537 * We first extract the parametric constant part of "aff" and
8538 * define that over the shared domain.
8539 * Then we iterate over all input dimensions of "aff" and add the corresponding
8540 * multiples of the elements of "mupa".
8541 * Finally, we consider the integer divisions, calling the function
8542 * recursively to obtain an isl_union_pw_aff corresponding to the
8543 * integer division argument.
8545 static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff(
8546 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
8548 int i, n_in, n_div;
8549 isl_union_pw_aff *upa;
8550 isl_union_set *uset;
8551 isl_val *v;
8552 isl_aff *cst;
8554 n_in = isl_aff_dim(aff, isl_dim_in);
8555 n_div = isl_aff_dim(aff, isl_dim_div);
8557 uset = isl_multi_union_pw_aff_domain(isl_multi_union_pw_aff_copy(mupa));
8558 cst = isl_aff_copy(aff);
8559 cst = isl_aff_drop_dims(cst, isl_dim_div, 0, n_div);
8560 cst = isl_aff_drop_dims(cst, isl_dim_in, 0, n_in);
8561 cst = isl_aff_project_domain_on_params(cst);
8562 upa = isl_union_pw_aff_aff_on_domain(uset, cst);
8564 for (i = 0; i < n_in; ++i) {
8565 isl_union_pw_aff *upa_i;
8567 if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
8568 continue;
8569 v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
8570 upa_i = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8571 upa_i = isl_union_pw_aff_scale_val(upa_i, v);
8572 upa = isl_union_pw_aff_add(upa, upa_i);
8575 for (i = 0; i < n_div; ++i) {
8576 isl_aff *div;
8577 isl_union_pw_aff *upa_i;
8579 if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
8580 continue;
8581 div = isl_aff_get_div(aff, i);
8582 upa_i = multi_union_pw_aff_apply_aff(
8583 isl_multi_union_pw_aff_copy(mupa), div);
8584 upa_i = isl_union_pw_aff_floor(upa_i);
8585 v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
8586 upa_i = isl_union_pw_aff_scale_val(upa_i, v);
8587 upa = isl_union_pw_aff_add(upa, upa_i);
8590 isl_multi_union_pw_aff_free(mupa);
8591 isl_aff_free(aff);
8593 return upa;
8596 /* Apply "aff" to "mupa". The space of "mupa" needs to be compatible
8597 * with the domain of "aff".
8598 * Furthermore, the dimension of this space needs to be greater than zero.
8599 * The result is defined over the shared domain of the elements of "mupa"
8601 * We perform these checks and then hand over control to
8602 * multi_union_pw_aff_apply_aff.
8604 __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff(
8605 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
8607 isl_space *space1, *space2;
8608 int equal;
8610 mupa = isl_multi_union_pw_aff_align_params(mupa,
8611 isl_aff_get_space(aff));
8612 aff = isl_aff_align_params(aff, isl_multi_union_pw_aff_get_space(mupa));
8613 if (!mupa || !aff)
8614 goto error;
8616 space1 = isl_multi_union_pw_aff_get_space(mupa);
8617 space2 = isl_aff_get_domain_space(aff);
8618 equal = isl_space_is_equal(space1, space2);
8619 isl_space_free(space1);
8620 isl_space_free(space2);
8621 if (equal < 0)
8622 goto error;
8623 if (!equal)
8624 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
8625 "spaces don't match", goto error);
8626 if (isl_aff_dim(aff, isl_dim_in) == 0)
8627 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
8628 "cannot determine domains", goto error);
8630 return multi_union_pw_aff_apply_aff(mupa, aff);
8631 error:
8632 isl_multi_union_pw_aff_free(mupa);
8633 isl_aff_free(aff);
8634 return NULL;
8637 /* Apply "ma" to "mupa". The space of "mupa" needs to be compatible
8638 * with the domain of "ma".
8639 * Furthermore, the dimension of this space needs to be greater than zero,
8640 * unless the dimension of the target space of "ma" is also zero.
8641 * The result is defined over the shared domain of the elements of "mupa"
8643 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
8644 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma)
8646 isl_space *space1, *space2;
8647 isl_multi_union_pw_aff *res;
8648 int equal;
8649 int i, n_out;
8651 mupa = isl_multi_union_pw_aff_align_params(mupa,
8652 isl_multi_aff_get_space(ma));
8653 ma = isl_multi_aff_align_params(ma,
8654 isl_multi_union_pw_aff_get_space(mupa));
8655 if (!mupa || !ma)
8656 goto error;
8658 space1 = isl_multi_union_pw_aff_get_space(mupa);
8659 space2 = isl_multi_aff_get_domain_space(ma);
8660 equal = isl_space_is_equal(space1, space2);
8661 isl_space_free(space1);
8662 isl_space_free(space2);
8663 if (equal < 0)
8664 goto error;
8665 if (!equal)
8666 isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
8667 "spaces don't match", goto error);
8668 n_out = isl_multi_aff_dim(ma, isl_dim_out);
8669 if (isl_multi_aff_dim(ma, isl_dim_in) == 0 && n_out != 0)
8670 isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
8671 "cannot determine domains", goto error);
8673 space1 = isl_space_range(isl_multi_aff_get_space(ma));
8674 res = isl_multi_union_pw_aff_alloc(space1);
8676 for (i = 0; i < n_out; ++i) {
8677 isl_aff *aff;
8678 isl_union_pw_aff *upa;
8680 aff = isl_multi_aff_get_aff(ma, i);
8681 upa = multi_union_pw_aff_apply_aff(
8682 isl_multi_union_pw_aff_copy(mupa), aff);
8683 res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa);
8686 isl_multi_aff_free(ma);
8687 isl_multi_union_pw_aff_free(mupa);
8688 return res;
8689 error:
8690 isl_multi_union_pw_aff_free(mupa);
8691 isl_multi_aff_free(ma);
8692 return NULL;
8695 /* Apply "pa" to "mupa". The space of "mupa" needs to be compatible
8696 * with the domain of "pa".
8697 * Furthermore, the dimension of this space needs to be greater than zero.
8698 * The result is defined over the shared domain of the elements of "mupa"
8700 __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff(
8701 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa)
8703 int i;
8704 int equal;
8705 isl_space *space, *space2;
8706 isl_union_pw_aff *upa;
8708 mupa = isl_multi_union_pw_aff_align_params(mupa,
8709 isl_pw_aff_get_space(pa));
8710 pa = isl_pw_aff_align_params(pa,
8711 isl_multi_union_pw_aff_get_space(mupa));
8712 if (!mupa || !pa)
8713 goto error;
8715 space = isl_multi_union_pw_aff_get_space(mupa);
8716 space2 = isl_pw_aff_get_domain_space(pa);
8717 equal = isl_space_is_equal(space, space2);
8718 isl_space_free(space);
8719 isl_space_free(space2);
8720 if (equal < 0)
8721 goto error;
8722 if (!equal)
8723 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
8724 "spaces don't match", goto error);
8725 if (isl_pw_aff_dim(pa, isl_dim_in) == 0)
8726 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
8727 "cannot determine domains", goto error);
8729 space = isl_space_params(isl_multi_union_pw_aff_get_space(mupa));
8730 upa = isl_union_pw_aff_empty(space);
8732 for (i = 0; i < pa->n; ++i) {
8733 isl_aff *aff;
8734 isl_set *domain;
8735 isl_multi_union_pw_aff *mupa_i;
8736 isl_union_pw_aff *upa_i;
8738 mupa_i = isl_multi_union_pw_aff_copy(mupa);
8739 domain = isl_set_copy(pa->p[i].set);
8740 mupa_i = isl_multi_union_pw_aff_intersect_range(mupa_i, domain);
8741 aff = isl_aff_copy(pa->p[i].aff);
8742 upa_i = multi_union_pw_aff_apply_aff(mupa_i, aff);
8743 upa = isl_union_pw_aff_union_add(upa, upa_i);
8746 isl_multi_union_pw_aff_free(mupa);
8747 isl_pw_aff_free(pa);
8748 return upa;
8749 error:
8750 isl_multi_union_pw_aff_free(mupa);
8751 isl_pw_aff_free(pa);
8752 return NULL;
8755 /* Apply "pma" to "mupa". The space of "mupa" needs to be compatible
8756 * with the domain of "pma".
8757 * Furthermore, the dimension of this space needs to be greater than zero,
8758 * unless the dimension of the target space of "pma" is also zero.
8759 * The result is defined over the shared domain of the elements of "mupa"
8761 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
8762 __isl_take isl_multi_union_pw_aff *mupa,
8763 __isl_take isl_pw_multi_aff *pma)
8765 isl_space *space1, *space2;
8766 isl_multi_union_pw_aff *res;
8767 int equal;
8768 int i, n_out;
8770 mupa = isl_multi_union_pw_aff_align_params(mupa,
8771 isl_pw_multi_aff_get_space(pma));
8772 pma = isl_pw_multi_aff_align_params(pma,
8773 isl_multi_union_pw_aff_get_space(mupa));
8774 if (!mupa || !pma)
8775 goto error;
8777 space1 = isl_multi_union_pw_aff_get_space(mupa);
8778 space2 = isl_pw_multi_aff_get_domain_space(pma);
8779 equal = isl_space_is_equal(space1, space2);
8780 isl_space_free(space1);
8781 isl_space_free(space2);
8782 if (equal < 0)
8783 goto error;
8784 if (!equal)
8785 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
8786 "spaces don't match", goto error);
8787 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
8788 if (isl_pw_multi_aff_dim(pma, isl_dim_in) == 0 && n_out != 0)
8789 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
8790 "cannot determine domains", goto error);
8792 space1 = isl_space_range(isl_pw_multi_aff_get_space(pma));
8793 res = isl_multi_union_pw_aff_alloc(space1);
8795 for (i = 0; i < n_out; ++i) {
8796 isl_pw_aff *pa;
8797 isl_union_pw_aff *upa;
8799 pa = isl_pw_multi_aff_get_pw_aff(pma, i);
8800 upa = isl_multi_union_pw_aff_apply_pw_aff(
8801 isl_multi_union_pw_aff_copy(mupa), pa);
8802 res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa);
8805 isl_pw_multi_aff_free(pma);
8806 isl_multi_union_pw_aff_free(mupa);
8807 return res;
8808 error:
8809 isl_multi_union_pw_aff_free(mupa);
8810 isl_pw_multi_aff_free(pma);
8811 return NULL;
8814 /* Compute the pullback of "mupa" by the function represented by "upma".
8815 * In other words, plug in "upma" in "mupa". The result contains
8816 * expressions defined over the domain space of "upma".
8818 * Run over all elements of "mupa" and plug in "upma" in each of them.
8820 __isl_give isl_multi_union_pw_aff *
8821 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
8822 __isl_take isl_multi_union_pw_aff *mupa,
8823 __isl_take isl_union_pw_multi_aff *upma)
8825 int i, n;
8827 mupa = isl_multi_union_pw_aff_align_params(mupa,
8828 isl_union_pw_multi_aff_get_space(upma));
8829 upma = isl_union_pw_multi_aff_align_params(upma,
8830 isl_multi_union_pw_aff_get_space(mupa));
8831 if (!mupa || !upma)
8832 goto error;
8834 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8835 for (i = 0; i < n; ++i) {
8836 isl_union_pw_aff *upa;
8838 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8839 upa = isl_union_pw_aff_pullback_union_pw_multi_aff(upa,
8840 isl_union_pw_multi_aff_copy(upma));
8841 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8844 isl_union_pw_multi_aff_free(upma);
8845 return mupa;
8846 error:
8847 isl_multi_union_pw_aff_free(mupa);
8848 isl_union_pw_multi_aff_free(upma);
8849 return NULL;
8852 /* Extract the sequence of elements in "mupa" with domain space "space"
8853 * (ignoring parameters).
8855 * For the elements of "mupa" that are not defined on the specified space,
8856 * the corresponding element in the result is empty.
8858 __isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
8859 __isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space)
8861 int i, n;
8862 isl_bool equal_params;
8863 isl_space *space_mpa = NULL;
8864 isl_multi_pw_aff *mpa;
8866 if (!mupa || !space)
8867 goto error;
8869 space_mpa = isl_multi_union_pw_aff_get_space(mupa);
8870 equal_params = isl_space_has_equal_params(space_mpa, space);
8871 if (equal_params < 0)
8872 goto error;
8873 if (!equal_params) {
8874 space = isl_space_drop_dims(space, isl_dim_param,
8875 0, isl_space_dim(space, isl_dim_param));
8876 space = isl_space_align_params(space,
8877 isl_space_copy(space_mpa));
8878 if (!space)
8879 goto error;
8881 space_mpa = isl_space_map_from_domain_and_range(isl_space_copy(space),
8882 space_mpa);
8883 mpa = isl_multi_pw_aff_alloc(space_mpa);
8885 space = isl_space_from_domain(space);
8886 space = isl_space_add_dims(space, isl_dim_out, 1);
8887 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8888 for (i = 0; i < n; ++i) {
8889 isl_union_pw_aff *upa;
8890 isl_pw_aff *pa;
8892 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8893 pa = isl_union_pw_aff_extract_pw_aff(upa,
8894 isl_space_copy(space));
8895 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
8896 isl_union_pw_aff_free(upa);
8899 isl_space_free(space);
8900 return mpa;
8901 error:
8902 isl_space_free(space_mpa);
8903 isl_space_free(space);
8904 return NULL;