isl_map_affine_hull: perform affine hull on underlying set
authorSven Verdoolaege <skimo@kotnet.org>
Sun, 17 Aug 2008 07:45:12 +0000 (09:45 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Mon, 25 Aug 2008 08:15:07 +0000 (10:15 +0200)
isl_affine_hull.c
isl_map.c
isl_map_private.h

index ad9cbaf..e8df67c 100644 (file)
@@ -75,42 +75,42 @@ struct isl_basic_set *isl_basic_set_affine_hull(struct isl_ctx *ctx,
  * after column col are zero.
  */
 static void set_common_multiple(
-       struct isl_basic_map *bmap1, struct isl_basic_map *bmap2,
+       struct isl_basic_set *bset1, struct isl_basic_set *bset2,
        unsigned row, unsigned col)
 {
        isl_int m, c;
 
-       if (isl_int_eq(bmap1->eq[row][col], bmap2->eq[row][col]))
+       if (isl_int_eq(bset1->eq[row][col], bset2->eq[row][col]))
                return;
 
        isl_int_init(c);
        isl_int_init(m);
-       isl_int_lcm(m, bmap1->eq[row][col], bmap2->eq[row][col]);
-       isl_int_divexact(c, m, bmap1->eq[row][col]);
-       isl_seq_scale(bmap1->eq[row], bmap1->eq[row], c, col+1);
-       isl_int_divexact(c, m, bmap2->eq[row][col]);
-       isl_seq_scale(bmap2->eq[row], bmap2->eq[row], c, col+1);
+       isl_int_lcm(m, bset1->eq[row][col], bset2->eq[row][col]);
+       isl_int_divexact(c, m, bset1->eq[row][col]);
+       isl_seq_scale(bset1->eq[row], bset1->eq[row], c, col+1);
+       isl_int_divexact(c, m, bset2->eq[row][col]);
+       isl_seq_scale(bset2->eq[row], bset2->eq[row], c, col+1);
        isl_int_clear(c);
        isl_int_clear(m);
 }
 
 /* Delete a given equality, moving all the following equalities one up.
  */
-static void delete_row(struct isl_basic_map *bmap, unsigned row)
+static void delete_row(struct isl_basic_set *bset, unsigned row)
 {
        isl_int *t;
        int r;
 
-       t = bmap->eq[row];
-       bmap->n_eq--;
-       for (r = row; r < bmap->n_eq; ++r)
-               bmap->eq[r] = bmap->eq[r+1];
-       bmap->eq[bmap->n_eq] = t;
+       t = bset->eq[row];
+       bset->n_eq--;
+       for (r = row; r < bset->n_eq; ++r)
+               bset->eq[r] = bset->eq[r+1];
+       bset->eq[bset->n_eq] = t;
 }
 
-/* Make first row entries in column col of bmap1 identical to
- * those of bmap2, using the fact that entry bmap1->eq[row][col]=a
- * is non-zero.  Initially, these elements of bmap1 are all zero.
+/* Make first row entries in column col of bset1 identical to
+ * those of bset2, using the fact that entry bset1->eq[row][col]=a
+ * is non-zero.  Initially, these elements of bset1 are all zero.
  * For each row i < row, we set
  *             A[i] = a * A[i] + B[i][col] * A[row]
  *             B[i] = a * B[i]
@@ -118,7 +118,7 @@ static void delete_row(struct isl_basic_map *bmap, unsigned row)
  *             A[i][col] = B[i][col] = a * old(B[i][col])
  */
 static void construct_column(
-       struct isl_basic_map *bmap1, struct isl_basic_map *bmap2,
+       struct isl_basic_set *bset1, struct isl_basic_set *bset2,
        unsigned row, unsigned col)
 {
        int r;
@@ -128,24 +128,24 @@ static void construct_column(
 
        isl_int_init(a);
        isl_int_init(b);
-       total = 1 + bmap1->nparam + bmap1->n_in + bmap1->n_out + bmap1->n_div;
+       total = 1 + bset1->dim;
        for (r = 0; r < row; ++r) {
-               if (isl_int_is_zero(bmap2->eq[r][col]))
+               if (isl_int_is_zero(bset2->eq[r][col]))
                        continue;
-               isl_int_gcd(b, bmap2->eq[r][col], bmap1->eq[row][col]);
-               isl_int_divexact(a, bmap1->eq[row][col], b);
-               isl_int_divexact(b, bmap2->eq[r][col], b);
-               isl_seq_combine(bmap1->eq[r], a, bmap1->eq[r],
-                                             b, bmap1->eq[row], total);
-               isl_seq_scale(bmap2->eq[r], bmap2->eq[r], a, total);
+               isl_int_gcd(b, bset2->eq[r][col], bset1->eq[row][col]);
+               isl_int_divexact(a, bset1->eq[row][col], b);
+               isl_int_divexact(b, bset2->eq[r][col], b);
+               isl_seq_combine(bset1->eq[r], a, bset1->eq[r],
+                                             b, bset1->eq[row], total);
+               isl_seq_scale(bset2->eq[r], bset2->eq[r], a, total);
        }
        isl_int_clear(a);
        isl_int_clear(b);
-       delete_row(bmap1, row);
+       delete_row(bset1, row);
 }
 
-/* Make first row entries in column col of bmap1 identical to
- * those of bmap2, using only these entries of the two matrices.
+/* Make first row entries in column col of bset1 identical to
+ * those of bset2, using only these entries of the two matrices.
  * Let t be the last row with different entries.
  * For each row i < t, we set
  *     A[i] = (A[t][col]-B[t][col]) * A[i] + (B[i][col]-A[i][col) * A[t]
@@ -154,7 +154,7 @@ static void construct_column(
  *     A[i][col] = B[i][col] = old(A[t][col]*B[i][col]-A[i][col]*B[t][col])
  */
 static int transform_column(
-       struct isl_basic_map *bmap1, struct isl_basic_map *bmap2,
+       struct isl_basic_set *bset1, struct isl_basic_set *bset2,
        unsigned row, unsigned col)
 {
        int i, t;
@@ -162,31 +162,31 @@ static int transform_column(
        unsigned total;
 
        for (t = row-1; t >= 0; --t)
-               if (isl_int_ne(bmap1->eq[t][col], bmap2->eq[t][col]))
+               if (isl_int_ne(bset1->eq[t][col], bset2->eq[t][col]))
                        break;
        if (t < 0)
                return 0;
 
-       total = 1 + bmap1->nparam + bmap1->n_in + bmap1->n_out + bmap1->n_div;
+       total = 1 + bset1->dim;
        isl_int_init(a);
        isl_int_init(b);
        isl_int_init(g);
-       isl_int_sub(b, bmap1->eq[t][col], bmap2->eq[t][col]);
+       isl_int_sub(b, bset1->eq[t][col], bset2->eq[t][col]);
        for (i = 0; i < t; ++i) {
-               isl_int_sub(a, bmap2->eq[i][col], bmap1->eq[i][col]);
+               isl_int_sub(a, bset2->eq[i][col], bset1->eq[i][col]);
                isl_int_gcd(g, a, b);
                isl_int_divexact(a, a, g);
                isl_int_divexact(g, b, g);
-               isl_seq_combine(bmap1->eq[i], g, bmap1->eq[i], a, bmap1->eq[t],
+               isl_seq_combine(bset1->eq[i], g, bset1->eq[i], a, bset1->eq[t],
                                total);
-               isl_seq_combine(bmap2->eq[i], g, bmap2->eq[i], a, bmap2->eq[t],
+               isl_seq_combine(bset2->eq[i], g, bset2->eq[i], a, bset2->eq[t],
                                total);
        }
        isl_int_clear(a);
        isl_int_clear(b);
        isl_int_clear(g);
-       delete_row(bmap1, t);
-       delete_row(bmap2, t);
+       delete_row(bset1, t);
+       delete_row(bset2, t);
        return 1;
 }
 
@@ -195,74 +195,91 @@ static int transform_column(
  * except that the echelon form we use starts from the last column
  * and that we are dealing with integer coefficients.
  */
-static struct isl_basic_map *affine_hull(struct isl_ctx *ctx,
-       struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+static struct isl_basic_set *affine_hull(struct isl_ctx *ctx,
+       struct isl_basic_set *bset1, struct isl_basic_set *bset2)
 {
        unsigned total;
        int col;
        int row;
 
-       total = 1 + bmap1->nparam + bmap1->n_in + bmap1->n_out + bmap1->n_div;
+       total = 1 + bset1->dim;
 
        row = 0;
        for (col = total-1; col >= 0; --col) {
-               int is_zero1 = row >= bmap1->n_eq ||
-                       isl_int_is_zero(bmap1->eq[row][col]);
-               int is_zero2 = row >= bmap2->n_eq ||
-                       isl_int_is_zero(bmap2->eq[row][col]);
+               int is_zero1 = row >= bset1->n_eq ||
+                       isl_int_is_zero(bset1->eq[row][col]);
+               int is_zero2 = row >= bset2->n_eq ||
+                       isl_int_is_zero(bset2->eq[row][col]);
                if (!is_zero1 && !is_zero2) {
-                       set_common_multiple(bmap1, bmap2, row, col);
+                       set_common_multiple(bset1, bset2, row, col);
                        ++row;
                } else if (!is_zero1 && is_zero2) {
-                       construct_column(bmap1, bmap2, row, col);
+                       construct_column(bset1, bset2, row, col);
                } else if (is_zero1 && !is_zero2) {
-                       construct_column(bmap2, bmap1, row, col);
+                       construct_column(bset2, bset1, row, col);
                } else {
-                       if (transform_column(bmap1, bmap2, row, col))
+                       if (transform_column(bset1, bset2, row, col))
                                --row;
                }
        }
-       isl_basic_map_free(ctx, bmap2);
-       return bmap1;
+       isl_basic_set_free(ctx, bset2);
+       return bset1;
 }
 
 struct isl_basic_map *isl_map_affine_hull(struct isl_ctx *ctx,
                                                struct isl_map *map)
 {
        int i;
-       struct isl_basic_map *bmap;
+       struct isl_basic_map *model = NULL;
+       struct isl_basic_map *hull = NULL;
+       struct isl_set *set;
 
        if (!map)
                return NULL;
 
        if (map->n == 0) {
-               bmap = isl_basic_map_empty(ctx,
+               hull = isl_basic_map_empty(ctx,
                                            map->nparam, map->n_in, map->n_out);
                isl_map_free(ctx, map);
-               return bmap;
+               return hull;
        }
 
        map = isl_map_align_divs(ctx, map);
-       map = isl_map_cow(ctx, map);
+       model = isl_basic_map_copy(ctx, map->p[0]);
+       set = isl_map_underlying_set(ctx, map);
+       set = isl_set_cow(ctx, set);
+       if (!set)
+               goto error;
 
-       for (i = 0; i < map->n; ++i) {
-               map->p[i] = isl_basic_map_cow(ctx, map->p[i]);
-               map->p[i] = isl_basic_map_affine_hull(ctx, map->p[i]);
-               map->p[i] = isl_basic_map_gauss(ctx, map->p[i], NULL);
-               if (!map->p[i])
+       for (i = 0; i < set->n; ++i) {
+               set->p[i] = isl_basic_set_cow(ctx, set->p[i]);
+               set->p[i] = isl_basic_set_affine_hull(ctx, set->p[i]);
+               set->p[i] = isl_basic_set_gauss(ctx, set->p[i], NULL);
+               if (!set->p[i])
                        goto error;
        }
-       while (map->n > 1) {
-               map->p[0] = affine_hull(ctx, map->p[0], map->p[--map->n]);
-               if (!map->p[0])
-                       goto error;
+       set = isl_set_remove_empty_parts(ctx, set);
+       if (set->n == 0) {
+               hull = isl_basic_map_empty(ctx,
+                                   model->nparam, model->n_in, model->n_out);
+               isl_basic_map_free(ctx, model);
+       } else {
+               struct isl_basic_set *bset;
+               while (set->n > 1) {
+                       set->p[0] = affine_hull(ctx, set->p[0],
+                                                       set->p[--set->n]);
+                       if (!set->p[0])
+                               goto error;
+               }
+               bset = isl_basic_set_copy(ctx, set->p[0]);
+               hull = isl_basic_map_overlying_set(ctx, bset, model);
        }
-       bmap = isl_basic_map_copy(ctx, map->p[0]);
-       isl_map_free(ctx, map);
-       bmap = isl_basic_map_simplify(ctx, bmap);
-       return isl_basic_map_finalize(ctx, bmap);
+       isl_set_free(ctx, set);
+       hull = isl_basic_map_simplify(ctx, hull);
+       return isl_basic_map_finalize(ctx, hull);
 error:
-       isl_map_free(ctx, map);
+       isl_basic_map_free(ctx, model);
+       isl_set_free(ctx, set);
        return NULL;
 }
 
index 033a1d3..fc001e9 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -489,7 +489,7 @@ struct isl_basic_map *isl_basic_map_cow(struct isl_ctx *ctx,
        return bmap;
 }
 
-static struct isl_set *isl_set_cow(struct isl_ctx *ctx, struct isl_set *set)
+struct isl_set *isl_set_cow(struct isl_ctx *ctx, struct isl_set *set)
 {
        if (!set)
                return NULL;
@@ -1776,6 +1776,37 @@ error:
        return NULL;
 }
 
+/* For a div d = floor(f/m), add the constraints
+ *
+ *             f - m d >= 0
+ *             -(f-(n-1)) + m d >= 0
+ *
+ * Note that the second constraint is the negation of
+ *
+ *             f - m d >= n
+ */
+static int add_div_constraints(struct isl_ctx *ctx,
+               struct isl_basic_map *bmap, unsigned div)
+{
+       int i, j;
+       unsigned div_pos = 1 + bmap->nparam + bmap->n_in + bmap->n_out + div;
+       unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra;
+
+       i = isl_basic_map_alloc_inequality(ctx, bmap);
+       if (i < 0)
+               return -1;
+       isl_seq_cpy(bmap->ineq[i], bmap->div[div]+1, 1+total);
+       isl_int_neg(bmap->ineq[i][div_pos], bmap->div[div][0]);
+
+       j = isl_basic_map_alloc_inequality(ctx, bmap);
+       if (j < 0)
+               return -1;
+       isl_seq_neg(bmap->ineq[j], bmap->ineq[i], 1 + total);
+       isl_int_add(bmap->ineq[j][0], bmap->ineq[j][0], bmap->ineq[j][div_pos]);
+       isl_int_sub_ui(bmap->ineq[j][0], bmap->ineq[j][0], 1);
+       return j;
+}
+
 static struct isl_basic_set *isl_basic_map_underlying_set(
                struct isl_ctx *ctx, struct isl_basic_map *bmap)
 {
@@ -1796,6 +1827,93 @@ error:
        return NULL;
 }
 
+struct isl_basic_map *isl_basic_map_overlying_set(
+       struct isl_ctx *ctx, struct isl_basic_set *bset,
+       struct isl_basic_map *like)
+{
+       struct isl_basic_map *bmap;
+       unsigned total;
+       int i, k;
+
+       if (!bset || !like)
+               goto error;
+       isl_assert(ctx, bset->dim ==
+                       like->nparam + like->n_in + like->n_out + like->n_div,
+                       goto error);
+       if (like->nparam == 0 && like->n_in == 0 && like->n_div == 0) {
+               isl_basic_map_free(ctx, like);
+               return (struct isl_basic_map *)bset;
+       }
+       bset = isl_basic_set_cow(ctx, bset);
+       total = bset->dim + bset->extra;
+       if (!bset)
+               goto error;
+       bmap = (struct isl_basic_map *)bset;
+       bmap->nparam = like->nparam;
+       bmap->n_in = like->n_in;
+       bmap->n_out = like->n_out;
+       bmap->extra += like->n_div;
+       if (bmap->extra) {
+               unsigned ltotal;
+               ltotal = total - bmap->extra + like->extra;
+               if (ltotal > total)
+                       ltotal = total;
+               bmap->block2 = isl_blk_extend(ctx, bmap->block2,
+                                       bmap->extra * (1 + 1 + total));
+               if (isl_blk_is_error(bmap->block2))
+                       goto error;
+               bmap->div = isl_realloc_array(ctx, bmap->div, isl_int *,
+                                               bmap->extra);
+               if (!bmap->div)
+                       goto error;
+               bmap = isl_basic_map_extend(ctx, bmap, bmap->nparam,
+                       bmap->n_in, bmap->n_out, 0, 0, 2 * like->n_div);
+               for (i = 0; i < like->n_div; ++i) {
+                       k = isl_basic_map_alloc_div(ctx, bmap);
+                       if (k < 0)
+                               goto error;
+                       isl_seq_cpy(bmap->div[k], like->div[i], 1 + 1 + ltotal);
+                       isl_seq_clr(bmap->div[k]+1+1+ltotal, total - ltotal);
+                       if (add_div_constraints(ctx, bmap, k) < 0)
+                               goto error;
+               }
+       }
+       isl_basic_map_free(ctx, like);
+       bmap = isl_basic_map_finalize(ctx, bmap);
+       return bmap;
+error:
+       isl_basic_map_free(ctx, like);
+       isl_basic_set_free(ctx, bset);
+       return NULL;
+}
+
+struct isl_set *isl_map_underlying_set(struct isl_ctx *ctx, struct isl_map *map)
+{
+       int i;
+
+       map = isl_map_align_divs(ctx, map);
+       map = isl_map_cow(ctx, map);
+       if (!map)
+               return NULL;
+
+       for (i = 0; i < map->n; ++i) {
+               map->p[i] = (struct isl_basic_map *)
+                               isl_basic_map_underlying_set(ctx, map->p[i]);
+               if (!map->p[i])
+                       goto error;
+       }
+       if (map->n == 0)
+               map->n_out += map->nparam + map->n_in;
+       else
+               map->n_out = map->p[0]->n_out;
+       map->nparam = 0;
+       map->n_in = 0;
+       return (struct isl_set *)map;
+error:
+       isl_map_free(ctx, map);
+       return NULL;
+}
+
 struct isl_basic_set *isl_basic_map_domain(struct isl_ctx *ctx,
                struct isl_basic_map *bmap)
 {
@@ -2793,37 +2911,6 @@ static int find_div(struct isl_basic_map *dst,
        return -1;
 }
 
-/* For a div d = floor(f/m), add the constraints
- *
- *             f - m d >= 0
- *             -(f-(n-1)) + m d >= 0
- *
- * Note that the second constraint is the negation of
- *
- *             f - m d >= n
- */
-static int add_div_constraints(struct isl_ctx *ctx,
-               struct isl_basic_map *bmap, unsigned div)
-{
-       int i, j;
-       unsigned div_pos = 1 + bmap->nparam + bmap->n_in + bmap->n_out + div;
-       unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra;
-
-       i = isl_basic_map_alloc_inequality(ctx, bmap);
-       if (i < 0)
-               return -1;
-       isl_seq_cpy(bmap->ineq[i], bmap->div[div]+1, 1+total);
-       isl_int_neg(bmap->ineq[i][div_pos], bmap->div[div][0]);
-
-       j = isl_basic_map_alloc_inequality(ctx, bmap);
-       if (j < 0)
-               return -1;
-       isl_seq_neg(bmap->ineq[j], bmap->ineq[i], 1 + total);
-       isl_int_add(bmap->ineq[j][0], bmap->ineq[j][0], bmap->ineq[j][div_pos]);
-       isl_int_sub_ui(bmap->ineq[j][0], bmap->ineq[j][0], 1);
-       return j;
-}
-
 struct isl_basic_map *isl_basic_map_align_divs(struct isl_ctx *ctx,
                struct isl_basic_map *dst, struct isl_basic_map *src)
 {
index fd713b9..7f980e0 100644 (file)
@@ -27,6 +27,7 @@ struct isl_basic_set *isl_basic_set_cow(struct isl_ctx *ctx,
                struct isl_basic_set *bset);
 struct isl_basic_map *isl_basic_map_cow(struct isl_ctx *ctx,
                struct isl_basic_map *bmap);
+struct isl_set *isl_set_cow(struct isl_ctx *ctx, struct isl_set *set);
 struct isl_map *isl_map_cow(struct isl_ctx *ctx, struct isl_map *map);
 
 struct isl_basic_map *isl_basic_map_set_to_empty(
@@ -43,6 +44,10 @@ struct isl_basic_map *isl_basic_map_gauss(struct isl_ctx *ctx,
        struct isl_basic_map *bmap, int *progress);
 struct isl_basic_set *isl_basic_set_gauss(struct isl_ctx *ctx,
        struct isl_basic_set *bset, int *progress);
+struct isl_set *isl_map_underlying_set(struct isl_ctx *ctx, struct isl_map *map);
+struct isl_basic_map *isl_basic_map_overlying_set(
+       struct isl_ctx *ctx, struct isl_basic_set *bset,
+       struct isl_basic_map *like);
 
 struct isl_map *isl_map_remove_empty_parts(struct isl_ctx *ctx,
        struct isl_map *map);