isl_basic_map_normalize_constraints: avoid NULL pointer dereference
[isl.git] / isl_fold.c
blobf04b4d485c983e144d60e16bcee26f88e3871fa3
1 /*
2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8 * 91893 Orsay, France
9 */
11 #include <isl_polynomial_private.h>
12 #include <isl_point_private.h>
13 #include <isl_dim.h>
14 #include <isl_map_private.h>
15 #include <isl_lp.h>
16 #include <isl_seq.h>
18 static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
19 enum isl_fold type, __isl_take isl_dim *dim, int n)
21 isl_qpolynomial_fold *fold;
23 if (!dim)
24 goto error;
26 isl_assert(dim->ctx, n >= 0, goto error);
27 fold = isl_calloc(dim->ctx, struct isl_qpolynomial_fold,
28 sizeof(struct isl_qpolynomial_fold) +
29 (n - 1) * sizeof(struct isl_qpolynomial *));
30 if (!fold)
31 goto error;
33 fold->ref = 1;
34 fold->size = n;
35 fold->n = 0;
36 fold->type = type;
37 fold->dim = dim;
39 return fold;
40 error:
41 isl_dim_free(dim);
42 return NULL;
45 int isl_qpolynomial_fold_involves_dims(__isl_keep isl_qpolynomial_fold *fold,
46 enum isl_dim_type type, unsigned first, unsigned n)
48 int i;
50 if (!fold)
51 return -1;
52 if (fold->n == 0 || n == 0)
53 return 0;
55 for (i = 0; i < fold->n; ++i) {
56 int involves = isl_qpolynomial_involves_dims(fold->qp[i],
57 type, first, n);
58 if (involves < 0 || involves)
59 return involves;
61 return 0;
64 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_drop_dims(
65 __isl_take isl_qpolynomial_fold *fold,
66 enum isl_dim_type type, unsigned first, unsigned n)
68 int i;
70 if (!fold)
71 return NULL;
72 if (n == 0)
73 return fold;
75 fold = isl_qpolynomial_fold_cow(fold);
76 if (!fold)
77 return NULL;
78 fold->dim = isl_dim_drop(fold->dim, type, first, n);
79 if (!fold->dim)
80 goto error;
82 for (i = 0; i < fold->n; ++i) {
83 fold->qp[i] = isl_qpolynomial_drop_dims(fold->qp[i],
84 type, first, n);
85 if (!fold->qp[i])
86 goto error;
89 return fold;
90 error:
91 isl_qpolynomial_fold_free(fold);
92 return NULL;
95 static int isl_qpolynomial_cst_sign(__isl_keep isl_qpolynomial *qp)
97 struct isl_upoly_cst *cst;
99 cst = isl_upoly_as_cst(qp->upoly);
100 if (!cst)
101 return 0;
103 return isl_int_sgn(cst->n) < 0 ? -1 : 1;
106 static int isl_qpolynomial_aff_sign(__isl_keep isl_set *set,
107 __isl_keep isl_qpolynomial *qp)
109 enum isl_lp_result res;
110 isl_vec *aff;
111 isl_int opt;
112 int sgn = 0;
114 aff = isl_qpolynomial_extract_affine(qp);
115 if (!aff)
116 return 0;
118 isl_int_init(opt);
120 res = isl_set_solve_lp(set, 0, aff->el + 1, aff->el[0],
121 &opt, NULL, NULL);
122 if (res == isl_lp_error)
123 goto done;
124 if (res == isl_lp_empty ||
125 (res == isl_lp_ok && !isl_int_is_neg(opt))) {
126 sgn = 1;
127 goto done;
130 res = isl_set_solve_lp(set, 1, aff->el + 1, aff->el[0],
131 &opt, NULL, NULL);
132 if (res == isl_lp_ok && !isl_int_is_pos(opt))
133 sgn = -1;
135 done:
136 isl_int_clear(opt);
137 isl_vec_free(aff);
138 return sgn;
141 /* Determine, if possible, the sign of the quasipolynomial "qp" on
142 * the domain "set".
144 * If qp is a constant, then the problem is trivial.
145 * If qp is linear, then we check if the minimum of the corresponding
146 * affine constraint is non-negative or if the maximum is non-positive.
148 * Otherwise, we check if the outermost variable "v" has a lower bound "l"
149 * in "set". If so, we write qp(v,v') as
151 * q(v,v') * (v - l) + r(v')
153 * if q(v,v') and r(v') have the same known sign, then the original
154 * quasipolynomial has the same sign as well.
156 * Return
157 * -1 if qp <= 0
158 * 1 if qp >= 0
159 * 0 if unknown
161 static int isl_qpolynomial_sign(__isl_keep isl_set *set,
162 __isl_keep isl_qpolynomial *qp)
164 int d;
165 int i;
166 int is;
167 struct isl_upoly_rec *rec;
168 isl_vec *v;
169 isl_int l;
170 enum isl_lp_result res;
171 int sgn = 0;
173 is = isl_qpolynomial_is_cst(qp, NULL, NULL);
174 if (is < 0)
175 return 0;
176 if (is)
177 return isl_qpolynomial_cst_sign(qp);
179 is = isl_qpolynomial_is_affine(qp);
180 if (is < 0)
181 return 0;
182 if (is)
183 return isl_qpolynomial_aff_sign(set, qp);
185 if (qp->div->n_row > 0)
186 return 0;
188 rec = isl_upoly_as_rec(qp->upoly);
189 if (!rec)
190 return 0;
192 d = isl_dim_total(qp->dim);
193 v = isl_vec_alloc(set->ctx, 2 + d);
194 if (!v)
195 return 0;
197 isl_seq_clr(v->el + 1, 1 + d);
198 isl_int_set_si(v->el[0], 1);
199 isl_int_set_si(v->el[2 + qp->upoly->var], 1);
201 isl_int_init(l);
203 res = isl_set_solve_lp(set, 0, v->el + 1, v->el[0], &l, NULL, NULL);
204 if (res == isl_lp_ok) {
205 isl_qpolynomial *min;
206 isl_qpolynomial *base;
207 isl_qpolynomial *r, *q;
208 isl_qpolynomial *t;
210 min = isl_qpolynomial_cst(isl_dim_copy(qp->dim), l);
211 base = isl_qpolynomial_pow(isl_dim_copy(qp->dim),
212 qp->upoly->var, 1);
214 r = isl_qpolynomial_alloc(isl_dim_copy(qp->dim), 0,
215 isl_upoly_copy(rec->p[rec->n - 1]));
216 q = isl_qpolynomial_copy(r);
218 for (i = rec->n - 2; i >= 0; --i) {
219 r = isl_qpolynomial_mul(r, isl_qpolynomial_copy(min));
220 t = isl_qpolynomial_alloc(isl_dim_copy(qp->dim), 0,
221 isl_upoly_copy(rec->p[i]));
222 r = isl_qpolynomial_add(r, t);
223 if (i == 0)
224 break;
225 q = isl_qpolynomial_mul(q, isl_qpolynomial_copy(base));
226 q = isl_qpolynomial_add(q, isl_qpolynomial_copy(r));
229 if (isl_qpolynomial_is_zero(q))
230 sgn = isl_qpolynomial_sign(set, r);
231 else if (isl_qpolynomial_is_zero(r))
232 sgn = isl_qpolynomial_sign(set, q);
233 else {
234 int sgn_q, sgn_r;
235 sgn_r = isl_qpolynomial_sign(set, r);
236 sgn_q = isl_qpolynomial_sign(set, q);
237 if (sgn_r == sgn_q)
238 sgn = sgn_r;
241 isl_qpolynomial_free(min);
242 isl_qpolynomial_free(base);
243 isl_qpolynomial_free(q);
244 isl_qpolynomial_free(r);
247 isl_int_clear(l);
249 isl_vec_free(v);
251 return sgn;
254 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold_on_domain(
255 __isl_keep isl_set *set,
256 __isl_take isl_qpolynomial_fold *fold1,
257 __isl_take isl_qpolynomial_fold *fold2)
259 int i, j;
260 int n1;
261 struct isl_qpolynomial_fold *res = NULL;
262 int better;
264 if (!fold1 || !fold2)
265 goto error;
267 isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
268 isl_assert(fold1->dim->ctx, isl_dim_equal(fold1->dim, fold2->dim),
269 goto error);
271 better = fold1->type == isl_fold_max ? -1 : 1;
273 if (isl_qpolynomial_fold_is_empty(fold1)) {
274 isl_qpolynomial_fold_free(fold1);
275 return fold2;
278 if (isl_qpolynomial_fold_is_empty(fold2)) {
279 isl_qpolynomial_fold_free(fold2);
280 return fold1;
283 res = qpolynomial_fold_alloc(fold1->type, isl_dim_copy(fold1->dim),
284 fold1->n + fold2->n);
285 if (!res)
286 goto error;
288 for (i = 0; i < fold1->n; ++i) {
289 res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
290 if (!res->qp[res->n])
291 goto error;
292 res->n++;
294 n1 = res->n;
296 for (i = 0; i < fold2->n; ++i) {
297 for (j = n1 - 1; j >= 0; --j) {
298 isl_qpolynomial *d;
299 int sgn;
300 d = isl_qpolynomial_sub(
301 isl_qpolynomial_copy(res->qp[j]),
302 isl_qpolynomial_copy(fold2->qp[i]));
303 sgn = isl_qpolynomial_sign(set, d);
304 isl_qpolynomial_free(d);
305 if (sgn == 0)
306 continue;
307 if (sgn != better)
308 break;
309 isl_qpolynomial_free(res->qp[j]);
310 if (j != n1 - 1)
311 res->qp[j] = res->qp[n1 - 1];
312 n1--;
313 if (n1 != res->n - 1)
314 res->qp[n1] = res->qp[res->n - 1];
315 res->n--;
317 if (j >= 0)
318 continue;
319 res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
320 if (!res->qp[res->n])
321 goto error;
322 res->n++;
325 isl_qpolynomial_fold_free(fold1);
326 isl_qpolynomial_fold_free(fold2);
328 return res;
329 error:
330 isl_qpolynomial_fold_free(res);
331 isl_qpolynomial_fold_free(fold1);
332 isl_qpolynomial_fold_free(fold2);
333 return NULL;
336 #undef PW
337 #define PW isl_pw_qpolynomial_fold
338 #undef EL
339 #define EL isl_qpolynomial_fold
340 #undef IS_ZERO
341 #define IS_ZERO is_empty
342 #undef FIELD
343 #define FIELD fold
344 #undef ADD
345 #define ADD(d,e1,e2) isl_qpolynomial_fold_fold_on_domain(d,e1,e2)
347 #include <isl_pw_templ.c>
349 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
350 __isl_take isl_dim *dim)
352 return qpolynomial_fold_alloc(type, dim, 0);
355 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
356 enum isl_fold type, __isl_take isl_qpolynomial *qp)
358 isl_qpolynomial_fold *fold;
360 if (!qp)
361 return NULL;
363 fold = qpolynomial_fold_alloc(type, isl_dim_copy(qp->dim), 1);
364 if (!fold)
365 goto error;
367 fold->qp[0] = qp;
368 fold->n++;
370 return fold;
371 error:
372 isl_qpolynomial_fold_free(fold);
373 isl_qpolynomial_free(qp);
374 return NULL;
377 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
378 __isl_keep isl_qpolynomial_fold *fold)
380 if (!fold)
381 return NULL;
383 fold->ref++;
384 return fold;
387 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_dup(
388 __isl_keep isl_qpolynomial_fold *fold)
390 int i;
391 isl_qpolynomial_fold *dup;
393 if (!fold)
394 return NULL;
395 dup = qpolynomial_fold_alloc(fold->type,
396 isl_dim_copy(fold->dim), fold->n);
397 if (!dup)
398 return NULL;
400 dup->n = fold->n;
401 for (i = 0; i < fold->n; ++i) {
402 dup->qp[i] = isl_qpolynomial_copy(fold->qp[i]);
403 if (!dup->qp[i])
404 goto error;
407 return dup;
408 error:
409 isl_qpolynomial_fold_free(dup);
410 return NULL;
413 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_cow(
414 __isl_take isl_qpolynomial_fold *fold)
416 if (!fold)
417 return NULL;
419 if (fold->ref == 1)
420 return fold;
421 fold->ref--;
422 return isl_qpolynomial_fold_dup(fold);
425 void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold)
427 int i;
429 if (!fold)
430 return;
431 if (--fold->ref > 0)
432 return;
434 for (i = 0; i < fold->n; ++i)
435 isl_qpolynomial_free(fold->qp[i]);
436 isl_dim_free(fold->dim);
437 free(fold);
440 int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
442 if (!fold)
443 return -1;
445 return fold->n == 0;
448 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
449 __isl_take isl_qpolynomial_fold *fold1,
450 __isl_take isl_qpolynomial_fold *fold2)
452 int i;
453 struct isl_qpolynomial_fold *res = NULL;
455 if (!fold1 || !fold2)
456 goto error;
458 isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
459 isl_assert(fold1->dim->ctx, isl_dim_equal(fold1->dim, fold2->dim),
460 goto error);
462 if (isl_qpolynomial_fold_is_empty(fold1)) {
463 isl_qpolynomial_fold_free(fold1);
464 return fold2;
467 if (isl_qpolynomial_fold_is_empty(fold2)) {
468 isl_qpolynomial_fold_free(fold2);
469 return fold1;
472 res = qpolynomial_fold_alloc(fold1->type, isl_dim_copy(fold1->dim),
473 fold1->n + fold2->n);
474 if (!res)
475 goto error;
477 for (i = 0; i < fold1->n; ++i) {
478 res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
479 if (!res->qp[res->n])
480 goto error;
481 res->n++;
484 for (i = 0; i < fold2->n; ++i) {
485 res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
486 if (!res->qp[res->n])
487 goto error;
488 res->n++;
491 isl_qpolynomial_fold_free(fold1);
492 isl_qpolynomial_fold_free(fold2);
494 return res;
495 error:
496 isl_qpolynomial_fold_free(res);
497 isl_qpolynomial_fold_free(fold1);
498 isl_qpolynomial_fold_free(fold2);
499 return NULL;
502 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
503 enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp)
505 int i;
506 isl_pw_qpolynomial_fold *pwf;
508 if (!pwqp)
509 return NULL;
511 pwf = isl_pw_qpolynomial_fold_alloc_(isl_dim_copy(pwqp->dim), pwqp->n);
513 for (i = 0; i < pwqp->n; ++i)
514 pwf = isl_pw_qpolynomial_fold_add_piece(pwf,
515 isl_set_copy(pwqp->p[i].set),
516 isl_qpolynomial_fold_alloc(type,
517 isl_qpolynomial_copy(pwqp->p[i].qp)));
519 isl_pw_qpolynomial_free(pwqp);
521 return pwf;
524 int isl_qpolynomial_fold_is_equal(__isl_keep isl_qpolynomial_fold *fold1,
525 __isl_keep isl_qpolynomial_fold *fold2)
527 int i;
529 if (!fold1 || !fold2)
530 return -1;
532 if (fold1->n != fold2->n)
533 return 0;
535 /* We probably want to sort the qps first... */
536 for (i = 0; i < fold1->n; ++i) {
537 int eq = isl_qpolynomial_is_equal(fold1->qp[i], fold2->qp[i]);
538 if (eq < 0 || !eq)
539 return eq;
542 return 1;
545 __isl_give isl_qpolynomial *isl_qpolynomial_fold_eval(
546 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_point *pnt)
548 isl_qpolynomial *qp;
550 if (!fold || !pnt)
551 goto error;
552 isl_assert(pnt->dim->ctx, isl_dim_equal(pnt->dim, fold->dim), goto error);
553 isl_assert(pnt->dim->ctx,
554 fold->type == isl_fold_max || fold->type == isl_fold_min,
555 goto error);
557 if (fold->n == 0)
558 qp = isl_qpolynomial_zero(isl_dim_copy(fold->dim));
559 else {
560 int i;
561 qp = isl_qpolynomial_eval(isl_qpolynomial_copy(fold->qp[0]),
562 isl_point_copy(pnt));
563 for (i = 1; i < fold->n; ++i) {
564 isl_qpolynomial *qp_i;
565 qp_i = isl_qpolynomial_eval(
566 isl_qpolynomial_copy(fold->qp[i]),
567 isl_point_copy(pnt));
568 if (fold->type == isl_fold_max)
569 qp = isl_qpolynomial_max_cst(qp, qp_i);
570 else
571 qp = isl_qpolynomial_min_cst(qp, qp_i);
574 isl_qpolynomial_fold_free(fold);
575 isl_point_free(pnt);
577 return qp;
578 error:
579 isl_qpolynomial_fold_free(fold);
580 isl_point_free(pnt);
581 return NULL;
584 size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold *pwf)
586 int i;
587 size_t n = 0;
589 for (i = 0; i < pwf->n; ++i)
590 n += pwf->p[i].fold->n;
592 return n;
595 __isl_give isl_qpolynomial *isl_qpolynomial_fold_opt_on_domain(
596 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *set, int max)
598 int i;
599 isl_qpolynomial *opt;
601 if (!set || !fold)
602 goto error;
604 if (fold->n == 0) {
605 isl_dim *dim = isl_dim_copy(fold->dim);
606 isl_set_free(set);
607 isl_qpolynomial_fold_free(fold);
608 return isl_qpolynomial_zero(dim);
611 opt = isl_qpolynomial_opt_on_domain(isl_qpolynomial_copy(fold->qp[0]),
612 isl_set_copy(set), max);
613 for (i = 1; i < fold->n; ++i) {
614 isl_qpolynomial *opt_i;
615 opt_i = isl_qpolynomial_opt_on_domain(
616 isl_qpolynomial_copy(fold->qp[i]),
617 isl_set_copy(set), max);
618 if (max)
619 opt = isl_qpolynomial_max_cst(opt, opt_i);
620 else
621 opt = isl_qpolynomial_min_cst(opt, opt_i);
624 isl_set_free(set);
625 isl_qpolynomial_fold_free(fold);
627 return opt;
628 error:
629 isl_set_free(set);
630 isl_qpolynomial_fold_free(fold);
631 return NULL;
634 /* Check whether for each quasi-polynomial in "fold2" there is
635 * a quasi-polynomial in "fold1" that dominates it on "set".
637 static int qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
638 __isl_keep isl_qpolynomial_fold *fold1,
639 __isl_keep isl_qpolynomial_fold *fold2)
641 int i, j;
642 int covers;
644 if (!set || !fold1 || !fold2)
645 return -1;
647 covers = fold1->type == isl_fold_max ? 1 : -1;
649 for (i = 0; i < fold2->n; ++i) {
650 for (j = 0; j < fold1->n; ++j) {
651 isl_qpolynomial *d;
652 int sgn;
654 d = isl_qpolynomial_sub(
655 isl_qpolynomial_copy(fold1->qp[j]),
656 isl_qpolynomial_copy(fold2->qp[i]));
657 sgn = isl_qpolynomial_sign(set, d);
658 isl_qpolynomial_free(d);
659 if (sgn == covers)
660 break;
662 if (j >= fold1->n)
663 return 0;
666 return 1;
669 /* Check whether "pwf1" dominated "pwf2", i.e., the domain of "pwf1" contains
670 * that of "pwf2" and on each cell, the corresponding fold from pwf1 dominates
671 * that of pwf2.
673 int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
674 __isl_keep isl_pw_qpolynomial_fold *pwf2)
676 int i, j;
677 isl_set *dom1, *dom2;
678 int is_subset;
680 if (!pwf1 || !pwf2)
681 return -1;
683 if (pwf2->n == 0)
684 return 1;
685 if (pwf1->n == 0)
686 return 0;
688 dom1 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf1));
689 dom2 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf2));
690 is_subset = isl_set_is_subset(dom2, dom1);
691 isl_set_free(dom1);
692 isl_set_free(dom2);
694 if (is_subset < 0 || !is_subset)
695 return is_subset;
697 for (i = 0; i < pwf2->n; ++i) {
698 for (j = 0; j < pwf1->n; ++j) {
699 int is_empty;
700 isl_set *common;
701 int covers;
703 common = isl_set_intersect(isl_set_copy(pwf1->p[j].set),
704 isl_set_copy(pwf2->p[i].set));
705 is_empty = isl_set_is_empty(common);
706 if (is_empty < 0 || is_empty) {
707 isl_set_free(common);
708 if (is_empty < 0)
709 return -1;
710 continue;
712 covers = qpolynomial_fold_covers_on_domain(common,
713 pwf1->p[j].fold, pwf2->p[i].fold);
714 isl_set_free(common);
715 if (covers < 0 || !covers)
716 return covers;
720 return 1;
723 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_morph(
724 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_morph *morph)
726 int i;
727 isl_ctx *ctx;
729 if (!fold || !morph)
730 goto error;
732 ctx = fold->dim->ctx;
733 isl_assert(ctx, isl_dim_equal(fold->dim, morph->dom->dim), goto error);
735 fold = isl_qpolynomial_fold_cow(fold);
736 if (!fold)
737 goto error;
739 isl_dim_free(fold->dim);
740 fold->dim = isl_dim_copy(morph->ran->dim);
741 if (!fold->dim)
742 goto error;
744 for (i = 0; i < fold->n; ++i) {
745 fold->qp[i] = isl_qpolynomial_morph(fold->qp[i],
746 isl_morph_copy(morph));
747 if (!fold->qp[i])
748 goto error;
751 isl_morph_free(morph);
753 return fold;
754 error:
755 isl_qpolynomial_fold_free(fold);
756 isl_morph_free(morph);
757 return NULL;
760 enum isl_fold isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold *fold)
762 if (!fold)
763 return isl_fold_list;
764 return fold->type;
767 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_lift(
768 __isl_take isl_qpolynomial_fold *fold, __isl_take isl_dim *dim)
770 int i;
771 isl_ctx *ctx;
773 if (!fold || !dim)
774 goto error;
776 if (isl_dim_equal(fold->dim, dim)) {
777 isl_dim_free(dim);
778 return fold;
781 fold = isl_qpolynomial_fold_cow(fold);
782 if (!fold)
783 goto error;
785 isl_dim_free(fold->dim);
786 fold->dim = isl_dim_copy(dim);
787 if (!fold->dim)
788 goto error;
790 for (i = 0; i < fold->n; ++i) {
791 fold->qp[i] = isl_qpolynomial_lift(fold->qp[i],
792 isl_dim_copy(dim));
793 if (!fold->qp[i])
794 goto error;
797 isl_dim_free(dim);
799 return fold;
800 error:
801 isl_qpolynomial_fold_free(fold);
802 isl_dim_free(dim);
803 return NULL;
806 int isl_qpolynomial_fold_foreach_qpolynomial(
807 __isl_keep isl_qpolynomial_fold *fold,
808 int (*fn)(__isl_take isl_qpolynomial *qp, void *user), void *user)
810 int i;
812 if (!fold)
813 return -1;
815 for (i = 0; i < fold->n; ++i)
816 if (fn(isl_qpolynomial_copy(fold->qp[i]), user) < 0)
817 return -1;
819 return 0;
822 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_move_dims(
823 __isl_take isl_qpolynomial_fold *fold,
824 enum isl_dim_type dst_type, unsigned dst_pos,
825 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
827 int i;
829 if (n == 0)
830 return fold;
832 fold = isl_qpolynomial_fold_cow(fold);
833 if (!fold)
834 return NULL;
836 fold->dim = isl_dim_move(fold->dim, dst_type, dst_pos,
837 src_type, src_pos, n);
838 if (!fold->dim)
839 goto error;
841 for (i = 0; i < fold->n; ++i) {
842 fold->qp[i] = isl_qpolynomial_move_dims(fold->qp[i],
843 dst_type, dst_pos, src_type, src_pos, n);
844 if (!fold->qp[i])
845 goto error;
848 return fold;
849 error:
850 isl_qpolynomial_fold_free(fold);
851 return NULL;