tab->mat = isl_mat_swap_rows(tab->mat, row1, row2);
}
-static void push(struct isl_tab *tab,
- enum isl_tab_undo_type type, struct isl_tab_var *var)
+static void push_union(struct isl_tab *tab,
+ enum isl_tab_undo_type type, union isl_tab_undo_val u)
{
struct isl_tab_undo *undo;
return;
}
undo->type = type;
- if (!var)
- undo->var_index = 0;
- else if (var->is_row)
- undo->var_index = tab->row_var[var->index];
- else
- undo->var_index = tab->col_var[var->index];
+ undo->u = u;
undo->next = tab->top;
tab->top = undo;
}
+void push_var(struct isl_tab *tab,
+ enum isl_tab_undo_type type, struct isl_tab_var *var)
+{
+ union isl_tab_undo_val u;
+ if (var->is_row)
+ u.var_index = tab->row_var[var->index];
+ else
+ u.var_index = tab->col_var[var->index];
+ push_union(tab, type, u);
+}
+
+void push(struct isl_tab *tab, enum isl_tab_undo_type type)
+{
+ union isl_tab_undo_val u = { 0 };
+ push_union(tab, type, u);
+}
+
/* Mark row with index "row" as being redundant.
* If we may need to undo the operation or if the row represents
* a variable of the original problem, the row is kept,
if (tab->need_undo || tab->row_var[row] >= 0) {
if (tab->row_var[row] >= 0 && !var->is_nonneg) {
var->is_nonneg = 1;
- push(tab, isl_tab_undo_nonneg, var);
+ push_var(tab, isl_tab_undo_nonneg, var);
}
if (row != tab->n_redundant)
swap_rows(tab, row, tab->n_redundant);
- push(tab, isl_tab_undo_redundant, var);
+ push_var(tab, isl_tab_undo_redundant, var);
tab->n_redundant++;
return 0;
} else {
static struct isl_tab *mark_empty(struct isl_tab *tab)
{
if (!tab->empty && tab->need_undo)
- push(tab, isl_tab_undo_empty, NULL);
+ push(tab, isl_tab_undo_empty);
tab->empty = 1;
return tab;
}
{
var_from_col(tab, col)->is_zero = 1;
if (tab->need_undo) {
- push(tab, isl_tab_undo_zero, var_from_col(tab, col));
+ push_var(tab, isl_tab_undo_zero, var_from_col(tab, col));
if (col != tab->n_dead)
swap_cols(tab, col, tab->n_dead);
tab->n_dead++;
tab->n_row++;
tab->n_con++;
- push(tab, isl_tab_undo_allocate, &tab->con[r]);
+ push_var(tab, isl_tab_undo_allocate, &tab->con[r]);
return r;
}
if (r < 0)
goto error;
tab->con[r].is_nonneg = 1;
- push(tab, isl_tab_undo_nonneg, &tab->con[r]);
+ push_var(tab, isl_tab_undo_nonneg, &tab->con[r]);
if (is_redundant(tab, tab->con[r].index)) {
mark_redundant(tab, tab->con[r].index);
return tab;
if (r < 0)
goto error;
tab->con[r].is_nonneg = 1;
- push(tab, isl_tab_undo_nonneg, &tab->con[r]);
+ push_var(tab, isl_tab_undo_nonneg, &tab->con[r]);
}
done:
isl_int_clear(cst);
tab->n_row++;
tab->n_con++;
- push(tab, isl_tab_undo_allocate, &tab->con[r]);
+ push_var(tab, isl_tab_undo_allocate, &tab->con[r]);
sgn = sign_of_max(tab, &tab->con[r]);
if (sgn < 0)
return mark_empty(tab);
tab->con[r].is_nonneg = 1;
- push(tab, isl_tab_undo_nonneg, &tab->con[r]);
+ push_var(tab, isl_tab_undo_nonneg, &tab->con[r]);
/* sgn == 0 */
close_row(tab, &tab->con[r]);
}
- push(tab, isl_tab_undo_relax, var);
+ push_var(tab, isl_tab_undo_relax, var);
return tab;
}
}
}
-static void perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
+static void perform_undo_var(struct isl_tab *tab, struct isl_tab_undo *undo)
{
- struct isl_tab_var *var = var_from_index(tab, undo->var_index);
+ struct isl_tab_var *var = var_from_index(tab, undo->u.var_index);
switch(undo->type) {
- case isl_tab_undo_empty:
- tab->empty = 0;
- break;
case isl_tab_undo_nonneg:
var->is_nonneg = 0;
break;
}
}
+static int perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
+{
+ switch (undo->type) {
+ case isl_tab_undo_empty:
+ tab->empty = 0;
+ break;
+ case isl_tab_undo_nonneg:
+ case isl_tab_undo_redundant:
+ case isl_tab_undo_zero:
+ case isl_tab_undo_allocate:
+ case isl_tab_undo_relax:
+ perform_undo_var(tab, undo);
+ break;
+ default:
+ isl_assert(tab->mat->ctx, 0, return -1);
+ }
+ return 0;
+}
+
/* Return the tableau to the state it was in when the snapshot "snap"
* was taken.
*/
next = undo->next;
if (undo == snap)
break;
- perform_undo(tab, undo);
+ if (perform_undo(tab, undo) < 0) {
+ free_undo(tab);
+ tab->in_undo = 0;
+ return -1;
+ }
free(undo);
}
tab->in_undo = 0;