drop deprecated isl_map_n_in
[isl.git] / isl_polynomial.c
blobe9f196de8a93761e2b0ea384c0b1940facdccefb
1 /*
2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8 * 91893 Orsay, France
9 */
11 #include <stdlib.h>
12 #include <isl_ctx_private.h>
13 #include <isl_map_private.h>
14 #include <isl_factorization.h>
15 #include <isl_lp_private.h>
16 #include <isl_seq.h>
17 #include <isl_union_map_private.h>
18 #include <isl_constraint_private.h>
19 #include <isl_polynomial_private.h>
20 #include <isl_point_private.h>
21 #include <isl_space_private.h>
22 #include <isl_mat_private.h>
23 #include <isl_vec_private.h>
24 #include <isl_range.h>
25 #include <isl_local.h>
26 #include <isl_local_space_private.h>
27 #include <isl_aff_private.h>
28 #include <isl_val_private.h>
29 #include <isl_config.h>
31 #undef BASE
32 #define BASE pw_qpolynomial
34 #include <isl_list_templ.c>
36 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
38 switch (type) {
39 case isl_dim_param: return 0;
40 case isl_dim_in: return dim->nparam;
41 case isl_dim_out: return dim->nparam + dim->n_in;
42 default: return 0;
46 isl_bool isl_poly_is_cst(__isl_keep isl_poly *poly)
48 if (!poly)
49 return isl_bool_error;
51 return poly->var < 0;
54 __isl_keep isl_poly_cst *isl_poly_as_cst(__isl_keep isl_poly *poly)
56 if (!poly)
57 return NULL;
59 isl_assert(poly->ctx, poly->var < 0, return NULL);
61 return (isl_poly_cst *) poly;
64 __isl_keep isl_poly_rec *isl_poly_as_rec(__isl_keep isl_poly *poly)
66 if (!poly)
67 return NULL;
69 isl_assert(poly->ctx, poly->var >= 0, return NULL);
71 return (isl_poly_rec *) poly;
74 /* Compare two polynomials.
76 * Return -1 if "poly1" is "smaller" than "poly2", 1 if "poly1" is "greater"
77 * than "poly2" and 0 if they are equal.
79 static int isl_poly_plain_cmp(__isl_keep isl_poly *poly1,
80 __isl_keep isl_poly *poly2)
82 int i;
83 isl_bool is_cst1;
84 isl_poly_rec *rec1, *rec2;
86 if (poly1 == poly2)
87 return 0;
88 is_cst1 = isl_poly_is_cst(poly1);
89 if (is_cst1 < 0)
90 return -1;
91 if (!poly2)
92 return 1;
93 if (poly1->var != poly2->var)
94 return poly1->var - poly2->var;
96 if (is_cst1) {
97 isl_poly_cst *cst1, *cst2;
98 int cmp;
100 cst1 = isl_poly_as_cst(poly1);
101 cst2 = isl_poly_as_cst(poly2);
102 if (!cst1 || !cst2)
103 return 0;
104 cmp = isl_int_cmp(cst1->n, cst2->n);
105 if (cmp != 0)
106 return cmp;
107 return isl_int_cmp(cst1->d, cst2->d);
110 rec1 = isl_poly_as_rec(poly1);
111 rec2 = isl_poly_as_rec(poly2);
112 if (!rec1 || !rec2)
113 return 0;
115 if (rec1->n != rec2->n)
116 return rec1->n - rec2->n;
118 for (i = 0; i < rec1->n; ++i) {
119 int cmp = isl_poly_plain_cmp(rec1->p[i], rec2->p[i]);
120 if (cmp != 0)
121 return cmp;
124 return 0;
127 isl_bool isl_poly_is_equal(__isl_keep isl_poly *poly1,
128 __isl_keep isl_poly *poly2)
130 int i;
131 isl_bool is_cst1;
132 isl_poly_rec *rec1, *rec2;
134 is_cst1 = isl_poly_is_cst(poly1);
135 if (is_cst1 < 0 || !poly2)
136 return isl_bool_error;
137 if (poly1 == poly2)
138 return isl_bool_true;
139 if (poly1->var != poly2->var)
140 return isl_bool_false;
141 if (is_cst1) {
142 isl_poly_cst *cst1, *cst2;
143 cst1 = isl_poly_as_cst(poly1);
144 cst2 = isl_poly_as_cst(poly2);
145 if (!cst1 || !cst2)
146 return isl_bool_error;
147 return isl_int_eq(cst1->n, cst2->n) &&
148 isl_int_eq(cst1->d, cst2->d);
151 rec1 = isl_poly_as_rec(poly1);
152 rec2 = isl_poly_as_rec(poly2);
153 if (!rec1 || !rec2)
154 return isl_bool_error;
156 if (rec1->n != rec2->n)
157 return isl_bool_false;
159 for (i = 0; i < rec1->n; ++i) {
160 isl_bool eq = isl_poly_is_equal(rec1->p[i], rec2->p[i]);
161 if (eq < 0 || !eq)
162 return eq;
165 return isl_bool_true;
168 isl_bool isl_poly_is_zero(__isl_keep isl_poly *poly)
170 isl_bool is_cst;
171 isl_poly_cst *cst;
173 is_cst = isl_poly_is_cst(poly);
174 if (is_cst < 0 || !is_cst)
175 return is_cst;
177 cst = isl_poly_as_cst(poly);
178 if (!cst)
179 return isl_bool_error;
181 return isl_int_is_zero(cst->n) && isl_int_is_pos(cst->d);
184 int isl_poly_sgn(__isl_keep isl_poly *poly)
186 isl_bool is_cst;
187 isl_poly_cst *cst;
189 is_cst = isl_poly_is_cst(poly);
190 if (is_cst < 0 || !is_cst)
191 return 0;
193 cst = isl_poly_as_cst(poly);
194 if (!cst)
195 return 0;
197 return isl_int_sgn(cst->n);
200 isl_bool isl_poly_is_nan(__isl_keep isl_poly *poly)
202 isl_bool is_cst;
203 isl_poly_cst *cst;
205 is_cst = isl_poly_is_cst(poly);
206 if (is_cst < 0 || !is_cst)
207 return is_cst;
209 cst = isl_poly_as_cst(poly);
210 if (!cst)
211 return isl_bool_error;
213 return isl_int_is_zero(cst->n) && isl_int_is_zero(cst->d);
216 isl_bool isl_poly_is_infty(__isl_keep isl_poly *poly)
218 isl_bool is_cst;
219 isl_poly_cst *cst;
221 is_cst = isl_poly_is_cst(poly);
222 if (is_cst < 0 || !is_cst)
223 return is_cst;
225 cst = isl_poly_as_cst(poly);
226 if (!cst)
227 return isl_bool_error;
229 return isl_int_is_pos(cst->n) && isl_int_is_zero(cst->d);
232 isl_bool isl_poly_is_neginfty(__isl_keep isl_poly *poly)
234 isl_bool is_cst;
235 isl_poly_cst *cst;
237 is_cst = isl_poly_is_cst(poly);
238 if (is_cst < 0 || !is_cst)
239 return is_cst;
241 cst = isl_poly_as_cst(poly);
242 if (!cst)
243 return isl_bool_error;
245 return isl_int_is_neg(cst->n) && isl_int_is_zero(cst->d);
248 isl_bool isl_poly_is_one(__isl_keep isl_poly *poly)
250 isl_bool is_cst;
251 isl_poly_cst *cst;
253 is_cst = isl_poly_is_cst(poly);
254 if (is_cst < 0 || !is_cst)
255 return is_cst;
257 cst = isl_poly_as_cst(poly);
258 if (!cst)
259 return isl_bool_error;
261 return isl_int_eq(cst->n, cst->d) && isl_int_is_pos(cst->d);
264 isl_bool isl_poly_is_negone(__isl_keep isl_poly *poly)
266 isl_bool is_cst;
267 isl_poly_cst *cst;
269 is_cst = isl_poly_is_cst(poly);
270 if (is_cst < 0 || !is_cst)
271 return is_cst;
273 cst = isl_poly_as_cst(poly);
274 if (!cst)
275 return isl_bool_error;
277 return isl_int_is_negone(cst->n) && isl_int_is_one(cst->d);
280 __isl_give isl_poly_cst *isl_poly_cst_alloc(isl_ctx *ctx)
282 isl_poly_cst *cst;
284 cst = isl_alloc_type(ctx, struct isl_poly_cst);
285 if (!cst)
286 return NULL;
288 cst->poly.ref = 1;
289 cst->poly.ctx = ctx;
290 isl_ctx_ref(ctx);
291 cst->poly.var = -1;
293 isl_int_init(cst->n);
294 isl_int_init(cst->d);
296 return cst;
299 __isl_give isl_poly *isl_poly_zero(isl_ctx *ctx)
301 isl_poly_cst *cst;
303 cst = isl_poly_cst_alloc(ctx);
304 if (!cst)
305 return NULL;
307 isl_int_set_si(cst->n, 0);
308 isl_int_set_si(cst->d, 1);
310 return &cst->poly;
313 __isl_give isl_poly *isl_poly_one(isl_ctx *ctx)
315 isl_poly_cst *cst;
317 cst = isl_poly_cst_alloc(ctx);
318 if (!cst)
319 return NULL;
321 isl_int_set_si(cst->n, 1);
322 isl_int_set_si(cst->d, 1);
324 return &cst->poly;
327 __isl_give isl_poly *isl_poly_infty(isl_ctx *ctx)
329 isl_poly_cst *cst;
331 cst = isl_poly_cst_alloc(ctx);
332 if (!cst)
333 return NULL;
335 isl_int_set_si(cst->n, 1);
336 isl_int_set_si(cst->d, 0);
338 return &cst->poly;
341 __isl_give isl_poly *isl_poly_neginfty(isl_ctx *ctx)
343 isl_poly_cst *cst;
345 cst = isl_poly_cst_alloc(ctx);
346 if (!cst)
347 return NULL;
349 isl_int_set_si(cst->n, -1);
350 isl_int_set_si(cst->d, 0);
352 return &cst->poly;
355 __isl_give isl_poly *isl_poly_nan(isl_ctx *ctx)
357 isl_poly_cst *cst;
359 cst = isl_poly_cst_alloc(ctx);
360 if (!cst)
361 return NULL;
363 isl_int_set_si(cst->n, 0);
364 isl_int_set_si(cst->d, 0);
366 return &cst->poly;
369 __isl_give isl_poly *isl_poly_rat_cst(isl_ctx *ctx, isl_int n, isl_int d)
371 isl_poly_cst *cst;
373 cst = isl_poly_cst_alloc(ctx);
374 if (!cst)
375 return NULL;
377 isl_int_set(cst->n, n);
378 isl_int_set(cst->d, d);
380 return &cst->poly;
383 __isl_give isl_poly_rec *isl_poly_alloc_rec(isl_ctx *ctx, int var, int size)
385 isl_poly_rec *rec;
387 isl_assert(ctx, var >= 0, return NULL);
388 isl_assert(ctx, size >= 0, return NULL);
389 rec = isl_calloc(ctx, struct isl_poly_rec,
390 sizeof(struct isl_poly_rec) +
391 size * sizeof(struct isl_poly *));
392 if (!rec)
393 return NULL;
395 rec->poly.ref = 1;
396 rec->poly.ctx = ctx;
397 isl_ctx_ref(ctx);
398 rec->poly.var = var;
400 rec->n = 0;
401 rec->size = size;
403 return rec;
406 __isl_give isl_qpolynomial *isl_qpolynomial_reset_domain_space(
407 __isl_take isl_qpolynomial *qp, __isl_take isl_space *dim)
409 qp = isl_qpolynomial_cow(qp);
410 if (!qp || !dim)
411 goto error;
413 isl_space_free(qp->dim);
414 qp->dim = dim;
416 return qp;
417 error:
418 isl_qpolynomial_free(qp);
419 isl_space_free(dim);
420 return NULL;
423 /* Reset the space of "qp". This function is called from isl_pw_templ.c
424 * and doesn't know if the space of an element object is represented
425 * directly or through its domain. It therefore passes along both.
427 __isl_give isl_qpolynomial *isl_qpolynomial_reset_space_and_domain(
428 __isl_take isl_qpolynomial *qp, __isl_take isl_space *space,
429 __isl_take isl_space *domain)
431 isl_space_free(space);
432 return isl_qpolynomial_reset_domain_space(qp, domain);
435 isl_ctx *isl_qpolynomial_get_ctx(__isl_keep isl_qpolynomial *qp)
437 return qp ? qp->dim->ctx : NULL;
440 /* Return the domain space of "qp".
442 static __isl_keep isl_space *isl_qpolynomial_peek_domain_space(
443 __isl_keep isl_qpolynomial *qp)
445 return qp ? qp->dim : NULL;
448 /* Return a copy of the domain space of "qp".
450 __isl_give isl_space *isl_qpolynomial_get_domain_space(
451 __isl_keep isl_qpolynomial *qp)
453 return isl_space_copy(isl_qpolynomial_peek_domain_space(qp));
456 /* Return a copy of the local space on which "qp" is defined.
458 static __isl_give isl_local_space *isl_qpolynomial_get_domain_local_space(
459 __isl_keep isl_qpolynomial *qp)
461 isl_space *space;
463 if (!qp)
464 return NULL;
466 space = isl_qpolynomial_get_domain_space(qp);
467 return isl_local_space_alloc_div(space, isl_mat_copy(qp->div));
470 __isl_give isl_space *isl_qpolynomial_get_space(__isl_keep isl_qpolynomial *qp)
472 isl_space *space;
473 if (!qp)
474 return NULL;
475 space = isl_space_copy(qp->dim);
476 space = isl_space_from_domain(space);
477 space = isl_space_add_dims(space, isl_dim_out, 1);
478 return space;
481 /* Return the number of variables of the given type in the domain of "qp".
483 unsigned isl_qpolynomial_domain_dim(__isl_keep isl_qpolynomial *qp,
484 enum isl_dim_type type)
486 isl_space *space;
488 space = isl_qpolynomial_peek_domain_space(qp);
490 if (!space)
491 return 0;
492 if (type == isl_dim_div)
493 return qp->div->n_row;
494 if (type == isl_dim_all)
495 return isl_space_dim(space, isl_dim_all) +
496 isl_qpolynomial_domain_dim(qp, isl_dim_div);
497 return isl_space_dim(space, type);
500 /* Given the type of a dimension of an isl_qpolynomial,
501 * return the type of the corresponding dimension in its domain.
502 * This function is only called for "type" equal to isl_dim_in or
503 * isl_dim_param.
505 static enum isl_dim_type domain_type(enum isl_dim_type type)
507 return type == isl_dim_in ? isl_dim_set : type;
510 /* Externally, an isl_qpolynomial has a map space, but internally, the
511 * ls field corresponds to the domain of that space.
513 unsigned isl_qpolynomial_dim(__isl_keep isl_qpolynomial *qp,
514 enum isl_dim_type type)
516 if (!qp)
517 return 0;
518 if (type == isl_dim_out)
519 return 1;
520 type = domain_type(type);
521 return isl_qpolynomial_domain_dim(qp, type);
524 /* Return the offset of the first variable of type "type" within
525 * the variables of the domain of "qp".
527 static int isl_qpolynomial_domain_var_offset(__isl_keep isl_qpolynomial *qp,
528 enum isl_dim_type type)
530 isl_space *space;
532 space = isl_qpolynomial_peek_domain_space(qp);
533 if (!space)
534 return -1;
536 switch (type) {
537 case isl_dim_param:
538 case isl_dim_set: return isl_space_offset(space, type);
539 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
540 case isl_dim_cst:
541 default:
542 isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
543 "invalid dimension type", return -1);
547 /* Return the offset of the first coefficient of type "type" in
548 * the domain of "qp".
550 unsigned isl_qpolynomial_domain_offset(__isl_keep isl_qpolynomial *qp,
551 enum isl_dim_type type)
553 switch (type) {
554 case isl_dim_cst:
555 return 0;
556 case isl_dim_param:
557 case isl_dim_set:
558 case isl_dim_div:
559 return 1 + isl_qpolynomial_domain_var_offset(qp, type);
560 default:
561 return 0;
565 isl_bool isl_qpolynomial_is_zero(__isl_keep isl_qpolynomial *qp)
567 return qp ? isl_poly_is_zero(qp->poly) : isl_bool_error;
570 isl_bool isl_qpolynomial_is_one(__isl_keep isl_qpolynomial *qp)
572 return qp ? isl_poly_is_one(qp->poly) : isl_bool_error;
575 isl_bool isl_qpolynomial_is_nan(__isl_keep isl_qpolynomial *qp)
577 return qp ? isl_poly_is_nan(qp->poly) : isl_bool_error;
580 isl_bool isl_qpolynomial_is_infty(__isl_keep isl_qpolynomial *qp)
582 return qp ? isl_poly_is_infty(qp->poly) : isl_bool_error;
585 isl_bool isl_qpolynomial_is_neginfty(__isl_keep isl_qpolynomial *qp)
587 return qp ? isl_poly_is_neginfty(qp->poly) : isl_bool_error;
590 int isl_qpolynomial_sgn(__isl_keep isl_qpolynomial *qp)
592 return qp ? isl_poly_sgn(qp->poly) : 0;
595 static void poly_free_cst(__isl_take isl_poly_cst *cst)
597 isl_int_clear(cst->n);
598 isl_int_clear(cst->d);
601 static void poly_free_rec(__isl_take isl_poly_rec *rec)
603 int i;
605 for (i = 0; i < rec->n; ++i)
606 isl_poly_free(rec->p[i]);
609 __isl_give isl_poly *isl_poly_copy(__isl_keep isl_poly *poly)
611 if (!poly)
612 return NULL;
614 poly->ref++;
615 return poly;
618 __isl_give isl_poly *isl_poly_dup_cst(__isl_keep isl_poly *poly)
620 isl_poly_cst *cst;
621 isl_poly_cst *dup;
623 cst = isl_poly_as_cst(poly);
624 if (!cst)
625 return NULL;
627 dup = isl_poly_as_cst(isl_poly_zero(poly->ctx));
628 if (!dup)
629 return NULL;
630 isl_int_set(dup->n, cst->n);
631 isl_int_set(dup->d, cst->d);
633 return &dup->poly;
636 __isl_give isl_poly *isl_poly_dup_rec(__isl_keep isl_poly *poly)
638 int i;
639 isl_poly_rec *rec;
640 isl_poly_rec *dup;
642 rec = isl_poly_as_rec(poly);
643 if (!rec)
644 return NULL;
646 dup = isl_poly_alloc_rec(poly->ctx, poly->var, rec->n);
647 if (!dup)
648 return NULL;
650 for (i = 0; i < rec->n; ++i) {
651 dup->p[i] = isl_poly_copy(rec->p[i]);
652 if (!dup->p[i])
653 goto error;
654 dup->n++;
657 return &dup->poly;
658 error:
659 isl_poly_free(&dup->poly);
660 return NULL;
663 __isl_give isl_poly *isl_poly_dup(__isl_keep isl_poly *poly)
665 isl_bool is_cst;
667 is_cst = isl_poly_is_cst(poly);
668 if (is_cst < 0)
669 return NULL;
670 if (is_cst)
671 return isl_poly_dup_cst(poly);
672 else
673 return isl_poly_dup_rec(poly);
676 __isl_give isl_poly *isl_poly_cow(__isl_take isl_poly *poly)
678 if (!poly)
679 return NULL;
681 if (poly->ref == 1)
682 return poly;
683 poly->ref--;
684 return isl_poly_dup(poly);
687 __isl_null isl_poly *isl_poly_free(__isl_take isl_poly *poly)
689 if (!poly)
690 return NULL;
692 if (--poly->ref > 0)
693 return NULL;
695 if (poly->var < 0)
696 poly_free_cst((isl_poly_cst *) poly);
697 else
698 poly_free_rec((isl_poly_rec *) poly);
700 isl_ctx_deref(poly->ctx);
701 free(poly);
702 return NULL;
705 static void isl_poly_cst_reduce(__isl_keep isl_poly_cst *cst)
707 isl_int gcd;
709 isl_int_init(gcd);
710 isl_int_gcd(gcd, cst->n, cst->d);
711 if (!isl_int_is_zero(gcd) && !isl_int_is_one(gcd)) {
712 isl_int_divexact(cst->n, cst->n, gcd);
713 isl_int_divexact(cst->d, cst->d, gcd);
715 isl_int_clear(gcd);
718 __isl_give isl_poly *isl_poly_sum_cst(__isl_take isl_poly *poly1,
719 __isl_take isl_poly *poly2)
721 isl_poly_cst *cst1;
722 isl_poly_cst *cst2;
724 poly1 = isl_poly_cow(poly1);
725 if (!poly1 || !poly2)
726 goto error;
728 cst1 = isl_poly_as_cst(poly1);
729 cst2 = isl_poly_as_cst(poly2);
731 if (isl_int_eq(cst1->d, cst2->d))
732 isl_int_add(cst1->n, cst1->n, cst2->n);
733 else {
734 isl_int_mul(cst1->n, cst1->n, cst2->d);
735 isl_int_addmul(cst1->n, cst2->n, cst1->d);
736 isl_int_mul(cst1->d, cst1->d, cst2->d);
739 isl_poly_cst_reduce(cst1);
741 isl_poly_free(poly2);
742 return poly1;
743 error:
744 isl_poly_free(poly1);
745 isl_poly_free(poly2);
746 return NULL;
749 static __isl_give isl_poly *replace_by_zero(__isl_take isl_poly *poly)
751 struct isl_ctx *ctx;
753 if (!poly)
754 return NULL;
755 ctx = poly->ctx;
756 isl_poly_free(poly);
757 return isl_poly_zero(ctx);
760 static __isl_give isl_poly *replace_by_constant_term(__isl_take isl_poly *poly)
762 isl_poly_rec *rec;
763 isl_poly *cst;
765 if (!poly)
766 return NULL;
768 rec = isl_poly_as_rec(poly);
769 if (!rec)
770 goto error;
771 cst = isl_poly_copy(rec->p[0]);
772 isl_poly_free(poly);
773 return cst;
774 error:
775 isl_poly_free(poly);
776 return NULL;
779 __isl_give isl_poly *isl_poly_sum(__isl_take isl_poly *poly1,
780 __isl_take isl_poly *poly2)
782 int i;
783 isl_bool is_zero, is_nan, is_cst;
784 isl_poly_rec *rec1, *rec2;
786 if (!poly1 || !poly2)
787 goto error;
789 is_nan = isl_poly_is_nan(poly1);
790 if (is_nan < 0)
791 goto error;
792 if (is_nan) {
793 isl_poly_free(poly2);
794 return poly1;
797 is_nan = isl_poly_is_nan(poly2);
798 if (is_nan < 0)
799 goto error;
800 if (is_nan) {
801 isl_poly_free(poly1);
802 return poly2;
805 is_zero = isl_poly_is_zero(poly1);
806 if (is_zero < 0)
807 goto error;
808 if (is_zero) {
809 isl_poly_free(poly1);
810 return poly2;
813 is_zero = isl_poly_is_zero(poly2);
814 if (is_zero < 0)
815 goto error;
816 if (is_zero) {
817 isl_poly_free(poly2);
818 return poly1;
821 if (poly1->var < poly2->var)
822 return isl_poly_sum(poly2, poly1);
824 if (poly2->var < poly1->var) {
825 isl_poly_rec *rec;
826 isl_bool is_infty;
828 is_infty = isl_poly_is_infty(poly2);
829 if (is_infty >= 0 && !is_infty)
830 is_infty = isl_poly_is_neginfty(poly2);
831 if (is_infty < 0)
832 goto error;
833 if (is_infty) {
834 isl_poly_free(poly1);
835 return poly2;
837 poly1 = isl_poly_cow(poly1);
838 rec = isl_poly_as_rec(poly1);
839 if (!rec)
840 goto error;
841 rec->p[0] = isl_poly_sum(rec->p[0], poly2);
842 if (rec->n == 1)
843 poly1 = replace_by_constant_term(poly1);
844 return poly1;
847 is_cst = isl_poly_is_cst(poly1);
848 if (is_cst < 0)
849 goto error;
850 if (is_cst)
851 return isl_poly_sum_cst(poly1, poly2);
853 rec1 = isl_poly_as_rec(poly1);
854 rec2 = isl_poly_as_rec(poly2);
855 if (!rec1 || !rec2)
856 goto error;
858 if (rec1->n < rec2->n)
859 return isl_poly_sum(poly2, poly1);
861 poly1 = isl_poly_cow(poly1);
862 rec1 = isl_poly_as_rec(poly1);
863 if (!rec1)
864 goto error;
866 for (i = rec2->n - 1; i >= 0; --i) {
867 isl_bool is_zero;
869 rec1->p[i] = isl_poly_sum(rec1->p[i],
870 isl_poly_copy(rec2->p[i]));
871 if (!rec1->p[i])
872 goto error;
873 if (i != rec1->n - 1)
874 continue;
875 is_zero = isl_poly_is_zero(rec1->p[i]);
876 if (is_zero < 0)
877 goto error;
878 if (is_zero) {
879 isl_poly_free(rec1->p[i]);
880 rec1->n--;
884 if (rec1->n == 0)
885 poly1 = replace_by_zero(poly1);
886 else if (rec1->n == 1)
887 poly1 = replace_by_constant_term(poly1);
889 isl_poly_free(poly2);
891 return poly1;
892 error:
893 isl_poly_free(poly1);
894 isl_poly_free(poly2);
895 return NULL;
898 __isl_give isl_poly *isl_poly_cst_add_isl_int(__isl_take isl_poly *poly,
899 isl_int v)
901 isl_poly_cst *cst;
903 poly = isl_poly_cow(poly);
904 if (!poly)
905 return NULL;
907 cst = isl_poly_as_cst(poly);
909 isl_int_addmul(cst->n, cst->d, v);
911 return poly;
914 __isl_give isl_poly *isl_poly_add_isl_int(__isl_take isl_poly *poly, isl_int v)
916 isl_bool is_cst;
917 isl_poly_rec *rec;
919 is_cst = isl_poly_is_cst(poly);
920 if (is_cst < 0)
921 return isl_poly_free(poly);
922 if (is_cst)
923 return isl_poly_cst_add_isl_int(poly, v);
925 poly = isl_poly_cow(poly);
926 rec = isl_poly_as_rec(poly);
927 if (!rec)
928 goto error;
930 rec->p[0] = isl_poly_add_isl_int(rec->p[0], v);
931 if (!rec->p[0])
932 goto error;
934 return poly;
935 error:
936 isl_poly_free(poly);
937 return NULL;
940 __isl_give isl_poly *isl_poly_cst_mul_isl_int(__isl_take isl_poly *poly,
941 isl_int v)
943 isl_bool is_zero;
944 isl_poly_cst *cst;
946 is_zero = isl_poly_is_zero(poly);
947 if (is_zero < 0)
948 return isl_poly_free(poly);
949 if (is_zero)
950 return poly;
952 poly = isl_poly_cow(poly);
953 if (!poly)
954 return NULL;
956 cst = isl_poly_as_cst(poly);
958 isl_int_mul(cst->n, cst->n, v);
960 return poly;
963 __isl_give isl_poly *isl_poly_mul_isl_int(__isl_take isl_poly *poly, isl_int v)
965 int i;
966 isl_bool is_cst;
967 isl_poly_rec *rec;
969 is_cst = isl_poly_is_cst(poly);
970 if (is_cst < 0)
971 return isl_poly_free(poly);
972 if (is_cst)
973 return isl_poly_cst_mul_isl_int(poly, v);
975 poly = isl_poly_cow(poly);
976 rec = isl_poly_as_rec(poly);
977 if (!rec)
978 goto error;
980 for (i = 0; i < rec->n; ++i) {
981 rec->p[i] = isl_poly_mul_isl_int(rec->p[i], v);
982 if (!rec->p[i])
983 goto error;
986 return poly;
987 error:
988 isl_poly_free(poly);
989 return NULL;
992 /* Multiply the constant polynomial "poly" by "v".
994 static __isl_give isl_poly *isl_poly_cst_scale_val(__isl_take isl_poly *poly,
995 __isl_keep isl_val *v)
997 isl_bool is_zero;
998 isl_poly_cst *cst;
1000 is_zero = isl_poly_is_zero(poly);
1001 if (is_zero < 0)
1002 return isl_poly_free(poly);
1003 if (is_zero)
1004 return poly;
1006 poly = isl_poly_cow(poly);
1007 if (!poly)
1008 return NULL;
1010 cst = isl_poly_as_cst(poly);
1012 isl_int_mul(cst->n, cst->n, v->n);
1013 isl_int_mul(cst->d, cst->d, v->d);
1014 isl_poly_cst_reduce(cst);
1016 return poly;
1019 /* Multiply the polynomial "poly" by "v".
1021 static __isl_give isl_poly *isl_poly_scale_val(__isl_take isl_poly *poly,
1022 __isl_keep isl_val *v)
1024 int i;
1025 isl_bool is_cst;
1026 isl_poly_rec *rec;
1028 is_cst = isl_poly_is_cst(poly);
1029 if (is_cst < 0)
1030 return isl_poly_free(poly);
1031 if (is_cst)
1032 return isl_poly_cst_scale_val(poly, v);
1034 poly = isl_poly_cow(poly);
1035 rec = isl_poly_as_rec(poly);
1036 if (!rec)
1037 goto error;
1039 for (i = 0; i < rec->n; ++i) {
1040 rec->p[i] = isl_poly_scale_val(rec->p[i], v);
1041 if (!rec->p[i])
1042 goto error;
1045 return poly;
1046 error:
1047 isl_poly_free(poly);
1048 return NULL;
1051 __isl_give isl_poly *isl_poly_mul_cst(__isl_take isl_poly *poly1,
1052 __isl_take isl_poly *poly2)
1054 isl_poly_cst *cst1;
1055 isl_poly_cst *cst2;
1057 poly1 = isl_poly_cow(poly1);
1058 if (!poly1 || !poly2)
1059 goto error;
1061 cst1 = isl_poly_as_cst(poly1);
1062 cst2 = isl_poly_as_cst(poly2);
1064 isl_int_mul(cst1->n, cst1->n, cst2->n);
1065 isl_int_mul(cst1->d, cst1->d, cst2->d);
1067 isl_poly_cst_reduce(cst1);
1069 isl_poly_free(poly2);
1070 return poly1;
1071 error:
1072 isl_poly_free(poly1);
1073 isl_poly_free(poly2);
1074 return NULL;
1077 __isl_give isl_poly *isl_poly_mul_rec(__isl_take isl_poly *poly1,
1078 __isl_take isl_poly *poly2)
1080 isl_poly_rec *rec1;
1081 isl_poly_rec *rec2;
1082 isl_poly_rec *res = NULL;
1083 int i, j;
1084 int size;
1086 rec1 = isl_poly_as_rec(poly1);
1087 rec2 = isl_poly_as_rec(poly2);
1088 if (!rec1 || !rec2)
1089 goto error;
1090 size = rec1->n + rec2->n - 1;
1091 res = isl_poly_alloc_rec(poly1->ctx, poly1->var, size);
1092 if (!res)
1093 goto error;
1095 for (i = 0; i < rec1->n; ++i) {
1096 res->p[i] = isl_poly_mul(isl_poly_copy(rec2->p[0]),
1097 isl_poly_copy(rec1->p[i]));
1098 if (!res->p[i])
1099 goto error;
1100 res->n++;
1102 for (; i < size; ++i) {
1103 res->p[i] = isl_poly_zero(poly1->ctx);
1104 if (!res->p[i])
1105 goto error;
1106 res->n++;
1108 for (i = 0; i < rec1->n; ++i) {
1109 for (j = 1; j < rec2->n; ++j) {
1110 isl_poly *poly;
1111 poly = isl_poly_mul(isl_poly_copy(rec2->p[j]),
1112 isl_poly_copy(rec1->p[i]));
1113 res->p[i + j] = isl_poly_sum(res->p[i + j], poly);
1114 if (!res->p[i + j])
1115 goto error;
1119 isl_poly_free(poly1);
1120 isl_poly_free(poly2);
1122 return &res->poly;
1123 error:
1124 isl_poly_free(poly1);
1125 isl_poly_free(poly2);
1126 isl_poly_free(&res->poly);
1127 return NULL;
1130 __isl_give isl_poly *isl_poly_mul(__isl_take isl_poly *poly1,
1131 __isl_take isl_poly *poly2)
1133 isl_bool is_zero, is_nan, is_one, is_cst;
1135 if (!poly1 || !poly2)
1136 goto error;
1138 is_nan = isl_poly_is_nan(poly1);
1139 if (is_nan < 0)
1140 goto error;
1141 if (is_nan) {
1142 isl_poly_free(poly2);
1143 return poly1;
1146 is_nan = isl_poly_is_nan(poly2);
1147 if (is_nan < 0)
1148 goto error;
1149 if (is_nan) {
1150 isl_poly_free(poly1);
1151 return poly2;
1154 is_zero = isl_poly_is_zero(poly1);
1155 if (is_zero < 0)
1156 goto error;
1157 if (is_zero) {
1158 isl_poly_free(poly2);
1159 return poly1;
1162 is_zero = isl_poly_is_zero(poly2);
1163 if (is_zero < 0)
1164 goto error;
1165 if (is_zero) {
1166 isl_poly_free(poly1);
1167 return poly2;
1170 is_one = isl_poly_is_one(poly1);
1171 if (is_one < 0)
1172 goto error;
1173 if (is_one) {
1174 isl_poly_free(poly1);
1175 return poly2;
1178 is_one = isl_poly_is_one(poly2);
1179 if (is_one < 0)
1180 goto error;
1181 if (is_one) {
1182 isl_poly_free(poly2);
1183 return poly1;
1186 if (poly1->var < poly2->var)
1187 return isl_poly_mul(poly2, poly1);
1189 if (poly2->var < poly1->var) {
1190 int i;
1191 isl_poly_rec *rec;
1192 isl_bool is_infty;
1194 is_infty = isl_poly_is_infty(poly2);
1195 if (is_infty >= 0 && !is_infty)
1196 is_infty = isl_poly_is_neginfty(poly2);
1197 if (is_infty < 0)
1198 goto error;
1199 if (is_infty) {
1200 isl_ctx *ctx = poly1->ctx;
1201 isl_poly_free(poly1);
1202 isl_poly_free(poly2);
1203 return isl_poly_nan(ctx);
1205 poly1 = isl_poly_cow(poly1);
1206 rec = isl_poly_as_rec(poly1);
1207 if (!rec)
1208 goto error;
1210 for (i = 0; i < rec->n; ++i) {
1211 rec->p[i] = isl_poly_mul(rec->p[i],
1212 isl_poly_copy(poly2));
1213 if (!rec->p[i])
1214 goto error;
1216 isl_poly_free(poly2);
1217 return poly1;
1220 is_cst = isl_poly_is_cst(poly1);
1221 if (is_cst < 0)
1222 goto error;
1223 if (is_cst)
1224 return isl_poly_mul_cst(poly1, poly2);
1226 return isl_poly_mul_rec(poly1, poly2);
1227 error:
1228 isl_poly_free(poly1);
1229 isl_poly_free(poly2);
1230 return NULL;
1233 __isl_give isl_poly *isl_poly_pow(__isl_take isl_poly *poly, unsigned power)
1235 isl_poly *res;
1237 if (!poly)
1238 return NULL;
1239 if (power == 1)
1240 return poly;
1242 if (power % 2)
1243 res = isl_poly_copy(poly);
1244 else
1245 res = isl_poly_one(poly->ctx);
1247 while (power >>= 1) {
1248 poly = isl_poly_mul(poly, isl_poly_copy(poly));
1249 if (power % 2)
1250 res = isl_poly_mul(res, isl_poly_copy(poly));
1253 isl_poly_free(poly);
1254 return res;
1257 __isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_space *space,
1258 unsigned n_div, __isl_take isl_poly *poly)
1260 struct isl_qpolynomial *qp = NULL;
1261 unsigned total;
1263 if (!space || !poly)
1264 goto error;
1266 if (!isl_space_is_set(space))
1267 isl_die(isl_space_get_ctx(space), isl_error_invalid,
1268 "domain of polynomial should be a set", goto error);
1270 total = isl_space_dim(space, isl_dim_all);
1272 qp = isl_calloc_type(space->ctx, struct isl_qpolynomial);
1273 if (!qp)
1274 goto error;
1276 qp->ref = 1;
1277 qp->div = isl_mat_alloc(space->ctx, n_div, 1 + 1 + total + n_div);
1278 if (!qp->div)
1279 goto error;
1281 qp->dim = space;
1282 qp->poly = poly;
1284 return qp;
1285 error:
1286 isl_space_free(space);
1287 isl_poly_free(poly);
1288 isl_qpolynomial_free(qp);
1289 return NULL;
1292 __isl_give isl_qpolynomial *isl_qpolynomial_copy(__isl_keep isl_qpolynomial *qp)
1294 if (!qp)
1295 return NULL;
1297 qp->ref++;
1298 return qp;
1301 __isl_give isl_qpolynomial *isl_qpolynomial_dup(__isl_keep isl_qpolynomial *qp)
1303 struct isl_qpolynomial *dup;
1305 if (!qp)
1306 return NULL;
1308 dup = isl_qpolynomial_alloc(isl_space_copy(qp->dim), qp->div->n_row,
1309 isl_poly_copy(qp->poly));
1310 if (!dup)
1311 return NULL;
1312 isl_mat_free(dup->div);
1313 dup->div = isl_mat_copy(qp->div);
1314 if (!dup->div)
1315 goto error;
1317 return dup;
1318 error:
1319 isl_qpolynomial_free(dup);
1320 return NULL;
1323 __isl_give isl_qpolynomial *isl_qpolynomial_cow(__isl_take isl_qpolynomial *qp)
1325 if (!qp)
1326 return NULL;
1328 if (qp->ref == 1)
1329 return qp;
1330 qp->ref--;
1331 return isl_qpolynomial_dup(qp);
1334 __isl_null isl_qpolynomial *isl_qpolynomial_free(
1335 __isl_take isl_qpolynomial *qp)
1337 if (!qp)
1338 return NULL;
1340 if (--qp->ref > 0)
1341 return NULL;
1343 isl_space_free(qp->dim);
1344 isl_mat_free(qp->div);
1345 isl_poly_free(qp->poly);
1347 free(qp);
1348 return NULL;
1351 __isl_give isl_poly *isl_poly_var_pow(isl_ctx *ctx, int pos, int power)
1353 int i;
1354 isl_poly_rec *rec;
1355 isl_poly_cst *cst;
1357 rec = isl_poly_alloc_rec(ctx, pos, 1 + power);
1358 if (!rec)
1359 return NULL;
1360 for (i = 0; i < 1 + power; ++i) {
1361 rec->p[i] = isl_poly_zero(ctx);
1362 if (!rec->p[i])
1363 goto error;
1364 rec->n++;
1366 cst = isl_poly_as_cst(rec->p[power]);
1367 isl_int_set_si(cst->n, 1);
1369 return &rec->poly;
1370 error:
1371 isl_poly_free(&rec->poly);
1372 return NULL;
1375 /* r array maps original positions to new positions.
1377 static __isl_give isl_poly *reorder(__isl_take isl_poly *poly, int *r)
1379 int i;
1380 isl_bool is_cst;
1381 isl_poly_rec *rec;
1382 isl_poly *base;
1383 isl_poly *res;
1385 is_cst = isl_poly_is_cst(poly);
1386 if (is_cst < 0)
1387 return isl_poly_free(poly);
1388 if (is_cst)
1389 return poly;
1391 rec = isl_poly_as_rec(poly);
1392 if (!rec)
1393 goto error;
1395 isl_assert(poly->ctx, rec->n >= 1, goto error);
1397 base = isl_poly_var_pow(poly->ctx, r[poly->var], 1);
1398 res = reorder(isl_poly_copy(rec->p[rec->n - 1]), r);
1400 for (i = rec->n - 2; i >= 0; --i) {
1401 res = isl_poly_mul(res, isl_poly_copy(base));
1402 res = isl_poly_sum(res, reorder(isl_poly_copy(rec->p[i]), r));
1405 isl_poly_free(base);
1406 isl_poly_free(poly);
1408 return res;
1409 error:
1410 isl_poly_free(poly);
1411 return NULL;
1414 static isl_bool compatible_divs(__isl_keep isl_mat *div1,
1415 __isl_keep isl_mat *div2)
1417 int n_row, n_col;
1418 isl_bool equal;
1420 isl_assert(div1->ctx, div1->n_row >= div2->n_row &&
1421 div1->n_col >= div2->n_col,
1422 return isl_bool_error);
1424 if (div1->n_row == div2->n_row)
1425 return isl_mat_is_equal(div1, div2);
1427 n_row = div1->n_row;
1428 n_col = div1->n_col;
1429 div1->n_row = div2->n_row;
1430 div1->n_col = div2->n_col;
1432 equal = isl_mat_is_equal(div1, div2);
1434 div1->n_row = n_row;
1435 div1->n_col = n_col;
1437 return equal;
1440 static int cmp_row(__isl_keep isl_mat *div, int i, int j)
1442 int li, lj;
1444 li = isl_seq_last_non_zero(div->row[i], div->n_col);
1445 lj = isl_seq_last_non_zero(div->row[j], div->n_col);
1447 if (li != lj)
1448 return li - lj;
1450 return isl_seq_cmp(div->row[i], div->row[j], div->n_col);
1453 struct isl_div_sort_info {
1454 isl_mat *div;
1455 int row;
1458 static int div_sort_cmp(const void *p1, const void *p2)
1460 const struct isl_div_sort_info *i1, *i2;
1461 i1 = (const struct isl_div_sort_info *) p1;
1462 i2 = (const struct isl_div_sort_info *) p2;
1464 return cmp_row(i1->div, i1->row, i2->row);
1467 /* Sort divs and remove duplicates.
1469 static __isl_give isl_qpolynomial *sort_divs(__isl_take isl_qpolynomial *qp)
1471 int i;
1472 int skip;
1473 int len;
1474 struct isl_div_sort_info *array = NULL;
1475 int *pos = NULL, *at = NULL;
1476 int *reordering = NULL;
1477 int div_pos;
1479 if (!qp)
1480 return NULL;
1481 if (qp->div->n_row <= 1)
1482 return qp;
1484 div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
1485 if (div_pos < 0)
1486 return isl_qpolynomial_free(qp);
1488 array = isl_alloc_array(qp->div->ctx, struct isl_div_sort_info,
1489 qp->div->n_row);
1490 pos = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);
1491 at = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);
1492 len = qp->div->n_col - 2;
1493 reordering = isl_alloc_array(qp->div->ctx, int, len);
1494 if (!array || !pos || !at || !reordering)
1495 goto error;
1497 for (i = 0; i < qp->div->n_row; ++i) {
1498 array[i].div = qp->div;
1499 array[i].row = i;
1500 pos[i] = i;
1501 at[i] = i;
1504 qsort(array, qp->div->n_row, sizeof(struct isl_div_sort_info),
1505 div_sort_cmp);
1507 for (i = 0; i < div_pos; ++i)
1508 reordering[i] = i;
1510 for (i = 0; i < qp->div->n_row; ++i) {
1511 if (pos[array[i].row] == i)
1512 continue;
1513 qp->div = isl_mat_swap_rows(qp->div, i, pos[array[i].row]);
1514 pos[at[i]] = pos[array[i].row];
1515 at[pos[array[i].row]] = at[i];
1516 at[i] = array[i].row;
1517 pos[array[i].row] = i;
1520 skip = 0;
1521 for (i = 0; i < len - div_pos; ++i) {
1522 if (i > 0 &&
1523 isl_seq_eq(qp->div->row[i - skip - 1],
1524 qp->div->row[i - skip], qp->div->n_col)) {
1525 qp->div = isl_mat_drop_rows(qp->div, i - skip, 1);
1526 isl_mat_col_add(qp->div, 2 + div_pos + i - skip - 1,
1527 2 + div_pos + i - skip);
1528 qp->div = isl_mat_drop_cols(qp->div,
1529 2 + div_pos + i - skip, 1);
1530 skip++;
1532 reordering[div_pos + array[i].row] = div_pos + i - skip;
1535 qp->poly = reorder(qp->poly, reordering);
1537 if (!qp->poly || !qp->div)
1538 goto error;
1540 free(at);
1541 free(pos);
1542 free(array);
1543 free(reordering);
1545 return qp;
1546 error:
1547 free(at);
1548 free(pos);
1549 free(array);
1550 free(reordering);
1551 isl_qpolynomial_free(qp);
1552 return NULL;
1555 static __isl_give isl_poly *expand(__isl_take isl_poly *poly, int *exp,
1556 int first)
1558 int i;
1559 isl_bool is_cst;
1560 isl_poly_rec *rec;
1562 is_cst = isl_poly_is_cst(poly);
1563 if (is_cst < 0)
1564 return isl_poly_free(poly);
1565 if (is_cst)
1566 return poly;
1568 if (poly->var < first)
1569 return poly;
1571 if (exp[poly->var - first] == poly->var - first)
1572 return poly;
1574 poly = isl_poly_cow(poly);
1575 if (!poly)
1576 goto error;
1578 poly->var = exp[poly->var - first] + first;
1580 rec = isl_poly_as_rec(poly);
1581 if (!rec)
1582 goto error;
1584 for (i = 0; i < rec->n; ++i) {
1585 rec->p[i] = expand(rec->p[i], exp, first);
1586 if (!rec->p[i])
1587 goto error;
1590 return poly;
1591 error:
1592 isl_poly_free(poly);
1593 return NULL;
1596 static __isl_give isl_qpolynomial *with_merged_divs(
1597 __isl_give isl_qpolynomial *(*fn)(__isl_take isl_qpolynomial *qp1,
1598 __isl_take isl_qpolynomial *qp2),
1599 __isl_take isl_qpolynomial *qp1, __isl_take isl_qpolynomial *qp2)
1601 int *exp1 = NULL;
1602 int *exp2 = NULL;
1603 isl_mat *div = NULL;
1604 int n_div1, n_div2;
1606 qp1 = isl_qpolynomial_cow(qp1);
1607 qp2 = isl_qpolynomial_cow(qp2);
1609 if (!qp1 || !qp2)
1610 goto error;
1612 isl_assert(qp1->div->ctx, qp1->div->n_row >= qp2->div->n_row &&
1613 qp1->div->n_col >= qp2->div->n_col, goto error);
1615 n_div1 = qp1->div->n_row;
1616 n_div2 = qp2->div->n_row;
1617 exp1 = isl_alloc_array(qp1->div->ctx, int, n_div1);
1618 exp2 = isl_alloc_array(qp2->div->ctx, int, n_div2);
1619 if ((n_div1 && !exp1) || (n_div2 && !exp2))
1620 goto error;
1622 div = isl_merge_divs(qp1->div, qp2->div, exp1, exp2);
1623 if (!div)
1624 goto error;
1626 isl_mat_free(qp1->div);
1627 qp1->div = isl_mat_copy(div);
1628 isl_mat_free(qp2->div);
1629 qp2->div = isl_mat_copy(div);
1631 qp1->poly = expand(qp1->poly, exp1, div->n_col - div->n_row - 2);
1632 qp2->poly = expand(qp2->poly, exp2, div->n_col - div->n_row - 2);
1634 if (!qp1->poly || !qp2->poly)
1635 goto error;
1637 isl_mat_free(div);
1638 free(exp1);
1639 free(exp2);
1641 return fn(qp1, qp2);
1642 error:
1643 isl_mat_free(div);
1644 free(exp1);
1645 free(exp2);
1646 isl_qpolynomial_free(qp1);
1647 isl_qpolynomial_free(qp2);
1648 return NULL;
1651 __isl_give isl_qpolynomial *isl_qpolynomial_add(__isl_take isl_qpolynomial *qp1,
1652 __isl_take isl_qpolynomial *qp2)
1654 isl_bool compatible;
1656 qp1 = isl_qpolynomial_cow(qp1);
1658 if (!qp1 || !qp2)
1659 goto error;
1661 if (qp1->div->n_row < qp2->div->n_row)
1662 return isl_qpolynomial_add(qp2, qp1);
1664 isl_assert(qp1->dim->ctx, isl_space_is_equal(qp1->dim, qp2->dim), goto error);
1665 compatible = compatible_divs(qp1->div, qp2->div);
1666 if (compatible < 0)
1667 goto error;
1668 if (!compatible)
1669 return with_merged_divs(isl_qpolynomial_add, qp1, qp2);
1671 qp1->poly = isl_poly_sum(qp1->poly, isl_poly_copy(qp2->poly));
1672 if (!qp1->poly)
1673 goto error;
1675 isl_qpolynomial_free(qp2);
1677 return qp1;
1678 error:
1679 isl_qpolynomial_free(qp1);
1680 isl_qpolynomial_free(qp2);
1681 return NULL;
1684 __isl_give isl_qpolynomial *isl_qpolynomial_add_on_domain(
1685 __isl_keep isl_set *dom,
1686 __isl_take isl_qpolynomial *qp1,
1687 __isl_take isl_qpolynomial *qp2)
1689 qp1 = isl_qpolynomial_add(qp1, qp2);
1690 qp1 = isl_qpolynomial_gist(qp1, isl_set_copy(dom));
1691 return qp1;
1694 __isl_give isl_qpolynomial *isl_qpolynomial_sub(__isl_take isl_qpolynomial *qp1,
1695 __isl_take isl_qpolynomial *qp2)
1697 return isl_qpolynomial_add(qp1, isl_qpolynomial_neg(qp2));
1700 __isl_give isl_qpolynomial *isl_qpolynomial_add_isl_int(
1701 __isl_take isl_qpolynomial *qp, isl_int v)
1703 if (isl_int_is_zero(v))
1704 return qp;
1706 qp = isl_qpolynomial_cow(qp);
1707 if (!qp)
1708 return NULL;
1710 qp->poly = isl_poly_add_isl_int(qp->poly, v);
1711 if (!qp->poly)
1712 goto error;
1714 return qp;
1715 error:
1716 isl_qpolynomial_free(qp);
1717 return NULL;
1721 __isl_give isl_qpolynomial *isl_qpolynomial_neg(__isl_take isl_qpolynomial *qp)
1723 if (!qp)
1724 return NULL;
1726 return isl_qpolynomial_mul_isl_int(qp, qp->dim->ctx->negone);
1729 __isl_give isl_qpolynomial *isl_qpolynomial_mul_isl_int(
1730 __isl_take isl_qpolynomial *qp, isl_int v)
1732 if (isl_int_is_one(v))
1733 return qp;
1735 if (qp && isl_int_is_zero(v)) {
1736 isl_qpolynomial *zero;
1737 zero = isl_qpolynomial_zero_on_domain(isl_space_copy(qp->dim));
1738 isl_qpolynomial_free(qp);
1739 return zero;
1742 qp = isl_qpolynomial_cow(qp);
1743 if (!qp)
1744 return NULL;
1746 qp->poly = isl_poly_mul_isl_int(qp->poly, v);
1747 if (!qp->poly)
1748 goto error;
1750 return qp;
1751 error:
1752 isl_qpolynomial_free(qp);
1753 return NULL;
1756 __isl_give isl_qpolynomial *isl_qpolynomial_scale(
1757 __isl_take isl_qpolynomial *qp, isl_int v)
1759 return isl_qpolynomial_mul_isl_int(qp, v);
1762 /* Multiply "qp" by "v".
1764 __isl_give isl_qpolynomial *isl_qpolynomial_scale_val(
1765 __isl_take isl_qpolynomial *qp, __isl_take isl_val *v)
1767 if (!qp || !v)
1768 goto error;
1770 if (!isl_val_is_rat(v))
1771 isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
1772 "expecting rational factor", goto error);
1774 if (isl_val_is_one(v)) {
1775 isl_val_free(v);
1776 return qp;
1779 if (isl_val_is_zero(v)) {
1780 isl_space *space;
1782 space = isl_qpolynomial_get_domain_space(qp);
1783 isl_qpolynomial_free(qp);
1784 isl_val_free(v);
1785 return isl_qpolynomial_zero_on_domain(space);
1788 qp = isl_qpolynomial_cow(qp);
1789 if (!qp)
1790 goto error;
1792 qp->poly = isl_poly_scale_val(qp->poly, v);
1793 if (!qp->poly)
1794 qp = isl_qpolynomial_free(qp);
1796 isl_val_free(v);
1797 return qp;
1798 error:
1799 isl_val_free(v);
1800 isl_qpolynomial_free(qp);
1801 return NULL;
1804 /* Divide "qp" by "v".
1806 __isl_give isl_qpolynomial *isl_qpolynomial_scale_down_val(
1807 __isl_take isl_qpolynomial *qp, __isl_take isl_val *v)
1809 if (!qp || !v)
1810 goto error;
1812 if (!isl_val_is_rat(v))
1813 isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
1814 "expecting rational factor", goto error);
1815 if (isl_val_is_zero(v))
1816 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1817 "cannot scale down by zero", goto error);
1819 return isl_qpolynomial_scale_val(qp, isl_val_inv(v));
1820 error:
1821 isl_val_free(v);
1822 isl_qpolynomial_free(qp);
1823 return NULL;
1826 __isl_give isl_qpolynomial *isl_qpolynomial_mul(__isl_take isl_qpolynomial *qp1,
1827 __isl_take isl_qpolynomial *qp2)
1829 isl_bool compatible;
1831 qp1 = isl_qpolynomial_cow(qp1);
1833 if (!qp1 || !qp2)
1834 goto error;
1836 if (qp1->div->n_row < qp2->div->n_row)
1837 return isl_qpolynomial_mul(qp2, qp1);
1839 isl_assert(qp1->dim->ctx, isl_space_is_equal(qp1->dim, qp2->dim), goto error);
1840 compatible = compatible_divs(qp1->div, qp2->div);
1841 if (compatible < 0)
1842 goto error;
1843 if (!compatible)
1844 return with_merged_divs(isl_qpolynomial_mul, qp1, qp2);
1846 qp1->poly = isl_poly_mul(qp1->poly, isl_poly_copy(qp2->poly));
1847 if (!qp1->poly)
1848 goto error;
1850 isl_qpolynomial_free(qp2);
1852 return qp1;
1853 error:
1854 isl_qpolynomial_free(qp1);
1855 isl_qpolynomial_free(qp2);
1856 return NULL;
1859 __isl_give isl_qpolynomial *isl_qpolynomial_pow(__isl_take isl_qpolynomial *qp,
1860 unsigned power)
1862 qp = isl_qpolynomial_cow(qp);
1864 if (!qp)
1865 return NULL;
1867 qp->poly = isl_poly_pow(qp->poly, power);
1868 if (!qp->poly)
1869 goto error;
1871 return qp;
1872 error:
1873 isl_qpolynomial_free(qp);
1874 return NULL;
1877 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_pow(
1878 __isl_take isl_pw_qpolynomial *pwqp, unsigned power)
1880 int i;
1882 if (power == 1)
1883 return pwqp;
1885 pwqp = isl_pw_qpolynomial_cow(pwqp);
1886 if (!pwqp)
1887 return NULL;
1889 for (i = 0; i < pwqp->n; ++i) {
1890 pwqp->p[i].qp = isl_qpolynomial_pow(pwqp->p[i].qp, power);
1891 if (!pwqp->p[i].qp)
1892 return isl_pw_qpolynomial_free(pwqp);
1895 return pwqp;
1898 __isl_give isl_qpolynomial *isl_qpolynomial_zero_on_domain(
1899 __isl_take isl_space *domain)
1901 if (!domain)
1902 return NULL;
1903 return isl_qpolynomial_alloc(domain, 0, isl_poly_zero(domain->ctx));
1906 __isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain(
1907 __isl_take isl_space *domain)
1909 if (!domain)
1910 return NULL;
1911 return isl_qpolynomial_alloc(domain, 0, isl_poly_one(domain->ctx));
1914 __isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain(
1915 __isl_take isl_space *domain)
1917 if (!domain)
1918 return NULL;
1919 return isl_qpolynomial_alloc(domain, 0, isl_poly_infty(domain->ctx));
1922 __isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain(
1923 __isl_take isl_space *domain)
1925 if (!domain)
1926 return NULL;
1927 return isl_qpolynomial_alloc(domain, 0, isl_poly_neginfty(domain->ctx));
1930 __isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain(
1931 __isl_take isl_space *domain)
1933 if (!domain)
1934 return NULL;
1935 return isl_qpolynomial_alloc(domain, 0, isl_poly_nan(domain->ctx));
1938 __isl_give isl_qpolynomial *isl_qpolynomial_cst_on_domain(
1939 __isl_take isl_space *domain,
1940 isl_int v)
1942 struct isl_qpolynomial *qp;
1943 isl_poly_cst *cst;
1945 qp = isl_qpolynomial_zero_on_domain(domain);
1946 if (!qp)
1947 return NULL;
1949 cst = isl_poly_as_cst(qp->poly);
1950 isl_int_set(cst->n, v);
1952 return qp;
1955 isl_bool isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
1956 isl_int *n, isl_int *d)
1958 isl_bool is_cst;
1959 isl_poly_cst *cst;
1961 if (!qp)
1962 return isl_bool_error;
1964 is_cst = isl_poly_is_cst(qp->poly);
1965 if (is_cst < 0 || !is_cst)
1966 return is_cst;
1968 cst = isl_poly_as_cst(qp->poly);
1969 if (!cst)
1970 return isl_bool_error;
1972 if (n)
1973 isl_int_set(*n, cst->n);
1974 if (d)
1975 isl_int_set(*d, cst->d);
1977 return isl_bool_true;
1980 /* Return the constant term of "poly".
1982 static __isl_give isl_val *isl_poly_get_constant_val(__isl_keep isl_poly *poly)
1984 isl_bool is_cst;
1985 isl_poly_cst *cst;
1987 if (!poly)
1988 return NULL;
1990 while ((is_cst = isl_poly_is_cst(poly)) == isl_bool_false) {
1991 isl_poly_rec *rec;
1993 rec = isl_poly_as_rec(poly);
1994 if (!rec)
1995 return NULL;
1996 poly = rec->p[0];
1998 if (is_cst < 0)
1999 return NULL;
2001 cst = isl_poly_as_cst(poly);
2002 if (!cst)
2003 return NULL;
2004 return isl_val_rat_from_isl_int(cst->poly.ctx, cst->n, cst->d);
2007 /* Return the constant term of "qp".
2009 __isl_give isl_val *isl_qpolynomial_get_constant_val(
2010 __isl_keep isl_qpolynomial *qp)
2012 if (!qp)
2013 return NULL;
2015 return isl_poly_get_constant_val(qp->poly);
2018 isl_bool isl_poly_is_affine(__isl_keep isl_poly *poly)
2020 isl_bool is_cst;
2021 isl_poly_rec *rec;
2023 if (!poly)
2024 return isl_bool_error;
2026 if (poly->var < 0)
2027 return isl_bool_true;
2029 rec = isl_poly_as_rec(poly);
2030 if (!rec)
2031 return isl_bool_error;
2033 if (rec->n > 2)
2034 return isl_bool_false;
2036 isl_assert(poly->ctx, rec->n > 1, return isl_bool_error);
2038 is_cst = isl_poly_is_cst(rec->p[1]);
2039 if (is_cst < 0 || !is_cst)
2040 return is_cst;
2042 return isl_poly_is_affine(rec->p[0]);
2045 isl_bool isl_qpolynomial_is_affine(__isl_keep isl_qpolynomial *qp)
2047 if (!qp)
2048 return isl_bool_error;
2050 if (qp->div->n_row > 0)
2051 return isl_bool_false;
2053 return isl_poly_is_affine(qp->poly);
2056 static void update_coeff(__isl_keep isl_vec *aff,
2057 __isl_keep isl_poly_cst *cst, int pos)
2059 isl_int gcd;
2060 isl_int f;
2062 if (isl_int_is_zero(cst->n))
2063 return;
2065 isl_int_init(gcd);
2066 isl_int_init(f);
2067 isl_int_gcd(gcd, cst->d, aff->el[0]);
2068 isl_int_divexact(f, cst->d, gcd);
2069 isl_int_divexact(gcd, aff->el[0], gcd);
2070 isl_seq_scale(aff->el, aff->el, f, aff->size);
2071 isl_int_mul(aff->el[1 + pos], gcd, cst->n);
2072 isl_int_clear(gcd);
2073 isl_int_clear(f);
2076 int isl_poly_update_affine(__isl_keep isl_poly *poly, __isl_keep isl_vec *aff)
2078 isl_poly_cst *cst;
2079 isl_poly_rec *rec;
2081 if (!poly || !aff)
2082 return -1;
2084 if (poly->var < 0) {
2085 isl_poly_cst *cst;
2087 cst = isl_poly_as_cst(poly);
2088 if (!cst)
2089 return -1;
2090 update_coeff(aff, cst, 0);
2091 return 0;
2094 rec = isl_poly_as_rec(poly);
2095 if (!rec)
2096 return -1;
2097 isl_assert(poly->ctx, rec->n == 2, return -1);
2099 cst = isl_poly_as_cst(rec->p[1]);
2100 if (!cst)
2101 return -1;
2102 update_coeff(aff, cst, 1 + poly->var);
2104 return isl_poly_update_affine(rec->p[0], aff);
2107 __isl_give isl_vec *isl_qpolynomial_extract_affine(
2108 __isl_keep isl_qpolynomial *qp)
2110 isl_vec *aff;
2111 unsigned d;
2113 if (!qp)
2114 return NULL;
2116 d = isl_qpolynomial_domain_dim(qp, isl_dim_all);
2117 aff = isl_vec_alloc(qp->div->ctx, 2 + d);
2118 if (!aff)
2119 return NULL;
2121 isl_seq_clr(aff->el + 1, 1 + d);
2122 isl_int_set_si(aff->el[0], 1);
2124 if (isl_poly_update_affine(qp->poly, aff) < 0)
2125 goto error;
2127 return aff;
2128 error:
2129 isl_vec_free(aff);
2130 return NULL;
2133 /* Compare two quasi-polynomials.
2135 * Return -1 if "qp1" is "smaller" than "qp2", 1 if "qp1" is "greater"
2136 * than "qp2" and 0 if they are equal.
2138 int isl_qpolynomial_plain_cmp(__isl_keep isl_qpolynomial *qp1,
2139 __isl_keep isl_qpolynomial *qp2)
2141 int cmp;
2143 if (qp1 == qp2)
2144 return 0;
2145 if (!qp1)
2146 return -1;
2147 if (!qp2)
2148 return 1;
2150 cmp = isl_space_cmp(qp1->dim, qp2->dim);
2151 if (cmp != 0)
2152 return cmp;
2154 cmp = isl_local_cmp(qp1->div, qp2->div);
2155 if (cmp != 0)
2156 return cmp;
2158 return isl_poly_plain_cmp(qp1->poly, qp2->poly);
2161 /* Is "qp1" obviously equal to "qp2"?
2163 * NaN is not equal to anything, not even to another NaN.
2165 isl_bool isl_qpolynomial_plain_is_equal(__isl_keep isl_qpolynomial *qp1,
2166 __isl_keep isl_qpolynomial *qp2)
2168 isl_bool equal;
2170 if (!qp1 || !qp2)
2171 return isl_bool_error;
2173 if (isl_qpolynomial_is_nan(qp1) || isl_qpolynomial_is_nan(qp2))
2174 return isl_bool_false;
2176 equal = isl_space_is_equal(qp1->dim, qp2->dim);
2177 if (equal < 0 || !equal)
2178 return equal;
2180 equal = isl_mat_is_equal(qp1->div, qp2->div);
2181 if (equal < 0 || !equal)
2182 return equal;
2184 return isl_poly_is_equal(qp1->poly, qp2->poly);
2187 static isl_stat poly_update_den(__isl_keep isl_poly *poly, isl_int *d)
2189 int i;
2190 isl_bool is_cst;
2191 isl_poly_rec *rec;
2193 is_cst = isl_poly_is_cst(poly);
2194 if (is_cst < 0)
2195 return isl_stat_error;
2196 if (is_cst) {
2197 isl_poly_cst *cst;
2198 cst = isl_poly_as_cst(poly);
2199 if (!cst)
2200 return isl_stat_error;
2201 isl_int_lcm(*d, *d, cst->d);
2202 return isl_stat_ok;
2205 rec = isl_poly_as_rec(poly);
2206 if (!rec)
2207 return isl_stat_error;
2209 for (i = 0; i < rec->n; ++i)
2210 poly_update_den(rec->p[i], d);
2212 return isl_stat_ok;
2215 __isl_give isl_val *isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp)
2217 isl_val *d;
2219 if (!qp)
2220 return NULL;
2221 d = isl_val_one(isl_qpolynomial_get_ctx(qp));
2222 if (!d)
2223 return NULL;
2224 if (poly_update_den(qp->poly, &d->n) < 0)
2225 return isl_val_free(d);
2226 return d;
2229 __isl_give isl_qpolynomial *isl_qpolynomial_var_pow_on_domain(
2230 __isl_take isl_space *domain, int pos, int power)
2232 struct isl_ctx *ctx;
2234 if (!domain)
2235 return NULL;
2237 ctx = domain->ctx;
2239 return isl_qpolynomial_alloc(domain, 0,
2240 isl_poly_var_pow(ctx, pos, power));
2243 __isl_give isl_qpolynomial *isl_qpolynomial_var_on_domain(
2244 __isl_take isl_space *domain, enum isl_dim_type type, unsigned pos)
2246 if (isl_space_check_is_set(domain ) < 0)
2247 goto error;
2248 if (isl_space_check_range(domain, type, pos, 1) < 0)
2249 goto error;
2251 pos += isl_space_offset(domain, type);
2253 return isl_qpolynomial_var_pow_on_domain(domain, pos, 1);
2254 error:
2255 isl_space_free(domain);
2256 return NULL;
2259 __isl_give isl_poly *isl_poly_subs(__isl_take isl_poly *poly,
2260 unsigned first, unsigned n, __isl_keep isl_poly **subs)
2262 int i;
2263 isl_bool is_cst;
2264 isl_poly_rec *rec;
2265 isl_poly *base, *res;
2267 is_cst = isl_poly_is_cst(poly);
2268 if (is_cst < 0)
2269 return isl_poly_free(poly);
2270 if (is_cst)
2271 return poly;
2273 if (poly->var < first)
2274 return poly;
2276 rec = isl_poly_as_rec(poly);
2277 if (!rec)
2278 goto error;
2280 isl_assert(poly->ctx, rec->n >= 1, goto error);
2282 if (poly->var >= first + n)
2283 base = isl_poly_var_pow(poly->ctx, poly->var, 1);
2284 else
2285 base = isl_poly_copy(subs[poly->var - first]);
2287 res = isl_poly_subs(isl_poly_copy(rec->p[rec->n - 1]), first, n, subs);
2288 for (i = rec->n - 2; i >= 0; --i) {
2289 isl_poly *t;
2290 t = isl_poly_subs(isl_poly_copy(rec->p[i]), first, n, subs);
2291 res = isl_poly_mul(res, isl_poly_copy(base));
2292 res = isl_poly_sum(res, t);
2295 isl_poly_free(base);
2296 isl_poly_free(poly);
2298 return res;
2299 error:
2300 isl_poly_free(poly);
2301 return NULL;
2304 __isl_give isl_poly *isl_poly_from_affine(isl_ctx *ctx, isl_int *f,
2305 isl_int denom, unsigned len)
2307 int i;
2308 isl_poly *poly;
2310 isl_assert(ctx, len >= 1, return NULL);
2312 poly = isl_poly_rat_cst(ctx, f[0], denom);
2313 for (i = 0; i < len - 1; ++i) {
2314 isl_poly *t;
2315 isl_poly *c;
2317 if (isl_int_is_zero(f[1 + i]))
2318 continue;
2320 c = isl_poly_rat_cst(ctx, f[1 + i], denom);
2321 t = isl_poly_var_pow(ctx, i, 1);
2322 t = isl_poly_mul(c, t);
2323 poly = isl_poly_sum(poly, t);
2326 return poly;
2329 /* Remove common factor of non-constant terms and denominator.
2331 static void normalize_div(__isl_keep isl_qpolynomial *qp, int div)
2333 isl_ctx *ctx = qp->div->ctx;
2334 unsigned total = qp->div->n_col - 2;
2336 isl_seq_gcd(qp->div->row[div] + 2, total, &ctx->normalize_gcd);
2337 isl_int_gcd(ctx->normalize_gcd,
2338 ctx->normalize_gcd, qp->div->row[div][0]);
2339 if (isl_int_is_one(ctx->normalize_gcd))
2340 return;
2342 isl_seq_scale_down(qp->div->row[div] + 2, qp->div->row[div] + 2,
2343 ctx->normalize_gcd, total);
2344 isl_int_divexact(qp->div->row[div][0], qp->div->row[div][0],
2345 ctx->normalize_gcd);
2346 isl_int_fdiv_q(qp->div->row[div][1], qp->div->row[div][1],
2347 ctx->normalize_gcd);
2350 /* Replace the integer division identified by "div" by the polynomial "s".
2351 * The integer division is assumed not to appear in the definition
2352 * of any other integer divisions.
2354 static __isl_give isl_qpolynomial *substitute_div(
2355 __isl_take isl_qpolynomial *qp, int div, __isl_take isl_poly *s)
2357 int i;
2358 int div_pos;
2359 int *reordering;
2360 isl_ctx *ctx;
2362 if (!qp || !s)
2363 goto error;
2365 qp = isl_qpolynomial_cow(qp);
2366 if (!qp)
2367 goto error;
2369 div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
2370 if (div_pos < 0)
2371 goto error;
2372 qp->poly = isl_poly_subs(qp->poly, div_pos + div, 1, &s);
2373 if (!qp->poly)
2374 goto error;
2376 ctx = isl_qpolynomial_get_ctx(qp);
2377 reordering = isl_alloc_array(ctx, int, div_pos + qp->div->n_row);
2378 if (!reordering)
2379 goto error;
2380 for (i = 0; i < div_pos + div; ++i)
2381 reordering[i] = i;
2382 for (i = div_pos + div + 1; i < div_pos + qp->div->n_row; ++i)
2383 reordering[i] = i - 1;
2384 qp->div = isl_mat_drop_rows(qp->div, div, 1);
2385 qp->div = isl_mat_drop_cols(qp->div, 2 + div_pos + div, 1);
2386 qp->poly = reorder(qp->poly, reordering);
2387 free(reordering);
2389 if (!qp->poly || !qp->div)
2390 goto error;
2392 isl_poly_free(s);
2393 return qp;
2394 error:
2395 isl_qpolynomial_free(qp);
2396 isl_poly_free(s);
2397 return NULL;
2400 /* Replace all integer divisions [e/d] that turn out to not actually be integer
2401 * divisions because d is equal to 1 by their definition, i.e., e.
2403 static __isl_give isl_qpolynomial *substitute_non_divs(
2404 __isl_take isl_qpolynomial *qp)
2406 int i, j;
2407 int div_pos;
2408 isl_poly *s;
2410 div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
2411 if (div_pos < 0)
2412 return isl_qpolynomial_free(qp);
2414 for (i = 0; qp && i < qp->div->n_row; ++i) {
2415 if (!isl_int_is_one(qp->div->row[i][0]))
2416 continue;
2417 for (j = i + 1; j < qp->div->n_row; ++j) {
2418 if (isl_int_is_zero(qp->div->row[j][2 + div_pos + i]))
2419 continue;
2420 isl_seq_combine(qp->div->row[j] + 1,
2421 qp->div->ctx->one, qp->div->row[j] + 1,
2422 qp->div->row[j][2 + div_pos + i],
2423 qp->div->row[i] + 1, 1 + div_pos + i);
2424 isl_int_set_si(qp->div->row[j][2 + div_pos + i], 0);
2425 normalize_div(qp, j);
2427 s = isl_poly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,
2428 qp->div->row[i][0], qp->div->n_col - 1);
2429 qp = substitute_div(qp, i, s);
2430 --i;
2433 return qp;
2436 /* Reduce the coefficients of div "div" to lie in the interval [0, d-1],
2437 * with d the denominator. When replacing the coefficient e of x by
2438 * d * frac(e/d) = e - d * floor(e/d), we are subtracting d * floor(e/d) * x
2439 * inside the division, so we need to add floor(e/d) * x outside.
2440 * That is, we replace q by q' + floor(e/d) * x and we therefore need
2441 * to adjust the coefficient of x in each later div that depends on the
2442 * current div "div" and also in the affine expressions in the rows of "mat"
2443 * (if they too depend on "div").
2445 static void reduce_div(__isl_keep isl_qpolynomial *qp, int div,
2446 __isl_keep isl_mat **mat)
2448 int i, j;
2449 isl_int v;
2450 unsigned total = qp->div->n_col - qp->div->n_row - 2;
2452 isl_int_init(v);
2453 for (i = 0; i < 1 + total + div; ++i) {
2454 if (isl_int_is_nonneg(qp->div->row[div][1 + i]) &&
2455 isl_int_lt(qp->div->row[div][1 + i], qp->div->row[div][0]))
2456 continue;
2457 isl_int_fdiv_q(v, qp->div->row[div][1 + i], qp->div->row[div][0]);
2458 isl_int_fdiv_r(qp->div->row[div][1 + i],
2459 qp->div->row[div][1 + i], qp->div->row[div][0]);
2460 *mat = isl_mat_col_addmul(*mat, i, v, 1 + total + div);
2461 for (j = div + 1; j < qp->div->n_row; ++j) {
2462 if (isl_int_is_zero(qp->div->row[j][2 + total + div]))
2463 continue;
2464 isl_int_addmul(qp->div->row[j][1 + i],
2465 v, qp->div->row[j][2 + total + div]);
2468 isl_int_clear(v);
2471 /* Check if the last non-zero coefficient is bigger that half of the
2472 * denominator. If so, we will invert the div to further reduce the number
2473 * of distinct divs that may appear.
2474 * If the last non-zero coefficient is exactly half the denominator,
2475 * then we continue looking for earlier coefficients that are bigger
2476 * than half the denominator.
2478 static int needs_invert(__isl_keep isl_mat *div, int row)
2480 int i;
2481 int cmp;
2483 for (i = div->n_col - 1; i >= 1; --i) {
2484 if (isl_int_is_zero(div->row[row][i]))
2485 continue;
2486 isl_int_mul_ui(div->row[row][i], div->row[row][i], 2);
2487 cmp = isl_int_cmp(div->row[row][i], div->row[row][0]);
2488 isl_int_divexact_ui(div->row[row][i], div->row[row][i], 2);
2489 if (cmp)
2490 return cmp > 0;
2491 if (i == 1)
2492 return 1;
2495 return 0;
2498 /* Replace div "div" q = [e/d] by -[(-e+(d-1))/d].
2499 * We only invert the coefficients of e (and the coefficient of q in
2500 * later divs and in the rows of "mat"). After calling this function, the
2501 * coefficients of e should be reduced again.
2503 static void invert_div(__isl_keep isl_qpolynomial *qp, int div,
2504 __isl_keep isl_mat **mat)
2506 unsigned total = qp->div->n_col - qp->div->n_row - 2;
2508 isl_seq_neg(qp->div->row[div] + 1,
2509 qp->div->row[div] + 1, qp->div->n_col - 1);
2510 isl_int_sub_ui(qp->div->row[div][1], qp->div->row[div][1], 1);
2511 isl_int_add(qp->div->row[div][1],
2512 qp->div->row[div][1], qp->div->row[div][0]);
2513 *mat = isl_mat_col_neg(*mat, 1 + total + div);
2514 isl_mat_col_mul(qp->div, 2 + total + div,
2515 qp->div->ctx->negone, 2 + total + div);
2518 /* Reduce all divs of "qp" to have coefficients
2519 * in the interval [0, d-1], with d the denominator and such that the
2520 * last non-zero coefficient that is not equal to d/2 is smaller than d/2.
2521 * The modifications to the integer divisions need to be reflected
2522 * in the factors of the polynomial that refer to the original
2523 * integer divisions. To this end, the modifications are collected
2524 * as a set of affine expressions and then plugged into the polynomial.
2526 * After the reduction, some divs may have become redundant or identical,
2527 * so we call substitute_non_divs and sort_divs. If these functions
2528 * eliminate divs or merge two or more divs into one, the coefficients
2529 * of the enclosing divs may have to be reduced again, so we call
2530 * ourselves recursively if the number of divs decreases.
2532 static __isl_give isl_qpolynomial *reduce_divs(__isl_take isl_qpolynomial *qp)
2534 int i;
2535 isl_ctx *ctx;
2536 isl_mat *mat;
2537 isl_poly **s;
2538 unsigned o_div, n_div, total;
2540 if (!qp)
2541 return NULL;
2543 total = isl_qpolynomial_domain_dim(qp, isl_dim_all);
2544 n_div = isl_qpolynomial_domain_dim(qp, isl_dim_div);
2545 o_div = isl_qpolynomial_domain_offset(qp, isl_dim_div);
2546 ctx = isl_qpolynomial_get_ctx(qp);
2547 mat = isl_mat_zero(ctx, n_div, 1 + total);
2549 for (i = 0; i < n_div; ++i)
2550 mat = isl_mat_set_element_si(mat, i, o_div + i, 1);
2552 for (i = 0; i < qp->div->n_row; ++i) {
2553 normalize_div(qp, i);
2554 reduce_div(qp, i, &mat);
2555 if (needs_invert(qp->div, i)) {
2556 invert_div(qp, i, &mat);
2557 reduce_div(qp, i, &mat);
2560 if (!mat)
2561 goto error;
2563 s = isl_alloc_array(ctx, struct isl_poly *, n_div);
2564 if (n_div && !s)
2565 goto error;
2566 for (i = 0; i < n_div; ++i)
2567 s[i] = isl_poly_from_affine(ctx, mat->row[i], ctx->one,
2568 1 + total);
2569 qp->poly = isl_poly_subs(qp->poly, o_div - 1, n_div, s);
2570 for (i = 0; i < n_div; ++i)
2571 isl_poly_free(s[i]);
2572 free(s);
2573 if (!qp->poly)
2574 goto error;
2576 isl_mat_free(mat);
2578 qp = substitute_non_divs(qp);
2579 qp = sort_divs(qp);
2580 if (qp && isl_qpolynomial_domain_dim(qp, isl_dim_div) < n_div)
2581 return reduce_divs(qp);
2583 return qp;
2584 error:
2585 isl_qpolynomial_free(qp);
2586 isl_mat_free(mat);
2587 return NULL;
2590 __isl_give isl_qpolynomial *isl_qpolynomial_rat_cst_on_domain(
2591 __isl_take isl_space *domain, const isl_int n, const isl_int d)
2593 struct isl_qpolynomial *qp;
2594 isl_poly_cst *cst;
2596 qp = isl_qpolynomial_zero_on_domain(domain);
2597 if (!qp)
2598 return NULL;
2600 cst = isl_poly_as_cst(qp->poly);
2601 isl_int_set(cst->n, n);
2602 isl_int_set(cst->d, d);
2604 return qp;
2607 /* Return an isl_qpolynomial that is equal to "val" on domain space "domain".
2609 __isl_give isl_qpolynomial *isl_qpolynomial_val_on_domain(
2610 __isl_take isl_space *domain, __isl_take isl_val *val)
2612 isl_qpolynomial *qp;
2613 isl_poly_cst *cst;
2615 qp = isl_qpolynomial_zero_on_domain(domain);
2616 if (!qp || !val)
2617 goto error;
2619 cst = isl_poly_as_cst(qp->poly);
2620 isl_int_set(cst->n, val->n);
2621 isl_int_set(cst->d, val->d);
2623 isl_val_free(val);
2624 return qp;
2625 error:
2626 isl_val_free(val);
2627 isl_qpolynomial_free(qp);
2628 return NULL;
2631 static isl_stat poly_set_active(__isl_keep isl_poly *poly, int *active, int d)
2633 isl_bool is_cst;
2634 isl_poly_rec *rec;
2635 int i;
2637 is_cst = isl_poly_is_cst(poly);
2638 if (is_cst < 0)
2639 return isl_stat_error;
2640 if (is_cst)
2641 return isl_stat_ok;
2643 if (poly->var < d)
2644 active[poly->var] = 1;
2646 rec = isl_poly_as_rec(poly);
2647 for (i = 0; i < rec->n; ++i)
2648 if (poly_set_active(rec->p[i], active, d) < 0)
2649 return isl_stat_error;
2651 return isl_stat_ok;
2654 static isl_stat set_active(__isl_keep isl_qpolynomial *qp, int *active)
2656 int i, j;
2657 int d;
2658 isl_space *space;
2660 space = isl_qpolynomial_peek_domain_space(qp);
2661 if (!space || !active)
2662 return isl_stat_error;
2664 d = isl_space_dim(space, isl_dim_all);
2665 for (i = 0; i < d; ++i)
2666 for (j = 0; j < qp->div->n_row; ++j) {
2667 if (isl_int_is_zero(qp->div->row[j][2 + i]))
2668 continue;
2669 active[i] = 1;
2670 break;
2673 return poly_set_active(qp->poly, active, d);
2676 #undef TYPE
2677 #define TYPE isl_qpolynomial
2678 static
2679 #include "check_type_range_templ.c"
2681 isl_bool isl_qpolynomial_involves_dims(__isl_keep isl_qpolynomial *qp,
2682 enum isl_dim_type type, unsigned first, unsigned n)
2684 int i;
2685 int *active = NULL;
2686 isl_bool involves = isl_bool_false;
2687 int offset;
2688 isl_space *space;
2690 if (!qp)
2691 return isl_bool_error;
2692 if (n == 0)
2693 return isl_bool_false;
2695 if (isl_qpolynomial_check_range(qp, type, first, n) < 0)
2696 return isl_bool_error;
2697 isl_assert(qp->dim->ctx, type == isl_dim_param ||
2698 type == isl_dim_in, return isl_bool_error);
2700 space = isl_qpolynomial_peek_domain_space(qp);
2701 active = isl_calloc_array(qp->dim->ctx, int,
2702 isl_space_dim(space, isl_dim_all));
2703 if (set_active(qp, active) < 0)
2704 goto error;
2706 offset = isl_qpolynomial_domain_var_offset(qp, domain_type(type));
2707 if (offset < 0)
2708 goto error;
2709 first += offset;
2710 for (i = 0; i < n; ++i)
2711 if (active[first + i]) {
2712 involves = isl_bool_true;
2713 break;
2716 free(active);
2718 return involves;
2719 error:
2720 free(active);
2721 return isl_bool_error;
2724 /* Remove divs that do not appear in the quasi-polynomial, nor in any
2725 * of the divs that do appear in the quasi-polynomial.
2727 static __isl_give isl_qpolynomial *remove_redundant_divs(
2728 __isl_take isl_qpolynomial *qp)
2730 int i, j;
2731 int div_pos;
2732 int len;
2733 int skip;
2734 int *active = NULL;
2735 int *reordering = NULL;
2736 int redundant = 0;
2737 int n_div;
2738 isl_ctx *ctx;
2740 if (!qp)
2741 return NULL;
2742 if (qp->div->n_row == 0)
2743 return qp;
2745 div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
2746 if (div_pos < 0)
2747 return isl_qpolynomial_free(qp);
2748 len = qp->div->n_col - 2;
2749 ctx = isl_qpolynomial_get_ctx(qp);
2750 active = isl_calloc_array(ctx, int, len);
2751 if (!active)
2752 goto error;
2754 if (poly_set_active(qp->poly, active, len) < 0)
2755 goto error;
2757 for (i = qp->div->n_row - 1; i >= 0; --i) {
2758 if (!active[div_pos + i]) {
2759 redundant = 1;
2760 continue;
2762 for (j = 0; j < i; ++j) {
2763 if (isl_int_is_zero(qp->div->row[i][2 + div_pos + j]))
2764 continue;
2765 active[div_pos + j] = 1;
2766 break;
2770 if (!redundant) {
2771 free(active);
2772 return qp;
2775 reordering = isl_alloc_array(qp->div->ctx, int, len);
2776 if (!reordering)
2777 goto error;
2779 for (i = 0; i < div_pos; ++i)
2780 reordering[i] = i;
2782 skip = 0;
2783 n_div = qp->div->n_row;
2784 for (i = 0; i < n_div; ++i) {
2785 if (!active[div_pos + i]) {
2786 qp->div = isl_mat_drop_rows(qp->div, i - skip, 1);
2787 qp->div = isl_mat_drop_cols(qp->div,
2788 2 + div_pos + i - skip, 1);
2789 skip++;
2791 reordering[div_pos + i] = div_pos + i - skip;
2794 qp->poly = reorder(qp->poly, reordering);
2796 if (!qp->poly || !qp->div)
2797 goto error;
2799 free(active);
2800 free(reordering);
2802 return qp;
2803 error:
2804 free(active);
2805 free(reordering);
2806 isl_qpolynomial_free(qp);
2807 return NULL;
2810 __isl_give isl_poly *isl_poly_drop(__isl_take isl_poly *poly,
2811 unsigned first, unsigned n)
2813 int i;
2814 isl_poly_rec *rec;
2816 if (!poly)
2817 return NULL;
2818 if (n == 0 || poly->var < 0 || poly->var < first)
2819 return poly;
2820 if (poly->var < first + n) {
2821 poly = replace_by_constant_term(poly);
2822 return isl_poly_drop(poly, first, n);
2824 poly = isl_poly_cow(poly);
2825 if (!poly)
2826 return NULL;
2827 poly->var -= n;
2828 rec = isl_poly_as_rec(poly);
2829 if (!rec)
2830 goto error;
2832 for (i = 0; i < rec->n; ++i) {
2833 rec->p[i] = isl_poly_drop(rec->p[i], first, n);
2834 if (!rec->p[i])
2835 goto error;
2838 return poly;
2839 error:
2840 isl_poly_free(poly);
2841 return NULL;
2844 __isl_give isl_qpolynomial *isl_qpolynomial_set_dim_name(
2845 __isl_take isl_qpolynomial *qp,
2846 enum isl_dim_type type, unsigned pos, const char *s)
2848 qp = isl_qpolynomial_cow(qp);
2849 if (!qp)
2850 return NULL;
2851 if (type == isl_dim_out)
2852 isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
2853 "cannot set name of output/set dimension",
2854 return isl_qpolynomial_free(qp));
2855 type = domain_type(type);
2856 qp->dim = isl_space_set_dim_name(qp->dim, type, pos, s);
2857 if (!qp->dim)
2858 goto error;
2859 return qp;
2860 error:
2861 isl_qpolynomial_free(qp);
2862 return NULL;
2865 __isl_give isl_qpolynomial *isl_qpolynomial_drop_dims(
2866 __isl_take isl_qpolynomial *qp,
2867 enum isl_dim_type type, unsigned first, unsigned n)
2869 int offset;
2871 if (!qp)
2872 return NULL;
2873 if (type == isl_dim_out)
2874 isl_die(qp->dim->ctx, isl_error_invalid,
2875 "cannot drop output/set dimension",
2876 goto error);
2877 if (isl_qpolynomial_check_range(qp, type, first, n) < 0)
2878 return isl_qpolynomial_free(qp);
2879 type = domain_type(type);
2880 if (n == 0 && !isl_space_is_named_or_nested(qp->dim, type))
2881 return qp;
2883 qp = isl_qpolynomial_cow(qp);
2884 if (!qp)
2885 return NULL;
2887 isl_assert(qp->dim->ctx, type == isl_dim_param ||
2888 type == isl_dim_set, goto error);
2890 qp->dim = isl_space_drop_dims(qp->dim, type, first, n);
2891 if (!qp->dim)
2892 goto error;
2894 offset = isl_qpolynomial_domain_var_offset(qp, type);
2895 if (offset < 0)
2896 goto error;
2897 first += offset;
2899 qp->div = isl_mat_drop_cols(qp->div, 2 + first, n);
2900 if (!qp->div)
2901 goto error;
2903 qp->poly = isl_poly_drop(qp->poly, first, n);
2904 if (!qp->poly)
2905 goto error;
2907 return qp;
2908 error:
2909 isl_qpolynomial_free(qp);
2910 return NULL;
2913 /* Project the domain of the quasi-polynomial onto its parameter space.
2914 * The quasi-polynomial may not involve any of the domain dimensions.
2916 __isl_give isl_qpolynomial *isl_qpolynomial_project_domain_on_params(
2917 __isl_take isl_qpolynomial *qp)
2919 isl_space *space;
2920 unsigned n;
2921 isl_bool involves;
2923 n = isl_qpolynomial_dim(qp, isl_dim_in);
2924 involves = isl_qpolynomial_involves_dims(qp, isl_dim_in, 0, n);
2925 if (involves < 0)
2926 return isl_qpolynomial_free(qp);
2927 if (involves)
2928 isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
2929 "polynomial involves some of the domain dimensions",
2930 return isl_qpolynomial_free(qp));
2931 qp = isl_qpolynomial_drop_dims(qp, isl_dim_in, 0, n);
2932 space = isl_qpolynomial_get_domain_space(qp);
2933 space = isl_space_params(space);
2934 qp = isl_qpolynomial_reset_domain_space(qp, space);
2935 return qp;
2938 static __isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities_lifted(
2939 __isl_take isl_qpolynomial *qp, __isl_take isl_basic_set *eq)
2941 int i, j, k;
2942 isl_int denom;
2943 unsigned total;
2944 unsigned n_div;
2945 isl_poly *poly;
2947 if (!eq)
2948 goto error;
2949 if (eq->n_eq == 0) {
2950 isl_basic_set_free(eq);
2951 return qp;
2954 qp = isl_qpolynomial_cow(qp);
2955 if (!qp)
2956 goto error;
2957 qp->div = isl_mat_cow(qp->div);
2958 if (!qp->div)
2959 goto error;
2961 total = isl_basic_set_offset(eq, isl_dim_div);
2962 n_div = eq->n_div;
2963 isl_int_init(denom);
2964 for (i = 0; i < eq->n_eq; ++i) {
2965 j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
2966 if (j < 0 || j == 0 || j >= total)
2967 continue;
2969 for (k = 0; k < qp->div->n_row; ++k) {
2970 if (isl_int_is_zero(qp->div->row[k][1 + j]))
2971 continue;
2972 isl_seq_elim(qp->div->row[k] + 1, eq->eq[i], j, total,
2973 &qp->div->row[k][0]);
2974 normalize_div(qp, k);
2977 if (isl_int_is_pos(eq->eq[i][j]))
2978 isl_seq_neg(eq->eq[i], eq->eq[i], total);
2979 isl_int_abs(denom, eq->eq[i][j]);
2980 isl_int_set_si(eq->eq[i][j], 0);
2982 poly = isl_poly_from_affine(qp->dim->ctx,
2983 eq->eq[i], denom, total);
2984 qp->poly = isl_poly_subs(qp->poly, j - 1, 1, &poly);
2985 isl_poly_free(poly);
2987 isl_int_clear(denom);
2989 if (!qp->poly)
2990 goto error;
2992 isl_basic_set_free(eq);
2994 qp = substitute_non_divs(qp);
2995 qp = sort_divs(qp);
2997 return qp;
2998 error:
2999 isl_basic_set_free(eq);
3000 isl_qpolynomial_free(qp);
3001 return NULL;
3004 /* Exploit the equalities in "eq" to simplify the quasi-polynomial.
3006 __isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities(
3007 __isl_take isl_qpolynomial *qp, __isl_take isl_basic_set *eq)
3009 if (!qp || !eq)
3010 goto error;
3011 if (qp->div->n_row > 0)
3012 eq = isl_basic_set_add_dims(eq, isl_dim_set, qp->div->n_row);
3013 return isl_qpolynomial_substitute_equalities_lifted(qp, eq);
3014 error:
3015 isl_basic_set_free(eq);
3016 isl_qpolynomial_free(qp);
3017 return NULL;
3020 /* Look for equalities among the variables shared by context and qp
3021 * and the integer divisions of qp, if any.
3022 * The equalities are then used to eliminate variables and/or integer
3023 * divisions from qp.
3025 __isl_give isl_qpolynomial *isl_qpolynomial_gist(
3026 __isl_take isl_qpolynomial *qp, __isl_take isl_set *context)
3028 isl_local_space *ls;
3029 isl_basic_set *aff;
3031 ls = isl_qpolynomial_get_domain_local_space(qp);
3032 context = isl_local_space_lift_set(ls, context);
3034 aff = isl_set_affine_hull(context);
3035 return isl_qpolynomial_substitute_equalities_lifted(qp, aff);
3038 __isl_give isl_qpolynomial *isl_qpolynomial_gist_params(
3039 __isl_take isl_qpolynomial *qp, __isl_take isl_set *context)
3041 isl_space *space = isl_qpolynomial_get_domain_space(qp);
3042 isl_set *dom_context = isl_set_universe(space);
3043 dom_context = isl_set_intersect_params(dom_context, context);
3044 return isl_qpolynomial_gist(qp, dom_context);
3047 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_qpolynomial(
3048 __isl_take isl_qpolynomial *qp)
3050 isl_set *dom;
3052 if (!qp)
3053 return NULL;
3054 if (isl_qpolynomial_is_zero(qp)) {
3055 isl_space *dim = isl_qpolynomial_get_space(qp);
3056 isl_qpolynomial_free(qp);
3057 return isl_pw_qpolynomial_zero(dim);
3060 dom = isl_set_universe(isl_qpolynomial_get_domain_space(qp));
3061 return isl_pw_qpolynomial_alloc(dom, qp);
3064 #define isl_qpolynomial_involves_nan isl_qpolynomial_is_nan
3066 #undef PW
3067 #define PW isl_pw_qpolynomial
3068 #undef EL
3069 #define EL isl_qpolynomial
3070 #undef EL_IS_ZERO
3071 #define EL_IS_ZERO is_zero
3072 #undef ZERO
3073 #define ZERO zero
3074 #undef IS_ZERO
3075 #define IS_ZERO is_zero
3076 #undef FIELD
3077 #define FIELD qp
3078 #undef DEFAULT_IS_ZERO
3079 #define DEFAULT_IS_ZERO 1
3081 #define NO_PULLBACK
3083 #include <isl_pw_templ.c>
3084 #include <isl_pw_eval.c>
3086 #undef BASE
3087 #define BASE pw_qpolynomial
3089 #include <isl_union_single.c>
3090 #include <isl_union_eval.c>
3091 #include <isl_union_neg.c>
3093 int isl_pw_qpolynomial_is_one(__isl_keep isl_pw_qpolynomial *pwqp)
3095 if (!pwqp)
3096 return -1;
3098 if (pwqp->n != -1)
3099 return 0;
3101 if (!isl_set_plain_is_universe(pwqp->p[0].set))
3102 return 0;
3104 return isl_qpolynomial_is_one(pwqp->p[0].qp);
3107 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add(
3108 __isl_take isl_pw_qpolynomial *pwqp1,
3109 __isl_take isl_pw_qpolynomial *pwqp2)
3111 return isl_pw_qpolynomial_union_add_(pwqp1, pwqp2);
3114 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
3115 __isl_take isl_pw_qpolynomial *pwqp1,
3116 __isl_take isl_pw_qpolynomial *pwqp2)
3118 int i, j, n;
3119 struct isl_pw_qpolynomial *res;
3121 if (!pwqp1 || !pwqp2)
3122 goto error;
3124 isl_assert(pwqp1->dim->ctx, isl_space_is_equal(pwqp1->dim, pwqp2->dim),
3125 goto error);
3127 if (isl_pw_qpolynomial_is_zero(pwqp1)) {
3128 isl_pw_qpolynomial_free(pwqp2);
3129 return pwqp1;
3132 if (isl_pw_qpolynomial_is_zero(pwqp2)) {
3133 isl_pw_qpolynomial_free(pwqp1);
3134 return pwqp2;
3137 if (isl_pw_qpolynomial_is_one(pwqp1)) {
3138 isl_pw_qpolynomial_free(pwqp1);
3139 return pwqp2;
3142 if (isl_pw_qpolynomial_is_one(pwqp2)) {
3143 isl_pw_qpolynomial_free(pwqp2);
3144 return pwqp1;
3147 n = pwqp1->n * pwqp2->n;
3148 res = isl_pw_qpolynomial_alloc_size(isl_space_copy(pwqp1->dim), n);
3150 for (i = 0; i < pwqp1->n; ++i) {
3151 for (j = 0; j < pwqp2->n; ++j) {
3152 struct isl_set *common;
3153 struct isl_qpolynomial *prod;
3154 common = isl_set_intersect(isl_set_copy(pwqp1->p[i].set),
3155 isl_set_copy(pwqp2->p[j].set));
3156 if (isl_set_plain_is_empty(common)) {
3157 isl_set_free(common);
3158 continue;
3161 prod = isl_qpolynomial_mul(
3162 isl_qpolynomial_copy(pwqp1->p[i].qp),
3163 isl_qpolynomial_copy(pwqp2->p[j].qp));
3165 res = isl_pw_qpolynomial_add_piece(res, common, prod);
3169 isl_pw_qpolynomial_free(pwqp1);
3170 isl_pw_qpolynomial_free(pwqp2);
3172 return res;
3173 error:
3174 isl_pw_qpolynomial_free(pwqp1);
3175 isl_pw_qpolynomial_free(pwqp2);
3176 return NULL;
3179 __isl_give isl_val *isl_poly_eval(__isl_take isl_poly *poly,
3180 __isl_take isl_vec *vec)
3182 int i;
3183 isl_bool is_cst;
3184 isl_poly_rec *rec;
3185 isl_val *res;
3186 isl_val *base;
3188 is_cst = isl_poly_is_cst(poly);
3189 if (is_cst < 0)
3190 goto error;
3191 if (is_cst) {
3192 isl_vec_free(vec);
3193 res = isl_poly_get_constant_val(poly);
3194 isl_poly_free(poly);
3195 return res;
3198 rec = isl_poly_as_rec(poly);
3199 if (!rec || !vec)
3200 goto error;
3202 isl_assert(poly->ctx, rec->n >= 1, goto error);
3204 base = isl_val_rat_from_isl_int(poly->ctx,
3205 vec->el[1 + poly->var], vec->el[0]);
3207 res = isl_poly_eval(isl_poly_copy(rec->p[rec->n - 1]),
3208 isl_vec_copy(vec));
3210 for (i = rec->n - 2; i >= 0; --i) {
3211 res = isl_val_mul(res, isl_val_copy(base));
3212 res = isl_val_add(res, isl_poly_eval(isl_poly_copy(rec->p[i]),
3213 isl_vec_copy(vec)));
3216 isl_val_free(base);
3217 isl_poly_free(poly);
3218 isl_vec_free(vec);
3219 return res;
3220 error:
3221 isl_poly_free(poly);
3222 isl_vec_free(vec);
3223 return NULL;
3226 /* Evaluate "qp" in the void point "pnt".
3227 * In particular, return the value NaN.
3229 static __isl_give isl_val *eval_void(__isl_take isl_qpolynomial *qp,
3230 __isl_take isl_point *pnt)
3232 isl_ctx *ctx;
3234 ctx = isl_point_get_ctx(pnt);
3235 isl_qpolynomial_free(qp);
3236 isl_point_free(pnt);
3237 return isl_val_nan(ctx);
3240 __isl_give isl_val *isl_qpolynomial_eval(__isl_take isl_qpolynomial *qp,
3241 __isl_take isl_point *pnt)
3243 isl_bool is_void;
3244 isl_vec *ext;
3245 isl_val *v;
3247 if (!qp || !pnt)
3248 goto error;
3249 isl_assert(pnt->dim->ctx, isl_space_is_equal(pnt->dim, qp->dim), goto error);
3250 is_void = isl_point_is_void(pnt);
3251 if (is_void < 0)
3252 goto error;
3253 if (is_void)
3254 return eval_void(qp, pnt);
3256 ext = isl_local_extend_point_vec(qp->div, isl_vec_copy(pnt->vec));
3258 v = isl_poly_eval(isl_poly_copy(qp->poly), ext);
3260 isl_qpolynomial_free(qp);
3261 isl_point_free(pnt);
3263 return v;
3264 error:
3265 isl_qpolynomial_free(qp);
3266 isl_point_free(pnt);
3267 return NULL;
3270 int isl_poly_cmp(__isl_keep isl_poly_cst *cst1, __isl_keep isl_poly_cst *cst2)
3272 int cmp;
3273 isl_int t;
3274 isl_int_init(t);
3275 isl_int_mul(t, cst1->n, cst2->d);
3276 isl_int_submul(t, cst2->n, cst1->d);
3277 cmp = isl_int_sgn(t);
3278 isl_int_clear(t);
3279 return cmp;
3282 __isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(
3283 __isl_take isl_qpolynomial *qp, enum isl_dim_type type,
3284 unsigned first, unsigned n)
3286 unsigned total;
3287 unsigned g_pos;
3288 int *exp;
3290 if (!qp)
3291 return NULL;
3292 if (type == isl_dim_out)
3293 isl_die(qp->div->ctx, isl_error_invalid,
3294 "cannot insert output/set dimensions",
3295 goto error);
3296 if (isl_qpolynomial_check_range(qp, type, first, 0) < 0)
3297 return isl_qpolynomial_free(qp);
3298 type = domain_type(type);
3299 if (n == 0 && !isl_space_is_named_or_nested(qp->dim, type))
3300 return qp;
3302 qp = isl_qpolynomial_cow(qp);
3303 if (!qp)
3304 return NULL;
3306 g_pos = pos(qp->dim, type) + first;
3308 qp->div = isl_mat_insert_zero_cols(qp->div, 2 + g_pos, n);
3309 if (!qp->div)
3310 goto error;
3312 total = qp->div->n_col - 2;
3313 if (total > g_pos) {
3314 int i;
3315 exp = isl_alloc_array(qp->div->ctx, int, total - g_pos);
3316 if (!exp)
3317 goto error;
3318 for (i = 0; i < total - g_pos; ++i)
3319 exp[i] = i + n;
3320 qp->poly = expand(qp->poly, exp, g_pos);
3321 free(exp);
3322 if (!qp->poly)
3323 goto error;
3326 qp->dim = isl_space_insert_dims(qp->dim, type, first, n);
3327 if (!qp->dim)
3328 goto error;
3330 return qp;
3331 error:
3332 isl_qpolynomial_free(qp);
3333 return NULL;
3336 __isl_give isl_qpolynomial *isl_qpolynomial_add_dims(
3337 __isl_take isl_qpolynomial *qp, enum isl_dim_type type, unsigned n)
3339 unsigned pos;
3341 pos = isl_qpolynomial_dim(qp, type);
3343 return isl_qpolynomial_insert_dims(qp, type, pos, n);
3346 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_dims(
3347 __isl_take isl_pw_qpolynomial *pwqp,
3348 enum isl_dim_type type, unsigned n)
3350 unsigned pos;
3352 pos = isl_pw_qpolynomial_dim(pwqp, type);
3354 return isl_pw_qpolynomial_insert_dims(pwqp, type, pos, n);
3357 static int *reordering_move(isl_ctx *ctx,
3358 unsigned len, unsigned dst, unsigned src, unsigned n)
3360 int i;
3361 int *reordering;
3363 reordering = isl_alloc_array(ctx, int, len);
3364 if (!reordering)
3365 return NULL;
3367 if (dst <= src) {
3368 for (i = 0; i < dst; ++i)
3369 reordering[i] = i;
3370 for (i = 0; i < n; ++i)
3371 reordering[src + i] = dst + i;
3372 for (i = 0; i < src - dst; ++i)
3373 reordering[dst + i] = dst + n + i;
3374 for (i = 0; i < len - src - n; ++i)
3375 reordering[src + n + i] = src + n + i;
3376 } else {
3377 for (i = 0; i < src; ++i)
3378 reordering[i] = i;
3379 for (i = 0; i < n; ++i)
3380 reordering[src + i] = dst + i;
3381 for (i = 0; i < dst - src; ++i)
3382 reordering[src + n + i] = src + i;
3383 for (i = 0; i < len - dst - n; ++i)
3384 reordering[dst + n + i] = dst + n + i;
3387 return reordering;
3390 __isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
3391 __isl_take isl_qpolynomial *qp,
3392 enum isl_dim_type dst_type, unsigned dst_pos,
3393 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3395 unsigned g_dst_pos;
3396 unsigned g_src_pos;
3397 int *reordering;
3399 if (!qp)
3400 return NULL;
3402 if (dst_type == isl_dim_out || src_type == isl_dim_out)
3403 isl_die(qp->dim->ctx, isl_error_invalid,
3404 "cannot move output/set dimension",
3405 goto error);
3406 if (isl_qpolynomial_check_range(qp, src_type, src_pos, n) < 0)
3407 return isl_qpolynomial_free(qp);
3408 if (dst_type == isl_dim_in)
3409 dst_type = isl_dim_set;
3410 if (src_type == isl_dim_in)
3411 src_type = isl_dim_set;
3413 if (n == 0 &&
3414 !isl_space_is_named_or_nested(qp->dim, src_type) &&
3415 !isl_space_is_named_or_nested(qp->dim, dst_type))
3416 return qp;
3418 qp = isl_qpolynomial_cow(qp);
3419 if (!qp)
3420 return NULL;
3422 g_dst_pos = pos(qp->dim, dst_type) + dst_pos;
3423 g_src_pos = pos(qp->dim, src_type) + src_pos;
3424 if (dst_type > src_type)
3425 g_dst_pos -= n;
3427 qp->div = isl_mat_move_cols(qp->div, 2 + g_dst_pos, 2 + g_src_pos, n);
3428 if (!qp->div)
3429 goto error;
3430 qp = sort_divs(qp);
3431 if (!qp)
3432 goto error;
3434 reordering = reordering_move(qp->dim->ctx,
3435 qp->div->n_col - 2, g_dst_pos, g_src_pos, n);
3436 if (!reordering)
3437 goto error;
3439 qp->poly = reorder(qp->poly, reordering);
3440 free(reordering);
3441 if (!qp->poly)
3442 goto error;
3444 qp->dim = isl_space_move_dims(qp->dim, dst_type, dst_pos, src_type, src_pos, n);
3445 if (!qp->dim)
3446 goto error;
3448 return qp;
3449 error:
3450 isl_qpolynomial_free(qp);
3451 return NULL;
3454 __isl_give isl_qpolynomial *isl_qpolynomial_from_affine(
3455 __isl_take isl_space *space, isl_int *f, isl_int denom)
3457 isl_poly *poly;
3459 space = isl_space_domain(space);
3460 if (!space)
3461 return NULL;
3463 poly = isl_poly_from_affine(space->ctx, f, denom,
3464 1 + isl_space_dim(space, isl_dim_all));
3466 return isl_qpolynomial_alloc(space, 0, poly);
3469 __isl_give isl_qpolynomial *isl_qpolynomial_from_aff(__isl_take isl_aff *aff)
3471 isl_ctx *ctx;
3472 isl_poly *poly;
3473 isl_qpolynomial *qp;
3475 if (!aff)
3476 return NULL;
3478 ctx = isl_aff_get_ctx(aff);
3479 poly = isl_poly_from_affine(ctx, aff->v->el + 1, aff->v->el[0],
3480 aff->v->size - 1);
3482 qp = isl_qpolynomial_alloc(isl_aff_get_domain_space(aff),
3483 aff->ls->div->n_row, poly);
3484 if (!qp)
3485 goto error;
3487 isl_mat_free(qp->div);
3488 qp->div = isl_mat_copy(aff->ls->div);
3489 qp->div = isl_mat_cow(qp->div);
3490 if (!qp->div)
3491 goto error;
3493 isl_aff_free(aff);
3494 qp = reduce_divs(qp);
3495 qp = remove_redundant_divs(qp);
3496 return qp;
3497 error:
3498 isl_aff_free(aff);
3499 return isl_qpolynomial_free(qp);
3502 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_pw_aff(
3503 __isl_take isl_pw_aff *pwaff)
3505 int i;
3506 isl_pw_qpolynomial *pwqp;
3508 if (!pwaff)
3509 return NULL;
3511 pwqp = isl_pw_qpolynomial_alloc_size(isl_pw_aff_get_space(pwaff),
3512 pwaff->n);
3514 for (i = 0; i < pwaff->n; ++i) {
3515 isl_set *dom;
3516 isl_qpolynomial *qp;
3518 dom = isl_set_copy(pwaff->p[i].set);
3519 qp = isl_qpolynomial_from_aff(isl_aff_copy(pwaff->p[i].aff));
3520 pwqp = isl_pw_qpolynomial_add_piece(pwqp, dom, qp);
3523 isl_pw_aff_free(pwaff);
3524 return pwqp;
3527 __isl_give isl_qpolynomial *isl_qpolynomial_from_constraint(
3528 __isl_take isl_constraint *c, enum isl_dim_type type, unsigned pos)
3530 isl_aff *aff;
3532 aff = isl_constraint_get_bound(c, type, pos);
3533 isl_constraint_free(c);
3534 return isl_qpolynomial_from_aff(aff);
3537 /* For each 0 <= i < "n", replace variable "first" + i of type "type"
3538 * in "qp" by subs[i].
3540 __isl_give isl_qpolynomial *isl_qpolynomial_substitute(
3541 __isl_take isl_qpolynomial *qp,
3542 enum isl_dim_type type, unsigned first, unsigned n,
3543 __isl_keep isl_qpolynomial **subs)
3545 int i;
3546 isl_poly **polys;
3548 if (n == 0)
3549 return qp;
3551 qp = isl_qpolynomial_cow(qp);
3552 if (!qp)
3553 return NULL;
3555 if (type == isl_dim_out)
3556 isl_die(qp->dim->ctx, isl_error_invalid,
3557 "cannot substitute output/set dimension",
3558 goto error);
3559 if (isl_qpolynomial_check_range(qp, type, first, n) < 0)
3560 return isl_qpolynomial_free(qp);
3561 type = domain_type(type);
3563 for (i = 0; i < n; ++i)
3564 if (!subs[i])
3565 goto error;
3567 for (i = 0; i < n; ++i)
3568 isl_assert(qp->dim->ctx, isl_space_is_equal(qp->dim, subs[i]->dim),
3569 goto error);
3571 isl_assert(qp->dim->ctx, qp->div->n_row == 0, goto error);
3572 for (i = 0; i < n; ++i)
3573 isl_assert(qp->dim->ctx, subs[i]->div->n_row == 0, goto error);
3575 first += pos(qp->dim, type);
3577 polys = isl_alloc_array(qp->dim->ctx, struct isl_poly *, n);
3578 if (!polys)
3579 goto error;
3580 for (i = 0; i < n; ++i)
3581 polys[i] = subs[i]->poly;
3583 qp->poly = isl_poly_subs(qp->poly, first, n, polys);
3585 free(polys);
3587 if (!qp->poly)
3588 goto error;
3590 return qp;
3591 error:
3592 isl_qpolynomial_free(qp);
3593 return NULL;
3596 /* Extend "bset" with extra set dimensions for each integer division
3597 * in "qp" and then call "fn" with the extended bset and the polynomial
3598 * that results from replacing each of the integer divisions by the
3599 * corresponding extra set dimension.
3601 isl_stat isl_qpolynomial_as_polynomial_on_domain(__isl_keep isl_qpolynomial *qp,
3602 __isl_keep isl_basic_set *bset,
3603 isl_stat (*fn)(__isl_take isl_basic_set *bset,
3604 __isl_take isl_qpolynomial *poly, void *user), void *user)
3606 isl_space *space;
3607 isl_local_space *ls;
3608 isl_qpolynomial *poly;
3610 if (!qp || !bset)
3611 return isl_stat_error;
3612 if (qp->div->n_row == 0)
3613 return fn(isl_basic_set_copy(bset), isl_qpolynomial_copy(qp),
3614 user);
3616 space = isl_space_copy(qp->dim);
3617 space = isl_space_add_dims(space, isl_dim_set, qp->div->n_row);
3618 poly = isl_qpolynomial_alloc(space, 0, isl_poly_copy(qp->poly));
3619 bset = isl_basic_set_copy(bset);
3620 ls = isl_qpolynomial_get_domain_local_space(qp);
3621 bset = isl_local_space_lift_basic_set(ls, bset);
3623 return fn(bset, poly, user);
3626 /* Return total degree in variables first (inclusive) up to last (exclusive).
3628 int isl_poly_degree(__isl_keep isl_poly *poly, int first, int last)
3630 int deg = -1;
3631 int i;
3632 isl_bool is_zero, is_cst;
3633 isl_poly_rec *rec;
3635 is_zero = isl_poly_is_zero(poly);
3636 if (is_zero < 0)
3637 return -2;
3638 if (is_zero)
3639 return -1;
3640 is_cst = isl_poly_is_cst(poly);
3641 if (is_cst < 0)
3642 return -2;
3643 if (is_cst || poly->var < first)
3644 return 0;
3646 rec = isl_poly_as_rec(poly);
3647 if (!rec)
3648 return -2;
3650 for (i = 0; i < rec->n; ++i) {
3651 int d;
3653 is_zero = isl_poly_is_zero(rec->p[i]);
3654 if (is_zero < 0)
3655 return -2;
3656 if (is_zero)
3657 continue;
3658 d = isl_poly_degree(rec->p[i], first, last);
3659 if (poly->var < last)
3660 d += i;
3661 if (d > deg)
3662 deg = d;
3665 return deg;
3668 /* Return total degree in set variables.
3670 int isl_qpolynomial_degree(__isl_keep isl_qpolynomial *poly)
3672 unsigned ovar;
3673 unsigned nvar;
3675 if (!poly)
3676 return -2;
3678 ovar = isl_space_offset(poly->dim, isl_dim_set);
3679 nvar = isl_space_dim(poly->dim, isl_dim_set);
3680 return isl_poly_degree(poly->poly, ovar, ovar + nvar);
3683 __isl_give isl_poly *isl_poly_coeff(__isl_keep isl_poly *poly,
3684 unsigned pos, int deg)
3686 int i;
3687 isl_bool is_cst;
3688 isl_poly_rec *rec;
3690 is_cst = isl_poly_is_cst(poly);
3691 if (is_cst < 0)
3692 return NULL;
3693 if (is_cst || poly->var < pos) {
3694 if (deg == 0)
3695 return isl_poly_copy(poly);
3696 else
3697 return isl_poly_zero(poly->ctx);
3700 rec = isl_poly_as_rec(poly);
3701 if (!rec)
3702 return NULL;
3704 if (poly->var == pos) {
3705 if (deg < rec->n)
3706 return isl_poly_copy(rec->p[deg]);
3707 else
3708 return isl_poly_zero(poly->ctx);
3711 poly = isl_poly_copy(poly);
3712 poly = isl_poly_cow(poly);
3713 rec = isl_poly_as_rec(poly);
3714 if (!rec)
3715 goto error;
3717 for (i = 0; i < rec->n; ++i) {
3718 isl_poly *t;
3719 t = isl_poly_coeff(rec->p[i], pos, deg);
3720 if (!t)
3721 goto error;
3722 isl_poly_free(rec->p[i]);
3723 rec->p[i] = t;
3726 return poly;
3727 error:
3728 isl_poly_free(poly);
3729 return NULL;
3732 /* Return coefficient of power "deg" of variable "t_pos" of type "type".
3734 __isl_give isl_qpolynomial *isl_qpolynomial_coeff(
3735 __isl_keep isl_qpolynomial *qp,
3736 enum isl_dim_type type, unsigned t_pos, int deg)
3738 unsigned g_pos;
3739 isl_poly *poly;
3740 isl_qpolynomial *c;
3742 if (!qp)
3743 return NULL;
3745 if (type == isl_dim_out)
3746 isl_die(qp->div->ctx, isl_error_invalid,
3747 "output/set dimension does not have a coefficient",
3748 return NULL);
3749 if (isl_qpolynomial_check_range(qp, type, t_pos, 1) < 0)
3750 return NULL;
3751 type = domain_type(type);
3753 g_pos = pos(qp->dim, type) + t_pos;
3754 poly = isl_poly_coeff(qp->poly, g_pos, deg);
3756 c = isl_qpolynomial_alloc(isl_space_copy(qp->dim),
3757 qp->div->n_row, poly);
3758 if (!c)
3759 return NULL;
3760 isl_mat_free(c->div);
3761 c->div = isl_mat_copy(qp->div);
3762 if (!c->div)
3763 goto error;
3764 return c;
3765 error:
3766 isl_qpolynomial_free(c);
3767 return NULL;
3770 /* Homogenize the polynomial in the variables first (inclusive) up to
3771 * last (exclusive) by inserting powers of variable first.
3772 * Variable first is assumed not to appear in the input.
3774 __isl_give isl_poly *isl_poly_homogenize(__isl_take isl_poly *poly, int deg,
3775 int target, int first, int last)
3777 int i;
3778 isl_bool is_zero, is_cst;
3779 isl_poly_rec *rec;
3781 is_zero = isl_poly_is_zero(poly);
3782 if (is_zero < 0)
3783 return isl_poly_free(poly);
3784 if (is_zero)
3785 return poly;
3786 if (deg == target)
3787 return poly;
3788 is_cst = isl_poly_is_cst(poly);
3789 if (is_cst < 0)
3790 return isl_poly_free(poly);
3791 if (is_cst || poly->var < first) {
3792 isl_poly *hom;
3794 hom = isl_poly_var_pow(poly->ctx, first, target - deg);
3795 if (!hom)
3796 goto error;
3797 rec = isl_poly_as_rec(hom);
3798 rec->p[target - deg] = isl_poly_mul(rec->p[target - deg], poly);
3800 return hom;
3803 poly = isl_poly_cow(poly);
3804 rec = isl_poly_as_rec(poly);
3805 if (!rec)
3806 goto error;
3808 for (i = 0; i < rec->n; ++i) {
3809 is_zero = isl_poly_is_zero(rec->p[i]);
3810 if (is_zero < 0)
3811 return isl_poly_free(poly);
3812 if (is_zero)
3813 continue;
3814 rec->p[i] = isl_poly_homogenize(rec->p[i],
3815 poly->var < last ? deg + i : i, target,
3816 first, last);
3817 if (!rec->p[i])
3818 goto error;
3821 return poly;
3822 error:
3823 isl_poly_free(poly);
3824 return NULL;
3827 /* Homogenize the polynomial in the set variables by introducing
3828 * powers of an extra set variable at position 0.
3830 __isl_give isl_qpolynomial *isl_qpolynomial_homogenize(
3831 __isl_take isl_qpolynomial *poly)
3833 unsigned ovar;
3834 unsigned nvar;
3835 int deg = isl_qpolynomial_degree(poly);
3837 if (deg < -1)
3838 goto error;
3840 poly = isl_qpolynomial_insert_dims(poly, isl_dim_in, 0, 1);
3841 poly = isl_qpolynomial_cow(poly);
3842 if (!poly)
3843 goto error;
3845 ovar = isl_space_offset(poly->dim, isl_dim_set);
3846 nvar = isl_space_dim(poly->dim, isl_dim_set);
3847 poly->poly = isl_poly_homogenize(poly->poly, 0, deg, ovar, ovar + nvar);
3848 if (!poly->poly)
3849 goto error;
3851 return poly;
3852 error:
3853 isl_qpolynomial_free(poly);
3854 return NULL;
3857 __isl_give isl_term *isl_term_alloc(__isl_take isl_space *space,
3858 __isl_take isl_mat *div)
3860 isl_term *term;
3861 int n;
3863 if (!space || !div)
3864 goto error;
3866 n = isl_space_dim(space, isl_dim_all) + div->n_row;
3868 term = isl_calloc(space->ctx, struct isl_term,
3869 sizeof(struct isl_term) + (n - 1) * sizeof(int));
3870 if (!term)
3871 goto error;
3873 term->ref = 1;
3874 term->dim = space;
3875 term->div = div;
3876 isl_int_init(term->n);
3877 isl_int_init(term->d);
3879 return term;
3880 error:
3881 isl_space_free(space);
3882 isl_mat_free(div);
3883 return NULL;
3886 __isl_give isl_term *isl_term_copy(__isl_keep isl_term *term)
3888 if (!term)
3889 return NULL;
3891 term->ref++;
3892 return term;
3895 __isl_give isl_term *isl_term_dup(__isl_keep isl_term *term)
3897 int i;
3898 isl_term *dup;
3899 unsigned total;
3901 if (!term)
3902 return NULL;
3904 total = isl_term_dim(term, isl_dim_all);
3906 dup = isl_term_alloc(isl_space_copy(term->dim), isl_mat_copy(term->div));
3907 if (!dup)
3908 return NULL;
3910 isl_int_set(dup->n, term->n);
3911 isl_int_set(dup->d, term->d);
3913 for (i = 0; i < total; ++i)
3914 dup->pow[i] = term->pow[i];
3916 return dup;
3919 __isl_give isl_term *isl_term_cow(__isl_take isl_term *term)
3921 if (!term)
3922 return NULL;
3924 if (term->ref == 1)
3925 return term;
3926 term->ref--;
3927 return isl_term_dup(term);
3930 __isl_null isl_term *isl_term_free(__isl_take isl_term *term)
3932 if (!term)
3933 return NULL;
3935 if (--term->ref > 0)
3936 return NULL;
3938 isl_space_free(term->dim);
3939 isl_mat_free(term->div);
3940 isl_int_clear(term->n);
3941 isl_int_clear(term->d);
3942 free(term);
3944 return NULL;
3947 unsigned isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type)
3949 if (!term)
3950 return 0;
3952 switch (type) {
3953 case isl_dim_param:
3954 case isl_dim_in:
3955 case isl_dim_out: return isl_space_dim(term->dim, type);
3956 case isl_dim_div: return term->div->n_row;
3957 case isl_dim_all: return isl_space_dim(term->dim, isl_dim_all) +
3958 term->div->n_row;
3959 default: return 0;
3963 /* Return the space of "term".
3965 static __isl_keep isl_space *isl_term_peek_space(__isl_keep isl_term *term)
3967 return term ? term->dim : NULL;
3970 /* Return the offset of the first variable of type "type" within
3971 * the variables of "term".
3973 static int isl_term_offset(__isl_keep isl_term *term, enum isl_dim_type type)
3975 isl_space *space;
3977 space = isl_term_peek_space(term);
3978 if (!space)
3979 return -1;
3981 switch (type) {
3982 case isl_dim_param:
3983 case isl_dim_set: return isl_space_offset(space, type);
3984 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
3985 default:
3986 isl_die(isl_term_get_ctx(term), isl_error_invalid,
3987 "invalid dimension type", return -1);
3991 isl_ctx *isl_term_get_ctx(__isl_keep isl_term *term)
3993 return term ? term->dim->ctx : NULL;
3996 void isl_term_get_num(__isl_keep isl_term *term, isl_int *n)
3998 if (!term)
3999 return;
4000 isl_int_set(*n, term->n);
4003 /* Return the coefficient of the term "term".
4005 __isl_give isl_val *isl_term_get_coefficient_val(__isl_keep isl_term *term)
4007 if (!term)
4008 return NULL;
4010 return isl_val_rat_from_isl_int(isl_term_get_ctx(term),
4011 term->n, term->d);
4014 #undef TYPE
4015 #define TYPE isl_term
4016 static
4017 #include "check_type_range_templ.c"
4019 int isl_term_get_exp(__isl_keep isl_term *term,
4020 enum isl_dim_type type, unsigned pos)
4022 int offset;
4024 if (isl_term_check_range(term, type, pos, 1) < 0)
4025 return -1;
4026 offset = isl_term_offset(term, type);
4027 if (offset < 0)
4028 return -1;
4030 return term->pow[offset + pos];
4033 __isl_give isl_aff *isl_term_get_div(__isl_keep isl_term *term, unsigned pos)
4035 isl_local_space *ls;
4036 isl_aff *aff;
4038 if (isl_term_check_range(term, isl_dim_div, pos, 1) < 0)
4039 return NULL;
4041 ls = isl_local_space_alloc_div(isl_space_copy(term->dim),
4042 isl_mat_copy(term->div));
4043 aff = isl_aff_alloc(ls);
4044 if (!aff)
4045 return NULL;
4047 isl_seq_cpy(aff->v->el, term->div->row[pos], aff->v->size);
4049 aff = isl_aff_normalize(aff);
4051 return aff;
4054 __isl_give isl_term *isl_poly_foreach_term(__isl_keep isl_poly *poly,
4055 isl_stat (*fn)(__isl_take isl_term *term, void *user),
4056 __isl_take isl_term *term, void *user)
4058 int i;
4059 isl_bool is_zero, is_bad, is_cst;
4060 isl_poly_rec *rec;
4062 is_zero = isl_poly_is_zero(poly);
4063 if (is_zero < 0 || !term)
4064 goto error;
4066 if (is_zero)
4067 return term;
4069 is_cst = isl_poly_is_cst(poly);
4070 is_bad = isl_poly_is_nan(poly);
4071 if (is_bad >= 0 && !is_bad)
4072 is_bad = isl_poly_is_infty(poly);
4073 if (is_bad >= 0 && !is_bad)
4074 is_bad = isl_poly_is_neginfty(poly);
4075 if (is_cst < 0 || is_bad < 0)
4076 return isl_term_free(term);
4077 if (is_bad)
4078 isl_die(isl_term_get_ctx(term), isl_error_invalid,
4079 "cannot handle NaN/infty polynomial",
4080 return isl_term_free(term));
4082 if (is_cst) {
4083 isl_poly_cst *cst;
4084 cst = isl_poly_as_cst(poly);
4085 if (!cst)
4086 goto error;
4087 term = isl_term_cow(term);
4088 if (!term)
4089 goto error;
4090 isl_int_set(term->n, cst->n);
4091 isl_int_set(term->d, cst->d);
4092 if (fn(isl_term_copy(term), user) < 0)
4093 goto error;
4094 return term;
4097 rec = isl_poly_as_rec(poly);
4098 if (!rec)
4099 goto error;
4101 for (i = 0; i < rec->n; ++i) {
4102 term = isl_term_cow(term);
4103 if (!term)
4104 goto error;
4105 term->pow[poly->var] = i;
4106 term = isl_poly_foreach_term(rec->p[i], fn, term, user);
4107 if (!term)
4108 goto error;
4110 term->pow[poly->var] = 0;
4112 return term;
4113 error:
4114 isl_term_free(term);
4115 return NULL;
4118 isl_stat isl_qpolynomial_foreach_term(__isl_keep isl_qpolynomial *qp,
4119 isl_stat (*fn)(__isl_take isl_term *term, void *user), void *user)
4121 isl_term *term;
4123 if (!qp)
4124 return isl_stat_error;
4126 term = isl_term_alloc(isl_space_copy(qp->dim), isl_mat_copy(qp->div));
4127 if (!term)
4128 return isl_stat_error;
4130 term = isl_poly_foreach_term(qp->poly, fn, term, user);
4132 isl_term_free(term);
4134 return term ? isl_stat_ok : isl_stat_error;
4137 __isl_give isl_qpolynomial *isl_qpolynomial_from_term(__isl_take isl_term *term)
4139 isl_poly *poly;
4140 isl_qpolynomial *qp;
4141 int i, n;
4143 if (!term)
4144 return NULL;
4146 n = isl_term_dim(term, isl_dim_all);
4148 poly = isl_poly_rat_cst(term->dim->ctx, term->n, term->d);
4149 for (i = 0; i < n; ++i) {
4150 if (!term->pow[i])
4151 continue;
4152 poly = isl_poly_mul(poly,
4153 isl_poly_var_pow(term->dim->ctx, i, term->pow[i]));
4156 qp = isl_qpolynomial_alloc(isl_space_copy(term->dim),
4157 term->div->n_row, poly);
4158 if (!qp)
4159 goto error;
4160 isl_mat_free(qp->div);
4161 qp->div = isl_mat_copy(term->div);
4162 if (!qp->div)
4163 goto error;
4165 isl_term_free(term);
4166 return qp;
4167 error:
4168 isl_qpolynomial_free(qp);
4169 isl_term_free(term);
4170 return NULL;
4173 __isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
4174 __isl_take isl_space *space)
4176 int i;
4177 int extra;
4178 unsigned total;
4180 if (!qp || !space)
4181 goto error;
4183 if (isl_space_is_equal(qp->dim, space)) {
4184 isl_space_free(space);
4185 return qp;
4188 qp = isl_qpolynomial_cow(qp);
4189 if (!qp)
4190 goto error;
4192 extra = isl_space_dim(space, isl_dim_set) -
4193 isl_qpolynomial_domain_dim(qp, isl_dim_set);
4194 total = isl_space_dim(qp->dim, isl_dim_all);
4195 if (qp->div->n_row) {
4196 int *exp;
4198 exp = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);
4199 if (!exp)
4200 goto error;
4201 for (i = 0; i < qp->div->n_row; ++i)
4202 exp[i] = extra + i;
4203 qp->poly = expand(qp->poly, exp, total);
4204 free(exp);
4205 if (!qp->poly)
4206 goto error;
4208 qp->div = isl_mat_insert_cols(qp->div, 2 + total, extra);
4209 if (!qp->div)
4210 goto error;
4211 for (i = 0; i < qp->div->n_row; ++i)
4212 isl_seq_clr(qp->div->row[i] + 2 + total, extra);
4214 isl_space_free(qp->dim);
4215 qp->dim = space;
4217 return qp;
4218 error:
4219 isl_space_free(space);
4220 isl_qpolynomial_free(qp);
4221 return NULL;
4224 /* For each parameter or variable that does not appear in qp,
4225 * first eliminate the variable from all constraints and then set it to zero.
4227 static __isl_give isl_set *fix_inactive(__isl_take isl_set *set,
4228 __isl_keep isl_qpolynomial *qp)
4230 int *active = NULL;
4231 int i;
4232 int d;
4233 unsigned nparam;
4234 unsigned nvar;
4236 if (!set || !qp)
4237 goto error;
4239 d = isl_set_dim(set, isl_dim_all);
4240 active = isl_calloc_array(set->ctx, int, d);
4241 if (set_active(qp, active) < 0)
4242 goto error;
4244 for (i = 0; i < d; ++i)
4245 if (!active[i])
4246 break;
4248 if (i == d) {
4249 free(active);
4250 return set;
4253 nparam = isl_set_dim(set, isl_dim_param);
4254 nvar = isl_set_dim(set, isl_dim_set);
4255 for (i = 0; i < nparam; ++i) {
4256 if (active[i])
4257 continue;
4258 set = isl_set_eliminate(set, isl_dim_param, i, 1);
4259 set = isl_set_fix_si(set, isl_dim_param, i, 0);
4261 for (i = 0; i < nvar; ++i) {
4262 if (active[nparam + i])
4263 continue;
4264 set = isl_set_eliminate(set, isl_dim_set, i, 1);
4265 set = isl_set_fix_si(set, isl_dim_set, i, 0);
4268 free(active);
4270 return set;
4271 error:
4272 free(active);
4273 isl_set_free(set);
4274 return NULL;
4277 struct isl_opt_data {
4278 isl_qpolynomial *qp;
4279 int first;
4280 isl_val *opt;
4281 int max;
4284 static isl_stat opt_fn(__isl_take isl_point *pnt, void *user)
4286 struct isl_opt_data *data = (struct isl_opt_data *)user;
4287 isl_val *val;
4289 val = isl_qpolynomial_eval(isl_qpolynomial_copy(data->qp), pnt);
4290 if (data->first) {
4291 data->first = 0;
4292 data->opt = val;
4293 } else if (data->max) {
4294 data->opt = isl_val_max(data->opt, val);
4295 } else {
4296 data->opt = isl_val_min(data->opt, val);
4299 return isl_stat_ok;
4302 __isl_give isl_val *isl_qpolynomial_opt_on_domain(
4303 __isl_take isl_qpolynomial *qp, __isl_take isl_set *set, int max)
4305 struct isl_opt_data data = { NULL, 1, NULL, max };
4306 isl_bool is_cst;
4308 if (!set || !qp)
4309 goto error;
4311 is_cst = isl_poly_is_cst(qp->poly);
4312 if (is_cst < 0)
4313 goto error;
4314 if (is_cst) {
4315 isl_set_free(set);
4316 data.opt = isl_qpolynomial_get_constant_val(qp);
4317 isl_qpolynomial_free(qp);
4318 return data.opt;
4321 set = fix_inactive(set, qp);
4323 data.qp = qp;
4324 if (isl_set_foreach_point(set, opt_fn, &data) < 0)
4325 goto error;
4327 if (data.first)
4328 data.opt = isl_val_zero(isl_set_get_ctx(set));
4330 isl_set_free(set);
4331 isl_qpolynomial_free(qp);
4332 return data.opt;
4333 error:
4334 isl_set_free(set);
4335 isl_qpolynomial_free(qp);
4336 isl_val_free(data.opt);
4337 return NULL;
4340 __isl_give isl_qpolynomial *isl_qpolynomial_morph_domain(
4341 __isl_take isl_qpolynomial *qp, __isl_take isl_morph *morph)
4343 int i;
4344 int n_sub;
4345 isl_ctx *ctx;
4346 isl_poly **subs;
4347 isl_mat *mat, *diag;
4349 qp = isl_qpolynomial_cow(qp);
4350 if (!qp || !morph)
4351 goto error;
4353 ctx = qp->dim->ctx;
4354 isl_assert(ctx, isl_space_is_equal(qp->dim, morph->dom->dim), goto error);
4356 n_sub = morph->inv->n_row - 1;
4357 if (morph->inv->n_row != morph->inv->n_col)
4358 n_sub += qp->div->n_row;
4359 subs = isl_calloc_array(ctx, struct isl_poly *, n_sub);
4360 if (n_sub && !subs)
4361 goto error;
4363 for (i = 0; 1 + i < morph->inv->n_row; ++i)
4364 subs[i] = isl_poly_from_affine(ctx, morph->inv->row[1 + i],
4365 morph->inv->row[0][0], morph->inv->n_col);
4366 if (morph->inv->n_row != morph->inv->n_col)
4367 for (i = 0; i < qp->div->n_row; ++i)
4368 subs[morph->inv->n_row - 1 + i] =
4369 isl_poly_var_pow(ctx, morph->inv->n_col - 1 + i, 1);
4371 qp->poly = isl_poly_subs(qp->poly, 0, n_sub, subs);
4373 for (i = 0; i < n_sub; ++i)
4374 isl_poly_free(subs[i]);
4375 free(subs);
4377 diag = isl_mat_diag(ctx, 1, morph->inv->row[0][0]);
4378 mat = isl_mat_diagonal(diag, isl_mat_copy(morph->inv));
4379 diag = isl_mat_diag(ctx, qp->div->n_row, morph->inv->row[0][0]);
4380 mat = isl_mat_diagonal(mat, diag);
4381 qp->div = isl_mat_product(qp->div, mat);
4382 isl_space_free(qp->dim);
4383 qp->dim = isl_space_copy(morph->ran->dim);
4385 if (!qp->poly || !qp->div || !qp->dim)
4386 goto error;
4388 isl_morph_free(morph);
4390 return qp;
4391 error:
4392 isl_qpolynomial_free(qp);
4393 isl_morph_free(morph);
4394 return NULL;
4397 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_mul(
4398 __isl_take isl_union_pw_qpolynomial *upwqp1,
4399 __isl_take isl_union_pw_qpolynomial *upwqp2)
4401 return isl_union_pw_qpolynomial_match_bin_op(upwqp1, upwqp2,
4402 &isl_pw_qpolynomial_mul);
4405 /* Reorder the dimension of "qp" according to the given reordering.
4407 __isl_give isl_qpolynomial *isl_qpolynomial_realign_domain(
4408 __isl_take isl_qpolynomial *qp, __isl_take isl_reordering *r)
4410 isl_space *space;
4412 qp = isl_qpolynomial_cow(qp);
4413 if (!qp)
4414 goto error;
4416 r = isl_reordering_extend(r, qp->div->n_row);
4417 if (!r)
4418 goto error;
4420 qp->div = isl_local_reorder(qp->div, isl_reordering_copy(r));
4421 if (!qp->div)
4422 goto error;
4424 qp->poly = reorder(qp->poly, r->pos);
4425 if (!qp->poly)
4426 goto error;
4428 space = isl_reordering_get_space(r);
4429 qp = isl_qpolynomial_reset_domain_space(qp, space);
4431 isl_reordering_free(r);
4432 return qp;
4433 error:
4434 isl_qpolynomial_free(qp);
4435 isl_reordering_free(r);
4436 return NULL;
4439 __isl_give isl_qpolynomial *isl_qpolynomial_align_params(
4440 __isl_take isl_qpolynomial *qp, __isl_take isl_space *model)
4442 isl_bool equal_params;
4444 if (!qp || !model)
4445 goto error;
4447 equal_params = isl_space_has_equal_params(qp->dim, model);
4448 if (equal_params < 0)
4449 goto error;
4450 if (!equal_params) {
4451 isl_reordering *exp;
4453 exp = isl_parameter_alignment_reordering(qp->dim, model);
4454 exp = isl_reordering_extend_space(exp,
4455 isl_qpolynomial_get_domain_space(qp));
4456 qp = isl_qpolynomial_realign_domain(qp, exp);
4459 isl_space_free(model);
4460 return qp;
4461 error:
4462 isl_space_free(model);
4463 isl_qpolynomial_free(qp);
4464 return NULL;
4467 struct isl_split_periods_data {
4468 int max_periods;
4469 isl_pw_qpolynomial *res;
4472 /* Create a slice where the integer division "div" has the fixed value "v".
4473 * In particular, if "div" refers to floor(f/m), then create a slice
4475 * m v <= f <= m v + (m - 1)
4477 * or
4479 * f - m v >= 0
4480 * -f + m v + (m - 1) >= 0
4482 static __isl_give isl_set *set_div_slice(__isl_take isl_space *space,
4483 __isl_keep isl_qpolynomial *qp, int div, isl_int v)
4485 int total;
4486 isl_basic_set *bset = NULL;
4487 int k;
4489 if (!space || !qp)
4490 goto error;
4492 total = isl_space_dim(space, isl_dim_all);
4493 bset = isl_basic_set_alloc_space(isl_space_copy(space), 0, 0, 2);
4495 k = isl_basic_set_alloc_inequality(bset);
4496 if (k < 0)
4497 goto error;
4498 isl_seq_cpy(bset->ineq[k], qp->div->row[div] + 1, 1 + total);
4499 isl_int_submul(bset->ineq[k][0], v, qp->div->row[div][0]);
4501 k = isl_basic_set_alloc_inequality(bset);
4502 if (k < 0)
4503 goto error;
4504 isl_seq_neg(bset->ineq[k], qp->div->row[div] + 1, 1 + total);
4505 isl_int_addmul(bset->ineq[k][0], v, qp->div->row[div][0]);
4506 isl_int_add(bset->ineq[k][0], bset->ineq[k][0], qp->div->row[div][0]);
4507 isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
4509 isl_space_free(space);
4510 return isl_set_from_basic_set(bset);
4511 error:
4512 isl_basic_set_free(bset);
4513 isl_space_free(space);
4514 return NULL;
4517 static isl_stat split_periods(__isl_take isl_set *set,
4518 __isl_take isl_qpolynomial *qp, void *user);
4520 /* Create a slice of the domain "set" such that integer division "div"
4521 * has the fixed value "v" and add the results to data->res,
4522 * replacing the integer division by "v" in "qp".
4524 static isl_stat set_div(__isl_take isl_set *set,
4525 __isl_take isl_qpolynomial *qp, int div, isl_int v,
4526 struct isl_split_periods_data *data)
4528 int i;
4529 int div_pos;
4530 isl_set *slice;
4531 isl_poly *cst;
4533 slice = set_div_slice(isl_set_get_space(set), qp, div, v);
4534 set = isl_set_intersect(set, slice);
4536 div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
4537 if (div_pos < 0)
4538 goto error;
4540 for (i = div + 1; i < qp->div->n_row; ++i) {
4541 if (isl_int_is_zero(qp->div->row[i][2 + div_pos + div]))
4542 continue;
4543 isl_int_addmul(qp->div->row[i][1],
4544 qp->div->row[i][2 + div_pos + div], v);
4545 isl_int_set_si(qp->div->row[i][2 + div_pos + div], 0);
4548 cst = isl_poly_rat_cst(qp->dim->ctx, v, qp->dim->ctx->one);
4549 qp = substitute_div(qp, div, cst);
4551 return split_periods(set, qp, data);
4552 error:
4553 isl_set_free(set);
4554 isl_qpolynomial_free(qp);
4555 return isl_stat_error;
4558 /* Split the domain "set" such that integer division "div"
4559 * has a fixed value (ranging from "min" to "max") on each slice
4560 * and add the results to data->res.
4562 static isl_stat split_div(__isl_take isl_set *set,
4563 __isl_take isl_qpolynomial *qp, int div, isl_int min, isl_int max,
4564 struct isl_split_periods_data *data)
4566 for (; isl_int_le(min, max); isl_int_add_ui(min, min, 1)) {
4567 isl_set *set_i = isl_set_copy(set);
4568 isl_qpolynomial *qp_i = isl_qpolynomial_copy(qp);
4570 if (set_div(set_i, qp_i, div, min, data) < 0)
4571 goto error;
4573 isl_set_free(set);
4574 isl_qpolynomial_free(qp);
4575 return isl_stat_ok;
4576 error:
4577 isl_set_free(set);
4578 isl_qpolynomial_free(qp);
4579 return isl_stat_error;
4582 /* If "qp" refers to any integer division
4583 * that can only attain "max_periods" distinct values on "set"
4584 * then split the domain along those distinct values.
4585 * Add the results (or the original if no splitting occurs)
4586 * to data->res.
4588 static isl_stat split_periods(__isl_take isl_set *set,
4589 __isl_take isl_qpolynomial *qp, void *user)
4591 int i;
4592 isl_pw_qpolynomial *pwqp;
4593 struct isl_split_periods_data *data;
4594 isl_int min, max;
4595 int div_pos;
4596 isl_stat r = isl_stat_ok;
4598 data = (struct isl_split_periods_data *)user;
4600 if (!set || !qp)
4601 goto error;
4603 if (qp->div->n_row == 0) {
4604 pwqp = isl_pw_qpolynomial_alloc(set, qp);
4605 data->res = isl_pw_qpolynomial_add_disjoint(data->res, pwqp);
4606 return isl_stat_ok;
4609 div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
4610 if (div_pos < 0)
4611 goto error;
4613 isl_int_init(min);
4614 isl_int_init(max);
4615 for (i = 0; i < qp->div->n_row; ++i) {
4616 enum isl_lp_result lp_res;
4618 if (isl_seq_first_non_zero(qp->div->row[i] + 2 + div_pos,
4619 qp->div->n_row) != -1)
4620 continue;
4622 lp_res = isl_set_solve_lp(set, 0, qp->div->row[i] + 1,
4623 set->ctx->one, &min, NULL, NULL);
4624 if (lp_res == isl_lp_error)
4625 goto error2;
4626 if (lp_res == isl_lp_unbounded || lp_res == isl_lp_empty)
4627 continue;
4628 isl_int_fdiv_q(min, min, qp->div->row[i][0]);
4630 lp_res = isl_set_solve_lp(set, 1, qp->div->row[i] + 1,
4631 set->ctx->one, &max, NULL, NULL);
4632 if (lp_res == isl_lp_error)
4633 goto error2;
4634 if (lp_res == isl_lp_unbounded || lp_res == isl_lp_empty)
4635 continue;
4636 isl_int_fdiv_q(max, max, qp->div->row[i][0]);
4638 isl_int_sub(max, max, min);
4639 if (isl_int_cmp_si(max, data->max_periods) < 0) {
4640 isl_int_add(max, max, min);
4641 break;
4645 if (i < qp->div->n_row) {
4646 r = split_div(set, qp, i, min, max, data);
4647 } else {
4648 pwqp = isl_pw_qpolynomial_alloc(set, qp);
4649 data->res = isl_pw_qpolynomial_add_disjoint(data->res, pwqp);
4652 isl_int_clear(max);
4653 isl_int_clear(min);
4655 return r;
4656 error2:
4657 isl_int_clear(max);
4658 isl_int_clear(min);
4659 error:
4660 isl_set_free(set);
4661 isl_qpolynomial_free(qp);
4662 return isl_stat_error;
4665 /* If any quasi-polynomial in pwqp refers to any integer division
4666 * that can only attain "max_periods" distinct values on its domain
4667 * then split the domain along those distinct values.
4669 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_split_periods(
4670 __isl_take isl_pw_qpolynomial *pwqp, int max_periods)
4672 struct isl_split_periods_data data;
4674 data.max_periods = max_periods;
4675 data.res = isl_pw_qpolynomial_zero(isl_pw_qpolynomial_get_space(pwqp));
4677 if (isl_pw_qpolynomial_foreach_piece(pwqp, &split_periods, &data) < 0)
4678 goto error;
4680 isl_pw_qpolynomial_free(pwqp);
4682 return data.res;
4683 error:
4684 isl_pw_qpolynomial_free(data.res);
4685 isl_pw_qpolynomial_free(pwqp);
4686 return NULL;
4689 /* Construct a piecewise quasipolynomial that is constant on the given
4690 * domain. In particular, it is
4691 * 0 if cst == 0
4692 * 1 if cst == 1
4693 * infinity if cst == -1
4695 * If cst == -1, then explicitly check whether the domain is empty and,
4696 * if so, return 0 instead.
4698 static __isl_give isl_pw_qpolynomial *constant_on_domain(
4699 __isl_take isl_basic_set *bset, int cst)
4701 isl_space *dim;
4702 isl_qpolynomial *qp;
4704 if (cst < 0 && isl_basic_set_is_empty(bset) == isl_bool_true)
4705 cst = 0;
4706 if (!bset)
4707 return NULL;
4709 bset = isl_basic_set_params(bset);
4710 dim = isl_basic_set_get_space(bset);
4711 if (cst < 0)
4712 qp = isl_qpolynomial_infty_on_domain(dim);
4713 else if (cst == 0)
4714 qp = isl_qpolynomial_zero_on_domain(dim);
4715 else
4716 qp = isl_qpolynomial_one_on_domain(dim);
4717 return isl_pw_qpolynomial_alloc(isl_set_from_basic_set(bset), qp);
4720 /* Factor bset, call fn on each of the factors and return the product.
4722 * If no factors can be found, simply call fn on the input.
4723 * Otherwise, construct the factors based on the factorizer,
4724 * call fn on each factor and compute the product.
4726 static __isl_give isl_pw_qpolynomial *compressed_multiplicative_call(
4727 __isl_take isl_basic_set *bset,
4728 __isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset))
4730 int i, n;
4731 isl_space *space;
4732 isl_set *set;
4733 isl_factorizer *f;
4734 isl_qpolynomial *qp;
4735 isl_pw_qpolynomial *pwqp;
4736 unsigned nparam;
4737 unsigned nvar;
4739 f = isl_basic_set_factorizer(bset);
4740 if (!f)
4741 goto error;
4742 if (f->n_group == 0) {
4743 isl_factorizer_free(f);
4744 return fn(bset);
4747 nparam = isl_basic_set_dim(bset, isl_dim_param);
4748 nvar = isl_basic_set_dim(bset, isl_dim_set);
4750 space = isl_basic_set_get_space(bset);
4751 space = isl_space_params(space);
4752 set = isl_set_universe(isl_space_copy(space));
4753 qp = isl_qpolynomial_one_on_domain(space);
4754 pwqp = isl_pw_qpolynomial_alloc(set, qp);
4756 bset = isl_morph_basic_set(isl_morph_copy(f->morph), bset);
4758 for (i = 0, n = 0; i < f->n_group; ++i) {
4759 isl_basic_set *bset_i;
4760 isl_pw_qpolynomial *pwqp_i;
4762 bset_i = isl_basic_set_copy(bset);
4763 bset_i = isl_basic_set_drop_constraints_involving(bset_i,
4764 nparam + n + f->len[i], nvar - n - f->len[i]);
4765 bset_i = isl_basic_set_drop_constraints_involving(bset_i,
4766 nparam, n);
4767 bset_i = isl_basic_set_drop(bset_i, isl_dim_set,
4768 n + f->len[i], nvar - n - f->len[i]);
4769 bset_i = isl_basic_set_drop(bset_i, isl_dim_set, 0, n);
4771 pwqp_i = fn(bset_i);
4772 pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp_i);
4774 n += f->len[i];
4777 isl_basic_set_free(bset);
4778 isl_factorizer_free(f);
4780 return pwqp;
4781 error:
4782 isl_basic_set_free(bset);
4783 return NULL;
4786 /* Factor bset, call fn on each of the factors and return the product.
4787 * The function is assumed to evaluate to zero on empty domains,
4788 * to one on zero-dimensional domains and to infinity on unbounded domains
4789 * and will not be called explicitly on zero-dimensional or unbounded domains.
4791 * We first check for some special cases and remove all equalities.
4792 * Then we hand over control to compressed_multiplicative_call.
4794 __isl_give isl_pw_qpolynomial *isl_basic_set_multiplicative_call(
4795 __isl_take isl_basic_set *bset,
4796 __isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset))
4798 isl_bool bounded;
4799 isl_morph *morph;
4800 isl_pw_qpolynomial *pwqp;
4802 if (!bset)
4803 return NULL;
4805 if (isl_basic_set_plain_is_empty(bset))
4806 return constant_on_domain(bset, 0);
4808 if (isl_basic_set_dim(bset, isl_dim_set) == 0)
4809 return constant_on_domain(bset, 1);
4811 bounded = isl_basic_set_is_bounded(bset);
4812 if (bounded < 0)
4813 goto error;
4814 if (!bounded)
4815 return constant_on_domain(bset, -1);
4817 if (bset->n_eq == 0)
4818 return compressed_multiplicative_call(bset, fn);
4820 morph = isl_basic_set_full_compression(bset);
4821 bset = isl_morph_basic_set(isl_morph_copy(morph), bset);
4823 pwqp = compressed_multiplicative_call(bset, fn);
4825 morph = isl_morph_dom_params(morph);
4826 morph = isl_morph_ran_params(morph);
4827 morph = isl_morph_inverse(morph);
4829 pwqp = isl_pw_qpolynomial_morph_domain(pwqp, morph);
4831 return pwqp;
4832 error:
4833 isl_basic_set_free(bset);
4834 return NULL;
4837 /* Drop all floors in "qp", turning each integer division [a/m] into
4838 * a rational division a/m. If "down" is set, then the integer division
4839 * is replaced by (a-(m-1))/m instead.
4841 static __isl_give isl_qpolynomial *qp_drop_floors(
4842 __isl_take isl_qpolynomial *qp, int down)
4844 int i;
4845 isl_poly *s;
4847 if (!qp)
4848 return NULL;
4849 if (qp->div->n_row == 0)
4850 return qp;
4852 qp = isl_qpolynomial_cow(qp);
4853 if (!qp)
4854 return NULL;
4856 for (i = qp->div->n_row - 1; i >= 0; --i) {
4857 if (down) {
4858 isl_int_sub(qp->div->row[i][1],
4859 qp->div->row[i][1], qp->div->row[i][0]);
4860 isl_int_add_ui(qp->div->row[i][1],
4861 qp->div->row[i][1], 1);
4863 s = isl_poly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,
4864 qp->div->row[i][0], qp->div->n_col - 1);
4865 qp = substitute_div(qp, i, s);
4866 if (!qp)
4867 return NULL;
4870 return qp;
4873 /* Drop all floors in "pwqp", turning each integer division [a/m] into
4874 * a rational division a/m.
4876 static __isl_give isl_pw_qpolynomial *pwqp_drop_floors(
4877 __isl_take isl_pw_qpolynomial *pwqp)
4879 int i;
4881 if (!pwqp)
4882 return NULL;
4884 if (isl_pw_qpolynomial_is_zero(pwqp))
4885 return pwqp;
4887 pwqp = isl_pw_qpolynomial_cow(pwqp);
4888 if (!pwqp)
4889 return NULL;
4891 for (i = 0; i < pwqp->n; ++i) {
4892 pwqp->p[i].qp = qp_drop_floors(pwqp->p[i].qp, 0);
4893 if (!pwqp->p[i].qp)
4894 goto error;
4897 return pwqp;
4898 error:
4899 isl_pw_qpolynomial_free(pwqp);
4900 return NULL;
4903 /* Adjust all the integer divisions in "qp" such that they are at least
4904 * one over the given orthant (identified by "signs"). This ensures
4905 * that they will still be non-negative even after subtracting (m-1)/m.
4907 * In particular, f is replaced by f' + v, changing f = [a/m]
4908 * to f' = [(a - m v)/m].
4909 * If the constant term k in a is smaller than m,
4910 * the constant term of v is set to floor(k/m) - 1.
4911 * For any other term, if the coefficient c and the variable x have
4912 * the same sign, then no changes are needed.
4913 * Otherwise, if the variable is positive (and c is negative),
4914 * then the coefficient of x in v is set to floor(c/m).
4915 * If the variable is negative (and c is positive),
4916 * then the coefficient of x in v is set to ceil(c/m).
4918 static __isl_give isl_qpolynomial *make_divs_pos(__isl_take isl_qpolynomial *qp,
4919 int *signs)
4921 int i, j;
4922 int div_pos;
4923 isl_vec *v = NULL;
4924 isl_poly *s;
4926 qp = isl_qpolynomial_cow(qp);
4927 div_pos = isl_qpolynomial_domain_var_offset(qp, isl_dim_div);
4928 if (div_pos < 0)
4929 return isl_qpolynomial_free(qp);
4930 qp->div = isl_mat_cow(qp->div);
4931 if (!qp->div)
4932 goto error;
4934 v = isl_vec_alloc(qp->div->ctx, qp->div->n_col - 1);
4936 for (i = 0; i < qp->div->n_row; ++i) {
4937 isl_int *row = qp->div->row[i];
4938 v = isl_vec_clr(v);
4939 if (!v)
4940 goto error;
4941 if (isl_int_lt(row[1], row[0])) {
4942 isl_int_fdiv_q(v->el[0], row[1], row[0]);
4943 isl_int_sub_ui(v->el[0], v->el[0], 1);
4944 isl_int_submul(row[1], row[0], v->el[0]);
4946 for (j = 0; j < div_pos; ++j) {
4947 if (isl_int_sgn(row[2 + j]) * signs[j] >= 0)
4948 continue;
4949 if (signs[j] < 0)
4950 isl_int_cdiv_q(v->el[1 + j], row[2 + j], row[0]);
4951 else
4952 isl_int_fdiv_q(v->el[1 + j], row[2 + j], row[0]);
4953 isl_int_submul(row[2 + j], row[0], v->el[1 + j]);
4955 for (j = 0; j < i; ++j) {
4956 if (isl_int_sgn(row[2 + div_pos + j]) >= 0)
4957 continue;
4958 isl_int_fdiv_q(v->el[1 + div_pos + j],
4959 row[2 + div_pos + j], row[0]);
4960 isl_int_submul(row[2 + div_pos + j],
4961 row[0], v->el[1 + div_pos + j]);
4963 for (j = i + 1; j < qp->div->n_row; ++j) {
4964 if (isl_int_is_zero(qp->div->row[j][2 + div_pos + i]))
4965 continue;
4966 isl_seq_combine(qp->div->row[j] + 1,
4967 qp->div->ctx->one, qp->div->row[j] + 1,
4968 qp->div->row[j][2 + div_pos + i], v->el,
4969 v->size);
4971 isl_int_set_si(v->el[1 + div_pos + i], 1);
4972 s = isl_poly_from_affine(qp->dim->ctx, v->el,
4973 qp->div->ctx->one, v->size);
4974 qp->poly = isl_poly_subs(qp->poly, div_pos + i, 1, &s);
4975 isl_poly_free(s);
4976 if (!qp->poly)
4977 goto error;
4980 isl_vec_free(v);
4981 return qp;
4982 error:
4983 isl_vec_free(v);
4984 isl_qpolynomial_free(qp);
4985 return NULL;
4988 struct isl_to_poly_data {
4989 int sign;
4990 isl_pw_qpolynomial *res;
4991 isl_qpolynomial *qp;
4994 /* Appoximate data->qp by a polynomial on the orthant identified by "signs".
4995 * We first make all integer divisions positive and then split the
4996 * quasipolynomials into terms with sign data->sign (the direction
4997 * of the requested approximation) and terms with the opposite sign.
4998 * In the first set of terms, each integer division [a/m] is
4999 * overapproximated by a/m, while in the second it is underapproximated
5000 * by (a-(m-1))/m.
5002 static isl_stat to_polynomial_on_orthant(__isl_take isl_set *orthant,
5003 int *signs, void *user)
5005 struct isl_to_poly_data *data = user;
5006 isl_pw_qpolynomial *t;
5007 isl_qpolynomial *qp, *up, *down;
5009 qp = isl_qpolynomial_copy(data->qp);
5010 qp = make_divs_pos(qp, signs);
5012 up = isl_qpolynomial_terms_of_sign(qp, signs, data->sign);
5013 up = qp_drop_floors(up, 0);
5014 down = isl_qpolynomial_terms_of_sign(qp, signs, -data->sign);
5015 down = qp_drop_floors(down, 1);
5017 isl_qpolynomial_free(qp);
5018 qp = isl_qpolynomial_add(up, down);
5020 t = isl_pw_qpolynomial_alloc(orthant, qp);
5021 data->res = isl_pw_qpolynomial_add_disjoint(data->res, t);
5023 return isl_stat_ok;
5026 /* Approximate each quasipolynomial by a polynomial. If "sign" is positive,
5027 * the polynomial will be an overapproximation. If "sign" is negative,
5028 * it will be an underapproximation. If "sign" is zero, the approximation
5029 * will lie somewhere in between.
5031 * In particular, is sign == 0, we simply drop the floors, turning
5032 * the integer divisions into rational divisions.
5033 * Otherwise, we split the domains into orthants, make all integer divisions
5034 * positive and then approximate each [a/m] by either a/m or (a-(m-1))/m,
5035 * depending on the requested sign and the sign of the term in which
5036 * the integer division appears.
5038 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_to_polynomial(
5039 __isl_take isl_pw_qpolynomial *pwqp, int sign)
5041 int i;
5042 struct isl_to_poly_data data;
5044 if (sign == 0)
5045 return pwqp_drop_floors(pwqp);
5047 if (!pwqp)
5048 return NULL;
5050 data.sign = sign;
5051 data.res = isl_pw_qpolynomial_zero(isl_pw_qpolynomial_get_space(pwqp));
5053 for (i = 0; i < pwqp->n; ++i) {
5054 if (pwqp->p[i].qp->div->n_row == 0) {
5055 isl_pw_qpolynomial *t;
5056 t = isl_pw_qpolynomial_alloc(
5057 isl_set_copy(pwqp->p[i].set),
5058 isl_qpolynomial_copy(pwqp->p[i].qp));
5059 data.res = isl_pw_qpolynomial_add_disjoint(data.res, t);
5060 continue;
5062 data.qp = pwqp->p[i].qp;
5063 if (isl_set_foreach_orthant(pwqp->p[i].set,
5064 &to_polynomial_on_orthant, &data) < 0)
5065 goto error;
5068 isl_pw_qpolynomial_free(pwqp);
5070 return data.res;
5071 error:
5072 isl_pw_qpolynomial_free(pwqp);
5073 isl_pw_qpolynomial_free(data.res);
5074 return NULL;
5077 static __isl_give isl_pw_qpolynomial *poly_entry(
5078 __isl_take isl_pw_qpolynomial *pwqp, void *user)
5080 int *sign = user;
5082 return isl_pw_qpolynomial_to_polynomial(pwqp, *sign);
5085 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_to_polynomial(
5086 __isl_take isl_union_pw_qpolynomial *upwqp, int sign)
5088 return isl_union_pw_qpolynomial_transform_inplace(upwqp,
5089 &poly_entry, &sign);
5092 __isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
5093 __isl_take isl_qpolynomial *qp)
5095 int i, k;
5096 isl_space *dim;
5097 isl_vec *aff = NULL;
5098 isl_basic_map *bmap = NULL;
5099 isl_bool is_affine;
5100 unsigned pos;
5101 unsigned n_div;
5103 if (!qp)
5104 return NULL;
5105 is_affine = isl_poly_is_affine(qp->poly);
5106 if (is_affine < 0)
5107 goto error;
5108 if (!is_affine)
5109 isl_die(qp->dim->ctx, isl_error_invalid,
5110 "input quasi-polynomial not affine", goto error);
5111 aff = isl_qpolynomial_extract_affine(qp);
5112 if (!aff)
5113 goto error;
5114 dim = isl_qpolynomial_get_space(qp);
5115 pos = 1 + isl_space_offset(dim, isl_dim_out);
5116 n_div = qp->div->n_row;
5117 bmap = isl_basic_map_alloc_space(dim, n_div, 1, 2 * n_div);
5119 for (i = 0; i < n_div; ++i) {
5120 k = isl_basic_map_alloc_div(bmap);
5121 if (k < 0)
5122 goto error;
5123 isl_seq_cpy(bmap->div[k], qp->div->row[i], qp->div->n_col);
5124 isl_int_set_si(bmap->div[k][qp->div->n_col], 0);
5125 bmap = isl_basic_map_add_div_constraints(bmap, k);
5127 k = isl_basic_map_alloc_equality(bmap);
5128 if (k < 0)
5129 goto error;
5130 isl_int_neg(bmap->eq[k][pos], aff->el[0]);
5131 isl_seq_cpy(bmap->eq[k], aff->el + 1, pos);
5132 isl_seq_cpy(bmap->eq[k] + pos + 1, aff->el + 1 + pos, n_div);
5134 isl_vec_free(aff);
5135 isl_qpolynomial_free(qp);
5136 bmap = isl_basic_map_finalize(bmap);
5137 return bmap;
5138 error:
5139 isl_vec_free(aff);
5140 isl_qpolynomial_free(qp);
5141 isl_basic_map_free(bmap);
5142 return NULL;