Merge branch 'maint'
[platform/upstream/isl.git] / isl_map_simplify.c
index 84e8d1a..e733cbd 100644 (file)
@@ -7,11 +7,14 @@
  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
  */
 
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
 #include "isl_equalities.h"
-#include "isl_map.h"
-#include "isl_map_private.h"
-#include "isl_seq.h"
+#include <isl/map.h>
+#include <isl/seq.h>
 #include "isl_tab.h"
+#include <isl_dim_private.h>
+#include <isl_mat_private.h>
 
 static void swap_equality(struct isl_basic_map *bmap, int a, int b)
 {
@@ -57,7 +60,7 @@ struct isl_basic_set *isl_basic_set_drop_dims(
 
        isl_assert(bset->ctx, first + n <= bset->dim->n_out, goto error);
 
-       if (n == 0)
+       if (n == 0 && !isl_dim_get_tuple_name(bset->dim, isl_dim_set))
                return bset;
 
        bset = isl_basic_set_cow(bset);
@@ -98,7 +101,7 @@ struct isl_set *isl_set_drop_dims(
 
        isl_assert(set->ctx, first + n <= set->dim->n_out, goto error);
 
-       if (n == 0)
+       if (n == 0 && !isl_dim_get_tuple_name(set->dim, isl_dim_set))
                return set;
        set = isl_set_cow(set);
        if (!set)
@@ -168,7 +171,7 @@ struct isl_basic_map *isl_basic_map_drop(struct isl_basic_map *bmap,
        dim = isl_basic_map_dim(bmap, type);
        isl_assert(bmap->ctx, first + n <= dim, goto error);
 
-       if (n == 0)
+       if (n == 0 && !isl_dim_get_tuple_name(bmap->dim, type))
                return bmap;
 
        bmap = isl_basic_map_cow(bmap);
@@ -204,6 +207,13 @@ error:
        return NULL;
 }
 
+__isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
+       enum isl_dim_type type, unsigned first, unsigned n)
+{
+       return (isl_basic_set *)isl_basic_map_drop((isl_basic_map *)bset,
+                                                       type, first, n);
+}
+
 struct isl_basic_map *isl_basic_map_drop_inputs(
                struct isl_basic_map *bmap, unsigned first, unsigned n)
 {
@@ -220,7 +230,7 @@ struct isl_map *isl_map_drop(struct isl_map *map,
 
        isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
 
-       if (n == 0)
+       if (n == 0 && !isl_dim_get_tuple_name(map->dim, type))
                return map;
        map = isl_map_cow(map);
        if (!map)
@@ -310,6 +320,9 @@ struct isl_basic_map *isl_basic_map_normalize_constraints(
        isl_int gcd;
        unsigned total = isl_basic_map_total_dim(bmap);
 
+       if (!bmap)
+               return NULL;
+
        isl_int_init(gcd);
        for (i = bmap->n_eq - 1; i >= 0; --i) {
                isl_seq_gcd(bmap->eq[i]+1, total, &gcd);
@@ -381,6 +394,7 @@ static void eliminate_var_using_equality(struct isl_basic_map *bmap,
                if (progress)
                        *progress = 1;
                isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL);
+               isl_seq_normalize(bmap->ctx, bmap->eq[k], 1 + total);
        }
 
        for (k = 0; k < bmap->n_ineq; ++k) {
@@ -389,6 +403,7 @@ static void eliminate_var_using_equality(struct isl_basic_map *bmap,
                if (progress)
                        *progress = 1;
                isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL);
+               isl_seq_normalize(bmap->ctx, bmap->ineq[k], 1 + total);
                ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
        }
 
@@ -517,7 +532,7 @@ static struct isl_basic_map *eliminate_divs_ineq(
                        continue;
                *progress = 1;
                bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1);
-               if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+               if (!bmap || ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
                        break;
                bmap = isl_basic_map_drop_div(bmap, d);
                if (!bmap)
@@ -635,13 +650,16 @@ static struct isl_basic_map *remove_duplicate_divs(
        int k, l, h;
        int bits;
        struct isl_blk eq;
-       unsigned total_var = isl_dim_total(bmap->dim);
-       unsigned total = total_var + bmap->n_div;
+       unsigned total_var;
+       unsigned total;
        struct isl_ctx *ctx;
 
-       if (bmap->n_div <= 1)
+       if (!bmap || bmap->n_div <= 1)
                return bmap;
 
+       total_var = isl_dim_total(bmap->dim);
+       total = total_var + bmap->n_div;
+
        ctx = bmap->ctx;
        for (k = bmap->n_div - 1; k >= 0; --k)
                if (!isl_int_is_zero(bmap->div[k][0]))
@@ -795,7 +813,7 @@ static struct isl_basic_map *normalize_divs(
                return bmap;
 
        if (div_eq < bmap->n_eq) {
-               B = isl_mat_sub_alloc(bmap->ctx, bmap->eq, div_eq,
+               B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, div_eq,
                                        bmap->n_eq - div_eq, 0, 1 + total);
                C = isl_mat_variable_compression(B, &C2);
                if (!C || !C2)
@@ -816,7 +834,7 @@ static struct isl_basic_map *normalize_divs(
                        --j;
                isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j]);
        }
-       B = isl_mat_sub_alloc(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total);
+       B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total);
 
        if (C) {
                B = isl_mat_product(B, C);
@@ -841,6 +859,8 @@ static struct isl_basic_map *normalize_divs(
        }
        isl_int_clear(v);
        pos = isl_alloc_array(bmap->ctx, int, T->n_row);
+       if (!pos)
+               goto error;
        /* We have to be careful because dropping equalities may reorder them */
        dropped = 0;
        for (j = bmap->n_div - 1; j >= 0; --j) {
@@ -996,7 +1016,7 @@ static struct isl_basic_map *check_for_div_constraints(
 }
 
 static struct isl_basic_map *remove_duplicate_constraints(
-       struct isl_basic_map *bmap, int *progress)
+       struct isl_basic_map *bmap, int *progress, int detect_divs)
 {
        unsigned int size;
        isl_int ***index;
@@ -1005,7 +1025,7 @@ static struct isl_basic_map *remove_duplicate_constraints(
        unsigned total = isl_basic_map_total_dim(bmap);
        isl_int sum;
 
-       if (bmap->n_ineq <= 1)
+       if (!bmap || bmap->n_ineq <= 1)
                return bmap;
 
        size = round_up(4 * (bmap->n_ineq+1) / 3 - 1);
@@ -1039,8 +1059,9 @@ static struct isl_basic_map *remove_duplicate_constraints(
                l = index[h] - &bmap->ineq[0];
                isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0]);
                if (isl_int_is_pos(sum)) {
-                       bmap = check_for_div_constraints(bmap, k, l, sum,
-                                                        progress);
+                       if (detect_divs)
+                               bmap = check_for_div_constraints(bmap, k, l,
+                                                                sum, progress);
                        continue;
                }
                if (isl_int_is_zero(sum)) {
@@ -1078,7 +1099,7 @@ struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap)
                bmap = isl_basic_map_gauss(bmap, &progress);
                /* requires equalities in normal form */
                bmap = normalize_divs(bmap, &progress);
-               bmap = remove_duplicate_constraints(bmap, &progress);
+               bmap = remove_duplicate_constraints(bmap, &progress, 1);
        }
        return bmap;
 }
@@ -1090,6 +1111,43 @@ struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset)
 }
 
 
+int isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap,
+       isl_int *constraint, unsigned div)
+{
+       unsigned pos;
+
+       if (!bmap)
+               return -1;
+
+       pos = 1 + isl_dim_total(bmap->dim) + div;
+
+       if (isl_int_eq(constraint[pos], bmap->div[div][0])) {
+               int neg;
+               isl_int_sub(bmap->div[div][1],
+                               bmap->div[div][1], bmap->div[div][0]);
+               isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1);
+               neg = isl_seq_is_neg(constraint, bmap->div[div]+1, pos);
+               isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
+               isl_int_add(bmap->div[div][1],
+                               bmap->div[div][1], bmap->div[div][0]);
+               if (!neg)
+                       return 0;
+               if (isl_seq_first_non_zero(constraint+pos+1,
+                                           bmap->n_div-div-1) != -1)
+                       return 0;
+       } else if (isl_int_abs_eq(constraint[pos], bmap->div[div][0])) {
+               if (!isl_seq_eq(constraint, bmap->div[div]+1, pos))
+                       return 0;
+               if (isl_seq_first_non_zero(constraint+pos+1,
+                                           bmap->n_div-div-1) != -1)
+                       return 0;
+       } else
+               return 0;
+
+       return 1;
+}
+
+
 /* If the only constraints a div d=floor(f/m)
  * appears in are its two defining constraints
  *
@@ -1110,27 +1168,7 @@ static int div_is_redundant(struct isl_basic_map *bmap, int div)
        for (i = 0; i < bmap->n_ineq; ++i) {
                if (isl_int_is_zero(bmap->ineq[i][pos]))
                        continue;
-               if (isl_int_eq(bmap->ineq[i][pos], bmap->div[div][0])) {
-                       int neg;
-                       isl_int_sub(bmap->div[div][1],
-                                       bmap->div[div][1], bmap->div[div][0]);
-                       isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1);
-                       neg = isl_seq_is_neg(bmap->ineq[i], bmap->div[div]+1, pos);
-                       isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
-                       isl_int_add(bmap->div[div][1],
-                                       bmap->div[div][1], bmap->div[div][0]);
-                       if (!neg)
-                               return 0;
-                       if (isl_seq_first_non_zero(bmap->ineq[i]+pos+1,
-                                                   bmap->n_div-div-1) != -1)
-                               return 0;
-               } else if (isl_int_abs_eq(bmap->ineq[i][pos], bmap->div[div][0])) {
-                       if (!isl_seq_eq(bmap->ineq[i], bmap->div[div]+1, pos))
-                               return 0;
-                       if (isl_seq_first_non_zero(bmap->ineq[i]+pos+1,
-                                                   bmap->n_div-div-1) != -1)
-                               return 0;
-               } else
+               if (!isl_basic_map_is_div_constraint(bmap, bmap->ineq[i], div))
                        return 0;
        }
 
@@ -1277,6 +1315,8 @@ struct isl_basic_map *isl_basic_map_eliminate_vars(
                }
                bmap = isl_basic_map_extend_constraints(bmap,
                                0, n_lower * n_upper);
+               if (!bmap)
+                       goto error;
                for (i = bmap->n_ineq - 1; i >= 0; --i) {
                        int last;
                        if (isl_int_is_zero(bmap->ineq[i][1+d]))
@@ -1302,9 +1342,9 @@ struct isl_basic_map *isl_basic_map_eliminate_vars(
                }
                if (n_lower > 0 && n_upper > 0) {
                        bmap = isl_basic_map_normalize_constraints(bmap);
-                       bmap = remove_duplicate_constraints(bmap, NULL);
+                       bmap = remove_duplicate_constraints(bmap, NULL, 0);
                        bmap = isl_basic_map_gauss(bmap, NULL);
-                       bmap = isl_basic_map_convex_hull(bmap);
+                       bmap = isl_basic_map_remove_redundancies(bmap);
                        if (!bmap)
                                goto error;
                        if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
@@ -1398,7 +1438,7 @@ static struct isl_basic_set *isl_basic_set_reduce_using_equalities(
        if (!bset)
                goto error;
 
-       elim = isl_alloc_array(ctx, int, isl_basic_set_n_dim(bset));
+       elim = isl_alloc_array(bset->ctx, int, isl_basic_set_n_dim(bset));
        if (!elim)
                goto error;
        set_compute_elimination_index(context, elim);
@@ -1519,7 +1559,7 @@ static struct isl_basic_set *normalize_constraints_in_compressed_space(
                return NULL;
 
        total = isl_basic_set_total_dim(bset);
-       B = isl_mat_sub_alloc(bset->ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
+       B = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
        C = isl_mat_variable_compression(B, NULL);
        if (!C)
                return bset;
@@ -1527,7 +1567,7 @@ static struct isl_basic_set *normalize_constraints_in_compressed_space(
                isl_mat_free(C);
                return isl_basic_set_set_to_empty(bset);
        }
-       B = isl_mat_sub_alloc(bset->ctx, bset->ineq,
+       B = isl_mat_sub_alloc6(bset->ctx, bset->ineq,
                                                0, bset->n_ineq, 0, 1 + total);
        C = isl_mat_product(B, C);
        if (!C)
@@ -1663,6 +1703,13 @@ error:
  * We first compute the integer affine hull of the intersection,
  * compute the gist inside this affine hull and then add back
  * those equalities that are not implied by the context.
+ *
+ * If two constraints are mutually redundant, then uset_gist_full
+ * will remove the second of those constraints.  We therefore first
+ * sort the constraints so that constraints not involving existentially
+ * quantified variables are given precedence over those that do.
+ * We have to perform this sorting before the variable compression,
+ * because that may effect the order of the variables.
  */
 static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
        __isl_take isl_basic_set *context)
@@ -1681,6 +1728,7 @@ static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
                isl_basic_set_free(context);
                return bset;
        }
