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 8317048188 : 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 8317048188 : unsigned off = 2 + M;
39 :
40 8317048188 : tab = isl_calloc_type(ctx, struct isl_tab);
41 8317048188 : if (!tab)
42 0 : return NULL;
43 8317048188 : tab->mat = isl_mat_alloc(ctx, n_row, off + n_var);
44 8317048188 : if (!tab->mat)
45 0 : goto error;
46 8317048188 : tab->var = isl_alloc_array(ctx, struct isl_tab_var, n_var);
47 8317048188 : if (n_var && !tab->var)
48 0 : goto error;
49 8317048188 : tab->con = isl_alloc_array(ctx, struct isl_tab_var, n_row);
50 8317048188 : if (n_row && !tab->con)
51 0 : goto error;
52 8317048188 : tab->col_var = isl_alloc_array(ctx, int, n_var);
53 8317048188 : if (n_var && !tab->col_var)
54 0 : goto error;
55 8317048188 : tab->row_var = isl_alloc_array(ctx, int, n_row);
56 8317048188 : if (n_row && !tab->row_var)
57 0 : goto error;
58 43526066917 : for (i = 0; i < n_var; ++i) {
59 35209018729 : tab->var[i].index = i;
60 35209018729 : tab->var[i].is_row = 0;
61 35209018729 : tab->var[i].is_nonneg = 0;
62 35209018729 : tab->var[i].is_zero = 0;
63 35209018729 : tab->var[i].is_redundant = 0;
64 35209018729 : tab->var[i].frozen = 0;
65 35209018729 : tab->var[i].negated = 0;
66 35209018729 : tab->col_var[i] = i;
67 : }
68 8317048188 : tab->n_row = 0;
69 8317048188 : tab->n_con = 0;
70 8317048188 : tab->n_eq = 0;
71 8317048188 : tab->max_con = n_row;
72 8317048188 : tab->n_col = n_var;
73 8317048188 : tab->n_var = n_var;
74 8317048188 : tab->max_var = n_var;
75 8317048188 : tab->n_param = 0;
76 8317048188 : tab->n_div = 0;
77 8317048188 : tab->n_dead = 0;
78 8317048188 : tab->n_redundant = 0;
79 8317048188 : tab->strict_redundant = 0;
80 8317048188 : tab->need_undo = 0;
81 8317048188 : tab->rational = 0;
82 8317048188 : tab->empty = 0;
83 8317048188 : tab->in_undo = 0;
84 8317048188 : tab->M = M;
85 8317048188 : tab->cone = 0;
86 8317048188 : tab->bottom.type = isl_tab_undo_bottom;
87 8317048188 : tab->bottom.next = NULL;
88 8317048188 : tab->top = &tab->bottom;
89 :
90 8317048188 : tab->n_zero = 0;
91 8317048188 : tab->n_unbounded = 0;
92 8317048188 : tab->basis = NULL;
93 :
94 8317048188 : return tab;
95 : error:
96 0 : isl_tab_free(tab);
97 0 : return NULL;
98 : }
99 :
100 44493435284 : isl_ctx *isl_tab_get_ctx(struct isl_tab *tab)
101 : {
102 44493435284 : return tab ? isl_mat_get_ctx(tab->mat) : NULL;
103 : }
104 :
105 25496805442 : int isl_tab_extend_cons(struct isl_tab *tab, unsigned n_new)
106 : {
107 : unsigned off;
108 :
109 25496805442 : if (!tab)
110 0 : return -1;
111 :
112 25496805442 : off = 2 + tab->M;
113 :
114 25496805442 : if (tab->max_con < tab->n_con + n_new) {
115 : struct isl_tab_var *con;
116 :
117 36534935 : con = isl_realloc_array(tab->mat->ctx, tab->con,
118 : struct isl_tab_var, tab->max_con + n_new);
119 36534935 : if (!con)
120 0 : return -1;
121 36534935 : tab->con = con;
122 36534935 : tab->max_con += n_new;
123 : }
124 25496805442 : if (tab->mat->n_row < tab->n_row + n_new) {
125 : int *row_var;
126 :
127 204864502 : tab->mat = isl_mat_extend(tab->mat,
128 204864502 : tab->n_row + n_new, off + tab->n_col);
129 102432251 : if (!tab->mat)
130 0 : return -1;
131 102432251 : row_var = isl_realloc_array(tab->mat->ctx, tab->row_var,
132 : int, tab->mat->n_row);
133 102432251 : if (!row_var)
134 0 : return -1;
135 102432251 : tab->row_var = row_var;
136 102432251 : 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 25496805442 : 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 >17771*10^7 : static void free_undo_record(struct isl_tab_undo *undo)
183 : {
184 >17771*10^7 : switch (undo->type) {
185 : case isl_tab_undo_saved_basis:
186 0 : free(undo->u.col_var);
187 0 : break;
188 : default:;
189 : }
190 >17771*10^7 : free(undo);
191 >17771*10^7 : }
192 :
193 8320351023 : static void free_undo(struct isl_tab *tab)
194 : {
195 : struct isl_tab_undo *undo, *next;
196 :
197 9652611126 : for (undo = tab->top; undo && undo != &tab->bottom; undo = next) {
198 1332260103 : next = undo->next;
199 1332260103 : free_undo_record(undo);
200 : }
201 8320351023 : tab->top = undo;
202 8320351023 : }
203 :
204 8321005721 : void isl_tab_free(struct isl_tab *tab)
205 : {
206 8321005721 : if (!tab)
207 654698 : return;
208 8320351023 : free_undo(tab);
209 8320351023 : isl_mat_free(tab->mat);
210 8320351023 : isl_vec_free(tab->dual);
211 8320351023 : isl_basic_map_free(tab->bmap);
212 8320351023 : free(tab->var);
213 8320351023 : free(tab->con);
214 8320351023 : free(tab->row_var);
215 8320351023 : free(tab->col_var);
216 8320351023 : free(tab->row_sign);
217 8320351023 : isl_mat_free(tab->samples);
218 8320351023 : free(tab->sample_index);
219 8320351023 : isl_mat_free(tab->basis);
220 8320351023 : 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 3302835 : 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 3302835 : prod = isl_mat_alloc(mat1->ctx, mat1->n_row + mat2->n_row,
333 3302835 : off + col1 + col2);
334 3302835 : if (!prod)
335 0 : return NULL;
336 :
337 3302835 : n = 0;
338 27671870 : for (i = 0; i < r1; ++i) {
339 24369035 : isl_seq_cpy(prod->row[n + i], mat1->row[i], off + d1);
340 24369035 : isl_seq_clr(prod->row[n + i] + off + d1, d2);
341 48738070 : isl_seq_cpy(prod->row[n + i] + off + d1 + d2,
342 24369035 : mat1->row[i] + off + d1, col1 - d1);
343 24369035 : isl_seq_clr(prod->row[n + i] + off + col1 + d1, col2 - d2);
344 : }
345 :
346 3302835 : n += r1;
347 27671870 : for (i = 0; i < r2; ++i) {
348 24369035 : isl_seq_cpy(prod->row[n + i], mat2->row[i], off);
349 24369035 : isl_seq_clr(prod->row[n + i] + off, d1);
350 48738070 : isl_seq_cpy(prod->row[n + i] + off + d1,
351 48738070 : mat2->row[i] + off, d2);
352 24369035 : isl_seq_clr(prod->row[n + i] + off + d1 + d2, col1 - d1);
353 48738070 : isl_seq_cpy(prod->row[n + i] + off + col1 + d1,
354 24369035 : mat2->row[i] + off + d2, col2 - d2);
355 : }
356 :
357 3302835 : n += r2;
358 42566725 : for (i = 0; i < row1 - r1; ++i) {
359 39263890 : isl_seq_cpy(prod->row[n + i], mat1->row[r1 + i], off + d1);
360 39263890 : isl_seq_clr(prod->row[n + i] + off + d1, d2);
361 78527780 : isl_seq_cpy(prod->row[n + i] + off + d1 + d2,
362 39263890 : mat1->row[r1 + i] + off + d1, col1 - d1);
363 39263890 : isl_seq_clr(prod->row[n + i] + off + col1 + d1, col2 - d2);
364 : }
365 :
366 3302835 : n += row1 - r1;
367 42566725 : for (i = 0; i < row2 - r2; ++i) {
368 39263890 : isl_seq_cpy(prod->row[n + i], mat2->row[r2 + i], off);
369 39263890 : isl_seq_clr(prod->row[n + i] + off, d1);
370 78527780 : isl_seq_cpy(prod->row[n + i] + off + d1,
371 78527780 : mat2->row[r2 + i] + off, d2);
372 39263890 : isl_seq_clr(prod->row[n + i] + off + d1 + d2, col1 - d1);
373 78527780 : isl_seq_cpy(prod->row[n + i] + off + col1 + d1,
374 39263890 : mat2->row[r2 + i] + off + d2, col2 - d2);
375 : }
376 :
377 3302835 : 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 80491241 : static void update_index1(struct isl_tab_var *var,
384 : unsigned r1, unsigned r2, unsigned d1, unsigned d2)
385 : {
386 80491241 : if (var->index == -1)
387 440441 : return;
388 80050800 : if (var->is_row && var->index >= r1)
389 39263890 : var->index += r2;
390 80050800 : if (!var->is_row && var->index >= d1)
391 15226941 : 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 80491241 : 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 80491241 : if (var->index == -1)
402 440441 : return;
403 80050800 : if (var->is_row) {
404 63632925 : if (var->index < r2)
405 24369035 : var->index += r1;
406 : else
407 39263890 : var->index += row1;
408 : } else {
409 16417875 : if (var->index < d2)
410 1190934 : var->index += d1;
411 : else
412 15226941 : 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 3302835 : 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 3302835 : if (!tab1 || !tab2)
442 0 : return NULL;
443 :
444 3302835 : isl_assert(tab1->mat->ctx, tab1->M == tab2->M, return NULL);
445 3302835 : isl_assert(tab1->mat->ctx, tab1->rational == tab2->rational, return NULL);
446 3302835 : isl_assert(tab1->mat->ctx, tab1->cone == tab2->cone, return NULL);
447 3302835 : isl_assert(tab1->mat->ctx, !tab1->row_sign, return NULL);
448 3302835 : isl_assert(tab1->mat->ctx, !tab2->row_sign, return NULL);
449 3302835 : isl_assert(tab1->mat->ctx, tab1->n_param == 0, return NULL);
450 3302835 : isl_assert(tab1->mat->ctx, tab2->n_param == 0, return NULL);
451 3302835 : isl_assert(tab1->mat->ctx, tab1->n_div == 0, return NULL);
452 3302835 : isl_assert(tab1->mat->ctx, tab2->n_div == 0, return NULL);
453 :
454 3302835 : off = 2 + tab1->M;
455 3302835 : r1 = tab1->n_redundant;
456 3302835 : r2 = tab2->n_redundant;
457 3302835 : d1 = tab1->n_dead;
458 3302835 : d2 = tab2->n_dead;
459 3302835 : prod = isl_calloc_type(tab1->mat->ctx, struct isl_tab);
460 3302835 : if (!prod)
461 0 : return NULL;
462 3302835 : 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 3302835 : if (!prod->mat)
466 0 : goto error;
467 3302835 : prod->var = isl_alloc_array(tab1->mat->ctx, struct isl_tab_var,
468 : tab1->max_var + tab2->max_var);
469 3302835 : if ((tab1->max_var + tab2->max_var) && !prod->var)
470 0 : goto error;
471 20161151 : for (i = 0; i < tab1->n_var; ++i) {
472 16858316 : prod->var[i] = tab1->var[i];
473 16858316 : update_index1(&prod->var[i], r1, r2, d1, d2);
474 : }
475 20161151 : for (i = 0; i < tab2->n_var; ++i) {
476 16858316 : prod->var[tab1->n_var + i] = tab2->var[i];
477 16858316 : update_index2(&prod->var[tab1->n_var + i],
478 : tab1->n_row, tab1->n_col,
479 : r1, r2, d1, d2);
480 : }
481 3302835 : prod->con = isl_alloc_array(tab1->mat->ctx, struct isl_tab_var,
482 : tab1->max_con + tab2->max_con);
483 3302835 : if ((tab1->max_con + tab2->max_con) && !prod->con)
484 0 : goto error;
485 66935760 : for (i = 0; i < tab1->n_con; ++i) {
486 63632925 : prod->con[i] = tab1->con[i];
487 63632925 : update_index1(&prod->con[i], r1, r2, d1, d2);
488 : }
489 66935760 : for (i = 0; i < tab2->n_con; ++i) {
490 63632925 : prod->con[tab1->n_con + i] = tab2->con[i];
491 63632925 : update_index2(&prod->con[tab1->n_con + i],
492 : tab1->n_row, tab1->n_col,
493 : r1, r2, d1, d2);
494 : }
495 3302835 : prod->col_var = isl_alloc_array(tab1->mat->ctx, int,
496 : tab1->n_col + tab2->n_col);
497 3302835 : if ((tab1->n_col + tab2->n_col) && !prod->col_var)
498 0 : goto error;
499 19720710 : for (i = 0; i < tab1->n_col; ++i) {
500 16417875 : int pos = i < d1 ? i : i + d2;
501 16417875 : prod->col_var[pos] = tab1->col_var[i];
502 : }
503 19720710 : for (i = 0; i < tab2->n_col; ++i) {
504 16417875 : int pos = i < d2 ? d1 + i : tab1->n_col + i;
505 16417875 : int t = tab2->col_var[i];
506 16417875 : if (t >= 0)
507 5699 : t += tab1->n_var;
508 : else
509 16412176 : t -= tab1->n_con;
510 16417875 : prod->col_var[pos] = t;
511 : }
512 3302835 : prod->row_var = isl_alloc_array(tab1->mat->ctx, int,
513 : tab1->mat->n_row + tab2->mat->n_row);
514 3302835 : if ((tab1->mat->n_row + tab2->mat->n_row) && !prod->row_var)
515 0 : goto error;
516 66935760 : for (i = 0; i < tab1->n_row; ++i) {
517 63632925 : int pos = i < r1 ? i : i + r2;
518 63632925 : prod->row_var[pos] = tab1->row_var[i];
519 : }
520 66935760 : for (i = 0; i < tab2->n_row; ++i) {
521 63632925 : int pos = i < r2 ? r1 + i : tab1->n_row + i;
522 63632925 : int t = tab2->row_var[i];
523 63632925 : if (t >= 0)
524 16852617 : t += tab1->n_var;
525 : else
526 46780308 : t -= tab1->n_con;
527 63632925 : prod->row_var[pos] = t;
528 : }
529 3302835 : prod->samples = NULL;
530 3302835 : prod->sample_index = NULL;
531 3302835 : prod->n_row = tab1->n_row + tab2->n_row;
532 3302835 : prod->n_con = tab1->n_con + tab2->n_con;
533 3302835 : prod->n_eq = 0;
534 3302835 : prod->max_con = tab1->max_con + tab2->max_con;
535 3302835 : prod->n_col = tab1->n_col + tab2->n_col;
536 3302835 : prod->n_var = tab1->n_var + tab2->n_var;
537 3302835 : prod->max_var = tab1->max_var + tab2->max_var;
538 3302835 : prod->n_param = 0;
539 3302835 : prod->n_div = 0;
540 3302835 : prod->n_dead = tab1->n_dead + tab2->n_dead;
541 3302835 : prod->n_redundant = tab1->n_redundant + tab2->n_redundant;
542 3302835 : prod->rational = tab1->rational;
543 3302835 : prod->empty = tab1->empty || tab2->empty;
544 3302835 : prod->strict_redundant = tab1->strict_redundant || tab2->strict_redundant;
545 3302835 : prod->need_undo = 0;
546 3302835 : prod->in_undo = 0;
547 3302835 : prod->M = tab1->M;
548 3302835 : prod->cone = tab1->cone;
549 3302835 : prod->bottom.type = isl_tab_undo_bottom;
550 3302835 : prod->bottom.next = NULL;
551 3302835 : prod->top = &prod->bottom;
552 :
553 3302835 : prod->n_zero = 0;
554 3302835 : prod->n_unbounded = 0;
555 3302835 : prod->basis = NULL;
556 :
557 3302835 : return prod;
558 : error:
559 0 : isl_tab_free(prod);
560 0 : return NULL;
561 : }
562 :
563 >12866*10^8 : static struct isl_tab_var *var_from_index(struct isl_tab *tab, int i)
564 : {
565 >12866*10^8 : if (i >= 0)
566 >30420*10^7 : return &tab->var[i];
567 : else
568 >98239*10^7 : return &tab->con[~i];
569 : }
570 :
571 >79627*10^7 : struct isl_tab_var *isl_tab_var_from_row(struct isl_tab *tab, int i)
572 : {
573 >79627*10^7 : return var_from_index(tab, tab->row_var[i]);
574 : }
575 :
576 >34128*10^7 : static struct isl_tab_var *var_from_col(struct isl_tab *tab, int i)
577 : {
578 >34128*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 12273619118 : static int max_is_manifestly_unbounded(struct isl_tab *tab,
586 : struct isl_tab_var *var)
587 : {
588 : int i;
589 12273619118 : unsigned off = 2 + tab->M;
590 :
591 12273619118 : if (var->is_row)
592 6497819905 : return 0;
593 35368146986 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
594 31271305798 : if (!isl_int_is_neg(tab->mat->row[i][off + var->index]))
595 23647230016 : continue;
596 7624075782 : if (isl_tab_var_from_row(tab, i)->is_nonneg)
597 1678958025 : return 0;
598 : }
599 4096841188 : 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 15824112525 : static int min_is_manifestly_unbounded(struct isl_tab *tab,
607 : struct isl_tab_var *var)
608 : {
609 : int i;
610 15824112525 : unsigned off = 2 + tab->M;
611 :
612 15824112525 : if (var->is_row)
613 12034938905 : return 0;
614 17566302782 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
615 16858033899 : if (!isl_int_is_pos(tab->mat->row[i][off + var->index]))
616 10868393483 : continue;
617 5989640416 : if (isl_tab_var_from_row(tab, i)->is_nonneg)
618 3080904737 : return 0;
619 : }
620 708268883 : return 1;
621 : }
622 :
623 36934495252 : static int row_cmp(struct isl_tab *tab, int r1, int r2, int c, isl_int *t)
624 : {
625 36934495252 : unsigned off = 2 + tab->M;
626 :
627 36934495252 : 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 36934495252 : isl_int_mul(*t, tab->mat->row[r1][1], tab->mat->row[r2][off + c]);
636 36934495252 : isl_int_submul(*t, tab->mat->row[r2][1], tab->mat->row[r1][off + c]);
637 36934495252 : 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 25556208138 : 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 25556208138 : unsigned off = 2 + tab->M;
666 :
667 25556208138 : isl_int_init(t);
668 25556208138 : r = -1;
669 >25769*10^7 : for (j = tab->n_redundant; j < tab->n_row; ++j) {
670 >23214*10^7 : if (var && j == var->index)
671 22386517434 : continue;
672 >20975*10^7 : if (!isl_tab_var_from_row(tab, j)->is_nonneg)
673 76897339959 : continue;
674 >13285*10^7 : if (sgn * isl_int_sgn(tab->mat->row[j][off + c]) >= 0)
675 77601456905 : continue;
676 55255447064 : if (r < 0) {
677 18320951812 : r = j;
678 18320951812 : continue;
679 : }
680 36934495252 : tsgn = sgn * row_cmp(tab, r, j, c, &t);
681 51789099973 : if (tsgn < 0 || (tsgn == 0 &&
682 14854604721 : tab->row_var[j] < tab->row_var[r]))
683 19213956017 : r = j;
684 : }
685 25556208138 : isl_int_clear(t);
686 25556208138 : 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 57586706830 : 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 57586706830 : *row = *col = -1;
713 :
714 57586706830 : isl_assert(tab->mat->ctx, var->is_row, return);
715 57586706830 : tr = tab->mat->row[var->index] + 2 + tab->M;
716 :
717 57586706830 : c = -1;
718 >22710*10^7 : for (j = tab->n_dead; j < tab->n_col; ++j) {
719 >16951*10^7 : if (isl_int_is_zero(tr[j]))
720 69578793417 : continue;
721 >17343*10^7 : if (isl_int_sgn(tr[j]) != sgn &&
722 73495490935 : var_from_col(tab, j)->is_nonneg)
723 60024995852 : continue;
724 39912154634 : if (c < 0 || tab->col_var[j] < tab->col_var[c])
725 25448939684 : c = j;
726 : }
727 57586706830 : if (c < 0)
728 35040166089 : return;
729 :
730 22546540741 : sgn *= isl_int_sgn(tr[c]);
731 22546540741 : r = pivot_row(tab, skip_var, sgn, c);
732 22546540741 : *row = r < 0 ? var->index : r;
733 22546540741 : *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 >25076*10^7 : int isl_tab_row_is_redundant(struct isl_tab *tab, int row)
743 : {
744 : int i;
745 >25076*10^7 : unsigned off = 2 + tab->M;
746 :
747 >25076*10^7 : if (tab->row_var[row] < 0 && !isl_tab_var_from_row(tab, row)->is_nonneg)
748 20322982079 : return 0;
749 :
750 >23044*10^7 : if (isl_int_is_neg(tab->mat->row[row][1]))
751 37738236787 : return 0;
752 >19270*10^7 : if (tab->strict_redundant && isl_int_is_zero(tab->mat->row[row][1]))
753 0 : return 0;
754 >19270*10^7 : if (tab->M && isl_int_is_neg(tab->mat->row[row][2]))
755 0 : return 0;
756 :
757 >55196*10^7 : for (i = tab->n_dead; i < tab->n_col; ++i) {
758 >53026*10^7 : if (isl_int_is_zero(tab->mat->row[row][off + i]))
759 >24176*10^7 : continue;
760 >28849*10^7 : if (tab->col_var[i] >= 0)
761 61370961373 : return 0;
762 >22712*10^7 : if (isl_int_is_neg(tab->mat->row[row][off + i]))
763 94816570947 : return 0;
764 >13231*10^7 : if (!var_from_col(tab, i)->is_nonneg)
765 14812386638 : return 0;
766 : }
767 21705458331 : return 1;
768 : }
769 :
770 30472455619 : 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 30472455619 : t = tab->row_var[row1];
776 30472455619 : tab->row_var[row1] = tab->row_var[row2];
777 30472455619 : tab->row_var[row2] = t;
778 30472455619 : isl_tab_var_from_row(tab, row1)->index = row1;
779 30472455619 : isl_tab_var_from_row(tab, row2)->index = row2;
780 30472455619 : tab->mat = isl_mat_swap_rows(tab->mat, row1, row2);
781 :
782 30472455619 : if (!tab->row_sign)
783 30472455619 : 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 >26352*10^7 : 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 >26352*10^7 : if (!tab)
805 0 : return isl_stat_error;
806 >26352*10^7 : if (!tab->need_undo)
807 85808834205 : return isl_stat_ok;
808 :
809 >17771*10^7 : undo = isl_alloc_type(tab->mat->ctx, struct isl_tab_undo);
810 >17771*10^7 : if (!undo)
811 0 : goto error;
812 >17771*10^7 : undo->type = type;
813 >17771*10^7 : undo->u = u;
814 >17771*10^7 : undo->next = tab->top;
815 >17771*10^7 : tab->top = undo;
816 :
817 >17771*10^7 : 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 >23595*10^7 : 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 >23595*10^7 : if (var->is_row)
829 >19900*10^7 : u.var_index = tab->row_var[var->index];
830 : else
831 36955139141 : u.var_index = tab->col_var[var->index];
832 >23595*10^7 : return push_union(tab, type, u);
833 : }
834 :
835 27568555880 : isl_stat isl_tab_push(struct isl_tab *tab, enum isl_tab_undo_type type)
836 : {
837 27568555880 : union isl_tab_undo_val u = { 0 };
838 27568555880 : 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 27048514827 : int isl_tab_mark_redundant(struct isl_tab *tab, int row)
957 : {
958 27048514827 : struct isl_tab_var *var = isl_tab_var_from_row(tab, row);
959 27048514827 : var->is_redundant = 1;
960 27048514827 : isl_assert(tab->mat->ctx, row >= tab->n_redundant, return -1);
961 27048514827 : if (tab->preserve || tab->need_undo || tab->row_var[row] >= 0) {
962 19010150760 : if (tab->row_var[row] >= 0 && !var->is_nonneg) {
963 9246361619 : var->is_nonneg = 1;
964 9246361619 : if (isl_tab_push_var(tab, isl_tab_undo_nonneg, var) < 0)
965 0 : return -1;
966 : }
967 19010150760 : if (row != tab->n_redundant)
968 16319986643 : swap_rows(tab, row, tab->n_redundant);
969 19010150760 : tab->n_redundant++;
970 19010150760 : return isl_tab_push_var(tab, isl_tab_undo_redundant, var);
971 : } else {
972 8038364067 : if (row != tab->n_row - 1)
973 5447318451 : swap_rows(tab, row, tab->n_row - 1);
974 8038364067 : isl_tab_var_from_row(tab, tab->n_row - 1)->index = -1;
975 8038364067 : tab->n_row--;
976 8038364067 : 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 146948 : int isl_tab_mark_rational(struct isl_tab *tab)
986 : {
987 146948 : if (!tab)
988 0 : return -1;
989 146948 : if (!tab->rational && tab->need_undo)
990 146436 : if (isl_tab_push(tab, isl_tab_undo_rational) < 0)
991 0 : return -1;
992 146948 : tab->rational = 1;
993 146948 : return 0;
994 : }
995 :
996 8741078486 : isl_stat isl_tab_mark_empty(struct isl_tab *tab)
997 : {
998 8741078486 : if (!tab)
999 0 : return isl_stat_error;
1000 8741078486 : if (!tab->empty && tab->need_undo)
1001 6822784797 : if (isl_tab_push(tab, isl_tab_undo_empty) < 0)
1002 0 : return isl_stat_error;
1003 8741078486 : tab->empty = 1;
1004 8741078486 : return isl_stat_ok;
1005 : }
1006 :
1007 71753564463 : int isl_tab_freeze_constraint(struct isl_tab *tab, int con)
1008 : {
1009 : struct isl_tab_var *var;
1010 :
1011 71753564463 : if (!tab)
1012 0 : return -1;
1013 :
1014 71753564463 : var = &tab->con[con];
1015 71753564463 : if (var->frozen)
1016 0 : return 0;
1017 71753564463 : if (var->index < 0)
1018 1483569404 : return 0;
1019 70269995059 : var->frozen = 1;
1020 :
1021 70269995059 : if (tab->need_undo)
1022 70269995059 : 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 44493432228 : static void update_row_sign(struct isl_tab *tab, int row, int col, int row_sgn)
1045 : {
1046 : int i;
1047 44493432228 : struct isl_mat *mat = tab->mat;
1048 44493432228 : unsigned off = 2 + tab->M;
1049 :
1050 44493432228 : if (!tab->row_sign)
1051 44493432228 : 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 44493432228 : 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 44493432228 : struct isl_mat *mat = tab->mat;
1132 : struct isl_tab_var *var;
1133 44493432228 : unsigned off = 2 + tab->M;
1134 :
1135 44493432228 : ctx = isl_tab_get_ctx(tab);
1136 44493432228 : if (isl_ctx_next_operation(ctx) < 0)
1137 0 : return -1;
1138 :
1139 44493432228 : isl_int_swap(mat->row[row][0], mat->row[row][off + col]);
1140 44493432228 : sgn = isl_int_sgn(mat->row[row][0]);
1141 44493432228 : if (sgn < 0) {
1142 16405290621 : isl_int_neg(mat->row[row][0], mat->row[row][0]);
1143 16405290621 : isl_int_neg(mat->row[row][off + col], mat->row[row][off + col]);
1144 : } else
1145 >21273*10^7 : for (j = 0; j < off - 1 + tab->n_col; ++j) {
1146 >18465*10^7 : if (j == off - 1 + col)
1147 28088141607 : continue;
1148 >15656*10^7 : isl_int_neg(mat->row[row][1 + j], mat->row[row][1 + j]);
1149 : }
1150 44493432228 : if (!isl_int_is_one(mat->row[row][0]))
1151 13443961054 : isl_seq_normalize(mat->ctx, mat->row[row], off + tab->n_col);
1152 >41406*10^7 : for (i = 0; i < tab->n_row; ++i) {
1153 >36957*10^7 : if (i == row)
1154 44493432228 : continue;
1155 >32507*10^7 : if (isl_int_is_zero(mat->row[i][off + col]))
1156 >15855*10^7 : continue;
1157 >16652*10^7 : isl_int_mul(mat->row[i][0], mat->row[i][0], mat->row[row][0]);
1158 >12779*10^8 : for (j = 0; j < off - 1 + tab->n_col; ++j) {
1159 >11113*10^8 : if (j == off - 1 + col)
1160 >16652*10^7 : continue;
1161 >94487*10^7 : isl_int_mul(mat->row[i][1 + j],
1162 : mat->row[i][1 + j], mat->row[row][0]);
1163 >94487*10^7 : isl_int_addmul(mat->row[i][1 + j],
1164 : mat->row[i][off + col], mat->row[row][1 + j]);
1165 : }
1166 >16652*10^7 : isl_int_mul(mat->row[i][off + col],
1167 : mat->row[i][off + col], mat->row[row][off + col]);
1168 >16652*10^7 : if (!isl_int_is_one(mat->row[i][0]))
1169 >11986*10^7 : isl_seq_normalize(mat->ctx, mat->row[i], off + tab->n_col);
1170 : }
1171 44493432228 : t = tab->row_var[row];
1172 44493432228 : tab->row_var[row] = tab->col_var[col];
1173 44493432228 : tab->col_var[col] = t;
1174 44493432228 : var = isl_tab_var_from_row(tab, row);
1175 44493432228 : var->is_row = 1;
1176 44493432228 : var->index = row;
1177 44493432228 : var = var_from_col(tab, col);
1178 44493432228 : var->is_row = 0;
1179 44493432228 : var->index = col;
1180 44493432228 : update_row_sign(tab, row, col, sgn);
1181 44493432228 : if (tab->in_undo)
1182 2042571711 : return 0;
1183 >35097*10^7 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
1184 >30852*10^7 : if (isl_int_is_zero(mat->row[i][off + col]))
1185 >13027*10^7 : continue;
1186 >33580*10^7 : if (!isl_tab_var_from_row(tab, i)->frozen &&
1187 >15756*10^7 : isl_tab_row_is_redundant(tab, i)) {
1188 12971790352 : int redo = isl_tab_mark_redundant(tab, i);
1189 12971790352 : if (redo < 0)
1190 0 : return -1;
1191 12971790352 : if (redo)
1192 1837332280 : --i;
1193 : }
1194 : }
1195 42450860517 : 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 9218829984 : static int to_row(struct isl_tab *tab, struct isl_tab_var *var, int sign)
1206 : {
1207 : int r;
1208 9218829984 : unsigned off = 2 + tab->M;
1209 :
1210 9218829984 : if (var->is_row)
1211 6503028973 : return 0;
1212 :
1213 2715801011 : if (sign == 0) {
1214 764467271 : for (r = tab->n_redundant; r < tab->n_row; ++r)
1215 764467271 : if (!isl_int_is_zero(tab->mat->row[r][off+var->index]))
1216 : break;
1217 237733649 : isl_assert(tab->mat->ctx, r < tab->n_row, return -1);
1218 : } else {
1219 2478067362 : r = pivot_row(tab, NULL, sign, var->index);
1220 2478067362 : isl_assert(tab->mat->ctx, r >= 0, return -1);
1221 : }
1222 :
1223 2715801011 : 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 7799083033 : static int sign_of_max(struct isl_tab *tab, struct isl_tab_var *var)
1265 : {
1266 : int row, col;
1267 :
1268 7799083033 : if (max_is_manifestly_unbounded(tab, var))
1269 859444004 : return 1;
1270 6939639029 : if (to_row(tab, var, 1) < 0)
1271 0 : return -2;
1272 20620672118 : while (!isl_int_is_pos(tab->mat->row[var->index][1])) {
1273 13408018163 : find_pivot(tab, var, var, 1, &row, &col);
1274 13408018163 : if (row == -1)
1275 5326264502 : return isl_int_sgn(tab->mat->row[var->index][1]);
1276 8081753661 : if (isl_tab_pivot(tab, row, col) < 0)
1277 0 : return -2;
1278 8081753661 : if (!var->is_row) /* manifestly unbounded */
1279 1340359601 : return 1;
1280 : }
1281 273014926 : 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 59027264137 : static int row_is_neg(struct isl_tab *tab, int row)
1299 : {
1300 59027264137 : if (!tab->M)
1301 59027264137 : 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 48122372165 : static int row_sgn(struct isl_tab *tab, int row)
1310 : {
1311 48122372165 : if (!tab->M)
1312 48122372165 : 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 53645324865 : static int restore_row(struct isl_tab *tab, struct isl_tab_var *var)
1325 : {
1326 : int row, col;
1327 :
1328 >11267*10^7 : while (row_is_neg(tab, var->index)) {
1329 19649467553 : find_pivot(tab, var, var, 1, &row, &col);
1330 19649467553 : if (row == -1)
1331 8744575581 : break;
1332 10904891972 : if (isl_tab_pivot(tab, row, col) < 0)
1333 0 : return -2;
1334 10904891972 : if (!var->is_row) /* manifestly unbounded */
1335 5522952700 : return 1;
1336 : }
1337 48122372165 : 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 7122673533 : static int at_least_zero(struct isl_tab *tab, struct isl_tab_var *var)
1346 : {
1347 : int row, col;
1348 :
1349 14271086468 : while (isl_int_is_neg(tab->mat->row[var->index][1])) {
1350 7138958804 : find_pivot(tab, var, var, 1, &row, &col);
1351 7138958804 : if (row == -1)
1352 7099033178 : break;
1353 39925626 : if (row == var->index) /* manifestly unbounded */
1354 14186224 : return 1;
1355 25739402 : if (isl_tab_pivot(tab, row, col) < 0)
1356 0 : return -1;
1357 : }
1358 7108487309 : 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 11221856972 : static int sign_of_min(struct isl_tab *tab, struct isl_tab_var *var)
1379 : {
1380 : int row, col;
1381 11221856972 : struct isl_tab_var *pivot_var = NULL;
1382 :
1383 11221856972 : if (min_is_manifestly_unbounded(tab, var))
1384 0 : return -1;
1385 11221856972 : if (!var->is_row) {
1386 900220 : col = var->index;
1387 900220 : row = pivot_row(tab, NULL, -1, col);
1388 900220 : pivot_var = var_from_col(tab, col);
1389 900220 : if (isl_tab_pivot(tab, row, col) < 0)
1390 0 : return -2;
1391 900220 : if (var->is_redundant)
1392 144351 : return 0;
1393 755869 : if (isl_int_is_neg(tab->mat->row[var->index][1])) {
1394 449887 : if (var->is_nonneg) {
1395 899774 : if (!pivot_var->is_redundant &&
1396 449887 : pivot_var->index == row) {
1397 838602 : if (isl_tab_pivot(tab, row, col) < 0)
1398 0 : return -2;
1399 : } else
1400 30586 : if (restore_row(tab, var) < -1)
1401 0 : return -2;
1402 : }
1403 449887 : return -1;
1404 : }
1405 : }
1406 11221262734 : if (var->is_redundant)
1407 0 : return 0;
1408 22467094411 : while (!isl_int_is_neg(tab->mat->row[var->index][1])) {
1409 11232056486 : find_pivot(tab, var, var, -1, &row, &col);
1410 11232056486 : if (row == var->index)
1411 25780111 : return -1;
1412 11206276375 : if (row == -1)
1413 11181226503 : return isl_int_sgn(tab->mat->row[var->index][1]);
1414 25049872 : pivot_var = var_from_col(tab, col);
1415 25049872 : if (isl_tab_pivot(tab, row, col) < 0)
1416 0 : return -2;
1417 25049872 : if (var->is_redundant)
1418 480929 : return 0;
1419 : }
1420 13775191 : if (pivot_var && var->is_nonneg) {
1421 : /* pivot back to non-negative value */
1422 512269 : if (!pivot_var->is_redundant && pivot_var->index == row) {
1423 973728 : if (isl_tab_pivot(tab, row, col) < 0)
1424 0 : return -2;
1425 : } else
1426 25405 : if (restore_row(tab, var) < -1)
1427 0 : return -2;
1428 : }
1429 13775191 : return -1;
1430 : }
1431 :
1432 1424913571 : static int row_at_most_neg_one(struct isl_tab *tab, int row)
1433 : {
1434 1424913571 : 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 2044876997 : return isl_int_is_neg(tab->mat->row[row][1]) &&
1441 619963426 : 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 1339472900 : 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 1339472900 : if (min_is_manifestly_unbounded(tab, var))
1460 0 : return 1;
1461 1339472900 : if (!var->is_row) {
1462 530699815 : col = var->index;
1463 530699815 : row = pivot_row(tab, NULL, -1, col);
1464 530699815 : pivot_var = var_from_col(tab, col);
1465 530699815 : if (isl_tab_pivot(tab, row, col) < 0)
1466 0 : return -1;
1467 530699815 : if (var->is_redundant)
1468 61346054 : return 0;
1469 469353761 : if (row_at_most_neg_one(tab, var->index)) {
1470 300696466 : if (var->is_nonneg) {
1471 601392932 : if (!pivot_var->is_redundant &&
1472 300696466 : pivot_var->index == row) {
1473 596397464 : if (isl_tab_pivot(tab, row, col) < 0)
1474 0 : return -1;
1475 : } else
1476 2497734 : if (restore_row(tab, var) < -1)
1477 0 : return -1;
1478 : }
1479 300696466 : return 1;
1480 : }
1481 : }
1482 977430380 : if (var->is_redundant)
1483 1 : return 0;
1484 : do {
1485 1714456894 : find_pivot(tab, var, var, -1, &row, &col);
1486 1714456894 : if (row == var->index) {
1487 304892108 : if (var->is_nonneg && restore_row(tab, var) < -1)
1488 0 : return -1;
1489 304892108 : return 1;
1490 : }
1491 1409564786 : if (row == -1)
1492 168617047 : return 0;
1493 1240947739 : pivot_var = var_from_col(tab, col);
1494 1240947739 : if (isl_tab_pivot(tab, row, col) < 0)
1495 0 : return -1;
1496 1240947739 : if (var->is_redundant)
1497 285387929 : return 0;
1498 955559810 : } while (!row_at_most_neg_one(tab, var->index));
1499 218533295 : if (var->is_nonneg) {
1500 : /* pivot back to non-negative value */
1501 211065489 : if (!pivot_var->is_redundant && pivot_var->index == row)
1502 209392545 : if (isl_tab_pivot(tab, row, col) < 0)
1503 0 : return -1;
1504 211065489 : if (restore_row(tab, var) < -1)
1505 0 : return -1;
1506 : }
1507 218533295 : return 1;
1508 : }
1509 :
1510 : /* Return 1 if "var" can attain values >= 1.
1511 : * Return 0 otherwise.
1512 : */
1513 2436146997 : 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 2436146997 : if (max_is_manifestly_unbounded(tab, var))
1519 2199803605 : return 1;
1520 236343392 : if (to_row(tab, var, 1) < 0)
1521 0 : return -1;
1522 236343392 : r = tab->mat->row[var->index];
1523 489974745 : while (isl_int_lt(r[1], r[0])) {
1524 43305818 : find_pivot(tab, var, var, 1, &row, &col);
1525 43305818 : if (row == -1)
1526 2835708 : return isl_int_ge(r[1], r[0]);
1527 40470110 : if (row == var->index) /* manifestly unbounded */
1528 23182149 : return 1;
1529 17287961 : if (isl_tab_pivot(tab, row, col) < 0)
1530 0 : return -1;
1531 : }
1532 210325535 : return 1;
1533 : }
1534 :
1535 12568376930 : static void swap_cols(struct isl_tab *tab, int col1, int col2)
1536 : {
1537 : int t;
1538 12568376930 : unsigned off = 2 + tab->M;
1539 12568376930 : t = tab->col_var[col1];
1540 12568376930 : tab->col_var[col1] = tab->col_var[col2];
1541 12568376930 : tab->col_var[col2] = t;
1542 12568376930 : var_from_col(tab, col1)->index = col1;
1543 12568376930 : var_from_col(tab, col2)->index = col2;
1544 12568376930 : tab->mat = isl_mat_swap_cols(tab->mat, off + col1, off + col2);
1545 12568376930 : }
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 23843744497 : int isl_tab_kill_col(struct isl_tab *tab, int col)
1560 : {
1561 23843744497 : var_from_col(tab, col)->is_zero = 1;
1562 23843744497 : if (tab->need_undo) {
1563 101549971 : if (isl_tab_push_var(tab, isl_tab_undo_zero,
1564 : var_from_col(tab, col)) < 0)
1565 0 : return -1;
1566 101549971 : if (col != tab->n_dead)
1567 64087872 : swap_cols(tab, col, tab->n_dead);
1568 101549971 : tab->n_dead++;
1569 101549971 : return 0;
1570 : } else {
1571 23742194526 : if (col != tab->n_col - 1)
1572 12504289058 : swap_cols(tab, col, tab->n_col - 1);
1573 23742194526 : var_from_col(tab, tab->n_col - 1)->index = -1;
1574 23742194526 : tab->n_col--;
1575 23742194526 : return 1;
1576 : }
1577 : }
1578 :
1579 23426833698 : static int row_is_manifestly_non_integral(struct isl_tab *tab, int row)
1580 : {
1581 23426833698 : unsigned off = 2 + tab->M;
1582 :
1583 23426833698 : if (tab->M && !isl_int_eq(tab->mat->row[row][2],
1584 : tab->mat->row[row][0]))
1585 0 : return 0;
1586 23426833698 : if (isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
1587 23426833698 : tab->n_col - tab->n_dead) != -1)
1588 3385309585 : return 0;
1589 :
1590 20041524113 : 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 5326213219 : static int tab_is_manifestly_empty(struct isl_tab *tab)
1598 : {
1599 : int i;
1600 :
1601 5326213219 : if (tab->empty)
1602 3255 : return 1;
1603 5326209964 : if (tab->rational)
1604 1147599 : return 0;
1605 :
1606 31554060641 : for (i = 0; i < tab->n_var; ++i) {
1607 26229080103 : if (!tab->var[i].is_row)
1608 2802246405 : continue;
1609 23426833698 : if (row_is_manifestly_non_integral(tab, tab->var[i].index))
1610 81827 : return 1;
1611 : }
1612 :
1613 5324980538 : 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 5326213219 : static isl_stat close_row(struct isl_tab *tab, struct isl_tab_var *var,
1636 : int temp_var)
1637 : {
1638 : int j;
1639 5326213219 : struct isl_mat *mat = tab->mat;
1640 5326213219 : unsigned off = 2 + tab->M;
1641 :
1642 5326213219 : 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 5326213219 : var->is_zero = 1;
1647 5326213219 : 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 15314659418 : for (j = tab->n_dead; j < tab->n_col; ++j) {
1651 : int recheck;
1652 9988446199 : if (isl_int_is_zero(mat->row[var->index][off + j]))
1653 4798749095 : continue;
1654 5189697104 : 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 5189697104 : recheck = isl_tab_kill_col(tab, j);
1659 5189697104 : if (recheck < 0)
1660 0 : return isl_stat_error;
1661 5189697104 : if (recheck)
1662 5189003373 : --j;
1663 : }
1664 5326213219 : if (!temp_var && isl_tab_mark_redundant(tab, var->index) < 0)
1665 0 : return isl_stat_error;
1666 5326213219 : if (tab_is_manifestly_empty(tab) && isl_tab_mark_empty(tab) < 0)
1667 0 : return isl_stat_error;
1668 5326213219 : 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 88495561809 : int isl_tab_allocate_con(struct isl_tab *tab)
1678 : {
1679 : int r;
1680 :
1681 88495561809 : isl_assert(tab->mat->ctx, tab->n_row < tab->mat->n_row, return -1);
1682 88495561809 : isl_assert(tab->mat->ctx, tab->n_con < tab->max_con, return -1);
1683 :
1684 88495561809 : r = tab->n_con;
1685 88495561809 : tab->con[r].index = tab->n_row;
1686 88495561809 : tab->con[r].is_row = 1;
1687 88495561809 : tab->con[r].is_nonneg = 0;
1688 88495561809 : tab->con[r].is_zero = 0;
1689 88495561809 : tab->con[r].is_redundant = 0;
1690 88495561809 : tab->con[r].frozen = 0;
1691 88495561809 : tab->con[r].negated = 0;
1692 88495561809 : tab->row_var[tab->n_row] = ~r;
1693 :
1694 88495561809 : tab->n_row++;
1695 88495561809 : tab->n_con++;
1696 88495561809 : if (isl_tab_push_var(tab, isl_tab_undo_allocate, &tab->con[r]) < 0)
1697 0 : return -1;
1698 :
1699 88495561809 : 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 88495508940 : 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 88495508940 : unsigned off = 2 + tab->M;
1830 :
1831 88495508940 : r = isl_tab_allocate_con(tab);
1832 88495508940 : if (r < 0)
1833 0 : return -1;
1834 :
1835 88495508940 : isl_int_init(a);
1836 88495508940 : isl_int_init(b);
1837 88495508940 : row = tab->mat->row[tab->con[r].index];
1838 88495508940 : isl_int_set_si(row[0], 1);
1839 88495508940 : isl_int_set(row[1], line[0]);
1840 88495508940 : isl_seq_clr(row + 2, tab->M + tab->n_col);
1841 >64781*10^7 : for (i = 0; i < tab->n_var; ++i) {
1842 >55931*10^7 : if (tab->var[i].is_zero)
1843 0 : continue;
1844 >55931*10^7 : if (tab->var[i].is_row) {
1845 >31607*10^7 : isl_int_lcm(a,
1846 : row[0], tab->mat->row[tab->var[i].index][0]);
1847 >31607*10^7 : isl_int_swap(a, row[0]);
1848 >31607*10^7 : isl_int_divexact(a, row[0], a);
1849 >31607*10^7 : isl_int_divexact(b,
1850 : row[0], tab->mat->row[tab->var[i].index][0]);
1851 >31607*10^7 : isl_int_mul(b, b, line[1 + i]);
1852 >63215*10^7 : isl_seq_combine(row + 1, a, row + 1,
1853 >31607*10^7 : b, tab->mat->row[tab->var[i].index] + 1,
1854 >31607*10^7 : 1 + tab->M + tab->n_col);
1855 : } else
1856 >24324*10^7 : isl_int_addmul(row[off + tab->var[i].index],
1857 : line[1 + i], row[0]);
1858 >55931*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 88495508940 : isl_seq_normalize(tab->mat->ctx, row, off + tab->n_col);
1862 88495508940 : isl_int_clear(a);
1863 88495508940 : isl_int_clear(b);
1864 :
1865 88495508940 : if (tab->row_sign)
1866 0 : tab->row_sign[tab->con[r].index] = isl_tab_row_unknown;
1867 :
1868 88495508940 : return r;
1869 : }
1870 :
1871 41579296890 : static isl_stat drop_row(struct isl_tab *tab, int row)
1872 : {
1873 41579296890 : isl_assert(tab->mat->ctx, ~tab->row_var[row] == tab->n_con - 1,
1874 : return isl_stat_error);
1875 41579296890 : if (row != tab->n_row - 1)
1876 8705150525 : swap_rows(tab, row, tab->n_row - 1);
1877 41579296890 : tab->n_row--;
1878 41579296890 : tab->n_con--;
1879 41579296890 : 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 48831805934 : 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 48831805934 : if (!tab)
1914 0 : return isl_stat_error;
1915 48831805934 : if (tab->bmap) {
1916 20745518909 : struct isl_basic_map *bmap = tab->bmap;
1917 :
1918 20745518909 : isl_assert(tab->mat->ctx, tab->n_eq == bmap->n_eq,
1919 : return isl_stat_error);
1920 20745518909 : isl_assert(tab->mat->ctx,
1921 : tab->n_con == bmap->n_eq + bmap->n_ineq,
1922 : return isl_stat_error);
1923 20745518909 : tab->bmap = isl_basic_map_add_ineq(tab->bmap, ineq);
1924 20745518909 : if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
1925 0 : return isl_stat_error;
1926 20745518909 : if (!tab->bmap)
1927 0 : return isl_stat_error;
1928 : }
1929 48831805934 : 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 48831805934 : r = isl_tab_add_row(tab, ineq);
1935 48831805934 : if (tab->cone) {
1936 0 : isl_int_swap(ineq[0], cst);
1937 0 : isl_int_clear(cst);
1938 : }
1939 48831805934 : if (r < 0)
1940 0 : return isl_stat_error;
1941 48831805934 : tab->con[r].is_nonneg = 1;
1942 48831805934 : if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
1943 0 : return isl_stat_error;
1944 48831805934 : if (isl_tab_row_is_redundant(tab, tab->con[r].index)) {
1945 8733667979 : if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
1946 0 : return isl_stat_error;
1947 8733667979 : return isl_stat_ok;
1948 : }
1949 :
1950 40098137955 : sgn = restore_row(tab, &tab->con[r]);
1951 40098137955 : if (sgn < -1)
1952 0 : return isl_stat_error;
1953 40098137955 : if (sgn < 0)
1954 8740948149 : return isl_tab_mark_empty(tab);
1955 31357189806 : 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 31357189806 : 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 100856240 : static int to_col(struct isl_tab *tab, struct isl_tab_var *var)
1966 : {
1967 : int i;
1968 : int row, col;
1969 100856240 : unsigned off = 2 + tab->M;
1970 :
1971 100856240 : if (!var->is_row)
1972 0 : return 0;
1973 :
1974 268561453 : while (isl_int_is_pos(tab->mat->row[var->index][1])) {
1975 157959342 : find_pivot(tab, var, NULL, -1, &row, &col);
1976 157959342 : isl_assert(tab->mat->ctx, row != -1, return -1);
1977 157959342 : if (isl_tab_pivot(tab, row, col) < 0)
1978 0 : return -1;
1979 157959342 : if (!var->is_row)
1980 91110369 : return 0;
1981 : }
1982 :
1983 16498861 : for (i = tab->n_dead; i < tab->n_col; ++i)
1984 16498861 : if (!isl_int_is_zero(tab->mat->row[var->index][off + i]))
1985 : break;
1986 :
1987 9745871 : isl_assert(tab->mat->ctx, i < tab->n_col, return -1);
1988 9745871 : if (isl_tab_pivot(tab, var->index, i) < 0)
1989 0 : return -1;
1990 :
1991 9745871 : 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 18553191153 : static struct isl_tab *add_eq(struct isl_tab *tab, isl_int *eq)
2003 : {
2004 : int i;
2005 : int r;
2006 :
2007 18553191153 : if (!tab)
2008 0 : return NULL;
2009 18553191153 : r = isl_tab_add_row(tab, eq);
2010 18553191153 : if (r < 0)
2011 0 : goto error;
2012 :
2013 18553191153 : r = tab->con[r].index;
2014 18553191153 : i = isl_seq_first_non_zero(tab->mat->row[r] + 2 + tab->M + tab->n_dead,
2015 18553191153 : tab->n_col - tab->n_dead);
2016 18553191153 : isl_assert(tab->mat->ctx, i >= 0, goto error);
2017 18553191153 : i += tab->n_dead;
2018 18553191153 : if (isl_tab_pivot(tab, r, i) < 0)
2019 0 : goto error;
2020 18553191153 : if (isl_tab_kill_col(tab, i) < 0)
2021 0 : goto error;
2022 18553191153 : tab->n_eq++;
2023 :
2024 18553191153 : 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 392851442 : static int row_is_big(struct isl_tab *tab, int row)
2034 : {
2035 392851442 : return tab->M && !isl_int_is_zero(tab->mat->row[row][2]);
2036 : }
2037 :
2038 102174081 : static int row_is_manifestly_zero(struct isl_tab *tab, int row)
2039 : {
2040 102174081 : unsigned off = 2 + tab->M;
2041 :
2042 102174081 : if (!isl_int_is_zero(tab->mat->row[row][1]))
2043 91116397 : return 0;
2044 11057684 : if (row_is_big(tab, row))
2045 0 : return 0;
2046 22115368 : return isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
2047 22115368 : 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 102110736 : 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 102110736 : if (!tab)
2061 0 : return -1;
2062 102110736 : r = isl_tab_add_row(tab, eq);
2063 102110736 : if (r < 0)
2064 0 : return -1;
2065 :
2066 102110736 : var = &tab->con[r];
2067 102110736 : r = var->index;
2068 102110736 : if (row_is_manifestly_zero(tab, r)) {
2069 1313876 : var->is_zero = 1;
2070 1313876 : if (isl_tab_mark_redundant(tab, r) < 0)
2071 0 : return -1;
2072 1313876 : return 0;
2073 : }
2074 :
2075 100796860 : if (isl_int_is_neg(tab->mat->row[r][1])) {
2076 28634946 : isl_seq_neg(tab->mat->row[r] + 1, tab->mat->row[r] + 1,
2077 28634946 : 1 + tab->n_col);
2078 28634946 : var->negated = 1;
2079 : }
2080 100796860 : var->is_nonneg = 1;
2081 100796860 : if (to_col(tab, var) < 0)
2082 0 : return -1;
2083 100796860 : var->is_nonneg = 0;
2084 100796860 : if (isl_tab_kill_col(tab, var->index) < 0)
2085 0 : return -1;
2086 :
2087 100796860 : 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 52869 : static int add_zero_row(struct isl_tab *tab)
2097 : {
2098 : int r;
2099 : isl_int *row;
2100 :
2101 52869 : r = isl_tab_allocate_con(tab);
2102 52869 : if (r < 0)
2103 0 : return -1;
2104 :
2105 52869 : row = tab->mat->row[tab->con[r].index];
2106 52869 : isl_seq_clr(row + 1, 1 + tab->M + tab->n_col);
2107 52869 : isl_int_set_si(row[0], 1);
2108 :
2109 52869 : 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 63345 : int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
2120 : {
2121 63345 : 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 63345 : if (!tab)
2129 0 : return -1;
2130 63345 : isl_assert(tab->mat->ctx, !tab->M, return -1);
2131 :
2132 63345 : if (tab->need_undo)
2133 63345 : snap = isl_tab_snap(tab);
2134 :
2135 63345 : 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 63345 : r = isl_tab_add_row(tab, eq);
2141 63345 : if (tab->cone) {
2142 0 : isl_int_swap(eq[0], cst);
2143 0 : isl_int_clear(cst);
2144 : }
2145 63345 : if (r < 0)
2146 0 : return -1;
2147 :
2148 63345 : var = &tab->con[r];
2149 63345 : row = var->index;
2150 63345 : if (row_is_manifestly_zero(tab, row)) {
2151 3965 : if (snap)
2152 3965 : return isl_tab_rollback(tab, snap);
2153 0 : return drop_row(tab, row);
2154 : }
2155 :
2156 59380 : if (tab->bmap) {
2157 52869 : tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
2158 52869 : if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
2159 0 : return -1;
2160 52869 : isl_seq_neg(eq, eq, 1 + tab->n_var);
2161 52869 : tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
2162 52869 : isl_seq_neg(eq, eq, 1 + tab->n_var);
2163 52869 : if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
2164 0 : return -1;
2165 52869 : if (!tab->bmap)
2166 0 : return -1;
2167 52869 : if (add_zero_row(tab) < 0)
2168 0 : return -1;
2169 : }
2170 :
2171 59380 : sgn = isl_int_sgn(tab->mat->row[row][1]);
2172 :
2173 59380 : if (sgn > 0) {
2174 1163 : isl_seq_neg(tab->mat->row[row] + 1, tab->mat->row[row] + 1,
2175 1163 : 1 + tab->n_col);
2176 1163 : var->negated = 1;
2177 1163 : sgn = -1;
2178 : }
2179 :
2180 59380 : if (sgn < 0) {
2181 16814 : sgn = sign_of_max(tab, var);
2182 16814 : if (sgn < -1)
2183 0 : return -1;
2184 16814 : if (sgn < 0) {
2185 0 : if (isl_tab_mark_empty(tab) < 0)
2186 0 : return -1;
2187 0 : return 0;
2188 : }
2189 : }
2190 :
2191 59380 : var->is_nonneg = 1;
2192 59380 : if (to_col(tab, var) < 0)
2193 0 : return -1;
2194 59380 : var->is_nonneg = 0;
2195 59380 : if (isl_tab_kill_col(tab, var->index) < 0)
2196 0 : return -1;
2197 :
2198 59380 : 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 8316155043 : __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 8316155043 : if (!bmap)
2397 0 : return NULL;
2398 16632310086 : tab = isl_tab_alloc(bmap->ctx,
2399 8316155043 : isl_basic_map_total_dim(bmap) + bmap->n_ineq + 1,
2400 : isl_basic_map_total_dim(bmap), 0);
2401 8316155043 : if (!tab)
2402 0 : return NULL;
2403 8316155043 : tab->preserve = track;
2404 8316155043 : tab->rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
2405 8316155043 : 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 26864963716 : for (i = 0; i < bmap->n_eq; ++i) {
2411 18548808673 : tab = add_eq(tab, bmap->eq[i]);
2412 18548808673 : if (!tab)
2413 0 : return tab;
2414 : }
2415 35071274743 : for (i = 0; i < bmap->n_ineq; ++i) {
2416 28080554861 : if (isl_tab_add_ineq(tab, bmap->ineq[i]) < 0)
2417 0 : goto error;
2418 28080554861 : if (tab->empty)
2419 1325435161 : goto done;
2420 : }
2421 : done:
2422 8316155043 : if (track && isl_tab_track_bmap(tab, isl_basic_map_copy(bmap)) < 0)
2423 0 : goto error;
2424 8316155043 : return tab;
2425 : error:
2426 0 : isl_tab_free(tab);
2427 0 : return NULL;
2428 : }
2429 :
2430 1421072486 : __isl_give struct isl_tab *isl_tab_from_basic_set(
2431 : __isl_keep isl_basic_set *bset, int track)
2432 : {
2433 1421072486 : return isl_tab_from_basic_map(bset, track);
2434 : }
2435 :
2436 : /* Construct a tableau corresponding to the recession cone of "bset".
2437 : */
2438 893145 : 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 893145 : unsigned offset = 0;
2445 :
2446 893145 : if (!bset)
2447 0 : return NULL;
2448 893145 : if (parametric)
2449 893145 : offset = isl_basic_set_dim(bset, isl_dim_param);
2450 893145 : tab = isl_tab_alloc(bset->ctx, bset->n_eq + bset->n_ineq,
2451 893145 : isl_basic_set_total_dim(bset) - offset, 0);
2452 893145 : if (!tab)
2453 0 : return NULL;
2454 893145 : tab->rational = ISL_F_ISSET(bset, ISL_BASIC_SET_RATIONAL);
2455 893145 : tab->cone = 1;
2456 :
2457 893145 : isl_int_init(cst);
2458 893145 : isl_int_set_si(cst, 0);
2459 5275625 : for (i = 0; i < bset->n_eq; ++i) {
2460 4382480 : isl_int_swap(bset->eq[i][offset], cst);
2461 4382480 : if (offset > 0) {
2462 0 : if (isl_tab_add_eq(tab, bset->eq[i] + offset) < 0)
2463 0 : goto error;
2464 : } else
2465 4382480 : tab = add_eq(tab, bset->eq[i]);
2466 4382480 : isl_int_swap(bset->eq[i][offset], cst);
2467 4382480 : if (!tab)
2468 0 : goto done;
2469 : }
2470 962814 : for (i = 0; i < bset->n_ineq; ++i) {
2471 : int r;
2472 69669 : isl_int_swap(bset->ineq[i][offset], cst);
2473 69669 : r = isl_tab_add_row(tab, bset->ineq[i] + offset);
2474 69669 : isl_int_swap(bset->ineq[i][offset], cst);
2475 69669 : if (r < 0)
2476 0 : goto error;
2477 69669 : tab->con[r].is_nonneg = 1;
2478 69669 : if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
2479 0 : goto error;
2480 : }
2481 : done:
2482 893145 : isl_int_clear(cst);
2483 893145 : 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 893145 : isl_bool isl_tab_cone_is_bounded(struct isl_tab *tab)
2494 : {
2495 : int i;
2496 :
2497 893145 : if (!tab)
2498 0 : return isl_bool_error;
2499 893145 : if (tab->empty)
2500 0 : return isl_bool_true;
2501 893145 : if (tab->n_dead == tab->n_col)
2502 867902 : return isl_bool_true;
2503 :
2504 : for (;;) {
2505 229416 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
2506 : struct isl_tab_var *var;
2507 : int sgn;
2508 114708 : var = isl_tab_var_from_row(tab, i);
2509 114708 : if (!var->is_nonneg)
2510 86523 : continue;
2511 28185 : sgn = sign_of_max(tab, var);
2512 28185 : if (sgn < -1)
2513 0 : return isl_bool_error;
2514 28185 : if (sgn != 0)
2515 0 : return isl_bool_false;
2516 28185 : if (close_row(tab, var, 0) < 0)
2517 0 : return isl_bool_error;
2518 28185 : break;
2519 : }
2520 28185 : if (tab->n_dead == tab->n_col)
2521 25243 : return isl_bool_true;
2522 2942 : if (i == tab->n_row)
2523 0 : return isl_bool_false;
2524 2942 : }
2525 : }
2526 :
2527 1632099111 : int isl_tab_sample_is_integer(struct isl_tab *tab)
2528 : {
2529 : int i;
2530 :
2531 1632099111 : if (!tab)
2532 0 : return -1;
2533 :
2534 9071895402 : for (i = 0; i < tab->n_var; ++i) {
2535 : int row;
2536 7570284094 : if (!tab->var[i].is_row)
2537 713829992 : continue;
2538 6856454102 : row = tab->var[i].index;
2539 6856454102 : if (!isl_int_is_divisible_by(tab->mat->row[row][1],
2540 : tab->mat->row[row][0]))
2541 130487803 : return 0;
2542 : }
2543 1501611308 : return 1;
2544 : }
2545 :
2546 1494243450 : static struct isl_vec *extract_integer_sample(struct isl_tab *tab)
2547 : {
2548 : int i;
2549 : struct isl_vec *vec;
2550 :
2551 1494243450 : vec = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
2552 1494243450 : if (!vec)
2553 0 : return NULL;
2554 :
2555 1494243450 : isl_int_set_si(vec->block.data[0], 1);
2556 8732120513 : for (i = 0; i < tab->n_var; ++i) {
2557 7237877063 : if (!tab->var[i].is_row)
2558 706113021 : isl_int_set_si(vec->block.data[1 + i], 0);
2559 : else {
2560 6531764042 : int row = tab->var[i].index;
2561 6531764042 : isl_int_divexact(vec->block.data[1 + i],
2562 : tab->mat->row[row][1], tab->mat->row[row][0]);
2563 : }
2564 : }
2565 :
2566 1494243450 : return vec;
2567 : }
2568 :
2569 105541573 : 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 105541573 : if (!tab)
2576 0 : return NULL;
2577 :
2578 105541573 : vec = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
2579 105541573 : if (!vec)
2580 0 : return NULL;
2581 :
2582 105541573 : isl_int_init(m);
2583 :
2584 105541573 : isl_int_set_si(vec->block.data[0], 1);
2585 669677594 : for (i = 0; i < tab->n_var; ++i) {
2586 : int row;
2587 564136021 : if (!tab->var[i].is_row) {
2588 127960600 : isl_int_set_si(vec->block.data[1 + i], 0);
2589 127960600 : continue;
2590 : }
2591 436175421 : row = tab->var[i].index;
2592 436175421 : isl_int_gcd(m, vec->block.data[0], tab->mat->row[row][0]);
2593 436175421 : isl_int_divexact(m, tab->mat->row[row][0], m);
2594 436175421 : isl_seq_scale(vec->block.data, vec->block.data, m, 1 + i);
2595 436175421 : isl_int_divexact(m, vec->block.data[0], tab->mat->row[row][0]);
2596 436175421 : isl_int_mul(vec->block.data[1 + i], m, tab->mat->row[row][1]);
2597 : }
2598 105541573 : vec = isl_vec_normalize(vec);
2599 :
2600 105541573 : isl_int_clear(m);
2601 105541573 : 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 148929893 : static void get_rounded_sample_value(struct isl_tab *tab,
2608 : struct isl_tab_var *var, int sgn, isl_int *v)
2609 : {
2610 148929893 : if (!var->is_row)
2611 1278282 : isl_int_set_si(*v, 0);
2612 147651611 : else if (sgn > 0)
2613 142439487 : isl_int_cdiv_q(*v, tab->mat->row[var->index][1],
2614 : tab->mat->row[var->index][0]);
2615 : else
2616 5212124 : isl_int_fdiv_q(*v, tab->mat->row[var->index][1],
2617 : tab->mat->row[var->index][0]);
2618 148929893 : }
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 4628748914 : 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 4628748914 : if (!bmap)
2635 0 : return NULL;
2636 4628748914 : if (!tab)
2637 0 : return bmap;
2638 :
2639 4628748914 : n_eq = tab->n_eq;
2640 4628748914 : if (tab->empty)
2641 2296485 : bmap = isl_basic_map_set_to_empty(bmap);
2642 : else
2643 20347481252 : for (i = bmap->n_ineq - 1; i >= 0; --i) {
2644 15721028823 : if (isl_tab_is_equality(tab, n_eq + i))
2645 10507856375 : isl_basic_map_inequality_to_equality(bmap, i);
2646 5213172448 : else if (isl_tab_is_redundant(tab, n_eq + i))
2647 1954620804 : isl_basic_map_drop_inequality(bmap, i);
2648 : }
2649 4628748914 : if (bmap->n_eq != n_eq)
2650 1346162311 : bmap = isl_basic_map_gauss(bmap, NULL);
2651 4628748914 : if (!tab->rational &&
2652 1742127323 : bmap && !bmap->sample && isl_tab_sample_is_integer(tab))
2653 1494243450 : bmap->sample = extract_integer_sample(tab);
2654 4628748914 : return bmap;
2655 : }
2656 :
2657 1402391 : struct isl_basic_set *isl_basic_set_update_from_tab(struct isl_basic_set *bset,
2658 : struct isl_tab *tab)
2659 : {
2660 1402391 : 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 3524788 : static isl_stat drop_last_con_in_row(struct isl_tab *tab, int r)
2668 : {
2669 3524788 : 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 3524788 : 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 3524788 : if (drop_row(tab, tab->con[r].index) < 0)
2677 0 : return isl_stat_error;
2678 :
2679 3524788 : 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 3524788 : 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 3524788 : unsigned off = 2 + tab->M;
2698 :
2699 3524788 : if (var->is_zero)
2700 0 : return isl_stat_ok;
2701 3524788 : 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 3524788 : if (isl_tab_extend_cons(tab, 1) < 0)
2707 0 : return isl_stat_error;
2708 :
2709 3524788 : r = tab->n_con;
2710 3524788 : tab->con[r].index = tab->n_row;
2711 3524788 : tab->con[r].is_row = 1;
2712 3524788 : tab->con[r].is_nonneg = 0;
2713 3524788 : tab->con[r].is_zero = 0;
2714 3524788 : tab->con[r].is_redundant = 0;
2715 3524788 : tab->con[r].frozen = 0;
2716 3524788 : tab->con[r].negated = 0;
2717 3524788 : tab->row_var[tab->n_row] = ~r;
2718 3524788 : row = tab->mat->row[tab->n_row];
2719 :
2720 3524788 : if (var->is_row) {
2721 2929919 : isl_int_set(row[0], tab->mat->row[var->index][0]);
2722 5859838 : isl_seq_neg(row + 1,
2723 5859838 : tab->mat->row[var->index] + 1, 1 + tab->n_col);
2724 : } else {
2725 594869 : isl_int_set_si(row[0], 1);
2726 594869 : isl_seq_clr(row + 1, 1 + tab->n_col);
2727 594869 : isl_int_set_si(row[off + var->index], -1);
2728 : }
2729 :
2730 3524788 : tab->n_row++;
2731 3524788 : tab->n_con++;
2732 :
2733 3524788 : sgn = sign_of_max(tab, &tab->con[r]);
2734 3524788 : if (sgn < -1)
2735 0 : return isl_stat_error;
2736 3524788 : if (sgn < 0) {
2737 45255 : if (drop_last_con_in_row(tab, r) < 0)
2738 0 : return isl_stat_error;
2739 45255 : if (isl_tab_mark_empty(tab) < 0)
2740 0 : return isl_stat_error;
2741 45255 : return isl_stat_ok;
2742 : }
2743 3479533 : tab->con[r].is_nonneg = 1;
2744 : /* sgn == 0 */
2745 3479533 : if (close_row(tab, &tab->con[r], 1) < 0)
2746 0 : return isl_stat_error;
2747 3479533 : if (drop_last_con_in_row(tab, r) < 0)
2748 0 : return isl_stat_error;
2749 :
2750 3479533 : return isl_stat_ok;
2751 : }
2752 :
2753 : /* Check that "con" is a valid constraint position for "tab".
2754 : */
2755 6556637197 : static isl_stat isl_tab_check_con(struct isl_tab *tab, int con)
2756 : {
2757 6556637197 : if (!tab)
2758 0 : return isl_stat_error;
2759 6556637197 : 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 6556637197 : 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 498520 : int isl_tab_relax(struct isl_tab *tab, int con)
2783 : {
2784 : struct isl_tab_var *var;
2785 :
2786 498520 : if (!tab)
2787 0 : return -1;
2788 :
2789 498520 : var = &tab->con[con];
2790 :
2791 498520 : 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 498520 : 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 498520 : if (!var->is_row && !max_is_manifestly_unbounded(tab, var))
2799 55155 : if (to_row(tab, var, 1) < 0)
2800 0 : return -1;
2801 498520 : if (!var->is_row && !min_is_manifestly_unbounded(tab, var))
2802 42904 : if (to_row(tab, var, -1) < 0)
2803 0 : return -1;
2804 :
2805 498520 : if (var->is_row) {
2806 99838 : isl_int_add(tab->mat->row[var->index][1],
2807 : tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
2808 99838 : if (restore_row(tab, var) < 0)
2809 0 : return -1;
2810 : } else {
2811 : int i;
2812 398682 : unsigned off = 2 + tab->M;
2813 :
2814 1641810 : for (i = 0; i < tab->n_row; ++i) {
2815 1243128 : if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
2816 721901 : continue;
2817 521227 : 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 498520 : if (isl_tab_push_var(tab, isl_tab_undo_relax, var) < 0)
2824 0 : return -1;
2825 :
2826 498520 : 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 1192261 : int isl_tab_unrestrict(struct isl_tab *tab, int con)
2893 : {
2894 : struct isl_tab_var *var;
2895 :
2896 1192261 : if (!tab)
2897 0 : return -1;
2898 :
2899 1192261 : var = &tab->con[con];
2900 1192261 : if (!var->is_nonneg)
2901 0 : return 0;
2902 :
2903 1192261 : var->is_nonneg = 0;
2904 1192261 : if (isl_tab_push_var(tab, isl_tab_undo_unrestrict, var) < 0)
2905 0 : return -1;
2906 :
2907 1192261 : return 0;
2908 : }
2909 :
2910 689080 : int isl_tab_select_facet(struct isl_tab *tab, int con)
2911 : {
2912 689080 : if (!tab)
2913 0 : return -1;
2914 :
2915 689080 : return cut_to_hyperplane(tab, &tab->con[con]);
2916 : }
2917 :
2918 31575684801 : static int may_be_equality(struct isl_tab *tab, int row)
2919 : {
2920 63208821659 : return tab->rational ? isl_int_is_zero(tab->mat->row[row][1])
2921 31633136858 : : 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 10424363111 : static struct isl_tab_var *select_marked(struct isl_tab *tab)
2937 : {
2938 : int i;
2939 : struct isl_tab_var *var;
2940 :
2941 61918871319 : for (i = tab->n_con - 1; i >= 0; --i) {
2942 60482539757 : var = &tab->con[i];
2943 60482539757 : if (var->index < 0)
2944 39382802951 : continue;
2945 21099736806 : if (var->is_row && var->index < tab->n_redundant)
2946 1667711494 : continue;
2947 19432025312 : if (!var->is_row && var->index < tab->n_dead)
2948 85385 : continue;
2949 19431939927 : if (var->marked)
2950 8988031549 : return var;
2951 : }
2952 :
2953 1436331562 : 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 4565119413 : int isl_tab_detect_implicit_equalities(struct isl_tab *tab)
2974 : {
2975 : int i;
2976 : unsigned n_marked;
2977 :
2978 4565119413 : if (!tab)
2979 0 : return -1;
2980 4565119413 : if (tab->empty)
2981 2445752 : return 0;
2982 4562673661 : if (tab->n_dead == tab->n_col)
2983 2851251002 : return 0;
2984 :
2985 1711422659 : n_marked = 0;
2986 16629144516 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
2987 14917721857 : struct isl_tab_var *var = isl_tab_var_from_row(tab, i);
2988 29244624354 : var->marked = !var->frozen && var->is_nonneg &&
2989 14326902497 : may_be_equality(tab, i);
2990 14917721857 : if (var->marked)
2991 13649316650 : n_marked++;
2992 : }
2993 9813452965 : for (i = tab->n_dead; i < tab->n_col; ++i) {
2994 8102030306 : struct isl_tab_var *var = var_from_col(tab, i);
2995 8102030306 : var->marked = !var->frozen && var->is_nonneg;
2996 8102030306 : if (var->marked)
2997 710639129 : n_marked++;
2998 : }
2999 11215522856 : while (n_marked) {
3000 : struct isl_tab_var *var;
3001 : int sgn;
3002 9181894076 : var = select_marked(tab);
3003 9181894076 : if (!var)
3004 1386380830 : break;
3005 7795513246 : var->marked = 0;
3006 7795513246 : n_marked--;
3007 7795513246 : sgn = sign_of_max(tab, var);
3008 7795513246 : if (sgn < 0)
3009 0 : return -1;
3010 7795513246 : if (sgn == 0) {
3011 5322705501 : if (close_row(tab, var, 0) < 0)
3012 0 : return -1;
3013 2472807745 : } else if (!tab->rational && !at_least_one(tab, var)) {
3014 2835708 : if (cut_to_hyperplane(tab, var) < 0)
3015 0 : return -1;
3016 2835708 : return isl_tab_detect_implicit_equalities(tab);
3017 : }
3018 50655476354 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
3019 42862798816 : var = isl_tab_var_from_row(tab, i);
3020 42862798816 : if (!var->marked)
3021 25614016512 : continue;
3022 17248782304 : if (may_be_equality(tab, i))
3023 17225889560 : continue;
3024 22892744 : var->marked = 0;
3025 22892744 : n_marked--;
3026 : }
3027 : }
3028 :
3029 1708586951 : 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 1652116 : static int update_con_after_move(struct isl_tab *tab, int i, int old)
3036 : {
3037 : int *p;
3038 : int index;
3039 :
3040 1652116 : index = tab->con[i].index;
3041 1652116 : if (index == -1)
3042 1175711 : return 0;
3043 476405 : p = tab->con[i].is_row ? tab->row_var : tab->col_var;
3044 476405 : if (p[index] != ~old)
3045 0 : isl_die(tab->mat->ctx, isl_error_internal,
3046 : "broken internal state", return -1);
3047 476405 : p[index] = ~i;
3048 :
3049 476405 : 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 65215 : isl_stat isl_tab_swap_constraints(struct isl_tab *tab, int con1, int con2)
3058 : {
3059 : struct isl_tab_var var;
3060 :
3061 130430 : if (isl_tab_check_con(tab, con1) < 0 ||
3062 65215 : isl_tab_check_con(tab, con2) < 0)
3063 0 : return isl_stat_error;
3064 :
3065 65215 : var = tab->con[con1];
3066 65215 : tab->con[con1] = tab->con[con2];
3067 65215 : if (update_con_after_move(tab, con1, con2) < 0)
3068 0 : return isl_stat_error;
3069 65215 : tab->con[con2] = var;
3070 65215 : if (update_con_after_move(tab, con2, con1) < 0)
3071 0 : return isl_stat_error;
3072 :
3073 65215 : 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 364552 : 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 364552 : if (n <= 1)
3085 116780 : return 0;
3086 :
3087 247772 : last = first + n - 1;
3088 247772 : var = tab->con[last];
3089 1362075 : for (i = last; i > first; --i) {
3090 1114303 : tab->con[i] = tab->con[i - 1];
3091 1114303 : if (update_con_after_move(tab, i, i - 1) < 0)
3092 0 : return -1;
3093 : }
3094 247772 : tab->con[first] = var;
3095 247772 : if (update_con_after_move(tab, first, last) < 0)
3096 0 : return -1;
3097 :
3098 247772 : 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 52099 : static isl_stat con_drop_entries(struct isl_tab *tab,
3107 : unsigned first, unsigned n)
3108 : {
3109 : int i;
3110 :
3111 52099 : 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 52099 : tab->n_con -= n;
3116 :
3117 211710 : for (i = first; i < tab->n_con; ++i) {
3118 159611 : tab->con[i] = tab->con[i + n];
3119 159611 : if (update_con_after_move(tab, i, i + n) < 0)
3120 0 : return isl_stat_error;
3121 : }
3122 :
3123 52099 : 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 65215 : static isl_stat swap_eq(unsigned a, unsigned b, void *user)
3131 : {
3132 65215 : struct isl_tab *tab = user;
3133 :
3134 65215 : 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 52099 : static isl_stat drop_eq(unsigned n, void *user)
3146 : {
3147 52099 : struct isl_tab *tab = user;
3148 :
3149 52099 : if (tab->n_eq == n)
3150 0 : return isl_tab_mark_empty(tab);
3151 :
3152 52099 : tab->n_eq -= n;
3153 52099 : 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 55490 : 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 55490 : single = isl_basic_map_has_single_reference(bmap);
3165 55490 : if (single < 0)
3166 0 : return isl_basic_map_free(bmap);
3167 55490 : if (single)
3168 807 : return bmap;
3169 54683 : 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 2855809721 : __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 2855809721 : if (!tab || !bmap)
3212 0 : return isl_basic_map_free(bmap);
3213 2855809721 : if (tab->empty)
3214 38306 : return bmap;
3215 :
3216 2855771415 : n_eq = tab->n_eq;
3217 2896675534 : for (i = bmap->n_ineq - 1; i >= 0; --i) {
3218 40904119 : if (!isl_tab_is_equality(tab, bmap->n_eq + i))
3219 40721843 : continue;
3220 182276 : isl_basic_map_inequality_to_equality(bmap, i);
3221 182276 : if (rotate_constraints(tab, 0, tab->n_eq + i + 1) < 0)
3222 0 : return isl_basic_map_free(bmap);
3223 182276 : if (rotate_constraints(tab, tab->n_eq + i + 1,
3224 182276 : bmap->n_ineq - i) < 0)
3225 0 : return isl_basic_map_free(bmap);
3226 182276 : tab->n_eq++;
3227 : }
3228 :
3229 2855771415 : if (n_eq != tab->n_eq)
3230 55490 : bmap = gauss_if_shared(bmap, tab);
3231 :
3232 2855771415 : return bmap;
3233 : }
3234 :
3235 12561329872 : static int con_is_redundant(struct isl_tab *tab, struct isl_tab_var *var)
3236 : {
3237 12561329872 : if (!tab)
3238 0 : return -1;
3239 12561329872 : if (tab->rational) {
3240 11221856972 : int sgn = sign_of_min(tab, var);
3241 11221856972 : if (sgn < -1)
3242 0 : return -1;
3243 11221856972 : return sgn >= 0;
3244 : } else {
3245 1339472900 : int irred = isl_tab_min_at_most_neg_one(tab, var);
3246 1339472900 : if (irred < 0)
3247 0 : return -1;
3248 1339472900 : 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 3218490093 : int isl_tab_detect_redundant(struct isl_tab *tab)
3266 : {
3267 : int i;
3268 : unsigned n_marked;
3269 :
3270 3218490093 : if (!tab)
3271 0 : return -1;
3272 3218490093 : if (tab->empty)
3273 445789 : return 0;
3274 3218044304 : if (tab->n_redundant == tab->n_row)
3275 998202 : return 0;
3276 :
3277 3217046102 : n_marked = 0;
3278 10723115629 : for (i = tab->n_redundant; i < tab->n_row; ++i) {
3279 7506069527 : struct isl_tab_var *var = isl_tab_var_from_row(tab, i);
3280 7506069527 : var->marked = !var->frozen && var->is_nonneg;
3281 7506069527 : if (var->marked)
3282 970422210 : n_marked++;
3283 : }
3284 5079608521 : for (i = tab->n_dead; i < tab->n_col; ++i) {
3285 1862562419 : struct isl_tab_var *var = var_from_col(tab, i);
3286 2704152933 : var->marked = !var->frozen && var->is_nonneg &&
3287 841590514 : !min_is_manifestly_unbounded(tab, var);
3288 1862562419 : if (var->marked)
3289 480823849 : n_marked++;
3290 : }
3291 7626610507 : while (n_marked) {
3292 : struct isl_tab_var *var;
3293 : int red;
3294 1242469035 : var = select_marked(tab);
3295 1242469035 : if (!var)
3296 49950732 : break;
3297 1192518303 : var->marked = 0;
3298 1192518303 : n_marked--;
3299 1192518303 : red = con_is_redundant(tab, var);
3300 1192518303 : if (red < 0)
3301 0 : return -1;
3302 1192518303 : if (red && !var->is_redundant)
3303 19008934 : if (isl_tab_mark_redundant(tab, var->index) < 0)
3304 0 : return -1;
3305 7588001692 : for (i = tab->n_dead; i < tab->n_col; ++i) {
3306 6395483389 : var = var_from_col(tab, i);
3307 6395483389 : if (!var->marked)
3308 5017990586 : continue;
3309 1377492803 : if (!min_is_manifestly_unbounded(tab, var))
3310 1269371516 : continue;
3311 108121287 : var->marked = 0;
3312 108121287 : n_marked--;
3313 : }
3314 : }
3315 :
3316 3217046102 : return 0;
3317 : }
3318 :
3319 15762431462 : int isl_tab_is_equality(struct isl_tab *tab, int con)
3320 : {
3321 : int row;
3322 : unsigned off;
3323 :
3324 15762431462 : if (!tab)
3325 0 : return -1;
3326 15762431462 : if (tab->con[con].is_zero)
3327 10508038647 : return 1;
3328 5254392815 : if (tab->con[con].is_redundant)
3329 1955719441 : return 0;
3330 3298673374 : if (!tab->con[con].is_row)
3331 2361878517 : return tab->con[con].index < tab->n_dead;
3332 :
3333 936794857 : row = tab->con[con].index;
3334 :
3335 936794857 : off = 2 + tab->M;
3336 3170548785 : return isl_int_is_zero(tab->mat->row[row][1]) &&
3337 1658157197 : !row_is_big(tab, row) &&
3338 360681170 : isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
3339 360681170 : 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 2516783001 : 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 2516783001 : enum isl_lp_result res = isl_lp_ok;
3358 : struct isl_tab_var *var;
3359 : struct isl_tab_undo *snap;
3360 :
3361 2516783001 : if (!tab)
3362 0 : return isl_lp_error;
3363 :
3364 2516783001 : if (tab->empty)
3365 0 : return isl_lp_empty;
3366 :
3367 2516783001 : snap = isl_tab_snap(tab);
3368 2516783001 : r = isl_tab_add_row(tab, f);
3369 2516783001 : if (r < 0)
3370 0 : return isl_lp_error;
3371 2516783001 : var = &tab->con[r];
3372 : for (;;) {
3373 : int row, col;
3374 4234557161 : find_pivot(tab, var, var, -1, &row, &col);
3375 4234557161 : if (row == var->index) {
3376 570940 : res = isl_lp_unbounded;
3377 2517353941 : break;
3378 : }
3379 4233986221 : if (row == -1)
3380 2516212061 : break;
3381 1717774160 : if (isl_tab_pivot(tab, row, col) < 0)
3382 0 : return isl_lp_error;
3383 1717774160 : }
3384 2516783001 : isl_int_mul(tab->mat->row[var->index][0],
3385 : tab->mat->row[var->index][0], denom);
3386 2516783001 : if (ISL_FL_ISSET(flags, ISL_TAB_SAVE_DUAL)) {
3387 : int i;
3388 :
3389 54971278 : isl_vec_free(tab->dual);
3390 54971278 : tab->dual = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_con);
3391 54971278 : if (!tab->dual)
3392 0 : return isl_lp_error;
3393 54971278 : isl_int_set(tab->dual->el[0], tab->mat->row[var->index][0]);
3394 2625081295 : for (i = 0; i < tab->n_con; ++i) {
3395 : int pos;
3396 2570110017 : if (tab->con[i].is_row) {
3397 1967546236 : isl_int_set_si(tab->dual->el[1 + i], 0);
3398 1967546236 : continue;
3399 : }
3400 602563781 : pos = 2 + tab->M + tab->con[i].index;
3401 602563781 : if (tab->con[i].negated)
3402 96619504 : isl_int_neg(tab->dual->el[1 + i],
3403 : tab->mat->row[var->index][pos]);
3404 : else
3405 505944277 : isl_int_set(tab->dual->el[1 + i],
3406 : tab->mat->row[var->index][pos]);
3407 : }
3408 : }
3409 2516783001 : if (opt && res == isl_lp_ok) {
3410 2516212061 : if (opt_denom) {
3411 2375171027 : isl_int_set(*opt, tab->mat->row[var->index][1]);
3412 2375171027 : isl_int_set(*opt_denom, tab->mat->row[var->index][0]);
3413 : } else
3414 141041034 : get_rounded_sample_value(tab, var, 1, opt);
3415 : }
3416 2516783001 : if (isl_tab_rollback(tab, snap) < 0)
3417 0 : return isl_lp_error;
3418 2516783001 : 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 6556506767 : int isl_tab_is_redundant(struct isl_tab *tab, int con)
3430 : {
3431 6556506767 : if (isl_tab_check_con(tab, con) < 0)
3432 0 : return -1;
3433 6556506767 : if (tab->con[con].is_zero)
3434 0 : return 0;
3435 6556506767 : if (tab->con[con].is_redundant)
3436 2912018833 : return 1;
3437 3644487934 : 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 6919671 : static isl_bool is_constant(struct isl_tab *tab, struct isl_tab_var *var,
3449 : isl_int *value)
3450 : {
3451 6919671 : unsigned off = 2 + tab->M;
3452 6919671 : isl_mat *mat = tab->mat;
3453 : int n;
3454 : int row;
3455 : int pos;
3456 :
3457 6919671 : if (!var->is_row)
3458 1278282 : return isl_bool_false;
3459 5641389 : row = var->index;
3460 5641389 : if (row_is_big(tab, row))
3461 0 : return isl_bool_false;
3462 5641389 : n = tab->n_col - tab->n_dead;
3463 5641389 : pos = isl_seq_first_non_zero(mat->row[row] + off + tab->n_dead, n);
3464 5641389 : if (pos != -1)
3465 5209068 : return isl_bool_false;
3466 432321 : if (value)
3467 0 : isl_int_divexact(*value, mat->row[row][1], mat->row[row][0]);
3468 432321 : 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 9829810 : static int reached(struct isl_tab *tab, struct isl_tab_var *var, int sgn,
3482 : isl_int target, isl_int *tmp)
3483 : {
3484 9829810 : if (row_is_big(tab, var->index))
3485 0 : return 1;
3486 9829810 : isl_int_mul(*tmp, tab->mat->row[var->index][0], target);
3487 9829810 : if (sgn > 0)
3488 2207943 : return isl_int_ge(tab->mat->row[var->index][1], *tmp);
3489 : else
3490 7621867 : 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 7885803 : 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 7885803 : if (sgn < 0 && min_is_manifestly_unbounded(tab, var))
3515 1248600 : return isl_bool_true;
3516 6637203 : if (sgn > 0 && max_is_manifestly_unbounded(tab, var))
3517 0 : return isl_bool_true;
3518 6637203 : if (to_row(tab, var, sgn) < 0)
3519 0 : return isl_bool_error;
3520 16467013 : while (!reached(tab, var, sgn, target, tmp)) {
3521 7926609 : find_pivot(tab, var, var, sgn, &row, &col);
3522 7926609 : if (row == -1)
3523 1401509 : return isl_bool_false;
3524 6525100 : if (row == var->index)
3525 3332493 : return isl_bool_true;
3526 3192607 : if (isl_tab_pivot(tab, row, col) < 0)
3527 0 : return isl_bool_error;
3528 : }
3529 :
3530 1903201 : 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 6487350 : 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 6487350 : get_rounded_sample_value(tab, var, -1, target);
3561 6487350 : isl_int_sub_ui(*target, *target, 1);
3562 6487350 : reached = var_reaches(tab, var, -1, *target, tmp);
3563 6487350 : if (reached < 0 || reached)
3564 5088897 : return isl_bool_not(reached);
3565 1398453 : get_rounded_sample_value(tab, var, 1, target);
3566 1398453 : isl_int_add_ui(*target, *target, 1);
3567 1398453 : reached = var_reaches(tab, var, 1, *target, tmp);
3568 1398453 : if (reached < 0 || reached)
3569 1395397 : return isl_bool_not(reached);
3570 3056 : get_rounded_sample_value(tab, var, -1, tmp);
3571 3056 : isl_int_sub_ui(*target, *target, 1);
3572 3056 : 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 3056 : if (isl_tab_extend_cons(tab, 1) < 0)
3579 0 : return isl_bool_error;
3580 3056 : eq = isl_vec_alloc(isl_tab_get_ctx(tab), 1 + tab->n_var);
3581 3056 : if (!eq)
3582 0 : return isl_bool_error;
3583 3056 : pos = var - tab->var;
3584 3056 : isl_seq_clr(eq->el + 1, tab->n_var);
3585 3056 : isl_int_set_si(eq->el[1 + pos], -1);
3586 3056 : isl_int_set(eq->el[0], *target);
3587 3056 : r = isl_tab_add_eq(tab, eq->el);
3588 3056 : isl_vec_free(eq);
3589 :
3590 3056 : 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 6919671 : 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 6919671 : if (var->is_row && row_is_big(tab, var->index))
3613 0 : return isl_bool_false;
3614 6919671 : is_cst = is_constant(tab, var, value);
3615 6919671 : if (is_cst < 0 || is_cst)
3616 432321 : return is_cst;
3617 :
3618 6487350 : if (!value)
3619 6487350 : isl_int_init(target);
3620 6487350 : isl_int_init(tmp);
3621 :
3622 6487350 : is_cst = detect_constant_with_tmp(tab, var,
3623 : value ? value : &target, &tmp);
3624 :
3625 6487350 : isl_int_clear(tmp);
3626 6487350 : if (!value)
3627 6487350 : isl_int_clear(target);
3628 :
3629 6487350 : 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 1192261 : isl_stat isl_tab_detect_constants(struct isl_tab *tab)
3659 : {
3660 : int i;
3661 :
3662 1192261 : if (!tab)
3663 0 : return isl_stat_error;
3664 1192261 : if (tab->rational)
3665 0 : return isl_stat_ok;
3666 :
3667 8111932 : for (i = 0; i < tab->n_var; ++i) {
3668 6919671 : if (get_constant(tab, &tab->var[i], NULL) < 0)
3669 0 : return isl_stat_error;
3670 : }
3671 :
3672 1192261 : 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 35136170521 : struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab)
3679 : {
3680 35136170521 : if (!tab)
3681 0 : return NULL;
3682 35136170521 : tab->need_undo = 1;
3683 35136170521 : 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 435685 : static isl_stat unrelax(struct isl_tab *tab, struct isl_tab_var *var)
3716 : {
3717 435685 : unsigned off = 2 + tab->M;
3718 :
3719 435685 : if (!var->is_row && !max_is_manifestly_unbounded(tab, var))
3720 48434 : if (to_row(tab, var, 1) < 0)
3721 0 : return isl_stat_error;
3722 :
3723 435685 : if (var->is_row) {
3724 54092 : isl_int_sub(tab->mat->row[var->index][1],
3725 : tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
3726 54092 : if (var->is_nonneg) {
3727 54092 : int sgn = restore_row(tab, var);
3728 54092 : isl_assert(tab->mat->ctx, sgn >= 0,
3729 : return isl_stat_error);
3730 : }
3731 : } else {
3732 : int i;
3733 :
3734 1568344 : for (i = 0; i < tab->n_row; ++i) {
3735 1186751 : if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
3736 674766 : continue;
3737 511985 : 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 435685 : 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 1190442 : static isl_stat ununrestrict(struct isl_tab *tab, struct isl_tab_var *var)
3752 : {
3753 1190442 : var->is_nonneg = 1;
3754 :
3755 1190442 : if (var->is_row && restore_row(tab, var) < -1)
3756 0 : return isl_stat_error;
3757 :
3758 1190442 : 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 13044641571 : static isl_stat restore_last_redundant(struct isl_tab *tab)
3769 : {
3770 : struct isl_tab_var *var;
3771 :
3772 13044641571 : 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 13044641571 : var = isl_tab_var_from_row(tab, tab->n_redundant - 1);
3777 13044641571 : var->is_redundant = 0;
3778 13044641571 : tab->n_redundant--;
3779 13044641571 : restore_row(tab, var);
3780 :
3781 13044641571 : 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 >14904*10^7 : static isl_stat perform_undo_var(struct isl_tab *tab, struct isl_tab_undo *undo)
3787 : {
3788 >14904*10^7 : struct isl_tab_var *var = var_from_index(tab, undo->u.var_index);
3789 >14904*10^7 : switch (undo->type) {
3790 : case isl_tab_undo_nonneg:
3791 24622380636 : var->is_nonneg = 0;
3792 24622380636 : break;
3793 : case isl_tab_undo_redundant:
3794 12709232757 : 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 12709232757 : return restore_last_redundant(tab);
3799 : case isl_tab_undo_freeze:
3800 70090799829 : var->frozen = 0;
3801 70090799829 : break;
3802 : case isl_tab_undo_zero:
3803 46076049 : var->is_zero = 0;
3804 46076049 : if (!var->is_row)
3805 46076049 : tab->n_dead--;
3806 46076049 : break;
3807 : case isl_tab_undo_allocate:
3808 41575772102 : 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 41575772102 : if (!var->is_row) {
3814 2036063867 : if (!max_is_manifestly_unbounded(tab, var)) {
3815 999293467 : if (to_row(tab, var, 1) < 0)
3816 0 : return isl_stat_error;
3817 1036770400 : } else if (!min_is_manifestly_unbounded(tab, var)) {
3818 799036751 : if (to_row(tab, var, -1) < 0)
3819 0 : return isl_stat_error;
3820 : } else
3821 237733649 : if (to_row(tab, var, 0) < 0)
3822 0 : return isl_stat_error;
3823 : }
3824 41575772102 : return drop_row(tab, var->index);
3825 : case isl_tab_undo_relax:
3826 435685 : return unrelax(tab, var);
3827 : case isl_tab_undo_unrestrict:
3828 1190442 : 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 94759256514 : 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 205381885 : isl_stat isl_tab_restore_redundant(struct isl_tab *tab)
3846 : {
3847 205381885 : if (!tab)
3848 0 : return isl_stat_error;
3849 :
3850 205381885 : 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 746172584 : while (tab->n_redundant > 0) {
3857 335408814 : if (tab->row_var[tab->n_redundant - 1] >= 0) {
3858 : struct isl_tab_var *var;
3859 :
3860 264449857 : var = isl_tab_var_from_row(tab, tab->n_redundant - 1);
3861 264449857 : var->is_nonneg = 0;
3862 : }
3863 335408814 : restore_last_redundant(tab);
3864 : }
3865 205381885 : 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 >17638*10^7 : static isl_stat perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
3968 : {
3969 >17638*10^7 : switch (undo->type) {
3970 : case isl_tab_undo_rational:
3971 146137 : tab->rational = 0;
3972 146137 : break;
3973 : case isl_tab_undo_empty:
3974 6822784530 : tab->empty = 0;
3975 6822784530 : 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 >14904*10^7 : 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 20515829007 : 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 6822930667 : 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 28076302690 : int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap)
4012 : {
4013 : struct isl_tab_undo *undo, *next;
4014 :
4015 28076302690 : if (!tab)
4016 0 : return -1;
4017 :
4018 28076302690 : tab->in_undo = 1;
4019 >20446*10^7 : for (undo = tab->top; undo && undo != &tab->bottom; undo = next) {
4020 >18182*10^7 : next = undo->next;
4021 >18182*10^7 : if (undo == snap)
4022 5442186391 : break;
4023 >17638*10^7 : 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 >17638*10^7 : free_undo_record(undo);
4030 : }
4031 28076302690 : tab->in_undo = 0;
4032 28076302690 : tab->top = undo;
4033 28076302690 : if (!undo)
4034 0 : return -1;
4035 28076302690 : 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 7099033178 : static enum isl_ineq_type separation_type(struct isl_tab *tab, unsigned row)
4049 : {
4050 : int pos;
4051 7099033178 : unsigned off = 2 + tab->M;
4052 :
4053 7099033178 : if (tab->rational)
4054 7037094675 : return isl_ineq_separate;
4055 :
4056 61938503 : if (!isl_int_is_one(tab->mat->row[row][0]))
4057 4262939 : return isl_ineq_separate;
4058 :
4059 57675564 : pos = isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
4060 57675564 : tab->n_col - tab->n_dead);
4061 57675564 : if (pos == -1) {
4062 27605212 : if (isl_int_is_negone(tab->mat->row[row][1]))
4063 2987884 : return isl_ineq_adj_eq;
4064 : else
4065 24617328 : return isl_ineq_separate;
4066 : }
4067 :
4068 30070352 : if (!isl_int_eq(tab->mat->row[row][1],
4069 : tab->mat->row[row][off + tab->n_dead + pos]))
4070 9281613 : return isl_ineq_separate;
4071 :
4072 41577478 : pos = isl_seq_first_non_zero(
4073 20788739 : tab->mat->row[row] + off + tab->n_dead + pos + 1,
4074 20788739 : tab->n_col - tab->n_dead - pos - 1);
4075 :
4076 20788739 : 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 18491485102 : enum isl_ineq_type isl_tab_ineq_type(struct isl_tab *tab, isl_int *ineq)
4088 : {
4089 18491485102 : enum isl_ineq_type type = isl_ineq_error;
4090 18491485102 : struct isl_tab_undo *snap = NULL;
4091 : int con;
4092 : int row;
4093 :
4094 18491485102 : if (!tab)
4095 0 : return isl_ineq_error;
4096 :
4097 18491485102 : if (isl_tab_extend_cons(tab, 1) < 0)
4098 0 : return isl_ineq_error;
4099 :
4100 18491485102 : snap = isl_tab_snap(tab);
4101 :
4102 18491485102 : con = isl_tab_add_row(tab, ineq);
4103 18491485102 : if (con < 0)
4104 0 : goto error;
4105 :
4106 18491485102 : row = tab->con[con].index;
4107 18491485102 : if (isl_tab_row_is_redundant(tab, row))
4108 0 : type = isl_ineq_redundant;
4109 25615972940 : else if (isl_int_is_neg(tab->mat->row[row][1]) &&
4110 7207667426 : (tab->rational ||
4111 83179588 : isl_int_abs_ge(tab->mat->row[row][1],
4112 7122673533 : tab->mat->row[row][0]))) {
4113 7122673533 : int nonneg = at_least_zero(tab, &tab->con[con]);
4114 7122673533 : if (nonneg < 0)
4115 0 : goto error;
4116 7122673533 : if (nonneg)
4117 23640355 : type = isl_ineq_cut;
4118 : else
4119 7099033178 : type = separation_type(tab, row);
4120 : } else {
4121 11368811569 : int red = con_is_redundant(tab, &tab->con[con]);
4122 11368811569 : if (red < 0)
4123 0 : goto error;
4124 11368811569 : if (!red)
4125 37976953 : type = isl_ineq_cut;
4126 : else
4127 11330834616 : type = isl_ineq_redundant;
4128 : }
4129 :
4130 18491485102 : if (isl_tab_rollback(tab, snap))
4131 0 : return isl_ineq_error;
4132 18491485102 : return type;
4133 : error:
4134 0 : return isl_ineq_error;
4135 : }
4136 :
4137 1383503511 : isl_stat isl_tab_track_bmap(struct isl_tab *tab, __isl_take isl_basic_map *bmap)
4138 : {
4139 1383503511 : bmap = isl_basic_map_cow(bmap);
4140 1383503511 : if (!tab || !bmap)
4141 : goto error;
4142 :
4143 1383503511 : if (tab->empty) {
4144 1323103687 : bmap = isl_basic_map_set_to_empty(bmap);
4145 1323103687 : if (!bmap)
4146 0 : goto error;
4147 1323103687 : tab->bmap = bmap;
4148 1323103687 : return isl_stat_ok;
4149 : }
4150 :
4151 60399824 : isl_assert(tab->mat->ctx, tab->n_eq == bmap->n_eq, goto error);
4152 60399824 : isl_assert(tab->mat->ctx,
4153 : tab->n_con == bmap->n_eq + bmap->n_ineq, goto error);
4154 :
4155 60399824 : tab->bmap = bmap;
4156 :
4157 60399824 : 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 1105725 : __isl_keep isl_basic_set *isl_tab_peek_bset(struct isl_tab *tab)
4169 : {
4170 1105725 : if (!tab)
4171 0 : return NULL;
4172 :
4173 1105725 : 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 : }
|