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_polynomial_private.h>
12 #include <isl_point_private.h>
14 #include <isl_map_private.h>
18 static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
19 enum isl_fold type, __isl_take isl_dim *dim, int n)
21 isl_qpolynomial_fold *fold;
26 isl_assert(dim->ctx, n >= 0, goto error);
27 fold = isl_alloc(dim->ctx, struct isl_qpolynomial_fold,
28 sizeof(struct isl_qpolynomial_fold) +
29 (n - 1) * sizeof(struct isl_qpolynomial *));
45 int isl_qpolynomial_fold_involves_dims(__isl_keep isl_qpolynomial_fold *fold,
46 enum isl_dim_type type, unsigned first, unsigned n)
52 if (fold->n == 0 || n == 0)
55 for (i = 0; i < fold->n; ++i) {
56 int involves = isl_qpolynomial_involves_dims(fold->qp[i],
58 if (involves < 0 || involves)
64 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_drop_dims(
65 __isl_take isl_qpolynomial_fold *fold,
66 enum isl_dim_type type, unsigned first, unsigned n)
75 fold = isl_qpolynomial_fold_cow(fold);
78 fold->dim = isl_dim_drop(fold->dim, type, first, n);
82 for (i = 0; i < fold->n; ++i) {
83 fold->qp[i] = isl_qpolynomial_drop_dims(fold->qp[i],
91 isl_qpolynomial_fold_free(fold);
95 static int isl_qpolynomial_cst_sign(__isl_keep isl_qpolynomial *qp)
97 struct isl_upoly_cst *cst;
99 cst = isl_upoly_as_cst(qp->upoly);
103 return isl_int_sgn(cst->n) < 0 ? -1 : 1;
106 static int isl_qpolynomial_aff_sign(__isl_keep isl_set *set,
107 __isl_keep isl_qpolynomial *qp)
109 enum isl_lp_result res;
114 aff = isl_qpolynomial_extract_affine(qp);
120 res = isl_set_solve_lp(set, 0, aff->el + 1, aff->el[0],
122 if (res == isl_lp_error)
124 if (res == isl_lp_empty ||
125 (res == isl_lp_ok && !isl_int_is_neg(opt))) {
130 res = isl_set_solve_lp(set, 1, aff->el + 1, aff->el[0],
132 if (res == isl_lp_ok && !isl_int_is_pos(opt))
141 /* Determine, if possible, the sign of the quasipolynomial "qp" on
144 * If qp is a constant, then the problem is trivial.
145 * If qp is linear, then we check if the minimum of the corresponding
146 * affine constraint is non-negative or if the maximum is non-positive.
148 * Otherwise, we check if the outermost variable "v" has a lower bound "l"
149 * in "set". If so, we write qp(v,v') as
151 * q(v,v') * (v - l) + r(v')
153 * if q(v,v') and r(v') have the same known sign, then the original
154 * quasipolynomial has the same sign as well.
161 static int isl_qpolynomial_sign(__isl_keep isl_set *set,
162 __isl_keep isl_qpolynomial *qp)
167 struct isl_upoly_rec *rec;
170 enum isl_lp_result res;
173 is = isl_qpolynomial_is_cst(qp, NULL, NULL);
177 return isl_qpolynomial_cst_sign(qp);
179 is = isl_qpolynomial_is_affine(qp);
183 return isl_qpolynomial_aff_sign(set, qp);
185 if (qp->div->n_row > 0)
188 rec = isl_upoly_as_rec(qp->upoly);
192 d = isl_dim_total(qp->dim);
193 v = isl_vec_alloc(set->ctx, 2 + d);
197 isl_seq_clr(v->el + 1, 1 + d);
198 isl_int_set_si(v->el[0], 1);
199 isl_int_set_si(v->el[2 + qp->upoly->var], 1);
203 res = isl_set_solve_lp(set, 0, v->el + 1, v->el[0], &l, NULL, NULL);
204 if (res == isl_lp_ok) {
205 isl_qpolynomial *min;
206 isl_qpolynomial *base;
207 isl_qpolynomial *r, *q;
210 min = isl_qpolynomial_cst(isl_dim_copy(qp->dim), l);
211 base = isl_qpolynomial_pow(isl_dim_copy(qp->dim),
214 r = isl_qpolynomial_alloc(isl_dim_copy(qp->dim), 0,
215 isl_upoly_copy(rec->p[rec->n - 1]));
216 q = isl_qpolynomial_copy(r);
218 for (i = rec->n - 2; i >= 0; --i) {
219 r = isl_qpolynomial_mul(r, isl_qpolynomial_copy(min));
220 t = isl_qpolynomial_alloc(isl_dim_copy(qp->dim), 0,
221 isl_upoly_copy(rec->p[i]));
222 r = isl_qpolynomial_add(r, t);
225 q = isl_qpolynomial_mul(q, isl_qpolynomial_copy(base));
226 q = isl_qpolynomial_add(q, isl_qpolynomial_copy(r));
229 if (isl_qpolynomial_is_zero(q))
230 sgn = isl_qpolynomial_sign(set, r);
231 else if (isl_qpolynomial_is_zero(r))
232 sgn = isl_qpolynomial_sign(set, q);
235 sgn_r = isl_qpolynomial_sign(set, r);
236 sgn_q = isl_qpolynomial_sign(set, q);
241 isl_qpolynomial_free(min);
242 isl_qpolynomial_free(base);
243 isl_qpolynomial_free(q);
244 isl_qpolynomial_free(r);
254 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold_on_domain(
255 __isl_keep isl_set *set,
256 __isl_take isl_qpolynomial_fold *fold1,
257 __isl_take isl_qpolynomial_fold *fold2)
261 struct isl_qpolynomial_fold *res = NULL;
264 if (!fold1 || !fold2)
267 isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
268 isl_assert(fold1->dim->ctx, isl_dim_equal(fold1->dim, fold2->dim),
271 better = fold1->type == isl_fold_max ? -1 : 1;
273 if (isl_qpolynomial_fold_is_empty(fold1)) {
274 isl_qpolynomial_fold_free(fold1);
278 if (isl_qpolynomial_fold_is_empty(fold2)) {
279 isl_qpolynomial_fold_free(fold2);
283 res = qpolynomial_fold_alloc(fold1->type, isl_dim_copy(fold1->dim),
284 fold1->n + fold2->n);
288 for (i = 0; i < fold1->n; ++i) {
289 res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
290 if (!res->qp[res->n])
296 for (i = 0; i < fold2->n; ++i) {
297 for (j = n1 - 1; j >= 0; --j) {
300 d = isl_qpolynomial_sub(
301 isl_qpolynomial_copy(res->qp[j]),
302 isl_qpolynomial_copy(fold2->qp[i]));
303 sgn = isl_qpolynomial_sign(set, d);
304 isl_qpolynomial_free(d);
309 isl_qpolynomial_free(res->qp[j]);
311 res->qp[j] = res->qp[n1 - 1];
313 if (n1 != res->n - 1)
314 res->qp[n1] = res->qp[res->n - 1];
319 res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
320 if (!res->qp[res->n])
325 isl_qpolynomial_fold_free(fold1);
326 isl_qpolynomial_fold_free(fold2);
330 isl_qpolynomial_fold_free(res);
331 isl_qpolynomial_fold_free(fold1);
332 isl_qpolynomial_fold_free(fold2);
337 #define PW isl_pw_qpolynomial_fold
339 #define EL isl_qpolynomial_fold
341 #define IS_ZERO is_empty
345 #define ADD(d,e1,e2) isl_qpolynomial_fold_fold_on_domain(d,e1,e2)
347 #include <isl_pw_templ.c>
349 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
350 __isl_take isl_dim *dim)
352 return qpolynomial_fold_alloc(type, dim, 0);
355 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
356 enum isl_fold type, __isl_take isl_qpolynomial *qp)
358 isl_qpolynomial_fold *fold;
363 fold = qpolynomial_fold_alloc(type, isl_dim_copy(qp->dim), 1);
372 isl_qpolynomial_fold_free(fold);
373 isl_qpolynomial_free(qp);
377 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
378 __isl_keep isl_qpolynomial_fold *fold)
387 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_dup(
388 __isl_keep isl_qpolynomial_fold *fold)
391 isl_qpolynomial_fold *dup;
395 dup = qpolynomial_fold_alloc(fold->type,
396 isl_dim_copy(fold->dim), fold->n);
400 for (i = 0; i < fold->n; ++i) {
401 dup->qp[i] = isl_qpolynomial_copy(fold->qp[i]);
408 isl_qpolynomial_fold_free(dup);
412 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_cow(
413 __isl_take isl_qpolynomial_fold *fold)
421 return isl_qpolynomial_fold_dup(fold);
424 void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold)
433 for (i = 0; i < fold->n; ++i)
434 isl_qpolynomial_free(fold->qp[i]);
435 isl_dim_free(fold->dim);
439 int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
447 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
448 __isl_take isl_qpolynomial_fold *fold1,
449 __isl_take isl_qpolynomial_fold *fold2)
452 struct isl_qpolynomial_fold *res = NULL;
454 if (!fold1 || !fold2)
457 isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
458 isl_assert(fold1->dim->ctx, isl_dim_equal(fold1->dim, fold2->dim),
461 if (isl_qpolynomial_fold_is_empty(fold1)) {
462 isl_qpolynomial_fold_free(fold1);
466 if (isl_qpolynomial_fold_is_empty(fold2)) {
467 isl_qpolynomial_fold_free(fold2);
471 res = qpolynomial_fold_alloc(fold1->type, isl_dim_copy(fold1->dim),
472 fold1->n + fold2->n);
476 for (i = 0; i < fold1->n; ++i) {
477 res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
478 if (!res->qp[res->n])
483 for (i = 0; i < fold2->n; ++i) {
484 res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
485 if (!res->qp[res->n])
490 isl_qpolynomial_fold_free(fold1);
491 isl_qpolynomial_fold_free(fold2);
495 isl_qpolynomial_fold_free(res);
496 isl_qpolynomial_fold_free(fold1);
497 isl_qpolynomial_fold_free(fold2);
501 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
502 enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp)
505 isl_pw_qpolynomial_fold *pwf;
510 pwf = isl_pw_qpolynomial_fold_alloc_(isl_dim_copy(pwqp->dim), pwqp->n);
512 for (i = 0; i < pwqp->n; ++i)
513 pwf = isl_pw_qpolynomial_fold_add_piece(pwf,
514 isl_set_copy(pwqp->p[i].set),
515 isl_qpolynomial_fold_alloc(type,
516 isl_qpolynomial_copy(pwqp->p[i].qp)));
518 isl_pw_qpolynomial_free(pwqp);
523 int isl_qpolynomial_fold_is_equal(__isl_keep isl_qpolynomial_fold *fold1,
524 __isl_keep isl_qpolynomial_fold *fold2)
528 if (!fold1 || !fold2)
531 if (fold1->n != fold2->n)
534 /* We probably want to sort the qps first... */
535 for (i = 0; i < fold1->n; ++i) {
536 int eq = isl_qpolynomial_is_equal(fold1->qp[i], fold2->qp[i]);
544 __isl_give isl_qpolynomial *isl_qpolynomial_fold_eval(
545 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_point *pnt)
551 isl_assert(pnt->dim->ctx, isl_dim_equal(pnt->dim, fold->dim), goto error);
552 isl_assert(pnt->dim->ctx,
553 fold->type == isl_fold_max || fold->type == isl_fold_min,
557 qp = isl_qpolynomial_zero(isl_dim_copy(fold->dim));
560 qp = isl_qpolynomial_eval(isl_qpolynomial_copy(fold->qp[0]),
561 isl_point_copy(pnt));
562 for (i = 1; i < fold->n; ++i) {
563 isl_qpolynomial *qp_i;
564 qp_i = isl_qpolynomial_eval(
565 isl_qpolynomial_copy(fold->qp[i]),
566 isl_point_copy(pnt));
567 if (fold->type == isl_fold_max)
568 qp = isl_qpolynomial_max_cst(qp, qp_i);
570 qp = isl_qpolynomial_min_cst(qp, qp_i);
573 isl_qpolynomial_fold_free(fold);
578 isl_qpolynomial_fold_free(fold);
583 size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold *pwf)
588 for (i = 0; i < pwf->n; ++i)
589 n += pwf->p[i].fold->n;
594 __isl_give isl_qpolynomial *isl_qpolynomial_fold_opt_on_domain(
595 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *set, int max)
598 isl_qpolynomial *opt;
604 isl_dim *dim = isl_dim_copy(fold->dim);
606 isl_qpolynomial_fold_free(fold);
607 return isl_qpolynomial_zero(dim);
610 opt = isl_qpolynomial_opt_on_domain(isl_qpolynomial_copy(fold->qp[0]),
611 isl_set_copy(set), max);
612 for (i = 1; i < fold->n; ++i) {
613 isl_qpolynomial *opt_i;
614 opt_i = isl_qpolynomial_opt_on_domain(
615 isl_qpolynomial_copy(fold->qp[i]),
616 isl_set_copy(set), max);
618 opt = isl_qpolynomial_max_cst(opt, opt_i);
620 opt = isl_qpolynomial_min_cst(opt, opt_i);
624 isl_qpolynomial_fold_free(fold);
629 isl_qpolynomial_fold_free(fold);
633 /* Check whether for each quasi-polynomial in "fold2" there is
634 * a quasi-polynomial in "fold1" that dominates it on "set".
636 static int qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
637 __isl_keep isl_qpolynomial_fold *fold1,
638 __isl_keep isl_qpolynomial_fold *fold2)
643 if (!set || !fold1 || !fold2)
646 covers = fold1->type == isl_fold_max ? 1 : -1;
648 for (i = 0; i < fold2->n; ++i) {
649 for (j = 0; j < fold1->n; ++j) {
653 d = isl_qpolynomial_sub(
654 isl_qpolynomial_copy(fold1->qp[j]),
655 isl_qpolynomial_copy(fold2->qp[i]));
656 sgn = isl_qpolynomial_sign(set, d);
657 isl_qpolynomial_free(d);
668 /* Check whether "pwf1" dominated "pwf2", i.e., the domain of "pwf1" contains
669 * that of "pwf2" and on each cell, the corresponding fold from pwf1 dominates
672 int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
673 __isl_keep isl_pw_qpolynomial_fold *pwf2)
676 isl_set *dom1, *dom2;
687 dom1 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf1));
688 dom2 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf2));
689 is_subset = isl_set_is_subset(dom2, dom1);
693 if (is_subset < 0 || !is_subset)
696 for (i = 0; i < pwf2->n; ++i) {
697 for (j = 0; j < pwf1->n; ++j) {
702 common = isl_set_intersect(isl_set_copy(pwf1->p[j].set),
703 isl_set_copy(pwf2->p[i].set));
704 is_empty = isl_set_is_empty(common);
705 if (is_empty < 0 || is_empty) {
706 isl_set_free(common);
711 covers = qpolynomial_fold_covers_on_domain(common,
712 pwf1->p[j].fold, pwf2->p[i].fold);
713 isl_set_free(common);
714 if (covers < 0 || !covers)