isl_qpolynomial_move_dims: plug memory leak and fix reordering of divs
authorSven Verdoolaege <skimo@kotnet.org>
Fri, 6 Aug 2010 10:28:04 +0000 (12:28 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Fri, 6 Aug 2010 13:39:47 +0000 (15:39 +0200)
In particular, when divs got reordered, the new order would not
be reflected in the associated upoly.

Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
isl_polynomial.c
isl_test.c

index bf51598..de500c2 100644 (file)
@@ -941,6 +941,67 @@ void isl_qpolynomial_free(__isl_take isl_qpolynomial *qp)
        free(qp);
 }
 
+__isl_give struct isl_upoly *isl_upoly_pow(isl_ctx *ctx, int pos, int power)
+{
+       int i;
+       struct isl_upoly *up;
+       struct isl_upoly_rec *rec;
+       struct isl_upoly_cst *cst;
+
+       rec = isl_upoly_alloc_rec(ctx, pos, 1 + power);
+       if (!rec)
+               return NULL;
+       for (i = 0; i < 1 + power; ++i) {
+               rec->p[i] = isl_upoly_zero(ctx);
+               if (!rec->p[i])
+                       goto error;
+               rec->n++;
+       }
+       cst = isl_upoly_as_cst(rec->p[power]);
+       isl_int_set_si(cst->n, 1);
+
+       return &rec->up;
+error:
+       isl_upoly_free(&rec->up);
+       return NULL;
+}
+
+/* r array maps original positions to new positions.
+ */
+static __isl_give struct isl_upoly *reorder(__isl_take struct isl_upoly *up,
+       int *r)
+{
+       int i;
+       struct isl_upoly_rec *rec;
+       struct isl_upoly *base;
+       struct isl_upoly *res;
+
+       if (isl_upoly_is_cst(up))
+               return up;
+
+       rec = isl_upoly_as_rec(up);
+       if (!rec)
+               goto error;
+
+       isl_assert(up->ctx, rec->n >= 1, goto error);
+
+       base = isl_upoly_pow(up->ctx, r[up->var], 1);
+       res = reorder(isl_upoly_copy(rec->p[rec->n - 1]), r);
+
+       for (i = rec->n - 2; i >= 0; --i) {
+               res = isl_upoly_mul(res, isl_upoly_copy(base));
+               res = isl_upoly_sum(res, reorder(isl_upoly_copy(rec->p[i]), r));
+       }
+
+       isl_upoly_free(base);
+       isl_upoly_free(up);
+
+       return res;
+error:
+       isl_upoly_free(up);
+       return NULL;
+}
+
 static int compatible_divs(__isl_keep isl_mat *div1, __isl_keep isl_mat *div2)
 {
        int n_row, n_col;
@@ -1005,49 +1066,69 @@ static int div_sort_cmp(const void *p1, const void *p2)
        return cmp_row(i1->div, i1->row, i2->row);
 }
 
-static __isl_give isl_mat *sort_divs(__isl_take isl_mat *div)
+static __isl_give isl_qpolynomial *sort_divs(__isl_take isl_qpolynomial *qp)
 {
        int i;
        struct isl_div_sort_info *array = NULL;
        int *pos = NULL;
+       int *reordering = NULL;
+       unsigned div_pos;
 
-       if (!div)
+       if (!qp)
                return NULL;
-       if (div->n_row <= 1)
-               return div;
+       if (qp->div->n_row <= 1)
+               return qp;
+
+       div_pos = isl_dim_total(qp->dim);
 
-       array = isl_alloc_array(div->ctx, struct isl_div_sort_info, div->n_row);
-       pos = isl_alloc_array(div->ctx, int, div->n_row);
-       if (!array || !pos)
+       array = isl_alloc_array(qp->div->ctx, struct isl_div_sort_info,
+                               qp->div->n_row);
+       pos = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);
+       reordering = isl_alloc_array(qp->div->ctx, int, qp->div->n_col - 2);
+       if (!array || !pos || !reordering)
                goto error;
 
