isl_qpolynomial_add: replace 0-degree polynomials by their constant terms
[isl.git] / isl_polynomial.c
blobe0f5adbe1d3bb1aacd5f0c6e113edd7c50ea61d2
1 #include <isl_seq.h>
2 #include <isl_polynomial_private.h>
3 #include <isl_point_private.h>
4 #include <isl_dim_private.h>
5 #include <isl_map_private.h>
7 int isl_upoly_is_cst(__isl_keep struct isl_upoly *up)
9 if (!up)
10 return -1;
12 return up->var < 0;
15 __isl_keep struct isl_upoly_cst *isl_upoly_as_cst(__isl_keep struct isl_upoly *up)
17 if (!up)
18 return NULL;
20 isl_assert(up->ctx, up->var < 0, return NULL);
22 return (struct isl_upoly_cst *)up;
25 __isl_keep struct isl_upoly_rec *isl_upoly_as_rec(__isl_keep struct isl_upoly *up)
27 if (!up)
28 return NULL;
30 isl_assert(up->ctx, up->var >= 0, return NULL);
32 return (struct isl_upoly_rec *)up;
35 int isl_upoly_is_zero(__isl_keep struct isl_upoly *up)
37 struct isl_upoly_cst *cst;
39 if (!up)
40 return -1;
41 if (!isl_upoly_is_cst(up))
42 return 0;
44 cst = isl_upoly_as_cst(up);
45 if (!cst)
46 return -1;
48 return isl_int_is_zero(cst->n) && isl_int_is_pos(cst->d);
51 int isl_upoly_is_nan(__isl_keep struct isl_upoly *up)
53 struct isl_upoly_cst *cst;
55 if (!up)
56 return -1;
57 if (!isl_upoly_is_cst(up))
58 return 0;
60 cst = isl_upoly_as_cst(up);
61 if (!cst)
62 return -1;
64 return isl_int_is_zero(cst->n) && isl_int_is_zero(cst->d);
67 int isl_upoly_is_infty(__isl_keep struct isl_upoly *up)
69 struct isl_upoly_cst *cst;
71 if (!up)
72 return -1;
73 if (!isl_upoly_is_cst(up))
74 return 0;
76 cst = isl_upoly_as_cst(up);
77 if (!cst)
78 return -1;
80 return isl_int_is_pos(cst->n) && isl_int_is_zero(cst->d);
83 int isl_upoly_is_neginfty(__isl_keep struct isl_upoly *up)
85 struct isl_upoly_cst *cst;
87 if (!up)
88 return -1;
89 if (!isl_upoly_is_cst(up))
90 return 0;
92 cst = isl_upoly_as_cst(up);
93 if (!cst)
94 return -1;
96 return isl_int_is_neg(cst->n) && isl_int_is_zero(cst->d);
99 int isl_upoly_is_one(__isl_keep struct isl_upoly *up)
101 struct isl_upoly_cst *cst;
103 if (!up)
104 return -1;
105 if (!isl_upoly_is_cst(up))
106 return 0;
108 cst = isl_upoly_as_cst(up);
109 if (!cst)
110 return -1;
112 return isl_int_eq(cst->n, cst->d) && isl_int_is_pos(cst->d);
115 int isl_upoly_is_negone(__isl_keep struct isl_upoly *up)
117 struct isl_upoly_cst *cst;
119 if (!up)
120 return -1;
121 if (!isl_upoly_is_cst(up))
122 return 0;
124 cst = isl_upoly_as_cst(up);
125 if (!cst)
126 return -1;
128 return isl_int_is_negone(cst->n) && isl_int_is_one(cst->d);
131 __isl_give struct isl_upoly_cst *isl_upoly_cst_alloc(struct isl_ctx *ctx)
133 struct isl_upoly_cst *cst;
135 cst = isl_alloc_type(ctx, struct isl_upoly_cst);
136 if (!cst)
137 return NULL;
139 cst->up.ref = 1;
140 cst->up.ctx = ctx;
141 isl_ctx_ref(ctx);
142 cst->up.var = -1;
144 isl_int_init(cst->n);
145 isl_int_init(cst->d);
147 return cst;
150 __isl_give struct isl_upoly *isl_upoly_zero(struct isl_ctx *ctx)
152 struct isl_upoly_cst *cst;
154 cst = isl_upoly_cst_alloc(ctx);
155 if (!cst)
156 return NULL;
158 isl_int_set_si(cst->n, 0);
159 isl_int_set_si(cst->d, 1);
161 return &cst->up;
164 __isl_give struct isl_upoly *isl_upoly_infty(struct isl_ctx *ctx)
166 struct isl_upoly_cst *cst;
168 cst = isl_upoly_cst_alloc(ctx);
169 if (!cst)
170 return NULL;
172 isl_int_set_si(cst->n, 1);
173 isl_int_set_si(cst->d, 0);
175 return &cst->up;
178 __isl_give struct isl_upoly *isl_upoly_nan(struct isl_ctx *ctx)
180 struct isl_upoly_cst *cst;
182 cst = isl_upoly_cst_alloc(ctx);
183 if (!cst)
184 return NULL;
186 isl_int_set_si(cst->n, 0);
187 isl_int_set_si(cst->d, 0);
189 return &cst->up;
192 __isl_give struct isl_upoly *isl_upoly_rat_cst(struct isl_ctx *ctx,
193 isl_int n, isl_int d)
195 struct isl_upoly_cst *cst;
197 cst = isl_upoly_cst_alloc(ctx);
198 if (!cst)
199 return NULL;
201 isl_int_set(cst->n, n);
202 isl_int_set(cst->d, d);
204 return &cst->up;
207 __isl_give struct isl_upoly_rec *isl_upoly_alloc_rec(struct isl_ctx *ctx,
208 int var, int size)
210 struct isl_upoly_rec *rec;
212 isl_assert(ctx, var >= 0, return NULL);
213 isl_assert(ctx, size >= 0, return NULL);
214 rec = isl_calloc(dim->ctx, struct isl_upoly_rec,
215 sizeof(struct isl_upoly_rec) +
216 (size - 1) * sizeof(struct isl_upoly *));
217 if (!rec)
218 return NULL;
220 rec->up.ref = 1;
221 rec->up.ctx = ctx;
222 isl_ctx_ref(ctx);
223 rec->up.var = var;
225 rec->n = 0;
226 rec->size = size;
228 return rec;
229 error:
230 isl_upoly_free(&rec->up);
231 return NULL;
234 int isl_qpolynomial_is_zero(__isl_keep isl_qpolynomial *qp)
236 struct isl_upoly_cst *cst;
238 if (!qp)
239 return -1;
241 return isl_upoly_is_zero(qp->upoly);
244 int isl_qpolynomial_is_one(__isl_keep isl_qpolynomial *qp)
246 struct isl_upoly_cst *cst;
248 if (!qp)
249 return -1;
251 return isl_upoly_is_one(qp->upoly);
254 static void upoly_free_cst(__isl_take struct isl_upoly_cst *cst)
256 isl_int_clear(cst->n);
257 isl_int_clear(cst->d);
260 static void upoly_free_rec(__isl_take struct isl_upoly_rec *rec)
262 int i;
264 for (i = 0; i < rec->n; ++i)
265 isl_upoly_free(rec->p[i]);
268 __isl_give struct isl_upoly *isl_upoly_copy(__isl_keep struct isl_upoly *up)
270 if (!up)
271 return NULL;
273 up->ref++;
274 return up;
277 __isl_give struct isl_upoly *isl_upoly_dup_cst(__isl_keep struct isl_upoly *up)
279 struct isl_upoly_cst *cst;
280 struct isl_upoly_cst *dup;
282 cst = isl_upoly_as_cst(up);
283 if (!cst)
284 return NULL;
286 dup = isl_upoly_as_cst(isl_upoly_zero(up->ctx));
287 if (!dup)
288 return NULL;
289 isl_int_set(dup->n, cst->n);
290 isl_int_set(dup->d, cst->d);
292 return &dup->up;
295 __isl_give struct isl_upoly *isl_upoly_dup_rec(__isl_keep struct isl_upoly *up)
297 int i;
298 struct isl_upoly_rec *rec;
299 struct isl_upoly_rec *dup;
301 rec = isl_upoly_as_rec(up);
302 if (!rec)
303 return NULL;
305 dup = isl_upoly_alloc_rec(up->ctx, up->var, rec->n);
306 if (!dup)
307 return NULL;
309 for (i = 0; i < rec->n; ++i) {
310 dup->p[i] = isl_upoly_copy(rec->p[i]);
311 if (!dup->p[i])
312 goto error;
313 dup->n++;
316 return &dup->up;
317 error:
318 isl_upoly_free(&dup->up);
319 return NULL;
322 __isl_give struct isl_upoly *isl_upoly_dup(__isl_keep struct isl_upoly *up)
324 struct isl_upoly *dup;
326 if (!up)
327 return NULL;
329 if (isl_upoly_is_cst(up))
330 return isl_upoly_dup_cst(up);
331 else
332 return isl_upoly_dup_rec(up);
335 __isl_give struct isl_upoly *isl_upoly_cow(__isl_take struct isl_upoly *up)
337 if (!up)
338 return NULL;
340 if (up->ref == 1)
341 return up;
342 up->ref--;
343 return isl_upoly_dup(up);
346 void isl_upoly_free(__isl_take struct isl_upoly *up)
348 if (!up)
349 return;
351 if (--up->ref > 0)
352 return;
354 if (up->var < 0)
355 upoly_free_cst((struct isl_upoly_cst *)up);
356 else
357 upoly_free_rec((struct isl_upoly_rec *)up);
359 isl_ctx_deref(up->ctx);
360 free(up);
363 static void isl_upoly_cst_reduce(__isl_keep struct isl_upoly_cst *cst)
365 isl_int gcd;
367 isl_int_init(gcd);
368 isl_int_gcd(gcd, cst->n, cst->d);
369 if (!isl_int_is_zero(gcd) && !isl_int_is_one(gcd)) {
370 isl_int_divexact(cst->n, cst->n, gcd);
371 isl_int_divexact(cst->d, cst->d, gcd);
373 isl_int_clear(gcd);
376 __isl_give struct isl_upoly *isl_upoly_sum_cst(__isl_take struct isl_upoly *up1,
377 __isl_take struct isl_upoly *up2)
379 struct isl_upoly_cst *cst1;
380 struct isl_upoly_cst *cst2;
382 up1 = isl_upoly_cow(up1);
383 if (!up1 || !up2)
384 goto error;
386 cst1 = isl_upoly_as_cst(up1);
387 cst2 = isl_upoly_as_cst(up2);
389 if (isl_int_eq(cst1->d, cst2->d))
390 isl_int_add(cst1->n, cst1->n, cst2->n);
391 else {
392 isl_int_mul(cst1->n, cst1->n, cst2->d);
393 isl_int_addmul(cst1->n, cst2->n, cst1->d);
394 isl_int_mul(cst1->d, cst1->d, cst2->d);
397 isl_upoly_cst_reduce(cst1);
399 isl_upoly_free(up2);
400 return up1;
401 error:
402 isl_upoly_free(up1);
403 isl_upoly_free(up2);
404 return NULL;
407 static __isl_give struct isl_upoly *replace_by_zero(
408 __isl_take struct isl_upoly *up)
410 struct isl_ctx *ctx;
412 if (!up)
413 return NULL;
414 ctx = up->ctx;
415 isl_upoly_free(up);
416 return isl_upoly_zero(ctx);
419 static __isl_give struct isl_upoly *replace_by_constant_term(
420 __isl_take struct isl_upoly *up)
422 struct isl_upoly_rec *rec;
423 struct isl_upoly *cst;
425 if (!up)
426 return NULL;
428 rec = isl_upoly_as_rec(up);
429 if (!rec)
430 goto error;
431 isl_assert(up->ctx, rec->n == 1, goto error);
432 cst = isl_upoly_copy(rec->p[0]);
433 isl_upoly_free(up);
434 return cst;
435 error:
436 isl_upoly_free(up);
437 return NULL;
440 __isl_give struct isl_upoly *isl_upoly_sum(__isl_take struct isl_upoly *up1,
441 __isl_take struct isl_upoly *up2)
443 int i;
444 struct isl_upoly_rec *rec1, *rec2;
446 if (!up1 || !up2)
447 goto error;
449 if (isl_upoly_is_nan(up1)) {
450 isl_upoly_free(up2);
451 return up1;
454 if (isl_upoly_is_nan(up2)) {
455 isl_upoly_free(up1);
456 return up2;
459 if (isl_upoly_is_zero(up1)) {
460 isl_upoly_free(up1);
461 return up2;
464 if (isl_upoly_is_zero(up2)) {
465 isl_upoly_free(up2);
466 return up1;
469 if (up1->var < up2->var)
470 return isl_upoly_sum(up2, up1);
472 if (up2->var < up1->var) {
473 struct isl_upoly_rec *rec;
474 if (isl_upoly_is_infty(up2) || isl_upoly_is_neginfty(up2)) {
475 isl_upoly_free(up1);
476 return up2;
478 up1 = isl_upoly_cow(up1);
479 rec = isl_upoly_as_rec(up1);
480 if (!rec)
481 goto error;
482 rec->p[0] = isl_upoly_sum(rec->p[0], up2);
483 if (rec->n == 1)
484 up1 = replace_by_constant_term(up1);
485 return up1;
488 if (isl_upoly_is_cst(up1))
489 return isl_upoly_sum_cst(up1, up2);
491 rec1 = isl_upoly_as_rec(up1);
492 rec2 = isl_upoly_as_rec(up2);
493 if (!rec1 || !rec2)
494 goto error;
496 if (rec1->n < rec2->n)
497 return isl_upoly_sum(up2, up1);
499 up1 = isl_upoly_cow(up1);
500 rec1 = isl_upoly_as_rec(up1);
501 if (!rec1)
502 goto error;
504 for (i = rec2->n - 1; i >= 0; --i) {
505 rec1->p[i] = isl_upoly_sum(rec1->p[i],
506 isl_upoly_copy(rec2->p[i]));
507 if (!rec1->p[i])
508 goto error;
509 if (i == rec1->n - 1 && isl_upoly_is_zero(rec1->p[i])) {
510 isl_upoly_free(rec1->p[i]);
511 rec1->n--;
515 if (rec1->n == 0)
516 up1 = replace_by_zero(up1);
517 else if (rec1->n == 1)
518 up1 = replace_by_constant_term(up1);
520 isl_upoly_free(up2);
522 return up1;
523 error:
524 isl_upoly_free(up1);
525 isl_upoly_free(up2);
526 return NULL;
529 __isl_give struct isl_upoly *isl_upoly_neg_cst(__isl_take struct isl_upoly *up)
531 struct isl_upoly_cst *cst;
533 if (isl_upoly_is_zero(up))
534 return up;
536 up = isl_upoly_cow(up);
537 if (!up)
538 return NULL;
540 cst = isl_upoly_as_cst(up);
542 isl_int_neg(cst->n, cst->n);
544 return up;
547 __isl_give struct isl_upoly *isl_upoly_neg(__isl_take struct isl_upoly *up)
549 int i;
550 struct isl_upoly_rec *rec;
552 if (!up)
553 return NULL;
555 if (isl_upoly_is_cst(up))
556 return isl_upoly_neg_cst(up);
558 up = isl_upoly_cow(up);
559 rec = isl_upoly_as_rec(up);
560 if (!rec)
561 goto error;
563 for (i = 0; i < rec->n; ++i) {
564 rec->p[i] = isl_upoly_neg(rec->p[i]);
565 if (!rec->p[i])
566 goto error;
569 return up;
570 error:
571 isl_upoly_free(up);
572 return NULL;
575 __isl_give struct isl_upoly *isl_upoly_mul_cst(__isl_take struct isl_upoly *up1,
576 __isl_take struct isl_upoly *up2)
578 struct isl_upoly_cst *cst1;
579 struct isl_upoly_cst *cst2;
581 up1 = isl_upoly_cow(up1);
582 if (!up1 || !up2)
583 goto error;
585 cst1 = isl_upoly_as_cst(up1);
586 cst2 = isl_upoly_as_cst(up2);
588 isl_int_mul(cst1->n, cst1->n, cst2->n);
589 isl_int_mul(cst1->d, cst1->d, cst2->d);
591 isl_upoly_cst_reduce(cst1);
593 isl_upoly_free(up2);
594 return up1;
595 error:
596 isl_upoly_free(up1);
597 isl_upoly_free(up2);
598 return NULL;
601 __isl_give struct isl_upoly *isl_upoly_mul_rec(__isl_take struct isl_upoly *up1,
602 __isl_take struct isl_upoly *up2)
604 struct isl_upoly_rec *rec1;
605 struct isl_upoly_rec *rec2;
606 struct isl_upoly_rec *res;
607 int i, j;
608 int size;
610 rec1 = isl_upoly_as_rec(up1);
611 rec2 = isl_upoly_as_rec(up2);
612 if (!rec1 || !rec2)
613 goto error;
614 size = rec1->n + rec2->n - 1;
615 res = isl_upoly_alloc_rec(up1->ctx, up1->var, size);
616 if (!res)
617 goto error;
619 for (i = 0; i < rec1->n; ++i) {
620 res->p[i] = isl_upoly_mul(isl_upoly_copy(rec2->p[0]),
621 isl_upoly_copy(rec1->p[i]));
622 if (!res->p[i])
623 goto error;
624 res->n++;
626 for (; i < size; ++i) {
627 res->p[i] = isl_upoly_zero(up1->ctx);
628 if (!res->p[i])
629 goto error;
630 res->n++;
632 for (i = 0; i < rec1->n; ++i) {
633 for (j = 1; j < rec2->n; ++j) {
634 struct isl_upoly *up;
635 up = isl_upoly_mul(isl_upoly_copy(rec2->p[j]),
636 isl_upoly_copy(rec1->p[i]));
637 res->p[i + j] = isl_upoly_sum(res->p[i + j], up);
638 if (!res->p[i + j])
639 goto error;
643 isl_upoly_free(up1);
644 isl_upoly_free(up2);
646 return &res->up;
647 error:
648 isl_upoly_free(up1);
649 isl_upoly_free(up2);
650 isl_upoly_free(&res->up);
651 return NULL;
654 __isl_give struct isl_upoly *isl_upoly_mul(__isl_take struct isl_upoly *up1,
655 __isl_take struct isl_upoly *up2)
657 if (!up1 || !up2)
658 goto error;
660 if (isl_upoly_is_nan(up1)) {
661 isl_upoly_free(up2);
662 return up1;
665 if (isl_upoly_is_nan(up2)) {
666 isl_upoly_free(up1);
667 return up2;
670 if (isl_upoly_is_zero(up1)) {
671 isl_upoly_free(up2);
672 return up1;
675 if (isl_upoly_is_zero(up2)) {
676 isl_upoly_free(up1);
677 return up2;
680 if (isl_upoly_is_one(up1)) {
681 isl_upoly_free(up1);
682 return up2;
685 if (isl_upoly_is_one(up2)) {
686 isl_upoly_free(up2);
687 return up1;
690 if (up1->var < up2->var)
691 return isl_upoly_mul(up2, up1);
693 if (up2->var < up1->var) {
694 int i;
695 struct isl_upoly_rec *rec;
696 if (isl_upoly_is_infty(up2) || isl_upoly_is_neginfty(up2)) {
697 isl_ctx *ctx = up1->ctx;
698 isl_upoly_free(up1);
699 isl_upoly_free(up2);
700 return isl_upoly_nan(ctx);
702 up1 = isl_upoly_cow(up1);
703 rec = isl_upoly_as_rec(up1);
704 if (!rec)
705 goto error;
707 for (i = 0; i < rec->n; ++i) {
708 rec->p[i] = isl_upoly_mul(rec->p[i],
709 isl_upoly_copy(up2));
710 if (!rec->p[i])
711 goto error;
713 isl_upoly_free(up2);
714 return up1;
717 if (isl_upoly_is_cst(up1))
718 return isl_upoly_mul_cst(up1, up2);
720 return isl_upoly_mul_rec(up1, up2);
721 error:
722 isl_upoly_free(up1);
723 isl_upoly_free(up2);
724 return NULL;
727 __isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_dim *dim,
728 unsigned n_div)
730 struct isl_qpolynomial *qp;
731 unsigned total;
733 if (!dim)
734 return NULL;
736 total = isl_dim_total(dim);
738 qp = isl_calloc_type(dim->ctx, struct isl_qpolynomial);
739 if (!qp)
740 return NULL;
742 qp->ref = 1;
743 qp->div = isl_mat_alloc(dim->ctx, n_div, 1 + 1 + total + n_div);
744 if (!qp->div)
745 goto error;
747 qp->dim = dim;
749 return qp;
750 error:
751 isl_dim_free(dim);
752 isl_qpolynomial_free(qp);
753 return NULL;
756 __isl_give isl_qpolynomial *isl_qpolynomial_copy(__isl_keep isl_qpolynomial *qp)
758 if (!qp)
759 return NULL;
761 qp->ref++;
762 return qp;
765 __isl_give isl_qpolynomial *isl_qpolynomial_dup(__isl_keep isl_qpolynomial *qp)
767 struct isl_qpolynomial *dup;
769 if (!qp)
770 return NULL;
772 dup = isl_qpolynomial_alloc(isl_dim_copy(qp->dim), qp->div->n_row);
773 if (!dup)
774 return NULL;
775 isl_mat_free(dup->div);
776 dup->div = isl_mat_copy(qp->div);
777 if (!dup->div)
778 goto error;
779 dup->upoly = isl_upoly_copy(qp->upoly);
780 if (!dup->upoly)
781 goto error;
783 return dup;
784 error:
785 isl_qpolynomial_free(dup);
786 return NULL;
789 __isl_give isl_qpolynomial *isl_qpolynomial_cow(__isl_take isl_qpolynomial *qp)
791 if (!qp)
792 return NULL;
794 if (qp->ref == 1)
795 return qp;
796 qp->ref--;
797 return isl_qpolynomial_dup(qp);
800 void isl_qpolynomial_free(__isl_take isl_qpolynomial *qp)
802 if (!qp)
803 return;
805 if (--qp->ref > 0)
806 return;
808 isl_dim_free(qp->dim);
809 isl_mat_free(qp->div);
810 isl_upoly_free(qp->upoly);
812 free(qp);
815 static int compatible_divs(__isl_keep isl_mat *div1, __isl_keep isl_mat *div2)
817 int n_row, n_col;
818 int equal;
820 isl_assert(div1->ctx, div1->n_row >= div2->n_row &&
821 div1->n_col >= div2->n_col, return -1);
823 if (div1->n_row == div2->n_row)
824 return isl_mat_is_equal(div1, div2);
826 n_row = div1->n_row;
827 n_col = div1->n_col;
828 div1->n_row = div2->n_row;
829 div1->n_col = div2->n_col;
831 equal = isl_mat_is_equal(div1, div2);
833 div1->n_row = n_row;
834 div1->n_col = n_col;
836 return equal;
839 static void expand_row(__isl_keep isl_mat *dst, int d,
840 __isl_keep isl_mat *src, int s, int *exp)
842 int i;
843 unsigned c = src->n_col - src->n_row;
845 isl_seq_cpy(dst->row[d], src->row[s], c);
846 isl_seq_clr(dst->row[d] + c, dst->n_col - c);
848 for (i = 0; i < s; ++i)
849 isl_int_set(dst->row[d][c + exp[i]], src->row[s][c + i]);
852 static int cmp_row(__isl_keep isl_mat *div, int i, int j)
854 int li, lj;
856 li = isl_seq_last_non_zero(div->row[i], div->n_col);
857 lj = isl_seq_last_non_zero(div->row[j], div->n_col);
859 if (li != lj)
860 return li - lj;
862 return isl_seq_cmp(div->row[i], div->row[j], div->n_col);
865 static __isl_give isl_mat *merge_divs(__isl_keep isl_mat *div1,
866 __isl_keep isl_mat *div2, int *exp1, int *exp2)
868 int i, j, k;
869 isl_mat *div = NULL;
870 unsigned d = div1->n_col - div1->n_row;
872 div = isl_mat_alloc(div1->ctx, 1 + div1->n_row + div2->n_row,
873 d + div1->n_row + div2->n_row);
874 if (!div)
875 return NULL;
877 for (i = 0, j = 0, k = 0; i < div1->n_row && j < div2->n_row; ++k) {
878 int cmp;
880 expand_row(div, k, div1, i, exp1);
881 expand_row(div, k + 1, div2, j, exp2);
883 cmp = cmp_row(div, k, k + 1);
884 if (cmp == 0) {
885 exp1[i++] = k;
886 exp2[j++] = k;
887 } else if (cmp < 0) {
888 exp1[i++] = k;
889 } else {
890 exp2[j++] = k;
891 isl_seq_cpy(div->row[k], div->row[k + 1], div->n_col);
894 for (; i < div1->n_row; ++i, ++k) {
895 expand_row(div, k, div1, i, exp1);
896 exp1[i] = k;
898 for (; j < div2->n_row; ++j, ++k) {
899 expand_row(div, k, div2, j, exp2);
900 exp2[j] = k;
903 div->n_row = k;
904 div->n_col = d + k;
906 return div;
909 static __isl_give struct isl_upoly *expand(__isl_take struct isl_upoly *up,
910 int *exp, int first)
912 int i;
913 struct isl_upoly_rec *rec;
915 if (isl_upoly_is_cst(up))
916 return up;
918 if (up->var < first)
919 return up;
921 if (exp[up->var - first] == up->var - first)
922 return up;
924 up = isl_upoly_cow(up);
925 if (!up)
926 goto error;
928 up->var = exp[up->var - first] + first;
930 rec = isl_upoly_as_rec(up);
931 if (!rec)
932 goto error;
934 for (i = 0; i < rec->n; ++i) {
935 rec->p[i] = expand(rec->p[i], exp, first);
936 if (!rec->p[i])
937 goto error;
940 return up;
941 error:
942 isl_upoly_free(up);
943 return NULL;
946 static __isl_give isl_qpolynomial *with_merged_divs(
947 __isl_give isl_qpolynomial *(*fn)(__isl_take isl_qpolynomial *qp1,
948 __isl_take isl_qpolynomial *qp2),
949 __isl_take isl_qpolynomial *qp1, __isl_take isl_qpolynomial *qp2)
951 int *exp1 = NULL;
952 int *exp2 = NULL;
953 isl_mat *div = NULL;
955 qp1 = isl_qpolynomial_cow(qp1);
956 qp2 = isl_qpolynomial_cow(qp2);
958 if (!qp1 || !qp2)
959 goto error;
961 isl_assert(qp1->div->ctx, qp1->div->n_row >= qp2->div->n_row &&
962 qp1->div->n_col >= qp2->div->n_col, goto error);
964 exp1 = isl_alloc_array(qp1->div->ctx, int, qp1->div->n_row);
965 exp2 = isl_alloc_array(qp2->div->ctx, int, qp2->div->n_row);
966 if (!exp1 || !exp2)
967 goto error;
969 div = merge_divs(qp1->div, qp2->div, exp1, exp2);
970 if (!div)
971 goto error;
973 isl_mat_free(qp1->div);
974 qp1->div = isl_mat_copy(div);
975 isl_mat_free(qp2->div);
976 qp2->div = isl_mat_copy(div);
978 qp1->upoly = expand(qp1->upoly, exp1, div->n_col - div->n_row - 2);
979 qp2->upoly = expand(qp2->upoly, exp2, div->n_col - div->n_row - 2);
981 if (!qp1->upoly || !qp2->upoly)
982 goto error;
984 isl_mat_free(div);
985 free(exp1);
986 free(exp2);
988 return fn(qp1, qp2);
989 error:
990 isl_mat_free(div);
991 free(exp1);
992 free(exp2);
993 isl_qpolynomial_free(qp1);
994 isl_qpolynomial_free(qp2);
995 return NULL;
998 __isl_give isl_qpolynomial *isl_qpolynomial_add(__isl_take isl_qpolynomial *qp1,
999 __isl_take isl_qpolynomial *qp2)
1001 qp1 = isl_qpolynomial_cow(qp1);
1003 if (!qp1 || !qp2)
1004 goto error;
1006 if (qp1->div->n_row < qp2->div->n_row)
1007 return isl_qpolynomial_add(qp2, qp1);
1009 isl_assert(qp1->dim->ctx, isl_dim_equal(qp1->dim, qp2->dim), goto error);
1010 if (!compatible_divs(qp1->div, qp2->div))
1011 return with_merged_divs(isl_qpolynomial_add, qp1, qp2);
1013 qp1->upoly = isl_upoly_sum(qp1->upoly, isl_upoly_copy(qp2->upoly));
1014 if (!qp1->upoly)
1015 goto error;
1017 isl_qpolynomial_free(qp2);
1019 return qp1;
1020 error:
1021 isl_qpolynomial_free(qp1);
1022 isl_qpolynomial_free(qp2);
1023 return NULL;
1026 __isl_give isl_qpolynomial *isl_qpolynomial_sub(__isl_take isl_qpolynomial *qp1,
1027 __isl_take isl_qpolynomial *qp2)
1029 return isl_qpolynomial_add(qp1, isl_qpolynomial_neg(qp2));
1032 __isl_give isl_qpolynomial *isl_qpolynomial_neg(__isl_take isl_qpolynomial *qp)
1034 qp = isl_qpolynomial_cow(qp);
1036 if (!qp)
1037 return NULL;
1039 qp->upoly = isl_upoly_neg(qp->upoly);
1040 if (!qp->upoly)
1041 goto error;
1043 return qp;
1044 error:
1045 isl_qpolynomial_free(qp);
1046 return NULL;
1049 __isl_give isl_qpolynomial *isl_qpolynomial_mul(__isl_take isl_qpolynomial *qp1,
1050 __isl_take isl_qpolynomial *qp2)
1052 qp1 = isl_qpolynomial_cow(qp1);
1054 if (!qp1 || !qp2)
1055 goto error;
1057 if (qp1->div->n_row < qp2->div->n_row)
1058 return isl_qpolynomial_mul(qp2, qp1);
1060 isl_assert(qp1->dim->ctx, isl_dim_equal(qp1->dim, qp2->dim), goto error);
1061 if (!compatible_divs(qp1->div, qp2->div))
1062 return with_merged_divs(isl_qpolynomial_mul, qp1, qp2);
1064 qp1->upoly = isl_upoly_mul(qp1->upoly, isl_upoly_copy(qp2->upoly));
1065 if (!qp1->upoly)
1066 goto error;
1068 isl_qpolynomial_free(qp2);
1070 return qp1;
1071 error:
1072 isl_qpolynomial_free(qp1);
1073 isl_qpolynomial_free(qp2);
1074 return NULL;
1077 __isl_give isl_qpolynomial *isl_qpolynomial_zero(__isl_take isl_dim *dim)
1079 struct isl_qpolynomial *qp;
1080 struct isl_upoly_cst *cst;
1082 qp = isl_qpolynomial_alloc(dim, 0);
1083 if (!qp)
1084 return NULL;
1086 qp->upoly = isl_upoly_zero(dim->ctx);
1087 if (!qp->upoly)
1088 goto error;
1090 return qp;
1091 error:
1092 isl_qpolynomial_free(qp);
1093 return NULL;
1096 __isl_give isl_qpolynomial *isl_qpolynomial_infty(__isl_take isl_dim *dim)
1098 struct isl_qpolynomial *qp;
1099 struct isl_upoly_cst *cst;
1101 qp = isl_qpolynomial_alloc(dim, 0);
1102 if (!qp)
1103 return NULL;
1105 qp->upoly = isl_upoly_infty(dim->ctx);
1106 if (!qp->upoly)
1107 goto error;
1109 return qp;
1110 error:
1111 isl_qpolynomial_free(qp);
1112 return NULL;
1115 __isl_give isl_qpolynomial *isl_qpolynomial_nan(__isl_take isl_dim *dim)
1117 struct isl_qpolynomial *qp;
1118 struct isl_upoly_cst *cst;
1120 qp = isl_qpolynomial_alloc(dim, 0);
1121 if (!qp)
1122 return NULL;
1124 qp->upoly = isl_upoly_nan(dim->ctx);
1125 if (!qp->upoly)
1126 goto error;
1128 return qp;
1129 error:
1130 isl_qpolynomial_free(qp);
1131 return NULL;
1134 __isl_give isl_qpolynomial *isl_qpolynomial_cst(__isl_take isl_dim *dim,
1135 isl_int v)
1137 struct isl_qpolynomial *qp;
1138 struct isl_upoly_cst *cst;
1140 qp = isl_qpolynomial_alloc(dim, 0);
1141 if (!qp)
1142 return NULL;
1144 qp->upoly = isl_upoly_zero(dim->ctx);
1145 if (!qp->upoly)
1146 goto error;
1147 cst = isl_upoly_as_cst(qp->upoly);
1148 isl_int_set(cst->n, v);
1150 return qp;
1151 error:
1152 isl_qpolynomial_free(qp);
1153 return NULL;
1156 int isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
1157 isl_int *n, isl_int *d)
1159 struct isl_upoly_cst *cst;
1161 if (!qp)
1162 return -1;
1164 if (!isl_upoly_is_cst(qp->upoly))
1165 return 0;
1167 cst = isl_upoly_as_cst(qp->upoly);
1168 if (!cst)
1169 return -1;
1171 if (n)
1172 isl_int_set(*n, cst->n);
1173 if (d)
1174 isl_int_set(*d, cst->d);
1176 return 1;
1179 __isl_give isl_qpolynomial *isl_qpolynomial_pow(__isl_take isl_dim *dim,
1180 int pos, int power)
1182 int i;
1183 struct isl_qpolynomial *qp;
1184 struct isl_upoly_rec *rec;
1185 struct isl_upoly_cst *cst;
1186 struct isl_ctx *ctx;
1188 if (!dim)
1189 return NULL;
1191 ctx = dim->ctx;
1193 qp = isl_qpolynomial_alloc(dim, 0);
1194 if (!qp)
1195 return NULL;
1197 qp->upoly = &isl_upoly_alloc_rec(ctx, pos, 1 + power)->up;
1198 if (!qp->upoly)
1199 goto error;
1200 rec = isl_upoly_as_rec(qp->upoly);
1201 for (i = 0; i < 1 + power; ++i) {
1202 rec->p[i] = isl_upoly_zero(ctx);
1203 if (!rec->p[i])
1204 goto error;
1205 rec->n++;
1207 cst = isl_upoly_as_cst(rec->p[power]);
1208 isl_int_set_si(cst->n, 1);
1210 return qp;
1211 error:
1212 isl_qpolynomial_free(qp);
1213 return NULL;
1216 __isl_give isl_qpolynomial *isl_qpolynomial_var(__isl_take isl_dim *dim,
1217 enum isl_dim_type type, unsigned pos)
1219 if (!dim)
1220 return NULL;
1222 isl_assert(dim->ctx, isl_dim_size(dim, isl_dim_in) == 0, goto error);
1223 isl_assert(dim->ctx, pos < isl_dim_size(dim, type), goto error);
1225 if (type == isl_dim_set)
1226 pos += isl_dim_size(dim, isl_dim_param);
1228 return isl_qpolynomial_pow(dim, pos, 1);
1229 error:
1230 isl_dim_free(dim);
1231 return NULL;
1234 __isl_give isl_qpolynomial *isl_qpolynomial_div_pow(__isl_take isl_div *div,
1235 int power)
1237 struct isl_qpolynomial *qp = NULL;
1238 struct isl_upoly_rec *rec;
1239 struct isl_upoly_cst *cst;
1240 int i;
1241 int pos;
1243 if (!div)
1244 return NULL;
1245 isl_assert(div->ctx, div->bmap->n_div == 1, goto error);
1247 qp = isl_qpolynomial_alloc(isl_basic_map_get_dim(div->bmap), 1);
1248 if (!qp)
1249 goto error;
1251 isl_seq_cpy(qp->div->row[0], div->line[0], qp->div->n_col - 1);
1252 isl_int_set_si(qp->div->row[0][qp->div->n_col - 1], 0);
1254 pos = isl_dim_total(qp->dim);
1255 qp->upoly = &isl_upoly_alloc_rec(div->ctx, pos, 1 + power)->up;
1256 if (!qp->upoly)
1257 goto error;
1258 rec = isl_upoly_as_rec(qp->upoly);
1259 for (i = 0; i < 1 + power; ++i) {
1260 rec->p[i] = isl_upoly_zero(div->ctx);
1261 if (!rec->p[i])
1262 goto error;
1263 rec->n++;
1265 cst = isl_upoly_as_cst(rec->p[power]);
1266 isl_int_set_si(cst->n, 1);
1268 isl_div_free(div);
1270 return qp;
1271 error:
1272 isl_qpolynomial_free(qp);
1273 isl_div_free(div);
1274 return NULL;
1277 __isl_give isl_qpolynomial *isl_qpolynomial_div(__isl_take isl_div *div)
1279 return isl_qpolynomial_div_pow(div, 1);
1282 __isl_give isl_qpolynomial *isl_qpolynomial_rat_cst(__isl_take isl_dim *dim,
1283 const isl_int n, const isl_int d)
1285 struct isl_qpolynomial *qp;
1286 struct isl_upoly_cst *cst;
1288 qp = isl_qpolynomial_alloc(dim, 0);
1289 if (!qp)
1290 return NULL;
1292 qp->upoly = isl_upoly_zero(dim->ctx);
1293 if (!qp->upoly)
1294 goto error;
1295 cst = isl_upoly_as_cst(qp->upoly);
1296 isl_int_set(cst->n, n);
1297 isl_int_set(cst->d, d);
1299 return qp;
1300 error:
1301 isl_qpolynomial_free(qp);
1302 return NULL;
1305 #undef PW
1306 #define PW isl_pw_qpolynomial
1307 #undef EL
1308 #define EL isl_qpolynomial
1309 #undef IS_ZERO
1310 #define IS_ZERO is_zero
1311 #undef FIELD
1312 #define FIELD qp
1313 #undef ADD
1314 #define ADD add
1316 #include <isl_pw_templ.c>
1318 #undef PW
1319 #define PW isl_pw_qpolynomial_fold
1320 #undef EL
1321 #define EL isl_qpolynomial_fold
1322 #undef IS_ZERO
1323 #define IS_ZERO is_empty
1324 #undef FIELD
1325 #define FIELD fold
1326 #undef ADD
1327 #define ADD fold
1329 #include <isl_pw_templ.c>
1331 int isl_pw_qpolynomial_is_one(__isl_keep isl_pw_qpolynomial *pwqp)
1333 if (!pwqp)
1334 return -1;
1336 if (pwqp->n != -1)
1337 return 0;
1339 if (!isl_set_fast_is_universe(pwqp->p[0].set))
1340 return 0;
1342 return isl_qpolynomial_is_one(pwqp->p[0].qp);
1345 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
1346 __isl_take isl_pw_qpolynomial *pwqp1,
1347 __isl_take isl_pw_qpolynomial *pwqp2)
1349 int i, j, n;
1350 struct isl_pw_qpolynomial *res;
1351 isl_set *set;
1353 if (!pwqp1 || !pwqp2)
1354 goto error;
1356 isl_assert(pwqp1->dim->ctx, isl_dim_equal(pwqp1->dim, pwqp2->dim),
1357 goto error);
1359 if (isl_pw_qpolynomial_is_zero(pwqp1)) {
1360 isl_pw_qpolynomial_free(pwqp2);
1361 return pwqp1;
1364 if (isl_pw_qpolynomial_is_zero(pwqp2)) {
1365 isl_pw_qpolynomial_free(pwqp1);
1366 return pwqp2;
1369 if (isl_pw_qpolynomial_is_one(pwqp1)) {
1370 isl_pw_qpolynomial_free(pwqp1);
1371 return pwqp2;
1374 if (isl_pw_qpolynomial_is_one(pwqp2)) {
1375 isl_pw_qpolynomial_free(pwqp2);
1376 return pwqp1;
1379 n = pwqp1->n * pwqp2->n;
1380 res = isl_pw_qpolynomial_alloc_(isl_dim_copy(pwqp1->dim), n);
1382 for (i = 0; i < pwqp1->n; ++i) {
1383 for (j = 0; j < pwqp2->n; ++j) {
1384 struct isl_set *common;
1385 struct isl_qpolynomial *prod;
1386 common = isl_set_intersect(isl_set_copy(pwqp1->p[i].set),
1387 isl_set_copy(pwqp2->p[j].set));
1388 if (isl_set_fast_is_empty(common)) {
1389 isl_set_free(common);
1390 continue;
1393 prod = isl_qpolynomial_mul(
1394 isl_qpolynomial_copy(pwqp1->p[i].qp),
1395 isl_qpolynomial_copy(pwqp2->p[j].qp));
1397 res = isl_pw_qpolynomial_add_piece(res, common, prod);
1401 isl_pw_qpolynomial_free(pwqp1);
1402 isl_pw_qpolynomial_free(pwqp2);
1404 return res;
1405 error:
1406 isl_pw_qpolynomial_free(pwqp1);
1407 isl_pw_qpolynomial_free(pwqp2);
1408 return NULL;
1411 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_neg(
1412 __isl_take isl_pw_qpolynomial *pwqp)
1414 int i, j, n;
1415 struct isl_pw_qpolynomial *res;
1416 isl_set *set;
1418 if (!pwqp)
1419 return NULL;
1421 if (isl_pw_qpolynomial_is_zero(pwqp))
1422 return pwqp;
1424 pwqp = isl_pw_qpolynomial_cow(pwqp);
1426 for (i = 0; i < pwqp->n; ++i) {
1427 pwqp->p[i].qp = isl_qpolynomial_neg(pwqp->p[i].qp);
1428 if (!pwqp->p[i].qp)
1429 goto error;
1432 return pwqp;
1433 error:
1434 isl_pw_qpolynomial_free(pwqp);
1435 return NULL;
1438 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_sub(
1439 __isl_take isl_pw_qpolynomial *pwqp1,
1440 __isl_take isl_pw_qpolynomial *pwqp2)
1442 return isl_pw_qpolynomial_add(pwqp1, isl_pw_qpolynomial_neg(pwqp2));
1445 __isl_give struct isl_upoly *isl_upoly_eval(
1446 __isl_take struct isl_upoly *up, __isl_take isl_vec *vec)
1448 int i;
1449 struct isl_upoly_rec *rec;
1450 struct isl_upoly *res;
1451 struct isl_upoly *base;
1453 if (isl_upoly_is_cst(up)) {
1454 isl_vec_free(vec);
1455 return up;
1458 rec = isl_upoly_as_rec(up);
1459 if (!rec)
1460 goto error;
1462 isl_assert(up->ctx, rec->n >= 1, goto error);
1464 base = isl_upoly_rat_cst(up->ctx, vec->el[1 + up->var], vec->el[0]);
1466 res = isl_upoly_eval(isl_upoly_copy(rec->p[rec->n - 1]),
1467 isl_vec_copy(vec));
1469 for (i = rec->n - 2; i >= 0; --i) {
1470 res = isl_upoly_mul(res, isl_upoly_copy(base));
1471 res = isl_upoly_sum(res,
1472 isl_upoly_eval(isl_upoly_copy(rec->p[i]),
1473 isl_vec_copy(vec)));
1476 isl_upoly_free(base);
1477 isl_upoly_free(up);
1478 isl_vec_free(vec);
1479 return res;
1480 error:
1481 isl_upoly_free(up);
1482 isl_vec_free(vec);
1483 return NULL;
1486 __isl_give isl_qpolynomial *isl_qpolynomial_eval(
1487 __isl_take isl_qpolynomial *qp, __isl_take isl_point *pnt)
1489 isl_vec *ext;
1490 struct isl_upoly *up;
1491 isl_dim *dim;
1493 if (!qp || !pnt)
1494 goto error;
1495 isl_assert(pnt->dim->ctx, isl_dim_equal(pnt->dim, qp->dim), goto error);
1497 if (qp->div->n_row == 0)
1498 ext = isl_vec_copy(pnt->vec);
1499 else {
1500 int i;
1501 unsigned dim = isl_dim_total(qp->dim);
1502 ext = isl_vec_alloc(qp->dim->ctx, 1 + dim + qp->div->n_row);
1503 if (!ext)
1504 goto error;
1506 isl_seq_cpy(ext->el, pnt->vec->el, pnt->vec->size);
1507 for (i = 0; i < qp->div->n_row; ++i) {
1508 isl_seq_inner_product(qp->div->row[i] + 1, ext->el,
1509 1 + dim + i, &ext->el[1+dim+i]);
1510 isl_int_fdiv_q(ext->el[1+dim+i], ext->el[1+dim+i],
1511 qp->div->row[i][0]);
1515 up = isl_upoly_eval(isl_upoly_copy(qp->upoly), ext);
1516 if (!up)
1517 goto error;
1519 dim = isl_dim_copy(qp->dim);
1520 isl_qpolynomial_free(qp);
1521 isl_point_free(pnt);
1523 qp = isl_qpolynomial_alloc(dim, 0);
1524 if (!qp)
1525 isl_upoly_free(up);
1526 else
1527 qp->upoly = up;
1529 return qp;
1530 error:
1531 isl_qpolynomial_free(qp);
1532 isl_point_free(pnt);
1533 return NULL;
1536 int isl_upoly_cmp(__isl_keep struct isl_upoly_cst *cst1,
1537 __isl_keep struct isl_upoly_cst *cst2)
1539 int cmp;
1540 isl_int t;
1541 isl_int_init(t);
1542 isl_int_mul(t, cst1->n, cst2->d);
1543 isl_int_submul(t, cst2->n, cst1->d);
1544 cmp = isl_int_sgn(t);
1545 isl_int_clear(t);
1546 return cmp;
1549 static __isl_give isl_qpolynomial *qpolynomial_min(
1550 __isl_take isl_qpolynomial *qp1, __isl_take isl_qpolynomial *qp2)
1552 struct isl_upoly_cst *cst1, *cst2;
1553 int cmp;
1555 if (!qp1 || !qp2)
1556 goto error;
1557 isl_assert(qp1->dim->ctx, isl_upoly_is_cst(qp1->upoly), goto error);
1558 isl_assert(qp2->dim->ctx, isl_upoly_is_cst(qp2->upoly), goto error);
1559 cst1 = isl_upoly_as_cst(qp1->upoly);
1560 cst2 = isl_upoly_as_cst(qp2->upoly);
1561 cmp = isl_upoly_cmp(cst1, cst2);
1563 if (cmp <= 0) {
1564 isl_qpolynomial_free(qp2);
1565 } else {
1566 isl_qpolynomial_free(qp1);
1567 qp1 = qp2;
1569 return qp1;
1570 error:
1571 isl_qpolynomial_free(qp1);
1572 isl_qpolynomial_free(qp2);
1573 return NULL;
1576 static __isl_give isl_qpolynomial *qpolynomial_max(
1577 __isl_take isl_qpolynomial *qp1, __isl_take isl_qpolynomial *qp2)
1579 struct isl_upoly_cst *cst1, *cst2;
1580 int cmp;
1582 if (!qp1 || !qp2)
1583 goto error;
1584 isl_assert(qp1->dim->ctx, isl_upoly_is_cst(qp1->upoly), goto error);
1585 isl_assert(qp2->dim->ctx, isl_upoly_is_cst(qp2->upoly), goto error);
1586 cst1 = isl_upoly_as_cst(qp1->upoly);
1587 cst2 = isl_upoly_as_cst(qp2->upoly);
1588 cmp = isl_upoly_cmp(cst1, cst2);
1590 if (cmp >= 0) {
1591 isl_qpolynomial_free(qp2);
1592 } else {
1593 isl_qpolynomial_free(qp1);
1594 qp1 = qp2;
1596 return qp1;
1597 error:
1598 isl_qpolynomial_free(qp1);
1599 isl_qpolynomial_free(qp2);
1600 return NULL;
1603 __isl_give isl_qpolynomial *isl_qpolynomial_fold_eval(
1604 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_point *pnt)
1606 isl_qpolynomial *qp;
1608 if (!fold || !pnt)
1609 goto error;
1610 isl_assert(pnt->dim->ctx, isl_dim_equal(pnt->dim, fold->dim), goto error);
1611 isl_assert(pnt->dim->ctx,
1612 fold->type == isl_fold_max || fold->type == isl_fold_min,
1613 goto error);
1615 if (fold->n == 0)
1616 qp = isl_qpolynomial_zero(isl_dim_copy(fold->dim));
1617 else {
1618 int i;
1619 qp = isl_qpolynomial_eval(isl_qpolynomial_copy(fold->qp[0]),
1620 isl_point_copy(pnt));
1621 for (i = 1; i < fold->n; ++i) {
1622 isl_qpolynomial *qp_i;
1623 qp_i = isl_qpolynomial_eval(
1624 isl_qpolynomial_copy(fold->qp[i]),
1625 isl_point_copy(pnt));
1626 if (fold->type == isl_fold_max)
1627 qp = qpolynomial_max(qp, qp_i);
1628 else
1629 qp = qpolynomial_min(qp, qp_i);
1632 isl_qpolynomial_fold_free(fold);
1633 isl_point_free(pnt);
1635 return qp;
1636 error:
1637 isl_qpolynomial_fold_free(fold);
1638 isl_point_free(pnt);
1639 return NULL;
1642 __isl_give isl_qpolynomial *isl_qpolynomial_move(__isl_take isl_qpolynomial *qp,
1643 enum isl_dim_type dst_type, unsigned dst_pos,
1644 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1646 if (!qp)
1647 return NULL;
1649 qp->dim = isl_dim_move(qp->dim, dst_type, dst_pos, src_type, src_pos, n);
1650 if (!qp->dim)
1651 goto error;
1653 /* Do something to polynomials when needed; later */
1655 return qp;
1656 error:
1657 isl_qpolynomial_free(qp);
1658 return NULL;
1661 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_move(
1662 __isl_take isl_pw_qpolynomial *pwqp,
1663 enum isl_dim_type dst_type, unsigned dst_pos,
1664 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1666 int i;
1668 if (!pwqp)
1669 return NULL;
1671 pwqp->dim = isl_dim_move(pwqp->dim,
1672 dst_type, dst_pos, src_type, src_pos, n);
1673 if (!pwqp->dim)
1674 goto error;
1676 for (i = 0; i < pwqp->n; ++i) {
1677 pwqp->p[i].set = isl_set_move(pwqp->p[i].set, dst_type, dst_pos,
1678 src_type, src_pos, n);
1679 if (!pwqp->p[i].set)
1680 goto error;
1681 pwqp->p[i].qp = isl_qpolynomial_move(pwqp->p[i].qp,
1682 dst_type, dst_pos, src_type, src_pos, n);
1683 if (!pwqp->p[i].qp)
1684 goto error;
1687 return pwqp;
1688 error:
1689 isl_pw_qpolynomial_free(pwqp);
1690 return NULL;
1693 __isl_give isl_dim *isl_pw_qpolynomial_get_dim(
1694 __isl_keep isl_pw_qpolynomial *pwqp)
1696 if (!pwqp)
1697 return NULL;
1699 return isl_dim_copy(pwqp->dim);
1702 unsigned isl_pw_qpolynomial_dim(__isl_keep isl_pw_qpolynomial *pwqp,
1703 enum isl_dim_type type)
1705 return pwqp ? isl_dim_size(pwqp->dim, type) : 0;
1708 __isl_give isl_term *isl_term_alloc(__isl_take isl_dim *dim,
1709 __isl_take isl_mat *div)
1711 isl_term *term;
1712 int n;
1714 if (!dim || !div)
1715 goto error;
1717 n = isl_dim_total(dim) + div->n_row;
1719 term = isl_calloc(dim->ctx, struct isl_term,
1720 sizeof(struct isl_term) + (n - 1) * sizeof(int));
1721 if (!term)
1722 goto error;
1724 term->ref = 1;
1725 term->dim = dim;
1726 term->div = div;
1727 isl_int_init(term->n);
1728 isl_int_init(term->d);
1730 return term;
1731 error:
1732 isl_dim_free(dim);
1733 isl_mat_free(div);
1734 return NULL;
1737 __isl_give isl_term *isl_term_copy(__isl_keep isl_term *term)
1739 if (!term)
1740 return NULL;
1742 term->ref++;
1743 return term;
1746 __isl_give isl_term *isl_term_dup(__isl_keep isl_term *term)
1748 int i;
1749 isl_term *dup;
1750 unsigned total;
1752 if (term)
1753 return NULL;
1755 total = isl_dim_total(term->dim) + term->div->n_row;
1757 dup = isl_term_alloc(isl_dim_copy(term->dim), isl_mat_copy(term->div));
1758 if (!dup)
1759 return NULL;
1761 isl_int_set(dup->n, term->n);
1762 isl_int_set(dup->d, term->d);
1764 for (i = 0; i < total; ++i)
1765 dup->pow[i] = term->pow[i];
1767 return dup;
1770 __isl_give isl_term *isl_term_cow(__isl_take isl_term *term)
1772 if (!term)
1773 return NULL;
1775 if (term->ref == 1)
1776 return term;
1777 term->ref--;
1778 return isl_term_dup(term);
1781 void isl_term_free(__isl_take isl_term *term)
1783 if (!term)
1784 return;
1786 if (--term->ref > 0)
1787 return;
1789 isl_dim_free(term->dim);
1790 isl_mat_free(term->div);
1791 isl_int_clear(term->n);
1792 isl_int_clear(term->d);
1793 free(term);
1796 unsigned isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type)
1798 if (!term)
1799 return 0;
1801 switch (type) {
1802 case isl_dim_param:
1803 case isl_dim_in:
1804 case isl_dim_out: return isl_dim_size(term->dim, type);
1805 case isl_dim_div: return term->div->n_row;
1806 case isl_dim_all: return isl_dim_total(term->dim) + term->div->n_row;
1810 isl_ctx *isl_term_get_ctx(__isl_keep isl_term *term)
1812 return term ? term->dim->ctx : NULL;
1815 void isl_term_get_num(__isl_keep isl_term *term, isl_int *n)
1817 if (!term)
1818 return;
1819 isl_int_set(*n, term->n);
1822 void isl_term_get_den(__isl_keep isl_term *term, isl_int *d)
1824 if (!term)
1825 return;
1826 isl_int_set(*d, term->d);
1829 int isl_term_get_exp(__isl_keep isl_term *term,
1830 enum isl_dim_type type, unsigned pos)
1832 if (!term)
1833 return -1;
1835 isl_assert(term->dim->ctx, pos < isl_term_dim(term, type), return -1);
1837 if (type >= isl_dim_set)
1838 pos += isl_dim_size(term->dim, isl_dim_param);
1839 if (type >= isl_dim_div)
1840 pos += isl_dim_size(term->dim, isl_dim_set);
1842 return term->pow[pos];
1845 __isl_give isl_div *isl_term_get_div(__isl_keep isl_term *term, unsigned pos)
1847 isl_basic_map *bmap;
1848 unsigned total;
1849 int k;
1851 if (!term)
1852 return NULL;
1854 isl_assert(term->dim->ctx, pos < isl_term_dim(term, isl_dim_div),
1855 return NULL);
1857 total = term->div->n_col - term->div->n_row - 2;
1858 /* No nested divs for now */
1859 isl_assert(term->dim->ctx,
1860 isl_seq_first_non_zero(term->div->row[pos] + 2 + total,
1861 term->div->n_row) == -1,
1862 return NULL);
1864 bmap = isl_basic_map_alloc_dim(isl_dim_copy(term->dim), 1, 0, 0);
1865 if ((k = isl_basic_map_alloc_div(bmap)) < 0)
1866 goto error;
1868 isl_seq_cpy(bmap->div[k], term->div->row[pos], 2 + total);
1870 return isl_basic_map_div(bmap, k);
1871 error:
1872 isl_basic_map_free(bmap);
1873 return NULL;
1876 __isl_give isl_term *isl_upoly_foreach_term(__isl_keep struct isl_upoly *up,
1877 int (*fn)(__isl_take isl_term *term, void *user),
1878 __isl_take isl_term *term, void *user)
1880 int i;
1881 struct isl_upoly_rec *rec;
1883 if (!up || !term)
1884 goto error;
1886 if (isl_upoly_is_zero(up))
1887 return term;
1889 isl_assert(up->ctx, !isl_upoly_is_nan(up), goto error);
1890 isl_assert(up->ctx, !isl_upoly_is_infty(up), goto error);
1891 isl_assert(up->ctx, !isl_upoly_is_neginfty(up), goto error);
1893 if (isl_upoly_is_cst(up)) {
1894 struct isl_upoly_cst *cst;
1895 cst = isl_upoly_as_cst(up);
1896 if (!cst)
1897 goto error;
1898 term = isl_term_cow(term);
1899 if (!term)
1900 goto error;
1901 isl_int_set(term->n, cst->n);
1902 isl_int_set(term->d, cst->d);
1903 if (fn(isl_term_copy(term), user) < 0)
1904 goto error;
1905 return term;
1908 rec = isl_upoly_as_rec(up);
1909 if (!rec)
1910 goto error;
1912 for (i = 0; i < rec->n; ++i) {
1913 term = isl_term_cow(term);
1914 if (!term)
1915 goto error;
1916 term->pow[up->var] = i;
1917 term = isl_upoly_foreach_term(rec->p[i], fn, term, user);
1918 if (!term)
1919 goto error;
1921 term->pow[up->var] = 0;
1923 return term;
1924 error:
1925 isl_term_free(term);
1926 return NULL;
1929 int isl_qpolynomial_foreach_term(__isl_keep isl_qpolynomial *qp,
1930 int (*fn)(__isl_take isl_term *term, void *user), void *user)
1932 isl_term *term;
1934 if (!qp)
1935 return -1;
1937 term = isl_term_alloc(isl_dim_copy(qp->dim), isl_mat_copy(qp->div));
1938 if (!term)
1939 return -1;
1941 term = isl_upoly_foreach_term(qp->upoly, fn, term, user);
1943 isl_term_free(term);
1945 return term ? 0 : -1;
1948 int isl_pw_qpolynomial_foreach_piece(__isl_keep isl_pw_qpolynomial *pwqp,
1949 int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
1950 void *user), void *user)
1952 int i;
1954 if (!pwqp)
1955 return -1;
1957 for (i = 0; i < pwqp->n; ++i)
1958 if (fn(isl_set_copy(pwqp->p[i].set),
1959 isl_qpolynomial_copy(pwqp->p[i].qp), user) < 0)
1960 return -1;
1962 return 0;
1965 static int any_divs(__isl_keep isl_set *set)
1967 int i;
1969 if (!set)
1970 return -1;
1972 for (i = 0; i < set->n; ++i)
1973 if (set->p[i]->n_div > 0)
1974 return 1;
1976 return 0;
1979 __isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
1980 __isl_take isl_dim *dim)
1982 if (!qp || !dim)
1983 goto error;
1985 if (isl_dim_equal(qp->dim, dim)) {
1986 isl_dim_free(dim);
1987 return qp;
1990 qp = isl_qpolynomial_cow(qp);
1991 if (!qp)
1992 goto error;
1994 if (qp->div->n_row) {
1995 int i;
1996 int extra;
1997 unsigned total;
1998 int *exp;
2000 extra = isl_dim_size(dim, isl_dim_set) -
2001 isl_dim_size(qp->dim, isl_dim_set);
2002 total = isl_dim_total(qp->dim);
2003 exp = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);
2004 if (!exp)
2005 goto error;
2006 for (i = 0; i < qp->div->n_row; ++i)
2007 exp[i] = extra + i;
2008 qp->upoly = expand(qp->upoly, exp, total);
2009 free(exp);
2010 if (!qp->upoly)
2011 goto error;
2012 qp->div = isl_mat_insert_cols(qp->div, 2 + total, extra);
2013 if (!qp->div)
2014 goto error;
2015 for (i = 0; i < qp->div->n_row; ++i)
2016 isl_seq_clr(qp->div->row[i] + 2 + total, extra);
2019 isl_dim_free(qp->dim);
2020 qp->dim = dim;
2022 return qp;
2023 error:
2024 isl_dim_free(dim);
2025 isl_qpolynomial_free(qp);
2026 return NULL;
2029 static int foreach_lifted_subset(__isl_take isl_set *set,
2030 __isl_take isl_qpolynomial *qp,
2031 int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
2032 void *user), void *user)
2034 int i;
2036 if (!set || !qp)
2037 goto error;
2039 for (i = 0; i < set->n; ++i) {
2040 isl_set *lift;
2041 isl_qpolynomial *copy;
2043 lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
2044 lift = isl_set_lift(lift);
2046 copy = isl_qpolynomial_copy(qp);
2047 copy = isl_qpolynomial_lift(copy, isl_set_get_dim(lift));
2049 if (fn(lift, copy, user) < 0)
2050 goto error;
2053 isl_set_free(set);
2054 isl_qpolynomial_free(qp);
2056 return 0;
2057 error:
2058 isl_set_free(set);
2059 isl_qpolynomial_free(qp);
2060 return -1;
2063 int isl_pw_qpolynomial_foreach_lifted_piece(__isl_keep isl_pw_qpolynomial *pwqp,
2064 int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
2065 void *user), void *user)
2067 int i;
2069 if (!pwqp)
2070 return -1;
2072 for (i = 0; i < pwqp->n; ++i) {
2073 isl_set *set;
2074 isl_qpolynomial *qp;
2076 set = isl_set_copy(pwqp->p[i].set);
2077 qp = isl_qpolynomial_copy(pwqp->p[i].qp);
2078 if (!any_divs(set)) {
2079 if (fn(set, qp, user) < 0)
2080 return -1;
2081 continue;
2083 if (foreach_lifted_subset(set, qp, fn, user) < 0)
2084 return -1;
2087 return 0;
2090 static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
2091 enum isl_fold type, __isl_take isl_dim *dim, int n)
2093 isl_qpolynomial_fold *fold;
2095 if (!dim)
2096 goto error;
2098 isl_assert(dim->ctx, n >= 0, goto error);
2099 fold = isl_alloc(dim->ctx, struct isl_qpolynomial_fold,
2100 sizeof(struct isl_qpolynomial_fold) +
2101 (n - 1) * sizeof(struct isl_qpolynomial *));
2102 if (!fold)
2103 goto error;
2105 fold->ref = 1;
2106 fold->size = n;
2107 fold->n = 0;
2108 fold->type = type;
2109 fold->dim = dim;
2111 return fold;
2112 error:
2113 isl_dim_free(dim);
2114 return NULL;
2117 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
2118 __isl_take isl_dim *dim)
2120 return qpolynomial_fold_alloc(type, dim, 0);
2123 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
2124 enum isl_fold type, __isl_take isl_qpolynomial *qp)
2126 isl_qpolynomial_fold *fold;
2128 if (!qp)
2129 return NULL;
2131 fold = qpolynomial_fold_alloc(type, isl_dim_copy(qp->dim), 1);
2132 if (!fold)
2133 goto error;
2135 fold->qp[0] = qp;
2136 fold->n++;
2138 return fold;
2139 error:
2140 isl_qpolynomial_fold_free(fold);
2141 isl_qpolynomial_free(qp);
2142 return NULL;
2145 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
2146 __isl_keep isl_qpolynomial_fold *fold)
2148 if (!fold)
2149 return NULL;
2151 fold->ref++;
2152 return fold;
2155 void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold)
2157 int i;
2159 if (!fold)
2160 return;
2161 if (--fold->ref > 0)
2162 return;
2164 for (i = 0; i < fold->n; ++i)
2165 isl_qpolynomial_free(fold->qp[i]);
2166 isl_dim_free(fold->dim);
2167 free(fold);
2170 int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
2172 if (!fold)
2173 return -1;
2175 return fold->n == 0;
2178 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
2179 __isl_take isl_qpolynomial_fold *fold1,
2180 __isl_take isl_qpolynomial_fold *fold2)
2182 int i;
2183 struct isl_qpolynomial_fold *res = NULL;
2185 if (!fold1 || !fold2)
2186 goto error;
2188 isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
2189 isl_assert(fold1->dim->ctx, isl_dim_equal(fold1->dim, fold2->dim),
2190 goto error);
2192 if (isl_qpolynomial_fold_is_empty(fold1)) {
2193 isl_qpolynomial_fold_free(fold1);
2194 return fold2;
2197 if (isl_qpolynomial_fold_is_empty(fold2)) {
2198 isl_qpolynomial_fold_free(fold2);
2199 return fold1;
2202 res = qpolynomial_fold_alloc(fold1->type, isl_dim_copy(fold1->dim),
2203 fold1->n + fold2->n);
2204 if (!res)
2205 goto error;
2207 for (i = 0; i < fold1->n; ++i) {
2208 res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
2209 if (!res->qp[res->n])
2210 goto error;
2211 res->n++;
2214 for (i = 0; i < fold2->n; ++i) {
2215 res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
2216 if (!res->qp[res->n])
2217 goto error;
2218 res->n++;
2221 isl_qpolynomial_fold_free(fold1);
2222 isl_qpolynomial_fold_free(fold2);
2224 return res;
2225 error:
2226 isl_qpolynomial_fold_free(res);
2227 isl_qpolynomial_fold_free(fold1);
2228 isl_qpolynomial_fold_free(fold2);
2229 return NULL;
2232 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
2233 enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp)
2235 int i;
2236 isl_pw_qpolynomial_fold *pwf;
2238 if (!pwqp)
2239 return NULL;
2241 pwf = isl_pw_qpolynomial_fold_alloc_(isl_dim_copy(pwqp->dim), pwqp->n);
2243 for (i = 0; i < pwqp->n; ++i)
2244 pwf = isl_pw_qpolynomial_fold_add_piece(pwf,
2245 isl_set_copy(pwqp->p[i].set),
2246 isl_qpolynomial_fold_alloc(type,
2247 isl_qpolynomial_copy(pwqp->p[i].qp)));
2249 isl_pw_qpolynomial_free(pwqp);
2251 return pwf;