fix some icc warnings
[platform/upstream/isl.git] / isl_tab.c
index 0666d6b..d0d9c26 100644 (file)
--- a/isl_tab.c
+++ b/isl_tab.c
@@ -1,3 +1,12 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the GNU LGPLv2.1 license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
 #include "isl_mat.h"
 #include "isl_map_private.h"
 #include "isl_tab.h"
@@ -733,6 +742,8 @@ int isl_tab_row_is_redundant(struct isl_tab *tab, int row)
 static void swap_rows(struct isl_tab *tab, int row1, int row2)
 {
        int t;
+       enum isl_tab_row_sign s;
+
        t = tab->row_var[row1];
        tab->row_var[row1] = tab->row_var[row2];
        tab->row_var[row2] = t;
@@ -742,9 +753,9 @@ static void swap_rows(struct isl_tab *tab, int row1, int row2)
 
        if (!tab->row_sign)
                return;
-       t = tab->row_sign[row1];
+       s = tab->row_sign[row1];
        tab->row_sign[row1] = tab->row_sign[row2];
-       tab->row_sign[row2] = t;
+       tab->row_sign[row2] = s;
 }
 
 static int push_union(struct isl_tab *tab,
@@ -1156,9 +1167,16 @@ static void check_table(struct isl_tab *tab)
 
        if (tab->empty)
                return;
-       for (i = 0; i < tab->n_row; ++i) {
-               if (!isl_tab_var_from_row(tab, i)->is_nonneg)
+       for (i = tab->n_redundant; i < tab->n_row; ++i) {
+               struct isl_tab_var *var;
+               var = isl_tab_var_from_row(tab, i);
+               if (!var->is_nonneg)
                        continue;
+               if (tab->M) {
+                       assert(!isl_int_is_neg(tab->mat->row[i][2]));
+                       if (isl_int_is_pos(tab->mat->row[i][2]))
+                               continue;
+               }
                assert(!isl_int_is_neg(tab->mat->row[i][1]));
        }
 }
@@ -1345,7 +1363,8 @@ static int row_at_most_neg_one(struct isl_tab *tab, int row)
  * Return 0 otherwise.
  *
  * The sample value of "var" is assumed to be non-negative when the
- * the function is called and will be made non-negative again before
+ * the function is called.  If 1 is returned then the constraint
+ * is not redundant and the sample value is made non-negative again before
  * the function returns.
  */
 int isl_tab_min_at_most_neg_one(struct isl_tab *tab, struct isl_tab_var *var)
@@ -1380,8 +1399,11 @@ int isl_tab_min_at_most_neg_one(struct isl_tab *tab, struct isl_tab_var *var)
                return 0;
        do {
                find_pivot(tab, var, var, -1, &row, &col);
-               if (row == var->index)
+               if (row == var->index) {
+                       if (restore_row(tab, var) < -1)
+                               return -1;
                        return 1;
+               }
                if (row == -1)
                        return 0;
                pivot_var = var_from_col(tab, col);
@@ -1623,7 +1645,7 @@ int isl_tab_add_row(struct isl_tab *tab, isl_int *line)
        isl_int_clear(b);
 
        if (tab->row_sign)
-               tab->row_sign[tab->con[r].index] = 0;
+               tab->row_sign[tab->con[r].index] = isl_tab_row_unknown;
 
        return r;
 }
@@ -1926,6 +1948,150 @@ error:
        return NULL;
 }
 
