2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 #include <isl_union_map_private.h>
12 #include <isl_polynomial_private.h>
13 #include <isl_point_private.h>
14 #include <isl_dim_private.h>
15 #include <isl_map_private.h>
19 static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
20 enum isl_fold type, __isl_take isl_dim *dim, int n)
22 isl_qpolynomial_fold *fold;
27 isl_assert(dim->ctx, n >= 0, goto error);
28 fold = isl_calloc(dim->ctx, struct isl_qpolynomial_fold,
29 sizeof(struct isl_qpolynomial_fold) +
30 (n - 1) * sizeof(struct isl_qpolynomial *));
46 int isl_qpolynomial_fold_involves_dims(__isl_keep isl_qpolynomial_fold *fold,
47 enum isl_dim_type type, unsigned first, unsigned n)
53 if (fold->n == 0 || n == 0)
56 for (i = 0; i < fold->n; ++i) {
57 int involves = isl_qpolynomial_involves_dims(fold->qp[i],
59 if (involves < 0 || involves)
65 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_drop_dims(
66 __isl_take isl_qpolynomial_fold *fold,
67 enum isl_dim_type type, unsigned first, unsigned n)
76 fold = isl_qpolynomial_fold_cow(fold);
79 fold->dim = isl_dim_drop(fold->dim, type, first, n);
83 for (i = 0; i < fold->n; ++i) {
84 fold->qp[i] = isl_qpolynomial_drop_dims(fold->qp[i],
92 isl_qpolynomial_fold_free(fold);
96 static int isl_qpolynomial_cst_sign(__isl_keep isl_qpolynomial *qp)
98 struct isl_upoly_cst *cst;
100 cst = isl_upoly_as_cst(qp->upoly);
104 return isl_int_sgn(cst->n) < 0 ? -1 : 1;
107 static int isl_qpolynomial_aff_sign(__isl_keep isl_set *set,
108 __isl_keep isl_qpolynomial *qp)
110 enum isl_lp_result res;
115 aff = isl_qpolynomial_extract_affine(qp);
121 res = isl_set_solve_lp(set, 0, aff->el + 1, aff->el[0],
123 if (res == isl_lp_error)
125 if (res == isl_lp_empty ||
126 (res == isl_lp_ok && !isl_int_is_neg(opt))) {
131 res = isl_set_solve_lp(set, 1, aff->el + 1, aff->el[0],
133 if (res == isl_lp_ok && !isl_int_is_pos(opt))
142 /* Determine, if possible, the sign of the quasipolynomial "qp" on
145 * If qp is a constant, then the problem is trivial.
146 * If qp is linear, then we check if the minimum of the corresponding
147 * affine constraint is non-negative or if the maximum is non-positive.
149 * Otherwise, we check if the outermost variable "v" has a lower bound "l"
150 * in "set". If so, we write qp(v,v') as
152 * q(v,v') * (v - l) + r(v')
154 * if q(v,v') and r(v') have the same known sign, then the original
155 * quasipolynomial has the same sign as well.
162 static int isl_qpolynomial_sign(__isl_keep isl_set *set,
163 __isl_keep isl_qpolynomial *qp)
168 struct isl_upoly_rec *rec;
171 enum isl_lp_result res;
174 is = isl_qpolynomial_is_cst(qp, NULL, NULL);
178 return isl_qpolynomial_cst_sign(qp);
180 is = isl_qpolynomial_is_affine(qp);
184 return isl_qpolynomial_aff_sign(set, qp);
186 if (qp->div->n_row > 0)
189 rec = isl_upoly_as_rec(qp->upoly);
193 d = isl_dim_total(qp->dim);
194 v = isl_vec_alloc(set->ctx, 2 + d);
198 isl_seq_clr(v->el + 1, 1 + d);
199 isl_int_set_si(v->el[0], 1);
200 isl_int_set_si(v->el[2 + qp->upoly->var], 1);
204 res = isl_set_solve_lp(set, 0, v->el + 1, v->el[0], &l, NULL, NULL);
205 if (res == isl_lp_ok) {
206 isl_qpolynomial *min;
207 isl_qpolynomial *base;
208 isl_qpolynomial *r, *q;
211 min = isl_qpolynomial_cst(isl_dim_copy(qp->dim), l);
212 base = isl_qpolynomial_pow(isl_dim_copy(qp->dim),
215 r = isl_qpolynomial_alloc(isl_dim_copy(qp->dim), 0,
216 isl_upoly_copy(rec->p[rec->n - 1]));
217 q = isl_qpolynomial_copy(r);
219 for (i = rec->n - 2; i >= 0; --i) {
220 r = isl_qpolynomial_mul(r, isl_qpolynomial_copy(min));
221 t = isl_qpolynomial_alloc(isl_dim_copy(qp->dim), 0,
222 isl_upoly_copy(rec->p[i]));
223 r = isl_qpolynomial_add(r, t);
226 q = isl_qpolynomial_mul(q, isl_qpolynomial_copy(base));
227 q = isl_qpolynomial_add(q, isl_qpolynomial_copy(r));
230 if (isl_qpolynomial_is_zero(q))
231 sgn = isl_qpolynomial_sign(set, r);
232 else if (isl_qpolynomial_is_zero(r))
233 sgn = isl_qpolynomial_sign(set, q);
236 sgn_r = isl_qpolynomial_sign(set, r);
237 sgn_q = isl_qpolynomial_sign(set, q);
242 isl_qpolynomial_free(min);
243 isl_qpolynomial_free(base);
244 isl_qpolynomial_free(q);
245 isl_qpolynomial_free(r);
255 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold_on_domain(
256 __isl_keep isl_set *set,
257 __isl_take isl_qpolynomial_fold *fold1,
258 __isl_take isl_qpolynomial_fold *fold2)
262 struct isl_qpolynomial_fold *res = NULL;
265 if (!fold1 || !fold2)
268 isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
269 isl_assert(fold1->dim->ctx, isl_dim_equal(fold1->dim, fold2->dim),
272 better = fold1->type == isl_fold_max ? -1 : 1;
274 if (isl_qpolynomial_fold_is_empty(fold1)) {
275 isl_qpolynomial_fold_free(fold1);
279 if (isl_qpolynomial_fold_is_empty(fold2)) {
280 isl_qpolynomial_fold_free(fold2);
284 res = qpolynomial_fold_alloc(fold1->type, isl_dim_copy(fold1->dim),
285 fold1->n + fold2->n);
289 for (i = 0; i < fold1->n; ++i) {
290 res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
291 if (!res->qp[res->n])
297 for (i = 0; i < fold2->n; ++i) {
298 for (j = n1 - 1; j >= 0; --j) {
301 d = isl_qpolynomial_sub(
302 isl_qpolynomial_copy(res->qp[j]),
303 isl_qpolynomial_copy(fold2->qp[i]));
304 sgn = isl_qpolynomial_sign(set, d);
305 isl_qpolynomial_free(d);
310 isl_qpolynomial_free(res->qp[j]);
312 res->qp[j] = res->qp[n1 - 1];
314 if (n1 != res->n - 1)
315 res->qp[n1] = res->qp[res->n - 1];
320 res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
321 if (!res->qp[res->n])
326 isl_qpolynomial_fold_free(fold1);
327 isl_qpolynomial_fold_free(fold2);
331 isl_qpolynomial_fold_free(res);
332 isl_qpolynomial_fold_free(fold1);
333 isl_qpolynomial_fold_free(fold2);
338 #define PW isl_pw_qpolynomial_fold
340 #define EL isl_qpolynomial_fold
342 #define IS_ZERO is_empty
346 #define ADD(d,e1,e2) isl_qpolynomial_fold_fold_on_domain(d,e1,e2)
348 #include <isl_pw_templ.c>
351 #define UNION isl_union_pw_qpolynomial_fold
353 #define PART isl_pw_qpolynomial_fold
355 #define PARTS pw_qpolynomial_fold
357 #include <isl_union_templ.c>
359 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
360 __isl_take isl_dim *dim)
362 return qpolynomial_fold_alloc(type, dim, 0);
365 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
366 enum isl_fold type, __isl_take isl_qpolynomial *qp)
368 isl_qpolynomial_fold *fold;
373 fold = qpolynomial_fold_alloc(type, isl_dim_copy(qp->dim), 1);
382 isl_qpolynomial_fold_free(fold);
383 isl_qpolynomial_free(qp);
387 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
388 __isl_keep isl_qpolynomial_fold *fold)
397 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_dup(
398 __isl_keep isl_qpolynomial_fold *fold)
401 isl_qpolynomial_fold *dup;
405 dup = qpolynomial_fold_alloc(fold->type,
406 isl_dim_copy(fold->dim), fold->n);
411 for (i = 0; i < fold->n; ++i) {
412 dup->qp[i] = isl_qpolynomial_copy(fold->qp[i]);
419 isl_qpolynomial_fold_free(dup);
423 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_cow(
424 __isl_take isl_qpolynomial_fold *fold)
432 return isl_qpolynomial_fold_dup(fold);
435 void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold)
444 for (i = 0; i < fold->n; ++i)
445 isl_qpolynomial_free(fold->qp[i]);
446 isl_dim_free(fold->dim);
450 int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
458 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
459 __isl_take isl_qpolynomial_fold *fold1,
460 __isl_take isl_qpolynomial_fold *fold2)
463 struct isl_qpolynomial_fold *res = NULL;
465 if (!fold1 || !fold2)
468 isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
469 isl_assert(fold1->dim->ctx, isl_dim_equal(fold1->dim, fold2->dim),
472 if (isl_qpolynomial_fold_is_empty(fold1)) {
473 isl_qpolynomial_fold_free(fold1);
477 if (isl_qpolynomial_fold_is_empty(fold2)) {
478 isl_qpolynomial_fold_free(fold2);
482 res = qpolynomial_fold_alloc(fold1->type, isl_dim_copy(fold1->dim),
483 fold1->n + fold2->n);
487 for (i = 0; i < fold1->n; ++i) {
488 res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
489 if (!res->qp[res->n])
494 for (i = 0; i < fold2->n; ++i) {
495 res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
496 if (!res->qp[res->n])
501 isl_qpolynomial_fold_free(fold1);
502 isl_qpolynomial_fold_free(fold2);
506 isl_qpolynomial_fold_free(res);
507 isl_qpolynomial_fold_free(fold1);
508 isl_qpolynomial_fold_free(fold2);
512 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
513 enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp)
516 isl_pw_qpolynomial_fold *pwf;
521 pwf = isl_pw_qpolynomial_fold_alloc_(isl_dim_copy(pwqp->dim), pwqp->n);
523 for (i = 0; i < pwqp->n; ++i)
524 pwf = isl_pw_qpolynomial_fold_add_piece(pwf,
525 isl_set_copy(pwqp->p[i].set),
526 isl_qpolynomial_fold_alloc(type,
527 isl_qpolynomial_copy(pwqp->p[i].qp)));
529 isl_pw_qpolynomial_free(pwqp);
534 int isl_qpolynomial_fold_is_equal(__isl_keep isl_qpolynomial_fold *fold1,
535 __isl_keep isl_qpolynomial_fold *fold2)
539 if (!fold1 || !fold2)
542 if (fold1->n != fold2->n)
545 /* We probably want to sort the qps first... */
546 for (i = 0; i < fold1->n; ++i) {
547 int eq = isl_qpolynomial_is_equal(fold1->qp[i], fold2->qp[i]);
555 __isl_give isl_qpolynomial *isl_qpolynomial_fold_eval(
556 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_point *pnt)
562 isl_assert(pnt->dim->ctx, isl_dim_equal(pnt->dim, fold->dim), goto error);
563 isl_assert(pnt->dim->ctx,
564 fold->type == isl_fold_max || fold->type == isl_fold_min,
568 qp = isl_qpolynomial_zero(isl_dim_copy(fold->dim));
571 qp = isl_qpolynomial_eval(isl_qpolynomial_copy(fold->qp[0]),
572 isl_point_copy(pnt));
573 for (i = 1; i < fold->n; ++i) {
574 isl_qpolynomial *qp_i;
575 qp_i = isl_qpolynomial_eval(
576 isl_qpolynomial_copy(fold->qp[i]),
577 isl_point_copy(pnt));
578 if (fold->type == isl_fold_max)
579 qp = isl_qpolynomial_max_cst(qp, qp_i);
581 qp = isl_qpolynomial_min_cst(qp, qp_i);
584 isl_qpolynomial_fold_free(fold);
589 isl_qpolynomial_fold_free(fold);
594 size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold *pwf)
599 for (i = 0; i < pwf->n; ++i)
600 n += pwf->p[i].fold->n;
605 __isl_give isl_qpolynomial *isl_qpolynomial_fold_opt_on_domain(
606 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *set, int max)
609 isl_qpolynomial *opt;
615 isl_dim *dim = isl_dim_copy(fold->dim);
617 isl_qpolynomial_fold_free(fold);
618 return isl_qpolynomial_zero(dim);
621 opt = isl_qpolynomial_opt_on_domain(isl_qpolynomial_copy(fold->qp[0]),
622 isl_set_copy(set), max);
623 for (i = 1; i < fold->n; ++i) {
624 isl_qpolynomial *opt_i;
625 opt_i = isl_qpolynomial_opt_on_domain(
626 isl_qpolynomial_copy(fold->qp[i]),
627 isl_set_copy(set), max);
629 opt = isl_qpolynomial_max_cst(opt, opt_i);
631 opt = isl_qpolynomial_min_cst(opt, opt_i);
635 isl_qpolynomial_fold_free(fold);
640 isl_qpolynomial_fold_free(fold);
644 /* Check whether for each quasi-polynomial in "fold2" there is
645 * a quasi-polynomial in "fold1" that dominates it on "set".
647 static int qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
648 __isl_keep isl_qpolynomial_fold *fold1,
649 __isl_keep isl_qpolynomial_fold *fold2)
654 if (!set || !fold1 || !fold2)
657 covers = fold1->type == isl_fold_max ? 1 : -1;
659 for (i = 0; i < fold2->n; ++i) {
660 for (j = 0; j < fold1->n; ++j) {
664 d = isl_qpolynomial_sub(
665 isl_qpolynomial_copy(fold1->qp[j]),
666 isl_qpolynomial_copy(fold2->qp[i]));
667 sgn = isl_qpolynomial_sign(set, d);
668 isl_qpolynomial_free(d);
679 /* Check whether "pwf1" dominated "pwf2", i.e., the domain of "pwf1" contains
680 * that of "pwf2" and on each cell, the corresponding fold from pwf1 dominates
683 int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
684 __isl_keep isl_pw_qpolynomial_fold *pwf2)
687 isl_set *dom1, *dom2;
698 dom1 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf1));
699 dom2 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf2));
700 is_subset = isl_set_is_subset(dom2, dom1);
704 if (is_subset < 0 || !is_subset)
707 for (i = 0; i < pwf2->n; ++i) {
708 for (j = 0; j < pwf1->n; ++j) {
713 common = isl_set_intersect(isl_set_copy(pwf1->p[j].set),
714 isl_set_copy(pwf2->p[i].set));
715 is_empty = isl_set_is_empty(common);
716 if (is_empty < 0 || is_empty) {
717 isl_set_free(common);
722 covers = qpolynomial_fold_covers_on_domain(common,
723 pwf1->p[j].fold, pwf2->p[i].fold);
724 isl_set_free(common);
725 if (covers < 0 || !covers)
733 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_morph(
734 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_morph *morph)
742 ctx = fold->dim->ctx;
743 isl_assert(ctx, isl_dim_equal(fold->dim, morph->dom->dim), goto error);
745 fold = isl_qpolynomial_fold_cow(fold);
749 isl_dim_free(fold->dim);
750 fold->dim = isl_dim_copy(morph->ran->dim);
754 for (i = 0; i < fold->n; ++i) {
755 fold->qp[i] = isl_qpolynomial_morph(fold->qp[i],
756 isl_morph_copy(morph));
761 isl_morph_free(morph);
765 isl_qpolynomial_fold_free(fold);
766 isl_morph_free(morph);
770 enum isl_fold isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold *fold)
773 return isl_fold_list;
777 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_lift(
778 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_dim *dim)
786 if (isl_dim_equal(fold->dim, dim)) {
791 fold = isl_qpolynomial_fold_cow(fold);
795 isl_dim_free(fold->dim);
796 fold->dim = isl_dim_copy(dim);
800 for (i = 0; i < fold->n; ++i) {
801 fold->qp[i] = isl_qpolynomial_lift(fold->qp[i],
811 isl_qpolynomial_fold_free(fold);
816 int isl_qpolynomial_fold_foreach_qpolynomial(
817 __isl_keep isl_qpolynomial_fold *fold,
818 int (*fn)(__isl_take isl_qpolynomial *qp, void *user), void *user)
825 for (i = 0; i < fold->n; ++i)
826 if (fn(isl_qpolynomial_copy(fold->qp[i]), user) < 0)
832 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_move_dims(
833 __isl_take isl_qpolynomial_fold *fold,
834 enum isl_dim_type dst_type, unsigned dst_pos,
835 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
842 fold = isl_qpolynomial_fold_cow(fold);
846 fold->dim = isl_dim_move(fold->dim, dst_type, dst_pos,
847 src_type, src_pos, n);
851 for (i = 0; i < fold->n; ++i) {
852 fold->qp[i] = isl_qpolynomial_move_dims(fold->qp[i],
853 dst_type, dst_pos, src_type, src_pos, n);
860 isl_qpolynomial_fold_free(fold);