isl_pw_*_normalize: sort pieces based on function value expressions
[isl.git] / isl_aff.c
blob0682a8bd16d5b026d973bf43de514ade1d0e150e
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 reodering.
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 isl_seq_cpy(res->el, vec->el, 2);
420 isl_seq_clr(res->el + 2, res->size - 2);
421 for (i = 0; i < r->len; ++i)
422 isl_int_set(res->el[2 + r->pos[i]], vec->el[2 + i]);
424 isl_reordering_free(r);
425 isl_vec_free(vec);
426 return res;
427 error:
428 isl_vec_free(vec);
429 isl_reordering_free(r);
430 return NULL;
433 /* Reorder the dimensions of the domain of "aff" according
434 * to the given reordering.
436 __isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff,
437 __isl_take isl_reordering *r)
439 aff = isl_aff_cow(aff);
440 if (!aff)
441 goto error;
443 r = isl_reordering_extend(r, aff->ls->div->n_row);
444 aff->v = vec_reorder(aff->v, isl_reordering_copy(r),
445 aff->ls->div->n_row);
446 aff->ls = isl_local_space_realign(aff->ls, r);
448 if (!aff->v || !aff->ls)
449 return isl_aff_free(aff);
451 return aff;
452 error:
453 isl_aff_free(aff);
454 isl_reordering_free(r);
455 return NULL;
458 __isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
459 __isl_take isl_space *model)
461 if (!aff || !model)
462 goto error;
464 if (!isl_space_match(aff->ls->dim, isl_dim_param,
465 model, isl_dim_param)) {
466 isl_reordering *exp;
468 model = isl_space_drop_dims(model, isl_dim_in,
469 0, isl_space_dim(model, isl_dim_in));
470 model = isl_space_drop_dims(model, isl_dim_out,
471 0, isl_space_dim(model, isl_dim_out));
472 exp = isl_parameter_alignment_reordering(aff->ls->dim, model);
473 exp = isl_reordering_extend_space(exp,
474 isl_aff_get_domain_space(aff));
475 aff = isl_aff_realign_domain(aff, exp);
478 isl_space_free(model);
479 return aff;
480 error:
481 isl_space_free(model);
482 isl_aff_free(aff);
483 return NULL;
486 /* Is "aff" obviously equal to zero?
488 * If the denominator is zero, then "aff" is not equal to zero.
490 isl_bool isl_aff_plain_is_zero(__isl_keep isl_aff *aff)
492 if (!aff)
493 return isl_bool_error;
495 if (isl_int_is_zero(aff->v->el[0]))
496 return isl_bool_false;
497 return isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1) < 0;
500 /* Does "aff" represent NaN?
502 isl_bool isl_aff_is_nan(__isl_keep isl_aff *aff)
504 if (!aff)
505 return isl_bool_error;
507 return isl_seq_first_non_zero(aff->v->el, 2) < 0;
510 /* Does "pa" involve any NaNs?
512 isl_bool isl_pw_aff_involves_nan(__isl_keep isl_pw_aff *pa)
514 int i;
516 if (!pa)
517 return isl_bool_error;
518 if (pa->n == 0)
519 return isl_bool_false;
521 for (i = 0; i < pa->n; ++i) {
522 isl_bool is_nan = isl_aff_is_nan(pa->p[i].aff);
523 if (is_nan < 0 || is_nan)
524 return is_nan;
527 return isl_bool_false;
530 /* Are "aff1" and "aff2" obviously equal?
532 * NaN is not equal to anything, not even to another NaN.
534 isl_bool isl_aff_plain_is_equal(__isl_keep isl_aff *aff1,
535 __isl_keep isl_aff *aff2)
537 isl_bool equal;
539 if (!aff1 || !aff2)
540 return isl_bool_error;
542 if (isl_aff_is_nan(aff1) || isl_aff_is_nan(aff2))
543 return isl_bool_false;
545 equal = isl_local_space_is_equal(aff1->ls, aff2->ls);
546 if (equal < 0 || !equal)
547 return equal;
549 return isl_vec_is_equal(aff1->v, aff2->v);
552 /* Return the common denominator of "aff" in "v".
554 * We cannot return anything meaningful in case of a NaN.
556 int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
558 if (!aff)
559 return -1;
560 if (isl_aff_is_nan(aff))
561 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
562 "cannot get denominator of NaN", return -1);
563 isl_int_set(*v, aff->v->el[0]);
564 return 0;
567 /* Return the common denominator of "aff".
569 __isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff)
571 isl_ctx *ctx;
573 if (!aff)
574 return NULL;
576 ctx = isl_aff_get_ctx(aff);
577 if (isl_aff_is_nan(aff))
578 return isl_val_nan(ctx);
579 return isl_val_int_from_isl_int(ctx, aff->v->el[0]);
582 /* Return the constant term of "aff" in "v".
584 * We cannot return anything meaningful in case of a NaN.
586 int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
588 if (!aff)
589 return -1;
590 if (isl_aff_is_nan(aff))
591 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
592 "cannot get constant term of NaN", return -1);
593 isl_int_set(*v, aff->v->el[1]);
594 return 0;
597 /* Return the constant term of "aff".
599 __isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff)
601 isl_ctx *ctx;
602 isl_val *v;
604 if (!aff)
605 return NULL;
607 ctx = isl_aff_get_ctx(aff);
608 if (isl_aff_is_nan(aff))
609 return isl_val_nan(ctx);
610 v = isl_val_rat_from_isl_int(ctx, aff->v->el[1], aff->v->el[0]);
611 return isl_val_normalize(v);
614 /* Return the coefficient of the variable of type "type" at position "pos"
615 * of "aff" in "v".
617 * We cannot return anything meaningful in case of a NaN.
619 int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
620 enum isl_dim_type type, int pos, isl_int *v)
622 if (!aff)
623 return -1;
625 if (type == isl_dim_out)
626 isl_die(aff->v->ctx, isl_error_invalid,
627 "output/set dimension does not have a coefficient",
628 return -1);
629 if (type == isl_dim_in)
630 type = isl_dim_set;
632 if (pos >= isl_local_space_dim(aff->ls, type))
633 isl_die(aff->v->ctx, isl_error_invalid,
634 "position out of bounds", return -1);
636 if (isl_aff_is_nan(aff))
637 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
638 "cannot get coefficient of NaN", return -1);
639 pos += isl_local_space_offset(aff->ls, type);
640 isl_int_set(*v, aff->v->el[1 + pos]);
642 return 0;
645 /* Return the coefficient of the variable of type "type" at position "pos"
646 * of "aff".
648 __isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
649 enum isl_dim_type type, int pos)
651 isl_ctx *ctx;
652 isl_val *v;
654 if (!aff)
655 return NULL;
657 ctx = isl_aff_get_ctx(aff);
658 if (type == isl_dim_out)
659 isl_die(ctx, isl_error_invalid,
660 "output/set dimension does not have a coefficient",
661 return NULL);
662 if (type == isl_dim_in)
663 type = isl_dim_set;
665 if (pos >= isl_local_space_dim(aff->ls, type))
666 isl_die(ctx, isl_error_invalid,
667 "position out of bounds", return NULL);
669 if (isl_aff_is_nan(aff))
670 return isl_val_nan(ctx);
671 pos += isl_local_space_offset(aff->ls, type);
672 v = isl_val_rat_from_isl_int(ctx, aff->v->el[1 + pos], aff->v->el[0]);
673 return isl_val_normalize(v);
676 /* Return the sign of the coefficient of the variable of type "type"
677 * at position "pos" of "aff".
679 int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type,
680 int pos)
682 isl_ctx *ctx;
684 if (!aff)
685 return 0;
687 ctx = isl_aff_get_ctx(aff);
688 if (type == isl_dim_out)
689 isl_die(ctx, isl_error_invalid,
690 "output/set dimension does not have a coefficient",
691 return 0);
692 if (type == isl_dim_in)
693 type = isl_dim_set;
695 if (pos >= isl_local_space_dim(aff->ls, type))
696 isl_die(ctx, isl_error_invalid,
697 "position out of bounds", return 0);
699 pos += isl_local_space_offset(aff->ls, type);
700 return isl_int_sgn(aff->v->el[1 + pos]);
703 /* Replace the denominator of "aff" by "v".
705 * A NaN is unaffected by this operation.
707 __isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v)
709 if (!aff)
710 return NULL;
711 if (isl_aff_is_nan(aff))
712 return aff;
713 aff = isl_aff_cow(aff);
714 if (!aff)
715 return NULL;
717 aff->v = isl_vec_cow(aff->v);
718 if (!aff->v)
719 return isl_aff_free(aff);
721 isl_int_set(aff->v->el[0], v);
723 return aff;
726 /* Replace the numerator of the constant term of "aff" by "v".
728 * A NaN is unaffected by this operation.
730 __isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
732 if (!aff)
733 return NULL;
734 if (isl_aff_is_nan(aff))
735 return aff;
736 aff = isl_aff_cow(aff);
737 if (!aff)
738 return NULL;
740 aff->v = isl_vec_cow(aff->v);
741 if (!aff->v)
742 return isl_aff_free(aff);
744 isl_int_set(aff->v->el[1], v);
746 return aff;
749 /* Replace the constant term of "aff" by "v".
751 * A NaN is unaffected by this operation.
753 __isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
754 __isl_take isl_val *v)
756 if (!aff || !v)
757 goto error;
759 if (isl_aff_is_nan(aff)) {
760 isl_val_free(v);
761 return aff;
764 if (!isl_val_is_rat(v))
765 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
766 "expecting rational value", goto error);
768 if (isl_int_eq(aff->v->el[1], v->n) &&
769 isl_int_eq(aff->v->el[0], v->d)) {
770 isl_val_free(v);
771 return aff;
774 aff = isl_aff_cow(aff);
775 if (!aff)
776 goto error;
777 aff->v = isl_vec_cow(aff->v);
778 if (!aff->v)
779 goto error;
781 if (isl_int_eq(aff->v->el[0], v->d)) {
782 isl_int_set(aff->v->el[1], v->n);
783 } else if (isl_int_is_one(v->d)) {
784 isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
785 } else {
786 isl_seq_scale(aff->v->el + 1,
787 aff->v->el + 1, v->d, aff->v->size - 1);
788 isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
789 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
790 aff->v = isl_vec_normalize(aff->v);
791 if (!aff->v)
792 goto error;
795 isl_val_free(v);
796 return aff;
797 error:
798 isl_aff_free(aff);
799 isl_val_free(v);
800 return NULL;
803 /* Add "v" to the constant term of "aff".
805 * A NaN is unaffected by this operation.
807 __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
809 if (isl_int_is_zero(v))
810 return aff;
812 if (!aff)
813 return NULL;
814 if (isl_aff_is_nan(aff))
815 return aff;
816 aff = isl_aff_cow(aff);
817 if (!aff)
818 return NULL;
820 aff->v = isl_vec_cow(aff->v);
821 if (!aff->v)
822 return isl_aff_free(aff);
824 isl_int_addmul(aff->v->el[1], aff->v->el[0], v);
826 return aff;
829 /* Add "v" to the constant term of "aff".
831 * A NaN is unaffected by this operation.
833 __isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff,
834 __isl_take isl_val *v)
836 if (!aff || !v)
837 goto error;
839 if (isl_aff_is_nan(aff) || isl_val_is_zero(v)) {
840 isl_val_free(v);
841 return aff;
844 if (!isl_val_is_rat(v))
845 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
846 "expecting rational value", goto error);
848 aff = isl_aff_cow(aff);
849 if (!aff)
850 goto error;
852 aff->v = isl_vec_cow(aff->v);
853 if (!aff->v)
854 goto error;
856 if (isl_int_is_one(v->d)) {
857 isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
858 } else if (isl_int_eq(aff->v->el[0], v->d)) {
859 isl_int_add(aff->v->el[1], aff->v->el[1], v->n);
860 aff->v = isl_vec_normalize(aff->v);
861 if (!aff->v)
862 goto error;
863 } else {
864 isl_seq_scale(aff->v->el + 1,
865 aff->v->el + 1, v->d, aff->v->size - 1);
866 isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
867 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
868 aff->v = isl_vec_normalize(aff->v);
869 if (!aff->v)
870 goto error;
873 isl_val_free(v);
874 return aff;
875 error:
876 isl_aff_free(aff);
877 isl_val_free(v);
878 return NULL;
881 __isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v)
883 isl_int t;
885 isl_int_init(t);
886 isl_int_set_si(t, v);
887 aff = isl_aff_add_constant(aff, t);
888 isl_int_clear(t);
890 return aff;
893 /* Add "v" to the numerator of the constant term of "aff".
895 * A NaN is unaffected by this operation.
897 __isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff, isl_int v)
899 if (isl_int_is_zero(v))
900 return aff;
902 if (!aff)
903 return NULL;
904 if (isl_aff_is_nan(aff))
905 return aff;
906 aff = isl_aff_cow(aff);
907 if (!aff)
908 return NULL;
910 aff->v = isl_vec_cow(aff->v);
911 if (!aff->v)
912 return isl_aff_free(aff);
914 isl_int_add(aff->v->el[1], aff->v->el[1], v);
916 return aff;
919 /* Add "v" to the numerator of the constant term of "aff".
921 * A NaN is unaffected by this operation.
923 __isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v)
925 isl_int t;
927 if (v == 0)
928 return aff;
930 isl_int_init(t);
931 isl_int_set_si(t, v);
932 aff = isl_aff_add_constant_num(aff, t);
933 isl_int_clear(t);
935 return aff;
938 /* Replace the numerator of the constant term of "aff" by "v".
940 * A NaN is unaffected by this operation.
942 __isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v)
944 if (!aff)
945 return NULL;
946 if (isl_aff_is_nan(aff))
947 return aff;
948 aff = isl_aff_cow(aff);
949 if (!aff)
950 return NULL;
952 aff->v = isl_vec_cow(aff->v);
953 if (!aff->v)
954 return isl_aff_free(aff);
956 isl_int_set_si(aff->v->el[1], v);
958 return aff;
961 /* Replace the numerator of the coefficient of the variable of type "type"
962 * at position "pos" of "aff" by "v".
964 * A NaN is unaffected by this operation.
966 __isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
967 enum isl_dim_type type, int pos, isl_int v)
969 if (!aff)
970 return NULL;
972 if (type == isl_dim_out)
973 isl_die(aff->v->ctx, isl_error_invalid,
974 "output/set dimension does not have a coefficient",
975 return isl_aff_free(aff));
976 if (type == isl_dim_in)
977 type = isl_dim_set;
979 if (pos >= isl_local_space_dim(aff->ls, type))
980 isl_die(aff->v->ctx, isl_error_invalid,
981 "position out of bounds", return isl_aff_free(aff));
983 if (isl_aff_is_nan(aff))
984 return aff;
985 aff = isl_aff_cow(aff);
986 if (!aff)
987 return NULL;
989 aff->v = isl_vec_cow(aff->v);
990 if (!aff->v)
991 return isl_aff_free(aff);
993 pos += isl_local_space_offset(aff->ls, type);
994 isl_int_set(aff->v->el[1 + pos], v);
996 return aff;
999 /* Replace the numerator of the coefficient of the variable of type "type"
1000 * at position "pos" of "aff" by "v".
1002 * A NaN is unaffected by this operation.
1004 __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
1005 enum isl_dim_type type, int pos, int v)
1007 if (!aff)
1008 return NULL;
1010 if (type == isl_dim_out)
1011 isl_die(aff->v->ctx, isl_error_invalid,
1012 "output/set dimension does not have a coefficient",
1013 return isl_aff_free(aff));
1014 if (type == isl_dim_in)
1015 type = isl_dim_set;
1017 if (pos < 0 || pos >= isl_local_space_dim(aff->ls, type))
1018 isl_die(aff->v->ctx, isl_error_invalid,
1019 "position out of bounds", return isl_aff_free(aff));
1021 if (isl_aff_is_nan(aff))
1022 return aff;
1023 pos += isl_local_space_offset(aff->ls, type);
1024 if (isl_int_cmp_si(aff->v->el[1 + pos], v) == 0)
1025 return aff;
1027 aff = isl_aff_cow(aff);
1028 if (!aff)
1029 return NULL;
1031 aff->v = isl_vec_cow(aff->v);
1032 if (!aff->v)
1033 return isl_aff_free(aff);
1035 isl_int_set_si(aff->v->el[1 + pos], v);
1037 return aff;
1040 /* Replace the coefficient of the variable of type "type" at position "pos"
1041 * of "aff" by "v".
1043 * A NaN is unaffected by this operation.
1045 __isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
1046 enum isl_dim_type type, int pos, __isl_take isl_val *v)
1048 if (!aff || !v)
1049 goto error;
1051 if (type == isl_dim_out)
1052 isl_die(aff->v->ctx, isl_error_invalid,
1053 "output/set dimension does not have a coefficient",
1054 goto error);
1055 if (type == isl_dim_in)
1056 type = isl_dim_set;
1058 if (pos >= isl_local_space_dim(aff->ls, type))
1059 isl_die(aff->v->ctx, isl_error_invalid,
1060 "position out of bounds", goto error);
1062 if (isl_aff_is_nan(aff)) {
1063 isl_val_free(v);
1064 return aff;
1066 if (!isl_val_is_rat(v))
1067 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1068 "expecting rational value", goto error);
1070 pos += isl_local_space_offset(aff->ls, type);
1071 if (isl_int_eq(aff->v->el[1 + pos], v->n) &&
1072 isl_int_eq(aff->v->el[0], v->d)) {
1073 isl_val_free(v);
1074 return aff;
1077 aff = isl_aff_cow(aff);
1078 if (!aff)
1079 goto error;
1080 aff->v = isl_vec_cow(aff->v);
1081 if (!aff->v)
1082 goto error;
1084 if (isl_int_eq(aff->v->el[0], v->d)) {
1085 isl_int_set(aff->v->el[1 + pos], v->n);
1086 } else if (isl_int_is_one(v->d)) {
1087 isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1088 } else {
1089 isl_seq_scale(aff->v->el + 1,
1090 aff->v->el + 1, v->d, aff->v->size - 1);
1091 isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1092 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
1093 aff->v = isl_vec_normalize(aff->v);
1094 if (!aff->v)
1095 goto error;
1098 isl_val_free(v);
1099 return aff;
1100 error:
1101 isl_aff_free(aff);
1102 isl_val_free(v);
1103 return NULL;
1106 /* Add "v" to the coefficient of the variable of type "type"
1107 * at position "pos" of "aff".
1109 * A NaN is unaffected by this operation.
1111 __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
1112 enum isl_dim_type type, int pos, isl_int v)
1114 if (!aff)
1115 return NULL;
1117 if (type == isl_dim_out)
1118 isl_die(aff->v->ctx, isl_error_invalid,
1119 "output/set dimension does not have a coefficient",
1120 return isl_aff_free(aff));
1121 if (type == isl_dim_in)
1122 type = isl_dim_set;
1124 if (pos >= isl_local_space_dim(aff->ls, type))
1125 isl_die(aff->v->ctx, isl_error_invalid,
1126 "position out of bounds", return isl_aff_free(aff));
1128 if (isl_aff_is_nan(aff))
1129 return aff;
1130 aff = isl_aff_cow(aff);
1131 if (!aff)
1132 return NULL;
1134 aff->v = isl_vec_cow(aff->v);
1135 if (!aff->v)
1136 return isl_aff_free(aff);
1138 pos += isl_local_space_offset(aff->ls, type);
1139 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v);
1141 return aff;
1144 /* Add "v" to the coefficient of the variable of type "type"
1145 * at position "pos" of "aff".
1147 * A NaN is unaffected by this operation.
1149 __isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff,
1150 enum isl_dim_type type, int pos, __isl_take isl_val *v)
1152 if (!aff || !v)
1153 goto error;
1155 if (isl_val_is_zero(v)) {
1156 isl_val_free(v);
1157 return aff;
1160 if (type == isl_dim_out)
1161 isl_die(aff->v->ctx, isl_error_invalid,
1162 "output/set dimension does not have a coefficient",
1163 goto error);
1164 if (type == isl_dim_in)
1165 type = isl_dim_set;
1167 if (pos >= isl_local_space_dim(aff->ls, type))
1168 isl_die(aff->v->ctx, isl_error_invalid,
1169 "position out of bounds", goto error);
1171 if (isl_aff_is_nan(aff)) {
1172 isl_val_free(v);
1173 return aff;
1175 if (!isl_val_is_rat(v))
1176 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1177 "expecting rational value", goto error);
1179 aff = isl_aff_cow(aff);
1180 if (!aff)
1181 goto error;
1183 aff->v = isl_vec_cow(aff->v);
1184 if (!aff->v)
1185 goto error;
1187 pos += isl_local_space_offset(aff->ls, type);
1188 if (isl_int_is_one(v->d)) {
1189 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1190 } else if (isl_int_eq(aff->v->el[0], v->d)) {
1191 isl_int_add(aff->v->el[1 + pos], aff->v->el[1 + pos], v->n);
1192 aff->v = isl_vec_normalize(aff->v);
1193 if (!aff->v)
1194 goto error;
1195 } else {
1196 isl_seq_scale(aff->v->el + 1,
1197 aff->v->el + 1, v->d, aff->v->size - 1);
1198 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1199 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
1200 aff->v = isl_vec_normalize(aff->v);
1201 if (!aff->v)
1202 goto error;
1205 isl_val_free(v);
1206 return aff;
1207 error:
1208 isl_aff_free(aff);
1209 isl_val_free(v);
1210 return NULL;
1213 __isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
1214 enum isl_dim_type type, int pos, int v)
1216 isl_int t;
1218 isl_int_init(t);
1219 isl_int_set_si(t, v);
1220 aff = isl_aff_add_coefficient(aff, type, pos, t);
1221 isl_int_clear(t);
1223 return aff;
1226 __isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos)
1228 if (!aff)
1229 return NULL;
1231 return isl_local_space_get_div(aff->ls, pos);
1234 /* Return the negation of "aff".
1236 * As a special case, -NaN = NaN.
1238 __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
1240 if (!aff)
1241 return NULL;
1242 if (isl_aff_is_nan(aff))
1243 return aff;
1244 aff = isl_aff_cow(aff);
1245 if (!aff)
1246 return NULL;
1247 aff->v = isl_vec_cow(aff->v);
1248 if (!aff->v)
1249 return isl_aff_free(aff);
1251 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
1253 return aff;
1256 /* Remove divs from the local space that do not appear in the affine
1257 * expression.
1258 * We currently only remove divs at the end.
1259 * Some intermediate divs may also not appear directly in the affine
1260 * expression, but we would also need to check that no other divs are
1261 * defined in terms of them.
1263 __isl_give isl_aff *isl_aff_remove_unused_divs(__isl_take isl_aff *aff)
1265 int pos;
1266 int off;
1267 int n;
1269 if (!aff)
1270 return NULL;
1272 n = isl_local_space_dim(aff->ls, isl_dim_div);
1273 off = isl_local_space_offset(aff->ls, isl_dim_div);
1275 pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1;
1276 if (pos == n)
1277 return aff;
1279 aff = isl_aff_cow(aff);
1280 if (!aff)
1281 return NULL;
1283 aff->ls = isl_local_space_drop_dims(aff->ls, isl_dim_div, pos, n - pos);
1284 aff->v = isl_vec_drop_els(aff->v, 1 + off + pos, n - pos);
1285 if (!aff->ls || !aff->v)
1286 return isl_aff_free(aff);
1288 return aff;
1291 /* Given two affine expressions "p" of length p_len (including the
1292 * denominator and the constant term) and "subs" of length subs_len,
1293 * plug in "subs" for the variable at position "pos".
1294 * The variables of "subs" and "p" are assumed to match up to subs_len,
1295 * but "p" may have additional variables.
1296 * "v" is an initialized isl_int that can be used internally.
1298 * In particular, if "p" represents the expression
1300 * (a i + g)/m
1302 * with i the variable at position "pos" and "subs" represents the expression
1304 * f/d
1306 * then the result represents the expression
1308 * (a f + d g)/(m d)
1311 void isl_seq_substitute(isl_int *p, int pos, isl_int *subs,
1312 int p_len, int subs_len, isl_int v)
1314 isl_int_set(v, p[1 + pos]);
1315 isl_int_set_si(p[1 + pos], 0);
1316 isl_seq_combine(p + 1, subs[0], p + 1, v, subs + 1, subs_len - 1);
1317 isl_seq_scale(p + subs_len, p + subs_len, subs[0], p_len - subs_len);
1318 isl_int_mul(p[0], p[0], subs[0]);
1321 /* Look for any divs in the aff->ls with a denominator equal to one
1322 * and plug them into the affine expression and any subsequent divs
1323 * that may reference the div.
1325 static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff)
1327 int i, n;
1328 int len;
1329 isl_int v;
1330 isl_vec *vec;
1331 isl_local_space *ls;
1332 unsigned pos;
1334 if (!aff)
1335 return NULL;
1337 n = isl_local_space_dim(aff->ls, isl_dim_div);
1338 len = aff->v->size;
1339 for (i = 0; i < n; ++i) {
1340 if (!isl_int_is_one(aff->ls->div->row[i][0]))
1341 continue;
1342 ls = isl_local_space_copy(aff->ls);
1343 ls = isl_local_space_substitute_seq(ls, isl_dim_div, i,
1344 aff->ls->div->row[i], len, i + 1, n - (i + 1));
1345 vec = isl_vec_copy(aff->v);
1346 vec = isl_vec_cow(vec);
1347 if (!ls || !vec)
1348 goto error;
1350 isl_int_init(v);
1352 pos = isl_local_space_offset(aff->ls, isl_dim_div) + i;
1353 isl_seq_substitute(vec->el, pos, aff->ls->div->row[i],
1354 len, len, v);
1356 isl_int_clear(v);
1358 isl_vec_free(aff->v);
1359 aff->v = vec;
1360 isl_local_space_free(aff->ls);
1361 aff->ls = ls;
1364 return aff;
1365 error:
1366 isl_vec_free(vec);
1367 isl_local_space_free(ls);
1368 return isl_aff_free(aff);
1371 /* Look for any divs j that appear with a unit coefficient inside
1372 * the definitions of other divs i and plug them into the definitions
1373 * of the divs i.
1375 * In particular, an expression of the form
1377 * floor((f(..) + floor(g(..)/n))/m)
1379 * is simplified to
1381 * floor((n * f(..) + g(..))/(n * m))
1383 * This simplification is correct because we can move the expression
1384 * f(..) into the inner floor in the original expression to obtain
1386 * floor(floor((n * f(..) + g(..))/n)/m)
1388 * from which we can derive the simplified expression.
1390 static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff)
1392 int i, j, n;
1393 int off;
1395 if (!aff)
1396 return NULL;
1398 n = isl_local_space_dim(aff->ls, isl_dim_div);
1399 off = isl_local_space_offset(aff->ls, isl_dim_div);
1400 for (i = 1; i < n; ++i) {
1401 for (j = 0; j < i; ++j) {
1402 if (!isl_int_is_one(aff->ls->div->row[i][1 + off + j]))
1403 continue;
1404 aff->ls = isl_local_space_substitute_seq(aff->ls,
1405 isl_dim_div, j, aff->ls->div->row[j],
1406 aff->v->size, i, 1);
1407 if (!aff->ls)
1408 return isl_aff_free(aff);
1412 return aff;
1415 /* Swap divs "a" and "b" in "aff", which is assumed to be non-NULL.
1417 * Even though this function is only called on isl_affs with a single
1418 * reference, we are careful to only change aff->v and aff->ls together.
1420 static __isl_give isl_aff *swap_div(__isl_take isl_aff *aff, int a, int b)
1422 unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
1423 isl_local_space *ls;
1424 isl_vec *v;
1426 ls = isl_local_space_copy(aff->ls);
1427 ls = isl_local_space_swap_div(ls, a, b);
1428 v = isl_vec_copy(aff->v);
1429 v = isl_vec_cow(v);
1430 if (!ls || !v)
1431 goto error;
1433 isl_int_swap(v->el[1 + off + a], v->el[1 + off + b]);
1434 isl_vec_free(aff->v);
1435 aff->v = v;
1436 isl_local_space_free(aff->ls);
1437 aff->ls = ls;
1439 return aff;
1440 error:
1441 isl_vec_free(v);
1442 isl_local_space_free(ls);
1443 return isl_aff_free(aff);
1446 /* Merge divs "a" and "b" in "aff", which is assumed to be non-NULL.
1448 * We currently do not actually remove div "b", but simply add its
1449 * coefficient to that of "a" and then zero it out.
1451 static __isl_give isl_aff *merge_divs(__isl_take isl_aff *aff, int a, int b)
1453 unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
1455 if (isl_int_is_zero(aff->v->el[1 + off + b]))
1456 return aff;
1458 aff->v = isl_vec_cow(aff->v);
1459 if (!aff->v)
1460 return isl_aff_free(aff);
1462 isl_int_add(aff->v->el[1 + off + a],
1463 aff->v->el[1 + off + a], aff->v->el[1 + off + b]);
1464 isl_int_set_si(aff->v->el[1 + off + b], 0);
1466 return aff;
1469 /* Sort the divs in the local space of "aff" according to
1470 * the comparison function "cmp_row" in isl_local_space.c,
1471 * combining the coefficients of identical divs.
1473 * Reordering divs does not change the semantics of "aff",
1474 * so there is no need to call isl_aff_cow.
1475 * Moreover, this function is currently only called on isl_affs
1476 * with a single reference.
1478 static __isl_give isl_aff *sort_divs(__isl_take isl_aff *aff)
1480 int i, j, n;
1482 if (!aff)
1483 return NULL;
1485 n = isl_aff_dim(aff, isl_dim_div);
1486 for (i = 1; i < n; ++i) {
1487 for (j = i - 1; j >= 0; --j) {
1488 int cmp = isl_mat_cmp_div(aff->ls->div, j, j + 1);
1489 if (cmp < 0)
1490 break;
1491 if (cmp == 0)
1492 aff = merge_divs(aff, j, j + 1);
1493 else
1494 aff = swap_div(aff, j, j + 1);
1495 if (!aff)
1496 return NULL;
1500 return aff;
1503 /* Normalize the representation of "aff".
1505 * This function should only be called of "new" isl_affs, i.e.,
1506 * with only a single reference. We therefore do not need to
1507 * worry about affecting other instances.
1509 __isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff)
1511 if (!aff)
1512 return NULL;
1513 aff->v = isl_vec_normalize(aff->v);
1514 if (!aff->v)
1515 return isl_aff_free(aff);
1516 aff = plug_in_integral_divs(aff);
1517 aff = plug_in_unit_divs(aff);
1518 aff = sort_divs(aff);
1519 aff = isl_aff_remove_unused_divs(aff);
1520 return aff;
1523 /* Given f, return floor(f).
1524 * If f is an integer expression, then just return f.
1525 * If f is a constant, then return the constant floor(f).
1526 * Otherwise, if f = g/m, write g = q m + r,
1527 * create a new div d = [r/m] and return the expression q + d.
1528 * The coefficients in r are taken to lie between -m/2 and m/2.
1530 * As a special case, floor(NaN) = NaN.
1532 __isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff)
1534 int i;
1535 int size;
1536 isl_ctx *ctx;
1537 isl_vec *div;
1539 if (!aff)
1540 return NULL;
1542 if (isl_aff_is_nan(aff))
1543 return aff;
1544 if (isl_int_is_one(aff->v->el[0]))
1545 return aff;
1547 aff = isl_aff_cow(aff);
1548 if (!aff)
1549 return NULL;
1551 aff->v = isl_vec_cow(aff->v);
1552 if (!aff->v)
1553 return isl_aff_free(aff);
1555 if (isl_aff_is_cst(aff)) {
1556 isl_int_fdiv_q(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
1557 isl_int_set_si(aff->v->el[0], 1);
1558 return aff;
1561 div = isl_vec_copy(aff->v);
1562 div = isl_vec_cow(div);
1563 if (!div)
1564 return isl_aff_free(aff);
1566 ctx = isl_aff_get_ctx(aff);
1567 isl_int_fdiv_q(aff->v->el[0], aff->v->el[0], ctx->two);
1568 for (i = 1; i < aff->v->size; ++i) {
1569 isl_int_fdiv_r(div->el[i], div->el[i], div->el[0]);
1570 isl_int_fdiv_q(aff->v->el[i], aff->v->el[i], div->el[0]);
1571 if (isl_int_gt(div->el[i], aff->v->el[0])) {
1572 isl_int_sub(div->el[i], div->el[i], div->el[0]);
1573 isl_int_add_ui(aff->v->el[i], aff->v->el[i], 1);
1577 aff->ls = isl_local_space_add_div(aff->ls, div);
1578 if (!aff->ls)
1579 return isl_aff_free(aff);
1581 size = aff->v->size;
1582 aff->v = isl_vec_extend(aff->v, size + 1);
1583 if (!aff->v)
1584 return isl_aff_free(aff);
1585 isl_int_set_si(aff->v->el[0], 1);
1586 isl_int_set_si(aff->v->el[size], 1);
1588 aff = isl_aff_normalize(aff);
1590 return aff;
1593 /* Compute
1595 * aff mod m = aff - m * floor(aff/m)
1597 __isl_give isl_aff *isl_aff_mod(__isl_take isl_aff *aff, isl_int m)
1599 isl_aff *res;
1601 res = isl_aff_copy(aff);
1602 aff = isl_aff_scale_down(aff, m);
1603 aff = isl_aff_floor(aff);
1604 aff = isl_aff_scale(aff, m);
1605 res = isl_aff_sub(res, aff);
1607 return res;
1610 /* Compute
1612 * aff mod m = aff - m * floor(aff/m)
1614 * with m an integer value.
1616 __isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
1617 __isl_take isl_val *m)
1619 isl_aff *res;
1621 if (!aff || !m)
1622 goto error;
1624 if (!isl_val_is_int(m))
1625 isl_die(isl_val_get_ctx(m), isl_error_invalid,
1626 "expecting integer modulo", goto error);
1628 res = isl_aff_copy(aff);
1629 aff = isl_aff_scale_down_val(aff, isl_val_copy(m));
1630 aff = isl_aff_floor(aff);
1631 aff = isl_aff_scale_val(aff, m);
1632 res = isl_aff_sub(res, aff);
1634 return res;
1635 error:
1636 isl_aff_free(aff);
1637 isl_val_free(m);
1638 return NULL;
1641 /* Compute
1643 * pwaff mod m = pwaff - m * floor(pwaff/m)
1645 __isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m)
1647 isl_pw_aff *res;
1649 res = isl_pw_aff_copy(pwaff);
1650 pwaff = isl_pw_aff_scale_down(pwaff, m);
1651 pwaff = isl_pw_aff_floor(pwaff);
1652 pwaff = isl_pw_aff_scale(pwaff, m);
1653 res = isl_pw_aff_sub(res, pwaff);
1655 return res;
1658 /* Compute
1660 * pa mod m = pa - m * floor(pa/m)
1662 * with m an integer value.
1664 __isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa,
1665 __isl_take isl_val *m)
1667 if (!pa || !m)
1668 goto error;
1669 if (!isl_val_is_int(m))
1670 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
1671 "expecting integer modulo", goto error);
1672 pa = isl_pw_aff_mod(pa, m->n);
1673 isl_val_free(m);
1674 return pa;
1675 error:
1676 isl_pw_aff_free(pa);
1677 isl_val_free(m);
1678 return NULL;
1681 /* Given f, return ceil(f).
1682 * If f is an integer expression, then just return f.
1683 * Otherwise, let f be the expression
1685 * e/m
1687 * then return
1689 * floor((e + m - 1)/m)
1691 * As a special case, ceil(NaN) = NaN.
1693 __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff)
1695 if (!aff)
1696 return NULL;
1698 if (isl_aff_is_nan(aff))
1699 return aff;
1700 if (isl_int_is_one(aff->v->el[0]))
1701 return aff;
1703 aff = isl_aff_cow(aff);
1704 if (!aff)
1705 return NULL;
1706 aff->v = isl_vec_cow(aff->v);
1707 if (!aff->v)
1708 return isl_aff_free(aff);
1710 isl_int_add(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
1711 isl_int_sub_ui(aff->v->el[1], aff->v->el[1], 1);
1712 aff = isl_aff_floor(aff);
1714 return aff;
1717 /* Apply the expansion computed by isl_merge_divs.
1718 * The expansion itself is given by "exp" while the resulting
1719 * list of divs is given by "div".
1721 __isl_give isl_aff *isl_aff_expand_divs( __isl_take isl_aff *aff,
1722 __isl_take isl_mat *div, int *exp)
1724 int i, j;
1725 int old_n_div;
1726 int new_n_div;
1727 int offset;
1729 aff = isl_aff_cow(aff);
1730 if (!aff || !div)
1731 goto error;
1733 old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
1734 new_n_div = isl_mat_rows(div);
1735 if (new_n_div < old_n_div)
1736 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
1737 "not an expansion", goto error);
1739 aff->v = isl_vec_extend(aff->v, aff->v->size + new_n_div - old_n_div);
1740 if (!aff->v)
1741 goto error;
1743 offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
1744 j = old_n_div - 1;
1745 for (i = new_n_div - 1; i >= 0; --i) {
1746 if (j >= 0 && exp[j] == i) {
1747 if (i != j)
1748 isl_int_swap(aff->v->el[offset + i],
1749 aff->v->el[offset + j]);
1750 j--;
1751 } else
1752 isl_int_set_si(aff->v->el[offset + i], 0);
1755 aff->ls = isl_local_space_replace_divs(aff->ls, isl_mat_copy(div));
1756 if (!aff->ls)
1757 goto error;
1758 isl_mat_free(div);
1759 return aff;
1760 error:
1761 isl_aff_free(aff);
1762 isl_mat_free(div);
1763 return NULL;
1766 /* Add two affine expressions that live in the same local space.
1768 static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1,
1769 __isl_take isl_aff *aff2)
1771 isl_int gcd, f;
1773 aff1 = isl_aff_cow(aff1);
1774 if (!aff1 || !aff2)
1775 goto error;
1777 aff1->v = isl_vec_cow(aff1->v);
1778 if (!aff1->v)
1779 goto error;
1781 isl_int_init(gcd);
1782 isl_int_init(f);
1783 isl_int_gcd(gcd, aff1->v->el[0], aff2->v->el[0]);
1784 isl_int_divexact(f, aff2->v->el[0], gcd);
1785 isl_seq_scale(aff1->v->el + 1, aff1->v->el + 1, f, aff1->v->size - 1);
1786 isl_int_divexact(f, aff1->v->el[0], gcd);
1787 isl_seq_addmul(aff1->v->el + 1, f, aff2->v->el + 1, aff1->v->size - 1);
1788 isl_int_divexact(f, aff2->v->el[0], gcd);
1789 isl_int_mul(aff1->v->el[0], aff1->v->el[0], f);
1790 isl_int_clear(f);
1791 isl_int_clear(gcd);
1793 isl_aff_free(aff2);
1794 return aff1;
1795 error:
1796 isl_aff_free(aff1);
1797 isl_aff_free(aff2);
1798 return NULL;
1801 /* Return the sum of "aff1" and "aff2".
1803 * If either of the two is NaN, then the result is NaN.
1805 __isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
1806 __isl_take isl_aff *aff2)
1808 isl_ctx *ctx;
1809 int *exp1 = NULL;
1810 int *exp2 = NULL;
1811 isl_mat *div;
1812 int n_div1, n_div2;
1814 if (!aff1 || !aff2)
1815 goto error;
1817 ctx = isl_aff_get_ctx(aff1);
1818 if (!isl_space_is_equal(aff1->ls->dim, aff2->ls->dim))
1819 isl_die(ctx, isl_error_invalid,
1820 "spaces don't match", goto error);
1822 if (isl_aff_is_nan(aff1)) {
1823 isl_aff_free(aff2);
1824 return aff1;
1826 if (isl_aff_is_nan(aff2)) {
1827 isl_aff_free(aff1);
1828 return aff2;
1831 n_div1 = isl_aff_dim(aff1, isl_dim_div);
1832 n_div2 = isl_aff_dim(aff2, isl_dim_div);
1833 if (n_div1 == 0 && n_div2 == 0)
1834 return add_expanded(aff1, aff2);
1836 exp1 = isl_alloc_array(ctx, int, n_div1);
1837 exp2 = isl_alloc_array(ctx, int, n_div2);
1838 if ((n_div1 && !exp1) || (n_div2 && !exp2))
1839 goto error;
1841 div = isl_merge_divs(aff1->ls->div, aff2->ls->div, exp1, exp2);
1842 aff1 = isl_aff_expand_divs(aff1, isl_mat_copy(div), exp1);
1843 aff2 = isl_aff_expand_divs(aff2, div, exp2);
1844 free(exp1);
1845 free(exp2);
1847 return add_expanded(aff1, aff2);
1848 error:
1849 free(exp1);
1850 free(exp2);
1851 isl_aff_free(aff1);
1852 isl_aff_free(aff2);
1853 return NULL;
1856 __isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
1857 __isl_take isl_aff *aff2)
1859 return isl_aff_add(aff1, isl_aff_neg(aff2));
1862 /* Return the result of scaling "aff" by a factor of "f".
1864 * As a special case, f * NaN = NaN.
1866 __isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f)
1868 isl_int gcd;
1870 if (!aff)
1871 return NULL;
1872 if (isl_aff_is_nan(aff))
1873 return aff;
1875 if (isl_int_is_one(f))
1876 return aff;
1878 aff = isl_aff_cow(aff);
1879 if (!aff)
1880 return NULL;
1881 aff->v = isl_vec_cow(aff->v);
1882 if (!aff->v)
1883 return isl_aff_free(aff);
1885 if (isl_int_is_pos(f) && isl_int_is_divisible_by(aff->v->el[0], f)) {
1886 isl_int_divexact(aff->v->el[0], aff->v->el[0], f);
1887 return aff;
1890 isl_int_init(gcd);
1891 isl_int_gcd(gcd, aff->v->el[0], f);
1892 isl_int_divexact(aff->v->el[0], aff->v->el[0], gcd);
1893 isl_int_divexact(gcd, f, gcd);
1894 isl_seq_scale(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
1895 isl_int_clear(gcd);
1897 return aff;
1900 /* Multiple "aff" by "v".
1902 __isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
1903 __isl_take isl_val *v)
1905 if (!aff || !v)
1906 goto error;
1908 if (isl_val_is_one(v)) {
1909 isl_val_free(v);
1910 return aff;
1913 if (!isl_val_is_rat(v))
1914 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1915 "expecting rational factor", goto error);
1917 aff = isl_aff_scale(aff, v->n);
1918 aff = isl_aff_scale_down(aff, v->d);
1920 isl_val_free(v);
1921 return aff;
1922 error:
1923 isl_aff_free(aff);
1924 isl_val_free(v);
1925 return NULL;
1928 /* Return the result of scaling "aff" down by a factor of "f".
1930 * As a special case, NaN/f = NaN.
1932 __isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f)
1934 isl_int gcd;
1936 if (!aff)
1937 return NULL;
1938 if (isl_aff_is_nan(aff))
1939 return aff;
1941 if (isl_int_is_one(f))
1942 return aff;
1944 aff = isl_aff_cow(aff);
1945 if (!aff)
1946 return NULL;
1948 if (isl_int_is_zero(f))
1949 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1950 "cannot scale down by zero", return isl_aff_free(aff));
1952 aff->v = isl_vec_cow(aff->v);
1953 if (!aff->v)
1954 return isl_aff_free(aff);
1956 isl_int_init(gcd);
1957 isl_seq_gcd(aff->v->el + 1, aff->v->size - 1, &gcd);
1958 isl_int_gcd(gcd, gcd, f);
1959 isl_seq_scale_down(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
1960 isl_int_divexact(gcd, f, gcd);
1961 isl_int_mul(aff->v->el[0], aff->v->el[0], gcd);
1962 isl_int_clear(gcd);
1964 return aff;
1967 /* Divide "aff" by "v".
1969 __isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff,
1970 __isl_take isl_val *v)
1972 if (!aff || !v)
1973 goto error;
1975 if (isl_val_is_one(v)) {
1976 isl_val_free(v);
1977 return aff;
1980 if (!isl_val_is_rat(v))
1981 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1982 "expecting rational factor", goto error);
1983 if (!isl_val_is_pos(v))
1984 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1985 "factor needs to be positive", goto error);
1987 aff = isl_aff_scale(aff, v->d);
1988 aff = isl_aff_scale_down(aff, v->n);
1990 isl_val_free(v);
1991 return aff;
1992 error:
1993 isl_aff_free(aff);
1994 isl_val_free(v);
1995 return NULL;
1998 __isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f)
2000 isl_int v;
2002 if (f == 1)
2003 return aff;
2005 isl_int_init(v);
2006 isl_int_set_ui(v, f);
2007 aff = isl_aff_scale_down(aff, v);
2008 isl_int_clear(v);
2010 return aff;
2013 __isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff,
2014 enum isl_dim_type type, unsigned pos, const char *s)
2016 aff = isl_aff_cow(aff);
2017 if (!aff)
2018 return NULL;
2019 if (type == isl_dim_out)
2020 isl_die(aff->v->ctx, isl_error_invalid,
2021 "cannot set name of output/set dimension",
2022 return isl_aff_free(aff));
2023 if (type == isl_dim_in)
2024 type = isl_dim_set;
2025 aff->ls = isl_local_space_set_dim_name(aff->ls, type, pos, s);
2026 if (!aff->ls)
2027 return isl_aff_free(aff);
2029 return aff;
2032 __isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff,
2033 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
2035 aff = isl_aff_cow(aff);
2036 if (!aff)
2037 goto error;
2038 if (type == isl_dim_out)
2039 isl_die(aff->v->ctx, isl_error_invalid,
2040 "cannot set name of output/set dimension",
2041 goto error);
2042 if (type == isl_dim_in)
2043 type = isl_dim_set;
2044 aff->ls = isl_local_space_set_dim_id(aff->ls, type, pos, id);
2045 if (!aff->ls)
2046 return isl_aff_free(aff);
2048 return aff;
2049 error:
2050 isl_id_free(id);
2051 isl_aff_free(aff);
2052 return NULL;
2055 /* Replace the identifier of the input tuple of "aff" by "id".
2056 * type is currently required to be equal to isl_dim_in
2058 __isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff,
2059 enum isl_dim_type type, __isl_take isl_id *id)
2061 aff = isl_aff_cow(aff);
2062 if (!aff)
2063 goto error;
2064 if (type != isl_dim_out)
2065 isl_die(aff->v->ctx, isl_error_invalid,
2066 "cannot only set id of input tuple", goto error);
2067 aff->ls = isl_local_space_set_tuple_id(aff->ls, isl_dim_set, id);
2068 if (!aff->ls)
2069 return isl_aff_free(aff);
2071 return aff;
2072 error:
2073 isl_id_free(id);
2074 isl_aff_free(aff);
2075 return NULL;
2078 /* Exploit the equalities in "eq" to simplify the affine expression
2079 * and the expressions of the integer divisions in the local space.
2080 * The integer divisions in this local space are assumed to appear
2081 * as regular dimensions in "eq".
2083 static __isl_give isl_aff *isl_aff_substitute_equalities_lifted(
2084 __isl_take isl_aff *aff, __isl_take isl_basic_set *eq)
2086 int i, j;
2087 unsigned total;
2088 unsigned n_div;
2090 if (!eq)
2091 goto error;
2092 if (eq->n_eq == 0) {
2093 isl_basic_set_free(eq);
2094 return aff;
2097 aff = isl_aff_cow(aff);
2098 if (!aff)
2099 goto error;
2101 aff->ls = isl_local_space_substitute_equalities(aff->ls,
2102 isl_basic_set_copy(eq));
2103 aff->v = isl_vec_cow(aff->v);
2104 if (!aff->ls || !aff->v)
2105 goto error;
2107 total = 1 + isl_space_dim(eq->dim, isl_dim_all);
2108 n_div = eq->n_div;
2109 for (i = 0; i < eq->n_eq; ++i) {
2110 j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
2111 if (j < 0 || j == 0 || j >= total)
2112 continue;
2114 isl_seq_elim(aff->v->el + 1, eq->eq[i], j, total,
2115 &aff->v->el[0]);
2118 isl_basic_set_free(eq);
2119 aff = isl_aff_normalize(aff);
2120 return aff;
2121 error:
2122 isl_basic_set_free(eq);
2123 isl_aff_free(aff);
2124 return NULL;
2127 /* Exploit the equalities in "eq" to simplify the affine expression
2128 * and the expressions of the integer divisions in the local space.
2130 __isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff,
2131 __isl_take isl_basic_set *eq)
2133 int n_div;
2135 if (!aff || !eq)
2136 goto error;
2137 n_div = isl_local_space_dim(aff->ls, isl_dim_div);
2138 if (n_div > 0)
2139 eq = isl_basic_set_add_dims(eq, isl_dim_set, n_div);
2140 return isl_aff_substitute_equalities_lifted(aff, eq);
2141 error:
2142 isl_basic_set_free(eq);
2143 isl_aff_free(aff);
2144 return NULL;
2147 /* Look for equalities among the variables shared by context and aff
2148 * and the integer divisions of aff, if any.
2149 * The equalities are then used to eliminate coefficients and/or integer
2150 * divisions from aff.
2152 __isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
2153 __isl_take isl_set *context)
2155 isl_basic_set *hull;
2156 int n_div;
2158 if (!aff)
2159 goto error;
2160 n_div = isl_local_space_dim(aff->ls, isl_dim_div);
2161 if (n_div > 0) {
2162 isl_basic_set *bset;
2163 isl_local_space *ls;
2164 context = isl_set_add_dims(context, isl_dim_set, n_div);
2165 ls = isl_aff_get_domain_local_space(aff);
2166 bset = isl_basic_set_from_local_space(ls);
2167 bset = isl_basic_set_lift(bset);
2168 bset = isl_basic_set_flatten(bset);
2169 context = isl_set_intersect(context,
2170 isl_set_from_basic_set(bset));
2173 hull = isl_set_affine_hull(context);
2174 return isl_aff_substitute_equalities_lifted(aff, hull);
2175 error:
2176 isl_aff_free(aff);
2177 isl_set_free(context);
2178 return NULL;
2181 __isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
2182 __isl_take isl_set *context)
2184 isl_set *dom_context = isl_set_universe(isl_aff_get_domain_space(aff));
2185 dom_context = isl_set_intersect_params(dom_context, context);
2186 return isl_aff_gist(aff, dom_context);
2189 /* Return a basic set containing those elements in the space
2190 * of aff where it is positive. "rational" should not be set.
2192 * If "aff" is NaN, then it is not positive.
2194 static __isl_give isl_basic_set *aff_pos_basic_set(__isl_take isl_aff *aff,
2195 int rational)
2197 isl_constraint *ineq;
2198 isl_basic_set *bset;
2199 isl_val *c;
2201 if (!aff)
2202 return NULL;
2203 if (isl_aff_is_nan(aff)) {
2204 isl_space *space = isl_aff_get_domain_space(aff);
2205 isl_aff_free(aff);
2206 return isl_basic_set_empty(space);
2208 if (rational)
2209 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
2210 "rational sets not supported", goto error);
2212 ineq = isl_inequality_from_aff(aff);
2213 c = isl_constraint_get_constant_val(ineq);
2214 c = isl_val_sub_ui(c, 1);
2215 ineq = isl_constraint_set_constant_val(ineq, c);
2217 bset = isl_basic_set_from_constraint(ineq);
2218 bset = isl_basic_set_simplify(bset);
2219 return bset;
2220 error:
2221 isl_aff_free(aff);
2222 return NULL;
2225 /* Return a basic set containing those elements in the space
2226 * of aff where it is non-negative.
2227 * If "rational" is set, then return a rational basic set.
2229 * If "aff" is NaN, then it is not non-negative (it's not negative either).
2231 static __isl_give isl_basic_set *aff_nonneg_basic_set(
2232 __isl_take isl_aff *aff, int rational)
2234 isl_constraint *ineq;
2235 isl_basic_set *bset;
2237 if (!aff)
2238 return NULL;
2239 if (isl_aff_is_nan(aff)) {
2240 isl_space *space = isl_aff_get_domain_space(aff);
2241 isl_aff_free(aff);
2242 return isl_basic_set_empty(space);
2245 ineq = isl_inequality_from_aff(aff);
2247 bset = isl_basic_set_from_constraint(ineq);
2248 if (rational)
2249 bset = isl_basic_set_set_rational(bset);
2250 bset = isl_basic_set_simplify(bset);
2251 return bset;
2254 /* Return a basic set containing those elements in the space
2255 * of aff where it is non-negative.
2257 __isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff)
2259 return aff_nonneg_basic_set(aff, 0);
2262 /* Return a basic set containing those elements in the domain space
2263 * of aff where it is negative.
2265 __isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff)
2267 aff = isl_aff_neg(aff);
2268 aff = isl_aff_add_constant_num_si(aff, -1);
2269 return isl_aff_nonneg_basic_set(aff);
2272 /* Return a basic set containing those elements in the space
2273 * of aff where it is zero.
2274 * If "rational" is set, then return a rational basic set.
2276 * If "aff" is NaN, then it is not zero.
2278 static __isl_give isl_basic_set *aff_zero_basic_set(__isl_take isl_aff *aff,
2279 int rational)
2281 isl_constraint *ineq;
2282 isl_basic_set *bset;
2284 if (!aff)
2285 return NULL;
2286 if (isl_aff_is_nan(aff)) {
2287 isl_space *space = isl_aff_get_domain_space(aff);
2288 isl_aff_free(aff);
2289 return isl_basic_set_empty(space);
2292 ineq = isl_equality_from_aff(aff);
2294 bset = isl_basic_set_from_constraint(ineq);
2295 if (rational)
2296 bset = isl_basic_set_set_rational(bset);
2297 bset = isl_basic_set_simplify(bset);
2298 return bset;
2301 /* Return a basic set containing those elements in the space
2302 * of aff where it is zero.
2304 __isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff)
2306 return aff_zero_basic_set(aff, 0);
2309 /* Return a basic set containing those elements in the shared space
2310 * of aff1 and aff2 where aff1 is greater than or equal to aff2.
2312 __isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1,
2313 __isl_take isl_aff *aff2)
2315 aff1 = isl_aff_sub(aff1, aff2);
2317 return isl_aff_nonneg_basic_set(aff1);
2320 /* Return a basic set containing those elements in the shared space
2321 * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
2323 __isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1,
2324 __isl_take isl_aff *aff2)
2326 return isl_aff_ge_basic_set(aff2, aff1);
2329 __isl_give isl_aff *isl_aff_add_on_domain(__isl_keep isl_set *dom,
2330 __isl_take isl_aff *aff1, __isl_take isl_aff *aff2)
2332 aff1 = isl_aff_add(aff1, aff2);
2333 aff1 = isl_aff_gist(aff1, isl_set_copy(dom));
2334 return aff1;
2337 int isl_aff_is_empty(__isl_keep isl_aff *aff)
2339 if (!aff)
2340 return -1;
2342 return 0;
2345 /* Check whether the given affine expression has non-zero coefficient
2346 * for any dimension in the given range or if any of these dimensions
2347 * appear with non-zero coefficients in any of the integer divisions
2348 * involved in the affine expression.
2350 isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff,
2351 enum isl_dim_type type, unsigned first, unsigned n)
2353 int i;
2354 isl_ctx *ctx;
2355 int *active = NULL;
2356 isl_bool involves = isl_bool_false;
2358 if (!aff)
2359 return isl_bool_error;
2360 if (n == 0)
2361 return isl_bool_false;
2363 ctx = isl_aff_get_ctx(aff);
2364 if (first + n > isl_aff_dim(aff, type))
2365 isl_die(ctx, isl_error_invalid,
2366 "range out of bounds", return isl_bool_error);
2368 active = isl_local_space_get_active(aff->ls, aff->v->el + 2);
2369 if (!active)
2370 goto error;
2372 first += isl_local_space_offset(aff->ls, type) - 1;
2373 for (i = 0; i < n; ++i)
2374 if (active[first + i]) {
2375 involves = isl_bool_true;
2376 break;
2379 free(active);
2381 return involves;
2382 error:
2383 free(active);
2384 return isl_bool_error;
2387 __isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
2388 enum isl_dim_type type, unsigned first, unsigned n)
2390 isl_ctx *ctx;
2392 if (!aff)
2393 return NULL;
2394 if (type == isl_dim_out)
2395 isl_die(aff->v->ctx, isl_error_invalid,
2396 "cannot drop output/set dimension",
2397 return isl_aff_free(aff));
2398 if (type == isl_dim_in)
2399 type = isl_dim_set;
2400 if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
2401 return aff;
2403 ctx = isl_aff_get_ctx(aff);
2404 if (first + n > isl_local_space_dim(aff->ls, type))
2405 isl_die(ctx, isl_error_invalid, "range out of bounds",
2406 return isl_aff_free(aff));
2408 aff = isl_aff_cow(aff);
2409 if (!aff)
2410 return NULL;
2412 aff->ls = isl_local_space_drop_dims(aff->ls, type, first, n);
2413 if (!aff->ls)
2414 return isl_aff_free(aff);
2416 first += 1 + isl_local_space_offset(aff->ls, type);
2417 aff->v = isl_vec_drop_els(aff->v, first, n);
2418 if (!aff->v)
2419 return isl_aff_free(aff);
2421 return aff;
2424 /* Project the domain of the affine expression onto its parameter space.
2425 * The affine expression may not involve any of the domain dimensions.
2427 __isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff)
2429 isl_space *space;
2430 unsigned n;
2431 int involves;
2433 n = isl_aff_dim(aff, isl_dim_in);
2434 involves = isl_aff_involves_dims(aff, isl_dim_in, 0, n);
2435 if (involves < 0)
2436 return isl_aff_free(aff);
2437 if (involves)
2438 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2439 "affine expression involves some of the domain dimensions",
2440 return isl_aff_free(aff));
2441 aff = isl_aff_drop_dims(aff, isl_dim_in, 0, n);
2442 space = isl_aff_get_domain_space(aff);
2443 space = isl_space_params(space);
2444 aff = isl_aff_reset_domain_space(aff, space);
2445 return aff;
2448 __isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
2449 enum isl_dim_type type, unsigned first, unsigned n)
2451 isl_ctx *ctx;
2453 if (!aff)
2454 return NULL;
2455 if (type == isl_dim_out)
2456 isl_die(aff->v->ctx, isl_error_invalid,
2457 "cannot insert output/set dimensions",
2458 return isl_aff_free(aff));
2459 if (type == isl_dim_in)
2460 type = isl_dim_set;
2461 if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
2462 return aff;
2464 ctx = isl_aff_get_ctx(aff);
2465 if (first > isl_local_space_dim(aff->ls, type))
2466 isl_die(ctx, isl_error_invalid, "position out of bounds",
2467 return isl_aff_free(aff));
2469 aff = isl_aff_cow(aff);
2470 if (!aff)
2471 return NULL;
2473 aff->ls = isl_local_space_insert_dims(aff->ls, type, first, n);
2474 if (!aff->ls)
2475 return isl_aff_free(aff);
2477 first += 1 + isl_local_space_offset(aff->ls, type);
2478 aff->v = isl_vec_insert_zero_els(aff->v, first, n);
2479 if (!aff->v)
2480 return isl_aff_free(aff);
2482 return aff;
2485 __isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
2486 enum isl_dim_type type, unsigned n)
2488 unsigned pos;
2490 pos = isl_aff_dim(aff, type);
2492 return isl_aff_insert_dims(aff, type, pos, n);
2495 __isl_give isl_pw_aff *isl_pw_aff_add_dims(__isl_take isl_pw_aff *pwaff,
2496 enum isl_dim_type type, unsigned n)
2498 unsigned pos;
2500 pos = isl_pw_aff_dim(pwaff, type);
2502 return isl_pw_aff_insert_dims(pwaff, type, pos, n);
2505 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "aff"
2506 * to dimensions of "dst_type" at "dst_pos".
2508 * We only support moving input dimensions to parameters and vice versa.
2510 __isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
2511 enum isl_dim_type dst_type, unsigned dst_pos,
2512 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
2514 unsigned g_dst_pos;
2515 unsigned g_src_pos;
2517 if (!aff)
2518 return NULL;
2519 if (n == 0 &&
2520 !isl_local_space_is_named_or_nested(aff->ls, src_type) &&
2521 !isl_local_space_is_named_or_nested(aff->ls, dst_type))
2522 return aff;
2524 if (dst_type == isl_dim_out || src_type == isl_dim_out)
2525 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2526 "cannot move output/set dimension",
2527 return isl_aff_free(aff));
2528 if (dst_type == isl_dim_div || src_type == isl_dim_div)
2529 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2530 "cannot move divs", return isl_aff_free(aff));
2531 if (dst_type == isl_dim_in)
2532 dst_type = isl_dim_set;
2533 if (src_type == isl_dim_in)
2534 src_type = isl_dim_set;
2536 if (src_pos + n > isl_local_space_dim(aff->ls, src_type))
2537 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2538 "range out of bounds", return isl_aff_free(aff));
2539 if (dst_type == src_type)
2540 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
2541 "moving dims within the same type not supported",
2542 return isl_aff_free(aff));
2544 aff = isl_aff_cow(aff);
2545 if (!aff)
2546 return NULL;
2548 g_src_pos = 1 + isl_local_space_offset(aff->ls, src_type) + src_pos;
2549 g_dst_pos = 1 + isl_local_space_offset(aff->ls, dst_type) + dst_pos;
2550 if (dst_type > src_type)
2551 g_dst_pos -= n;
2553 aff->v = isl_vec_move_els(aff->v, g_dst_pos, g_src_pos, n);
2554 aff->ls = isl_local_space_move_dims(aff->ls, dst_type, dst_pos,
2555 src_type, src_pos, n);
2556 if (!aff->v || !aff->ls)
2557 return isl_aff_free(aff);
2559 aff = sort_divs(aff);
2561 return aff;
2564 __isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
2566 isl_set *dom = isl_set_universe(isl_aff_get_domain_space(aff));
2567 return isl_pw_aff_alloc(dom, aff);
2570 #undef PW
2571 #define PW isl_pw_aff
2572 #undef EL
2573 #define EL isl_aff
2574 #undef EL_IS_ZERO
2575 #define EL_IS_ZERO is_empty
2576 #undef ZERO
2577 #define ZERO empty
2578 #undef IS_ZERO
2579 #define IS_ZERO is_empty
2580 #undef FIELD
2581 #define FIELD aff
2582 #undef DEFAULT_IS_ZERO
2583 #define DEFAULT_IS_ZERO 0
2585 #define NO_EVAL
2586 #define NO_OPT
2587 #define NO_LIFT
2588 #define NO_MORPH
2590 #include <isl_pw_templ.c>
2591 #include <isl_pw_hash.c>
2593 #undef UNION
2594 #define UNION isl_union_pw_aff
2595 #undef PART
2596 #define PART isl_pw_aff
2597 #undef PARTS
2598 #define PARTS pw_aff
2600 #include <isl_union_single.c>
2601 #include <isl_union_neg.c>
2603 static __isl_give isl_set *align_params_pw_pw_set_and(
2604 __isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2,
2605 __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
2606 __isl_take isl_pw_aff *pwaff2))
2608 if (!pwaff1 || !pwaff2)
2609 goto error;
2610 if (isl_space_match(pwaff1->dim, isl_dim_param,
2611 pwaff2->dim, isl_dim_param))
2612 return fn(pwaff1, pwaff2);
2613 if (!isl_space_has_named_params(pwaff1->dim) ||
2614 !isl_space_has_named_params(pwaff2->dim))
2615 isl_die(isl_pw_aff_get_ctx(pwaff1), isl_error_invalid,
2616 "unaligned unnamed parameters", goto error);
2617 pwaff1 = isl_pw_aff_align_params(pwaff1, isl_pw_aff_get_space(pwaff2));
2618 pwaff2 = isl_pw_aff_align_params(pwaff2, isl_pw_aff_get_space(pwaff1));
2619 return fn(pwaff1, pwaff2);
2620 error:
2621 isl_pw_aff_free(pwaff1);
2622 isl_pw_aff_free(pwaff2);
2623 return NULL;
2626 /* Align the parameters of the to isl_pw_aff arguments and
2627 * then apply a function "fn" on them that returns an isl_map.
2629 static __isl_give isl_map *align_params_pw_pw_map_and(
2630 __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
2631 __isl_give isl_map *(*fn)(__isl_take isl_pw_aff *pa1,
2632 __isl_take isl_pw_aff *pa2))
2634 if (!pa1 || !pa2)
2635 goto error;
2636 if (isl_space_match(pa1->dim, isl_dim_param, pa2->dim, isl_dim_param))
2637 return fn(pa1, pa2);
2638 if (!isl_space_has_named_params(pa1->dim) ||
2639 !isl_space_has_named_params(pa2->dim))
2640 isl_die(isl_pw_aff_get_ctx(pa1), isl_error_invalid,
2641 "unaligned unnamed parameters", goto error);
2642 pa1 = isl_pw_aff_align_params(pa1, isl_pw_aff_get_space(pa2));
2643 pa2 = isl_pw_aff_align_params(pa2, isl_pw_aff_get_space(pa1));
2644 return fn(pa1, pa2);
2645 error:
2646 isl_pw_aff_free(pa1);
2647 isl_pw_aff_free(pa2);
2648 return NULL;
2651 /* Compute a piecewise quasi-affine expression with a domain that
2652 * is the union of those of pwaff1 and pwaff2 and such that on each
2653 * cell, the quasi-affine expression is the better (according to cmp)
2654 * of those of pwaff1 and pwaff2. If only one of pwaff1 or pwaff2
2655 * is defined on a given cell, then the associated expression
2656 * is the defined one.
2658 static __isl_give isl_pw_aff *pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
2659 __isl_take isl_pw_aff *pwaff2,
2660 __isl_give isl_basic_set *(*cmp)(__isl_take isl_aff *aff1,
2661 __isl_take isl_aff *aff2))
2663 int i, j, n;
2664 isl_pw_aff *res;
2665 isl_ctx *ctx;
2666 isl_set *set;
2668 if (!pwaff1 || !pwaff2)
2669 goto error;
2671 ctx = isl_space_get_ctx(pwaff1->dim);
2672 if (!isl_space_is_equal(pwaff1->dim, pwaff2->dim))
2673 isl_die(ctx, isl_error_invalid,
2674 "arguments should live in same space", goto error);
2676 if (isl_pw_aff_is_empty(pwaff1)) {
2677 isl_pw_aff_free(pwaff1);
2678 return pwaff2;
2681 if (isl_pw_aff_is_empty(pwaff2)) {
2682 isl_pw_aff_free(pwaff2);
2683 return pwaff1;
2686 n = 2 * (pwaff1->n + 1) * (pwaff2->n + 1);
2687 res = isl_pw_aff_alloc_size(isl_space_copy(pwaff1->dim), n);
2689 for (i = 0; i < pwaff1->n; ++i) {
2690 set = isl_set_copy(pwaff1->p[i].set);
2691 for (j = 0; j < pwaff2->n; ++j) {
2692 struct isl_set *common;
2693 isl_set *better;
2695 common = isl_set_intersect(
2696 isl_set_copy(pwaff1->p[i].set),
2697 isl_set_copy(pwaff2->p[j].set));
2698 better = isl_set_from_basic_set(cmp(
2699 isl_aff_copy(pwaff2->p[j].aff),
2700 isl_aff_copy(pwaff1->p[i].aff)));
2701 better = isl_set_intersect(common, better);
2702 if (isl_set_plain_is_empty(better)) {
2703 isl_set_free(better);
2704 continue;
2706 set = isl_set_subtract(set, isl_set_copy(better));
2708 res = isl_pw_aff_add_piece(res, better,
2709 isl_aff_copy(pwaff2->p[j].aff));
2711 res = isl_pw_aff_add_piece(res, set,
2712 isl_aff_copy(pwaff1->p[i].aff));
2715 for (j = 0; j < pwaff2->n; ++j) {
2716 set = isl_set_copy(pwaff2->p[j].set);
2717 for (i = 0; i < pwaff1->n; ++i)
2718 set = isl_set_subtract(set,
2719 isl_set_copy(pwaff1->p[i].set));
2720 res = isl_pw_aff_add_piece(res, set,
2721 isl_aff_copy(pwaff2->p[j].aff));
2724 isl_pw_aff_free(pwaff1);
2725 isl_pw_aff_free(pwaff2);
2727 return res;
2728 error:
2729 isl_pw_aff_free(pwaff1);
2730 isl_pw_aff_free(pwaff2);
2731 return NULL;
2734 /* Compute a piecewise quasi-affine expression with a domain that
2735 * is the union of those of pwaff1 and pwaff2 and such that on each
2736 * cell, the quasi-affine expression is the maximum of those of pwaff1
2737 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
2738 * cell, then the associated expression is the defined one.
2740 static __isl_give isl_pw_aff *pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
2741 __isl_take isl_pw_aff *pwaff2)
2743 return pw_aff_union_opt(pwaff1, pwaff2, &isl_aff_ge_basic_set);
2746 __isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
2747 __isl_take isl_pw_aff *pwaff2)
2749 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
2750 &pw_aff_union_max);
2753 /* Compute a piecewise quasi-affine expression with a domain that
2754 * is the union of those of pwaff1 and pwaff2 and such that on each
2755 * cell, the quasi-affine expression is the minimum of those of pwaff1
2756 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
2757 * cell, then the associated expression is the defined one.
2759 static __isl_give isl_pw_aff *pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
2760 __isl_take isl_pw_aff *pwaff2)
2762 return pw_aff_union_opt(pwaff1, pwaff2, &isl_aff_le_basic_set);
2765 __isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
2766 __isl_take isl_pw_aff *pwaff2)
2768 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
2769 &pw_aff_union_min);
2772 __isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
2773 __isl_take isl_pw_aff *pwaff2, int max)
2775 if (max)
2776 return isl_pw_aff_union_max(pwaff1, pwaff2);
2777 else
2778 return isl_pw_aff_union_min(pwaff1, pwaff2);
2781 /* Construct a map with as domain the domain of pwaff and
2782 * one-dimensional range corresponding to the affine expressions.
2784 static __isl_give isl_map *map_from_pw_aff(__isl_take isl_pw_aff *pwaff)
2786 int i;
2787 isl_space *dim;
2788 isl_map *map;
2790 if (!pwaff)
2791 return NULL;
2793 dim = isl_pw_aff_get_space(pwaff);
2794 map = isl_map_empty(dim);
2796 for (i = 0; i < pwaff->n; ++i) {
2797 isl_basic_map *bmap;
2798 isl_map *map_i;
2800 bmap = isl_basic_map_from_aff(isl_aff_copy(pwaff->p[i].aff));
2801 map_i = isl_map_from_basic_map(bmap);
2802 map_i = isl_map_intersect_domain(map_i,
2803 isl_set_copy(pwaff->p[i].set));
2804 map = isl_map_union_disjoint(map, map_i);
2807 isl_pw_aff_free(pwaff);
2809 return map;
2812 /* Construct a map with as domain the domain of pwaff and
2813 * one-dimensional range corresponding to the affine expressions.
2815 __isl_give isl_map *isl_map_from_pw_aff(__isl_take isl_pw_aff *pwaff)
2817 if (!pwaff)
2818 return NULL;
2819 if (isl_space_is_set(pwaff->dim))
2820 isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
2821 "space of input is not a map", goto error);
2822 return map_from_pw_aff(pwaff);
2823 error:
2824 isl_pw_aff_free(pwaff);
2825 return NULL;
2828 /* Construct a one-dimensional set with as parameter domain
2829 * the domain of pwaff and the single set dimension
2830 * corresponding to the affine expressions.
2832 __isl_give isl_set *isl_set_from_pw_aff(__isl_take isl_pw_aff *pwaff)
2834 if (!pwaff)
2835 return NULL;
2836 if (!isl_space_is_set(pwaff->dim))
2837 isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
2838 "space of input is not a set", goto error);
2839 return map_from_pw_aff(pwaff);
2840 error:
2841 isl_pw_aff_free(pwaff);
2842 return NULL;
2845 /* Return a set containing those elements in the domain
2846 * of "pwaff" where it satisfies "fn" (if complement is 0) or
2847 * does not satisfy "fn" (if complement is 1).
2849 * The pieces with a NaN never belong to the result since
2850 * NaN does not satisfy any property.
2852 static __isl_give isl_set *pw_aff_locus(__isl_take isl_pw_aff *pwaff,
2853 __isl_give isl_basic_set *(*fn)(__isl_take isl_aff *aff, int rational),
2854 int complement)
2856 int i;
2857 isl_set *set;
2859 if (!pwaff)
2860 return NULL;
2862 set = isl_set_empty(isl_pw_aff_get_domain_space(pwaff));
2864 for (i = 0; i < pwaff->n; ++i) {
2865 isl_basic_set *bset;
2866 isl_set *set_i, *locus;
2867 int rational;
2869 if (isl_aff_is_nan(pwaff->p[i].aff))
2870 continue;
2872 rational = isl_set_has_rational(pwaff->p[i].set);
2873 bset = fn(isl_aff_copy(pwaff->p[i].aff), rational);
2874 locus = isl_set_from_basic_set(bset);
2875 set_i = isl_set_copy(pwaff->p[i].set);
2876 if (complement)
2877 set_i = isl_set_subtract(set_i, locus);
2878 else
2879 set_i = isl_set_intersect(set_i, locus);
2880 set = isl_set_union_disjoint(set, set_i);
2883 isl_pw_aff_free(pwaff);
2885 return set;
2888 /* Return a set containing those elements in the domain
2889 * of "pa" where it is positive.
2891 __isl_give isl_set *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa)
2893 return pw_aff_locus(pa, &aff_pos_basic_set, 0);
2896 /* Return a set containing those elements in the domain
2897 * of pwaff where it is non-negative.
2899 __isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff)
2901 return pw_aff_locus(pwaff, &aff_nonneg_basic_set, 0);
2904 /* Return a set containing those elements in the domain
2905 * of pwaff where it is zero.
2907 __isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff)
2909 return pw_aff_locus(pwaff, &aff_zero_basic_set, 0);
2912 /* Return a set containing those elements in the domain
2913 * of pwaff where it is not zero.
2915 __isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff)
2917 return pw_aff_locus(pwaff, &aff_zero_basic_set, 1);
2920 /* Return a set containing those elements in the shared domain
2921 * of pwaff1 and pwaff2 where pwaff1 is greater than (or equal) to pwaff2.
2923 * We compute the difference on the shared domain and then construct
2924 * the set of values where this difference is non-negative.
2925 * If strict is set, we first subtract 1 from the difference.
2926 * If equal is set, we only return the elements where pwaff1 and pwaff2
2927 * are equal.
2929 static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1,
2930 __isl_take isl_pw_aff *pwaff2, int strict, int equal)
2932 isl_set *set1, *set2;
2934 set1 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff1));
2935 set2 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff2));
2936 set1 = isl_set_intersect(set1, set2);
2937 pwaff1 = isl_pw_aff_intersect_domain(pwaff1, isl_set_copy(set1));
2938 pwaff2 = isl_pw_aff_intersect_domain(pwaff2, isl_set_copy(set1));
2939 pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_neg(pwaff2));
2941 if (strict) {
2942 isl_space *dim = isl_set_get_space(set1);
2943 isl_aff *aff;
2944 aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
2945 aff = isl_aff_add_constant_si(aff, -1);
2946 pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_alloc(set1, aff));
2947 } else
2948 isl_set_free(set1);
2950 if (equal)
2951 return isl_pw_aff_zero_set(pwaff1);
2952 return isl_pw_aff_nonneg_set(pwaff1);
2955 /* Return a set containing those elements in the shared domain
2956 * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2.
2958 static __isl_give isl_set *pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
2959 __isl_take isl_pw_aff *pwaff2)
2961 return pw_aff_gte_set(pwaff1, pwaff2, 0, 1);
2964 __isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
2965 __isl_take isl_pw_aff *pwaff2)
2967 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_eq_set);
2970 /* Return a set containing those elements in the shared domain
2971 * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2.
2973 static __isl_give isl_set *pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
2974 __isl_take isl_pw_aff *pwaff2)
2976 return pw_aff_gte_set(pwaff1, pwaff2, 0, 0);
2979 __isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
2980 __isl_take isl_pw_aff *pwaff2)
2982 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ge_set);
2985 /* Return a set containing those elements in the shared domain
2986 * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2.
2988 static __isl_give isl_set *pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
2989 __isl_take isl_pw_aff *pwaff2)
2991 return pw_aff_gte_set(pwaff1, pwaff2, 1, 0);
2994 __isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
2995 __isl_take isl_pw_aff *pwaff2)
2997 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_gt_set);
3000 __isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
3001 __isl_take isl_pw_aff *pwaff2)
3003 return isl_pw_aff_ge_set(pwaff2, pwaff1);
3006 __isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
3007 __isl_take isl_pw_aff *pwaff2)
3009 return isl_pw_aff_gt_set(pwaff2, pwaff1);
3012 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3013 * where the function values are ordered in the same way as "order",
3014 * which returns a set in the shared domain of its two arguments.
3015 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3017 * Let "pa1" and "pa2" be defined on domains A and B respectively.
3018 * We first pull back the two functions such that they are defined on
3019 * the domain [A -> B]. Then we apply "order", resulting in a set
3020 * in the space [A -> B]. Finally, we unwrap this set to obtain
3021 * a map in the space A -> B.
3023 static __isl_give isl_map *isl_pw_aff_order_map_aligned(
3024 __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
3025 __isl_give isl_set *(*order)(__isl_take isl_pw_aff *pa1,
3026 __isl_take isl_pw_aff *pa2))
3028 isl_space *space1, *space2;
3029 isl_multi_aff *ma;
3030 isl_set *set;
3032 space1 = isl_space_domain(isl_pw_aff_get_space(pa1));
3033 space2 = isl_space_domain(isl_pw_aff_get_space(pa2));
3034 space1 = isl_space_map_from_domain_and_range(space1, space2);
3035 ma = isl_multi_aff_domain_map(isl_space_copy(space1));
3036 pa1 = isl_pw_aff_pullback_multi_aff(pa1, ma);
3037 ma = isl_multi_aff_range_map(space1);
3038 pa2 = isl_pw_aff_pullback_multi_aff(pa2, ma);
3039 set = order(pa1, pa2);
3041 return isl_set_unwrap(set);
3044 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3045 * where the function values are equal.
3046 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3048 static __isl_give isl_map *isl_pw_aff_eq_map_aligned(__isl_take isl_pw_aff *pa1,
3049 __isl_take isl_pw_aff *pa2)
3051 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_eq_set);
3054 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3055 * where the function values are equal.
3057 __isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1,
3058 __isl_take isl_pw_aff *pa2)
3060 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_eq_map_aligned);
3063 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3064 * where the function value of "pa1" is less than the function value of "pa2".
3065 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3067 static __isl_give isl_map *isl_pw_aff_lt_map_aligned(__isl_take isl_pw_aff *pa1,
3068 __isl_take isl_pw_aff *pa2)
3070 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_lt_set);
3073 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3074 * where the function value of "pa1" is less than the function value of "pa2".
3076 __isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1,
3077 __isl_take isl_pw_aff *pa2)
3079 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_lt_map_aligned);
3082 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3083 * where the function value of "pa1" is greater than the function value
3084 * of "pa2".
3085 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3087 static __isl_give isl_map *isl_pw_aff_gt_map_aligned(__isl_take isl_pw_aff *pa1,
3088 __isl_take isl_pw_aff *pa2)
3090 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_gt_set);
3093 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3094 * where the function value of "pa1" is greater than the function value
3095 * of "pa2".
3097 __isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1,
3098 __isl_take isl_pw_aff *pa2)
3100 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_gt_map_aligned);
3103 /* Return a set containing those elements in the shared domain
3104 * of the elements of list1 and list2 where each element in list1
3105 * has the relation specified by "fn" with each element in list2.
3107 static __isl_give isl_set *pw_aff_list_set(__isl_take isl_pw_aff_list *list1,
3108 __isl_take isl_pw_aff_list *list2,
3109 __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
3110 __isl_take isl_pw_aff *pwaff2))
3112 int i, j;
3113 isl_ctx *ctx;
3114 isl_set *set;
3116 if (!list1 || !list2)
3117 goto error;
3119 ctx = isl_pw_aff_list_get_ctx(list1);
3120 if (list1->n < 1 || list2->n < 1)
3121 isl_die(ctx, isl_error_invalid,
3122 "list should contain at least one element", goto error);
3124 set = isl_set_universe(isl_pw_aff_get_domain_space(list1->p[0]));
3125 for (i = 0; i < list1->n; ++i)
3126 for (j = 0; j < list2->n; ++j) {
3127 isl_set *set_ij;
3129 set_ij = fn(isl_pw_aff_copy(list1->p[i]),
3130 isl_pw_aff_copy(list2->p[j]));
3131 set = isl_set_intersect(set, set_ij);
3134 isl_pw_aff_list_free(list1);
3135 isl_pw_aff_list_free(list2);
3136 return set;
3137 error:
3138 isl_pw_aff_list_free(list1);
3139 isl_pw_aff_list_free(list2);
3140 return NULL;
3143 /* Return a set containing those elements in the shared domain
3144 * of the elements of list1 and list2 where each element in list1
3145 * is equal to each element in list2.
3147 __isl_give isl_set *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1,
3148 __isl_take isl_pw_aff_list *list2)
3150 return pw_aff_list_set(list1, list2, &isl_pw_aff_eq_set);
3153 __isl_give isl_set *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1,
3154 __isl_take isl_pw_aff_list *list2)
3156 return pw_aff_list_set(list1, list2, &isl_pw_aff_ne_set);
3159 /* Return a set containing those elements in the shared domain
3160 * of the elements of list1 and list2 where each element in list1
3161 * is less than or equal to each element in list2.
3163 __isl_give isl_set *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1,
3164 __isl_take isl_pw_aff_list *list2)
3166 return pw_aff_list_set(list1, list2, &isl_pw_aff_le_set);
3169 __isl_give isl_set *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1,
3170 __isl_take isl_pw_aff_list *list2)
3172 return pw_aff_list_set(list1, list2, &isl_pw_aff_lt_set);
3175 __isl_give isl_set *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1,
3176 __isl_take isl_pw_aff_list *list2)
3178 return pw_aff_list_set(list1, list2, &isl_pw_aff_ge_set);
3181 __isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1,
3182 __isl_take isl_pw_aff_list *list2)
3184 return pw_aff_list_set(list1, list2, &isl_pw_aff_gt_set);
3188 /* Return a set containing those elements in the shared domain
3189 * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2.
3191 static __isl_give isl_set *pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
3192 __isl_take isl_pw_aff *pwaff2)
3194 isl_set *set_lt, *set_gt;
3196 set_lt = isl_pw_aff_lt_set(isl_pw_aff_copy(pwaff1),
3197 isl_pw_aff_copy(pwaff2));
3198 set_gt = isl_pw_aff_gt_set(pwaff1, pwaff2);
3199 return isl_set_union_disjoint(set_lt, set_gt);
3202 __isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
3203 __isl_take isl_pw_aff *pwaff2)
3205 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ne_set);
3208 __isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
3209 isl_int v)
3211 int i;
3213 if (isl_int_is_one(v))
3214 return pwaff;
3215 if (!isl_int_is_pos(v))
3216 isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
3217 "factor needs to be positive",
3218 return isl_pw_aff_free(pwaff));
3219 pwaff = isl_pw_aff_cow(pwaff);
3220 if (!pwaff)
3221 return NULL;
3222 if (pwaff->n == 0)
3223 return pwaff;
3225 for (i = 0; i < pwaff->n; ++i) {
3226 pwaff->p[i].aff = isl_aff_scale_down(pwaff->p[i].aff, v);
3227 if (!pwaff->p[i].aff)
3228 return isl_pw_aff_free(pwaff);
3231 return pwaff;
3234 __isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff)
3236 int i;
3238 pwaff = isl_pw_aff_cow(pwaff);
3239 if (!pwaff)
3240 return NULL;
3241 if (pwaff->n == 0)
3242 return pwaff;
3244 for (i = 0; i < pwaff->n; ++i) {
3245 pwaff->p[i].aff = isl_aff_floor(pwaff->p[i].aff);
3246 if (!pwaff->p[i].aff)
3247 return isl_pw_aff_free(pwaff);
3250 return pwaff;
3253 __isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff)
3255 int i;
3257 pwaff = isl_pw_aff_cow(pwaff);
3258 if (!pwaff)
3259 return NULL;
3260 if (pwaff->n == 0)
3261 return pwaff;
3263 for (i = 0; i < pwaff->n; ++i) {
3264 pwaff->p[i].aff = isl_aff_ceil(pwaff->p[i].aff);
3265 if (!pwaff->p[i].aff)
3266 return isl_pw_aff_free(pwaff);
3269 return pwaff;
3272 /* Assuming that "cond1" and "cond2" are disjoint,
3273 * return an affine expression that is equal to pwaff1 on cond1
3274 * and to pwaff2 on cond2.
3276 static __isl_give isl_pw_aff *isl_pw_aff_select(
3277 __isl_take isl_set *cond1, __isl_take isl_pw_aff *pwaff1,
3278 __isl_take isl_set *cond2, __isl_take isl_pw_aff *pwaff2)
3280 pwaff1 = isl_pw_aff_intersect_domain(pwaff1, cond1);
3281 pwaff2 = isl_pw_aff_intersect_domain(pwaff2, cond2);
3283 return isl_pw_aff_add_disjoint(pwaff1, pwaff2);
3286 /* Return an affine expression that is equal to pwaff_true for elements
3287 * where "cond" is non-zero and to pwaff_false for elements where "cond"
3288 * is zero.
3289 * That is, return cond ? pwaff_true : pwaff_false;
3291 * If "cond" involves and NaN, then we conservatively return a NaN
3292 * on its entire domain. In principle, we could consider the pieces
3293 * where it is NaN separately from those where it is not.
3295 * If "pwaff_true" and "pwaff_false" are obviously equal to each other,
3296 * then only use the domain of "cond" to restrict the domain.
3298 __isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond,
3299 __isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false)
3301 isl_set *cond_true, *cond_false;
3302 isl_bool equal;
3304 if (!cond)
3305 goto error;
3306 if (isl_pw_aff_involves_nan(cond)) {
3307 isl_space *space = isl_pw_aff_get_domain_space(cond);
3308 isl_local_space *ls = isl_local_space_from_space(space);
3309 isl_pw_aff_free(cond);
3310 isl_pw_aff_free(pwaff_true);
3311 isl_pw_aff_free(pwaff_false);
3312 return isl_pw_aff_nan_on_domain(ls);
3315 pwaff_true = isl_pw_aff_align_params(pwaff_true,
3316 isl_pw_aff_get_space(pwaff_false));
3317 pwaff_false = isl_pw_aff_align_params(pwaff_false,
3318 isl_pw_aff_get_space(pwaff_true));
3319 equal = isl_pw_aff_plain_is_equal(pwaff_true, pwaff_false);
3320 if (equal < 0)
3321 goto error;
3322 if (equal) {
3323 isl_set *dom;
3325 dom = isl_set_coalesce(isl_pw_aff_domain(cond));
3326 isl_pw_aff_free(pwaff_false);
3327 return isl_pw_aff_intersect_domain(pwaff_true, dom);
3330 cond_true = isl_pw_aff_non_zero_set(isl_pw_aff_copy(cond));
3331 cond_false = isl_pw_aff_zero_set(cond);
3332 return isl_pw_aff_select(cond_true, pwaff_true,
3333 cond_false, pwaff_false);
3334 error:
3335 isl_pw_aff_free(cond);
3336 isl_pw_aff_free(pwaff_true);
3337 isl_pw_aff_free(pwaff_false);
3338 return NULL;
3341 isl_bool isl_aff_is_cst(__isl_keep isl_aff *aff)
3343 if (!aff)
3344 return isl_bool_error;
3346 return isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2) == -1;
3349 /* Check whether pwaff is a piecewise constant.
3351 isl_bool isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff)
3353 int i;
3355 if (!pwaff)
3356 return isl_bool_error;
3358 for (i = 0; i < pwaff->n; ++i) {
3359 isl_bool is_cst = isl_aff_is_cst(pwaff->p[i].aff);
3360 if (is_cst < 0 || !is_cst)
3361 return is_cst;
3364 return isl_bool_true;
3367 /* Are all elements of "mpa" piecewise constants?
3369 isl_bool isl_multi_pw_aff_is_cst(__isl_keep isl_multi_pw_aff *mpa)
3371 int i;
3373 if (!mpa)
3374 return isl_bool_error;
3376 for (i = 0; i < mpa->n; ++i) {
3377 isl_bool is_cst = isl_pw_aff_is_cst(mpa->p[i]);
3378 if (is_cst < 0 || !is_cst)
3379 return is_cst;
3382 return isl_bool_true;
3385 /* Return the product of "aff1" and "aff2".
3387 * If either of the two is NaN, then the result is NaN.
3389 * Otherwise, at least one of "aff1" or "aff2" needs to be a constant.
3391 __isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1,
3392 __isl_take isl_aff *aff2)
3394 if (!aff1 || !aff2)
3395 goto error;
3397 if (isl_aff_is_nan(aff1)) {
3398 isl_aff_free(aff2);
3399 return aff1;
3401 if (isl_aff_is_nan(aff2)) {
3402 isl_aff_free(aff1);
3403 return aff2;
3406 if (!isl_aff_is_cst(aff2) && isl_aff_is_cst(aff1))
3407 return isl_aff_mul(aff2, aff1);
3409 if (!isl_aff_is_cst(aff2))
3410 isl_die(isl_aff_get_ctx(aff1), isl_error_invalid,
3411 "at least one affine expression should be constant",
3412 goto error);
3414 aff1 = isl_aff_cow(aff1);
3415 if (!aff1 || !aff2)
3416 goto error;
3418 aff1 = isl_aff_scale(aff1, aff2->v->el[1]);
3419 aff1 = isl_aff_scale_down(aff1, aff2->v->el[0]);
3421 isl_aff_free(aff2);
3422 return aff1;
3423 error:
3424 isl_aff_free(aff1);
3425 isl_aff_free(aff2);
3426 return NULL;
3429 /* Divide "aff1" by "aff2", assuming "aff2" is a constant.
3431 * If either of the two is NaN, then the result is NaN.
3433 __isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
3434 __isl_take isl_aff *aff2)
3436 int is_cst;
3437 int neg;
3439 if (!aff1 || !aff2)
3440 goto error;
3442 if (isl_aff_is_nan(aff1)) {
3443 isl_aff_free(aff2);
3444 return aff1;
3446 if (isl_aff_is_nan(aff2)) {
3447 isl_aff_free(aff1);
3448 return aff2;
3451 is_cst = isl_aff_is_cst(aff2);
3452 if (is_cst < 0)
3453 goto error;
3454 if (!is_cst)
3455 isl_die(isl_aff_get_ctx(aff2), isl_error_invalid,
3456 "second argument should be a constant", goto error);
3458 if (!aff2)
3459 goto error;
3461 neg = isl_int_is_neg(aff2->v->el[1]);
3462 if (neg) {
3463 isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
3464 isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
3467 aff1 = isl_aff_scale(aff1, aff2->v->el[0]);
3468 aff1 = isl_aff_scale_down(aff1, aff2->v->el[1]);
3470 if (neg) {
3471 isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
3472 isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
3475 isl_aff_free(aff2);
3476 return aff1;
3477 error:
3478 isl_aff_free(aff1);
3479 isl_aff_free(aff2);
3480 return NULL;
3483 static __isl_give isl_pw_aff *pw_aff_add(__isl_take isl_pw_aff *pwaff1,
3484 __isl_take isl_pw_aff *pwaff2)
3486 return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_add);
3489 __isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1,
3490 __isl_take isl_pw_aff *pwaff2)
3492 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_add);
3495 __isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
3496 __isl_take isl_pw_aff *pwaff2)
3498 return isl_pw_aff_union_add_(pwaff1, pwaff2);
3501 static __isl_give isl_pw_aff *pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
3502 __isl_take isl_pw_aff *pwaff2)
3504 return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_mul);
3507 __isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
3508 __isl_take isl_pw_aff *pwaff2)
3510 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_mul);
3513 static __isl_give isl_pw_aff *pw_aff_div(__isl_take isl_pw_aff *pa1,
3514 __isl_take isl_pw_aff *pa2)
3516 return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div);
3519 /* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant.
3521 __isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
3522 __isl_take isl_pw_aff *pa2)
3524 int is_cst;
3526 is_cst = isl_pw_aff_is_cst(pa2);
3527 if (is_cst < 0)
3528 goto error;
3529 if (!is_cst)
3530 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3531 "second argument should be a piecewise constant",
3532 goto error);
3533 return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_div);
3534 error:
3535 isl_pw_aff_free(pa1);
3536 isl_pw_aff_free(pa2);
3537 return NULL;
3540 /* Compute the quotient of the integer division of "pa1" by "pa2"
3541 * with rounding towards zero.
3542 * "pa2" is assumed to be a piecewise constant.
3544 * In particular, return
3546 * pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)
3549 __isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1,
3550 __isl_take isl_pw_aff *pa2)
3552 int is_cst;
3553 isl_set *cond;
3554 isl_pw_aff *f, *c;
3556 is_cst = isl_pw_aff_is_cst(pa2);
3557 if (is_cst < 0)
3558 goto error;
3559 if (!is_cst)
3560 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3561 "second argument should be a piecewise constant",
3562 goto error);
3564 pa1 = isl_pw_aff_div(pa1, pa2);
3566 cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1));
3567 f = isl_pw_aff_floor(isl_pw_aff_copy(pa1));
3568 c = isl_pw_aff_ceil(pa1);
3569 return isl_pw_aff_cond(isl_set_indicator_function(cond), f, c);
3570 error:
3571 isl_pw_aff_free(pa1);
3572 isl_pw_aff_free(pa2);
3573 return NULL;
3576 /* Compute the remainder of the integer division of "pa1" by "pa2"
3577 * with rounding towards zero.
3578 * "pa2" is assumed to be a piecewise constant.
3580 * In particular, return
3582 * pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2))
3585 __isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
3586 __isl_take isl_pw_aff *pa2)
3588 int is_cst;
3589 isl_pw_aff *res;
3591 is_cst = isl_pw_aff_is_cst(pa2);
3592 if (is_cst < 0)
3593 goto error;
3594 if (!is_cst)
3595 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3596 "second argument should be a piecewise constant",
3597 goto error);
3598 res = isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1), isl_pw_aff_copy(pa2));
3599 res = isl_pw_aff_mul(pa2, res);
3600 res = isl_pw_aff_sub(pa1, res);
3601 return res;
3602 error:
3603 isl_pw_aff_free(pa1);
3604 isl_pw_aff_free(pa2);
3605 return NULL;
3608 static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1,
3609 __isl_take isl_pw_aff *pwaff2)
3611 isl_set *le;
3612 isl_set *dom;
3614 dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
3615 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
3616 le = isl_pw_aff_le_set(isl_pw_aff_copy(pwaff1),
3617 isl_pw_aff_copy(pwaff2));
3618 dom = isl_set_subtract(dom, isl_set_copy(le));
3619 return isl_pw_aff_select(le, pwaff1, dom, pwaff2);
3622 __isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
3623 __isl_take isl_pw_aff *pwaff2)
3625 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_min);
3628 static __isl_give isl_pw_aff *pw_aff_max(__isl_take isl_pw_aff *pwaff1,
3629 __isl_take isl_pw_aff *pwaff2)
3631 isl_set *ge;
3632 isl_set *dom;
3634 dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
3635 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
3636 ge = isl_pw_aff_ge_set(isl_pw_aff_copy(pwaff1),
3637 isl_pw_aff_copy(pwaff2));
3638 dom = isl_set_subtract(dom, isl_set_copy(ge));
3639 return isl_pw_aff_select(ge, pwaff1, dom, pwaff2);
3642 __isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
3643 __isl_take isl_pw_aff *pwaff2)
3645 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_max);
3648 static __isl_give isl_pw_aff *pw_aff_list_reduce(
3649 __isl_take isl_pw_aff_list *list,
3650 __isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pwaff1,
3651 __isl_take isl_pw_aff *pwaff2))
3653 int i;
3654 isl_ctx *ctx;
3655 isl_pw_aff *res;
3657 if (!list)
3658 return NULL;
3660 ctx = isl_pw_aff_list_get_ctx(list);
3661 if (list->n < 1)
3662 isl_die(ctx, isl_error_invalid,
3663 "list should contain at least one element", goto error);
3665 res = isl_pw_aff_copy(list->p[0]);
3666 for (i = 1; i < list->n; ++i)
3667 res = fn(res, isl_pw_aff_copy(list->p[i]));
3669 isl_pw_aff_list_free(list);
3670 return res;
3671 error:
3672 isl_pw_aff_list_free(list);
3673 return NULL;
3676 /* Return an isl_pw_aff that maps each element in the intersection of the
3677 * domains of the elements of list to the minimal corresponding affine
3678 * expression.
3680 __isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list)
3682 return pw_aff_list_reduce(list, &isl_pw_aff_min);
3685 /* Return an isl_pw_aff that maps each element in the intersection of the
3686 * domains of the elements of list to the maximal corresponding affine
3687 * expression.
3689 __isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list)
3691 return pw_aff_list_reduce(list, &isl_pw_aff_max);
3694 /* Mark the domains of "pwaff" as rational.
3696 __isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff)
3698 int i;
3700 pwaff = isl_pw_aff_cow(pwaff);
3701 if (!pwaff)
3702 return NULL;
3703 if (pwaff->n == 0)
3704 return pwaff;
3706 for (i = 0; i < pwaff->n; ++i) {
3707 pwaff->p[i].set = isl_set_set_rational(pwaff->p[i].set);
3708 if (!pwaff->p[i].set)
3709 return isl_pw_aff_free(pwaff);
3712 return pwaff;
3715 /* Mark the domains of the elements of "list" as rational.
3717 __isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational(
3718 __isl_take isl_pw_aff_list *list)
3720 int i, n;
3722 if (!list)
3723 return NULL;
3724 if (list->n == 0)
3725 return list;
3727 n = list->n;
3728 for (i = 0; i < n; ++i) {
3729 isl_pw_aff *pa;
3731 pa = isl_pw_aff_list_get_pw_aff(list, i);
3732 pa = isl_pw_aff_set_rational(pa);
3733 list = isl_pw_aff_list_set_pw_aff(list, i, pa);
3736 return list;
3739 /* Do the parameters of "aff" match those of "space"?
3741 int isl_aff_matching_params(__isl_keep isl_aff *aff,
3742 __isl_keep isl_space *space)
3744 isl_space *aff_space;
3745 int match;
3747 if (!aff || !space)
3748 return -1;
3750 aff_space = isl_aff_get_domain_space(aff);
3752 match = isl_space_match(space, isl_dim_param, aff_space, isl_dim_param);
3754 isl_space_free(aff_space);
3755 return match;
3758 /* Check that the domain space of "aff" matches "space".
3760 * Return 0 on success and -1 on error.
3762 int isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
3763 __isl_keep isl_space *space)
3765 isl_space *aff_space;
3766 int match;
3768 if (!aff || !space)
3769 return -1;
3771 aff_space = isl_aff_get_domain_space(aff);
3773 match = isl_space_match(space, isl_dim_param, aff_space, isl_dim_param);
3774 if (match < 0)
3775 goto error;
3776 if (!match)
3777 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
3778 "parameters don't match", goto error);
3779 match = isl_space_tuple_is_equal(space, isl_dim_in,
3780 aff_space, isl_dim_set);
3781 if (match < 0)
3782 goto error;
3783 if (!match)
3784 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
3785 "domains don't match", goto error);
3786 isl_space_free(aff_space);
3787 return 0;
3788 error:
3789 isl_space_free(aff_space);
3790 return -1;
3793 #undef BASE
3794 #define BASE aff
3795 #undef DOMBASE
3796 #define DOMBASE set
3797 #define NO_DOMAIN
3799 #include <isl_multi_templ.c>
3800 #include <isl_multi_apply_set.c>
3801 #include <isl_multi_cmp.c>
3802 #include <isl_multi_floor.c>
3803 #include <isl_multi_gist.c>
3805 #undef NO_DOMAIN
3807 /* Remove any internal structure of the domain of "ma".
3808 * If there is any such internal structure in the input,
3809 * then the name of the corresponding space is also removed.
3811 __isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
3812 __isl_take isl_multi_aff *ma)
3814 isl_space *space;
3816 if (!ma)
3817 return NULL;
3819 if (!ma->space->nested[0])
3820 return ma;
3822 space = isl_multi_aff_get_space(ma);
3823 space = isl_space_flatten_domain(space);
3824 ma = isl_multi_aff_reset_space(ma, space);
3826 return ma;
3829 /* Given a map space, return an isl_multi_aff that maps a wrapped copy
3830 * of the space to its domain.
3832 __isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space)
3834 int i, n_in;
3835 isl_local_space *ls;
3836 isl_multi_aff *ma;
3838 if (!space)
3839 return NULL;
3840 if (!isl_space_is_map(space))
3841 isl_die(isl_space_get_ctx(space), isl_error_invalid,
3842 "not a map space", goto error);
3844 n_in = isl_space_dim(space, isl_dim_in);
3845 space = isl_space_domain_map(space);
3847 ma = isl_multi_aff_alloc(isl_space_copy(space));
3848 if (n_in == 0) {
3849 isl_space_free(space);
3850 return ma;
3853 space = isl_space_domain(space);
3854 ls = isl_local_space_from_space(space);
3855 for (i = 0; i < n_in; ++i) {
3856 isl_aff *aff;
3858 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
3859 isl_dim_set, i);
3860 ma = isl_multi_aff_set_aff(ma, i, aff);
3862 isl_local_space_free(ls);
3863 return ma;
3864 error:
3865 isl_space_free(space);
3866 return NULL;
3869 /* Given a map space, return an isl_multi_aff that maps a wrapped copy
3870 * of the space to its range.
3872 __isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space)
3874 int i, n_in, n_out;
3875 isl_local_space *ls;
3876 isl_multi_aff *ma;
3878 if (!space)
3879 return NULL;
3880 if (!isl_space_is_map(space))
3881 isl_die(isl_space_get_ctx(space), isl_error_invalid,
3882 "not a map space", goto error);
3884 n_in = isl_space_dim(space, isl_dim_in);
3885 n_out = isl_space_dim(space, isl_dim_out);
3886 space = isl_space_range_map(space);
3888 ma = isl_multi_aff_alloc(isl_space_copy(space));
3889 if (n_out == 0) {
3890 isl_space_free(space);
3891 return ma;
3894 space = isl_space_domain(space);
3895 ls = isl_local_space_from_space(space);
3896 for (i = 0; i < n_out; ++i) {
3897 isl_aff *aff;
3899 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
3900 isl_dim_set, n_in + i);
3901 ma = isl_multi_aff_set_aff(ma, i, aff);
3903 isl_local_space_free(ls);
3904 return ma;
3905 error:
3906 isl_space_free(space);
3907 return NULL;
3910 /* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy
3911 * of the space to its range.
3913 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map(
3914 __isl_take isl_space *space)
3916 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_range_map(space));
3919 /* Given the space of a set and a range of set dimensions,
3920 * construct an isl_multi_aff that projects out those dimensions.
3922 __isl_give isl_multi_aff *isl_multi_aff_project_out_map(
3923 __isl_take isl_space *space, enum isl_dim_type type,
3924 unsigned first, unsigned n)
3926 int i, dim;
3927 isl_local_space *ls;
3928 isl_multi_aff *ma;
3930 if (!space)
3931 return NULL;
3932 if (!isl_space_is_set(space))
3933 isl_die(isl_space_get_ctx(space), isl_error_unsupported,
3934 "expecting set space", goto error);
3935 if (type != isl_dim_set)
3936 isl_die(isl_space_get_ctx(space), isl_error_invalid,
3937 "only set dimensions can be projected out", goto error);
3939 dim = isl_space_dim(space, isl_dim_set);
3940 if (first + n > dim)
3941 isl_die(isl_space_get_ctx(space), isl_error_invalid,
3942 "range out of bounds", goto error);
3944 space = isl_space_from_domain(space);
3945 space = isl_space_add_dims(space, isl_dim_out, dim - n);
3947 if (dim == n)
3948 return isl_multi_aff_alloc(space);
3950 ma = isl_multi_aff_alloc(isl_space_copy(space));
3951 space = isl_space_domain(space);
3952 ls = isl_local_space_from_space(space);
3954 for (i = 0; i < first; ++i) {
3955 isl_aff *aff;
3957 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
3958 isl_dim_set, i);
3959 ma = isl_multi_aff_set_aff(ma, i, aff);
3962 for (i = 0; i < dim - (first + n); ++i) {
3963 isl_aff *aff;
3965 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
3966 isl_dim_set, first + n + i);
3967 ma = isl_multi_aff_set_aff(ma, first + i, aff);
3970 isl_local_space_free(ls);
3971 return ma;
3972 error:
3973 isl_space_free(space);
3974 return NULL;
3977 /* Given the space of a set and a range of set dimensions,
3978 * construct an isl_pw_multi_aff that projects out those dimensions.
3980 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out_map(
3981 __isl_take isl_space *space, enum isl_dim_type type,
3982 unsigned first, unsigned n)
3984 isl_multi_aff *ma;
3986 ma = isl_multi_aff_project_out_map(space, type, first, n);
3987 return isl_pw_multi_aff_from_multi_aff(ma);
3990 /* Create an isl_pw_multi_aff with the given isl_multi_aff on a universe
3991 * domain.
3993 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_aff(
3994 __isl_take isl_multi_aff *ma)
3996 isl_set *dom = isl_set_universe(isl_multi_aff_get_domain_space(ma));
3997 return isl_pw_multi_aff_alloc(dom, ma);
4000 /* Create a piecewise multi-affine expression in the given space that maps each
4001 * input dimension to the corresponding output dimension.
4003 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
4004 __isl_take isl_space *space)
4006 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_identity(space));
4009 /* Exploit the equalities in "eq" to simplify the affine expressions.
4011 static __isl_give isl_multi_aff *isl_multi_aff_substitute_equalities(
4012 __isl_take isl_multi_aff *maff, __isl_take isl_basic_set *eq)
4014 int i;
4016 maff = isl_multi_aff_cow(maff);
4017 if (!maff || !eq)
4018 goto error;
4020 for (i = 0; i < maff->n; ++i) {
4021 maff->p[i] = isl_aff_substitute_equalities(maff->p[i],
4022 isl_basic_set_copy(eq));
4023 if (!maff->p[i])
4024 goto error;
4027 isl_basic_set_free(eq);
4028 return maff;
4029 error:
4030 isl_basic_set_free(eq);
4031 isl_multi_aff_free(maff);
4032 return NULL;
4035 __isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff,
4036 isl_int f)
4038 int i;
4040 maff = isl_multi_aff_cow(maff);
4041 if (!maff)
4042 return NULL;
4044 for (i = 0; i < maff->n; ++i) {
4045 maff->p[i] = isl_aff_scale(maff->p[i], f);
4046 if (!maff->p[i])
4047 return isl_multi_aff_free(maff);
4050 return maff;
4053 __isl_give isl_multi_aff *isl_multi_aff_add_on_domain(__isl_keep isl_set *dom,
4054 __isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2)
4056 maff1 = isl_multi_aff_add(maff1, maff2);
4057 maff1 = isl_multi_aff_gist(maff1, isl_set_copy(dom));
4058 return maff1;
4061 int isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff)
4063 if (!maff)
4064 return -1;
4066 return 0;
4069 /* Return the set of domain elements where "ma1" is lexicographically
4070 * smaller than or equal to "ma2".
4072 __isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1,
4073 __isl_take isl_multi_aff *ma2)
4075 return isl_multi_aff_lex_ge_set(ma2, ma1);
4078 /* Return the set of domain elements where "ma1" is lexicographically
4079 * smaller than "ma2".
4081 __isl_give isl_set *isl_multi_aff_lex_lt_set(__isl_take isl_multi_aff *ma1,
4082 __isl_take isl_multi_aff *ma2)
4084 return isl_multi_aff_lex_gt_set(ma2, ma1);
4087 /* Return the set of domain elements where "ma1" and "ma2"
4088 * satisfy "order".
4090 static __isl_give isl_set *isl_multi_aff_order_set(
4091 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2,
4092 __isl_give isl_map *order(__isl_take isl_space *set_space))
4094 isl_space *space;
4095 isl_map *map1, *map2;
4096 isl_map *map, *ge;
4098 map1 = isl_map_from_multi_aff(ma1);
4099 map2 = isl_map_from_multi_aff(ma2);
4100 map = isl_map_range_product(map1, map2);
4101 space = isl_space_range(isl_map_get_space(map));
4102 space = isl_space_domain(isl_space_unwrap(space));
4103 ge = order(space);
4104 map = isl_map_intersect_range(map, isl_map_wrap(ge));
4106 return isl_map_domain(map);
4109 /* Return the set of domain elements where "ma1" is lexicographically
4110 * greater than or equal to "ma2".
4112 __isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
4113 __isl_take isl_multi_aff *ma2)
4115 return isl_multi_aff_order_set(ma1, ma2, &isl_map_lex_ge);
4118 /* Return the set of domain elements where "ma1" is lexicographically
4119 * greater than "ma2".
4121 __isl_give isl_set *isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff *ma1,
4122 __isl_take isl_multi_aff *ma2)
4124 return isl_multi_aff_order_set(ma1, ma2, &isl_map_lex_gt);
4127 #undef PW
4128 #define PW isl_pw_multi_aff
4129 #undef EL
4130 #define EL isl_multi_aff
4131 #undef EL_IS_ZERO
4132 #define EL_IS_ZERO is_empty
4133 #undef ZERO
4134 #define ZERO empty
4135 #undef IS_ZERO
4136 #define IS_ZERO is_empty
4137 #undef FIELD
4138 #define FIELD maff
4139 #undef DEFAULT_IS_ZERO
4140 #define DEFAULT_IS_ZERO 0
4142 #define NO_SUB
4143 #define NO_EVAL
4144 #define NO_OPT
4145 #define NO_INVOLVES_DIMS
4146 #define NO_INSERT_DIMS
4147 #define NO_LIFT
4148 #define NO_MORPH
4150 #include <isl_pw_templ.c>
4152 #undef NO_SUB
4154 #undef UNION
4155 #define UNION isl_union_pw_multi_aff
4156 #undef PART
4157 #define PART isl_pw_multi_aff
4158 #undef PARTS
4159 #define PARTS pw_multi_aff
4161 #include <isl_union_multi.c>
4162 #include <isl_union_neg.c>
4164 /* Given a function "cmp" that returns the set of elements where
4165 * "ma1" is "better" than "ma2", return the intersection of this
4166 * set with "dom1" and "dom2".
4168 static __isl_give isl_set *shared_and_better(__isl_keep isl_set *dom1,
4169 __isl_keep isl_set *dom2, __isl_keep isl_multi_aff *ma1,
4170 __isl_keep isl_multi_aff *ma2,
4171 __isl_give isl_set *(*cmp)(__isl_take isl_multi_aff *ma1,
4172 __isl_take isl_multi_aff *ma2))
4174 isl_set *common;
4175 isl_set *better;
4176 int is_empty;
4178 common = isl_set_intersect(isl_set_copy(dom1), isl_set_copy(dom2));
4179 is_empty = isl_set_plain_is_empty(common);
4180 if (is_empty >= 0 && is_empty)
4181 return common;
4182 if (is_empty < 0)
4183 return isl_set_free(common);
4184 better = cmp(isl_multi_aff_copy(ma1), isl_multi_aff_copy(ma2));
4185 better = isl_set_intersect(common, better);
4187 return better;
4190 /* Given a function "cmp" that returns the set of elements where
4191 * "ma1" is "better" than "ma2", return a piecewise multi affine
4192 * expression defined on the union of the definition domains
4193 * of "pma1" and "pma2" that maps to the "best" of "pma1" and
4194 * "pma2" on each cell. If only one of the two input functions
4195 * is defined on a given cell, then it is considered the best.
4197 static __isl_give isl_pw_multi_aff *pw_multi_aff_union_opt(
4198 __isl_take isl_pw_multi_aff *pma1,
4199 __isl_take isl_pw_multi_aff *pma2,
4200 __isl_give isl_set *(*cmp)(__isl_take isl_multi_aff *ma1,
4201 __isl_take isl_multi_aff *ma2))
4203 int i, j, n;
4204 isl_pw_multi_aff *res = NULL;
4205 isl_ctx *ctx;
4206 isl_set *set = NULL;
4208 if (!pma1 || !pma2)
4209 goto error;
4211 ctx = isl_space_get_ctx(pma1->dim);
4212 if (!isl_space_is_equal(pma1->dim, pma2->dim))
4213 isl_die(ctx, isl_error_invalid,
4214 "arguments should live in the same space", goto error);
4216 if (isl_pw_multi_aff_is_empty(pma1)) {
4217 isl_pw_multi_aff_free(pma1);
4218 return pma2;
4221 if (isl_pw_multi_aff_is_empty(pma2)) {
4222 isl_pw_multi_aff_free(pma2);
4223 return pma1;
4226 n = 2 * (pma1->n + 1) * (pma2->n + 1);
4227 res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma1->dim), n);
4229 for (i = 0; i < pma1->n; ++i) {
4230 set = isl_set_copy(pma1->p[i].set);
4231 for (j = 0; j < pma2->n; ++j) {
4232 isl_set *better;
4233 int is_empty;
4235 better = shared_and_better(pma2->p[j].set,
4236 pma1->p[i].set, pma2->p[j].maff,
4237 pma1->p[i].maff, cmp);
4238 is_empty = isl_set_plain_is_empty(better);
4239 if (is_empty < 0 || is_empty) {
4240 isl_set_free(better);
4241 if (is_empty < 0)
4242 goto error;
4243 continue;
4245 set = isl_set_subtract(set, isl_set_copy(better));
4247 res = isl_pw_multi_aff_add_piece(res, better,
4248 isl_multi_aff_copy(pma2->p[j].maff));
4250 res = isl_pw_multi_aff_add_piece(res, set,
4251 isl_multi_aff_copy(pma1->p[i].maff));
4254 for (j = 0; j < pma2->n; ++j) {
4255 set = isl_set_copy(pma2->p[j].set);
4256 for (i = 0; i < pma1->n; ++i)
4257 set = isl_set_subtract(set,
4258 isl_set_copy(pma1->p[i].set));
4259 res = isl_pw_multi_aff_add_piece(res, set,
4260 isl_multi_aff_copy(pma2->p[j].maff));
4263 isl_pw_multi_aff_free(pma1);
4264 isl_pw_multi_aff_free(pma2);
4266 return res;
4267 error:
4268 isl_pw_multi_aff_free(pma1);
4269 isl_pw_multi_aff_free(pma2);
4270 isl_set_free(set);
4271 return isl_pw_multi_aff_free(res);
4274 static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmax(
4275 __isl_take isl_pw_multi_aff *pma1,
4276 __isl_take isl_pw_multi_aff *pma2)
4278 return pw_multi_aff_union_opt(pma1, pma2, &isl_multi_aff_lex_ge_set);
4281 /* Given two piecewise multi affine expressions, return a piecewise
4282 * multi-affine expression defined on the union of the definition domains
4283 * of the inputs that is equal to the lexicographic maximum of the two
4284 * inputs on each cell. If only one of the two inputs is defined on
4285 * a given cell, then it is considered to be the maximum.
4287 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
4288 __isl_take isl_pw_multi_aff *pma1,
4289 __isl_take isl_pw_multi_aff *pma2)
4291 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4292 &pw_multi_aff_union_lexmax);
4295 static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmin(
4296 __isl_take isl_pw_multi_aff *pma1,
4297 __isl_take isl_pw_multi_aff *pma2)
4299 return pw_multi_aff_union_opt(pma1, pma2, &isl_multi_aff_lex_le_set);
4302 /* Given two piecewise multi affine expressions, return a piecewise
4303 * multi-affine expression defined on the union of the definition domains
4304 * of the inputs that is equal to the lexicographic minimum of the two
4305 * inputs on each cell. If only one of the two inputs is defined on
4306 * a given cell, then it is considered to be the minimum.
4308 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
4309 __isl_take isl_pw_multi_aff *pma1,
4310 __isl_take isl_pw_multi_aff *pma2)
4312 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4313 &pw_multi_aff_union_lexmin);
4316 static __isl_give isl_pw_multi_aff *pw_multi_aff_add(
4317 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4319 return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
4320 &isl_multi_aff_add);
4323 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_add(
4324 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4326 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4327 &pw_multi_aff_add);
4330 static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
4331 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4333 return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
4334 &isl_multi_aff_sub);
4337 /* Subtract "pma2" from "pma1" and return the result.
4339 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
4340 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4342 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4343 &pw_multi_aff_sub);
4346 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
4347 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4349 return isl_pw_multi_aff_union_add_(pma1, pma2);
4352 /* Compute the sum of "upa1" and "upa2" on the union of their domains,
4353 * with the actual sum on the shared domain and
4354 * the defined expression on the symmetric difference of the domains.
4356 __isl_give isl_union_pw_aff *isl_union_pw_aff_union_add(
4357 __isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2)
4359 return isl_union_pw_aff_union_add_(upa1, upa2);
4362 /* Compute the sum of "upma1" and "upma2" on the union of their domains,
4363 * with the actual sum on the shared domain and
4364 * the defined expression on the symmetric difference of the domains.
4366 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_union_add(
4367 __isl_take isl_union_pw_multi_aff *upma1,
4368 __isl_take isl_union_pw_multi_aff *upma2)
4370 return isl_union_pw_multi_aff_union_add_(upma1, upma2);
4373 /* Given two piecewise multi-affine expressions A -> B and C -> D,
4374 * construct a piecewise multi-affine expression [A -> C] -> [B -> D].
4376 static __isl_give isl_pw_multi_aff *pw_multi_aff_product(
4377 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4379 int i, j, n;
4380 isl_space *space;
4381 isl_pw_multi_aff *res;
4383 if (!pma1 || !pma2)
4384 goto error;
4386 n = pma1->n * pma2->n;
4387 space = isl_space_product(isl_space_copy(pma1->dim),
4388 isl_space_copy(pma2->dim));
4389 res = isl_pw_multi_aff_alloc_size(space, n);
4391 for (i = 0; i < pma1->n; ++i) {
4392 for (j = 0; j < pma2->n; ++j) {
4393 isl_set *domain;
4394 isl_multi_aff *ma;
4396 domain = isl_set_product(isl_set_copy(pma1->p[i].set),
4397 isl_set_copy(pma2->p[j].set));
4398 ma = isl_multi_aff_product(
4399 isl_multi_aff_copy(pma1->p[i].maff),
4400 isl_multi_aff_copy(pma2->p[j].maff));
4401 res = isl_pw_multi_aff_add_piece(res, domain, ma);
4405 isl_pw_multi_aff_free(pma1);
4406 isl_pw_multi_aff_free(pma2);
4407 return res;
4408 error:
4409 isl_pw_multi_aff_free(pma1);
4410 isl_pw_multi_aff_free(pma2);
4411 return NULL;
4414 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_product(
4415 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4417 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4418 &pw_multi_aff_product);
4421 /* Construct a map mapping the domain of the piecewise multi-affine expression
4422 * to its range, with each dimension in the range equated to the
4423 * corresponding affine expression on its cell.
4425 __isl_give isl_map *isl_map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma)
4427 int i;
4428 isl_map *map;
4430 if (!pma)
4431 return NULL;
4433 map = isl_map_empty(isl_pw_multi_aff_get_space(pma));
4435 for (i = 0; i < pma->n; ++i) {
4436 isl_multi_aff *maff;
4437 isl_basic_map *bmap;
4438 isl_map *map_i;
4440 maff = isl_multi_aff_copy(pma->p[i].maff);
4441 bmap = isl_basic_map_from_multi_aff(maff);
4442 map_i = isl_map_from_basic_map(bmap);
4443 map_i = isl_map_intersect_domain(map_i,
4444 isl_set_copy(pma->p[i].set));
4445 map = isl_map_union_disjoint(map, map_i);
4448 isl_pw_multi_aff_free(pma);
4449 return map;
4452 __isl_give isl_set *isl_set_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma)
4454 if (!pma)
4455 return NULL;
4457 if (!isl_space_is_set(pma->dim))
4458 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
4459 "isl_pw_multi_aff cannot be converted into an isl_set",
4460 goto error);
4462 return isl_map_from_pw_multi_aff(pma);
4463 error:
4464 isl_pw_multi_aff_free(pma);
4465 return NULL;
4468 /* Subtract the initial "n" elements in "ma" with coefficients in "c" and
4469 * denominator "denom".
4470 * "denom" is allowed to be negative, in which case the actual denominator
4471 * is -denom and the expressions are added instead.
4473 static __isl_give isl_aff *subtract_initial(__isl_take isl_aff *aff,
4474 __isl_keep isl_multi_aff *ma, int n, isl_int *c, isl_int denom)
4476 int i, first;
4477 int sign;
4478 isl_int d;
4480 first = isl_seq_first_non_zero(c, n);
4481 if (first == -1)
4482 return aff;
4484 sign = isl_int_sgn(denom);
4485 isl_int_init(d);
4486 isl_int_abs(d, denom);
4487 for (i = first; i < n; ++i) {
4488 isl_aff *aff_i;
4490 if (isl_int_is_zero(c[i]))
4491 continue;
4492 aff_i = isl_multi_aff_get_aff(ma, i);
4493 aff_i = isl_aff_scale(aff_i, c[i]);
4494 aff_i = isl_aff_scale_down(aff_i, d);
4495 if (sign >= 0)
4496 aff = isl_aff_sub(aff, aff_i);
4497 else
4498 aff = isl_aff_add(aff, aff_i);
4500 isl_int_clear(d);
4502 return aff;
4505 /* Extract an affine expression that expresses the output dimension "pos"
4506 * of "bmap" in terms of the parameters and input dimensions from
4507 * equality "eq".
4508 * Note that this expression may involve integer divisions defined
4509 * in terms of parameters and input dimensions.
4510 * The equality may also involve references to earlier (but not later)
4511 * output dimensions. These are replaced by the corresponding elements
4512 * in "ma".
4514 * If the equality is of the form
4516 * f(i) + h(j) + a x + g(i) = 0,
4518 * with f(i) a linear combinations of the parameters and input dimensions,
4519 * g(i) a linear combination of integer divisions defined in terms of the same
4520 * and h(j) a linear combinations of earlier output dimensions,
4521 * then the affine expression is
4523 * (-f(i) - g(i))/a - h(j)/a
4525 * If the equality is of the form
4527 * f(i) + h(j) - a x + g(i) = 0,
4529 * then the affine expression is
4531 * (f(i) + g(i))/a - h(j)/(-a)
4534 * If "div" refers to an integer division (i.e., it is smaller than
4535 * the number of integer divisions), then the equality constraint
4536 * does involve an integer division (the one at position "div") that
4537 * is defined in terms of output dimensions. However, this integer
4538 * division can be eliminated by exploiting a pair of constraints
4539 * x >= l and x <= l + n, with n smaller than the coefficient of "div"
4540 * in the equality constraint. "ineq" refers to inequality x >= l, i.e.,
4541 * -l + x >= 0.
4542 * In particular, let
4544 * x = e(i) + m floor(...)
4546 * with e(i) the expression derived above and floor(...) the integer
4547 * division involving output dimensions.
4548 * From
4550 * l <= x <= l + n,
4552 * we have
4554 * 0 <= x - l <= n
4556 * This means
4558 * e(i) + m floor(...) - l = (e(i) + m floor(...) - l) mod m
4559 * = (e(i) - l) mod m
4561 * Therefore,
4563 * x - l = (e(i) - l) mod m
4565 * or
4567 * x = ((e(i) - l) mod m) + l
4569 * The variable "shift" below contains the expression -l, which may
4570 * also involve a linear combination of earlier output dimensions.
4572 static __isl_give isl_aff *extract_aff_from_equality(
4573 __isl_keep isl_basic_map *bmap, int pos, int eq, int div, int ineq,
4574 __isl_keep isl_multi_aff *ma)
4576 unsigned o_out;
4577 unsigned n_div, n_out;
4578 isl_ctx *ctx;
4579 isl_local_space *ls;
4580 isl_aff *aff, *shift;
4581 isl_val *mod;
4583 ctx = isl_basic_map_get_ctx(bmap);
4584 ls = isl_basic_map_get_local_space(bmap);
4585 ls = isl_local_space_domain(ls);
4586 aff = isl_aff_alloc(isl_local_space_copy(ls));
4587 if (!aff)
4588 goto error;
4589 o_out = isl_basic_map_offset(bmap, isl_dim_out);
4590 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4591 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4592 if (isl_int_is_neg(bmap->eq[eq][o_out + pos])) {
4593 isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], o_out);
4594 isl_seq_cpy(aff->v->el + 1 + o_out,
4595 bmap->eq[eq] + o_out + n_out, n_div);
4596 } else {
4597 isl_seq_neg(aff->v->el + 1, bmap->eq[eq], o_out);
4598 isl_seq_neg(aff->v->el + 1 + o_out,
4599 bmap->eq[eq] + o_out + n_out, n_div);
4601 if (div < n_div)
4602 isl_int_set_si(aff->v->el[1 + o_out + div], 0);
4603 isl_int_abs(aff->v->el[0], bmap->eq[eq][o_out + pos]);
4604 aff = subtract_initial(aff, ma, pos, bmap->eq[eq] + o_out,
4605 bmap->eq[eq][o_out + pos]);
4606 if (div < n_div) {
4607 shift = isl_aff_alloc(isl_local_space_copy(ls));
4608 if (!shift)
4609 goto error;
4610 isl_seq_cpy(shift->v->el + 1, bmap->ineq[ineq], o_out);
4611 isl_seq_cpy(shift->v->el + 1 + o_out,
4612 bmap->ineq[ineq] + o_out + n_out, n_div);
4613 isl_int_set_si(shift->v->el[0], 1);
4614 shift = subtract_initial(shift, ma, pos,
4615 bmap->ineq[ineq] + o_out, ctx->negone);
4616 aff = isl_aff_add(aff, isl_aff_copy(shift));
4617 mod = isl_val_int_from_isl_int(ctx,
4618 bmap->eq[eq][o_out + n_out + div]);
4619 mod = isl_val_abs(mod);
4620 aff = isl_aff_mod_val(aff, mod);
4621 aff = isl_aff_sub(aff, shift);
4624 isl_local_space_free(ls);
4625 return aff;
4626 error:
4627 isl_local_space_free(ls);
4628 isl_aff_free(aff);
4629 return NULL;
4632 /* Given a basic map with output dimensions defined
4633 * in terms of the parameters input dimensions and earlier
4634 * output dimensions using an equality (and possibly a pair on inequalities),
4635 * extract an isl_aff that expresses output dimension "pos" in terms
4636 * of the parameters and input dimensions.
4637 * Note that this expression may involve integer divisions defined
4638 * in terms of parameters and input dimensions.
4639 * "ma" contains the expressions corresponding to earlier output dimensions.
4641 * This function shares some similarities with
4642 * isl_basic_map_has_defining_equality and isl_constraint_get_bound.
4644 static __isl_give isl_aff *extract_isl_aff_from_basic_map(
4645 __isl_keep isl_basic_map *bmap, int pos, __isl_keep isl_multi_aff *ma)
4647 int eq, div, ineq;
4648 isl_aff *aff;
4650 if (!bmap)
4651 return NULL;
4652 eq = isl_basic_map_output_defining_equality(bmap, pos, &div, &ineq);
4653 if (eq >= bmap->n_eq)
4654 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4655 "unable to find suitable equality", return NULL);
4656 aff = extract_aff_from_equality(bmap, pos, eq, div, ineq, ma);
4658 aff = isl_aff_remove_unused_divs(aff);
4659 return aff;
4662 /* Given a basic map where each output dimension is defined
4663 * in terms of the parameters and input dimensions using an equality,
4664 * extract an isl_multi_aff that expresses the output dimensions in terms
4665 * of the parameters and input dimensions.
4667 static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map(
4668 __isl_take isl_basic_map *bmap)
4670 int i;
4671 unsigned n_out;
4672 isl_multi_aff *ma;
4674 if (!bmap)
4675 return NULL;
4677 ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap));
4678 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4680 for (i = 0; i < n_out; ++i) {
4681 isl_aff *aff;
4683 aff = extract_isl_aff_from_basic_map(bmap, i, ma);
4684 ma = isl_multi_aff_set_aff(ma, i, aff);
4687 isl_basic_map_free(bmap);
4689 return ma;
4692 /* Given a basic set where each set dimension is defined
4693 * in terms of the parameters using an equality,
4694 * extract an isl_multi_aff that expresses the set dimensions in terms
4695 * of the parameters.
4697 __isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities(
4698 __isl_take isl_basic_set *bset)
4700 return extract_isl_multi_aff_from_basic_map(bset);
4703 /* Create an isl_pw_multi_aff that is equivalent to
4704 * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain).
4705 * The given basic map is such that each output dimension is defined
4706 * in terms of the parameters and input dimensions using an equality.
4708 * Since some applications expect the result of isl_pw_multi_aff_from_map
4709 * to only contain integer affine expressions, we compute the floor
4710 * of the expression before returning.
4712 * Remove all constraints involving local variables without
4713 * an explicit representation (resulting in the removal of those
4714 * local variables) prior to the actual extraction to ensure
4715 * that the local spaces in which the resulting affine expressions
4716 * are created do not contain any unknown local variables.
4717 * Removing such constraints is safe because constraints involving
4718 * unknown local variables are not used to determine whether
4719 * a basic map is obviously single-valued.
4721 static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map(
4722 __isl_take isl_set *domain, __isl_take isl_basic_map *bmap)
4724 isl_multi_aff *ma;
4726 bmap = isl_basic_map_drop_constraint_involving_unknown_divs(bmap);
4727 ma = extract_isl_multi_aff_from_basic_map(bmap);
4728 ma = isl_multi_aff_floor(ma);
4729 return isl_pw_multi_aff_alloc(domain, ma);
4732 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
4733 * This obviously only works if the input "map" is single-valued.
4734 * If so, we compute the lexicographic minimum of the image in the form
4735 * of an isl_pw_multi_aff. Since the image is unique, it is equal
4736 * to its lexicographic minimum.
4737 * If the input is not single-valued, we produce an error.
4739 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_base(
4740 __isl_take isl_map *map)
4742 int i;
4743 int sv;
4744 isl_pw_multi_aff *pma;
4746 sv = isl_map_is_single_valued(map);
4747 if (sv < 0)
4748 goto error;
4749 if (!sv)
4750 isl_die(isl_map_get_ctx(map), isl_error_invalid,
4751 "map is not single-valued", goto error);
4752 map = isl_map_make_disjoint(map);
4753 if (!map)
4754 return NULL;
4756 pma = isl_pw_multi_aff_empty(isl_map_get_space(map));
4758 for (i = 0; i < map->n; ++i) {
4759 isl_pw_multi_aff *pma_i;
4760 isl_basic_map *bmap;
4761 bmap = isl_basic_map_copy(map->p[i]);
4762 pma_i = isl_basic_map_lexmin_pw_multi_aff(bmap);
4763 pma = isl_pw_multi_aff_add_disjoint(pma, pma_i);
4766 isl_map_free(map);
4767 return pma;
4768 error:
4769 isl_map_free(map);
4770 return NULL;
4773 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
4774 * taking into account that the output dimension at position "d"
4775 * can be represented as
4777 * x = floor((e(...) + c1) / m)
4779 * given that constraint "i" is of the form
4781 * e(...) + c1 - m x >= 0
4784 * Let "map" be of the form
4786 * A -> B
4788 * We construct a mapping
4790 * A -> [A -> x = floor(...)]
4792 * apply that to the map, obtaining
4794 * [A -> x = floor(...)] -> B
4796 * and equate dimension "d" to x.
4797 * We then compute a isl_pw_multi_aff representation of the resulting map
4798 * and plug in the mapping above.
4800 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div(
4801 __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i)
4803 isl_ctx *ctx;
4804 isl_space *space;
4805 isl_local_space *ls;
4806 isl_multi_aff *ma;
4807 isl_aff *aff;
4808 isl_vec *v;
4809 isl_map *insert;
4810 int offset;
4811 int n;
4812 int n_in;
4813 isl_pw_multi_aff *pma;
4814 int is_set;
4816 is_set = isl_map_is_set(map);
4818 offset = isl_basic_map_offset(hull, isl_dim_out);
4819 ctx = isl_map_get_ctx(map);
4820 space = isl_space_domain(isl_map_get_space(map));
4821 n_in = isl_space_dim(space, isl_dim_set);
4822 n = isl_space_dim(space, isl_dim_all);
4824 v = isl_vec_alloc(ctx, 1 + 1 + n);
4825 if (v) {
4826 isl_int_neg(v->el[0], hull->ineq[i][offset + d]);
4827 isl_seq_cpy(v->el + 1, hull->ineq[i], 1 + n);
4829 isl_basic_map_free(hull);
4831 ls = isl_local_space_from_space(isl_space_copy(space));
4832 aff = isl_aff_alloc_vec(ls, v);
4833 aff = isl_aff_floor(aff);
4834 if (is_set) {
4835 isl_space_free(space);
4836 ma = isl_multi_aff_from_aff(aff);
4837 } else {
4838 ma = isl_multi_aff_identity(isl_space_map_from_set(space));
4839 ma = isl_multi_aff_range_product(ma,
4840 isl_multi_aff_from_aff(aff));
4843 insert = isl_map_from_multi_aff(isl_multi_aff_copy(ma));
4844 map = isl_map_apply_domain(map, insert);
4845 map = isl_map_equate(map, isl_dim_in, n_in, isl_dim_out, d);
4846 pma = isl_pw_multi_aff_from_map(map);
4847 pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma);
4849 return pma;
4852 /* Is constraint "c" of the form
4854 * e(...) + c1 - m x >= 0
4856 * or
4858 * -e(...) + c2 + m x >= 0
4860 * where m > 1 and e only depends on parameters and input dimemnsions?
4862 * "offset" is the offset of the output dimensions
4863 * "pos" is the position of output dimension x.
4865 static int is_potential_div_constraint(isl_int *c, int offset, int d, int total)
4867 if (isl_int_is_zero(c[offset + d]))
4868 return 0;
4869 if (isl_int_is_one(c[offset + d]))
4870 return 0;
4871 if (isl_int_is_negone(c[offset + d]))
4872 return 0;
4873 if (isl_seq_first_non_zero(c + offset, d) != -1)
4874 return 0;
4875 if (isl_seq_first_non_zero(c + offset + d + 1,
4876 total - (offset + d + 1)) != -1)
4877 return 0;
4878 return 1;
4881 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
4883 * As a special case, we first check if there is any pair of constraints,
4884 * shared by all the basic maps in "map" that force a given dimension
4885 * to be equal to the floor of some affine combination of the input dimensions.
4887 * In particular, if we can find two constraints
4889 * e(...) + c1 - m x >= 0 i.e., m x <= e(...) + c1
4891 * and
4893 * -e(...) + c2 + m x >= 0 i.e., m x >= e(...) - c2
4895 * where m > 1 and e only depends on parameters and input dimemnsions,
4896 * and such that
4898 * c1 + c2 < m i.e., -c2 >= c1 - (m - 1)
4900 * then we know that we can take
4902 * x = floor((e(...) + c1) / m)
4904 * without having to perform any computation.
4906 * Note that we know that
4908 * c1 + c2 >= 1
4910 * If c1 + c2 were 0, then we would have detected an equality during
4911 * simplification. If c1 + c2 were negative, then we would have detected
4912 * a contradiction.
4914 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_div(
4915 __isl_take isl_map *map)
4917 int d, dim;
4918 int i, j, n;
4919 int offset, total;
4920 isl_int sum;
4921 isl_basic_map *hull;
4923 hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
4924 if (!hull)
4925 goto error;
4927 isl_int_init(sum);
4928 dim = isl_map_dim(map, isl_dim_out);
4929 offset = isl_basic_map_offset(hull, isl_dim_out);
4930 total = 1 + isl_basic_map_total_dim(hull);
4931 n = hull->n_ineq;
4932 for (d = 0; d < dim; ++d) {
4933 for (i = 0; i < n; ++i) {
4934 if (!is_potential_div_constraint(hull->ineq[i],
4935 offset, d, total))
4936 continue;
4937 for (j = i + 1; j < n; ++j) {
4938 if (!isl_seq_is_neg(hull->ineq[i] + 1,
4939 hull->ineq[j] + 1, total - 1))
4940 continue;
4941 isl_int_add(sum, hull->ineq[i][0],
4942 hull->ineq[j][0]);
4943 if (isl_int_abs_lt(sum,
4944 hull->ineq[i][offset + d]))
4945 break;
4948 if (j >= n)
4949 continue;
4950 isl_int_clear(sum);
4951 if (isl_int_is_pos(hull->ineq[j][offset + d]))
4952 j = i;
4953 return pw_multi_aff_from_map_div(map, hull, d, j);
4956 isl_int_clear(sum);
4957 isl_basic_map_free(hull);
4958 return pw_multi_aff_from_map_base(map);
4959 error:
4960 isl_map_free(map);
4961 isl_basic_map_free(hull);
4962 return NULL;
4965 /* Given an affine expression
4967 * [A -> B] -> f(A,B)
4969 * construct an isl_multi_aff
4971 * [A -> B] -> B'
4973 * such that dimension "d" in B' is set to "aff" and the remaining
4974 * dimensions are set equal to the corresponding dimensions in B.
4975 * "n_in" is the dimension of the space A.
4976 * "n_out" is the dimension of the space B.
4978 * If "is_set" is set, then the affine expression is of the form
4980 * [B] -> f(B)
4982 * and we construct an isl_multi_aff
4984 * B -> B'
4986 static __isl_give isl_multi_aff *range_map(__isl_take isl_aff *aff, int d,
4987 unsigned n_in, unsigned n_out, int is_set)
4989 int i;
4990 isl_multi_aff *ma;
4991 isl_space *space, *space2;
4992 isl_local_space *ls;
4994 space = isl_aff_get_domain_space(aff);
4995 ls = isl_local_space_from_space(isl_space_copy(space));
4996 space2 = isl_space_copy(space);
4997 if (!is_set)
4998 space2 = isl_space_range(isl_space_unwrap(space2));
4999 space = isl_space_map_from_domain_and_range(space, space2);
5000 ma = isl_multi_aff_alloc(space);
5001 ma = isl_multi_aff_set_aff(ma, d, aff);
5003 for (i = 0; i < n_out; ++i) {
5004 if (i == d)
5005 continue;
5006 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
5007 isl_dim_set, n_in + i);
5008 ma = isl_multi_aff_set_aff(ma, i, aff);
5011 isl_local_space_free(ls);
5013 return ma;
5016 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
5017 * taking into account that the dimension at position "d" can be written as
5019 * x = m a + f(..) (1)
5021 * where m is equal to "gcd".
5022 * "i" is the index of the equality in "hull" that defines f(..).
5023 * In particular, the equality is of the form
5025 * f(..) - x + m g(existentials) = 0
5027 * or
5029 * -f(..) + x + m g(existentials) = 0
5031 * We basically plug (1) into "map", resulting in a map with "a"
5032 * in the range instead of "x". The corresponding isl_pw_multi_aff
5033 * defining "a" is then plugged back into (1) to obtain a definition for "x".
5035 * Specifically, given the input map
5037 * A -> B
5039 * We first wrap it into a set
5041 * [A -> B]
5043 * and define (1) on top of the corresponding space, resulting in "aff".
5044 * We use this to create an isl_multi_aff that maps the output position "d"
5045 * from "a" to "x", leaving all other (intput and output) dimensions unchanged.
5046 * We plug this into the wrapped map, unwrap the result and compute the
5047 * corresponding isl_pw_multi_aff.
5048 * The result is an expression
5050 * A -> T(A)
5052 * We adjust that to
5054 * A -> [A -> T(A)]
5056 * so that we can plug that into "aff", after extending the latter to
5057 * a mapping
5059 * [A -> B] -> B'
5062 * If "map" is actually a set, then there is no "A" space, meaning
5063 * that we do not need to perform any wrapping, and that the result
5064 * of the recursive call is of the form
5066 * [T]
5068 * which is plugged into a mapping of the form
5070 * B -> B'
5072 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
5073 __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i,
5074 isl_int gcd)
5076 isl_set *set;
5077 isl_space *space;
5078 isl_local_space *ls;
5079 isl_aff *aff;
5080 isl_multi_aff *ma;
5081 isl_pw_multi_aff *pma, *id;
5082 unsigned n_in;
5083 unsigned o_out;
5084 unsigned n_out;
5085 int is_set;
5087 is_set = isl_map_is_set(map);
5089 n_in = isl_basic_map_dim(hull, isl_dim_in);
5090 n_out = isl_basic_map_dim(hull, isl_dim_out);
5091 o_out = isl_basic_map_offset(hull, isl_dim_out);
5093 if (is_set)
5094 set = map;
5095 else
5096 set = isl_map_wrap(map);
5097 space = isl_space_map_from_set(isl_set_get_space(set));
5098 ma = isl_multi_aff_identity(space);
5099 ls = isl_local_space_from_space(isl_set_get_space(set));
5100 aff = isl_aff_alloc(ls);
5101 if (aff) {
5102 isl_int_set_si(aff->v->el[0], 1);
5103 if (isl_int_is_one(hull->eq[i][o_out + d]))
5104 isl_seq_neg(aff->v->el + 1, hull->eq[i],
5105 aff->v->size - 1);
5106 else
5107 isl_seq_cpy(aff->v->el + 1, hull->eq[i],
5108 aff->v->size - 1);
5109 isl_int_set(aff->v->el[1 + o_out + d], gcd);
5111 ma = isl_multi_aff_set_aff(ma, n_in + d, isl_aff_copy(aff));
5112 set = isl_set_preimage_multi_aff(set, ma);
5114 ma = range_map(aff, d, n_in, n_out, is_set);
5116 if (is_set)
5117 map = set;
5118 else
5119 map = isl_set_unwrap(set);
5120 pma = isl_pw_multi_aff_from_map(map);
5122 if (!is_set) {
5123 space = isl_pw_multi_aff_get_domain_space(pma);
5124 space = isl_space_map_from_set(space);
5125 id = isl_pw_multi_aff_identity(space);
5126 pma = isl_pw_multi_aff_range_product(id, pma);
5128 id = isl_pw_multi_aff_from_multi_aff(ma);
5129 pma = isl_pw_multi_aff_pullback_pw_multi_aff(id, pma);
5131 isl_basic_map_free(hull);
5132 return pma;
5135 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5137 * As a special case, we first check if all output dimensions are uniquely
5138 * defined in terms of the parameters and input dimensions over the entire
5139 * domain. If so, we extract the desired isl_pw_multi_aff directly
5140 * from the affine hull of "map" and its domain.
5142 * Otherwise, we check if any of the output dimensions is "strided".
5143 * That is, we check if can be written as
5145 * x = m a + f(..)
5147 * with m greater than 1, a some combination of existentially quantified
5148 * variables and f an expression in the parameters and input dimensions.
5149 * If so, we remove the stride in pw_multi_aff_from_map_stride.
5151 * Otherwise, we continue with pw_multi_aff_from_map_check_div for a further
5152 * special case.
5154 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
5156 int i, j;
5157 isl_bool sv;
5158 isl_basic_map *hull;
5159 unsigned n_out;
5160 unsigned o_out;
5161 unsigned n_div;
5162 unsigned o_div;
5163 isl_int gcd;
5165 if (!map)
5166 return NULL;
5168 map = isl_map_detect_equalities(map);
5169 hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
5170 sv = isl_basic_map_plain_is_single_valued(hull);
5171 if (sv >= 0 && sv)
5172 return plain_pw_multi_aff_from_map(isl_map_domain(map), hull);
5173 if (sv < 0)
5174 hull = isl_basic_map_free(hull);
5175 if (!hull)
5176 goto error;
5178 n_div = isl_basic_map_dim(hull, isl_dim_div);
5179 o_div = isl_basic_map_offset(hull, isl_dim_div);
5181 if (n_div == 0) {
5182 isl_basic_map_free(hull);
5183 return pw_multi_aff_from_map_check_div(map);
5186 isl_int_init(gcd);
5188 n_out = isl_basic_map_dim(hull, isl_dim_out);
5189 o_out = isl_basic_map_offset(hull, isl_dim_out);
5191 for (i = 0; i < n_out; ++i) {
5192 for (j = 0; j < hull->n_eq; ++j) {
5193 isl_int *eq = hull->eq[j];
5194 isl_pw_multi_aff *res;
5196 if (!isl_int_is_one(eq[o_out + i]) &&
5197 !isl_int_is_negone(eq[o_out + i]))
5198 continue;
5199 if (isl_seq_first_non_zero(eq + o_out, i) != -1)
5200 continue;
5201 if (isl_seq_first_non_zero(eq + o_out + i + 1,
5202 n_out - (i + 1)) != -1)
5203 continue;
5204 isl_seq_gcd(eq + o_div, n_div, &gcd);
5205 if (isl_int_is_zero(gcd))
5206 continue;
5207 if (isl_int_is_one(gcd))
5208 continue;
5210 res = pw_multi_aff_from_map_stride(map, hull,
5211 i, j, gcd);
5212 isl_int_clear(gcd);
5213 return res;
5217 isl_int_clear(gcd);
5218 isl_basic_map_free(hull);
5219 return pw_multi_aff_from_map_check_div(map);
5220 error:
5221 isl_map_free(map);
5222 return NULL;
5225 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(__isl_take isl_set *set)
5227 return isl_pw_multi_aff_from_map(set);
5230 /* Convert "map" into an isl_pw_multi_aff (if possible) and
5231 * add it to *user.
5233 static isl_stat pw_multi_aff_from_map(__isl_take isl_map *map, void *user)
5235 isl_union_pw_multi_aff **upma = user;
5236 isl_pw_multi_aff *pma;
5238 pma = isl_pw_multi_aff_from_map(map);
5239 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
5241 return *upma ? isl_stat_ok : isl_stat_error;
5244 /* Create an isl_union_pw_multi_aff with the given isl_aff on a universe
5245 * domain.
5247 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff(
5248 __isl_take isl_aff *aff)
5250 isl_multi_aff *ma;
5251 isl_pw_multi_aff *pma;
5253 ma = isl_multi_aff_from_aff(aff);
5254 pma = isl_pw_multi_aff_from_multi_aff(ma);
5255 return isl_union_pw_multi_aff_from_pw_multi_aff(pma);
5258 /* Try and create an isl_union_pw_multi_aff that is equivalent
5259 * to the given isl_union_map.
5260 * The isl_union_map is required to be single-valued in each space.
5261 * Otherwise, an error is produced.
5263 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map(
5264 __isl_take isl_union_map *umap)
5266 isl_space *space;
5267 isl_union_pw_multi_aff *upma;
5269 space = isl_union_map_get_space(umap);
5270 upma = isl_union_pw_multi_aff_empty(space);
5271 if (isl_union_map_foreach_map(umap, &pw_multi_aff_from_map, &upma) < 0)
5272 upma = isl_union_pw_multi_aff_free(upma);
5273 isl_union_map_free(umap);
5275 return upma;
5278 /* Try and create an isl_union_pw_multi_aff that is equivalent
5279 * to the given isl_union_set.
5280 * The isl_union_set is required to be a singleton in each space.
5281 * Otherwise, an error is produced.
5283 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set(
5284 __isl_take isl_union_set *uset)
5286 return isl_union_pw_multi_aff_from_union_map(uset);
5289 /* Return the piecewise affine expression "set ? 1 : 0".
5291 __isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set)
5293 isl_pw_aff *pa;
5294 isl_space *space = isl_set_get_space(set);
5295 isl_local_space *ls = isl_local_space_from_space(space);
5296 isl_aff *zero = isl_aff_zero_on_domain(isl_local_space_copy(ls));
5297 isl_aff *one = isl_aff_zero_on_domain(ls);
5299 one = isl_aff_add_constant_si(one, 1);
5300 pa = isl_pw_aff_alloc(isl_set_copy(set), one);
5301 set = isl_set_complement(set);
5302 pa = isl_pw_aff_add_disjoint(pa, isl_pw_aff_alloc(set, zero));
5304 return pa;
5307 /* Plug in "subs" for dimension "type", "pos" of "aff".
5309 * Let i be the dimension to replace and let "subs" be of the form
5311 * f/d
5313 * and "aff" of the form
5315 * (a i + g)/m
5317 * The result is
5319 * (a f + d g')/(m d)
5321 * where g' is the result of plugging in "subs" in each of the integer
5322 * divisions in g.
5324 __isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *aff,
5325 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
5327 isl_ctx *ctx;
5328 isl_int v;
5330 aff = isl_aff_cow(aff);
5331 if (!aff || !subs)
5332 return isl_aff_free(aff);
5334 ctx = isl_aff_get_ctx(aff);
5335 if (!isl_space_is_equal(aff->ls->dim, subs->ls->dim))
5336 isl_die(ctx, isl_error_invalid,
5337 "spaces don't match", return isl_aff_free(aff));
5338 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
5339 isl_die(ctx, isl_error_unsupported,
5340 "cannot handle divs yet", return isl_aff_free(aff));
5342 aff->ls = isl_local_space_substitute(aff->ls, type, pos, subs);
5343 if (!aff->ls)
5344 return isl_aff_free(aff);
5346 aff->v = isl_vec_cow(aff->v);
5347 if (!aff->v)
5348 return isl_aff_free(aff);
5350 pos += isl_local_space_offset(aff->ls, type);
5352 isl_int_init(v);
5353 isl_seq_substitute(aff->v->el, pos, subs->v->el,
5354 aff->v->size, subs->v->size, v);
5355 isl_int_clear(v);
5357 return aff;
5360 /* Plug in "subs" for dimension "type", "pos" in each of the affine
5361 * expressions in "maff".
5363 __isl_give isl_multi_aff *isl_multi_aff_substitute(
5364 __isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos,
5365 __isl_keep isl_aff *subs)
5367 int i;
5369 maff = isl_multi_aff_cow(maff);
5370 if (!maff || !subs)
5371 return isl_multi_aff_free(maff);
5373 if (type == isl_dim_in)
5374 type = isl_dim_set;
5376 for (i = 0; i < maff->n; ++i) {
5377 maff->p[i] = isl_aff_substitute(maff->p[i], type, pos, subs);
5378 if (!maff->p[i])
5379 return isl_multi_aff_free(maff);
5382 return maff;
5385 /* Plug in "subs" for dimension "type", "pos" of "pma".
5387 * pma is of the form
5389 * A_i(v) -> M_i(v)
5391 * while subs is of the form
5393 * v' = B_j(v) -> S_j
5395 * Each pair i,j such that C_ij = A_i \cap B_i is non-empty
5396 * has a contribution in the result, in particular
5398 * C_ij(S_j) -> M_i(S_j)
5400 * Note that plugging in S_j in C_ij may also result in an empty set
5401 * and this contribution should simply be discarded.
5403 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute(
5404 __isl_take isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned pos,
5405 __isl_keep isl_pw_aff *subs)
5407 int i, j, n;
5408 isl_pw_multi_aff *res;
5410 if (!pma || !subs)
5411 return isl_pw_multi_aff_free(pma);
5413 n = pma->n * subs->n;
5414 res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma->dim), n);
5416 for (i = 0; i < pma->n; ++i) {
5417 for (j = 0; j < subs->n; ++j) {
5418 isl_set *common;
5419 isl_multi_aff *res_ij;
5420 int empty;
5422 common = isl_set_intersect(
5423 isl_set_copy(pma->p[i].set),
5424 isl_set_copy(subs->p[j].set));
5425 common = isl_set_substitute(common,
5426 type, pos, subs->p[j].aff);
5427 empty = isl_set_plain_is_empty(common);
5428 if (empty < 0 || empty) {
5429 isl_set_free(common);
5430 if (empty < 0)
5431 goto error;
5432 continue;
5435 res_ij = isl_multi_aff_substitute(
5436 isl_multi_aff_copy(pma->p[i].maff),
5437 type, pos, subs->p[j].aff);
5439 res = isl_pw_multi_aff_add_piece(res, common, res_ij);
5443 isl_pw_multi_aff_free(pma);
5444 return res;
5445 error:
5446 isl_pw_multi_aff_free(pma);
5447 isl_pw_multi_aff_free(res);
5448 return NULL;
5451 /* Compute the preimage of a range of dimensions in the affine expression "src"
5452 * under "ma" and put the result in "dst". The number of dimensions in "src"
5453 * that precede the range is given by "n_before". The number of dimensions
5454 * in the range is given by the number of output dimensions of "ma".
5455 * The number of dimensions that follow the range is given by "n_after".
5456 * If "has_denom" is set (to one),
5457 * then "src" and "dst" have an extra initial denominator.
5458 * "n_div_ma" is the number of existentials in "ma"
5459 * "n_div_bset" is the number of existentials in "src"
5460 * The resulting "dst" (which is assumed to have been allocated by
5461 * the caller) contains coefficients for both sets of existentials,
5462 * first those in "ma" and then those in "src".
5463 * f, c1, c2 and g are temporary objects that have been initialized
5464 * by the caller.
5466 * Let src represent the expression
5468 * (a(p) + f_u u + b v + f_w w + c(divs))/d
5470 * and let ma represent the expressions
5472 * v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i
5474 * We start out with the following expression for dst:
5476 * (a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d
5478 * with the multiplication factor f initially equal to 1
5479 * and f \sum_i b_i v_i kept separately.
5480 * For each x_i that we substitute, we multiply the numerator
5481 * (and denominator) of dst by c_1 = m_i and add the numerator
5482 * of the x_i expression multiplied by c_2 = f b_i,
5483 * after removing the common factors of c_1 and c_2.
5484 * The multiplication factor f also needs to be multiplied by c_1
5485 * for the next x_j, j > i.
5487 void isl_seq_preimage(isl_int *dst, isl_int *src,
5488 __isl_keep isl_multi_aff *ma, int n_before, int n_after,
5489 int n_div_ma, int n_div_bmap,
5490 isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom)
5492 int i;
5493 int n_param, n_in, n_out;
5494 int o_dst, o_src;
5496 n_param = isl_multi_aff_dim(ma, isl_dim_param);
5497 n_in = isl_multi_aff_dim(ma, isl_dim_in);
5498 n_out = isl_multi_aff_dim(ma, isl_dim_out);
5500 isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before);
5501 o_dst = o_src = has_denom + 1 + n_param + n_before;
5502 isl_seq_clr(dst + o_dst, n_in);
5503 o_dst += n_in;
5504 o_src += n_out;
5505 isl_seq_cpy(dst + o_dst, src + o_src, n_after);
5506 o_dst += n_after;
5507 o_src += n_after;
5508 isl_seq_clr(dst + o_dst, n_div_ma);
5509 o_dst += n_div_ma;
5510 isl_seq_cpy(dst + o_dst, src + o_src, n_div_bmap);
5512 isl_int_set_si(f, 1);
5514 for (i = 0; i < n_out; ++i) {
5515 int offset = has_denom + 1 + n_param + n_before + i;
5517 if (isl_int_is_zero(src[offset]))
5518 continue;
5519 isl_int_set(c1, ma->p[i]->v->el[0]);
5520 isl_int_mul(c2, f, src[offset]);
5521 isl_int_gcd(g, c1, c2);
5522 isl_int_divexact(c1, c1, g);
5523 isl_int_divexact(c2, c2, g);
5525 isl_int_mul(f, f, c1);
5526 o_dst = has_denom;
5527 o_src = 1;
5528 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5529 c2, ma->p[i]->v->el + o_src, 1 + n_param);
5530 o_dst += 1 + n_param;
5531 o_src += 1 + n_param;
5532 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_before);
5533 o_dst += n_before;
5534 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5535 c2, ma->p[i]->v->el + o_src, n_in);
5536 o_dst += n_in;
5537 o_src += n_in;
5538 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_after);
5539 o_dst += n_after;
5540 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5541 c2, ma->p[i]->v->el + o_src, n_div_ma);
5542 o_dst += n_div_ma;
5543 o_src += n_div_ma;
5544 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_div_bmap);
5545 if (has_denom)
5546 isl_int_mul(dst[0], dst[0], c1);
5550 /* Compute the pullback of "aff" by the function represented by "ma".
5551 * In other words, plug in "ma" in "aff". The result is an affine expression
5552 * defined over the domain space of "ma".
5554 * If "aff" is represented by
5556 * (a(p) + b x + c(divs))/d
5558 * and ma is represented by
5560 * x = D(p) + F(y) + G(divs')
5562 * then the result is
5564 * (a(p) + b D(p) + b F(y) + b G(divs') + c(divs))/d
5566 * The divs in the local space of the input are similarly adjusted
5567 * through a call to isl_local_space_preimage_multi_aff.
5569 __isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
5570 __isl_take isl_multi_aff *ma)
5572 isl_aff *res = NULL;
5573 isl_local_space *ls;
5574 int n_div_aff, n_div_ma;
5575 isl_int f, c1, c2, g;
5577 ma = isl_multi_aff_align_divs(ma);
5578 if (!aff || !ma)
5579 goto error;
5581 n_div_aff = isl_aff_dim(aff, isl_dim_div);
5582 n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
5584 ls = isl_aff_get_domain_local_space(aff);
5585 ls = isl_local_space_preimage_multi_aff(ls, isl_multi_aff_copy(ma));
5586 res = isl_aff_alloc(ls);
5587 if (!res)
5588 goto error;
5590 isl_int_init(f);
5591 isl_int_init(c1);
5592 isl_int_init(c2);
5593 isl_int_init(g);
5595 isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0, n_div_ma, n_div_aff,
5596 f, c1, c2, g, 1);
5598 isl_int_clear(f);
5599 isl_int_clear(c1);
5600 isl_int_clear(c2);
5601 isl_int_clear(g);
5603 isl_aff_free(aff);
5604 isl_multi_aff_free(ma);
5605 res = isl_aff_normalize(res);
5606 return res;
5607 error:
5608 isl_aff_free(aff);
5609 isl_multi_aff_free(ma);
5610 isl_aff_free(res);
5611 return NULL;
5614 /* Compute the pullback of "aff1" by the function represented by "aff2".
5615 * In other words, plug in "aff2" in "aff1". The result is an affine expression
5616 * defined over the domain space of "aff1".
5618 * The domain of "aff1" should match the range of "aff2", which means
5619 * that it should be single-dimensional.
5621 __isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
5622 __isl_take isl_aff *aff2)
5624 isl_multi_aff *ma;
5626 ma = isl_multi_aff_from_aff(aff2);
5627 return isl_aff_pullback_multi_aff(aff1, ma);
5630 /* Compute the pullback of "ma1" by the function represented by "ma2".
5631 * In other words, plug in "ma2" in "ma1".
5633 * The parameters of "ma1" and "ma2" are assumed to have been aligned.
5635 static __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff_aligned(
5636 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
5638 int i;
5639 isl_space *space = NULL;
5641 ma2 = isl_multi_aff_align_divs(ma2);
5642 ma1 = isl_multi_aff_cow(ma1);
5643 if (!ma1 || !ma2)
5644 goto error;
5646 space = isl_space_join(isl_multi_aff_get_space(ma2),
5647 isl_multi_aff_get_space(ma1));
5649 for (i = 0; i < ma1->n; ++i) {
5650 ma1->p[i] = isl_aff_pullback_multi_aff(ma1->p[i],
5651 isl_multi_aff_copy(ma2));
5652 if (!ma1->p[i])
5653 goto error;
5656 ma1 = isl_multi_aff_reset_space(ma1, space);
5657 isl_multi_aff_free(ma2);
5658 return ma1;
5659 error:
5660 isl_space_free(space);
5661 isl_multi_aff_free(ma2);
5662 isl_multi_aff_free(ma1);
5663 return NULL;
5666 /* Compute the pullback of "ma1" by the function represented by "ma2".
5667 * In other words, plug in "ma2" in "ma1".
5669 __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
5670 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
5672 return isl_multi_aff_align_params_multi_multi_and(ma1, ma2,
5673 &isl_multi_aff_pullback_multi_aff_aligned);
5676 /* Extend the local space of "dst" to include the divs
5677 * in the local space of "src".
5679 __isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst,
5680 __isl_keep isl_aff *src)
5682 isl_ctx *ctx;
5683 int *exp1 = NULL;
5684 int *exp2 = NULL;
5685 isl_mat *div;
5687 if (!src || !dst)
5688 return isl_aff_free(dst);
5690 ctx = isl_aff_get_ctx(src);
5691 if (!isl_space_is_equal(src->ls->dim, dst->ls->dim))
5692 isl_die(ctx, isl_error_invalid,
5693 "spaces don't match", goto error);
5695 if (src->ls->div->n_row == 0)
5696 return dst;
5698 exp1 = isl_alloc_array(ctx, int, src->ls->div->n_row);
5699 exp2 = isl_alloc_array(ctx, int, dst->ls->div->n_row);
5700 if (!exp1 || (dst->ls->div->n_row && !exp2))
5701 goto error;
5703 div = isl_merge_divs(src->ls->div, dst->ls->div, exp1, exp2);
5704 dst = isl_aff_expand_divs(dst, div, exp2);
5705 free(exp1);
5706 free(exp2);
5708 return dst;
5709 error:
5710 free(exp1);
5711 free(exp2);
5712 return isl_aff_free(dst);
5715 /* Adjust the local spaces of the affine expressions in "maff"
5716 * such that they all have the save divs.
5718 __isl_give isl_multi_aff *isl_multi_aff_align_divs(
5719 __isl_take isl_multi_aff *maff)
5721 int i;
5723 if (!maff)
5724 return NULL;
5725 if (maff->n == 0)
5726 return maff;
5727 maff = isl_multi_aff_cow(maff);
5728 if (!maff)
5729 return NULL;
5731 for (i = 1; i < maff->n; ++i)
5732 maff->p[0] = isl_aff_align_divs(maff->p[0], maff->p[i]);
5733 for (i = 1; i < maff->n; ++i) {
5734 maff->p[i] = isl_aff_align_divs(maff->p[i], maff->p[0]);
5735 if (!maff->p[i])
5736 return isl_multi_aff_free(maff);
5739 return maff;
5742 __isl_give isl_aff *isl_aff_lift(__isl_take isl_aff *aff)
5744 aff = isl_aff_cow(aff);
5745 if (!aff)
5746 return NULL;
5748 aff->ls = isl_local_space_lift(aff->ls);
5749 if (!aff->ls)
5750 return isl_aff_free(aff);
5752 return aff;
5755 /* Lift "maff" to a space with extra dimensions such that the result
5756 * has no more existentially quantified variables.
5757 * If "ls" is not NULL, then *ls is assigned the local space that lies
5758 * at the basis of the lifting applied to "maff".
5760 __isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
5761 __isl_give isl_local_space **ls)
5763 int i;
5764 isl_space *space;
5765 unsigned n_div;
5767 if (ls)
5768 *ls = NULL;
5770 if (!maff)
5771 return NULL;
5773 if (maff->n == 0) {
5774 if (ls) {
5775 isl_space *space = isl_multi_aff_get_domain_space(maff);
5776 *ls = isl_local_space_from_space(space);
5777 if (!*ls)
5778 return isl_multi_aff_free(maff);
5780 return maff;
5783 maff = isl_multi_aff_cow(maff);
5784 maff = isl_multi_aff_align_divs(maff);
5785 if (!maff)
5786 return NULL;
5788 n_div = isl_aff_dim(maff->p[0], isl_dim_div);
5789 space = isl_multi_aff_get_space(maff);
5790 space = isl_space_lift(isl_space_domain(space), n_div);
5791 space = isl_space_extend_domain_with_range(space,
5792 isl_multi_aff_get_space(maff));
5793 if (!space)
5794 return isl_multi_aff_free(maff);
5795 isl_space_free(maff->space);
5796 maff->space = space;
5798 if (ls) {
5799 *ls = isl_aff_get_domain_local_space(maff->p[0]);
5800 if (!*ls)
5801 return isl_multi_aff_free(maff);
5804 for (i = 0; i < maff->n; ++i) {
5805 maff->p[i] = isl_aff_lift(maff->p[i]);
5806 if (!maff->p[i])
5807 goto error;
5810 return maff;
5811 error:
5812 if (ls)
5813 isl_local_space_free(*ls);
5814 return isl_multi_aff_free(maff);
5818 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma".
5820 __isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
5821 __isl_keep isl_pw_multi_aff *pma, int pos)
5823 int i;
5824 int n_out;
5825 isl_space *space;
5826 isl_pw_aff *pa;
5828 if (!pma)
5829 return NULL;
5831 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
5832 if (pos < 0 || pos >= n_out)
5833 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
5834 "index out of bounds", return NULL);
5836 space = isl_pw_multi_aff_get_space(pma);
5837 space = isl_space_drop_dims(space, isl_dim_out,
5838 pos + 1, n_out - pos - 1);
5839 space = isl_space_drop_dims(space, isl_dim_out, 0, pos);
5841 pa = isl_pw_aff_alloc_size(space, pma->n);
5842 for (i = 0; i < pma->n; ++i) {
5843 isl_aff *aff;
5844 aff = isl_multi_aff_get_aff(pma->p[i].maff, pos);
5845 pa = isl_pw_aff_add_piece(pa, isl_set_copy(pma->p[i].set), aff);
5848 return pa;
5851 /* Return an isl_pw_multi_aff with the given "set" as domain and
5852 * an unnamed zero-dimensional range.
5854 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
5855 __isl_take isl_set *set)
5857 isl_multi_aff *ma;
5858 isl_space *space;
5860 space = isl_set_get_space(set);
5861 space = isl_space_from_domain(space);
5862 ma = isl_multi_aff_zero(space);
5863 return isl_pw_multi_aff_alloc(set, ma);
5866 /* Add an isl_pw_multi_aff with the given "set" as domain and
5867 * an unnamed zero-dimensional range to *user.
5869 static isl_stat add_pw_multi_aff_from_domain(__isl_take isl_set *set,
5870 void *user)
5872 isl_union_pw_multi_aff **upma = user;
5873 isl_pw_multi_aff *pma;
5875 pma = isl_pw_multi_aff_from_domain(set);
5876 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
5878 return isl_stat_ok;
5881 /* Return an isl_union_pw_multi_aff with the given "uset" as domain and
5882 * an unnamed zero-dimensional range.
5884 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
5885 __isl_take isl_union_set *uset)
5887 isl_space *space;
5888 isl_union_pw_multi_aff *upma;
5890 if (!uset)
5891 return NULL;
5893 space = isl_union_set_get_space(uset);
5894 upma = isl_union_pw_multi_aff_empty(space);
5896 if (isl_union_set_foreach_set(uset,
5897 &add_pw_multi_aff_from_domain, &upma) < 0)
5898 goto error;
5900 isl_union_set_free(uset);
5901 return upma;
5902 error:
5903 isl_union_set_free(uset);
5904 isl_union_pw_multi_aff_free(upma);
5905 return NULL;
5908 /* Convert "pma" to an isl_map and add it to *umap.
5910 static isl_stat map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma,
5911 void *user)
5913 isl_union_map **umap = user;
5914 isl_map *map;
5916 map = isl_map_from_pw_multi_aff(pma);
5917 *umap = isl_union_map_add_map(*umap, map);
5919 return isl_stat_ok;
5922 /* Construct a union map mapping the domain of the union
5923 * piecewise multi-affine expression to its range, with each dimension
5924 * in the range equated to the corresponding affine expression on its cell.
5926 __isl_give isl_union_map *isl_union_map_from_union_pw_multi_aff(
5927 __isl_take isl_union_pw_multi_aff *upma)
5929 isl_space *space;
5930 isl_union_map *umap;
5932 if (!upma)
5933 return NULL;
5935 space = isl_union_pw_multi_aff_get_space(upma);
5936 umap = isl_union_map_empty(space);
5938 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
5939 &map_from_pw_multi_aff, &umap) < 0)
5940 goto error;
5942 isl_union_pw_multi_aff_free(upma);
5943 return umap;
5944 error:
5945 isl_union_pw_multi_aff_free(upma);
5946 isl_union_map_free(umap);
5947 return NULL;
5950 /* Local data for bin_entry and the callback "fn".
5952 struct isl_union_pw_multi_aff_bin_data {
5953 isl_union_pw_multi_aff *upma2;
5954 isl_union_pw_multi_aff *res;
5955 isl_pw_multi_aff *pma;
5956 isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user);
5959 /* Given an isl_pw_multi_aff from upma1, store it in data->pma
5960 * and call data->fn for each isl_pw_multi_aff in data->upma2.
5962 static isl_stat bin_entry(__isl_take isl_pw_multi_aff *pma, void *user)
5964 struct isl_union_pw_multi_aff_bin_data *data = user;
5965 isl_stat r;
5967 data->pma = pma;
5968 r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma2,
5969 data->fn, data);
5970 isl_pw_multi_aff_free(pma);
5972 return r;
5975 /* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
5976 * The isl_pw_multi_aff from upma1 is stored in data->pma (where data is
5977 * passed as user field) and the isl_pw_multi_aff from upma2 is available
5978 * as *entry. The callback should adjust data->res if desired.
5980 static __isl_give isl_union_pw_multi_aff *bin_op(
5981 __isl_take isl_union_pw_multi_aff *upma1,
5982 __isl_take isl_union_pw_multi_aff *upma2,
5983 isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user))
5985 isl_space *space;
5986 struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn };
5988 space = isl_union_pw_multi_aff_get_space(upma2);
5989 upma1 = isl_union_pw_multi_aff_align_params(upma1, space);
5990 space = isl_union_pw_multi_aff_get_space(upma1);
5991 upma2 = isl_union_pw_multi_aff_align_params(upma2, space);
5993 if (!upma1 || !upma2)
5994 goto error;
5996 data.upma2 = upma2;
5997 data.res = isl_union_pw_multi_aff_alloc_same_size(upma1);
5998 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1,
5999 &bin_entry, &data) < 0)
6000 goto error;
6002 isl_union_pw_multi_aff_free(upma1);
6003 isl_union_pw_multi_aff_free(upma2);
6004 return data.res;
6005 error:
6006 isl_union_pw_multi_aff_free(upma1);
6007 isl_union_pw_multi_aff_free(upma2);
6008 isl_union_pw_multi_aff_free(data.res);
6009 return NULL;
6012 /* Given two aligned isl_pw_multi_affs A -> B and C -> D,
6013 * construct an isl_pw_multi_aff (A * C) -> [B -> D].
6015 static __isl_give isl_pw_multi_aff *pw_multi_aff_range_product(
6016 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6018 isl_space *space;
6020 space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
6021 isl_pw_multi_aff_get_space(pma2));
6022 return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
6023 &isl_multi_aff_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_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_range_product);
6036 /* Given two aligned isl_pw_multi_affs A -> B and C -> D,
6037 * construct an isl_pw_multi_aff (A * C) -> (B, D).
6039 static __isl_give isl_pw_multi_aff *pw_multi_aff_flat_range_product(
6040 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6042 isl_space *space;
6044 space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
6045 isl_pw_multi_aff_get_space(pma2));
6046 space = isl_space_flatten_range(space);
6047 return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
6048 &isl_multi_aff_flat_range_product);
6051 /* Given two isl_pw_multi_affs A -> B and C -> D,
6052 * construct an isl_pw_multi_aff (A * C) -> (B, D).
6054 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
6055 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6057 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
6058 &pw_multi_aff_flat_range_product);
6061 /* If data->pma and "pma2" have the same domain space, then compute
6062 * their flat range product and the result to data->res.
6064 static isl_stat flat_range_product_entry(__isl_take isl_pw_multi_aff *pma2,
6065 void *user)
6067 struct isl_union_pw_multi_aff_bin_data *data = user;
6069 if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
6070 pma2->dim, isl_dim_in)) {
6071 isl_pw_multi_aff_free(pma2);
6072 return isl_stat_ok;
6075 pma2 = isl_pw_multi_aff_flat_range_product(
6076 isl_pw_multi_aff_copy(data->pma), pma2);
6078 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
6080 return isl_stat_ok;
6083 /* Given two isl_union_pw_multi_affs A -> B and C -> D,
6084 * construct an isl_union_pw_multi_aff (A * C) -> (B, D).
6086 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_flat_range_product(
6087 __isl_take isl_union_pw_multi_aff *upma1,
6088 __isl_take isl_union_pw_multi_aff *upma2)
6090 return bin_op(upma1, upma2, &flat_range_product_entry);
6093 /* Replace the affine expressions at position "pos" in "pma" by "pa".
6094 * The parameters are assumed to have been aligned.
6096 * The implementation essentially performs an isl_pw_*_on_shared_domain,
6097 * except that it works on two different isl_pw_* types.
6099 static __isl_give isl_pw_multi_aff *pw_multi_aff_set_pw_aff(
6100 __isl_take isl_pw_multi_aff *pma, unsigned pos,
6101 __isl_take isl_pw_aff *pa)
6103 int i, j, n;
6104 isl_pw_multi_aff *res = NULL;
6106 if (!pma || !pa)
6107 goto error;
6109 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_in,
6110 pa->dim, isl_dim_in))
6111 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6112 "domains don't match", goto error);
6113 if (pos >= isl_pw_multi_aff_dim(pma, isl_dim_out))
6114 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6115 "index out of bounds", goto error);
6117 n = pma->n * pa->n;
6118 res = isl_pw_multi_aff_alloc_size(isl_pw_multi_aff_get_space(pma), n);
6120 for (i = 0; i < pma->n; ++i) {
6121 for (j = 0; j < pa->n; ++j) {
6122 isl_set *common;
6123 isl_multi_aff *res_ij;
6124 int empty;
6126 common = isl_set_intersect(isl_set_copy(pma->p[i].set),
6127 isl_set_copy(pa->p[j].set));
6128 empty = isl_set_plain_is_empty(common);
6129 if (empty < 0 || empty) {
6130 isl_set_free(common);
6131 if (empty < 0)
6132 goto error;
6133 continue;
6136 res_ij = isl_multi_aff_set_aff(
6137 isl_multi_aff_copy(pma->p[i].maff), pos,
6138 isl_aff_copy(pa->p[j].aff));
6139 res_ij = isl_multi_aff_gist(res_ij,
6140 isl_set_copy(common));
6142 res = isl_pw_multi_aff_add_piece(res, common, res_ij);
6146 isl_pw_multi_aff_free(pma);
6147 isl_pw_aff_free(pa);
6148 return res;
6149 error:
6150 isl_pw_multi_aff_free(pma);
6151 isl_pw_aff_free(pa);
6152 return isl_pw_multi_aff_free(res);
6155 /* Replace the affine expressions at position "pos" in "pma" by "pa".
6157 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
6158 __isl_take isl_pw_multi_aff *pma, unsigned pos,
6159 __isl_take isl_pw_aff *pa)
6161 if (!pma || !pa)
6162 goto error;
6163 if (isl_space_match(pma->dim, isl_dim_param, pa->dim, isl_dim_param))
6164 return pw_multi_aff_set_pw_aff(pma, pos, pa);
6165 if (!isl_space_has_named_params(pma->dim) ||
6166 !isl_space_has_named_params(pa->dim))
6167 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6168 "unaligned unnamed parameters", goto error);
6169 pma = isl_pw_multi_aff_align_params(pma, isl_pw_aff_get_space(pa));
6170 pa = isl_pw_aff_align_params(pa, isl_pw_multi_aff_get_space(pma));
6171 return pw_multi_aff_set_pw_aff(pma, pos, pa);
6172 error:
6173 isl_pw_multi_aff_free(pma);
6174 isl_pw_aff_free(pa);
6175 return NULL;
6178 /* Do the parameters of "pa" match those of "space"?
6180 int isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa,
6181 __isl_keep isl_space *space)
6183 isl_space *pa_space;
6184 int match;
6186 if (!pa || !space)
6187 return -1;
6189 pa_space = isl_pw_aff_get_space(pa);
6191 match = isl_space_match(space, isl_dim_param, pa_space, isl_dim_param);
6193 isl_space_free(pa_space);
6194 return match;
6197 /* Check that the domain space of "pa" matches "space".
6199 * Return 0 on success and -1 on error.
6201 int isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
6202 __isl_keep isl_space *space)
6204 isl_space *pa_space;
6205 int match;
6207 if (!pa || !space)
6208 return -1;
6210 pa_space = isl_pw_aff_get_space(pa);
6212 match = isl_space_match(space, isl_dim_param, pa_space, isl_dim_param);
6213 if (match < 0)
6214 goto error;
6215 if (!match)
6216 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
6217 "parameters don't match", goto error);
6218 match = isl_space_tuple_is_equal(space, isl_dim_in,
6219 pa_space, isl_dim_in);
6220 if (match < 0)
6221 goto error;
6222 if (!match)
6223 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
6224 "domains don't match", goto error);
6225 isl_space_free(pa_space);
6226 return 0;
6227 error:
6228 isl_space_free(pa_space);
6229 return -1;
6232 #undef BASE
6233 #define BASE pw_aff
6234 #undef DOMBASE
6235 #define DOMBASE set
6237 #include <isl_multi_templ.c>
6238 #include <isl_multi_apply_set.c>
6239 #include <isl_multi_coalesce.c>
6240 #include <isl_multi_gist.c>
6241 #include <isl_multi_hash.c>
6242 #include <isl_multi_intersect.c>
6244 /* Scale the elements of "pma" by the corresponding elements of "mv".
6246 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
6247 __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv)
6249 int i;
6251 pma = isl_pw_multi_aff_cow(pma);
6252 if (!pma || !mv)
6253 goto error;
6254 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
6255 mv->space, isl_dim_set))
6256 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6257 "spaces don't match", goto error);
6258 if (!isl_space_match(pma->dim, isl_dim_param,
6259 mv->space, isl_dim_param)) {
6260 pma = isl_pw_multi_aff_align_params(pma,
6261 isl_multi_val_get_space(mv));
6262 mv = isl_multi_val_align_params(mv,
6263 isl_pw_multi_aff_get_space(pma));
6264 if (!pma || !mv)
6265 goto error;
6268 for (i = 0; i < pma->n; ++i) {
6269 pma->p[i].maff = isl_multi_aff_scale_multi_val(pma->p[i].maff,
6270 isl_multi_val_copy(mv));
6271 if (!pma->p[i].maff)
6272 goto error;
6275 isl_multi_val_free(mv);
6276 return pma;
6277 error:
6278 isl_multi_val_free(mv);
6279 isl_pw_multi_aff_free(pma);
6280 return NULL;
6283 /* This function is called for each entry of an isl_union_pw_multi_aff.
6284 * If the space of the entry matches that of data->mv,
6285 * then apply isl_pw_multi_aff_scale_multi_val and return the result.
6286 * Otherwise, return an empty isl_pw_multi_aff.
6288 static __isl_give isl_pw_multi_aff *union_pw_multi_aff_scale_multi_val_entry(
6289 __isl_take isl_pw_multi_aff *pma, void *user)
6291 isl_multi_val *mv = user;
6293 if (!pma)
6294 return NULL;
6295 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
6296 mv->space, isl_dim_set)) {
6297 isl_space *space = isl_pw_multi_aff_get_space(pma);
6298 isl_pw_multi_aff_free(pma);
6299 return isl_pw_multi_aff_empty(space);
6302 return isl_pw_multi_aff_scale_multi_val(pma, isl_multi_val_copy(mv));
6305 /* Scale the elements of "upma" by the corresponding elements of "mv",
6306 * for those entries that match the space of "mv".
6308 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
6309 __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv)
6311 upma = isl_union_pw_multi_aff_align_params(upma,
6312 isl_multi_val_get_space(mv));
6313 mv = isl_multi_val_align_params(mv,
6314 isl_union_pw_multi_aff_get_space(upma));
6315 if (!upma || !mv)
6316 goto error;
6318 return isl_union_pw_multi_aff_transform(upma,
6319 &union_pw_multi_aff_scale_multi_val_entry, mv);
6321 isl_multi_val_free(mv);
6322 return upma;
6323 error:
6324 isl_multi_val_free(mv);
6325 isl_union_pw_multi_aff_free(upma);
6326 return NULL;
6329 /* Construct and return a piecewise multi affine expression
6330 * in the given space with value zero in each of the output dimensions and
6331 * a universe domain.
6333 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(__isl_take isl_space *space)
6335 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_zero(space));
6338 /* Construct and return a piecewise multi affine expression
6339 * that is equal to the given piecewise affine expression.
6341 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff(
6342 __isl_take isl_pw_aff *pa)
6344 int i;
6345 isl_space *space;
6346 isl_pw_multi_aff *pma;
6348 if (!pa)
6349 return NULL;
6351 space = isl_pw_aff_get_space(pa);
6352 pma = isl_pw_multi_aff_alloc_size(space, pa->n);
6354 for (i = 0; i < pa->n; ++i) {
6355 isl_set *set;
6356 isl_multi_aff *ma;
6358 set = isl_set_copy(pa->p[i].set);
6359 ma = isl_multi_aff_from_aff(isl_aff_copy(pa->p[i].aff));
6360 pma = isl_pw_multi_aff_add_piece(pma, set, ma);
6363 isl_pw_aff_free(pa);
6364 return pma;
6367 /* Construct a set or map mapping the shared (parameter) domain
6368 * of the piecewise affine expressions to the range of "mpa"
6369 * with each dimension in the range equated to the
6370 * corresponding piecewise affine expression.
6372 static __isl_give isl_map *map_from_multi_pw_aff(
6373 __isl_take isl_multi_pw_aff *mpa)
6375 int i;
6376 isl_space *space;
6377 isl_map *map;
6379 if (!mpa)
6380 return NULL;
6382 if (isl_space_dim(mpa->space, isl_dim_out) != mpa->n)
6383 isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
6384 "invalid space", goto error);
6386 space = isl_multi_pw_aff_get_domain_space(mpa);
6387 map = isl_map_universe(isl_space_from_domain(space));
6389 for (i = 0; i < mpa->n; ++i) {
6390 isl_pw_aff *pa;
6391 isl_map *map_i;
6393 pa = isl_pw_aff_copy(mpa->p[i]);
6394 map_i = map_from_pw_aff(pa);
6396 map = isl_map_flat_range_product(map, map_i);
6399 map = isl_map_reset_space(map, isl_multi_pw_aff_get_space(mpa));
6401 isl_multi_pw_aff_free(mpa);
6402 return map;
6403 error:
6404 isl_multi_pw_aff_free(mpa);
6405 return NULL;
6408 /* Construct a map mapping the shared domain
6409 * of the piecewise affine expressions to the range of "mpa"
6410 * with each dimension in the range equated to the
6411 * corresponding piecewise affine expression.
6413 __isl_give isl_map *isl_map_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 map", goto error);
6421 return map_from_multi_pw_aff(mpa);
6422 error:
6423 isl_multi_pw_aff_free(mpa);
6424 return NULL;
6427 /* Construct a set mapping the shared parameter domain
6428 * of the piecewise affine expressions to the space of "mpa"
6429 * with each dimension in the range equated to the
6430 * corresponding piecewise affine expression.
6432 __isl_give isl_set *isl_set_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa)
6434 if (!mpa)
6435 return NULL;
6436 if (!isl_space_is_set(mpa->space))
6437 isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
6438 "space of input is not a set", goto error);
6440 return map_from_multi_pw_aff(mpa);
6441 error:
6442 isl_multi_pw_aff_free(mpa);
6443 return NULL;
6446 /* Construct and return a piecewise multi affine expression
6447 * that is equal to the given multi piecewise affine expression
6448 * on the shared domain of the piecewise affine expressions.
6450 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff(
6451 __isl_take isl_multi_pw_aff *mpa)
6453 int i;
6454 isl_space *space;
6455 isl_pw_aff *pa;
6456 isl_pw_multi_aff *pma;
6458 if (!mpa)
6459 return NULL;
6461 space = isl_multi_pw_aff_get_space(mpa);
6463 if (mpa->n == 0) {
6464 isl_multi_pw_aff_free(mpa);
6465 return isl_pw_multi_aff_zero(space);
6468 pa = isl_multi_pw_aff_get_pw_aff(mpa, 0);
6469 pma = isl_pw_multi_aff_from_pw_aff(pa);
6471 for (i = 1; i < mpa->n; ++i) {
6472 isl_pw_multi_aff *pma_i;
6474 pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
6475 pma_i = isl_pw_multi_aff_from_pw_aff(pa);
6476 pma = isl_pw_multi_aff_range_product(pma, pma_i);
6479 pma = isl_pw_multi_aff_reset_space(pma, space);
6481 isl_multi_pw_aff_free(mpa);
6482 return pma;
6485 /* Construct and return a multi piecewise affine expression
6486 * that is equal to the given multi affine expression.
6488 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
6489 __isl_take isl_multi_aff *ma)
6491 int i, n;
6492 isl_multi_pw_aff *mpa;
6494 if (!ma)
6495 return NULL;
6497 n = isl_multi_aff_dim(ma, isl_dim_out);
6498 mpa = isl_multi_pw_aff_alloc(isl_multi_aff_get_space(ma));
6500 for (i = 0; i < n; ++i) {
6501 isl_pw_aff *pa;
6503 pa = isl_pw_aff_from_aff(isl_multi_aff_get_aff(ma, i));
6504 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
6507 isl_multi_aff_free(ma);
6508 return mpa;
6511 /* Construct and return a multi piecewise affine expression
6512 * that is equal to the given piecewise multi affine expression.
6514 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
6515 __isl_take isl_pw_multi_aff *pma)
6517 int i, n;
6518 isl_space *space;
6519 isl_multi_pw_aff *mpa;
6521 if (!pma)
6522 return NULL;
6524 n = isl_pw_multi_aff_dim(pma, isl_dim_out);
6525 space = isl_pw_multi_aff_get_space(pma);
6526 mpa = isl_multi_pw_aff_alloc(space);
6528 for (i = 0; i < n; ++i) {
6529 isl_pw_aff *pa;
6531 pa = isl_pw_multi_aff_get_pw_aff(pma, i);
6532 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
6535 isl_pw_multi_aff_free(pma);
6536 return mpa;
6539 /* Do "pa1" and "pa2" represent the same function?
6541 * We first check if they are obviously equal.
6542 * If not, we convert them to maps and check if those are equal.
6544 int isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1, __isl_keep isl_pw_aff *pa2)
6546 int equal;
6547 isl_map *map1, *map2;
6549 if (!pa1 || !pa2)
6550 return -1;
6552 equal = isl_pw_aff_plain_is_equal(pa1, pa2);
6553 if (equal < 0 || equal)
6554 return equal;
6556 map1 = map_from_pw_aff(isl_pw_aff_copy(pa1));
6557 map2 = map_from_pw_aff(isl_pw_aff_copy(pa2));
6558 equal = isl_map_is_equal(map1, map2);
6559 isl_map_free(map1);
6560 isl_map_free(map2);
6562 return equal;
6565 /* Do "mpa1" and "mpa2" represent the same function?
6567 * Note that we cannot convert the entire isl_multi_pw_aff
6568 * to a map because the domains of the piecewise affine expressions
6569 * may not be the same.
6571 isl_bool isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
6572 __isl_keep isl_multi_pw_aff *mpa2)
6574 int i;
6575 isl_bool equal;
6577 if (!mpa1 || !mpa2)
6578 return isl_bool_error;
6580 if (!isl_space_match(mpa1->space, isl_dim_param,
6581 mpa2->space, isl_dim_param)) {
6582 if (!isl_space_has_named_params(mpa1->space))
6583 return isl_bool_false;
6584 if (!isl_space_has_named_params(mpa2->space))
6585 return isl_bool_false;
6586 mpa1 = isl_multi_pw_aff_copy(mpa1);
6587 mpa2 = isl_multi_pw_aff_copy(mpa2);
6588 mpa1 = isl_multi_pw_aff_align_params(mpa1,
6589 isl_multi_pw_aff_get_space(mpa2));
6590 mpa2 = isl_multi_pw_aff_align_params(mpa2,
6591 isl_multi_pw_aff_get_space(mpa1));
6592 equal = isl_multi_pw_aff_is_equal(mpa1, mpa2);
6593 isl_multi_pw_aff_free(mpa1);
6594 isl_multi_pw_aff_free(mpa2);
6595 return equal;
6598 equal = isl_space_is_equal(mpa1->space, mpa2->space);
6599 if (equal < 0 || !equal)
6600 return equal;
6602 for (i = 0; i < mpa1->n; ++i) {
6603 equal = isl_pw_aff_is_equal(mpa1->p[i], mpa2->p[i]);
6604 if (equal < 0 || !equal)
6605 return equal;
6608 return isl_bool_true;
6611 /* Compute the pullback of "mpa" by the function represented by "ma".
6612 * In other words, plug in "ma" in "mpa".
6614 * The parameters of "mpa" and "ma" are assumed to have been aligned.
6616 static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff_aligned(
6617 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
6619 int i;
6620 isl_space *space = NULL;
6622 mpa = isl_multi_pw_aff_cow(mpa);
6623 if (!mpa || !ma)
6624 goto error;
6626 space = isl_space_join(isl_multi_aff_get_space(ma),
6627 isl_multi_pw_aff_get_space(mpa));
6628 if (!space)
6629 goto error;
6631 for (i = 0; i < mpa->n; ++i) {
6632 mpa->p[i] = isl_pw_aff_pullback_multi_aff(mpa->p[i],
6633 isl_multi_aff_copy(ma));
6634 if (!mpa->p[i])
6635 goto error;
6638 isl_multi_aff_free(ma);
6639 isl_space_free(mpa->space);
6640 mpa->space = space;
6641 return mpa;
6642 error:
6643 isl_space_free(space);
6644 isl_multi_pw_aff_free(mpa);
6645 isl_multi_aff_free(ma);
6646 return NULL;
6649 /* Compute the pullback of "mpa" by the function represented by "ma".
6650 * In other words, plug in "ma" in "mpa".
6652 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff(
6653 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
6655 if (!mpa || !ma)
6656 goto error;
6657 if (isl_space_match(mpa->space, isl_dim_param,
6658 ma->space, isl_dim_param))
6659 return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
6660 mpa = isl_multi_pw_aff_align_params(mpa, isl_multi_aff_get_space(ma));
6661 ma = isl_multi_aff_align_params(ma, isl_multi_pw_aff_get_space(mpa));
6662 return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
6663 error:
6664 isl_multi_pw_aff_free(mpa);
6665 isl_multi_aff_free(ma);
6666 return NULL;
6669 /* Compute the pullback of "mpa" by the function represented by "pma".
6670 * In other words, plug in "pma" in "mpa".
6672 * The parameters of "mpa" and "mpa" are assumed to have been aligned.
6674 static __isl_give isl_multi_pw_aff *
6675 isl_multi_pw_aff_pullback_pw_multi_aff_aligned(
6676 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
6678 int i;
6679 isl_space *space = NULL;
6681 mpa = isl_multi_pw_aff_cow(mpa);
6682 if (!mpa || !pma)
6683 goto error;
6685 space = isl_space_join(isl_pw_multi_aff_get_space(pma),
6686 isl_multi_pw_aff_get_space(mpa));
6688 for (i = 0; i < mpa->n; ++i) {
6689 mpa->p[i] = isl_pw_aff_pullback_pw_multi_aff_aligned(mpa->p[i],
6690 isl_pw_multi_aff_copy(pma));
6691 if (!mpa->p[i])
6692 goto error;
6695 isl_pw_multi_aff_free(pma);
6696 isl_space_free(mpa->space);
6697 mpa->space = space;
6698 return mpa;
6699 error:
6700 isl_space_free(space);
6701 isl_multi_pw_aff_free(mpa);
6702 isl_pw_multi_aff_free(pma);
6703 return NULL;
6706 /* Compute the pullback of "mpa" by the function represented by "pma".
6707 * In other words, plug in "pma" in "mpa".
6709 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_pw_multi_aff(
6710 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
6712 if (!mpa || !pma)
6713 goto error;
6714 if (isl_space_match(mpa->space, isl_dim_param, pma->dim, isl_dim_param))
6715 return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
6716 mpa = isl_multi_pw_aff_align_params(mpa,
6717 isl_pw_multi_aff_get_space(pma));
6718 pma = isl_pw_multi_aff_align_params(pma,
6719 isl_multi_pw_aff_get_space(mpa));
6720 return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
6721 error:
6722 isl_multi_pw_aff_free(mpa);
6723 isl_pw_multi_aff_free(pma);
6724 return NULL;
6727 /* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
6728 * with the domain of "aff". The domain of the result is the same
6729 * as that of "mpa".
6730 * "mpa" and "aff" are assumed to have been aligned.
6732 * We first extract the parametric constant from "aff", defined
6733 * over the correct domain.
6734 * Then we add the appropriate combinations of the members of "mpa".
6735 * Finally, we add the integer divisions through recursive calls.
6737 static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff_aligned(
6738 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
6740 int i, n_in, n_div;
6741 isl_space *space;
6742 isl_val *v;
6743 isl_pw_aff *pa;
6744 isl_aff *tmp;
6746 n_in = isl_aff_dim(aff, isl_dim_in);
6747 n_div = isl_aff_dim(aff, isl_dim_div);
6749 space = isl_space_domain(isl_multi_pw_aff_get_space(mpa));
6750 tmp = isl_aff_copy(aff);
6751 tmp = isl_aff_drop_dims(tmp, isl_dim_div, 0, n_div);
6752 tmp = isl_aff_drop_dims(tmp, isl_dim_in, 0, n_in);
6753 tmp = isl_aff_add_dims(tmp, isl_dim_in,
6754 isl_space_dim(space, isl_dim_set));
6755 tmp = isl_aff_reset_domain_space(tmp, space);
6756 pa = isl_pw_aff_from_aff(tmp);
6758 for (i = 0; i < n_in; ++i) {
6759 isl_pw_aff *pa_i;
6761 if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
6762 continue;
6763 v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
6764 pa_i = isl_multi_pw_aff_get_pw_aff(mpa, i);
6765 pa_i = isl_pw_aff_scale_val(pa_i, v);
6766 pa = isl_pw_aff_add(pa, pa_i);
6769 for (i = 0; i < n_div; ++i) {
6770 isl_aff *div;
6771 isl_pw_aff *pa_i;
6773 if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
6774 continue;
6775 div = isl_aff_get_div(aff, i);
6776 pa_i = isl_multi_pw_aff_apply_aff_aligned(
6777 isl_multi_pw_aff_copy(mpa), div);
6778 pa_i = isl_pw_aff_floor(pa_i);
6779 v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
6780 pa_i = isl_pw_aff_scale_val(pa_i, v);
6781 pa = isl_pw_aff_add(pa, pa_i);
6784 isl_multi_pw_aff_free(mpa);
6785 isl_aff_free(aff);
6787 return pa;
6790 /* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
6791 * with the domain of "aff". The domain of the result is the same
6792 * as that of "mpa".
6794 __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff(
6795 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
6797 if (!aff || !mpa)
6798 goto error;
6799 if (isl_space_match(aff->ls->dim, isl_dim_param,
6800 mpa->space, isl_dim_param))
6801 return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
6803 aff = isl_aff_align_params(aff, isl_multi_pw_aff_get_space(mpa));
6804 mpa = isl_multi_pw_aff_align_params(mpa, isl_aff_get_space(aff));
6806 return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
6807 error:
6808 isl_aff_free(aff);
6809 isl_multi_pw_aff_free(mpa);
6810 return NULL;
6813 /* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
6814 * with the domain of "pa". The domain of the result is the same
6815 * as that of "mpa".
6816 * "mpa" and "pa" are assumed to have been aligned.
6818 * We consider each piece in turn. Note that the domains of the
6819 * pieces are assumed to be disjoint and they remain disjoint
6820 * after taking the preimage (over the same function).
6822 static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff_aligned(
6823 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
6825 isl_space *space;
6826 isl_pw_aff *res;
6827 int i;
6829 if (!mpa || !pa)
6830 goto error;
6832 space = isl_space_join(isl_multi_pw_aff_get_space(mpa),
6833 isl_pw_aff_get_space(pa));
6834 res = isl_pw_aff_empty(space);
6836 for (i = 0; i < pa->n; ++i) {
6837 isl_pw_aff *pa_i;
6838 isl_set *domain;
6840 pa_i = isl_multi_pw_aff_apply_aff_aligned(
6841 isl_multi_pw_aff_copy(mpa),
6842 isl_aff_copy(pa->p[i].aff));
6843 domain = isl_set_copy(pa->p[i].set);
6844 domain = isl_set_preimage_multi_pw_aff(domain,
6845 isl_multi_pw_aff_copy(mpa));
6846 pa_i = isl_pw_aff_intersect_domain(pa_i, domain);
6847 res = isl_pw_aff_add_disjoint(res, pa_i);
6850 isl_pw_aff_free(pa);
6851 isl_multi_pw_aff_free(mpa);
6852 return res;
6853 error:
6854 isl_pw_aff_free(pa);
6855 isl_multi_pw_aff_free(mpa);
6856 return NULL;
6859 /* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
6860 * with the domain of "pa". The domain of the result is the same
6861 * as that of "mpa".
6863 __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff(
6864 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
6866 if (!pa || !mpa)
6867 goto error;
6868 if (isl_space_match(pa->dim, isl_dim_param, mpa->space, isl_dim_param))
6869 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
6871 pa = isl_pw_aff_align_params(pa, isl_multi_pw_aff_get_space(mpa));
6872 mpa = isl_multi_pw_aff_align_params(mpa, isl_pw_aff_get_space(pa));
6874 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
6875 error:
6876 isl_pw_aff_free(pa);
6877 isl_multi_pw_aff_free(mpa);
6878 return NULL;
6881 /* Compute the pullback of "pa" by the function represented by "mpa".
6882 * In other words, plug in "mpa" in "pa".
6883 * "pa" and "mpa" are assumed to have been aligned.
6885 * The pullback is computed by applying "pa" to "mpa".
6887 static __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff_aligned(
6888 __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
6890 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
6893 /* Compute the pullback of "pa" by the function represented by "mpa".
6894 * In other words, plug in "mpa" in "pa".
6896 * The pullback is computed by applying "pa" to "mpa".
6898 __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
6899 __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
6901 return isl_multi_pw_aff_apply_pw_aff(mpa, pa);
6904 /* Compute the pullback of "mpa1" by the function represented by "mpa2".
6905 * In other words, plug in "mpa2" in "mpa1".
6907 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
6909 * We pullback each member of "mpa1" in turn.
6911 static __isl_give isl_multi_pw_aff *
6912 isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
6913 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
6915 int i;
6916 isl_space *space = NULL;
6918 mpa1 = isl_multi_pw_aff_cow(mpa1);
6919 if (!mpa1 || !mpa2)
6920 goto error;
6922 space = isl_space_join(isl_multi_pw_aff_get_space(mpa2),
6923 isl_multi_pw_aff_get_space(mpa1));
6925 for (i = 0; i < mpa1->n; ++i) {
6926 mpa1->p[i] = isl_pw_aff_pullback_multi_pw_aff_aligned(
6927 mpa1->p[i], isl_multi_pw_aff_copy(mpa2));
6928 if (!mpa1->p[i])
6929 goto error;
6932 mpa1 = isl_multi_pw_aff_reset_space(mpa1, space);
6934 isl_multi_pw_aff_free(mpa2);
6935 return mpa1;
6936 error:
6937 isl_space_free(space);
6938 isl_multi_pw_aff_free(mpa1);
6939 isl_multi_pw_aff_free(mpa2);
6940 return NULL;
6943 /* Compute the pullback of "mpa1" by the function represented by "mpa2".
6944 * In other words, plug in "mpa2" in "mpa1".
6946 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_pw_aff(
6947 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
6949 return isl_multi_pw_aff_align_params_multi_multi_and(mpa1, mpa2,
6950 &isl_multi_pw_aff_pullback_multi_pw_aff_aligned);
6953 /* Align the parameters of "mpa1" and "mpa2", check that the ranges
6954 * of "mpa1" and "mpa2" live in the same space, construct map space
6955 * between the domain spaces of "mpa1" and "mpa2" and call "order"
6956 * with this map space as extract argument.
6958 static __isl_give isl_map *isl_multi_pw_aff_order_map(
6959 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
6960 __isl_give isl_map *(*order)(__isl_keep isl_multi_pw_aff *mpa1,
6961 __isl_keep isl_multi_pw_aff *mpa2, __isl_take isl_space *space))
6963 int match;
6964 isl_space *space1, *space2;
6965 isl_map *res;
6967 mpa1 = isl_multi_pw_aff_align_params(mpa1,
6968 isl_multi_pw_aff_get_space(mpa2));
6969 mpa2 = isl_multi_pw_aff_align_params(mpa2,
6970 isl_multi_pw_aff_get_space(mpa1));
6971 if (!mpa1 || !mpa2)
6972 goto error;
6973 match = isl_space_tuple_is_equal(mpa1->space, isl_dim_out,
6974 mpa2->space, isl_dim_out);
6975 if (match < 0)
6976 goto error;
6977 if (!match)
6978 isl_die(isl_multi_pw_aff_get_ctx(mpa1), isl_error_invalid,
6979 "range spaces don't match", goto error);
6980 space1 = isl_space_domain(isl_multi_pw_aff_get_space(mpa1));
6981 space2 = isl_space_domain(isl_multi_pw_aff_get_space(mpa2));
6982 space1 = isl_space_map_from_domain_and_range(space1, space2);
6984 res = order(mpa1, mpa2, space1);
6985 isl_multi_pw_aff_free(mpa1);
6986 isl_multi_pw_aff_free(mpa2);
6987 return res;
6988 error:
6989 isl_multi_pw_aff_free(mpa1);
6990 isl_multi_pw_aff_free(mpa2);
6991 return NULL;
6994 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
6995 * where the function values are equal. "space" is the space of the result.
6996 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
6998 * "mpa1" and "mpa2" are equal when each of the pairs of elements
6999 * in the sequences are equal.
7001 static __isl_give isl_map *isl_multi_pw_aff_eq_map_on_space(
7002 __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2,
7003 __isl_take isl_space *space)
7005 int i, n;
7006 isl_map *res;
7008 res = isl_map_universe(space);
7010 n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
7011 for (i = 0; i < n; ++i) {
7012 isl_pw_aff *pa1, *pa2;
7013 isl_map *map;
7015 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7016 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7017 map = isl_pw_aff_eq_map(pa1, pa2);
7018 res = isl_map_intersect(res, map);
7021 return res;
7024 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7025 * where the function values are equal.
7027 __isl_give isl_map *isl_multi_pw_aff_eq_map(__isl_take isl_multi_pw_aff *mpa1,
7028 __isl_take isl_multi_pw_aff *mpa2)
7030 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7031 &isl_multi_pw_aff_eq_map_on_space);
7034 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7035 * where the function values of "mpa1" is lexicographically satisfies "base"
7036 * compared to that of "mpa2". "space" is the space of the result.
7037 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7039 * "mpa1" lexicographically satisfies "base" compared to "mpa2"
7040 * if its i-th element satisfies "base" when compared to
7041 * the i-th element of "mpa2" while all previous elements are
7042 * pairwise equal.
7044 static __isl_give isl_map *isl_multi_pw_aff_lex_map_on_space(
7045 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
7046 __isl_give isl_map *(*base)(__isl_take isl_pw_aff *pa1,
7047 __isl_take isl_pw_aff *pa2),
7048 __isl_take isl_space *space)
7050 int i, n;
7051 isl_map *res, *rest;
7053 res = isl_map_empty(isl_space_copy(space));
7054 rest = isl_map_universe(space);
7056 n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
7057 for (i = 0; i < n; ++i) {
7058 isl_pw_aff *pa1, *pa2;
7059 isl_map *map;
7061 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7062 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7063 map = base(pa1, pa2);
7064 map = isl_map_intersect(map, isl_map_copy(rest));
7065 res = isl_map_union(res, map);
7067 if (i == n - 1)
7068 continue;
7070 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7071 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7072 map = isl_pw_aff_eq_map(pa1, pa2);
7073 rest = isl_map_intersect(rest, map);
7076 isl_map_free(rest);
7077 return res;
7080 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7081 * where the function value of "mpa1" is lexicographically less than that
7082 * of "mpa2". "space" is the space of the result.
7083 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7085 * "mpa1" is less than "mpa2" if its i-th element is smaller
7086 * than the i-th element of "mpa2" while all previous elements are
7087 * pairwise equal.
7089 __isl_give isl_map *isl_multi_pw_aff_lex_lt_map_on_space(
7090 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
7091 __isl_take isl_space *space)
7093 return isl_multi_pw_aff_lex_map_on_space(mpa1, mpa2,
7094 &isl_pw_aff_lt_map, space);
7097 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7098 * where the function value of "mpa1" is lexicographically less than that
7099 * of "mpa2".
7101 __isl_give isl_map *isl_multi_pw_aff_lex_lt_map(
7102 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
7104 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7105 &isl_multi_pw_aff_lex_lt_map_on_space);
7108 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7109 * where the function value of "mpa1" is lexicographically greater than that
7110 * of "mpa2". "space" is the space of the result.
7111 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7113 * "mpa1" is greater than "mpa2" if its i-th element is greater
7114 * than the i-th element of "mpa2" while all previous elements are
7115 * pairwise equal.
7117 __isl_give isl_map *isl_multi_pw_aff_lex_gt_map_on_space(
7118 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
7119 __isl_take isl_space *space)
7121 return isl_multi_pw_aff_lex_map_on_space(mpa1, mpa2,
7122 &isl_pw_aff_gt_map, space);
7125 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7126 * where the function value of "mpa1" is lexicographically greater than that
7127 * of "mpa2".
7129 __isl_give isl_map *isl_multi_pw_aff_lex_gt_map(
7130 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
7132 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7133 &isl_multi_pw_aff_lex_gt_map_on_space);
7136 /* Compare two isl_affs.
7138 * Return -1 if "aff1" is "smaller" than "aff2", 1 if "aff1" is "greater"
7139 * than "aff2" and 0 if they are equal.
7141 * The order is fairly arbitrary. We do consider expressions that only involve
7142 * earlier dimensions as "smaller".
7144 int isl_aff_plain_cmp(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2)
7146 int cmp;
7147 int last1, last2;
7149 if (aff1 == aff2)
7150 return 0;
7152 if (!aff1)
7153 return -1;
7154 if (!aff2)
7155 return 1;
7157 cmp = isl_local_space_cmp(aff1->ls, aff2->ls);
7158 if (cmp != 0)
7159 return cmp;
7161 last1 = isl_seq_last_non_zero(aff1->v->el + 1, aff1->v->size - 1);
7162 last2 = isl_seq_last_non_zero(aff2->v->el + 1, aff1->v->size - 1);
7163 if (last1 != last2)
7164 return last1 - last2;
7166 return isl_seq_cmp(aff1->v->el, aff2->v->el, aff1->v->size);
7169 /* Compare two isl_pw_affs.
7171 * Return -1 if "pa1" is "smaller" than "pa2", 1 if "pa1" is "greater"
7172 * than "pa2" and 0 if they are equal.
7174 * The order is fairly arbitrary. We do consider expressions that only involve
7175 * earlier dimensions as "smaller".
7177 int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1,
7178 __isl_keep isl_pw_aff *pa2)
7180 int i;
7181 int cmp;
7183 if (pa1 == pa2)
7184 return 0;
7186 if (!pa1)
7187 return -1;
7188 if (!pa2)
7189 return 1;
7191 cmp = isl_space_cmp(pa1->dim, pa2->dim);
7192 if (cmp != 0)
7193 return cmp;
7195 if (pa1->n != pa2->n)
7196 return pa1->n - pa2->n;
7198 for (i = 0; i < pa1->n; ++i) {
7199 cmp = isl_set_plain_cmp(pa1->p[i].set, pa2->p[i].set);
7200 if (cmp != 0)
7201 return cmp;
7202 cmp = isl_aff_plain_cmp(pa1->p[i].aff, pa2->p[i].aff);
7203 if (cmp != 0)
7204 return cmp;
7207 return 0;
7210 /* Return a piecewise affine expression that is equal to "v" on "domain".
7212 __isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
7213 __isl_take isl_val *v)
7215 isl_space *space;
7216 isl_local_space *ls;
7217 isl_aff *aff;
7219 space = isl_set_get_space(domain);
7220 ls = isl_local_space_from_space(space);
7221 aff = isl_aff_val_on_domain(ls, v);
7223 return isl_pw_aff_alloc(domain, aff);
7226 /* Return a multi affine expression that is equal to "mv" on domain
7227 * space "space".
7229 __isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
7230 __isl_take isl_space *space, __isl_take isl_multi_val *mv)
7232 int i, n;
7233 isl_space *space2;
7234 isl_local_space *ls;
7235 isl_multi_aff *ma;
7237 if (!space || !mv)
7238 goto error;
7240 n = isl_multi_val_dim(mv, isl_dim_set);
7241 space2 = isl_multi_val_get_space(mv);
7242 space2 = isl_space_align_params(space2, isl_space_copy(space));
7243 space = isl_space_align_params(space, isl_space_copy(space2));
7244 space = isl_space_map_from_domain_and_range(space, space2);
7245 ma = isl_multi_aff_alloc(isl_space_copy(space));
7246 ls = isl_local_space_from_space(isl_space_domain(space));
7247 for (i = 0; i < n; ++i) {
7248 isl_val *v;
7249 isl_aff *aff;
7251 v = isl_multi_val_get_val(mv, i);
7252 aff = isl_aff_val_on_domain(isl_local_space_copy(ls), v);
7253 ma = isl_multi_aff_set_aff(ma, i, aff);
7255 isl_local_space_free(ls);
7257 isl_multi_val_free(mv);
7258 return ma;
7259 error:
7260 isl_space_free(space);
7261 isl_multi_val_free(mv);
7262 return NULL;
7265 /* Return a piecewise multi-affine expression
7266 * that is equal to "mv" on "domain".
7268 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_multi_val_on_domain(
7269 __isl_take isl_set *domain, __isl_take isl_multi_val *mv)
7271 isl_space *space;
7272 isl_multi_aff *ma;
7274 space = isl_set_get_space(domain);
7275 ma = isl_multi_aff_multi_val_on_space(space, mv);
7277 return isl_pw_multi_aff_alloc(domain, ma);
7280 /* Internal data structure for isl_union_pw_multi_aff_multi_val_on_domain.
7281 * mv is the value that should be attained on each domain set
7282 * res collects the results
7284 struct isl_union_pw_multi_aff_multi_val_on_domain_data {
7285 isl_multi_val *mv;
7286 isl_union_pw_multi_aff *res;
7289 /* Create an isl_pw_multi_aff equal to data->mv on "domain"
7290 * and add it to data->res.
7292 static isl_stat pw_multi_aff_multi_val_on_domain(__isl_take isl_set *domain,
7293 void *user)
7295 struct isl_union_pw_multi_aff_multi_val_on_domain_data *data = user;
7296 isl_pw_multi_aff *pma;
7297 isl_multi_val *mv;
7299 mv = isl_multi_val_copy(data->mv);
7300 pma = isl_pw_multi_aff_multi_val_on_domain(domain, mv);
7301 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
7303 return data->res ? isl_stat_ok : isl_stat_error;
7306 /* Return a union piecewise multi-affine expression
7307 * that is equal to "mv" on "domain".
7309 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_multi_val_on_domain(
7310 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
7312 struct isl_union_pw_multi_aff_multi_val_on_domain_data data;
7313 isl_space *space;
7315 space = isl_union_set_get_space(domain);
7316 data.res = isl_union_pw_multi_aff_empty(space);
7317 data.mv = mv;
7318 if (isl_union_set_foreach_set(domain,
7319 &pw_multi_aff_multi_val_on_domain, &data) < 0)
7320 data.res = isl_union_pw_multi_aff_free(data.res);
7321 isl_union_set_free(domain);
7322 isl_multi_val_free(mv);
7323 return data.res;
7326 /* Compute the pullback of data->pma by the function represented by "pma2",
7327 * provided the spaces match, and add the results to data->res.
7329 static isl_stat pullback_entry(__isl_take isl_pw_multi_aff *pma2, void *user)
7331 struct isl_union_pw_multi_aff_bin_data *data = user;
7333 if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
7334 pma2->dim, isl_dim_out)) {
7335 isl_pw_multi_aff_free(pma2);
7336 return isl_stat_ok;
7339 pma2 = isl_pw_multi_aff_pullback_pw_multi_aff(
7340 isl_pw_multi_aff_copy(data->pma), pma2);
7342 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
7343 if (!data->res)
7344 return isl_stat_error;
7346 return isl_stat_ok;
7349 /* Compute the pullback of "upma1" by the function represented by "upma2".
7351 __isl_give isl_union_pw_multi_aff *
7352 isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
7353 __isl_take isl_union_pw_multi_aff *upma1,
7354 __isl_take isl_union_pw_multi_aff *upma2)
7356 return bin_op(upma1, upma2, &pullback_entry);
7359 /* Check that the domain space of "upa" matches "space".
7361 * Return 0 on success and -1 on error.
7363 * This function is called from isl_multi_union_pw_aff_set_union_pw_aff and
7364 * can in principle never fail since the space "space" is that
7365 * of the isl_multi_union_pw_aff and is a set space such that
7366 * there is no domain space to match.
7368 * We check the parameters and double-check that "space" is
7369 * indeed that of a set.
7371 static int isl_union_pw_aff_check_match_domain_space(
7372 __isl_keep isl_union_pw_aff *upa, __isl_keep isl_space *space)
7374 isl_space *upa_space;
7375 int match;
7377 if (!upa || !space)
7378 return -1;
7380 match = isl_space_is_set(space);
7381 if (match < 0)
7382 return -1;
7383 if (!match)
7384 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7385 "expecting set space", return -1);
7387 upa_space = isl_union_pw_aff_get_space(upa);
7388 match = isl_space_match(space, isl_dim_param, upa_space, isl_dim_param);
7389 if (match < 0)
7390 goto error;
7391 if (!match)
7392 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7393 "parameters don't match", goto error);
7395 isl_space_free(upa_space);
7396 return 0;
7397 error:
7398 isl_space_free(upa_space);
7399 return -1;
7402 /* Do the parameters of "upa" match those of "space"?
7404 static int isl_union_pw_aff_matching_params(__isl_keep isl_union_pw_aff *upa,
7405 __isl_keep isl_space *space)
7407 isl_space *upa_space;
7408 int match;
7410 if (!upa || !space)
7411 return -1;
7413 upa_space = isl_union_pw_aff_get_space(upa);
7415 match = isl_space_match(space, isl_dim_param, upa_space, isl_dim_param);
7417 isl_space_free(upa_space);
7418 return match;
7421 /* Internal data structure for isl_union_pw_aff_reset_domain_space.
7422 * space represents the new parameters.
7423 * res collects the results.
7425 struct isl_union_pw_aff_reset_params_data {
7426 isl_space *space;
7427 isl_union_pw_aff *res;
7430 /* Replace the parameters of "pa" by data->space and
7431 * add the result to data->res.
7433 static isl_stat reset_params(__isl_take isl_pw_aff *pa, void *user)
7435 struct isl_union_pw_aff_reset_params_data *data = user;
7436 isl_space *space;
7438 space = isl_pw_aff_get_space(pa);
7439 space = isl_space_replace(space, isl_dim_param, data->space);
7440 pa = isl_pw_aff_reset_space(pa, space);
7441 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7443 return data->res ? isl_stat_ok : isl_stat_error;
7446 /* Replace the domain space of "upa" by "space".
7447 * Since a union expression does not have a (single) domain space,
7448 * "space" is necessarily a parameter space.
7450 * Since the order and the names of the parameters determine
7451 * the hash value, we need to create a new hash table.
7453 static __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_domain_space(
7454 __isl_take isl_union_pw_aff *upa, __isl_take isl_space *space)
7456 struct isl_union_pw_aff_reset_params_data data = { space };
7457 int match;
7459 match = isl_union_pw_aff_matching_params(upa, space);
7460 if (match < 0)
7461 upa = isl_union_pw_aff_free(upa);
7462 else if (match) {
7463 isl_space_free(space);
7464 return upa;
7467 data.res = isl_union_pw_aff_empty(isl_space_copy(space));
7468 if (isl_union_pw_aff_foreach_pw_aff(upa, &reset_params, &data) < 0)
7469 data.res = isl_union_pw_aff_free(data.res);
7471 isl_union_pw_aff_free(upa);
7472 isl_space_free(space);
7473 return data.res;
7476 /* Return the floor of "pa".
7478 static __isl_give isl_pw_aff *floor_entry(__isl_take isl_pw_aff *pa, void *user)
7480 return isl_pw_aff_floor(pa);
7483 /* Given f, return floor(f).
7485 __isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
7486 __isl_take isl_union_pw_aff *upa)
7488 return isl_union_pw_aff_transform_inplace(upa, &floor_entry, NULL);
7491 /* Compute
7493 * upa mod m = upa - m * floor(upa/m)
7495 * with m an integer value.
7497 __isl_give isl_union_pw_aff *isl_union_pw_aff_mod_val(
7498 __isl_take isl_union_pw_aff *upa, __isl_take isl_val *m)
7500 isl_union_pw_aff *res;
7502 if (!upa || !m)
7503 goto error;
7505 if (!isl_val_is_int(m))
7506 isl_die(isl_val_get_ctx(m), isl_error_invalid,
7507 "expecting integer modulo", goto error);
7508 if (!isl_val_is_pos(m))
7509 isl_die(isl_val_get_ctx(m), isl_error_invalid,
7510 "expecting positive modulo", goto error);
7512 res = isl_union_pw_aff_copy(upa);
7513 upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(m));
7514 upa = isl_union_pw_aff_floor(upa);
7515 upa = isl_union_pw_aff_scale_val(upa, m);
7516 res = isl_union_pw_aff_sub(res, upa);
7518 return res;
7519 error:
7520 isl_val_free(m);
7521 isl_union_pw_aff_free(upa);
7522 return NULL;
7525 /* Internal data structure for isl_union_pw_aff_aff_on_domain.
7526 * "aff" is the symbolic value that the resulting isl_union_pw_aff
7527 * needs to attain.
7528 * "res" collects the results.
7530 struct isl_union_pw_aff_aff_on_domain_data {
7531 isl_aff *aff;
7532 isl_union_pw_aff *res;
7535 /* Construct a piecewise affine expression that is equal to data->aff
7536 * on "domain" and add the result to data->res.
7538 static isl_stat pw_aff_aff_on_domain(__isl_take isl_set *domain, void *user)
7540 struct isl_union_pw_aff_aff_on_domain_data *data = user;
7541 isl_pw_aff *pa;
7542 isl_aff *aff;
7543 int dim;
7545 aff = isl_aff_copy(data->aff);
7546 dim = isl_set_dim(domain, isl_dim_set);
7547 aff = isl_aff_add_dims(aff, isl_dim_in, dim);
7548 aff = isl_aff_reset_domain_space(aff, isl_set_get_space(domain));
7549 pa = isl_pw_aff_alloc(domain, aff);
7550 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7552 return data->res ? isl_stat_ok : isl_stat_error;
7555 /* Internal data structure for isl_union_pw_multi_aff_get_union_pw_aff.
7556 * pos is the output position that needs to be extracted.
7557 * res collects the results.
7559 struct isl_union_pw_multi_aff_get_union_pw_aff_data {
7560 int pos;
7561 isl_union_pw_aff *res;
7564 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma"
7565 * (assuming it has such a dimension) and add it to data->res.
7567 static isl_stat get_union_pw_aff(__isl_take isl_pw_multi_aff *pma, void *user)
7569 struct isl_union_pw_multi_aff_get_union_pw_aff_data *data = user;
7570 int n_out;
7571 isl_pw_aff *pa;
7573 if (!pma)
7574 return isl_stat_error;
7576 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
7577 if (data->pos >= n_out) {
7578 isl_pw_multi_aff_free(pma);
7579 return isl_stat_ok;
7582 pa = isl_pw_multi_aff_get_pw_aff(pma, data->pos);
7583 isl_pw_multi_aff_free(pma);
7585 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7587 return data->res ? isl_stat_ok : isl_stat_error;
7590 /* Extract an isl_union_pw_aff corresponding to
7591 * output dimension "pos" of "upma".
7593 __isl_give isl_union_pw_aff *isl_union_pw_multi_aff_get_union_pw_aff(
7594 __isl_keep isl_union_pw_multi_aff *upma, int pos)
7596 struct isl_union_pw_multi_aff_get_union_pw_aff_data data;
7597 isl_space *space;
7599 if (!upma)
7600 return NULL;
7602 if (pos < 0)
7603 isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
7604 "cannot extract at negative position", return NULL);
7606 space = isl_union_pw_multi_aff_get_space(upma);
7607 data.res = isl_union_pw_aff_empty(space);
7608 data.pos = pos;
7609 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
7610 &get_union_pw_aff, &data) < 0)
7611 data.res = isl_union_pw_aff_free(data.res);
7613 return data.res;
7616 /* Return a union piecewise affine expression
7617 * that is equal to "aff" on "domain".
7619 * Construct an isl_pw_aff on each of the sets in "domain" and
7620 * collect the results.
7622 __isl_give isl_union_pw_aff *isl_union_pw_aff_aff_on_domain(
7623 __isl_take isl_union_set *domain, __isl_take isl_aff *aff)
7625 struct isl_union_pw_aff_aff_on_domain_data data;
7626 isl_space *space;
7628 if (!domain || !aff)
7629 goto error;
7630 if (!isl_local_space_is_params(aff->ls))
7631 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
7632 "expecting parametric expression", goto error);
7634 space = isl_union_set_get_space(domain);
7635 data.res = isl_union_pw_aff_empty(space);
7636 data.aff = aff;
7637 if (isl_union_set_foreach_set(domain, &pw_aff_aff_on_domain, &data) < 0)
7638 data.res = isl_union_pw_aff_free(data.res);
7639 isl_union_set_free(domain);
7640 isl_aff_free(aff);
7641 return data.res;
7642 error:
7643 isl_union_set_free(domain);
7644 isl_aff_free(aff);
7645 return NULL;
7648 /* Internal data structure for isl_union_pw_aff_val_on_domain.
7649 * "v" is the value that the resulting isl_union_pw_aff needs to attain.
7650 * "res" collects the results.
7652 struct isl_union_pw_aff_val_on_domain_data {
7653 isl_val *v;
7654 isl_union_pw_aff *res;
7657 /* Construct a piecewise affine expression that is equal to data->v
7658 * on "domain" and add the result to data->res.
7660 static isl_stat pw_aff_val_on_domain(__isl_take isl_set *domain, void *user)
7662 struct isl_union_pw_aff_val_on_domain_data *data = user;
7663 isl_pw_aff *pa;
7664 isl_val *v;
7666 v = isl_val_copy(data->v);
7667 pa = isl_pw_aff_val_on_domain(domain, v);
7668 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7670 return data->res ? isl_stat_ok : isl_stat_error;
7673 /* Return a union piecewise affine expression
7674 * that is equal to "v" on "domain".
7676 * Construct an isl_pw_aff on each of the sets in "domain" and
7677 * collect the results.
7679 __isl_give isl_union_pw_aff *isl_union_pw_aff_val_on_domain(
7680 __isl_take isl_union_set *domain, __isl_take isl_val *v)
7682 struct isl_union_pw_aff_val_on_domain_data data;
7683 isl_space *space;
7685 space = isl_union_set_get_space(domain);
7686 data.res = isl_union_pw_aff_empty(space);
7687 data.v = v;
7688 if (isl_union_set_foreach_set(domain, &pw_aff_val_on_domain, &data) < 0)
7689 data.res = isl_union_pw_aff_free(data.res);
7690 isl_union_set_free(domain);
7691 isl_val_free(v);
7692 return data.res;
7695 /* Construct a piecewise multi affine expression
7696 * that is equal to "pa" and add it to upma.
7698 static isl_stat pw_multi_aff_from_pw_aff_entry(__isl_take isl_pw_aff *pa,
7699 void *user)
7701 isl_union_pw_multi_aff **upma = user;
7702 isl_pw_multi_aff *pma;
7704 pma = isl_pw_multi_aff_from_pw_aff(pa);
7705 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
7707 return *upma ? isl_stat_ok : isl_stat_error;
7710 /* Construct and return a union piecewise multi affine expression
7711 * that is equal to the given union piecewise affine expression.
7713 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_pw_aff(
7714 __isl_take isl_union_pw_aff *upa)
7716 isl_space *space;
7717 isl_union_pw_multi_aff *upma;
7719 if (!upa)
7720 return NULL;
7722 space = isl_union_pw_aff_get_space(upa);
7723 upma = isl_union_pw_multi_aff_empty(space);
7725 if (isl_union_pw_aff_foreach_pw_aff(upa,
7726 &pw_multi_aff_from_pw_aff_entry, &upma) < 0)
7727 upma = isl_union_pw_multi_aff_free(upma);
7729 isl_union_pw_aff_free(upa);
7730 return upma;
7733 /* Compute the set of elements in the domain of "pa" where it is zero and
7734 * add this set to "uset".
7736 static isl_stat zero_union_set(__isl_take isl_pw_aff *pa, void *user)
7738 isl_union_set **uset = (isl_union_set **)user;
7740 *uset = isl_union_set_add_set(*uset, isl_pw_aff_zero_set(pa));
7742 return *uset ? isl_stat_ok : isl_stat_error;
7745 /* Return a union set containing those elements in the domain
7746 * of "upa" where it is zero.
7748 __isl_give isl_union_set *isl_union_pw_aff_zero_union_set(
7749 __isl_take isl_union_pw_aff *upa)
7751 isl_union_set *zero;
7753 zero = isl_union_set_empty(isl_union_pw_aff_get_space(upa));
7754 if (isl_union_pw_aff_foreach_pw_aff(upa, &zero_union_set, &zero) < 0)
7755 zero = isl_union_set_free(zero);
7757 isl_union_pw_aff_free(upa);
7758 return zero;
7761 /* Convert "pa" to an isl_map and add it to *umap.
7763 static isl_stat map_from_pw_aff_entry(__isl_take isl_pw_aff *pa, void *user)
7765 isl_union_map **umap = user;
7766 isl_map *map;
7768 map = isl_map_from_pw_aff(pa);
7769 *umap = isl_union_map_add_map(*umap, map);
7771 return *umap ? isl_stat_ok : isl_stat_error;
7774 /* Construct a union map mapping the domain of the union
7775 * piecewise affine expression to its range, with the single output dimension
7776 * equated to the corresponding affine expressions on their cells.
7778 __isl_give isl_union_map *isl_union_map_from_union_pw_aff(
7779 __isl_take isl_union_pw_aff *upa)
7781 isl_space *space;
7782 isl_union_map *umap;
7784 if (!upa)
7785 return NULL;
7787 space = isl_union_pw_aff_get_space(upa);
7788 umap = isl_union_map_empty(space);
7790 if (isl_union_pw_aff_foreach_pw_aff(upa, &map_from_pw_aff_entry,
7791 &umap) < 0)
7792 umap = isl_union_map_free(umap);
7794 isl_union_pw_aff_free(upa);
7795 return umap;
7798 /* Internal data structure for isl_union_pw_aff_pullback_union_pw_multi_aff.
7799 * upma is the function that is plugged in.
7800 * pa is the current part of the function in which upma is plugged in.
7801 * res collects the results.
7803 struct isl_union_pw_aff_pullback_upma_data {
7804 isl_union_pw_multi_aff *upma;
7805 isl_pw_aff *pa;
7806 isl_union_pw_aff *res;
7809 /* Check if "pma" can be plugged into data->pa.
7810 * If so, perform the pullback and add the result to data->res.
7812 static isl_stat pa_pb_pma(__isl_take isl_pw_multi_aff *pma, void *user)
7814 struct isl_union_pw_aff_pullback_upma_data *data = user;
7815 isl_pw_aff *pa;
7817 if (!isl_space_tuple_is_equal(data->pa->dim, isl_dim_in,
7818 pma->dim, isl_dim_out)) {
7819 isl_pw_multi_aff_free(pma);
7820 return isl_stat_ok;
7823 pa = isl_pw_aff_copy(data->pa);
7824 pa = isl_pw_aff_pullback_pw_multi_aff(pa, pma);
7826 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7828 return data->res ? isl_stat_ok : isl_stat_error;
7831 /* Check if any of the elements of data->upma can be plugged into pa,
7832 * add if so add the result to data->res.
7834 static isl_stat upa_pb_upma(__isl_take isl_pw_aff *pa, void *user)
7836 struct isl_union_pw_aff_pullback_upma_data *data = user;
7837 isl_stat r;
7839 data->pa = pa;
7840 r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma,
7841 &pa_pb_pma, data);
7842 isl_pw_aff_free(pa);
7844 return r;
7847 /* Compute the pullback of "upa" by the function represented by "upma".
7848 * In other words, plug in "upma" in "upa". The result contains
7849 * expressions defined over the domain space of "upma".
7851 * Run over all pairs of elements in "upa" and "upma", perform
7852 * the pullback when appropriate and collect the results.
7853 * If the hash value were based on the domain space rather than
7854 * the function space, then we could run through all elements
7855 * of "upma" and directly pick out the corresponding element of "upa".
7857 __isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
7858 __isl_take isl_union_pw_aff *upa,
7859 __isl_take isl_union_pw_multi_aff *upma)
7861 struct isl_union_pw_aff_pullback_upma_data data = { NULL, NULL };
7862 isl_space *space;
7864 space = isl_union_pw_multi_aff_get_space(upma);
7865 upa = isl_union_pw_aff_align_params(upa, space);
7866 space = isl_union_pw_aff_get_space(upa);
7867 upma = isl_union_pw_multi_aff_align_params(upma, space);
7869 if (!upa || !upma)
7870 goto error;
7872 data.upma = upma;
7873 data.res = isl_union_pw_aff_alloc_same_size(upa);
7874 if (isl_union_pw_aff_foreach_pw_aff(upa, &upa_pb_upma, &data) < 0)
7875 data.res = isl_union_pw_aff_free(data.res);
7877 isl_union_pw_aff_free(upa);
7878 isl_union_pw_multi_aff_free(upma);
7879 return data.res;
7880 error:
7881 isl_union_pw_aff_free(upa);
7882 isl_union_pw_multi_aff_free(upma);
7883 return NULL;
7886 #undef BASE
7887 #define BASE union_pw_aff
7888 #undef DOMBASE
7889 #define DOMBASE union_set
7891 #define NO_MOVE_DIMS
7892 #define NO_DIMS
7893 #define NO_DOMAIN
7894 #define NO_PRODUCT
7895 #define NO_SPLICE
7896 #define NO_ZERO
7897 #define NO_IDENTITY
7898 #define NO_GIST
7900 #include <isl_multi_templ.c>
7901 #include <isl_multi_apply_set.c>
7902 #include <isl_multi_apply_union_set.c>
7903 #include <isl_multi_coalesce.c>
7904 #include <isl_multi_floor.c>
7905 #include <isl_multi_gist.c>
7906 #include <isl_multi_intersect.c>
7908 /* Construct a multiple union piecewise affine expression
7909 * in the given space with value zero in each of the output dimensions.
7911 * Since there is no canonical zero value for
7912 * a union piecewise affine expression, we can only construct
7913 * zero-dimensional "zero" value.
7915 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_zero(
7916 __isl_take isl_space *space)
7918 if (!space)
7919 return NULL;
7921 if (!isl_space_is_set(space))
7922 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7923 "expecting set space", goto error);
7924 if (isl_space_dim(space , isl_dim_out) != 0)
7925 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7926 "expecting 0D space", goto error);
7928 return isl_multi_union_pw_aff_alloc(space);
7929 error:
7930 isl_space_free(space);
7931 return NULL;
7934 /* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
7935 * with the actual sum on the shared domain and
7936 * the defined expression on the symmetric difference of the domains.
7938 * We simply iterate over the elements in both arguments and
7939 * call isl_union_pw_aff_union_add on each of them.
7941 static __isl_give isl_multi_union_pw_aff *
7942 isl_multi_union_pw_aff_union_add_aligned(
7943 __isl_take isl_multi_union_pw_aff *mupa1,
7944 __isl_take isl_multi_union_pw_aff *mupa2)
7946 return isl_multi_union_pw_aff_bin_op(mupa1, mupa2,
7947 &isl_union_pw_aff_union_add);
7950 /* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
7951 * with the actual sum on the shared domain and
7952 * the defined expression on the symmetric difference of the domains.
7954 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_union_add(
7955 __isl_take isl_multi_union_pw_aff *mupa1,
7956 __isl_take isl_multi_union_pw_aff *mupa2)
7958 return isl_multi_union_pw_aff_align_params_multi_multi_and(mupa1, mupa2,
7959 &isl_multi_union_pw_aff_union_add_aligned);
7962 /* Construct and return a multi union piecewise affine expression
7963 * that is equal to the given multi affine expression.
7965 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff(
7966 __isl_take isl_multi_aff *ma)
7968 isl_multi_pw_aff *mpa;
7970 mpa = isl_multi_pw_aff_from_multi_aff(ma);
7971 return isl_multi_union_pw_aff_from_multi_pw_aff(mpa);
7974 /* Construct and return a multi union piecewise affine expression
7975 * that is equal to the given multi piecewise affine expression.
7977 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff(
7978 __isl_take isl_multi_pw_aff *mpa)
7980 int i, n;
7981 isl_space *space;
7982 isl_multi_union_pw_aff *mupa;
7984 if (!mpa)
7985 return NULL;
7987 space = isl_multi_pw_aff_get_space(mpa);
7988 space = isl_space_range(space);
7989 mupa = isl_multi_union_pw_aff_alloc(space);
7991 n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
7992 for (i = 0; i < n; ++i) {
7993 isl_pw_aff *pa;
7994 isl_union_pw_aff *upa;
7996 pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
7997 upa = isl_union_pw_aff_from_pw_aff(pa);
7998 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8001 isl_multi_pw_aff_free(mpa);
8003 return mupa;
8006 /* Extract the range space of "pma" and assign it to *space.
8007 * If *space has already been set (through a previous call to this function),
8008 * then check that the range space is the same.
8010 static isl_stat extract_space(__isl_take isl_pw_multi_aff *pma, void *user)
8012 isl_space **space = user;
8013 isl_space *pma_space;
8014 isl_bool equal;
8016 pma_space = isl_space_range(isl_pw_multi_aff_get_space(pma));
8017 isl_pw_multi_aff_free(pma);
8019 if (!pma_space)
8020 return isl_stat_error;
8021 if (!*space) {
8022 *space = pma_space;
8023 return isl_stat_ok;
8026 equal = isl_space_is_equal(pma_space, *space);
8027 isl_space_free(pma_space);
8029 if (equal < 0)
8030 return isl_stat_error;
8031 if (!equal)
8032 isl_die(isl_space_get_ctx(*space), isl_error_invalid,
8033 "range spaces not the same", return isl_stat_error);
8034 return isl_stat_ok;
8037 /* Construct and return a multi union piecewise affine expression
8038 * that is equal to the given union piecewise multi affine expression.
8040 * In order to be able to perform the conversion, the input
8041 * needs to be non-empty and may only involve a single range space.
8043 __isl_give isl_multi_union_pw_aff *
8044 isl_multi_union_pw_aff_from_union_pw_multi_aff(
8045 __isl_take isl_union_pw_multi_aff *upma)
8047 isl_space *space = NULL;
8048 isl_multi_union_pw_aff *mupa;
8049 int i, n;
8051 if (!upma)
8052 return NULL;
8053 if (isl_union_pw_multi_aff_n_pw_multi_aff(upma) == 0)
8054 isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
8055 "cannot extract range space from empty input",
8056 goto error);
8057 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, &extract_space,
8058 &space) < 0)
8059 goto error;
8061 if (!space)
8062 goto error;
8064 n = isl_space_dim(space, isl_dim_set);
8065 mupa = isl_multi_union_pw_aff_alloc(space);
8067 for (i = 0; i < n; ++i) {
8068 isl_union_pw_aff *upa;
8070 upa = isl_union_pw_multi_aff_get_union_pw_aff(upma, i);
8071 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8074 isl_union_pw_multi_aff_free(upma);
8075 return mupa;
8076 error:
8077 isl_space_free(space);
8078 isl_union_pw_multi_aff_free(upma);
8079 return NULL;
8082 /* Try and create an isl_multi_union_pw_aff that is equivalent
8083 * to the given isl_union_map.
8084 * The isl_union_map is required to be single-valued in each space.
8085 * Moreover, it cannot be empty and all range spaces need to be the same.
8086 * Otherwise, an error is produced.
8088 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_map(
8089 __isl_take isl_union_map *umap)
8091 isl_union_pw_multi_aff *upma;
8093 upma = isl_union_pw_multi_aff_from_union_map(umap);
8094 return isl_multi_union_pw_aff_from_union_pw_multi_aff(upma);
8097 /* Return a multiple union piecewise affine expression
8098 * that is equal to "mv" on "domain", assuming "domain" and "mv"
8099 * have been aligned.
8101 static __isl_give isl_multi_union_pw_aff *
8102 isl_multi_union_pw_aff_multi_val_on_domain_aligned(
8103 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
8105 int i, n;
8106 isl_space *space;
8107 isl_multi_union_pw_aff *mupa;
8109 if (!domain || !mv)
8110 goto error;
8112 n = isl_multi_val_dim(mv, isl_dim_set);
8113 space = isl_multi_val_get_space(mv);
8114 mupa = isl_multi_union_pw_aff_alloc(space);
8115 for (i = 0; i < n; ++i) {
8116 isl_val *v;
8117 isl_union_pw_aff *upa;
8119 v = isl_multi_val_get_val(mv, i);
8120 upa = isl_union_pw_aff_val_on_domain(isl_union_set_copy(domain),
8122 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8125 isl_union_set_free(domain);
8126 isl_multi_val_free(mv);
8127 return mupa;
8128 error:
8129 isl_union_set_free(domain);
8130 isl_multi_val_free(mv);
8131 return NULL;
8134 /* Return a multiple union piecewise affine expression
8135 * that is equal to "mv" on "domain".
8137 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_val_on_domain(
8138 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
8140 if (!domain || !mv)
8141 goto error;
8142 if (isl_space_match(domain->dim, isl_dim_param,
8143 mv->space, isl_dim_param))
8144 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(
8145 domain, mv);
8146 domain = isl_union_set_align_params(domain,
8147 isl_multi_val_get_space(mv));
8148 mv = isl_multi_val_align_params(mv, isl_union_set_get_space(domain));
8149 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(domain, mv);
8150 error:
8151 isl_union_set_free(domain);
8152 isl_multi_val_free(mv);
8153 return NULL;
8156 /* Return a multiple union piecewise affine expression
8157 * that is equal to "ma" on "domain", assuming "domain" and "ma"
8158 * have been aligned.
8160 static __isl_give isl_multi_union_pw_aff *
8161 isl_multi_union_pw_aff_multi_aff_on_domain_aligned(
8162 __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma)
8164 int i, n;
8165 isl_space *space;
8166 isl_multi_union_pw_aff *mupa;
8168 if (!domain || !ma)
8169 goto error;
8171 n = isl_multi_aff_dim(ma, isl_dim_set);
8172 space = isl_multi_aff_get_space(ma);
8173 mupa = isl_multi_union_pw_aff_alloc(space);
8174 for (i = 0; i < n; ++i) {
8175 isl_aff *aff;
8176 isl_union_pw_aff *upa;
8178 aff = isl_multi_aff_get_aff(ma, i);
8179 upa = isl_union_pw_aff_aff_on_domain(isl_union_set_copy(domain),
8180 aff);
8181 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8184 isl_union_set_free(domain);
8185 isl_multi_aff_free(ma);
8186 return mupa;
8187 error:
8188 isl_union_set_free(domain);
8189 isl_multi_aff_free(ma);
8190 return NULL;
8193 /* Return a multiple union piecewise affine expression
8194 * that is equal to "ma" on "domain".
8196 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_aff_on_domain(
8197 __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma)
8199 if (!domain || !ma)
8200 goto error;
8201 if (isl_space_match(domain->dim, isl_dim_param,
8202 ma->space, isl_dim_param))
8203 return isl_multi_union_pw_aff_multi_aff_on_domain_aligned(
8204 domain, ma);
8205 domain = isl_union_set_align_params(domain,
8206 isl_multi_aff_get_space(ma));
8207 ma = isl_multi_aff_align_params(ma, isl_union_set_get_space(domain));
8208 return isl_multi_union_pw_aff_multi_aff_on_domain_aligned(domain, ma);
8209 error:
8210 isl_union_set_free(domain);
8211 isl_multi_aff_free(ma);
8212 return NULL;
8215 /* Return a union set containing those elements in the domains
8216 * of the elements of "mupa" where they are all zero.
8218 __isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
8219 __isl_take isl_multi_union_pw_aff *mupa)
8221 int i, n;
8222 isl_union_pw_aff *upa;
8223 isl_union_set *zero;
8225 if (!mupa)
8226 return NULL;
8228 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8229 if (n == 0)
8230 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8231 "cannot determine zero set "
8232 "of zero-dimensional function", goto error);
8234 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8235 zero = isl_union_pw_aff_zero_union_set(upa);
8237 for (i = 1; i < n; ++i) {
8238 isl_union_set *zero_i;
8240 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8241 zero_i = isl_union_pw_aff_zero_union_set(upa);
8243 zero = isl_union_set_intersect(zero, zero_i);
8246 isl_multi_union_pw_aff_free(mupa);
8247 return zero;
8248 error:
8249 isl_multi_union_pw_aff_free(mupa);
8250 return NULL;
8253 /* Construct a union map mapping the shared domain
8254 * of the union piecewise affine expressions to the range of "mupa"
8255 * with each dimension in the range equated to the
8256 * corresponding union piecewise affine expression.
8258 * The input cannot be zero-dimensional as there is
8259 * no way to extract a domain from a zero-dimensional isl_multi_union_pw_aff.
8261 __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
8262 __isl_take isl_multi_union_pw_aff *mupa)
8264 int i, n;
8265 isl_space *space;
8266 isl_union_map *umap;
8267 isl_union_pw_aff *upa;
8269 if (!mupa)
8270 return NULL;
8272 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8273 if (n == 0)
8274 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8275 "cannot determine domain of zero-dimensional "
8276 "isl_multi_union_pw_aff", goto error);
8278 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8279 umap = isl_union_map_from_union_pw_aff(upa);
8281 for (i = 1; i < n; ++i) {
8282 isl_union_map *umap_i;
8284 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8285 umap_i = isl_union_map_from_union_pw_aff(upa);
8286 umap = isl_union_map_flat_range_product(umap, umap_i);
8289 space = isl_multi_union_pw_aff_get_space(mupa);
8290 umap = isl_union_map_reset_range_space(umap, space);
8292 isl_multi_union_pw_aff_free(mupa);
8293 return umap;
8294 error:
8295 isl_multi_union_pw_aff_free(mupa);
8296 return NULL;
8299 /* Internal data structure for isl_union_pw_multi_aff_reset_range_space.
8300 * "range" is the space from which to set the range space.
8301 * "res" collects the results.
8303 struct isl_union_pw_multi_aff_reset_range_space_data {
8304 isl_space *range;
8305 isl_union_pw_multi_aff *res;
8308 /* Replace the range space of "pma" by the range space of data->range and
8309 * add the result to data->res.
8311 static isl_stat reset_range_space(__isl_take isl_pw_multi_aff *pma, void *user)
8313 struct isl_union_pw_multi_aff_reset_range_space_data *data = user;
8314 isl_space *space;
8316 space = isl_pw_multi_aff_get_space(pma);
8317 space = isl_space_domain(space);
8318 space = isl_space_extend_domain_with_range(space,
8319 isl_space_copy(data->range));
8320 pma = isl_pw_multi_aff_reset_space(pma, space);
8321 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
8323 return data->res ? isl_stat_ok : isl_stat_error;
8326 /* Replace the range space of all the piecewise affine expressions in "upma" by
8327 * the range space of "space".
8329 * This assumes that all these expressions have the same output dimension.
8331 * Since the spaces of the expressions change, so do their hash values.
8332 * We therefore need to create a new isl_union_pw_multi_aff.
8333 * Note that the hash value is currently computed based on the entire
8334 * space even though there can only be a single expression with a given
8335 * domain space.
8337 static __isl_give isl_union_pw_multi_aff *
8338 isl_union_pw_multi_aff_reset_range_space(
8339 __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *space)
8341 struct isl_union_pw_multi_aff_reset_range_space_data data = { space };
8342 isl_space *space_upma;
8344 space_upma = isl_union_pw_multi_aff_get_space(upma);
8345 data.res = isl_union_pw_multi_aff_empty(space_upma);
8346 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
8347 &reset_range_space, &data) < 0)
8348 data.res = isl_union_pw_multi_aff_free(data.res);
8350 isl_space_free(space);
8351 isl_union_pw_multi_aff_free(upma);
8352 return data.res;
8355 /* Construct and return a union piecewise multi affine expression
8356 * that is equal to the given multi union piecewise affine expression.
8358 * In order to be able to perform the conversion, the input
8359 * needs to have a least one output dimension.
8361 __isl_give isl_union_pw_multi_aff *
8362 isl_union_pw_multi_aff_from_multi_union_pw_aff(
8363 __isl_take isl_multi_union_pw_aff *mupa)
8365 int i, n;
8366 isl_space *space;
8367 isl_union_pw_multi_aff *upma;
8368 isl_union_pw_aff *upa;
8370 if (!mupa)
8371 return NULL;
8373 space = isl_multi_union_pw_aff_get_space(mupa);
8375 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8376 if (n == 0)
8377 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8378 "cannot determine domain of zero-dimensional "
8379 "isl_multi_union_pw_aff", goto error);
8381 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8382 upma = isl_union_pw_multi_aff_from_union_pw_aff(upa);
8384 for (i = 1; i < n; ++i) {
8385 isl_union_pw_multi_aff *upma_i;
8387 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8388 upma_i = isl_union_pw_multi_aff_from_union_pw_aff(upa);
8389 upma = isl_union_pw_multi_aff_flat_range_product(upma, upma_i);
8392 upma = isl_union_pw_multi_aff_reset_range_space(upma, space);
8394 isl_multi_union_pw_aff_free(mupa);
8395 return upma;
8396 error:
8397 isl_multi_union_pw_aff_free(mupa);
8398 return NULL;
8401 /* Intersect the range of "mupa" with "range".
8402 * That is, keep only those domain elements that have a function value
8403 * in "range".
8405 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
8406 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *range)
8408 isl_union_pw_multi_aff *upma;
8409 isl_union_set *domain;
8410 isl_space *space;
8411 int n;
8412 int match;
8414 if (!mupa || !range)
8415 goto error;
8417 space = isl_set_get_space(range);
8418 match = isl_space_tuple_is_equal(mupa->space, isl_dim_set,
8419 space, isl_dim_set);
8420 isl_space_free(space);
8421 if (match < 0)
8422 goto error;
8423 if (!match)
8424 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8425 "space don't match", goto error);
8426 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8427 if (n == 0)
8428 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8429 "cannot intersect range of zero-dimensional "
8430 "isl_multi_union_pw_aff", goto error);
8432 upma = isl_union_pw_multi_aff_from_multi_union_pw_aff(
8433 isl_multi_union_pw_aff_copy(mupa));
8434 domain = isl_union_set_from_set(range);
8435 domain = isl_union_set_preimage_union_pw_multi_aff(domain, upma);
8436 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, domain);
8438 return mupa;
8439 error:
8440 isl_multi_union_pw_aff_free(mupa);
8441 isl_set_free(range);
8442 return NULL;
8445 /* Return the shared domain of the elements of "mupa".
8447 __isl_give isl_union_set *isl_multi_union_pw_aff_domain(
8448 __isl_take isl_multi_union_pw_aff *mupa)
8450 int i, n;
8451 isl_union_pw_aff *upa;
8452 isl_union_set *dom;
8454 if (!mupa)
8455 return NULL;
8457 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8458 if (n == 0)
8459 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8460 "cannot determine domain", goto error);
8462 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8463 dom = isl_union_pw_aff_domain(upa);
8464 for (i = 1; i < n; ++i) {
8465 isl_union_set *dom_i;
8467 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8468 dom_i = isl_union_pw_aff_domain(upa);
8469 dom = isl_union_set_intersect(dom, dom_i);
8472 isl_multi_union_pw_aff_free(mupa);
8473 return dom;
8474 error:
8475 isl_multi_union_pw_aff_free(mupa);
8476 return NULL;
8479 /* Apply "aff" to "mupa". The space of "mupa" is equal to the domain of "aff".
8480 * In particular, the spaces have been aligned.
8481 * The result is defined over the shared domain of the elements of "mupa"
8483 * We first extract the parametric constant part of "aff" and
8484 * define that over the shared domain.
8485 * Then we iterate over all input dimensions of "aff" and add the corresponding
8486 * multiples of the elements of "mupa".
8487 * Finally, we consider the integer divisions, calling the function
8488 * recursively to obtain an isl_union_pw_aff corresponding to the
8489 * integer division argument.
8491 static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff(
8492 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
8494 int i, n_in, n_div;
8495 isl_union_pw_aff *upa;
8496 isl_union_set *uset;
8497 isl_val *v;
8498 isl_aff *cst;
8500 n_in = isl_aff_dim(aff, isl_dim_in);
8501 n_div = isl_aff_dim(aff, isl_dim_div);
8503 uset = isl_multi_union_pw_aff_domain(isl_multi_union_pw_aff_copy(mupa));
8504 cst = isl_aff_copy(aff);
8505 cst = isl_aff_drop_dims(cst, isl_dim_div, 0, n_div);
8506 cst = isl_aff_drop_dims(cst, isl_dim_in, 0, n_in);
8507 cst = isl_aff_project_domain_on_params(cst);
8508 upa = isl_union_pw_aff_aff_on_domain(uset, cst);
8510 for (i = 0; i < n_in; ++i) {
8511 isl_union_pw_aff *upa_i;
8513 if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
8514 continue;
8515 v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
8516 upa_i = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8517 upa_i = isl_union_pw_aff_scale_val(upa_i, v);
8518 upa = isl_union_pw_aff_add(upa, upa_i);
8521 for (i = 0; i < n_div; ++i) {
8522 isl_aff *div;
8523 isl_union_pw_aff *upa_i;
8525 if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
8526 continue;
8527 div = isl_aff_get_div(aff, i);
8528 upa_i = multi_union_pw_aff_apply_aff(
8529 isl_multi_union_pw_aff_copy(mupa), div);
8530 upa_i = isl_union_pw_aff_floor(upa_i);
8531 v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
8532 upa_i = isl_union_pw_aff_scale_val(upa_i, v);
8533 upa = isl_union_pw_aff_add(upa, upa_i);
8536 isl_multi_union_pw_aff_free(mupa);
8537 isl_aff_free(aff);
8539 return upa;
8542 /* Apply "aff" to "mupa". The space of "mupa" needs to be compatible
8543 * with the domain of "aff".
8544 * Furthermore, the dimension of this space needs to be greater than zero.
8545 * The result is defined over the shared domain of the elements of "mupa"
8547 * We perform these checks and then hand over control to
8548 * multi_union_pw_aff_apply_aff.
8550 __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff(
8551 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
8553 isl_space *space1, *space2;
8554 int equal;
8556 mupa = isl_multi_union_pw_aff_align_params(mupa,
8557 isl_aff_get_space(aff));
8558 aff = isl_aff_align_params(aff, isl_multi_union_pw_aff_get_space(mupa));
8559 if (!mupa || !aff)
8560 goto error;
8562 space1 = isl_multi_union_pw_aff_get_space(mupa);
8563 space2 = isl_aff_get_domain_space(aff);
8564 equal = isl_space_is_equal(space1, space2);
8565 isl_space_free(space1);
8566 isl_space_free(space2);
8567 if (equal < 0)
8568 goto error;
8569 if (!equal)
8570 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
8571 "spaces don't match", goto error);
8572 if (isl_aff_dim(aff, isl_dim_in) == 0)
8573 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
8574 "cannot determine domains", goto error);
8576 return multi_union_pw_aff_apply_aff(mupa, aff);
8577 error:
8578 isl_multi_union_pw_aff_free(mupa);
8579 isl_aff_free(aff);
8580 return NULL;
8583 /* Apply "ma" to "mupa". The space of "mupa" needs to be compatible
8584 * with the domain of "ma".
8585 * Furthermore, the dimension of this space needs to be greater than zero,
8586 * unless the dimension of the target space of "ma" is also zero.
8587 * The result is defined over the shared domain of the elements of "mupa"
8589 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
8590 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma)
8592 isl_space *space1, *space2;
8593 isl_multi_union_pw_aff *res;
8594 int equal;
8595 int i, n_out;
8597 mupa = isl_multi_union_pw_aff_align_params(mupa,
8598 isl_multi_aff_get_space(ma));
8599 ma = isl_multi_aff_align_params(ma,
8600 isl_multi_union_pw_aff_get_space(mupa));
8601 if (!mupa || !ma)
8602 goto error;
8604 space1 = isl_multi_union_pw_aff_get_space(mupa);
8605 space2 = isl_multi_aff_get_domain_space(ma);
8606 equal = isl_space_is_equal(space1, space2);
8607 isl_space_free(space1);
8608 isl_space_free(space2);
8609 if (equal < 0)
8610 goto error;
8611 if (!equal)
8612 isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
8613 "spaces don't match", goto error);
8614 n_out = isl_multi_aff_dim(ma, isl_dim_out);
8615 if (isl_multi_aff_dim(ma, isl_dim_in) == 0 && n_out != 0)
8616 isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
8617 "cannot determine domains", goto error);
8619 space1 = isl_space_range(isl_multi_aff_get_space(ma));
8620 res = isl_multi_union_pw_aff_alloc(space1);
8622 for (i = 0; i < n_out; ++i) {
8623 isl_aff *aff;
8624 isl_union_pw_aff *upa;
8626 aff = isl_multi_aff_get_aff(ma, i);
8627 upa = multi_union_pw_aff_apply_aff(
8628 isl_multi_union_pw_aff_copy(mupa), aff);
8629 res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa);
8632 isl_multi_aff_free(ma);
8633 isl_multi_union_pw_aff_free(mupa);
8634 return res;
8635 error:
8636 isl_multi_union_pw_aff_free(mupa);
8637 isl_multi_aff_free(ma);
8638 return NULL;
8641 /* Apply "pa" to "mupa". The space of "mupa" needs to be compatible
8642 * with the domain of "pa".
8643 * Furthermore, the dimension of this space needs to be greater than zero.
8644 * The result is defined over the shared domain of the elements of "mupa"
8646 __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff(
8647 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa)
8649 int i;
8650 int equal;
8651 isl_space *space, *space2;
8652 isl_union_pw_aff *upa;
8654 mupa = isl_multi_union_pw_aff_align_params(mupa,
8655 isl_pw_aff_get_space(pa));
8656 pa = isl_pw_aff_align_params(pa,
8657 isl_multi_union_pw_aff_get_space(mupa));
8658 if (!mupa || !pa)
8659 goto error;
8661 space = isl_multi_union_pw_aff_get_space(mupa);
8662 space2 = isl_pw_aff_get_domain_space(pa);
8663 equal = isl_space_is_equal(space, space2);
8664 isl_space_free(space);
8665 isl_space_free(space2);
8666 if (equal < 0)
8667 goto error;
8668 if (!equal)
8669 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
8670 "spaces don't match", goto error);
8671 if (isl_pw_aff_dim(pa, isl_dim_in) == 0)
8672 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
8673 "cannot determine domains", goto error);
8675 space = isl_space_params(isl_multi_union_pw_aff_get_space(mupa));
8676 upa = isl_union_pw_aff_empty(space);
8678 for (i = 0; i < pa->n; ++i) {
8679 isl_aff *aff;
8680 isl_set *domain;
8681 isl_multi_union_pw_aff *mupa_i;
8682 isl_union_pw_aff *upa_i;
8684 mupa_i = isl_multi_union_pw_aff_copy(mupa);
8685 domain = isl_set_copy(pa->p[i].set);
8686 mupa_i = isl_multi_union_pw_aff_intersect_range(mupa_i, domain);
8687 aff = isl_aff_copy(pa->p[i].aff);
8688 upa_i = multi_union_pw_aff_apply_aff(mupa_i, aff);
8689 upa = isl_union_pw_aff_union_add(upa, upa_i);
8692 isl_multi_union_pw_aff_free(mupa);
8693 isl_pw_aff_free(pa);
8694 return upa;
8695 error:
8696 isl_multi_union_pw_aff_free(mupa);
8697 isl_pw_aff_free(pa);
8698 return NULL;
8701 /* Apply "pma" to "mupa". The space of "mupa" needs to be compatible
8702 * with the domain of "pma".
8703 * Furthermore, the dimension of this space needs to be greater than zero,
8704 * unless the dimension of the target space of "pma" is also zero.
8705 * The result is defined over the shared domain of the elements of "mupa"
8707 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
8708 __isl_take isl_multi_union_pw_aff *mupa,
8709 __isl_take isl_pw_multi_aff *pma)
8711 isl_space *space1, *space2;
8712 isl_multi_union_pw_aff *res;
8713 int equal;
8714 int i, n_out;
8716 mupa = isl_multi_union_pw_aff_align_params(mupa,
8717 isl_pw_multi_aff_get_space(pma));
8718 pma = isl_pw_multi_aff_align_params(pma,
8719 isl_multi_union_pw_aff_get_space(mupa));
8720 if (!mupa || !pma)
8721 goto error;
8723 space1 = isl_multi_union_pw_aff_get_space(mupa);
8724 space2 = isl_pw_multi_aff_get_domain_space(pma);
8725 equal = isl_space_is_equal(space1, space2);
8726 isl_space_free(space1);
8727 isl_space_free(space2);
8728 if (equal < 0)
8729 goto error;
8730 if (!equal)
8731 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
8732 "spaces don't match", goto error);
8733 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
8734 if (isl_pw_multi_aff_dim(pma, isl_dim_in) == 0 && n_out != 0)
8735 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
8736 "cannot determine domains", goto error);
8738 space1 = isl_space_range(isl_pw_multi_aff_get_space(pma));
8739 res = isl_multi_union_pw_aff_alloc(space1);
8741 for (i = 0; i < n_out; ++i) {
8742 isl_pw_aff *pa;
8743 isl_union_pw_aff *upa;
8745 pa = isl_pw_multi_aff_get_pw_aff(pma, i);
8746 upa = isl_multi_union_pw_aff_apply_pw_aff(
8747 isl_multi_union_pw_aff_copy(mupa), pa);
8748 res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa);
8751 isl_pw_multi_aff_free(pma);
8752 isl_multi_union_pw_aff_free(mupa);
8753 return res;
8754 error:
8755 isl_multi_union_pw_aff_free(mupa);
8756 isl_pw_multi_aff_free(pma);
8757 return NULL;
8760 /* Compute the pullback of "mupa" by the function represented by "upma".
8761 * In other words, plug in "upma" in "mupa". The result contains
8762 * expressions defined over the domain space of "upma".
8764 * Run over all elements of "mupa" and plug in "upma" in each of them.
8766 __isl_give isl_multi_union_pw_aff *
8767 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
8768 __isl_take isl_multi_union_pw_aff *mupa,
8769 __isl_take isl_union_pw_multi_aff *upma)
8771 int i, n;
8773 mupa = isl_multi_union_pw_aff_align_params(mupa,
8774 isl_union_pw_multi_aff_get_space(upma));
8775 upma = isl_union_pw_multi_aff_align_params(upma,
8776 isl_multi_union_pw_aff_get_space(mupa));
8777 if (!mupa || !upma)
8778 goto error;
8780 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8781 for (i = 0; i < n; ++i) {
8782 isl_union_pw_aff *upa;
8784 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8785 upa = isl_union_pw_aff_pullback_union_pw_multi_aff(upa,
8786 isl_union_pw_multi_aff_copy(upma));
8787 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8790 isl_union_pw_multi_aff_free(upma);
8791 return mupa;
8792 error:
8793 isl_multi_union_pw_aff_free(mupa);
8794 isl_union_pw_multi_aff_free(upma);
8795 return NULL;
8798 /* Extract the sequence of elements in "mupa" with domain space "space"
8799 * (ignoring parameters).
8801 * For the elements of "mupa" that are not defined on the specified space,
8802 * the corresponding element in the result is empty.
8804 __isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
8805 __isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space)
8807 int i, n;
8808 isl_space *space_mpa = NULL;
8809 isl_multi_pw_aff *mpa;
8811 if (!mupa || !space)
8812 goto error;
8814 space_mpa = isl_multi_union_pw_aff_get_space(mupa);
8815 if (!isl_space_match(space_mpa, isl_dim_param, space, isl_dim_param)) {
8816 space = isl_space_drop_dims(space, isl_dim_param,
8817 0, isl_space_dim(space, isl_dim_param));
8818 space = isl_space_align_params(space,
8819 isl_space_copy(space_mpa));
8820 if (!space)
8821 goto error;
8823 space_mpa = isl_space_map_from_domain_and_range(isl_space_copy(space),
8824 space_mpa);
8825 mpa = isl_multi_pw_aff_alloc(space_mpa);
8827 space = isl_space_from_domain(space);
8828 space = isl_space_add_dims(space, isl_dim_out, 1);
8829 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8830 for (i = 0; i < n; ++i) {
8831 isl_union_pw_aff *upa;
8832 isl_pw_aff *pa;
8834 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8835 pa = isl_union_pw_aff_extract_pw_aff(upa,
8836 isl_space_copy(space));
8837 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
8838 isl_union_pw_aff_free(upa);
8841 isl_space_free(space);
8842 return mpa;
8843 error:
8844 isl_space_free(space_mpa);
8845 isl_space_free(space);
8846 return NULL;