+/* Construct and return an inequality that expresses an upper bound
+ * on the given div.
+ * In particular, if the div is given by
+ *
+ *     d = floor(e/m)
+ *
+ * then the inequality expresses
+ *
+ *     m d <= e
+ */
+static struct isl_vec *ineq_for_div(struct isl_basic_map *bmap, unsigned div)
+{
+       unsigned total;
+       unsigned div_pos;
+       struct isl_vec *ineq;
+
+       if (!bmap)
+               return NULL;
+
+       total = isl_basic_map_total_dim(bmap);
+       div_pos = 1 + total - bmap->n_div + div;
+
+       ineq = isl_vec_alloc(bmap->ctx, 1 + total);
+       if (!ineq)
+               return NULL;
+
+       isl_seq_cpy(ineq->el, bmap->div[div] + 1, 1 + total);
+       isl_int_neg(ineq->el[div_pos], bmap->div[div][0]);
+       return ineq;
+}
+
+/* For a div d = floor(f/m), add the constraints
+ *
+ *             f - m d >= 0
+ *             -(f-(m-1)) + m d >= 0
+ *
+ * Note that the second constraint is the negation of
+ *
+ *             f - m d >= m
+ *
+ * If add_ineq is not NULL, then this function is used
+ * instead of isl_tab_add_ineq to effectively add the inequalities.
+ */
+static int add_div_constraints(struct isl_tab *tab, unsigned div,
+       int (*add_ineq)(void *user, isl_int *), void *user)
+{
+       unsigned total;
+       unsigned div_pos;
+       struct isl_vec *ineq;
+
+       total = isl_basic_map_total_dim(tab->bmap);
+       div_pos = 1 + total - tab->bmap->n_div + div;
+
+       ineq = ineq_for_div(tab->bmap, div);
+       if (!ineq)
+               goto error;
+
+       if (add_ineq) {
+               if (add_ineq(user, ineq->el) < 0)
+                       goto error;
+       } else {
+               if (isl_tab_add_ineq(tab, ineq->el) < 0)
+                       goto error;
+       }
+
+       isl_seq_neg(ineq->el, tab->bmap->div[div] + 1, 1 + total);
+       isl_int_set(ineq->el[div_pos], tab->bmap->div[div][0]);
+       isl_int_add(ineq->el[0], ineq->el[0], ineq->el[div_pos]);
+       isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+
+       if (add_ineq) {
+               if (add_ineq(user, ineq->el) < 0)
+                       goto error;
+       } else {
+               if (isl_tab_add_ineq(tab, ineq->el) < 0)
+                       goto error;
+       }
+
+       isl_vec_free(ineq);
+
+       return 0;
+error:
+       isl_vec_free(ineq);
+       return -1;
+}
+
+/* Add an extra div, prescrived by "div" to the tableau and
+ * the associated bmap (which is assumed to be non-NULL).
+ *
+ * If add_ineq is not NULL, then this function is used instead
+ * of isl_tab_add_ineq to add the div constraints.
+ * This complication is needed because the code in isl_tab_pip
+ * wants to perform some extra processing when an inequality
+ * is added to the tableau.
+ */
+int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div,
+       int (*add_ineq)(void *user, isl_int *), void *user)
+{
+       int i;
+       int r;
+       int k;
+       int nonneg;
+
+       if (!tab || !div)
+               return -1;
+
+       isl_assert(tab->mat->ctx, tab->bmap, return -1);
+
+       for (i = 0; i < tab->n_var; ++i) {
+               if (isl_int_is_neg(div->el[2 + i]))
+                       break;
+               if (isl_int_is_zero(div->el[2 + i]))
+                       continue;
+               if (!tab->var[i].is_nonneg)
+                       break;
+       }
+       nonneg = i == tab->n_var && !isl_int_is_neg(div->el[1]);
+
+       if (isl_tab_extend_cons(tab, 3) < 0)
+               return -1;
+       if (isl_tab_extend_vars(tab, 1) < 0)
+               return -1;
+       r = isl_tab_allocate_var(tab);
+       if (r < 0)
+               return -1;
+
+       if (nonneg)
+               tab->var[r].is_nonneg = 1;
+
+       tab->bmap = isl_basic_map_extend_dim(tab->bmap,
+               isl_basic_map_get_dim(tab->bmap), 1, 0, 2);
+       k = isl_basic_map_alloc_div(tab->bmap);
+       if (k < 0)
+               return -1;
+       isl_seq_cpy(tab->bmap->div[k], div->el, div->size);
+       if (isl_tab_push(tab, isl_tab_undo_bmap_div) < 0)
+               return -1;
+
+       if (add_div_constraints(tab, k, add_ineq, user) < 0)
+               return -1;
+
+       return r;
+}
+
 struct isl_tab *isl_tab_from_basic_map(struct isl_basic_map *bmap)
 {
        int i;
@@ -2154,6 +2320,8 @@ struct isl_basic_map *isl_basic_map_update_from_tab(struct isl_basic_map *bmap,
                        else if (isl_tab_is_redundant(tab, n_eq + i))
                                isl_basic_map_drop_inequality(bmap, i);
                }
+       if (bmap->n_eq != n_eq)
+               isl_basic_map_gauss(bmap, NULL);
        if (!tab->rational &&
            !bmap->sample && isl_tab_sample_is_integer(tab))
                bmap->sample = extract_integer_sample(tab);
@@ -2187,6 +2355,7 @@ static struct isl_tab *cut_to_hyperplane(struct isl_tab *tab,
        if (var->is_zero)
                return tab;
        isl_assert(tab->mat->ctx, !var->is_redundant, goto error);
+       isl_assert(tab->mat->ctx, var->is_nonneg, goto error);
 
        if (isl_tab_extend_cons(tab, 1) < 0)
                goto error;
@@ -2246,6 +2415,14 @@ error:
  * If r is a column variable, then we need to modify each row that
  * refers to r = r' - 1 by substituting this equality, effectively
  * subtracting the coefficient of the column from the constant.
+ * We should only do this if the minimum is manifestly unbounded,
+ * however.  Otherwise, we may end up with negative sample values
+ * for non-negative variables.
+ * So, if r is a column variable with a minimum that is not
+ * manifestly unbounded, then we need to move it to a row.
+ * However, the sample value of this row may be negative,
+ * even after the relaxation, so we need to restore it.
+ * We therefore prefer to pivot a column up to a row, if possible.
  */
 struct isl_tab *isl_tab_relax(struct isl_tab *tab, int con)
 {
@@ -2260,11 +2437,16 @@ struct isl_tab *isl_tab_relax(struct isl_tab *tab, int con)
        if (!var->is_row && !max_is_manifestly_unbounded(tab, var))
                if (to_row(tab, var, 1) < 0)
                        goto error;
+       if (!var->is_row && !min_is_manifestly_unbounded(tab, var))
+               if (to_row(tab, var, -1) < 0)
+                       goto error;
 
-       if (var->is_row)
+       if (var->is_row) {
                isl_int_add(tab->mat->row[var->index][1],
                    tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
-       else {
+               if (restore_row(tab, var) < 0)
+                       goto error;
+       } else {
                int i;
 
                for (i = 0; i < tab->n_row; ++i) {
@@ -2615,10 +2797,14 @@ static int unrelax(struct isl_tab *tab, struct isl_tab_var *var)
                if (to_row(tab, var, 1) < 0)
                        return -1;
 
-       if (var->is_row)
+       if (var->is_row) {
                isl_int_sub(tab->mat->row[var->index][1],
                    tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
-       else {
+               if (var->is_nonneg) {
+                       int sgn = restore_row(tab, var);
+                       isl_assert(tab->mat->ctx, sgn >= 0, return -1);
+               }
+       } else {
                int i;
 
                for (i = 0; i < tab->n_row; ++i) {
@@ -2644,6 +2830,7 @@ static int perform_undo_var(struct isl_tab *tab, struct isl_tab_undo *undo)
        case isl_tab_undo_redundant:
                var->is_redundant = 0;
                tab->n_redundant--;
+               restore_row(tab, isl_tab_var_from_row(tab, tab->n_redundant));
                break;
        case isl_tab_undo_freeze:
                var->frozen = 0;