/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_tab_pip.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2008-2009 Katholieke Universiteit Leuven |
3 | | * Copyright 2010 INRIA Saclay |
4 | | * Copyright 2016-2017 Sven Verdoolaege |
5 | | * |
6 | | * Use of this software is governed by the MIT license |
7 | | * |
8 | | * Written by Sven Verdoolaege, K.U.Leuven, Departement |
9 | | * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium |
10 | | * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, |
11 | | * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France |
12 | | */ |
13 | | |
14 | | #include <isl_ctx_private.h> |
15 | | #include "isl_map_private.h" |
16 | | #include <isl_seq.h> |
17 | | #include "isl_tab.h" |
18 | | #include "isl_sample.h" |
19 | | #include <isl_mat_private.h> |
20 | | #include <isl_vec_private.h> |
21 | | #include <isl_aff_private.h> |
22 | | #include <isl_constraint_private.h> |
23 | | #include <isl_options_private.h> |
24 | | #include <isl_config.h> |
25 | | |
26 | | #include <bset_to_bmap.c> |
27 | | |
28 | | /* |
29 | | * The implementation of parametric integer linear programming in this file |
30 | | * was inspired by the paper "Parametric Integer Programming" and the |
31 | | * report "Solving systems of affine (in)equalities" by Paul Feautrier |
32 | | * (and others). |
33 | | * |
34 | | * The strategy used for obtaining a feasible solution is different |
35 | | * from the one used in isl_tab.c. In particular, in isl_tab.c, |
36 | | * upon finding a constraint that is not yet satisfied, we pivot |
37 | | * in a row that increases the constant term of the row holding the |
38 | | * constraint, making sure the sample solution remains feasible |
39 | | * for all the constraints it already satisfied. |
40 | | * Here, we always pivot in the row holding the constraint, |
41 | | * choosing a column that induces the lexicographically smallest |
42 | | * increment to the sample solution. |
43 | | * |
44 | | * By starting out from a sample value that is lexicographically |
45 | | * smaller than any integer point in the problem space, the first |
46 | | * feasible integer sample point we find will also be the lexicographically |
47 | | * smallest. If all variables can be assumed to be non-negative, |
48 | | * then the initial sample value may be chosen equal to zero. |
49 | | * However, we will not make this assumption. Instead, we apply |
50 | | * the "big parameter" trick. Any variable x is then not directly |
51 | | * used in the tableau, but instead it is represented by another |
52 | | * variable x' = M + x, where M is an arbitrarily large (positive) |
53 | | * value. x' is therefore always non-negative, whatever the value of x. |
54 | | * Taking as initial sample value x' = 0 corresponds to x = -M, |
55 | | * which is always smaller than any possible value of x. |
56 | | * |
57 | | * The big parameter trick is used in the main tableau and |
58 | | * also in the context tableau if isl_context_lex is used. |
59 | | * In this case, each tableaus has its own big parameter. |
60 | | * Before doing any real work, we check if all the parameters |
61 | | * happen to be non-negative. If so, we drop the column corresponding |
62 | | * to M from the initial context tableau. |
63 | | * If isl_context_gbr is used, then the big parameter trick is only |
64 | | * used in the main tableau. |
65 | | */ |
66 | | |
67 | | struct isl_context; |
68 | | struct isl_context_op { |
69 | | /* detect nonnegative parameters in context and mark them in tab */ |
70 | | struct isl_tab *(*detect_nonnegative_parameters)( |
71 | | struct isl_context *context, struct isl_tab *tab); |
72 | | /* return temporary reference to basic set representation of context */ |
73 | | struct isl_basic_set *(*peek_basic_set)(struct isl_context *context); |
74 | | /* return temporary reference to tableau representation of context */ |
75 | | struct isl_tab *(*peek_tab)(struct isl_context *context); |
76 | | /* add equality; check is 1 if eq may not be valid; |
77 | | * update is 1 if we may want to call ineq_sign on context later. |
78 | | */ |
79 | | void (*add_eq)(struct isl_context *context, isl_int *eq, |
80 | | int check, int update); |
81 | | /* add inequality; check is 1 if ineq may not be valid; |
82 | | * update is 1 if we may want to call ineq_sign on context later. |
83 | | */ |
84 | | void (*add_ineq)(struct isl_context *context, isl_int *ineq, |
85 | | int check, int update); |
86 | | /* check sign of ineq based on previous information. |
87 | | * strict is 1 if saturation should be treated as a positive sign. |
88 | | */ |
89 | | enum isl_tab_row_sign (*ineq_sign)(struct isl_context *context, |
90 | | isl_int *ineq, int strict); |
91 | | /* check if inequality maintains feasibility */ |
92 | | int (*test_ineq)(struct isl_context *context, isl_int *ineq); |
93 | | /* return index of a div that corresponds to "div" */ |
94 | | int (*get_div)(struct isl_context *context, struct isl_tab *tab, |
95 | | struct isl_vec *div); |
96 | | /* insert div "div" to context at "pos" and return non-negativity */ |
97 | | isl_bool (*insert_div)(struct isl_context *context, int pos, |
98 | | __isl_keep isl_vec *div); |
99 | | int (*detect_equalities)(struct isl_context *context, |
100 | | struct isl_tab *tab); |
101 | | /* return row index of "best" split */ |
102 | | int (*best_split)(struct isl_context *context, struct isl_tab *tab); |
103 | | /* check if context has already been determined to be empty */ |
104 | | int (*is_empty)(struct isl_context *context); |
105 | | /* check if context is still usable */ |
106 | | int (*is_ok)(struct isl_context *context); |
107 | | /* save a copy/snapshot of context */ |
108 | | void *(*save)(struct isl_context *context); |
109 | | /* restore saved context */ |
110 | | void (*restore)(struct isl_context *context, void *); |
111 | | /* discard saved context */ |
112 | | void (*discard)(void *); |
113 | | /* invalidate context */ |
114 | | void (*invalidate)(struct isl_context *context); |
115 | | /* free context */ |
116 | | __isl_null struct isl_context *(*free)(struct isl_context *context); |
117 | | }; |
118 | | |
119 | | /* Shared parts of context representation. |
120 | | * |
121 | | * "n_unknown" is the number of final unknown integer divisions |
122 | | * in the input domain. |
123 | | */ |
124 | | struct isl_context { |
125 | | struct isl_context_op *op; |
126 | | int n_unknown; |
127 | | }; |
128 | | |
129 | | struct isl_context_lex { |
130 | | struct isl_context context; |
131 | | struct isl_tab *tab; |
132 | | }; |
133 | | |
134 | | /* A stack (linked list) of solutions of subtrees of the search space. |
135 | | * |
136 | | * "ma" describes the solution as a function of "dom". |
137 | | * In particular, the domain space of "ma" is equal to the space of "dom". |
138 | | * |
139 | | * If "ma" is NULL, then there is no solution on "dom". |
140 | | */ |
141 | | struct isl_partial_sol { |
142 | | int level; |
143 | | struct isl_basic_set *dom; |
144 | | isl_multi_aff *ma; |
145 | | |
146 | | struct isl_partial_sol *next; |
147 | | }; |
148 | | |
149 | | struct isl_sol; |
150 | | struct isl_sol_callback { |
151 | | struct isl_tab_callback callback; |
152 | | struct isl_sol *sol; |
153 | | }; |
154 | | |
155 | | /* isl_sol is an interface for constructing a solution to |
156 | | * a parametric integer linear programming problem. |
157 | | * Every time the algorithm reaches a state where a solution |
158 | | * can be read off from the tableau, the function "add" is called |
159 | | * on the isl_sol passed to find_solutions_main. In a state where |
160 | | * the tableau is empty, "add_empty" is called instead. |
161 | | * "free" is called to free the implementation specific fields, if any. |
162 | | * |
163 | | * "error" is set if some error has occurred. This flag invalidates |
164 | | * the remainder of the data structure. |
165 | | * If "rational" is set, then a rational optimization is being performed. |
166 | | * "level" is the current level in the tree with nodes for each |
167 | | * split in the context. |
168 | | * If "max" is set, then a maximization problem is being solved, rather than |
169 | | * a minimization problem, which means that the variables in the |
170 | | * tableau have value "M - x" rather than "M + x". |
171 | | * "n_out" is the number of output dimensions in the input. |
172 | | * "space" is the space in which the solution (and also the input) lives. |
173 | | * |
174 | | * The context tableau is owned by isl_sol and is updated incrementally. |
175 | | * |
176 | | * There are currently two implementations of this interface, |
177 | | * isl_sol_map, which simply collects the solutions in an isl_map |
178 | | * and (optionally) the parts of the context where there is no solution |
179 | | * in an isl_set, and |
180 | | * isl_sol_pma, which collects an isl_pw_multi_aff instead. |
181 | | */ |
182 | | struct isl_sol { |
183 | | int error; |
184 | | int rational; |
185 | | int level; |
186 | | int max; |
187 | | int n_out; |
188 | | isl_space *space; |
189 | | struct isl_context *context; |
190 | | struct isl_partial_sol *partial; |
191 | | void (*add)(struct isl_sol *sol, |
192 | | __isl_take isl_basic_set *dom, __isl_take isl_multi_aff *ma); |
193 | | void (*add_empty)(struct isl_sol *sol, struct isl_basic_set *bset); |
194 | | void (*free)(struct isl_sol *sol); |
195 | | struct isl_sol_callback dec_level; |
196 | | }; |
197 | | |
198 | | static void sol_free(struct isl_sol *sol) |
199 | 7.85k | { |
200 | 7.85k | struct isl_partial_sol *partial, *next; |
201 | 7.85k | if (!sol) |
202 | 0 | return; |
203 | 7.85k | for (partial = sol->partial; partial; partial = next0 ) { |
204 | 0 | next = partial->next; |
205 | 0 | isl_basic_set_free(partial->dom); |
206 | 0 | isl_multi_aff_free(partial->ma); |
207 | 0 | free(partial); |
208 | 0 | } |
209 | 7.85k | isl_space_free(sol->space); |
210 | 7.85k | if (sol->context) |
211 | 7.85k | sol->context->op->free(sol->context); |
212 | 7.85k | sol->free(sol); |
213 | 7.85k | free(sol); |
214 | 7.85k | } |
215 | | |
216 | | /* Push a partial solution represented by a domain and function "ma" |
217 | | * onto the stack of partial solutions. |
218 | | * If "ma" is NULL, then "dom" represents a part of the domain |
219 | | * with no solution. |
220 | | */ |
221 | | static void sol_push_sol(struct isl_sol *sol, |
222 | | __isl_take isl_basic_set *dom, __isl_take isl_multi_aff *ma) |
223 | 9.69k | { |
224 | 9.69k | struct isl_partial_sol *partial; |
225 | 9.69k | |
226 | 9.69k | if (sol->error || !dom) |
227 | 0 | goto error; |
228 | 9.69k | |
229 | 9.69k | partial = isl_alloc_type(dom->ctx, struct isl_partial_sol); |
230 | 9.69k | if (!partial) |
231 | 0 | goto error; |
232 | 9.69k | |
233 | 9.69k | partial->level = sol->level; |
234 | 9.69k | partial->dom = dom; |
235 | 9.69k | partial->ma = ma; |
236 | 9.69k | partial->next = sol->partial; |
237 | 9.69k | |
238 | 9.69k | sol->partial = partial; |
239 | 9.69k | |
240 | 9.69k | return; |
241 | 0 | error: |
242 | 0 | isl_basic_set_free(dom); |
243 | 0 | isl_multi_aff_free(ma); |
244 | 0 | sol->error = 1; |
245 | 0 | } |
246 | | |
247 | | /* Check that the final columns of "M", starting at "first", are zero. |
248 | | */ |
249 | | static isl_stat check_final_columns_are_zero(__isl_keep isl_mat *M, |
250 | | unsigned first) |
251 | 7.51k | { |
252 | 7.51k | int i; |
253 | 7.51k | unsigned rows, cols, n; |
254 | 7.51k | |
255 | 7.51k | if (!M) |
256 | 0 | return isl_stat_error; |
257 | 7.51k | rows = isl_mat_rows(M); |
258 | 7.51k | cols = isl_mat_cols(M); |
259 | 7.51k | n = cols - first; |
260 | 32.5k | for (i = 0; i < rows; ++i24.9k ) |
261 | 24.9k | if (isl_seq_first_non_zero(M->row[i] + first, n) != -1) |
262 | 24.9k | isl_die0 (isl_mat_get_ctx(M), isl_error_internal, |
263 | 7.51k | "final columns should be zero", |
264 | 7.51k | return isl_stat_error); |
265 | 7.51k | return isl_stat_ok; |
266 | 7.51k | } |
267 | | |
268 | | /* Set the affine expressions in "ma" according to the rows in "M", which |
269 | | * are defined over the local space "ls". |
270 | | * The matrix "M" may have extra (zero) columns beyond the number |
271 | | * of variables in "ls". |
272 | | */ |
273 | | static __isl_give isl_multi_aff *set_from_affine_matrix( |
274 | | __isl_take isl_multi_aff *ma, __isl_take isl_local_space *ls, |
275 | | __isl_take isl_mat *M) |
276 | 7.51k | { |
277 | 7.51k | int i, dim; |
278 | 7.51k | isl_aff *aff; |
279 | 7.51k | |
280 | 7.51k | if (!ma || !ls || !M) |
281 | 0 | goto error; |
282 | 7.51k | |
283 | 7.51k | dim = isl_local_space_dim(ls, isl_dim_all); |
284 | 7.51k | if (check_final_columns_are_zero(M, 1 + dim) < 0) |
285 | 0 | goto error; |
286 | 24.9k | for (i = 1; 7.51k i < M->n_row; ++i17.4k ) { |
287 | 17.4k | aff = isl_aff_alloc(isl_local_space_copy(ls)); |
288 | 17.4k | if (aff) { |
289 | 17.4k | isl_int_set(aff->v->el[0], M->row[0][0]); |
290 | 17.4k | isl_seq_cpy(aff->v->el + 1, M->row[i], 1 + dim); |
291 | 17.4k | } |
292 | 17.4k | aff = isl_aff_normalize(aff); |
293 | 17.4k | ma = isl_multi_aff_set_aff(ma, i - 1, aff); |
294 | 17.4k | } |
295 | 7.51k | isl_local_space_free(ls); |
296 | 7.51k | isl_mat_free(M); |
297 | 7.51k | |
298 | 7.51k | return ma; |
299 | 0 | error: |
300 | 0 | isl_local_space_free(ls); |
301 | 0 | isl_mat_free(M); |
302 | 0 | isl_multi_aff_free(ma); |
303 | 0 | return NULL; |
304 | 7.51k | } |
305 | | |
306 | | /* Push a partial solution represented by a domain and mapping M |
307 | | * onto the stack of partial solutions. |
308 | | * |
309 | | * The affine matrix "M" maps the dimensions of the context |
310 | | * to the output variables. Convert it into an isl_multi_aff and |
311 | | * then call sol_push_sol. |
312 | | * |
313 | | * Note that the description of the initial context may have involved |
314 | | * existentially quantified variables, in which case they also appear |
315 | | * in "dom". These need to be removed before creating the affine |
316 | | * expression because an affine expression cannot be defined in terms |
317 | | * of existentially quantified variables without a known representation. |
318 | | * Since newly added integer divisions are inserted before these |
319 | | * existentially quantified variables, they are still in the final |
320 | | * positions and the corresponding final columns of "M" are zero |
321 | | * because align_context_divs adds the existentially quantified |
322 | | * variables of the context to the main tableau without any constraints and |
323 | | * any equality constraints that are added later on can only serve |
324 | | * to eliminate these existentially quantified variables. |
325 | | */ |
326 | | static void sol_push_sol_mat(struct isl_sol *sol, |
327 | | __isl_take isl_basic_set *dom, __isl_take isl_mat *M) |
328 | 7.51k | { |
329 | 7.51k | isl_local_space *ls; |
330 | 7.51k | isl_multi_aff *ma; |
331 | 7.51k | int n_div, n_known; |
332 | 7.51k | |
333 | 7.51k | n_div = isl_basic_set_dim(dom, isl_dim_div); |
334 | 7.51k | n_known = n_div - sol->context->n_unknown; |
335 | 7.51k | |
336 | 7.51k | ma = isl_multi_aff_alloc(isl_space_copy(sol->space)); |
337 | 7.51k | ls = isl_basic_set_get_local_space(dom); |
338 | 7.51k | ls = isl_local_space_drop_dims(ls, isl_dim_div, |
339 | 7.51k | n_known, n_div - n_known); |
340 | 7.51k | ma = set_from_affine_matrix(ma, ls, M); |
341 | 7.51k | |
342 | 7.51k | if (!ma) |
343 | 0 | dom = isl_basic_set_free(dom); |
344 | 7.51k | sol_push_sol(sol, dom, ma); |
345 | 7.51k | } |
346 | | |
347 | | /* Pop one partial solution from the partial solution stack and |
348 | | * pass it on to sol->add or sol->add_empty. |
349 | | */ |
350 | | static void sol_pop_one(struct isl_sol *sol) |
351 | 9.57k | { |
352 | 9.57k | struct isl_partial_sol *partial; |
353 | 9.57k | |
354 | 9.57k | partial = sol->partial; |
355 | 9.57k | sol->partial = partial->next; |
356 | 9.57k | |
357 | 9.57k | if (partial->ma) |
358 | 7.38k | sol->add(sol, partial->dom, partial->ma); |
359 | 2.18k | else |
360 | 2.18k | sol->add_empty(sol, partial->dom); |
361 | 9.57k | free(partial); |
362 | 9.57k | } |
363 | | |
364 | | /* Return a fresh copy of the domain represented by the context tableau. |
365 | | */ |
366 | | static struct isl_basic_set *sol_domain(struct isl_sol *sol) |
367 | 9.82k | { |
368 | 9.82k | struct isl_basic_set *bset; |
369 | 9.82k | |
370 | 9.82k | if (sol->error) |
371 | 0 | return NULL; |
372 | 9.82k | |
373 | 9.82k | bset = isl_basic_set_dup(sol->context->op->peek_basic_set(sol->context)); |
374 | 9.82k | bset = isl_basic_set_update_from_tab(bset, |
375 | 9.82k | sol->context->op->peek_tab(sol->context)); |
376 | 9.82k | |
377 | 9.82k | return bset; |
378 | 9.82k | } |
379 | | |
380 | | /* Check whether two partial solutions have the same affine expressions. |
381 | | */ |
382 | | static isl_bool same_solution(struct isl_partial_sol *s1, |
383 | | struct isl_partial_sol *s2) |
384 | 2.10k | { |
385 | 2.10k | if (!s1->ma != !s2->ma) |
386 | 1.86k | return isl_bool_false; |
387 | 235 | if (!s1->ma) |
388 | 0 | return isl_bool_true; |
389 | 235 | |
390 | 235 | return isl_multi_aff_plain_is_equal(s1->ma, s2->ma); |
391 | 235 | } |
392 | | |
393 | | /* Swap the initial two partial solutions in "sol". |
394 | | * |
395 | | * That is, go from |
396 | | * |
397 | | * sol->partial = p1; p1->next = p2; p2->next = p3 |
398 | | * |
399 | | * to |
400 | | * |
401 | | * sol->partial = p2; p2->next = p1; p1->next = p3 |
402 | | */ |
403 | | static void swap_initial(struct isl_sol *sol) |
404 | 93 | { |
405 | 93 | struct isl_partial_sol *partial; |
406 | 93 | |
407 | 93 | partial = sol->partial; |
408 | 93 | sol->partial = partial->next; |
409 | 93 | partial->next = partial->next->next; |
410 | 93 | sol->partial->next = partial; |
411 | 93 | } |
412 | | |
413 | | /* Combine the initial two partial solution of "sol" into |
414 | | * a partial solution with the current context domain of "sol" and |
415 | | * the function description of the second partial solution in the list. |
416 | | * The level of the new partial solution is set to the current level. |
417 | | * |
418 | | * That is, the first two partial solutions (D1,M1) and (D2,M2) are |
419 | | * replaced by (D,M2), where D is the domain of "sol", which is assumed |
420 | | * to be the union of D1 and D2, while M1 is assumed to be equal to M2 |
421 | | * (at least on D1). |
422 | | */ |
423 | | static isl_stat combine_initial_into_second(struct isl_sol *sol) |
424 | 126 | { |
425 | 126 | struct isl_partial_sol *partial; |
426 | 126 | isl_basic_set *bset; |
427 | 126 | |
428 | 126 | partial = sol->partial; |
429 | 126 | |
430 | 126 | bset = sol_domain(sol); |
431 | 126 | isl_basic_set_free(partial->next->dom); |
432 | 126 | partial->next->dom = bset; |
433 | 126 | partial->next->level = sol->level; |
434 | 126 | |
435 | 126 | if (!bset) |
436 | 0 | return isl_stat_error; |
437 | 126 | |
438 | 126 | sol->partial = partial->next; |
439 | 126 | isl_basic_set_free(partial->dom); |
440 | 126 | isl_multi_aff_free(partial->ma); |
441 | 126 | free(partial); |
442 | 126 | |
443 | 126 | return isl_stat_ok; |
444 | 126 | } |
445 | | |
446 | | /* Are "ma1" and "ma2" equal to each other on "dom"? |
447 | | * |
448 | | * Combine "ma1" and "ma2" with "dom" and check if the results are the same. |
449 | | * "dom" may have existentially quantified variables. Eliminate them first |
450 | | * as otherwise they would have to be eliminated twice, in a more complicated |
451 | | * context. |
452 | | */ |
453 | | static isl_bool equal_on_domain(__isl_keep isl_multi_aff *ma1, |
454 | | __isl_keep isl_multi_aff *ma2, __isl_keep isl_basic_set *dom) |
455 | 410 | { |
456 | 410 | isl_set *set; |
457 | 410 | isl_pw_multi_aff *pma1, *pma2; |
458 | 410 | isl_bool equal; |
459 | 410 | |
460 | 410 | set = isl_basic_set_compute_divs(isl_basic_set_copy(dom)); |
461 | 410 | pma1 = isl_pw_multi_aff_alloc(isl_set_copy(set), |
462 | 410 | isl_multi_aff_copy(ma1)); |
463 | 410 | pma2 = isl_pw_multi_aff_alloc(set, isl_multi_aff_copy(ma2)); |
464 | 410 | equal = isl_pw_multi_aff_is_equal(pma1, pma2); |
465 | 410 | isl_pw_multi_aff_free(pma1); |
466 | 410 | isl_pw_multi_aff_free(pma2); |
467 | 410 | |
468 | 410 | return equal; |
469 | 410 | } |
470 | | |
471 | | /* The initial two partial solutions of "sol" are known to be at |
472 | | * the same level. |
473 | | * If they represent the same solution (on different parts of the domain), |
474 | | * then combine them into a single solution at the current level. |
475 | | * Otherwise, pop them both. |
476 | | * |
477 | | * Even if the two partial solution are not obviously the same, |
478 | | * one may still be a simplification of the other over its own domain. |
479 | | * Also check if the two sets of affine functions are equal when |
480 | | * restricted to one of the domains. If so, combine the two |
481 | | * using the set of affine functions on the other domain. |
482 | | * That is, for two partial solutions (D1,M1) and (D2,M2), |
483 | | * if M1 = M2 on D1, then the pair of partial solutions can |
484 | | * be replaced by (D1+D2,M2) and similarly when M1 = M2 on D2. |
485 | | */ |
486 | | static isl_stat combine_initial_if_equal(struct isl_sol *sol) |
487 | 2.10k | { |
488 | 2.10k | struct isl_partial_sol *partial; |
489 | 2.10k | isl_bool same; |
490 | 2.10k | |
491 | 2.10k | partial = sol->partial; |
492 | 2.10k | |
493 | 2.10k | same = same_solution(partial, partial->next); |
494 | 2.10k | if (same < 0) |
495 | 0 | return isl_stat_error; |
496 | 2.10k | if (same) |
497 | 27 | return combine_initial_into_second(sol); |
498 | 2.07k | if (partial->ma && partial->next->ma223 ) { |
499 | 208 | same = equal_on_domain(partial->ma, partial->next->ma, |
500 | 208 | partial->dom); |
501 | 208 | if (same < 0) |
502 | 0 | return isl_stat_error; |
503 | 208 | if (same) |
504 | 6 | return combine_initial_into_second(sol); |
505 | 202 | same = equal_on_domain(partial->ma, partial->next->ma, |
506 | 202 | partial->next->dom); |
507 | 202 | if (same) { |
508 | 93 | swap_initial(sol); |
509 | 93 | return combine_initial_into_second(sol); |
510 | 93 | } |
511 | 1.97k | } |
512 | 1.97k | |
513 | 1.97k | sol_pop_one(sol); |
514 | 1.97k | sol_pop_one(sol); |
515 | 1.97k | |
516 | 1.97k | return isl_stat_ok; |
517 | 1.97k | } |
518 | | |
519 | | /* Pop all solutions from the partial solution stack that were pushed onto |
520 | | * the stack at levels that are deeper than the current level. |
521 | | * If the two topmost elements on the stack have the same level |
522 | | * and represent the same solution, then their domains are combined. |
523 | | * This combined domain is the same as the current context domain |
524 | | * as sol_pop is called each time we move back to a higher level. |
525 | | * If the outer level (0) has been reached, then all partial solutions |
526 | | * at the current level are also popped off. |
527 | | */ |
528 | | static void sol_pop(struct isl_sol *sol) |
529 | 9.58k | { |
530 | 9.58k | struct isl_partial_sol *partial; |
531 | 9.58k | |
532 | 9.58k | if (sol->error) |
533 | 6 | return; |
534 | 9.57k | |
535 | 9.57k | partial = sol->partial; |
536 | 9.57k | if (!partial) |
537 | 2.04k | return; |
538 | 7.52k | |
539 | 7.52k | if (partial->level == 0 && sol->level == 03.30k ) { |
540 | 6.60k | for (partial = sol->partial; partial; partial = sol->partial3.30k ) |
541 | 3.30k | sol_pop_one(sol); |
542 | 3.30k | return; |
543 | 3.30k | } |
544 | 4.22k | |
545 | 4.22k | if (partial->level <= sol->level) |
546 | 7 | return; |
547 | 4.21k | |
548 | 4.21k | if (partial->next && partial->next->level == partial->level2.24k ) { |
549 | 2.10k | if (combine_initial_if_equal(sol) < 0) |
550 | 0 | goto error; |
551 | 2.11k | } else |
552 | 2.11k | sol_pop_one(sol); |
553 | 4.21k | |
554 | 4.21k | if (sol->level == 0) { |
555 | 2.23k | for (partial = sol->partial; partial; partial = sol->partial201 ) |
556 | 201 | sol_pop_one(sol); |
557 | 2.03k | return; |
558 | 2.03k | } |
559 | 2.18k | |
560 | 2.18k | if (0) |
561 | 0 | error: sol->error = 1; |
562 | 2.18k | } |
563 | | |
564 | | static void sol_dec_level(struct isl_sol *sol) |
565 | 2.41k | { |
566 | 2.41k | if (sol->error) |
567 | 0 | return; |
568 | 2.41k | |
569 | 2.41k | sol->level--; |
570 | 2.41k | |
571 | 2.41k | sol_pop(sol); |
572 | 2.41k | } |
573 | | |
574 | | static isl_stat sol_dec_level_wrap(struct isl_tab_callback *cb) |
575 | 2.41k | { |
576 | 2.41k | struct isl_sol_callback *callback = (struct isl_sol_callback *)cb; |
577 | 2.41k | |
578 | 2.41k | sol_dec_level(callback->sol); |
579 | 2.41k | |
580 | 2.41k | return callback->sol->error ? isl_stat_error0 : isl_stat_ok; |
581 | 2.41k | } |
582 | | |
583 | | /* Move down to next level and push callback onto context tableau |
584 | | * to decrease the level again when it gets rolled back across |
585 | | * the current state. That is, dec_level will be called with |
586 | | * the context tableau in the same state as it is when inc_level |
587 | | * is called. |
588 | | */ |
589 | | static void sol_inc_level(struct isl_sol *sol) |
590 | 21.7k | { |
591 | 21.7k | struct isl_tab *tab; |
592 | 21.7k | |
593 | 21.7k | if (sol->error) |
594 | 0 | return; |
595 | 21.7k | |
596 | 21.7k | sol->level++; |
597 | 21.7k | tab = sol->context->op->peek_tab(sol->context); |
598 | 21.7k | if (isl_tab_push_callback(tab, &sol->dec_level.callback) < 0) |
599 | 0 | sol->error = 1; |
600 | 21.7k | } |
601 | | |
602 | | static void scale_rows(struct isl_mat *mat, isl_int m, int n_row) |
603 | 17.4k | { |
604 | 17.4k | int i; |
605 | 17.4k | |
606 | 17.4k | if (isl_int_is_one(m)) |
607 | 17.4k | return17.4k ; |
608 | 40 | |
609 | 119 | for (i = 0; 40 i < n_row; ++i79 ) |
610 | 79 | isl_seq_scale(mat->row[i], mat->row[i], m, mat->n_col); |
611 | 40 | } |
612 | | |
613 | | /* Add the solution identified by the tableau and the context tableau. |
614 | | * |
615 | | * The layout of the variables is as follows. |
616 | | * tab->n_var is equal to the total number of variables in the input |
617 | | * map (including divs that were copied from the context) |
618 | | * + the number of extra divs constructed |
619 | | * Of these, the first tab->n_param and the last tab->n_div variables |
620 | | * correspond to the variables in the context, i.e., |
621 | | * tab->n_param + tab->n_div = context_tab->n_var |
622 | | * tab->n_param is equal to the number of parameters and input |
623 | | * dimensions in the input map |
624 | | * tab->n_div is equal to the number of divs in the context |
625 | | * |
626 | | * If there is no solution, then call add_empty with a basic set |
627 | | * that corresponds to the context tableau. (If add_empty is NULL, |
628 | | * then do nothing). |
629 | | * |
630 | | * If there is a solution, then first construct a matrix that maps |
631 | | * all dimensions of the context to the output variables, i.e., |
632 | | * the output dimensions in the input map. |
633 | | * The divs in the input map (if any) that do not correspond to any |
634 | | * div in the context do not appear in the solution. |
635 | | * The algorithm will make sure that they have an integer value, |
636 | | * but these values themselves are of no interest. |
637 | | * We have to be careful not to drop or rearrange any divs in the |
638 | | * context because that would change the meaning of the matrix. |
639 | | * |
640 | | * To extract the value of the output variables, it should be noted |
641 | | * that we always use a big parameter M in the main tableau and so |
642 | | * the variable stored in this tableau is not an output variable x itself, but |
643 | | * x' = M + x (in case of minimization) |
644 | | * or |
645 | | * x' = M - x (in case of maximization) |
646 | | * If x' appears in a column, then its optimal value is zero, |
647 | | * which means that the optimal value of x is an unbounded number |
648 | | * (-M for minimization and M for maximization). |
649 | | * We currently assume that the output dimensions in the original map |
650 | | * are bounded, so this cannot occur. |
651 | | * Similarly, when x' appears in a row, then the coefficient of M in that |
652 | | * row is necessarily 1. |
653 | | * If the row in the tableau represents |
654 | | * d x' = c + d M + e(y) |
655 | | * then, in case of minimization, the corresponding row in the matrix |
656 | | * will be |
657 | | * a c + a e(y) |
658 | | * with a d = m, the (updated) common denominator of the matrix. |
659 | | * In case of maximization, the row will be |
660 | | * -a c - a e(y) |
661 | | */ |
662 | | static void sol_add(struct isl_sol *sol, struct isl_tab *tab) |
663 | 28.9k | { |
664 | 28.9k | struct isl_basic_set *bset = NULL; |
665 | 28.9k | struct isl_mat *mat = NULL; |
666 | 28.9k | unsigned off; |
667 | 28.9k | int row; |
668 | 28.9k | isl_int m; |
669 | 28.9k | |
670 | 28.9k | if (sol->error || !tab) |
671 | 0 | goto error; |
672 | 28.9k | |
673 | 28.9k | if (tab->empty && !sol->add_empty21.4k ) |
674 | 3.32k | return; |
675 | 25.6k | if (sol->context->op->is_empty(sol->context)) |
676 | 15.9k | return; |
677 | 9.70k | |
678 | 9.70k | bset = sol_domain(sol); |
679 | 9.70k | |
680 | 9.70k | if (tab->empty) { |
681 | 2.18k | sol_push_sol(sol, bset, NULL); |
682 | 2.18k | return; |
683 | 2.18k | } |
684 | 7.51k | |
685 | 7.51k | off = 2 + tab->M; |
686 | 7.51k | |
687 | 7.51k | mat = isl_mat_alloc(tab->mat->ctx, 1 + sol->n_out, |
688 | 7.51k | 1 + tab->n_param + tab->n_div); |
689 | 7.51k | if (!mat) |
690 | 0 | goto error; |
691 | 7.51k | |
692 | 7.51k | isl_int_init(m); |
693 | 7.51k | |
694 | 7.51k | isl_seq_clr(mat->row[0] + 1, mat->n_col - 1); |
695 | 7.51k | isl_int_set_si(mat->row[0][0], 1); |
696 | 25.0k | for (row = 0; row < sol->n_out; ++row17.4k ) { |
697 | 17.4k | int i = tab->n_param + row; |
698 | 17.4k | int r, j; |
699 | 17.4k | |
700 | 17.4k | isl_seq_clr(mat->row[1 + row], mat->n_col); |
701 | 17.4k | if (!tab->var[i].is_row) { |
702 | 6 | if (tab->M) |
703 | 6 | isl_die(mat->ctx, isl_error_invalid, |
704 | 6 | "unbounded optimum", goto error2); |
705 | 6 | continue0 ; |
706 | 17.4k | } |
707 | 17.4k | |
708 | 17.4k | r = tab->var[i].index; |
709 | 17.4k | if (tab->M && |
710 | 17.4k | isl_int_ne(tab->mat->row[r][2], tab->mat->row[r][0])) |
711 | 17.4k | isl_die0 (mat->ctx, isl_error_invalid, |
712 | 17.4k | "unbounded optimum", goto error2); |
713 | 17.4k | isl_int_gcd(m, mat->row[0][0], tab->mat->row[r][0]); |
714 | 17.4k | isl_int_divexact(m, tab->mat->row[r][0], m); |
715 | 17.4k | scale_rows(mat, m, 1 + row); |
716 | 17.4k | isl_int_divexact(m, mat->row[0][0], tab->mat->row[r][0]); |
717 | 17.4k | isl_int_mul(mat->row[1 + row][0], m, tab->mat->row[r][1]); |
718 | 95.8k | for (j = 0; j < tab->n_param; ++j78.3k ) { |
719 | 78.3k | int col; |
720 | 78.3k | if (tab->var[j].is_row) |
721 | 37.3k | continue; |
722 | 41.0k | col = tab->var[j].index; |
723 | 41.0k | isl_int_mul(mat->row[1 + row][1 + j], m, |
724 | 41.0k | tab->mat->row[r][off + col]); |
725 | 41.0k | } |
726 | 21.0k | for (j = 0; j < tab->n_div; ++j3.60k ) { |
727 | 3.60k | int col; |
728 | 3.60k | if (tab->var[tab->n_var - tab->n_div+j].is_row) |
729 | 650 | continue; |
730 | 2.95k | col = tab->var[tab->n_var - tab->n_div+j].index; |
731 | 2.95k | isl_int_mul(mat->row[1 + row][1 + tab->n_param + j], m, |
732 | 2.95k | tab->mat->row[r][off + col]); |
733 | 2.95k | } |
734 | 17.4k | if (sol->max) |
735 | 12.8k | isl_seq_neg(mat->row[1 + row], mat->row[1 + row], |
736 | 12.8k | mat->n_col); |
737 | 17.4k | } |
738 | 7.51k | |
739 | 7.51k | isl_int_clear7.51k (m); |
740 | 7.51k | |
741 | 7.51k | sol_push_sol_mat(sol, bset, mat); |
742 | 7.51k | return; |
743 | 6 | error2: |
744 | 6 | isl_int_clear(m); |
745 | 6 | error: |
746 | 6 | isl_basic_set_free(bset); |
747 | 6 | isl_mat_free(mat); |
748 | 6 | sol->error = 1; |
749 | 6 | } |
750 | | |
751 | | struct isl_sol_map { |
752 | | struct isl_sol sol; |
753 | | struct isl_map *map; |
754 | | struct isl_set *empty; |
755 | | }; |
756 | | |
757 | | static void sol_map_free(struct isl_sol *sol) |
758 | 3.64k | { |
759 | 3.64k | struct isl_sol_map *sol_map = (struct isl_sol_map *) sol; |
760 | 3.64k | isl_map_free(sol_map->map); |
761 | 3.64k | isl_set_free(sol_map->empty); |
762 | 3.64k | } |
763 | | |
764 | | /* This function is called for parts of the context where there is |
765 | | * no solution, with "bset" corresponding to the context tableau. |
766 | | * Simply add the basic set to the set "empty". |
767 | | */ |
768 | | static void sol_map_add_empty(struct isl_sol_map *sol, |
769 | | struct isl_basic_set *bset) |
770 | 2.30k | { |
771 | 2.30k | if (!bset || !sol->empty) |
772 | 0 | goto error; |
773 | 2.30k | |
774 | 2.30k | sol->empty = isl_set_grow(sol->empty, 1); |
775 | 2.30k | bset = isl_basic_set_simplify(bset); |
776 | 2.30k | bset = isl_basic_set_finalize(bset); |
777 | 2.30k | sol->empty = isl_set_add_basic_set(sol->empty, isl_basic_set_copy(bset)); |
778 | 2.30k | if (!sol->empty) |
779 | 0 | goto error; |
780 | 2.30k | isl_basic_set_free(bset); |
781 | 2.30k | return; |
782 | 0 | error: |
783 | 0 | isl_basic_set_free(bset); |
784 | 0 | sol->sol.error = 1; |
785 | 0 | } |
786 | | |
787 | | static void sol_map_add_empty_wrap(struct isl_sol *sol, |
788 | | struct isl_basic_set *bset) |
789 | 2.30k | { |
790 | 2.30k | sol_map_add_empty((struct isl_sol_map *)sol, bset); |
791 | 2.30k | } |
792 | | |
793 | | /* Given a basic set "dom" that represents the context and a tuple of |
794 | | * affine expressions "ma" defined over this domain, construct a basic map |
795 | | * that expresses this function on the domain. |
796 | | */ |
797 | | static void sol_map_add(struct isl_sol_map *sol, |
798 | | __isl_take isl_basic_set *dom, __isl_take isl_multi_aff *ma) |
799 | 3.43k | { |
800 | 3.43k | isl_basic_map *bmap; |
801 | 3.43k | |
802 | 3.43k | if (sol->sol.error || !dom || !ma) |
803 | 0 | goto error; |
804 | 3.43k | |
805 | 3.43k | bmap = isl_basic_map_from_multi_aff2(ma, sol->sol.rational); |
806 | 3.43k | bmap = isl_basic_map_intersect_domain(bmap, dom); |
807 | 3.43k | sol->map = isl_map_grow(sol->map, 1); |
808 | 3.43k | sol->map = isl_map_add_basic_map(sol->map, bmap); |
809 | 3.43k | if (!sol->map) |
810 | 0 | sol->sol.error = 1; |
811 | 3.43k | return; |
812 | 0 | error: |
813 | 0 | isl_basic_set_free(dom); |
814 | 0 | isl_multi_aff_free(ma); |
815 | 0 | sol->sol.error = 1; |
816 | 0 | } |
817 | | |
818 | | static void sol_map_add_wrap(struct isl_sol *sol, |
819 | | __isl_take isl_basic_set *dom, __isl_take isl_multi_aff *ma) |
820 | 3.43k | { |
821 | 3.43k | sol_map_add((struct isl_sol_map *)sol, dom, ma); |
822 | 3.43k | } |
823 | | |
824 | | |
825 | | /* Store the "parametric constant" of row "row" of tableau "tab" in "line", |
826 | | * i.e., the constant term and the coefficients of all variables that |
827 | | * appear in the context tableau. |
828 | | * Note that the coefficient of the big parameter M is NOT copied. |
829 | | * The context tableau may not have a big parameter and even when it |
830 | | * does, it is a different big parameter. |
831 | | */ |
832 | | static void get_row_parameter_line(struct isl_tab *tab, int row, isl_int *line) |
833 | 26.8k | { |
834 | 26.8k | int i; |
835 | 26.8k | unsigned off = 2 + tab->M; |
836 | 26.8k | |
837 | 26.8k | isl_int_set(line[0], tab->mat->row[row][1]); |
838 | 158k | for (i = 0; i < tab->n_param; ++i131k ) { |
839 | 131k | if (tab->var[i].is_row) |
840 | 131k | isl_int_set_si64.0k (line[1 + i], 0); |
841 | 131k | else { |
842 | 67.8k | int col = tab->var[i].index; |
843 | 67.8k | isl_int_set(line[1 + i], tab->mat->row[row][off + col]); |
844 | 67.8k | } |
845 | 131k | } |
846 | 35.6k | for (i = 0; i < tab->n_div; ++i8.85k ) { |
847 | 8.85k | if (tab->var[tab->n_var - tab->n_div + i].is_row) |
848 | 8.85k | isl_int_set_si2.74k (line[1 + tab->n_param + i], 0); |
849 | 8.85k | else { |
850 | 6.10k | int col = tab->var[tab->n_var - tab->n_div + i].index; |
851 | 6.10k | isl_int_set(line[1 + tab->n_param + i], |
852 | 6.10k | tab->mat->row[row][off + col]); |
853 | 6.10k | } |
854 | 8.85k | } |
855 | 26.8k | } |
856 | | |
857 | | /* Check if rows "row1" and "row2" have identical "parametric constants", |
858 | | * as explained above. |
859 | | * In this case, we also insist that the coefficients of the big parameter |
860 | | * be the same as the values of the constants will only be the same |
861 | | * if these coefficients are also the same. |
862 | | */ |
863 | | static int identical_parameter_line(struct isl_tab *tab, int row1, int row2) |
864 | 77.2k | { |
865 | 77.2k | int i; |
866 | 77.2k | unsigned off = 2 + tab->M; |
867 | 77.2k | |
868 | 77.2k | if (isl_int_ne(tab->mat->row[row1][1], tab->mat->row[row2][1])) |
869 | 77.2k | return 070.0k ; |
870 | 7.15k | |
871 | 7.15k | if (tab->M && isl_int_ne(tab->mat->row[row1][2], |
872 | 7.15k | tab->mat->row[row2][2])) |
873 | 7.15k | return 03.18k ; |
874 | 3.97k | |
875 | 10.2k | for (i = 0; 3.97k i < tab->n_param + tab->n_div; ++i6.22k ) { |
876 | 10.0k | int pos = i < tab->n_param ? i9.57k : |
877 | 10.0k | tab->n_var - tab->n_div + i - tab->n_param458 ; |
878 | 10.0k | int col; |
879 | 10.0k | |
880 | 10.0k | if (tab->var[pos].is_row) |
881 | 3.03k | continue; |
882 | 6.99k | col = tab->var[pos].index; |
883 | 6.99k | if (isl_int_ne(tab->mat->row[row1][off + col], |
884 | 6.99k | tab->mat->row[row2][off + col])) |
885 | 6.99k | return 03.80k ; |
886 | 6.99k | } |
887 | 3.97k | return 1173 ; |
888 | 3.97k | } |
889 | | |
890 | | /* Return an inequality that expresses that the "parametric constant" |
891 | | * should be non-negative. |
892 | | * This function is only called when the coefficient of the big parameter |
893 | | * is equal to zero. |
894 | | */ |
895 | | static struct isl_vec *get_row_parameter_ineq(struct isl_tab *tab, int row) |
896 | 16.5k | { |
897 | 16.5k | struct isl_vec *ineq; |
898 | 16.5k | |
899 | 16.5k | ineq = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_param + tab->n_div); |
900 | 16.5k | if (!ineq) |
901 | 0 | return NULL; |
902 | 16.5k | |
903 | 16.5k | get_row_parameter_line(tab, row, ineq->el); |
904 | 16.5k | if (ineq) |
905 | 16.5k | ineq = isl_vec_normalize(ineq); |
906 | 16.5k | |
907 | 16.5k | return ineq; |
908 | 16.5k | } |
909 | | |
910 | | /* Normalize a div expression of the form |
911 | | * |
912 | | * [(g*f(x) + c)/(g * m)] |
913 | | * |
914 | | * with c the constant term and f(x) the remaining coefficients, to |
915 | | * |
916 | | * [(f(x) + [c/g])/m] |
917 | | */ |
918 | | static void normalize_div(__isl_keep isl_vec *div) |
919 | 824 | { |
920 | 824 | isl_ctx *ctx = isl_vec_get_ctx(div); |
921 | 824 | int len = div->size - 2; |
922 | 824 | |
923 | 824 | isl_seq_gcd(div->el + 2, len, &ctx->normalize_gcd); |
924 | 824 | isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, div->el[0]); |
925 | 824 | |
926 | 824 | if (isl_int_is_one(ctx->normalize_gcd)) |
927 | 824 | return773 ; |
928 | 51 | |
929 | 51 | isl_int_divexact(div->el[0], div->el[0], ctx->normalize_gcd); |
930 | 51 | isl_int_fdiv_q(div->el[1], div->el[1], ctx->normalize_gcd); |
931 | 51 | isl_seq_scale_down(div->el + 2, div->el + 2, ctx->normalize_gcd, len); |
932 | 51 | } |
933 | | |
934 | | /* Return an integer division for use in a parametric cut based |
935 | | * on the given row. |
936 | | * In particular, let the parametric constant of the row be |
937 | | * |
938 | | * \sum_i a_i y_i |
939 | | * |
940 | | * where y_0 = 1, but none of the y_i corresponds to the big parameter M. |
941 | | * The div returned is equal to |
942 | | * |
943 | | * floor(\sum_i {-a_i} y_i) = floor((\sum_i (-a_i mod d) y_i)/d) |
944 | | */ |
945 | | static struct isl_vec *get_row_parameter_div(struct isl_tab *tab, int row) |
946 | 707 | { |
947 | 707 | struct isl_vec *div; |
948 | 707 | |
949 | 707 | div = isl_vec_alloc(tab->mat->ctx, 1 + 1 + tab->n_param + tab->n_div); |
950 | 707 | if (!div) |
951 | 0 | return NULL; |
952 | 707 | |
953 | 707 | isl_int_set(div->el[0], tab->mat->row[row][0]); |
954 | 707 | get_row_parameter_line(tab, row, div->el + 1); |
955 | 707 | isl_seq_neg(div->el + 1, div->el + 1, div->size - 1); |
956 | 707 | normalize_div(div); |
957 | 707 | isl_seq_fdiv_r(div->el + 1, div->el + 1, div->el[0], div->size - 1); |
958 | 707 | |
959 | 707 | return div; |
960 | 707 | } |
961 | | |
962 | | /* Return an integer division for use in transferring an integrality constraint |
963 | | * to the context. |
964 | | * In particular, let the parametric constant of the row be |
965 | | * |
966 | | * \sum_i a_i y_i |
967 | | * |
968 | | * where y_0 = 1, but none of the y_i corresponds to the big parameter M. |
969 | | * The the returned div is equal to |
970 | | * |
971 | | * floor(\sum_i {a_i} y_i) = floor((\sum_i (a_i mod d) y_i)/d) |
972 | | */ |
973 | | static struct isl_vec *get_row_split_div(struct isl_tab *tab, int row) |
974 | 117 | { |
975 | 117 | struct isl_vec *div; |
976 | 117 | |
977 | 117 | div = isl_vec_alloc(tab->mat->ctx, 1 + 1 + tab->n_param + tab->n_div); |
978 | 117 | if (!div) |
979 | 0 | return NULL; |
980 | 117 | |
981 | 117 | isl_int_set(div->el[0], tab->mat->row[row][0]); |
982 | 117 | get_row_parameter_line(tab, row, div->el + 1); |
983 | 117 | normalize_div(div); |
984 | 117 | isl_seq_fdiv_r(div->el + 1, div->el + 1, div->el[0], div->size - 1); |
985 | 117 | |
986 | 117 | return div; |
987 | 117 | } |
988 | | |
989 | | /* Construct and return an inequality that expresses an upper bound |
990 | | * on the given div. |
991 | | * In particular, if the div is given by |
992 | | * |
993 | | * d = floor(e/m) |
994 | | * |
995 | | * then the inequality expresses |
996 | | * |
997 | | * m d <= e |
998 | | */ |
999 | | static __isl_give isl_vec *ineq_for_div(__isl_keep isl_basic_set *bset, |
1000 | | unsigned div) |
1001 | 117 | { |
1002 | 117 | unsigned total; |
1003 | 117 | unsigned div_pos; |
1004 | 117 | struct isl_vec *ineq; |
1005 | 117 | |
1006 | 117 | if (!bset) |
1007 | 0 | return NULL; |
1008 | 117 | |
1009 | 117 | total = isl_basic_set_total_dim(bset); |
1010 | 117 | div_pos = 1 + total - bset->n_div + div; |
1011 | 117 | |
1012 | 117 | ineq = isl_vec_alloc(bset->ctx, 1 + total); |
1013 | 117 | if (!ineq) |
1014 | 0 | return NULL; |
1015 | 117 | |
1016 | 117 | isl_seq_cpy(ineq->el, bset->div[div] + 1, 1 + total); |
1017 | 117 | isl_int_neg(ineq->el[div_pos], bset->div[div][0]); |
1018 | 117 | return ineq; |
1019 | 117 | } |
1020 | | |
1021 | | /* Given a row in the tableau and a div that was created |
1022 | | * using get_row_split_div and that has been constrained to equality, i.e., |
1023 | | * |
1024 | | * d = floor(\sum_i {a_i} y_i) = \sum_i {a_i} y_i |
1025 | | * |
1026 | | * replace the expression "\sum_i {a_i} y_i" in the row by d, |
1027 | | * i.e., we subtract "\sum_i {a_i} y_i" and add 1 d. |
1028 | | * The coefficients of the non-parameters in the tableau have been |
1029 | | * verified to be integral. We can therefore simply replace coefficient b |
1030 | | * by floor(b). For the coefficients of the parameters we have |
1031 | | * floor(a_i) = a_i - {a_i}, while for the other coefficients, we have |
1032 | | * floor(b) = b. |
1033 | | */ |
1034 | | static struct isl_tab *set_row_cst_to_div(struct isl_tab *tab, int row, int div) |
1035 | 117 | { |
1036 | 117 | isl_seq_fdiv_q(tab->mat->row[row] + 1, tab->mat->row[row] + 1, |
1037 | 117 | tab->mat->row[row][0], 1 + tab->M + tab->n_col); |
1038 | 117 | |
1039 | 117 | isl_int_set_si(tab->mat->row[row][0], 1); |
1040 | 117 | |
1041 | 117 | if (tab->var[tab->n_var - tab->n_div + div].is_row) { |
1042 | 0 | int drow = tab->var[tab->n_var - tab->n_div + div].index; |
1043 | 0 |
|
1044 | 0 | isl_assert(tab->mat->ctx, |
1045 | 0 | isl_int_is_one(tab->mat->row[drow][0]), goto error); |
1046 | 0 | isl_seq_combine(tab->mat->row[row] + 1, |
1047 | 0 | tab->mat->ctx->one, tab->mat->row[row] + 1, |
1048 | 0 | tab->mat->ctx->one, tab->mat->row[drow] + 1, |
1049 | 0 | 1 + tab->M + tab->n_col); |
1050 | 117 | } else { |
1051 | 117 | int dcol = tab->var[tab->n_var - tab->n_div + div].index; |
1052 | 117 | |
1053 | 117 | isl_int_add_ui(tab->mat->row[row][2 + tab->M + dcol], |
1054 | 117 | tab->mat->row[row][2 + tab->M + dcol], 1); |
1055 | 117 | } |
1056 | 117 | |
1057 | 117 | return tab; |
1058 | 0 | error: |
1059 | 0 | isl_tab_free(tab); |
1060 | 0 | return NULL; |
1061 | 117 | } |
1062 | | |
1063 | | /* Check if the (parametric) constant of the given row is obviously |
1064 | | * negative, meaning that we don't need to consult the context tableau. |
1065 | | * If there is a big parameter and its coefficient is non-zero, |
1066 | | * then this coefficient determines the outcome. |
1067 | | * Otherwise, we check whether the constant is negative and |
1068 | | * all non-zero coefficients of parameters are negative and |
1069 | | * belong to non-negative parameters. |
1070 | | */ |
1071 | | static int is_obviously_neg(struct isl_tab *tab, int row) |
1072 | 207k | { |
1073 | 207k | int i; |
1074 | 207k | int col; |
1075 | 207k | unsigned off = 2 + tab->M; |
1076 | 207k | |
1077 | 207k | if (tab->M) { |
1078 | 110k | if (isl_int_is_pos(tab->mat->row[row][2])) |
1079 | 110k | return 057.6k ; |
1080 | 52.8k | if (isl_int_is_neg(tab->mat->row[row][2])) |
1081 | 52.8k | return 10 ; |
1082 | 150k | } |
1083 | 150k | |
1084 | 150k | if (isl_int_is_nonneg(tab->mat->row[row][1])) |
1085 | 150k | return 0134k ; |
1086 | 31.7k | for (i = 0; 15.9k i < tab->n_param; ++i15.8k ) { |
1087 | 27.6k | /* Eliminated parameter */ |
1088 | 27.6k | if (tab->var[i].is_row) |
1089 | 7.63k | continue; |
1090 | 20.0k | col = tab->var[i].index; |
1091 | 20.0k | if (isl_int_is_zero(tab->mat->row[row][off + col])) |
1092 | 20.0k | continue8.11k ; |
1093 | 11.9k | if (!tab->var[i].is_nonneg) |
1094 | 10.8k | return 0; |
1095 | 1.01k | if (isl_int_is_pos(tab->mat->row[row][off + col])) |
1096 | 1.01k | return 0965 ; |
1097 | 1.01k | } |
1098 | 15.9k | for (i = 0; 4.05k i < tab->n_div4.53k ; ++i480 ) { |
1099 | 763 | if (tab->var[tab->n_var - tab->n_div + i].is_row) |
1100 | 419 | continue; |
1101 | 344 | col = tab->var[tab->n_var - tab->n_div + i].index; |
1102 | 344 | if (isl_int_is_zero(tab->mat->row[row][off + col])) |
1103 | 344 | continue61 ; |
1104 | 283 | if (!tab->var[tab->n_var - tab->n_div + i].is_nonneg) |
1105 | 239 | return 0; |
1106 | 44 | if (isl_int_is_pos(tab->mat->row[row][off + col])) |
1107 | 44 | return 0; |
1108 | 44 | } |
1109 | 4.05k | return 13.77k ; |
1110 | 4.05k | } |
1111 | | |
1112 | | /* Check if the (parametric) constant of the given row is obviously |
1113 | | * non-negative, meaning that we don't need to consult the context tableau. |
1114 | | * If there is a big parameter and its coefficient is non-zero, |
1115 | | * then this coefficient determines the outcome. |
1116 | | * Otherwise, we check whether the constant is non-negative and |
1117 | | * all non-zero coefficients of parameters are positive and |
1118 | | * belong to non-negative parameters. |
1119 | | */ |
1120 | | static int is_obviously_nonneg(struct isl_tab *tab, int row) |
1121 | 34.9k | { |
1122 | 34.9k | int i; |
1123 | 34.9k | int col; |
1124 | 34.9k | unsigned off = 2 + tab->M; |
1125 | 34.9k | |
1126 | 34.9k | if (tab->M) { |
1127 | 34.9k | if (isl_int_is_pos(tab->mat->row[row][2])) |
1128 | 34.9k | return 114.6k ; |
1129 | 20.3k | if (isl_int_is_neg(tab->mat->row[row][2])) |
1130 | 20.3k | return 00 ; |
1131 | 20.3k | } |
1132 | 20.3k | |
1133 | 20.3k | if (isl_int_is_neg(tab->mat->row[row][1])) |
1134 | 20.3k | return 06.60k ; |
1135 | 52.6k | for (i = 0; 13.7k i < tab->n_param; ++i38.8k ) { |
1136 | 45.2k | /* Eliminated parameter */ |
1137 | 45.2k | if (tab->var[i].is_row) |
1138 | 17.5k | continue; |
1139 | 27.6k | col = tab->var[i].index; |
1140 | 27.6k | if (isl_int_is_zero(tab->mat->row[row][off + col])) |
1141 | 27.6k | continue17.9k ; |
1142 | 9.70k | if (!tab->var[i].is_nonneg) |
1143 | 2.12k | return 0; |
1144 | 7.58k | if (isl_int_is_neg(tab->mat->row[row][off + col])) |
1145 | 7.58k | return 04.25k ; |
1146 | 7.58k | } |
1147 | 13.7k | for (i = 0; 7.35k i < tab->n_div12.2k ; ++i4.87k ) { |
1148 | 5.08k | if (tab->var[tab->n_var - tab->n_div + i].is_row) |
1149 | 3.93k | continue; |
1150 | 1.15k | col = tab->var[tab->n_var - tab->n_div + i].index; |
1151 | 1.15k | if (isl_int_is_zero(tab->mat->row[row][off + col])) |
1152 | 1.15k | continue934 ; |
1153 | 218 | if (!tab->var[tab->n_var - tab->n_div + i].is_nonneg) |
1154 | 186 | return 0; |
1155 | 32 | if (isl_int_is_neg(tab->mat->row[row][off + col])) |
1156 | 32 | return 023 ; |
1157 | 32 | } |
1158 | 7.35k | return 17.14k ; |
1159 | 7.35k | } |
1160 | | |
1161 | | /* Given a row r and two columns, return the column that would |
1162 | | * lead to the lexicographically smallest increment in the sample |
1163 | | * solution when leaving the basis in favor of the row. |
1164 | | * Pivoting with column c will increment the sample value by a non-negative |
1165 | | * constant times a_{V,c}/a_{r,c}, with a_{V,c} the elements of column c |
1166 | | * corresponding to the non-parametric variables. |
1167 | | * If variable v appears in a column c_v, then a_{v,c} = 1 iff c = c_v, |
1168 | | * with all other entries in this virtual row equal to zero. |
1169 | | * If variable v appears in a row, then a_{v,c} is the element in column c |
1170 | | * of that row. |
1171 | | * |
1172 | | * Let v be the first variable with a_{v,c1}/a_{r,c1} != a_{v,c2}/a_{r,c2}. |
1173 | | * Then if a_{v,c1}/a_{r,c1} < a_{v,c2}/a_{r,c2}, i.e., |
1174 | | * a_{v,c2} a_{r,c1} - a_{v,c1} a_{r,c2} > 0, c1 results in the minimal |
1175 | | * increment. Otherwise, it's c2. |
1176 | | */ |
1177 | | static int lexmin_col_pair(struct isl_tab *tab, |
1178 | | int row, int col1, int col2, isl_int tmp) |
1179 | 5.14k | { |
1180 | 5.14k | int i; |
1181 | 5.14k | isl_int *tr; |
1182 | 5.14k | |
1183 | 5.14k | tr = tab->mat->row[row] + 2 + tab->M; |
1184 | 5.14k | |
1185 | 21.3k | for (i = tab->n_param; i < tab->n_var - tab->n_div; ++i16.2k ) { |
1186 | 21.3k | int s1, s2; |
1187 | 21.3k | isl_int *r; |
1188 | 21.3k | |
1189 | 21.3k | if (!tab->var[i].is_row) { |
1190 | 7.16k | if (tab->var[i].index == col1) |
1191 | 707 | return col2; |
1192 | 6.46k | if (tab->var[i].index == col2) |
1193 | 460 | return col1; |
1194 | 6.00k | continue; |
1195 | 6.00k | } |
1196 | 14.1k | |
1197 | 14.1k | if (tab->var[i].index == row) |
1198 | 106 | continue; |
1199 | 14.0k | |
1200 | 14.0k | r = tab->mat->row[tab->var[i].index] + 2 + tab->M; |
1201 | 14.0k | s1 = isl_int_sgn(r[col1]); |
1202 | 14.0k | s2 = isl_int_sgn(r[col2]); |
1203 | 14.0k | if (s1 == 0 && s2 == 010.5k ) |
1204 | 9.02k | continue; |
1205 | 5.05k | if (s1 < s2) |
1206 | 1.70k | return col1; |
1207 | 3.35k | if (s2 < s1) |
1208 | 943 | return col2; |
1209 | 2.41k | |
1210 | 2.41k | isl_int_mul(tmp, r[col2], tr[col1]); |
1211 | 2.41k | isl_int_submul(tmp, r[col1], tr[col2]); |
1212 | 2.41k | if (isl_int_is_pos(tmp)) |
1213 | 2.41k | return col1910 ; |
1214 | 1.50k | if (isl_int_is_neg(tmp)) |
1215 | 1.50k | return col2420 ; |
1216 | 1.50k | } |
1217 | 5.14k | return -10 ; |
1218 | 5.14k | } |
1219 | | |
1220 | | /* Does the index into the tab->var or tab->con array "index" |
1221 | | * correspond to a variable in the context tableau? |
1222 | | * In particular, it needs to be an index into the tab->var array and |
1223 | | * it needs to refer to either one of the first tab->n_param variables or |
1224 | | * one of the last tab->n_div variables. |
1225 | | */ |
1226 | | static int is_parameter_var(struct isl_tab *tab, int index) |
1227 | 215k | { |
1228 | 215k | if (index < 0) |
1229 | 51.9k | return 0; |
1230 | 163k | if (index < tab->n_param) |
1231 | 67.2k | return 1; |
1232 | 96.0k | if (index >= tab->n_var - tab->n_div) |
1233 | 4.81k | return 1; |
1234 | 91.2k | return 0; |
1235 | 91.2k | } |
1236 | | |
1237 | | /* Does column "col" of "tab" refer to a variable in the context tableau? |
1238 | | */ |
1239 | | static int col_is_parameter_var(struct isl_tab *tab, int col) |
1240 | 142k | { |
1241 | 142k | return is_parameter_var(tab, tab->col_var[col]); |
1242 | 142k | } |
1243 | | |
1244 | | /* Does row "row" of "tab" refer to a variable in the context tableau? |
1245 | | */ |
1246 | | static int row_is_parameter_var(struct isl_tab *tab, int row) |
1247 | 72.2k | { |
1248 | 72.2k | return is_parameter_var(tab, tab->row_var[row]); |
1249 | 72.2k | } |
1250 | | |
1251 | | /* Given a row in the tableau, find and return the column that would |
1252 | | * result in the lexicographically smallest, but positive, increment |
1253 | | * in the sample point. |
1254 | | * If there is no such column, then return tab->n_col. |
1255 | | * If anything goes wrong, return -1. |
1256 | | */ |
1257 | | static int lexmin_pivot_col(struct isl_tab *tab, int row) |
1258 | 12.4k | { |
1259 | 12.4k | int j; |
1260 | 12.4k | int col = tab->n_col; |
1261 | 12.4k | isl_int *tr; |
1262 | 12.4k | isl_int tmp; |
1263 | 12.4k | |
1264 | 12.4k | tr = tab->mat->row[row] + 2 + tab->M; |
1265 | 12.4k | |
1266 | 12.4k | isl_int_init(tmp); |
1267 | 12.4k | |
1268 | 94.7k | for (j = tab->n_dead; j < tab->n_col; ++j82.2k ) { |
1269 | 82.2k | if (col_is_parameter_var(tab, j)) |
1270 | 22.4k | continue; |
1271 | 59.8k | |
1272 | 59.8k | if (!isl_int_is_pos(tr[j])) |
1273 | 59.8k | continue45.1k ; |
1274 | 14.6k | |
1275 | 14.6k | if (col == tab->n_col) |
1276 | 9.51k | col = j; |
1277 | 5.14k | else |
1278 | 5.14k | col = lexmin_col_pair(tab, row, col, j, tmp); |
1279 | 14.6k | isl_assert(tab->mat->ctx, col >= 0, goto error); |
1280 | 14.6k | } |
1281 | 12.4k | |
1282 | 12.4k | isl_int_clear(tmp); |
1283 | 12.4k | return col; |
1284 | 0 | error: |
1285 | 0 | isl_int_clear(tmp); |
1286 | 0 | return -1; |
1287 | 12.4k | } |
1288 | | |
1289 | | /* Return the first known violated constraint, i.e., a non-negative |
1290 | | * constraint that currently has an either obviously negative value |
1291 | | * or a previously determined to be negative value. |
1292 | | * |
1293 | | * If any constraint has a negative coefficient for the big parameter, |
1294 | | * if any, then we return one of these first. |
1295 | | */ |
1296 | | static int first_neg(struct isl_tab *tab) |
1297 | 44.8k | { |
1298 | 44.8k | int row; |
1299 | 44.8k | |
1300 | 44.8k | if (tab->M) |
1301 | 285k | for (row = tab->n_redundant; 36.6k row < tab->n_row; ++row248k ) { |
1302 | 253k | if (!isl_tab_var_from_row(tab, row)->is_nonneg) |
1303 | 56.2k | continue; |
1304 | 197k | if (!isl_int_is_neg(tab->mat->row[row][2])) |
1305 | 197k | continue192k ; |
1306 | 4.63k | if (tab->row_sign) |
1307 | 4.63k | tab->row_sign[row] = isl_tab_row_neg; |
1308 | 4.63k | return row; |
1309 | 4.63k | } |
1310 | 350k | for (row = tab->n_redundant; 40.2k row < tab->n_row; ++row309k ) { |
1311 | 317k | if (!isl_tab_var_from_row(tab, row)->is_nonneg) |
1312 | 48.7k | continue; |
1313 | 268k | if (tab->row_sign) { |
1314 | 171k | if (tab->row_sign[row] == 0 && |
1315 | 171k | is_obviously_neg(tab, row)110k ) |
1316 | 302 | tab->row_sign[row] = isl_tab_row_neg; |
1317 | 171k | if (tab->row_sign[row] != isl_tab_row_neg) |
1318 | 167k | continue; |
1319 | 97.1k | } else if (!is_obviously_neg(tab, row)) |
1320 | 93.7k | continue; |
1321 | 7.82k | return row; |
1322 | 7.82k | } |
1323 | 40.2k | return -132.3k ; |
1324 | 40.2k | } |
1325 | | |
1326 | | /* Check whether the invariant that all columns are lexico-positive |
1327 | | * is satisfied. This function is not called from the current code |
1328 | | * but is useful during debugging. |
1329 | | */ |
1330 | | static void check_lexpos(struct isl_tab *tab) __attribute__ ((unused)); |
1331 | | static void check_lexpos(struct isl_tab *tab) |
1332 | 0 | { |
1333 | 0 | unsigned off = 2 + tab->M; |
1334 | 0 | int col; |
1335 | 0 | int var; |
1336 | 0 | int row; |
1337 | 0 |
|
1338 | 0 | for (col = tab->n_dead; col < tab->n_col; ++col) { |
1339 | 0 | if (col_is_parameter_var(tab, col)) |
1340 | 0 | continue; |
1341 | 0 | for (var = tab->n_param; var < tab->n_var - tab->n_div; ++var) { |
1342 | 0 | if (!tab->var[var].is_row) { |
1343 | 0 | if (tab->var[var].index == col) |
1344 | 0 | break; |
1345 | 0 | else |
1346 | 0 | continue; |
1347 | 0 | } |
1348 | 0 | row = tab->var[var].index; |
1349 | 0 | if (isl_int_is_zero(tab->mat->row[row][off + col])) |
1350 | 0 | continue; |
1351 | 0 | if (isl_int_is_pos(tab->mat->row[row][off + col])) |
1352 | 0 | break; |
1353 | 0 | fprintf(stderr, "lexneg column %d (row %d)\n", |
1354 | 0 | col, row); |
1355 | 0 | } |
1356 | 0 | if (var >= tab->n_var - tab->n_div) |
1357 | 0 | fprintf(stderr, "zero column %d\n", col); |
1358 | 0 | } |
1359 | 0 | } |
1360 | | |
1361 | | /* Report to the caller that the given constraint is part of an encountered |
1362 | | * conflict. |
1363 | | */ |
1364 | | static int report_conflicting_constraint(struct isl_tab *tab, int con) |
1365 | 1.14k | { |
1366 | 1.14k | return tab->conflict(con, tab->conflict_user); |
1367 | 1.14k | } |
1368 | | |
1369 | | /* Given a conflicting row in the tableau, report all constraints |
1370 | | * involved in the row to the caller. That is, the row itself |
1371 | | * (if it represents a constraint) and all constraint columns with |
1372 | | * non-zero (and therefore negative) coefficients. |
1373 | | */ |
1374 | | static int report_conflict(struct isl_tab *tab, int row) |
1375 | 2.93k | { |
1376 | 2.93k | int j; |
1377 | 2.93k | isl_int *tr; |
1378 | 2.93k | |
1379 | 2.93k | if (!tab->conflict) |
1380 | 2.49k | return 0; |
1381 | 448 | |
1382 | 448 | if (tab->row_var[row] < 0 && |
1383 | 448 | report_conflicting_constraint(tab, ~tab->row_var[row]) < 0) |
1384 | 0 | return -1; |
1385 | 448 | |
1386 | 448 | tr = tab->mat->row[row] + 2 + tab->M; |
1387 | 448 | |
1388 | 5.34k | for (j = tab->n_dead; j < tab->n_col; ++j4.90k ) { |
1389 | 4.90k | if (col_is_parameter_var(tab, j)) |
1390 | 0 | continue; |
1391 | 4.90k | |
1392 | 4.90k | if (!isl_int_is_neg(tr[j])) |
1393 | 4.90k | continue4.16k ; |
1394 | 732 | |
1395 | 732 | if (tab->col_var[j] < 0 && |
1396 | 732 | report_conflicting_constraint(tab, ~tab->col_var[j]) < 0697 ) |
1397 | 0 | return -1; |
1398 | 732 | } |
1399 | 448 | |
1400 | 448 | return 0; |
1401 | 448 | } |
1402 | | |
1403 | | /* Resolve all known or obviously violated constraints through pivoting. |
1404 | | * In particular, as long as we can find any violated constraint, we |
1405 | | * look for a pivoting column that would result in the lexicographically |
1406 | | * smallest increment in the sample point. If there is no such column |
1407 | | * then the tableau is infeasible. |
1408 | | */ |
1409 | | static int restore_lexmin(struct isl_tab *tab) WARN_UNUSED; |
1410 | | static int restore_lexmin(struct isl_tab *tab) |
1411 | 35.3k | { |
1412 | 35.3k | int row, col; |
1413 | 35.3k | |
1414 | 35.3k | if (!tab) |
1415 | 0 | return -1; |
1416 | 35.3k | if (tab->empty) |
1417 | 9 | return 0; |
1418 | 44.8k | while (35.3k (row = first_neg(tab)) != -1) { |
1419 | 12.4k | col = lexmin_pivot_col(tab, row); |
1420 | 12.4k | if (col >= tab->n_col) { |
1421 | 2.93k | if (report_conflict(tab, row) < 0) |
1422 | 0 | return -1; |
1423 | 2.93k | if (isl_tab_mark_empty(tab) < 0) |
1424 | 0 | return -1; |
1425 | 2.93k | return 0; |
1426 | 2.93k | } |
1427 | 9.51k | if (col < 0) |
1428 | 0 | return -1; |
1429 | 9.51k | if (isl_tab_pivot(tab, row, col) < 0) |
1430 | 0 | return -1; |
1431 | 9.51k | } |
1432 | 35.3k | return 032.3k ; |
1433 | 35.3k | } |
1434 | | |
1435 | | /* Given a row that represents an equality, look for an appropriate |
1436 | | * pivoting column. |
1437 | | * In particular, if there are any non-zero coefficients among |
1438 | | * the non-parameter variables, then we take the last of these |
1439 | | * variables. Eliminating this variable in terms of the other |
1440 | | * variables and/or parameters does not influence the property |
1441 | | * that all column in the initial tableau are lexicographically |
1442 | | * positive. The row corresponding to the eliminated variable |
1443 | | * will only have non-zero entries below the diagonal of the |
1444 | | * initial tableau. That is, we transform |
1445 | | * |
1446 | | * I I |
1447 | | * 1 into a |
1448 | | * I I |
1449 | | * |
1450 | | * If there is no such non-parameter variable, then we are dealing with |
1451 | | * pure parameter equality and we pick any parameter with coefficient 1 or -1 |
1452 | | * for elimination. This will ensure that the eliminated parameter |
1453 | | * always has an integer value whenever all the other parameters are integral. |
1454 | | * If there is no such parameter then we return -1. |
1455 | | */ |
1456 | | static int last_var_col_or_int_par_col(struct isl_tab *tab, int row) |
1457 | 23.9k | { |
1458 | 23.9k | unsigned off = 2 + tab->M; |
1459 | 23.9k | int i; |
1460 | 23.9k | |
1461 | 85.0k | for (i = tab->n_var - tab->n_div - 1; i >= 0 && i >= tab->n_param84.0k ; --i61.1k ) { |
1462 | 74.6k | int col; |
1463 | 74.6k | if (tab->var[i].is_row) |
1464 | 44.6k | continue; |
1465 | 30.0k | col = tab->var[i].index; |
1466 | 30.0k | if (col <= tab->n_dead) |
1467 | 1.99k | continue; |
1468 | 28.0k | if (!isl_int_is_zero(tab->mat->row[row][off + col])) |
1469 | 28.0k | return col13.5k ; |
1470 | 28.0k | } |
1471 | 28.3k | for (i = tab->n_dead; 10.4k i < tab->n_col; ++i17.9k ) { |
1472 | 28.2k | if (isl_int_is_one(tab->mat->row[row][off + i])) |
1473 | 28.2k | return i4.91k ; |
1474 | 23.3k | if (isl_int_is_negone(tab->mat->row[row][off + i])) |
1475 | 23.3k | return i5.42k ; |
1476 | 23.3k | } |
1477 | 10.4k | return -184 ; |
1478 | 10.4k | } |
1479 | | |
1480 | | /* Add an equality that is known to be valid to the tableau. |
1481 | | * We first check if we can eliminate a variable or a parameter. |
1482 | | * If not, we add the equality as two inequalities. |
1483 | | * In this case, the equality was a pure parameter equality and there |
1484 | | * is no need to resolve any constraint violations. |
1485 | | * |
1486 | | * This function assumes that at least two more rows and at least |
1487 | | * two more elements in the constraint array are available in the tableau. |
1488 | | */ |
1489 | | static struct isl_tab *add_lexmin_valid_eq(struct isl_tab *tab, isl_int *eq) |
1490 | 23.9k | { |
1491 | 23.9k | int i; |
1492 | 23.9k | int r; |
1493 | 23.9k | |
1494 | 23.9k | if (!tab) |
1495 | 0 | return NULL; |
1496 | 23.9k | r = isl_tab_add_row(tab, eq); |
1497 | 23.9k | if (r < 0) |
1498 | 0 | goto error; |
1499 | 23.9k | |
1500 | 23.9k | r = tab->con[r].index; |
1501 | 23.9k | i = last_var_col_or_int_par_col(tab, r); |
1502 | 23.9k | if (i < 0) { |
1503 | 84 | tab->con[r].is_nonneg = 1; |
1504 | 84 | if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0) |
1505 | 0 | goto error; |
1506 | 84 | isl_seq_neg(eq, eq, 1 + tab->n_var); |
1507 | 84 | r = isl_tab_add_row(tab, eq); |
1508 | 84 | if (r < 0) |
1509 | 0 | goto error; |
1510 | 84 | tab->con[r].is_nonneg = 1; |
1511 | 84 | if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0) |
1512 | 0 | goto error; |
1513 | 23.8k | } else { |
1514 | 23.8k | if (isl_tab_pivot(tab, r, i) < 0) |
1515 | 0 | goto error; |
1516 | 23.8k | if (isl_tab_kill_col(tab, i) < 0) |
1517 | 0 | goto error; |
1518 | 23.8k | tab->n_eq++; |
1519 | 23.8k | } |
1520 | 23.9k | |
1521 | 23.9k | return tab; |
1522 | 0 | error: |
1523 | 0 | isl_tab_free(tab); |
1524 | 0 | return NULL; |
1525 | 23.9k | } |
1526 | | |
1527 | | /* Check if the given row is a pure constant. |
1528 | | */ |
1529 | | static int is_constant(struct isl_tab *tab, int row) |
1530 | 298 | { |
1531 | 298 | unsigned off = 2 + tab->M; |
1532 | 298 | |
1533 | 298 | return isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead, |
1534 | 298 | tab->n_col - tab->n_dead) == -1; |
1535 | 298 | } |
1536 | | |
1537 | | /* Is the given row a parametric constant? |
1538 | | * That is, does it only involve variables that also appear in the context? |
1539 | | */ |
1540 | | static int is_parametric_constant(struct isl_tab *tab, int row) |
1541 | 463 | { |
1542 | 463 | unsigned off = 2 + tab->M; |
1543 | 463 | int col; |
1544 | 463 | |
1545 | 1.93k | for (col = tab->n_dead; col < tab->n_col; ++col1.46k ) { |
1546 | 1.80k | if (col_is_parameter_var(tab, col)) |
1547 | 1.40k | continue; |
1548 | 400 | if (isl_int_is_zero(tab->mat->row[row][off + col])) |
1549 | 400 | continue65 ; |
1550 | 335 | return 0; |
1551 | 335 | } |
1552 | 463 | |
1553 | 463 | return 1128 ; |
1554 | 463 | } |
1555 | | |
1556 | | /* Add an equality that may or may not be valid to the tableau. |
1557 | | * If the resulting row is a pure constant, then it must be zero. |
1558 | | * Otherwise, the resulting tableau is empty. |
1559 | | * |
1560 | | * If the row is not a pure constant, then we add two inequalities, |
1561 | | * each time checking that they can be satisfied. |
1562 | | * In the end we try to use one of the two constraints to eliminate |
1563 | | * a column. |
1564 | | * |
1565 | | * This function assumes that at least two more rows and at least |
1566 | | * two more elements in the constraint array are available in the tableau. |
1567 | | */ |
1568 | | static int add_lexmin_eq(struct isl_tab *tab, isl_int *eq) WARN_UNUSED; |
1569 | | static int add_lexmin_eq(struct isl_tab *tab, isl_int *eq) |
1570 | 298 | { |
1571 | 298 | int r1, r2; |
1572 | 298 | int row; |
1573 | 298 | struct isl_tab_undo *snap; |
1574 | 298 | |
1575 | 298 | if (!tab) |
1576 | 0 | return -1; |
1577 | 298 | snap = isl_tab_snap(tab); |
1578 | 298 | r1 = isl_tab_add_row(tab, eq); |
1579 | 298 | if (r1 < 0) |
1580 | 0 | return -1; |
1581 | 298 | tab->con[r1].is_nonneg = 1; |
1582 | 298 | if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r1]) < 0) |
1583 | 0 | return -1; |
1584 | 298 | |
1585 | 298 | row = tab->con[r1].index; |
1586 | 298 | if (is_constant(tab, row)) { |
1587 | 54 | if (!isl_int_is_zero(tab->mat->row[row][1]) || |
1588 | 54 | (tab->M && !0 isl_int_is_zero0 (tab->mat->row[row][2]))) { |
1589 | 0 | if (isl_tab_mark_empty(tab) < 0) |
1590 | 0 | return -1; |
1591 | 0 | return 0; |
1592 | 0 | } |
1593 | 54 | if (isl_tab_rollback(tab, snap) < 0) |
1594 | 0 | return -1; |
1595 | 54 | return 0; |
1596 | 54 | } |
1597 | 244 | |
1598 | 244 | if (restore_lexmin(tab) < 0) |
1599 | 0 | return -1; |
1600 | 244 | if (tab->empty) |
1601 | 8 | return 0; |
1602 | 236 | |
1603 | 236 | isl_seq_neg(eq, eq, 1 + tab->n_var); |
1604 | 236 | |
1605 | 236 | r2 = isl_tab_add_row(tab, eq); |
1606 | 236 | if (r2 < 0) |
1607 | 0 | return -1; |
1608 | 236 | tab->con[r2].is_nonneg = 1; |
1609 | 236 | if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r2]) < 0) |
1610 | 0 | return -1; |
1611 | 236 | |
1612 | 236 | if (restore_lexmin(tab) < 0) |
1613 | 0 | return -1; |
1614 | 236 | if (tab->empty) |
1615 | 0 | return 0; |
1616 | 236 | |
1617 | 236 | if (!tab->con[r1].is_row) { |
1618 | 0 | if (isl_tab_kill_col(tab, tab->con[r1].index) < 0) |
1619 | 0 | return -1; |
1620 | 236 | } else if (!tab->con[r2].is_row) { |
1621 | 0 | if (isl_tab_kill_col(tab, tab->con[r2].index) < 0) |
1622 | 0 | return -1; |
1623 | 236 | } |
1624 | 236 | |
1625 | 236 | if (tab->bmap) { |
1626 | 0 | tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq); |
1627 | 0 | if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0) |
1628 | 0 | return -1; |
1629 | 0 | isl_seq_neg(eq, eq, 1 + tab->n_var); |
1630 | 0 | tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq); |
1631 | 0 | isl_seq_neg(eq, eq, 1 + tab->n_var); |
1632 | 0 | if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0) |
1633 | 0 | return -1; |
1634 | 0 | if (!tab->bmap) |
1635 | 0 | return -1; |
1636 | 236 | } |
1637 | 236 | |
1638 | 236 | return 0; |
1639 | 236 | } |
1640 | | |
1641 | | /* Add an inequality to the tableau, resolving violations using |
1642 | | * restore_lexmin. |
1643 | | * |
1644 | | * This function assumes that at least one more row and at least |
1645 | | * one more element in the constraint array are available in the tableau. |
1646 | | */ |
1647 | | static struct isl_tab *add_lexmin_ineq(struct isl_tab *tab, isl_int *ineq) |
1648 | 23.9k | { |
1649 | 23.9k | int r; |
1650 | 23.9k | |
1651 | 23.9k | if (!tab) |
1652 | 0 | return NULL; |
1653 | 23.9k | if (tab->bmap) { |
1654 | 0 | tab->bmap = isl_basic_map_add_ineq(tab->bmap, ineq); |
1655 | 0 | if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0) |
1656 | 0 | goto error; |
1657 | 0 | if (!tab->bmap) |
1658 | 0 | goto error; |
1659 | 23.9k | } |
1660 | 23.9k | r = isl_tab_add_row(tab, ineq); |
1661 | 23.9k | if (r < 0) |
1662 | 0 | goto error; |
1663 | 23.9k | tab->con[r].is_nonneg = 1; |
1664 | 23.9k | if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0) |
1665 | 0 | goto error; |
1666 | 23.9k | if (isl_tab_row_is_redundant(tab, tab->con[r].index)) { |
1667 | 41 | if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0) |
1668 | 0 | goto error; |
1669 | 41 | return tab; |
1670 | 41 | } |
1671 | 23.8k | |
1672 | 23.8k | if (restore_lexmin(tab) < 0) |
1673 | 0 | goto error; |
1674 | 23.8k | if (!tab->empty && tab->con[r].is_row23.4k && |
1675 | 23.8k | isl_tab_row_is_redundant(tab, tab->con[r].index)18.4k ) |
1676 | 0 | if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0) |
1677 | 0 | goto error; |
1678 | 23.8k | return tab; |
1679 | 0 | error: |
1680 | 0 | isl_tab_free(tab); |
1681 | 0 | return NULL; |
1682 | 23.8k | } |
1683 | | |
1684 | | /* Check if the coefficients of the parameters are all integral. |
1685 | | */ |
1686 | | static int integer_parameter(struct isl_tab *tab, int row) |
1687 | 24.6k | { |
1688 | 24.6k | int i; |
1689 | 24.6k | int col; |
1690 | 24.6k | unsigned off = 2 + tab->M; |
1691 | 24.6k | |
1692 | 114k | for (i = 0; i < tab->n_param; ++i89.4k ) { |
1693 | 90.1k | /* Eliminated parameter */ |
1694 | 90.1k | if (tab->var[i].is_row) |
1695 | 38.7k | continue; |
1696 | 51.4k | col = tab->var[i].index; |
1697 | 51.4k | if (!isl_int_is_divisible_by(tab->mat->row[row][off + col], |
1698 | 51.4k | tab->mat->row[row][0])) |
1699 | 51.4k | return 0742 ; |
1700 | 51.4k | } |
1701 | 32.7k | for (i = 0; 23.9k i < tab->n_div; ++i8.80k ) { |
1702 | 8.88k | if (tab->var[tab->n_var - tab->n_div + i].is_row) |
1703 | 2.32k | continue; |
1704 | 6.56k | col = tab->var[tab->n_var - tab->n_div + i].index; |
1705 | 6.56k | if (!isl_int_is_divisible_by(tab->mat->row[row][off + col], |
1706 | 6.56k | tab->mat->row[row][0])) |
1707 | 6.56k | return 082 ; |
1708 | 6.56k | } |
1709 | 23.9k | return 123.8k ; |
1710 | 23.9k | } |
1711 | | |
1712 | | /* Check if the coefficients of the non-parameter variables are all integral. |
1713 | | */ |
1714 | | static int integer_variable(struct isl_tab *tab, int row) |
1715 | 1.36k | { |
1716 | 1.36k | int i; |
1717 | 1.36k | unsigned off = 2 + tab->M; |
1718 | 1.36k | |
1719 | 4.54k | for (i = tab->n_dead; i < tab->n_col; ++i3.18k ) { |
1720 | 4.42k | if (col_is_parameter_var(tab, i)) |
1721 | 2.82k | continue; |
1722 | 1.60k | if (!isl_int_is_divisible_by(tab->mat->row[row][off + i], |
1723 | 1.60k | tab->mat->row[row][0])) |
1724 | 1.60k | return 01.24k ; |
1725 | 1.60k | } |
1726 | 1.36k | return 1117 ; |
1727 | 1.36k | } |
1728 | | |
1729 | | /* Check if the constant term is integral. |
1730 | | */ |
1731 | | static int integer_constant(struct isl_tab *tab, int row) |
1732 | 24.6k | { |
1733 | 24.6k | return isl_int_is_divisible_by(tab->mat->row[row][1], |
1734 | 24.6k | tab->mat->row[row][0]); |
1735 | 24.6k | } |
1736 | | |
1737 | | #define I_CST 1 << 0 |
1738 | | #define I_PAR 1 << 1 |
1739 | | #define I_VAR 1 << 2 |
1740 | | |
1741 | | /* Check for next (non-parameter) variable after "var" (first if var == -1) |
1742 | | * that is non-integer and therefore requires a cut and return |
1743 | | * the index of the variable. |
1744 | | * For parametric tableaus, there are three parts in a row, |
1745 | | * the constant, the coefficients of the parameters and the rest. |
1746 | | * For each part, we check whether the coefficients in that part |
1747 | | * are all integral and if so, set the corresponding flag in *f. |
1748 | | * If the constant and the parameter part are integral, then the |
1749 | | * current sample value is integral and no cut is required |
1750 | | * (irrespective of whether the variable part is integral). |
1751 | | */ |
1752 | | static int next_non_integer_var(struct isl_tab *tab, int var, int *f) |
1753 | 9.60k | { |
1754 | 9.60k | var = var < 0 ? tab->n_param : var + 10 ; |
1755 | 9.60k | |
1756 | 39.3k | for (; var < tab->n_var - tab->n_div; ++var29.7k ) { |
1757 | 31.0k | int flags = 0; |
1758 | 31.0k | int row; |
1759 | 31.0k | if (!tab->var[var].is_row) |
1760 | 6.39k | continue; |
1761 | 24.6k | row = tab->var[var].index; |
1762 | 24.6k | if (integer_constant(tab, row)) |
1763 | 24.6k | ISL_FL_SET23.7k (flags, I_CST); |
1764 | 24.6k | if (integer_parameter(tab, row)) |
1765 | 24.6k | ISL_FL_SET23.8k (flags, I_PAR); |
1766 | 24.6k | if (ISL_FL_ISSET(flags, I_CST) && ISL_FL_ISSET23.7k (flags, I_PAR)) |
1767 | 24.6k | continue23.3k ; |
1768 | 1.36k | if (integer_variable(tab, row)) |
1769 | 1.36k | ISL_FL_SET117 (flags, I_VAR); |
1770 | 1.36k | *f = flags; |
1771 | 1.36k | return var; |
1772 | 1.36k | } |
1773 | 9.60k | return -18.24k ; |
1774 | 9.60k | } |
1775 | | |
1776 | | /* Check for first (non-parameter) variable that is non-integer and |
1777 | | * therefore requires a cut and return the corresponding row. |
1778 | | * For parametric tableaus, there are three parts in a row, |
1779 | | * the constant, the coefficients of the parameters and the rest. |
1780 | | * For each part, we check whether the coefficients in that part |
1781 | | * are all integral and if so, set the corresponding flag in *f. |
1782 | | * If the constant and the parameter part are integral, then the |
1783 | | * current sample value is integral and no cut is required |
1784 | | * (irrespective of whether the variable part is integral). |
1785 | | */ |
1786 | | static int first_non_integer_row(struct isl_tab *tab, int *f) |
1787 | 8.82k | { |
1788 | 8.82k | int var = next_non_integer_var(tab, -1, f); |
1789 | 8.82k | |
1790 | 8.82k | return var < 0 ? -17.51k : tab->var[var].index1.30k ; |
1791 | 8.82k | } |
1792 | | |
1793 | | /* Add a (non-parametric) cut to cut away the non-integral sample |
1794 | | * value of the given row. |
1795 | | * |
1796 | | * If the row is given by |
1797 | | * |
1798 | | * m r = f + \sum_i a_i y_i |
1799 | | * |
1800 | | * then the cut is |
1801 | | * |
1802 | | * c = - {-f/m} + \sum_i {a_i/m} y_i >= 0 |
1803 | | * |
1804 | | * The big parameter, if any, is ignored, since it is assumed to be big |
1805 | | * enough to be divisible by any integer. |
1806 | | * If the tableau is actually a parametric tableau, then this function |
1807 | | * is only called when all coefficients of the parameters are integral. |
1808 | | * The cut therefore has zero coefficients for the parameters. |
1809 | | * |
1810 | | * The current value is known to be negative, so row_sign, if it |
1811 | | * exists, is set accordingly. |
1812 | | * |
1813 | | * Return the row of the cut or -1. |
1814 | | */ |
1815 | | static int add_cut(struct isl_tab *tab, int row) |
1816 | 536 | { |
1817 | 536 | int i; |
1818 | 536 | int r; |
1819 | 536 | isl_int *r_row; |
1820 | 536 | unsigned off = 2 + tab->M; |
1821 | 536 | |
1822 | 536 | if (isl_tab_extend_cons(tab, 1) < 0) |
1823 | 0 | return -1; |
1824 | 536 | r = isl_tab_allocate_con(tab); |
1825 | 536 | if (r < 0) |
1826 | 0 | return -1; |
1827 | 536 | |
1828 | 536 | r_row = tab->mat->row[tab->con[r].index]; |
1829 | 536 | isl_int_set(r_row[0], tab->mat->row[row][0]); |
1830 | 536 | isl_int_neg(r_row[1], tab->mat->row[row][1]); |
1831 | 536 | isl_int_fdiv_r(r_row[1], r_row[1], tab->mat->row[row][0]); |
1832 | 536 | isl_int_neg(r_row[1], r_row[1]); |
1833 | 536 | if (tab->M) |
1834 | 536 | isl_int_set_si482 (r_row[2], 0); |
1835 | 4.90k | for (i = 0; i < tab->n_col; ++i4.37k ) |
1836 | 4.37k | isl_int_fdiv_r(r_row[off + i], |
1837 | 536 | tab->mat->row[row][off + i], tab->mat->row[row][0]); |
1838 | 536 | |
1839 | 536 | tab->con[r].is_nonneg = 1; |
1840 | 536 | if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0) |
1841 | 0 | return -1; |
1842 | 536 | if (tab->row_sign) |
1843 | 482 | tab->row_sign[tab->con[r].index] = isl_tab_row_neg; |
1844 | 536 | |
1845 | 536 | return tab->con[r].index; |
1846 | 536 | } |
1847 | | |
1848 | 0 | #define CUT_ALL 1 |
1849 | 1.22k | #define CUT_ONE 0 |
1850 | | |
1851 | | /* Given a non-parametric tableau, add cuts until an integer |
1852 | | * sample point is obtained or until the tableau is determined |
1853 | | * to be integer infeasible. |
1854 | | * As long as there is any non-integer value in the sample point, |
1855 | | * we add appropriate cuts, if possible, for each of these |
1856 | | * non-integer values and then resolve the violated |
1857 | | * cut constraints using restore_lexmin. |
1858 | | * If one of the corresponding rows is equal to an integral |
1859 | | * combination of variables/constraints plus a non-integral constant, |
1860 | | * then there is no way to obtain an integer point and we return |
1861 | | * a tableau that is marked empty. |
1862 | | * The parameter cutting_strategy controls the strategy used when adding cuts |
1863 | | * to remove non-integer points. CUT_ALL adds all possible cuts |
1864 | | * before continuing the search. CUT_ONE adds only one cut at a time. |
1865 | | */ |
1866 | | static struct isl_tab *cut_to_integer_lexmin(struct isl_tab *tab, |
1867 | | int cutting_strategy) |
1868 | 1.17k | { |
1869 | 1.17k | int var; |
1870 | 1.17k | int row; |
1871 | 1.17k | int flags; |
1872 | 1.17k | |
1873 | 1.17k | if (!tab) |
1874 | 0 | return NULL; |
1875 | 1.17k | if (tab->empty) |
1876 | 446 | return tab; |
1877 | 727 | |
1878 | 779 | while (727 (var = next_non_integer_var(tab, -1, &flags)) != -1) { |
1879 | 54 | do { |
1880 | 54 | if (ISL_FL_ISSET(flags, I_VAR)) { |
1881 | 0 | if (isl_tab_mark_empty(tab) < 0) |
1882 | 0 | goto error; |
1883 | 0 | return tab; |
1884 | 0 | } |
1885 | 54 | row = tab->var[var].index; |
1886 | 54 | row = add_cut(tab, row); |
1887 | 54 | if (row < 0) |
1888 | 0 | goto error; |
1889 | 54 | if (cutting_strategy == CUT_ONE) |
1890 | 54 | break; |
1891 | 0 | } while ((var = next_non_integer_var(tab, var, &flags)) != -1); |
1892 | 54 | if (restore_lexmin(tab) < 0) |
1893 | 0 | goto error; |
1894 | 54 | if (tab->empty) |
1895 | 2 | break; |
1896 | 54 | } |
1897 | 727 | return tab; |
1898 | 0 | error: |
1899 | 0 | isl_tab_free(tab); |
1900 | 0 | return NULL; |
1901 | 727 | } |
1902 | | |
1903 | | /* Check whether all the currently active samples also satisfy the inequality |
1904 | | * "ineq" (treated as an equality if eq is set). |
1905 | | * Remove those samples that do not. |
1906 | | */ |
1907 | | static struct isl_tab *check_samples(struct isl_tab *tab, isl_int *ineq, int eq) |
1908 | 15.2k | { |
1909 | 15.2k | int i; |
1910 | 15.2k | isl_int v; |
1911 | 15.2k | |
1912 | 15.2k | if (!tab) |
1913 | 0 | return NULL; |
1914 | 15.2k | |
1915 | 15.2k | isl_assert(tab->mat->ctx, tab->bmap, goto error); |
1916 | 15.2k | isl_assert(tab->mat->ctx, tab->samples, goto error); |
1917 | 15.2k | isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, goto error); |
1918 | 15.2k | |
1919 | 15.2k | isl_int_init(v); |
1920 | 38.0k | for (i = tab->n_outside; i < tab->n_sample; ++i22.8k ) { |
1921 | 22.8k | int sgn; |
1922 | 22.8k | isl_seq_inner_product(ineq, tab->samples->row[i], |
1923 | 22.8k | 1 + tab->n_var, &v); |
1924 | 22.8k | sgn = isl_int_sgn(v); |
1925 | 22.8k | if (eq ? (sgn == 0)9.49k : (sgn >= 0)13.3k ) |
1926 | 16.1k | continue; |
1927 | 6.69k | tab = isl_tab_drop_sample(tab, i); |
1928 | 6.69k | if (!tab) |
1929 | 0 | break; |
1930 | 6.69k | } |
1931 | 15.2k | isl_int_clear(v); |
1932 | 15.2k | |
1933 | 15.2k | return tab; |
1934 | 0 | error: |
1935 | 0 | isl_tab_free(tab); |
1936 | 0 | return NULL; |
1937 | 15.2k | } |
1938 | | |
1939 | | /* Check whether the sample value of the tableau is finite, |
1940 | | * i.e., either the tableau does not use a big parameter, or |
1941 | | * all values of the variables are equal to the big parameter plus |
1942 | | * some constant. This constant is the actual sample value. |
1943 | | */ |
1944 | | static int sample_is_finite(struct isl_tab *tab) |
1945 | 0 | { |
1946 | 0 | int i; |
1947 | 0 |
|
1948 | 0 | if (!tab->M) |
1949 | 0 | return 1; |
1950 | 0 | |
1951 | 0 | for (i = 0; i < tab->n_var; ++i) { |
1952 | 0 | int row; |
1953 | 0 | if (!tab->var[i].is_row) |
1954 | 0 | return 0; |
1955 | 0 | row = tab->var[i].index; |
1956 | 0 | if (isl_int_ne(tab->mat->row[row][0], tab->mat->row[row][2])) |
1957 | 0 | return 0; |
1958 | 0 | } |
1959 | 0 | return 1; |
1960 | 0 | } |
1961 | | |
1962 | | /* Check if the context tableau of sol has any integer points. |
1963 | | * Leave tab in empty state if no integer point can be found. |
1964 | | * If an integer point can be found and if moreover it is finite, |
1965 | | * then it is added to the list of sample values. |
1966 | | * |
1967 | | * This function is only called when none of the currently active sample |
1968 | | * values satisfies the most recently added constraint. |
1969 | | */ |
1970 | | static struct isl_tab *check_integer_feasible(struct isl_tab *tab) |
1971 | 0 | { |
1972 | 0 | struct isl_tab_undo *snap; |
1973 | 0 |
|
1974 | 0 | if (!tab) |
1975 | 0 | return NULL; |
1976 | 0 | |
1977 | 0 | snap = isl_tab_snap(tab); |
1978 | 0 | if (isl_tab_push_basis(tab) < 0) |
1979 | 0 | goto error; |
1980 | 0 | |
1981 | 0 | tab = cut_to_integer_lexmin(tab, CUT_ALL); |
1982 | 0 | if (!tab) |
1983 | 0 | goto error; |
1984 | 0 | |
1985 | 0 | if (!tab->empty && sample_is_finite(tab)) { |
1986 | 0 | struct isl_vec *sample; |
1987 | 0 |
|
1988 | 0 | sample = isl_tab_get_sample_value(tab); |
1989 | 0 |
|
1990 | 0 | if (isl_tab_add_sample(tab, sample) < 0) |
1991 | 0 | goto error; |
1992 | 0 | } |
1993 | 0 | |
1994 | 0 | if (!tab->empty && isl_tab_rollback(tab, snap) < 0) |
1995 | 0 | goto error; |
1996 | 0 | |
1997 | 0 | return tab; |
1998 | 0 | error: |
1999 | 0 | isl_tab_free(tab); |
2000 | 0 | return NULL; |
2001 | 0 | } |
2002 | | |
2003 | | /* Check if any of the currently active sample values satisfies |
2004 | | * the inequality "ineq" (an equality if eq is set). |
2005 | | */ |
2006 | | static int tab_has_valid_sample(struct isl_tab *tab, isl_int *ineq, int eq) |
2007 | 28.4k | { |
2008 | 28.4k | int i; |
2009 | 28.4k | isl_int v; |
2010 | 28.4k | |
2011 | 28.4k | if (!tab) |
2012 | 0 | return -1; |
2013 | 28.4k | |
2014 | 28.4k | isl_assert(tab->mat->ctx, tab->bmap, return -1); |
2015 | 28.4k | isl_assert(tab->mat->ctx, tab->samples, return -1); |
2016 | 28.4k | isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, return -1); |
2017 | 28.4k | |
2018 | 28.4k | isl_int_init(v); |
2019 | 47.4k | for (i = tab->n_outside; i < tab->n_sample; ++i18.9k ) { |
2020 | 28.4k | int sgn; |
2021 | 28.4k | isl_seq_inner_product(ineq, tab->samples->row[i], |
2022 | 28.4k | 1 + tab->n_var, &v); |
2023 | 28.4k | sgn = isl_int_sgn(v); |
2024 | 28.4k | if (eq ? (sgn == 0)9.41k : (sgn >= 0)19.0k ) |
2025 | 9.53k | break; |
2026 | 28.4k | } |
2027 | 28.4k | isl_int_clear(v); |
2028 | 28.4k | |
2029 | 28.4k | return i < tab->n_sample; |
2030 | 28.4k | } |
2031 | | |
2032 | | /* Insert a div specified by "div" to the tableau "tab" at position "pos" and |
2033 | | * return isl_bool_true if the div is obviously non-negative. |
2034 | | */ |
2035 | | static isl_bool context_tab_insert_div(struct isl_tab *tab, int pos, |
2036 | | __isl_keep isl_vec *div, |
2037 | | isl_stat (*add_ineq)(void *user, isl_int *), void *user) |
2038 | 759 | { |
2039 | 759 | int i; |
2040 | 759 | int r; |
2041 | 759 | struct isl_mat *samples; |
2042 | 759 | int nonneg; |
2043 | 759 | |
2044 | 759 | r = isl_tab_insert_div(tab, pos, div, add_ineq, user); |
2045 | 759 | if (r < 0) |
2046 | 0 | return isl_bool_error; |
2047 | 759 | nonneg = tab->var[r].is_nonneg; |
2048 | 759 | tab->var[r].frozen = 1; |
2049 | 759 | |
2050 | 759 | samples = isl_mat_extend(tab->samples, |
2051 | 759 | tab->n_sample, 1 + tab->n_var); |
2052 | 759 | tab->samples = samples; |
2053 | 759 | if (!samples) |
2054 | 0 | return isl_bool_error; |
2055 | 2.55k | for (i = tab->n_outside; 759 i < samples->n_row; ++i1.79k ) { |
2056 | 1.79k | isl_seq_inner_product(div->el + 1, samples->row[i], |
2057 | 1.79k | div->size - 1, &samples->row[i][samples->n_col - 1]); |
2058 | 1.79k | isl_int_fdiv_q(samples->row[i][samples->n_col - 1], |
2059 | 1.79k | samples->row[i][samples->n_col - 1], div->el[0]); |
2060 | 1.79k | } |
2061 | 759 | tab->samples = isl_mat_move_cols(tab->samples, 1 + pos, |
2062 | 759 | 1 + tab->n_var - 1, 1); |
2063 | 759 | if (!tab->samples) |
2064 | 0 | return isl_bool_error; |
2065 | 759 | |
2066 | 759 | return nonneg; |
2067 | 759 | } |
2068 | | |
2069 | | /* Add a div specified by "div" to both the main tableau and |
2070 | | * the context tableau. In case of the main tableau, we only |
2071 | | * need to add an extra div. In the context tableau, we also |
2072 | | * need to express the meaning of the div. |
2073 | | * Return the index of the div or -1 if anything went wrong. |
2074 | | * |
2075 | | * The new integer division is added before any unknown integer |
2076 | | * divisions in the context to ensure that it does not get |
2077 | | * equated to some linear combination involving unknown integer |
2078 | | * divisions. |
2079 | | */ |
2080 | | static int add_div(struct isl_tab *tab, struct isl_context *context, |
2081 | | __isl_keep isl_vec *div) |
2082 | 759 | { |
2083 | 759 | int r; |
2084 | 759 | int pos; |
2085 | 759 | isl_bool nonneg; |
2086 | 759 | struct isl_tab *context_tab = context->op->peek_tab(context); |
2087 | 759 | |
2088 | 759 | if (!tab || !context_tab) |
2089 | 0 | goto error; |
2090 | 759 | |
2091 | 759 | pos = context_tab->n_var - context->n_unknown; |
2092 | 759 | if ((nonneg = context->op->insert_div(context, pos, div)) < 0) |
2093 | 0 | goto error; |
2094 | 759 | |
2095 | 759 | if (!context->op->is_ok(context)) |
2096 | 0 | goto error; |
2097 | 759 | |
2098 | 759 | pos = tab->n_var - context->n_unknown; |
2099 | 759 | if (isl_tab_extend_vars(tab, 1) < 0) |
2100 | 0 | goto error; |
2101 | 759 | r = isl_tab_insert_var(tab, pos); |
2102 | 759 | if (r < 0) |
2103 | 0 | goto error; |
2104 | 759 | if (nonneg) |
2105 | 105 | tab->var[r].is_nonneg = 1; |
2106 | 759 | tab->var[r].frozen = 1; |
2107 | 759 | tab->n_div++; |
2108 | 759 | |
2109 | 759 | return tab->n_div - 1 - context->n_unknown; |
2110 | 0 | error: |
2111 | 0 | context->op->invalidate(context); |
2112 | 0 | return -1; |
2113 | 759 | } |
2114 | | |
2115 | | static int find_div(struct isl_tab *tab, isl_int *div, isl_int denom) |
2116 | 824 | { |
2117 | 824 | int i; |
2118 | 824 | unsigned total = isl_basic_map_total_dim(tab->bmap); |
2119 | 824 | |
2120 | 1.94k | for (i = 0; i < tab->bmap->n_div; ++i1.12k ) { |
2121 | 1.18k | if (isl_int_ne(tab->bmap->div[i][0], denom)) |
2122 | 1.18k | continue1.04k ; |
2123 | 147 | if (!isl_seq_eq(tab->bmap->div[i] + 1, div, 1 + total)) |
2124 | 82 | continue; |
2125 | 65 | return i; |
2126 | 65 | } |
2127 | 824 | return -1759 ; |
2128 | 824 | } |
2129 | | |
2130 | | /* Return the index of a div that corresponds to "div". |
2131 | | * We first check if we already have such a div and if not, we create one. |
2132 | | */ |
2133 | | static int get_div(struct isl_tab *tab, struct isl_context *context, |
2134 | | struct isl_vec *div) |
2135 | 824 | { |
2136 | 824 | int d; |
2137 | 824 | struct isl_tab *context_tab = context->op->peek_tab(context); |
2138 | 824 | |
2139 | 824 | if (!context_tab) |
2140 | 0 | return -1; |
2141 | 824 | |
2142 | 824 | d = find_div(context_tab, div->el + 1, div->el[0]); |
2143 | 824 | if (d != -1) |
2144 | 65 | return d; |
2145 | 759 | |
2146 | 759 | return add_div(tab, context, div); |
2147 | 759 | } |
2148 | | |
2149 | | /* Add a parametric cut to cut away the non-integral sample value |
2150 | | * of the given row. |
2151 | | * Let a_i be the coefficients of the constant term and the parameters |
2152 | | * and let b_i be the coefficients of the variables or constraints |
2153 | | * in basis of the tableau. |
2154 | | * Let q be the div q = floor(\sum_i {-a_i} y_i). |
2155 | | * |
2156 | | * The cut is expressed as |
2157 | | * |
2158 | | * c = \sum_i -{-a_i} y_i + \sum_i {b_i} x_i + q >= 0 |
2159 | | * |
2160 | | * If q did not already exist in the context tableau, then it is added first. |
2161 | | * If q is in a column of the main tableau then the "+ q" can be accomplished |
2162 | | * by setting the corresponding entry to the denominator of the constraint. |
2163 | | * If q happens to be in a row of the main tableau, then the corresponding |
2164 | | * row needs to be added instead (taking care of the denominators). |
2165 | | * Note that this is very unlikely, but perhaps not entirely impossible. |
2166 | | * |
2167 | | * The current value of the cut is known to be negative (or at least |
2168 | | * non-positive), so row_sign is set accordingly. |
2169 | | * |
2170 | | * Return the row of the cut or -1. |
2171 | | */ |
2172 | | static int add_parametric_cut(struct isl_tab *tab, int row, |
2173 | | struct isl_context *context) |
2174 | 707 | { |
2175 | 707 | struct isl_vec *div; |
2176 | 707 | int d; |
2177 | 707 | int i; |
2178 | 707 | int r; |
2179 | 707 | isl_int *r_row; |
2180 | 707 | int col; |
2181 | 707 | int n; |
2182 | 707 | unsigned off = 2 + tab->M; |
2183 | 707 | |
2184 | 707 | if (!context) |
2185 | 0 | return -1; |
2186 | 707 | |
2187 | 707 | div = get_row_parameter_div(tab, row); |
2188 | 707 | if (!div) |
2189 | 0 | return -1; |
2190 | 707 | |
2191 | 707 | n = tab->n_div - context->n_unknown; |
2192 | 707 | d = context->op->get_div(context, tab, div); |
2193 | 707 | isl_vec_free(div); |
2194 | 707 | if (d < 0) |
2195 | 0 | return -1; |
2196 | 707 | |
2197 | 707 | if (isl_tab_extend_cons(tab, 1) < 0) |
2198 | 0 | return -1; |
2199 | 707 | r = isl_tab_allocate_con(tab); |
2200 | 707 | if (r < 0) |
2201 | 0 | return -1; |
2202 | 707 | |
2203 | 707 | r_row = tab->mat->row[tab->con[r].index]; |
2204 | 707 | isl_int_set(r_row[0], tab->mat->row[row][0]); |
2205 | 707 | isl_int_neg(r_row[1], tab->mat->row[row][1]); |
2206 | 707 | isl_int_fdiv_r(r_row[1], r_row[1], tab->mat->row[row][0]); |
2207 | 707 | isl_int_neg(r_row[1], r_row[1]); |
2208 | 707 | if (tab->M) |
2209 | 707 | isl_int_set_si(r_row[2], 0); |
2210 | 2.92k | for (i = 0; i < tab->n_param; ++i2.21k ) { |
2211 | 2.21k | if (tab->var[i].is_row) |
2212 | 87 | continue; |
2213 | 2.12k | col = tab->var[i].index; |
2214 | 2.12k | isl_int_neg(r_row[off + col], tab->mat->row[row][off + col]); |
2215 | 2.12k | isl_int_fdiv_r(r_row[off + col], r_row[off + col], |
2216 | 2.12k | tab->mat->row[row][0]); |
2217 | 2.12k | isl_int_neg(r_row[off + col], r_row[off + col]); |
2218 | 2.12k | } |
2219 | 2.48k | for (i = 0; i < tab->n_div; ++i1.78k ) { |
2220 | 1.78k | if (tab->var[tab->n_var - tab->n_div + i].is_row) |
2221 | 150 | continue; |
2222 | 1.63k | col = tab->var[tab->n_var - tab->n_div + i].index; |
2223 | 1.63k | isl_int_neg(r_row[off + col], tab->mat->row[row][off + col]); |
2224 | 1.63k | isl_int_fdiv_r(r_row[off + col], r_row[off + col], |
2225 | 1.63k | tab->mat->row[row][0]); |
2226 | 1.63k | isl_int_neg(r_row[off + col], r_row[off + col]); |
2227 | 1.63k | } |
2228 | 6.31k | for (i = 0; i < tab->n_col; ++i5.60k ) { |
2229 | 5.60k | if (tab->col_var[i] >= 0 && |
2230 | 5.60k | (3.76k tab->col_var[i] < tab->n_param3.76k || |
2231 | 3.76k | tab->col_var[i] >= tab->n_var - tab->n_div1.63k )) |
2232 | 3.76k | continue; |
2233 | 1.84k | isl_int_fdiv_r(r_row[off + i], |
2234 | 1.84k | tab->mat->row[row][off + i], tab->mat->row[row][0]); |
2235 | 1.84k | } |
2236 | 707 | if (tab->var[tab->n_var - tab->n_div + d].is_row) { |
2237 | 1 | isl_int gcd; |
2238 | 1 | int d_row = tab->var[tab->n_var - tab->n_div + d].index; |
2239 | 1 | isl_int_init(gcd); |
2240 | 1 | isl_int_gcd(gcd, tab->mat->row[d_row][0], r_row[0]); |
2241 | 1 | isl_int_divexact(r_row[0], r_row[0], gcd); |
2242 | 1 | isl_int_divexact(gcd, tab->mat->row[d_row][0], gcd); |
2243 | 1 | isl_seq_combine(r_row + 1, gcd, r_row + 1, |
2244 | 1 | r_row[0], tab->mat->row[d_row] + 1, |
2245 | 1 | off - 1 + tab->n_col); |
2246 | 1 | isl_int_mul(r_row[0], r_row[0], tab->mat->row[d_row][0]); |
2247 | 1 | isl_int_clear(gcd); |
2248 | 706 | } else { |
2249 | 706 | col = tab->var[tab->n_var - tab->n_div + d].index; |
2250 | 706 | isl_int_set(r_row[off + col], tab->mat->row[row][0]); |
2251 | 706 | } |
2252 | 707 | |
2253 | 707 | tab->con[r].is_nonneg = 1; |
2254 | 707 | if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0) |
2255 | 0 | return -1; |
2256 | 707 | if (tab->row_sign) |
2257 | 707 | tab->row_sign[tab->con[r].index] = isl_tab_row_neg; |
2258 | 707 | |
2259 | 707 | row = tab->con[r].index; |
2260 | 707 | |
2261 | 707 | if (d >= n && context->op->detect_equalities(context, tab) < 0692 ) |
2262 | 0 | return -1; |
2263 | 707 | |
2264 | 707 | return row; |
2265 | 707 | } |
2266 | | |
2267 | | /* Construct a tableau for bmap that can be used for computing |
2268 | | * the lexicographic minimum (or maximum) of bmap. |
2269 | | * If not NULL, then dom is the domain where the minimum |
2270 | | * should be computed. In this case, we set up a parametric |
2271 | | * tableau with row signs (initialized to "unknown"). |
2272 | | * If M is set, then the tableau will use a big parameter. |
2273 | | * If max is set, then a maximum should be computed instead of a minimum. |
2274 | | * This means that for each variable x, the tableau will contain the variable |
2275 | | * x' = M - x, rather than x' = M + x. This in turn means that the coefficient |
2276 | | * of the variables in all constraints are negated prior to adding them |
2277 | | * to the tableau. |
2278 | | */ |
2279 | | static __isl_give struct isl_tab *tab_for_lexmin(__isl_keep isl_basic_map *bmap, |
2280 | | __isl_keep isl_basic_set *dom, unsigned M, int max) |
2281 | 7.60k | { |
2282 | 7.60k | int i; |
2283 | 7.60k | struct isl_tab *tab; |
2284 | 7.60k | unsigned n_var; |
2285 | 7.60k | unsigned o_var; |
2286 | 7.60k | |
2287 | 7.60k | tab = isl_tab_alloc(bmap->ctx, 2 * bmap->n_eq + bmap->n_ineq + 1, |
2288 | 7.60k | isl_basic_map_total_dim(bmap), M); |
2289 | 7.60k | if (!tab) |
2290 | 0 | return NULL; |
2291 | 7.60k | |
2292 | 7.60k | tab->rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL); |
2293 | 7.60k | if (dom) { |
2294 | 7.16k | tab->n_param = isl_basic_set_total_dim(dom) - dom->n_div; |
2295 | 7.16k | tab->n_div = dom->n_div; |
2296 | 7.16k | tab->row_sign = isl_calloc_array(bmap->ctx, |
2297 | 7.16k | enum isl_tab_row_sign, tab->mat->n_row); |
2298 | 7.16k | if (tab->mat->n_row && !tab->row_sign) |
2299 | 0 | goto error; |
2300 | 7.60k | } |
2301 | 7.60k | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) { |
2302 | 0 | if (isl_tab_mark_empty(tab) < 0) |
2303 | 0 | goto error; |
2304 | 0 | return tab; |
2305 | 0 | } |
2306 | 7.60k | |
2307 | 30.7k | for (i = tab->n_param; 7.60k i < tab->n_var - tab->n_div; ++i23.1k ) { |
2308 | 23.1k | tab->var[i].is_nonneg = 1; |
2309 | 23.1k | tab->var[i].frozen = 1; |
2310 | 23.1k | } |
2311 | 7.60k | o_var = 1 + tab->n_param; |
2312 | 7.60k | n_var = tab->n_var - tab->n_param - tab->n_div; |
2313 | 31.5k | for (i = 0; i < bmap->n_eq; ++i23.9k ) { |
2314 | 23.9k | if (max) |
2315 | 18.3k | isl_seq_neg(bmap->eq[i] + o_var, |
2316 | 18.3k | bmap->eq[i] + o_var, n_var); |
2317 | 23.9k | tab = add_lexmin_valid_eq(tab, bmap->eq[i]); |
2318 | 23.9k | if (max) |
2319 | 18.3k | isl_seq_neg(bmap->eq[i] + o_var, |
2320 | 18.3k | bmap->eq[i] + o_var, n_var); |
2321 | 23.9k | if (!tab || tab->empty) |
2322 | 0 | return tab; |
2323 | 23.9k | } |
2324 | 7.60k | if (bmap->n_eq && restore_lexmin(tab) < 06.53k ) |
2325 | 0 | goto error; |
2326 | 30.7k | for (i = 0; 7.60k i < bmap->n_ineq; ++i23.1k ) { |
2327 | 23.1k | if (max) |
2328 | 14.1k | isl_seq_neg(bmap->ineq[i] + o_var, |
2329 | 14.1k | bmap->ineq[i] + o_var, n_var); |
2330 | 23.1k | tab = add_lexmin_ineq(tab, bmap->ineq[i]); |
2331 | 23.1k | if (max) |
2332 | 14.1k | isl_seq_neg(bmap->ineq[i] + o_var, |
2333 | 14.1k | bmap->ineq[i] + o_var, n_var); |
2334 | 23.1k | if (!tab || tab->empty) |
2335 | 0 | return tab; |
2336 | 23.1k | } |
2337 | 7.60k | return tab; |
2338 | 0 | error: |
2339 | 0 | isl_tab_free(tab); |
2340 | 0 | return NULL; |
2341 | 7.60k | } |
2342 | | |
2343 | | /* Given a main tableau where more than one row requires a split, |
2344 | | * determine and return the "best" row to split on. |
2345 | | * |
2346 | | * If any of the rows requiring a split only involves |
2347 | | * variables that also appear in the context tableau, |
2348 | | * then the negative part is guaranteed not to have a solution. |
2349 | | * It is therefore best to split on any of these rows first. |
2350 | | * |
2351 | | * Otherwise, |
2352 | | * given two rows in the main tableau, if the inequality corresponding |
2353 | | * to the first row is redundant with respect to that of the second row |
2354 | | * in the current tableau, then it is better to split on the second row, |
2355 | | * since in the positive part, both rows will be positive. |
2356 | | * (In the negative part a pivot will have to be performed and just about |
2357 | | * anything can happen to the sign of the other row.) |
2358 | | * |
2359 | | * As a simple heuristic, we therefore select the row that makes the most |
2360 | | * of the other rows redundant. |
2361 | | * |
2362 | | * Perhaps it would also be useful to look at the number of constraints |
2363 | | * that conflict with any given constraint. |
2364 | | * |
2365 | | * best is the best row so far (-1 when we have not found any row yet). |
2366 | | * best_r is the number of other rows made redundant by row best. |
2367 | | * When best is still -1, bset_r is meaningless, but it is initialized |
2368 | | * to some arbitrary value (0) anyway. Without this redundant initialization |
2369 | | * valgrind may warn about uninitialized memory accesses when isl |
2370 | | * is compiled with some versions of gcc. |
2371 | | */ |
2372 | | static int best_split(struct isl_tab *tab, struct isl_tab *context_tab) |
2373 | 287 | { |
2374 | 287 | struct isl_tab_undo *snap; |
2375 | 287 | int split; |
2376 | 287 | int row; |
2377 | 287 | int best = -1; |
2378 | 287 | int best_r = 0; |
2379 | 287 | |
2380 | 287 | if (isl_tab_extend_cons(context_tab, 2) < 0) |
2381 | 0 | return -1; |
2382 | 287 | |
2383 | 287 | snap = isl_tab_snap(context_tab); |
2384 | 287 | |
2385 | 2.50k | for (split = tab->n_redundant; split < tab->n_row; ++split2.21k ) { |
2386 | 2.34k | struct isl_tab_undo *snap2; |
2387 | 2.34k | struct isl_vec *ineq = NULL; |
2388 | 2.34k | int r = 0; |
2389 | 2.34k | int ok; |
2390 | 2.34k | |
2391 | 2.34k | if (!isl_tab_var_from_row(tab, split)->is_nonneg) |
2392 | 22 | continue; |
2393 | 2.32k | if (tab->row_sign[split] != isl_tab_row_any) |
2394 | 1.85k | continue; |
2395 | 463 | |
2396 | 463 | if (is_parametric_constant(tab, split)) |
2397 | 128 | return split; |
2398 | 335 | |
2399 | 335 | ineq = get_row_parameter_ineq(tab, split); |
2400 | 335 | if (!ineq) |
2401 | 0 | return -1; |
2402 | 335 | ok = isl_tab_add_ineq(context_tab, ineq->el) >= 0; |
2403 | 335 | isl_vec_free(ineq); |
2404 | 335 | if (!ok) |
2405 | 0 | return -1; |
2406 | 335 | |
2407 | 335 | snap2 = isl_tab_snap(context_tab); |
2408 | 335 | |
2409 | 3.83k | for (row = tab->n_redundant; row < tab->n_row; ++row3.50k ) { |
2410 | 3.50k | struct isl_tab_var *var; |
2411 | 3.50k | |
2412 | 3.50k | if (row == split) |
2413 | 335 | continue; |
2414 | 3.16k | if (!isl_tab_var_from_row(tab, row)->is_nonneg) |
2415 | 44 | continue; |
2416 | 3.12k | if (tab->row_sign[row] != isl_tab_row_any) |
2417 | 2.73k | continue; |
2418 | 386 | |
2419 | 386 | ineq = get_row_parameter_ineq(tab, row); |
2420 | 386 | if (!ineq) |
2421 | 0 | return -1; |
2422 | 386 | ok = isl_tab_add_ineq(context_tab, ineq->el) >= 0; |
2423 | 386 | isl_vec_free(ineq); |
2424 | 386 | if (!ok) |
2425 | 0 | return -1; |
2426 | 386 | var = &context_tab->con[context_tab->n_con - 1]; |
2427 | 386 | if (!context_tab->empty && |
2428 | 386 | !isl_tab_min_at_most_neg_one(context_tab, var)) |
2429 | 118 | r++; |
2430 | 386 | if (isl_tab_rollback(context_tab, snap2) < 0) |
2431 | 0 | return -1; |
2432 | 386 | } |
2433 | 335 | if (best == -1 || r > best_r174 ) { |
2434 | 171 | best = split; |
2435 | 171 | best_r = r; |
2436 | 171 | } |
2437 | 335 | if (isl_tab_rollback(context_tab, snap) < 0) |
2438 | 0 | return -1; |
2439 | 335 | } |
2440 | 287 | |
2441 | 287 | return best159 ; |
2442 | 287 | } |
2443 | | |
2444 | | static struct isl_basic_set *context_lex_peek_basic_set( |
2445 | | struct isl_context *context) |
2446 | 0 | { |
2447 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2448 | 0 | if (!clex->tab) |
2449 | 0 | return NULL; |
2450 | 0 | return isl_tab_peek_bset(clex->tab); |
2451 | 0 | } |
2452 | | |
2453 | | static struct isl_tab *context_lex_peek_tab(struct isl_context *context) |
2454 | 0 | { |
2455 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2456 | 0 | return clex->tab; |
2457 | 0 | } |
2458 | | |
2459 | | static void context_lex_add_eq(struct isl_context *context, isl_int *eq, |
2460 | | int check, int update) |
2461 | 0 | { |
2462 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2463 | 0 | if (isl_tab_extend_cons(clex->tab, 2) < 0) |
2464 | 0 | goto error; |
2465 | 0 | if (add_lexmin_eq(clex->tab, eq) < 0) |
2466 | 0 | goto error; |
2467 | 0 | if (check) { |
2468 | 0 | int v = tab_has_valid_sample(clex->tab, eq, 1); |
2469 | 0 | if (v < 0) |
2470 | 0 | goto error; |
2471 | 0 | if (!v) |
2472 | 0 | clex->tab = check_integer_feasible(clex->tab); |
2473 | 0 | } |
2474 | 0 | if (update) |
2475 | 0 | clex->tab = check_samples(clex->tab, eq, 1); |
2476 | 0 | return; |
2477 | 0 | error: |
2478 | 0 | isl_tab_free(clex->tab); |
2479 | 0 | clex->tab = NULL; |
2480 | 0 | } |
2481 | | |
2482 | | static void context_lex_add_ineq(struct isl_context *context, isl_int *ineq, |
2483 | | int check, int update) |
2484 | 0 | { |
2485 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2486 | 0 | if (isl_tab_extend_cons(clex->tab, 1) < 0) |
2487 | 0 | goto error; |
2488 | 0 | clex->tab = add_lexmin_ineq(clex->tab, ineq); |
2489 | 0 | if (check) { |
2490 | 0 | int v = tab_has_valid_sample(clex->tab, ineq, 0); |
2491 | 0 | if (v < 0) |
2492 | 0 | goto error; |
2493 | 0 | if (!v) |
2494 | 0 | clex->tab = check_integer_feasible(clex->tab); |
2495 | 0 | } |
2496 | 0 | if (update) |
2497 | 0 | clex->tab = check_samples(clex->tab, ineq, 0); |
2498 | 0 | return; |
2499 | 0 | error: |
2500 | 0 | isl_tab_free(clex->tab); |
2501 | 0 | clex->tab = NULL; |
2502 | 0 | } |
2503 | | |
2504 | | static isl_stat context_lex_add_ineq_wrap(void *user, isl_int *ineq) |
2505 | 0 | { |
2506 | 0 | struct isl_context *context = (struct isl_context *)user; |
2507 | 0 | context_lex_add_ineq(context, ineq, 0, 0); |
2508 | 0 | return context->op->is_ok(context) ? isl_stat_ok : isl_stat_error; |
2509 | 0 | } |
2510 | | |
2511 | | /* Check which signs can be obtained by "ineq" on all the currently |
2512 | | * active sample values. See row_sign for more information. |
2513 | | */ |
2514 | | static enum isl_tab_row_sign tab_ineq_sign(struct isl_tab *tab, isl_int *ineq, |
2515 | | int strict) |
2516 | 13.0k | { |
2517 | 13.0k | int i; |
2518 | 13.0k | int sgn; |
2519 | 13.0k | isl_int tmp; |
2520 | 13.0k | enum isl_tab_row_sign res = isl_tab_row_unknown; |
2521 | 13.0k | |
2522 | 13.0k | isl_assert(tab->mat->ctx, tab->samples, return isl_tab_row_unknown); |
2523 | 13.0k | isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, |
2524 | 13.0k | return isl_tab_row_unknown); |
2525 | 13.0k | |
2526 | 13.0k | isl_int_init(tmp); |
2527 | 31.1k | for (i = tab->n_outside; i < tab->n_sample; ++i18.1k ) { |
2528 | 18.5k | isl_seq_inner_product(tab->samples->row[i], ineq, |
2529 | 18.5k | 1 + tab->n_var, &tmp); |
2530 | 18.5k | sgn = isl_int_sgn(tmp); |
2531 | 18.5k | if (sgn > 0 || (8.35k sgn == 08.35k && strict5.39k )) { |
2532 | 15.0k | if (res == isl_tab_row_unknown) |
2533 | 10.6k | res = isl_tab_row_pos; |
2534 | 15.0k | if (res == isl_tab_row_neg) |
2535 | 215 | res = isl_tab_row_any; |
2536 | 15.0k | } |
2537 | 18.5k | if (sgn < 0) { |
2538 | 2.96k | if (res == isl_tab_row_unknown) |
2539 | 2.32k | res = isl_tab_row_neg; |
2540 | 2.96k | if (res == isl_tab_row_pos) |
2541 | 234 | res = isl_tab_row_any; |
2542 | 2.96k | } |
2543 | 18.5k | if (res == isl_tab_row_any) |
2544 | 449 | break; |
2545 | 18.5k | } |
2546 | 13.0k | isl_int_clear(tmp); |
2547 | 13.0k | |
2548 | 13.0k | return res; |
2549 | 13.0k | } |
2550 | | |
2551 | | static enum isl_tab_row_sign context_lex_ineq_sign(struct isl_context *context, |
2552 | | isl_int *ineq, int strict) |
2553 | 0 | { |
2554 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2555 | 0 | return tab_ineq_sign(clex->tab, ineq, strict); |
2556 | 0 | } |
2557 | | |
2558 | | /* Check whether "ineq" can be added to the tableau without rendering |
2559 | | * it infeasible. |
2560 | | */ |
2561 | | static int context_lex_test_ineq(struct isl_context *context, isl_int *ineq) |
2562 | 0 | { |
2563 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2564 | 0 | struct isl_tab_undo *snap; |
2565 | 0 | int feasible; |
2566 | 0 |
|
2567 | 0 | if (!clex->tab) |
2568 | 0 | return -1; |
2569 | 0 | |
2570 | 0 | if (isl_tab_extend_cons(clex->tab, 1) < 0) |
2571 | 0 | return -1; |
2572 | 0 | |
2573 | 0 | snap = isl_tab_snap(clex->tab); |
2574 | 0 | if (isl_tab_push_basis(clex->tab) < 0) |
2575 | 0 | return -1; |
2576 | 0 | clex->tab = add_lexmin_ineq(clex->tab, ineq); |
2577 | 0 | clex->tab = check_integer_feasible(clex->tab); |
2578 | 0 | if (!clex->tab) |
2579 | 0 | return -1; |
2580 | 0 | feasible = !clex->tab->empty; |
2581 | 0 | if (isl_tab_rollback(clex->tab, snap) < 0) |
2582 | 0 | return -1; |
2583 | 0 | |
2584 | 0 | return feasible; |
2585 | 0 | } |
2586 | | |
2587 | | static int context_lex_get_div(struct isl_context *context, struct isl_tab *tab, |
2588 | | struct isl_vec *div) |
2589 | 0 | { |
2590 | 0 | return get_div(tab, context, div); |
2591 | 0 | } |
2592 | | |
2593 | | /* Insert a div specified by "div" to the context tableau at position "pos" and |
2594 | | * return isl_bool_true if the div is obviously non-negative. |
2595 | | * context_tab_add_div will always return isl_bool_true, because all variables |
2596 | | * in a isl_context_lex tableau are non-negative. |
2597 | | * However, if we are using a big parameter in the context, then this only |
2598 | | * reflects the non-negativity of the variable used to _encode_ the |
2599 | | * div, i.e., div' = M + div, so we can't draw any conclusions. |
2600 | | */ |
2601 | | static isl_bool context_lex_insert_div(struct isl_context *context, int pos, |
2602 | | __isl_keep isl_vec *div) |
2603 | 0 | { |
2604 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2605 | 0 | isl_bool nonneg; |
2606 | 0 | nonneg = context_tab_insert_div(clex->tab, pos, div, |
2607 | 0 | context_lex_add_ineq_wrap, context); |
2608 | 0 | if (nonneg < 0) |
2609 | 0 | return isl_bool_error; |
2610 | 0 | if (clex->tab->M) |
2611 | 0 | return isl_bool_false; |
2612 | 0 | return nonneg; |
2613 | 0 | } |
2614 | | |
2615 | | static int context_lex_detect_equalities(struct isl_context *context, |
2616 | | struct isl_tab *tab) |
2617 | 0 | { |
2618 | 0 | return 0; |
2619 | 0 | } |
2620 | | |
2621 | | static int context_lex_best_split(struct isl_context *context, |
2622 | | struct isl_tab *tab) |
2623 | 0 | { |
2624 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2625 | 0 | struct isl_tab_undo *snap; |
2626 | 0 | int r; |
2627 | 0 |
|
2628 | 0 | snap = isl_tab_snap(clex->tab); |
2629 | 0 | if (isl_tab_push_basis(clex->tab) < 0) |
2630 | 0 | return -1; |
2631 | 0 | r = best_split(tab, clex->tab); |
2632 | 0 |
|
2633 | 0 | if (r >= 0 && isl_tab_rollback(clex->tab, snap) < 0) |
2634 | 0 | return -1; |
2635 | 0 | |
2636 | 0 | return r; |
2637 | 0 | } |
2638 | | |
2639 | | static int context_lex_is_empty(struct isl_context *context) |
2640 | 0 | { |
2641 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2642 | 0 | if (!clex->tab) |
2643 | 0 | return -1; |
2644 | 0 | return clex->tab->empty; |
2645 | 0 | } |
2646 | | |
2647 | | static void *context_lex_save(struct isl_context *context) |
2648 | 0 | { |
2649 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2650 | 0 | struct isl_tab_undo *snap; |
2651 | 0 |
|
2652 | 0 | snap = isl_tab_snap(clex->tab); |
2653 | 0 | if (isl_tab_push_basis(clex->tab) < 0) |
2654 | 0 | return NULL; |
2655 | 0 | if (isl_tab_save_samples(clex->tab) < 0) |
2656 | 0 | return NULL; |
2657 | 0 | |
2658 | 0 | return snap; |
2659 | 0 | } |
2660 | | |
2661 | | static void context_lex_restore(struct isl_context *context, void *save) |
2662 | 0 | { |
2663 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2664 | 0 | if (isl_tab_rollback(clex->tab, (struct isl_tab_undo *)save) < 0) { |
2665 | 0 | isl_tab_free(clex->tab); |
2666 | 0 | clex->tab = NULL; |
2667 | 0 | } |
2668 | 0 | } |
2669 | | |
2670 | | static void context_lex_discard(void *save) |
2671 | 0 | { |
2672 | 0 | } |
2673 | | |
2674 | | static int context_lex_is_ok(struct isl_context *context) |
2675 | 0 | { |
2676 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2677 | 0 | return !!clex->tab; |
2678 | 0 | } |
2679 | | |
2680 | | /* For each variable in the context tableau, check if the variable can |
2681 | | * only attain non-negative values. If so, mark the parameter as non-negative |
2682 | | * in the main tableau. This allows for a more direct identification of some |
2683 | | * cases of violated constraints. |
2684 | | */ |
2685 | | static struct isl_tab *tab_detect_nonnegative_parameters(struct isl_tab *tab, |
2686 | | struct isl_tab *context_tab) |
2687 | 7.16k | { |
2688 | 7.16k | int i; |
2689 | 7.16k | struct isl_tab_undo *snap; |
2690 | 7.16k | struct isl_vec *ineq = NULL; |
2691 | 7.16k | struct isl_tab_var *var; |
2692 | 7.16k | int n; |
2693 | 7.16k | |
2694 | 7.16k | if (context_tab->n_var == 0) |
2695 | 1.48k | return tab; |
2696 | 5.68k | |
2697 | 5.68k | ineq = isl_vec_alloc(tab->mat->ctx, 1 + context_tab->n_var); |
2698 | 5.68k | if (!ineq) |
2699 | 0 | goto error; |
2700 | 5.68k | |
2701 | 5.68k | if (isl_tab_extend_cons(context_tab, 1) < 0) |
2702 | 0 | goto error; |
2703 | 5.68k | |
2704 | 5.68k | snap = isl_tab_snap(context_tab); |
2705 | 5.68k | |
2706 | 5.68k | n = 0; |
2707 | 5.68k | isl_seq_clr(ineq->el, ineq->size); |
2708 | 28.3k | for (i = 0; i < context_tab->n_var; ++i22.6k ) { |
2709 | 22.6k | isl_int_set_si(ineq->el[1 + i], 1); |
2710 | 22.6k | if (isl_tab_add_ineq(context_tab, ineq->el) < 0) |
2711 | 0 | goto error; |
2712 | 22.6k | var = &context_tab->con[context_tab->n_con - 1]; |
2713 | 22.6k | if (!context_tab->empty && |
2714 | 22.6k | !isl_tab_min_at_most_neg_one(context_tab, var)22.3k ) { |
2715 | 16.8k | int j = i; |
2716 | 16.8k | if (i >= tab->n_param) |
2717 | 181 | j = i - tab->n_param + tab->n_var - tab->n_div; |
2718 | 16.8k | tab->var[j].is_nonneg = 1; |
2719 | 16.8k | n++; |
2720 | 16.8k | } |
2721 | 22.6k | isl_int_set_si(ineq->el[1 + i], 0); |
2722 | 22.6k | if (isl_tab_rollback(context_tab, snap) < 0) |
2723 | 0 | goto error; |
2724 | 22.6k | } |
2725 | 5.68k | |
2726 | 5.68k | if (context_tab->M && n == context_tab->n_var0 ) { |
2727 | 0 | context_tab->mat = isl_mat_drop_cols(context_tab->mat, 2, 1); |
2728 | 0 | context_tab->M = 0; |
2729 | 0 | } |
2730 | 5.68k | |
2731 | 5.68k | isl_vec_free(ineq); |
2732 | 5.68k | return tab; |
2733 | 0 | error: |
2734 | 0 | isl_vec_free(ineq); |
2735 | 0 | isl_tab_free(tab); |
2736 | 0 | return NULL; |
2737 | 5.68k | } |
2738 | | |
2739 | | static struct isl_tab *context_lex_detect_nonnegative_parameters( |
2740 | | struct isl_context *context, struct isl_tab *tab) |
2741 | 0 | { |
2742 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2743 | 0 | struct isl_tab_undo *snap; |
2744 | 0 |
|
2745 | 0 | if (!tab) |
2746 | 0 | return NULL; |
2747 | 0 | |
2748 | 0 | snap = isl_tab_snap(clex->tab); |
2749 | 0 | if (isl_tab_push_basis(clex->tab) < 0) |
2750 | 0 | goto error; |
2751 | 0 | |
2752 | 0 | tab = tab_detect_nonnegative_parameters(tab, clex->tab); |
2753 | 0 |
|
2754 | 0 | if (isl_tab_rollback(clex->tab, snap) < 0) |
2755 | 0 | goto error; |
2756 | 0 | |
2757 | 0 | return tab; |
2758 | 0 | error: |
2759 | 0 | isl_tab_free(tab); |
2760 | 0 | return NULL; |
2761 | 0 | } |
2762 | | |
2763 | | static void context_lex_invalidate(struct isl_context *context) |
2764 | 0 | { |
2765 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2766 | 0 | isl_tab_free(clex->tab); |
2767 | 0 | clex->tab = NULL; |
2768 | 0 | } |
2769 | | |
2770 | | static __isl_null struct isl_context *context_lex_free( |
2771 | | struct isl_context *context) |
2772 | 0 | { |
2773 | 0 | struct isl_context_lex *clex = (struct isl_context_lex *)context; |
2774 | 0 | isl_tab_free(clex->tab); |
2775 | 0 | free(clex); |
2776 | 0 |
|
2777 | 0 | return NULL; |
2778 | 0 | } |
2779 | | |
2780 | | struct isl_context_op isl_context_lex_op = { |
2781 | | context_lex_detect_nonnegative_parameters, |
2782 | | context_lex_peek_basic_set, |
2783 | | context_lex_peek_tab, |
2784 | | context_lex_add_eq, |
2785 | | context_lex_add_ineq, |
2786 | | context_lex_ineq_sign, |
2787 | | context_lex_test_ineq, |
2788 | | context_lex_get_div, |
2789 | | context_lex_insert_div, |
2790 | | context_lex_detect_equalities, |
2791 | | context_lex_best_split, |
2792 | | context_lex_is_empty, |
2793 | | context_lex_is_ok, |
2794 | | context_lex_save, |
2795 | | context_lex_restore, |
2796 | | context_lex_discard, |
2797 | | context_lex_invalidate, |
2798 | | context_lex_free, |
2799 | | }; |
2800 | | |
2801 | | static struct isl_tab *context_tab_for_lexmin(__isl_take isl_basic_set *bset) |
2802 | 0 | { |
2803 | 0 | struct isl_tab *tab; |
2804 | 0 |
|
2805 | 0 | if (!bset) |
2806 | 0 | return NULL; |
2807 | 0 | tab = tab_for_lexmin(bset_to_bmap(bset), NULL, 1, 0); |
2808 | 0 | if (isl_tab_track_bset(tab, bset) < 0) |
2809 | 0 | goto error; |
2810 | 0 | tab = isl_tab_init_samples(tab); |
2811 | 0 | return tab; |
2812 | 0 | error: |
2813 | 0 | isl_tab_free(tab); |
2814 | 0 | return NULL; |
2815 | 0 | } |
2816 | | |
2817 | | static struct isl_context *isl_context_lex_alloc(struct isl_basic_set *dom) |
2818 | 0 | { |
2819 | 0 | struct isl_context_lex *clex; |
2820 | 0 |
|
2821 | 0 | if (!dom) |
2822 | 0 | return NULL; |
2823 | 0 | |
2824 | 0 | clex = isl_alloc_type(dom->ctx, struct isl_context_lex); |
2825 | 0 | if (!clex) |
2826 | 0 | return NULL; |
2827 | 0 | |
2828 | 0 | clex->context.op = &isl_context_lex_op; |
2829 | 0 |
|
2830 | 0 | clex->tab = context_tab_for_lexmin(isl_basic_set_copy(dom)); |
2831 | 0 | if (restore_lexmin(clex->tab) < 0) |
2832 | 0 | goto error; |
2833 | 0 | clex->tab = check_integer_feasible(clex->tab); |
2834 | 0 | if (!clex->tab) |
2835 | 0 | goto error; |
2836 | 0 | |
2837 | 0 | return &clex->context; |
2838 | 0 | error: |
2839 | 0 | clex->context.op->free(&clex->context); |
2840 | 0 | return NULL; |
2841 | 0 | } |
2842 | | |
2843 | | /* Representation of the context when using generalized basis reduction. |
2844 | | * |
2845 | | * "shifted" contains the offsets of the unit hypercubes that lie inside the |
2846 | | * context. Any rational point in "shifted" can therefore be rounded |
2847 | | * up to an integer point in the context. |
2848 | | * If the context is constrained by any equality, then "shifted" is not used |
2849 | | * as it would be empty. |
2850 | | */ |
2851 | | struct isl_context_gbr { |
2852 | | struct isl_context context; |
2853 | | struct isl_tab *tab; |
2854 | | struct isl_tab *shifted; |
2855 | | struct isl_tab *cone; |
2856 | | }; |
2857 | | |
2858 | | static struct isl_tab *context_gbr_detect_nonnegative_parameters( |
2859 | | struct isl_context *context, struct isl_tab *tab) |
2860 | 7.16k | { |
2861 | 7.16k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
2862 | 7.16k | if (!tab) |
2863 | 0 | return NULL; |
2864 | 7.16k | return tab_detect_nonnegative_parameters(tab, cgbr->tab); |
2865 | 7.16k | } |
2866 | | |
2867 | | static struct isl_basic_set *context_gbr_peek_basic_set( |
2868 | | struct isl_context *context) |
2869 | 25.6k | { |
2870 | 25.6k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
2871 | 25.6k | if (!cgbr->tab) |
2872 | 0 | return NULL; |
2873 | 25.6k | return isl_tab_peek_bset(cgbr->tab); |
2874 | 25.6k | } |
2875 | | |
2876 | | static struct isl_tab *context_gbr_peek_tab(struct isl_context *context) |
2877 | 33.2k | { |
2878 | 33.2k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
2879 | 33.2k | return cgbr->tab; |
2880 | 33.2k | } |
2881 | | |
2882 | | /* Initialize the "shifted" tableau of the context, which |
2883 | | * contains the constraints of the original tableau shifted |
2884 | | * by the sum of all negative coefficients. This ensures |
2885 | | * that any rational point in the shifted tableau can |
2886 | | * be rounded up to yield an integer point in the original tableau. |
2887 | | */ |
2888 | | static void gbr_init_shifted(struct isl_context_gbr *cgbr) |
2889 | 251 | { |
2890 | 251 | int i, j; |
2891 | 251 | struct isl_vec *cst; |
2892 | 251 | struct isl_basic_set *bset = isl_tab_peek_bset(cgbr->tab); |
2893 | 251 | unsigned dim = isl_basic_set_total_dim(bset); |
2894 | 251 | |
2895 | 251 | cst = isl_vec_alloc(cgbr->tab->mat->ctx, bset->n_ineq); |
2896 | 251 | if (!cst) |
2897 | 0 | return; |
2898 | 251 | |
2899 | 2.16k | for (i = 0; 251 i < bset->n_ineq; ++i1.91k ) { |
2900 | 1.91k | isl_int_set(cst->el[i], bset->ineq[i][0]); |
2901 | 13.7k | for (j = 0; j < dim; ++j11.8k ) { |
2902 | 11.8k | if (!isl_int_is_neg(bset->ineq[i][1 + j])) |
2903 | 11.8k | continue10.1k ; |
2904 | 1.73k | isl_int_add(bset->ineq[i][0], bset->ineq[i][0], |
2905 | 1.73k | bset->ineq[i][1 + j]); |
2906 | 1.73k | } |
2907 | 1.91k | } |
2908 | 251 | |
2909 | 251 | cgbr->shifted = isl_tab_from_basic_set(bset, 0); |
2910 | 251 | |
2911 | 2.16k | for (i = 0; i < bset->n_ineq; ++i1.91k ) |
2912 | 1.91k | isl_int_set(bset->ineq[i][0], cst->el[i]); |
2913 | 251 | |
2914 | 251 | isl_vec_free(cst); |
2915 | 251 | } |
2916 | | |
2917 | | /* Check if the shifted tableau is non-empty, and if so |
2918 | | * use the sample point to construct an integer point |
2919 | | * of the context tableau. |
2920 | | */ |
2921 | | static struct isl_vec *gbr_get_shifted_sample(struct isl_context_gbr *cgbr) |
2922 | 297 | { |
2923 | 297 | struct isl_vec *sample; |
2924 | 297 | |
2925 | 297 | if (!cgbr->shifted) |
2926 | 251 | gbr_init_shifted(cgbr); |
2927 | 297 | if (!cgbr->shifted) |
2928 | 0 | return NULL; |
2929 | 297 | if (cgbr->shifted->empty) |
2930 | 220 | return isl_vec_alloc(cgbr->tab->mat->ctx, 0); |
2931 | 77 | |
2932 | 77 | sample = isl_tab_get_sample_value(cgbr->shifted); |
2933 | 77 | sample = isl_vec_ceil(sample); |
2934 | 77 | |
2935 | 77 | return sample; |
2936 | 77 | } |
2937 | | |
2938 | | static __isl_give isl_basic_set *drop_constant_terms( |
2939 | | __isl_take isl_basic_set *bset) |
2940 | 821 | { |
2941 | 821 | int i; |
2942 | 821 | |
2943 | 821 | if (!bset) |
2944 | 0 | return NULL; |
2945 | 821 | |
2946 | 2.18k | for (i = 0; 821 i < bset->n_eq; ++i1.36k ) |
2947 | 1.36k | isl_int_set_si(bset->eq[i][0], 0); |
2948 | 821 | |
2949 | 7.27k | for (i = 0; i < bset->n_ineq; ++i6.45k ) |
2950 | 6.45k | isl_int_set_si(bset->ineq[i][0], 0); |
2951 | 821 | |
2952 | 821 | return bset; |
2953 | 821 | } |
2954 | | |
2955 | | static int use_shifted(struct isl_context_gbr *cgbr) |
2956 | 1.12k | { |
2957 | 1.12k | if (!cgbr->tab) |
2958 | 0 | return 0; |
2959 | 1.12k | return cgbr->tab->bmap->n_eq == 0 && cgbr->tab->bmap->n_div == 0609 ; |
2960 | 1.12k | } |
2961 | | |
2962 | | static struct isl_vec *gbr_get_sample(struct isl_context_gbr *cgbr) |
2963 | 11.1k | { |
2964 | 11.1k | struct isl_basic_set *bset; |
2965 | 11.1k | struct isl_basic_set *cone; |
2966 | 11.1k | |
2967 | 11.1k | if (isl_tab_sample_is_integer(cgbr->tab)) |
2968 | 10.0k | return isl_tab_get_sample_value(cgbr->tab); |
2969 | 1.11k | |
2970 | 1.11k | if (use_shifted(cgbr)) { |
2971 | 297 | struct isl_vec *sample; |
2972 | 297 | |
2973 | 297 | sample = gbr_get_shifted_sample(cgbr); |
2974 | 297 | if (!sample || sample->size > 0) |
2975 | 77 | return sample; |
2976 | 220 | |
2977 | 220 | isl_vec_free(sample); |
2978 | 220 | } |
2979 | 1.11k | |
2980 | 1.11k | if (1.03k !cgbr->cone1.03k ) { |
2981 | 621 | bset = isl_tab_peek_bset(cgbr->tab); |
2982 | 621 | cgbr->cone = isl_tab_from_recession_cone(bset, 0); |
2983 | 621 | if (!cgbr->cone) |
2984 | 0 | return NULL; |
2985 | 621 | if (isl_tab_track_bset(cgbr->cone, |
2986 | 621 | isl_basic_set_copy(bset)) < 0) |
2987 | 0 | return NULL; |
2988 | 1.03k | } |
2989 | 1.03k | if (isl_tab_detect_implicit_equalities(cgbr->cone) < 0) |
2990 | 0 | return NULL; |
2991 | 1.03k | |
2992 | 1.03k | if (cgbr->cone->n_dead == cgbr->cone->n_col) { |
2993 | 217 | struct isl_vec *sample; |
2994 | 217 | struct isl_tab_undo *snap; |
2995 | 217 | |
2996 | 217 | if (cgbr->tab->basis) { |
2997 | 59 | if (cgbr->tab->basis->n_col != 1 + cgbr->tab->n_var) { |
2998 | 23 | isl_mat_free(cgbr->tab->basis); |
2999 | 23 | cgbr->tab->basis = NULL; |
3000 | 23 | } |
3001 | 59 | cgbr->tab->n_zero = 0; |
3002 | 59 | cgbr->tab->n_unbounded = 0; |
3003 | 59 | } |
3004 | 217 | |
3005 | 217 | snap = isl_tab_snap(cgbr->tab); |
3006 | 217 | |
3007 | 217 | sample = isl_tab_sample(cgbr->tab); |
3008 | 217 | |
3009 | 217 | if (!sample || isl_tab_rollback(cgbr->tab, snap) < 0) { |
3010 | 0 | isl_vec_free(sample); |
3011 | 0 | return NULL; |
3012 | 0 | } |
3013 | 217 | |
3014 | 217 | return sample; |
3015 | 217 | } |
3016 | 821 | |
3017 | 821 | cone = isl_basic_set_dup(isl_tab_peek_bset(cgbr->cone)); |
3018 | 821 | cone = drop_constant_terms(cone); |
3019 | 821 | cone = isl_basic_set_update_from_tab(cone, cgbr->cone); |
3020 | 821 | cone = isl_basic_set_underlying_set(cone); |
3021 | 821 | cone = isl_basic_set_gauss(cone, NULL); |
3022 | 821 | |
3023 | 821 | bset = isl_basic_set_dup(isl_tab_peek_bset(cgbr->tab)); |
3024 | 821 | bset = isl_basic_set_update_from_tab(bset, cgbr->tab); |
3025 | 821 | bset = isl_basic_set_underlying_set(bset); |
3026 | 821 | bset = isl_basic_set_gauss(bset, NULL); |
3027 | 821 | |
3028 | 821 | return isl_basic_set_sample_with_cone(bset, cone); |
3029 | 821 | } |
3030 | | |
3031 | | static void check_gbr_integer_feasible(struct isl_context_gbr *cgbr) |
3032 | 39.4k | { |
3033 | 39.4k | struct isl_vec *sample; |
3034 | 39.4k | |
3035 | 39.4k | if (!cgbr->tab) |
3036 | 0 | return; |
3037 | 39.4k | |
3038 | 39.4k | if (cgbr->tab->empty) |
3039 | 28.2k | return; |
3040 | 11.1k | |
3041 | 11.1k | sample = gbr_get_sample(cgbr); |
3042 | 11.1k | if (!sample) |
3043 | 0 | goto error; |
3044 | 11.1k | |
3045 | 11.1k | if (sample->size == 0) { |
3046 | 287 | isl_vec_free(sample); |
3047 | 287 | if (isl_tab_mark_empty(cgbr->tab) < 0) |
3048 | 0 | goto error; |
3049 | 287 | return; |
3050 | 287 | } |
3051 | 10.8k | |
3052 | 10.8k | if (isl_tab_add_sample(cgbr->tab, sample) < 0) |
3053 | 0 | goto error; |
3054 | 10.8k | |
3055 | 10.8k | return; |
3056 | 0 | error: |
3057 | 0 | isl_tab_free(cgbr->tab); |
3058 | 0 | cgbr->tab = NULL; |
3059 | 0 | } |
3060 | | |
3061 | | static struct isl_tab *add_gbr_eq(struct isl_tab *tab, isl_int *eq) |
3062 | 9.41k | { |
3063 | 9.41k | if (!tab) |
3064 | 0 | return NULL; |
3065 | 9.41k | |
3066 | 9.41k | if (isl_tab_extend_cons(tab, 2) < 0) |
3067 | 0 | goto error; |
3068 | 9.41k | |
3069 | 9.41k | if (isl_tab_add_eq(tab, eq) < 0) |
3070 | 0 | goto error; |
3071 | 9.41k | |
3072 | 9.41k | return tab; |
3073 | 0 | error: |
3074 | 0 | isl_tab_free(tab); |
3075 | 0 | return NULL; |
3076 | 9.41k | } |
3077 | | |
3078 | | /* Add the equality described by "eq" to the context. |
3079 | | * If "check" is set, then we check if the context is empty after |
3080 | | * adding the equality. |
3081 | | * If "update" is set, then we check if the samples are still valid. |
3082 | | * |
3083 | | * We do not explicitly add shifted copies of the equality to |
3084 | | * cgbr->shifted since they would conflict with each other. |
3085 | | * Instead, we directly mark cgbr->shifted empty. |
3086 | | */ |
3087 | | static void context_gbr_add_eq(struct isl_context *context, isl_int *eq, |
3088 | | int check, int update) |
3089 | 9.41k | { |
3090 | 9.41k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3091 | 9.41k | |
3092 | 9.41k | cgbr->tab = add_gbr_eq(cgbr->tab, eq); |
3093 | 9.41k | |
3094 | 9.41k | if (cgbr->shifted && !cgbr->shifted->empty60 && use_shifted(cgbr)1 ) { |
3095 | 1 | if (isl_tab_mark_empty(cgbr->shifted) < 0) |
3096 | 0 | goto error; |
3097 | 9.41k | } |
3098 | 9.41k | |
3099 | 9.41k | if (cgbr->cone && cgbr->cone->n_col != cgbr->cone->n_dead633 ) { |
3100 | 603 | if (isl_tab_extend_cons(cgbr->cone, 2) < 0) |
3101 | 0 | goto error; |
3102 | 603 | if (isl_tab_add_eq(cgbr->cone, eq) < 0) |
3103 | 0 | goto error; |
3104 | 9.41k | } |
3105 | 9.41k | |
3106 | 9.41k | if (check) { |
3107 | 9.41k | int v = tab_has_valid_sample(cgbr->tab, eq, 1); |
3108 | 9.41k | if (v < 0) |
3109 | 0 | goto error; |
3110 | 9.41k | if (!v) |
3111 | 76 | check_gbr_integer_feasible(cgbr); |
3112 | 9.41k | } |
3113 | 9.41k | if (update) |
3114 | 9.41k | cgbr->tab = check_samples(cgbr->tab, eq, 1); |
3115 | 9.41k | return; |
3116 | 0 | error: |
3117 | 0 | isl_tab_free(cgbr->tab); |
3118 | 0 | cgbr->tab = NULL; |
3119 | 0 | } |
3120 | | |
3121 | | static void add_gbr_ineq(struct isl_context_gbr *cgbr, isl_int *ineq) |
3122 | 38.8k | { |
3123 | 38.8k | if (!cgbr->tab) |
3124 | 0 | return; |
3125 | 38.8k | |
3126 | 38.8k | if (isl_tab_extend_cons(cgbr->tab, 1) < 0) |
3127 | 0 | goto error; |
3128 | 38.8k | |
3129 | 38.8k | if (isl_tab_add_ineq(cgbr->tab, ineq) < 0) |
3130 | 0 | goto error; |
3131 | 38.8k | |
3132 | 38.8k | if (cgbr->shifted && !cgbr->shifted->empty597 && use_shifted(cgbr)6 ) { |
3133 | 6 | int i; |
3134 | 6 | unsigned dim; |
3135 | 6 | dim = isl_basic_map_total_dim(cgbr->tab->bmap); |
3136 | 6 | |
3137 | 6 | if (isl_tab_extend_cons(cgbr->shifted, 1) < 0) |
3138 | 0 | goto error; |
3139 | 6 | |
3140 | 22 | for (i = 0; 6 i < dim; ++i16 ) { |
3141 | 16 | if (!isl_int_is_neg(ineq[1 + i])) |
3142 | 16 | continue11 ; |
3143 | 5 | isl_int_add(ineq[0], ineq[0], ineq[1 + i]); |
3144 | 5 | } |
3145 | 6 | |
3146 | 6 | if (isl_tab_add_ineq(cgbr->shifted, ineq) < 0) |
3147 | 0 | goto error; |
3148 | 6 | |
3149 | 22 | for (i = 0; 6 i < dim; ++i16 ) { |
3150 | 16 | if (!isl_int_is_neg(ineq[1 + i])) |
3151 | 16 | continue11 ; |
3152 | 5 | isl_int_sub(ineq[0], ineq[0], ineq[1 + i]); |
3153 | 5 | } |
3154 | 6 | } |
3155 | 38.8k | |
3156 | 38.8k | if (cgbr->cone && cgbr->cone->n_col != cgbr->cone->n_dead6.02k ) { |
3157 | 4.68k | if (isl_tab_extend_cons(cgbr->cone, 1) < 0) |
3158 | 0 | goto error; |
3159 | 4.68k | if (isl_tab_add_ineq(cgbr->cone, ineq) < 0) |
3160 | 0 | goto error; |
3161 | 38.8k | } |
3162 | 38.8k | |
3163 | 38.8k | return; |
3164 | 0 | error: |
3165 | 0 | isl_tab_free(cgbr->tab); |
3166 | 0 | cgbr->tab = NULL; |
3167 | 0 | } |
3168 | | |
3169 | | static void context_gbr_add_ineq(struct isl_context *context, isl_int *ineq, |
3170 | | int check, int update) |
3171 | 26.2k | { |
3172 | 26.2k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3173 | 26.2k | |
3174 | 26.2k | add_gbr_ineq(cgbr, ineq); |
3175 | 26.2k | if (!cgbr->tab) |
3176 | 0 | return; |
3177 | 26.2k | |
3178 | 26.2k | if (check) { |
3179 | 19.0k | int v = tab_has_valid_sample(cgbr->tab, ineq, 0); |
3180 | 19.0k | if (v < 0) |
3181 | 0 | goto error; |
3182 | 19.0k | if (!v) |
3183 | 18.8k | check_gbr_integer_feasible(cgbr); |
3184 | 19.0k | } |
3185 | 26.2k | if (update) |
3186 | 5.79k | cgbr->tab = check_samples(cgbr->tab, ineq, 0); |
3187 | 26.2k | return; |
3188 | 0 | error: |
3189 | 0 | isl_tab_free(cgbr->tab); |
3190 | 0 | cgbr->tab = NULL; |
3191 | 0 | } |
3192 | | |
3193 | | static isl_stat context_gbr_add_ineq_wrap(void *user, isl_int *ineq) |
3194 | 1.51k | { |
3195 | 1.51k | struct isl_context *context = (struct isl_context *)user; |
3196 | 1.51k | context_gbr_add_ineq(context, ineq, 0, 0); |
3197 | 1.51k | return context->op->is_ok(context) ? isl_stat_ok : isl_stat_error0 ; |
3198 | 1.51k | } |
3199 | | |
3200 | | static enum isl_tab_row_sign context_gbr_ineq_sign(struct isl_context *context, |
3201 | | isl_int *ineq, int strict) |
3202 | 13.0k | { |
3203 | 13.0k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3204 | 13.0k | return tab_ineq_sign(cgbr->tab, ineq, strict); |
3205 | 13.0k | } |
3206 | | |
3207 | | /* Check whether "ineq" can be added to the tableau without rendering |
3208 | | * it infeasible. |
3209 | | */ |
3210 | | static int context_gbr_test_ineq(struct isl_context *context, isl_int *ineq) |
3211 | 12.6k | { |
3212 | 12.6k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3213 | 12.6k | struct isl_tab_undo *snap; |
3214 | 12.6k | struct isl_tab_undo *shifted_snap = NULL; |
3215 | 12.6k | struct isl_tab_undo *cone_snap = NULL; |
3216 | 12.6k | int feasible; |
3217 | 12.6k | |
3218 | 12.6k | if (!cgbr->tab) |
3219 | 0 | return -1; |
3220 | 12.6k | |
3221 | 12.6k | if (isl_tab_extend_cons(cgbr->tab, 1) < 0) |
3222 | 0 | return -1; |
3223 | 12.6k | |
3224 | 12.6k | snap = isl_tab_snap(cgbr->tab); |
3225 | 12.6k | if (cgbr->shifted) |
3226 | 403 | shifted_snap = isl_tab_snap(cgbr->shifted); |
3227 | 12.6k | if (cgbr->cone) |
3228 | 2.88k | cone_snap = isl_tab_snap(cgbr->cone); |
3229 | 12.6k | add_gbr_ineq(cgbr, ineq); |
3230 | 12.6k | check_gbr_integer_feasible(cgbr); |
3231 | 12.6k | if (!cgbr->tab) |
3232 | 0 | return -1; |
3233 | 12.6k | feasible = !cgbr->tab->empty; |
3234 | 12.6k | if (isl_tab_rollback(cgbr->tab, snap) < 0) |
3235 | 0 | return -1; |
3236 | 12.6k | if (shifted_snap) { |
3237 | 403 | if (isl_tab_rollback(cgbr->shifted, shifted_snap)) |
3238 | 0 | return -1; |
3239 | 12.2k | } else if (cgbr->shifted) { |
3240 | 189 | isl_tab_free(cgbr->shifted); |
3241 | 189 | cgbr->shifted = NULL; |
3242 | 189 | } |
3243 | 12.6k | if (cone_snap) { |
3244 | 2.88k | if (isl_tab_rollback(cgbr->cone, cone_snap)) |
3245 | 0 | return -1; |
3246 | 9.71k | } else if (cgbr->cone) { |
3247 | 168 | isl_tab_free(cgbr->cone); |
3248 | 168 | cgbr->cone = NULL; |
3249 | 168 | } |
3250 | 12.6k | |
3251 | 12.6k | return feasible; |
3252 | 12.6k | } |
3253 | | |
3254 | | /* Return the column of the last of the variables associated to |
3255 | | * a column that has a non-zero coefficient. |
3256 | | * This function is called in a context where only coefficients |
3257 | | * of parameters or divs can be non-zero. |
3258 | | */ |
3259 | | static int last_non_zero_var_col(struct isl_tab *tab, isl_int *p) |
3260 | 281 | { |
3261 | 281 | int i; |
3262 | 281 | int col; |
3263 | 281 | |
3264 | 281 | if (tab->n_var == 0) |
3265 | 0 | return -1; |
3266 | 281 | |
3267 | 738 | for (i = tab->n_var - 1; 281 i >= 0; --i457 ) { |
3268 | 738 | if (i >= tab->n_param && i < tab->n_var - tab->n_div672 ) |
3269 | 119 | continue; |
3270 | 619 | if (tab->var[i].is_row) |
3271 | 112 | continue; |
3272 | 507 | col = tab->var[i].index; |
3273 | 507 | if (!isl_int_is_zero(p[col])) |
3274 | 507 | return col281 ; |
3275 | 507 | } |
3276 | 281 | |
3277 | 281 | return -10 ; |
3278 | 281 | } |
3279 | | |
3280 | | /* Look through all the recently added equalities in the context |
3281 | | * to see if we can propagate any of them to the main tableau. |
3282 | | * |
3283 | | * The newly added equalities in the context are encoded as pairs |
3284 | | * of inequalities starting at inequality "first". |
3285 | | * |
3286 | | * We tentatively add each of these equalities to the main tableau |
3287 | | * and if this happens to result in a row with a final coefficient |
3288 | | * that is one or negative one, we use it to kill a column |
3289 | | * in the main tableau. Otherwise, we discard the tentatively |
3290 | | * added row. |
3291 | | * This tentative addition of equality constraints turns |
3292 | | * on the undo facility of the tableau. Turn it off again |
3293 | | * at the end, assuming it was turned off to begin with. |
3294 | | * |
3295 | | * Return 0 on success and -1 on failure. |
3296 | | */ |
3297 | | static int propagate_equalities(struct isl_context_gbr *cgbr, |
3298 | | struct isl_tab *tab, unsigned first) |
3299 | 176 | { |
3300 | 176 | int i; |
3301 | 176 | struct isl_vec *eq = NULL; |
3302 | 176 | isl_bool needs_undo; |
3303 | 176 | |
3304 | 176 | needs_undo = isl_tab_need_undo(tab); |
3305 | 176 | if (needs_undo < 0) |
3306 | 0 | goto error; |
3307 | 176 | eq = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var); |
3308 | 176 | if (!eq) |
3309 | 0 | goto error; |
3310 | 176 | |
3311 | 176 | if (isl_tab_extend_cons(tab, (cgbr->tab->bmap->n_ineq - first)/2) < 0) |
3312 | 0 | goto error; |
3313 | 176 | |
3314 | 176 | isl_seq_clr(eq->el + 1 + tab->n_param, |
3315 | 176 | tab->n_var - tab->n_param - tab->n_div); |
3316 | 457 | for (i = first; i < cgbr->tab->bmap->n_ineq; i += 2281 ) { |
3317 | 281 | int j; |
3318 | 281 | int r; |
3319 | 281 | struct isl_tab_undo *snap; |
3320 | 281 | snap = isl_tab_snap(tab); |
3321 | 281 | |
3322 | 281 | isl_seq_cpy(eq->el, cgbr->tab->bmap->ineq[i], 1 + tab->n_param); |
3323 | 281 | isl_seq_cpy(eq->el + 1 + tab->n_var - tab->n_div, |
3324 | 281 | cgbr->tab->bmap->ineq[i] + 1 + tab->n_param, |
3325 | 281 | tab->n_div); |
3326 | 281 | |
3327 | 281 | r = isl_tab_add_row(tab, eq->el); |
3328 | 281 | if (r < 0) |
3329 | 0 | goto error; |
3330 | 281 | r = tab->con[r].index; |
3331 | 281 | j = last_non_zero_var_col(tab, tab->mat->row[r] + 2 + tab->M); |
3332 | 281 | if (j < 0 || j < tab->n_dead || |
3333 | 281 | !isl_int_is_one(tab->mat->row[r][0]) || |
3334 | 281 | (!isl_int_is_one(tab->mat->row[r][2 + tab->M + j]) && |
3335 | 281 | !145 isl_int_is_negone145 (tab->mat->row[r][2 + tab->M + j]))) { |
3336 | 65 | if (isl_tab_rollback(tab, snap) < 0) |
3337 | 0 | goto error; |
3338 | 65 | continue; |
3339 | 65 | } |
3340 | 216 | if (isl_tab_pivot(tab, r, j) < 0) |
3341 | 0 | goto error; |
3342 | 216 | if (isl_tab_kill_col(tab, j) < 0) |
3343 | 0 | goto error; |
3344 | 216 | |
3345 | 216 | if (restore_lexmin(tab) < 0) |
3346 | 0 | goto error; |
3347 | 216 | } |
3348 | 176 | |
3349 | 176 | if (!needs_undo) |
3350 | 176 | isl_tab_clear_undo(tab); |
3351 | 176 | isl_vec_free(eq); |
3352 | 176 | |
3353 | 176 | return 0; |
3354 | 0 | error: |
3355 | 0 | isl_vec_free(eq); |
3356 | 0 | isl_tab_free(cgbr->tab); |
3357 | 0 | cgbr->tab = NULL; |
3358 | 0 | return -1; |
3359 | 176 | } |
3360 | | |
3361 | | static int context_gbr_detect_equalities(struct isl_context *context, |
3362 | | struct isl_tab *tab) |
3363 | 692 | { |
3364 | 692 | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3365 | 692 | unsigned n_ineq; |
3366 | 692 | |
3367 | 692 | if (!cgbr->cone) { |
3368 | 248 | struct isl_basic_set *bset = isl_tab_peek_bset(cgbr->tab); |
3369 | 248 | cgbr->cone = isl_tab_from_recession_cone(bset, 0); |
3370 | 248 | if (!cgbr->cone) |
3371 | 0 | goto error; |
3372 | 248 | if (isl_tab_track_bset(cgbr->cone, |
3373 | 248 | isl_basic_set_copy(bset)) < 0) |
3374 | 0 | goto error; |
3375 | 692 | } |
3376 | 692 | if (isl_tab_detect_implicit_equalities(cgbr->cone) < 0) |
3377 | 0 | goto error; |
3378 | 692 | |
3379 | 692 | n_ineq = cgbr->tab->bmap->n_ineq; |
3380 | 692 | cgbr->tab = isl_tab_detect_equalities(cgbr->tab, cgbr->cone); |
3381 | 692 | if (!cgbr->tab) |
3382 | 0 | return -1; |
3383 | 692 | if (cgbr->tab->bmap->n_ineq > n_ineq && |
3384 | 692 | propagate_equalities(cgbr, tab, n_ineq) < 0176 ) |
3385 | 0 | return -1; |
3386 | 692 | |
3387 | 692 | return 0; |
3388 | 0 | error: |
3389 | 0 | isl_tab_free(cgbr->tab); |
3390 | 0 | cgbr->tab = NULL; |
3391 | 0 | return -1; |
3392 | 692 | } |
3393 | | |
3394 | | static int context_gbr_get_div(struct isl_context *context, struct isl_tab *tab, |
3395 | | struct isl_vec *div) |
3396 | 824 | { |
3397 | 824 | return get_div(tab, context, div); |
3398 | 824 | } |
3399 | | |
3400 | | static isl_bool context_gbr_insert_div(struct isl_context *context, int pos, |
3401 | | __isl_keep isl_vec *div) |
3402 | 759 | { |
3403 | 759 | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3404 | 759 | if (cgbr->cone) { |
3405 | 453 | int r, n_div, o_div; |
3406 | 453 | |
3407 | 453 | n_div = isl_basic_map_dim(cgbr->cone->bmap, isl_dim_div); |
3408 | 453 | o_div = cgbr->cone->n_var - n_div; |
3409 | 453 | |
3410 | 453 | if (isl_tab_extend_cons(cgbr->cone, 3) < 0) |
3411 | 0 | return isl_bool_error; |
3412 | 453 | if (isl_tab_extend_vars(cgbr->cone, 1) < 0) |
3413 | 0 | return isl_bool_error; |
3414 | 453 | if ((r = isl_tab_insert_var(cgbr->cone, pos)) <0) |
3415 | 0 | return isl_bool_error; |
3416 | 453 | |
3417 | 453 | cgbr->cone->bmap = isl_basic_map_insert_div(cgbr->cone->bmap, |
3418 | 453 | r - o_div, div); |
3419 | 453 | if (!cgbr->cone->bmap) |
3420 | 0 | return isl_bool_error; |
3421 | 453 | if (isl_tab_push_var(cgbr->cone, isl_tab_undo_bmap_div, |
3422 | 453 | &cgbr->cone->var[r]) < 0) |
3423 | 0 | return isl_bool_error; |
3424 | 759 | } |
3425 | 759 | return context_tab_insert_div(cgbr->tab, pos, div, |
3426 | 759 | context_gbr_add_ineq_wrap, context); |
3427 | 759 | } |
3428 | | |
3429 | | static int context_gbr_best_split(struct isl_context *context, |
3430 | | struct isl_tab *tab) |
3431 | 287 | { |
3432 | 287 | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3433 | 287 | struct isl_tab_undo *snap; |
3434 | 287 | int r; |
3435 | 287 | |
3436 | 287 | snap = isl_tab_snap(cgbr->tab); |
3437 | 287 | r = best_split(tab, cgbr->tab); |
3438 | 287 | |
3439 | 287 | if (r >= 0 && isl_tab_rollback(cgbr->tab, snap) < 0) |
3440 | 0 | return -1; |
3441 | 287 | |
3442 | 287 | return r; |
3443 | 287 | } |
3444 | | |
3445 | | static int context_gbr_is_empty(struct isl_context *context) |
3446 | 45.1k | { |
3447 | 45.1k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3448 | 45.1k | if (!cgbr->tab) |
3449 | 0 | return -1; |
3450 | 45.1k | return cgbr->tab->empty; |
3451 | 45.1k | } |
3452 | | |
3453 | | struct isl_gbr_tab_undo { |
3454 | | struct isl_tab_undo *tab_snap; |
3455 | | struct isl_tab_undo *shifted_snap; |
3456 | | struct isl_tab_undo *cone_snap; |
3457 | | }; |
3458 | | |
3459 | | static void *context_gbr_save(struct isl_context *context) |
3460 | 28.9k | { |
3461 | 28.9k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3462 | 28.9k | struct isl_gbr_tab_undo *snap; |
3463 | 28.9k | |
3464 | 28.9k | if (!cgbr->tab) |
3465 | 0 | return NULL; |
3466 | 28.9k | |
3467 | 28.9k | snap = isl_alloc_type(cgbr->tab->mat->ctx, struct isl_gbr_tab_undo); |
3468 | 28.9k | if (!snap) |
3469 | 0 | return NULL; |
3470 | 28.9k | |
3471 | 28.9k | snap->tab_snap = isl_tab_snap(cgbr->tab); |
3472 | 28.9k | if (isl_tab_save_samples(cgbr->tab) < 0) |
3473 | 0 | goto error; |
3474 | 28.9k | |
3475 | 28.9k | if (cgbr->shifted) |
3476 | 194 | snap->shifted_snap = isl_tab_snap(cgbr->shifted); |
3477 | 28.7k | else |
3478 | 28.7k | snap->shifted_snap = NULL; |
3479 | 28.9k | |
3480 | 28.9k | if (cgbr->cone) |
3481 | 2.03k | snap->cone_snap = isl_tab_snap(cgbr->cone); |
3482 | 26.9k | else |
3483 | 26.9k | snap->cone_snap = NULL; |
3484 | 28.9k | |
3485 | 28.9k | return snap; |
3486 | 0 | error: |
3487 | 0 | free(snap); |
3488 | 0 | return NULL; |
3489 | 28.9k | } |
3490 | | |
3491 | | static void context_gbr_restore(struct isl_context *context, void *save) |
3492 | 23.6k | { |
3493 | 23.6k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3494 | 23.6k | struct isl_gbr_tab_undo *snap = (struct isl_gbr_tab_undo *)save; |
3495 | 23.6k | if (!snap) |
3496 | 0 | goto error; |
3497 | 23.6k | if (isl_tab_rollback(cgbr->tab, snap->tab_snap) < 0) |
3498 | 0 | goto error; |
3499 | 23.6k | |
3500 | 23.6k | if (snap->shifted_snap) { |
3501 | 137 | if (isl_tab_rollback(cgbr->shifted, snap->shifted_snap) < 0) |
3502 | 0 | goto error; |
3503 | 23.5k | } else if (cgbr->shifted) { |
3504 | 0 | isl_tab_free(cgbr->shifted); |
3505 | 0 | cgbr->shifted = NULL; |
3506 | 0 | } |
3507 | 23.6k | |
3508 | 23.6k | if (snap->cone_snap) { |
3509 | 1.91k | if (isl_tab_rollback(cgbr->cone, snap->cone_snap) < 0) |
3510 | 0 | goto error; |
3511 | 21.7k | } else if (cgbr->cone) { |
3512 | 271 | isl_tab_free(cgbr->cone); |
3513 | 271 | cgbr->cone = NULL; |
3514 | 271 | } |
3515 | 23.6k | |
3516 | 23.6k | free(snap); |
3517 | 23.6k | |
3518 | 23.6k | return; |
3519 | 0 | error: |
3520 | 0 | free(snap); |
3521 | 0 | isl_tab_free(cgbr->tab); |
3522 | 0 | cgbr->tab = NULL; |
3523 | 0 | } |
3524 | | |
3525 | | static void context_gbr_discard(void *save) |
3526 | 5.27k | { |
3527 | 5.27k | struct isl_gbr_tab_undo *snap = (struct isl_gbr_tab_undo *)save; |
3528 | 5.27k | free(snap); |
3529 | 5.27k | } |
3530 | | |
3531 | | static int context_gbr_is_ok(struct isl_context *context) |
3532 | 2.39k | { |
3533 | 2.39k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3534 | 2.39k | return !!cgbr->tab; |
3535 | 2.39k | } |
3536 | | |
3537 | | static void context_gbr_invalidate(struct isl_context *context) |
3538 | 0 | { |
3539 | 0 | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3540 | 0 | isl_tab_free(cgbr->tab); |
3541 | 0 | cgbr->tab = NULL; |
3542 | 0 | } |
3543 | | |
3544 | | static __isl_null struct isl_context *context_gbr_free( |
3545 | | struct isl_context *context) |
3546 | 7.85k | { |
3547 | 7.85k | struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context; |
3548 | 7.85k | isl_tab_free(cgbr->tab); |
3549 | 7.85k | isl_tab_free(cgbr->shifted); |
3550 | 7.85k | isl_tab_free(cgbr->cone); |
3551 | 7.85k | free(cgbr); |
3552 | 7.85k | |
3553 | 7.85k | return NULL; |
3554 | 7.85k | } |
3555 | | |
3556 | | struct isl_context_op isl_context_gbr_op = { |
3557 | | context_gbr_detect_nonnegative_parameters, |
3558 | | context_gbr_peek_basic_set, |
3559 | | context_gbr_peek_tab, |
3560 | | context_gbr_add_eq, |
3561 | | context_gbr_add_ineq, |
3562 | | context_gbr_ineq_sign, |
3563 | | context_gbr_test_ineq, |
3564 | | context_gbr_get_div, |
3565 | | context_gbr_insert_div, |
3566 | | context_gbr_detect_equalities, |
3567 | | context_gbr_best_split, |
3568 | | context_gbr_is_empty, |
3569 | | context_gbr_is_ok, |
3570 | | context_gbr_save, |
3571 | | context_gbr_restore, |
3572 | | context_gbr_discard, |
3573 | | context_gbr_invalidate, |
3574 | | context_gbr_free, |
3575 | | }; |
3576 | | |
3577 | | static struct isl_context *isl_context_gbr_alloc(__isl_keep isl_basic_set *dom) |
3578 | 7.85k | { |
3579 | 7.85k | struct isl_context_gbr *cgbr; |
3580 | 7.85k | |
3581 | 7.85k | if (!dom) |
3582 | 0 | return NULL; |
3583 | 7.85k | |
3584 | 7.85k | cgbr = isl_calloc_type(dom->ctx, struct isl_context_gbr); |
3585 | 7.85k | if (!cgbr) |
3586 | 0 | return NULL; |
3587 | 7.85k | |
3588 | 7.85k | cgbr->context.op = &isl_context_gbr_op; |
3589 | 7.85k | |
3590 | 7.85k | cgbr->shifted = NULL; |
3591 | 7.85k | cgbr->cone = NULL; |
3592 | 7.85k | cgbr->tab = isl_tab_from_basic_set(dom, 1); |
3593 | 7.85k | cgbr->tab = isl_tab_init_samples(cgbr->tab); |
3594 | 7.85k | if (!cgbr->tab) |
3595 | 0 | goto error; |
3596 | 7.85k | check_gbr_integer_feasible(cgbr); |
3597 | 7.85k | |
3598 | 7.85k | return &cgbr->context; |
3599 | 0 | error: |
3600 | 0 | cgbr->context.op->free(&cgbr->context); |
3601 | 0 | return NULL; |
3602 | 7.85k | } |
3603 | | |
3604 | | /* Allocate a context corresponding to "dom". |
3605 | | * The representation specific fields are initialized by |
3606 | | * isl_context_lex_alloc or isl_context_gbr_alloc. |
3607 | | * The shared "n_unknown" field is initialized to the number |
3608 | | * of final unknown integer divisions in "dom". |
3609 | | */ |
3610 | | static struct isl_context *isl_context_alloc(__isl_keep isl_basic_set *dom) |
3611 | 7.85k | { |
3612 | 7.85k | struct isl_context *context; |
3613 | 7.85k | int first; |
3614 | 7.85k | |
3615 | 7.85k | if (!dom) |
3616 | 0 | return NULL; |
3617 | 7.85k | |
3618 | 7.85k | if (dom->ctx->opt->context == ISL_CONTEXT_LEXMIN) |
3619 | 7.85k | context = isl_context_lex_alloc(dom)0 ; |
3620 | 7.85k | else |
3621 | 7.85k | context = isl_context_gbr_alloc(dom); |
3622 | 7.85k | |
3623 | 7.85k | if (!context) |
3624 | 0 | return NULL; |
3625 | 7.85k | |
3626 | 7.85k | first = isl_basic_set_first_unknown_div(dom); |
3627 | 7.85k | if (first < 0) |
3628 | 0 | return context->op->free(context); |
3629 | 7.85k | context->n_unknown = isl_basic_set_dim(dom, isl_dim_div) - first; |
3630 | 7.85k | |
3631 | 7.85k | return context; |
3632 | 7.85k | } |
3633 | | |
3634 | | /* Initialize some common fields of "sol", which keeps track |
3635 | | * of the solution of an optimization problem on "bmap" over |
3636 | | * the domain "dom". |
3637 | | * If "max" is set, then a maximization problem is being solved, rather than |
3638 | | * a minimization problem, which means that the variables in the |
3639 | | * tableau have value "M - x" rather than "M + x". |
3640 | | */ |
3641 | | static isl_stat sol_init(struct isl_sol *sol, __isl_keep isl_basic_map *bmap, |
3642 | | __isl_keep isl_basic_set *dom, int max) |
3643 | 7.85k | { |
3644 | 7.85k | sol->rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL); |
3645 | 7.85k | sol->dec_level.callback.run = &sol_dec_level_wrap; |
3646 | 7.85k | sol->dec_level.sol = sol; |
3647 | 7.85k | sol->max = max; |
3648 | 7.85k | sol->n_out = isl_basic_map_dim(bmap, isl_dim_out); |
3649 | 7.85k | sol->space = isl_basic_map_get_space(bmap); |
3650 | 7.85k | |
3651 | 7.85k | sol->context = isl_context_alloc(dom); |
3652 | 7.85k | if (!sol->space || !sol->context) |
3653 | 0 | return isl_stat_error; |
3654 | 7.85k | |
3655 | 7.85k | return isl_stat_ok; |
3656 | 7.85k | } |
3657 | | |
3658 | | /* Construct an isl_sol_map structure for accumulating the solution. |
3659 | | * If track_empty is set, then we also keep track of the parts |
3660 | | * of the context where there is no solution. |
3661 | | * If max is set, then we are solving a maximization, rather than |
3662 | | * a minimization problem, which means that the variables in the |
3663 | | * tableau have value "M - x" rather than "M + x". |
3664 | | */ |
3665 | | static struct isl_sol *sol_map_init(__isl_keep isl_basic_map *bmap, |
3666 | | __isl_take isl_basic_set *dom, int track_empty, int max) |
3667 | 3.64k | { |
3668 | 3.64k | struct isl_sol_map *sol_map = NULL; |
3669 | 3.64k | isl_space *space; |
3670 | 3.64k | |
3671 | 3.64k | if (!bmap) |
3672 | 0 | goto error; |
3673 | 3.64k | |
3674 | 3.64k | sol_map = isl_calloc_type(bmap->ctx, struct isl_sol_map); |
3675 | 3.64k | if (!sol_map) |
3676 | 0 | goto error; |
3677 | 3.64k | |
3678 | 3.64k | sol_map->sol.free = &sol_map_free; |
3679 | 3.64k | if (sol_init(&sol_map->sol, bmap, dom, max) < 0) |
3680 | 0 | goto error; |
3681 | 3.64k | sol_map->sol.add = &sol_map_add_wrap; |
3682 | 3.64k | sol_map->sol.add_empty = track_empty ? &sol_map_add_empty_wrap2.75k : NULL; |
3683 | 3.64k | space = isl_space_copy(sol_map->sol.space); |
3684 | 3.64k | sol_map->map = isl_map_alloc_space(space, 1, ISL_MAP_DISJOINT); |
3685 | 3.64k | if (!sol_map->map) |
3686 | 0 | goto error; |
3687 | 3.64k | |
3688 | 3.64k | if (track_empty) { |
3689 | 2.75k | sol_map->empty = isl_set_alloc_space(isl_basic_set_get_space(dom), |
3690 | 2.75k | 1, ISL_SET_DISJOINT); |
3691 | 2.75k | if (!sol_map->empty) |
3692 | 0 | goto error; |
3693 | 3.64k | } |
3694 | 3.64k | |
3695 | 3.64k | isl_basic_set_free(dom); |
3696 | 3.64k | return &sol_map->sol; |
3697 | 0 | error: |
3698 | 0 | isl_basic_set_free(dom); |
3699 | 0 | sol_free(&sol_map->sol); |
3700 | 0 | return NULL; |
3701 | 3.64k | } |
3702 | | |
3703 | | /* Check whether all coefficients of (non-parameter) variables |
3704 | | * are non-positive, meaning that no pivots can be performed on the row. |
3705 | | */ |
3706 | | static int is_critical(struct isl_tab *tab, int row) |
3707 | 13.0k | { |
3708 | 13.0k | int j; |
3709 | 13.0k | unsigned off = 2 + tab->M; |
3710 | 13.0k | |
3711 | 61.0k | for (j = tab->n_dead; j < tab->n_col; ++j47.9k ) { |
3712 | 49.5k | if (col_is_parameter_var(tab, j)) |
3713 | 35.9k | continue; |
3714 | 13.5k | |
3715 | 13.5k | if (isl_int_is_pos(tab->mat->row[row][off + j])) |
3716 | 13.5k | return 01.54k ; |
3717 | 13.5k | } |
3718 | 13.0k | |
3719 | 13.0k | return 111.4k ; |
3720 | 13.0k | } |
3721 | | |
3722 | | /* Check whether the inequality represented by vec is strict over the integers, |
3723 | | * i.e., there are no integer values satisfying the constraint with |
3724 | | * equality. This happens if the gcd of the coefficients is not a divisor |
3725 | | * of the constant term. If so, scale the constraint down by the gcd |
3726 | | * of the coefficients. |
3727 | | */ |
3728 | | static int is_strict(struct isl_vec *vec) |
3729 | 15.8k | { |
3730 | 15.8k | isl_int gcd; |
3731 | 15.8k | int strict = 0; |
3732 | 15.8k | |
3733 | 15.8k | isl_int_init(gcd); |
3734 | 15.8k | isl_seq_gcd(vec->el + 1, vec->size - 1, &gcd); |
3735 | 15.8k | if (!isl_int_is_one(gcd)) { |
3736 | 1.11k | strict = !isl_int_is_divisible_by(vec->el[0], gcd); |
3737 | 1.11k | isl_int_fdiv_q(vec->el[0], vec->el[0], gcd); |
3738 | 1.11k | isl_seq_scale_down(vec->el + 1, vec->el + 1, gcd, vec->size-1); |
3739 | 1.11k | } |
3740 | 15.8k | isl_int_clear(gcd); |
3741 | 15.8k | |
3742 | 15.8k | return strict; |
3743 | 15.8k | } |
3744 | | |
3745 | | /* Determine the sign of the given row of the main tableau. |
3746 | | * The result is one of |
3747 | | * isl_tab_row_pos: always non-negative; no pivot needed |
3748 | | * isl_tab_row_neg: always non-positive; pivot |
3749 | | * isl_tab_row_any: can be both positive and negative; split |
3750 | | * |
3751 | | * We first handle some simple cases |
3752 | | * - the row sign may be known already |
3753 | | * - the row may be obviously non-negative |
3754 | | * - the parametric constant may be equal to that of another row |
3755 | | * for which we know the sign. This sign will be either "pos" or |
3756 | | * "any". If it had been "neg" then we would have pivoted before. |
3757 | | * |
3758 | | * If none of these cases hold, we check the value of the row for each |
3759 | | * of the currently active samples. Based on the signs of these values |
3760 | | * we make an initial determination of the sign of the row. |
3761 | | * |
3762 | | * all zero -> unk(nown) |
3763 | | * all non-negative -> pos |
3764 | | * all non-positive -> neg |
3765 | | * both negative and positive -> all |
3766 | | * |
3767 | | * If we end up with "all", we are done. |
3768 | | * Otherwise, we perform a check for positive and/or negative |
3769 | | * values as follows. |
3770 | | * |
3771 | | * samples neg unk pos |
3772 | | * <0 ? Y N Y N |
3773 | | * pos any pos |
3774 | | * >0 ? Y N Y N |
3775 | | * any neg any neg |
3776 | | * |
3777 | | * There is no special sign for "zero", because we can usually treat zero |
3778 | | * as either non-negative or non-positive, whatever works out best. |
3779 | | * However, if the row is "critical", meaning that pivoting is impossible |
3780 | | * then we don't want to limp zero with the non-positive case, because |
3781 | | * then we we would lose the solution for those values of the parameters |
3782 | | * where the value of the row is zero. Instead, we treat 0 as non-negative |
3783 | | * ensuring a split if the row can attain both zero and negative values. |
3784 | | * The same happens when the original constraint was one that could not |
3785 | | * be satisfied with equality by any integer values of the parameters. |
3786 | | * In this case, we normalize the constraint, but then a value of zero |
3787 | | * for the normalized constraint is actually a positive value for the |
3788 | | * original constraint, so again we need to treat zero as non-negative. |
3789 | | * In both these cases, we have the following decision tree instead: |
3790 | | * |
3791 | | * all non-negative -> pos |
3792 | | * all negative -> neg |
3793 | | * both negative and non-negative -> all |
3794 | | * |
3795 | | * samples neg pos |
3796 | | * <0 ? Y N |
3797 | | * any pos |
3798 | | * >=0 ? Y N |
3799 | | * any neg |
3800 | | */ |
3801 | | static enum isl_tab_row_sign row_sign(struct isl_tab *tab, |
3802 | | struct isl_sol *sol, int row) |
3803 | 72.8k | { |
3804 | 72.8k | struct isl_vec *ineq = NULL; |
3805 | 72.8k | enum isl_tab_row_sign res = isl_tab_row_unknown; |
3806 | 72.8k | int critical; |
3807 | 72.8k | int strict; |
3808 | 72.8k | int row2; |
3809 | 72.8k | |
3810 | 72.8k | if (tab->row_sign[row] != isl_tab_row_unknown) |
3811 | 37.9k | return tab->row_sign[row]; |
3812 | 34.9k | if (is_obviously_nonneg(tab, row)) |
3813 | 21.7k | return isl_tab_row_pos; |
3814 | 125k | for (row2 = tab->n_redundant; 13.1k row2 < tab->n_row; ++row2112k ) { |
3815 | 112k | if (tab->row_sign[row2] == isl_tab_row_unknown) |
3816 | 35.1k | continue; |
3817 | 77.2k | if (identical_parameter_line(tab, row, row2)) |
3818 | 173 | return tab->row_sign[row2]; |
3819 | 77.2k | } |
3820 | 13.1k | |
3821 | 13.1k | critical = is_critical(tab, row); |
3822 | 13.0k | |
3823 | 13.0k | ineq = get_row_parameter_ineq(tab, row); |
3824 | 13.0k | if (!ineq) |
3825 | 0 | goto error; |
3826 | 13.0k | |
3827 | 13.0k | strict = is_strict(ineq); |
3828 | 13.0k | |
3829 | 13.0k | res = sol->context->op->ineq_sign(sol->context, ineq->el, |
3830 | 13.0k | critical || strict1.54k ); |
3831 | 13.0k | |
3832 | 13.0k | if (res == isl_tab_row_unknown || res == isl_tab_row_pos12.9k ) { |
3833 | 10.4k | /* test for negative values */ |
3834 | 10.4k | int feasible; |
3835 | 10.4k | isl_seq_neg(ineq->el, ineq->el, ineq->size); |
3836 | 10.4k | isl_int_sub_ui(ineq->el[0], ineq->el[0], 1); |
3837 | 10.4k | |
3838 | 10.4k | feasible = sol->context->op->test_ineq(sol->context, ineq->el); |
3839 | 10.4k | if (feasible < 0) |
3840 | 0 | goto error; |
3841 | 10.4k | if (!feasible) |
3842 | 9.82k | res = isl_tab_row_pos; |
3843 | 647 | else |
3844 | 647 | res = (res == isl_tab_row_unknown) ? isl_tab_row_neg27 |
3845 | 647 | : isl_tab_row_any620 ; |
3846 | 10.4k | if (res == isl_tab_row_neg) { |
3847 | 27 | isl_seq_neg(ineq->el, ineq->el, ineq->size); |
3848 | 27 | isl_int_sub_ui(ineq->el[0], ineq->el[0], 1); |
3849 | 27 | } |
3850 | 10.4k | } |
3851 | 13.0k | |
3852 | 13.0k | if (res == isl_tab_row_neg) { |
3853 | 2.13k | /* test for positive values */ |
3854 | 2.13k | int feasible; |
3855 | 2.13k | if (!critical && !strict178 ) |
3856 | 2.13k | isl_int_sub_ui170 (ineq->el[0], ineq->el[0], 1); |
3857 | 2.13k | |
3858 | 2.13k | feasible = sol->context->op->test_ineq(sol->context, ineq->el); |
3859 | 2.13k | if (feasible < 0) |
3860 | 0 | goto error; |
3861 | 2.13k | if (feasible) |
3862 | 2.11k | res = isl_tab_row_any; |
3863 | 2.13k | } |
3864 | 13.0k | |
3865 | 13.0k | isl_vec_free(ineq); |
3866 | 13.0k | return res; |
3867 | 0 | error: |
3868 | 0 | isl_vec_free(ineq); |
3869 | 0 | return isl_tab_row_unknown; |
3870 | 13.0k | } |
3871 | | |
3872 | | static void find_solutions(struct isl_sol *sol, struct isl_tab *tab); |
3873 | | |
3874 | | /* Find solutions for values of the parameters that satisfy the given |
3875 | | * inequality. |
3876 | | * |
3877 | | * We currently take a snapshot of the context tableau that is reset |
3878 | | * when we return from this function, while we make a copy of the main |
3879 | | * tableau, leaving the original main tableau untouched. |
3880 | | * These are fairly arbitrary choices. Making a copy also of the context |
3881 | | * tableau would obviate the need to undo any changes made to it later, |
3882 | | * while taking a snapshot of the main tableau could reduce memory usage. |
3883 | | * If we were to switch to taking a snapshot of the main tableau, |
3884 | | * we would have to keep in mind that we need to save the row signs |
3885 | | * and that we need to do this before saving the current basis |
3886 | | * such that the basis has been restore before we restore the row signs. |
3887 | | */ |
3888 | | static void find_in_pos(struct isl_sol *sol, struct isl_tab *tab, isl_int *ineq) |
3889 | 2.84k | { |
3890 | 2.84k | void *saved; |
3891 | 2.84k | |
3892 | 2.84k | if (!sol->context) |
3893 | 0 | goto error; |
3894 | 2.84k | saved = sol->context->op->save(sol->context); |
3895 | 2.84k | |
3896 | 2.84k | tab = isl_tab_dup(tab); |
3897 | 2.84k | if (!tab) |
3898 | 0 | goto error; |
3899 | 2.84k | |
3900 | 2.84k | sol->context->op->add_ineq(sol->context, ineq, 0, 1); |
3901 | 2.84k | |
3902 | 2.84k | find_solutions(sol, tab); |
3903 | 2.84k | |
3904 | 2.84k | if (!sol->error) |
3905 | 2.84k | sol->context->op->restore(sol->context, saved); |
3906 | 0 | else |
3907 | 0 | sol->context->op->discard(saved); |
3908 | 2.84k | return; |
3909 | 0 | error: |
3910 | 0 | sol->error = 1; |
3911 | 0 | } |
3912 | | |
3913 | | /* Record the absence of solutions for those values of the parameters |
3914 | | * that do not satisfy the given inequality with equality. |
3915 | | */ |
3916 | | static void no_sol_in_strict(struct isl_sol *sol, |
3917 | | struct isl_tab *tab, struct isl_vec *ineq) |
3918 | 18.9k | { |
3919 | 18.9k | int empty; |
3920 | 18.9k | void *saved; |
3921 | 18.9k | |
3922 | 18.9k | if (!sol->context || sol->error) |
3923 | 0 | goto error; |
3924 | 18.9k | saved = sol->context->op->save(sol->context); |
3925 | 18.9k | |
3926 | 18.9k | isl_int_sub_ui(ineq->el[0], ineq->el[0], 1); |
3927 | 18.9k | |
3928 | 18.9k | sol->context->op->add_ineq(sol->context, ineq->el, 1, 0); |
3929 | 18.9k | if (!sol->context) |
3930 | 0 | goto error; |
3931 | 18.9k | |
3932 | 18.9k | empty = tab->empty; |
3933 | 18.9k | tab->empty = 1; |
3934 | 18.9k | sol_add(sol, tab); |
3935 | 18.9k | tab->empty = empty; |
3936 | 18.9k | |
3937 | 18.9k | isl_int_add_ui(ineq->el[0], ineq->el[0], 1); |
3938 | 18.9k | |
3939 | 18.9k | sol->context->op->restore(sol->context, saved); |
3940 | 18.9k | return; |
3941 | 0 | error: |
3942 | 0 | sol->error = 1; |
3943 | 0 | } |
3944 | | |
3945 | | /* Reset all row variables that are marked to have a sign that may |
3946 | | * be both positive and negative to have an unknown sign. |
3947 | | */ |
3948 | | static void reset_any_to_unknown(struct isl_tab *tab) |
3949 | 2.84k | { |
3950 | 2.84k | int row; |
3951 | 2.84k | |
3952 | 23.9k | for (row = tab->n_redundant; row < tab->n_row; ++row21.0k ) { |
3953 | 21.0k | if (!isl_tab_var_from_row(tab, row)->is_nonneg) |
3954 | 110 | continue; |
3955 | 20.9k | if (tab->row_sign[row] == isl_tab_row_any) |
3956 | 3.22k | tab->row_sign[row] = isl_tab_row_unknown; |
3957 | 20.9k | } |
3958 | 2.84k | } |
3959 | | |
3960 | | /* Compute the lexicographic minimum of the set represented by the main |
3961 | | * tableau "tab" within the context "sol->context_tab". |
3962 | | * On entry the sample value of the main tableau is lexicographically |
3963 | | * less than or equal to this lexicographic minimum. |
3964 | | * Pivots are performed until a feasible point is found, which is then |
3965 | | * necessarily equal to the minimum, or until the tableau is found to |
3966 | | * be infeasible. Some pivots may need to be performed for only some |
3967 | | * feasible values of the context tableau. If so, the context tableau |
3968 | | * is split into a part where the pivot is needed and a part where it is not. |
3969 | | * |
3970 | | * Whenever we enter the main loop, the main tableau is such that no |
3971 | | * "obvious" pivots need to be performed on it, where "obvious" means |
3972 | | * that the given row can be seen to be negative without looking at |
3973 | | * the context tableau. In particular, for non-parametric problems, |
3974 | | * no pivots need to be performed on the main tableau. |
3975 | | * The caller of find_solutions is responsible for making this property |
3976 | | * hold prior to the first iteration of the loop, while restore_lexmin |
3977 | | * is called before every other iteration. |
3978 | | * |
3979 | | * Inside the main loop, we first examine the signs of the rows of |
3980 | | * the main tableau within the context of the context tableau. |
3981 | | * If we find a row that is always non-positive for all values of |
3982 | | * the parameters satisfying the context tableau and negative for at |
3983 | | * least one value of the parameters, we perform the appropriate pivot |
3984 | | * and start over. An exception is the case where no pivot can be |
3985 | | * performed on the row. In this case, we require that the sign of |
3986 | | * the row is negative for all values of the parameters (rather than just |
3987 | | * non-positive). This special case is handled inside row_sign, which |
3988 | | * will say that the row can have any sign if it determines that it can |
3989 | | * attain both negative and zero values. |
3990 | | * |
3991 | | * If we can't find a row that always requires a pivot, but we can find |
3992 | | * one or more rows that require a pivot for some values of the parameters |
3993 | | * (i.e., the row can attain both positive and negative signs), then we split |
3994 | | * the context tableau into two parts, one where we force the sign to be |
3995 | | * non-negative and one where we force is to be negative. |
3996 | | * The non-negative part is handled by a recursive call (through find_in_pos). |
3997 | | * Upon returning from this call, we continue with the negative part and |
3998 | | * perform the required pivot. |
3999 | | * |
4000 | | * If no such rows can be found, all rows are non-negative and we have |
4001 | | * found a (rational) feasible point. If we only wanted a rational point |
4002 | | * then we are done. |
4003 | | * Otherwise, we check if all values of the sample point of the tableau |
4004 | | * are integral for the variables. If so, we have found the minimal |
4005 | | * integral point and we are done. |
4006 | | * If the sample point is not integral, then we need to make a distinction |
4007 | | * based on whether the constant term is non-integral or the coefficients |
4008 | | * of the parameters. Furthermore, in order to decide how to handle |
4009 | | * the non-integrality, we also need to know whether the coefficients |
4010 | | * of the other columns in the tableau are integral. This leads |
4011 | | * to the following table. The first two rows do not correspond |
4012 | | * to a non-integral sample point and are only mentioned for completeness. |
4013 | | * |
4014 | | * constant parameters other |
4015 | | * |
4016 | | * int int int | |
4017 | | * int int rat | -> no problem |
4018 | | * |
4019 | | * rat int int -> fail |
4020 | | * |
4021 | | * rat int rat -> cut |
4022 | | * |
4023 | | * int rat rat | |
4024 | | * rat rat rat | -> parametric cut |
4025 | | * |
4026 | | * int rat int | |
4027 | | * rat rat int | -> split context |
4028 | | * |
4029 | | * If the parametric constant is completely integral, then there is nothing |
4030 | | * to be done. If the constant term is non-integral, but all the other |
4031 | | * coefficient are integral, then there is nothing that can be done |
4032 | | * and the tableau has no integral solution. |
4033 | | * If, on the other hand, one or more of the other columns have rational |
4034 | | * coefficients, but the parameter coefficients are all integral, then |
4035 | | * we can perform a regular (non-parametric) cut. |
4036 | | * Finally, if there is any parameter coefficient that is non-integral, |
4037 | | * then we need to involve the context tableau. There are two cases here. |
4038 | | * If at least one other column has a rational coefficient, then we |
4039 | | * can perform a parametric cut in the main tableau by adding a new |
4040 | | * integer division in the context tableau. |
4041 | | * If all other columns have integral coefficients, then we need to |
4042 | | * enforce that the rational combination of parameters (c + \sum a_i y_i)/m |
4043 | | * is always integral. We do this by introducing an integer division |
4044 | | * q = floor((c + \sum a_i y_i)/m) and stipulating that its argument should |
4045 | | * always be integral in the context tableau, i.e., m q = c + \sum a_i y_i. |
4046 | | * Since q is expressed in the tableau as |
4047 | | * c + \sum a_i y_i - m q >= 0 |
4048 | | * -c - \sum a_i y_i + m q + m - 1 >= 0 |
4049 | | * it is sufficient to add the inequality |
4050 | | * -c - \sum a_i y_i + m q >= 0 |
4051 | | * In the part of the context where this inequality does not hold, the |
4052 | | * main tableau is marked as being empty. |
4053 | | */ |
4054 | | static void find_solutions(struct isl_sol *sol, struct isl_tab *tab) |
4055 | 10.0k | { |
4056 | 10.0k | struct isl_context *context; |
4057 | 10.0k | int r; |
4058 | 10.0k | |
4059 | 10.0k | if (!tab || sol->error) |
4060 | 0 | goto error; |
4061 | 10.0k | |
4062 | 10.0k | context = sol->context; |
4063 | 10.0k | |
4064 | 10.0k | if (tab->empty) |
4065 | 0 | goto done; |
4066 | 10.0k | if (context->op->is_empty(context)) |
4067 | 0 | goto done; |
4068 | 10.0k | |
4069 | 14.1k | for (r = 0; 10.0k r >= 0 && tab && !tab->empty; r = restore_lexmin(tab)4.16k ) { |
4070 | 11.6k | int flags; |
4071 | 11.6k | int row; |
4072 | 11.6k | enum isl_tab_row_sign sgn; |
4073 | 11.6k | int split = -1; |
4074 | 11.6k | int n_split = 0; |
4075 | 11.6k | |
4076 | 85.5k | for (row = tab->n_redundant; row < tab->n_row; ++row73.8k ) { |
4077 | 73.9k | if (!isl_tab_var_from_row(tab, row)->is_nonneg) |
4078 | 1.05k | continue; |
4079 | 72.8k | sgn = row_sign(tab, sol, row); |
4080 | 72.8k | if (!sgn) |
4081 | 0 | goto error; |
4082 | 72.8k | tab->row_sign[row] = sgn; |
4083 | 72.8k | if (sgn == isl_tab_row_any) |
4084 | 3.22k | n_split++; |
4085 | 72.8k | if (sgn == isl_tab_row_any && split == -13.22k ) |
4086 | 2.84k | split = row; |
4087 | 72.8k | if (sgn == isl_tab_row_neg) |
4088 | 21 | break; |
4089 | 72.8k | } |
4090 | 11.6k | if (row < tab->n_row) |
4091 | 21 | continue; |
4092 | 11.6k | if (split != -1) { |
4093 | 2.84k | struct isl_vec *ineq; |
4094 | 2.84k | if (n_split != 1) |
4095 | 287 | split = context->op->best_split(context, tab); |
4096 | 2.84k | if (split < 0) |
4097 | 0 | goto error; |
4098 | 2.84k | ineq = get_row_parameter_ineq(tab, split); |
4099 | 2.84k | if (!ineq) |
4100 | 0 | goto error; |
4101 | 2.84k | is_strict(ineq); |
4102 | 2.84k | reset_any_to_unknown(tab); |
4103 | 2.84k | tab->row_sign[split] = isl_tab_row_pos; |
4104 | 2.84k | sol_inc_level(sol); |
4105 | 2.84k | find_in_pos(sol, tab, ineq->el); |
4106 | 2.84k | tab->row_sign[split] = isl_tab_row_neg; |
4107 | 2.84k | isl_seq_neg(ineq->el, ineq->el, ineq->size); |
4108 | 2.84k | isl_int_sub_ui(ineq->el[0], ineq->el[0], 1); |
4109 | 2.84k | if (!sol->error) |
4110 | 2.84k | context->op->add_ineq(context, ineq->el, 0, 1); |
4111 | 2.84k | isl_vec_free(ineq); |
4112 | 2.84k | if (sol->error) |
4113 | 0 | goto error; |
4114 | 2.84k | continue; |
4115 | 2.84k | } |
4116 | 8.82k | if (tab->rational) |
4117 | 3 | break; |
4118 | 8.82k | row = first_non_integer_row(tab, &flags); |
4119 | 8.82k | if (row < 0) |
4120 | 7.51k | break; |
4121 | 1.30k | if (ISL_FL_ISSET(flags, I_PAR)) { |
4122 | 482 | if (ISL_FL_ISSET(flags, I_VAR)) { |
4123 | 0 | if (isl_tab_mark_empty(tab) < 0) |
4124 | 0 | goto error; |
4125 | 0 | break; |
4126 | 0 | } |
4127 | 482 | row = add_cut(tab, row); |
4128 | 824 | } else if (ISL_FL_ISSET(flags, I_VAR)) { |
4129 | 117 | struct isl_vec *div; |
4130 | 117 | struct isl_vec *ineq; |
4131 | 117 | int d; |
4132 | 117 | div = get_row_split_div(tab, row); |
4133 | 117 | if (!div) |
4134 | 0 | goto error; |
4135 | 117 | d = context->op->get_div(context, tab, div); |
4136 | 117 | isl_vec_free(div); |
4137 | 117 | if (d < 0) |
4138 | 0 | goto error; |
4139 | 117 | ineq = ineq_for_div(context->op->peek_basic_set(context), d); |
4140 | 117 | if (!ineq) |
4141 | 0 | goto error; |
4142 | 117 | sol_inc_level(sol); |
4143 | 117 | no_sol_in_strict(sol, tab, ineq); |
4144 | 117 | isl_seq_neg(ineq->el, ineq->el, ineq->size); |
4145 | 117 | context->op->add_ineq(context, ineq->el, 1, 1); |
4146 | 117 | isl_vec_free(ineq); |
4147 | 117 | if (sol->error || !context->op->is_ok(context)) |
4148 | 0 | goto error; |
4149 | 117 | tab = set_row_cst_to_div(tab, row, d); |
4150 | 117 | if (context->op->is_empty(context)) |
4151 | 0 | break; |
4152 | 707 | } else |
4153 | 707 | row = add_parametric_cut(tab, row, context); |
4154 | 1.30k | if (row < 0) |
4155 | 0 | goto error; |
4156 | 1.30k | } |
4157 | 10.0k | if (r < 0) |
4158 | 0 | goto error; |
4159 | 10.0k | done: |
4160 | 10.0k | sol_add(sol, tab); |
4161 | 10.0k | isl_tab_free(tab); |
4162 | 10.0k | return; |
4163 | 0 | error: |
4164 | 0 | isl_tab_free(tab); |
4165 | 0 | sol->error = 1; |
4166 | 0 | } |
4167 | | |
4168 | | /* Does "sol" contain a pair of partial solutions that could potentially |
4169 | | * be merged? |
4170 | | * |
4171 | | * We currently only check that "sol" is not in an error state |
4172 | | * and that there are at least two partial solutions of which the final two |
4173 | | * are defined at the same level. |
4174 | | */ |
4175 | | static int sol_has_mergeable_solutions(struct isl_sol *sol) |
4176 | 7.16k | { |
4177 | 7.16k | if (sol->error) |
4178 | 6 | return 0; |
4179 | 7.16k | if (!sol->partial) |
4180 | 74 | return 0; |
4181 | 7.08k | if (!sol->partial->next) |
4182 | 5.10k | return 0; |
4183 | 1.98k | return sol->partial->level == sol->partial->next->level; |
4184 | 1.98k | } |
4185 | | |
4186 | | /* Compute the lexicographic minimum of the set represented by the main |
4187 | | * tableau "tab" within the context "sol->context_tab". |
4188 | | * |
4189 | | * As a preprocessing step, we first transfer all the purely parametric |
4190 | | * equalities from the main tableau to the context tableau, i.e., |
4191 | | * parameters that have been pivoted to a row. |
4192 | | * These equalities are ignored by the main algorithm, because the |
4193 | | * corresponding rows may not be marked as being non-negative. |
4194 | | * In parts of the context where the added equality does not hold, |
4195 | | * the main tableau is marked as being empty. |
4196 | | * |
4197 | | * Before we embark on the actual computation, we save a copy |
4198 | | * of the context. When we return, we check if there are any |
4199 | | * partial solutions that can potentially be merged. If so, |
4200 | | * we perform a rollback to the initial state of the context. |
4201 | | * The merging of partial solutions happens inside calls to |
4202 | | * sol_dec_level that are pushed onto the undo stack of the context. |
4203 | | * If there are no partial solutions that can potentially be merged |
4204 | | * then the rollback is skipped as it would just be wasted effort. |
4205 | | */ |
4206 | | static void find_solutions_main(struct isl_sol *sol, struct isl_tab *tab) |
4207 | 7.16k | { |
4208 | 7.16k | int row; |
4209 | 7.16k | void *saved; |
4210 | 7.16k | |
4211 | 7.16k | if (!tab) |
4212 | 0 | goto error; |
4213 | 7.16k | |
4214 | 7.16k | sol->level = 0; |
4215 | 7.16k | |
4216 | 79.4k | for (row = tab->n_redundant; row < tab->n_row; ++row72.2k ) { |
4217 | 72.2k | int p; |
4218 | 72.2k | struct isl_vec *eq; |
4219 | 72.2k | |
4220 | 72.2k | if (!row_is_parameter_var(tab, row)) |
4221 | 62.8k | continue; |
4222 | 9.41k | if (tab->row_var[row] < tab->n_param) |
4223 | 9.41k | p = tab->row_var[row]; |
4224 | 0 | else |
4225 | 0 | p = tab->row_var[row] |
4226 | 0 | + tab->n_param - (tab->n_var - tab->n_div); |
4227 | 9.41k | |
4228 | 9.41k | eq = isl_vec_alloc(tab->mat->ctx, 1+tab->n_param+tab->n_div); |
4229 | 9.41k | if (!eq) |
4230 | 0 | goto error; |
4231 | 9.41k | get_row_parameter_line(tab, row, eq->el); |
4232 | 9.41k | isl_int_neg(eq->el[1 + p], tab->mat->row[row][0]); |
4233 | 9.41k | eq = isl_vec_normalize(eq); |
4234 | 9.41k | |
4235 | 9.41k | sol_inc_level(sol); |
4236 | 9.41k | no_sol_in_strict(sol, tab, eq); |
4237 | 9.41k | |
4238 | 9.41k | isl_seq_neg(eq->el, eq->el, eq->size); |
4239 | 9.41k | sol_inc_level(sol); |
4240 | 9.41k | no_sol_in_strict(sol, tab, eq); |
4241 | 9.41k | isl_seq_neg(eq->el, eq->el, eq->size); |
4242 | 9.41k | |
4243 | 9.41k | sol->context->op->add_eq(sol->context, eq->el, 1, 1); |
4244 | 9.41k | |
4245 | 9.41k | isl_vec_free(eq); |
4246 | 9.41k | |
4247 | 9.41k | if (isl_tab_mark_redundant(tab, row) < 0) |
4248 | 0 | goto error; |
4249 | 9.41k | |
4250 | 9.41k | if (sol->context->op->is_empty(sol->context)) |
4251 | 0 | break; |
4252 | 9.41k | |
4253 | 9.41k | row = tab->n_redundant - 1; |
4254 | 9.41k | } |
4255 | 7.16k | |
4256 | 7.16k | saved = sol->context->op->save(sol->context); |
4257 | 7.16k | |
4258 | 7.16k | find_solutions(sol, tab); |
4259 | 7.16k | |
4260 | 7.16k | if (sol_has_mergeable_solutions(sol)) |
4261 | 1.89k | sol->context->op->restore(sol->context, saved); |
4262 | 5.27k | else |
4263 | 5.27k | sol->context->op->discard(saved); |
4264 | 7.16k | |
4265 | 7.16k | sol->level = 0; |
4266 | 7.16k | sol_pop(sol); |
4267 | 7.16k | |
4268 | 7.16k | return; |
4269 | 0 | error: |
4270 | 0 | isl_tab_free(tab); |
4271 | 0 | sol->error = 1; |
4272 | 0 | } |
4273 | | |
4274 | | /* Check if integer division "div" of "dom" also occurs in "bmap". |
4275 | | * If so, return its position within the divs. |
4276 | | * If not, return -1. |
4277 | | */ |
4278 | | static int find_context_div(struct isl_basic_map *bmap, |
4279 | | struct isl_basic_set *dom, unsigned div) |
4280 | 526 | { |
4281 | 526 | int i; |
4282 | 526 | unsigned b_dim = isl_space_dim(bmap->dim, isl_dim_all); |
4283 | 526 | unsigned d_dim = isl_space_dim(dom->dim, isl_dim_all); |
4284 | 526 | |
4285 | 526 | if (isl_int_is_zero(dom->div[div][0])) |
4286 | 526 | return -1144 ; |
4287 | 382 | if (isl_seq_first_non_zero(dom->div[div] + 2 + d_dim, dom->n_div) != -1) |
4288 | 2 | return -1; |
4289 | 380 | |
4290 | 563 | for (i = 0; 380 i < bmap->n_div; ++i183 ) { |
4291 | 297 | if (isl_int_is_zero(bmap->div[i][0])) |
4292 | 297 | continue29 ; |
4293 | 268 | if (isl_seq_first_non_zero(bmap->div[i] + 2 + d_dim, |
4294 | 268 | (b_dim - d_dim) + bmap->n_div) != -1) |
4295 | 68 | continue; |
4296 | 200 | if (isl_seq_eq(bmap->div[i], dom->div[div], 2 + d_dim)) |
4297 | 114 | return i; |
4298 | 200 | } |
4299 | 380 | return -1266 ; |
4300 | 380 | } |
4301 | | |
4302 | | /* The correspondence between the variables in the main tableau, |
4303 | | * the context tableau, and the input map and domain is as follows. |
4304 | | * The first n_param and the last n_div variables of the main tableau |
4305 | | * form the variables of the context tableau. |
4306 | | * In the basic map, these n_param variables correspond to the |
4307 | | * parameters and the input dimensions. In the domain, they correspond |
4308 | | * to the parameters and the set dimensions. |
4309 | | * The n_div variables correspond to the integer divisions in the domain. |
4310 | | * To ensure that everything lines up, we may need to copy some of the |
4311 | | * integer divisions of the domain to the map. These have to be placed |
4312 | | * in the same order as those in the context and they have to be placed |
4313 | | * after any other integer divisions that the map may have. |
4314 | | * This function performs the required reordering. |
4315 | | */ |
4316 | | static __isl_give isl_basic_map *align_context_divs( |
4317 | | __isl_take isl_basic_map *bmap, __isl_keep isl_basic_set *dom) |
4318 | 198 | { |
4319 | 198 | int i; |
4320 | 198 | int common = 0; |
4321 | 198 | int other; |
4322 | 198 | |
4323 | 461 | for (i = 0; i < dom->n_div; ++i263 ) |
4324 | 263 | if (find_context_div(bmap, dom, i) != -1) |
4325 | 57 | common++; |
4326 | 198 | other = bmap->n_div - common; |
4327 | 198 | if (dom->n_div - common > 0) { |
4328 | 161 | bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), |
4329 | 161 | dom->n_div - common, 0, 0); |
4330 | 161 | if (!bmap) |
4331 | 0 | return NULL; |
4332 | 198 | } |
4333 | 461 | for (i = 0; 198 i < dom->n_div; ++i263 ) { |
4334 | 263 | int pos = find_context_div(bmap, dom, i); |
4335 | 263 | if (pos < 0) { |
4336 | 206 | pos = isl_basic_map_alloc_div(bmap); |
4337 | 206 | if (pos < 0) |
4338 | 0 | goto error; |
4339 | 206 | isl_int_set_si(bmap->div[pos][0], 0); |
4340 | 206 | } |
4341 | 263 | if (pos != other + i) |
4342 | 30 | isl_basic_map_swap_div(bmap, pos, other + i); |
4343 | 263 | } |
4344 | 198 | return bmap; |
4345 | 0 | error: |
4346 | 0 | isl_basic_map_free(bmap); |
4347 | 0 | return NULL; |
4348 | 198 | } |
4349 | | |
4350 | | /* Base case of isl_tab_basic_map_partial_lexopt, after removing |
4351 | | * some obvious symmetries. |
4352 | | * |
4353 | | * We make sure the divs in the domain are properly ordered, |
4354 | | * because they will be added one by one in the given order |
4355 | | * during the construction of the solution map. |
4356 | | * Furthermore, make sure that the known integer divisions |
4357 | | * appear before any unknown integer division because the solution |
4358 | | * may depend on the known integer divisions, while anything that |
4359 | | * depends on any variable starting from the first unknown integer |
4360 | | * division is ignored in sol_pma_add. |
4361 | | */ |
4362 | | static struct isl_sol *basic_map_partial_lexopt_base_sol( |
4363 | | __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom, |
4364 | | __isl_give isl_set **empty, int max, |
4365 | | struct isl_sol *(*init)(__isl_keep isl_basic_map *bmap, |
4366 | | __isl_take isl_basic_set *dom, int track_empty, int max)) |
4367 | 7.85k | { |
4368 | 7.85k | struct isl_tab *tab; |
4369 | 7.85k | struct isl_sol *sol = NULL; |
4370 | 7.85k | struct isl_context *context; |
4371 | 7.85k | |
4372 | 7.85k | if (dom->n_div) { |
4373 | 198 | dom = isl_basic_set_sort_divs(dom); |
4374 | 198 | bmap = align_context_divs(bmap, dom); |
4375 | 198 | } |
4376 | 7.85k | sol = init(bmap, dom, !!empty, max); |
4377 | 7.85k | if (!sol) |
4378 | 0 | goto error; |
4379 | 7.85k | |
4380 | 7.85k | context = sol->context; |
4381 | 7.85k | if (isl_basic_set_plain_is_empty(context->op->peek_basic_set(context))) |
4382 | 0 | /* nothing */; |
4383 | 7.85k | else if (isl_basic_map_plain_is_empty(bmap)) { |
4384 | 687 | if (sol->add_empty) |
4385 | 683 | sol->add_empty(sol, |
4386 | 683 | isl_basic_set_copy(context->op->peek_basic_set(context))); |
4387 | 7.16k | } else { |
4388 | 7.16k | tab = tab_for_lexmin(bmap, |
4389 | 7.16k | context->op->peek_basic_set(context), 1, max); |
4390 | 7.16k | tab = context->op->detect_nonnegative_parameters(context, tab); |
4391 | 7.16k | find_solutions_main(sol, tab); |
4392 | 7.16k | } |
4393 | 7.85k | if (sol->error) |
4394 | 6 | goto error; |
4395 | 7.85k | |
4396 | 7.85k | isl_basic_map_free(bmap); |
4397 | 7.85k | return sol; |
4398 | 6 | error: |
4399 | 6 | sol_free(sol); |
4400 | 6 | isl_basic_map_free(bmap); |
4401 | 6 | return NULL; |
4402 | 7.85k | } |
4403 | | |
4404 | | /* Base case of isl_tab_basic_map_partial_lexopt, after removing |
4405 | | * some obvious symmetries. |
4406 | | * |
4407 | | * We call basic_map_partial_lexopt_base_sol and extract the results. |
4408 | | */ |
4409 | | static __isl_give isl_map *basic_map_partial_lexopt_base( |
4410 | | __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom, |
4411 | | __isl_give isl_set **empty, int max) |
4412 | 3.64k | { |
4413 | 3.64k | isl_map *result = NULL; |
4414 | 3.64k | struct isl_sol *sol; |
4415 | 3.64k | struct isl_sol_map *sol_map; |
4416 | 3.64k | |
4417 | 3.64k | sol = basic_map_partial_lexopt_base_sol(bmap, dom, empty, max, |
4418 | 3.64k | &sol_map_init); |
4419 | 3.64k | if (!sol) |
4420 | 0 | return NULL; |
4421 | 3.64k | sol_map = (struct isl_sol_map *) sol; |
4422 | 3.64k | |
4423 | 3.64k | result = isl_map_copy(sol_map->map); |
4424 | 3.64k | if (empty) |
4425 | 2.75k | *empty = isl_set_copy(sol_map->empty); |
4426 | 3.64k | sol_free(&sol_map->sol); |
4427 | 3.64k | return result; |
4428 | 3.64k | } |
4429 | | |
4430 | | /* Return a count of the number of occurrences of the "n" first |
4431 | | * variables in the inequality constraints of "bmap". |
4432 | | */ |
4433 | | static __isl_give int *count_occurrences(__isl_keep isl_basic_map *bmap, |
4434 | | int n) |
4435 | 8.09k | { |
4436 | 8.09k | int i, j; |
4437 | 8.09k | isl_ctx *ctx; |
4438 | 8.09k | int *occurrences; |
4439 | 8.09k | |
4440 | 8.09k | if (!bmap) |
4441 | 0 | return NULL; |
4442 | 8.09k | ctx = isl_basic_map_get_ctx(bmap); |
4443 | 8.09k | occurrences = isl_calloc_array(ctx, int, n); |
4444 | 8.09k | if (!occurrences) |
4445 | 0 | return NULL; |
4446 | 8.09k | |
4447 | 28.7k | for (i = 0; 8.09k i < bmap->n_ineq; ++i20.6k ) { |
4448 | 108k | for (j = 0; j < n; ++j88.1k ) { |
4449 | 88.1k | if (!isl_int_is_zero(bmap->ineq[i][1 + j])) |
4450 | 88.1k | occurrences[j]++16.7k ; |
4451 | 88.1k | } |
4452 | 20.6k | } |
4453 | 8.09k | |
4454 | 8.09k | return occurrences; |
4455 | 8.09k | } |
4456 | | |
4457 | | /* Do all of the "n" variables with non-zero coefficients in "c" |
4458 | | * occur in exactly a single constraint. |
4459 | | * "occurrences" is an array of length "n" containing the number |
4460 | | * of occurrences of each of the variables in the inequality constraints. |
4461 | | */ |
4462 | | static int single_occurrence(int n, isl_int *c, int *occurrences) |
4463 | 9.14k | { |
4464 | 9.14k | int i; |
4465 | 9.14k | |
4466 | 32.5k | for (i = 0; i < n; ++i23.4k ) { |
4467 | 25.6k | if (isl_int_is_zero(c[i])) |
4468 | 25.6k | continue22.5k ; |
4469 | 3.11k | if (occurrences[i] != 1) |
4470 | 2.20k | return 0; |
4471 | 3.11k | } |
4472 | 9.14k | |
4473 | 9.14k | return 16.94k ; |
4474 | 9.14k | } |
4475 | | |
4476 | | /* Do all of the "n" initial variables that occur in inequality constraint |
4477 | | * "ineq" of "bmap" only occur in that constraint? |
4478 | | */ |
4479 | | static int all_single_occurrence(__isl_keep isl_basic_map *bmap, int ineq, |
4480 | | int n) |
4481 | 3 | { |
4482 | 3 | int i, j; |
4483 | 3 | |
4484 | 3 | for (i = 0; i < n; ++i0 ) { |
4485 | 3 | if (isl_int_is_zero(bmap->ineq[ineq][1 + i])) |
4486 | 3 | continue0 ; |
4487 | 3 | for (j = 0; j < bmap->n_ineq; ++j0 ) { |
4488 | 3 | if (j == ineq) |
4489 | 0 | continue; |
4490 | 3 | if (!isl_int_is_zero(bmap->ineq[j][1 + i])) |
4491 | 3 | return 0; |
4492 | 3 | } |
4493 | 3 | } |
4494 | 3 | |
4495 | 3 | return 10 ; |
4496 | 3 | } |
4497 | | |
4498 | | /* Structure used during detection of parallel constraints. |
4499 | | * n_in: number of "input" variables: isl_dim_param + isl_dim_in |
4500 | | * n_out: number of "output" variables: isl_dim_out + isl_dim_div |
4501 | | * val: the coefficients of the output variables |
4502 | | */ |
4503 | | struct isl_constraint_equal_info { |
4504 | | unsigned n_in; |
4505 | | unsigned n_out; |
4506 | | isl_int *val; |
4507 | | }; |
4508 | | |
4509 | | /* Check whether the coefficients of the output variables |
4510 | | * of the constraint in "entry" are equal to info->val. |
4511 | | */ |
4512 | | static int constraint_equal(const void *entry, const void *val) |
4513 | 238 | { |
4514 | 238 | isl_int **row = (isl_int **)entry; |
4515 | 238 | const struct isl_constraint_equal_info *info = val; |
4516 | 238 | |
4517 | 238 | return isl_seq_eq((*row) + 1 + info->n_in, info->val, info->n_out); |
4518 | 238 | } |
4519 | | |
4520 | | /* Check whether "bmap" has a pair of constraints that have |
4521 | | * the same coefficients for the output variables. |
4522 | | * Note that the coefficients of the existentially quantified |
4523 | | * variables need to be zero since the existentially quantified |
4524 | | * of the result are usually not the same as those of the input. |
4525 | | * Furthermore, check that each of the input variables that occur |
4526 | | * in those constraints does not occur in any other constraint. |
4527 | | * If so, return true and return the row indices of the two constraints |
4528 | | * in *first and *second. |
4529 | | */ |
4530 | | static isl_bool parallel_constraints(__isl_keep isl_basic_map *bmap, |
4531 | | int *first, int *second) |
4532 | 8.09k | { |
4533 | 8.09k | int i; |
4534 | 8.09k | isl_ctx *ctx; |
4535 | 8.09k | int *occurrences = NULL; |
4536 | 8.09k | struct isl_hash_table *table = NULL; |
4537 | 8.09k | struct isl_hash_table_entry *entry; |
4538 | 8.09k | struct isl_constraint_equal_info info; |
4539 | 8.09k | unsigned n_out; |
4540 | 8.09k | unsigned n_div; |
4541 | 8.09k | |
4542 | 8.09k | ctx = isl_basic_map_get_ctx(bmap); |
4543 | 8.09k | table = isl_hash_table_alloc(ctx, bmap->n_ineq); |
4544 | 8.09k | if (!table) |
4545 | 0 | goto error; |
4546 | 8.09k | |
4547 | 8.09k | info.n_in = isl_basic_map_dim(bmap, isl_dim_param) + |
4548 | 8.09k | isl_basic_map_dim(bmap, isl_dim_in); |
4549 | 8.09k | occurrences = count_occurrences(bmap, info.n_in); |
4550 | 8.09k | if (info.n_in && !occurrences6.61k ) |
4551 | 0 | goto error; |
4552 | 8.09k | n_out = isl_basic_map_dim(bmap, isl_dim_out); |
4553 | 8.09k | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
4554 | 8.09k | info.n_out = n_out + n_div; |
4555 | 28.3k | for (i = 0; i < bmap->n_ineq; ++i20.2k ) { |
4556 | 20.4k | uint32_t hash; |
4557 | 20.4k | |
4558 | 20.4k | info.val = bmap->ineq[i] + 1 + info.n_in; |
4559 | 20.4k | if (isl_seq_first_non_zero(info.val, n_out) < 0) |
4560 | 11.1k | continue; |
4561 | 9.30k | if (isl_seq_first_non_zero(info.val + n_out, n_div) >= 0) |
4562 | 153 | continue; |
4563 | 9.14k | if (!single_occurrence(info.n_in, bmap->ineq[i] + 1, |
4564 | 9.14k | occurrences)) |
4565 | 2.20k | continue; |
4566 | 6.94k | hash = isl_seq_get_hash(info.val, info.n_out); |
4567 | 6.94k | entry = isl_hash_table_find(ctx, table, hash, |
4568 | 6.94k | constraint_equal, &info, 1); |
4569 | 6.94k | if (!entry) |
4570 | 0 | goto error; |
4571 | 6.94k | if (entry->data) |
4572 | 238 | break; |
4573 | 6.71k | entry->data = &bmap->ineq[i]; |
4574 | 6.71k | } |
4575 | 8.09k | |
4576 | 8.09k | if (i < bmap->n_ineq) { |
4577 | 238 | *first = ((isl_int **)entry->data) - bmap->ineq; |
4578 | 238 | *second = i; |
4579 | 238 | } |
4580 | 8.09k | |
4581 | 8.09k | isl_hash_table_free(ctx, table); |
4582 | 8.09k | free(occurrences); |
4583 | 8.09k | |
4584 | 8.09k | return i < bmap->n_ineq; |
4585 | 0 | error: |
4586 | 0 | isl_hash_table_free(ctx, table); |
4587 | 0 | free(occurrences); |
4588 | 0 | return isl_bool_error; |
4589 | 8.09k | } |
4590 | | |
4591 | | /* Given a set of upper bounds in "var", add constraints to "bset" |
4592 | | * that make the i-th bound smallest. |
4593 | | * |
4594 | | * In particular, if there are n bounds b_i, then add the constraints |
4595 | | * |
4596 | | * b_i <= b_j for j > i |
4597 | | * b_i < b_j for j < i |
4598 | | */ |
4599 | | static __isl_give isl_basic_set *select_minimum(__isl_take isl_basic_set *bset, |
4600 | | __isl_keep isl_mat *var, int i) |
4601 | 842 | { |
4602 | 842 | isl_ctx *ctx; |
4603 | 842 | int j, k; |
4604 | 842 | |
4605 | 842 | ctx = isl_mat_get_ctx(var); |
4606 | 842 | |
4607 | 2.52k | for (j = 0; j < var->n_row; ++j1.68k ) { |
4608 | 1.68k | if (j == i) |
4609 | 842 | continue; |
4610 | 842 | k = isl_basic_set_alloc_inequality(bset); |
4611 | 842 | if (k < 0) |
4612 | 0 | goto error; |
4613 | 842 | isl_seq_combine(bset->ineq[k], ctx->one, var->row[j], |
4614 | 842 | ctx->negone, var->row[i], var->n_col); |
4615 | 842 | isl_int_set_si(bset->ineq[k][var->n_col], 0); |
4616 | 842 | if (j < i) |
4617 | 842 | isl_int_sub_ui421 (bset->ineq[k][0], bset->ineq[k][0], 1); |
4618 | 842 | } |
4619 | 842 | |
4620 | 842 | bset = isl_basic_set_finalize(bset); |
4621 | 842 | |
4622 | 842 | return bset; |
4623 | 0 | error: |
4624 | 0 | isl_basic_set_free(bset); |
4625 | 0 | return NULL; |
4626 | 842 | } |
4627 | | |
4628 | | /* Given a set of upper bounds on the last "input" variable m, |
4629 | | * construct a set that assigns the minimal upper bound to m, i.e., |
4630 | | * construct a set that divides the space into cells where one |
4631 | | * of the upper bounds is smaller than all the others and assign |
4632 | | * this upper bound to m. |
4633 | | * |
4634 | | * In particular, if there are n bounds b_i, then the result |
4635 | | * consists of n basic sets, each one of the form |
4636 | | * |
4637 | | * m = b_i |
4638 | | * b_i <= b_j for j > i |
4639 | | * b_i < b_j for j < i |
4640 | | */ |
4641 | | static __isl_give isl_set *set_minimum(__isl_take isl_space *dim, |
4642 | | __isl_take isl_mat *var) |
4643 | 238 | { |
4644 | 238 | int i, k; |
4645 | 238 | isl_basic_set *bset = NULL; |
4646 | 238 | isl_set *set = NULL; |
4647 | 238 | |
4648 | 238 | if (!dim || !var) |
4649 | 0 | goto error; |
4650 | 238 | |
4651 | 238 | set = isl_set_alloc_space(isl_space_copy(dim), |
4652 | 238 | var->n_row, ISL_SET_DISJOINT); |
4653 | 238 | |
4654 | 714 | for (i = 0; i < var->n_row; ++i476 ) { |
4655 | 476 | bset = isl_basic_set_alloc_space(isl_space_copy(dim), 0, |
4656 | 476 | 1, var->n_row - 1); |
4657 | 476 | k = isl_basic_set_alloc_equality(bset); |
4658 | 476 | if (k < 0) |
4659 | 0 | goto error; |
4660 | 476 | isl_seq_cpy(bset->eq[k], var->row[i], var->n_col); |
4661 | 476 | isl_int_set_si(bset->eq[k][var->n_col], -1); |
4662 | 476 | bset = select_minimum(bset, var, i); |
4663 | 476 | set = isl_set_add_basic_set(set, bset); |
4664 | 476 | } |
4665 | 238 | |
4666 | 238 | isl_space_free(dim); |
4667 | 238 | isl_mat_free(var); |
4668 | 238 | return set; |
4669 | 0 | error: |
4670 | 0 | isl_basic_set_free(bset); |
4671 | 0 | isl_set_free(set); |
4672 | 0 | isl_space_free(dim); |
4673 | 0 | isl_mat_free(var); |
4674 | 0 | return NULL; |
4675 | 238 | } |
4676 | | |
4677 | | /* Given that the last input variable of "bmap" represents the minimum |
4678 | | * of the bounds in "cst", check whether we need to split the domain |
4679 | | * based on which bound attains the minimum. |
4680 | | * |
4681 | | * A split is needed when the minimum appears in an integer division |
4682 | | * or in an equality. Otherwise, it is only needed if it appears in |
4683 | | * an upper bound that is different from the upper bounds on which it |
4684 | | * is defined. |
4685 | | */ |
4686 | | static isl_bool need_split_basic_map(__isl_keep isl_basic_map *bmap, |
4687 | | __isl_keep isl_mat *cst) |
4688 | 123 | { |
4689 | 123 | int i, j; |
4690 | 123 | unsigned total; |
4691 | 123 | unsigned pos; |
4692 | 123 | |
4693 | 123 | pos = cst->n_col - 1; |
4694 | 123 | total = isl_basic_map_dim(bmap, isl_dim_all); |
4695 | 123 | |
4696 | 158 | for (i = 0; i < bmap->n_div; ++i35 ) |
4697 | 113 | if (!isl_int_is_zero(bmap->div[i][2 + pos])) |
4698 | 113 | return isl_bool_true78 ; |
4699 | 123 | |
4700 | 123 | for (i = 0; 45 i < bmap->n_eq92 ; ++i47 ) |
4701 | 56 | if (!isl_int_is_zero(bmap->eq[i][1 + pos])) |
4702 | 56 | return isl_bool_true9 ; |
4703 | 45 | |
4704 | 163 | for (i = 0; 36 i < bmap->n_ineq; ++i127 ) { |
4705 | 148 | if (isl_int_is_nonneg(bmap->ineq[i][1 + pos])) |
4706 | 148 | continue85 ; |
4707 | 63 | if (!isl_int_is_negone(bmap->ineq[i][1 + pos])) |
4708 | 63 | return isl_bool_true0 ; |
4709 | 63 | if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + pos + 1, |
4710 | 63 | total - pos - 1) >= 0) |
4711 | 15 | return isl_bool_true; |
4712 | 48 | |
4713 | 81 | for (j = 0; 48 j < cst->n_row; ++j33 ) |
4714 | 75 | if (isl_seq_eq(bmap->ineq[i], cst->row[j], cst->n_col)) |
4715 | 42 | break; |
4716 | 48 | if (j >= cst->n_row) |
4717 | 6 | return isl_bool_true; |
4718 | 48 | } |
4719 | 36 | |
4720 | 36 | return isl_bool_false15 ; |
4721 | 36 | } |
4722 | | |
4723 | | /* Given that the last set variable of "bset" represents the minimum |
4724 | | * of the bounds in "cst", check whether we need to split the domain |
4725 | | * based on which bound attains the minimum. |
4726 | | * |
4727 | | * We simply call need_split_basic_map here. This is safe because |
4728 | | * the position of the minimum is computed from "cst" and not |
4729 | | * from "bmap". |
4730 | | */ |
4731 | | static isl_bool need_split_basic_set(__isl_keep isl_basic_set *bset, |
4732 | | __isl_keep isl_mat *cst) |
4733 | 19 | { |
4734 | 19 | return need_split_basic_map(bset_to_bmap(bset), cst); |
4735 | 19 | } |
4736 | | |
4737 | | /* Given that the last set variable of "set" represents the minimum |
4738 | | * of the bounds in "cst", check whether we need to split the domain |
4739 | | * based on which bound attains the minimum. |
4740 | | */ |
4741 | | static isl_bool need_split_set(__isl_keep isl_set *set, __isl_keep isl_mat *cst) |
4742 | 13 | { |
4743 | 13 | int i; |
4744 | 13 | |
4745 | 22 | for (i = 0; i < set->n; ++i9 ) { |
4746 | 13 | isl_bool split; |
4747 | 13 | |
4748 | 13 | split = need_split_basic_set(set->p[i], cst); |
4749 | 13 | if (split < 0 || split) |
4750 | 4 | return split; |
4751 | 13 | } |
4752 | 13 | |
4753 | 13 | return isl_bool_false9 ; |
4754 | 13 | } |
4755 | | |
4756 | | /* Given a set of which the last set variable is the minimum |
4757 | | * of the bounds in "cst", split each basic set in the set |
4758 | | * in pieces where one of the bounds is (strictly) smaller than the others. |
4759 | | * This subdivision is given in "min_expr". |
4760 | | * The variable is subsequently projected out. |
4761 | | * |
4762 | | * We only do the split when it is needed. |
4763 | | * For example if the last input variable m = min(a,b) and the only |
4764 | | * constraints in the given basic set are lower bounds on m, |
4765 | | * i.e., l <= m = min(a,b), then we can simply project out m |
4766 | | * to obtain l <= a and l <= b, without having to split on whether |
4767 | | * m is equal to a or b. |
4768 | | */ |
4769 | | static __isl_give isl_set *split(__isl_take isl_set *empty, |
4770 | | __isl_take isl_set *min_expr, __isl_take isl_mat *cst) |
4771 | 6 | { |
4772 | 6 | int n_in; |
4773 | 6 | int i; |
4774 | 6 | isl_space *dim; |
4775 | 6 | isl_set *res; |
4776 | 6 | |
4777 | 6 | if (!empty || !min_expr || !cst) |
4778 | 0 | goto error; |
4779 | 6 | |
4780 | 6 | n_in = isl_set_dim(empty, isl_dim_set); |
4781 | 6 | dim = isl_set_get_space(empty); |
4782 | 6 | dim = isl_space_drop_dims(dim, isl_dim_set, n_in - 1, 1); |
4783 | 6 | res = isl_set_empty(dim); |
4784 | 6 | |
4785 | 12 | for (i = 0; i < empty->n; ++i6 ) { |
4786 | 6 | isl_bool split; |
4787 | 6 | isl_set *set; |
4788 | 6 | |
4789 | 6 | set = isl_set_from_basic_set(isl_basic_set_copy(empty->p[i])); |
4790 | 6 | split = need_split_basic_set(empty->p[i], cst); |
4791 | 6 | if (split < 0) |
4792 | 0 | set = isl_set_free(set); |
4793 | 6 | else if (split) |
4794 | 6 | set = isl_set_intersect(set, isl_set_copy(min_expr)); |
4795 | 6 | set = isl_set_remove_dims(set, isl_dim_set, n_in - 1, 1); |
4796 | 6 | |
4797 | 6 | res = isl_set_union_disjoint(res, set); |
4798 | 6 | } |
4799 | 6 | |
4800 | 6 | isl_set_free(empty); |
4801 | 6 | isl_set_free(min_expr); |
4802 | 6 | isl_mat_free(cst); |
4803 | 6 | return res; |
4804 | 0 | error: |
4805 | 0 | isl_set_free(empty); |
4806 | 0 | isl_set_free(min_expr); |
4807 | 0 | isl_mat_free(cst); |
4808 | 0 | return NULL; |
4809 | 6 | } |
4810 | | |
4811 | | /* Given a map of which the last input variable is the minimum |
4812 | | * of the bounds in "cst", split each basic set in the set |
4813 | | * in pieces where one of the bounds is (strictly) smaller than the others. |
4814 | | * This subdivision is given in "min_expr". |
4815 | | * The variable is subsequently projected out. |
4816 | | * |
4817 | | * The implementation is essentially the same as that of "split". |
4818 | | */ |
4819 | | static __isl_give isl_map *split_domain(__isl_take isl_map *opt, |
4820 | | __isl_take isl_set *min_expr, __isl_take isl_mat *cst) |
4821 | 55 | { |
4822 | 55 | int n_in; |
4823 | 55 | int i; |
4824 | 55 | isl_space *dim; |
4825 | 55 | isl_map *res; |
4826 | 55 | |
4827 | 55 | if (!opt || !min_expr || !cst) |
4828 | 0 | goto error; |
4829 | 55 | |
4830 | 55 | n_in = isl_map_dim(opt, isl_dim_in); |
4831 | 55 | dim = isl_map_get_space(opt); |
4832 | 55 | dim = isl_space_drop_dims(dim, isl_dim_in, n_in - 1, 1); |
4833 | 55 | res = isl_map_empty(dim); |
4834 | 55 | |
4835 | 159 | for (i = 0; i < opt->n; ++i104 ) { |
4836 | 104 | isl_map *map; |
4837 | 104 | isl_bool split; |
4838 | 104 | |
4839 | 104 | map = isl_map_from_basic_map(isl_basic_map_copy(opt->p[i])); |
4840 | 104 | split = need_split_basic_map(opt->p[i], cst); |
4841 | 104 | if (split < 0) |
4842 | 0 | map = isl_map_free(map); |
4843 | 104 | else if (split) |
4844 | 98 | map = isl_map_intersect_domain(map, |
4845 | 98 | isl_set_copy(min_expr)); |
4846 | 104 | map = isl_map_remove_dims(map, isl_dim_in, n_in - 1, 1); |
4847 | 104 | |
4848 | 104 | res = isl_map_union_disjoint(res, map); |
4849 | 104 | } |
4850 | 55 | |
4851 | 55 | isl_map_free(opt); |
4852 | 55 | isl_set_free(min_expr); |
4853 | 55 | isl_mat_free(cst); |
4854 | 55 | return res; |
4855 | 0 | error: |
4856 | 0 | isl_map_free(opt); |
4857 | 0 | isl_set_free(min_expr); |
4858 | 0 | isl_mat_free(cst); |
4859 | 0 | return NULL; |
4860 | 55 | } |
4861 | | |
4862 | | static __isl_give isl_map *basic_map_partial_lexopt( |
4863 | | __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom, |
4864 | | __isl_give isl_set **empty, int max); |
4865 | | |
4866 | | /* This function is called from basic_map_partial_lexopt_symm. |
4867 | | * The last variable of "bmap" and "dom" corresponds to the minimum |
4868 | | * of the bounds in "cst". "map_space" is the space of the original |
4869 | | * input relation (of basic_map_partial_lexopt_symm) and "set_space" |
4870 | | * is the space of the original domain. |
4871 | | * |
4872 | | * We recursively call basic_map_partial_lexopt and then plug in |
4873 | | * the definition of the minimum in the result. |
4874 | | */ |
4875 | | static __isl_give isl_map *basic_map_partial_lexopt_symm_core( |
4876 | | __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom, |
4877 | | __isl_give isl_set **empty, int max, __isl_take isl_mat *cst, |
4878 | | __isl_take isl_space *map_space, __isl_take isl_space *set_space) |
4879 | 55 | { |
4880 | 55 | isl_map *opt; |
4881 | 55 | isl_set *min_expr; |
4882 | 55 | |
4883 | 55 | min_expr = set_minimum(isl_basic_set_get_space(dom), isl_mat_copy(cst)); |
4884 | 55 | |
4885 | 55 | opt = basic_map_partial_lexopt(bmap, dom, empty, max); |
4886 | 55 | |
4887 | 55 | if (empty) { |
4888 | 6 | *empty = split(*empty, |
4889 | 6 | isl_set_copy(min_expr), isl_mat_copy(cst)); |
4890 | 6 | *empty = isl_set_reset_space(*empty, set_space); |
4891 | 6 | } |
4892 | 55 | |
4893 | 55 | opt = split_domain(opt, min_expr, cst); |
4894 | 55 | opt = isl_map_reset_space(opt, map_space); |
4895 | 55 | |
4896 | 55 | return opt; |
4897 | 55 | } |
4898 | | |
4899 | | /* Extract a domain from "bmap" for the purpose of computing |
4900 | | * a lexicographic optimum. |
4901 | | * |
4902 | | * This function is only called when the caller wants to compute a full |
4903 | | * lexicographic optimum, i.e., without specifying a domain. In this case, |
4904 | | * the caller is not interested in the part of the domain space where |
4905 | | * there is no solution and the domain can be initialized to those constraints |
4906 | | * of "bmap" that only involve the parameters and the input dimensions. |
4907 | | * This relieves the parametric programming engine from detecting those |
4908 | | * inequalities and transferring them to the context. More importantly, |
4909 | | * it ensures that those inequalities are transferred first and not |
4910 | | * intermixed with inequalities that actually split the domain. |
4911 | | * |
4912 | | * If the caller does not require the absence of existentially quantified |
4913 | | * variables in the result (i.e., if ISL_OPT_QE is not set in "flags"), |
4914 | | * then the actual domain of "bmap" can be used. This ensures that |
4915 | | * the domain does not need to be split at all just to separate out |
4916 | | * pieces of the domain that do not have a solution from piece that do. |
4917 | | * This domain cannot be used in general because it may involve |
4918 | | * (unknown) existentially quantified variables which will then also |
4919 | | * appear in the solution. |
4920 | | */ |
4921 | | static __isl_give isl_basic_set *extract_domain(__isl_keep isl_basic_map *bmap, |
4922 | | unsigned flags) |
4923 | 4.53k | { |
4924 | 4.53k | int n_div; |
4925 | 4.53k | int n_out; |
4926 | 4.53k | |
4927 | 4.53k | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
4928 | 4.53k | n_out = isl_basic_map_dim(bmap, isl_dim_out); |
4929 | 4.53k | bmap = isl_basic_map_copy(bmap); |
4930 | 4.53k | if (ISL_FL_ISSET(flags, ISL_OPT_QE)) { |
4931 | 213 | bmap = isl_basic_map_drop_constraints_involving_dims(bmap, |
4932 | 213 | isl_dim_div, 0, n_div); |
4933 | 213 | bmap = isl_basic_map_drop_constraints_involving_dims(bmap, |
4934 | 213 | isl_dim_out, 0, n_out); |
4935 | 213 | } |
4936 | 4.53k | return isl_basic_map_domain(bmap); |
4937 | 4.53k | } |
4938 | | |
4939 | | #undef TYPE |
4940 | | #define TYPE isl_map |
4941 | | #undef SUFFIX |
4942 | | #define SUFFIX |
4943 | | #include "isl_tab_lexopt_templ.c" |
4944 | | |
4945 | | /* Extract the subsequence of the sample value of "tab" |
4946 | | * starting at "pos" and of length "len". |
4947 | | */ |
4948 | | static __isl_give isl_vec *extract_sample_sequence(struct isl_tab *tab, |
4949 | | int pos, int len) |
4950 | 789 | { |
4951 | 789 | int i; |
4952 | 789 | isl_ctx *ctx; |
4953 | 789 | isl_vec *v; |
4954 | 789 | |
4955 | 789 | ctx = isl_tab_get_ctx(tab); |
4956 | 789 | v = isl_vec_alloc(ctx, len); |
4957 | 789 | if (!v) |
4958 | 0 | return NULL; |
4959 | 4.06k | for (i = 0; 789 i < len; ++i3.27k ) { |
4960 | 3.27k | if (!tab->var[pos + i].is_row) { |
4961 | 2.48k | isl_int_set_si(v->el[i], 0); |
4962 | 2.48k | } else { |
4963 | 788 | int row; |
4964 | 788 | |
4965 | 788 | row = tab->var[pos + i].index; |
4966 | 788 | isl_int_divexact(v->el[i], tab->mat->row[row][1], |
4967 | 788 | tab->mat->row[row][0]); |
4968 | 788 | } |
4969 | 3.27k | } |
4970 | 789 | |
4971 | 789 | return v; |
4972 | 789 | } |
4973 | | |
4974 | | /* Check if the sequence of variables starting at "pos" |
4975 | | * represents a trivial solution according to "trivial". |
4976 | | * That is, is the result of applying "trivial" to this sequence |
4977 | | * equal to the zero vector? |
4978 | | */ |
4979 | | static isl_bool region_is_trivial(struct isl_tab *tab, int pos, |
4980 | | __isl_keep isl_mat *trivial) |
4981 | 898 | { |
4982 | 898 | int n, len; |
4983 | 898 | isl_vec *v; |
4984 | 898 | isl_bool is_trivial; |
4985 | 898 | |
4986 | 898 | if (!trivial) |
4987 | 0 | return isl_bool_error; |
4988 | 898 | |
4989 | 898 | n = isl_mat_rows(trivial); |
4990 | 898 | if (n == 0) |
4991 | 109 | return isl_bool_false; |
4992 | 789 | |
4993 | 789 | len = isl_mat_cols(trivial); |
4994 | 789 | v = extract_sample_sequence(tab, pos, len); |
4995 | 789 | v = isl_mat_vec_product(isl_mat_copy(trivial), v); |
4996 | 789 | is_trivial = isl_vec_is_zero(v); |
4997 | 789 | isl_vec_free(v); |
4998 | 789 | |
4999 | 789 | return is_trivial; |
5000 | 789 | } |
5001 | | |
5002 | | /* Global internal data for isl_tab_basic_set_non_trivial_lexmin. |
5003 | | * |
5004 | | * "n_op" is the number of initial coordinates to optimize, |
5005 | | * as passed to isl_tab_basic_set_non_trivial_lexmin. |
5006 | | * "region" is the "n_region"-sized array of regions passed |
5007 | | * to isl_tab_basic_set_non_trivial_lexmin. |
5008 | | * |
5009 | | * "tab" is the tableau that corresponds to the ILP problem. |
5010 | | * "local" is an array of local data structure, one for each |
5011 | | * (potential) level of the backtracking procedure of |
5012 | | * isl_tab_basic_set_non_trivial_lexmin. |
5013 | | * "v" is a pre-allocated vector that can be used for adding |
5014 | | * constraints to the tableau. |
5015 | | * |
5016 | | * "sol" contains the best solution found so far. |
5017 | | * It is initialized to a vector of size zero. |
5018 | | */ |
5019 | | struct isl_lexmin_data { |
5020 | | int n_op; |
5021 | | int n_region; |
5022 | | struct isl_trivial_region *region; |
5023 | | |
5024 | | struct isl_tab *tab; |
5025 | | struct isl_local_region *local; |
5026 | | isl_vec *v; |
5027 | | |
5028 | | isl_vec *sol; |
5029 | | }; |
5030 | | |
5031 | | /* Return the index of the first trivial region, "n_region" if all regions |
5032 | | * are non-trivial or -1 in case of error. |
5033 | | */ |
5034 | | static int first_trivial_region(struct isl_lexmin_data *data) |
5035 | 723 | { |
5036 | 723 | int i; |
5037 | 723 | |
5038 | 1.20k | for (i = 0; i < data->n_region; ++i477 ) { |
5039 | 898 | isl_bool trivial; |
5040 | 898 | trivial = region_is_trivial(data->tab, data->region[i].pos, |
5041 | 898 | data->region[i].trivial); |
5042 | 898 | if (trivial < 0) |
5043 | 0 | return -1; |
5044 | 898 | if (trivial) |
5045 | 421 | return i; |
5046 | 898 | } |
5047 | 723 | |
5048 | 723 | return data->n_region302 ; |
5049 | 723 | } |
5050 | | |
5051 | | /* Check if the solution is optimal, i.e., whether the first |
5052 | | * n_op entries are zero. |
5053 | | */ |
5054 | | static int is_optimal(__isl_keep isl_vec *sol, int n_op) |
5055 | 302 | { |
5056 | 302 | int i; |
5057 | 302 | |
5058 | 786 | for (i = 0; i < n_op; ++i484 ) |
5059 | 598 | if (!isl_int_is_zero(sol->el[1 + i])) |
5060 | 598 | return 0114 ; |
5061 | 302 | return 1188 ; |
5062 | 302 | } |
5063 | | |
5064 | | /* Add constraints to "tab" that ensure that any solution is significantly |
5065 | | * better than that represented by "sol". That is, find the first |
5066 | | * relevant (within first n_op) non-zero coefficient and force it (along |
5067 | | * with all previous coefficients) to be zero. |
5068 | | * If the solution is already optimal (all relevant coefficients are zero), |
5069 | | * then just mark the table as empty. |
5070 | | * "n_zero" is the number of coefficients that have been forced zero |
5071 | | * by previous calls to this function at the same level. |
5072 | | * Return the updated number of forced zero coefficients or -1 on error. |
5073 | | * |
5074 | | * This function assumes that at least 2 * (n_op - n_zero) more rows and |
5075 | | * at least 2 * (n_op - n_zero) more elements in the constraint array |
5076 | | * are available in the tableau. |
5077 | | */ |
5078 | | static int force_better_solution(struct isl_tab *tab, |
5079 | | __isl_keep isl_vec *sol, int n_op, int n_zero) |
5080 | 125 | { |
5081 | 125 | int i, n; |
5082 | 125 | isl_ctx *ctx; |
5083 | 125 | isl_vec *v = NULL; |
5084 | 125 | |
5085 | 125 | if (!sol) |
5086 | 0 | return -1; |
5087 | 125 | |
5088 | 241 | for (i = n_zero; 125 i < n_op; ++i116 ) |
5089 | 241 | if (!isl_int_is_zero(sol->el[1 + i])) |
5090 | 241 | break125 ; |
5091 | 125 | |
5092 | 125 | if (i == n_op) { |
5093 | 0 | if (isl_tab_mark_empty(tab) < 0) |
5094 | 0 | return -1; |
5095 | 0 | return n_op; |
5096 | 0 | } |
5097 | 125 | |
5098 | 125 | ctx = isl_vec_get_ctx(sol); |
5099 | 125 | v = isl_vec_alloc(ctx, 1 + tab->n_var); |
5100 | 125 | if (!v) |
5101 | 0 | return -1; |
5102 | 125 | |
5103 | 125 | n = i + 1; |
5104 | 366 | for (; i >= n_zero; --i241 ) { |
5105 | 241 | v = isl_vec_clr(v); |
5106 | 241 | isl_int_set_si(v->el[1 + i], -1); |
5107 | 241 | if (add_lexmin_eq(tab, v->el) < 0) |
5108 | 0 | goto error; |
5109 | 241 | } |
5110 | 125 | |
5111 | 125 | isl_vec_free(v); |
5112 | 125 | return n; |
5113 | 0 | error: |
5114 | 0 | isl_vec_free(v); |
5115 | 0 | return -1; |
5116 | 125 | } |
5117 | | |
5118 | | /* Fix triviality direction "dir" of the given region to zero. |
5119 | | * |
5120 | | * This function assumes that at least two more rows and at least |
5121 | | * two more elements in the constraint array are available in the tableau. |
5122 | | */ |
5123 | | static isl_stat fix_zero(struct isl_tab *tab, struct isl_trivial_region *region, |
5124 | | int dir, struct isl_lexmin_data *data) |
5125 | 57 | { |
5126 | 57 | int len; |
5127 | 57 | |
5128 | 57 | data->v = isl_vec_clr(data->v); |
5129 | 57 | if (!data->v) |
5130 | 0 | return isl_stat_error; |
5131 | 57 | len = isl_mat_cols(region->trivial); |
5132 | 57 | isl_seq_cpy(data->v->el + 1 + region->pos, region->trivial->row[dir], |
5133 | 57 | len); |
5134 | 57 | if (add_lexmin_eq(tab, data->v->el) < 0) |
5135 | 0 | return isl_stat_error; |
5136 | 57 | |
5137 | 57 | return isl_stat_ok; |
5138 | 57 | } |
5139 | | |
5140 | | /* This function selects case "side" for non-triviality region "region", |
5141 | | * assuming all the equality constraints have been imposed already. |
5142 | | * In particular, the triviality direction side/2 is made positive |
5143 | | * if side is even and made negative if side is odd. |
5144 | | * |
5145 | | * This function assumes that at least one more row and at least |
5146 | | * one more element in the constraint array are available in the tableau. |
5147 | | */ |
5148 | | static struct isl_tab *pos_neg(struct isl_tab *tab, |
5149 | | struct isl_trivial_region *region, |
5150 | | int side, struct isl_lexmin_data *data) |
5151 | 766 | { |
5152 | 766 | int len; |
5153 | 766 | |
5154 | 766 | data->v = isl_vec_clr(data->v); |
5155 | 766 | if (!data->v) |
5156 | 0 | goto error; |
5157 | 766 | isl_int_set_si(data->v->el[0], -1); |
5158 | 766 | len = isl_mat_cols(region->trivial); |
5159 | 766 | if (side % 2 == 0) |
5160 | 478 | isl_seq_cpy(data->v->el + 1 + region->pos, |
5161 | 478 | region->trivial->row[side / 2], len); |
5162 | 288 | else |
5163 | 288 | isl_seq_neg(data->v->el + 1 + region->pos, |
5164 | 288 | region->trivial->row[side / 2], len); |
5165 | 766 | return add_lexmin_ineq(tab, data->v->el); |
5166 | 0 | error: |
5167 | 0 | isl_tab_free(tab); |
5168 | 0 | return NULL; |
5169 | 766 | } |
5170 | | |
5171 | | /* Local data at each level of the backtracking procedure of |
5172 | | * isl_tab_basic_set_non_trivial_lexmin. |
5173 | | * |
5174 | | * "update" is set if a solution has been found in the current case |
5175 | | * of this level, such that a better solution needs to be enforced |
5176 | | * in the next case. |
5177 | | * "n_zero" is the number of initial coordinates that have already |
5178 | | * been forced to be zero at this level. |
5179 | | * "region" is the non-triviality region considered at this level. |
5180 | | * "side" is the index of the current case at this level. |
5181 | | * "n" is the number of triviality directions. |
5182 | | * "snap" is a snapshot of the tableau holding a state that needs |
5183 | | * to be satisfied by all subsequent cases. |
5184 | | */ |
5185 | | struct isl_local_region { |
5186 | | int update; |
5187 | | int n_zero; |
5188 | | int region; |
5189 | | int side; |
5190 | | int n; |
5191 | | struct isl_tab_undo *snap; |
5192 | | }; |
5193 | | |
5194 | | /* Initialize the global data structure "data" used while solving |
5195 | | * the ILP problem "bset". |
5196 | | */ |
5197 | | static isl_stat init_lexmin_data(struct isl_lexmin_data *data, |
5198 | | __isl_keep isl_basic_set *bset) |
5199 | 405 | { |
5200 | 405 | isl_ctx *ctx; |
5201 | 405 | |
5202 | 405 | ctx = isl_basic_set_get_ctx(bset); |
5203 | 405 | |
5204 | 405 | data->tab = tab_for_lexmin(bset, NULL, 0, 0); |
5205 | 405 | if (!data->tab) |
5206 | 0 | return isl_stat_error; |
5207 | 405 | |
5208 | 405 | data->v = isl_vec_alloc(ctx, 1 + data->tab->n_var); |
5209 | 405 | if (!data->v) |
5210 | 0 | return isl_stat_error; |
5211 | 405 | data->local = isl_calloc_array(ctx, struct isl_local_region, |
5212 | 405 | data->n_region); |
5213 | 405 | if (data->n_region && !data->local) |
5214 | 0 | return isl_stat_error; |
5215 | 405 | |
5216 | 405 | data->sol = isl_vec_alloc(ctx, 0); |
5217 | 405 | |
5218 | 405 | return isl_stat_ok; |
5219 | 405 | } |
5220 | | |
5221 | | /* Mark all outer levels as requiring a better solution |
5222 | | * in the next cases. |
5223 | | */ |
5224 | | static void update_outer_levels(struct isl_lexmin_data *data, int level) |
5225 | 302 | { |
5226 | 302 | int i; |
5227 | 302 | |
5228 | 617 | for (i = 0; i < level; ++i315 ) |
5229 | 315 | data->local[i].update = 1; |
5230 | 302 | } |
5231 | | |
5232 | | /* Initialize "local" to refer to region "region" and |
5233 | | * to initiate processing at this level. |
5234 | | */ |
5235 | | static void init_local_region(struct isl_local_region *local, int region, |
5236 | | struct isl_lexmin_data *data) |
5237 | 421 | { |
5238 | 421 | local->n = isl_mat_rows(data->region[region].trivial); |
5239 | 421 | local->region = region; |
5240 | 421 | local->side = 0; |
5241 | 421 | local->update = 0; |
5242 | 421 | local->n_zero = 0; |
5243 | 421 | } |
5244 | | |
5245 | | /* What to do next after entering a level of the backtracking procedure. |
5246 | | * |
5247 | | * error: some error has occurred; abort |
5248 | | * done: an optimal solution has been found; stop search |
5249 | | * backtrack: backtrack to the previous level |
5250 | | * handle: add the constraints for the current level and |
5251 | | * move to the next level |
5252 | | */ |
5253 | | enum isl_next { |
5254 | | isl_next_error = -1, |
5255 | | isl_next_done, |
5256 | | isl_next_backtrack, |
5257 | | isl_next_handle, |
5258 | | }; |
5259 | | |
5260 | | /* Have all cases of the current region been considered? |
5261 | | * If there are n directions, then there are 2n cases. |
5262 | | * |
5263 | | * The constraints in the current tableau are imposed |
5264 | | * in all subsequent cases. This means that if the current |
5265 | | * tableau is empty, then none of those cases should be considered |
5266 | | * anymore and all cases have effectively been considered. |
5267 | | */ |
5268 | | static int finished_all_cases(struct isl_local_region *local, |
5269 | | struct isl_lexmin_data *data) |
5270 | 997 | { |
5271 | 997 | if (data->tab->empty) |
5272 | 8 | return 1; |
5273 | 989 | return local->side >= 2 * local->n; |
5274 | 989 | } |
5275 | | |
5276 | | /* Enter level "level" of the backtracking search and figure out |
5277 | | * what to do next. "init" is set if the level was entered |
5278 | | * from a higher level and needs to be initialized. |
5279 | | * Otherwise, the level is entered as a result of backtracking and |
5280 | | * the tableau needs to be restored to a position that can |
5281 | | * be used for the next case at this level. |
5282 | | * The snapshot is assumed to have been saved in the previous case, |
5283 | | * before the constraints specific to that case were added. |
5284 | | * |
5285 | | * In the initialization case, the local region is initialized |
5286 | | * to point to the first violated region. |
5287 | | * If the constraints of all regions are satisfied by the current |
5288 | | * sample of the tableau, then tell the caller to continue looking |
5289 | | * for a better solution or to stop searching if an optimal solution |
5290 | | * has been found. |
5291 | | * |
5292 | | * If the tableau is empty or if all cases at the current level |
5293 | | * have been considered, then the caller needs to backtrack as well. |
5294 | | */ |
5295 | | static enum isl_next enter_level(int level, int init, |
5296 | | struct isl_lexmin_data *data) |
5297 | 1.74k | { |
5298 | 1.74k | struct isl_local_region *local = &data->local[level]; |
5299 | 1.74k | |
5300 | 1.74k | if (init) { |
5301 | 1.17k | int r; |
5302 | 1.17k | |
5303 | 1.17k | data->tab = cut_to_integer_lexmin(data->tab, CUT_ONE); |
5304 | 1.17k | if (!data->tab) |
5305 | 0 | return isl_next_error; |
5306 | |