-       for (i = 0; i < div->n_row; ++i) {
-               array[i].div = div;
+       for (i = 0; i < qp->div->n_row; ++i) {
+               array[i].div = qp->div;
                array[i].row = i;
                pos[i] = i;
        }
 
-       qsort(array, div->n_row, sizeof(struct isl_div_sort_info),
+       qsort(array, qp->div->n_row, sizeof(struct isl_div_sort_info),
                div_sort_cmp);
 
-       for (i = 0; i < div->n_row; ++i) {
+       for (i = 0; i < div_pos; ++i)
+               reordering[i] = i;
+
+       for (i = 0; i < qp->div->n_row; ++i)
+               reordering[div_pos + array[i].row] = div_pos + i;
+
+       for (i = 0; i < qp->div->n_row; ++i) {
                int t;
                if (pos[array[i].row] == i)
                        continue;
-               div = isl_mat_cow(div);
-               div = isl_mat_swap_rows(div, i, pos[array[i].row]);
+               qp->div = isl_mat_cow(qp->div);
+               qp->div = isl_mat_swap_rows(qp->div, i, pos[array[i].row]);
                t = pos[array[i].row];
                pos[array[i].row] = pos[i];
                pos[i] = t;
        }
 
+       qp->upoly = reorder(qp->upoly, reordering);
+
+       if (!qp->upoly || !qp->div)
+               goto error;
+
+       free(pos);
        free(array);
+       free(reordering);
 
-       return div;
+       return qp;
 error:
        free(pos);
        free(array);
-       isl_mat_free(div);
+       free(reordering);
+       isl_qpolynomial_free(qp);
        return NULL;
 }
 
@@ -1480,31 +1561,6 @@ void isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp, isl_int *d)
        upoly_update_den(qp->upoly, d);
 }
 
-__isl_give struct isl_upoly *isl_upoly_pow(isl_ctx *ctx, int pos, int power)
-{
-       int i;
-       struct isl_upoly *up;
-       struct isl_upoly_rec *rec;
-       struct isl_upoly_cst *cst;
-
-       rec = isl_upoly_alloc_rec(ctx, pos, 1 + power);
-       if (!rec)
-               return NULL;
-       for (i = 0; i < 1 + power; ++i) {
-               rec->p[i] = isl_upoly_zero(ctx);
-               if (!rec->p[i])
-                       goto error;
-               rec->n++;
-       }
-       cst = isl_upoly_as_cst(rec->p[power]);
-       isl_int_set_si(cst->n, 1);
-
-       return &rec->up;
-error:
-       isl_upoly_free(&rec->up);
-       return NULL;
-}
-
 __isl_give isl_qpolynomial *isl_qpolynomial_pow(__isl_take isl_dim *dim,
        int pos, int power)
 {
@@ -2192,40 +2248,6 @@ static int *reordering_move(isl_ctx *ctx,
        return reordering;
 }
 
-static __isl_give struct isl_upoly *reorder(__isl_take struct isl_upoly *up,
-       int *r)
-{
-       int i;
-       struct isl_upoly_rec *rec;
-       struct isl_upoly *base;
-       struct isl_upoly *res;
-
-       if (isl_upoly_is_cst(up))
-               return up;
-
-       rec = isl_upoly_as_rec(up);
-       if (!rec)
-               goto error;
-
-       isl_assert(up->ctx, rec->n >= 1, goto error);
-
-       base = isl_upoly_pow(up->ctx, r[up->var], 1);
-       res = reorder(isl_upoly_copy(rec->p[rec->n - 1]), r);
-
-       for (i = rec->n - 2; i >= 0; --i) {
-               res = isl_upoly_mul(res, isl_upoly_copy(base));
-               res = isl_upoly_sum(res, reorder(isl_upoly_copy(rec->p[i]), r));
-       }
-
-       isl_upoly_free(base);
-       isl_upoly_free(up);
-
-       return res;
-error:
-       isl_upoly_free(up);
-       return NULL;
-}
-
 __isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
        __isl_take isl_qpolynomial *qp,
        enum isl_dim_type dst_type, unsigned dst_pos,
@@ -2248,9 +2270,11 @@ __isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
                g_dst_pos -= n;
 
        qp->div = isl_mat_move_cols(qp->div, 2 + g_dst_pos, 2 + g_src_pos, n);
-       qp->div = sort_divs(qp->div);
        if (!qp->div)
                goto error;
+       qp = sort_divs(qp);
+       if (!qp)
+               goto error;
 
        reordering = reordering_move(qp->dim->ctx,
                                qp->div->n_col - 2, g_dst_pos, g_src_pos, n);
index dcb417d..14f633d 100644 (file)
@@ -14,6 +14,7 @@
 #include <isl_set.h>
 #include <isl_flow.h>
 #include <isl_constraint.h>
+#include <isl_polynomial.h>
 
 static char *srcdir;
 
@@ -1362,6 +1363,27 @@ void test_bijective(struct isl_ctx *ctx)
        test_bijective_case(ctx, "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1);
 }
 
+void test_pwqp(struct isl_ctx *ctx)
+{
+       const char *str;
+       isl_pw_qpolynomial *pwqp1, *pwqp2;
+
+       str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
+       pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+       pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
+                                               isl_dim_set, 1, 1);
+
+       str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
+       pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+       pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+
+       assert(isl_pw_qpolynomial_is_zero(pwqp1));
+
+       isl_pw_qpolynomial_free(pwqp1);
+}
+
 int main()
 {
        struct isl_ctx *ctx;
@@ -1370,6 +1392,7 @@ int main()
        assert(srcdir);
 
        ctx = isl_ctx_alloc();
+       test_pwqp(ctx);
        test_lex(ctx);
        test_sv(ctx);
        test_bijective(ctx);