+       bset = isl_basic_set_sort_constraints(bset);
        aff = isl_basic_set_affine_hull(isl_basic_set_copy(bset));
        if (!aff)
                goto error;
@@ -1694,7 +1742,7 @@ static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
                return uset_gist_full(bset, context);
        }
        total = isl_basic_set_total_dim(bset);
-       eq = isl_mat_sub_alloc(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total);
+       eq = isl_mat_sub_alloc6(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total);
        eq = isl_mat_cow(eq);
        T = isl_mat_variable_compression(eq, &T2);
        if (T && T->n_col == 0) {
@@ -1772,10 +1820,6 @@ struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
        if (!bmap || !context)
                goto error;
 
-       if (isl_basic_map_is_universe(context)) {
-               isl_basic_map_free(context);
-               return bmap;
-       }
        if (isl_basic_map_is_universe(bmap)) {
                isl_basic_map_free(context);
                return bmap;
@@ -1791,8 +1835,8 @@ struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
                return bmap;
        }
 
-       bmap = isl_basic_map_convex_hull(bmap);
-       context = isl_basic_map_convex_hull(context);
+       bmap = isl_basic_map_remove_redundancies(bmap);
+       context = isl_basic_map_remove_redundancies(context);
 
        if (context->n_eq)
                bmap = normalize_divs_in_context(bmap, context);
@@ -1821,10 +1865,6 @@ __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
        if (!map || !context)
                goto error;;
 
-       if (isl_basic_map_is_universe(context)) {
-               isl_basic_map_free(context);
-               return map;
-       }
        if (isl_basic_map_fast_is_empty(context)) {
                struct isl_dim *dim = isl_dim_copy(map->dim);
                isl_basic_map_free(context);
@@ -1832,7 +1872,7 @@ __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
                return isl_map_universe(dim);
        }
 
-       context = isl_basic_map_convex_hull(context);
+       context = isl_basic_map_remove_redundancies(context);
        map = isl_map_cow(map);
        if (!map || !context)
                goto error;;
@@ -1840,11 +1880,17 @@ __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
        map = isl_map_compute_divs(map);
        for (i = 0; i < map->n; ++i)
                context = isl_basic_map_align_divs(context, map->p[i]);
-       for (i = 0; i < map->n; ++i) {
+       for (i = map->n - 1; i >= 0; --i) {
                map->p[i] = isl_basic_map_gist(map->p[i],
                                                isl_basic_map_copy(context));
                if (!map->p[i])
                        goto error;
+               if (isl_basic_map_fast_is_empty(map->p[i])) {
+                       isl_basic_map_free(map->p[i]);
+                       if (i != map->n - 1)
+                               map->p[i] = map->p[map->n - 1];
+                       map->n--;
+               }
        }
        isl_basic_map_free(context);
        ISL_F_CLR(map, ISL_MAP_NORMALIZED);
@@ -1858,7 +1904,8 @@ error:
 __isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
        __isl_take isl_map *context)
 {
-       return isl_map_gist_basic_map(map, isl_map_convex_hull(context));
+       context = isl_map_compute_divs(context);
+       return isl_map_gist_basic_map(map, isl_map_simple_hull(context));
 }
 
 struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset,
@@ -2227,7 +2274,7 @@ static struct isl_basic_map *drop_more_redundant_divs(
        if (remove < 0)
                return bmap;
 
-       bmap = isl_basic_map_remove(bmap, isl_dim_div, remove, 1);
+       bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, remove, 1);
        return isl_basic_map_drop_redundant_divs(bmap);
 error:
        free(pairs);