isl_input.c: accept_ternary: rename "dim" variable to "space"
[isl.git] / isl_aff.c
blob6ea860e24bc864d07e00ee0efde682d7f35fc1c6
1 /*
2 * Copyright 2011 INRIA Saclay
3 * Copyright 2011 Sven Verdoolaege
4 * Copyright 2012-2014 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
6 * Copyright 2018 Cerebras Systems
8 * Use of this software is governed by the MIT license
10 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
11 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
12 * 91893 Orsay, France
13 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
14 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
15 * B.P. 105 - 78153 Le Chesnay, France
16 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
19 #include <isl_ctx_private.h>
20 #include <isl_map_private.h>
21 #include <isl_union_map_private.h>
22 #include <isl_aff_private.h>
23 #include <isl_space_private.h>
24 #include <isl_local_space_private.h>
25 #include <isl_vec_private.h>
26 #include <isl_mat_private.h>
27 #include <isl_id_private.h>
28 #include <isl/constraint.h>
29 #include <isl_seq.h>
30 #include <isl/set.h>
31 #include <isl_val_private.h>
32 #include <isl_point_private.h>
33 #include <isl_config.h>
35 #undef EL_BASE
36 #define EL_BASE aff
38 #include <isl_list_templ.c>
40 #undef EL_BASE
41 #define EL_BASE pw_aff
43 #include <isl_list_templ.c>
45 #undef EL_BASE
46 #define EL_BASE pw_multi_aff
48 #include <isl_list_templ.c>
50 #undef EL_BASE
51 #define EL_BASE union_pw_aff
53 #include <isl_list_templ.c>
55 #undef EL_BASE
56 #define EL_BASE union_pw_multi_aff
58 #include <isl_list_templ.c>
60 __isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
61 __isl_take isl_vec *v)
63 isl_aff *aff;
65 if (!ls || !v)
66 goto error;
68 aff = isl_calloc_type(v->ctx, struct isl_aff);
69 if (!aff)
70 goto error;
72 aff->ref = 1;
73 aff->ls = ls;
74 aff->v = v;
76 return aff;
77 error:
78 isl_local_space_free(ls);
79 isl_vec_free(v);
80 return NULL;
83 __isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls)
85 isl_ctx *ctx;
86 isl_vec *v;
87 isl_size total;
89 if (!ls)
90 return NULL;
92 ctx = isl_local_space_get_ctx(ls);
93 if (!isl_local_space_divs_known(ls))
94 isl_die(ctx, isl_error_invalid, "local space has unknown divs",
95 goto error);
96 if (!isl_local_space_is_set(ls))
97 isl_die(ctx, isl_error_invalid,
98 "domain of affine expression should be a set",
99 goto error);
101 total = isl_local_space_dim(ls, isl_dim_all);
102 if (total < 0)
103 goto error;
104 v = isl_vec_alloc(ctx, 1 + 1 + total);
105 return isl_aff_alloc_vec(ls, v);
106 error:
107 isl_local_space_free(ls);
108 return NULL;
111 __isl_give isl_aff *isl_aff_zero_on_domain(__isl_take isl_local_space *ls)
113 isl_aff *aff;
115 aff = isl_aff_alloc(ls);
116 if (!aff)
117 return NULL;
119 isl_int_set_si(aff->v->el[0], 1);
120 isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
122 return aff;
125 /* Return a piecewise affine expression defined on the specified domain
126 * that is equal to zero.
128 __isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(__isl_take isl_local_space *ls)
130 return isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls));
133 /* Return an affine expression defined on the specified domain
134 * that represents NaN.
136 __isl_give isl_aff *isl_aff_nan_on_domain(__isl_take isl_local_space *ls)
138 isl_aff *aff;
140 aff = isl_aff_alloc(ls);
141 if (!aff)
142 return NULL;
144 isl_seq_clr(aff->v->el, aff->v->size);
146 return aff;
149 /* Return a piecewise affine expression defined on the specified domain
150 * that represents NaN.
152 __isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls)
154 return isl_pw_aff_from_aff(isl_aff_nan_on_domain(ls));
157 /* Return an affine expression that is equal to "val" on
158 * domain local space "ls".
160 __isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls,
161 __isl_take isl_val *val)
163 isl_aff *aff;
165 if (!ls || !val)
166 goto error;
167 if (!isl_val_is_rat(val))
168 isl_die(isl_val_get_ctx(val), isl_error_invalid,
169 "expecting rational value", goto error);
171 aff = isl_aff_alloc(isl_local_space_copy(ls));
172 if (!aff)
173 goto error;
175 isl_seq_clr(aff->v->el + 2, aff->v->size - 2);
176 isl_int_set(aff->v->el[1], val->n);
177 isl_int_set(aff->v->el[0], val->d);
179 isl_local_space_free(ls);
180 isl_val_free(val);
181 return aff;
182 error:
183 isl_local_space_free(ls);
184 isl_val_free(val);
185 return NULL;
188 /* Return an affine expression that is equal to the specified dimension
189 * in "ls".
191 __isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls,
192 enum isl_dim_type type, unsigned pos)
194 isl_space *space;
195 isl_aff *aff;
197 if (!ls)
198 return NULL;
200 space = isl_local_space_get_space(ls);
201 if (!space)
202 goto error;
203 if (isl_space_is_map(space))
204 isl_die(isl_space_get_ctx(space), isl_error_invalid,
205 "expecting (parameter) set space", goto error);
206 if (isl_local_space_check_range(ls, type, pos, 1) < 0)
207 goto error;
209 isl_space_free(space);
210 aff = isl_aff_alloc(ls);
211 if (!aff)
212 return NULL;
214 pos += isl_local_space_offset(aff->ls, type);
216 isl_int_set_si(aff->v->el[0], 1);
217 isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
218 isl_int_set_si(aff->v->el[1 + pos], 1);
220 return aff;
221 error:
222 isl_local_space_free(ls);
223 isl_space_free(space);
224 return NULL;
227 /* Return a piecewise affine expression that is equal to
228 * the specified dimension in "ls".
230 __isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls,
231 enum isl_dim_type type, unsigned pos)
233 return isl_pw_aff_from_aff(isl_aff_var_on_domain(ls, type, pos));
236 /* Return an affine expression that is equal to the parameter
237 * in the domain space "space" with identifier "id".
239 __isl_give isl_aff *isl_aff_param_on_domain_space_id(
240 __isl_take isl_space *space, __isl_take isl_id *id)
242 int pos;
243 isl_local_space *ls;
245 if (!space || !id)
246 goto error;
247 pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
248 if (pos < 0)
249 isl_die(isl_space_get_ctx(space), isl_error_invalid,
250 "parameter not found in space", goto error);
251 isl_id_free(id);
252 ls = isl_local_space_from_space(space);
253 return isl_aff_var_on_domain(ls, isl_dim_param, pos);
254 error:
255 isl_space_free(space);
256 isl_id_free(id);
257 return NULL;
260 __isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff)
262 if (!aff)
263 return NULL;
265 aff->ref++;
266 return aff;
269 __isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff)
271 if (!aff)
272 return NULL;
274 return isl_aff_alloc_vec(isl_local_space_copy(aff->ls),
275 isl_vec_copy(aff->v));
278 __isl_give isl_aff *isl_aff_cow(__isl_take isl_aff *aff)
280 if (!aff)
281 return NULL;
283 if (aff->ref == 1)
284 return aff;
285 aff->ref--;
286 return isl_aff_dup(aff);
289 __isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff)
291 if (!aff)
292 return NULL;
294 if (--aff->ref > 0)
295 return NULL;
297 isl_local_space_free(aff->ls);
298 isl_vec_free(aff->v);
300 free(aff);
302 return NULL;
305 isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff)
307 return aff ? isl_local_space_get_ctx(aff->ls) : NULL;
310 /* Return a hash value that digests "aff".
312 uint32_t isl_aff_get_hash(__isl_keep isl_aff *aff)
314 uint32_t hash, ls_hash, v_hash;
316 if (!aff)
317 return 0;
319 hash = isl_hash_init();
320 ls_hash = isl_local_space_get_hash(aff->ls);
321 isl_hash_hash(hash, ls_hash);
322 v_hash = isl_vec_get_hash(aff->v);
323 isl_hash_hash(hash, v_hash);
325 return hash;
328 /* Externally, an isl_aff has a map space, but internally, the
329 * ls field corresponds to the domain of that space.
331 isl_size isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type)
333 if (!aff)
334 return isl_size_error;
335 if (type == isl_dim_out)
336 return 1;
337 if (type == isl_dim_in)
338 type = isl_dim_set;
339 return isl_local_space_dim(aff->ls, type);
342 /* Return the position of the dimension of the given type and name
343 * in "aff".
344 * Return -1 if no such dimension can be found.
346 int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff, enum isl_dim_type type,
347 const char *name)
349 if (!aff)
350 return -1;
351 if (type == isl_dim_out)
352 return -1;
353 if (type == isl_dim_in)
354 type = isl_dim_set;
355 return isl_local_space_find_dim_by_name(aff->ls, type, name);
358 /* Return the domain space of "aff".
360 static __isl_keep isl_space *isl_aff_peek_domain_space(__isl_keep isl_aff *aff)
362 return aff ? isl_local_space_peek_space(aff->ls) : NULL;
365 __isl_give isl_space *isl_aff_get_domain_space(__isl_keep isl_aff *aff)
367 return isl_space_copy(isl_aff_peek_domain_space(aff));
370 __isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff)
372 isl_space *space;
373 if (!aff)
374 return NULL;
375 space = isl_local_space_get_space(aff->ls);
376 space = isl_space_from_domain(space);
377 space = isl_space_add_dims(space, isl_dim_out, 1);
378 return space;
381 __isl_give isl_local_space *isl_aff_get_domain_local_space(
382 __isl_keep isl_aff *aff)
384 return aff ? isl_local_space_copy(aff->ls) : NULL;
387 __isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff)
389 isl_local_space *ls;
390 if (!aff)
391 return NULL;
392 ls = isl_local_space_copy(aff->ls);
393 ls = isl_local_space_from_domain(ls);
394 ls = isl_local_space_add_dims(ls, isl_dim_out, 1);
395 return ls;
398 /* Return the local space of the domain of "aff".
399 * This may be either a copy or the local space itself
400 * if there is only one reference to "aff".
401 * This allows the local space to be modified inplace
402 * if both the expression and its local space have only a single reference.
403 * The caller is not allowed to modify "aff" between this call and
404 * a subsequent call to isl_aff_restore_domain_local_space.
405 * The only exception is that isl_aff_free can be called instead.
407 __isl_give isl_local_space *isl_aff_take_domain_local_space(
408 __isl_keep isl_aff *aff)
410 isl_local_space *ls;
412 if (!aff)
413 return NULL;
414 if (aff->ref != 1)
415 return isl_aff_get_domain_local_space(aff);
416 ls = aff->ls;
417 aff->ls = NULL;
418 return ls;
421 /* Set the local space of the domain of "aff" to "ls",
422 * where the local space of "aff" may be missing
423 * due to a preceding call to isl_aff_take_domain_local_space.
424 * However, in this case, "aff" only has a single reference and
425 * then the call to isl_aff_cow has no effect.
427 __isl_give isl_aff *isl_aff_restore_domain_local_space(
428 __isl_keep isl_aff *aff, __isl_take isl_local_space *ls)
430 if (!aff || !ls)
431 goto error;
433 if (aff->ls == ls) {
434 isl_local_space_free(ls);
435 return aff;
438 aff = isl_aff_cow(aff);
439 if (!aff)
440 goto error;
441 isl_local_space_free(aff->ls);
442 aff->ls = ls;
444 return aff;
445 error:
446 isl_aff_free(aff);
447 isl_local_space_free(ls);
448 return NULL;
451 /* Externally, an isl_aff has a map space, but internally, the
452 * ls field corresponds to the domain of that space.
454 const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
455 enum isl_dim_type type, unsigned pos)
457 if (!aff)
458 return NULL;
459 if (type == isl_dim_out)
460 return NULL;
461 if (type == isl_dim_in)
462 type = isl_dim_set;
463 return isl_local_space_get_dim_name(aff->ls, type, pos);
466 __isl_give isl_aff *isl_aff_reset_domain_space(__isl_take isl_aff *aff,
467 __isl_take isl_space *dim)
469 aff = isl_aff_cow(aff);
470 if (!aff || !dim)
471 goto error;
473 aff->ls = isl_local_space_reset_space(aff->ls, dim);
474 if (!aff->ls)
475 return isl_aff_free(aff);
477 return aff;
478 error:
479 isl_aff_free(aff);
480 isl_space_free(dim);
481 return NULL;
484 /* Reset the space of "aff". This function is called from isl_pw_templ.c
485 * and doesn't know if the space of an element object is represented
486 * directly or through its domain. It therefore passes along both.
488 __isl_give isl_aff *isl_aff_reset_space_and_domain(__isl_take isl_aff *aff,
489 __isl_take isl_space *space, __isl_take isl_space *domain)
491 isl_space_free(space);
492 return isl_aff_reset_domain_space(aff, domain);
495 /* Reorder the coefficients of the affine expression based
496 * on the given reordering.
497 * The reordering r is assumed to have been extended with the local
498 * variables.
500 static __isl_give isl_vec *vec_reorder(__isl_take isl_vec *vec,
501 __isl_take isl_reordering *r, int n_div)
503 isl_space *space;
504 isl_vec *res;
505 isl_size dim;
506 int i;
508 if (!vec || !r)
509 goto error;
511 space = isl_reordering_peek_space(r);
512 dim = isl_space_dim(space, isl_dim_all);
513 if (dim < 0)
514 goto error;
515 res = isl_vec_alloc(vec->ctx, 2 + dim + n_div);
516 if (!res)
517 goto error;
518 isl_seq_cpy(res->el, vec->el, 2);
519 isl_seq_clr(res->el + 2, res->size - 2);
520 for (i = 0; i < r->len; ++i)
521 isl_int_set(res->el[2 + r->pos[i]], vec->el[2 + i]);
523 isl_reordering_free(r);
524 isl_vec_free(vec);
525 return res;
526 error:
527 isl_vec_free(vec);
528 isl_reordering_free(r);
529 return NULL;
532 /* Reorder the dimensions of the domain of "aff" according
533 * to the given reordering.
535 __isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff,
536 __isl_take isl_reordering *r)
538 aff = isl_aff_cow(aff);
539 if (!aff)
540 goto error;
542 r = isl_reordering_extend(r, aff->ls->div->n_row);
543 aff->v = vec_reorder(aff->v, isl_reordering_copy(r),
544 aff->ls->div->n_row);
545 aff->ls = isl_local_space_realign(aff->ls, r);
547 if (!aff->v || !aff->ls)
548 return isl_aff_free(aff);
550 return aff;
551 error:
552 isl_aff_free(aff);
553 isl_reordering_free(r);
554 return NULL;
557 __isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
558 __isl_take isl_space *model)
560 isl_bool equal_params;
562 if (!aff || !model)
563 goto error;
565 equal_params = isl_space_has_equal_params(aff->ls->dim, model);
566 if (equal_params < 0)
567 goto error;
568 if (!equal_params) {
569 isl_reordering *exp;
571 exp = isl_parameter_alignment_reordering(aff->ls->dim, model);
572 exp = isl_reordering_extend_space(exp,
573 isl_aff_get_domain_space(aff));
574 aff = isl_aff_realign_domain(aff, exp);
577 isl_space_free(model);
578 return aff;
579 error:
580 isl_space_free(model);
581 isl_aff_free(aff);
582 return NULL;
585 /* Given an affine function "aff" defined over a parameter domain,
586 * convert it to a function defined over a domain corresponding
587 * to "domain".
588 * Any parameters with identifiers in "domain" are reinterpreted
589 * as the corresponding domain dimensions.
591 __isl_give isl_aff *isl_aff_unbind_params_insert_domain(
592 __isl_take isl_aff *aff, __isl_take isl_multi_id *domain)
594 isl_bool is_params;
595 isl_space *space;
596 isl_reordering *r;
598 space = isl_aff_peek_domain_space(aff);
599 is_params = isl_space_is_params(space);
600 if (is_params < 0)
601 domain = isl_multi_id_free(domain);
602 else if (!is_params)
603 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
604 "expecting function with parameter domain",
605 domain = isl_multi_id_free(domain));
606 r = isl_reordering_unbind_params_insert_domain(space, domain);
607 isl_multi_id_free(domain);
609 return isl_aff_realign_domain(aff, r);
612 /* Is "aff" obviously equal to zero?
614 * If the denominator is zero, then "aff" is not equal to zero.
616 isl_bool isl_aff_plain_is_zero(__isl_keep isl_aff *aff)
618 int pos;
620 if (!aff)
621 return isl_bool_error;
623 if (isl_int_is_zero(aff->v->el[0]))
624 return isl_bool_false;
625 pos = isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1);
626 return isl_bool_ok(pos < 0);
629 /* Does "aff" represent NaN?
631 isl_bool isl_aff_is_nan(__isl_keep isl_aff *aff)
633 if (!aff)
634 return isl_bool_error;
636 return isl_bool_ok(isl_seq_first_non_zero(aff->v->el, 2) < 0);
639 /* Are "aff1" and "aff2" obviously equal?
641 * NaN is not equal to anything, not even to another NaN.
643 isl_bool isl_aff_plain_is_equal(__isl_keep isl_aff *aff1,
644 __isl_keep isl_aff *aff2)
646 isl_bool equal;
648 if (!aff1 || !aff2)
649 return isl_bool_error;
651 if (isl_aff_is_nan(aff1) || isl_aff_is_nan(aff2))
652 return isl_bool_false;
654 equal = isl_local_space_is_equal(aff1->ls, aff2->ls);
655 if (equal < 0 || !equal)
656 return equal;
658 return isl_vec_is_equal(aff1->v, aff2->v);
661 /* Return the common denominator of "aff" in "v".
663 * We cannot return anything meaningful in case of a NaN.
665 isl_stat isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
667 if (!aff)
668 return isl_stat_error;
669 if (isl_aff_is_nan(aff))
670 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
671 "cannot get denominator of NaN", return isl_stat_error);
672 isl_int_set(*v, aff->v->el[0]);
673 return isl_stat_ok;
676 /* Return the common denominator of "aff".
678 __isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff)
680 isl_ctx *ctx;
682 if (!aff)
683 return NULL;
685 ctx = isl_aff_get_ctx(aff);
686 if (isl_aff_is_nan(aff))
687 return isl_val_nan(ctx);
688 return isl_val_int_from_isl_int(ctx, aff->v->el[0]);
691 /* Return the constant term of "aff".
693 __isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff)
695 isl_ctx *ctx;
696 isl_val *v;
698 if (!aff)
699 return NULL;
701 ctx = isl_aff_get_ctx(aff);
702 if (isl_aff_is_nan(aff))
703 return isl_val_nan(ctx);
704 v = isl_val_rat_from_isl_int(ctx, aff->v->el[1], aff->v->el[0]);
705 return isl_val_normalize(v);
708 /* Return the coefficient of the variable of type "type" at position "pos"
709 * of "aff".
711 __isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
712 enum isl_dim_type type, int pos)
714 isl_ctx *ctx;
715 isl_val *v;
717 if (!aff)
718 return NULL;
720 ctx = isl_aff_get_ctx(aff);
721 if (type == isl_dim_out)
722 isl_die(ctx, isl_error_invalid,
723 "output/set dimension does not have a coefficient",
724 return NULL);
725 if (type == isl_dim_in)
726 type = isl_dim_set;
728 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
729 return NULL;
731 if (isl_aff_is_nan(aff))
732 return isl_val_nan(ctx);
733 pos += isl_local_space_offset(aff->ls, type);
734 v = isl_val_rat_from_isl_int(ctx, aff->v->el[1 + pos], aff->v->el[0]);
735 return isl_val_normalize(v);
738 /* Return the sign of the coefficient of the variable of type "type"
739 * at position "pos" of "aff".
741 int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type,
742 int pos)
744 isl_ctx *ctx;
746 if (!aff)
747 return 0;
749 ctx = isl_aff_get_ctx(aff);
750 if (type == isl_dim_out)
751 isl_die(ctx, isl_error_invalid,
752 "output/set dimension does not have a coefficient",
753 return 0);
754 if (type == isl_dim_in)
755 type = isl_dim_set;
757 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
758 return 0;
760 pos += isl_local_space_offset(aff->ls, type);
761 return isl_int_sgn(aff->v->el[1 + pos]);
764 /* Replace the numerator of the constant term of "aff" by "v".
766 * A NaN is unaffected by this operation.
768 __isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
770 if (!aff)
771 return NULL;
772 if (isl_aff_is_nan(aff))
773 return aff;
774 aff = isl_aff_cow(aff);
775 if (!aff)
776 return NULL;
778 aff->v = isl_vec_cow(aff->v);
779 if (!aff->v)
780 return isl_aff_free(aff);
782 isl_int_set(aff->v->el[1], v);
784 return aff;
787 /* Replace the constant term of "aff" by "v".
789 * A NaN is unaffected by this operation.
791 __isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
792 __isl_take isl_val *v)
794 if (!aff || !v)
795 goto error;
797 if (isl_aff_is_nan(aff)) {
798 isl_val_free(v);
799 return aff;
802 if (!isl_val_is_rat(v))
803 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
804 "expecting rational value", goto error);
806 if (isl_int_eq(aff->v->el[1], v->n) &&
807 isl_int_eq(aff->v->el[0], v->d)) {
808 isl_val_free(v);
809 return aff;
812 aff = isl_aff_cow(aff);
813 if (!aff)
814 goto error;
815 aff->v = isl_vec_cow(aff->v);
816 if (!aff->v)
817 goto error;
819 if (isl_int_eq(aff->v->el[0], v->d)) {
820 isl_int_set(aff->v->el[1], v->n);
821 } else if (isl_int_is_one(v->d)) {
822 isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
823 } else {
824 isl_seq_scale(aff->v->el + 1,
825 aff->v->el + 1, v->d, aff->v->size - 1);
826 isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
827 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
828 aff->v = isl_vec_normalize(aff->v);
829 if (!aff->v)
830 goto error;
833 isl_val_free(v);
834 return aff;
835 error:
836 isl_aff_free(aff);
837 isl_val_free(v);
838 return NULL;
841 /* Add "v" to the constant term of "aff".
843 * A NaN is unaffected by this operation.
845 __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
847 if (isl_int_is_zero(v))
848 return aff;
850 if (!aff)
851 return NULL;
852 if (isl_aff_is_nan(aff))
853 return aff;
854 aff = isl_aff_cow(aff);
855 if (!aff)
856 return NULL;
858 aff->v = isl_vec_cow(aff->v);
859 if (!aff->v)
860 return isl_aff_free(aff);
862 isl_int_addmul(aff->v->el[1], aff->v->el[0], v);
864 return aff;
867 /* Add "v" to the constant term of "aff".
869 * A NaN is unaffected by this operation.
871 __isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff,
872 __isl_take isl_val *v)
874 if (!aff || !v)
875 goto error;
877 if (isl_aff_is_nan(aff) || isl_val_is_zero(v)) {
878 isl_val_free(v);
879 return aff;
882 if (!isl_val_is_rat(v))
883 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
884 "expecting rational value", goto error);
886 aff = isl_aff_cow(aff);
887 if (!aff)
888 goto error;
890 aff->v = isl_vec_cow(aff->v);
891 if (!aff->v)
892 goto error;
894 if (isl_int_is_one(v->d)) {
895 isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
896 } else if (isl_int_eq(aff->v->el[0], v->d)) {
897 isl_int_add(aff->v->el[1], aff->v->el[1], v->n);
898 aff->v = isl_vec_normalize(aff->v);
899 if (!aff->v)
900 goto error;
901 } else {
902 isl_seq_scale(aff->v->el + 1,
903 aff->v->el + 1, v->d, aff->v->size - 1);
904 isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
905 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
906 aff->v = isl_vec_normalize(aff->v);
907 if (!aff->v)
908 goto error;
911 isl_val_free(v);
912 return aff;
913 error:
914 isl_aff_free(aff);
915 isl_val_free(v);
916 return NULL;
919 __isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v)
921 isl_int t;
923 isl_int_init(t);
924 isl_int_set_si(t, v);
925 aff = isl_aff_add_constant(aff, t);
926 isl_int_clear(t);
928 return aff;
931 /* Add "v" to the numerator of the constant term of "aff".
933 * A NaN is unaffected by this operation.
935 __isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff, isl_int v)
937 if (isl_int_is_zero(v))
938 return aff;
940 if (!aff)
941 return NULL;
942 if (isl_aff_is_nan(aff))
943 return aff;
944 aff = isl_aff_cow(aff);
945 if (!aff)
946 return NULL;
948 aff->v = isl_vec_cow(aff->v);
949 if (!aff->v)
950 return isl_aff_free(aff);
952 isl_int_add(aff->v->el[1], aff->v->el[1], v);
954 return aff;
957 /* Add "v" to the numerator of the constant term of "aff".
959 * A NaN is unaffected by this operation.
961 __isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v)
963 isl_int t;
965 if (v == 0)
966 return aff;
968 isl_int_init(t);
969 isl_int_set_si(t, v);
970 aff = isl_aff_add_constant_num(aff, t);
971 isl_int_clear(t);
973 return aff;
976 /* Replace the numerator of the constant term of "aff" by "v".
978 * A NaN is unaffected by this operation.
980 __isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v)
982 if (!aff)
983 return NULL;
984 if (isl_aff_is_nan(aff))
985 return aff;
986 aff = isl_aff_cow(aff);
987 if (!aff)
988 return NULL;
990 aff->v = isl_vec_cow(aff->v);
991 if (!aff->v)
992 return isl_aff_free(aff);
994 isl_int_set_si(aff->v->el[1], 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(__isl_take isl_aff *aff,
1005 enum isl_dim_type type, int pos, isl_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 (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
1018 return isl_aff_free(aff);
1020 if (isl_aff_is_nan(aff))
1021 return aff;
1022 aff = isl_aff_cow(aff);
1023 if (!aff)
1024 return NULL;
1026 aff->v = isl_vec_cow(aff->v);
1027 if (!aff->v)
1028 return isl_aff_free(aff);
1030 pos += isl_local_space_offset(aff->ls, type);
1031 isl_int_set(aff->v->el[1 + pos], v);
1033 return aff;
1036 /* Replace the numerator of the coefficient of the variable of type "type"
1037 * at position "pos" of "aff" by "v".
1039 * A NaN is unaffected by this operation.
1041 __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
1042 enum isl_dim_type type, int pos, int v)
1044 if (!aff)
1045 return NULL;
1047 if (type == isl_dim_out)
1048 isl_die(aff->v->ctx, isl_error_invalid,
1049 "output/set dimension does not have a coefficient",
1050 return isl_aff_free(aff));
1051 if (type == isl_dim_in)
1052 type = isl_dim_set;
1054 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
1055 return isl_aff_free(aff);
1057 if (isl_aff_is_nan(aff))
1058 return aff;
1059 pos += isl_local_space_offset(aff->ls, type);
1060 if (isl_int_cmp_si(aff->v->el[1 + pos], v) == 0)
1061 return aff;
1063 aff = isl_aff_cow(aff);
1064 if (!aff)
1065 return NULL;
1067 aff->v = isl_vec_cow(aff->v);
1068 if (!aff->v)
1069 return isl_aff_free(aff);
1071 isl_int_set_si(aff->v->el[1 + pos], v);
1073 return aff;
1076 /* Replace the coefficient of the variable of type "type" at position "pos"
1077 * of "aff" by "v".
1079 * A NaN is unaffected by this operation.
1081 __isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
1082 enum isl_dim_type type, int pos, __isl_take isl_val *v)
1084 if (!aff || !v)
1085 goto error;
1087 if (type == isl_dim_out)
1088 isl_die(aff->v->ctx, isl_error_invalid,
1089 "output/set dimension does not have a coefficient",
1090 goto error);
1091 if (type == isl_dim_in)
1092 type = isl_dim_set;
1094 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
1095 return isl_aff_free(aff);
1097 if (isl_aff_is_nan(aff)) {
1098 isl_val_free(v);
1099 return aff;
1101 if (!isl_val_is_rat(v))
1102 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1103 "expecting rational value", goto error);
1105 pos += isl_local_space_offset(aff->ls, type);
1106 if (isl_int_eq(aff->v->el[1 + pos], v->n) &&
1107 isl_int_eq(aff->v->el[0], v->d)) {
1108 isl_val_free(v);
1109 return aff;
1112 aff = isl_aff_cow(aff);
1113 if (!aff)
1114 goto error;
1115 aff->v = isl_vec_cow(aff->v);
1116 if (!aff->v)
1117 goto error;
1119 if (isl_int_eq(aff->v->el[0], v->d)) {
1120 isl_int_set(aff->v->el[1 + pos], v->n);
1121 } else if (isl_int_is_one(v->d)) {
1122 isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1123 } else {
1124 isl_seq_scale(aff->v->el + 1,
1125 aff->v->el + 1, v->d, aff->v->size - 1);
1126 isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1127 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
1128 aff->v = isl_vec_normalize(aff->v);
1129 if (!aff->v)
1130 goto error;
1133 isl_val_free(v);
1134 return aff;
1135 error:
1136 isl_aff_free(aff);
1137 isl_val_free(v);
1138 return NULL;
1141 /* Add "v" to the coefficient of the variable of type "type"
1142 * at position "pos" of "aff".
1144 * A NaN is unaffected by this operation.
1146 __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
1147 enum isl_dim_type type, int pos, isl_int v)
1149 if (!aff)
1150 return NULL;
1152 if (type == isl_dim_out)
1153 isl_die(aff->v->ctx, isl_error_invalid,
1154 "output/set dimension does not have a coefficient",
1155 return isl_aff_free(aff));
1156 if (type == isl_dim_in)
1157 type = isl_dim_set;
1159 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
1160 return isl_aff_free(aff);
1162 if (isl_aff_is_nan(aff))
1163 return aff;
1164 aff = isl_aff_cow(aff);
1165 if (!aff)
1166 return NULL;
1168 aff->v = isl_vec_cow(aff->v);
1169 if (!aff->v)
1170 return isl_aff_free(aff);
1172 pos += isl_local_space_offset(aff->ls, type);
1173 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v);
1175 return aff;
1178 /* Add "v" to the coefficient of the variable of type "type"
1179 * at position "pos" of "aff".
1181 * A NaN is unaffected by this operation.
1183 __isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff,
1184 enum isl_dim_type type, int pos, __isl_take isl_val *v)
1186 if (!aff || !v)
1187 goto error;
1189 if (isl_val_is_zero(v)) {
1190 isl_val_free(v);
1191 return aff;
1194 if (type == isl_dim_out)
1195 isl_die(aff->v->ctx, isl_error_invalid,
1196 "output/set dimension does not have a coefficient",
1197 goto error);
1198 if (type == isl_dim_in)
1199 type = isl_dim_set;
1201 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0)
1202 goto error;
1204 if (isl_aff_is_nan(aff)) {
1205 isl_val_free(v);
1206 return aff;
1208 if (!isl_val_is_rat(v))
1209 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1210 "expecting rational value", goto error);
1212 aff = isl_aff_cow(aff);
1213 if (!aff)
1214 goto error;
1216 aff->v = isl_vec_cow(aff->v);
1217 if (!aff->v)
1218 goto error;
1220 pos += isl_local_space_offset(aff->ls, type);
1221 if (isl_int_is_one(v->d)) {
1222 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1223 } else if (isl_int_eq(aff->v->el[0], v->d)) {
1224 isl_int_add(aff->v->el[1 + pos], aff->v->el[1 + pos], v->n);
1225 aff->v = isl_vec_normalize(aff->v);
1226 if (!aff->v)
1227 goto error;
1228 } else {
1229 isl_seq_scale(aff->v->el + 1,
1230 aff->v->el + 1, v->d, aff->v->size - 1);
1231 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
1232 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
1233 aff->v = isl_vec_normalize(aff->v);
1234 if (!aff->v)
1235 goto error;
1238 isl_val_free(v);
1239 return aff;
1240 error:
1241 isl_aff_free(aff);
1242 isl_val_free(v);
1243 return NULL;
1246 __isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
1247 enum isl_dim_type type, int pos, int v)
1249 isl_int t;
1251 isl_int_init(t);
1252 isl_int_set_si(t, v);
1253 aff = isl_aff_add_coefficient(aff, type, pos, t);
1254 isl_int_clear(t);
1256 return aff;
1259 __isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos)
1261 if (!aff)
1262 return NULL;
1264 return isl_local_space_get_div(aff->ls, pos);
1267 /* Return the negation of "aff".
1269 * As a special case, -NaN = NaN.
1271 __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
1273 if (!aff)
1274 return NULL;
1275 if (isl_aff_is_nan(aff))
1276 return aff;
1277 aff = isl_aff_cow(aff);
1278 if (!aff)
1279 return NULL;
1280 aff->v = isl_vec_cow(aff->v);
1281 if (!aff->v)
1282 return isl_aff_free(aff);
1284 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
1286 return aff;
1289 /* Remove divs from the local space that do not appear in the affine
1290 * expression.
1291 * We currently only remove divs at the end.
1292 * Some intermediate divs may also not appear directly in the affine
1293 * expression, but we would also need to check that no other divs are
1294 * defined in terms of them.
1296 __isl_give isl_aff *isl_aff_remove_unused_divs(__isl_take isl_aff *aff)
1298 int pos;
1299 int off;
1300 isl_size n;
1302 if (!aff)
1303 return NULL;
1305 n = isl_local_space_dim(aff->ls, isl_dim_div);
1306 if (n < 0)
1307 return isl_aff_free(aff);
1308 off = isl_local_space_offset(aff->ls, isl_dim_div);
1310 pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1;
1311 if (pos == n)
1312 return aff;
1314 aff = isl_aff_cow(aff);
1315 if (!aff)
1316 return NULL;
1318 aff->ls = isl_local_space_drop_dims(aff->ls, isl_dim_div, pos, n - pos);
1319 aff->v = isl_vec_drop_els(aff->v, 1 + off + pos, n - pos);
1320 if (!aff->ls || !aff->v)
1321 return isl_aff_free(aff);
1323 return aff;
1326 /* Look for any divs in the aff->ls with a denominator equal to one
1327 * and plug them into the affine expression and any subsequent divs
1328 * that may reference the div.
1330 static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff)
1332 int i;
1333 isl_size n;
1334 int len;
1335 isl_int v;
1336 isl_vec *vec;
1337 isl_local_space *ls;
1338 unsigned pos;
1340 if (!aff)
1341 return NULL;
1343 n = isl_local_space_dim(aff->ls, isl_dim_div);
1344 if (n < 0)
1345 return isl_aff_free(aff);
1346 len = aff->v->size;
1347 for (i = 0; i < n; ++i) {
1348 if (!isl_int_is_one(aff->ls->div->row[i][0]))
1349 continue;
1350 ls = isl_local_space_copy(aff->ls);
1351 ls = isl_local_space_substitute_seq(ls, isl_dim_div, i,
1352 aff->ls->div->row[i], len, i + 1, n - (i + 1));
1353 vec = isl_vec_copy(aff->v);
1354 vec = isl_vec_cow(vec);
1355 if (!ls || !vec)
1356 goto error;
1358 isl_int_init(v);
1360 pos = isl_local_space_offset(aff->ls, isl_dim_div) + i;
1361 isl_seq_substitute(vec->el, pos, aff->ls->div->row[i],
1362 len, len, v);
1364 isl_int_clear(v);
1366 isl_vec_free(aff->v);
1367 aff->v = vec;
1368 isl_local_space_free(aff->ls);
1369 aff->ls = ls;
1372 return aff;
1373 error:
1374 isl_vec_free(vec);
1375 isl_local_space_free(ls);
1376 return isl_aff_free(aff);
1379 /* Look for any divs j that appear with a unit coefficient inside
1380 * the definitions of other divs i and plug them into the definitions
1381 * of the divs i.
1383 * In particular, an expression of the form
1385 * floor((f(..) + floor(g(..)/n))/m)
1387 * is simplified to
1389 * floor((n * f(..) + g(..))/(n * m))
1391 * This simplification is correct because we can move the expression
1392 * f(..) into the inner floor in the original expression to obtain
1394 * floor(floor((n * f(..) + g(..))/n)/m)
1396 * from which we can derive the simplified expression.
1398 static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff)
1400 int i, j;
1401 isl_size n;
1402 int off;
1404 if (!aff)
1405 return NULL;
1407 n = isl_local_space_dim(aff->ls, isl_dim_div);
1408 if (n < 0)
1409 return isl_aff_free(aff);
1410 off = isl_local_space_offset(aff->ls, isl_dim_div);
1411 for (i = 1; i < n; ++i) {
1412 for (j = 0; j < i; ++j) {
1413 if (!isl_int_is_one(aff->ls->div->row[i][1 + off + j]))
1414 continue;
1415 aff->ls = isl_local_space_substitute_seq(aff->ls,
1416 isl_dim_div, j, aff->ls->div->row[j],
1417 aff->v->size, i, 1);
1418 if (!aff->ls)
1419 return isl_aff_free(aff);
1423 return aff;
1426 /* Swap divs "a" and "b" in "aff", which is assumed to be non-NULL.
1428 * Even though this function is only called on isl_affs with a single
1429 * reference, we are careful to only change aff->v and aff->ls together.
1431 static __isl_give isl_aff *swap_div(__isl_take isl_aff *aff, int a, int b)
1433 unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
1434 isl_local_space *ls;
1435 isl_vec *v;
1437 ls = isl_local_space_copy(aff->ls);
1438 ls = isl_local_space_swap_div(ls, a, b);
1439 v = isl_vec_copy(aff->v);
1440 v = isl_vec_cow(v);
1441 if (!ls || !v)
1442 goto error;
1444 isl_int_swap(v->el[1 + off + a], v->el[1 + off + b]);
1445 isl_vec_free(aff->v);
1446 aff->v = v;
1447 isl_local_space_free(aff->ls);
1448 aff->ls = ls;
1450 return aff;
1451 error:
1452 isl_vec_free(v);
1453 isl_local_space_free(ls);
1454 return isl_aff_free(aff);
1457 /* Merge divs "a" and "b" in "aff", which is assumed to be non-NULL.
1459 * We currently do not actually remove div "b", but simply add its
1460 * coefficient to that of "a" and then zero it out.
1462 static __isl_give isl_aff *merge_divs(__isl_take isl_aff *aff, int a, int b)
1464 unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
1466 if (isl_int_is_zero(aff->v->el[1 + off + b]))
1467 return aff;
1469 aff->v = isl_vec_cow(aff->v);
1470 if (!aff->v)
1471 return isl_aff_free(aff);
1473 isl_int_add(aff->v->el[1 + off + a],
1474 aff->v->el[1 + off + a], aff->v->el[1 + off + b]);
1475 isl_int_set_si(aff->v->el[1 + off + b], 0);
1477 return aff;
1480 /* Sort the divs in the local space of "aff" according to
1481 * the comparison function "cmp_row" in isl_local_space.c,
1482 * combining the coefficients of identical divs.
1484 * Reordering divs does not change the semantics of "aff",
1485 * so there is no need to call isl_aff_cow.
1486 * Moreover, this function is currently only called on isl_affs
1487 * with a single reference.
1489 static __isl_give isl_aff *sort_divs(__isl_take isl_aff *aff)
1491 isl_size n;
1492 int i, j;
1494 n = isl_aff_dim(aff, isl_dim_div);
1495 if (n < 0)
1496 return isl_aff_free(aff);
1497 for (i = 1; i < n; ++i) {
1498 for (j = i - 1; j >= 0; --j) {
1499 int cmp = isl_mat_cmp_div(aff->ls->div, j, j + 1);
1500 if (cmp < 0)
1501 break;
1502 if (cmp == 0)
1503 aff = merge_divs(aff, j, j + 1);
1504 else
1505 aff = swap_div(aff, j, j + 1);
1506 if (!aff)
1507 return NULL;
1511 return aff;
1514 /* Normalize the representation of "aff".
1516 * This function should only be called of "new" isl_affs, i.e.,
1517 * with only a single reference. We therefore do not need to
1518 * worry about affecting other instances.
1520 __isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff)
1522 if (!aff)
1523 return NULL;
1524 aff->v = isl_vec_normalize(aff->v);
1525 if (!aff->v)
1526 return isl_aff_free(aff);
1527 aff = plug_in_integral_divs(aff);
1528 aff = plug_in_unit_divs(aff);
1529 aff = sort_divs(aff);
1530 aff = isl_aff_remove_unused_divs(aff);
1531 return aff;
1534 /* Given f, return floor(f).
1535 * If f is an integer expression, then just return f.
1536 * If f is a constant, then return the constant floor(f).
1537 * Otherwise, if f = g/m, write g = q m + r,
1538 * create a new div d = [r/m] and return the expression q + d.
1539 * The coefficients in r are taken to lie between -m/2 and m/2.
1541 * reduce_div_coefficients performs the same normalization.
1543 * As a special case, floor(NaN) = NaN.
1545 __isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff)
1547 int i;
1548 int size;
1549 isl_ctx *ctx;
1550 isl_vec *div;
1552 if (!aff)
1553 return NULL;
1555 if (isl_aff_is_nan(aff))
1556 return aff;
1557 if (isl_int_is_one(aff->v->el[0]))
1558 return aff;
1560 aff = isl_aff_cow(aff);
1561 if (!aff)
1562 return NULL;
1564 aff->v = isl_vec_cow(aff->v);
1565 if (!aff->v)
1566 return isl_aff_free(aff);
1568 if (isl_aff_is_cst(aff)) {
1569 isl_int_fdiv_q(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
1570 isl_int_set_si(aff->v->el[0], 1);
1571 return aff;
1574 div = isl_vec_copy(aff->v);
1575 div = isl_vec_cow(div);
1576 if (!div)
1577 return isl_aff_free(aff);
1579 ctx = isl_aff_get_ctx(aff);
1580 isl_int_fdiv_q(aff->v->el[0], aff->v->el[0], ctx->two);
1581 for (i = 1; i < aff->v->size; ++i) {
1582 isl_int_fdiv_r(div->el[i], div->el[i], div->el[0]);
1583 isl_int_fdiv_q(aff->v->el[i], aff->v->el[i], div->el[0]);
1584 if (isl_int_gt(div->el[i], aff->v->el[0])) {
1585 isl_int_sub(div->el[i], div->el[i], div->el[0]);
1586 isl_int_add_ui(aff->v->el[i], aff->v->el[i], 1);
1590 aff->ls = isl_local_space_add_div(aff->ls, div);
1591 if (!aff->ls)
1592 return isl_aff_free(aff);
1594 size = aff->v->size;
1595 aff->v = isl_vec_extend(aff->v, size + 1);
1596 if (!aff->v)
1597 return isl_aff_free(aff);
1598 isl_int_set_si(aff->v->el[0], 1);
1599 isl_int_set_si(aff->v->el[size], 1);
1601 aff = isl_aff_normalize(aff);
1603 return aff;
1606 /* Compute
1608 * aff mod m = aff - m * floor(aff/m)
1610 * with m an integer value.
1612 __isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
1613 __isl_take isl_val *m)
1615 isl_aff *res;
1617 if (!aff || !m)
1618 goto error;
1620 if (!isl_val_is_int(m))
1621 isl_die(isl_val_get_ctx(m), isl_error_invalid,
1622 "expecting integer modulo", goto error);
1624 res = isl_aff_copy(aff);
1625 aff = isl_aff_scale_down_val(aff, isl_val_copy(m));
1626 aff = isl_aff_floor(aff);
1627 aff = isl_aff_scale_val(aff, m);
1628 res = isl_aff_sub(res, aff);
1630 return res;
1631 error:
1632 isl_aff_free(aff);
1633 isl_val_free(m);
1634 return NULL;
1637 /* Compute
1639 * pwaff mod m = pwaff - m * floor(pwaff/m)
1641 __isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m)
1643 isl_pw_aff *res;
1645 res = isl_pw_aff_copy(pwaff);
1646 pwaff = isl_pw_aff_scale_down(pwaff, m);
1647 pwaff = isl_pw_aff_floor(pwaff);
1648 pwaff = isl_pw_aff_scale(pwaff, m);
1649 res = isl_pw_aff_sub(res, pwaff);
1651 return res;
1654 /* Compute
1656 * pa mod m = pa - m * floor(pa/m)
1658 * with m an integer value.
1660 __isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa,
1661 __isl_take isl_val *m)
1663 if (!pa || !m)
1664 goto error;
1665 if (!isl_val_is_int(m))
1666 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
1667 "expecting integer modulo", goto error);
1668 pa = isl_pw_aff_mod(pa, m->n);
1669 isl_val_free(m);
1670 return pa;
1671 error:
1672 isl_pw_aff_free(pa);
1673 isl_val_free(m);
1674 return NULL;
1677 /* Given f, return ceil(f).
1678 * If f is an integer expression, then just return f.
1679 * Otherwise, let f be the expression
1681 * e/m
1683 * then return
1685 * floor((e + m - 1)/m)
1687 * As a special case, ceil(NaN) = NaN.
1689 __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff)
1691 if (!aff)
1692 return NULL;
1694 if (isl_aff_is_nan(aff))
1695 return aff;
1696 if (isl_int_is_one(aff->v->el[0]))
1697 return aff;
1699 aff = isl_aff_cow(aff);
1700 if (!aff)
1701 return NULL;
1702 aff->v = isl_vec_cow(aff->v);
1703 if (!aff->v)
1704 return isl_aff_free(aff);
1706 isl_int_add(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
1707 isl_int_sub_ui(aff->v->el[1], aff->v->el[1], 1);
1708 aff = isl_aff_floor(aff);
1710 return aff;
1713 /* Apply the expansion computed by isl_merge_divs.
1714 * The expansion itself is given by "exp" while the resulting
1715 * list of divs is given by "div".
1717 __isl_give isl_aff *isl_aff_expand_divs(__isl_take isl_aff *aff,
1718 __isl_take isl_mat *div, int *exp)
1720 isl_size old_n_div;
1721 isl_size new_n_div;
1722 int offset;
1724 aff = isl_aff_cow(aff);
1725 if (!aff || !div)
1726 goto error;
1728 old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
1729 new_n_div = isl_mat_rows(div);
1730 if (old_n_div < 0 || new_n_div < 0)
1731 goto error;
1732 offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
1734 aff->v = isl_vec_expand(aff->v, offset, old_n_div, exp, new_n_div);
1735 aff->ls = isl_local_space_replace_divs(aff->ls, div);
1736 if (!aff->v || !aff->ls)
1737 return isl_aff_free(aff);
1738 return aff;
1739 error:
1740 isl_aff_free(aff);
1741 isl_mat_free(div);
1742 return NULL;
1745 /* Add two affine expressions that live in the same local space.
1747 static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1,
1748 __isl_take isl_aff *aff2)
1750 isl_int gcd, f;
1752 aff1 = isl_aff_cow(aff1);
1753 if (!aff1 || !aff2)
1754 goto error;
1756 aff1->v = isl_vec_cow(aff1->v);
1757 if (!aff1->v)
1758 goto error;
1760 isl_int_init(gcd);
1761 isl_int_init(f);
1762 isl_int_gcd(gcd, aff1->v->el[0], aff2->v->el[0]);
1763 isl_int_divexact(f, aff2->v->el[0], gcd);
1764 isl_seq_scale(aff1->v->el + 1, aff1->v->el + 1, f, aff1->v->size - 1);
1765 isl_int_divexact(f, aff1->v->el[0], gcd);
1766 isl_seq_addmul(aff1->v->el + 1, f, aff2->v->el + 1, aff1->v->size - 1);
1767 isl_int_divexact(f, aff2->v->el[0], gcd);
1768 isl_int_mul(aff1->v->el[0], aff1->v->el[0], f);
1769 isl_int_clear(f);
1770 isl_int_clear(gcd);
1772 isl_aff_free(aff2);
1773 return aff1;
1774 error:
1775 isl_aff_free(aff1);
1776 isl_aff_free(aff2);
1777 return NULL;
1780 /* Return the sum of "aff1" and "aff2".
1782 * If either of the two is NaN, then the result is NaN.
1784 __isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
1785 __isl_take isl_aff *aff2)
1787 isl_ctx *ctx;
1788 int *exp1 = NULL;
1789 int *exp2 = NULL;
1790 isl_mat *div;
1791 isl_size n_div1, n_div2;
1793 if (!aff1 || !aff2)
1794 goto error;
1796 ctx = isl_aff_get_ctx(aff1);
1797 if (!isl_space_is_equal(aff1->ls->dim, aff2->ls->dim))
1798 isl_die(ctx, isl_error_invalid,
1799 "spaces don't match", goto error);
1801 if (isl_aff_is_nan(aff1)) {
1802 isl_aff_free(aff2);
1803 return aff1;
1805 if (isl_aff_is_nan(aff2)) {
1806 isl_aff_free(aff1);
1807 return aff2;
1810 n_div1 = isl_aff_dim(aff1, isl_dim_div);
1811 n_div2 = isl_aff_dim(aff2, isl_dim_div);
1812 if (n_div1 < 0 || n_div2 < 0)
1813 goto error;
1814 if (n_div1 == 0 && n_div2 == 0)
1815 return add_expanded(aff1, aff2);
1817 exp1 = isl_alloc_array(ctx, int, n_div1);
1818 exp2 = isl_alloc_array(ctx, int, n_div2);
1819 if ((n_div1 && !exp1) || (n_div2 && !exp2))
1820 goto error;
1822 div = isl_merge_divs(aff1->ls->div, aff2->ls->div, exp1, exp2);
1823 aff1 = isl_aff_expand_divs(aff1, isl_mat_copy(div), exp1);
1824 aff2 = isl_aff_expand_divs(aff2, div, exp2);
1825 free(exp1);
1826 free(exp2);
1828 return add_expanded(aff1, aff2);
1829 error:
1830 free(exp1);
1831 free(exp2);
1832 isl_aff_free(aff1);
1833 isl_aff_free(aff2);
1834 return NULL;
1837 __isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
1838 __isl_take isl_aff *aff2)
1840 return isl_aff_add(aff1, isl_aff_neg(aff2));
1843 /* Return the result of scaling "aff" by a factor of "f".
1845 * As a special case, f * NaN = NaN.
1847 __isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f)
1849 isl_int gcd;
1851 if (!aff)
1852 return NULL;
1853 if (isl_aff_is_nan(aff))
1854 return aff;
1856 if (isl_int_is_one(f))
1857 return aff;
1859 aff = isl_aff_cow(aff);
1860 if (!aff)
1861 return NULL;
1862 aff->v = isl_vec_cow(aff->v);
1863 if (!aff->v)
1864 return isl_aff_free(aff);
1866 if (isl_int_is_pos(f) && isl_int_is_divisible_by(aff->v->el[0], f)) {
1867 isl_int_divexact(aff->v->el[0], aff->v->el[0], f);
1868 return aff;
1871 isl_int_init(gcd);
1872 isl_int_gcd(gcd, aff->v->el[0], f);
1873 isl_int_divexact(aff->v->el[0], aff->v->el[0], gcd);
1874 isl_int_divexact(gcd, f, gcd);
1875 isl_seq_scale(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
1876 isl_int_clear(gcd);
1878 return aff;
1881 /* Multiple "aff" by "v".
1883 __isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
1884 __isl_take isl_val *v)
1886 if (!aff || !v)
1887 goto error;
1889 if (isl_val_is_one(v)) {
1890 isl_val_free(v);
1891 return aff;
1894 if (!isl_val_is_rat(v))
1895 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1896 "expecting rational factor", goto error);
1898 aff = isl_aff_scale(aff, v->n);
1899 aff = isl_aff_scale_down(aff, v->d);
1901 isl_val_free(v);
1902 return aff;
1903 error:
1904 isl_aff_free(aff);
1905 isl_val_free(v);
1906 return NULL;
1909 /* Return the result of scaling "aff" down by a factor of "f".
1911 * As a special case, NaN/f = NaN.
1913 __isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f)
1915 isl_int gcd;
1917 if (!aff)
1918 return NULL;
1919 if (isl_aff_is_nan(aff))
1920 return aff;
1922 if (isl_int_is_one(f))
1923 return aff;
1925 aff = isl_aff_cow(aff);
1926 if (!aff)
1927 return NULL;
1929 if (isl_int_is_zero(f))
1930 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1931 "cannot scale down by zero", return isl_aff_free(aff));
1933 aff->v = isl_vec_cow(aff->v);
1934 if (!aff->v)
1935 return isl_aff_free(aff);
1937 isl_int_init(gcd);
1938 isl_seq_gcd(aff->v->el + 1, aff->v->size - 1, &gcd);
1939 isl_int_gcd(gcd, gcd, f);
1940 isl_seq_scale_down(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
1941 isl_int_divexact(gcd, f, gcd);
1942 isl_int_mul(aff->v->el[0], aff->v->el[0], gcd);
1943 isl_int_clear(gcd);
1945 return aff;
1948 /* Divide "aff" by "v".
1950 __isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff,
1951 __isl_take isl_val *v)
1953 if (!aff || !v)
1954 goto error;
1956 if (isl_val_is_one(v)) {
1957 isl_val_free(v);
1958 return aff;
1961 if (!isl_val_is_rat(v))
1962 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1963 "expecting rational factor", goto error);
1964 if (!isl_val_is_pos(v))
1965 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
1966 "factor needs to be positive", goto error);
1968 aff = isl_aff_scale(aff, v->d);
1969 aff = isl_aff_scale_down(aff, v->n);
1971 isl_val_free(v);
1972 return aff;
1973 error:
1974 isl_aff_free(aff);
1975 isl_val_free(v);
1976 return NULL;
1979 __isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f)
1981 isl_int v;
1983 if (f == 1)
1984 return aff;
1986 isl_int_init(v);
1987 isl_int_set_ui(v, f);
1988 aff = isl_aff_scale_down(aff, v);
1989 isl_int_clear(v);
1991 return aff;
1994 __isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff,
1995 enum isl_dim_type type, unsigned pos, const char *s)
1997 aff = isl_aff_cow(aff);
1998 if (!aff)
1999 return NULL;
2000 if (type == isl_dim_out)
2001 isl_die(aff->v->ctx, isl_error_invalid,
2002 "cannot set name of output/set dimension",
2003 return isl_aff_free(aff));
2004 if (type == isl_dim_in)
2005 type = isl_dim_set;
2006 aff->ls = isl_local_space_set_dim_name(aff->ls, type, pos, s);
2007 if (!aff->ls)
2008 return isl_aff_free(aff);
2010 return aff;
2013 __isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff,
2014 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
2016 aff = isl_aff_cow(aff);
2017 if (!aff)
2018 goto error;
2019 if (type == isl_dim_out)
2020 isl_die(aff->v->ctx, isl_error_invalid,
2021 "cannot set name of output/set dimension",
2022 goto error);
2023 if (type == isl_dim_in)
2024 type = isl_dim_set;
2025 aff->ls = isl_local_space_set_dim_id(aff->ls, type, pos, id);
2026 if (!aff->ls)
2027 return isl_aff_free(aff);
2029 return aff;
2030 error:
2031 isl_id_free(id);
2032 isl_aff_free(aff);
2033 return NULL;
2036 /* Replace the identifier of the input tuple of "aff" by "id".
2037 * type is currently required to be equal to isl_dim_in
2039 __isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff,
2040 enum isl_dim_type type, __isl_take isl_id *id)
2042 aff = isl_aff_cow(aff);
2043 if (!aff)
2044 goto error;
2045 if (type != isl_dim_in)
2046 isl_die(aff->v->ctx, isl_error_invalid,
2047 "cannot only set id of input tuple", goto error);
2048 aff->ls = isl_local_space_set_tuple_id(aff->ls, isl_dim_set, id);
2049 if (!aff->ls)
2050 return isl_aff_free(aff);
2052 return aff;
2053 error:
2054 isl_id_free(id);
2055 isl_aff_free(aff);
2056 return NULL;
2059 /* Exploit the equalities in "eq" to simplify the affine expression
2060 * and the expressions of the integer divisions in the local space.
2061 * The integer divisions in this local space are assumed to appear
2062 * as regular dimensions in "eq".
2064 static __isl_give isl_aff *isl_aff_substitute_equalities_lifted(
2065 __isl_take isl_aff *aff, __isl_take isl_basic_set *eq)
2067 int i, j;
2068 unsigned o_div;
2069 unsigned n_div;
2071 if (!eq)
2072 goto error;
2073 if (eq->n_eq == 0) {
2074 isl_basic_set_free(eq);
2075 return aff;
2078 aff = isl_aff_cow(aff);
2079 if (!aff)
2080 goto error;
2082 aff->ls = isl_local_space_substitute_equalities(aff->ls,
2083 isl_basic_set_copy(eq));
2084 aff->v = isl_vec_cow(aff->v);
2085 if (!aff->ls || !aff->v)
2086 goto error;
2088 o_div = isl_basic_set_offset(eq, isl_dim_div);
2089 n_div = eq->n_div;
2090 for (i = 0; i < eq->n_eq; ++i) {
2091 j = isl_seq_last_non_zero(eq->eq[i], o_div + n_div);
2092 if (j < 0 || j == 0 || j >= o_div)
2093 continue;
2095 isl_seq_elim(aff->v->el + 1, eq->eq[i], j, o_div,
2096 &aff->v->el[0]);
2099 isl_basic_set_free(eq);
2100 aff = isl_aff_normalize(aff);
2101 return aff;
2102 error:
2103 isl_basic_set_free(eq);
2104 isl_aff_free(aff);
2105 return NULL;
2108 /* Exploit the equalities in "eq" to simplify the affine expression
2109 * and the expressions of the integer divisions in the local space.
2111 __isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff,
2112 __isl_take isl_basic_set *eq)
2114 isl_size n_div;
2116 if (!aff || !eq)
2117 goto error;
2118 n_div = isl_local_space_dim(aff->ls, isl_dim_div);
2119 if (n_div < 0)
2120 goto error;
2121 if (n_div > 0)
2122 eq = isl_basic_set_add_dims(eq, isl_dim_set, n_div);
2123 return isl_aff_substitute_equalities_lifted(aff, eq);
2124 error:
2125 isl_basic_set_free(eq);
2126 isl_aff_free(aff);
2127 return NULL;
2130 /* Look for equalities among the variables shared by context and aff
2131 * and the integer divisions of aff, if any.
2132 * The equalities are then used to eliminate coefficients and/or integer
2133 * divisions from aff.
2135 __isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
2136 __isl_take isl_set *context)
2138 isl_local_space *ls;
2139 isl_basic_set *hull;
2141 ls = isl_aff_get_domain_local_space(aff);
2142 context = isl_local_space_lift_set(ls, context);
2144 hull = isl_set_affine_hull(context);
2145 return isl_aff_substitute_equalities_lifted(aff, hull);
2148 __isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
2149 __isl_take isl_set *context)
2151 isl_set *dom_context = isl_set_universe(isl_aff_get_domain_space(aff));
2152 dom_context = isl_set_intersect_params(dom_context, context);
2153 return isl_aff_gist(aff, dom_context);
2156 /* Return a basic set containing those elements in the space
2157 * of aff where it is positive. "rational" should not be set.
2159 * If "aff" is NaN, then it is not positive.
2161 static __isl_give isl_basic_set *aff_pos_basic_set(__isl_take isl_aff *aff,
2162 int rational, void *user)
2164 isl_constraint *ineq;
2165 isl_basic_set *bset;
2166 isl_val *c;
2168 if (!aff)
2169 return NULL;
2170 if (isl_aff_is_nan(aff)) {
2171 isl_space *space = isl_aff_get_domain_space(aff);
2172 isl_aff_free(aff);
2173 return isl_basic_set_empty(space);
2175 if (rational)
2176 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
2177 "rational sets not supported", goto error);
2179 ineq = isl_inequality_from_aff(aff);
2180 c = isl_constraint_get_constant_val(ineq);
2181 c = isl_val_sub_ui(c, 1);
2182 ineq = isl_constraint_set_constant_val(ineq, c);
2184 bset = isl_basic_set_from_constraint(ineq);
2185 bset = isl_basic_set_simplify(bset);
2186 return bset;
2187 error:
2188 isl_aff_free(aff);
2189 return NULL;
2192 /* Return a basic set containing those elements in the space
2193 * of aff where it is non-negative.
2194 * If "rational" is set, then return a rational basic set.
2196 * If "aff" is NaN, then it is not non-negative (it's not negative either).
2198 static __isl_give isl_basic_set *aff_nonneg_basic_set(
2199 __isl_take isl_aff *aff, int rational, void *user)
2201 isl_constraint *ineq;
2202 isl_basic_set *bset;
2204 if (!aff)
2205 return NULL;
2206 if (isl_aff_is_nan(aff)) {
2207 isl_space *space = isl_aff_get_domain_space(aff);
2208 isl_aff_free(aff);
2209 return isl_basic_set_empty(space);
2212 ineq = isl_inequality_from_aff(aff);
2214 bset = isl_basic_set_from_constraint(ineq);
2215 if (rational)
2216 bset = isl_basic_set_set_rational(bset);
2217 bset = isl_basic_set_simplify(bset);
2218 return bset;
2221 /* Return a basic set containing those elements in the space
2222 * of aff where it is non-negative.
2224 __isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff)
2226 return aff_nonneg_basic_set(aff, 0, NULL);
2229 /* Return a basic set containing those elements in the domain space
2230 * of "aff" where it is positive.
2232 __isl_give isl_basic_set *isl_aff_pos_basic_set(__isl_take isl_aff *aff)
2234 aff = isl_aff_add_constant_num_si(aff, -1);
2235 return isl_aff_nonneg_basic_set(aff);
2238 /* Return a basic set containing those elements in the domain space
2239 * of aff where it is negative.
2241 __isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff)
2243 aff = isl_aff_neg(aff);
2244 return isl_aff_pos_basic_set(aff);
2247 /* Return a basic set containing those elements in the space
2248 * of aff where it is zero.
2249 * If "rational" is set, then return a rational basic set.
2251 * If "aff" is NaN, then it is not zero.
2253 static __isl_give isl_basic_set *aff_zero_basic_set(__isl_take isl_aff *aff,
2254 int rational, void *user)
2256 isl_constraint *ineq;
2257 isl_basic_set *bset;
2259 if (!aff)
2260 return NULL;
2261 if (isl_aff_is_nan(aff)) {
2262 isl_space *space = isl_aff_get_domain_space(aff);
2263 isl_aff_free(aff);
2264 return isl_basic_set_empty(space);
2267 ineq = isl_equality_from_aff(aff);
2269 bset = isl_basic_set_from_constraint(ineq);
2270 if (rational)
2271 bset = isl_basic_set_set_rational(bset);
2272 bset = isl_basic_set_simplify(bset);
2273 return bset;
2276 /* Return a basic set containing those elements in the space
2277 * of aff where it is zero.
2279 __isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff)
2281 return aff_zero_basic_set(aff, 0, NULL);
2284 /* Return a basic set containing those elements in the shared space
2285 * of aff1 and aff2 where aff1 is greater than or equal to aff2.
2287 __isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1,
2288 __isl_take isl_aff *aff2)
2290 aff1 = isl_aff_sub(aff1, aff2);
2292 return isl_aff_nonneg_basic_set(aff1);
2295 /* Return a basic set containing those elements in the shared domain space
2296 * of "aff1" and "aff2" where "aff1" is greater than "aff2".
2298 __isl_give isl_basic_set *isl_aff_gt_basic_set(__isl_take isl_aff *aff1,
2299 __isl_take isl_aff *aff2)
2301 aff1 = isl_aff_sub(aff1, aff2);
2303 return isl_aff_pos_basic_set(aff1);
2306 /* Return a set containing those elements in the shared space
2307 * of aff1 and aff2 where aff1 is greater than or equal to aff2.
2309 __isl_give isl_set *isl_aff_ge_set(__isl_take isl_aff *aff1,
2310 __isl_take isl_aff *aff2)
2312 return isl_set_from_basic_set(isl_aff_ge_basic_set(aff1, aff2));
2315 /* Return a set containing those elements in the shared domain space
2316 * of aff1 and aff2 where aff1 is greater than aff2.
2318 * If either of the two inputs is NaN, then the result is empty,
2319 * as comparisons with NaN always return false.
2321 __isl_give isl_set *isl_aff_gt_set(__isl_take isl_aff *aff1,
2322 __isl_take isl_aff *aff2)
2324 return isl_set_from_basic_set(isl_aff_gt_basic_set(aff1, aff2));
2327 /* Return a basic set containing those elements in the shared space
2328 * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
2330 __isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1,
2331 __isl_take isl_aff *aff2)
2333 return isl_aff_ge_basic_set(aff2, aff1);
2336 /* Return a basic set containing those elements in the shared domain space
2337 * of "aff1" and "aff2" where "aff1" is smaller than "aff2".
2339 __isl_give isl_basic_set *isl_aff_lt_basic_set(__isl_take isl_aff *aff1,
2340 __isl_take isl_aff *aff2)
2342 return isl_aff_gt_basic_set(aff2, aff1);
2345 /* Return a set containing those elements in the shared space
2346 * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
2348 __isl_give isl_set *isl_aff_le_set(__isl_take isl_aff *aff1,
2349 __isl_take isl_aff *aff2)
2351 return isl_aff_ge_set(aff2, aff1);
2354 /* Return a set containing those elements in the shared domain space
2355 * of "aff1" and "aff2" where "aff1" is smaller than "aff2".
2357 __isl_give isl_set *isl_aff_lt_set(__isl_take isl_aff *aff1,
2358 __isl_take isl_aff *aff2)
2360 return isl_set_from_basic_set(isl_aff_lt_basic_set(aff1, aff2));
2363 /* Return a basic set containing those elements in the shared space
2364 * of aff1 and aff2 where aff1 and aff2 are equal.
2366 __isl_give isl_basic_set *isl_aff_eq_basic_set(__isl_take isl_aff *aff1,
2367 __isl_take isl_aff *aff2)
2369 aff1 = isl_aff_sub(aff1, aff2);
2371 return isl_aff_zero_basic_set(aff1);
2374 /* Return a set containing those elements in the shared space
2375 * of aff1 and aff2 where aff1 and aff2 are equal.
2377 __isl_give isl_set *isl_aff_eq_set(__isl_take isl_aff *aff1,
2378 __isl_take isl_aff *aff2)
2380 return isl_set_from_basic_set(isl_aff_eq_basic_set(aff1, aff2));
2383 /* Return a set containing those elements in the shared domain space
2384 * of aff1 and aff2 where aff1 and aff2 are not equal.
2386 * If either of the two inputs is NaN, then the result is empty,
2387 * as comparisons with NaN always return false.
2389 __isl_give isl_set *isl_aff_ne_set(__isl_take isl_aff *aff1,
2390 __isl_take isl_aff *aff2)
2392 isl_set *set_lt, *set_gt;
2394 set_lt = isl_aff_lt_set(isl_aff_copy(aff1),
2395 isl_aff_copy(aff2));
2396 set_gt = isl_aff_gt_set(aff1, aff2);
2397 return isl_set_union_disjoint(set_lt, set_gt);
2400 __isl_give isl_aff *isl_aff_add_on_domain(__isl_keep isl_set *dom,
2401 __isl_take isl_aff *aff1, __isl_take isl_aff *aff2)
2403 aff1 = isl_aff_add(aff1, aff2);
2404 aff1 = isl_aff_gist(aff1, isl_set_copy(dom));
2405 return aff1;
2408 int isl_aff_is_empty(__isl_keep isl_aff *aff)
2410 if (!aff)
2411 return -1;
2413 return 0;
2416 #undef TYPE
2417 #define TYPE isl_aff
2418 static
2419 #include "check_type_range_templ.c"
2421 /* Check whether the given affine expression has non-zero coefficient
2422 * for any dimension in the given range or if any of these dimensions
2423 * appear with non-zero coefficients in any of the integer divisions
2424 * involved in the affine expression.
2426 isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff,
2427 enum isl_dim_type type, unsigned first, unsigned n)
2429 int i;
2430 int *active = NULL;
2431 isl_bool involves = isl_bool_false;
2433 if (!aff)
2434 return isl_bool_error;
2435 if (n == 0)
2436 return isl_bool_false;
2437 if (isl_aff_check_range(aff, type, first, n) < 0)
2438 return isl_bool_error;
2440 active = isl_local_space_get_active(aff->ls, aff->v->el + 2);
2441 if (!active)
2442 goto error;
2444 first += isl_local_space_offset(aff->ls, type) - 1;
2445 for (i = 0; i < n; ++i)
2446 if (active[first + i]) {
2447 involves = isl_bool_true;
2448 break;
2451 free(active);
2453 return involves;
2454 error:
2455 free(active);
2456 return isl_bool_error;
2459 __isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
2460 enum isl_dim_type type, unsigned first, unsigned n)
2462 isl_ctx *ctx;
2464 if (!aff)
2465 return NULL;
2466 if (type == isl_dim_out)
2467 isl_die(aff->v->ctx, isl_error_invalid,
2468 "cannot drop output/set dimension",
2469 return isl_aff_free(aff));
2470 if (type == isl_dim_in)
2471 type = isl_dim_set;
2472 if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
2473 return aff;
2475 ctx = isl_aff_get_ctx(aff);
2476 if (isl_local_space_check_range(aff->ls, type, first, n) < 0)
2477 return isl_aff_free(aff);
2479 aff = isl_aff_cow(aff);
2480 if (!aff)
2481 return NULL;
2483 aff->ls = isl_local_space_drop_dims(aff->ls, type, first, n);
2484 if (!aff->ls)
2485 return isl_aff_free(aff);
2487 first += 1 + isl_local_space_offset(aff->ls, type);
2488 aff->v = isl_vec_drop_els(aff->v, first, n);
2489 if (!aff->v)
2490 return isl_aff_free(aff);
2492 return aff;
2495 /* Drop the "n" domain dimensions starting at "first" from "aff",
2496 * after checking that they do not appear in the affine expression.
2498 static __isl_give isl_aff *drop_domain(__isl_take isl_aff *aff, unsigned first,
2499 unsigned n)
2501 isl_bool involves;
2503 involves = isl_aff_involves_dims(aff, isl_dim_in, first, n);
2504 if (involves < 0)
2505 return isl_aff_free(aff);
2506 if (involves)
2507 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2508 "affine expression involves some of the domain dimensions",
2509 return isl_aff_free(aff));
2510 return isl_aff_drop_dims(aff, isl_dim_in, first, n);
2513 /* Project the domain of the affine expression onto its parameter space.
2514 * The affine expression may not involve any of the domain dimensions.
2516 __isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff)
2518 isl_space *space;
2519 isl_size n;
2521 n = isl_aff_dim(aff, isl_dim_in);
2522 if (n < 0)
2523 return isl_aff_free(aff);
2524 aff = drop_domain(aff, 0, n);
2525 space = isl_aff_get_domain_space(aff);
2526 space = isl_space_params(space);
2527 aff = isl_aff_reset_domain_space(aff, space);
2528 return aff;
2531 /* Check that the domain of "aff" is a product.
2533 static isl_stat check_domain_product(__isl_keep isl_aff *aff)
2535 isl_bool is_product;
2537 is_product = isl_space_is_product(isl_aff_peek_domain_space(aff));
2538 if (is_product < 0)
2539 return isl_stat_error;
2540 if (!is_product)
2541 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2542 "domain is not a product", return isl_stat_error);
2543 return isl_stat_ok;
2546 /* Given an affine function with a domain of the form [A -> B] that
2547 * does not depend on B, return the same function on domain A.
2549 __isl_give isl_aff *isl_aff_domain_factor_domain(__isl_take isl_aff *aff)
2551 isl_space *space;
2552 isl_size n, n_in;
2554 if (check_domain_product(aff) < 0)
2555 return isl_aff_free(aff);
2556 space = isl_aff_get_domain_space(aff);
2557 n = isl_space_dim(space, isl_dim_set);
2558 space = isl_space_factor_domain(space);
2559 n_in = isl_space_dim(space, isl_dim_set);
2560 if (n < 0 || n_in < 0)
2561 aff = isl_aff_free(aff);
2562 else
2563 aff = drop_domain(aff, n_in, n - n_in);
2564 aff = isl_aff_reset_domain_space(aff, space);
2565 return aff;
2568 /* Convert an affine expression defined over a parameter domain
2569 * into one that is defined over a zero-dimensional set.
2571 __isl_give isl_aff *isl_aff_from_range(__isl_take isl_aff *aff)
2573 isl_local_space *ls;
2575 ls = isl_aff_take_domain_local_space(aff);
2576 ls = isl_local_space_set_from_params(ls);
2577 aff = isl_aff_restore_domain_local_space(aff, ls);
2579 return aff;
2582 __isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
2583 enum isl_dim_type type, unsigned first, unsigned n)
2585 isl_ctx *ctx;
2587 if (!aff)
2588 return NULL;
2589 if (type == isl_dim_out)
2590 isl_die(aff->v->ctx, isl_error_invalid,
2591 "cannot insert output/set dimensions",
2592 return isl_aff_free(aff));
2593 if (type == isl_dim_in)
2594 type = isl_dim_set;
2595 if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
2596 return aff;
2598 ctx = isl_aff_get_ctx(aff);
2599 if (isl_local_space_check_range(aff->ls, type, first, 0) < 0)
2600 return isl_aff_free(aff);
2602 aff = isl_aff_cow(aff);
2603 if (!aff)
2604 return NULL;
2606 aff->ls = isl_local_space_insert_dims(aff->ls, type, first, n);
2607 if (!aff->ls)
2608 return isl_aff_free(aff);
2610 first += 1 + isl_local_space_offset(aff->ls, type);
2611 aff->v = isl_vec_insert_zero_els(aff->v, first, n);
2612 if (!aff->v)
2613 return isl_aff_free(aff);
2615 return aff;
2618 __isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
2619 enum isl_dim_type type, unsigned n)
2621 isl_size pos;
2623 pos = isl_aff_dim(aff, type);
2624 if (pos < 0)
2625 return isl_aff_free(aff);
2627 return isl_aff_insert_dims(aff, type, pos, n);
2630 __isl_give isl_pw_aff *isl_pw_aff_add_dims(__isl_take isl_pw_aff *pwaff,
2631 enum isl_dim_type type, unsigned n)
2633 isl_size pos;
2635 pos = isl_pw_aff_dim(pwaff, type);
2636 if (pos < 0)
2637 return isl_pw_aff_free(pwaff);
2639 return isl_pw_aff_insert_dims(pwaff, type, pos, n);
2642 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "aff"
2643 * to dimensions of "dst_type" at "dst_pos".
2645 * We only support moving input dimensions to parameters and vice versa.
2647 __isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
2648 enum isl_dim_type dst_type, unsigned dst_pos,
2649 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
2651 unsigned g_dst_pos;
2652 unsigned g_src_pos;
2654 if (!aff)
2655 return NULL;
2656 if (n == 0 &&
2657 !isl_local_space_is_named_or_nested(aff->ls, src_type) &&
2658 !isl_local_space_is_named_or_nested(aff->ls, dst_type))
2659 return aff;
2661 if (dst_type == isl_dim_out || src_type == isl_dim_out)
2662 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2663 "cannot move output/set dimension",
2664 return isl_aff_free(aff));
2665 if (dst_type == isl_dim_div || src_type == isl_dim_div)
2666 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
2667 "cannot move divs", return isl_aff_free(aff));
2668 if (dst_type == isl_dim_in)
2669 dst_type = isl_dim_set;
2670 if (src_type == isl_dim_in)
2671 src_type = isl_dim_set;
2673 if (isl_local_space_check_range(aff->ls, src_type, src_pos, n) < 0)
2674 return isl_aff_free(aff);
2675 if (dst_type == src_type)
2676 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
2677 "moving dims within the same type not supported",
2678 return isl_aff_free(aff));
2680 aff = isl_aff_cow(aff);
2681 if (!aff)
2682 return NULL;
2684 g_src_pos = 1 + isl_local_space_offset(aff->ls, src_type) + src_pos;
2685 g_dst_pos = 1 + isl_local_space_offset(aff->ls, dst_type) + dst_pos;
2686 if (dst_type > src_type)
2687 g_dst_pos -= n;
2689 aff->v = isl_vec_move_els(aff->v, g_dst_pos, g_src_pos, n);
2690 aff->ls = isl_local_space_move_dims(aff->ls, dst_type, dst_pos,
2691 src_type, src_pos, n);
2692 if (!aff->v || !aff->ls)
2693 return isl_aff_free(aff);
2695 aff = sort_divs(aff);
2697 return aff;
2700 __isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
2702 isl_set *dom = isl_set_universe(isl_aff_get_domain_space(aff));
2703 return isl_pw_aff_alloc(dom, aff);
2706 #define isl_aff_involves_nan isl_aff_is_nan
2708 #undef PW
2709 #define PW isl_pw_aff
2710 #undef EL
2711 #define EL isl_aff
2712 #undef EL_IS_ZERO
2713 #define EL_IS_ZERO is_empty
2714 #undef ZERO
2715 #define ZERO empty
2716 #undef IS_ZERO
2717 #define IS_ZERO is_empty
2718 #undef FIELD
2719 #define FIELD aff
2720 #undef DEFAULT_IS_ZERO
2721 #define DEFAULT_IS_ZERO 0
2723 #define NO_OPT
2724 #define NO_LIFT
2725 #define NO_MORPH
2727 #include <isl_pw_templ.c>
2728 #include <isl_pw_bind_domain_templ.c>
2729 #include <isl_pw_eval.c>
2730 #include <isl_pw_hash.c>
2731 #include <isl_pw_union_opt.c>
2733 #undef BASE
2734 #define BASE pw_aff
2736 #include <isl_union_single.c>
2737 #include <isl_union_neg.c>
2739 static __isl_give isl_set *align_params_pw_pw_set_and(
2740 __isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2,
2741 __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
2742 __isl_take isl_pw_aff *pwaff2))
2744 isl_bool equal_params;
2746 if (!pwaff1 || !pwaff2)
2747 goto error;
2748 equal_params = isl_space_has_equal_params(pwaff1->dim, pwaff2->dim);
2749 if (equal_params < 0)
2750 goto error;
2751 if (equal_params)
2752 return fn(pwaff1, pwaff2);
2753 if (isl_pw_aff_check_named_params(pwaff1) < 0 ||
2754 isl_pw_aff_check_named_params(pwaff2) < 0)
2755 goto error;
2756 pwaff1 = isl_pw_aff_align_params(pwaff1, isl_pw_aff_get_space(pwaff2));
2757 pwaff2 = isl_pw_aff_align_params(pwaff2, isl_pw_aff_get_space(pwaff1));
2758 return fn(pwaff1, pwaff2);
2759 error:
2760 isl_pw_aff_free(pwaff1);
2761 isl_pw_aff_free(pwaff2);
2762 return NULL;
2765 /* Align the parameters of the to isl_pw_aff arguments and
2766 * then apply a function "fn" on them that returns an isl_map.
2768 static __isl_give isl_map *align_params_pw_pw_map_and(
2769 __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
2770 __isl_give isl_map *(*fn)(__isl_take isl_pw_aff *pa1,
2771 __isl_take isl_pw_aff *pa2))
2773 isl_bool equal_params;
2775 if (!pa1 || !pa2)
2776 goto error;
2777 equal_params = isl_space_has_equal_params(pa1->dim, pa2->dim);
2778 if (equal_params < 0)
2779 goto error;
2780 if (equal_params)
2781 return fn(pa1, pa2);
2782 if (isl_pw_aff_check_named_params(pa1) < 0 ||
2783 isl_pw_aff_check_named_params(pa2) < 0)
2784 goto error;
2785 pa1 = isl_pw_aff_align_params(pa1, isl_pw_aff_get_space(pa2));
2786 pa2 = isl_pw_aff_align_params(pa2, isl_pw_aff_get_space(pa1));
2787 return fn(pa1, pa2);
2788 error:
2789 isl_pw_aff_free(pa1);
2790 isl_pw_aff_free(pa2);
2791 return NULL;
2794 /* Compute a piecewise quasi-affine expression with a domain that
2795 * is the union of those of pwaff1 and pwaff2 and such that on each
2796 * cell, the quasi-affine expression is the maximum of those of pwaff1
2797 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
2798 * cell, then the associated expression is the defined one.
2800 static __isl_give isl_pw_aff *pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
2801 __isl_take isl_pw_aff *pwaff2)
2803 return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_ge_set);
2806 __isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
2807 __isl_take isl_pw_aff *pwaff2)
2809 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
2810 &pw_aff_union_max);
2813 /* Compute a piecewise quasi-affine expression with a domain that
2814 * is the union of those of pwaff1 and pwaff2 and such that on each
2815 * cell, the quasi-affine expression is the minimum of those of pwaff1
2816 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
2817 * cell, then the associated expression is the defined one.
2819 static __isl_give isl_pw_aff *pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
2820 __isl_take isl_pw_aff *pwaff2)
2822 return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_le_set);
2825 __isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
2826 __isl_take isl_pw_aff *pwaff2)
2828 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
2829 &pw_aff_union_min);
2832 __isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
2833 __isl_take isl_pw_aff *pwaff2, int max)
2835 if (max)
2836 return isl_pw_aff_union_max(pwaff1, pwaff2);
2837 else
2838 return isl_pw_aff_union_min(pwaff1, pwaff2);
2841 /* Return a set containing those elements in the domain
2842 * of "pwaff" where it satisfies "fn" (if complement is 0) or
2843 * does not satisfy "fn" (if complement is 1).
2845 * The pieces with a NaN never belong to the result since
2846 * NaN does not satisfy any property.
2848 static __isl_give isl_set *pw_aff_locus(__isl_take isl_pw_aff *pwaff,
2849 __isl_give isl_basic_set *(*fn)(__isl_take isl_aff *aff, int rational,
2850 void *user),
2851 int complement, void *user)
2853 int i;
2854 isl_set *set;
2856 if (!pwaff)
2857 return NULL;
2859 set = isl_set_empty(isl_pw_aff_get_domain_space(pwaff));
2861 for (i = 0; i < pwaff->n; ++i) {
2862 isl_basic_set *bset;
2863 isl_set *set_i, *locus;
2864 isl_bool rational;
2866 if (isl_aff_is_nan(pwaff->p[i].aff))
2867 continue;
2869 rational = isl_set_has_rational(pwaff->p[i].set);
2870 bset = fn(isl_aff_copy(pwaff->p[i].aff), rational, user);
2871 locus = isl_set_from_basic_set(bset);
2872 set_i = isl_set_copy(pwaff->p[i].set);
2873 if (complement)
2874 set_i = isl_set_subtract(set_i, locus);
2875 else
2876 set_i = isl_set_intersect(set_i, locus);
2877 set = isl_set_union_disjoint(set, set_i);
2880 isl_pw_aff_free(pwaff);
2882 return set;
2885 /* Return a set containing those elements in the domain
2886 * of "pa" where it is positive.
2888 __isl_give isl_set *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa)
2890 return pw_aff_locus(pa, &aff_pos_basic_set, 0, NULL);
2893 /* Return a set containing those elements in the domain
2894 * of pwaff where it is non-negative.
2896 __isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff)
2898 return pw_aff_locus(pwaff, &aff_nonneg_basic_set, 0, NULL);
2901 /* Return a set containing those elements in the domain
2902 * of pwaff where it is zero.
2904 __isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff)
2906 return pw_aff_locus(pwaff, &aff_zero_basic_set, 0, NULL);
2909 /* Return a set containing those elements in the domain
2910 * of pwaff where it is not zero.
2912 __isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff)
2914 return pw_aff_locus(pwaff, &aff_zero_basic_set, 1, NULL);
2917 /* Bind the affine function "aff" to the parameter "id",
2918 * returning the elements in the domain where the affine expression
2919 * is equal to the parameter.
2921 __isl_give isl_basic_set *isl_aff_bind_id(__isl_take isl_aff *aff,
2922 __isl_take isl_id *id)
2924 isl_space *space;
2925 isl_aff *aff_id;
2927 space = isl_aff_get_domain_space(aff);
2928 space = isl_space_add_param_id(space, isl_id_copy(id));
2930 aff = isl_aff_align_params(aff, isl_space_copy(space));
2931 aff_id = isl_aff_param_on_domain_space_id(space, id);
2933 return isl_aff_eq_basic_set(aff, aff_id);
2936 /* Wrapper around isl_aff_bind_id for use as pw_aff_locus callback.
2937 * "rational" should not be set.
2939 static __isl_give isl_basic_set *aff_bind_id(__isl_take isl_aff *aff,
2940 int rational, void *user)
2942 isl_id *id = user;
2944 if (!aff)
2945 return NULL;
2946 if (rational)
2947 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
2948 "rational binding not supported", goto error);
2949 return isl_aff_bind_id(aff, isl_id_copy(id));
2950 error:
2951 isl_aff_free(aff);
2952 return NULL;
2955 /* Bind the piecewise affine function "pa" to the parameter "id",
2956 * returning the elements in the domain where the expression
2957 * is equal to the parameter.
2959 __isl_give isl_set *isl_pw_aff_bind_id(__isl_take isl_pw_aff *pa,
2960 __isl_take isl_id *id)
2962 isl_set *bound;
2964 bound = pw_aff_locus(pa, &aff_bind_id, 0, id);
2965 isl_id_free(id);
2967 return bound;
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 * We compute the difference on the shared domain and then construct
2974 * the set of values where this difference is non-negative.
2975 * If strict is set, we first subtract 1 from the difference.
2976 * If equal is set, we only return the elements where pwaff1 and pwaff2
2977 * are equal.
2979 static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1,
2980 __isl_take isl_pw_aff *pwaff2, int strict, int equal)
2982 isl_set *set1, *set2;
2984 set1 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff1));
2985 set2 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff2));
2986 set1 = isl_set_intersect(set1, set2);
2987 pwaff1 = isl_pw_aff_intersect_domain(pwaff1, isl_set_copy(set1));
2988 pwaff2 = isl_pw_aff_intersect_domain(pwaff2, isl_set_copy(set1));
2989 pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_neg(pwaff2));
2991 if (strict) {
2992 isl_space *space = isl_set_get_space(set1);
2993 isl_aff *aff;
2994 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
2995 aff = isl_aff_add_constant_si(aff, -1);
2996 pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_alloc(set1, aff));
2997 } else
2998 isl_set_free(set1);
3000 if (equal)
3001 return isl_pw_aff_zero_set(pwaff1);
3002 return isl_pw_aff_nonneg_set(pwaff1);
3005 /* Return a set containing those elements in the shared domain
3006 * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2.
3008 static __isl_give isl_set *pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
3009 __isl_take isl_pw_aff *pwaff2)
3011 return pw_aff_gte_set(pwaff1, pwaff2, 0, 1);
3014 __isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
3015 __isl_take isl_pw_aff *pwaff2)
3017 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_eq_set);
3020 /* Return a set containing those elements in the shared domain
3021 * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2.
3023 static __isl_give isl_set *pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
3024 __isl_take isl_pw_aff *pwaff2)
3026 return pw_aff_gte_set(pwaff1, pwaff2, 0, 0);
3029 __isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
3030 __isl_take isl_pw_aff *pwaff2)
3032 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ge_set);
3035 /* Return a set containing those elements in the shared domain
3036 * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2.
3038 static __isl_give isl_set *pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
3039 __isl_take isl_pw_aff *pwaff2)
3041 return pw_aff_gte_set(pwaff1, pwaff2, 1, 0);
3044 __isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
3045 __isl_take isl_pw_aff *pwaff2)
3047 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_gt_set);
3050 __isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
3051 __isl_take isl_pw_aff *pwaff2)
3053 return isl_pw_aff_ge_set(pwaff2, pwaff1);
3056 __isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
3057 __isl_take isl_pw_aff *pwaff2)
3059 return isl_pw_aff_gt_set(pwaff2, pwaff1);
3062 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3063 * where the function values are ordered in the same way as "order",
3064 * which returns a set in the shared domain of its two arguments.
3065 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3067 * Let "pa1" and "pa2" be defined on domains A and B respectively.
3068 * We first pull back the two functions such that they are defined on
3069 * the domain [A -> B]. Then we apply "order", resulting in a set
3070 * in the space [A -> B]. Finally, we unwrap this set to obtain
3071 * a map in the space A -> B.
3073 static __isl_give isl_map *isl_pw_aff_order_map_aligned(
3074 __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
3075 __isl_give isl_set *(*order)(__isl_take isl_pw_aff *pa1,
3076 __isl_take isl_pw_aff *pa2))
3078 isl_space *space1, *space2;
3079 isl_multi_aff *ma;
3080 isl_set *set;
3082 space1 = isl_space_domain(isl_pw_aff_get_space(pa1));
3083 space2 = isl_space_domain(isl_pw_aff_get_space(pa2));
3084 space1 = isl_space_map_from_domain_and_range(space1, space2);
3085 ma = isl_multi_aff_domain_map(isl_space_copy(space1));
3086 pa1 = isl_pw_aff_pullback_multi_aff(pa1, ma);
3087 ma = isl_multi_aff_range_map(space1);
3088 pa2 = isl_pw_aff_pullback_multi_aff(pa2, ma);
3089 set = order(pa1, pa2);
3091 return isl_set_unwrap(set);
3094 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3095 * where the function values are equal.
3096 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3098 static __isl_give isl_map *isl_pw_aff_eq_map_aligned(__isl_take isl_pw_aff *pa1,
3099 __isl_take isl_pw_aff *pa2)
3101 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_eq_set);
3104 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3105 * where the function values are equal.
3107 __isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1,
3108 __isl_take isl_pw_aff *pa2)
3110 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_eq_map_aligned);
3113 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3114 * where the function value of "pa1" is less than the function value of "pa2".
3115 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3117 static __isl_give isl_map *isl_pw_aff_lt_map_aligned(__isl_take isl_pw_aff *pa1,
3118 __isl_take isl_pw_aff *pa2)
3120 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_lt_set);
3123 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3124 * where the function value of "pa1" is less than the function value of "pa2".
3126 __isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1,
3127 __isl_take isl_pw_aff *pa2)
3129 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_lt_map_aligned);
3132 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3133 * where the function value of "pa1" is greater than the function value
3134 * of "pa2".
3135 * The parameters of "pa1" and "pa2" are assumed to have been aligned.
3137 static __isl_give isl_map *isl_pw_aff_gt_map_aligned(__isl_take isl_pw_aff *pa1,
3138 __isl_take isl_pw_aff *pa2)
3140 return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_gt_set);
3143 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3144 * where the function value of "pa1" is greater than the function value
3145 * of "pa2".
3147 __isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1,
3148 __isl_take isl_pw_aff *pa2)
3150 return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_gt_map_aligned);
3153 /* Return a set containing those elements in the shared domain
3154 * of the elements of list1 and list2 where each element in list1
3155 * has the relation specified by "fn" with each element in list2.
3157 static __isl_give isl_set *pw_aff_list_set(__isl_take isl_pw_aff_list *list1,
3158 __isl_take isl_pw_aff_list *list2,
3159 __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
3160 __isl_take isl_pw_aff *pwaff2))
3162 int i, j;
3163 isl_ctx *ctx;
3164 isl_set *set;
3166 if (!list1 || !list2)
3167 goto error;
3169 ctx = isl_pw_aff_list_get_ctx(list1);
3170 if (list1->n < 1 || list2->n < 1)
3171 isl_die(ctx, isl_error_invalid,
3172 "list should contain at least one element", goto error);
3174 set = isl_set_universe(isl_pw_aff_get_domain_space(list1->p[0]));
3175 for (i = 0; i < list1->n; ++i)
3176 for (j = 0; j < list2->n; ++j) {
3177 isl_set *set_ij;
3179 set_ij = fn(isl_pw_aff_copy(list1->p[i]),
3180 isl_pw_aff_copy(list2->p[j]));
3181 set = isl_set_intersect(set, set_ij);
3184 isl_pw_aff_list_free(list1);
3185 isl_pw_aff_list_free(list2);
3186 return set;
3187 error:
3188 isl_pw_aff_list_free(list1);
3189 isl_pw_aff_list_free(list2);
3190 return NULL;
3193 /* Return a set containing those elements in the shared domain
3194 * of the elements of list1 and list2 where each element in list1
3195 * is equal to each element in list2.
3197 __isl_give isl_set *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1,
3198 __isl_take isl_pw_aff_list *list2)
3200 return pw_aff_list_set(list1, list2, &isl_pw_aff_eq_set);
3203 __isl_give isl_set *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1,
3204 __isl_take isl_pw_aff_list *list2)
3206 return pw_aff_list_set(list1, list2, &isl_pw_aff_ne_set);
3209 /* Return a set containing those elements in the shared domain
3210 * of the elements of list1 and list2 where each element in list1
3211 * is less than or equal to each element in list2.
3213 __isl_give isl_set *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1,
3214 __isl_take isl_pw_aff_list *list2)
3216 return pw_aff_list_set(list1, list2, &isl_pw_aff_le_set);
3219 __isl_give isl_set *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1,
3220 __isl_take isl_pw_aff_list *list2)
3222 return pw_aff_list_set(list1, list2, &isl_pw_aff_lt_set);
3225 __isl_give isl_set *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1,
3226 __isl_take isl_pw_aff_list *list2)
3228 return pw_aff_list_set(list1, list2, &isl_pw_aff_ge_set);
3231 __isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1,
3232 __isl_take isl_pw_aff_list *list2)
3234 return pw_aff_list_set(list1, list2, &isl_pw_aff_gt_set);
3238 /* Return a set containing those elements in the shared domain
3239 * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2.
3241 static __isl_give isl_set *pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
3242 __isl_take isl_pw_aff *pwaff2)
3244 isl_set *set_lt, *set_gt;
3246 set_lt = isl_pw_aff_lt_set(isl_pw_aff_copy(pwaff1),
3247 isl_pw_aff_copy(pwaff2));
3248 set_gt = isl_pw_aff_gt_set(pwaff1, pwaff2);
3249 return isl_set_union_disjoint(set_lt, set_gt);
3252 __isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
3253 __isl_take isl_pw_aff *pwaff2)
3255 return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ne_set);
3258 __isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
3259 isl_int v)
3261 int i;
3263 if (isl_int_is_one(v))
3264 return pwaff;
3265 if (!isl_int_is_pos(v))
3266 isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
3267 "factor needs to be positive",
3268 return isl_pw_aff_free(pwaff));
3269 pwaff = isl_pw_aff_cow(pwaff);
3270 if (!pwaff)
3271 return NULL;
3272 if (pwaff->n == 0)
3273 return pwaff;
3275 for (i = 0; i < pwaff->n; ++i) {
3276 pwaff->p[i].aff = isl_aff_scale_down(pwaff->p[i].aff, v);
3277 if (!pwaff->p[i].aff)
3278 return isl_pw_aff_free(pwaff);
3281 return pwaff;
3284 __isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff)
3286 int i;
3288 pwaff = isl_pw_aff_cow(pwaff);
3289 if (!pwaff)
3290 return NULL;
3291 if (pwaff->n == 0)
3292 return pwaff;
3294 for (i = 0; i < pwaff->n; ++i) {
3295 pwaff->p[i].aff = isl_aff_floor(pwaff->p[i].aff);
3296 if (!pwaff->p[i].aff)
3297 return isl_pw_aff_free(pwaff);
3300 return pwaff;
3303 __isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff)
3305 int i;
3307 pwaff = isl_pw_aff_cow(pwaff);
3308 if (!pwaff)
3309 return NULL;
3310 if (pwaff->n == 0)
3311 return pwaff;
3313 for (i = 0; i < pwaff->n; ++i) {
3314 pwaff->p[i].aff = isl_aff_ceil(pwaff->p[i].aff);
3315 if (!pwaff->p[i].aff)
3316 return isl_pw_aff_free(pwaff);
3319 return pwaff;
3322 /* Assuming that "cond1" and "cond2" are disjoint,
3323 * return an affine expression that is equal to pwaff1 on cond1
3324 * and to pwaff2 on cond2.
3326 static __isl_give isl_pw_aff *isl_pw_aff_select(
3327 __isl_take isl_set *cond1, __isl_take isl_pw_aff *pwaff1,
3328 __isl_take isl_set *cond2, __isl_take isl_pw_aff *pwaff2)
3330 pwaff1 = isl_pw_aff_intersect_domain(pwaff1, cond1);
3331 pwaff2 = isl_pw_aff_intersect_domain(pwaff2, cond2);
3333 return isl_pw_aff_add_disjoint(pwaff1, pwaff2);
3336 /* Return an affine expression that is equal to pwaff_true for elements
3337 * where "cond" is non-zero and to pwaff_false for elements where "cond"
3338 * is zero.
3339 * That is, return cond ? pwaff_true : pwaff_false;
3341 * If "cond" involves and NaN, then we conservatively return a NaN
3342 * on its entire domain. In principle, we could consider the pieces
3343 * where it is NaN separately from those where it is not.
3345 * If "pwaff_true" and "pwaff_false" are obviously equal to each other,
3346 * then only use the domain of "cond" to restrict the domain.
3348 __isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond,
3349 __isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false)
3351 isl_set *cond_true, *cond_false;
3352 isl_bool equal;
3354 if (!cond)
3355 goto error;
3356 if (isl_pw_aff_involves_nan(cond)) {
3357 isl_space *space = isl_pw_aff_get_domain_space(cond);
3358 isl_local_space *ls = isl_local_space_from_space(space);
3359 isl_pw_aff_free(cond);
3360 isl_pw_aff_free(pwaff_true);
3361 isl_pw_aff_free(pwaff_false);
3362 return isl_pw_aff_nan_on_domain(ls);
3365 pwaff_true = isl_pw_aff_align_params(pwaff_true,
3366 isl_pw_aff_get_space(pwaff_false));
3367 pwaff_false = isl_pw_aff_align_params(pwaff_false,
3368 isl_pw_aff_get_space(pwaff_true));
3369 equal = isl_pw_aff_plain_is_equal(pwaff_true, pwaff_false);
3370 if (equal < 0)
3371 goto error;
3372 if (equal) {
3373 isl_set *dom;
3375 dom = isl_set_coalesce(isl_pw_aff_domain(cond));
3376 isl_pw_aff_free(pwaff_false);
3377 return isl_pw_aff_intersect_domain(pwaff_true, dom);
3380 cond_true = isl_pw_aff_non_zero_set(isl_pw_aff_copy(cond));
3381 cond_false = isl_pw_aff_zero_set(cond);
3382 return isl_pw_aff_select(cond_true, pwaff_true,
3383 cond_false, pwaff_false);
3384 error:
3385 isl_pw_aff_free(cond);
3386 isl_pw_aff_free(pwaff_true);
3387 isl_pw_aff_free(pwaff_false);
3388 return NULL;
3391 isl_bool isl_aff_is_cst(__isl_keep isl_aff *aff)
3393 int pos;
3395 if (!aff)
3396 return isl_bool_error;
3398 pos = isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2);
3399 return isl_bool_ok(pos == -1);
3402 /* Check whether pwaff is a piecewise constant.
3404 isl_bool isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff)
3406 int i;
3408 if (!pwaff)
3409 return isl_bool_error;
3411 for (i = 0; i < pwaff->n; ++i) {
3412 isl_bool is_cst = isl_aff_is_cst(pwaff->p[i].aff);
3413 if (is_cst < 0 || !is_cst)
3414 return is_cst;
3417 return isl_bool_true;
3420 /* Are all elements of "mpa" piecewise constants?
3422 isl_bool isl_multi_pw_aff_is_cst(__isl_keep isl_multi_pw_aff *mpa)
3424 int i;
3426 if (!mpa)
3427 return isl_bool_error;
3429 for (i = 0; i < mpa->n; ++i) {
3430 isl_bool is_cst = isl_pw_aff_is_cst(mpa->u.p[i]);
3431 if (is_cst < 0 || !is_cst)
3432 return is_cst;
3435 return isl_bool_true;
3438 /* Return the product of "aff1" and "aff2".
3440 * If either of the two is NaN, then the result is NaN.
3442 * Otherwise, at least one of "aff1" or "aff2" needs to be a constant.
3444 __isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1,
3445 __isl_take isl_aff *aff2)
3447 if (!aff1 || !aff2)
3448 goto error;
3450 if (isl_aff_is_nan(aff1)) {
3451 isl_aff_free(aff2);
3452 return aff1;
3454 if (isl_aff_is_nan(aff2)) {
3455 isl_aff_free(aff1);
3456 return aff2;
3459 if (!isl_aff_is_cst(aff2) && isl_aff_is_cst(aff1))
3460 return isl_aff_mul(aff2, aff1);
3462 if (!isl_aff_is_cst(aff2))
3463 isl_die(isl_aff_get_ctx(aff1), isl_error_invalid,
3464 "at least one affine expression should be constant",
3465 goto error);
3467 aff1 = isl_aff_cow(aff1);
3468 if (!aff1 || !aff2)
3469 goto error;
3471 aff1 = isl_aff_scale(aff1, aff2->v->el[1]);
3472 aff1 = isl_aff_scale_down(aff1, aff2->v->el[0]);
3474 isl_aff_free(aff2);
3475 return aff1;
3476 error:
3477 isl_aff_free(aff1);
3478 isl_aff_free(aff2);
3479 return NULL;
3482 /* Divide "aff1" by "aff2", assuming "aff2" is a constant.
3484 * If either of the two is NaN, then the result is NaN.
3486 __isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
3487 __isl_take isl_aff *aff2)
3489 int is_cst;
3490 int neg;
3492 if (!aff1 || !aff2)
3493 goto error;
3495 if (isl_aff_is_nan(aff1)) {
3496 isl_aff_free(aff2);
3497 return aff1;
3499 if (isl_aff_is_nan(aff2)) {
3500 isl_aff_free(aff1);
3501 return aff2;
3504 is_cst = isl_aff_is_cst(aff2);
3505 if (is_cst < 0)
3506 goto error;
3507 if (!is_cst)
3508 isl_die(isl_aff_get_ctx(aff2), isl_error_invalid,
3509 "second argument should be a constant", goto error);
3511 if (!aff2)
3512 goto error;
3514 neg = isl_int_is_neg(aff2->v->el[1]);
3515 if (neg) {
3516 isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
3517 isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
3520 aff1 = isl_aff_scale(aff1, aff2->v->el[0]);
3521 aff1 = isl_aff_scale_down(aff1, aff2->v->el[1]);
3523 if (neg) {
3524 isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
3525 isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
3528 isl_aff_free(aff2);
3529 return aff1;
3530 error:
3531 isl_aff_free(aff1);
3532 isl_aff_free(aff2);
3533 return NULL;
3536 static __isl_give isl_pw_aff *pw_aff_add(__isl_take isl_pw_aff *pwaff1,
3537 __isl_take isl_pw_aff *pwaff2)
3539 return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_add);
3542 __isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1,
3543 __isl_take isl_pw_aff *pwaff2)
3545 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_add);
3548 __isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
3549 __isl_take isl_pw_aff *pwaff2)
3551 return isl_pw_aff_union_add_(pwaff1, pwaff2);
3554 static __isl_give isl_pw_aff *pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
3555 __isl_take isl_pw_aff *pwaff2)
3557 return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_mul);
3560 __isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
3561 __isl_take isl_pw_aff *pwaff2)
3563 return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_mul);
3566 static __isl_give isl_pw_aff *pw_aff_div(__isl_take isl_pw_aff *pa1,
3567 __isl_take isl_pw_aff *pa2)
3569 return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div);
3572 /* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant.
3574 __isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
3575 __isl_take isl_pw_aff *pa2)
3577 int is_cst;
3579 is_cst = isl_pw_aff_is_cst(pa2);
3580 if (is_cst < 0)
3581 goto error;
3582 if (!is_cst)
3583 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3584 "second argument should be a piecewise constant",
3585 goto error);
3586 return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_div);
3587 error:
3588 isl_pw_aff_free(pa1);
3589 isl_pw_aff_free(pa2);
3590 return NULL;
3593 /* Compute the quotient of the integer division of "pa1" by "pa2"
3594 * with rounding towards zero.
3595 * "pa2" is assumed to be a piecewise constant.
3597 * In particular, return
3599 * pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)
3602 __isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1,
3603 __isl_take isl_pw_aff *pa2)
3605 int is_cst;
3606 isl_set *cond;
3607 isl_pw_aff *f, *c;
3609 is_cst = isl_pw_aff_is_cst(pa2);
3610 if (is_cst < 0)
3611 goto error;
3612 if (!is_cst)
3613 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3614 "second argument should be a piecewise constant",
3615 goto error);
3617 pa1 = isl_pw_aff_div(pa1, pa2);
3619 cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1));
3620 f = isl_pw_aff_floor(isl_pw_aff_copy(pa1));
3621 c = isl_pw_aff_ceil(pa1);
3622 return isl_pw_aff_cond(isl_set_indicator_function(cond), f, c);
3623 error:
3624 isl_pw_aff_free(pa1);
3625 isl_pw_aff_free(pa2);
3626 return NULL;
3629 /* Compute the remainder of the integer division of "pa1" by "pa2"
3630 * with rounding towards zero.
3631 * "pa2" is assumed to be a piecewise constant.
3633 * In particular, return
3635 * pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2))
3638 __isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
3639 __isl_take isl_pw_aff *pa2)
3641 int is_cst;
3642 isl_pw_aff *res;
3644 is_cst = isl_pw_aff_is_cst(pa2);
3645 if (is_cst < 0)
3646 goto error;
3647 if (!is_cst)
3648 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
3649 "second argument should be a piecewise constant",
3650 goto error);
3651 res = isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1), isl_pw_aff_copy(pa2));
3652 res = isl_pw_aff_mul(pa2, res);
3653 res = isl_pw_aff_sub(pa1, res);
3654 return res;
3655 error:
3656 isl_pw_aff_free(pa1);
3657 isl_pw_aff_free(pa2);
3658 return NULL;
3661 /* Does either of "pa1" or "pa2" involve any NaN2?
3663 static isl_bool either_involves_nan(__isl_keep isl_pw_aff *pa1,
3664 __isl_keep isl_pw_aff *pa2)
3666 isl_bool has_nan;
3668 has_nan = isl_pw_aff_involves_nan(pa1);
3669 if (has_nan < 0 || has_nan)
3670 return has_nan;
3671 return isl_pw_aff_involves_nan(pa2);
3674 /* Replace "pa1" and "pa2" (at least one of which involves a NaN)
3675 * by a NaN on their shared domain.
3677 * In principle, the result could be refined to only being NaN
3678 * on the parts of this domain where at least one of "pa1" or "pa2" is NaN.
3680 static __isl_give isl_pw_aff *replace_by_nan(__isl_take isl_pw_aff *pa1,
3681 __isl_take isl_pw_aff *pa2)
3683 isl_local_space *ls;
3684 isl_set *dom;
3685 isl_pw_aff *pa;
3687 dom = isl_set_intersect(isl_pw_aff_domain(pa1), isl_pw_aff_domain(pa2));
3688 ls = isl_local_space_from_space(isl_set_get_space(dom));
3689 pa = isl_pw_aff_nan_on_domain(ls);
3690 pa = isl_pw_aff_intersect_domain(pa, dom);
3692 return pa;
3695 static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1,
3696 __isl_take isl_pw_aff *pwaff2)
3698 isl_set *le;
3699 isl_set *dom;
3701 dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
3702 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
3703 le = isl_pw_aff_le_set(isl_pw_aff_copy(pwaff1),
3704 isl_pw_aff_copy(pwaff2));
3705 dom = isl_set_subtract(dom, isl_set_copy(le));
3706 return isl_pw_aff_select(le, pwaff1, dom, pwaff2);
3709 static __isl_give isl_pw_aff *pw_aff_max(__isl_take isl_pw_aff *pwaff1,
3710 __isl_take isl_pw_aff *pwaff2)
3712 isl_set *ge;
3713 isl_set *dom;
3715 dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
3716 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
3717 ge = isl_pw_aff_ge_set(isl_pw_aff_copy(pwaff1),
3718 isl_pw_aff_copy(pwaff2));
3719 dom = isl_set_subtract(dom, isl_set_copy(ge));
3720 return isl_pw_aff_select(ge, pwaff1, dom, pwaff2);
3723 /* Return an expression for the minimum (if "max" is not set) or
3724 * the maximum (if "max" is set) of "pa1" and "pa2".
3725 * If either expression involves any NaN, then return a NaN
3726 * on the shared domain as result.
3728 static __isl_give isl_pw_aff *pw_aff_min_max(__isl_take isl_pw_aff *pa1,
3729 __isl_take isl_pw_aff *pa2, int max)
3731 isl_bool has_nan;
3733 has_nan = either_involves_nan(pa1, pa2);
3734 if (has_nan < 0)
3735 pa1 = isl_pw_aff_free(pa1);
3736 else if (has_nan)
3737 return replace_by_nan(pa1, pa2);
3739 if (max)
3740 return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_max);
3741 else
3742 return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_min);
3745 /* Return an expression for the minimum of "pwaff1" and "pwaff2".
3747 __isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
3748 __isl_take isl_pw_aff *pwaff2)
3750 return pw_aff_min_max(pwaff1, pwaff2, 0);
3753 /* Return an expression for the maximum of "pwaff1" and "pwaff2".
3755 __isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
3756 __isl_take isl_pw_aff *pwaff2)
3758 return pw_aff_min_max(pwaff1, pwaff2, 1);
3761 static __isl_give isl_pw_aff *pw_aff_list_reduce(
3762 __isl_take isl_pw_aff_list *list,
3763 __isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pwaff1,
3764 __isl_take isl_pw_aff *pwaff2))
3766 int i;
3767 isl_ctx *ctx;
3768 isl_pw_aff *res;
3770 if (!list)
3771 return NULL;
3773 ctx = isl_pw_aff_list_get_ctx(list);
3774 if (list->n < 1)
3775 isl_die(ctx, isl_error_invalid,
3776 "list should contain at least one element", goto error);
3778 res = isl_pw_aff_copy(list->p[0]);
3779 for (i = 1; i < list->n; ++i)
3780 res = fn(res, isl_pw_aff_copy(list->p[i]));
3782 isl_pw_aff_list_free(list);
3783 return res;
3784 error:
3785 isl_pw_aff_list_free(list);
3786 return NULL;
3789 /* Return an isl_pw_aff that maps each element in the intersection of the
3790 * domains of the elements of list to the minimal corresponding affine
3791 * expression.
3793 __isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list)
3795 return pw_aff_list_reduce(list, &isl_pw_aff_min);
3798 /* Return an isl_pw_aff that maps each element in the intersection of the
3799 * domains of the elements of list to the maximal corresponding affine
3800 * expression.
3802 __isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list)
3804 return pw_aff_list_reduce(list, &isl_pw_aff_max);
3807 /* Mark the domains of "pwaff" as rational.
3809 __isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff)
3811 int i;
3813 pwaff = isl_pw_aff_cow(pwaff);
3814 if (!pwaff)
3815 return NULL;
3816 if (pwaff->n == 0)
3817 return pwaff;
3819 for (i = 0; i < pwaff->n; ++i) {
3820 pwaff->p[i].set = isl_set_set_rational(pwaff->p[i].set);
3821 if (!pwaff->p[i].set)
3822 return isl_pw_aff_free(pwaff);
3825 return pwaff;
3828 /* Mark the domains of the elements of "list" as rational.
3830 __isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational(
3831 __isl_take isl_pw_aff_list *list)
3833 int i, n;
3835 if (!list)
3836 return NULL;
3837 if (list->n == 0)
3838 return list;
3840 n = list->n;
3841 for (i = 0; i < n; ++i) {
3842 isl_pw_aff *pa;
3844 pa = isl_pw_aff_list_get_pw_aff(list, i);
3845 pa = isl_pw_aff_set_rational(pa);
3846 list = isl_pw_aff_list_set_pw_aff(list, i, pa);
3849 return list;
3852 /* Do the parameters of "aff" match those of "space"?
3854 isl_bool isl_aff_matching_params(__isl_keep isl_aff *aff,
3855 __isl_keep isl_space *space)
3857 isl_space *aff_space;
3858 isl_bool match;
3860 if (!aff || !space)
3861 return isl_bool_error;
3863 aff_space = isl_aff_get_domain_space(aff);
3865 match = isl_space_has_equal_params(space, aff_space);
3867 isl_space_free(aff_space);
3868 return match;
3871 /* Check that the domain space of "aff" matches "space".
3873 isl_stat isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
3874 __isl_keep isl_space *space)
3876 isl_space *aff_space;
3877 isl_bool match;
3879 if (!aff || !space)
3880 return isl_stat_error;
3882 aff_space = isl_aff_get_domain_space(aff);
3884 match = isl_space_has_equal_params(space, aff_space);
3885 if (match < 0)
3886 goto error;
3887 if (!match)
3888 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
3889 "parameters don't match", goto error);
3890 match = isl_space_tuple_is_equal(space, isl_dim_in,
3891 aff_space, isl_dim_set);
3892 if (match < 0)
3893 goto error;
3894 if (!match)
3895 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
3896 "domains don't match", goto error);
3897 isl_space_free(aff_space);
3898 return isl_stat_ok;
3899 error:
3900 isl_space_free(aff_space);
3901 return isl_stat_error;
3904 /* Return the shared (universe) domain of the elements of "ma".
3906 * Since an isl_multi_aff (and an isl_aff) is always total,
3907 * the domain is always the universe set in its domain space.
3908 * This is a helper function for use in the generic isl_multi_*_bind.
3910 static __isl_give isl_basic_set *isl_multi_aff_domain(
3911 __isl_take isl_multi_aff *ma)
3913 isl_space *space;
3915 space = isl_multi_aff_get_space(ma);
3916 isl_multi_aff_free(ma);
3918 return isl_basic_set_universe(isl_space_domain(space));
3921 #undef BASE
3922 #define BASE aff
3924 #include <isl_multi_no_explicit_domain.c>
3925 #include <isl_multi_templ.c>
3926 #include <isl_multi_apply_set.c>
3927 #include <isl_multi_arith_templ.c>
3928 #include <isl_multi_bind_domain_templ.c>
3929 #include <isl_multi_cmp.c>
3930 #include <isl_multi_dim_id_templ.c>
3931 #include <isl_multi_dims.c>
3932 #include <isl_multi_floor.c>
3933 #include <isl_multi_from_base_templ.c>
3934 #include <isl_multi_identity_templ.c>
3935 #include <isl_multi_move_dims_templ.c>
3936 #include <isl_multi_nan_templ.c>
3937 #include <isl_multi_product_templ.c>
3938 #include <isl_multi_splice_templ.c>
3939 #include <isl_multi_tuple_id_templ.c>
3940 #include <isl_multi_zero_templ.c>
3942 #undef DOMBASE
3943 #define DOMBASE set
3944 #include <isl_multi_gist.c>
3946 #undef DOMBASE
3947 #define DOMBASE basic_set
3948 #include <isl_multi_bind_templ.c>
3950 /* Construct an isl_multi_aff living in "space" that corresponds
3951 * to the affine transformation matrix "mat".
3953 __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat(
3954 __isl_take isl_space *space, __isl_take isl_mat *mat)
3956 isl_ctx *ctx;
3957 isl_local_space *ls = NULL;
3958 isl_multi_aff *ma = NULL;
3959 isl_size n_row, n_col, n_out, total;
3960 int i;
3962 if (!space || !mat)
3963 goto error;
3965 ctx = isl_mat_get_ctx(mat);
3967 n_row = isl_mat_rows(mat);
3968 n_col = isl_mat_cols(mat);
3969 n_out = isl_space_dim(space, isl_dim_out);
3970 total = isl_space_dim(space, isl_dim_all);
3971 if (n_row < 0 || n_col < 0 || n_out < 0 || total < 0)
3972 goto error;
3973 if (n_row < 1)
3974 isl_die(ctx, isl_error_invalid,
3975 "insufficient number of rows", goto error);
3976 if (n_col < 1)
3977 isl_die(ctx, isl_error_invalid,
3978 "insufficient number of columns", goto error);
3979 if (1 + n_out != n_row || 2 + total != n_row + n_col)
3980 isl_die(ctx, isl_error_invalid,
3981 "dimension mismatch", goto error);
3983 ma = isl_multi_aff_zero(isl_space_copy(space));
3984 ls = isl_local_space_from_space(isl_space_domain(space));
3986 for (i = 0; i < n_row - 1; ++i) {
3987 isl_vec *v;
3988 isl_aff *aff;
3990 v = isl_vec_alloc(ctx, 1 + n_col);
3991 if (!v)
3992 goto error;
3993 isl_int_set(v->el[0], mat->row[0][0]);
3994 isl_seq_cpy(v->el + 1, mat->row[1 + i], n_col);
3995 v = isl_vec_normalize(v);
3996 aff = isl_aff_alloc_vec(isl_local_space_copy(ls), v);
3997 ma = isl_multi_aff_set_aff(ma, i, aff);
4000 isl_local_space_free(ls);
4001 isl_mat_free(mat);
4002 return ma;
4003 error:
4004 isl_local_space_free(ls);
4005 isl_mat_free(mat);
4006 isl_multi_aff_free(ma);
4007 return NULL;
4010 /* Remove any internal structure of the domain of "ma".
4011 * If there is any such internal structure in the input,
4012 * then the name of the corresponding space is also removed.
4014 __isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
4015 __isl_take isl_multi_aff *ma)
4017 isl_space *space;
4019 if (!ma)
4020 return NULL;
4022 if (!ma->space->nested[0])
4023 return ma;
4025 space = isl_multi_aff_get_space(ma);
4026 space = isl_space_flatten_domain(space);
4027 ma = isl_multi_aff_reset_space(ma, space);
4029 return ma;
4032 /* Given a map space, return an isl_multi_aff that maps a wrapped copy
4033 * of the space to its domain.
4035 __isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space)
4037 int i;
4038 isl_size n_in;
4039 isl_local_space *ls;
4040 isl_multi_aff *ma;
4042 if (!space)
4043 return NULL;
4044 if (!isl_space_is_map(space))
4045 isl_die(isl_space_get_ctx(space), isl_error_invalid,
4046 "not a map space", goto error);
4048 n_in = isl_space_dim(space, isl_dim_in);
4049 if (n_in < 0)
4050 goto error;
4051 space = isl_space_domain_map(space);
4053 ma = isl_multi_aff_alloc(isl_space_copy(space));
4054 if (n_in == 0) {
4055 isl_space_free(space);
4056 return ma;
4059 space = isl_space_domain(space);
4060 ls = isl_local_space_from_space(space);
4061 for (i = 0; i < n_in; ++i) {
4062 isl_aff *aff;
4064 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
4065 isl_dim_set, i);
4066 ma = isl_multi_aff_set_aff(ma, i, aff);
4068 isl_local_space_free(ls);
4069 return ma;
4070 error:
4071 isl_space_free(space);
4072 return NULL;
4075 /* Given a map space, return an isl_multi_aff that maps a wrapped copy
4076 * of the space to its range.
4078 __isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space)
4080 int i;
4081 isl_size n_in, n_out;
4082 isl_local_space *ls;
4083 isl_multi_aff *ma;
4085 if (!space)
4086 return NULL;
4087 if (!isl_space_is_map(space))
4088 isl_die(isl_space_get_ctx(space), isl_error_invalid,
4089 "not a map space", goto error);
4091 n_in = isl_space_dim(space, isl_dim_in);
4092 n_out = isl_space_dim(space, isl_dim_out);
4093 if (n_in < 0 || n_out < 0)
4094 goto error;
4095 space = isl_space_range_map(space);
4097 ma = isl_multi_aff_alloc(isl_space_copy(space));
4098 if (n_out == 0) {
4099 isl_space_free(space);
4100 return ma;
4103 space = isl_space_domain(space);
4104 ls = isl_local_space_from_space(space);
4105 for (i = 0; i < n_out; ++i) {
4106 isl_aff *aff;
4108 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
4109 isl_dim_set, n_in + i);
4110 ma = isl_multi_aff_set_aff(ma, i, aff);
4112 isl_local_space_free(ls);
4113 return ma;
4114 error:
4115 isl_space_free(space);
4116 return NULL;
4119 /* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy
4120 * of the space to its range.
4122 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map(
4123 __isl_take isl_space *space)
4125 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_range_map(space));
4128 /* Given the space of a set and a range of set dimensions,
4129 * construct an isl_multi_aff that projects out those dimensions.
4131 __isl_give isl_multi_aff *isl_multi_aff_project_out_map(
4132 __isl_take isl_space *space, enum isl_dim_type type,
4133 unsigned first, unsigned n)
4135 int i;
4136 isl_size dim;
4137 isl_local_space *ls;
4138 isl_multi_aff *ma;
4140 if (!space)
4141 return NULL;
4142 if (!isl_space_is_set(space))
4143 isl_die(isl_space_get_ctx(space), isl_error_unsupported,
4144 "expecting set space", goto error);
4145 if (type != isl_dim_set)
4146 isl_die(isl_space_get_ctx(space), isl_error_invalid,
4147 "only set dimensions can be projected out", goto error);
4148 if (isl_space_check_range(space, type, first, n) < 0)
4149 goto error;
4151 dim = isl_space_dim(space, isl_dim_set);
4152 if (dim < 0)
4153 goto error;
4155 space = isl_space_from_domain(space);
4156 space = isl_space_add_dims(space, isl_dim_out, dim - n);
4158 if (dim == n)
4159 return isl_multi_aff_alloc(space);
4161 ma = isl_multi_aff_alloc(isl_space_copy(space));
4162 space = isl_space_domain(space);
4163 ls = isl_local_space_from_space(space);
4165 for (i = 0; i < first; ++i) {
4166 isl_aff *aff;
4168 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
4169 isl_dim_set, i);
4170 ma = isl_multi_aff_set_aff(ma, i, aff);
4173 for (i = 0; i < dim - (first + n); ++i) {
4174 isl_aff *aff;
4176 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
4177 isl_dim_set, first + n + i);
4178 ma = isl_multi_aff_set_aff(ma, first + i, aff);
4181 isl_local_space_free(ls);
4182 return ma;
4183 error:
4184 isl_space_free(space);
4185 return NULL;
4188 /* Given the space of a set and a range of set dimensions,
4189 * construct an isl_pw_multi_aff that projects out those dimensions.
4191 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out_map(
4192 __isl_take isl_space *space, enum isl_dim_type type,
4193 unsigned first, unsigned n)
4195 isl_multi_aff *ma;
4197 ma = isl_multi_aff_project_out_map(space, type, first, n);
4198 return isl_pw_multi_aff_from_multi_aff(ma);
4201 /* Create an isl_pw_multi_aff with the given isl_multi_aff on a universe
4202 * domain.
4204 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_aff(
4205 __isl_take isl_multi_aff *ma)
4207 isl_set *dom = isl_set_universe(isl_multi_aff_get_domain_space(ma));
4208 return isl_pw_multi_aff_alloc(dom, ma);
4211 /* Create a piecewise multi-affine expression in the given space that maps each
4212 * input dimension to the corresponding output dimension.
4214 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
4215 __isl_take isl_space *space)
4217 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_identity(space));
4220 /* Exploit the equalities in "eq" to simplify the affine expressions.
4222 static __isl_give isl_multi_aff *isl_multi_aff_substitute_equalities(
4223 __isl_take isl_multi_aff *maff, __isl_take isl_basic_set *eq)
4225 int i;
4227 maff = isl_multi_aff_cow(maff);
4228 if (!maff || !eq)
4229 goto error;
4231 for (i = 0; i < maff->n; ++i) {
4232 maff->u.p[i] = isl_aff_substitute_equalities(maff->u.p[i],
4233 isl_basic_set_copy(eq));
4234 if (!maff->u.p[i])
4235 goto error;
4238 isl_basic_set_free(eq);
4239 return maff;
4240 error:
4241 isl_basic_set_free(eq);
4242 isl_multi_aff_free(maff);
4243 return NULL;
4246 __isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff,
4247 isl_int f)
4249 int i;
4251 maff = isl_multi_aff_cow(maff);
4252 if (!maff)
4253 return NULL;
4255 for (i = 0; i < maff->n; ++i) {
4256 maff->u.p[i] = isl_aff_scale(maff->u.p[i], f);
4257 if (!maff->u.p[i])
4258 return isl_multi_aff_free(maff);
4261 return maff;
4264 __isl_give isl_multi_aff *isl_multi_aff_add_on_domain(__isl_keep isl_set *dom,
4265 __isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2)
4267 maff1 = isl_multi_aff_add(maff1, maff2);
4268 maff1 = isl_multi_aff_gist(maff1, isl_set_copy(dom));
4269 return maff1;
4272 int isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff)
4274 if (!maff)
4275 return -1;
4277 return 0;
4280 /* Return the set of domain elements where "ma1" is lexicographically
4281 * smaller than or equal to "ma2".
4283 __isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1,
4284 __isl_take isl_multi_aff *ma2)
4286 return isl_multi_aff_lex_ge_set(ma2, ma1);
4289 /* Return the set of domain elements where "ma1" is lexicographically
4290 * smaller than "ma2".
4292 __isl_give isl_set *isl_multi_aff_lex_lt_set(__isl_take isl_multi_aff *ma1,
4293 __isl_take isl_multi_aff *ma2)
4295 return isl_multi_aff_lex_gt_set(ma2, ma1);
4298 /* Return the set of domain elements where "ma1" and "ma2"
4299 * satisfy "order".
4301 static __isl_give isl_set *isl_multi_aff_order_set(
4302 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2,
4303 __isl_give isl_map *order(__isl_take isl_space *set_space))
4305 isl_space *space;
4306 isl_map *map1, *map2;
4307 isl_map *map, *ge;
4309 map1 = isl_map_from_multi_aff_internal(ma1);
4310 map2 = isl_map_from_multi_aff_internal(ma2);
4311 map = isl_map_range_product(map1, map2);
4312 space = isl_space_range(isl_map_get_space(map));
4313 space = isl_space_domain(isl_space_unwrap(space));
4314 ge = order(space);
4315 map = isl_map_intersect_range(map, isl_map_wrap(ge));
4317 return isl_map_domain(map);
4320 /* Return the set of domain elements where "ma1" is lexicographically
4321 * greater than or equal to "ma2".
4323 __isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
4324 __isl_take isl_multi_aff *ma2)
4326 return isl_multi_aff_order_set(ma1, ma2, &isl_map_lex_ge);
4329 /* Return the set of domain elements where "ma1" is lexicographically
4330 * greater than "ma2".
4332 __isl_give isl_set *isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff *ma1,
4333 __isl_take isl_multi_aff *ma2)
4335 return isl_multi_aff_order_set(ma1, ma2, &isl_map_lex_gt);
4338 #undef PW
4339 #define PW isl_pw_multi_aff
4340 #undef EL
4341 #define EL isl_multi_aff
4342 #undef EL_IS_ZERO
4343 #define EL_IS_ZERO is_empty
4344 #undef ZERO
4345 #define ZERO empty
4346 #undef IS_ZERO
4347 #define IS_ZERO is_empty
4348 #undef FIELD
4349 #define FIELD maff
4350 #undef DEFAULT_IS_ZERO
4351 #define DEFAULT_IS_ZERO 0
4353 #define NO_SUB
4354 #define NO_OPT
4355 #define NO_INSERT_DIMS
4356 #define NO_LIFT
4357 #define NO_MORPH
4359 #include <isl_pw_templ.c>
4360 #include <isl_pw_bind_domain_templ.c>
4361 #include <isl_pw_union_opt.c>
4363 #undef NO_SUB
4365 #undef BASE
4366 #define BASE pw_multi_aff
4368 #include <isl_union_multi.c>
4369 #include <isl_union_neg.c>
4371 static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmax(
4372 __isl_take isl_pw_multi_aff *pma1,
4373 __isl_take isl_pw_multi_aff *pma2)
4375 return isl_pw_multi_aff_union_opt_cmp(pma1, pma2,
4376 &isl_multi_aff_lex_ge_set);
4379 /* Given two piecewise multi affine expressions, return a piecewise
4380 * multi-affine expression defined on the union of the definition domains
4381 * of the inputs that is equal to the lexicographic maximum of the two
4382 * inputs on each cell. If only one of the two inputs is defined on
4383 * a given cell, then it is considered to be the maximum.
4385 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
4386 __isl_take isl_pw_multi_aff *pma1,
4387 __isl_take isl_pw_multi_aff *pma2)
4389 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4390 &pw_multi_aff_union_lexmax);
4393 static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmin(
4394 __isl_take isl_pw_multi_aff *pma1,
4395 __isl_take isl_pw_multi_aff *pma2)
4397 return isl_pw_multi_aff_union_opt_cmp(pma1, pma2,
4398 &isl_multi_aff_lex_le_set);
4401 /* Given two piecewise multi affine expressions, return a piecewise
4402 * multi-affine expression defined on the union of the definition domains
4403 * of the inputs that is equal to the lexicographic minimum of the two
4404 * inputs on each cell. If only one of the two inputs is defined on
4405 * a given cell, then it is considered to be the minimum.
4407 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
4408 __isl_take isl_pw_multi_aff *pma1,
4409 __isl_take isl_pw_multi_aff *pma2)
4411 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4412 &pw_multi_aff_union_lexmin);
4415 static __isl_give isl_pw_multi_aff *pw_multi_aff_add(
4416 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4418 return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
4419 &isl_multi_aff_add);
4422 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_add(
4423 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4425 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4426 &pw_multi_aff_add);
4429 static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
4430 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4432 return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
4433 &isl_multi_aff_sub);
4436 /* Subtract "pma2" from "pma1" and return the result.
4438 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
4439 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4441 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4442 &pw_multi_aff_sub);
4445 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
4446 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4448 return isl_pw_multi_aff_union_add_(pma1, pma2);
4451 /* Compute the sum of "upa1" and "upa2" on the union of their domains,
4452 * with the actual sum on the shared domain and
4453 * the defined expression on the symmetric difference of the domains.
4455 __isl_give isl_union_pw_aff *isl_union_pw_aff_union_add(
4456 __isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2)
4458 return isl_union_pw_aff_union_add_(upa1, upa2);
4461 /* Compute the sum of "upma1" and "upma2" on the union of their domains,
4462 * with the actual sum on the shared domain and
4463 * the defined expression on the symmetric difference of the domains.
4465 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_union_add(
4466 __isl_take isl_union_pw_multi_aff *upma1,
4467 __isl_take isl_union_pw_multi_aff *upma2)
4469 return isl_union_pw_multi_aff_union_add_(upma1, upma2);
4472 /* Given two piecewise multi-affine expressions A -> B and C -> D,
4473 * construct a piecewise multi-affine expression [A -> C] -> [B -> D].
4475 static __isl_give isl_pw_multi_aff *pw_multi_aff_product(
4476 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4478 int i, j, n;
4479 isl_space *space;
4480 isl_pw_multi_aff *res;
4482 if (!pma1 || !pma2)
4483 goto error;
4485 n = pma1->n * pma2->n;
4486 space = isl_space_product(isl_space_copy(pma1->dim),
4487 isl_space_copy(pma2->dim));
4488 res = isl_pw_multi_aff_alloc_size(space, n);
4490 for (i = 0; i < pma1->n; ++i) {
4491 for (j = 0; j < pma2->n; ++j) {
4492 isl_set *domain;
4493 isl_multi_aff *ma;
4495 domain = isl_set_product(isl_set_copy(pma1->p[i].set),
4496 isl_set_copy(pma2->p[j].set));
4497 ma = isl_multi_aff_product(
4498 isl_multi_aff_copy(pma1->p[i].maff),
4499 isl_multi_aff_copy(pma2->p[j].maff));
4500 res = isl_pw_multi_aff_add_piece(res, domain, ma);
4504 isl_pw_multi_aff_free(pma1);
4505 isl_pw_multi_aff_free(pma2);
4506 return res;
4507 error:
4508 isl_pw_multi_aff_free(pma1);
4509 isl_pw_multi_aff_free(pma2);
4510 return NULL;
4513 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_product(
4514 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
4516 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
4517 &pw_multi_aff_product);
4520 /* Subtract the initial "n" elements in "ma" with coefficients in "c" and
4521 * denominator "denom".
4522 * "denom" is allowed to be negative, in which case the actual denominator
4523 * is -denom and the expressions are added instead.
4525 static __isl_give isl_aff *subtract_initial(__isl_take isl_aff *aff,
4526 __isl_keep isl_multi_aff *ma, int n, isl_int *c, isl_int denom)
4528 int i, first;
4529 int sign;
4530 isl_int d;
4532 first = isl_seq_first_non_zero(c, n);
4533 if (first == -1)
4534 return aff;
4536 sign = isl_int_sgn(denom);
4537 isl_int_init(d);
4538 isl_int_abs(d, denom);
4539 for (i = first; i < n; ++i) {
4540 isl_aff *aff_i;
4542 if (isl_int_is_zero(c[i]))
4543 continue;
4544 aff_i = isl_multi_aff_get_aff(ma, i);
4545 aff_i = isl_aff_scale(aff_i, c[i]);
4546 aff_i = isl_aff_scale_down(aff_i, d);
4547 if (sign >= 0)
4548 aff = isl_aff_sub(aff, aff_i);
4549 else
4550 aff = isl_aff_add(aff, aff_i);
4552 isl_int_clear(d);
4554 return aff;
4557 /* Extract an affine expression that expresses the output dimension "pos"
4558 * of "bmap" in terms of the parameters and input dimensions from
4559 * equality "eq".
4560 * Note that this expression may involve integer divisions defined
4561 * in terms of parameters and input dimensions.
4562 * The equality may also involve references to earlier (but not later)
4563 * output dimensions. These are replaced by the corresponding elements
4564 * in "ma".
4566 * If the equality is of the form
4568 * f(i) + h(j) + a x + g(i) = 0,
4570 * with f(i) a linear combinations of the parameters and input dimensions,
4571 * g(i) a linear combination of integer divisions defined in terms of the same
4572 * and h(j) a linear combinations of earlier output dimensions,
4573 * then the affine expression is
4575 * (-f(i) - g(i))/a - h(j)/a
4577 * If the equality is of the form
4579 * f(i) + h(j) - a x + g(i) = 0,
4581 * then the affine expression is
4583 * (f(i) + g(i))/a - h(j)/(-a)
4586 * If "div" refers to an integer division (i.e., it is smaller than
4587 * the number of integer divisions), then the equality constraint
4588 * does involve an integer division (the one at position "div") that
4589 * is defined in terms of output dimensions. However, this integer
4590 * division can be eliminated by exploiting a pair of constraints
4591 * x >= l and x <= l + n, with n smaller than the coefficient of "div"
4592 * in the equality constraint. "ineq" refers to inequality x >= l, i.e.,
4593 * -l + x >= 0.
4594 * In particular, let
4596 * x = e(i) + m floor(...)
4598 * with e(i) the expression derived above and floor(...) the integer
4599 * division involving output dimensions.
4600 * From
4602 * l <= x <= l + n,
4604 * we have
4606 * 0 <= x - l <= n
4608 * This means
4610 * e(i) + m floor(...) - l = (e(i) + m floor(...) - l) mod m
4611 * = (e(i) - l) mod m
4613 * Therefore,
4615 * x - l = (e(i) - l) mod m
4617 * or
4619 * x = ((e(i) - l) mod m) + l
4621 * The variable "shift" below contains the expression -l, which may
4622 * also involve a linear combination of earlier output dimensions.
4624 static __isl_give isl_aff *extract_aff_from_equality(
4625 __isl_keep isl_basic_map *bmap, int pos, int eq, int div, int ineq,
4626 __isl_keep isl_multi_aff *ma)
4628 unsigned o_out;
4629 isl_size n_div, n_out;
4630 isl_ctx *ctx;
4631 isl_local_space *ls;
4632 isl_aff *aff, *shift;
4633 isl_val *mod;
4635 ctx = isl_basic_map_get_ctx(bmap);
4636 ls = isl_basic_map_get_local_space(bmap);
4637 ls = isl_local_space_domain(ls);
4638 aff = isl_aff_alloc(isl_local_space_copy(ls));
4639 if (!aff)
4640 goto error;
4641 o_out = isl_basic_map_offset(bmap, isl_dim_out);
4642 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4643 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4644 if (n_out < 0 || n_div < 0)
4645 goto error;
4646 if (isl_int_is_neg(bmap->eq[eq][o_out + pos])) {
4647 isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], o_out);
4648 isl_seq_cpy(aff->v->el + 1 + o_out,
4649 bmap->eq[eq] + o_out + n_out, n_div);
4650 } else {
4651 isl_seq_neg(aff->v->el + 1, bmap->eq[eq], o_out);
4652 isl_seq_neg(aff->v->el + 1 + o_out,
4653 bmap->eq[eq] + o_out + n_out, n_div);
4655 if (div < n_div)
4656 isl_int_set_si(aff->v->el[1 + o_out + div], 0);
4657 isl_int_abs(aff->v->el[0], bmap->eq[eq][o_out + pos]);
4658 aff = subtract_initial(aff, ma, pos, bmap->eq[eq] + o_out,
4659 bmap->eq[eq][o_out + pos]);
4660 if (div < n_div) {
4661 shift = isl_aff_alloc(isl_local_space_copy(ls));
4662 if (!shift)
4663 goto error;
4664 isl_seq_cpy(shift->v->el + 1, bmap->ineq[ineq], o_out);
4665 isl_seq_cpy(shift->v->el + 1 + o_out,
4666 bmap->ineq[ineq] + o_out + n_out, n_div);
4667 isl_int_set_si(shift->v->el[0], 1);
4668 shift = subtract_initial(shift, ma, pos,
4669 bmap->ineq[ineq] + o_out, ctx->negone);
4670 aff = isl_aff_add(aff, isl_aff_copy(shift));
4671 mod = isl_val_int_from_isl_int(ctx,
4672 bmap->eq[eq][o_out + n_out + div]);
4673 mod = isl_val_abs(mod);
4674 aff = isl_aff_mod_val(aff, mod);
4675 aff = isl_aff_sub(aff, shift);
4678 isl_local_space_free(ls);
4679 return aff;
4680 error:
4681 isl_local_space_free(ls);
4682 isl_aff_free(aff);
4683 return NULL;
4686 /* Given a basic map with output dimensions defined
4687 * in terms of the parameters input dimensions and earlier
4688 * output dimensions using an equality (and possibly a pair on inequalities),
4689 * extract an isl_aff that expresses output dimension "pos" in terms
4690 * of the parameters and input dimensions.
4691 * Note that this expression may involve integer divisions defined
4692 * in terms of parameters and input dimensions.
4693 * "ma" contains the expressions corresponding to earlier output dimensions.
4695 * This function shares some similarities with
4696 * isl_basic_map_has_defining_equality and isl_constraint_get_bound.
4698 static __isl_give isl_aff *extract_isl_aff_from_basic_map(
4699 __isl_keep isl_basic_map *bmap, int pos, __isl_keep isl_multi_aff *ma)
4701 int eq, div, ineq;
4702 isl_aff *aff;
4704 if (!bmap)
4705 return NULL;
4706 eq = isl_basic_map_output_defining_equality(bmap, pos, &div, &ineq);
4707 if (eq >= bmap->n_eq)
4708 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4709 "unable to find suitable equality", return NULL);
4710 aff = extract_aff_from_equality(bmap, pos, eq, div, ineq, ma);
4712 aff = isl_aff_remove_unused_divs(aff);
4713 return aff;
4716 /* Given a basic map where each output dimension is defined
4717 * in terms of the parameters and input dimensions using an equality,
4718 * extract an isl_multi_aff that expresses the output dimensions in terms
4719 * of the parameters and input dimensions.
4721 static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map(
4722 __isl_take isl_basic_map *bmap)
4724 int i;
4725 isl_size n_out;
4726 isl_multi_aff *ma;
4728 if (!bmap)
4729 return NULL;
4731 ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap));
4732 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4733 if (n_out < 0)
4734 ma = isl_multi_aff_free(ma);
4736 for (i = 0; i < n_out; ++i) {
4737 isl_aff *aff;
4739 aff = extract_isl_aff_from_basic_map(bmap, i, ma);
4740 ma = isl_multi_aff_set_aff(ma, i, aff);
4743 isl_basic_map_free(bmap);
4745 return ma;
4748 /* Given a basic set where each set dimension is defined
4749 * in terms of the parameters using an equality,
4750 * extract an isl_multi_aff that expresses the set dimensions in terms
4751 * of the parameters.
4753 __isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities(
4754 __isl_take isl_basic_set *bset)
4756 return extract_isl_multi_aff_from_basic_map(bset);
4759 /* Create an isl_pw_multi_aff that is equivalent to
4760 * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain).
4761 * The given basic map is such that each output dimension is defined
4762 * in terms of the parameters and input dimensions using an equality.
4764 * Since some applications expect the result of isl_pw_multi_aff_from_map
4765 * to only contain integer affine expressions, we compute the floor
4766 * of the expression before returning.
4768 * Remove all constraints involving local variables without
4769 * an explicit representation (resulting in the removal of those
4770 * local variables) prior to the actual extraction to ensure
4771 * that the local spaces in which the resulting affine expressions
4772 * are created do not contain any unknown local variables.
4773 * Removing such constraints is safe because constraints involving
4774 * unknown local variables are not used to determine whether
4775 * a basic map is obviously single-valued.
4777 static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map(
4778 __isl_take isl_set *domain, __isl_take isl_basic_map *bmap)
4780 isl_multi_aff *ma;
4782 bmap = isl_basic_map_drop_constraint_involving_unknown_divs(bmap);
4783 ma = extract_isl_multi_aff_from_basic_map(bmap);
4784 ma = isl_multi_aff_floor(ma);
4785 return isl_pw_multi_aff_alloc(domain, ma);
4788 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
4789 * This obviously only works if the input "map" is single-valued.
4790 * If so, we compute the lexicographic minimum of the image in the form
4791 * of an isl_pw_multi_aff. Since the image is unique, it is equal
4792 * to its lexicographic minimum.
4793 * If the input is not single-valued, we produce an error.
4795 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_base(
4796 __isl_take isl_map *map)
4798 int i;
4799 int sv;
4800 isl_pw_multi_aff *pma;
4802 sv = isl_map_is_single_valued(map);
4803 if (sv < 0)
4804 goto error;
4805 if (!sv)
4806 isl_die(isl_map_get_ctx(map), isl_error_invalid,
4807 "map is not single-valued", goto error);
4808 map = isl_map_make_disjoint(map);
4809 if (!map)
4810 return NULL;
4812 pma = isl_pw_multi_aff_empty(isl_map_get_space(map));
4814 for (i = 0; i < map->n; ++i) {
4815 isl_pw_multi_aff *pma_i;
4816 isl_basic_map *bmap;
4817 bmap = isl_basic_map_copy(map->p[i]);
4818 pma_i = isl_basic_map_lexmin_pw_multi_aff(bmap);
4819 pma = isl_pw_multi_aff_add_disjoint(pma, pma_i);
4822 isl_map_free(map);
4823 return pma;
4824 error:
4825 isl_map_free(map);
4826 return NULL;
4829 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
4830 * taking into account that the output dimension at position "d"
4831 * can be represented as
4833 * x = floor((e(...) + c1) / m)
4835 * given that constraint "i" is of the form
4837 * e(...) + c1 - m x >= 0
4840 * Let "map" be of the form
4842 * A -> B
4844 * We construct a mapping
4846 * A -> [A -> x = floor(...)]
4848 * apply that to the map, obtaining
4850 * [A -> x = floor(...)] -> B
4852 * and equate dimension "d" to x.
4853 * We then compute a isl_pw_multi_aff representation of the resulting map
4854 * and plug in the mapping above.
4856 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div(
4857 __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i)
4859 isl_ctx *ctx;
4860 isl_space *space = NULL;
4861 isl_local_space *ls;
4862 isl_multi_aff *ma;
4863 isl_aff *aff;
4864 isl_vec *v;
4865 isl_map *insert;
4866 int offset;
4867 isl_size n;
4868 isl_size n_in;
4869 isl_pw_multi_aff *pma;
4870 isl_bool is_set;
4872 is_set = isl_map_is_set(map);
4873 if (is_set < 0)
4874 goto error;
4876 offset = isl_basic_map_offset(hull, isl_dim_out);
4877 ctx = isl_map_get_ctx(map);
4878 space = isl_space_domain(isl_map_get_space(map));
4879 n_in = isl_space_dim(space, isl_dim_set);
4880 n = isl_space_dim(space, isl_dim_all);
4881 if (n_in < 0 || n < 0)
4882 goto error;
4884 v = isl_vec_alloc(ctx, 1 + 1 + n);
4885 if (v) {
4886 isl_int_neg(v->el[0], hull->ineq[i][offset + d]);
4887 isl_seq_cpy(v->el + 1, hull->ineq[i], 1 + n);
4889 isl_basic_map_free(hull);
4891 ls = isl_local_space_from_space(isl_space_copy(space));
4892 aff = isl_aff_alloc_vec(ls, v);
4893 aff = isl_aff_floor(aff);
4894 if (is_set) {
4895 isl_space_free(space);
4896 ma = isl_multi_aff_from_aff(aff);
4897 } else {
4898 ma = isl_multi_aff_identity(isl_space_map_from_set(space));
4899 ma = isl_multi_aff_range_product(ma,
4900 isl_multi_aff_from_aff(aff));
4903 insert = isl_map_from_multi_aff_internal(isl_multi_aff_copy(ma));
4904 map = isl_map_apply_domain(map, insert);
4905 map = isl_map_equate(map, isl_dim_in, n_in, isl_dim_out, d);
4906 pma = isl_pw_multi_aff_from_map(map);
4907 pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma);
4909 return pma;
4910 error:
4911 isl_space_free(space);
4912 isl_map_free(map);
4913 isl_basic_map_free(hull);
4914 return NULL;
4917 /* Is constraint "c" of the form
4919 * e(...) + c1 - m x >= 0
4921 * or
4923 * -e(...) + c2 + m x >= 0
4925 * where m > 1 and e only depends on parameters and input dimemnsions?
4927 * "offset" is the offset of the output dimensions
4928 * "pos" is the position of output dimension x.
4930 static int is_potential_div_constraint(isl_int *c, int offset, int d, int total)
4932 if (isl_int_is_zero(c[offset + d]))
4933 return 0;
4934 if (isl_int_is_one(c[offset + d]))
4935 return 0;
4936 if (isl_int_is_negone(c[offset + d]))
4937 return 0;
4938 if (isl_seq_first_non_zero(c + offset, d) != -1)
4939 return 0;
4940 if (isl_seq_first_non_zero(c + offset + d + 1,
4941 total - (offset + d + 1)) != -1)
4942 return 0;
4943 return 1;
4946 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
4948 * As a special case, we first check if there is any pair of constraints,
4949 * shared by all the basic maps in "map" that force a given dimension
4950 * to be equal to the floor of some affine combination of the input dimensions.
4952 * In particular, if we can find two constraints
4954 * e(...) + c1 - m x >= 0 i.e., m x <= e(...) + c1
4956 * and
4958 * -e(...) + c2 + m x >= 0 i.e., m x >= e(...) - c2
4960 * where m > 1 and e only depends on parameters and input dimemnsions,
4961 * and such that
4963 * c1 + c2 < m i.e., -c2 >= c1 - (m - 1)
4965 * then we know that we can take
4967 * x = floor((e(...) + c1) / m)
4969 * without having to perform any computation.
4971 * Note that we know that
4973 * c1 + c2 >= 1
4975 * If c1 + c2 were 0, then we would have detected an equality during
4976 * simplification. If c1 + c2 were negative, then we would have detected
4977 * a contradiction.
4979 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_div(
4980 __isl_take isl_map *map)
4982 int d;
4983 isl_size dim;
4984 int i, j, n;
4985 int offset;
4986 isl_size total;
4987 isl_int sum;
4988 isl_basic_map *hull;
4990 hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
4991 dim = isl_map_dim(map, isl_dim_out);
4992 total = isl_basic_map_dim(hull, isl_dim_all);
4993 if (dim < 0 || total < 0)
4994 goto error;
4996 isl_int_init(sum);
4997 offset = isl_basic_map_offset(hull, isl_dim_out);
4998 n = hull->n_ineq;
4999 for (d = 0; d < dim; ++d) {
5000 for (i = 0; i < n; ++i) {
5001 if (!is_potential_div_constraint(hull->ineq[i],
5002 offset, d, 1 + total))
5003 continue;
5004 for (j = i + 1; j < n; ++j) {
5005 if (!isl_seq_is_neg(hull->ineq[i] + 1,
5006 hull->ineq[j] + 1, total))
5007 continue;
5008 isl_int_add(sum, hull->ineq[i][0],
5009 hull->ineq[j][0]);
5010 if (isl_int_abs_lt(sum,
5011 hull->ineq[i][offset + d]))
5012 break;
5015 if (j >= n)
5016 continue;
5017 isl_int_clear(sum);
5018 if (isl_int_is_pos(hull->ineq[j][offset + d]))
5019 j = i;
5020 return pw_multi_aff_from_map_div(map, hull, d, j);
5023 isl_int_clear(sum);
5024 isl_basic_map_free(hull);
5025 return pw_multi_aff_from_map_base(map);
5026 error:
5027 isl_map_free(map);
5028 isl_basic_map_free(hull);
5029 return NULL;
5032 /* Given an affine expression
5034 * [A -> B] -> f(A,B)
5036 * construct an isl_multi_aff
5038 * [A -> B] -> B'
5040 * such that dimension "d" in B' is set to "aff" and the remaining
5041 * dimensions are set equal to the corresponding dimensions in B.
5042 * "n_in" is the dimension of the space A.
5043 * "n_out" is the dimension of the space B.
5045 * If "is_set" is set, then the affine expression is of the form
5047 * [B] -> f(B)
5049 * and we construct an isl_multi_aff
5051 * B -> B'
5053 static __isl_give isl_multi_aff *range_map(__isl_take isl_aff *aff, int d,
5054 unsigned n_in, unsigned n_out, int is_set)
5056 int i;
5057 isl_multi_aff *ma;
5058 isl_space *space, *space2;
5059 isl_local_space *ls;
5061 space = isl_aff_get_domain_space(aff);
5062 ls = isl_local_space_from_space(isl_space_copy(space));
5063 space2 = isl_space_copy(space);
5064 if (!is_set)
5065 space2 = isl_space_range(isl_space_unwrap(space2));
5066 space = isl_space_map_from_domain_and_range(space, space2);
5067 ma = isl_multi_aff_alloc(space);
5068 ma = isl_multi_aff_set_aff(ma, d, aff);
5070 for (i = 0; i < n_out; ++i) {
5071 if (i == d)
5072 continue;
5073 aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
5074 isl_dim_set, n_in + i);
5075 ma = isl_multi_aff_set_aff(ma, i, aff);
5078 isl_local_space_free(ls);
5080 return ma;
5083 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
5084 * taking into account that the dimension at position "d" can be written as
5086 * x = m a + f(..) (1)
5088 * where m is equal to "gcd".
5089 * "i" is the index of the equality in "hull" that defines f(..).
5090 * In particular, the equality is of the form
5092 * f(..) - x + m g(existentials) = 0
5094 * or
5096 * -f(..) + x + m g(existentials) = 0
5098 * We basically plug (1) into "map", resulting in a map with "a"
5099 * in the range instead of "x". The corresponding isl_pw_multi_aff
5100 * defining "a" is then plugged back into (1) to obtain a definition for "x".
5102 * Specifically, given the input map
5104 * A -> B
5106 * We first wrap it into a set
5108 * [A -> B]
5110 * and define (1) on top of the corresponding space, resulting in "aff".
5111 * We use this to create an isl_multi_aff that maps the output position "d"
5112 * from "a" to "x", leaving all other (intput and output) dimensions unchanged.
5113 * We plug this into the wrapped map, unwrap the result and compute the
5114 * corresponding isl_pw_multi_aff.
5115 * The result is an expression
5117 * A -> T(A)
5119 * We adjust that to
5121 * A -> [A -> T(A)]
5123 * so that we can plug that into "aff", after extending the latter to
5124 * a mapping
5126 * [A -> B] -> B'
5129 * If "map" is actually a set, then there is no "A" space, meaning
5130 * that we do not need to perform any wrapping, and that the result
5131 * of the recursive call is of the form
5133 * [T]
5135 * which is plugged into a mapping of the form
5137 * B -> B'
5139 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
5140 __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i,
5141 isl_int gcd)
5143 isl_set *set;
5144 isl_space *space;
5145 isl_local_space *ls;
5146 isl_aff *aff;
5147 isl_multi_aff *ma;
5148 isl_pw_multi_aff *pma, *id;
5149 isl_size n_in;
5150 unsigned o_out;
5151 isl_size n_out;
5152 isl_bool is_set;
5154 is_set = isl_map_is_set(map);
5155 if (is_set < 0)
5156 goto error;
5158 n_in = isl_basic_map_dim(hull, isl_dim_in);
5159 n_out = isl_basic_map_dim(hull, isl_dim_out);
5160 if (n_in < 0 || n_out < 0)
5161 goto error;
5162 o_out = isl_basic_map_offset(hull, isl_dim_out);
5164 if (is_set)
5165 set = map;
5166 else
5167 set = isl_map_wrap(map);
5168 space = isl_space_map_from_set(isl_set_get_space(set));
5169 ma = isl_multi_aff_identity(space);
5170 ls = isl_local_space_from_space(isl_set_get_space(set));
5171 aff = isl_aff_alloc(ls);
5172 if (aff) {
5173 isl_int_set_si(aff->v->el[0], 1);
5174 if (isl_int_is_one(hull->eq[i][o_out + d]))
5175 isl_seq_neg(aff->v->el + 1, hull->eq[i],
5176 aff->v->size - 1);
5177 else
5178 isl_seq_cpy(aff->v->el + 1, hull->eq[i],
5179 aff->v->size - 1);
5180 isl_int_set(aff->v->el[1 + o_out + d], gcd);
5182 ma = isl_multi_aff_set_aff(ma, n_in + d, isl_aff_copy(aff));
5183 set = isl_set_preimage_multi_aff(set, ma);
5185 ma = range_map(aff, d, n_in, n_out, is_set);
5187 if (is_set)
5188 map = set;
5189 else
5190 map = isl_set_unwrap(set);
5191 pma = isl_pw_multi_aff_from_map(map);
5193 if (!is_set) {
5194 space = isl_pw_multi_aff_get_domain_space(pma);
5195 space = isl_space_map_from_set(space);
5196 id = isl_pw_multi_aff_identity(space);
5197 pma = isl_pw_multi_aff_range_product(id, pma);
5199 id = isl_pw_multi_aff_from_multi_aff(ma);
5200 pma = isl_pw_multi_aff_pullback_pw_multi_aff(id, pma);
5202 isl_basic_map_free(hull);
5203 return pma;
5204 error:
5205 isl_map_free(map);
5206 isl_basic_map_free(hull);
5207 return NULL;
5210 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5211 * "hull" contains the equalities valid for "map".
5213 * Check if any of the output dimensions is "strided".
5214 * That is, we check if it can be written as
5216 * x = m a + f(..)
5218 * with m greater than 1, a some combination of existentially quantified
5219 * variables and f an expression in the parameters and input dimensions.
5220 * If so, we remove the stride in pw_multi_aff_from_map_stride.
5222 * Otherwise, we continue with pw_multi_aff_from_map_check_div for a further
5223 * special case.
5225 static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_strides(
5226 __isl_take isl_map *map, __isl_take isl_basic_map *hull)
5228 int i, j;
5229 isl_size n_out;
5230 unsigned o_out;
5231 isl_size n_div;
5232 unsigned o_div;
5233 isl_int gcd;
5235 n_div = isl_basic_map_dim(hull, isl_dim_div);
5236 n_out = isl_basic_map_dim(hull, isl_dim_out);
5237 if (n_div < 0 || n_out < 0)
5238 goto error;
5240 if (n_div == 0) {
5241 isl_basic_map_free(hull);
5242 return pw_multi_aff_from_map_check_div(map);
5245 isl_int_init(gcd);
5247 o_div = isl_basic_map_offset(hull, isl_dim_div);
5248 o_out = isl_basic_map_offset(hull, isl_dim_out);
5250 for (i = 0; i < n_out; ++i) {
5251 for (j = 0; j < hull->n_eq; ++j) {
5252 isl_int *eq = hull->eq[j];
5253 isl_pw_multi_aff *res;
5255 if (!isl_int_is_one(eq[o_out + i]) &&
5256 !isl_int_is_negone(eq[o_out + i]))
5257 continue;
5258 if (isl_seq_first_non_zero(eq + o_out, i) != -1)
5259 continue;
5260 if (isl_seq_first_non_zero(eq + o_out + i + 1,
5261 n_out - (i + 1)) != -1)
5262 continue;
5263 isl_seq_gcd(eq + o_div, n_div, &gcd);
5264 if (isl_int_is_zero(gcd))
5265 continue;
5266 if (isl_int_is_one(gcd))
5267 continue;
5269 res = pw_multi_aff_from_map_stride(map, hull,
5270 i, j, gcd);
5271 isl_int_clear(gcd);
5272 return res;
5276 isl_int_clear(gcd);
5277 isl_basic_map_free(hull);
5278 return pw_multi_aff_from_map_check_div(map);
5279 error:
5280 isl_map_free(map);
5281 isl_basic_map_free(hull);
5282 return NULL;
5285 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5287 * As a special case, we first check if all output dimensions are uniquely
5288 * defined in terms of the parameters and input dimensions over the entire
5289 * domain. If so, we extract the desired isl_pw_multi_aff directly
5290 * from the affine hull of "map" and its domain.
5292 * Otherwise, continue with pw_multi_aff_from_map_check_strides for more
5293 * special cases.
5295 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
5297 isl_bool sv;
5298 isl_size n;
5299 isl_basic_map *hull;
5301 n = isl_map_n_basic_map(map);
5302 if (n < 0)
5303 goto error;
5305 if (n == 1) {
5306 hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
5307 hull = isl_basic_map_plain_affine_hull(hull);
5308 sv = isl_basic_map_plain_is_single_valued(hull);
5309 if (sv >= 0 && sv)
5310 return plain_pw_multi_aff_from_map(isl_map_domain(map),
5311 hull);
5312 isl_basic_map_free(hull);
5314 map = isl_map_detect_equalities(map);
5315 hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
5316 sv = isl_basic_map_plain_is_single_valued(hull);
5317 if (sv >= 0 && sv)
5318 return plain_pw_multi_aff_from_map(isl_map_domain(map), hull);
5319 if (sv >= 0)
5320 return pw_multi_aff_from_map_check_strides(map, hull);
5321 isl_basic_map_free(hull);
5322 error:
5323 isl_map_free(map);
5324 return NULL;
5327 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(__isl_take isl_set *set)
5329 return isl_pw_multi_aff_from_map(set);
5332 /* Convert "map" into an isl_pw_multi_aff (if possible) and
5333 * add it to *user.
5335 static isl_stat pw_multi_aff_from_map(__isl_take isl_map *map, void *user)
5337 isl_union_pw_multi_aff **upma = user;
5338 isl_pw_multi_aff *pma;
5340 pma = isl_pw_multi_aff_from_map(map);
5341 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
5343 return *upma ? isl_stat_ok : isl_stat_error;
5346 /* Create an isl_union_pw_multi_aff with the given isl_aff on a universe
5347 * domain.
5349 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff(
5350 __isl_take isl_aff *aff)
5352 isl_multi_aff *ma;
5353 isl_pw_multi_aff *pma;
5355 ma = isl_multi_aff_from_aff(aff);
5356 pma = isl_pw_multi_aff_from_multi_aff(ma);
5357 return isl_union_pw_multi_aff_from_pw_multi_aff(pma);
5360 /* Try and create an isl_union_pw_multi_aff that is equivalent
5361 * to the given isl_union_map.
5362 * The isl_union_map is required to be single-valued in each space.
5363 * Otherwise, an error is produced.
5365 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map(
5366 __isl_take isl_union_map *umap)
5368 isl_space *space;
5369 isl_union_pw_multi_aff *upma;
5371 space = isl_union_map_get_space(umap);
5372 upma = isl_union_pw_multi_aff_empty(space);
5373 if (isl_union_map_foreach_map(umap, &pw_multi_aff_from_map, &upma) < 0)
5374 upma = isl_union_pw_multi_aff_free(upma);
5375 isl_union_map_free(umap);
5377 return upma;
5380 /* Try and create an isl_union_pw_multi_aff that is equivalent
5381 * to the given isl_union_set.
5382 * The isl_union_set is required to be a singleton in each space.
5383 * Otherwise, an error is produced.
5385 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set(
5386 __isl_take isl_union_set *uset)
5388 return isl_union_pw_multi_aff_from_union_map(uset);
5391 /* Return the piecewise affine expression "set ? 1 : 0".
5393 __isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set)
5395 isl_pw_aff *pa;
5396 isl_space *space = isl_set_get_space(set);
5397 isl_local_space *ls = isl_local_space_from_space(space);
5398 isl_aff *zero = isl_aff_zero_on_domain(isl_local_space_copy(ls));
5399 isl_aff *one = isl_aff_zero_on_domain(ls);
5401 one = isl_aff_add_constant_si(one, 1);
5402 pa = isl_pw_aff_alloc(isl_set_copy(set), one);
5403 set = isl_set_complement(set);
5404 pa = isl_pw_aff_add_disjoint(pa, isl_pw_aff_alloc(set, zero));
5406 return pa;
5409 /* Plug in "subs" for dimension "type", "pos" of "aff".
5411 * Let i be the dimension to replace and let "subs" be of the form
5413 * f/d
5415 * and "aff" of the form
5417 * (a i + g)/m
5419 * The result is
5421 * (a f + d g')/(m d)
5423 * where g' is the result of plugging in "subs" in each of the integer
5424 * divisions in g.
5426 __isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *aff,
5427 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
5429 isl_ctx *ctx;
5430 isl_int v;
5431 isl_size n_div;
5433 aff = isl_aff_cow(aff);
5434 if (!aff || !subs)
5435 return isl_aff_free(aff);
5437 ctx = isl_aff_get_ctx(aff);
5438 if (!isl_space_is_equal(aff->ls->dim, subs->ls->dim))
5439 isl_die(ctx, isl_error_invalid,
5440 "spaces don't match", return isl_aff_free(aff));
5441 n_div = isl_local_space_dim(subs->ls, isl_dim_div);
5442 if (n_div < 0)
5443 return isl_aff_free(aff);
5444 if (n_div != 0)
5445 isl_die(ctx, isl_error_unsupported,
5446 "cannot handle divs yet", return isl_aff_free(aff));
5448 aff->ls = isl_local_space_substitute(aff->ls, type, pos, subs);
5449 if (!aff->ls)
5450 return isl_aff_free(aff);
5452 aff->v = isl_vec_cow(aff->v);
5453 if (!aff->v)
5454 return isl_aff_free(aff);
5456 pos += isl_local_space_offset(aff->ls, type);
5458 isl_int_init(v);
5459 isl_seq_substitute(aff->v->el, pos, subs->v->el,
5460 aff->v->size, subs->v->size, v);
5461 isl_int_clear(v);
5463 return aff;
5466 /* Plug in "subs" for dimension "type", "pos" in each of the affine
5467 * expressions in "maff".
5469 __isl_give isl_multi_aff *isl_multi_aff_substitute(
5470 __isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos,
5471 __isl_keep isl_aff *subs)
5473 int i;
5475 maff = isl_multi_aff_cow(maff);
5476 if (!maff || !subs)
5477 return isl_multi_aff_free(maff);
5479 if (type == isl_dim_in)
5480 type = isl_dim_set;
5482 for (i = 0; i < maff->n; ++i) {
5483 maff->u.p[i] = isl_aff_substitute(maff->u.p[i],
5484 type, pos, subs);
5485 if (!maff->u.p[i])
5486 return isl_multi_aff_free(maff);
5489 return maff;
5492 /* Plug in "subs" for dimension "type", "pos" of "pma".
5494 * pma is of the form
5496 * A_i(v) -> M_i(v)
5498 * while subs is of the form
5500 * v' = B_j(v) -> S_j
5502 * Each pair i,j such that C_ij = A_i \cap B_i is non-empty
5503 * has a contribution in the result, in particular
5505 * C_ij(S_j) -> M_i(S_j)
5507 * Note that plugging in S_j in C_ij may also result in an empty set
5508 * and this contribution should simply be discarded.
5510 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute(
5511 __isl_take isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned pos,
5512 __isl_keep isl_pw_aff *subs)
5514 int i, j, n;
5515 isl_pw_multi_aff *res;
5517 if (!pma || !subs)
5518 return isl_pw_multi_aff_free(pma);
5520 n = pma->n * subs->n;
5521 res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma->dim), n);
5523 for (i = 0; i < pma->n; ++i) {
5524 for (j = 0; j < subs->n; ++j) {
5525 isl_set *common;
5526 isl_multi_aff *res_ij;
5527 int empty;
5529 common = isl_set_intersect(
5530 isl_set_copy(pma->p[i].set),
5531 isl_set_copy(subs->p[j].set));
5532 common = isl_set_substitute(common,
5533 type, pos, subs->p[j].aff);
5534 empty = isl_set_plain_is_empty(common);
5535 if (empty < 0 || empty) {
5536 isl_set_free(common);
5537 if (empty < 0)
5538 goto error;
5539 continue;
5542 res_ij = isl_multi_aff_substitute(
5543 isl_multi_aff_copy(pma->p[i].maff),
5544 type, pos, subs->p[j].aff);
5546 res = isl_pw_multi_aff_add_piece(res, common, res_ij);
5550 isl_pw_multi_aff_free(pma);
5551 return res;
5552 error:
5553 isl_pw_multi_aff_free(pma);
5554 isl_pw_multi_aff_free(res);
5555 return NULL;
5558 /* Compute the preimage of a range of dimensions in the affine expression "src"
5559 * under "ma" and put the result in "dst". The number of dimensions in "src"
5560 * that precede the range is given by "n_before". The number of dimensions
5561 * in the range is given by the number of output dimensions of "ma".
5562 * The number of dimensions that follow the range is given by "n_after".
5563 * If "has_denom" is set (to one),
5564 * then "src" and "dst" have an extra initial denominator.
5565 * "n_div_ma" is the number of existentials in "ma"
5566 * "n_div_bset" is the number of existentials in "src"
5567 * The resulting "dst" (which is assumed to have been allocated by
5568 * the caller) contains coefficients for both sets of existentials,
5569 * first those in "ma" and then those in "src".
5570 * f, c1, c2 and g are temporary objects that have been initialized
5571 * by the caller.
5573 * Let src represent the expression
5575 * (a(p) + f_u u + b v + f_w w + c(divs))/d
5577 * and let ma represent the expressions
5579 * v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i
5581 * We start out with the following expression for dst:
5583 * (a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d
5585 * with the multiplication factor f initially equal to 1
5586 * and f \sum_i b_i v_i kept separately.
5587 * For each x_i that we substitute, we multiply the numerator
5588 * (and denominator) of dst by c_1 = m_i and add the numerator
5589 * of the x_i expression multiplied by c_2 = f b_i,
5590 * after removing the common factors of c_1 and c_2.
5591 * The multiplication factor f also needs to be multiplied by c_1
5592 * for the next x_j, j > i.
5594 isl_stat isl_seq_preimage(isl_int *dst, isl_int *src,
5595 __isl_keep isl_multi_aff *ma, int n_before, int n_after,
5596 int n_div_ma, int n_div_bmap,
5597 isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom)
5599 int i;
5600 isl_size n_param, n_in, n_out;
5601 int o_dst, o_src;
5603 n_param = isl_multi_aff_dim(ma, isl_dim_param);
5604 n_in = isl_multi_aff_dim(ma, isl_dim_in);
5605 n_out = isl_multi_aff_dim(ma, isl_dim_out);
5606 if (n_param < 0 || n_in < 0 || n_out < 0)
5607 return isl_stat_error;
5609 isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before);
5610 o_dst = o_src = has_denom + 1 + n_param + n_before;
5611 isl_seq_clr(dst + o_dst, n_in);
5612 o_dst += n_in;
5613 o_src += n_out;
5614 isl_seq_cpy(dst + o_dst, src + o_src, n_after);
5615 o_dst += n_after;
5616 o_src += n_after;
5617 isl_seq_clr(dst + o_dst, n_div_ma);
5618 o_dst += n_div_ma;
5619 isl_seq_cpy(dst + o_dst, src + o_src, n_div_bmap);
5621 isl_int_set_si(f, 1);
5623 for (i = 0; i < n_out; ++i) {
5624 int offset = has_denom + 1 + n_param + n_before + i;
5626 if (isl_int_is_zero(src[offset]))
5627 continue;
5628 isl_int_set(c1, ma->u.p[i]->v->el[0]);
5629 isl_int_mul(c2, f, src[offset]);
5630 isl_int_gcd(g, c1, c2);
5631 isl_int_divexact(c1, c1, g);
5632 isl_int_divexact(c2, c2, g);
5634 isl_int_mul(f, f, c1);
5635 o_dst = has_denom;
5636 o_src = 1;
5637 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5638 c2, ma->u.p[i]->v->el + o_src, 1 + n_param);
5639 o_dst += 1 + n_param;
5640 o_src += 1 + n_param;
5641 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_before);
5642 o_dst += n_before;
5643 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5644 c2, ma->u.p[i]->v->el + o_src, n_in);
5645 o_dst += n_in;
5646 o_src += n_in;
5647 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_after);
5648 o_dst += n_after;
5649 isl_seq_combine(dst + o_dst, c1, dst + o_dst,
5650 c2, ma->u.p[i]->v->el + o_src, n_div_ma);
5651 o_dst += n_div_ma;
5652 o_src += n_div_ma;
5653 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_div_bmap);
5654 if (has_denom)
5655 isl_int_mul(dst[0], dst[0], c1);
5658 return isl_stat_ok;
5661 /* Compute the pullback of "aff" by the function represented by "ma".
5662 * In other words, plug in "ma" in "aff". The result is an affine expression
5663 * defined over the domain space of "ma".
5665 * If "aff" is represented by
5667 * (a(p) + b x + c(divs))/d
5669 * and ma is represented by
5671 * x = D(p) + F(y) + G(divs')
5673 * then the result is
5675 * (a(p) + b D(p) + b F(y) + b G(divs') + c(divs))/d
5677 * The divs in the local space of the input are similarly adjusted
5678 * through a call to isl_local_space_preimage_multi_aff.
5680 __isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
5681 __isl_take isl_multi_aff *ma)
5683 isl_aff *res = NULL;
5684 isl_local_space *ls;
5685 isl_size n_div_aff, n_div_ma;
5686 isl_int f, c1, c2, g;
5688 ma = isl_multi_aff_align_divs(ma);
5689 if (!aff || !ma)
5690 goto error;
5692 n_div_aff = isl_aff_dim(aff, isl_dim_div);
5693 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
5694 if (n_div_aff < 0 || n_div_ma < 0)
5695 goto error;
5697 ls = isl_aff_get_domain_local_space(aff);
5698 ls = isl_local_space_preimage_multi_aff(ls, isl_multi_aff_copy(ma));
5699 res = isl_aff_alloc(ls);
5700 if (!res)
5701 goto error;
5703 isl_int_init(f);
5704 isl_int_init(c1);
5705 isl_int_init(c2);
5706 isl_int_init(g);
5708 if (isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0,
5709 n_div_ma, n_div_aff, f, c1, c2, g, 1) < 0)
5710 res = isl_aff_free(res);
5712 isl_int_clear(f);
5713 isl_int_clear(c1);
5714 isl_int_clear(c2);
5715 isl_int_clear(g);
5717 isl_aff_free(aff);
5718 isl_multi_aff_free(ma);
5719 res = isl_aff_normalize(res);
5720 return res;
5721 error:
5722 isl_aff_free(aff);
5723 isl_multi_aff_free(ma);
5724 isl_aff_free(res);
5725 return NULL;
5728 /* Compute the pullback of "aff1" by the function represented by "aff2".
5729 * In other words, plug in "aff2" in "aff1". The result is an affine expression
5730 * defined over the domain space of "aff1".
5732 * The domain of "aff1" should match the range of "aff2", which means
5733 * that it should be single-dimensional.
5735 __isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
5736 __isl_take isl_aff *aff2)
5738 isl_multi_aff *ma;
5740 ma = isl_multi_aff_from_aff(aff2);
5741 return isl_aff_pullback_multi_aff(aff1, ma);
5744 /* Compute the pullback of "ma1" by the function represented by "ma2".
5745 * In other words, plug in "ma2" in "ma1".
5747 * The parameters of "ma1" and "ma2" are assumed to have been aligned.
5749 static __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff_aligned(
5750 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
5752 int i;
5753 isl_space *space = NULL;
5755 ma2 = isl_multi_aff_align_divs(ma2);
5756 ma1 = isl_multi_aff_cow(ma1);
5757 if (!ma1 || !ma2)
5758 goto error;
5760 space = isl_space_join(isl_multi_aff_get_space(ma2),
5761 isl_multi_aff_get_space(ma1));
5763 for (i = 0; i < ma1->n; ++i) {
5764 ma1->u.p[i] = isl_aff_pullback_multi_aff(ma1->u.p[i],
5765 isl_multi_aff_copy(ma2));
5766 if (!ma1->u.p[i])
5767 goto error;
5770 ma1 = isl_multi_aff_reset_space(ma1, space);
5771 isl_multi_aff_free(ma2);
5772 return ma1;
5773 error:
5774 isl_space_free(space);
5775 isl_multi_aff_free(ma2);
5776 isl_multi_aff_free(ma1);
5777 return NULL;
5780 /* Compute the pullback of "ma1" by the function represented by "ma2".
5781 * In other words, plug in "ma2" in "ma1".
5783 __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
5784 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
5786 return isl_multi_aff_align_params_multi_multi_and(ma1, ma2,
5787 &isl_multi_aff_pullback_multi_aff_aligned);
5790 /* Extend the local space of "dst" to include the divs
5791 * in the local space of "src".
5793 * If "src" does not have any divs or if the local spaces of "dst" and
5794 * "src" are the same, then no extension is required.
5796 __isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst,
5797 __isl_keep isl_aff *src)
5799 isl_ctx *ctx;
5800 isl_size src_n_div, dst_n_div;
5801 int *exp1 = NULL;
5802 int *exp2 = NULL;
5803 isl_bool equal;
5804 isl_mat *div;
5806 if (!src || !dst)
5807 return isl_aff_free(dst);
5809 ctx = isl_aff_get_ctx(src);
5810 equal = isl_local_space_has_equal_space(src->ls, dst->ls);
5811 if (equal < 0)
5812 return isl_aff_free(dst);
5813 if (!equal)
5814 isl_die(ctx, isl_error_invalid,
5815 "spaces don't match", goto error);
5817 src_n_div = isl_local_space_dim(src->ls, isl_dim_div);
5818 dst_n_div = isl_local_space_dim(dst->ls, isl_dim_div);
5819 if (src_n_div == 0)
5820 return dst;
5821 equal = isl_local_space_is_equal(src->ls, dst->ls);
5822 if (equal < 0 || src_n_div < 0 || dst_n_div < 0)
5823 return isl_aff_free(dst);
5824 if (equal)
5825 return dst;
5827 exp1 = isl_alloc_array(ctx, int, src_n_div);
5828 exp2 = isl_alloc_array(ctx, int, dst_n_div);
5829 if (!exp1 || (dst_n_div && !exp2))
5830 goto error;
5832 div = isl_merge_divs(src->ls->div, dst->ls->div, exp1, exp2);
5833 dst = isl_aff_expand_divs(dst, div, exp2);
5834 free(exp1);
5835 free(exp2);
5837 return dst;
5838 error:
5839 free(exp1);
5840 free(exp2);
5841 return isl_aff_free(dst);
5844 /* Adjust the local spaces of the affine expressions in "maff"
5845 * such that they all have the save divs.
5847 __isl_give isl_multi_aff *isl_multi_aff_align_divs(
5848 __isl_take isl_multi_aff *maff)
5850 int i;
5852 if (!maff)
5853 return NULL;
5854 if (maff->n == 0)
5855 return maff;
5856 maff = isl_multi_aff_cow(maff);
5857 if (!maff)
5858 return NULL;
5860 for (i = 1; i < maff->n; ++i)
5861 maff->u.p[0] = isl_aff_align_divs(maff->u.p[0], maff->u.p[i]);
5862 for (i = 1; i < maff->n; ++i) {
5863 maff->u.p[i] = isl_aff_align_divs(maff->u.p[i], maff->u.p[0]);
5864 if (!maff->u.p[i])
5865 return isl_multi_aff_free(maff);
5868 return maff;
5871 __isl_give isl_aff *isl_aff_lift(__isl_take isl_aff *aff)
5873 aff = isl_aff_cow(aff);
5874 if (!aff)
5875 return NULL;
5877 aff->ls = isl_local_space_lift(aff->ls);
5878 if (!aff->ls)
5879 return isl_aff_free(aff);
5881 return aff;
5884 /* Lift "maff" to a space with extra dimensions such that the result
5885 * has no more existentially quantified variables.
5886 * If "ls" is not NULL, then *ls is assigned the local space that lies
5887 * at the basis of the lifting applied to "maff".
5889 __isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
5890 __isl_give isl_local_space **ls)
5892 int i;
5893 isl_space *space;
5894 isl_size n_div;
5896 if (ls)
5897 *ls = NULL;
5899 if (!maff)
5900 return NULL;
5902 if (maff->n == 0) {
5903 if (ls) {
5904 isl_space *space = isl_multi_aff_get_domain_space(maff);
5905 *ls = isl_local_space_from_space(space);
5906 if (!*ls)
5907 return isl_multi_aff_free(maff);
5909 return maff;
5912 maff = isl_multi_aff_cow(maff);
5913 maff = isl_multi_aff_align_divs(maff);
5914 if (!maff)
5915 return NULL;
5917 n_div = isl_aff_dim(maff->u.p[0], isl_dim_div);
5918 if (n_div < 0)
5919 return isl_multi_aff_free(maff);
5920 space = isl_multi_aff_get_space(maff);
5921 space = isl_space_lift(isl_space_domain(space), n_div);
5922 space = isl_space_extend_domain_with_range(space,
5923 isl_multi_aff_get_space(maff));
5924 if (!space)
5925 return isl_multi_aff_free(maff);
5926 isl_space_free(maff->space);
5927 maff->space = space;
5929 if (ls) {
5930 *ls = isl_aff_get_domain_local_space(maff->u.p[0]);
5931 if (!*ls)
5932 return isl_multi_aff_free(maff);
5935 for (i = 0; i < maff->n; ++i) {
5936 maff->u.p[i] = isl_aff_lift(maff->u.p[i]);
5937 if (!maff->u.p[i])
5938 goto error;
5941 return maff;
5942 error:
5943 if (ls)
5944 isl_local_space_free(*ls);
5945 return isl_multi_aff_free(maff);
5948 #undef TYPE
5949 #define TYPE isl_pw_multi_aff
5950 static
5951 #include "check_type_range_templ.c"
5953 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma".
5955 __isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
5956 __isl_keep isl_pw_multi_aff *pma, int pos)
5958 int i;
5959 isl_size n_out;
5960 isl_space *space;
5961 isl_pw_aff *pa;
5963 if (isl_pw_multi_aff_check_range(pma, isl_dim_out, pos, 1) < 0)
5964 return NULL;
5966 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
5967 if (n_out < 0)
5968 return NULL;
5970 space = isl_pw_multi_aff_get_space(pma);
5971 space = isl_space_drop_dims(space, isl_dim_out,
5972 pos + 1, n_out - pos - 1);
5973 space = isl_space_drop_dims(space, isl_dim_out, 0, pos);
5975 pa = isl_pw_aff_alloc_size(space, pma->n);
5976 for (i = 0; i < pma->n; ++i) {
5977 isl_aff *aff;
5978 aff = isl_multi_aff_get_aff(pma->p[i].maff, pos);
5979 pa = isl_pw_aff_add_piece(pa, isl_set_copy(pma->p[i].set), aff);
5982 return pa;
5985 /* Return an isl_pw_multi_aff with the given "set" as domain and
5986 * an unnamed zero-dimensional range.
5988 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
5989 __isl_take isl_set *set)
5991 isl_multi_aff *ma;
5992 isl_space *space;
5994 space = isl_set_get_space(set);
5995 space = isl_space_from_domain(space);
5996 ma = isl_multi_aff_zero(space);
5997 return isl_pw_multi_aff_alloc(set, ma);
6000 /* Add an isl_pw_multi_aff with the given "set" as domain and
6001 * an unnamed zero-dimensional range to *user.
6003 static isl_stat add_pw_multi_aff_from_domain(__isl_take isl_set *set,
6004 void *user)
6006 isl_union_pw_multi_aff **upma = user;
6007 isl_pw_multi_aff *pma;
6009 pma = isl_pw_multi_aff_from_domain(set);
6010 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
6012 return isl_stat_ok;
6015 /* Return an isl_union_pw_multi_aff with the given "uset" as domain and
6016 * an unnamed zero-dimensional range.
6018 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
6019 __isl_take isl_union_set *uset)
6021 isl_space *space;
6022 isl_union_pw_multi_aff *upma;
6024 if (!uset)
6025 return NULL;
6027 space = isl_union_set_get_space(uset);
6028 upma = isl_union_pw_multi_aff_empty(space);
6030 if (isl_union_set_foreach_set(uset,
6031 &add_pw_multi_aff_from_domain, &upma) < 0)
6032 goto error;
6034 isl_union_set_free(uset);
6035 return upma;
6036 error:
6037 isl_union_set_free(uset);
6038 isl_union_pw_multi_aff_free(upma);
6039 return NULL;
6042 /* Local data for bin_entry and the callback "fn".
6044 struct isl_union_pw_multi_aff_bin_data {
6045 isl_union_pw_multi_aff *upma2;
6046 isl_union_pw_multi_aff *res;
6047 isl_pw_multi_aff *pma;
6048 isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user);
6051 /* Given an isl_pw_multi_aff from upma1, store it in data->pma
6052 * and call data->fn for each isl_pw_multi_aff in data->upma2.
6054 static isl_stat bin_entry(__isl_take isl_pw_multi_aff *pma, void *user)
6056 struct isl_union_pw_multi_aff_bin_data *data = user;
6057 isl_stat r;
6059 data->pma = pma;
6060 r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma2,
6061 data->fn, data);
6062 isl_pw_multi_aff_free(pma);
6064 return r;
6067 /* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
6068 * The isl_pw_multi_aff from upma1 is stored in data->pma (where data is
6069 * passed as user field) and the isl_pw_multi_aff from upma2 is available
6070 * as *entry. The callback should adjust data->res if desired.
6072 static __isl_give isl_union_pw_multi_aff *bin_op(
6073 __isl_take isl_union_pw_multi_aff *upma1,
6074 __isl_take isl_union_pw_multi_aff *upma2,
6075 isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user))
6077 isl_space *space;
6078 struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn };
6080 space = isl_union_pw_multi_aff_get_space(upma2);
6081 upma1 = isl_union_pw_multi_aff_align_params(upma1, space);
6082 space = isl_union_pw_multi_aff_get_space(upma1);
6083 upma2 = isl_union_pw_multi_aff_align_params(upma2, space);
6085 if (!upma1 || !upma2)
6086 goto error;
6088 data.upma2 = upma2;
6089 data.res = isl_union_pw_multi_aff_alloc_same_size(upma1);
6090 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1,
6091 &bin_entry, &data) < 0)
6092 goto error;
6094 isl_union_pw_multi_aff_free(upma1);
6095 isl_union_pw_multi_aff_free(upma2);
6096 return data.res;
6097 error:
6098 isl_union_pw_multi_aff_free(upma1);
6099 isl_union_pw_multi_aff_free(upma2);
6100 isl_union_pw_multi_aff_free(data.res);
6101 return NULL;
6104 /* Given two aligned isl_pw_multi_affs A -> B and C -> D,
6105 * construct an isl_pw_multi_aff (A * C) -> [B -> D].
6107 static __isl_give isl_pw_multi_aff *pw_multi_aff_range_product(
6108 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6110 isl_space *space;
6112 space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
6113 isl_pw_multi_aff_get_space(pma2));
6114 return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
6115 &isl_multi_aff_range_product);
6118 /* Given two isl_pw_multi_affs A -> B and C -> D,
6119 * construct an isl_pw_multi_aff (A * C) -> [B -> D].
6121 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_product(
6122 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6124 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
6125 &pw_multi_aff_range_product);
6128 /* Given two aligned isl_pw_multi_affs A -> B and C -> D,
6129 * construct an isl_pw_multi_aff (A * C) -> (B, D).
6131 static __isl_give isl_pw_multi_aff *pw_multi_aff_flat_range_product(
6132 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6134 isl_space *space;
6136 space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
6137 isl_pw_multi_aff_get_space(pma2));
6138 space = isl_space_flatten_range(space);
6139 return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
6140 &isl_multi_aff_flat_range_product);
6143 /* Given two isl_pw_multi_affs A -> B and C -> D,
6144 * construct an isl_pw_multi_aff (A * C) -> (B, D).
6146 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
6147 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
6149 return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
6150 &pw_multi_aff_flat_range_product);
6153 /* If data->pma and "pma2" have the same domain space, then compute
6154 * their flat range product and the result to data->res.
6156 static isl_stat flat_range_product_entry(__isl_take isl_pw_multi_aff *pma2,
6157 void *user)
6159 struct isl_union_pw_multi_aff_bin_data *data = user;
6161 if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
6162 pma2->dim, isl_dim_in)) {
6163 isl_pw_multi_aff_free(pma2);
6164 return isl_stat_ok;
6167 pma2 = isl_pw_multi_aff_flat_range_product(
6168 isl_pw_multi_aff_copy(data->pma), pma2);
6170 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
6172 return isl_stat_ok;
6175 /* Given two isl_union_pw_multi_affs A -> B and C -> D,
6176 * construct an isl_union_pw_multi_aff (A * C) -> (B, D).
6178 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_flat_range_product(
6179 __isl_take isl_union_pw_multi_aff *upma1,
6180 __isl_take isl_union_pw_multi_aff *upma2)
6182 return bin_op(upma1, upma2, &flat_range_product_entry);
6185 /* Replace the affine expressions at position "pos" in "pma" by "pa".
6186 * The parameters are assumed to have been aligned.
6188 * The implementation essentially performs an isl_pw_*_on_shared_domain,
6189 * except that it works on two different isl_pw_* types.
6191 static __isl_give isl_pw_multi_aff *pw_multi_aff_set_pw_aff(
6192 __isl_take isl_pw_multi_aff *pma, unsigned pos,
6193 __isl_take isl_pw_aff *pa)
6195 int i, j, n;
6196 isl_pw_multi_aff *res = NULL;
6198 if (!pma || !pa)
6199 goto error;
6201 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_in,
6202 pa->dim, isl_dim_in))
6203 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6204 "domains don't match", goto error);
6205 if (isl_pw_multi_aff_check_range(pma, isl_dim_out, pos, 1) < 0)
6206 goto error;
6208 n = pma->n * pa->n;
6209 res = isl_pw_multi_aff_alloc_size(isl_pw_multi_aff_get_space(pma), n);
6211 for (i = 0; i < pma->n; ++i) {
6212 for (j = 0; j < pa->n; ++j) {
6213 isl_set *common;
6214 isl_multi_aff *res_ij;
6215 int empty;
6217 common = isl_set_intersect(isl_set_copy(pma->p[i].set),
6218 isl_set_copy(pa->p[j].set));
6219 empty = isl_set_plain_is_empty(common);
6220 if (empty < 0 || empty) {
6221 isl_set_free(common);
6222 if (empty < 0)
6223 goto error;
6224 continue;
6227 res_ij = isl_multi_aff_set_aff(
6228 isl_multi_aff_copy(pma->p[i].maff), pos,
6229 isl_aff_copy(pa->p[j].aff));
6230 res_ij = isl_multi_aff_gist(res_ij,
6231 isl_set_copy(common));
6233 res = isl_pw_multi_aff_add_piece(res, common, res_ij);
6237 isl_pw_multi_aff_free(pma);
6238 isl_pw_aff_free(pa);
6239 return res;
6240 error:
6241 isl_pw_multi_aff_free(pma);
6242 isl_pw_aff_free(pa);
6243 return isl_pw_multi_aff_free(res);
6246 /* Replace the affine expressions at position "pos" in "pma" by "pa".
6248 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
6249 __isl_take isl_pw_multi_aff *pma, unsigned pos,
6250 __isl_take isl_pw_aff *pa)
6252 isl_bool equal_params;
6254 if (!pma || !pa)
6255 goto error;
6256 equal_params = isl_space_has_equal_params(pma->dim, pa->dim);
6257 if (equal_params < 0)
6258 goto error;
6259 if (equal_params)
6260 return pw_multi_aff_set_pw_aff(pma, pos, pa);
6261 if (isl_pw_multi_aff_check_named_params(pma) < 0 ||
6262 isl_pw_aff_check_named_params(pa) < 0)
6263 goto error;
6264 pma = isl_pw_multi_aff_align_params(pma, isl_pw_aff_get_space(pa));
6265 pa = isl_pw_aff_align_params(pa, isl_pw_multi_aff_get_space(pma));
6266 return pw_multi_aff_set_pw_aff(pma, pos, pa);
6267 error:
6268 isl_pw_multi_aff_free(pma);
6269 isl_pw_aff_free(pa);
6270 return NULL;
6273 /* Do the parameters of "pa" match those of "space"?
6275 isl_bool isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa,
6276 __isl_keep isl_space *space)
6278 isl_space *pa_space;
6279 isl_bool match;
6281 if (!pa || !space)
6282 return isl_bool_error;
6284 pa_space = isl_pw_aff_get_space(pa);
6286 match = isl_space_has_equal_params(space, pa_space);
6288 isl_space_free(pa_space);
6289 return match;
6292 /* Check that the domain space of "pa" matches "space".
6294 isl_stat isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
6295 __isl_keep isl_space *space)
6297 isl_space *pa_space;
6298 isl_bool match;
6300 if (!pa || !space)
6301 return isl_stat_error;
6303 pa_space = isl_pw_aff_get_space(pa);
6305 match = isl_space_has_equal_params(space, pa_space);
6306 if (match < 0)
6307 goto error;
6308 if (!match)
6309 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
6310 "parameters don't match", goto error);
6311 match = isl_space_tuple_is_equal(space, isl_dim_in,
6312 pa_space, isl_dim_in);
6313 if (match < 0)
6314 goto error;
6315 if (!match)
6316 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
6317 "domains don't match", goto error);
6318 isl_space_free(pa_space);
6319 return isl_stat_ok;
6320 error:
6321 isl_space_free(pa_space);
6322 return isl_stat_error;
6325 #undef BASE
6326 #define BASE pw_aff
6327 #undef DOMBASE
6328 #define DOMBASE set
6330 #include <isl_multi_explicit_domain.c>
6331 #include <isl_multi_pw_aff_explicit_domain.c>
6332 #include <isl_multi_templ.c>
6333 #include <isl_multi_apply_set.c>
6334 #include <isl_multi_arith_templ.c>
6335 #include <isl_multi_bind_templ.c>
6336 #include <isl_multi_bind_domain_templ.c>
6337 #include <isl_multi_coalesce.c>
6338 #include <isl_multi_domain_templ.c>
6339 #include <isl_multi_dim_id_templ.c>
6340 #include <isl_multi_dims.c>
6341 #include <isl_multi_from_base_templ.c>
6342 #include <isl_multi_gist.c>
6343 #include <isl_multi_hash.c>
6344 #include <isl_multi_identity_templ.c>
6345 #include <isl_multi_align_set.c>
6346 #include <isl_multi_intersect.c>
6347 #include <isl_multi_move_dims_templ.c>
6348 #include <isl_multi_nan_templ.c>
6349 #include <isl_multi_param_templ.c>
6350 #include <isl_multi_product_templ.c>
6351 #include <isl_multi_splice_templ.c>
6352 #include <isl_multi_tuple_id_templ.c>
6353 #include <isl_multi_zero_templ.c>
6355 /* Does "mpa" have a non-trivial explicit domain?
6357 * The explicit domain, if present, is trivial if it represents
6358 * an (obviously) universe set.
6360 isl_bool isl_multi_pw_aff_has_non_trivial_domain(
6361 __isl_keep isl_multi_pw_aff *mpa)
6363 if (!mpa)
6364 return isl_bool_error;
6365 if (!isl_multi_pw_aff_has_explicit_domain(mpa))
6366 return isl_bool_false;
6367 return isl_bool_not(isl_set_plain_is_universe(mpa->u.dom));
6370 /* Scale the elements of "pma" by the corresponding elements of "mv".
6372 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
6373 __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv)
6375 int i;
6376 isl_bool equal_params;
6378 pma = isl_pw_multi_aff_cow(pma);
6379 if (!pma || !mv)
6380 goto error;
6381 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
6382 mv->space, isl_dim_set))
6383 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
6384 "spaces don't match", goto error);
6385 equal_params = isl_space_has_equal_params(pma->dim, mv->space);
6386 if (equal_params < 0)
6387 goto error;
6388 if (!equal_params) {
6389 pma = isl_pw_multi_aff_align_params(pma,
6390 isl_multi_val_get_space(mv));
6391 mv = isl_multi_val_align_params(mv,
6392 isl_pw_multi_aff_get_space(pma));
6393 if (!pma || !mv)
6394 goto error;
6397 for (i = 0; i < pma->n; ++i) {
6398 pma->p[i].maff = isl_multi_aff_scale_multi_val(pma->p[i].maff,
6399 isl_multi_val_copy(mv));
6400 if (!pma->p[i].maff)
6401 goto error;
6404 isl_multi_val_free(mv);
6405 return pma;
6406 error:
6407 isl_multi_val_free(mv);
6408 isl_pw_multi_aff_free(pma);
6409 return NULL;
6412 /* This function is called for each entry of an isl_union_pw_multi_aff.
6413 * If the space of the entry matches that of data->mv,
6414 * then apply isl_pw_multi_aff_scale_multi_val and return the result.
6415 * Otherwise, return an empty isl_pw_multi_aff.
6417 static __isl_give isl_pw_multi_aff *union_pw_multi_aff_scale_multi_val_entry(
6418 __isl_take isl_pw_multi_aff *pma, void *user)
6420 isl_multi_val *mv = user;
6422 if (!pma)
6423 return NULL;
6424 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
6425 mv->space, isl_dim_set)) {
6426 isl_space *space = isl_pw_multi_aff_get_space(pma);
6427 isl_pw_multi_aff_free(pma);
6428 return isl_pw_multi_aff_empty(space);
6431 return isl_pw_multi_aff_scale_multi_val(pma, isl_multi_val_copy(mv));
6434 /* Scale the elements of "upma" by the corresponding elements of "mv",
6435 * for those entries that match the space of "mv".
6437 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
6438 __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv)
6440 upma = isl_union_pw_multi_aff_align_params(upma,
6441 isl_multi_val_get_space(mv));
6442 mv = isl_multi_val_align_params(mv,
6443 isl_union_pw_multi_aff_get_space(upma));
6444 if (!upma || !mv)
6445 goto error;
6447 return isl_union_pw_multi_aff_transform(upma,
6448 &union_pw_multi_aff_scale_multi_val_entry, mv);
6450 isl_multi_val_free(mv);
6451 return upma;
6452 error:
6453 isl_multi_val_free(mv);
6454 isl_union_pw_multi_aff_free(upma);
6455 return NULL;
6458 /* Construct and return a piecewise multi affine expression
6459 * in the given space with value zero in each of the output dimensions and
6460 * a universe domain.
6462 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(__isl_take isl_space *space)
6464 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_zero(space));
6467 /* Construct and return a piecewise multi affine expression
6468 * that is equal to the given piecewise affine expression.
6470 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff(
6471 __isl_take isl_pw_aff *pa)
6473 int i;
6474 isl_space *space;
6475 isl_pw_multi_aff *pma;
6477 if (!pa)
6478 return NULL;
6480 space = isl_pw_aff_get_space(pa);
6481 pma = isl_pw_multi_aff_alloc_size(space, pa->n);
6483 for (i = 0; i < pa->n; ++i) {
6484 isl_set *set;
6485 isl_multi_aff *ma;
6487 set = isl_set_copy(pa->p[i].set);
6488 ma = isl_multi_aff_from_aff(isl_aff_copy(pa->p[i].aff));
6489 pma = isl_pw_multi_aff_add_piece(pma, set, ma);
6492 isl_pw_aff_free(pa);
6493 return pma;
6496 /* Construct and return a piecewise multi affine expression
6497 * that is equal to the given multi piecewise affine expression
6498 * on the shared domain of the piecewise affine expressions,
6499 * in the special case of a 0D multi piecewise affine expression.
6501 * Create a piecewise multi affine expression with the explicit domain of
6502 * the 0D multi piecewise affine expression as domain.
6504 static __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff_0D(
6505 __isl_take isl_multi_pw_aff *mpa)
6507 isl_space *space;
6508 isl_set *dom;
6509 isl_multi_aff *ma;
6511 space = isl_multi_pw_aff_get_space(mpa);
6512 dom = isl_multi_pw_aff_get_explicit_domain(mpa);
6513 isl_multi_pw_aff_free(mpa);
6515 ma = isl_multi_aff_zero(space);
6516 return isl_pw_multi_aff_alloc(dom, ma);
6519 /* Construct and return a piecewise multi affine expression
6520 * that is equal to the given multi piecewise affine expression
6521 * on the shared domain of the piecewise affine expressions.
6523 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff(
6524 __isl_take isl_multi_pw_aff *mpa)
6526 int i;
6527 isl_space *space;
6528 isl_pw_aff *pa;
6529 isl_pw_multi_aff *pma;
6531 if (!mpa)
6532 return NULL;
6534 if (mpa->n == 0)
6535 return isl_pw_multi_aff_from_multi_pw_aff_0D(mpa);
6537 space = isl_multi_pw_aff_get_space(mpa);
6538 pa = isl_multi_pw_aff_get_pw_aff(mpa, 0);
6539 pma = isl_pw_multi_aff_from_pw_aff(pa);
6541 for (i = 1; i < mpa->n; ++i) {
6542 isl_pw_multi_aff *pma_i;
6544 pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
6545 pma_i = isl_pw_multi_aff_from_pw_aff(pa);
6546 pma = isl_pw_multi_aff_range_product(pma, pma_i);
6549 pma = isl_pw_multi_aff_reset_space(pma, space);
6551 isl_multi_pw_aff_free(mpa);
6552 return pma;
6555 /* Construct and return a multi piecewise affine expression
6556 * that is equal to the given multi affine expression.
6558 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
6559 __isl_take isl_multi_aff *ma)
6561 int i;
6562 isl_size n;
6563 isl_multi_pw_aff *mpa;
6565 n = isl_multi_aff_dim(ma, isl_dim_out);
6566 if (n < 0)
6567 ma = isl_multi_aff_free(ma);
6568 if (!ma)
6569 return NULL;
6571 mpa = isl_multi_pw_aff_alloc(isl_multi_aff_get_space(ma));
6573 for (i = 0; i < n; ++i) {
6574 isl_pw_aff *pa;
6576 pa = isl_pw_aff_from_aff(isl_multi_aff_get_aff(ma, i));
6577 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
6580 isl_multi_aff_free(ma);
6581 return mpa;
6584 /* Construct and return a multi piecewise affine expression
6585 * that is equal to the given piecewise multi affine expression.
6587 * If the resulting multi piecewise affine expression has
6588 * an explicit domain, then assign it the domain of the input.
6589 * In other cases, the domain is stored in the individual elements.
6591 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
6592 __isl_take isl_pw_multi_aff *pma)
6594 int i;
6595 isl_size n;
6596 isl_space *space;
6597 isl_multi_pw_aff *mpa;
6599 n = isl_pw_multi_aff_dim(pma, isl_dim_out);
6600 if (n < 0)
6601 pma = isl_pw_multi_aff_free(pma);
6602 space = isl_pw_multi_aff_get_space(pma);
6603 mpa = isl_multi_pw_aff_alloc(space);
6605 for (i = 0; i < n; ++i) {
6606 isl_pw_aff *pa;
6608 pa = isl_pw_multi_aff_get_pw_aff(pma, i);
6609 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
6611 if (isl_multi_pw_aff_has_explicit_domain(mpa)) {
6612 isl_set *dom;
6614 dom = isl_pw_multi_aff_domain(isl_pw_multi_aff_copy(pma));
6615 mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
6618 isl_pw_multi_aff_free(pma);
6619 return mpa;
6622 /* Do "pa1" and "pa2" represent the same function?
6624 * We first check if they are obviously equal.
6625 * If not, we convert them to maps and check if those are equal.
6627 * If "pa1" or "pa2" contain any NaNs, then they are considered
6628 * not to be the same. A NaN is not equal to anything, not even
6629 * to another NaN.
6631 isl_bool isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1,
6632 __isl_keep isl_pw_aff *pa2)
6634 isl_bool equal;
6635 isl_bool has_nan;
6636 isl_map *map1, *map2;
6638 if (!pa1 || !pa2)
6639 return isl_bool_error;
6641 equal = isl_pw_aff_plain_is_equal(pa1, pa2);
6642 if (equal < 0 || equal)
6643 return equal;
6644 has_nan = either_involves_nan(pa1, pa2);
6645 if (has_nan < 0)
6646 return isl_bool_error;
6647 if (has_nan)
6648 return isl_bool_false;
6650 map1 = isl_map_from_pw_aff_internal(isl_pw_aff_copy(pa1));
6651 map2 = isl_map_from_pw_aff_internal(isl_pw_aff_copy(pa2));
6652 equal = isl_map_is_equal(map1, map2);
6653 isl_map_free(map1);
6654 isl_map_free(map2);
6656 return equal;
6659 /* Do "mpa1" and "mpa2" represent the same function?
6661 * Note that we cannot convert the entire isl_multi_pw_aff
6662 * to a map because the domains of the piecewise affine expressions
6663 * may not be the same.
6665 isl_bool isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
6666 __isl_keep isl_multi_pw_aff *mpa2)
6668 int i;
6669 isl_bool equal, equal_params;
6671 if (!mpa1 || !mpa2)
6672 return isl_bool_error;
6674 equal_params = isl_space_has_equal_params(mpa1->space, mpa2->space);
6675 if (equal_params < 0)
6676 return isl_bool_error;
6677 if (!equal_params) {
6678 if (!isl_space_has_named_params(mpa1->space))
6679 return isl_bool_false;
6680 if (!isl_space_has_named_params(mpa2->space))
6681 return isl_bool_false;
6682 mpa1 = isl_multi_pw_aff_copy(mpa1);
6683 mpa2 = isl_multi_pw_aff_copy(mpa2);
6684 mpa1 = isl_multi_pw_aff_align_params(mpa1,
6685 isl_multi_pw_aff_get_space(mpa2));
6686 mpa2 = isl_multi_pw_aff_align_params(mpa2,
6687 isl_multi_pw_aff_get_space(mpa1));
6688 equal = isl_multi_pw_aff_is_equal(mpa1, mpa2);
6689 isl_multi_pw_aff_free(mpa1);
6690 isl_multi_pw_aff_free(mpa2);
6691 return equal;
6694 equal = isl_space_is_equal(mpa1->space, mpa2->space);
6695 if (equal < 0 || !equal)
6696 return equal;
6698 for (i = 0; i < mpa1->n; ++i) {
6699 equal = isl_pw_aff_is_equal(mpa1->u.p[i], mpa2->u.p[i]);
6700 if (equal < 0 || !equal)
6701 return equal;
6704 return isl_bool_true;
6707 /* Do "pma1" and "pma2" represent the same function?
6709 * First check if they are obviously equal.
6710 * If not, then convert them to maps and check if those are equal.
6712 * If "pa1" or "pa2" contain any NaNs, then they are considered
6713 * not to be the same. A NaN is not equal to anything, not even
6714 * to another NaN.
6716 isl_bool isl_pw_multi_aff_is_equal(__isl_keep isl_pw_multi_aff *pma1,
6717 __isl_keep isl_pw_multi_aff *pma2)
6719 isl_bool equal;
6720 isl_bool has_nan;
6721 isl_map *map1, *map2;
6723 if (!pma1 || !pma2)
6724 return isl_bool_error;
6726 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
6727 if (equal < 0 || equal)
6728 return equal;
6729 has_nan = isl_pw_multi_aff_involves_nan(pma1);
6730 if (has_nan >= 0 && !has_nan)
6731 has_nan = isl_pw_multi_aff_involves_nan(pma2);
6732 if (has_nan < 0 || has_nan)
6733 return isl_bool_not(has_nan);
6735 map1 = isl_map_from_pw_multi_aff(isl_pw_multi_aff_copy(pma1));
6736 map2 = isl_map_from_pw_multi_aff(isl_pw_multi_aff_copy(pma2));
6737 equal = isl_map_is_equal(map1, map2);
6738 isl_map_free(map1);
6739 isl_map_free(map2);
6741 return equal;
6744 /* Compute the pullback of "mpa" by the function represented by "ma".
6745 * In other words, plug in "ma" in "mpa".
6747 * The parameters of "mpa" and "ma" are assumed to have been aligned.
6749 * If "mpa" has an explicit domain, then it is this domain
6750 * that needs to undergo a pullback, i.e., a preimage.
6752 static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff_aligned(
6753 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
6755 int i;
6756 isl_space *space = NULL;
6758 mpa = isl_multi_pw_aff_cow(mpa);
6759 if (!mpa || !ma)
6760 goto error;
6762 space = isl_space_join(isl_multi_aff_get_space(ma),
6763 isl_multi_pw_aff_get_space(mpa));
6764 if (!space)
6765 goto error;
6767 for (i = 0; i < mpa->n; ++i) {
6768 mpa->u.p[i] = isl_pw_aff_pullback_multi_aff(mpa->u.p[i],
6769 isl_multi_aff_copy(ma));
6770 if (!mpa->u.p[i])
6771 goto error;
6773 if (isl_multi_pw_aff_has_explicit_domain(mpa)) {
6774 mpa->u.dom = isl_set_preimage_multi_aff(mpa->u.dom,
6775 isl_multi_aff_copy(ma));
6776 if (!mpa->u.dom)
6777 goto error;
6780 isl_multi_aff_free(ma);
6781 isl_space_free(mpa->space);
6782 mpa->space = space;
6783 return mpa;
6784 error:
6785 isl_space_free(space);
6786 isl_multi_pw_aff_free(mpa);
6787 isl_multi_aff_free(ma);
6788 return NULL;
6791 /* Compute the pullback of "mpa" by the function represented by "ma".
6792 * In other words, plug in "ma" in "mpa".
6794 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff(
6795 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
6797 isl_bool equal_params;
6799 if (!mpa || !ma)
6800 goto error;
6801 equal_params = isl_space_has_equal_params(mpa->space, ma->space);
6802 if (equal_params < 0)
6803 goto error;
6804 if (equal_params)
6805 return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
6806 mpa = isl_multi_pw_aff_align_params(mpa, isl_multi_aff_get_space(ma));
6807 ma = isl_multi_aff_align_params(ma, isl_multi_pw_aff_get_space(mpa));
6808 return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
6809 error:
6810 isl_multi_pw_aff_free(mpa);
6811 isl_multi_aff_free(ma);
6812 return NULL;
6815 /* Compute the pullback of "mpa" by the function represented by "pma".
6816 * In other words, plug in "pma" in "mpa".
6818 * The parameters of "mpa" and "mpa" are assumed to have been aligned.
6820 * If "mpa" has an explicit domain, then it is this domain
6821 * that needs to undergo a pullback, i.e., a preimage.
6823 static __isl_give isl_multi_pw_aff *
6824 isl_multi_pw_aff_pullback_pw_multi_aff_aligned(
6825 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
6827 int i;
6828 isl_space *space = NULL;
6830 mpa = isl_multi_pw_aff_cow(mpa);
6831 if (!mpa || !pma)
6832 goto error;
6834 space = isl_space_join(isl_pw_multi_aff_get_space(pma),
6835 isl_multi_pw_aff_get_space(mpa));
6837 for (i = 0; i < mpa->n; ++i) {
6838 mpa->u.p[i] = isl_pw_aff_pullback_pw_multi_aff_aligned(
6839 mpa->u.p[i], isl_pw_multi_aff_copy(pma));
6840 if (!mpa->u.p[i])
6841 goto error;
6843 if (isl_multi_pw_aff_has_explicit_domain(mpa)) {
6844 mpa->u.dom = isl_set_preimage_pw_multi_aff(mpa->u.dom,
6845 isl_pw_multi_aff_copy(pma));
6846 if (!mpa->u.dom)
6847 goto error;
6850 isl_pw_multi_aff_free(pma);
6851 isl_space_free(mpa->space);
6852 mpa->space = space;
6853 return mpa;
6854 error:
6855 isl_space_free(space);
6856 isl_multi_pw_aff_free(mpa);
6857 isl_pw_multi_aff_free(pma);
6858 return NULL;
6861 /* Compute the pullback of "mpa" by the function represented by "pma".
6862 * In other words, plug in "pma" in "mpa".
6864 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_pw_multi_aff(
6865 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
6867 isl_bool equal_params;
6869 if (!mpa || !pma)
6870 goto error;
6871 equal_params = isl_space_has_equal_params(mpa->space, pma->dim);
6872 if (equal_params < 0)
6873 goto error;
6874 if (equal_params)
6875 return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
6876 mpa = isl_multi_pw_aff_align_params(mpa,
6877 isl_pw_multi_aff_get_space(pma));
6878 pma = isl_pw_multi_aff_align_params(pma,
6879 isl_multi_pw_aff_get_space(mpa));
6880 return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
6881 error:
6882 isl_multi_pw_aff_free(mpa);
6883 isl_pw_multi_aff_free(pma);
6884 return NULL;
6887 /* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
6888 * with the domain of "aff". The domain of the result is the same
6889 * as that of "mpa".
6890 * "mpa" and "aff" are assumed to have been aligned.
6892 * We first extract the parametric constant from "aff", defined
6893 * over the correct domain.
6894 * Then we add the appropriate combinations of the members of "mpa".
6895 * Finally, we add the integer divisions through recursive calls.
6897 static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff_aligned(
6898 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
6900 int i;
6901 isl_size n_in, n_div, n_mpa_in;
6902 isl_space *space;
6903 isl_val *v;
6904 isl_pw_aff *pa;
6905 isl_aff *tmp;
6907 n_in = isl_aff_dim(aff, isl_dim_in);
6908 n_div = isl_aff_dim(aff, isl_dim_div);
6909 n_mpa_in = isl_multi_pw_aff_dim(mpa, isl_dim_in);
6910 if (n_in < 0 || n_div < 0 || n_mpa_in < 0)
6911 goto error;
6913 space = isl_space_domain(isl_multi_pw_aff_get_space(mpa));
6914 tmp = isl_aff_copy(aff);
6915 tmp = isl_aff_drop_dims(tmp, isl_dim_div, 0, n_div);
6916 tmp = isl_aff_drop_dims(tmp, isl_dim_in, 0, n_in);
6917 tmp = isl_aff_add_dims(tmp, isl_dim_in, n_mpa_in);
6918 tmp = isl_aff_reset_domain_space(tmp, space);
6919 pa = isl_pw_aff_from_aff(tmp);
6921 for (i = 0; i < n_in; ++i) {
6922 isl_pw_aff *pa_i;
6924 if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
6925 continue;
6926 v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
6927 pa_i = isl_multi_pw_aff_get_pw_aff(mpa, i);
6928 pa_i = isl_pw_aff_scale_val(pa_i, v);
6929 pa = isl_pw_aff_add(pa, pa_i);
6932 for (i = 0; i < n_div; ++i) {
6933 isl_aff *div;
6934 isl_pw_aff *pa_i;
6936 if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
6937 continue;
6938 div = isl_aff_get_div(aff, i);
6939 pa_i = isl_multi_pw_aff_apply_aff_aligned(
6940 isl_multi_pw_aff_copy(mpa), div);
6941 pa_i = isl_pw_aff_floor(pa_i);
6942 v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
6943 pa_i = isl_pw_aff_scale_val(pa_i, v);
6944 pa = isl_pw_aff_add(pa, pa_i);
6947 isl_multi_pw_aff_free(mpa);
6948 isl_aff_free(aff);
6950 return pa;
6951 error:
6952 isl_multi_pw_aff_free(mpa);
6953 isl_aff_free(aff);
6954 return NULL;
6957 /* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
6958 * with the domain of "aff". The domain of the result is the same
6959 * as that of "mpa".
6961 __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff(
6962 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
6964 isl_bool equal_params;
6966 if (!aff || !mpa)
6967 goto error;
6968 equal_params = isl_space_has_equal_params(aff->ls->dim, mpa->space);
6969 if (equal_params < 0)
6970 goto error;
6971 if (equal_params)
6972 return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
6974 aff = isl_aff_align_params(aff, isl_multi_pw_aff_get_space(mpa));
6975 mpa = isl_multi_pw_aff_align_params(mpa, isl_aff_get_space(aff));
6977 return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
6978 error:
6979 isl_aff_free(aff);
6980 isl_multi_pw_aff_free(mpa);
6981 return NULL;
6984 /* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
6985 * with the domain of "pa". The domain of the result is the same
6986 * as that of "mpa".
6987 * "mpa" and "pa" are assumed to have been aligned.
6989 * We consider each piece in turn. Note that the domains of the
6990 * pieces are assumed to be disjoint and they remain disjoint
6991 * after taking the preimage (over the same function).
6993 static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff_aligned(
6994 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
6996 isl_space *space;
6997 isl_pw_aff *res;
6998 int i;
7000 if (!mpa || !pa)
7001 goto error;
7003 space = isl_space_join(isl_multi_pw_aff_get_space(mpa),
7004 isl_pw_aff_get_space(pa));
7005 res = isl_pw_aff_empty(space);
7007 for (i = 0; i < pa->n; ++i) {
7008 isl_pw_aff *pa_i;
7009 isl_set *domain;
7011 pa_i = isl_multi_pw_aff_apply_aff_aligned(
7012 isl_multi_pw_aff_copy(mpa),
7013 isl_aff_copy(pa->p[i].aff));
7014 domain = isl_set_copy(pa->p[i].set);
7015 domain = isl_set_preimage_multi_pw_aff(domain,
7016 isl_multi_pw_aff_copy(mpa));
7017 pa_i = isl_pw_aff_intersect_domain(pa_i, domain);
7018 res = isl_pw_aff_add_disjoint(res, pa_i);
7021 isl_pw_aff_free(pa);
7022 isl_multi_pw_aff_free(mpa);
7023 return res;
7024 error:
7025 isl_pw_aff_free(pa);
7026 isl_multi_pw_aff_free(mpa);
7027 return NULL;
7030 /* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
7031 * with the domain of "pa". The domain of the result is the same
7032 * as that of "mpa".
7034 __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff(
7035 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
7037 isl_bool equal_params;
7039 if (!pa || !mpa)
7040 goto error;
7041 equal_params = isl_space_has_equal_params(pa->dim, mpa->space);
7042 if (equal_params < 0)
7043 goto error;
7044 if (equal_params)
7045 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
7047 pa = isl_pw_aff_align_params(pa, isl_multi_pw_aff_get_space(mpa));
7048 mpa = isl_multi_pw_aff_align_params(mpa, isl_pw_aff_get_space(pa));
7050 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
7051 error:
7052 isl_pw_aff_free(pa);
7053 isl_multi_pw_aff_free(mpa);
7054 return NULL;
7057 /* Compute the pullback of "pa" by the function represented by "mpa".
7058 * In other words, plug in "mpa" in "pa".
7059 * "pa" and "mpa" are assumed to have been aligned.
7061 * The pullback is computed by applying "pa" to "mpa".
7063 static __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff_aligned(
7064 __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
7066 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
7069 /* Compute the pullback of "pa" by the function represented by "mpa".
7070 * In other words, plug in "mpa" in "pa".
7072 * The pullback is computed by applying "pa" to "mpa".
7074 __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
7075 __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
7077 return isl_multi_pw_aff_apply_pw_aff(mpa, pa);
7080 /* Compute the pullback of "mpa1" by the function represented by "mpa2".
7081 * In other words, plug in "mpa2" in "mpa1".
7083 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7085 * We pullback each member of "mpa1" in turn.
7087 * If "mpa1" has an explicit domain, then it is this domain
7088 * that needs to undergo a pullback instead, i.e., a preimage.
7090 static __isl_give isl_multi_pw_aff *
7091 isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
7092 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
7094 int i;
7095 isl_space *space = NULL;
7097 mpa1 = isl_multi_pw_aff_cow(mpa1);
7098 if (!mpa1 || !mpa2)
7099 goto error;
7101 space = isl_space_join(isl_multi_pw_aff_get_space(mpa2),
7102 isl_multi_pw_aff_get_space(mpa1));
7104 for (i = 0; i < mpa1->n; ++i) {
7105 mpa1->u.p[i] = isl_pw_aff_pullback_multi_pw_aff_aligned(
7106 mpa1->u.p[i], isl_multi_pw_aff_copy(mpa2));
7107 if (!mpa1->u.p[i])
7108 goto error;
7111 if (isl_multi_pw_aff_has_explicit_domain(mpa1)) {
7112 mpa1->u.dom = isl_set_preimage_multi_pw_aff(mpa1->u.dom,
7113 isl_multi_pw_aff_copy(mpa2));
7114 if (!mpa1->u.dom)
7115 goto error;
7117 mpa1 = isl_multi_pw_aff_reset_space(mpa1, space);
7119 isl_multi_pw_aff_free(mpa2);
7120 return mpa1;
7121 error:
7122 isl_space_free(space);
7123 isl_multi_pw_aff_free(mpa1);
7124 isl_multi_pw_aff_free(mpa2);
7125 return NULL;
7128 /* Compute the pullback of "mpa1" by the function represented by "mpa2".
7129 * In other words, plug in "mpa2" in "mpa1".
7131 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_pw_aff(
7132 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
7134 return isl_multi_pw_aff_align_params_multi_multi_and(mpa1, mpa2,
7135 &isl_multi_pw_aff_pullback_multi_pw_aff_aligned);
7138 /* Align the parameters of "mpa1" and "mpa2", check that the ranges
7139 * of "mpa1" and "mpa2" live in the same space, construct map space
7140 * between the domain spaces of "mpa1" and "mpa2" and call "order"
7141 * with this map space as extract argument.
7143 static __isl_give isl_map *isl_multi_pw_aff_order_map(
7144 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
7145 __isl_give isl_map *(*order)(__isl_keep isl_multi_pw_aff *mpa1,
7146 __isl_keep isl_multi_pw_aff *mpa2, __isl_take isl_space *space))
7148 int match;
7149 isl_space *space1, *space2;
7150 isl_map *res;
7152 mpa1 = isl_multi_pw_aff_align_params(mpa1,
7153 isl_multi_pw_aff_get_space(mpa2));
7154 mpa2 = isl_multi_pw_aff_align_params(mpa2,
7155 isl_multi_pw_aff_get_space(mpa1));
7156 if (!mpa1 || !mpa2)
7157 goto error;
7158 match = isl_space_tuple_is_equal(mpa1->space, isl_dim_out,
7159 mpa2->space, isl_dim_out);
7160 if (match < 0)
7161 goto error;
7162 if (!match)
7163 isl_die(isl_multi_pw_aff_get_ctx(mpa1), isl_error_invalid,
7164 "range spaces don't match", goto error);
7165 space1 = isl_space_domain(isl_multi_pw_aff_get_space(mpa1));
7166 space2 = isl_space_domain(isl_multi_pw_aff_get_space(mpa2));
7167 space1 = isl_space_map_from_domain_and_range(space1, space2);
7169 res = order(mpa1, mpa2, space1);
7170 isl_multi_pw_aff_free(mpa1);
7171 isl_multi_pw_aff_free(mpa2);
7172 return res;
7173 error:
7174 isl_multi_pw_aff_free(mpa1);
7175 isl_multi_pw_aff_free(mpa2);
7176 return NULL;
7179 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7180 * where the function values are equal. "space" is the space of the result.
7181 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7183 * "mpa1" and "mpa2" are equal when each of the pairs of elements
7184 * in the sequences are equal.
7186 static __isl_give isl_map *isl_multi_pw_aff_eq_map_on_space(
7187 __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2,
7188 __isl_take isl_space *space)
7190 int i;
7191 isl_size n;
7192 isl_map *res;
7194 n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
7195 if (n < 0)
7196 space = isl_space_free(space);
7197 res = isl_map_universe(space);
7199 for (i = 0; i < n; ++i) {
7200 isl_pw_aff *pa1, *pa2;
7201 isl_map *map;
7203 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7204 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7205 map = isl_pw_aff_eq_map(pa1, pa2);
7206 res = isl_map_intersect(res, map);
7209 return res;
7212 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7213 * where the function values are equal.
7215 __isl_give isl_map *isl_multi_pw_aff_eq_map(__isl_take isl_multi_pw_aff *mpa1,
7216 __isl_take isl_multi_pw_aff *mpa2)
7218 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7219 &isl_multi_pw_aff_eq_map_on_space);
7222 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7223 * where the function values of "mpa1" is lexicographically satisfies "base"
7224 * compared to that of "mpa2". "space" is the space of the result.
7225 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7227 * "mpa1" lexicographically satisfies "base" compared to "mpa2"
7228 * if its i-th element satisfies "base" when compared to
7229 * the i-th element of "mpa2" while all previous elements are
7230 * pairwise equal.
7232 static __isl_give isl_map *isl_multi_pw_aff_lex_map_on_space(
7233 __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2,
7234 __isl_give isl_map *(*base)(__isl_take isl_pw_aff *pa1,
7235 __isl_take isl_pw_aff *pa2),
7236 __isl_take isl_space *space)
7238 int i;
7239 isl_size n;
7240 isl_map *res, *rest;
7242 n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
7243 if (n < 0)
7244 space = isl_space_free(space);
7245 res = isl_map_empty(isl_space_copy(space));
7246 rest = isl_map_universe(space);
7248 for (i = 0; i < n; ++i) {
7249 isl_pw_aff *pa1, *pa2;
7250 isl_map *map;
7252 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7253 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7254 map = base(pa1, pa2);
7255 map = isl_map_intersect(map, isl_map_copy(rest));
7256 res = isl_map_union(res, map);
7258 if (i == n - 1)
7259 continue;
7261 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
7262 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
7263 map = isl_pw_aff_eq_map(pa1, pa2);
7264 rest = isl_map_intersect(rest, map);
7267 isl_map_free(rest);
7268 return res;
7271 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7272 * where the function value of "mpa1" is lexicographically less than that
7273 * of "mpa2". "space" is the space of the result.
7274 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7276 * "mpa1" is less than "mpa2" if its i-th element is smaller
7277 * than the i-th element of "mpa2" while all previous elements are
7278 * pairwise equal.
7280 __isl_give isl_map *isl_multi_pw_aff_lex_lt_map_on_space(
7281 __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2,
7282 __isl_take isl_space *space)
7284 return isl_multi_pw_aff_lex_map_on_space(mpa1, mpa2,
7285 &isl_pw_aff_lt_map, space);
7288 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7289 * where the function value of "mpa1" is lexicographically less than that
7290 * of "mpa2".
7292 __isl_give isl_map *isl_multi_pw_aff_lex_lt_map(
7293 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
7295 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7296 &isl_multi_pw_aff_lex_lt_map_on_space);
7299 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7300 * where the function value of "mpa1" is lexicographically greater than that
7301 * of "mpa2". "space" is the space of the result.
7302 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7304 * "mpa1" is greater than "mpa2" if its i-th element is greater
7305 * than the i-th element of "mpa2" while all previous elements are
7306 * pairwise equal.
7308 __isl_give isl_map *isl_multi_pw_aff_lex_gt_map_on_space(
7309 __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2,
7310 __isl_take isl_space *space)
7312 return isl_multi_pw_aff_lex_map_on_space(mpa1, mpa2,
7313 &isl_pw_aff_gt_map, space);
7316 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7317 * where the function value of "mpa1" is lexicographically greater than that
7318 * of "mpa2".
7320 __isl_give isl_map *isl_multi_pw_aff_lex_gt_map(
7321 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
7323 return isl_multi_pw_aff_order_map(mpa1, mpa2,
7324 &isl_multi_pw_aff_lex_gt_map_on_space);
7327 /* Compare two isl_affs.
7329 * Return -1 if "aff1" is "smaller" than "aff2", 1 if "aff1" is "greater"
7330 * than "aff2" and 0 if they are equal.
7332 * The order is fairly arbitrary. We do consider expressions that only involve
7333 * earlier dimensions as "smaller".
7335 int isl_aff_plain_cmp(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2)
7337 int cmp;
7338 int last1, last2;
7340 if (aff1 == aff2)
7341 return 0;
7343 if (!aff1)
7344 return -1;
7345 if (!aff2)
7346 return 1;
7348 cmp = isl_local_space_cmp(aff1->ls, aff2->ls);
7349 if (cmp != 0)
7350 return cmp;
7352 last1 = isl_seq_last_non_zero(aff1->v->el + 1, aff1->v->size - 1);
7353 last2 = isl_seq_last_non_zero(aff2->v->el + 1, aff1->v->size - 1);
7354 if (last1 != last2)
7355 return last1 - last2;
7357 return isl_seq_cmp(aff1->v->el, aff2->v->el, aff1->v->size);
7360 /* Compare two isl_pw_affs.
7362 * Return -1 if "pa1" is "smaller" than "pa2", 1 if "pa1" is "greater"
7363 * than "pa2" and 0 if they are equal.
7365 * The order is fairly arbitrary. We do consider expressions that only involve
7366 * earlier dimensions as "smaller".
7368 int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1,
7369 __isl_keep isl_pw_aff *pa2)
7371 int i;
7372 int cmp;
7374 if (pa1 == pa2)
7375 return 0;
7377 if (!pa1)
7378 return -1;
7379 if (!pa2)
7380 return 1;
7382 cmp = isl_space_cmp(pa1->dim, pa2->dim);
7383 if (cmp != 0)
7384 return cmp;
7386 if (pa1->n != pa2->n)
7387 return pa1->n - pa2->n;
7389 for (i = 0; i < pa1->n; ++i) {
7390 cmp = isl_set_plain_cmp(pa1->p[i].set, pa2->p[i].set);
7391 if (cmp != 0)
7392 return cmp;
7393 cmp = isl_aff_plain_cmp(pa1->p[i].aff, pa2->p[i].aff);
7394 if (cmp != 0)
7395 return cmp;
7398 return 0;
7401 /* Return a piecewise affine expression that is equal to "v" on "domain".
7403 __isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
7404 __isl_take isl_val *v)
7406 isl_space *space;
7407 isl_local_space *ls;
7408 isl_aff *aff;
7410 space = isl_set_get_space(domain);
7411 ls = isl_local_space_from_space(space);
7412 aff = isl_aff_val_on_domain(ls, v);
7414 return isl_pw_aff_alloc(domain, aff);
7417 /* Return a multi affine expression that is equal to "mv" on domain
7418 * space "space".
7420 __isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
7421 __isl_take isl_space *space, __isl_take isl_multi_val *mv)
7423 int i;
7424 isl_size n;
7425 isl_space *space2;
7426 isl_local_space *ls;
7427 isl_multi_aff *ma;
7429 n = isl_multi_val_dim(mv, isl_dim_set);
7430 if (!space || n < 0)
7431 goto error;
7433 space2 = isl_multi_val_get_space(mv);
7434 space2 = isl_space_align_params(space2, isl_space_copy(space));
7435 space = isl_space_align_params(space, isl_space_copy(space2));
7436 space = isl_space_map_from_domain_and_range(space, space2);
7437 ma = isl_multi_aff_alloc(isl_space_copy(space));
7438 ls = isl_local_space_from_space(isl_space_domain(space));
7439 for (i = 0; i < n; ++i) {
7440 isl_val *v;
7441 isl_aff *aff;
7443 v = isl_multi_val_get_val(mv, i);
7444 aff = isl_aff_val_on_domain(isl_local_space_copy(ls), v);
7445 ma = isl_multi_aff_set_aff(ma, i, aff);
7447 isl_local_space_free(ls);
7449 isl_multi_val_free(mv);
7450 return ma;
7451 error:
7452 isl_space_free(space);
7453 isl_multi_val_free(mv);
7454 return NULL;
7457 /* Return a piecewise multi-affine expression
7458 * that is equal to "mv" on "domain".
7460 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_multi_val_on_domain(
7461 __isl_take isl_set *domain, __isl_take isl_multi_val *mv)
7463 isl_space *space;
7464 isl_multi_aff *ma;
7466 space = isl_set_get_space(domain);
7467 ma = isl_multi_aff_multi_val_on_space(space, mv);
7469 return isl_pw_multi_aff_alloc(domain, ma);
7472 /* Internal data structure for isl_union_pw_multi_aff_multi_val_on_domain.
7473 * mv is the value that should be attained on each domain set
7474 * res collects the results
7476 struct isl_union_pw_multi_aff_multi_val_on_domain_data {
7477 isl_multi_val *mv;
7478 isl_union_pw_multi_aff *res;
7481 /* Create an isl_pw_multi_aff equal to data->mv on "domain"
7482 * and add it to data->res.
7484 static isl_stat pw_multi_aff_multi_val_on_domain(__isl_take isl_set *domain,
7485 void *user)
7487 struct isl_union_pw_multi_aff_multi_val_on_domain_data *data = user;
7488 isl_pw_multi_aff *pma;
7489 isl_multi_val *mv;
7491 mv = isl_multi_val_copy(data->mv);
7492 pma = isl_pw_multi_aff_multi_val_on_domain(domain, mv);
7493 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
7495 return data->res ? isl_stat_ok : isl_stat_error;
7498 /* Return a union piecewise multi-affine expression
7499 * that is equal to "mv" on "domain".
7501 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_multi_val_on_domain(
7502 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
7504 struct isl_union_pw_multi_aff_multi_val_on_domain_data data;
7505 isl_space *space;
7507 space = isl_union_set_get_space(domain);
7508 data.res = isl_union_pw_multi_aff_empty(space);
7509 data.mv = mv;
7510 if (isl_union_set_foreach_set(domain,
7511 &pw_multi_aff_multi_val_on_domain, &data) < 0)
7512 data.res = isl_union_pw_multi_aff_free(data.res);
7513 isl_union_set_free(domain);
7514 isl_multi_val_free(mv);
7515 return data.res;
7518 /* Compute the pullback of data->pma by the function represented by "pma2",
7519 * provided the spaces match, and add the results to data->res.
7521 static isl_stat pullback_entry(__isl_take isl_pw_multi_aff *pma2, void *user)
7523 struct isl_union_pw_multi_aff_bin_data *data = user;
7525 if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
7526 pma2->dim, isl_dim_out)) {
7527 isl_pw_multi_aff_free(pma2);
7528 return isl_stat_ok;
7531 pma2 = isl_pw_multi_aff_pullback_pw_multi_aff(
7532 isl_pw_multi_aff_copy(data->pma), pma2);
7534 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
7535 if (!data->res)
7536 return isl_stat_error;
7538 return isl_stat_ok;
7541 /* Compute the pullback of "upma1" by the function represented by "upma2".
7543 __isl_give isl_union_pw_multi_aff *
7544 isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
7545 __isl_take isl_union_pw_multi_aff *upma1,
7546 __isl_take isl_union_pw_multi_aff *upma2)
7548 return bin_op(upma1, upma2, &pullback_entry);
7551 /* Check that the domain space of "upa" matches "space".
7553 * This function is called from isl_multi_union_pw_aff_set_union_pw_aff and
7554 * can in principle never fail since the space "space" is that
7555 * of the isl_multi_union_pw_aff and is a set space such that
7556 * there is no domain space to match.
7558 * We check the parameters and double-check that "space" is
7559 * indeed that of a set.
7561 static isl_stat isl_union_pw_aff_check_match_domain_space(
7562 __isl_keep isl_union_pw_aff *upa, __isl_keep isl_space *space)
7564 isl_space *upa_space;
7565 isl_bool match;
7567 if (!upa || !space)
7568 return isl_stat_error;
7570 match = isl_space_is_set(space);
7571 if (match < 0)
7572 return isl_stat_error;
7573 if (!match)
7574 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7575 "expecting set space", return isl_stat_error);
7577 upa_space = isl_union_pw_aff_get_space(upa);
7578 match = isl_space_has_equal_params(space, upa_space);
7579 if (match < 0)
7580 goto error;
7581 if (!match)
7582 isl_die(isl_space_get_ctx(space), isl_error_invalid,
7583 "parameters don't match", goto error);
7585 isl_space_free(upa_space);
7586 return isl_stat_ok;
7587 error:
7588 isl_space_free(upa_space);
7589 return isl_stat_error;
7592 /* Do the parameters of "upa" match those of "space"?
7594 static isl_bool isl_union_pw_aff_matching_params(
7595 __isl_keep isl_union_pw_aff *upa, __isl_keep isl_space *space)
7597 isl_space *upa_space;
7598 isl_bool match;
7600 if (!upa || !space)
7601 return isl_bool_error;
7603 upa_space = isl_union_pw_aff_get_space(upa);
7605 match = isl_space_has_equal_params(space, upa_space);
7607 isl_space_free(upa_space);
7608 return match;
7611 /* Internal data structure for isl_union_pw_aff_reset_domain_space.
7612 * space represents the new parameters.
7613 * res collects the results.
7615 struct isl_union_pw_aff_reset_params_data {
7616 isl_space *space;
7617 isl_union_pw_aff *res;
7620 /* Replace the parameters of "pa" by data->space and
7621 * add the result to data->res.
7623 static isl_stat reset_params(__isl_take isl_pw_aff *pa, void *user)
7625 struct isl_union_pw_aff_reset_params_data *data = user;
7626 isl_space *space;
7628 space = isl_pw_aff_get_space(pa);
7629 space = isl_space_replace_params(space, data->space);
7630 pa = isl_pw_aff_reset_space(pa, space);
7631 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7633 return data->res ? isl_stat_ok : isl_stat_error;
7636 /* Replace the domain space of "upa" by "space".
7637 * Since a union expression does not have a (single) domain space,
7638 * "space" is necessarily a parameter space.
7640 * Since the order and the names of the parameters determine
7641 * the hash value, we need to create a new hash table.
7643 static __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_domain_space(
7644 __isl_take isl_union_pw_aff *upa, __isl_take isl_space *space)
7646 struct isl_union_pw_aff_reset_params_data data = { space };
7647 isl_bool match;
7649 match = isl_union_pw_aff_matching_params(upa, space);
7650 if (match < 0)
7651 upa = isl_union_pw_aff_free(upa);
7652 else if (match) {
7653 isl_space_free(space);
7654 return upa;
7657 data.res = isl_union_pw_aff_empty(isl_space_copy(space));
7658 if (isl_union_pw_aff_foreach_pw_aff(upa, &reset_params, &data) < 0)
7659 data.res = isl_union_pw_aff_free(data.res);
7661 isl_union_pw_aff_free(upa);
7662 isl_space_free(space);
7663 return data.res;
7666 /* Return the floor of "pa".
7668 static __isl_give isl_pw_aff *floor_entry(__isl_take isl_pw_aff *pa, void *user)
7670 return isl_pw_aff_floor(pa);
7673 /* Given f, return floor(f).
7675 __isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
7676 __isl_take isl_union_pw_aff *upa)
7678 return isl_union_pw_aff_transform_inplace(upa, &floor_entry, NULL);
7681 /* Compute
7683 * upa mod m = upa - m * floor(upa/m)
7685 * with m an integer value.
7687 __isl_give isl_union_pw_aff *isl_union_pw_aff_mod_val(
7688 __isl_take isl_union_pw_aff *upa, __isl_take isl_val *m)
7690 isl_union_pw_aff *res;
7692 if (!upa || !m)
7693 goto error;
7695 if (!isl_val_is_int(m))
7696 isl_die(isl_val_get_ctx(m), isl_error_invalid,
7697 "expecting integer modulo", goto error);
7698 if (!isl_val_is_pos(m))
7699 isl_die(isl_val_get_ctx(m), isl_error_invalid,
7700 "expecting positive modulo", goto error);
7702 res = isl_union_pw_aff_copy(upa);
7703 upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(m));
7704 upa = isl_union_pw_aff_floor(upa);
7705 upa = isl_union_pw_aff_scale_val(upa, m);
7706 res = isl_union_pw_aff_sub(res, upa);
7708 return res;
7709 error:
7710 isl_val_free(m);
7711 isl_union_pw_aff_free(upa);
7712 return NULL;
7715 /* Internal data structure for isl_union_pw_multi_aff_get_union_pw_aff.
7716 * pos is the output position that needs to be extracted.
7717 * res collects the results.
7719 struct isl_union_pw_multi_aff_get_union_pw_aff_data {
7720 int pos;
7721 isl_union_pw_aff *res;
7724 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma"
7725 * (assuming it has such a dimension) and add it to data->res.
7727 static isl_stat get_union_pw_aff(__isl_take isl_pw_multi_aff *pma, void *user)
7729 struct isl_union_pw_multi_aff_get_union_pw_aff_data *data = user;
7730 isl_size n_out;
7731 isl_pw_aff *pa;
7733 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
7734 if (n_out < 0)
7735 return isl_stat_error;
7736 if (data->pos >= n_out) {
7737 isl_pw_multi_aff_free(pma);
7738 return isl_stat_ok;
7741 pa = isl_pw_multi_aff_get_pw_aff(pma, data->pos);
7742 isl_pw_multi_aff_free(pma);
7744 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7746 return data->res ? isl_stat_ok : isl_stat_error;
7749 /* Extract an isl_union_pw_aff corresponding to
7750 * output dimension "pos" of "upma".
7752 __isl_give isl_union_pw_aff *isl_union_pw_multi_aff_get_union_pw_aff(
7753 __isl_keep isl_union_pw_multi_aff *upma, int pos)
7755 struct isl_union_pw_multi_aff_get_union_pw_aff_data data;
7756 isl_space *space;
7758 if (!upma)
7759 return NULL;
7761 if (pos < 0)
7762 isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
7763 "cannot extract at negative position", return NULL);
7765 space = isl_union_pw_multi_aff_get_space(upma);
7766 data.res = isl_union_pw_aff_empty(space);
7767 data.pos = pos;
7768 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
7769 &get_union_pw_aff, &data) < 0)
7770 data.res = isl_union_pw_aff_free(data.res);
7772 return data.res;
7775 /* Return a union piecewise affine expression
7776 * that is equal to "aff" on "domain".
7778 __isl_give isl_union_pw_aff *isl_union_pw_aff_aff_on_domain(
7779 __isl_take isl_union_set *domain, __isl_take isl_aff *aff)
7781 isl_pw_aff *pa;
7783 pa = isl_pw_aff_from_aff(aff);
7784 return isl_union_pw_aff_pw_aff_on_domain(domain, pa);
7787 /* Return a union piecewise affine expression
7788 * that is equal to the parameter identified by "id" on "domain".
7790 * Make sure the parameter appears in the space passed to
7791 * isl_aff_param_on_domain_space_id.
7793 __isl_give isl_union_pw_aff *isl_union_pw_aff_param_on_domain_id(
7794 __isl_take isl_union_set *domain, __isl_take isl_id *id)
7796 isl_space *space;
7797 isl_aff *aff;
7799 space = isl_union_set_get_space(domain);
7800 space = isl_space_add_param_id(space, isl_id_copy(id));
7801 aff = isl_aff_param_on_domain_space_id(space, id);
7802 return isl_union_pw_aff_aff_on_domain(domain, aff);
7805 /* Internal data structure for isl_union_pw_aff_pw_aff_on_domain.
7806 * "pa" is the piecewise symbolic value that the resulting isl_union_pw_aff
7807 * needs to attain.
7808 * "res" collects the results.
7810 struct isl_union_pw_aff_pw_aff_on_domain_data {
7811 isl_pw_aff *pa;
7812 isl_union_pw_aff *res;
7815 /* Construct a piecewise affine expression that is equal to data->pa
7816 * on "domain" and add the result to data->res.
7818 static isl_stat pw_aff_on_domain(__isl_take isl_set *domain, void *user)
7820 struct isl_union_pw_aff_pw_aff_on_domain_data *data = user;
7821 isl_pw_aff *pa;
7822 isl_size dim;
7824 pa = isl_pw_aff_copy(data->pa);
7825 dim = isl_set_dim(domain, isl_dim_set);
7826 if (dim < 0)
7827 pa = isl_pw_aff_free(pa);
7828 pa = isl_pw_aff_from_range(pa);
7829 pa = isl_pw_aff_add_dims(pa, isl_dim_in, dim);
7830 pa = isl_pw_aff_reset_domain_space(pa, isl_set_get_space(domain));
7831 pa = isl_pw_aff_intersect_domain(pa, domain);
7832 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7834 return data->res ? isl_stat_ok : isl_stat_error;
7837 /* Return a union piecewise affine expression
7838 * that is equal to "pa" on "domain", assuming "domain" and "pa"
7839 * have been aligned.
7841 * Construct an isl_pw_aff on each of the sets in "domain" and
7842 * collect the results.
7844 static __isl_give isl_union_pw_aff *isl_union_pw_aff_pw_aff_on_domain_aligned(
7845 __isl_take isl_union_set *domain, __isl_take isl_pw_aff *pa)
7847 struct isl_union_pw_aff_pw_aff_on_domain_data data;
7848 isl_space *space;
7850 space = isl_union_set_get_space(domain);
7851 data.res = isl_union_pw_aff_empty(space);
7852 data.pa = pa;
7853 if (isl_union_set_foreach_set(domain, &pw_aff_on_domain, &data) < 0)
7854 data.res = isl_union_pw_aff_free(data.res);
7855 isl_union_set_free(domain);
7856 isl_pw_aff_free(pa);
7857 return data.res;
7860 /* Return a union piecewise affine expression
7861 * that is equal to "pa" on "domain".
7863 * Check that "pa" is a parametric expression,
7864 * align the parameters if needed and call
7865 * isl_union_pw_aff_pw_aff_on_domain_aligned.
7867 __isl_give isl_union_pw_aff *isl_union_pw_aff_pw_aff_on_domain(
7868 __isl_take isl_union_set *domain, __isl_take isl_pw_aff *pa)
7870 isl_bool is_set;
7871 isl_bool equal_params;
7872 isl_space *domain_space, *pa_space;
7874 pa_space = isl_pw_aff_peek_space(pa);
7875 is_set = isl_space_is_set(pa_space);
7876 if (is_set < 0)
7877 goto error;
7878 if (!is_set)
7879 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
7880 "expecting parametric expression", goto error);
7882 domain_space = isl_union_set_get_space(domain);
7883 pa_space = isl_pw_aff_get_space(pa);
7884 equal_params = isl_space_has_equal_params(domain_space, pa_space);
7885 if (equal_params >= 0 && !equal_params) {
7886 isl_space *space;
7888 space = isl_space_align_params(domain_space, pa_space);
7889 pa = isl_pw_aff_align_params(pa, isl_space_copy(space));
7890 domain = isl_union_set_align_params(domain, space);
7891 } else {
7892 isl_space_free(domain_space);
7893 isl_space_free(pa_space);
7896 if (equal_params < 0)
7897 goto error;
7898 return isl_union_pw_aff_pw_aff_on_domain_aligned(domain, pa);
7899 error:
7900 isl_union_set_free(domain);
7901 isl_pw_aff_free(pa);
7902 return NULL;
7905 /* Internal data structure for isl_union_pw_aff_val_on_domain.
7906 * "v" is the value that the resulting isl_union_pw_aff needs to attain.
7907 * "res" collects the results.
7909 struct isl_union_pw_aff_val_on_domain_data {
7910 isl_val *v;
7911 isl_union_pw_aff *res;
7914 /* Construct a piecewise affine expression that is equal to data->v
7915 * on "domain" and add the result to data->res.
7917 static isl_stat pw_aff_val_on_domain(__isl_take isl_set *domain, void *user)
7919 struct isl_union_pw_aff_val_on_domain_data *data = user;
7920 isl_pw_aff *pa;
7921 isl_val *v;
7923 v = isl_val_copy(data->v);
7924 pa = isl_pw_aff_val_on_domain(domain, v);
7925 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
7927 return data->res ? isl_stat_ok : isl_stat_error;
7930 /* Return a union piecewise affine expression
7931 * that is equal to "v" on "domain".
7933 * Construct an isl_pw_aff on each of the sets in "domain" and
7934 * collect the results.
7936 __isl_give isl_union_pw_aff *isl_union_pw_aff_val_on_domain(
7937 __isl_take isl_union_set *domain, __isl_take isl_val *v)
7939 struct isl_union_pw_aff_val_on_domain_data data;
7940 isl_space *space;
7942 space = isl_union_set_get_space(domain);
7943 data.res = isl_union_pw_aff_empty(space);
7944 data.v = v;
7945 if (isl_union_set_foreach_set(domain, &pw_aff_val_on_domain, &data) < 0)
7946 data.res = isl_union_pw_aff_free(data.res);
7947 isl_union_set_free(domain);
7948 isl_val_free(v);
7949 return data.res;
7952 /* Construct a piecewise multi affine expression
7953 * that is equal to "pa" and add it to upma.
7955 static isl_stat pw_multi_aff_from_pw_aff_entry(__isl_take isl_pw_aff *pa,
7956 void *user)
7958 isl_union_pw_multi_aff **upma = user;
7959 isl_pw_multi_aff *pma;
7961 pma = isl_pw_multi_aff_from_pw_aff(pa);
7962 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
7964 return *upma ? isl_stat_ok : isl_stat_error;
7967 /* Construct and return a union piecewise multi affine expression
7968 * that is equal to the given union piecewise affine expression.
7970 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_pw_aff(
7971 __isl_take isl_union_pw_aff *upa)
7973 isl_space *space;
7974 isl_union_pw_multi_aff *upma;
7976 if (!upa)
7977 return NULL;
7979 space = isl_union_pw_aff_get_space(upa);
7980 upma = isl_union_pw_multi_aff_empty(space);
7982 if (isl_union_pw_aff_foreach_pw_aff(upa,
7983 &pw_multi_aff_from_pw_aff_entry, &upma) < 0)
7984 upma = isl_union_pw_multi_aff_free(upma);
7986 isl_union_pw_aff_free(upa);
7987 return upma;
7990 /* Compute the set of elements in the domain of "pa" where it is zero and
7991 * add this set to "uset".
7993 static isl_stat zero_union_set(__isl_take isl_pw_aff *pa, void *user)
7995 isl_union_set **uset = (isl_union_set **)user;
7997 *uset = isl_union_set_add_set(*uset, isl_pw_aff_zero_set(pa));
7999 return *uset ? isl_stat_ok : isl_stat_error;
8002 /* Return a union set containing those elements in the domain
8003 * of "upa" where it is zero.
8005 __isl_give isl_union_set *isl_union_pw_aff_zero_union_set(
8006 __isl_take isl_union_pw_aff *upa)
8008 isl_union_set *zero;
8010 zero = isl_union_set_empty(isl_union_pw_aff_get_space(upa));
8011 if (isl_union_pw_aff_foreach_pw_aff(upa, &zero_union_set, &zero) < 0)
8012 zero = isl_union_set_free(zero);
8014 isl_union_pw_aff_free(upa);
8015 return zero;
8018 /* Internal data structure for isl_union_pw_aff_bind_id,
8019 * storing the parameter that needs to be bound and
8020 * the accumulated results.
8022 struct isl_bind_id_data {
8023 isl_id *id;
8024 isl_union_set *bound;
8027 /* Bind the piecewise affine function "pa" to the parameter data->id,
8028 * adding the resulting elements in the domain where the expression
8029 * is equal to the parameter to data->bound.
8031 static isl_stat bind_id(__isl_take isl_pw_aff *pa, void *user)
8033 struct isl_bind_id_data *data = user;
8034 isl_set *bound;
8036 bound = isl_pw_aff_bind_id(pa, isl_id_copy(data->id));
8037 data->bound = isl_union_set_add_set(data->bound, bound);
8039 return data->bound ? isl_stat_ok : isl_stat_error;
8042 /* Bind the union piecewise affine function "upa" to the parameter "id",
8043 * returning the elements in the domain where the expression
8044 * is equal to the parameter.
8046 __isl_give isl_union_set *isl_union_pw_aff_bind_id(
8047 __isl_take isl_union_pw_aff *upa, __isl_take isl_id *id)
8049 struct isl_bind_id_data data = { id };
8051 data.bound = isl_union_set_empty(isl_union_pw_aff_get_space(upa));
8052 if (isl_union_pw_aff_foreach_pw_aff(upa, &bind_id, &data) < 0)
8053 data.bound = isl_union_set_free(data.bound);
8055 isl_union_pw_aff_free(upa);
8056 isl_id_free(id);
8057 return data.bound;
8060 /* Internal data structure for isl_union_pw_aff_pullback_union_pw_multi_aff.
8061 * upma is the function that is plugged in.
8062 * pa is the current part of the function in which upma is plugged in.
8063 * res collects the results.
8065 struct isl_union_pw_aff_pullback_upma_data {
8066 isl_union_pw_multi_aff *upma;
8067 isl_pw_aff *pa;
8068 isl_union_pw_aff *res;
8071 /* Check if "pma" can be plugged into data->pa.
8072 * If so, perform the pullback and add the result to data->res.
8074 static isl_stat pa_pb_pma(__isl_take isl_pw_multi_aff *pma, void *user)
8076 struct isl_union_pw_aff_pullback_upma_data *data = user;
8077 isl_pw_aff *pa;
8079 if (!isl_space_tuple_is_equal(data->pa->dim, isl_dim_in,
8080 pma->dim, isl_dim_out)) {
8081 isl_pw_multi_aff_free(pma);
8082 return isl_stat_ok;
8085 pa = isl_pw_aff_copy(data->pa);
8086 pa = isl_pw_aff_pullback_pw_multi_aff(pa, pma);
8088 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
8090 return data->res ? isl_stat_ok : isl_stat_error;
8093 /* Check if any of the elements of data->upma can be plugged into pa,
8094 * add if so add the result to data->res.
8096 static isl_stat upa_pb_upma(__isl_take isl_pw_aff *pa, void *user)
8098 struct isl_union_pw_aff_pullback_upma_data *data = user;
8099 isl_stat r;
8101 data->pa = pa;
8102 r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma,
8103 &pa_pb_pma, data);
8104 isl_pw_aff_free(pa);
8106 return r;
8109 /* Compute the pullback of "upa" by the function represented by "upma".
8110 * In other words, plug in "upma" in "upa". The result contains
8111 * expressions defined over the domain space of "upma".
8113 * Run over all pairs of elements in "upa" and "upma", perform
8114 * the pullback when appropriate and collect the results.
8115 * If the hash value were based on the domain space rather than
8116 * the function space, then we could run through all elements
8117 * of "upma" and directly pick out the corresponding element of "upa".
8119 __isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
8120 __isl_take isl_union_pw_aff *upa,
8121 __isl_take isl_union_pw_multi_aff *upma)
8123 struct isl_union_pw_aff_pullback_upma_data data = { NULL, NULL };
8124 isl_space *space;
8126 space = isl_union_pw_multi_aff_get_space(upma);
8127 upa = isl_union_pw_aff_align_params(upa, space);
8128 space = isl_union_pw_aff_get_space(upa);
8129 upma = isl_union_pw_multi_aff_align_params(upma, space);
8131 if (!upa || !upma)
8132 goto error;
8134 data.upma = upma;
8135 data.res = isl_union_pw_aff_alloc_same_size(upa);
8136 if (isl_union_pw_aff_foreach_pw_aff(upa, &upa_pb_upma, &data) < 0)
8137 data.res = isl_union_pw_aff_free(data.res);
8139 isl_union_pw_aff_free(upa);
8140 isl_union_pw_multi_aff_free(upma);
8141 return data.res;
8142 error:
8143 isl_union_pw_aff_free(upa);
8144 isl_union_pw_multi_aff_free(upma);
8145 return NULL;
8148 #undef BASE
8149 #define BASE union_pw_aff
8150 #undef DOMBASE
8151 #define DOMBASE union_set
8153 #include <isl_multi_explicit_domain.c>
8154 #include <isl_multi_union_pw_aff_explicit_domain.c>
8155 #include <isl_multi_templ.c>
8156 #include <isl_multi_apply_set.c>
8157 #include <isl_multi_apply_union_set.c>
8158 #include <isl_multi_arith_templ.c>
8159 #include <isl_multi_bind_templ.c>
8160 #include <isl_multi_coalesce.c>
8161 #include <isl_multi_dim_id_templ.c>
8162 #include <isl_multi_floor.c>
8163 #include <isl_multi_from_base_templ.c>
8164 #include <isl_multi_gist.c>
8165 #include <isl_multi_align_set.c>
8166 #include <isl_multi_align_union_set.c>
8167 #include <isl_multi_intersect.c>
8168 #include <isl_multi_nan_templ.c>
8169 #include <isl_multi_tuple_id_templ.c>
8171 /* Does "mupa" have a non-trivial explicit domain?
8173 * The explicit domain, if present, is trivial if it represents
8174 * an (obviously) universe parameter set.
8176 isl_bool isl_multi_union_pw_aff_has_non_trivial_domain(
8177 __isl_keep isl_multi_union_pw_aff *mupa)
8179 isl_bool is_params, trivial;
8180 isl_set *set;
8182 if (!mupa)
8183 return isl_bool_error;
8184 if (!isl_multi_union_pw_aff_has_explicit_domain(mupa))
8185 return isl_bool_false;
8186 is_params = isl_union_set_is_params(mupa->u.dom);
8187 if (is_params < 0 || !is_params)
8188 return isl_bool_not(is_params);
8189 set = isl_set_from_union_set(isl_union_set_copy(mupa->u.dom));
8190 trivial = isl_set_plain_is_universe(set);
8191 isl_set_free(set);
8192 return isl_bool_not(trivial);
8195 /* Construct a multiple union piecewise affine expression
8196 * in the given space with value zero in each of the output dimensions.
8198 * Since there is no canonical zero value for
8199 * a union piecewise affine expression, we can only construct
8200 * a zero-dimensional "zero" value.
8202 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_zero(
8203 __isl_take isl_space *space)
8205 isl_bool params;
8206 isl_size dim;
8208 if (!space)
8209 return NULL;
8211 params = isl_space_is_params(space);
8212 if (params < 0)
8213 goto error;
8214 if (params)
8215 isl_die(isl_space_get_ctx(space), isl_error_invalid,
8216 "expecting proper set space", goto error);
8217 if (!isl_space_is_set(space))
8218 isl_die(isl_space_get_ctx(space), isl_error_invalid,
8219 "expecting set space", goto error);
8220 dim = isl_space_dim(space, isl_dim_out);
8221 if (dim < 0)
8222 goto error;
8223 if (dim != 0)
8224 isl_die(isl_space_get_ctx(space), isl_error_invalid,
8225 "expecting 0D space", goto error);
8227 return isl_multi_union_pw_aff_alloc(space);
8228 error:
8229 isl_space_free(space);
8230 return NULL;
8233 /* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
8234 * with the actual sum on the shared domain and
8235 * the defined expression on the symmetric difference of the domains.
8237 * We simply iterate over the elements in both arguments and
8238 * call isl_union_pw_aff_union_add on each of them, if there is
8239 * at least one element.
8241 * Otherwise, the two expressions have an explicit domain and
8242 * the union of these explicit domains is computed.
8243 * This assumes that the explicit domains are either both in terms
8244 * of specific domains elements or both in terms of parameters.
8245 * However, if one of the expressions does not have any constraints
8246 * on its explicit domain, then this is allowed as well and the result
8247 * is the expression with no constraints on its explicit domain.
8249 static __isl_give isl_multi_union_pw_aff *
8250 isl_multi_union_pw_aff_union_add_aligned(
8251 __isl_take isl_multi_union_pw_aff *mupa1,
8252 __isl_take isl_multi_union_pw_aff *mupa2)
8254 isl_bool has_domain, is_params1, is_params2;
8256 if (isl_multi_union_pw_aff_check_equal_space(mupa1, mupa2) < 0)
8257 goto error;
8258 if (mupa1->n > 0)
8259 return isl_multi_union_pw_aff_bin_op(mupa1, mupa2,
8260 &isl_union_pw_aff_union_add);
8261 if (isl_multi_union_pw_aff_check_has_explicit_domain(mupa1) < 0 ||
8262 isl_multi_union_pw_aff_check_has_explicit_domain(mupa2) < 0)
8263 goto error;
8265 has_domain = isl_multi_union_pw_aff_has_non_trivial_domain(mupa1);
8266 if (has_domain < 0)
8267 goto error;
8268 if (!has_domain) {
8269 isl_multi_union_pw_aff_free(mupa2);
8270 return mupa1;
8272 has_domain = isl_multi_union_pw_aff_has_non_trivial_domain(mupa2);
8273 if (has_domain < 0)
8274 goto error;
8275 if (!has_domain) {
8276 isl_multi_union_pw_aff_free(mupa1);
8277 return mupa2;
8280 is_params1 = isl_union_set_is_params(mupa1->u.dom);
8281 is_params2 = isl_union_set_is_params(mupa2->u.dom);
8282 if (is_params1 < 0 || is_params2 < 0)
8283 goto error;
8284 if (is_params1 != is_params2)
8285 isl_die(isl_multi_union_pw_aff_get_ctx(mupa1),
8286 isl_error_invalid,
8287 "cannot compute union of concrete domain and "
8288 "parameter constraints", goto error);
8289 mupa1 = isl_multi_union_pw_aff_cow(mupa1);
8290 if (!mupa1)
8291 goto error;
8292 mupa1->u.dom = isl_union_set_union(mupa1->u.dom,
8293 isl_union_set_copy(mupa2->u.dom));
8294 if (!mupa1->u.dom)
8295 goto error;
8296 isl_multi_union_pw_aff_free(mupa2);
8297 return mupa1;
8298 error:
8299 isl_multi_union_pw_aff_free(mupa1);
8300 isl_multi_union_pw_aff_free(mupa2);
8301 return NULL;
8304 /* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
8305 * with the actual sum on the shared domain and
8306 * the defined expression on the symmetric difference of the domains.
8308 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_union_add(
8309 __isl_take isl_multi_union_pw_aff *mupa1,
8310 __isl_take isl_multi_union_pw_aff *mupa2)
8312 return isl_multi_union_pw_aff_align_params_multi_multi_and(mupa1, mupa2,
8313 &isl_multi_union_pw_aff_union_add_aligned);
8316 /* Construct and return a multi union piecewise affine expression
8317 * that is equal to the given multi affine expression.
8319 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff(
8320 __isl_take isl_multi_aff *ma)
8322 isl_multi_pw_aff *mpa;
8324 mpa = isl_multi_pw_aff_from_multi_aff(ma);
8325 return isl_multi_union_pw_aff_from_multi_pw_aff(mpa);
8328 /* Construct and return a multi union piecewise affine expression
8329 * that is equal to the given multi piecewise affine expression.
8331 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff(
8332 __isl_take isl_multi_pw_aff *mpa)
8334 int i;
8335 isl_size n;
8336 isl_space *space;
8337 isl_multi_union_pw_aff *mupa;
8339 n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
8340 if (n < 0)
8341 mpa = isl_multi_pw_aff_free(mpa);
8342 if (!mpa)
8343 return NULL;
8345 space = isl_multi_pw_aff_get_space(mpa);
8346 space = isl_space_range(space);
8347 mupa = isl_multi_union_pw_aff_alloc(space);
8349 for (i = 0; i < n; ++i) {
8350 isl_pw_aff *pa;
8351 isl_union_pw_aff *upa;
8353 pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
8354 upa = isl_union_pw_aff_from_pw_aff(pa);
8355 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8358 isl_multi_pw_aff_free(mpa);
8360 return mupa;
8363 /* Extract the range space of "pma" and assign it to *space.
8364 * If *space has already been set (through a previous call to this function),
8365 * then check that the range space is the same.
8367 static isl_stat extract_space(__isl_take isl_pw_multi_aff *pma, void *user)
8369 isl_space **space = user;
8370 isl_space *pma_space;
8371 isl_bool equal;
8373 pma_space = isl_space_range(isl_pw_multi_aff_get_space(pma));
8374 isl_pw_multi_aff_free(pma);
8376 if (!pma_space)
8377 return isl_stat_error;
8378 if (!*space) {
8379 *space = pma_space;
8380 return isl_stat_ok;
8383 equal = isl_space_is_equal(pma_space, *space);
8384 isl_space_free(pma_space);
8386 if (equal < 0)
8387 return isl_stat_error;
8388 if (!equal)
8389 isl_die(isl_space_get_ctx(*space), isl_error_invalid,
8390 "range spaces not the same", return isl_stat_error);
8391 return isl_stat_ok;
8394 /* Construct and return a multi union piecewise affine expression
8395 * that is equal to the given union piecewise multi affine expression.
8397 * In order to be able to perform the conversion, the input
8398 * needs to be non-empty and may only involve a single range space.
8400 * If the resulting multi union piecewise affine expression has
8401 * an explicit domain, then assign it the domain of the input.
8402 * In other cases, the domain is stored in the individual elements.
8404 __isl_give isl_multi_union_pw_aff *
8405 isl_multi_union_pw_aff_from_union_pw_multi_aff(
8406 __isl_take isl_union_pw_multi_aff *upma)
8408 isl_space *space = NULL;
8409 isl_multi_union_pw_aff *mupa;
8410 int i;
8411 isl_size n;
8413 n = isl_union_pw_multi_aff_n_pw_multi_aff(upma);
8414 if (n < 0)
8415 goto error;
8416 if (n == 0)
8417 isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
8418 "cannot extract range space from empty input",
8419 goto error);
8420 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, &extract_space,
8421 &space) < 0)
8422 goto error;
8424 if (!space)
8425 goto error;
8427 n = isl_space_dim(space, isl_dim_set);
8428 if (n < 0)
8429 space = isl_space_free(space);
8430 mupa = isl_multi_union_pw_aff_alloc(space);
8432 for (i = 0; i < n; ++i) {
8433 isl_union_pw_aff *upa;
8435 upa = isl_union_pw_multi_aff_get_union_pw_aff(upma, i);
8436 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8438 if (isl_multi_union_pw_aff_has_explicit_domain(mupa)) {
8439 isl_union_set *dom;
8440 isl_union_pw_multi_aff *copy;
8442 copy = isl_union_pw_multi_aff_copy(upma);
8443 dom = isl_union_pw_multi_aff_domain(copy);
8444 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
8447 isl_union_pw_multi_aff_free(upma);
8448 return mupa;
8449 error:
8450 isl_space_free(space);
8451 isl_union_pw_multi_aff_free(upma);
8452 return NULL;
8455 /* Try and create an isl_multi_union_pw_aff that is equivalent
8456 * to the given isl_union_map.
8457 * The isl_union_map is required to be single-valued in each space.
8458 * Moreover, it cannot be empty and all range spaces need to be the same.
8459 * Otherwise, an error is produced.
8461 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_map(
8462 __isl_take isl_union_map *umap)
8464 isl_union_pw_multi_aff *upma;
8466 upma = isl_union_pw_multi_aff_from_union_map(umap);
8467 return isl_multi_union_pw_aff_from_union_pw_multi_aff(upma);
8470 /* Return a multiple union piecewise affine expression
8471 * that is equal to "mv" on "domain", assuming "domain" and "mv"
8472 * have been aligned.
8474 * If the resulting multi union piecewise affine expression has
8475 * an explicit domain, then assign it the input domain.
8476 * In other cases, the domain is stored in the individual elements.
8478 static __isl_give isl_multi_union_pw_aff *
8479 isl_multi_union_pw_aff_multi_val_on_domain_aligned(
8480 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
8482 int i;
8483 isl_size n;
8484 isl_space *space;
8485 isl_multi_union_pw_aff *mupa;
8487 n = isl_multi_val_dim(mv, isl_dim_set);
8488 if (!domain || n < 0)
8489 goto error;
8491 space = isl_multi_val_get_space(mv);
8492 mupa = isl_multi_union_pw_aff_alloc(space);
8493 for (i = 0; i < n; ++i) {
8494 isl_val *v;
8495 isl_union_pw_aff *upa;
8497 v = isl_multi_val_get_val(mv, i);
8498 upa = isl_union_pw_aff_val_on_domain(isl_union_set_copy(domain),
8500 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8502 if (isl_multi_union_pw_aff_has_explicit_domain(mupa))
8503 mupa = isl_multi_union_pw_aff_intersect_domain(mupa,
8504 isl_union_set_copy(domain));
8506 isl_union_set_free(domain);
8507 isl_multi_val_free(mv);
8508 return mupa;
8509 error:
8510 isl_union_set_free(domain);
8511 isl_multi_val_free(mv);
8512 return NULL;
8515 /* Return a multiple union piecewise affine expression
8516 * that is equal to "mv" on "domain".
8518 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_val_on_domain(
8519 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
8521 isl_bool equal_params;
8523 if (!domain || !mv)
8524 goto error;
8525 equal_params = isl_space_has_equal_params(domain->dim, mv->space);
8526 if (equal_params < 0)
8527 goto error;
8528 if (equal_params)
8529 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(
8530 domain, mv);
8531 domain = isl_union_set_align_params(domain,
8532 isl_multi_val_get_space(mv));
8533 mv = isl_multi_val_align_params(mv, isl_union_set_get_space(domain));
8534 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(domain, mv);
8535 error:
8536 isl_union_set_free(domain);
8537 isl_multi_val_free(mv);
8538 return NULL;
8541 /* Return a multiple union piecewise affine expression
8542 * that is equal to "ma" on "domain".
8544 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_aff_on_domain(
8545 __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma)
8547 isl_pw_multi_aff *pma;
8549 pma = isl_pw_multi_aff_from_multi_aff(ma);
8550 return isl_multi_union_pw_aff_pw_multi_aff_on_domain(domain, pma);
8553 /* Return a multiple union piecewise affine expression
8554 * that is equal to "pma" on "domain", assuming "domain" and "pma"
8555 * have been aligned.
8557 * If the resulting multi union piecewise affine expression has
8558 * an explicit domain, then assign it the input domain.
8559 * In other cases, the domain is stored in the individual elements.
8561 static __isl_give isl_multi_union_pw_aff *
8562 isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(
8563 __isl_take isl_union_set *domain, __isl_take isl_pw_multi_aff *pma)
8565 int i;
8566 isl_size n;
8567 isl_space *space;
8568 isl_multi_union_pw_aff *mupa;
8570 n = isl_pw_multi_aff_dim(pma, isl_dim_set);
8571 if (!domain || n < 0)
8572 goto error;
8573 space = isl_pw_multi_aff_get_space(pma);
8574 mupa = isl_multi_union_pw_aff_alloc(space);
8575 for (i = 0; i < n; ++i) {
8576 isl_pw_aff *pa;
8577 isl_union_pw_aff *upa;
8579 pa = isl_pw_multi_aff_get_pw_aff(pma, i);
8580 upa = isl_union_pw_aff_pw_aff_on_domain(
8581 isl_union_set_copy(domain), pa);
8582 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
8584 if (isl_multi_union_pw_aff_has_explicit_domain(mupa))
8585 mupa = isl_multi_union_pw_aff_intersect_domain(mupa,
8586 isl_union_set_copy(domain));
8588 isl_union_set_free(domain);
8589 isl_pw_multi_aff_free(pma);
8590 return mupa;
8591 error:
8592 isl_union_set_free(domain);
8593 isl_pw_multi_aff_free(pma);
8594 return NULL;
8597 /* Return a multiple union piecewise affine expression
8598 * that is equal to "pma" on "domain".
8600 __isl_give isl_multi_union_pw_aff *
8601 isl_multi_union_pw_aff_pw_multi_aff_on_domain(__isl_take isl_union_set *domain,
8602 __isl_take isl_pw_multi_aff *pma)
8604 isl_bool equal_params;
8605 isl_space *space;
8607 space = isl_pw_multi_aff_peek_space(pma);
8608 equal_params = isl_union_set_space_has_equal_params(domain, space);
8609 if (equal_params < 0)
8610 goto error;
8611 if (equal_params)
8612 return isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(
8613 domain, pma);
8614 domain = isl_union_set_align_params(domain,
8615 isl_pw_multi_aff_get_space(pma));
8616 pma = isl_pw_multi_aff_align_params(pma,
8617 isl_union_set_get_space(domain));
8618 return isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(domain,
8619 pma);
8620 error:
8621 isl_union_set_free(domain);
8622 isl_pw_multi_aff_free(pma);
8623 return NULL;
8626 /* Return a union set containing those elements in the domains
8627 * of the elements of "mupa" where they are all zero.
8629 * If there are no elements, then simply return the entire domain.
8631 __isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
8632 __isl_take isl_multi_union_pw_aff *mupa)
8634 int i;
8635 isl_size n;
8636 isl_union_pw_aff *upa;
8637 isl_union_set *zero;
8639 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8640 if (n < 0)
8641 mupa = isl_multi_union_pw_aff_free(mupa);
8642 if (!mupa)
8643 return NULL;
8645 if (n == 0)
8646 return isl_multi_union_pw_aff_domain(mupa);
8648 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8649 zero = isl_union_pw_aff_zero_union_set(upa);
8651 for (i = 1; i < n; ++i) {
8652 isl_union_set *zero_i;
8654 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8655 zero_i = isl_union_pw_aff_zero_union_set(upa);
8657 zero = isl_union_set_intersect(zero, zero_i);
8660 isl_multi_union_pw_aff_free(mupa);
8661 return zero;
8664 /* Construct a union map mapping the shared domain
8665 * of the union piecewise affine expressions to the range of "mupa"
8666 * in the special case of a 0D multi union piecewise affine expression.
8668 * Construct a map between the explicit domain of "mupa" and
8669 * the range space.
8670 * Note that this assumes that the domain consists of explicit elements.
8672 static __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff_0D(
8673 __isl_take isl_multi_union_pw_aff *mupa)
8675 isl_bool is_params;
8676 isl_space *space;
8677 isl_union_set *dom, *ran;
8679 space = isl_multi_union_pw_aff_get_space(mupa);
8680 dom = isl_multi_union_pw_aff_domain(mupa);
8681 ran = isl_union_set_from_set(isl_set_universe(space));
8683 is_params = isl_union_set_is_params(dom);
8684 if (is_params < 0)
8685 dom = isl_union_set_free(dom);
8686 else if (is_params)
8687 isl_die(isl_union_set_get_ctx(dom), isl_error_invalid,
8688 "cannot create union map from expression without "
8689 "explicit domain elements",
8690 dom = isl_union_set_free(dom));
8692 return isl_union_map_from_domain_and_range(dom, ran);
8695 /* Construct a union map mapping the shared domain
8696 * of the union piecewise affine expressions to the range of "mupa"
8697 * with each dimension in the range equated to the
8698 * corresponding union piecewise affine expression.
8700 * If the input is zero-dimensional, then construct a mapping
8701 * from its explicit domain.
8703 __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
8704 __isl_take isl_multi_union_pw_aff *mupa)
8706 int i;
8707 isl_size n;
8708 isl_space *space;
8709 isl_union_map *umap;
8710 isl_union_pw_aff *upa;
8712 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8713 if (n < 0)
8714 mupa = isl_multi_union_pw_aff_free(mupa);
8715 if (!mupa)
8716 return NULL;
8718 if (n == 0)
8719 return isl_union_map_from_multi_union_pw_aff_0D(mupa);
8721 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8722 umap = isl_union_map_from_union_pw_aff(upa);
8724 for (i = 1; i < n; ++i) {
8725 isl_union_map *umap_i;
8727 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8728 umap_i = isl_union_map_from_union_pw_aff(upa);
8729 umap = isl_union_map_flat_range_product(umap, umap_i);
8732 space = isl_multi_union_pw_aff_get_space(mupa);
8733 umap = isl_union_map_reset_range_space(umap, space);
8735 isl_multi_union_pw_aff_free(mupa);
8736 return umap;
8739 /* Internal data structure for isl_union_pw_multi_aff_reset_range_space.
8740 * "range" is the space from which to set the range space.
8741 * "res" collects the results.
8743 struct isl_union_pw_multi_aff_reset_range_space_data {
8744 isl_space *range;
8745 isl_union_pw_multi_aff *res;
8748 /* Replace the range space of "pma" by the range space of data->range and
8749 * add the result to data->res.
8751 static isl_stat reset_range_space(__isl_take isl_pw_multi_aff *pma, void *user)
8753 struct isl_union_pw_multi_aff_reset_range_space_data *data = user;
8754 isl_space *space;
8756 space = isl_pw_multi_aff_get_space(pma);
8757 space = isl_space_domain(space);
8758 space = isl_space_extend_domain_with_range(space,
8759 isl_space_copy(data->range));
8760 pma = isl_pw_multi_aff_reset_space(pma, space);
8761 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
8763 return data->res ? isl_stat_ok : isl_stat_error;
8766 /* Replace the range space of all the piecewise affine expressions in "upma" by
8767 * the range space of "space".
8769 * This assumes that all these expressions have the same output dimension.
8771 * Since the spaces of the expressions change, so do their hash values.
8772 * We therefore need to create a new isl_union_pw_multi_aff.
8773 * Note that the hash value is currently computed based on the entire
8774 * space even though there can only be a single expression with a given
8775 * domain space.
8777 static __isl_give isl_union_pw_multi_aff *
8778 isl_union_pw_multi_aff_reset_range_space(
8779 __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *space)
8781 struct isl_union_pw_multi_aff_reset_range_space_data data = { space };
8782 isl_space *space_upma;
8784 space_upma = isl_union_pw_multi_aff_get_space(upma);
8785 data.res = isl_union_pw_multi_aff_empty(space_upma);
8786 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
8787 &reset_range_space, &data) < 0)
8788 data.res = isl_union_pw_multi_aff_free(data.res);
8790 isl_space_free(space);
8791 isl_union_pw_multi_aff_free(upma);
8792 return data.res;
8795 /* Construct and return a union piecewise multi affine expression
8796 * that is equal to the given multi union piecewise affine expression,
8797 * in the special case of a 0D multi union piecewise affine expression.
8799 * Construct a union piecewise multi affine expression
8800 * on top of the explicit domain of the input.
8802 __isl_give isl_union_pw_multi_aff *
8803 isl_union_pw_multi_aff_from_multi_union_pw_aff_0D(
8804 __isl_take isl_multi_union_pw_aff *mupa)
8806 isl_space *space;
8807 isl_multi_val *mv;
8808 isl_union_set *domain;
8810 space = isl_multi_union_pw_aff_get_space(mupa);
8811 mv = isl_multi_val_zero(space);
8812 domain = isl_multi_union_pw_aff_domain(mupa);
8813 return isl_union_pw_multi_aff_multi_val_on_domain(domain, mv);
8816 /* Construct and return a union piecewise multi affine expression
8817 * that is equal to the given multi union piecewise affine expression.
8819 * If the input is zero-dimensional, then
8820 * construct a union piecewise multi affine expression
8821 * on top of the explicit domain of the input.
8823 __isl_give isl_union_pw_multi_aff *
8824 isl_union_pw_multi_aff_from_multi_union_pw_aff(
8825 __isl_take isl_multi_union_pw_aff *mupa)
8827 int i;
8828 isl_size n;
8829 isl_space *space;
8830 isl_union_pw_multi_aff *upma;
8831 isl_union_pw_aff *upa;
8833 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8834 if (n < 0)
8835 mupa = isl_multi_union_pw_aff_free(mupa);
8836 if (!mupa)
8837 return NULL;
8839 if (n == 0)
8840 return isl_union_pw_multi_aff_from_multi_union_pw_aff_0D(mupa);
8842 space = isl_multi_union_pw_aff_get_space(mupa);
8843 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8844 upma = isl_union_pw_multi_aff_from_union_pw_aff(upa);
8846 for (i = 1; i < n; ++i) {
8847 isl_union_pw_multi_aff *upma_i;
8849 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8850 upma_i = isl_union_pw_multi_aff_from_union_pw_aff(upa);
8851 upma = isl_union_pw_multi_aff_flat_range_product(upma, upma_i);
8854 upma = isl_union_pw_multi_aff_reset_range_space(upma, space);
8856 isl_multi_union_pw_aff_free(mupa);
8857 return upma;
8860 /* Intersect the range of "mupa" with "range",
8861 * in the special case where "mupa" is 0D.
8863 * Intersect the domain of "mupa" with the constraints on the parameters
8864 * of "range".
8866 static __isl_give isl_multi_union_pw_aff *mupa_intersect_range_0D(
8867 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *range)
8869 range = isl_set_params(range);
8870 mupa = isl_multi_union_pw_aff_intersect_params(mupa, range);
8871 return mupa;
8874 /* Intersect the range of "mupa" with "range".
8875 * That is, keep only those domain elements that have a function value
8876 * in "range".
8878 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
8879 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *range)
8881 isl_union_pw_multi_aff *upma;
8882 isl_union_set *domain;
8883 isl_space *space;
8884 isl_size n;
8885 int match;
8887 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8888 if (n < 0 || !range)
8889 goto error;
8891 space = isl_set_get_space(range);
8892 match = isl_space_tuple_is_equal(mupa->space, isl_dim_set,
8893 space, isl_dim_set);
8894 isl_space_free(space);
8895 if (match < 0)
8896 goto error;
8897 if (!match)
8898 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
8899 "space don't match", goto error);
8900 if (n == 0)
8901 return mupa_intersect_range_0D(mupa, range);
8903 upma = isl_union_pw_multi_aff_from_multi_union_pw_aff(
8904 isl_multi_union_pw_aff_copy(mupa));
8905 domain = isl_union_set_from_set(range);
8906 domain = isl_union_set_preimage_union_pw_multi_aff(domain, upma);
8907 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, domain);
8909 return mupa;
8910 error:
8911 isl_multi_union_pw_aff_free(mupa);
8912 isl_set_free(range);
8913 return NULL;
8916 /* Return the shared domain of the elements of "mupa",
8917 * in the special case where "mupa" is zero-dimensional.
8919 * Return the explicit domain of "mupa".
8920 * Note that this domain may be a parameter set, either
8921 * because "mupa" is meant to live in a set space or
8922 * because no explicit domain has been set.
8924 __isl_give isl_union_set *isl_multi_union_pw_aff_domain_0D(
8925 __isl_take isl_multi_union_pw_aff *mupa)
8927 isl_union_set *dom;
8929 dom = isl_multi_union_pw_aff_get_explicit_domain(mupa);
8930 isl_multi_union_pw_aff_free(mupa);
8932 return dom;
8935 /* Return the shared domain of the elements of "mupa".
8937 * If "mupa" is zero-dimensional, then return its explicit domain.
8939 __isl_give isl_union_set *isl_multi_union_pw_aff_domain(
8940 __isl_take isl_multi_union_pw_aff *mupa)
8942 int i;
8943 isl_size n;
8944 isl_union_pw_aff *upa;
8945 isl_union_set *dom;
8947 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
8948 if (n < 0)
8949 mupa = isl_multi_union_pw_aff_free(mupa);
8950 if (!mupa)
8951 return NULL;
8953 if (n == 0)
8954 return isl_multi_union_pw_aff_domain_0D(mupa);
8956 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
8957 dom = isl_union_pw_aff_domain(upa);
8958 for (i = 1; i < n; ++i) {
8959 isl_union_set *dom_i;
8961 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
8962 dom_i = isl_union_pw_aff_domain(upa);
8963 dom = isl_union_set_intersect(dom, dom_i);
8966 isl_multi_union_pw_aff_free(mupa);
8967 return dom;
8970 /* Apply "aff" to "mupa". The space of "mupa" is equal to the domain of "aff".
8971 * In particular, the spaces have been aligned.
8972 * The result is defined over the shared domain of the elements of "mupa"
8974 * We first extract the parametric constant part of "aff" and
8975 * define that over the shared domain.
8976 * Then we iterate over all input dimensions of "aff" and add the corresponding
8977 * multiples of the elements of "mupa".
8978 * Finally, we consider the integer divisions, calling the function
8979 * recursively to obtain an isl_union_pw_aff corresponding to the
8980 * integer division argument.
8982 static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff(
8983 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
8985 int i;
8986 isl_size n_in, n_div;
8987 isl_union_pw_aff *upa;
8988 isl_union_set *uset;
8989 isl_val *v;
8990 isl_aff *cst;
8992 n_in = isl_aff_dim(aff, isl_dim_in);
8993 n_div = isl_aff_dim(aff, isl_dim_div);
8994 if (n_in < 0 || n_div < 0)
8995 goto error;
8997 uset = isl_multi_union_pw_aff_domain(isl_multi_union_pw_aff_copy(mupa));
8998 cst = isl_aff_copy(aff);
8999 cst = isl_aff_drop_dims(cst, isl_dim_div, 0, n_div);
9000 cst = isl_aff_drop_dims(cst, isl_dim_in, 0, n_in);
9001 cst = isl_aff_project_domain_on_params(cst);
9002 upa = isl_union_pw_aff_aff_on_domain(uset, cst);
9004 for (i = 0; i < n_in; ++i) {
9005 isl_union_pw_aff *upa_i;
9007 if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
9008 continue;
9009 v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
9010 upa_i = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
9011 upa_i = isl_union_pw_aff_scale_val(upa_i, v);
9012 upa = isl_union_pw_aff_add(upa, upa_i);
9015 for (i = 0; i < n_div; ++i) {
9016 isl_aff *div;
9017 isl_union_pw_aff *upa_i;
9019 if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
9020 continue;
9021 div = isl_aff_get_div(aff, i);
9022 upa_i = multi_union_pw_aff_apply_aff(
9023 isl_multi_union_pw_aff_copy(mupa), div);
9024 upa_i = isl_union_pw_aff_floor(upa_i);
9025 v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
9026 upa_i = isl_union_pw_aff_scale_val(upa_i, v);
9027 upa = isl_union_pw_aff_add(upa, upa_i);
9030 isl_multi_union_pw_aff_free(mupa);
9031 isl_aff_free(aff);
9033 return upa;
9034 error:
9035 isl_multi_union_pw_aff_free(mupa);
9036 isl_aff_free(aff);
9037 return NULL;
9040 /* Apply "aff" to "mupa". The space of "mupa" needs to be compatible
9041 * with the domain of "aff".
9042 * Furthermore, the dimension of this space needs to be greater than zero.
9043 * The result is defined over the shared domain of the elements of "mupa"
9045 * We perform these checks and then hand over control to
9046 * multi_union_pw_aff_apply_aff.
9048 __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff(
9049 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
9051 isl_size dim;
9052 isl_space *space1, *space2;
9053 isl_bool equal;
9055 mupa = isl_multi_union_pw_aff_align_params(mupa,
9056 isl_aff_get_space(aff));
9057 aff = isl_aff_align_params(aff, isl_multi_union_pw_aff_get_space(mupa));
9058 if (!mupa || !aff)
9059 goto error;
9061 space1 = isl_multi_union_pw_aff_get_space(mupa);
9062 space2 = isl_aff_get_domain_space(aff);
9063 equal = isl_space_is_equal(space1, space2);
9064 isl_space_free(space1);
9065 isl_space_free(space2);
9066 if (equal < 0)
9067 goto error;
9068 if (!equal)
9069 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
9070 "spaces don't match", goto error);
9071 dim = isl_aff_dim(aff, isl_dim_in);
9072 if (dim < 0)
9073 goto error;
9074 if (dim == 0)
9075 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
9076 "cannot determine domains", goto error);
9078 return multi_union_pw_aff_apply_aff(mupa, aff);
9079 error:
9080 isl_multi_union_pw_aff_free(mupa);
9081 isl_aff_free(aff);
9082 return NULL;
9085 /* Apply "ma" to "mupa", in the special case where "mupa" is 0D.
9086 * The space of "mupa" is known to be compatible with the domain of "ma".
9088 * Construct an isl_multi_union_pw_aff that is equal to "ma"
9089 * on the domain of "mupa".
9091 static __isl_give isl_multi_union_pw_aff *mupa_apply_multi_aff_0D(
9092 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma)
9094 isl_union_set *dom;
9096 dom = isl_multi_union_pw_aff_domain(mupa);
9097 ma = isl_multi_aff_project_domain_on_params(ma);
9099 return isl_multi_union_pw_aff_multi_aff_on_domain(dom, ma);
9102 /* Apply "ma" to "mupa". The space of "mupa" needs to be compatible
9103 * with the domain of "ma".
9104 * The result is defined over the shared domain of the elements of "mupa"
9106 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
9107 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma)
9109 isl_space *space1, *space2;
9110 isl_multi_union_pw_aff *res;
9111 isl_bool equal;
9112 int i;
9113 isl_size n_in, n_out;
9115 mupa = isl_multi_union_pw_aff_align_params(mupa,
9116 isl_multi_aff_get_space(ma));
9117 ma = isl_multi_aff_align_params(ma,
9118 isl_multi_union_pw_aff_get_space(mupa));
9119 n_in = isl_multi_aff_dim(ma, isl_dim_in);
9120 n_out = isl_multi_aff_dim(ma, isl_dim_out);
9121 if (!mupa || n_in < 0 || n_out < 0)
9122 goto error;
9124 space1 = isl_multi_union_pw_aff_get_space(mupa);
9125 space2 = isl_multi_aff_get_domain_space(ma);
9126 equal = isl_space_is_equal(space1, space2);
9127 isl_space_free(space1);
9128 isl_space_free(space2);
9129 if (equal < 0)
9130 goto error;
9131 if (!equal)
9132 isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
9133 "spaces don't match", goto error);
9134 if (n_in == 0)
9135 return mupa_apply_multi_aff_0D(mupa, ma);
9137 space1 = isl_space_range(isl_multi_aff_get_space(ma));
9138 res = isl_multi_union_pw_aff_alloc(space1);
9140 for (i = 0; i < n_out; ++i) {
9141 isl_aff *aff;
9142 isl_union_pw_aff *upa;
9144 aff = isl_multi_aff_get_aff(ma, i);
9145 upa = multi_union_pw_aff_apply_aff(
9146 isl_multi_union_pw_aff_copy(mupa), aff);
9147 res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa);
9150 isl_multi_aff_free(ma);
9151 isl_multi_union_pw_aff_free(mupa);
9152 return res;
9153 error:
9154 isl_multi_union_pw_aff_free(mupa);
9155 isl_multi_aff_free(ma);
9156 return NULL;
9159 /* Apply "pa" to "mupa", in the special case where "mupa" is 0D.
9160 * The space of "mupa" is known to be compatible with the domain of "pa".
9162 * Construct an isl_multi_union_pw_aff that is equal to "pa"
9163 * on the domain of "mupa".
9165 static __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff_0D(
9166 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa)
9168 isl_union_set *dom;
9170 dom = isl_multi_union_pw_aff_domain(mupa);
9171 pa = isl_pw_aff_project_domain_on_params(pa);
9173 return isl_union_pw_aff_pw_aff_on_domain(dom, pa);
9176 /* Apply "pa" to "mupa". The space of "mupa" needs to be compatible
9177 * with the domain of "pa".
9178 * Furthermore, the dimension of this space needs to be greater than zero.
9179 * The result is defined over the shared domain of the elements of "mupa"
9181 __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff(
9182 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa)
9184 int i;
9185 isl_bool equal;
9186 isl_size n_in;
9187 isl_space *space, *space2;
9188 isl_union_pw_aff *upa;
9190 mupa = isl_multi_union_pw_aff_align_params(mupa,
9191 isl_pw_aff_get_space(pa));
9192 pa = isl_pw_aff_align_params(pa,
9193 isl_multi_union_pw_aff_get_space(mupa));
9194 if (!mupa || !pa)
9195 goto error;
9197 space = isl_multi_union_pw_aff_get_space(mupa);
9198 space2 = isl_pw_aff_get_domain_space(pa);
9199 equal = isl_space_is_equal(space, space2);
9200 isl_space_free(space);
9201 isl_space_free(space2);
9202 if (equal < 0)
9203 goto error;
9204 if (!equal)
9205 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
9206 "spaces don't match", goto error);
9207 n_in = isl_pw_aff_dim(pa, isl_dim_in);
9208 if (n_in < 0)
9209 goto error;
9210 if (n_in == 0)
9211 return isl_multi_union_pw_aff_apply_pw_aff_0D(mupa, pa);
9213 space = isl_space_params(isl_multi_union_pw_aff_get_space(mupa));
9214 upa = isl_union_pw_aff_empty(space);
9216 for (i = 0; i < pa->n; ++i) {
9217 isl_aff *aff;
9218 isl_set *domain;
9219 isl_multi_union_pw_aff *mupa_i;
9220 isl_union_pw_aff *upa_i;
9222 mupa_i = isl_multi_union_pw_aff_copy(mupa);
9223 domain = isl_set_copy(pa->p[i].set);
9224 mupa_i = isl_multi_union_pw_aff_intersect_range(mupa_i, domain);
9225 aff = isl_aff_copy(pa->p[i].aff);
9226 upa_i = multi_union_pw_aff_apply_aff(mupa_i, aff);
9227 upa = isl_union_pw_aff_union_add(upa, upa_i);
9230 isl_multi_union_pw_aff_free(mupa);
9231 isl_pw_aff_free(pa);
9232 return upa;
9233 error:
9234 isl_multi_union_pw_aff_free(mupa);
9235 isl_pw_aff_free(pa);
9236 return NULL;
9239 /* Apply "pma" to "mupa", in the special case where "mupa" is 0D.
9240 * The space of "mupa" is known to be compatible with the domain of "pma".
9242 * Construct an isl_multi_union_pw_aff that is equal to "pma"
9243 * on the domain of "mupa".
9245 static __isl_give isl_multi_union_pw_aff *mupa_apply_pw_multi_aff_0D(
9246 __isl_take isl_multi_union_pw_aff *mupa,
9247 __isl_take isl_pw_multi_aff *pma)
9249 isl_union_set *dom;
9251 dom = isl_multi_union_pw_aff_domain(mupa);
9252 pma = isl_pw_multi_aff_project_domain_on_params(pma);
9254 return isl_multi_union_pw_aff_pw_multi_aff_on_domain(dom, pma);
9257 /* Apply "pma" to "mupa". The space of "mupa" needs to be compatible
9258 * with the domain of "pma".
9259 * The result is defined over the shared domain of the elements of "mupa"
9261 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
9262 __isl_take isl_multi_union_pw_aff *mupa,
9263 __isl_take isl_pw_multi_aff *pma)
9265 isl_space *space1, *space2;
9266 isl_multi_union_pw_aff *res;
9267 isl_bool equal;
9268 int i;
9269 isl_size n_in, n_out;
9271 mupa = isl_multi_union_pw_aff_align_params(mupa,
9272 isl_pw_multi_aff_get_space(pma));
9273 pma = isl_pw_multi_aff_align_params(pma,
9274 isl_multi_union_pw_aff_get_space(mupa));
9275 if (!mupa || !pma)
9276 goto error;
9278 space1 = isl_multi_union_pw_aff_get_space(mupa);
9279 space2 = isl_pw_multi_aff_get_domain_space(pma);
9280 equal = isl_space_is_equal(space1, space2);
9281 isl_space_free(space1);
9282 isl_space_free(space2);
9283 if (equal < 0)
9284 goto error;
9285 if (!equal)
9286 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
9287 "spaces don't match", goto error);
9288 n_in = isl_pw_multi_aff_dim(pma, isl_dim_in);
9289 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
9290 if (n_in < 0 || n_out < 0)
9291 goto error;
9292 if (n_in == 0)
9293 return mupa_apply_pw_multi_aff_0D(mupa, pma);
9295 space1 = isl_space_range(isl_pw_multi_aff_get_space(pma));
9296 res = isl_multi_union_pw_aff_alloc(space1);
9298 for (i = 0; i < n_out; ++i) {
9299 isl_pw_aff *pa;
9300 isl_union_pw_aff *upa;
9302 pa = isl_pw_multi_aff_get_pw_aff(pma, i);
9303 upa = isl_multi_union_pw_aff_apply_pw_aff(
9304 isl_multi_union_pw_aff_copy(mupa), pa);
9305 res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa);
9308 isl_pw_multi_aff_free(pma);
9309 isl_multi_union_pw_aff_free(mupa);
9310 return res;
9311 error:
9312 isl_multi_union_pw_aff_free(mupa);
9313 isl_pw_multi_aff_free(pma);
9314 return NULL;
9317 /* Replace the explicit domain of "mupa" by its preimage under "upma".
9318 * If the explicit domain only keeps track of constraints on the parameters,
9319 * then only update those constraints.
9321 static __isl_give isl_multi_union_pw_aff *preimage_explicit_domain(
9322 __isl_take isl_multi_union_pw_aff *mupa,
9323 __isl_keep isl_union_pw_multi_aff *upma)
9325 isl_bool is_params;
9327 if (isl_multi_union_pw_aff_check_has_explicit_domain(mupa) < 0)
9328 return isl_multi_union_pw_aff_free(mupa);
9330 mupa = isl_multi_union_pw_aff_cow(mupa);
9331 if (!mupa)
9332 return NULL;
9334 is_params = isl_union_set_is_params(mupa->u.dom);
9335 if (is_params < 0)
9336 return isl_multi_union_pw_aff_free(mupa);
9338 upma = isl_union_pw_multi_aff_copy(upma);
9339 if (is_params)
9340 mupa->u.dom = isl_union_set_intersect_params(mupa->u.dom,
9341 isl_union_set_params(isl_union_pw_multi_aff_domain(upma)));
9342 else
9343 mupa->u.dom = isl_union_set_preimage_union_pw_multi_aff(
9344 mupa->u.dom, upma);
9345 if (!mupa->u.dom)
9346 return isl_multi_union_pw_aff_free(mupa);
9347 return mupa;
9350 /* Compute the pullback of "mupa" by the function represented by "upma".
9351 * In other words, plug in "upma" in "mupa". The result contains
9352 * expressions defined over the domain space of "upma".
9354 * Run over all elements of "mupa" and plug in "upma" in each of them.
9356 * If "mupa" has an explicit domain, then it is this domain
9357 * that needs to undergo a pullback instead, i.e., a preimage.
9359 __isl_give isl_multi_union_pw_aff *
9360 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
9361 __isl_take isl_multi_union_pw_aff *mupa,
9362 __isl_take isl_union_pw_multi_aff *upma)
9364 int i;
9365 isl_size n;
9367 mupa = isl_multi_union_pw_aff_align_params(mupa,
9368 isl_union_pw_multi_aff_get_space(upma));
9369 upma = isl_union_pw_multi_aff_align_params(upma,
9370 isl_multi_union_pw_aff_get_space(mupa));
9371 mupa = isl_multi_union_pw_aff_cow(mupa);
9372 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
9373 if (n < 0 || !upma)
9374 goto error;
9376 for (i = 0; i < n; ++i) {
9377 isl_union_pw_aff *upa;
9379 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
9380 upa = isl_union_pw_aff_pullback_union_pw_multi_aff(upa,
9381 isl_union_pw_multi_aff_copy(upma));
9382 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
9385 if (isl_multi_union_pw_aff_has_explicit_domain(mupa))
9386 mupa = preimage_explicit_domain(mupa, upma);
9388 isl_union_pw_multi_aff_free(upma);
9389 return mupa;
9390 error:
9391 isl_multi_union_pw_aff_free(mupa);
9392 isl_union_pw_multi_aff_free(upma);
9393 return NULL;
9396 /* Extract the sequence of elements in "mupa" with domain space "space"
9397 * (ignoring parameters).
9399 * For the elements of "mupa" that are not defined on the specified space,
9400 * the corresponding element in the result is empty.
9402 __isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
9403 __isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space)
9405 int i;
9406 isl_size n;
9407 isl_space *space_mpa;
9408 isl_multi_pw_aff *mpa;
9410 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
9411 if (n < 0 || !space)
9412 goto error;
9414 space_mpa = isl_multi_union_pw_aff_get_space(mupa);
9415 space = isl_space_replace_params(space, space_mpa);
9416 space_mpa = isl_space_map_from_domain_and_range(isl_space_copy(space),
9417 space_mpa);
9418 mpa = isl_multi_pw_aff_alloc(space_mpa);
9420 space = isl_space_from_domain(space);
9421 space = isl_space_add_dims(space, isl_dim_out, 1);
9422 for (i = 0; i < n; ++i) {
9423 isl_union_pw_aff *upa;
9424 isl_pw_aff *pa;
9426 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
9427 pa = isl_union_pw_aff_extract_pw_aff(upa,
9428 isl_space_copy(space));
9429 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
9430 isl_union_pw_aff_free(upa);
9433 isl_space_free(space);
9434 return mpa;
9435 error:
9436 isl_space_free(space);
9437 return NULL;
9440 /* Evaluate the affine function "aff" in the void point "pnt".
9441 * In particular, return the value NaN.
9443 static __isl_give isl_val *eval_void(__isl_take isl_aff *aff,
9444 __isl_take isl_point *pnt)
9446 isl_ctx *ctx;
9448 ctx = isl_point_get_ctx(pnt);
9449 isl_aff_free(aff);
9450 isl_point_free(pnt);
9451 return isl_val_nan(ctx);
9454 /* Evaluate the affine expression "aff"
9455 * in the coordinates (with denominator) "pnt".
9457 static __isl_give isl_val *eval(__isl_keep isl_vec *aff,
9458 __isl_keep isl_vec *pnt)
9460 isl_int n, d;
9461 isl_ctx *ctx;
9462 isl_val *v;
9464 if (!aff || !pnt)
9465 return NULL;
9467 ctx = isl_vec_get_ctx(aff);
9468 isl_int_init(n);
9469 isl_int_init(d);
9470 isl_seq_inner_product(aff->el + 1, pnt->el, pnt->size, &n);
9471 isl_int_mul(d, aff->el[0], pnt->el[0]);
9472 v = isl_val_rat_from_isl_int(ctx, n, d);
9473 v = isl_val_normalize(v);
9474 isl_int_clear(n);
9475 isl_int_clear(d);
9477 return v;
9480 /* Check that the domain space of "aff" is equal to "space".
9482 static isl_stat isl_aff_check_has_domain_space(__isl_keep isl_aff *aff,
9483 __isl_keep isl_space *space)
9485 isl_bool ok;
9487 ok = isl_space_is_equal(isl_aff_peek_domain_space(aff), space);
9488 if (ok < 0)
9489 return isl_stat_error;
9490 if (!ok)
9491 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
9492 "incompatible spaces", return isl_stat_error);
9493 return isl_stat_ok;
9496 /* Evaluate the affine function "aff" in "pnt".
9498 __isl_give isl_val *isl_aff_eval(__isl_take isl_aff *aff,
9499 __isl_take isl_point *pnt)
9501 isl_bool is_void;
9502 isl_val *v;
9503 isl_local_space *ls;
9505 if (isl_aff_check_has_domain_space(aff, isl_point_peek_space(pnt)) < 0)
9506 goto error;
9507 is_void = isl_point_is_void(pnt);
9508 if (is_void < 0)
9509 goto error;
9510 if (is_void)
9511 return eval_void(aff, pnt);
9513 ls = isl_aff_get_domain_local_space(aff);
9514 pnt = isl_local_space_lift_point(ls, pnt);
9516 v = eval(aff->v, isl_point_peek_vec(pnt));
9518 isl_aff_free(aff);
9519 isl_point_free(pnt);
9521 return v;
9522 error:
9523 isl_aff_free(aff);
9524 isl_point_free(pnt);
9525 return NULL;