Line data Source code
1 : /*
2 : * Copyright 2008-2009 Katholieke Universiteit Leuven
3 : * Copyright 2013 Ecole Normale Superieure
4 : * Copyright 2014 INRIA Rocquencourt
5 : * Copyright 2016 Sven Verdoolaege
6 : *
7 : * Use of this software is governed by the MIT license
8 : *
9 : * Written by Sven Verdoolaege, K.U.Leuven, Departement
10 : * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
11 : * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
12 : * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
13 : * B.P. 105 - 78153 Le Chesnay, France
14 : */
15 :
16 : #include <isl_ctx_private.h>
17 : #include <isl_mat_private.h>
18 : #include <isl_vec_private.h>
19 : #include "isl_map_private.h"
20 : #include "isl_tab.h"
21 : #include <isl_seq.h>
22 : #include <isl_config.h>
23 :
24 : #include <bset_to_bmap.c>
25 : #include <bset_from_bmap.c>
26 :
27 : /*
28 : * The implementation of tableaus in this file was inspired by Section 8
29 : * of David Detlefs, Greg Nelson and James B. Saxe, "Simplify: a theorem
30 : * prover for program checking".
31 : */
32 :
33 5455930109 : struct isl_tab *isl_tab_alloc(struct isl_ctx *ctx,
34 : unsigned n_row, unsigned n_var, unsigned M)
35 : {
36 : int i;
37 : struct isl_tab *tab;
38 5455930109 : unsigned off = 2 + M;
39 :
40 5455930109 : tab = isl_calloc_type(ctx, struct isl_tab);
41 5455930109 : if (!tab)
42 0 : return NULL;
43 5455930109 : tab->mat = isl_mat_alloc(ctx, n_row, off + n_var);
44 5455930109 : if (!tab->mat)
45 0 : goto error;
46 5455930109 : tab->var = isl_alloc_array(ctx, struct isl_tab_var, n_var);
47 5455930109 : if (n_var && !tab->var)
48 0 : goto error;
49 5455930109 : tab->con = isl_alloc_array(ctx, struct isl_tab_var, n_row);
50 5455930109 : if (n_row && !tab->con)
51 0 : goto error;
52 5455930109 : tab->col_var = isl_alloc_array(ctx, int, n_var);
53 5455930109 : if (n_var && !tab->col_var)
54 0 : goto error;
55 5455930109 : tab->row_var = isl_alloc_array(ctx, int, n_row);
56 5455930109 : if (n_row && !tab->row_var)
57 0 : goto error;
58 27999054656 : for (i = 0; i < n_var; ++i) {
59 22543124547 : tab->var[i].index = i;
60 22543124547 : tab->var[i].is_row = 0;
61 22543124547 : tab->var[i].is_nonneg = 0;
62 22543124547 : tab->var[i].is_zero = 0;
63 22543124547 : tab->var[i].is_redundant = 0;
64 22543124547 : tab->var[i].frozen = 0;
65 22543124547 : tab->var[i].negated = 0;
66 22543124547 : tab->col_var[i] = i;
67 : }
68 5455930109 : tab->n_row = 0;
69 5455930109 : tab->n_con = 0;
70 5455930109 : tab->n_eq = 0;
71 5455930109 : tab->max_con = n_row;
72 5455930109 : tab->n_col = n_var;
73 5455930109 : tab->n_var = n_var;
74 5455930109 : tab->max_var = n_var;
75 5455930109 : tab->n_param = 0;
76 5455930109 : tab->n_div = 0;
77 5455930109 : tab->n_dead = 0;
78 5455930109 : tab->n_redundant = 0;
79 5455930109 : tab->strict_redundant = 0;
80 5455930109 : tab->need_undo = 0;
81 5455930109 : tab->rational = 0;
82 5455930109 : tab->empty = 0;
83 5455930109 : tab->in_undo = 0;
84 5455930109 : tab->M = M;
85 5455930109 : tab->cone = 0;
86 5455930109 : tab->bottom.type = isl_tab_undo_bottom;
87 5455930109 : tab->bottom.next = NULL;
88 5455930109 : tab->top = &tab->bottom;
89 :
90 5455930109 : tab->n_zero = 0;
91 5455930109 : tab->n_unbounded = 0;
92 5455930109 : tab->basis = NULL;
93 :
94 5455930109 : return tab;
95 : error:
96 0 : isl_tab_free(tab);
97 0 : return NULL;
98 : }
99 :
100 24716208471 : isl_ctx *isl_tab_get_ctx(struct isl_tab *tab)
101 : {
102 24716208471 : return tab ? isl_mat_get_ctx(tab->mat) : NULL;
103 : }
104 :
105 19534137986 : int isl_tab_extend_cons(struct isl_tab *tab, unsigned n_new)
106 : {
107 : unsigned off;
108 :
109 19534137986 : if (!tab)
110 0 : return -1;
111 :
112 19534137986 : off = 2 + tab->M;
113 :
114 19534137986 : if (tab->max_con < tab->n_con + n_new) {
115 : struct isl_tab_var *con;
116 :
117 18123842 : con = isl_realloc_array(tab->mat->ctx, tab->con,
118 : struct isl_tab_var, tab->max_con + n_new);
119 18123842 : if (!con)
120 0 : return -1;
121 18123842 : tab->con = con;
122 18123842 : tab->max_con += n_new;
123 : }
124 19534137986 : if (tab->mat->n_row < tab->n_row + n_new) {
125 : int *row_var;
126 :
127 98494934 : tab->mat = isl_mat_extend(tab->mat,
128 98494934 : tab->n_row + n_new, off + tab->n_col);
129 49247467 : if (!tab->mat)
130 0 : return -1;
131 49247467 : row_var = isl_realloc_array(tab->mat->ctx, tab->row_var,
132 : int, tab->mat->n_row);
133 49247467 : if (!row_var)
134 0 : return -1;
135 49247467 : tab->row_var = row_var;
136 49247467 : if (tab->row_sign) {
137 : enum isl_tab_row_sign *s;
138 0 : s = isl_realloc_array(tab->mat->ctx, tab->row_sign,
139 : enum isl_tab_row_sign, tab->mat->n_row);
140 0 : if (!s)
141 0 : return -1;
142 0 : tab->row_sign = s;
143 : }
144 : }
145 19534137986 : return 0;
146 : }
147 :
148 : /* Make room for at least n_new extra variables.
149 : * Return -1 if anything went wrong.
150 : */
151 0 : int isl_tab_extend_vars(struct isl_tab *tab, unsigned n_new)
152 : {
153 : struct isl_tab_var *var;
154 0 : unsigned off = 2 + tab->M;
155 :
156 0 : if (tab->max_var < tab->n_var + n_new) {
157 0 : var = isl_realloc_array(tab->mat->ctx, tab->var,
158 : struct isl_tab_var, tab->n_var + n_new);
159 0 : if (!var)
160 0 : return -1;
161 0 : tab->var = var;
162 0 : tab->max_var = tab->n_var + n_new;
163 : }
164 :
165 0 : if (tab->mat->n_col < off + tab->n_col + n_new) {
166 : int *p;
167 :
168 0 : tab->mat = isl_mat_extend(tab->mat,
169 0 : tab->mat->n_row, off + tab->n_col + n_new);
170 0 : if (!tab->mat)
171 0 : return -1;
172 0 : p = isl_realloc_array(tab->mat->ctx, tab->col_var,
173 : int, tab->n_col + n_new);
174 0 : if (!p)
175 0 : return -1;
176 0 : tab->col_var = p;
177 : }
178 :
179 0 : return 0;
180 : }
181 :
182 53023335647 : static void free_undo_record(struct isl_tab_undo *undo)
183 : {
184 53023335647 : switch (undo->type) {
185 : case isl_tab_undo_saved_basis:
186 0 : free(undo->u.col_var);
187 0 : break;
188 : default:;
189 : }
190 53023335647 : free(undo);
191 53023335647 : }
192 :
193 5459292214 : static void free_undo(struct isl_tab *tab)
194 : {
195 : struct isl_tab_undo *undo, *next;
196 :
197 6110050875 : for (undo = tab->top; undo && undo != &tab->bottom; undo = next) {
198 650758661 : next = undo->next;
199 650758661 : free_undo_record(undo);
200 : }
201 5459292214 : tab->top = undo;
202 5459292214 : }
203 :
204 5459467163 : void isl_tab_free(struct isl_tab *tab)
205 : {
206 5459467163 : if (!tab)
207 174949 : return;
208 5459292214 : free_undo(tab);
209 5459292214 : isl_mat_free(tab->mat);
210 5459292214 : isl_vec_free(tab->dual);
211 5459292214 : isl_basic_map_free(tab->bmap);
212 5459292214 : free(tab->var);
213 5459292214 : free(tab->con);
214 5459292214 : free(tab->row_var);
215 5459292214 : free(tab->col_var);
216 5459292214 : free(tab->row_sign);
217 5459292214 : isl_mat_free(tab->samples);
218 5459292214 : free(tab->sample_index);
219 5459292214 : isl_mat_free(tab->basis);
220 5459292214 : free(tab);
221 : }
222 :
223 0 : struct isl_tab *isl_tab_dup(struct isl_tab *tab)
224 : {
225 : int i;
226 : struct isl_tab *dup;
227 : unsigned off;
228 :
229 0 : if (!tab)
230 0 : return NULL;
231 :
232 0 : off = 2 + tab->M;
233 0 : dup = isl_calloc_type(tab->mat->ctx, struct isl_tab);
234 0 : if (!dup)
235 0 : return NULL;
236 0 : dup->mat = isl_mat_dup(tab->mat);
237 0 : if (!dup->mat)
238 0 : goto error;
239 0 : dup->var = isl_alloc_array(tab->mat->ctx, struct isl_tab_var, tab->max_var);
240 0 : if (tab->max_var && !dup->var)
241 0 : goto error;
242 0 : for (i = 0; i < tab->n_var; ++i)
243 0 : dup->var[i] = tab->var[i];
244 0 : dup->con = isl_alloc_array(tab->mat->ctx, struct isl_tab_var, tab->max_con);
245 0 : if (tab->max_con && !dup->con)
246 0 : goto error;
247 0 : for (i = 0; i < tab->n_con; ++i)
248 0 : dup->con[i] = tab->con[i];
249 0 : dup->col_var = isl_alloc_array(tab->mat->ctx, int, tab->mat->n_col - off);
250 0 : if ((tab->mat->n_col - off) && !dup->col_var)
251 0 : goto error;
252 0 : for (i = 0; i < tab->n_col; ++i)
253 0 : dup->col_var[i] = tab->col_var[i];
254 0 : dup->row_var = isl_alloc_array(tab->mat->ctx, int, tab->mat->n_row);
255 0 : if (tab->mat->n_row && !dup->row_var)
256 0 : goto error;
257 0 : for (i = 0; i < tab->n_row; ++i)
258 0 : dup->row_var[i] = tab->row_var[i];
259 0 : if (tab->row_sign) {
260 0 : dup->row_sign = isl_alloc_array(tab->mat->ctx, enum isl_tab_row_sign,
261 : tab->mat->n_row);
262 0 : if (tab->mat->n_row && !dup->row_sign)
263 0 : goto error;
264 0 : for (i = 0; i < tab->n_row; ++i)
265 0 : dup->row_sign[i] = tab->row_sign[i];
266 : }
267 0 : if (tab->samples) {
268 0 : dup->samples = isl_mat_dup(tab->samples);
269 0 : if (!dup->samples)
270 0 : goto error;
271 0 : dup->sample_index = isl_alloc_array(tab->mat->ctx, int,
272 : tab->samples->n_row);
273 0 : if (tab->samples->n_row && !dup->sample_index)
274 0 : goto error;
275 0 : dup->n_sample = tab->n_sample;
276 0 : dup->n_outside = tab->n_outside;
277 : }
278 0 : dup->n_row = tab->n_row;
279 0 : dup->n_con = tab->n_con;
280 0 : dup->n_eq = tab->n_eq;
281 0 : dup->max_con = tab->max_con;
282 0 : dup->n_col = tab->n_col;
283 0 : dup->n_var = tab->n_var;
284 0 : dup->max_var = tab->max_var;
285 0 : dup->n_param = tab->n_param;
286 0 : dup->n_div = tab->n_div;
287 0 : dup->n_dead = tab->n_dead;
288 0 : dup->n_redundant = tab->n_redundant;
289 0 : dup->rational = tab->rational;
290 0 : dup->empty = tab->empty;
291 0 : dup->strict_redundant = 0;
292 0 : dup->need_undo = 0;
293 0 : dup->in_undo = 0;
294 0 : dup->M = tab->M;
295 0 : tab->cone = tab->cone;
296 0 : dup->bottom.type = isl_tab_undo_bottom;
297 0 : dup->bottom.next = NULL;
298 0 : dup->top = &dup->bottom;
299 :
300 0 : dup->n_zero = tab->n_zero;
301 0 : dup->n_unbounded = tab->n_unbounded;
302 0 : dup->basis = isl_mat_dup(tab->basis);
303 :
304 0 : return dup;
305 : error:
306 0 : isl_tab_free(dup);
307 0 : return NULL;
308 : }
309 :
310 : /* Construct the coefficient matrix of the product tableau
311 : * of two tableaus.
312 : * mat{1,2} is the coefficient matrix of tableau {1,2}
313 : * row{1,2} is the number of rows in tableau {1,2}
314 : * col{1,2} is the number of columns in tableau {1,2}
315 : * off is the offset to the coefficient column (skipping the
316 : * denominator, the constant term and the big parameter if any)
317 : * r{1,2} is the number of redundant rows in tableau {1,2}
318 : * d{1,2} is the number of dead columns in tableau {1,2}
319 : *
320 : * The order of the rows and columns in the result is as explained
321 : * in isl_tab_product.
322 : */
323 3362105 : static struct isl_mat *tab_mat_product(struct isl_mat *mat1,
324 : struct isl_mat *mat2, unsigned row1, unsigned row2,
325 : unsigned col1, unsigned col2,
326 : unsigned off, unsigned r1, unsigned r2, unsigned d1, unsigned d2)
327 : {
328 : int i;
329 : struct isl_mat *prod;
330 : unsigned n;
331 :
332 3362105 : prod = isl_mat_alloc(mat1->ctx, mat1->n_row + mat2->n_row,
333 3362105 : off + col1 + col2);
334 3362105 : if (!prod)
335 0 : return NULL;
336 :
337 3362105 : n = 0;
338 28166891 : for (i = 0; i < r1; ++i) {
339 24804786 : isl_seq_cpy(prod->row[n + i], mat1->row[i], off + d1);
340 24804786 : isl_seq_clr(prod->row[n + i] + off + d1, d2);
341 49609572 : isl_seq_cpy(prod->row[n + i] + off + d1 + d2,
342 24804786 : mat1->row[i] + off + d1, col1 - d1);
343 24804786 : isl_seq_clr(prod->row[n + i] + off + col1 + d1, col2 - d2);
344 : }
345 :
346 3362105 : n += r1;
347 28166891 : for (i = 0; i < r2; ++i) {
348 24804786 : isl_seq_cpy(prod->row[n + i], mat2->row[i], off);
349 24804786 : isl_seq_clr(prod->row[n + i] + off, d1);
350 49609572 : isl_seq_cpy(prod->row[n + i] + off + d1,
351 49609572 : mat2->row[i] + off, d2);
352 24804786 : isl_seq_clr(prod->row[n + i] + off + d1 + d2, col1 - d1);
353 49609572 : isl_seq_cpy(prod->row[n + i] + off + col1 + d1,
354 24804786 : mat2->row[i] + off + d2, col2 - d2);
355 : }
356 :
357 3362105 : n += r2;
358 43292650 : for (i = 0; i < row1 - r1; ++i) {
359 39930545 : isl_seq_cpy(prod->row[n + i], mat1->row[r1 + i], off + d1);
360 39930545 : isl_seq_clr(prod->row[n + i] + off + d1, d2);
361 79861090 : isl_seq_cpy(prod->row[n + i] + off + d1 + d2,
362 39930545 : mat1->row[r1 + i] + off + d1, col1 - d1);
363 39930545 : isl_seq_clr(prod->row[n + i] + off + col1 + d1, col2 - d2);
364 : }
365 :
366 3362105 : n += row1 - r1;
367 43292650 : for (i = 0; i < row2 - r2; ++i) {
368 39930545 : isl_seq_cpy(prod->row[n + i], mat2->row[r2 + i], off);
369 39930545 : isl_seq_clr(prod->row[n + i] + off, d1);
370 79861090 : isl_seq_cpy(prod->row[n + i] + off + d1,
371 79861090 : mat2->row[r2 + i] + off, d2);
372 39930545 : isl_seq_clr(prod->row[n + i] + off + d1 + d2, col1 - d1);
373 79861090 : isl_seq_cpy(prod->row[n + i] + off + col1 + d1,
374 39930545 : mat2->row[r2 + i] + off + d2, col2 - d2);
375 : }
376 :
377 3362105 : return prod;
378 : }
379 :
380 : /* Update the row or column index of a variable that corresponds
381 : * to a variable in the first input tableau.
382 : */
383 81892547 : static void update_index1(struct isl_tab_var *var,
384 : unsigned r1, unsigned r2, unsigned d1, unsigned d2)
385 : {
386 81892547 : if (var->index == -1)
387 451254 : return;
388 81441293 : if (var->is_row && var->index >= r1)
389 39930545 : var->index += r2;
390 81441293 : if (!var->is_row && var->index >= d1)
391 15495213 : var->index += d2;
392 : }
393 :
394 : /* Update the row or column index of a variable that corresponds
395 : * to a variable in the second input tableau.
396 : */
397 81892547 : static void update_index2(struct isl_tab_var *var,
398 : unsigned row1, unsigned col1,
399 : unsigned r1, unsigned r2, unsigned d1, unsigned d2)
400 : {
401 81892547 : if (var->index == -1)
402 451254 : return;
403 81441293 : if (var->is_row) {
404 64735331 : if (var->index < r2)
405 24804786 : var->index += r1;
406 : else
407 39930545 : var->index += row1;
408 : } else {
409 16705962 : if (var->index < d2)
410 1210749 : var->index += d1;
411 : else
412 15495213 : var->index += col1;
413 : }
414 : }
415 :
416 : /* Create a tableau that represents the Cartesian product of the sets
417 : * represented by tableaus tab1 and tab2.
418 : * The order of the rows in the product is
419 : * - redundant rows of tab1
420 : * - redundant rows of tab2
421 : * - non-redundant rows of tab1
422 : * - non-redundant rows of tab2
423 : * The order of the columns is
424 : * - denominator
425 : * - constant term
426 : * - coefficient of big parameter, if any
427 : * - dead columns of tab1
428 : * - dead columns of tab2
429 : * - live columns of tab1
430 : * - live columns of tab2
431 : * The order of the variables and the constraints is a concatenation
432 : * of order in the two input tableaus.
433 : */
434 3362105 : struct isl_tab *isl_tab_product(struct isl_tab *tab1, struct isl_tab *tab2)
435 : {
436 : int i;
437 : struct isl_tab *prod;
438 : unsigned off;
439 : unsigned r1, r2, d1, d2;
440 :
441 3362105 : if (!tab1 || !tab2)
442 0 : return NULL;
443 :
444 3362105 : isl_assert(tab1->mat->ctx, tab1->M == tab2->M, return NULL);
445 3362105 : isl_assert(tab1->mat->ctx, tab1->rational == tab2->rational, return NULL);
446 3362105 : isl_assert(tab1->mat->ctx, tab1->cone == tab2->cone, return NULL);
447 3362105 : isl_assert(tab1->mat->ctx, !tab1->row_sign, return NULL);
448 3362105 : isl_assert(tab1->mat->ctx, !tab2->row_sign, return NULL);
449 3362105 : isl_assert(tab1->mat->ctx, tab1->n_param == 0, return NULL);
450 3362105 : isl_assert(tab1->mat->ctx, tab2->n_param == 0, return NULL);
451 3362105 : isl_assert(tab1->mat->ctx, tab1->n_div == 0, return NULL);
452 3362105 : isl_assert(tab1->mat->ctx, tab2->n_div == 0, return NULL);
453 :
454 3362105 : off = 2 + tab1->M;
455 3362105 : r1 = tab1->n_redundant;
456 3362105 : r2 = tab2->n_redundant;
457 3362105 : d1 = tab1->n_dead;
458 3362105 : d2 = tab2->n_dead;
459 3362105 : prod = isl_calloc_type(tab1->mat->ctx, struct isl_tab);
460 3362105 : if (!prod)
461 0 : return NULL;
462 3362105 : prod->mat = tab_mat_product(tab1->mat, tab2->mat,
463 : tab1->n_row, tab2->n_row,
464 : tab1->n_col, tab2->n_col, off, r1, r2, d1, d2);
465 3362105 : if (!prod->mat)
466 0 : goto error;
467 3362105 : prod->var = isl_alloc_array(tab1->mat->ctx, struct isl_tab_var,
468 : tab1->max_var + tab2->max_var);
469 3362105 : if ((tab1->max_var + tab2->max_var) && !prod->var)
470 0 : goto error;
471 20519321 : for (i = 0; i < tab1->n_var; ++i) {
472 17157216 : prod->var[i] = tab1->var[i];
473 17157216 : update_index1(&prod->var[i], r1, r2, d1, d2);
474 : }
475 20519321 : for (i = 0; i < tab2->n_var; ++i) {
476 17157216 : prod->var[tab1->n_var + i] = tab2->var[i];
477 17157216 : update_index2(&prod->var[tab1->n_var + i],
478 : tab1->n_row, tab1->n_col,
479 : r1, r2, d1, d2);
480 : }
481 3362105 : prod->con = isl_alloc_array(tab1->mat->ctx, struct isl_tab_var,
482 : tab1->max_con + tab2->max_con);
483 3362105 : if ((tab1->max_con + tab2->max_con) && !prod->con)
484 0 : goto error;
485 68097436 : for (i = 0; i < tab1->n_con; ++i) {
486 64735331 : prod->con[i] = tab1->con[i];
487 64735331 : update_index1(&prod->con[i], r1, r2, d1, d2);
488 : }
489 68097436 : for (i = 0; i < tab2->n_con; ++i) {
490 64735331 : prod->con[tab1->n_con + i] = tab2->con[i];
491 64735331 : update_index2(&prod->con[tab1->n_con + i],
492 : tab1->n_row, tab1->n_col,
493 : r1, r2, d1, d2);
494 : }
495 3362105 : prod->col_var = isl_alloc_array(tab1->mat->ctx, int,
496 : tab1->n_col + tab2->n_col);
497 3362105 : if ((tab1->n_col + tab2->n_col) && !prod->col_var)
498 0 : goto error;
499 20068067 : for (i = 0; i < tab1->n_col; ++i) {
500 16705962 : int pos = i < d1 ? i : i + d2;
501 16705962 : prod->col_var[pos] = tab1->col_var[i];
502 : }
503 20068067 : for (i = 0; i < tab2->n_col; ++i) {
504 16705962 : int pos = i < d2 ? d1 + i : tab1->n_col + i;
505 16705962 : int t = tab2->col_var[i];
506 16705962 : if (t >= 0)
507 5809 : t += tab1->n_var;
508 : else
509 16700153 : t -= tab1->n_con;
510 16705962 : prod->col_var[pos] = t;
511 : }
512 3362105 : prod->row_var = isl_alloc_array(tab1->mat->ctx, int,
513 : tab1->mat->n_row + tab2->mat->n_row);
514 3362105 : if ((tab1->mat->n_row + tab2->mat->n_row) && !prod->row_var)
515 0 : goto error;
516 68097436 : for (i = 0; i < tab1->n_row; ++i) {
517 64735331 : int pos = i < r1 ? i : i + r2;
518 64735331 : prod->row_var[pos] = tab1->row_var[i];
519 : }
520 68097436 : for (i = 0; i < tab2->n_row; ++i) {
521 64735331 : int pos = i < r2 ? r1 + i : tab1->n_row + i;
522 64735331 : int t = tab2->row_var[i];
523 64735331 : if (t >= 0)
524 17151407 : t += tab1->n_var;
525 : else
526 47583924 : t -= tab1->n_con;
527 64735331 : prod->row_var[pos] = t;
528 : }
529 3362105 : prod->samples = NULL;
530 3362105 : prod->sample_index = NULL;
531 3362105 : prod->n_row = tab1->n_row + tab2->n_row;
532 3362105 : prod->n_con = tab1->n_con + tab2->n_con;
533 3362105 : prod->n_eq = 0;
534 3362105 : prod->max_con = tab1->max_con + tab2->max_con;
535 3362105 : prod->n_col = tab1->n_col + tab2->n_col;
536 3362105 : prod->n_var = tab1->n_var + tab2->n_var;
537 3362105 : prod->max_var = tab1->max_var + tab2->max_var;
538 3362105 : prod->n_param = 0;
539 3362105 : prod->n_div = 0;
540 3362105 : prod->n_dead = tab1->n_dead + tab2->n_dead;
541 3362105 : prod->n_redundant = tab1->n_redundant + tab2->n_redundant;
542 3362105 : prod->rational = tab1->rational;
543 3362105 : prod->empty = tab1->empty || tab2->empty;
544 3362105 : prod->strict_redundant = tab1->strict_redundant || tab2->strict_redundant;
545 3362105 : prod->need_undo = 0;
546 3362105 : prod->in_undo = 0;
547 3362105 : prod->M = tab1->M;
548 3362105 : prod->cone = tab1->cone;
549 3362105 : prod->bottom.type = isl_tab_undo_bottom;
550 3362105 : prod->bottom.next = NULL;
551 3362105 : prod->top = &prod->bottom;
552 :
553 3362105 : prod->n_zero = 0;
554 3362105 : prod->n_unbounded = 0;
555 3362105 : prod->basis = NULL;
556 :
557 3362105 : return prod;
558 : error:
559 0 : isl_tab_free(prod);
560 0 : return NULL;
561 : }
562 :
563 >51995*10^7 : static struct isl_tab_var *var_from_index(struct isl_tab *tab, int i)
564 : {
565 >51995*10^7 : if (i >= 0)
566 >12922*10^7 : return &tab->var[i];
567 : else
568 >39072*10^7 : return &tab->con[~i];
569 : }
570 :
571 >31758*10^7 : struct isl_tab_var *isl_tab_var_from_row(struct isl_tab *tab, int i)
572 : {
573 >31758*10^7 : return var_from_index(tab, tab->row_var[i]);
574 : }
575 :
576 >15448*10^7 : static struct isl_tab_var *var_from_col(struct isl_tab *tab, int i)
577 : {
578 >15448*10^7 : return var_from_index(tab, tab->col_var[i]);
579 : }
580 :
581 : /* Check if there are any upper bounds on column variable "var",
582 : * i.e., non-negative rows where var appears with a negative coefficient.
583 : * Return 1 if there are no such bounds.
584 : */
585 1294877277 : static int max_is_manifestly_unbounded(struct isl_tab *tab,
586 : struct isl_tab_var *var)
587 : {
588 : int i;
589 1294877277 : unsigned off = 2 + tab->M;
590 :
591 1294877277 : if (var->is_row)
592 616703802 : return 0;
593 3849437880 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
594 3637926229 : if (!isl_int_is_neg(tab->mat->row[i][off + var->index]))
595 2722679996 : continue;
596 915246233 : if (isl_tab_var_from_row(tab, i)->is_nonneg)
597 466661824 : return 0;
598 : }
599 211511651 : return 1;
600 : }
601 :
602 : /* Check if there are any lower bounds on column variable "var",
603 : * i.e., non-negative rows where var appears with a positive coefficient.
604 : * Return 1 if there are no such bounds.
605 : */
606 12817740870 : static int min_is_manifestly_unbounded(struct isl_tab *tab,
607 : struct isl_tab_var *var)
608 : {
609 : int i;
610 12817740870 : unsigned off = 2 + tab->M;
611 :
612 12817740870 : if (var->is_row)
613 11854101727 : return 0;
614 4573174600 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
615 4429753381 : if (!isl_int_is_pos(tab->mat->row[i][off + var->index]))
616 3091662991 : continue;
617 1338090390 : if (isl_tab_var_from_row(tab, i)->is_nonneg)
618 820217924 : return 0;
619 : }
620 143421219 : return 1;
621 : }
622 :
623 21161341164 : static int row_cmp(struct isl_tab *tab, int r1, int r2, int c, isl_int *t)
624 : {
625 21161341164 : unsigned off = 2 + tab->M;
626 :
627 21161341164 : if (tab->M) {
628 : int s;
629 0 : isl_int_mul(*t, tab->mat->row[r1][2], tab->mat->row[r2][off+c]);
630 0 : isl_int_submul(*t, tab->mat->row[r2][2], tab->mat->row[r1][off+c]);
631 0 : s = isl_int_sgn(*t);
632 0 : if (s)
633 0 : return s;
634 : }
635 21161341164 : isl_int_mul(*t, tab->mat->row[r1][1], tab->mat->row[r2][off + c]);
636 21161341164 : isl_int_submul(*t, tab->mat->row[r2][1], tab->mat->row[r1][off + c]);
637 21161341164 : return isl_int_sgn(*t);
638 : }
639 :
640 : /* Given the index of a column "c", return the index of a row
641 : * that can be used to pivot the column in, with either an increase
642 : * (sgn > 0) or a decrease (sgn < 0) of the corresponding variable.
643 : * If "var" is not NULL, then the row returned will be different from
644 : * the one associated with "var".
645 : *
646 : * Each row in the tableau is of the form
647 : *
648 : * x_r = a_r0 + \sum_i a_ri x_i
649 : *
650 : * Only rows with x_r >= 0 and with the sign of a_ri opposite to "sgn"
651 : * impose any limit on the increase or decrease in the value of x_c
652 : * and this bound is equal to a_r0 / |a_rc|. We are therefore looking
653 : * for the row with the smallest (most stringent) such bound.
654 : * Note that the common denominator of each row drops out of the fraction.
655 : * To check if row j has a smaller bound than row r, i.e.,
656 : * a_j0 / |a_jc| < a_r0 / |a_rc| or a_j0 |a_rc| < a_r0 |a_jc|,
657 : * we check if -sign(a_jc) (a_j0 a_rc - a_r0 a_jc) < 0,
658 : * where -sign(a_jc) is equal to "sgn".
659 : */
660 5707718385 : static int pivot_row(struct isl_tab *tab,
661 : struct isl_tab_var *var, int sgn, int c)
662 : {
663 : int j, r, tsgn;
664 : isl_int t;
665 5707718385 : unsigned off = 2 + tab->M;
666 :
667 5707718385 : isl_int_init(t);
668 5707718385 : r = -1;
669 99518206739 : for (j = tab->n_redundant; j < tab->n_row; ++j) {
670 93810488354 : if (var && j == var->index)
671 4892239600 : continue;
672 88918248754 : if (!isl_tab_var_from_row(tab, j)->is_nonneg)
673 30121924285 : continue;
674 58796324469 : if (sgn * isl_int_sgn(tab->mat->row[j][off + c]) >= 0)
675 32360293081 : continue;
676 26436031388 : if (r < 0) {
677 5274690224 : r = j;
678 5274690224 : continue;
679 : }
680 21161341164 : tsgn = sgn * row_cmp(tab, r, j, c, &t);
681 24558580068 : if (tsgn < 0 || (tsgn == 0 &&
682 3397238904 : tab->row_var[j] < tab->row_var[r]))
683 6486609515 : r = j;
684 : }
685 5707718385 : isl_int_clear(t);
686 5707718385 : return r;
687 : }
688 :
689 : /* Find a pivot (row and col) that will increase (sgn > 0) or decrease
690 : * (sgn < 0) the value of row variable var.
691 : * If not NULL, then skip_var is a row variable that should be ignored
692 : * while looking for a pivot row. It is usually equal to var.
693 : *
694 : * As the given row in the tableau is of the form
695 : *
696 : * x_r = a_r0 + \sum_i a_ri x_i
697 : *
698 : * we need to find a column such that the sign of a_ri is equal to "sgn"
699 : * (such that an increase in x_i will have the desired effect) or a
700 : * column with a variable that may attain negative values.
701 : * If a_ri is positive, then we need to move x_i in the same direction
702 : * to obtain the desired effect. Otherwise, x_i has to move in the
703 : * opposite direction.
704 : */
705 27492068353 : static void find_pivot(struct isl_tab *tab,
706 : struct isl_tab_var *var, struct isl_tab_var *skip_var,
707 : int sgn, int *row, int *col)
708 : {
709 : int j, r, c;
710 : isl_int *tr;
711 :
712 27492068353 : *row = *col = -1;
713 :
714 27492068353 : isl_assert(tab->mat->ctx, var->is_row, return);
715 27492068353 : tr = tab->mat->row[var->index] + 2 + tab->M;
716 :
717 27492068353 : c = -1;
718 59239487936 : for (j = tab->n_dead; j < tab->n_col; ++j) {
719 31747419583 : if (isl_int_is_zero(tr[j]))
720 10216870646 : continue;
721 35463640499 : if (isl_int_sgn(tr[j]) != sgn &&
722 13933091562 : var_from_col(tab, j)->is_nonneg)
723 11845678892 : continue;
724 9684870045 : if (c < 0 || tab->col_var[j] < tab->col_var[c])
725 6490498734 : c = j;
726 : }
727 27492068353 : if (c < 0)
728 22438075420 : return;
729 :
730 5053992933 : sgn *= isl_int_sgn(tr[c]);
731 5053992933 : r = pivot_row(tab, skip_var, sgn, c);
732 5053992933 : *row = r < 0 ? var->index : r;
733 5053992933 : *col = c;
734 : }
735 :
736 : /* Return 1 if row "row" represents an obviously redundant inequality.
737 : * This means
738 : * - it represents an inequality or a variable
739 : * - that is the sum of a non-negative sample value and a positive
740 : * combination of zero or more non-negative constraints.
741 : */
742 >10885*10^7 : int isl_tab_row_is_redundant(struct isl_tab *tab, int row)
743 : {
744 : int i;
745 >10885*10^7 : unsigned off = 2 + tab->M;
746 :
747 >10885*10^7 : if (tab->row_var[row] < 0 && !isl_tab_var_from_row(tab, row)->is_nonneg)
748 20541672816 : return 0;
749 :
750 88309122804 : if (isl_int_is_neg(tab->mat->row[row][1]))
751 9873288850 : return 0;
752 78435833954 : if (tab->strict_redundant && isl_int_is_zero(tab->mat->row[row][1]))
753 0 : return 0;
754 78435833954 : if (tab->M && isl_int_is_neg(tab->mat->row[row][2]))
755 0 : return 0;
756 :
757 >24678*10^7 : for (i = tab->n_dead; i < tab->n_col; ++i) {
758 >23988*10^7 : if (isl_int_is_zero(tab->mat->row[row][off + i]))
759 >12850*10^7 : continue;
760 >11137*10^7 : if (tab->col_var[i] >= 0)
761 11925854604 : return 0;
762 99448020500 : if (isl_int_is_neg(tab->mat->row[row][off + i]))
763 44564035637 : return 0;
764 54883984863 : if (!var_from_col(tab, i)->is_nonneg)
765 15044768923 : return 0;
766 : }
767 6901174790 : return 1;
768 : }
769 :
770 7469002579 : static void swap_rows(struct isl_tab *tab, int row1, int row2)
771 : {
772 : int t;
773 : enum isl_tab_row_sign s;
774 :
775 7469002579 : t = tab->row_var[row1];
776 7469002579 : tab->row_var[row1] = tab->row_var[row2];
777 7469002579 : tab->row_var[row2] = t;
778 7469002579 : isl_tab_var_from_row(tab, row1)->index = row1;
779 7469002579 : isl_tab_var_from_row(tab, row2)->index = row2;
780 7469002579 : tab->mat = isl_mat_swap_rows(tab->mat, row1, row2);
781 :
782 7469002579 : if (!tab->row_sign)
783 7469002579 : return;
784 0 : s = tab->row_sign[row1];
785 0 : tab->row_sign[row1] = tab->row_sign[row2];
786 0 : tab->row_sign[row2] = s;
787 : }
788 :
789 : static isl_stat push_union(struct isl_tab *tab,
790 : enum isl_tab_undo_type type, union isl_tab_undo_val u) WARN_UNUSED;
791 :
792 : /* Push record "u" onto the undo stack of "tab", provided "tab"
793 : * keeps track of undo information.
794 : *
795 : * If the record cannot be pushed, then mark the undo stack as invalid
796 : * such that a later rollback attempt will not try to undo earlier
797 : * records without having been able to undo the current record.
798 : */
799 84629203562 : static isl_stat push_union(struct isl_tab *tab,
800 : enum isl_tab_undo_type type, union isl_tab_undo_val u)
801 : {
802 : struct isl_tab_undo *undo;
803 :
804 84629203562 : if (!tab)
805 0 : return isl_stat_error;
806 84629203562 : if (!tab->need_undo)
807 31605867915 : return isl_stat_ok;
808 :
809 53023335647 : undo = isl_alloc_type(tab->mat->ctx, struct isl_tab_undo);
810 53023335647 : if (!undo)
811 0 : goto error;
812 53023335647 : undo->type = type;
813 53023335647 : undo->u = u;
814 53023335647 : undo->next = tab->top;
815 53023335647 : tab->top = undo;
816 :
817 53023335647 : return isl_stat_ok;
818 : error:
819 0 : free_undo(tab);
820 0 : tab->top = NULL;
821 0 : return isl_stat_error;
822 : }
823 :
824 80049571913 : isl_stat isl_tab_push_var(struct isl_tab *tab,
825 : enum isl_tab_undo_type type, struct isl_tab_var *var)
826 : {
827 : union isl_tab_undo_val u;
828 80049571913 : if (var->is_row)
829 76295722248 : u.var_index = tab->row_var[var->index];
830 : else
831 3753849665 : u.var_index = tab->col_var[var->index];
832 80049571913 : return push_union(tab, type, u);
833 : }
834 :
835 4579631649 : isl_stat isl_tab_push(struct isl_tab *tab, enum isl_tab_undo_type type)
836 : {
837 4579631649 : union isl_tab_undo_val u = { 0 };
838 4579631649 : return push_union(tab, type, u);
839 : }
840 :
841 : /* Push a record on the undo stack describing the current basic
842 : * variables, so that the this state can be restored during rollback.
843 : */
844 0 : isl_stat isl_tab_push_basis(struct isl_tab *tab)
845 : {
846 : int i;
847 : union isl_tab_undo_val u;
848 :
849 0 : u.col_var = isl_alloc_array(tab->mat->ctx, int, tab->n_col);
850 0 : if (tab->n_col && !u.col_var)
851 0 : return isl_stat_error;
852 0 : for (i = 0; i < tab->n_col; ++i)
853 0 : u.col_var[i] = tab->col_var[i];
854 0 : return push_union(tab, isl_tab_undo_saved_basis, u);
855 : }
856 :
857 0 : isl_stat isl_tab_push_callback(struct isl_tab *tab,
858 : struct isl_tab_callback *callback)
859 : {
860 : union isl_tab_undo_val u;
861 0 : u.callback = callback;
862 0 : return push_union(tab, isl_tab_undo_callback, u);
863 : }
864 :
865 0 : struct isl_tab *isl_tab_init_samples(struct isl_tab *tab)
866 : {
867 0 : if (!tab)
868 0 : return NULL;
869 :
870 0 : tab->n_sample = 0;
871 0 : tab->n_outside = 0;
872 0 : tab->samples = isl_mat_alloc(tab->mat->ctx, 1, 1 + tab->n_var);
873 0 : if (!tab->samples)
874 0 : goto error;
875 0 : tab->sample_index = isl_alloc_array(tab->mat->ctx, int, 1);
876 0 : if (!tab->sample_index)
877 0 : goto error;
878 0 : return tab;
879 : error:
880 0 : isl_tab_free(tab);
881 0 : return NULL;
882 : }
883 :
884 0 : int isl_tab_add_sample(struct isl_tab *tab, __isl_take isl_vec *sample)
885 : {
886 0 : if (!tab || !sample)
887 : goto error;
888 :
889 0 : if (tab->n_sample + 1 > tab->samples->n_row) {
890 0 : int *t = isl_realloc_array(tab->mat->ctx,
891 : tab->sample_index, int, tab->n_sample + 1);
892 0 : if (!t)
893 0 : goto error;
894 0 : tab->sample_index = t;
895 : }
896 :
897 0 : tab->samples = isl_mat_extend(tab->samples,
898 0 : tab->n_sample + 1, tab->samples->n_col);
899 0 : if (!tab->samples)
900 0 : goto error;
901 :
902 0 : isl_seq_cpy(tab->samples->row[tab->n_sample], sample->el, sample->size);
903 0 : isl_vec_free(sample);
904 0 : tab->sample_index[tab->n_sample] = tab->n_sample;
905 0 : tab->n_sample++;
906 :
907 0 : return 0;
908 : error:
909 0 : isl_vec_free(sample);
910 0 : return -1;
911 : }
912 :
913 0 : struct isl_tab *isl_tab_drop_sample(struct isl_tab *tab, int s)
914 : {
915 0 : if (s != tab->n_outside) {
916 0 : int t = tab->sample_index[tab->n_outside];
917 0 : tab->sample_index[tab->n_outside] = tab->sample_index[s];
918 0 : tab->sample_index[s] = t;
919 0 : isl_mat_swap_rows(tab->samples, tab->n_outside, s);
920 : }
921 0 : tab->n_outside++;
922 0 : if (isl_tab_push(tab, isl_tab_undo_drop_sample) < 0) {
923 0 : isl_tab_free(tab);
924 0 : return NULL;
925 : }
926 :
927 0 : return tab;
928 : }
929 :
930 : /* Record the current number of samples so that we can remove newer
931 : * samples during a rollback.
932 : */
933 0 : isl_stat isl_tab_save_samples(struct isl_tab *tab)
934 : {
935 : union isl_tab_undo_val u;
936 :
937 0 : if (!tab)
938 0 : return isl_stat_error;
939 :
940 0 : u.n = tab->n_sample;
941 0 : return push_union(tab, isl_tab_undo_saved_samples, u);
942 : }
943 :
944 : /* Mark row with index "row" as being redundant.
945 : * If we may need to undo the operation or if the row represents
946 : * a variable of the original problem, the row is kept,
947 : * but no longer considered when looking for a pivot row.
948 : * Otherwise, the row is simply removed.
949 : *
950 : * The row may be interchanged with some other row. If it
951 : * is interchanged with a later row, return 1. Otherwise return 0.
952 : * If the rows are checked in order in the calling function,
953 : * then a return value of 1 means that the row with the given
954 : * row number may now contain a different row that hasn't been checked yet.
955 : */
956 7292744120 : int isl_tab_mark_redundant(struct isl_tab *tab, int row)
957 : {
958 7292744120 : struct isl_tab_var *var = isl_tab_var_from_row(tab, row);
959 7292744120 : var->is_redundant = 1;
960 7292744120 : isl_assert(tab->mat->ctx, row >= tab->n_redundant, return -1);
961 7292744120 : if (tab->preserve || tab->need_undo || tab->row_var[row] >= 0) {
962 5825065685 : if (tab->row_var[row] >= 0 && !var->is_nonneg) {
963 3579057047 : var->is_nonneg = 1;
964 3579057047 : if (isl_tab_push_var(tab, isl_tab_undo_nonneg, var) < 0)
965 0 : return -1;
966 : }
967 5825065685 : if (row != tab->n_redundant)
968 5184096694 : swap_rows(tab, row, tab->n_redundant);
969 5825065685 : tab->n_redundant++;
970 5825065685 : return isl_tab_push_var(tab, isl_tab_undo_redundant, var);
971 : } else {
972 1467678435 : if (row != tab->n_row - 1)
973 544074291 : swap_rows(tab, row, tab->n_row - 1);
974 1467678435 : isl_tab_var_from_row(tab, tab->n_row - 1)->index = -1;
975 1467678435 : tab->n_row--;
976 1467678435 : return 1;
977 : }
978 : }
979 :
980 : /* Mark "tab" as a rational tableau.
981 : * If it wasn't marked as a rational tableau already and if we may
982 : * need to undo changes, then arrange for the marking to be undone
983 : * during the undo.
984 : */
985 11179 : int isl_tab_mark_rational(struct isl_tab *tab)
986 : {
987 11179 : if (!tab)
988 0 : return -1;
989 11179 : if (!tab->rational && tab->need_undo)
990 10643 : if (isl_tab_push(tab, isl_tab_undo_rational) < 0)
991 0 : return -1;
992 11179 : tab->rational = 1;
993 11179 : return 0;
994 : }
995 :
996 805460820 : isl_stat isl_tab_mark_empty(struct isl_tab *tab)
997 : {
998 805460820 : if (!tab)
999 0 : return isl_stat_error;
1000 805460820 : if (!tab->empty && tab->need_undo)
1001 749697170 : if (isl_tab_push(tab, isl_tab_undo_empty) < 0)
1002 0 : return isl_stat_error;
1003 805460820 : tab->empty = 1;
1004 805460820 : return isl_stat_ok;
1005 : }
1006 :
1007 10910083355 : int isl_tab_freeze_constraint(struct isl_tab *tab, int con)
1008 : {
1009 : struct isl_tab_var *var;
1010 :
1011 10910083355 : if (!tab)
1012 0 : return -1;
1013 :
1014 10910083355 : var = &tab->con[con];
1015 10910083355 : if (var->frozen)
1016 0 : return 0;
1017 10910083355 : if (var->index < 0)
1018 311580467 : return 0;
1019 10598502888 : var->frozen = 1;
1020 :
1021 10598502888 : if (tab->need_undo)
1022 10598502888 : return isl_tab_push_var(tab, isl_tab_undo_freeze, var);
1023 :
1024 0 : return 0;
1025 : }
1026 :
1027 : /* Update the rows signs after a pivot of "row" and "col", with "row_sgn"
1028 : * the original sign of the pivot element.
1029 : * We only keep track of row signs during PILP solving and in this case
1030 : * we only pivot a row with negative sign (meaning the value is always
1031 : * non-positive) using a positive pivot element.
1032 : *
1033 : * For each row j, the new value of the parametric constant is equal to
1034 : *
1035 : * a_j0 - a_jc a_r0/a_rc
1036 : *
1037 : * where a_j0 is the original parametric constant, a_rc is the pivot element,
1038 : * a_r0 is the parametric constant of the pivot row and a_jc is the
1039 : * pivot column entry of the row j.
1040 : * Since a_r0 is non-positive and a_rc is positive, the sign of row j
1041 : * remains the same if a_jc has the same sign as the row j or if
1042 : * a_jc is zero. In all other cases, we reset the sign to "unknown".
1043 : */
1044 24716205376 : static void update_row_sign(struct isl_tab *tab, int row, int col, int row_sgn)
1045 : {
1046 : int i;
1047 24716205376 : struct isl_mat *mat = tab->mat;
1048 24716205376 : unsigned off = 2 + tab->M;
1049 :
1050 24716205376 : if (!tab->row_sign)
1051 24716205376 : return;
1052 :
1053 0 : if (tab->row_sign[row] == 0)
1054 0 : return;
1055 0 : isl_assert(mat->ctx, row_sgn > 0, return);
1056 0 : isl_assert(mat->ctx, tab->row_sign[row] == isl_tab_row_neg, return);
1057 0 : tab->row_sign[row] = isl_tab_row_pos;
1058 0 : for (i = 0; i < tab->n_row; ++i) {
1059 : int s;
1060 0 : if (i == row)
1061 0 : continue;
1062 0 : s = isl_int_sgn(mat->row[i][off + col]);
1063 0 : if (!s)
1064 0 : continue;
1065 0 : if (!tab->row_sign[i])
1066 0 : continue;
1067 0 : if (s < 0 && tab->row_sign[i] == isl_tab_row_neg)
1068 0 : continue;
1069 0 : if (s > 0 && tab->row_sign[i] == isl_tab_row_pos)
1070 0 : continue;
1071 0 : tab->row_sign[i] = isl_tab_row_unknown;
1072 : }
1073 : }
1074 :
1075 : /* Given a row number "row" and a column number "col", pivot the tableau
1076 : * such that the associated variables are interchanged.
1077 : * The given row in the tableau expresses
1078 : *
1079 : * x_r = a_r0 + \sum_i a_ri x_i
1080 : *
1081 : * or
1082 : *
1083 : * x_c = 1/a_rc x_r - a_r0/a_rc + sum_{i \ne r} -a_ri/a_rc
1084 : *
1085 : * Substituting this equality into the other rows
1086 : *
1087 : * x_j = a_j0 + \sum_i a_ji x_i
1088 : *
1089 : * with a_jc \ne 0, we obtain
1090 : *
1091 : * x_j = a_jc/a_rc x_r + a_j0 - a_jc a_r0/a_rc + sum a_ji - a_jc a_ri/a_rc
1092 : *
1093 : * The tableau
1094 : *
1095 : * n_rc/d_r n_ri/d_r
1096 : * n_jc/d_j n_ji/d_j
1097 : *
1098 : * where i is any other column and j is any other row,
1099 : * is therefore transformed into
1100 : *
1101 : * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
1102 : * s(n_rc)d_r n_jc/(|n_rc| d_j) (n_ji |n_rc| - s(n_rc)n_jc n_ri)/(|n_rc| d_j)
1103 : *
1104 : * The transformation is performed along the following steps
1105 : *
1106 : * d_r/n_rc n_ri/n_rc
1107 : * n_jc/d_j n_ji/d_j
1108 : *
1109 : * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
1110 : * n_jc/d_j n_ji/d_j
1111 : *
1112 : * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
1113 : * n_jc/(|n_rc| d_j) n_ji/(|n_rc| d_j)
1114 : *
1115 : * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
1116 : * n_jc/(|n_rc| d_j) (n_ji |n_rc|)/(|n_rc| d_j)
1117 : *
1118 : * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
1119 : * n_jc/(|n_rc| d_j) (n_ji |n_rc| - s(n_rc)n_jc n_ri)/(|n_rc| d_j)
1120 : *
1121 : * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
1122 : * s(n_rc)d_r n_jc/(|n_rc| d_j) (n_ji |n_rc| - s(n_rc)n_jc n_ri)/(|n_rc| d_j)
1123 : *
1124 : */
1125 24716205376 : int isl_tab_pivot(struct isl_tab *tab, int row, int col)
1126 : {
1127 : int i, j;
1128 : int sgn;
1129 : int t;
1130 : isl_ctx *ctx;
1131 24716205376 : struct isl_mat *mat = tab->mat;
1132 : struct isl_tab_var *var;
1133 24716205376 : unsigned off = 2 + tab->M;
1134 :
1135 24716205376 : ctx = isl_tab_get_ctx(tab);
1136 24716205376 : if (isl_ctx_next_operation(ctx) < 0)
1137 0 : return -1;
1138 :
1139 24716205376 : isl_int_swap(mat->row[row][0], mat->row[row][off + col]);
1140 24716205376 : sgn = isl_int_sgn(mat->row[row][0]);
1141 24716205376 : if (sgn < 0) {
1142 5990149498 : isl_int_neg(mat->row[row][0], mat->row[row][0]);
1143 5990149498 : isl_int_neg(mat->row[row][off + col], mat->row[row][off + col]);
1144 : } else
1145 >14923*10^7 : for (j = 0; j < off - 1 + tab->n_col; ++j) {
1146 >13050*10^7 : if (j == off - 1 + col)
1147 18726055878 : continue;
1148 >11178*10^7 : isl_int_neg(mat->row[row][1 + j], mat->row[row][1 + j]);
1149 : }
1150 24716205376 : if (!isl_int_is_one(mat->row[row][0]))
1151 8098515831 : isl_seq_normalize(mat->ctx, mat->row[row], off + tab->n_col);
1152 >23370*10^7 : for (i = 0; i < tab->n_row; ++i) {
1153 >20899*10^7 : if (i == row)
1154 24716205376 : continue;
1155 >18427*10^7 : if (isl_int_is_zero(mat->row[i][off + col]))
1156 >10698*10^7 : continue;
1157 77294032788 : isl_int_mul(mat->row[i][0], mat->row[i][0], mat->row[row][0]);
1158 >62802*10^7 : for (j = 0; j < off - 1 + tab->n_col; ++j) {
1159 >55073*10^7 : if (j == off - 1 + col)
1160 77294032788 : continue;
1161 >47343*10^7 : isl_int_mul(mat->row[i][1 + j],
1162 : mat->row[i][1 + j], mat->row[row][0]);
1163 >47343*10^7 : isl_int_addmul(mat->row[i][1 + j],
1164 : mat->row[i][off + col], mat->row[row][1 + j]);
1165 : }
1166 77294032788 : isl_int_mul(mat->row[i][off + col],
1167 : mat->row[i][off + col], mat->row[row][off + col]);
1168 77294032788 : if (!isl_int_is_one(mat->row[i][0]))
1169 74322745097 : isl_seq_normalize(mat->ctx, mat->row[i], off + tab->n_col);
1170 : }
1171 24716205376 : t = tab->row_var[row];
1172 24716205376 : tab->row_var[row] = tab->col_var[col];
1173 24716205376 : tab->col_var[col] = t;
1174 24716205376 : var = isl_tab_var_from_row(tab, row);
1175 24716205376 : var->is_row = 1;
1176 24716205376 : var->index = row;
1177 24716205376 : var = var_from_col(tab, col);
1178 24716205376 : var->is_row = 0;
1179 24716205376 : var->index = col;
1180 24716205376 : update_row_sign(tab, row, col, sgn);
1181 24716205376 : if (tab->in_undo)
1182 381339560 : return 0;
1183 >20834*10^7 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
1184 >18400*10^7 : if (isl_int_is_zero(mat->row[i][off + col]))
1185 97410802631 : continue;
1186 >16017*10^7 : if (!isl_tab_var_from_row(tab, i)->frozen &&
1187 73575099776 : isl_tab_row_is_redundant(tab, i)) {
1188 4812270692 : int redo = isl_tab_mark_redundant(tab, i);
1189 4812270692 : if (redo < 0)
1190 0 : return -1;
1191 4812270692 : if (redo)
1192 230379432 : --i;
1193 : }
1194 : }
1195 24334865816 : return 0;
1196 : }
1197 :
1198 : /* If "var" represents a column variable, then pivot is up (sgn > 0)
1199 : * or down (sgn < 0) to a row. The variable is assumed not to be
1200 : * unbounded in the specified direction.
1201 : * If sgn = 0, then the variable is unbounded in both directions,
1202 : * and we pivot with any row we can find.
1203 : */
1204 : static int to_row(struct isl_tab *tab, struct isl_tab_var *var, int sign) WARN_UNUSED;
1205 1171567299 : static int to_row(struct isl_tab *tab, struct isl_tab_var *var, int sign)
1206 : {
1207 : int r;
1208 1171567299 : unsigned off = 2 + tab->M;
1209 :
1210 1171567299 : if (var->is_row)
1211 619370503 : return 0;
1212 :
1213 552196796 : if (sign == 0) {
1214 157771337 : for (r = tab->n_redundant; r < tab->n_row; ++r)
1215 157771337 : if (!isl_int_is_zero(tab->mat->row[r][off+var->index]))
1216 : break;
1217 47261337 : isl_assert(tab->mat->ctx, r < tab->n_row, return -1);
1218 : } else {
1219 504935459 : r = pivot_row(tab, NULL, sign, var->index);
1220 504935459 : isl_assert(tab->mat->ctx, r >= 0, return -1);
1221 : }
1222 :
1223 552196796 : return isl_tab_pivot(tab, r, var->index);
1224 : }
1225 :
1226 : /* Check whether all variables that are marked as non-negative
1227 : * also have a non-negative sample value. This function is not
1228 : * called from the current code but is useful during debugging.
1229 : */
1230 : static void check_table(struct isl_tab *tab) __attribute__ ((unused));
1231 0 : static void check_table(struct isl_tab *tab)
1232 : {
1233 : int i;
1234 :
1235 0 : if (tab->empty)
1236 0 : return;
1237 0 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
1238 : struct isl_tab_var *var;
1239 0 : var = isl_tab_var_from_row(tab, i);
1240 0 : if (!var->is_nonneg)
1241 0 : continue;
1242 0 : if (tab->M) {
1243 0 : isl_assert(tab->mat->ctx,
1244 : !isl_int_is_neg(tab->mat->row[i][2]), abort());
1245 0 : if (isl_int_is_pos(tab->mat->row[i][2]))
1246 0 : continue;
1247 : }
1248 0 : isl_assert(tab->mat->ctx, !isl_int_is_neg(tab->mat->row[i][1]),
1249 : abort());
1250 : }
1251 : }
1252 :
1253 : /* Return the sign of the maximal value of "var".
1254 : * If the sign is not negative, then on return from this function,
1255 : * the sample value will also be non-negative.
1256 : *
1257 : * If "var" is manifestly unbounded wrt positive values, we are done.
1258 : * Otherwise, we pivot the variable up to a row if needed
1259 : * Then we continue pivoting down until either
1260 : * - no more down pivots can be performed
1261 : * - the sample value is positive
1262 : * - the variable is pivoted into a manifestly unbounded column
1263 : */
1264 670044224 : static int sign_of_max(struct isl_tab *tab, struct isl_tab_var *var)
1265 : {
1266 : int row, col;
1267 :
1268 670044224 : if (max_is_manifestly_unbounded(tab, var))
1269 34854614 : return 1;
1270 635189610 : if (to_row(tab, var, 1) < 0)
1271 0 : return -2;
1272 1630498137 : while (!isl_int_is_pos(tab->mat->row[var->index][1])) {
1273 802973078 : find_pivot(tab, var, var, 1, &row, &col);
1274 802973078 : if (row == -1)
1275 387244848 : return isl_int_sgn(tab->mat->row[var->index][1]);
1276 415728230 : if (isl_tab_pivot(tab, row, col) < 0)
1277 0 : return -2;
1278 415728230 : if (!var->is_row) /* manifestly unbounded */
1279 55609313 : return 1;
1280 : }
1281 192335449 : return 1;
1282 : }
1283 :
1284 0 : int isl_tab_sign_of_max(struct isl_tab *tab, int con)
1285 : {
1286 : struct isl_tab_var *var;
1287 :
1288 0 : if (!tab)
1289 0 : return -2;
1290 :
1291 0 : var = &tab->con[con];
1292 0 : isl_assert(tab->mat->ctx, !var->is_redundant, return -2);
1293 0 : isl_assert(tab->mat->ctx, !var->is_zero, return -2);
1294 :
1295 0 : return sign_of_max(tab, var);
1296 : }
1297 :
1298 14699681607 : static int row_is_neg(struct isl_tab *tab, int row)
1299 : {
1300 14699681607 : if (!tab->M)
1301 14699681607 : return isl_int_is_neg(tab->mat->row[row][1]);
1302 0 : if (isl_int_is_pos(tab->mat->row[row][2]))
1303 0 : return 0;
1304 0 : if (isl_int_is_neg(tab->mat->row[row][2]))
1305 0 : return 1;
1306 0 : return isl_int_is_neg(tab->mat->row[row][1]);
1307 : }
1308 :
1309 12998964181 : static int row_sgn(struct isl_tab *tab, int row)
1310 : {
1311 12998964181 : if (!tab->M)
1312 12998964181 : return isl_int_sgn(tab->mat->row[row][1]);
1313 0 : if (!isl_int_is_zero(tab->mat->row[row][2]))
1314 0 : return isl_int_sgn(tab->mat->row[row][2]);
1315 : else
1316 0 : return isl_int_sgn(tab->mat->row[row][1]);
1317 : }
1318 :
1319 : /* Perform pivots until the row variable "var" has a non-negative
1320 : * sample value or until no more upward pivots can be performed.
1321 : * Return the sign of the sample value after the pivots have been
1322 : * performed.
1323 : */
1324 13286314264 : static int restore_row(struct isl_tab *tab, struct isl_tab_var *var)
1325 : {
1326 : int row, col;
1327 :
1328 27985995871 : while (row_is_neg(tab, var->index)) {
1329 2506500974 : find_pivot(tab, var, var, 1, &row, &col);
1330 2506500974 : if (row == -1)
1331 805783548 : break;
1332 1700717426 : if (isl_tab_pivot(tab, row, col) < 0)
1333 0 : return -2;
1334 1700717426 : if (!var->is_row) /* manifestly unbounded */
1335 287350083 : return 1;
1336 : }
1337 12998964181 : return row_sgn(tab, var->index);
1338 : }
1339 :
1340 : /* Perform pivots until we are sure that the row variable "var"
1341 : * can attain non-negative values. After return from this
1342 : * function, "var" is still a row variable, but its sample
1343 : * value may not be non-negative, even if the function returns 1.
1344 : */
1345 7208278280 : static int at_least_zero(struct isl_tab *tab, struct isl_tab_var *var)
1346 : {
1347 : int row, col;
1348 :
1349 14431794877 : while (isl_int_is_neg(tab->mat->row[var->index][1])) {
1350 7216359581 : find_pivot(tab, var, var, 1, &row, &col);
1351 7216359581 : if (row == -1)
1352 7196337328 : break;
1353 20022253 : if (row == var->index) /* manifestly unbounded */
1354 4783936 : return 1;
1355 15238317 : if (isl_tab_pivot(tab, row, col) < 0)
1356 0 : return -1;
1357 : }
1358 7203494344 : return !isl_int_is_neg(tab->mat->row[var->index][1]);
1359 : }
1360 :
1361 : /* Return a negative value if "var" can attain negative values.
1362 : * Return a non-negative value otherwise.
1363 : *
1364 : * If "var" is manifestly unbounded wrt negative values, we are done.
1365 : * Otherwise, if var is in a column, we can pivot it down to a row.
1366 : * Then we continue pivoting down until either
1367 : * - the pivot would result in a manifestly unbounded column
1368 : * => we don't perform the pivot, but simply return -1
1369 : * - no more down pivots can be performed
1370 : * - the sample value is negative
1371 : * If the sample value becomes negative and the variable is supposed
1372 : * to be nonnegative, then we undo the last pivot.
1373 : * However, if the last pivot has made the pivoting variable
1374 : * obviously redundant, then it may have moved to another row.
1375 : * In that case we look for upward pivots until we reach a non-negative
1376 : * value again.
1377 : */
1378 11417362933 : static int sign_of_min(struct isl_tab *tab, struct isl_tab_var *var)
1379 : {
1380 : int row, col;
1381 11417362933 : struct isl_tab_var *pivot_var = NULL;
1382 :
1383 11417362933 : if (min_is_manifestly_unbounded(tab, var))
1384 0 : return -1;
1385 11417362933 : if (!var->is_row) {
1386 925086 : col = var->index;
1387 925086 : row = pivot_row(tab, NULL, -1, col);
1388 925086 : pivot_var = var_from_col(tab, col);
1389 925086 : if (isl_tab_pivot(tab, row, col) < 0)
1390 0 : return -2;
1391 925086 : if (var->is_redundant)
1392 147649 : return 0;
1393 777437 : if (isl_int_is_neg(tab->mat->row[var->index][1])) {
1394 461312 : if (var->is_nonneg) {
1395 922624 : if (!pivot_var->is_redundant &&
1396 461312 : pivot_var->index == row) {
1397 860244 : if (isl_tab_pivot(tab, row, col) < 0)
1398 0 : return -2;
1399 : } else
1400 31190 : if (restore_row(tab, var) < -1)
1401 0 : return -2;
1402 : }
1403 461312 : return -1;
1404 : }
1405 : }
1406 11416753972 : if (var->is_redundant)
1407 0 : return 0;
1408 22858463627 : while (!isl_int_is_neg(tab->mat->row[var->index][1])) {
1409 11427722368 : find_pivot(tab, var, var, -1, &row, &col);
1410 11427722368 : if (row == var->index)
1411 26222183 : return -1;
1412 11401500185 : if (row == -1)
1413 11376053425 : return isl_int_sgn(tab->mat->row[var->index][1]);
1414 25446760 : pivot_var = var_from_col(tab, col);
1415 25446760 : if (isl_tab_pivot(tab, row, col) < 0)
1416 0 : return -2;
1417 25446760 : if (var->is_redundant)
1418 491077 : return 0;
1419 : }
1420 13987287 : if (pivot_var && var->is_nonneg) {
1421 : /* pivot back to non-negative value */
1422 523082 : if (!pivot_var->is_redundant && pivot_var->index == row) {
1423 994522 : if (isl_tab_pivot(tab, row, col) < 0)
1424 0 : return -2;
1425 : } else
1426 25821 : if (restore_row(tab, var) < -1)
1427 0 : return -2;
1428 : }
1429 13987287 : return -1;
1430 : }
1431 :
1432 836082677 : static int row_at_most_neg_one(struct isl_tab *tab, int row)
1433 : {
1434 836082677 : if (tab->M) {
1435 0 : if (isl_int_is_pos(tab->mat->row[row][2]))
1436 0 : return 0;
1437 0 : if (isl_int_is_neg(tab->mat->row[row][2]))
1438 0 : return 1;
1439 : }
1440 1092270702 : return isl_int_is_neg(tab->mat->row[row][1]) &&
1441 256188025 : isl_int_abs_ge(tab->mat->row[row][1],
1442 : tab->mat->row[row][0]);
1443 : }
1444 :
1445 : /* Return 1 if "var" can attain values <= -1.
1446 : * Return 0 otherwise.
1447 : *
1448 : * If the variable "var" is supposed to be non-negative (is_nonneg is set),
1449 : * then the sample value of "var" is assumed to be non-negative when the
1450 : * the function is called. If 1 is returned then the constraint
1451 : * is not redundant and the sample value is made non-negative again before
1452 : * the function returns.
1453 : */
1454 582862086 : int isl_tab_min_at_most_neg_one(struct isl_tab *tab, struct isl_tab_var *var)
1455 : {
1456 : int row, col;
1457 : struct isl_tab_var *pivot_var;
1458 :
1459 582862086 : if (min_is_manifestly_unbounded(tab, var))
1460 0 : return 1;
1461 582862086 : if (!var->is_row) {
1462 147864907 : col = var->index;
1463 147864907 : row = pivot_row(tab, NULL, -1, col);
1464 147864907 : pivot_var = var_from_col(tab, col);
1465 147864907 : if (isl_tab_pivot(tab, row, col) < 0)
1466 0 : return -1;
1467 147864907 : if (var->is_redundant)
1468 24661944 : return 0;
1469 123202963 : if (row_at_most_neg_one(tab, var->index)) {
1470 80502838 : if (var->is_nonneg) {
1471 161005676 : if (!pivot_var->is_redundant &&
1472 80502838 : pivot_var->index == row) {
1473 159918060 : if (isl_tab_pivot(tab, row, col) < 0)
1474 0 : return -1;
1475 : } else
1476 543808 : if (restore_row(tab, var) < -1)
1477 0 : return -1;
1478 : }
1479 80502838 : return 1;
1480 : }
1481 : }
1482 477697304 : if (var->is_redundant)
1483 2 : return 0;
1484 : do {
1485 1047951548 : find_pivot(tab, var, var, -1, &row, &col);
1486 1047951548 : if (row == var->index) {
1487 56687786 : if (var->is_nonneg && restore_row(tab, var) < -1)
1488 0 : return -1;
1489 56687786 : return 1;
1490 : }
1491 991263762 : if (row == -1)
1492 109144629 : return 0;
1493 882119133 : pivot_var = var_from_col(tab, col);
1494 882119133 : if (isl_tab_pivot(tab, row, col) < 0)
1495 0 : return -1;
1496 882119133 : if (var->is_redundant)
1497 169239419 : return 0;
1498 712879714 : } while (!row_at_most_neg_one(tab, var->index));
1499 142625468 : if (var->is_nonneg) {
1500 : /* pivot back to non-negative value */
1501 138736701 : if (!pivot_var->is_redundant && pivot_var->index == row)
1502 137853481 : if (isl_tab_pivot(tab, row, col) < 0)
1503 0 : return -1;
1504 138736701 : if (restore_row(tab, var) < -1)
1505 0 : return -1;
1506 : }
1507 142625468 : return 1;
1508 : }
1509 :
1510 : /* Return 1 if "var" can attain values >= 1.
1511 : * Return 0 otherwise.
1512 : */
1513 245410099 : static int at_least_one(struct isl_tab *tab, struct isl_tab_var *var)
1514 : {
1515 : int row, col;
1516 : isl_int *r;
1517 :
1518 245410099 : if (max_is_manifestly_unbounded(tab, var))
1519 90463927 : return 1;
1520 154946172 : if (to_row(tab, var, 1) < 0)
1521 0 : return -1;
1522 154946172 : r = tab->mat->row[var->index];
1523 323523064 : while (isl_int_lt(r[1], r[0])) {
1524 17368142 : find_pivot(tab, var, var, 1, &row, &col);
1525 17368142 : if (row == -1)
1526 2878036 : return isl_int_ge(r[1], r[0]);
1527 14490106 : if (row == var->index) /* manifestly unbounded */
1528 859386 : return 1;
1529 13630720 : if (isl_tab_pivot(tab, row, col) < 0)
1530 0 : return -1;
1531 : }
1532 151208750 : return 1;
1533 : }
1534 :
1535 9032103822 : static void swap_cols(struct isl_tab *tab, int col1, int col2)
1536 : {
1537 : int t;
1538 9032103822 : unsigned off = 2 + tab->M;
1539 9032103822 : t = tab->col_var[col1];
1540 9032103822 : tab->col_var[col1] = tab->col_var[col2];
1541 9032103822 : tab->col_var[col2] = t;
1542 9032103822 : var_from_col(tab, col1)->index = col1;
1543 9032103822 : var_from_col(tab, col2)->index = col2;
1544 9032103822 : tab->mat = isl_mat_swap_cols(tab->mat, off + col1, off + col2);
1545 9032103822 : }
1546 :
1547 : /* Mark column with index "col" as representing a zero variable.
1548 : * If we may need to undo the operation the column is kept,
1549 : * but no longer considered.
1550 : * Otherwise, the column is simply removed.
1551 : *
1552 : * The column may be interchanged with some other column. If it
1553 : * is interchanged with a later column, return 1. Otherwise return 0.
1554 : * If the columns are checked in order in the calling function,
1555 : * then a return value of 1 means that the column with the given
1556 : * column number may now contain a different column that
1557 : * hasn't been checked yet.
1558 : */
1559 19128236403 : int isl_tab_kill_col(struct isl_tab *tab, int col)
1560 : {
1561 19128236403 : var_from_col(tab, col)->is_zero = 1;
1562 19128236403 : if (tab->need_undo) {
1563 103087761 : if (isl_tab_push_var(tab, isl_tab_undo_zero,
1564 : var_from_col(tab, col)) < 0)
1565 0 : return -1;
1566 103087761 : if (col != tab->n_dead)
1567 65094659 : swap_cols(tab, col, tab->n_dead);
1568 103087761 : tab->n_dead++;
1569 103087761 : return 0;
1570 : } else {
1571 19025148642 : if (col != tab->n_col - 1)
1572 8967009163 : swap_cols(tab, col, tab->n_col - 1);
1573 19025148642 : var_from_col(tab, tab->n_col - 1)->index = -1;
1574 19025148642 : tab->n_col--;
1575 19025148642 : return 1;
1576 : }
1577 : }
1578 :
1579 1840570125 : static int row_is_manifestly_non_integral(struct isl_tab *tab, int row)
1580 : {
1581 1840570125 : unsigned off = 2 + tab->M;
1582 :
1583 1840570125 : if (tab->M && !isl_int_eq(tab->mat->row[row][2],
1584 : tab->mat->row[row][0]))
1585 0 : return 0;
1586 1840570125 : if (isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
1587 1840570125 : tab->n_col - tab->n_dead) != -1)
1588 40848126 : return 0;
1589 :
1590 1799721999 : return !isl_int_is_divisible_by(tab->mat->row[row][1],
1591 : tab->mat->row[row][0]);
1592 : }
1593 :
1594 : /* For integer tableaus, check if any of the coordinates are stuck
1595 : * at a non-integral value.
1596 : */
1597 387194228 : static int tab_is_manifestly_empty(struct isl_tab *tab)
1598 : {
1599 : int i;
1600 :
1601 387194228 : if (tab->empty)
1602 2572 : return 1;
1603 387191656 : if (tab->rational)
1604 1034763 : return 0;
1605 :
1606 2246235839 : for (i = 0; i < tab->n_var; ++i) {
1607 1860158993 : if (!tab->var[i].is_row)
1608 19588868 : continue;
1609 1840570125 : if (row_is_manifestly_non_integral(tab, tab->var[i].index))
1610 80047 : return 1;
1611 : }
1612 :
1613 386076846 : return 0;
1614 : }
1615 :
1616 : /* Row variable "var" is non-negative and cannot attain any values
1617 : * larger than zero. This means that the coefficients of the unrestricted
1618 : * column variables are zero and that the coefficients of the non-negative
1619 : * column variables are zero or negative.
1620 : * Each of the non-negative variables with a negative coefficient can
1621 : * then also be written as the negative sum of non-negative variables
1622 : * and must therefore also be zero.
1623 : *
1624 : * If "temp_var" is set, then "var" is a temporary variable that
1625 : * will be removed after this function returns and for which
1626 : * no information is recorded on the undo stack.
1627 : * Do not add any undo records involving this variable in this case
1628 : * since the variable will have been removed before any future undo
1629 : * operations. Also avoid marking the variable as redundant,
1630 : * since that either adds an undo record or needlessly removes the row
1631 : * (the caller will take care of removing the row).
1632 : */
1633 : static isl_stat close_row(struct isl_tab *tab, struct isl_tab_var *var,
1634 : int temp_var) WARN_UNUSED;
1635 387194228 : static isl_stat close_row(struct isl_tab *tab, struct isl_tab_var *var,
1636 : int temp_var)
1637 : {
1638 : int j;
1639 387194228 : struct isl_mat *mat = tab->mat;
1640 387194228 : unsigned off = 2 + tab->M;
1641 :
1642 387194228 : if (!var->is_nonneg)
1643 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
1644 : "expecting non-negative variable",
1645 : return isl_stat_error);
1646 387194228 : var->is_zero = 1;
1647 387194228 : if (!temp_var && tab->need_undo)
1648 0 : if (isl_tab_push_var(tab, isl_tab_undo_zero, var) < 0)
1649 0 : return isl_stat_error;
1650 638202601 : for (j = tab->n_dead; j < tab->n_col; ++j) {
1651 : int recheck;
1652 251008373 : if (isl_int_is_zero(mat->row[var->index][off + j]))
1653 48132206 : continue;
1654 202876167 : if (isl_int_is_pos(mat->row[var->index][off + j]))
1655 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
1656 : "row cannot have positive coefficients",
1657 : return isl_stat_error);
1658 202876167 : recheck = isl_tab_kill_col(tab, j);
1659 202876167 : if (recheck < 0)
1660 0 : return isl_stat_error;
1661 202876167 : if (recheck)
1662 202490385 : --j;
1663 : }
1664 387194228 : if (!temp_var && isl_tab_mark_redundant(tab, var->index) < 0)
1665 0 : return isl_stat_error;
1666 387194228 : if (tab_is_manifestly_empty(tab) && isl_tab_mark_empty(tab) < 0)
1667 0 : return isl_stat_error;
1668 387194228 : return isl_stat_ok;
1669 : }
1670 :
1671 : /* Add a constraint to the tableau and allocate a row for it.
1672 : * Return the index into the constraint array "con".
1673 : *
1674 : * This function assumes that at least one more row and at least
1675 : * one more element in the constraint array are available in the tableau.
1676 : */
1677 50070934420 : int isl_tab_allocate_con(struct isl_tab *tab)
1678 : {
1679 : int r;
1680 :
1681 50070934420 : isl_assert(tab->mat->ctx, tab->n_row < tab->mat->n_row, return -1);
1682 50070934420 : isl_assert(tab->mat->ctx, tab->n_con < tab->max_con, return -1);
1683 :
1684 50070934420 : r = tab->n_con;
1685 50070934420 : tab->con[r].index = tab->n_row;
1686 50070934420 : tab->con[r].is_row = 1;
1687 50070934420 : tab->con[r].is_nonneg = 0;
1688 50070934420 : tab->con[r].is_zero = 0;
1689 50070934420 : tab->con[r].is_redundant = 0;
1690 50070934420 : tab->con[r].frozen = 0;
1691 50070934420 : tab->con[r].negated = 0;
1692 50070934420 : tab->row_var[tab->n_row] = ~r;
1693 :
1694 50070934420 : tab->n_row++;
1695 50070934420 : tab->n_con++;
1696 50070934420 : if (isl_tab_push_var(tab, isl_tab_undo_allocate, &tab->con[r]) < 0)
1697 0 : return -1;
1698 :
1699 50070934420 : return r;
1700 : }
1701 :
1702 : /* Move the entries in tab->var up one position, starting at "first",
1703 : * creating room for an extra entry at position "first".
1704 : * Since some of the entries of tab->row_var and tab->col_var contain
1705 : * indices into this array, they have to be updated accordingly.
1706 : */
1707 0 : static int var_insert_entry(struct isl_tab *tab, int first)
1708 : {
1709 : int i;
1710 :
1711 0 : if (tab->n_var >= tab->max_var)
1712 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
1713 : "not enough room for new variable", return -1);
1714 0 : if (first > tab->n_var)
1715 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
1716 : "invalid initial position", return -1);
1717 :
1718 0 : for (i = tab->n_var - 1; i >= first; --i) {
1719 0 : tab->var[i + 1] = tab->var[i];
1720 0 : if (tab->var[i + 1].is_row)
1721 0 : tab->row_var[tab->var[i + 1].index]++;
1722 : else
1723 0 : tab->col_var[tab->var[i + 1].index]++;
1724 : }
1725 :
1726 0 : tab->n_var++;
1727 :
1728 0 : return 0;
1729 : }
1730 :
1731 : /* Drop the entry at position "first" in tab->var, moving all
1732 : * subsequent entries down.
1733 : * Since some of the entries of tab->row_var and tab->col_var contain
1734 : * indices into this array, they have to be updated accordingly.
1735 : */
1736 0 : static int var_drop_entry(struct isl_tab *tab, int first)
1737 : {
1738 : int i;
1739 :
1740 0 : if (first >= tab->n_var)
1741 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
1742 : "invalid initial position", return -1);
1743 :
1744 0 : tab->n_var--;
1745 :
1746 0 : for (i = first; i < tab->n_var; ++i) {
1747 0 : tab->var[i] = tab->var[i + 1];
1748 0 : if (tab->var[i + 1].is_row)
1749 0 : tab->row_var[tab->var[i].index]--;
1750 : else
1751 0 : tab->col_var[tab->var[i].index]--;
1752 : }
1753 :
1754 0 : return 0;
1755 : }
1756 :
1757 : /* Add a variable to the tableau at position "r" and allocate a column for it.
1758 : * Return the index into the variable array "var", i.e., "r",
1759 : * or -1 on error.
1760 : */
1761 0 : int isl_tab_insert_var(struct isl_tab *tab, int r)
1762 : {
1763 : int i;
1764 0 : unsigned off = 2 + tab->M;
1765 :
1766 0 : isl_assert(tab->mat->ctx, tab->n_col < tab->mat->n_col, return -1);
1767 :
1768 0 : if (var_insert_entry(tab, r) < 0)
1769 0 : return -1;
1770 :
1771 0 : tab->var[r].index = tab->n_col;
1772 0 : tab->var[r].is_row = 0;
1773 0 : tab->var[r].is_nonneg = 0;
1774 0 : tab->var[r].is_zero = 0;
1775 0 : tab->var[r].is_redundant = 0;
1776 0 : tab->var[r].frozen = 0;
1777 0 : tab->var[r].negated = 0;
1778 0 : tab->col_var[tab->n_col] = r;
1779 :
1780 0 : for (i = 0; i < tab->n_row; ++i)
1781 0 : isl_int_set_si(tab->mat->row[i][off + tab->n_col], 0);
1782 :
1783 0 : tab->n_col++;
1784 0 : if (isl_tab_push_var(tab, isl_tab_undo_allocate, &tab->var[r]) < 0)
1785 0 : return -1;
1786 :
1787 0 : return r;
1788 : }
1789 :
1790 : /* Add a variable to the tableau and allocate a column for it.
1791 : * Return the index into the variable array "var".
1792 : */
1793 0 : int isl_tab_allocate_var(struct isl_tab *tab)
1794 : {
1795 0 : if (!tab)
1796 0 : return -1;
1797 :
1798 0 : return isl_tab_insert_var(tab, tab->n_var);
1799 : }
1800 :
1801 : /* Add a row to the tableau. The row is given as an affine combination
1802 : * of the original variables and needs to be expressed in terms of the
1803 : * column variables.
1804 : *
1805 : * This function assumes that at least one more row and at least
1806 : * one more element in the constraint array are available in the tableau.
1807 : *
1808 : * We add each term in turn.
1809 : * If r = n/d_r is the current sum and we need to add k x, then
1810 : * if x is a column variable, we increase the numerator of
1811 : * this column by k d_r
1812 : * if x = f/d_x is a row variable, then the new representation of r is
1813 : *
1814 : * n k f d_x/g n + d_r/g k f m/d_r n + m/d_g k f
1815 : * --- + --- = ------------------- = -------------------
1816 : * d_r d_r d_r d_x/g m
1817 : *
1818 : * with g the gcd of d_r and d_x and m the lcm of d_r and d_x.
1819 : *
1820 : * If tab->M is set, then, internally, each variable x is represented
1821 : * as x' - M. We then also need no subtract k d_r from the coefficient of M.
1822 : */
1823 50070910073 : int isl_tab_add_row(struct isl_tab *tab, isl_int *line)
1824 : {
1825 : int i;
1826 : int r;
1827 : isl_int *row;
1828 : isl_int a, b;
1829 50070910073 : unsigned off = 2 + tab->M;
1830 :
1831 50070910073 : r = isl_tab_allocate_con(tab);
1832 50070910073 : if (r < 0)
1833 0 : return -1;
1834 :
1835 50070910073 : isl_int_init(a);
1836 50070910073 : isl_int_init(b);
1837 50070910073 : row = tab->mat->row[tab->con[r].index];
1838 50070910073 : isl_int_set_si(row[0], 1);
1839 50070910073 : isl_int_set(row[1], line[0]);
1840 50070910073 : isl_seq_clr(row + 2, tab->M + tab->n_col);
1841 >40675*10^7 : for (i = 0; i < tab->n_var; ++i) {
1842 >35668*10^7 : if (tab->var[i].is_zero)
1843 0 : continue;
1844 >35668*10^7 : if (tab->var[i].is_row) {
1845 >20606*10^7 : isl_int_lcm(a,
1846 : row[0], tab->mat->row[tab->var[i].index][0]);
1847 >20606*10^7 : isl_int_swap(a, row[0]);
1848 >20606*10^7 : isl_int_divexact(a, row[0], a);
1849 >20606*10^7 : isl_int_divexact(b,
1850 : row[0], tab->mat->row[tab->var[i].index][0]);
1851 >20606*10^7 : isl_int_mul(b, b, line[1 + i]);
1852 >41213*10^7 : isl_seq_combine(row + 1, a, row + 1,
1853 >20606*10^7 : b, tab->mat->row[tab->var[i].index] + 1,
1854 >20606*10^7 : 1 + tab->M + tab->n_col);
1855 : } else
1856 >15061*10^7 : isl_int_addmul(row[off + tab->var[i].index],
1857 : line[1 + i], row[0]);
1858 >35668*10^7 : if (tab->M && i >= tab->n_param && i < tab->n_var - tab->n_div)
1859 0 : isl_int_submul(row[2], line[1 + i], row[0]);
1860 : }
1861 50070910073 : isl_seq_normalize(tab->mat->ctx, row, off + tab->n_col);
1862 50070910073 : isl_int_clear(a);
1863 50070910073 : isl_int_clear(b);
1864 :
1865 50070910073 : if (tab->row_sign)
1866 0 : tab->row_sign[tab->con[r].index] = isl_tab_row_unknown;
1867 :
1868 50070910073 : return r;
1869 : }
1870 :
1871 25065482622 : static isl_stat drop_row(struct isl_tab *tab, int row)
1872 : {
1873 25065482622 : isl_assert(tab->mat->ctx, ~tab->row_var[row] == tab->n_con - 1,
1874 : return isl_stat_error);
1875 25065482622 : if (row != tab->n_row - 1)
1876 1740831594 : swap_rows(tab, row, tab->n_row - 1);
1877 25065482622 : tab->n_row--;
1878 25065482622 : tab->n_con--;
1879 25065482622 : return isl_stat_ok;
1880 : }
1881 :
1882 : /* Drop the variable in column "col" along with the column.
1883 : * The column is removed first because it may need to be moved
1884 : * into the last position and this process requires
1885 : * the contents of the col_var array in a state
1886 : * before the removal of the variable.
1887 : */
1888 0 : static isl_stat drop_col(struct isl_tab *tab, int col)
1889 : {
1890 : int var;
1891 :
1892 0 : var = tab->col_var[col];
1893 0 : if (col != tab->n_col - 1)
1894 0 : swap_cols(tab, col, tab->n_col - 1);
1895 0 : tab->n_col--;
1896 0 : if (var_drop_entry(tab, var) < 0)
1897 0 : return isl_stat_error;
1898 0 : return isl_stat_ok;
1899 : }
1900 :
1901 : /* Add inequality "ineq" and check if it conflicts with the
1902 : * previously added constraints or if it is obviously redundant.
1903 : *
1904 : * This function assumes that at least one more row and at least
1905 : * one more element in the constraint array are available in the tableau.
1906 : */
1907 9871784566 : isl_stat isl_tab_add_ineq(struct isl_tab *tab, isl_int *ineq)
1908 : {
1909 : int r;
1910 : int sgn;
1911 : isl_int cst;
1912 :
1913 9871784566 : if (!tab)
1914 0 : return isl_stat_error;
1915 9871784566 : if (tab->bmap) {
1916 3829875142 : struct isl_basic_map *bmap = tab->bmap;
1917 :
1918 3829875142 : isl_assert(tab->mat->ctx, tab->n_eq == bmap->n_eq,
1919 : return isl_stat_error);
1920 3829875142 : isl_assert(tab->mat->ctx,
1921 : tab->n_con == bmap->n_eq + bmap->n_ineq,
1922 : return isl_stat_error);
1923 3829875142 : tab->bmap = isl_basic_map_add_ineq(tab->bmap, ineq);
1924 3829875142 : if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
1925 0 : return isl_stat_error;
1926 3829875142 : if (!tab->bmap)
1927 0 : return isl_stat_error;
1928 : }
1929 9871784566 : if (tab->cone) {
1930 0 : isl_int_init(cst);
1931 0 : isl_int_set_si(cst, 0);
1932 0 : isl_int_swap(ineq[0], cst);
1933 : }
1934 9871784566 : r = isl_tab_add_row(tab, ineq);
1935 9871784566 : if (tab->cone) {
1936 0 : isl_int_swap(ineq[0], cst);
1937 0 : isl_int_clear(cst);
1938 : }
1939 9871784566 : if (r < 0)
1940 0 : return isl_stat_error;
1941 9871784566 : tab->con[r].is_nonneg = 1;
1942 9871784566 : if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
1943 0 : return isl_stat_error;
1944 9871784566 : if (isl_tab_row_is_redundant(tab, tab->con[r].index)) {
1945 2088904098 : if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
1946 0 : return isl_stat_error;
1947 2088904098 : return isl_stat_ok;
1948 : }
1949 :
1950 7782880468 : sgn = restore_row(tab, &tab->con[r]);
1951 7782880468 : if (sgn < -1)
1952 0 : return isl_stat_error;
1953 7782880468 : if (sgn < 0)
1954 805333643 : return isl_tab_mark_empty(tab);
1955 6977546825 : if (tab->con[r].is_row && isl_tab_row_is_redundant(tab, tab->con[r].index))
1956 0 : if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
1957 0 : return isl_stat_error;
1958 6977546825 : return isl_stat_ok;
1959 : }
1960 :
1961 : /* Pivot a non-negative variable down until it reaches the value zero
1962 : * and then pivot the variable into a column position.
1963 : */
1964 : static int to_col(struct isl_tab *tab, struct isl_tab_var *var) WARN_UNUSED;
1965 102701979 : static int to_col(struct isl_tab *tab, struct isl_tab_var *var)
1966 : {
1967 : int i;
1968 : int row, col;
1969 102701979 : unsigned off = 2 + tab->M;
1970 :
1971 102701979 : if (!var->is_row)
1972 0 : return 0;
1973 :
1974 273449658 : while (isl_int_is_pos(tab->mat->row[var->index][1])) {
1975 160851411 : find_pivot(tab, var, NULL, -1, &row, &col);
1976 160851411 : isl_assert(tab->mat->ctx, row != -1, return -1);
1977 160851411 : if (isl_tab_pivot(tab, row, col) < 0)
1978 0 : return -1;
1979 160851411 : if (!var->is_row)
1980 92805711 : return 0;
1981 : }
1982 :
1983 16766505 : for (i = tab->n_dead; i < tab->n_col; ++i)
1984 16766505 : if (!isl_int_is_zero(tab->mat->row[var->index][off + i]))
1985 : break;
1986 :
1987 9896268 : isl_assert(tab->mat->ctx, i < tab->n_col, return -1);
1988 9896268 : if (isl_tab_pivot(tab, var->index, i) < 0)
1989 0 : return -1;
1990 :
1991 9896268 : return 0;
1992 : }
1993 :
1994 : /* We assume Gaussian elimination has been performed on the equalities.
1995 : * The equalities can therefore never conflict.
1996 : * Adding the equalities is currently only really useful for a later call
1997 : * to isl_tab_ineq_type.
1998 : *
1999 : * This function assumes that at least one more row and at least
2000 : * one more element in the constraint array are available in the tableau.
2001 : */
2002 18822658257 : static struct isl_tab *add_eq(struct isl_tab *tab, isl_int *eq)
2003 : {
2004 : int i;
2005 : int r;
2006 :
2007 18822658257 : if (!tab)
2008 0 : return NULL;
2009 18822658257 : r = isl_tab_add_row(tab, eq);
2010 18822658257 : if (r < 0)
2011 0 : goto error;
2012 :
2013 18822658257 : r = tab->con[r].index;
2014 18822658257 : i = isl_seq_first_non_zero(tab->mat->row[r] + 2 + tab->M + tab->n_dead,
2015 18822658257 : tab->n_col - tab->n_dead);
2016 18822658257 : isl_assert(tab->mat->ctx, i >= 0, goto error);
2017 18822658257 : i += tab->n_dead;
2018 18822658257 : if (isl_tab_pivot(tab, r, i) < 0)
2019 0 : goto error;
2020 18822658257 : if (isl_tab_kill_col(tab, i) < 0)
2021 0 : goto error;
2022 18822658257 : tab->n_eq++;
2023 :
2024 18822658257 : return tab;
2025 : error:
2026 0 : isl_tab_free(tab);
2027 0 : return NULL;
2028 : }
2029 :
2030 : /* Does the sample value of row "row" of "tab" involve the big parameter,
2031 : * if any?
2032 : */
2033 96541618 : static int row_is_big(struct isl_tab *tab, int row)
2034 : {
2035 96541618 : return tab->M && !isl_int_is_zero(tab->mat->row[row][2]);
2036 : }
2037 :
2038 104041679 : static int row_is_manifestly_zero(struct isl_tab *tab, int row)
2039 : {
2040 104041679 : unsigned off = 2 + tab->M;
2041 :
2042 104041679 : if (!isl_int_is_zero(tab->mat->row[row][1]))
2043 92811773 : return 0;
2044 11229906 : if (row_is_big(tab, row))
2045 0 : return 0;
2046 22459812 : return isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
2047 22459812 : tab->n_col - tab->n_dead) == -1;
2048 : }
2049 :
2050 : /* Add an equality that is known to be valid for the given tableau.
2051 : *
2052 : * This function assumes that at least one more row and at least
2053 : * one more element in the constraint array are available in the tableau.
2054 : */
2055 104008423 : int isl_tab_add_valid_eq(struct isl_tab *tab, isl_int *eq)
2056 : {
2057 : struct isl_tab_var *var;
2058 : int r;
2059 :
2060 104008423 : if (!tab)
2061 0 : return -1;
2062 104008423 : r = isl_tab_add_row(tab, eq);
2063 104008423 : if (r < 0)
2064 0 : return -1;
2065 :
2066 104008423 : var = &tab->con[r];
2067 104008423 : r = var->index;
2068 104008423 : if (row_is_manifestly_zero(tab, r)) {
2069 1335891 : var->is_zero = 1;
2070 1335891 : if (isl_tab_mark_redundant(tab, r) < 0)
2071 0 : return -1;
2072 1335891 : return 0;
2073 : }
2074 :
2075 102672532 : if (isl_int_is_neg(tab->mat->row[r][1])) {
2076 29157967 : isl_seq_neg(tab->mat->row[r] + 1, tab->mat->row[r] + 1,
2077 29157967 : 1 + tab->n_col);
2078 29157967 : var->negated = 1;
2079 : }
2080 102672532 : var->is_nonneg = 1;
2081 102672532 : if (to_col(tab, var) < 0)
2082 0 : return -1;
2083 102672532 : var->is_nonneg = 0;
2084 102672532 : if (isl_tab_kill_col(tab, var->index) < 0)
2085 0 : return -1;
2086 :
2087 102672532 : return 0;
2088 : }
2089 :
2090 : /* Add a zero row to "tab" and return the corresponding index
2091 : * in the constraint array.
2092 : *
2093 : * This function assumes that at least one more row and at least
2094 : * one more element in the constraint array are available in the tableau.
2095 : */
2096 24347 : static int add_zero_row(struct isl_tab *tab)
2097 : {
2098 : int r;
2099 : isl_int *row;
2100 :
2101 24347 : r = isl_tab_allocate_con(tab);
2102 24347 : if (r < 0)
2103 0 : return -1;
2104 :
2105 24347 : row = tab->mat->row[tab->con[r].index];
2106 24347 : isl_seq_clr(row + 1, 1 + tab->M + tab->n_col);
2107 24347 : isl_int_set_si(row[0], 1);
2108 :
2109 24347 : return r;
2110 : }
2111 :
2112 : /* Add equality "eq" and check if it conflicts with the
2113 : * previously added constraints or if it is obviously redundant.
2114 : *
2115 : * This function assumes that at least one more row and at least
2116 : * one more element in the constraint array are available in the tableau.
2117 : * If tab->bmap is set, then two rows are needed instead of one.
2118 : */
2119 33256 : int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
2120 : {
2121 33256 : struct isl_tab_undo *snap = NULL;
2122 : struct isl_tab_var *var;
2123 : int r;
2124 : int row;
2125 : int sgn;
2126 : isl_int cst;
2127 :
2128 33256 : if (!tab)
2129 0 : return -1;
2130 33256 : isl_assert(tab->mat->ctx, !tab->M, return -1);
2131 :
2132 33256 : if (tab->need_undo)
2133 33256 : snap = isl_tab_snap(tab);
2134 :
2135 33256 : if (tab->cone) {
2136 0 : isl_int_init(cst);
2137 0 : isl_int_set_si(cst, 0);
2138 0 : isl_int_swap(eq[0], cst);
2139 : }
2140 33256 : r = isl_tab_add_row(tab, eq);
2141 33256 : if (tab->cone) {
2142 0 : isl_int_swap(eq[0], cst);
2143 0 : isl_int_clear(cst);
2144 : }
2145 33256 : if (r < 0)
2146 0 : return -1;
2147 :
2148 33256 : var = &tab->con[r];
2149 33256 : row = var->index;
2150 33256 : if (row_is_manifestly_zero(tab, row)) {
2151 3809 : if (snap)
2152 3809 : return isl_tab_rollback(tab, snap);
2153 0 : return drop_row(tab, row);
2154 : }
2155 :
2156 29447 : if (tab->bmap) {
2157 24347 : tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
2158 24347 : if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
2159 0 : return -1;
2160 24347 : isl_seq_neg(eq, eq, 1 + tab->n_var);
2161 24347 : tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
2162 24347 : isl_seq_neg(eq, eq, 1 + tab->n_var);
2163 24347 : if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
2164 0 : return -1;
2165 24347 : if (!tab->bmap)
2166 0 : return -1;
2167 24347 : if (add_zero_row(tab) < 0)
2168 0 : return -1;
2169 : }
2170 :
2171 29447 : sgn = isl_int_sgn(tab->mat->row[row][1]);
2172 :
2173 29447 : if (sgn > 0) {
2174 1154 : isl_seq_neg(tab->mat->row[row] + 1, tab->mat->row[row] + 1,
2175 1154 : 1 + tab->n_col);
2176 1154 : var->negated = 1;
2177 1154 : sgn = -1;
2178 : }
2179 :
2180 29447 : if (sgn < 0) {
2181 16959 : sgn = sign_of_max(tab, var);
2182 16959 : if (sgn < -1)
2183 0 : return -1;
2184 16959 : if (sgn < 0) {
2185 0 : if (isl_tab_mark_empty(tab) < 0)
2186 0 : return -1;
2187 0 : return 0;
2188 : }
2189 : }
2190 :
2191 29447 : var->is_nonneg = 1;
2192 29447 : if (to_col(tab, var) < 0)
2193 0 : return -1;
2194 29447 : var->is_nonneg = 0;
2195 29447 : if (isl_tab_kill_col(tab, var->index) < 0)
2196 0 : return -1;
2197 :
2198 29447 : return 0;
2199 : }
2200 :
2201 : /* Construct and return an inequality that expresses an upper bound
2202 : * on the given div.
2203 : * In particular, if the div is given by
2204 : *
2205 : * d = floor(e/m)
2206 : *
2207 : * then the inequality expresses
2208 : *
2209 : * m d <= e
2210 : */
2211 0 : static struct isl_vec *ineq_for_div(struct isl_basic_map *bmap, unsigned div)
2212 : {
2213 : unsigned total;
2214 : unsigned div_pos;
2215 : struct isl_vec *ineq;
2216 :
2217 0 : if (!bmap)
2218 0 : return NULL;
2219 :
2220 0 : total = isl_basic_map_total_dim(bmap);
2221 0 : div_pos = 1 + total - bmap->n_div + div;
2222 :
2223 0 : ineq = isl_vec_alloc(bmap->ctx, 1 + total);
2224 0 : if (!ineq)
2225 0 : return NULL;
2226 :
2227 0 : isl_seq_cpy(ineq->el, bmap->div[div] + 1, 1 + total);
2228 0 : isl_int_neg(ineq->el[div_pos], bmap->div[div][0]);
2229 0 : return ineq;
2230 : }
2231 :
2232 : /* For a div d = floor(f/m), add the constraints
2233 : *
2234 : * f - m d >= 0
2235 : * -(f-(m-1)) + m d >= 0
2236 : *
2237 : * Note that the second constraint is the negation of
2238 : *
2239 : * f - m d >= m
2240 : *
2241 : * If add_ineq is not NULL, then this function is used
2242 : * instead of isl_tab_add_ineq to effectively add the inequalities.
2243 : *
2244 : * This function assumes that at least two more rows and at least
2245 : * two more elements in the constraint array are available in the tableau.
2246 : */
2247 0 : static isl_stat add_div_constraints(struct isl_tab *tab, unsigned div,
2248 : isl_stat (*add_ineq)(void *user, isl_int *), void *user)
2249 : {
2250 : unsigned total;
2251 : unsigned div_pos;
2252 : struct isl_vec *ineq;
2253 :
2254 0 : total = isl_basic_map_total_dim(tab->bmap);
2255 0 : div_pos = 1 + total - tab->bmap->n_div + div;
2256 :
2257 0 : ineq = ineq_for_div(tab->bmap, div);
2258 0 : if (!ineq)
2259 0 : goto error;
2260 :
2261 0 : if (add_ineq) {
2262 0 : if (add_ineq(user, ineq->el) < 0)
2263 0 : goto error;
2264 : } else {
2265 0 : if (isl_tab_add_ineq(tab, ineq->el) < 0)
2266 0 : goto error;
2267 : }
2268 :
2269 0 : isl_seq_neg(ineq->el, tab->bmap->div[div] + 1, 1 + total);
2270 0 : isl_int_set(ineq->el[div_pos], tab->bmap->div[div][0]);
2271 0 : isl_int_add(ineq->el[0], ineq->el[0], ineq->el[div_pos]);
2272 0 : isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
2273 :
2274 0 : if (add_ineq) {
2275 0 : if (add_ineq(user, ineq->el) < 0)
2276 0 : goto error;
2277 : } else {
2278 0 : if (isl_tab_add_ineq(tab, ineq->el) < 0)
2279 0 : goto error;
2280 : }
2281 :
2282 0 : isl_vec_free(ineq);
2283 :
2284 0 : return isl_stat_ok;
2285 : error:
2286 0 : isl_vec_free(ineq);
2287 0 : return isl_stat_error;
2288 : }
2289 :
2290 : /* Check whether the div described by "div" is obviously non-negative.
2291 : * If we are using a big parameter, then we will encode the div
2292 : * as div' = M + div, which is always non-negative.
2293 : * Otherwise, we check whether div is a non-negative affine combination
2294 : * of non-negative variables.
2295 : */
2296 0 : static int div_is_nonneg(struct isl_tab *tab, __isl_keep isl_vec *div)
2297 : {
2298 : int i;
2299 :
2300 0 : if (tab->M)
2301 0 : return 1;
2302 :
2303 0 : if (isl_int_is_neg(div->el[1]))
2304 0 : return 0;
2305 :
2306 0 : for (i = 0; i < tab->n_var; ++i) {
2307 0 : if (isl_int_is_neg(div->el[2 + i]))
2308 0 : return 0;
2309 0 : if (isl_int_is_zero(div->el[2 + i]))
2310 0 : continue;
2311 0 : if (!tab->var[i].is_nonneg)
2312 0 : return 0;
2313 : }
2314 :
2315 0 : return 1;
2316 : }
2317 :
2318 : /* Insert an extra div, prescribed by "div", to the tableau and
2319 : * the associated bmap (which is assumed to be non-NULL).
2320 : * The extra integer division is inserted at (tableau) position "pos".
2321 : * Return "pos" or -1 if an error occurred.
2322 : *
2323 : * If add_ineq is not NULL, then this function is used instead
2324 : * of isl_tab_add_ineq to add the div constraints.
2325 : * This complication is needed because the code in isl_tab_pip
2326 : * wants to perform some extra processing when an inequality
2327 : * is added to the tableau.
2328 : */
2329 0 : int isl_tab_insert_div(struct isl_tab *tab, int pos, __isl_keep isl_vec *div,
2330 : isl_stat (*add_ineq)(void *user, isl_int *), void *user)
2331 : {
2332 : int r;
2333 : int nonneg;
2334 : int n_div, o_div;
2335 :
2336 0 : if (!tab || !div)
2337 0 : return -1;
2338 :
2339 0 : if (div->size != 1 + 1 + tab->n_var)
2340 0 : isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
2341 : "unexpected size", return -1);
2342 :
2343 0 : isl_assert(tab->mat->ctx, tab->bmap, return -1);
2344 0 : n_div = isl_basic_map_dim(tab->bmap, isl_dim_div);
2345 0 : o_div = tab->n_var - n_div;
2346 0 : if (pos < o_div || pos > tab->n_var)
2347 0 : isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
2348 : "invalid position", return -1);
2349 :
2350 0 : nonneg = div_is_nonneg(tab, div);
2351 :
2352 0 : if (isl_tab_extend_cons(tab, 3) < 0)
2353 0 : return -1;
2354 0 : if (isl_tab_extend_vars(tab, 1) < 0)
2355 0 : return -1;
2356 0 : r = isl_tab_insert_var(tab, pos);
2357 0 : if (r < 0)
2358 0 : return -1;
2359 :
2360 0 : if (nonneg)
2361 0 : tab->var[r].is_nonneg = 1;
2362 :
2363 0 : tab->bmap = isl_basic_map_insert_div(tab->bmap, pos - o_div, div);
2364 0 : if (!tab->bmap)
2365 0 : return -1;
2366 0 : if (isl_tab_push_var(tab, isl_tab_undo_bmap_div, &tab->var[r]) < 0)
2367 0 : return -1;
2368 :
2369 0 : if (add_div_constraints(tab, pos - o_div, add_ineq, user) < 0)
2370 0 : return -1;
2371 :
2372 0 : return r;
2373 : }
2374 :
2375 : /* Add an extra div, prescribed by "div", to the tableau and
2376 : * the associated bmap (which is assumed to be non-NULL).
2377 : */
2378 0 : int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div)
2379 : {
2380 0 : if (!tab)
2381 0 : return -1;
2382 0 : return isl_tab_insert_div(tab, tab->n_var, div, NULL, NULL);
2383 : }
2384 :
2385 : /* If "track" is set, then we want to keep track of all constraints in tab
2386 : * in its bmap field. This field is initialized from a copy of "bmap",
2387 : * so we need to make sure that all constraints in "bmap" also appear
2388 : * in the constructed tab.
2389 : */
2390 5455020296 : __isl_give struct isl_tab *isl_tab_from_basic_map(
2391 : __isl_keep isl_basic_map *bmap, int track)
2392 : {
2393 : int i;
2394 : struct isl_tab *tab;
2395 :
2396 5455020296 : if (!bmap)
2397 0 : return NULL;
2398 10910040592 : tab = isl_tab_alloc(bmap->ctx,
2399 5455020296 : isl_basic_map_total_dim(bmap) + bmap->n_ineq + 1,
2400 : isl_basic_map_total_dim(bmap), 0);
2401 5455020296 : if (!tab)
2402 0 : return NULL;
2403 5455020296 : tab->preserve = track;
2404 5455020296 : tab->rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
2405 5455020296 : if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) {
2406 0 : if (isl_tab_mark_empty(tab) < 0)
2407 0 : goto error;
2408 0 : goto done;
2409 : }
2410 24273214798 : for (i = 0; i < bmap->n_eq; ++i) {
2411 18818194502 : tab = add_eq(tab, bmap->eq[i]);
2412 18818194502 : if (!tab)
2413 0 : return tab;
2414 : }
2415 11464381692 : for (i = 0; i < bmap->n_ineq; ++i) {
2416 6038590142 : if (isl_tab_add_ineq(tab, bmap->ineq[i]) < 0)
2417 0 : goto error;
2418 6038590142 : if (tab->empty)
2419 29228746 : goto done;
2420 : }
2421 : done:
2422 5455020296 : if (track && isl_tab_track_bmap(tab, isl_basic_map_copy(bmap)) < 0)
2423 0 : goto error;
2424 5455020296 : return tab;
2425 : error:
2426 0 : isl_tab_free(tab);
2427 0 : return NULL;
2428 : }
2429 :
2430 66139487 : __isl_give struct isl_tab *isl_tab_from_basic_set(
2431 : __isl_keep isl_basic_set *bset, int track)
2432 : {
2433 66139487 : return isl_tab_from_basic_map(bset, track);
2434 : }
2435 :
2436 : /* Construct a tableau corresponding to the recession cone of "bset".
2437 : */
2438 909813 : struct isl_tab *isl_tab_from_recession_cone(__isl_keep isl_basic_set *bset,
2439 : int parametric)
2440 : {
2441 : isl_int cst;
2442 : int i;
2443 : struct isl_tab *tab;
2444 909813 : unsigned offset = 0;
2445 :
2446 909813 : if (!bset)
2447 0 : return NULL;
2448 909813 : if (parametric)
2449 909813 : offset = isl_basic_set_dim(bset, isl_dim_param);
2450 909813 : tab = isl_tab_alloc(bset->ctx, bset->n_eq + bset->n_ineq,
2451 909813 : isl_basic_set_total_dim(bset) - offset, 0);
2452 909813 : if (!tab)
2453 0 : return NULL;
2454 909813 : tab->rational = ISL_F_ISSET(bset, ISL_BASIC_SET_RATIONAL);
2455 909813 : tab->cone = 1;
2456 :
2457 909813 : isl_int_init(cst);
2458 909813 : isl_int_set_si(cst, 0);
2459 5373568 : for (i = 0; i < bset->n_eq; ++i) {
2460 4463755 : isl_int_swap(bset->eq[i][offset], cst);
2461 4463755 : if (offset > 0) {
2462 0 : if (isl_tab_add_eq(tab, bset->eq[i] + offset) < 0)
2463 0 : goto error;
2464 : } else
2465 4463755 : tab = add_eq(tab, bset->eq[i]);
2466 4463755 : isl_int_swap(bset->eq[i][offset], cst);
2467 4463755 : if (!tab)
2468 0 : goto done;
2469 : }
2470 980750 : for (i = 0; i < bset->n_ineq; ++i) {
2471 : int r;
2472 70937 : isl_int_swap(bset->ineq[i][offset], cst);
2473 70937 : r = isl_tab_add_row(tab, bset->ineq[i] + offset);
2474 70937 : isl_int_swap(bset->ineq[i][offset], cst);
2475 70937 : if (r < 0)
2476 0 : goto error;
2477 70937 : tab->con[r].is_nonneg = 1;
2478 70937 : if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
2479 0 : goto error;
2480 : }
2481 : done:
2482 909813 : isl_int_clear(cst);
2483 909813 : return tab;
2484 : error:
2485 0 : isl_int_clear(cst);
2486 0 : isl_tab_free(tab);
2487 0 : return NULL;
2488 : }
2489 :
2490 : /* Assuming "tab" is the tableau of a cone, check if the cone is
2491 : * bounded, i.e., if it is empty or only contains the origin.
2492 : */
2493 909813 : isl_bool isl_tab_cone_is_bounded(struct isl_tab *tab)
2494 : {
2495 : int i;
2496 :
2497 909813 : if (!tab)
2498 0 : return isl_bool_error;
2499 909813 : if (tab->empty)
2500 0 : return isl_bool_true;
2501 909813 : if (tab->n_dead == tab->n_col)
2502 884106 : return isl_bool_true;
2503 :
2504 : for (;;) {
2505 233624 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
2506 : struct isl_tab_var *var;
2507 : int sgn;
2508 116812 : var = isl_tab_var_from_row(tab, i);
2509 116812 : if (!var->is_nonneg)
2510 88103 : continue;
2511 28709 : sgn = sign_of_max(tab, var);
2512 28709 : if (sgn < -1)
2513 0 : return isl_bool_error;
2514 28709 : if (sgn != 0)
2515 0 : return isl_bool_false;
2516 28709 : if (close_row(tab, var, 0) < 0)
2517 0 : return isl_bool_error;
2518 28709 : break;
2519 : }
2520 28709 : if (tab->n_dead == tab->n_col)
2521 25707 : return isl_bool_true;
2522 3002 : if (i == tab->n_row)
2523 0 : return isl_bool_false;
2524 3002 : }
2525 : }
2526 :
2527 188854843 : int isl_tab_sample_is_integer(struct isl_tab *tab)
2528 : {
2529 : int i;
2530 :
2531 188854843 : if (!tab)
2532 0 : return -1;
2533 :
2534 725708940 : for (i = 0; i < tab->n_var; ++i) {
2535 : int row;
2536 649722286 : if (!tab->var[i].is_row)
2537 65246544 : continue;
2538 584475742 : row = tab->var[i].index;
2539 584475742 : if (!isl_int_is_divisible_by(tab->mat->row[row][1],
2540 : tab->mat->row[row][0]))
2541 112868189 : return 0;
2542 : }
2543 75986654 : return 1;
2544 : }
2545 :
2546 68904148 : static struct isl_vec *extract_integer_sample(struct isl_tab *tab)
2547 : {
2548 : int i;
2549 : struct isl_vec *vec;
2550 :
2551 68904148 : vec = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
2552 68904148 : if (!vec)
2553 0 : return NULL;
2554 :
2555 68904148 : isl_int_set_si(vec->block.data[0], 1);
2556 417960289 : for (i = 0; i < tab->n_var; ++i) {
2557 349056141 : if (!tab->var[i].is_row)
2558 60655936 : isl_int_set_si(vec->block.data[1 + i], 0);
2559 : else {
2560 288400205 : int row = tab->var[i].index;
2561 288400205 : isl_int_divexact(vec->block.data[1 + i],
2562 : tab->mat->row[row][1], tab->mat->row[row][0]);
2563 : }
2564 : }
2565 :
2566 68904148 : return vec;
2567 : }
2568 :
2569 46597212 : struct isl_vec *isl_tab_get_sample_value(struct isl_tab *tab)
2570 : {
2571 : int i;
2572 : struct isl_vec *vec;
2573 : isl_int m;
2574 :
2575 46597212 : if (!tab)
2576 0 : return NULL;
2577 :
2578 46597212 : vec = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
2579 46597212 : if (!vec)
2580 0 : return NULL;
2581 :
2582 46597212 : isl_int_init(m);
2583 :
2584 46597212 : isl_int_set_si(vec->block.data[0], 1);
2585 307386577 : for (i = 0; i < tab->n_var; ++i) {
2586 : int row;
2587 260789365 : if (!tab->var[i].is_row) {
2588 47866252 : isl_int_set_si(vec->block.data[1 + i], 0);
2589 47866252 : continue;
2590 : }
2591 212923113 : row = tab->var[i].index;
2592 212923113 : isl_int_gcd(m, vec->block.data[0], tab->mat->row[row][0]);
2593 212923113 : isl_int_divexact(m, tab->mat->row[row][0], m);
2594 212923113 : isl_seq_scale(vec->block.data, vec->block.data, m, 1 + i);
2595 212923113 : isl_int_divexact(m, vec->block.data[0], tab->mat->row[row][0]);
2596 212923113 : isl_int_mul(vec->block.data[1 + i], m, tab->mat->row[row][1]);
2597 : }
2598 46597212 : vec = isl_vec_normalize(vec);
2599 :
2600 46597212 : isl_int_clear(m);
2601 46597212 : return vec;
2602 : }
2603 :
2604 : /* Store the sample value of "var" of "tab" rounded up (if sgn > 0)
2605 : * or down (if sgn < 0) to the nearest integer in *v.
2606 : */
2607 147512582 : static void get_rounded_sample_value(struct isl_tab *tab,
2608 : struct isl_tab_var *var, int sgn, isl_int *v)
2609 : {
2610 147512582 : if (!var->is_row)
2611 859648 : isl_int_set_si(*v, 0);
2612 146652934 : else if (sgn > 0)
2613 143983138 : isl_int_cdiv_q(*v, tab->mat->row[var->index][1],
2614 : tab->mat->row[var->index][0]);
2615 : else
2616 2669796 : isl_int_fdiv_q(*v, tab->mat->row[var->index][1],
2617 : tab->mat->row[var->index][0]);
2618 147512582 : }
2619 :
2620 : /* Update "bmap" based on the results of the tableau "tab".
2621 : * In particular, implicit equalities are made explicit, redundant constraints
2622 : * are removed and if the sample value happens to be integer, it is stored
2623 : * in "bmap" (unless "bmap" already had an integer sample).
2624 : *
2625 : * The tableau is assumed to have been created from "bmap" using
2626 : * isl_tab_from_basic_map.
2627 : */
2628 3069314595 : struct isl_basic_map *isl_basic_map_update_from_tab(struct isl_basic_map *bmap,
2629 : struct isl_tab *tab)
2630 : {
2631 : int i;
2632 : unsigned n_eq;
2633 :
2634 3069314595 : if (!bmap)
2635 0 : return NULL;
2636 3069314595 : if (!tab)
2637 0 : return bmap;
2638 :
2639 3069314595 : n_eq = tab->n_eq;
2640 3069314595 : if (tab->empty)
2641 1926672 : bmap = isl_basic_map_set_to_empty(bmap);
2642 : else
2643 4724143616 : for (i = bmap->n_ineq - 1; i >= 0; --i) {
2644 1656755693 : if (isl_tab_is_equality(tab, n_eq + i))
2645 583854842 : isl_basic_map_inequality_to_equality(bmap, i);
2646 1072900851 : else if (isl_tab_is_redundant(tab, n_eq + i))
2647 259605480 : isl_basic_map_drop_inequality(bmap, i);
2648 : }
2649 3069314595 : if (bmap->n_eq != n_eq)
2650 48709663 : bmap = isl_basic_map_gauss(bmap, NULL);
2651 3069314595 : if (!tab->rational &&
2652 132209644 : bmap && !bmap->sample && isl_tab_sample_is_integer(tab))
2653 68904148 : bmap->sample = extract_integer_sample(tab);
2654 3069314595 : return bmap;
2655 : }
2656 :
2657 1065652 : struct isl_basic_set *isl_basic_set_update_from_tab(struct isl_basic_set *bset,
2658 : struct isl_tab *tab)
2659 : {
2660 1065652 : return bset_from_bmap(isl_basic_map_update_from_tab(bset_to_bmap(bset),
2661 : tab));
2662 : }
2663 :
2664 : /* Drop the last constraint added to "tab" in position "r".
2665 : * The constraint is expected to have remained in a row.
2666 : */
2667 3262293 : static isl_stat drop_last_con_in_row(struct isl_tab *tab, int r)
2668 : {
2669 3262293 : if (!tab->con[r].is_row)
2670 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
2671 : "row unexpectedly moved to column",
2672 : return isl_stat_error);
2673 3262293 : if (r + 1 != tab->n_con)
2674 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
2675 : "additional constraints added", return isl_stat_error);
2676 3262293 : if (drop_row(tab, tab->con[r].index) < 0)
2677 0 : return isl_stat_error;
2678 :
2679 3262293 : return isl_stat_ok;
2680 : }
2681 :
2682 : /* Given a non-negative variable "var", temporarily add a new non-negative
2683 : * variable that is the opposite of "var", ensuring that "var" can only attain
2684 : * the value zero. The new variable is removed again before this function
2685 : * returns. However, the effect of forcing "var" to be zero remains.
2686 : * If var = n/d is a row variable, then the new variable = -n/d.
2687 : * If var is a column variables, then the new variable = -var.
2688 : * If the new variable cannot attain non-negative values, then
2689 : * the resulting tableau is empty.
2690 : * Otherwise, we know the value will be zero and we close the row.
2691 : */
2692 3262293 : static isl_stat cut_to_hyperplane(struct isl_tab *tab, struct isl_tab_var *var)
2693 : {
2694 : unsigned r;
2695 : isl_int *row;
2696 : int sgn;
2697 3262293 : unsigned off = 2 + tab->M;
2698 :
2699 3262293 : if (var->is_zero)
2700 0 : return isl_stat_ok;
2701 3262293 : if (var->is_redundant || !var->is_nonneg)
2702 0 : isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
2703 : "expecting non-redundant non-negative variable",
2704 : return isl_stat_error);
2705 :
2706 3262293 : if (isl_tab_extend_cons(tab, 1) < 0)
2707 0 : return isl_stat_error;
2708 :
2709 3262293 : r = tab->n_con;
2710 3262293 : tab->con[r].index = tab->n_row;
2711 3262293 : tab->con[r].is_row = 1;
2712 3262293 : tab->con[r].is_nonneg = 0;
2713 3262293 : tab->con[r].is_zero = 0;
2714 3262293 : tab->con[r].is_redundant = 0;
2715 3262293 : tab->con[r].frozen = 0;
2716 3262293 : tab->con[r].negated = 0;
2717 3262293 : tab->row_var[tab->n_row] = ~r;
2718 3262293 : row = tab->mat->row[tab->n_row];
2719 :
2720 3262293 : if (var->is_row) {
2721 2918079 : isl_int_set(row[0], tab->mat->row[var->index][0]);
2722 5836158 : isl_seq_neg(row + 1,
2723 5836158 : tab->mat->row[var->index] + 1, 1 + tab->n_col);
2724 : } else {
2725 344214 : isl_int_set_si(row[0], 1);
2726 344214 : isl_seq_clr(row + 1, 1 + tab->n_col);
2727 344214 : isl_int_set_si(row[off + var->index], -1);
2728 : }
2729 :
2730 3262293 : tab->n_row++;
2731 3262293 : tab->n_con++;
2732 :
2733 3262293 : sgn = sign_of_max(tab, &tab->con[r]);
2734 3262293 : if (sgn < -1)
2735 0 : return isl_stat_error;
2736 3262293 : if (sgn < 0) {
2737 44558 : if (drop_last_con_in_row(tab, r) < 0)
2738 0 : return isl_stat_error;
2739 44558 : if (isl_tab_mark_empty(tab) < 0)
2740 0 : return isl_stat_error;
2741 44558 : return isl_stat_ok;
2742 : }
2743 3217735 : tab->con[r].is_nonneg = 1;
2744 : /* sgn == 0 */
2745 3217735 : if (close_row(tab, &tab->con[r], 1) < 0)
2746 0 : return isl_stat_error;
2747 3217735 : if (drop_last_con_in_row(tab, r) < 0)
2748 0 : return isl_stat_error;
2749 :
2750 3217735 : return isl_stat_ok;
2751 : }
2752 :
2753 : /* Check that "con" is a valid constraint position for "tab".
2754 : */
2755 1624792070 : static isl_stat isl_tab_check_con(struct isl_tab *tab, int con)
2756 : {
2757 1624792070 : if (!tab)
2758 0 : return isl_stat_error;
2759 1624792070 : if (con < 0 || con >= tab->n_con)
2760 0 : isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
2761 : "position out of bounds", return isl_stat_error);
2762 1624792070 : return isl_stat_ok;
2763 : }
2764 :
2765 : /* Given a tableau "tab" and an inequality constraint "con" of the tableau,
2766 : * relax the inequality by one. That is, the inequality r >= 0 is replaced
2767 : * by r' = r + 1 >= 0.
2768 : * If r is a row variable, we simply increase the constant term by one
2769 : * (taking into account the denominator).
2770 : * If r is a column variable, then we need to modify each row that
2771 : * refers to r = r' - 1 by substituting this equality, effectively
2772 : * subtracting the coefficient of the column from the constant.
2773 : * We should only do this if the minimum is manifestly unbounded,
2774 : * however. Otherwise, we may end up with negative sample values
2775 : * for non-negative variables.
2776 : * So, if r is a column variable with a minimum that is not
2777 : * manifestly unbounded, then we need to move it to a row.
2778 : * However, the sample value of this row may be negative,
2779 : * even after the relaxation, so we need to restore it.
2780 : * We therefore prefer to pivot a column up to a row, if possible.
2781 : */
2782 380231 : int isl_tab_relax(struct isl_tab *tab, int con)
2783 : {
2784 : struct isl_tab_var *var;
2785 :
2786 380231 : if (!tab)
2787 0 : return -1;
2788 :
2789 380231 : var = &tab->con[con];
2790 :
2791 380231 : if (var->is_row && (var->index < 0 || var->index < tab->n_redundant))
2792 0 : isl_die(tab->mat->ctx, isl_error_invalid,
2793 : "cannot relax redundant constraint", return -1);
2794 380231 : if (!var->is_row && (var->index < 0 || var->index < tab->n_dead))
2795 0 : isl_die(tab->mat->ctx, isl_error_invalid,
2796 : "cannot relax dead constraint", return -1);
2797 :
2798 380231 : if (!var->is_row && !max_is_manifestly_unbounded(tab, var))
2799 36170 : if (to_row(tab, var, 1) < 0)
2800 0 : return -1;
2801 380231 : if (!var->is_row && !min_is_manifestly_unbounded(tab, var))
2802 4540 : if (to_row(tab, var, -1) < 0)
2803 0 : return -1;
2804 :
2805 380231 : if (var->is_row) {
2806 41891 : isl_int_add(tab->mat->row[var->index][1],
2807 : tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
2808 41891 : if (restore_row(tab, var) < 0)
2809 0 : return -1;
2810 : } else {
2811 : int i;
2812 338340 : unsigned off = 2 + tab->M;
2813 :
2814 1293049 : for (i = 0; i < tab->n_row; ++i) {
2815 954709 : if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
2816 576556 : continue;
2817 378153 : isl_int_sub(tab->mat->row[i][1], tab->mat->row[i][1],
2818 : tab->mat->row[i][off + var->index]);
2819 : }
2820 :
2821 : }
2822 :
2823 380231 : if (isl_tab_push_var(tab, isl_tab_undo_relax, var) < 0)
2824 0 : return -1;
2825 :
2826 380231 : return 0;
2827 : }
2828 :
2829 : /* Replace the variable v at position "pos" in the tableau "tab"
2830 : * by v' = v + shift.
2831 : *
2832 : * If the variable is in a column, then we first check if we can
2833 : * simply plug in v = v' - shift. The effect on a row with
2834 : * coefficient f/d for variable v is that the constant term c/d
2835 : * is replaced by (c - f * shift)/d. If shift is positive and
2836 : * f is negative for each row that needs to remain non-negative,
2837 : * then this is clearly safe. In other words, if the minimum of v
2838 : * is manifestly unbounded, then we can keep v in a column position.
2839 : * Otherwise, we can pivot it down to a row.
2840 : * Similarly, if shift is negative, we need to check if the maximum
2841 : * of is manifestly unbounded.
2842 : *
2843 : * If the variable is in a row (from the start or after pivoting),
2844 : * then the constant term c/d is replaced by (c + d * shift)/d.
2845 : */
2846 0 : int isl_tab_shift_var(struct isl_tab *tab, int pos, isl_int shift)
2847 : {
2848 : struct isl_tab_var *var;
2849 :
2850 0 : if (!tab)
2851 0 : return -1;
2852 0 : if (isl_int_is_zero(shift))
2853 0 : return 0;
2854 :
2855 0 : var = &tab->var[pos];
2856 0 : if (!var->is_row) {
2857 0 : if (isl_int_is_neg(shift)) {
2858 0 : if (!max_is_manifestly_unbounded(tab, var))
2859 0 : if (to_row(tab, var, 1) < 0)
2860 0 : return -1;
2861 : } else {
2862 0 : if (!min_is_manifestly_unbounded(tab, var))
2863 0 : if (to_row(tab, var, -1) < 0)
2864 0 : return -1;
2865 : }
2866 : }
2867 :
2868 0 : if (var->is_row) {
2869 0 : isl_int_addmul(tab->mat->row[var->index][1],
2870 : shift, tab->mat->row[var->index][0]);
2871 : } else {
2872 : int i;
2873 0 : unsigned off = 2 + tab->M;
2874 :
2875 0 : for (i = 0; i < tab->n_row; ++i) {
2876 0 : if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
2877 0 : continue;
2878 0 : isl_int_submul(tab->mat->row[i][1],
2879 : shift, tab->mat->row[i][off + var->index]);
2880 : }
2881 :
2882 : }
2883 :
2884 0 : return 0;
2885 : }
2886 :
2887 : /* Remove the sign constraint from constraint "con".
2888 : *
2889 : * If the constraint variable was originally marked non-negative,
2890 : * then we make sure we mark it non-negative again during rollback.
2891 : */
2892 688378 : int isl_tab_unrestrict(struct isl_tab *tab, int con)
2893 : {
2894 : struct isl_tab_var *var;
2895 :
2896 688378 : if (!tab)
2897 0 : return -1;
2898 :
2899 688378 : var = &tab->con[con];
2900 688378 : if (!var->is_nonneg)
2901 0 : return 0;
2902 :
2903 688378 : var->is_nonneg = 0;
2904 688378 : if (isl_tab_push_var(tab, isl_tab_undo_unrestrict, var) < 0)
2905 0 : return -1;
2906 :
2907 688378 : return 0;
2908 : }
2909 :
2910 384257 : int isl_tab_select_facet(struct isl_tab *tab, int con)
2911 : {
2912 384257 : if (!tab)
2913 0 : return -1;
2914 :
2915 384257 : return cut_to_hyperplane(tab, &tab->con[con]);
2916 : }
2917 :
2918 4077465203 : static int may_be_equality(struct isl_tab *tab, int row)
2919 : {
2920 8213525812 : return tab->rational ? isl_int_is_zero(tab->mat->row[row][1])
2921 4136060609 : : isl_int_lt(tab->mat->row[row][1],
2922 : tab->mat->row[row][0]);
2923 : }
2924 :
2925 : /* Return an isl_tab_var that has been marked or NULL if no such
2926 : * variable can be found.
2927 : * The marked field has only been set for variables that
2928 : * appear in non-redundant rows or non-dead columns.
2929 : *
2930 : * Pick the last constraint variable that is marked and
2931 : * that appears in either a non-redundant row or a non-dead columns.
2932 : * Since the returned variable is tested for being a redundant constraint or
2933 : * an implicit equality, there is no need to return any tab variable that
2934 : * corresponds to a variable.
2935 : */
2936 1237786113 : static struct isl_tab_var *select_marked(struct isl_tab *tab)
2937 : {
2938 : int i;
2939 : struct isl_tab_var *var;
2940 :
2941 10894147036 : for (i = tab->n_con - 1; i >= 0; --i) {
2942 10819561321 : var = &tab->con[i];
2943 10819561321 : if (var->index < 0)
2944 5373514603 : continue;
2945 5446046718 : if (var->is_row && var->index < tab->n_redundant)
2946 1099995297 : continue;
2947 4346051421 : if (!var->is_row && var->index < tab->n_dead)
2948 15254 : continue;
2949 4346036167 : if (var->marked)
2950 1163200398 : return var;
2951 : }
2952 :
2953 74585715 : return NULL;
2954 : }
2955 :
2956 : /* Check for (near) equalities among the constraints.
2957 : * A constraint is an equality if it is non-negative and if
2958 : * its maximal value is either
2959 : * - zero (in case of rational tableaus), or
2960 : * - strictly less than 1 (in case of integer tableaus)
2961 : *
2962 : * We first mark all non-redundant and non-dead variables that
2963 : * are not frozen and not obviously not an equality.
2964 : * Then we iterate over all marked variables if they can attain
2965 : * any values larger than zero or at least one.
2966 : * If the maximal value is zero, we mark any column variables
2967 : * that appear in the row as being zero and mark the row as being redundant.
2968 : * Otherwise, if the maximal value is strictly less than one (and the
2969 : * tableau is integer), then we restrict the value to being zero
2970 : * by adding an opposite non-negative variable.
2971 : * The order in which the variables are considered is not important.
2972 : */
2973 3051342963 : int isl_tab_detect_implicit_equalities(struct isl_tab *tab)
2974 : {
2975 : int i;
2976 : unsigned n_marked;
2977 :
2978 3051342963 : if (!tab)
2979 0 : return -1;
2980 3051342963 : if (tab->empty)
2981 2078749 : return 0;
2982 3049264214 : if (tab->n_dead == tab->n_col)
2983 2901044469 : return 0;
2984 :
2985 148219745 : n_marked = 0;
2986 1632122324 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
2987 1483902579 : struct isl_tab_var *var = isl_tab_var_from_row(tab, i);
2988 2754253383 : var->marked = !var->frozen && var->is_nonneg &&
2989 1270350804 : may_be_equality(tab, i);
2990 1483902579 : if (var->marked)
2991 772122446 : n_marked++;
2992 : }
2993 718536201 : for (i = tab->n_dead; i < tab->n_col; ++i) {
2994 570316456 : struct isl_tab_var *var = var_from_col(tab, i);
2995 570316456 : var->marked = !var->frozen && var->is_nonneg;
2996 570316456 : if (var->marked)
2997 191221269 : n_marked++;
2998 : }
2999 960297717 : while (n_marked) {
3000 : struct isl_tab_var *var;
3001 : int sgn;
3002 715938933 : var = select_marked(tab);
3003 715938933 : if (!var)
3004 49202670 : break;
3005 666736263 : var->marked = 0;
3006 666736263 : n_marked--;
3007 666736263 : sgn = sign_of_max(tab, var);
3008 666736263 : if (sgn < 0)
3009 0 : return -1;
3010 666736263 : if (sgn == 0) {
3011 383947784 : if (close_row(tab, var, 0) < 0)
3012 0 : return -1;
3013 282788479 : } else if (!tab->rational && !at_least_one(tab, var)) {
3014 2878036 : if (cut_to_hyperplane(tab, var) < 0)
3015 0 : return -1;
3016 2878036 : return isl_tab_detect_implicit_equalities(tab);
3017 : }
3018 7185446198 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
3019 6521587971 : var = isl_tab_var_from_row(tab, i);
3020 6521587971 : if (!var->marked)
3021 3714473572 : continue;
3022 2807114399 : if (may_be_equality(tab, i))
3023 2792379314 : continue;
3024 14735085 : var->marked = 0;
3025 14735085 : n_marked--;
3026 : }
3027 : }
3028 :
3029 145341709 : return 0;
3030 : }
3031 :
3032 : /* Update the element of row_var or col_var that corresponds to
3033 : * constraint tab->con[i] to a move from position "old" to position "i".
3034 : */
3035 1544746 : static int update_con_after_move(struct isl_tab *tab, int i, int old)
3036 : {
3037 : int *p;
3038 : int index;
3039 :
3040 1544746 : index = tab->con[i].index;
3041 1544746 : if (index == -1)
3042 1118901 : return 0;
3043 425845 : p = tab->con[i].is_row ? tab->row_var : tab->col_var;
3044 425845 : if (p[index] != ~old)
3045 0 : isl_die(tab->mat->ctx, isl_error_internal,
3046 : "broken internal state", return -1);
3047 425845 : p[index] = ~i;
3048 :
3049 425845 : return 0;
3050 : }
3051 :
3052 : /* Interchange constraints "con1" and "con2" in "tab".
3053 : * In particular, interchange the contents of these entries in tab->con.
3054 : * Since tab->col_var and tab->row_var point back into this array,
3055 : * they need to be updated accordingly.
3056 : */
3057 63502 : isl_stat isl_tab_swap_constraints(struct isl_tab *tab, int con1, int con2)
3058 : {
3059 : struct isl_tab_var var;
3060 :
3061 127004 : if (isl_tab_check_con(tab, con1) < 0 ||
3062 63502 : isl_tab_check_con(tab, con2) < 0)
3063 0 : return isl_stat_error;
3064 :
3065 63502 : var = tab->con[con1];
3066 63502 : tab->con[con1] = tab->con[con2];
3067 63502 : if (update_con_after_move(tab, con1, con2) < 0)
3068 0 : return isl_stat_error;
3069 63502 : tab->con[con2] = var;
3070 63502 : if (update_con_after_move(tab, con2, con1) < 0)
3071 0 : return isl_stat_error;
3072 :
3073 63502 : return isl_stat_ok;
3074 : }
3075 :
3076 : /* Rotate the "n" constraints starting at "first" to the right,
3077 : * putting the last constraint in the position of the first constraint.
3078 : */
3079 345222 : static int rotate_constraints(struct isl_tab *tab, int first, int n)
3080 : {
3081 : int i, last;
3082 : struct isl_tab_var var;
3083 :
3084 345222 : if (n <= 1)
3085 113290 : return 0;
3086 :
3087 231932 : last = first + n - 1;
3088 231932 : var = tab->con[last];
3089 1274050 : for (i = last; i > first; --i) {
3090 1042118 : tab->con[i] = tab->con[i - 1];
3091 1042118 : if (update_con_after_move(tab, i, i - 1) < 0)
3092 0 : return -1;
3093 : }
3094 231932 : tab->con[first] = var;
3095 231932 : if (update_con_after_move(tab, first, last) < 0)
3096 0 : return -1;
3097 :
3098 231932 : return 0;
3099 : }
3100 :
3101 : /* Drop the "n" entries starting at position "first" in tab->con, moving all
3102 : * subsequent entries down.
3103 : * Since some of the entries of tab->row_var and tab->col_var contain
3104 : * indices into this array, they have to be updated accordingly.
3105 : */
3106 49454 : static isl_stat con_drop_entries(struct isl_tab *tab,
3107 : unsigned first, unsigned n)
3108 : {
3109 : int i;
3110 :
3111 49454 : if (first + n > tab->n_con || first + n < first)
3112 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
3113 : "invalid range", return isl_stat_error);
3114 :
3115 49454 : tab->n_con -= n;
3116 :
3117 193146 : for (i = first; i < tab->n_con; ++i) {
3118 143692 : tab->con[i] = tab->con[i + n];
3119 143692 : if (update_con_after_move(tab, i, i + n) < 0)
3120 0 : return isl_stat_error;
3121 : }
3122 :
3123 49454 : return isl_stat_ok;
3124 : }
3125 :
3126 : /* isl_basic_map_gauss5 callback that gets called when
3127 : * two (equality) constraints "a" and "b" get interchanged
3128 : * in the basic map. Perform the same interchange in "tab".
3129 : */
3130 63502 : static isl_stat swap_eq(unsigned a, unsigned b, void *user)
3131 : {
3132 63502 : struct isl_tab *tab = user;
3133 :
3134 63502 : return isl_tab_swap_constraints(tab, a, b);
3135 : }
3136 :
3137 : /* isl_basic_map_gauss5 callback that gets called when
3138 : * the final "n" equality constraints get removed.
3139 : * As a special case, if "n" is equal to the total number
3140 : * of equality constraints, then this means the basic map
3141 : * turned out to be empty.
3142 : * Drop the same number of equality constraints from "tab" or
3143 : * mark it empty in the special case.
3144 : */
3145 49454 : static isl_stat drop_eq(unsigned n, void *user)
3146 : {
3147 49454 : struct isl_tab *tab = user;
3148 :
3149 49454 : if (tab->n_eq == n)
3150 0 : return isl_tab_mark_empty(tab);
3151 :
3152 49454 : tab->n_eq -= n;
3153 49454 : return con_drop_entries(tab, tab->n_eq, n);
3154 : }
3155 :
3156 : /* If "bmap" has more than a single reference, then call
3157 : * isl_basic_map_gauss on it, updating "tab" accordingly.
3158 : */
3159 52565 : static __isl_give isl_basic_map *gauss_if_shared(__isl_take isl_basic_map *bmap,
3160 : struct isl_tab *tab)
3161 : {
3162 : isl_bool single;
3163 :
3164 52565 : single = isl_basic_map_has_single_reference(bmap);
3165 52565 : if (single < 0)
3166 0 : return isl_basic_map_free(bmap);
3167 52565 : if (single)
3168 499 : return bmap;
3169 52066 : return isl_basic_map_gauss5(bmap, NULL, &swap_eq, &drop_eq, tab);
3170 : }
3171 :
3172 : /* Make the equalities that are implicit in "bmap" but that have been
3173 : * detected in the corresponding "tab" explicit in "bmap" and update
3174 : * "tab" to reflect the new order of the constraints.
3175 : *
3176 : * In particular, if inequality i is an implicit equality then
3177 : * isl_basic_map_inequality_to_equality will move the inequality
3178 : * in front of the other equality and it will move the last inequality
3179 : * in the position of inequality i.
3180 : * In the tableau, the inequalities of "bmap" are stored after the equalities
3181 : * and so the original order
3182 : *
3183 : * E E E E E A A A I B B B B L
3184 : *
3185 : * is changed into
3186 : *
3187 : * I E E E E E A A A L B B B B
3188 : *
3189 : * where I is the implicit equality, the E are equalities,
3190 : * the A inequalities before I, the B inequalities after I and
3191 : * L the last inequality.
3192 : * We therefore need to rotate to the right two sets of constraints,
3193 : * those up to and including I and those after I.
3194 : *
3195 : * If "tab" contains any constraints that are not in "bmap" then they
3196 : * appear after those in "bmap" and they should be left untouched.
3197 : *
3198 : * Note that this function only calls isl_basic_map_gauss
3199 : * (in case some equality constraints got detected)
3200 : * if "bmap" has more than one reference.
3201 : * If it only has a single reference, then it is left in a temporary state,
3202 : * because the caller may require this state.
3203 : * Calling isl_basic_map_gauss is then the responsibility of the caller.
3204 : */
3205 2904988922 : __isl_give isl_basic_map *isl_tab_make_equalities_explicit(struct isl_tab *tab,
3206 : __isl_take isl_basic_map *bmap)
3207 : {
3208 : int i;
3209 : unsigned n_eq;
3210 :
3211 2904988922 : if (!tab || !bmap)
3212 0 : return isl_basic_map_free(bmap);
3213 2904988922 : if (tab->empty)
3214 38835 : return bmap;
3215 :
3216 2904950087 : n_eq = tab->n_eq;
3217 2942094715 : for (i = bmap->n_ineq - 1; i >= 0; --i) {
3218 37144628 : if (!isl_tab_is_equality(tab, bmap->n_eq + i))
3219 36972017 : continue;
3220 172611 : isl_basic_map_inequality_to_equality(bmap, i);
3221 172611 : if (rotate_constraints(tab, 0, tab->n_eq + i + 1) < 0)
3222 0 : return isl_basic_map_free(bmap);
3223 172611 : if (rotate_constraints(tab, tab->n_eq + i + 1,
3224 172611 : bmap->n_ineq - i) < 0)
3225 0 : return isl_basic_map_free(bmap);
3226 172611 : tab->n_eq++;
3227 : }
3228 :
3229 2904950087 : if (n_eq != tab->n_eq)
3230 52565 : bmap = gauss_if_shared(bmap, tab);
3231 :
3232 2904950087 : return bmap;
3233 : }
3234 :
3235 12000225019 : static int con_is_redundant(struct isl_tab *tab, struct isl_tab_var *var)
3236 : {
3237 12000225019 : if (!tab)
3238 0 : return -1;
3239 12000225019 : if (tab->rational) {
3240 11417362933 : int sgn = sign_of_min(tab, var);
3241 11417362933 : if (sgn < -1)
3242 0 : return -1;
3243 11417362933 : return sgn >= 0;
3244 : } else {
3245 582862086 : int irred = isl_tab_min_at_most_neg_one(tab, var);
3246 582862086 : if (irred < 0)
3247 0 : return -1;
3248 582862086 : return !irred;
3249 : }
3250 : }
3251 :
3252 : /* Check for (near) redundant constraints.
3253 : * A constraint is redundant if it is non-negative and if
3254 : * its minimal value (temporarily ignoring the non-negativity) is either
3255 : * - zero (in case of rational tableaus), or
3256 : * - strictly larger than -1 (in case of integer tableaus)
3257 : *
3258 : * We first mark all non-redundant and non-dead variables that
3259 : * are not frozen and not obviously negatively unbounded.
3260 : * Then we iterate over all marked variables if they can attain
3261 : * any values smaller than zero or at most negative one.
3262 : * If not, we mark the row as being redundant (assuming it hasn't
3263 : * been detected as being obviously redundant in the mean time).
3264 : */
3265 3001868136 : int isl_tab_detect_redundant(struct isl_tab *tab)
3266 : {
3267 : int i;
3268 : unsigned n_marked;
3269 :
3270 3001868136 : if (!tab)
3271 0 : return -1;
3272 3001868136 : if (tab->empty)
3273 38835 : return 0;
3274 3001829301 : if (tab->n_redundant == tab->n_row)
3275 260284 : return 0;
3276 :
3277 3001569017 : n_marked = 0;
3278 8830925903 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
3279 5829356886 : struct isl_tab_var *var = isl_tab_var_from_row(tab, i);
3280 5829356886 : var->marked = !var->frozen && var->is_nonneg;
3281 5829356886 : if (var->marked)
3282 528600794 : n_marked++;
3283 : }
3284 3482882398 : for (i = tab->n_dead; i < tab->n_col; ++i) {
3285 481313381 : struct isl_tab_var *var = var_from_col(tab, i);
3286 663027342 : var->marked = !var->frozen && var->is_nonneg &&
3287 181713961 : !min_is_manifestly_unbounded(tab, var);
3288 481313381 : if (var->marked)
3289 114700640 : n_marked++;
3290 : }
3291 6499602169 : while (n_marked) {
3292 : struct isl_tab_var *var;
3293 : int red;
3294 521847180 : var = select_marked(tab);
3295 521847180 : if (!var)
3296 25383045 : break;
3297 496464135 : var->marked = 0;
3298 496464135 : n_marked--;
3299 496464135 : red = con_is_redundant(tab, var);
3300 496464135 : if (red < 0)
3301 0 : return -1;
3302 496464135 : if (red && !var->is_redundant)
3303 6256946 : if (isl_tab_mark_redundant(tab, var->index) < 0)
3304 0 : return -1;
3305 3020247138 : for (i = tab->n_dead; i < tab->n_col; ++i) {
3306 2523783003 : var = var_from_col(tab, i);
3307 2523783003 : if (!var->marked)
3308 1977360783 : continue;
3309 546422220 : if (!min_is_manifestly_unbounded(tab, var))
3310 518453656 : continue;
3311 27968564 : var->marked = 0;
3312 27968564 : n_marked--;
3313 : }
3314 : }
3315 :
3316 3001569017 : return 0;
3317 : }
3318 :
3319 1694280552 : int isl_tab_is_equality(struct isl_tab *tab, int con)
3320 : {
3321 : int row;
3322 : unsigned off;
3323 :
3324 1694280552 : if (!tab)
3325 0 : return -1;
3326 1694280552 : if (tab->con[con].is_zero)
3327 584027445 : return 1;
3328 1110253107 : if (tab->con[con].is_redundant)
3329 260380169 : return 0;
3330 849872938 : if (!tab->con[con].is_row)
3331 396497427 : return tab->con[con].index < tab->n_dead;
3332 :
3333 453375511 : row = tab->con[con].index;
3334 :
3335 453375511 : off = 2 + tab->M;
3336 1433133202 : return isl_int_is_zero(tab->mat->row[row][1]) &&
3337 600067175 : !row_is_big(tab, row) &&
3338 73345832 : isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
3339 73345832 : tab->n_col - tab->n_dead) == -1;
3340 : }
3341 :
3342 : /* Return the minimal value of the affine expression "f" with denominator
3343 : * "denom" in *opt, *opt_denom, assuming the tableau is not empty and
3344 : * the expression cannot attain arbitrarily small values.
3345 : * If opt_denom is NULL, then *opt is rounded up to the nearest integer.
3346 : * The return value reflects the nature of the result (empty, unbounded,
3347 : * minimal value returned in *opt).
3348 : *
3349 : * This function assumes that at least one more row and at least
3350 : * one more element in the constraint array are available in the tableau.
3351 : */
3352 2560315470 : enum isl_lp_result isl_tab_min(struct isl_tab *tab,
3353 : isl_int *f, isl_int denom, isl_int *opt, isl_int *opt_denom,
3354 : unsigned flags)
3355 : {
3356 : int r;
3357 2560315470 : enum isl_lp_result res = isl_lp_ok;
3358 : struct isl_tab_var *var;
3359 : struct isl_tab_undo *snap;
3360 :
3361 2560315470 : if (!tab)
3362 0 : return isl_lp_error;
3363 :
3364 2560315470 : if (tab->empty)
3365 0 : return isl_lp_empty;
3366 :
3367 2560315470 : snap = isl_tab_snap(tab);
3368 2560315470 : r = isl_tab_add_row(tab, f);
3369 2560315470 : if (r < 0)
3370 0 : return isl_lp_error;
3371 2560315470 : var = &tab->con[r];
3372 : for (;;) {
3373 : int row, col;
3374 4308142892 : find_pivot(tab, var, var, -1, &row, &col);
3375 4308142892 : if (row == var->index) {
3376 426448 : res = isl_lp_unbounded;
3377 2560741918 : break;
3378 : }
3379 4307716444 : if (row == -1)
3380 2559889022 : break;
3381 1747827422 : if (isl_tab_pivot(tab, row, col) < 0)
3382 0 : return isl_lp_error;
3383 1747827422 : }
3384 2560315470 : isl_int_mul(tab->mat->row[var->index][0],
3385 : tab->mat->row[var->index][0], denom);
3386 2560315470 : if (ISL_FL_ISSET(flags, ISL_TAB_SAVE_DUAL)) {
3387 : int i;
3388 :
3389 55978629 : isl_vec_free(tab->dual);
3390 55978629 : tab->dual = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_con);
3391 55978629 : if (!tab->dual)
3392 0 : return isl_lp_error;
3393 55978629 : isl_int_set(tab->dual->el[0], tab->mat->row[var->index][0]);
3394 2672641811 : for (i = 0; i < tab->n_con; ++i) {
3395 : int pos;
3396 2616663182 : if (tab->con[i].is_row) {
3397 2003034698 : isl_int_set_si(tab->dual->el[1 + i], 0);
3398 2003034698 : continue;
3399 : }
3400 613628484 : pos = 2 + tab->M + tab->con[i].index;
3401 613628484 : if (tab->con[i].negated)
3402 98396265 : isl_int_neg(tab->dual->el[1 + i],
3403 : tab->mat->row[var->index][pos]);
3404 : else
3405 515232219 : isl_int_set(tab->dual->el[1 + i],
3406 : tab->mat->row[var->index][pos]);
3407 : }
3408 : }
3409 2560315470 : if (opt && res == isl_lp_ok) {
3410 2559889022 : if (opt_denom) {
3411 2416647373 : isl_int_set(*opt, tab->mat->row[var->index][1]);
3412 2416647373 : isl_int_set(*opt_denom, tab->mat->row[var->index][0]);
3413 : } else
3414 143241649 : get_rounded_sample_value(tab, var, 1, opt);
3415 : }
3416 2560315470 : if (isl_tab_rollback(tab, snap) < 0)
3417 0 : return isl_lp_error;
3418 2560315470 : return res;
3419 : }
3420 :
3421 : /* Is the constraint at position "con" marked as being redundant?
3422 : * If it is marked as representing an equality, then it is not
3423 : * considered to be redundant.
3424 : * Note that isl_tab_mark_redundant marks both the isl_tab_var as
3425 : * redundant and moves the corresponding row into the first
3426 : * tab->n_redundant positions (or removes the row, assigning it index -1),
3427 : * so the final test is actually redundant itself.
3428 : */
3429 1624665066 : int isl_tab_is_redundant(struct isl_tab *tab, int con)
3430 : {
3431 1624665066 : if (isl_tab_check_con(tab, con) < 0)
3432 0 : return -1;
3433 1624665066 : if (tab->con[con].is_zero)
3434 0 : return 0;
3435 1624665066 : if (tab->con[con].is_redundant)
3436 645241482 : return 1;
3437 979423584 : return tab->con[con].is_row && tab->con[con].index < tab->n_redundant;
3438 : }
3439 :
3440 : /* Is variable "var" of "tab" fixed to a constant value by its row
3441 : * in the tableau?
3442 : * If so and if "value" is not NULL, then store this constant value
3443 : * in "value".
3444 : *
3445 : * That is, is it a row variable that only has non-zero coefficients
3446 : * for dead columns?
3447 : */
3448 3946123 : static isl_bool is_constant(struct isl_tab *tab, struct isl_tab_var *var,
3449 : isl_int *value)
3450 : {
3451 3946123 : unsigned off = 2 + tab->M;
3452 3946123 : isl_mat *mat = tab->mat;
3453 : int n;
3454 : int row;
3455 : int pos;
3456 :
3457 3946123 : if (!var->is_row)
3458 859648 : return isl_bool_false;
3459 3086475 : row = var->index;
3460 3086475 : if (row_is_big(tab, row))
3461 0 : return isl_bool_false;
3462 3086475 : n = tab->n_col - tab->n_dead;
3463 3086475 : pos = isl_seq_first_non_zero(mat->row[row] + off + tab->n_dead, n);
3464 3086475 : if (pos != -1)
3465 2666701 : return isl_bool_false;
3466 419774 : if (value)
3467 0 : isl_int_divexact(*value, mat->row[row][1], mat->row[row][0]);
3468 419774 : return isl_bool_true;
3469 : }
3470 :
3471 : /* Has the variable "var' of "tab" reached a value that is greater than
3472 : * or equal (if sgn > 0) or smaller than or equal (if sgn < 0) to "target"?
3473 : * "tmp" has been initialized by the caller and can be used
3474 : * to perform local computations.
3475 : *
3476 : * If the sample value involves the big parameter, then any value
3477 : * is reached.
3478 : * Otherwise check if n/d >= t, i.e., n >= d * t (if sgn > 0)
3479 : * or n/d <= t, i.e., n <= d * t (if sgn < 0).
3480 : */
3481 5792930 : static int reached(struct isl_tab *tab, struct isl_tab_var *var, int sgn,
3482 : isl_int target, isl_int *tmp)
3483 : {
3484 5792930 : if (row_is_big(tab, var->index))
3485 0 : return 1;
3486 5792930 : isl_int_mul(*tmp, tab->mat->row[var->index][0], target);
3487 5792930 : if (sgn > 0)
3488 1333495 : return isl_int_ge(tab->mat->row[var->index][1], *tmp);
3489 : else
3490 4459435 : return isl_int_le(tab->mat->row[var->index][1], *tmp);
3491 : }
3492 :
3493 : /* Can variable "var" of "tab" attain the value "target" by
3494 : * pivoting up (if sgn > 0) or down (if sgn < 0)?
3495 : * If not, then pivot up [down] to the greatest [smallest]
3496 : * rational value.
3497 : * "tmp" has been initialized by the caller and can be used
3498 : * to perform local computations.
3499 : *
3500 : * If the variable is manifestly unbounded in the desired direction,
3501 : * then it can attain any value.
3502 : * Otherwise, it can be moved to a row.
3503 : * Continue pivoting until the target is reached.
3504 : * If no more pivoting can be performed, the maximal [minimal]
3505 : * rational value has been reached and the target cannot be reached.
3506 : * If the variable would be pivoted into a manifestly unbounded column,
3507 : * then the target can be reached.
3508 : */
3509 4267838 : static isl_bool var_reaches(struct isl_tab *tab, struct isl_tab_var *var,
3510 : int sgn, isl_int target, isl_int *tmp)
3511 : {
3512 : int row, col;
3513 :
3514 4267838 : if (sgn < 0 && min_is_manifestly_unbounded(tab, var))
3515 839657 : return isl_bool_true;
3516 3428181 : if (sgn > 0 && max_is_manifestly_unbounded(tab, var))
3517 0 : return isl_bool_true;
3518 3428181 : if (to_row(tab, var, sgn) < 0)
3519 0 : return isl_bool_error;
3520 9221111 : while (!reached(tab, var, sgn, target, tmp)) {
3521 4198359 : find_pivot(tab, var, var, sgn, &row, &col);
3522 4198359 : if (row == -1)
3523 744584 : return isl_bool_false;
3524 3453775 : if (row == var->index)
3525 1089026 : return isl_bool_true;
3526 2364749 : if (isl_tab_pivot(tab, row, col) < 0)
3527 0 : return isl_bool_error;
3528 : }
3529 :
3530 1594571 : return isl_bool_true;
3531 : }
3532 :
3533 : /* Check if variable "var" of "tab" can only attain a single (integer)
3534 : * value, and, if so, add an equality constraint to fix the variable
3535 : * to this single value and store the result in "target".
3536 : * "target" and "tmp" have been initialized by the caller.
3537 : *
3538 : * Given the current sample value, round it down and check
3539 : * whether it is possible to attain a strictly smaller integer value.
3540 : * If so, the variable is not restricted to a single integer value.
3541 : * Otherwise, the search stops at the smallest rational value.
3542 : * Round up this value and check whether it is possible to attain
3543 : * a strictly greater integer value.
3544 : * If so, the variable is not restricted to a single integer value.
3545 : * Otherwise, the search stops at the greatest rational value.
3546 : * If rounding down this value yields a value that is different
3547 : * from rounding up the smallest rational value, then the variable
3548 : * cannot attain any integer value. Mark the tableau empty.
3549 : * Otherwise, add an equality constraint that fixes the variable
3550 : * to the single integer value found.
3551 : */
3552 3526349 : static isl_bool detect_constant_with_tmp(struct isl_tab *tab,
3553 : struct isl_tab_var *var, isl_int *target, isl_int *tmp)
3554 : {
3555 : isl_bool reached;
3556 : isl_vec *eq;
3557 : int pos;
3558 : isl_stat r;
3559 :
3560 3526349 : get_rounded_sample_value(tab, var, -1, target);
3561 3526349 : isl_int_sub_ui(*target, *target, 1);
3562 3526349 : reached = var_reaches(tab, var, -1, *target, tmp);
3563 3526349 : if (reached < 0 || reached)
3564 2784860 : return isl_bool_not(reached);
3565 741489 : get_rounded_sample_value(tab, var, 1, target);
3566 741489 : isl_int_add_ui(*target, *target, 1);
3567 741489 : reached = var_reaches(tab, var, 1, *target, tmp);
3568 741489 : if (reached < 0 || reached)
3569 738394 : return isl_bool_not(reached);
3570 3095 : get_rounded_sample_value(tab, var, -1, tmp);
3571 3095 : isl_int_sub_ui(*target, *target, 1);
3572 3095 : if (isl_int_ne(*target, *tmp)) {
3573 0 : if (isl_tab_mark_empty(tab) < 0)
3574 0 : return isl_bool_error;
3575 0 : return isl_bool_false;
3576 : }
3577 :
3578 3095 : if (isl_tab_extend_cons(tab, 1) < 0)
3579 0 : return isl_bool_error;
3580 3095 : eq = isl_vec_alloc(isl_tab_get_ctx(tab), 1 + tab->n_var);
3581 3095 : if (!eq)
3582 0 : return isl_bool_error;
3583 3095 : pos = var - tab->var;
3584 3095 : isl_seq_clr(eq->el + 1, tab->n_var);
3585 3095 : isl_int_set_si(eq->el[1 + pos], -1);
3586 3095 : isl_int_set(eq->el[0], *target);
3587 3095 : r = isl_tab_add_eq(tab, eq->el);
3588 3095 : isl_vec_free(eq);
3589 :
3590 3095 : return r < 0 ? isl_bool_error : isl_bool_true;
3591 : }
3592 :
3593 : /* Check if variable "var" of "tab" can only attain a single (integer)
3594 : * value, and, if so, add an equality constraint to fix the variable
3595 : * to this single value and store the result in "value" (if "value"
3596 : * is not NULL).
3597 : *
3598 : * If the current sample value involves the big parameter,
3599 : * then the variable cannot have a fixed integer value.
3600 : * If the variable is already fixed to a single value by its row, then
3601 : * there is no need to add another equality constraint.
3602 : *
3603 : * Otherwise, allocate some temporary variables and continue
3604 : * with detect_constant_with_tmp.
3605 : */
3606 3946123 : static isl_bool get_constant(struct isl_tab *tab, struct isl_tab_var *var,
3607 : isl_int *value)
3608 : {
3609 : isl_int target, tmp;
3610 : isl_bool is_cst;
3611 :
3612 3946123 : if (var->is_row && row_is_big(tab, var->index))
3613 0 : return isl_bool_false;
3614 3946123 : is_cst = is_constant(tab, var, value);
3615 3946123 : if (is_cst < 0 || is_cst)
3616 419774 : return is_cst;
3617 :
3618 3526349 : if (!value)
3619 3526349 : isl_int_init(target);
3620 3526349 : isl_int_init(tmp);
3621 :
3622 3526349 : is_cst = detect_constant_with_tmp(tab, var,
3623 : value ? value : &target, &tmp);
3624 :
3625 3526349 : isl_int_clear(tmp);
3626 3526349 : if (!value)
3627 3526349 : isl_int_clear(target);
3628 :
3629 3526349 : return is_cst;
3630 : }
3631 :
3632 : /* Check if variable "var" of "tab" can only attain a single (integer)
3633 : * value, and, if so, add an equality constraint to fix the variable
3634 : * to this single value and store the result in "value" (if "value"
3635 : * is not NULL).
3636 : *
3637 : * For rational tableaus, nothing needs to be done.
3638 : */
3639 0 : isl_bool isl_tab_is_constant(struct isl_tab *tab, int var, isl_int *value)
3640 : {
3641 0 : if (!tab)
3642 0 : return isl_bool_error;
3643 0 : if (var < 0 || var >= tab->n_var)
3644 0 : isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
3645 : "position out of bounds", return isl_bool_error);
3646 0 : if (tab->rational)
3647 0 : return isl_bool_false;
3648 :
3649 0 : return get_constant(tab, &tab->var[var], value);
3650 : }
3651 :
3652 : /* Check if any of the variables of "tab" can only attain a single (integer)
3653 : * value, and, if so, add equality constraints to fix those variables
3654 : * to these single values.
3655 : *
3656 : * For rational tableaus, nothing needs to be done.
3657 : */
3658 688378 : isl_stat isl_tab_detect_constants(struct isl_tab *tab)
3659 : {
3660 : int i;
3661 :
3662 688378 : if (!tab)
3663 0 : return isl_stat_error;
3664 688378 : if (tab->rational)
3665 0 : return isl_stat_ok;
3666 :
3667 4634501 : for (i = 0; i < tab->n_var; ++i) {
3668 3946123 : if (get_constant(tab, &tab->var[i], NULL) < 0)
3669 0 : return isl_stat_error;
3670 : }
3671 :
3672 688378 : return isl_stat_ok;
3673 : }
3674 :
3675 : /* Take a snapshot of the tableau that can be restored by a call to
3676 : * isl_tab_rollback.
3677 : */
3678 22975919148 : struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab)
3679 : {
3680 22975919148 : if (!tab)
3681 0 : return NULL;
3682 22975919148 : tab->need_undo = 1;
3683 22975919148 : return tab->top;
3684 : }
3685 :
3686 : /* Does "tab" need to keep track of undo information?
3687 : * That is, was a snapshot taken that may need to be restored?
3688 : */
3689 0 : isl_bool isl_tab_need_undo(struct isl_tab *tab)
3690 : {
3691 0 : if (!tab)
3692 0 : return isl_bool_error;
3693 :
3694 0 : return tab->need_undo;
3695 : }
3696 :
3697 : /* Remove all tracking of undo information from "tab", invalidating
3698 : * any snapshots that may have been taken of the tableau.
3699 : * Since all snapshots have been invalidated, there is also
3700 : * no need to start keeping track of undo information again.
3701 : */
3702 0 : void isl_tab_clear_undo(struct isl_tab *tab)
3703 : {
3704 0 : if (!tab)
3705 0 : return;
3706 :
3707 0 : free_undo(tab);
3708 0 : tab->need_undo = 0;
3709 : }
3710 :
3711 : /* Undo the operation performed by isl_tab_relax.
3712 : */
3713 : static isl_stat unrelax(struct isl_tab *tab, struct isl_tab_var *var)
3714 : WARN_UNUSED;
3715 370821 : static isl_stat unrelax(struct isl_tab *tab, struct isl_tab_var *var)
3716 : {
3717 370821 : unsigned off = 2 + tab->M;
3718 :
3719 370821 : if (!var->is_row && !max_is_manifestly_unbounded(tab, var))
3720 29748 : if (to_row(tab, var, 1) < 0)
3721 0 : return isl_stat_error;
3722 :
3723 370821 : if (var->is_row) {
3724 31032 : isl_int_sub(tab->mat->row[var->index][1],
3725 : tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
3726 31032 : if (var->is_nonneg) {
3727 31032 : int sgn = restore_row(tab, var);
3728 31032 : isl_assert(tab->mat->ctx, sgn >= 0,
3729 : return isl_stat_error);
3730 : }
3731 : } else {
3732 : int i;
3733 :
3734 1308715 : for (i = 0; i < tab->n_row; ++i) {
3735 968926 : if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
3736 579118 : continue;
3737 389808 : isl_int_add(tab->mat->row[i][1], tab->mat->row[i][1],
3738 : tab->mat->row[i][off + var->index]);
3739 : }
3740 :
3741 : }
3742 :
3743 370821 : return isl_stat_ok;
3744 : }
3745 :
3746 : /* Undo the operation performed by isl_tab_unrestrict.
3747 : *
3748 : * In particular, mark the variable as being non-negative and make
3749 : * sure the sample value respects this constraint.
3750 : */
3751 687508 : static isl_stat ununrestrict(struct isl_tab *tab, struct isl_tab_var *var)
3752 : {
3753 687508 : var->is_nonneg = 1;
3754 :
3755 687508 : if (var->is_row && restore_row(tab, var) < -1)
3756 0 : return isl_stat_error;
3757 :
3758 687508 : return isl_stat_ok;
3759 : }
3760 :
3761 : /* Unmark the last redundant row in "tab" as being redundant.
3762 : * This undoes part of the modifications performed by isl_tab_mark_redundant.
3763 : * In particular, remove the redundant mark and make
3764 : * sure the sample value respects the constraint again.
3765 : * A variable that is marked non-negative by isl_tab_mark_redundant
3766 : * is covered by a separate undo record.
3767 : */
3768 5314195918 : static isl_stat restore_last_redundant(struct isl_tab *tab)
3769 : {
3770 : struct isl_tab_var *var;
3771 :
3772 5314195918 : if (tab->n_redundant < 1)
3773 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
3774 : "no redundant rows", return isl_stat_error);
3775 :
3776 5314195918 : var = isl_tab_var_from_row(tab, tab->n_redundant - 1);
3777 5314195918 : var->is_redundant = 0;
3778 5314195918 : tab->n_redundant--;
3779 5314195918 : restore_row(tab, var);
3780 :
3781 5314195918 : return isl_stat_ok;
3782 : }
3783 :
3784 : static isl_stat perform_undo_var(struct isl_tab *tab, struct isl_tab_undo *undo)
3785 : WARN_UNUSED;
3786 47883103905 : static isl_stat perform_undo_var(struct isl_tab *tab, struct isl_tab_undo *undo)
3787 : {
3788 47883103905 : struct isl_tab_var *var = var_from_index(tab, undo->u.var_index);
3789 47883103905 : switch (undo->type) {
3790 : case isl_tab_undo_nonneg:
3791 6996032757 : var->is_nonneg = 0;
3792 6996032757 : break;
3793 : case isl_tab_undo_redundant:
3794 5228617723 : if (!var->is_row || var->index != tab->n_redundant - 1)
3795 0 : isl_die(isl_tab_get_ctx(tab), isl_error_internal,
3796 : "not undoing last redundant row",
3797 : return isl_stat_error);
3798 5228617723 : return restore_last_redundant(tab);
3799 : case isl_tab_undo_freeze:
3800 10548579195 : var->frozen = 0;
3801 10548579195 : break;
3802 : case isl_tab_undo_zero:
3803 46595572 : var->is_zero = 0;
3804 46595572 : if (!var->is_row)
3805 46595572 : tab->n_dead--;
3806 46595572 : break;
3807 : case isl_tab_undo_allocate:
3808 25062220329 : if (undo->u.var_index >= 0) {
3809 0 : isl_assert(tab->mat->ctx, !var->is_row,
3810 : return isl_stat_error);
3811 0 : return drop_col(tab, var->index);
3812 : }
3813 25062220329 : if (!var->is_row) {
3814 377932878 : if (!max_is_manifestly_unbounded(tab, var)) {
3815 292422437 : if (to_row(tab, var, 1) < 0)
3816 0 : return isl_stat_error;
3817 85510441 : } else if (!min_is_manifestly_unbounded(tab, var)) {
3818 38249104 : if (to_row(tab, var, -1) < 0)
3819 0 : return isl_stat_error;
3820 : } else
3821 47261337 : if (to_row(tab, var, 0) < 0)
3822 0 : return isl_stat_error;
3823 : }
3824 25062220329 : return drop_row(tab, var->index);
3825 : case isl_tab_undo_relax:
3826 370821 : return unrelax(tab, var);
3827 : case isl_tab_undo_unrestrict:
3828 687508 : return ununrestrict(tab, var);
3829 : default:
3830 0 : isl_die(tab->mat->ctx, isl_error_internal,
3831 : "perform_undo_var called on invalid undo record",
3832 : return isl_stat_error);
3833 : }
3834 :
3835 17591207524 : return isl_stat_ok;
3836 : }
3837 :
3838 : /* Restore all rows that have been marked redundant by isl_tab_mark_redundant
3839 : * and that have been preserved in the tableau.
3840 : * Note that isl_tab_mark_redundant may also have marked some variables
3841 : * as being non-negative before marking them redundant. These need
3842 : * to be removed as well as otherwise some constraints could end up
3843 : * getting marked redundant with respect to the variable.
3844 : */
3845 48749036 : isl_stat isl_tab_restore_redundant(struct isl_tab *tab)
3846 : {
3847 48749036 : if (!tab)
3848 0 : return isl_stat_error;
3849 :
3850 48749036 : if (tab->need_undo)
3851 0 : isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
3852 : "manually restoring redundant constraints "
3853 : "interferes with undo history",
3854 : return isl_stat_error);
3855 :
3856 183076267 : while (tab->n_redundant > 0) {
3857 85578195 : if (tab->row_var[tab->n_redundant - 1] >= 0) {
3858 : struct isl_tab_var *var;
3859 :
3860 47664391 : var = isl_tab_var_from_row(tab, tab->n_redundant - 1);
3861 47664391 : var->is_nonneg = 0;
3862 : }
3863 85578195 : restore_last_redundant(tab);
3864 : }
3865 48749036 : return isl_stat_ok;
3866 : }
3867 :
3868 : /* Undo the addition of an integer division to the basic map representation
3869 : * of "tab" in position "pos".
3870 : */
3871 0 : static isl_stat drop_bmap_div(struct isl_tab *tab, int pos)
3872 : {
3873 : int off;
3874 :
3875 0 : off = tab->n_var - isl_basic_map_dim(tab->bmap, isl_dim_div);
3876 0 : if (isl_basic_map_drop_div(tab->bmap, pos - off) < 0)
3877 : return isl_stat_error;
3878 0 : if (tab->samples) {
3879 0 : tab->samples = isl_mat_drop_cols(tab->samples, 1 + pos, 1);
3880 0 : if (!tab->samples)
3881 0 : return isl_stat_error;
3882 : }
3883 :
3884 0 : return isl_stat_ok;
3885 : }
3886 :
3887 : /* Restore the tableau to the state where the basic variables
3888 : * are those in "col_var".
3889 : * We first construct a list of variables that are currently in
3890 : * the basis, but shouldn't. Then we iterate over all variables
3891 : * that should be in the basis and for each one that is currently
3892 : * not in the basis, we exchange it with one of the elements of the
3893 : * list constructed before.
3894 : * We can always find an appropriate variable to pivot with because
3895 : * the current basis is mapped to the old basis by a non-singular
3896 : * matrix and so we can never end up with a zero row.
3897 : */
3898 0 : static int restore_basis(struct isl_tab *tab, int *col_var)
3899 : {
3900 : int i, j;
3901 0 : int n_extra = 0;
3902 0 : int *extra = NULL; /* current columns that contain bad stuff */
3903 0 : unsigned off = 2 + tab->M;
3904 :
3905 0 : extra = isl_alloc_array(tab->mat->ctx, int, tab->n_col);
3906 0 : if (tab->n_col && !extra)
3907 0 : goto error;
3908 0 : for (i = 0; i < tab->n_col; ++i) {
3909 0 : for (j = 0; j < tab->n_col; ++j)
3910 0 : if (tab->col_var[i] == col_var[j])
3911 0 : break;
3912 0 : if (j < tab->n_col)
3913 0 : continue;
3914 0 : extra[n_extra++] = i;
3915 : }
3916 0 : for (i = 0; i < tab->n_col && n_extra > 0; ++i) {
3917 : struct isl_tab_var *var;
3918 : int row;
3919 :
3920 0 : for (j = 0; j < tab->n_col; ++j)
3921 0 : if (col_var[i] == tab->col_var[j])
3922 0 : break;
3923 0 : if (j < tab->n_col)
3924 0 : continue;
3925 0 : var = var_from_index(tab, col_var[i]);
3926 0 : row = var->index;
3927 0 : for (j = 0; j < n_extra; ++j)
3928 0 : if (!isl_int_is_zero(tab->mat->row[row][off+extra[j]]))
3929 : break;
3930 0 : isl_assert(tab->mat->ctx, j < n_extra, goto error);
3931 0 : if (isl_tab_pivot(tab, row, extra[j]) < 0)
3932 0 : goto error;
3933 0 : extra[j] = extra[--n_extra];
3934 : }
3935 :
3936 0 : free(extra);
3937 0 : return 0;
3938 : error:
3939 0 : free(extra);
3940 0 : return -1;
3941 : }
3942 :
3943 : /* Remove all samples with index n or greater, i.e., those samples
3944 : * that were added since we saved this number of samples in
3945 : * isl_tab_save_samples.
3946 : */
3947 0 : static void drop_samples_since(struct isl_tab *tab, int n)
3948 : {
3949 : int i;
3950 :
3951 0 : for (i = tab->n_sample - 1; i >= 0 && tab->n_sample > n; --i) {
3952 0 : if (tab->sample_index[i] < n)
3953 0 : continue;
3954 :
3955 0 : if (i != tab->n_sample - 1) {
3956 0 : int t = tab->sample_index[tab->n_sample-1];
3957 0 : tab->sample_index[tab->n_sample-1] = tab->sample_index[i];
3958 0 : tab->sample_index[i] = t;
3959 0 : isl_mat_swap_rows(tab->samples, tab->n_sample-1, i);
3960 : }
3961 0 : tab->n_sample--;
3962 : }
3963 0 : }
3964 :
3965 : static isl_stat perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
3966 : WARN_UNUSED;
3967 52372576986 : static isl_stat perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
3968 : {
3969 52372576986 : switch (undo->type) {
3970 : case isl_tab_undo_rational:
3971 10639 : tab->rational = 0;
3972 10639 : break;
3973 : case isl_tab_undo_empty:
3974 749697066 : tab->empty = 0;
3975 749697066 : break;
3976 : case isl_tab_undo_nonneg:
3977 : case isl_tab_undo_redundant:
3978 : case isl_tab_undo_freeze:
3979 : case isl_tab_undo_zero:
3980 : case isl_tab_undo_allocate:
3981 : case isl_tab_undo_relax:
3982 : case isl_tab_undo_unrestrict:
3983 47883103905 : return perform_undo_var(tab, undo);
3984 : case isl_tab_undo_bmap_eq:
3985 0 : return isl_basic_map_free_equality(tab->bmap, 1);
3986 : case isl_tab_undo_bmap_ineq:
3987 3739765376 : return isl_basic_map_free_inequality(tab->bmap, 1);
3988 : case isl_tab_undo_bmap_div:
3989 0 : return drop_bmap_div(tab, undo->u.var_index);
3990 : case isl_tab_undo_saved_basis:
3991 0 : if (restore_basis(tab, undo->u.col_var) < 0)
3992 0 : return isl_stat_error;
3993 0 : break;
3994 : case isl_tab_undo_drop_sample:
3995 0 : tab->n_outside--;
3996 0 : break;
3997 : case isl_tab_undo_saved_samples:
3998 0 : drop_samples_since(tab, undo->u.n);
3999 0 : break;
4000 : case isl_tab_undo_callback:
4001 0 : return undo->u.callback->run(undo->u.callback);
4002 : default:
4003 0 : isl_assert(tab->mat->ctx, 0, return isl_stat_error);
4004 : }
4005 749707705 : return isl_stat_ok;
4006 : }
4007 :
4008 : /* Return the tableau to the state it was in when the snapshot "snap"
4009 : * was taken.
4010 : */
4011 22138649812 : int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap)
4012 : {
4013 : struct isl_tab_undo *undo, *next;
4014 :
4015 22138649812 : if (!tab)
4016 0 : return -1;
4017 :
4018 22138649812 : tab->in_undo = 1;
4019 74511226798 : for (undo = tab->top; undo && undo != &tab->bottom; undo = next) {
4020 53168171988 : next = undo->next;
4021 53168171988 : if (undo == snap)
4022 795595002 : break;
4023 52372576986 : if (perform_undo(tab, undo) < 0) {
4024 0 : tab->top = undo;
4025 0 : free_undo(tab);
4026 0 : tab->in_undo = 0;
4027 0 : return -1;
4028 : }
4029 52372576986 : free_undo_record(undo);
4030 : }
4031 22138649812 : tab->in_undo = 0;
4032 22138649812 : tab->top = undo;
4033 22138649812 : if (!undo)
4034 0 : return -1;
4035 22138649812 : return 0;
4036 : }
4037 :
4038 : /* The given row "row" represents an inequality violated by all
4039 : * points in the tableau. Check for some special cases of such
4040 : * separating constraints.
4041 : * In particular, if the row has been reduced to the constant -1,
4042 : * then we know the inequality is adjacent (but opposite) to
4043 : * an equality in the tableau.
4044 : * If the row has been reduced to r = c*(-1 -r'), with r' an inequality
4045 : * of the tableau and c a positive constant, then the inequality
4046 : * is adjacent (but opposite) to the inequality r'.
4047 : */
4048 7196337328 : static enum isl_ineq_type separation_type(struct isl_tab *tab, unsigned row)
4049 : {
4050 : int pos;
4051 7196337328 : unsigned off = 2 + tab->M;
4052 :
4053 7196337328 : if (tab->rational)
4054 7160499218 : return isl_ineq_separate;
4055 :
4056 35838110 : if (!isl_int_is_one(tab->mat->row[row][0]))
4057 2292298 : return isl_ineq_separate;
4058 :
4059 33545812 : pos = isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
4060 33545812 : tab->n_col - tab->n_dead);
4061 33545812 : if (pos == -1) {
4062 27028711 : if (isl_int_is_negone(tab->mat->row[row][1]))
4063 1968157 : return isl_ineq_adj_eq;
4064 : else
4065 25060554 : return isl_ineq_separate;
4066 : }
4067 :
4068 6517101 : if (!isl_int_eq(tab->mat->row[row][1],
4069 : tab->mat->row[row][off + tab->n_dead + pos]))
4070 763248 : return isl_ineq_separate;
4071 :
4072 11507706 : pos = isl_seq_first_non_zero(
4073 5753853 : tab->mat->row[row] + off + tab->n_dead + pos + 1,
4074 5753853 : tab->n_col - tab->n_dead - pos - 1);
4075 :
4076 5753853 : return pos == -1 ? isl_ineq_adj_ineq : isl_ineq_separate;
4077 : }
4078 :
4079 : /* Check the effect of inequality "ineq" on the tableau "tab".
4080 : * The result may be
4081 : * isl_ineq_redundant: satisfied by all points in the tableau
4082 : * isl_ineq_separate: satisfied by no point in the tableau
4083 : * isl_ineq_cut: satisfied by some by not all points
4084 : * isl_ineq_adj_eq: adjacent to an equality
4085 : * isl_ineq_adj_ineq: adjacent to an inequality.
4086 : */
4087 18712039164 : enum isl_ineq_type isl_tab_ineq_type(struct isl_tab *tab, isl_int *ineq)
4088 : {
4089 18712039164 : enum isl_ineq_type type = isl_ineq_error;
4090 18712039164 : struct isl_tab_undo *snap = NULL;
4091 : int con;
4092 : int row;
4093 :
4094 18712039164 : if (!tab)
4095 0 : return isl_ineq_error;
4096 :
4097 18712039164 : if (isl_tab_extend_cons(tab, 1) < 0)
4098 0 : return isl_ineq_error;
4099 :
4100 18712039164 : snap = isl_tab_snap(tab);
4101 :
4102 18712039164 : con = isl_tab_add_row(tab, ineq);
4103 18712039164 : if (con < 0)
4104 0 : goto error;
4105 :
4106 18712039164 : row = tab->con[con].index;
4107 18712039164 : if (isl_tab_row_is_redundant(tab, row))
4108 0 : type = isl_ineq_redundant;
4109 25920564982 : else if (isl_int_is_neg(tab->mat->row[row][1]) &&
4110 7252340012 : (tab->rational ||
4111 43814194 : isl_int_abs_ge(tab->mat->row[row][1],
4112 7208278280 : tab->mat->row[row][0]))) {
4113 7208278280 : int nonneg = at_least_zero(tab, &tab->con[con]);
4114 7208278280 : if (nonneg < 0)
4115 0 : goto error;
4116 7208278280 : if (nonneg)
4117 11940952 : type = isl_ineq_cut;
4118 : else
4119 7196337328 : type = separation_type(tab, row);
4120 : } else {
4121 11503760884 : int red = con_is_redundant(tab, &tab->con[con]);
4122 11503760884 : if (red < 0)
4123 0 : goto error;
4124 11503760884 : if (!red)
4125 24819776 : type = isl_ineq_cut;
4126 : else
4127 11478941108 : type = isl_ineq_redundant;
4128 : }
4129 :
4130 18712039164 : if (isl_tab_rollback(tab, snap))
4131 0 : return isl_ineq_error;
4132 18712039164 : return type;
4133 : error:
4134 0 : return isl_ineq_error;
4135 : }
4136 :
4137 55812133 : isl_stat isl_tab_track_bmap(struct isl_tab *tab, __isl_take isl_basic_map *bmap)
4138 : {
4139 55812133 : bmap = isl_basic_map_cow(bmap);
4140 55812133 : if (!tab || !bmap)
4141 : goto error;
4142 :
4143 55812133 : if (tab->empty) {
4144 27263921 : bmap = isl_basic_map_set_to_empty(bmap);
4145 27263921 : if (!bmap)
4146 0 : goto error;
4147 27263921 : tab->bmap = bmap;
4148 27263921 : return isl_stat_ok;
4149 : }
4150 :
4151 28548212 : isl_assert(tab->mat->ctx, tab->n_eq == bmap->n_eq, goto error);
4152 28548212 : isl_assert(tab->mat->ctx,
4153 : tab->n_con == bmap->n_eq + bmap->n_ineq, goto error);
4154 :
4155 28548212 : tab->bmap = bmap;
4156 :
4157 28548212 : return isl_stat_ok;
4158 : error:
4159 0 : isl_basic_map_free(bmap);
4160 0 : return isl_stat_error;
4161 : }
4162 :
4163 0 : isl_stat isl_tab_track_bset(struct isl_tab *tab, __isl_take isl_basic_set *bset)
4164 : {
4165 0 : return isl_tab_track_bmap(tab, bset_to_bmap(bset));
4166 : }
4167 :
4168 1123714 : __isl_keep isl_basic_set *isl_tab_peek_bset(struct isl_tab *tab)
4169 : {
4170 1123714 : if (!tab)
4171 0 : return NULL;
4172 :
4173 1123714 : return bset_from_bmap(tab->bmap);
4174 : }
4175 :
4176 0 : static void isl_tab_print_internal(__isl_keep struct isl_tab *tab,
4177 : FILE *out, int indent)
4178 : {
4179 : unsigned r, c;
4180 : int i;
4181 :
4182 0 : if (!tab) {
4183 0 : fprintf(out, "%*snull tab\n", indent, "");
4184 0 : return;
4185 : }
4186 0 : fprintf(out, "%*sn_redundant: %d, n_dead: %d", indent, "",
4187 : tab->n_redundant, tab->n_dead);
4188 0 : if (tab->rational)
4189 0 : fprintf(out, ", rational");
4190 0 : if (tab->empty)
4191 0 : fprintf(out, ", empty");
4192 0 : fprintf(out, "\n");
4193 0 : fprintf(out, "%*s[", indent, "");
4194 0 : for (i = 0; i < tab->n_var; ++i) {
4195 0 : if (i)
4196 0 : fprintf(out, (i == tab->n_param ||
4197 0 : i == tab->n_var - tab->n_div) ? "; "
4198 : : ", ");
4199 0 : fprintf(out, "%c%d%s", tab->var[i].is_row ? 'r' : 'c',
4200 0 : tab->var[i].index,
4201 0 : tab->var[i].is_zero ? " [=0]" :
4202 0 : tab->var[i].is_redundant ? " [R]" : "");
4203 : }
4204 0 : fprintf(out, "]\n");
4205 0 : fprintf(out, "%*s[", indent, "");
4206 0 : for (i = 0; i < tab->n_con; ++i) {
4207 0 : if (i)
4208 0 : fprintf(out, ", ");
4209 0 : fprintf(out, "%c%d%s", tab->con[i].is_row ? 'r' : 'c',
4210 0 : tab->con[i].index,
4211 0 : tab->con[i].is_zero ? " [=0]" :
4212 0 : tab->con[i].is_redundant ? " [R]" : "");
4213 : }
4214 0 : fprintf(out, "]\n");
4215 0 : fprintf(out, "%*s[", indent, "");
4216 0 : for (i = 0; i < tab->n_row; ++i) {
4217 0 : const char *sign = "";
4218 0 : if (i)
4219 0 : fprintf(out, ", ");
4220 0 : if (tab->row_sign) {
4221 0 : if (tab->row_sign[i] == isl_tab_row_unknown)
4222 0 : sign = "?";
4223 0 : else if (tab->row_sign[i] == isl_tab_row_neg)
4224 0 : sign = "-";
4225 0 : else if (tab->row_sign[i] == isl_tab_row_pos)
4226 0 : sign = "+";
4227 : else
4228 0 : sign = "+-";
4229 : }
4230 0 : fprintf(out, "r%d: %d%s%s", i, tab->row_var[i],
4231 0 : isl_tab_var_from_row(tab, i)->is_nonneg ? " [>=0]" : "", sign);
4232 : }
4233 0 : fprintf(out, "]\n");
4234 0 : fprintf(out, "%*s[", indent, "");
4235 0 : for (i = 0; i < tab->n_col; ++i) {
4236 0 : if (i)
4237 0 : fprintf(out, ", ");
4238 0 : fprintf(out, "c%d: %d%s", i, tab->col_var[i],
4239 0 : var_from_col(tab, i)->is_nonneg ? " [>=0]" : "");
4240 : }
4241 0 : fprintf(out, "]\n");
4242 0 : r = tab->mat->n_row;
4243 0 : tab->mat->n_row = tab->n_row;
4244 0 : c = tab->mat->n_col;
4245 0 : tab->mat->n_col = 2 + tab->M + tab->n_col;
4246 0 : isl_mat_print_internal(tab->mat, out, indent);
4247 0 : tab->mat->n_row = r;
4248 0 : tab->mat->n_col = c;
4249 0 : if (tab->bmap)
4250 0 : isl_basic_map_print_internal(tab->bmap, out, indent);
4251 : }
4252 :
4253 0 : void isl_tab_dump(__isl_keep struct isl_tab *tab)
4254 : {
4255 0 : isl_tab_print_internal(tab, stderr, 0);
4256 0 : }
|