Line data Source code
1 : /*
2 : * Copyright 2008-2009 Katholieke Universiteit Leuven
3 : *
4 : * Use of this software is governed by the MIT license
5 : *
6 : * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 : * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8 : */
9 :
10 : #include <isl_ctx_private.h>
11 : #include <isl_map_private.h>
12 : #include "isl_sample.h"
13 : #include <isl/vec.h>
14 : #include <isl/mat.h>
15 : #include <isl_seq.h>
16 : #include "isl_equalities.h"
17 : #include "isl_tab.h"
18 : #include "isl_basis_reduction.h"
19 : #include <isl_factorization.h>
20 : #include <isl_point_private.h>
21 : #include <isl_options_private.h>
22 : #include <isl_vec_private.h>
23 :
24 : #include <bset_from_bmap.c>
25 : #include <set_to_map.c>
26 :
27 166168 : static __isl_give isl_vec *empty_sample(__isl_take isl_basic_set *bset)
28 : {
29 : struct isl_vec *vec;
30 :
31 166168 : vec = isl_vec_alloc(bset->ctx, 0);
32 166168 : isl_basic_set_free(bset);
33 166168 : return vec;
34 : }
35 :
36 : /* Construct a zero sample of the same dimension as bset.
37 : * As a special case, if bset is zero-dimensional, this
38 : * function creates a zero-dimensional sample point.
39 : */
40 10587440 : static __isl_give isl_vec *zero_sample(__isl_take isl_basic_set *bset)
41 : {
42 : unsigned dim;
43 : struct isl_vec *sample;
44 :
45 10587440 : dim = isl_basic_set_total_dim(bset);
46 10587440 : sample = isl_vec_alloc(bset->ctx, 1 + dim);
47 10587440 : if (sample) {
48 10587440 : isl_int_set_si(sample->el[0], 1);
49 10587440 : isl_seq_clr(sample->el + 1, dim);
50 : }
51 10587440 : isl_basic_set_free(bset);
52 10587440 : return sample;
53 : }
54 :
55 1058979 : static __isl_give isl_vec *interval_sample(__isl_take isl_basic_set *bset)
56 : {
57 : int i;
58 : isl_int t;
59 : struct isl_vec *sample;
60 :
61 1058979 : bset = isl_basic_set_simplify(bset);
62 1058979 : if (!bset)
63 0 : return NULL;
64 1058979 : if (isl_basic_set_plain_is_empty(bset))
65 0 : return empty_sample(bset);
66 1058979 : if (bset->n_eq == 0 && bset->n_ineq == 0)
67 1083 : return zero_sample(bset);
68 :
69 1057896 : sample = isl_vec_alloc(bset->ctx, 2);
70 1057896 : if (!sample)
71 0 : goto error;
72 1057896 : if (!bset)
73 0 : return NULL;
74 1057896 : isl_int_set_si(sample->block.data[0], 1);
75 :
76 1057896 : if (bset->n_eq > 0) {
77 0 : isl_assert(bset->ctx, bset->n_eq == 1, goto error);
78 0 : isl_assert(bset->ctx, bset->n_ineq == 0, goto error);
79 0 : if (isl_int_is_one(bset->eq[0][1]))
80 0 : isl_int_neg(sample->el[1], bset->eq[0][0]);
81 : else {
82 0 : isl_assert(bset->ctx, isl_int_is_negone(bset->eq[0][1]),
83 : goto error);
84 0 : isl_int_set(sample->el[1], bset->eq[0][0]);
85 : }
86 0 : isl_basic_set_free(bset);
87 0 : return sample;
88 : }
89 :
90 1057896 : isl_int_init(t);
91 1057896 : if (isl_int_is_one(bset->ineq[0][1]))
92 575824 : isl_int_neg(sample->block.data[1], bset->ineq[0][0]);
93 : else
94 482072 : isl_int_set(sample->block.data[1], bset->ineq[0][0]);
95 2085644 : for (i = 1; i < bset->n_ineq; ++i) {
96 1027748 : isl_seq_inner_product(sample->block.data,
97 1027748 : bset->ineq[i], 2, &t);
98 1027748 : if (isl_int_is_neg(t))
99 0 : break;
100 : }
101 1057896 : isl_int_clear(t);
102 1057896 : if (i < bset->n_ineq) {
103 0 : isl_vec_free(sample);
104 0 : return empty_sample(bset);
105 : }
106 :
107 1057896 : isl_basic_set_free(bset);
108 1057896 : return sample;
109 : error:
110 0 : isl_basic_set_free(bset);
111 0 : isl_vec_free(sample);
112 0 : return NULL;
113 : }
114 :
115 : /* Find a sample integer point, if any, in bset, which is known
116 : * to have equalities. If bset contains no integer points, then
117 : * return a zero-length vector.
118 : * We simply remove the known equalities, compute a sample
119 : * in the resulting bset, using the specified recurse function,
120 : * and then transform the sample back to the original space.
121 : */
122 22116812 : static __isl_give isl_vec *sample_eq(__isl_take isl_basic_set *bset,
123 : __isl_give isl_vec *(*recurse)(__isl_take isl_basic_set *))
124 : {
125 : struct isl_mat *T;
126 : struct isl_vec *sample;
127 :
128 22116812 : if (!bset)
129 0 : return NULL;
130 :
131 22116812 : bset = isl_basic_set_remove_equalities(bset, &T, NULL);
132 22116812 : sample = recurse(bset);
133 22116812 : if (!sample || sample->size == 0)
134 10345793 : isl_mat_free(T);
135 : else
136 11771019 : sample = isl_mat_vec_product(T, sample);
137 22116812 : return sample;
138 : }
139 :
140 : /* Return a matrix containing the equalities of the tableau
141 : * in constraint form. The tableau is assumed to have
142 : * an associated bset that has been kept up-to-date.
143 : */
144 1123655 : static struct isl_mat *tab_equalities(struct isl_tab *tab)
145 : {
146 : int i, j;
147 : int n_eq;
148 : struct isl_mat *eq;
149 : struct isl_basic_set *bset;
150 :
151 1123655 : if (!tab)
152 0 : return NULL;
153 :
154 1123655 : bset = isl_tab_peek_bset(tab);
155 1123655 : isl_assert(tab->mat->ctx, bset, return NULL);
156 :
157 1123655 : n_eq = tab->n_var - tab->n_col + tab->n_dead;
158 1123655 : if (tab->empty || n_eq == 0)
159 0 : return isl_mat_alloc(tab->mat->ctx, 0, tab->n_var);
160 1123655 : if (n_eq == tab->n_var)
161 0 : return isl_mat_identity(tab->mat->ctx, tab->n_var);
162 :
163 1123655 : eq = isl_mat_alloc(tab->mat->ctx, n_eq, tab->n_var);
164 1123655 : if (!eq)
165 0 : return NULL;
166 16327912 : for (i = 0, j = 0; i < tab->n_con; ++i) {
167 15204257 : if (tab->con[i].is_row)
168 10096248 : continue;
169 5108009 : if (tab->con[i].index >= 0 && tab->con[i].index >= tab->n_dead)
170 3471518 : continue;
171 1636491 : if (i < bset->n_eq)
172 109 : isl_seq_cpy(eq->row[j], bset->eq[i] + 1, tab->n_var);
173 : else
174 3272764 : isl_seq_cpy(eq->row[j],
175 1636382 : bset->ineq[i - bset->n_eq] + 1, tab->n_var);
176 1636491 : ++j;
177 : }
178 1123655 : isl_assert(bset->ctx, j == n_eq, goto error);
179 1123655 : return eq;
180 : error:
181 0 : isl_mat_free(eq);
182 0 : return NULL;
183 : }
184 :
185 : /* Compute and return an initial basis for the bounded tableau "tab".
186 : *
187 : * If the tableau is either full-dimensional or zero-dimensional,
188 : * the we simply return an identity matrix.
189 : * Otherwise, we construct a basis whose first directions correspond
190 : * to equalities.
191 : */
192 16559854 : static struct isl_mat *initial_basis(struct isl_tab *tab)
193 : {
194 : int n_eq;
195 : struct isl_mat *eq;
196 : struct isl_mat *Q;
197 :
198 16559854 : tab->n_unbounded = 0;
199 16559854 : tab->n_zero = n_eq = tab->n_var - tab->n_col + tab->n_dead;
200 16559854 : if (tab->empty || n_eq == 0 || n_eq == tab->n_var)
201 15436199 : return isl_mat_identity(tab->mat->ctx, 1 + tab->n_var);
202 :
203 1123655 : eq = tab_equalities(tab);
204 1123655 : eq = isl_mat_left_hermite(eq, 0, NULL, &Q);
205 1123655 : if (!eq)
206 0 : return NULL;
207 1123655 : isl_mat_free(eq);
208 :
209 1123655 : Q = isl_mat_lin_to_aff(Q);
210 1123655 : return Q;
211 : }
212 :
213 : /* Compute the minimum of the current ("level") basis row over "tab"
214 : * and store the result in position "level" of "min".
215 : *
216 : * This function assumes that at least one more row and at least
217 : * one more element in the constraint array are available in the tableau.
218 : */
219 72811324 : static enum isl_lp_result compute_min(isl_ctx *ctx, struct isl_tab *tab,
220 : __isl_keep isl_vec *min, int level)
221 : {
222 218433972 : return isl_tab_min(tab, tab->basis->row[1 + level],
223 218433972 : ctx->one, &min->el[level], NULL, 0);
224 : }
225 :
226 : /* Compute the maximum of the current ("level") basis row over "tab"
227 : * and store the result in position "level" of "max".
228 : *
229 : * This function assumes that at least one more row and at least
230 : * one more element in the constraint array are available in the tableau.
231 : */
232 70348156 : static enum isl_lp_result compute_max(isl_ctx *ctx, struct isl_tab *tab,
233 : __isl_keep isl_vec *max, int level)
234 : {
235 : enum isl_lp_result res;
236 70348156 : unsigned dim = tab->n_var;
237 :
238 70348156 : isl_seq_neg(tab->basis->row[1 + level] + 1,
239 70348156 : tab->basis->row[1 + level] + 1, dim);
240 211044468 : res = isl_tab_min(tab, tab->basis->row[1 + level],
241 211044468 : ctx->one, &max->el[level], NULL, 0);
242 70348156 : isl_seq_neg(tab->basis->row[1 + level] + 1,
243 70348156 : tab->basis->row[1 + level] + 1, dim);
244 70348156 : isl_int_neg(max->el[level], max->el[level]);
245 :
246 70348156 : return res;
247 : }
248 :
249 : /* Perform a greedy search for an integer point in the set represented
250 : * by "tab", given that the minimal rational value (rounded up to the
251 : * nearest integer) at "level" is smaller than the maximal rational
252 : * value (rounded down to the nearest integer).
253 : *
254 : * Return 1 if we have found an integer point (if tab->n_unbounded > 0
255 : * then we may have only found integer values for the bounded dimensions
256 : * and it is the responsibility of the caller to extend this solution
257 : * to the unbounded dimensions).
258 : * Return 0 if greedy search did not result in a solution.
259 : * Return -1 if some error occurred.
260 : *
261 : * We assign a value half-way between the minimum and the maximum
262 : * to the current dimension and check if the minimal value of the
263 : * next dimension is still smaller than (or equal) to the maximal value.
264 : * We continue this process until either
265 : * - the minimal value (rounded up) is greater than the maximal value
266 : * (rounded down). In this case, greedy search has failed.
267 : * - we have exhausted all bounded dimensions, meaning that we have
268 : * found a solution.
269 : * - the sample value of the tableau is integral.
270 : * - some error has occurred.
271 : */
272 16002777 : static int greedy_search(isl_ctx *ctx, struct isl_tab *tab,
273 : __isl_keep isl_vec *min, __isl_keep isl_vec *max, int level)
274 : {
275 : struct isl_tab_undo *snap;
276 : enum isl_lp_result res;
277 :
278 16002777 : snap = isl_tab_snap(tab);
279 :
280 : do {
281 60474470 : isl_int_add(tab->basis->row[1 + level][0],
282 : min->el[level], max->el[level]);
283 60474470 : isl_int_fdiv_q_ui(tab->basis->row[1 + level][0],
284 : tab->basis->row[1 + level][0], 2);
285 60474470 : isl_int_neg(tab->basis->row[1 + level][0],
286 : tab->basis->row[1 + level][0]);
287 60474470 : if (isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]) < 0)
288 0 : return -1;
289 60474470 : isl_int_set_si(tab->basis->row[1 + level][0], 0);
290 :
291 60474470 : if (++level >= tab->n_var - tab->n_unbounded)
292 8422653 : return 1;
293 52051817 : if (isl_tab_sample_is_integer(tab))
294 3643765 : return 1;
295 :
296 48408052 : res = compute_min(ctx, tab, min, level);
297 48408052 : if (res == isl_lp_error)
298 0 : return -1;
299 48408052 : if (res != isl_lp_ok)
300 0 : isl_die(ctx, isl_error_internal,
301 : "expecting bounded rational solution",
302 : return -1);
303 48408052 : res = compute_max(ctx, tab, max, level);
304 48408052 : if (res == isl_lp_error)
305 0 : return -1;
306 48408052 : if (res != isl_lp_ok)
307 0 : isl_die(ctx, isl_error_internal,
308 : "expecting bounded rational solution",
309 : return -1);
310 48408052 : } while (isl_int_le(min->el[level], max->el[level]));
311 :
312 3936359 : if (isl_tab_rollback(tab, snap) < 0)
313 0 : return -1;
314 :
315 3936359 : return 0;
316 : }
317 :
318 : /* Given a tableau representing a set, find and return
319 : * an integer point in the set, if there is any.
320 : *
321 : * We perform a depth first search
322 : * for an integer point, by scanning all possible values in the range
323 : * attained by a basis vector, where an initial basis may have been set
324 : * by the calling function. Otherwise an initial basis that exploits
325 : * the equalities in the tableau is created.
326 : * tab->n_zero is currently ignored and is clobbered by this function.
327 : *
328 : * The tableau is allowed to have unbounded direction, but then
329 : * the calling function needs to set an initial basis, with the
330 : * unbounded directions last and with tab->n_unbounded set
331 : * to the number of unbounded directions.
332 : * Furthermore, the calling functions needs to add shifted copies
333 : * of all constraints involving unbounded directions to ensure
334 : * that any feasible rational value in these directions can be rounded
335 : * up to yield a feasible integer value.
336 : * In particular, let B define the given basis x' = B x
337 : * and let T be the inverse of B, i.e., X = T x'.
338 : * Let a x + c >= 0 be a constraint of the set represented by the tableau,
339 : * or a T x' + c >= 0 in terms of the given basis. Assume that
340 : * the bounded directions have an integer value, then we can safely
341 : * round up the values for the unbounded directions if we make sure
342 : * that x' not only satisfies the original constraint, but also
343 : * the constraint "a T x' + c + s >= 0" with s the sum of all
344 : * negative values in the last n_unbounded entries of "a T".
345 : * The calling function therefore needs to add the constraint
346 : * a x + c + s >= 0. The current function then scans the first
347 : * directions for an integer value and once those have been found,
348 : * it can compute "T ceil(B x)" to yield an integer point in the set.
349 : * Note that during the search, the first rows of B may be changed
350 : * by a basis reduction, but the last n_unbounded rows of B remain
351 : * unaltered and are also not mixed into the first rows.
352 : *
353 : * The search is implemented iteratively. "level" identifies the current
354 : * basis vector. "init" is true if we want the first value at the current
355 : * level and false if we want the next value.
356 : *
357 : * At the start of each level, we first check if we can find a solution
358 : * using greedy search. If not, we continue with the exhaustive search.
359 : *
360 : * The initial basis is the identity matrix. If the range in some direction
361 : * contains more than one integer value, we perform basis reduction based
362 : * on the value of ctx->opt->gbr
363 : * - ISL_GBR_NEVER: never perform basis reduction
364 : * - ISL_GBR_ONCE: only perform basis reduction the first
365 : * time such a range is encountered
366 : * - ISL_GBR_ALWAYS: always perform basis reduction when
367 : * such a range is encountered
368 : *
369 : * When ctx->opt->gbr is set to ISL_GBR_ALWAYS, then we allow the basis
370 : * reduction computation to return early. That is, as soon as it
371 : * finds a reasonable first direction.
372 : */
373 16841069 : struct isl_vec *isl_tab_sample(struct isl_tab *tab)
374 : {
375 : unsigned dim;
376 : unsigned gbr;
377 : struct isl_ctx *ctx;
378 : struct isl_vec *sample;
379 : struct isl_vec *min;
380 : struct isl_vec *max;
381 : enum isl_lp_result res;
382 : int level;
383 : int init;
384 : int reduced;
385 : struct isl_tab_undo **snap;
386 :
387 16841069 : if (!tab)
388 0 : return NULL;
389 16841069 : if (tab->empty)
390 198270 : return isl_vec_alloc(tab->mat->ctx, 0);
391 :
392 16642799 : if (!tab->basis)
393 16559854 : tab->basis = initial_basis(tab);
394 16642799 : if (!tab->basis)
395 0 : return NULL;
396 16642799 : isl_assert(tab->mat->ctx, tab->basis->n_row == tab->n_var + 1,
397 : return NULL);
398 16642799 : isl_assert(tab->mat->ctx, tab->basis->n_col == tab->n_var + 1,
399 : return NULL);
400 :
401 16642799 : ctx = tab->mat->ctx;
402 16642799 : dim = tab->n_var;
403 16642799 : gbr = ctx->opt->gbr;
404 :
405 16642799 : if (tab->n_unbounded == tab->n_var) {
406 0 : sample = isl_tab_get_sample_value(tab);
407 0 : sample = isl_mat_vec_product(isl_mat_copy(tab->basis), sample);
408 0 : sample = isl_vec_ceil(sample);
409 0 : sample = isl_mat_vec_inverse_product(isl_mat_copy(tab->basis),
410 : sample);
411 0 : return sample;
412 : }
413 :
414 16642799 : if (isl_tab_extend_cons(tab, dim + 1) < 0)
415 0 : return NULL;
416 :
417 16642799 : min = isl_vec_alloc(ctx, dim);
418 16642799 : max = isl_vec_alloc(ctx, dim);
419 16642799 : snap = isl_alloc_array(ctx, struct isl_tab_undo *, dim);
420 :
421 16642799 : if (!min || !max || !snap)
422 : goto error;
423 :
424 16642799 : level = 0;
425 16642799 : init = 1;
426 16642799 : reduced = 0;
427 :
428 44431626 : while (level >= 0) {
429 26698549 : if (init) {
430 : int choice;
431 :
432 24403272 : res = compute_min(ctx, tab, min, level);
433 24403272 : if (res == isl_lp_error)
434 0 : goto error;
435 24403272 : if (res != isl_lp_ok)
436 0 : isl_die(ctx, isl_error_internal,
437 : "expecting bounded rational solution",
438 : goto error);
439 24403272 : if (isl_tab_sample_is_integer(tab))
440 2463168 : break;
441 21940104 : res = compute_max(ctx, tab, max, level);
442 21940104 : if (res == isl_lp_error)
443 0 : goto error;
444 21940104 : if (res != isl_lp_ok)
445 0 : isl_die(ctx, isl_error_internal,
446 : "expecting bounded rational solution",
447 : goto error);
448 21940104 : if (isl_tab_sample_is_integer(tab))
449 972471 : break;
450 20967633 : choice = isl_int_lt(min->el[level], max->el[level]);
451 20967633 : if (choice) {
452 : int g;
453 16002777 : g = greedy_search(ctx, tab, min, max, level);
454 16002777 : if (g < 0)
455 0 : goto error;
456 16002777 : if (g)
457 12066418 : break;
458 : }
459 12262174 : if (!reduced && choice &&
460 3360959 : ctx->opt->gbr != ISL_GBR_NEVER) {
461 : unsigned gbr_only_first;
462 3360959 : if (ctx->opt->gbr == ISL_GBR_ONCE)
463 0 : ctx->opt->gbr = ISL_GBR_NEVER;
464 3360959 : tab->n_zero = level;
465 3360959 : gbr_only_first = ctx->opt->gbr_only_first;
466 6721918 : ctx->opt->gbr_only_first =
467 3360959 : ctx->opt->gbr == ISL_GBR_ALWAYS;
468 3360959 : tab = isl_tab_compute_reduced_basis(tab);
469 3360959 : ctx->opt->gbr_only_first = gbr_only_first;
470 3360959 : if (!tab || !tab->basis)
471 : goto error;
472 3360959 : reduced = 1;
473 3360959 : continue;
474 : }
475 5540256 : reduced = 0;
476 5540256 : snap[level] = isl_tab_snap(tab);
477 : } else
478 2295277 : isl_int_add_ui(min->el[level], min->el[level], 1);
479 :
480 7835533 : if (isl_int_gt(min->el[level], max->el[level])) {
481 3385555 : level--;
482 3385555 : init = 0;
483 3385555 : if (level >= 0)
484 2295277 : if (isl_tab_rollback(tab, snap[level]) < 0)
485 0 : goto error;
486 3385555 : continue;
487 : }
488 4449978 : isl_int_neg(tab->basis->row[1 + level][0], min->el[level]);
489 4449978 : if (isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]) < 0)
490 0 : goto error;
491 4449978 : isl_int_set_si(tab->basis->row[1 + level][0], 0);
492 4449978 : if (level + tab->n_unbounded < dim - 1) {
493 4399514 : ++level;
494 4399514 : init = 1;
495 4399514 : continue;
496 : }
497 50464 : break;
498 : }
499 :
500 16642799 : if (level >= 0) {
501 15552521 : sample = isl_tab_get_sample_value(tab);
502 15552521 : if (!sample)
503 0 : goto error;
504 15552521 : if (tab->n_unbounded && !isl_int_is_one(sample->el[0])) {
505 0 : sample = isl_mat_vec_product(isl_mat_copy(tab->basis),
506 : sample);
507 0 : sample = isl_vec_ceil(sample);
508 0 : sample = isl_mat_vec_inverse_product(
509 0 : isl_mat_copy(tab->basis), sample);
510 : }
511 : } else
512 1090278 : sample = isl_vec_alloc(ctx, 0);
513 :
514 16642799 : ctx->opt->gbr = gbr;
515 16642799 : isl_vec_free(min);
516 16642799 : isl_vec_free(max);
517 16642799 : free(snap);
518 16642799 : return sample;
519 : error:
520 0 : ctx->opt->gbr = gbr;
521 0 : isl_vec_free(min);
522 0 : isl_vec_free(max);
523 0 : free(snap);
524 0 : return NULL;
525 : }
526 :
527 : static __isl_give isl_vec *sample_bounded(__isl_take isl_basic_set *bset);
528 :
529 : /* Compute a sample point of the given basic set, based on the given,
530 : * non-trivial factorization.
531 : */
532 129106 : static __isl_give isl_vec *factored_sample(__isl_take isl_basic_set *bset,
533 : __isl_take isl_factorizer *f)
534 : {
535 : int i, n;
536 129106 : isl_vec *sample = NULL;
537 : isl_ctx *ctx;
538 : unsigned nparam;
539 : unsigned nvar;
540 :
541 129106 : ctx = isl_basic_set_get_ctx(bset);
542 129106 : if (!ctx)
543 0 : goto error;
544 :
545 129106 : nparam = isl_basic_set_dim(bset, isl_dim_param);
546 129106 : nvar = isl_basic_set_dim(bset, isl_dim_set);
547 :
548 129106 : sample = isl_vec_alloc(ctx, 1 + isl_basic_set_total_dim(bset));
549 129106 : if (!sample)
550 0 : goto error;
551 129106 : isl_int_set_si(sample->el[0], 1);
552 :
553 129106 : bset = isl_morph_basic_set(isl_morph_copy(f->morph), bset);
554 :
555 330407 : for (i = 0, n = 0; i < f->n_group; ++i) {
556 : isl_basic_set *bset_i;
557 : isl_vec *sample_i;
558 :
559 238314 : bset_i = isl_basic_set_copy(bset);
560 476628 : bset_i = isl_basic_set_drop_constraints_involving(bset_i,
561 476628 : nparam + n + f->len[i], nvar - n - f->len[i]);
562 238314 : bset_i = isl_basic_set_drop_constraints_involving(bset_i,
563 : nparam, n);
564 476628 : bset_i = isl_basic_set_drop(bset_i, isl_dim_set,
565 476628 : n + f->len[i], nvar - n - f->len[i]);
566 238314 : bset_i = isl_basic_set_drop(bset_i, isl_dim_set, 0, n);
567 :
568 238314 : sample_i = sample_bounded(bset_i);
569 238314 : if (!sample_i)
570 0 : goto error;
571 238314 : if (sample_i->size == 0) {
572 37013 : isl_basic_set_free(bset);
573 37013 : isl_factorizer_free(f);
574 37013 : isl_vec_free(sample);
575 37013 : return sample_i;
576 : }
577 402602 : isl_seq_cpy(sample->el + 1 + nparam + n,
578 402602 : sample_i->el + 1, f->len[i]);
579 201301 : isl_vec_free(sample_i);
580 :
581 201301 : n += f->len[i];
582 : }
583 :
584 92093 : f->morph = isl_morph_inverse(f->morph);
585 92093 : sample = isl_morph_vec(isl_morph_copy(f->morph), sample);
586 :
587 92093 : isl_basic_set_free(bset);
588 92093 : isl_factorizer_free(f);
589 92093 : return sample;
590 : error:
591 0 : isl_basic_set_free(bset);
592 0 : isl_factorizer_free(f);
593 0 : isl_vec_free(sample);
594 0 : return NULL;
595 : }
596 :
597 : /* Given a basic set that is known to be bounded, find and return
598 : * an integer point in the basic set, if there is any.
599 : *
600 : * After handling some trivial cases, we construct a tableau
601 : * and then use isl_tab_sample to find a sample, passing it
602 : * the identity matrix as initial basis.
603 : */
604 55523765 : static __isl_give isl_vec *sample_bounded(__isl_take isl_basic_set *bset)
605 : {
606 : unsigned dim;
607 : struct isl_vec *sample;
608 55523765 : struct isl_tab *tab = NULL;
609 : isl_factorizer *f;
610 :
611 55523765 : if (!bset)
612 0 : return NULL;
613 :
614 55523765 : if (isl_basic_set_plain_is_empty(bset))
615 0 : return empty_sample(bset);
616 :
617 55523765 : dim = isl_basic_set_total_dim(bset);
618 55523765 : if (dim == 0)
619 10569884 : return zero_sample(bset);
620 44953881 : if (dim == 1)
621 995698 : return interval_sample(bset);
622 43958183 : if (bset->n_eq > 0)
623 0 : return sample_eq(bset, sample_bounded);
624 :
625 43958183 : f = isl_basic_set_factorizer(bset);
626 43958183 : if (!f)
627 0 : goto error;
628 43958183 : if (f->n_group != 0)
629 129106 : return factored_sample(bset, f);
630 43829077 : isl_factorizer_free(f);
631 :
632 43829077 : tab = isl_tab_from_basic_set(bset, 1);
633 43829077 : if (tab && tab->empty) {
634 27237109 : isl_tab_free(tab);
635 27237109 : ISL_F_SET(bset, ISL_BASIC_SET_EMPTY);
636 27237109 : sample = isl_vec_alloc(isl_basic_set_get_ctx(bset), 0);
637 27237109 : isl_basic_set_free(bset);
638 27237109 : return sample;
639 : }
640 :
641 16591968 : if (!ISL_F_ISSET(bset, ISL_BASIC_SET_NO_IMPLICIT))
642 16547718 : if (isl_tab_detect_implicit_equalities(tab) < 0)
643 0 : goto error;
644 :
645 16591968 : sample = isl_tab_sample(tab);
646 16591968 : if (!sample)
647 0 : goto error;
648 :
649 16591968 : if (sample->size > 0) {
650 15388094 : isl_vec_free(bset->sample);
651 15388094 : bset->sample = isl_vec_copy(sample);
652 : }
653 :
654 16591968 : isl_basic_set_free(bset);
655 16591968 : isl_tab_free(tab);
656 16591968 : return sample;
657 : error:
658 0 : isl_basic_set_free(bset);
659 0 : isl_tab_free(tab);
660 0 : return NULL;
661 : }
662 :
663 : /* Given a basic set "bset" and a value "sample" for the first coordinates
664 : * of bset, plug in these values and drop the corresponding coordinates.
665 : *
666 : * We do this by computing the preimage of the transformation
667 : *
668 : * [ 1 0 ]
669 : * x = [ s 0 ] x'
670 : * [ 0 I ]
671 : *
672 : * where [1 s] is the sample value and I is the identity matrix of the
673 : * appropriate dimension.
674 : */
675 14447846 : static __isl_give isl_basic_set *plug_in(__isl_take isl_basic_set *bset,
676 : __isl_take isl_vec *sample)
677 : {
678 : int i;
679 : unsigned total;
680 : struct isl_mat *T;
681 :
682 14447846 : if (!bset || !sample)
683 : goto error;
684 :
685 14447846 : total = isl_basic_set_total_dim(bset);
686 14447846 : T = isl_mat_alloc(bset->ctx, 1 + total, 1 + total - (sample->size - 1));
687 14447846 : if (!T)
688 0 : goto error;
689 :
690 40112358 : for (i = 0; i < sample->size; ++i) {
691 25664512 : isl_int_set(T->row[i][0], sample->el[i]);
692 25664512 : isl_seq_clr(T->row[i] + 1, T->n_col - 1);
693 : }
694 76221758 : for (i = 0; i < T->n_col - 1; ++i) {
695 61773912 : isl_seq_clr(T->row[sample->size + i], T->n_col);
696 61773912 : isl_int_set_si(T->row[sample->size + i][1 + i], 1);
697 : }
698 14447846 : isl_vec_free(sample);
699 :
700 14447846 : bset = isl_basic_set_preimage(bset, T);
701 14447846 : return bset;
702 : error:
703 0 : isl_basic_set_free(bset);
704 0 : isl_vec_free(sample);
705 0 : return NULL;
706 : }
707 :
708 : /* Given a basic set "bset", return any (possibly non-integer) point
709 : * in the basic set.
710 : */
711 22151852 : static __isl_give isl_vec *rational_sample(__isl_take isl_basic_set *bset)
712 : {
713 : struct isl_tab *tab;
714 : struct isl_vec *sample;
715 :
716 22151852 : if (!bset)
717 0 : return NULL;
718 :
719 22151852 : tab = isl_tab_from_basic_set(bset, 0);
720 22151852 : sample = isl_tab_get_sample_value(tab);
721 22151852 : isl_tab_free(tab);
722 :
723 22151852 : isl_basic_set_free(bset);
724 :
725 22151852 : return sample;
726 : }
727 :
728 : /* Given a linear cone "cone" and a rational point "vec",
729 : * construct a polyhedron with shifted copies of the constraints in "cone",
730 : * i.e., a polyhedron with "cone" as its recession cone, such that each
731 : * point x in this polyhedron is such that the unit box positioned at x
732 : * lies entirely inside the affine cone 'vec + cone'.
733 : * Any rational point in this polyhedron may therefore be rounded up
734 : * to yield an integer point that lies inside said affine cone.
735 : *
736 : * Denote the constraints of cone by "<a_i, x> >= 0" and the rational
737 : * point "vec" by v/d.
738 : * Let b_i = <a_i, v>. Then the affine cone 'vec + cone' is given
739 : * by <a_i, x> - b/d >= 0.
740 : * The polyhedron <a_i, x> - ceil{b/d} >= 0 is a subset of this affine cone.
741 : * We prefer this polyhedron over the actual affine cone because it doesn't
742 : * require a scaling of the constraints.
743 : * If each of the vertices of the unit cube positioned at x lies inside
744 : * this polyhedron, then the whole unit cube at x lies inside the affine cone.
745 : * We therefore impose that x' = x + \sum e_i, for any selection of unit
746 : * vectors lies inside the polyhedron, i.e.,
747 : *
748 : * <a_i, x'> - ceil{b/d} = <a_i, x> + sum a_i - ceil{b/d} >= 0
749 : *
750 : * The most stringent of these constraints is the one that selects
751 : * all negative a_i, so the polyhedron we are looking for has constraints
752 : *
753 : * <a_i, x> + sum_{a_i < 0} a_i - ceil{b/d} >= 0
754 : *
755 : * Note that if cone were known to have only non-negative rays
756 : * (which can be accomplished by a unimodular transformation),
757 : * then we would only have to check the points x' = x + e_i
758 : * and we only have to add the smallest negative a_i (if any)
759 : * instead of the sum of all negative a_i.
760 : */
761 7704006 : static __isl_give isl_basic_set *shift_cone(__isl_take isl_basic_set *cone,
762 : __isl_take isl_vec *vec)
763 : {
764 : int i, j, k;
765 : unsigned total;
766 :
767 7704006 : struct isl_basic_set *shift = NULL;
768 :
769 7704006 : if (!cone || !vec)
770 : goto error;
771 :
772 7704006 : isl_assert(cone->ctx, cone->n_eq == 0, goto error);
773 :
774 7704006 : total = isl_basic_set_total_dim(cone);
775 :
776 7704006 : shift = isl_basic_set_alloc_space(isl_basic_set_get_space(cone),
777 : 0, 0, cone->n_ineq);
778 :
779 48743050 : for (i = 0; i < cone->n_ineq; ++i) {
780 41039044 : k = isl_basic_set_alloc_inequality(shift);
781 41039044 : if (k < 0)
782 0 : goto error;
783 41039044 : isl_seq_cpy(shift->ineq[k] + 1, cone->ineq[i] + 1, total);
784 41039044 : isl_seq_inner_product(shift->ineq[k] + 1, vec->el + 1, total,
785 41039044 : &shift->ineq[k][0]);
786 41039044 : isl_int_cdiv_q(shift->ineq[k][0],
787 : shift->ineq[k][0], vec->el[0]);
788 41039044 : isl_int_neg(shift->ineq[k][0], shift->ineq[k][0]);
789 253120520 : for (j = 0; j < total; ++j) {
790 212081476 : if (isl_int_is_nonneg(shift->ineq[k][1 + j]))
791 155296258 : continue;
792 56785218 : isl_int_add(shift->ineq[k][0],
793 : shift->ineq[k][0], shift->ineq[k][1 + j]);
794 : }
795 : }
796 :
797 7704006 : isl_basic_set_free(cone);
798 7704006 : isl_vec_free(vec);
799 :
800 7704006 : return isl_basic_set_finalize(shift);
801 : error:
802 0 : isl_basic_set_free(shift);
803 0 : isl_basic_set_free(cone);
804 0 : isl_vec_free(vec);
805 0 : return NULL;
806 : }
807 :
808 : /* Given a rational point vec in a (transformed) basic set,
809 : * such that cone is the recession cone of the original basic set,
810 : * "round up" the rational point to an integer point.
811 : *
812 : * We first check if the rational point just happens to be integer.
813 : * If not, we transform the cone in the same way as the basic set,
814 : * pick a point x in this cone shifted to the rational point such that
815 : * the whole unit cube at x is also inside this affine cone.
816 : * Then we simply round up the coordinates of x and return the
817 : * resulting integer point.
818 : */
819 14447846 : static __isl_give isl_vec *round_up_in_cone(__isl_take isl_vec *vec,
820 : __isl_take isl_basic_set *cone, __isl_take isl_mat *U)
821 : {
822 : unsigned total;
823 :
824 14447846 : if (!vec || !cone || !U)
825 : goto error;
826 :
827 14447846 : isl_assert(vec->ctx, vec->size != 0, goto error);
828 14447846 : if (isl_int_is_one(vec->el[0])) {
829 6743840 : isl_mat_free(U);
830 6743840 : isl_basic_set_free(cone);
831 6743840 : return vec;
832 : }
833 :
834 7704006 : total = isl_basic_set_total_dim(cone);
835 7704006 : cone = isl_basic_set_preimage(cone, U);
836 7704006 : cone = isl_basic_set_remove_dims(cone, isl_dim_set,
837 7704006 : 0, total - (vec->size - 1));
838 :
839 7704006 : cone = shift_cone(cone, vec);
840 :
841 7704006 : vec = rational_sample(cone);
842 7704006 : vec = isl_vec_ceil(vec);
843 7704006 : return vec;
844 : error:
845 0 : isl_mat_free(U);
846 0 : isl_vec_free(vec);
847 0 : isl_basic_set_free(cone);
848 0 : return NULL;
849 : }
850 :
851 : /* Concatenate two integer vectors, i.e., two vectors with denominator
852 : * (stored in element 0) equal to 1.
853 : */
854 14447846 : static __isl_give isl_vec *vec_concat(__isl_take isl_vec *vec1,
855 : __isl_take isl_vec *vec2)
856 : {
857 : struct isl_vec *vec;
858 :
859 14447846 : if (!vec1 || !vec2)
860 : goto error;
861 14447846 : isl_assert(vec1->ctx, vec1->size > 0, goto error);
862 14447846 : isl_assert(vec2->ctx, vec2->size > 0, goto error);
863 14447846 : isl_assert(vec1->ctx, isl_int_is_one(vec1->el[0]), goto error);
864 14447846 : isl_assert(vec2->ctx, isl_int_is_one(vec2->el[0]), goto error);
865 :
866 14447846 : vec = isl_vec_alloc(vec1->ctx, vec1->size + vec2->size - 1);
867 14447846 : if (!vec)
868 0 : goto error;
869 :
870 14447846 : isl_seq_cpy(vec->el, vec1->el, vec1->size);
871 14447846 : isl_seq_cpy(vec->el + vec1->size, vec2->el + 1, vec2->size - 1);
872 :
873 14447846 : isl_vec_free(vec1);
874 14447846 : isl_vec_free(vec2);
875 :
876 14447846 : return vec;
877 : error:
878 0 : isl_vec_free(vec1);
879 0 : isl_vec_free(vec2);
880 0 : return NULL;
881 : }
882 :
883 : /* Give a basic set "bset" with recession cone "cone", compute and
884 : * return an integer point in bset, if any.
885 : *
886 : * If the recession cone is full-dimensional, then we know that
887 : * bset contains an infinite number of integer points and it is
888 : * fairly easy to pick one of them.
889 : * If the recession cone is not full-dimensional, then we first
890 : * transform bset such that the bounded directions appear as
891 : * the first dimensions of the transformed basic set.
892 : * We do this by using a unimodular transformation that transforms
893 : * the equalities in the recession cone to equalities on the first
894 : * dimensions.
895 : *
896 : * The transformed set is then projected onto its bounded dimensions.
897 : * Note that to compute this projection, we can simply drop all constraints
898 : * involving any of the unbounded dimensions since these constraints
899 : * cannot be combined to produce a constraint on the bounded dimensions.
900 : * To see this, assume that there is such a combination of constraints
901 : * that produces a constraint on the bounded dimensions. This means
902 : * that some combination of the unbounded dimensions has both an upper
903 : * bound and a lower bound in terms of the bounded dimensions, but then
904 : * this combination would be a bounded direction too and would have been
905 : * transformed into a bounded dimensions.
906 : *
907 : * We then compute a sample value in the bounded dimensions.
908 : * If no such value can be found, then the original set did not contain
909 : * any integer points and we are done.
910 : * Otherwise, we plug in the value we found in the bounded dimensions,
911 : * project out these bounded dimensions and end up with a set with
912 : * a full-dimensional recession cone.
913 : * A sample point in this set is computed by "rounding up" any
914 : * rational point in the set.
915 : *
916 : * The sample points in the bounded and unbounded dimensions are
917 : * then combined into a single sample point and transformed back
918 : * to the original space.
919 : */
920 16016813 : __isl_give isl_vec *isl_basic_set_sample_with_cone(
921 : __isl_take isl_basic_set *bset, __isl_take isl_basic_set *cone)
922 : {
923 : unsigned total;
924 : unsigned cone_dim;
925 : struct isl_mat *M, *U;
926 : struct isl_vec *sample;
927 : struct isl_vec *cone_sample;
928 : struct isl_ctx *ctx;
929 : struct isl_basic_set *bounded;
930 :
931 16016813 : if (!bset || !cone)
932 : goto error;
933 :
934 16016813 : ctx = isl_basic_set_get_ctx(bset);
935 16016813 : total = isl_basic_set_total_dim(cone);
936 16016813 : cone_dim = total - cone->n_eq;
937 :
938 16016813 : M = isl_mat_sub_alloc6(ctx, cone->eq, 0, cone->n_eq, 1, total);
939 16016813 : M = isl_mat_left_hermite(M, 0, &U, NULL);
940 16016813 : if (!M)
941 0 : goto error;
942 16016813 : isl_mat_free(M);
943 :
944 16016813 : U = isl_mat_lin_to_aff(U);
945 16016813 : bset = isl_basic_set_preimage(bset, isl_mat_copy(U));
946 :
947 16016813 : bounded = isl_basic_set_copy(bset);
948 16016813 : bounded = isl_basic_set_drop_constraints_involving(bounded,
949 : total - cone_dim, cone_dim);
950 16016813 : bounded = isl_basic_set_drop_dims(bounded, total - cone_dim, cone_dim);
951 16016813 : sample = sample_bounded(bounded);
952 16016813 : if (!sample || sample->size == 0) {
953 1568967 : isl_basic_set_free(bset);
954 1568967 : isl_basic_set_free(cone);
955 1568967 : isl_mat_free(U);
956 1568967 : return sample;
957 : }
958 14447846 : bset = plug_in(bset, isl_vec_copy(sample));
959 14447846 : cone_sample = rational_sample(bset);
960 14447846 : cone_sample = round_up_in_cone(cone_sample, cone, isl_mat_copy(U));
961 14447846 : sample = vec_concat(sample, cone_sample);
962 14447846 : sample = isl_mat_vec_product(U, sample);
963 14447846 : return sample;
964 : error:
965 0 : isl_basic_set_free(cone);
966 0 : isl_basic_set_free(bset);
967 0 : return NULL;
968 : }
969 :
970 0 : static void vec_sum_of_neg(struct isl_vec *v, isl_int *s)
971 : {
972 : int i;
973 :
974 0 : isl_int_set_si(*s, 0);
975 :
976 0 : for (i = 0; i < v->size; ++i)
977 0 : if (isl_int_is_neg(v->el[i]))
978 0 : isl_int_add(*s, *s, v->el[i]);
979 0 : }
980 :
981 : /* Given a tableau "tab", a tableau "tab_cone" that corresponds
982 : * to the recession cone and the inverse of a new basis U = inv(B),
983 : * with the unbounded directions in B last,
984 : * add constraints to "tab" that ensure any rational value
985 : * in the unbounded directions can be rounded up to an integer value.
986 : *
987 : * The new basis is given by x' = B x, i.e., x = U x'.
988 : * For any rational value of the last tab->n_unbounded coordinates
989 : * in the update tableau, the value that is obtained by rounding
990 : * up this value should be contained in the original tableau.
991 : * For any constraint "a x + c >= 0", we therefore need to add
992 : * a constraint "a x + c + s >= 0", with s the sum of all negative
993 : * entries in the last elements of "a U".
994 : *
995 : * Since we are not interested in the first entries of any of the "a U",
996 : * we first drop the columns of U that correpond to bounded directions.
997 : */
998 0 : static int tab_shift_cone(struct isl_tab *tab,
999 : struct isl_tab *tab_cone, struct isl_mat *U)
1000 : {
1001 : int i;
1002 : isl_int v;
1003 0 : struct isl_basic_set *bset = NULL;
1004 :
1005 0 : if (tab && tab->n_unbounded == 0) {
1006 0 : isl_mat_free(U);
1007 0 : return 0;
1008 : }
1009 0 : isl_int_init(v);
1010 0 : if (!tab || !tab_cone || !U)
1011 : goto error;
1012 0 : bset = isl_tab_peek_bset(tab_cone);
1013 0 : U = isl_mat_drop_cols(U, 0, tab->n_var - tab->n_unbounded);
1014 0 : for (i = 0; i < bset->n_ineq; ++i) {
1015 : int ok;
1016 0 : struct isl_vec *row = NULL;
1017 0 : if (isl_tab_is_equality(tab_cone, tab_cone->n_eq + i))
1018 0 : continue;
1019 0 : row = isl_vec_alloc(bset->ctx, tab_cone->n_var);
1020 0 : if (!row)
1021 0 : goto error;
1022 0 : isl_seq_cpy(row->el, bset->ineq[i] + 1, tab_cone->n_var);
1023 0 : row = isl_vec_mat_product(row, isl_mat_copy(U));
1024 0 : if (!row)
1025 0 : goto error;
1026 0 : vec_sum_of_neg(row, &v);
1027 0 : isl_vec_free(row);
1028 0 : if (isl_int_is_zero(v))
1029 0 : continue;
1030 0 : if (isl_tab_extend_cons(tab, 1) < 0)
1031 0 : goto error;
1032 0 : isl_int_add(bset->ineq[i][0], bset->ineq[i][0], v);
1033 0 : ok = isl_tab_add_ineq(tab, bset->ineq[i]) >= 0;
1034 0 : isl_int_sub(bset->ineq[i][0], bset->ineq[i][0], v);
1035 0 : if (!ok)
1036 0 : goto error;
1037 : }
1038 :
1039 0 : isl_mat_free(U);
1040 0 : isl_int_clear(v);
1041 0 : return 0;
1042 : error:
1043 0 : isl_mat_free(U);
1044 0 : isl_int_clear(v);
1045 0 : return -1;
1046 : }
1047 :
1048 : /* Compute and return an initial basis for the possibly
1049 : * unbounded tableau "tab". "tab_cone" is a tableau
1050 : * for the corresponding recession cone.
1051 : * Additionally, add constraints to "tab" that ensure
1052 : * that any rational value for the unbounded directions
1053 : * can be rounded up to an integer value.
1054 : *
1055 : * If the tableau is bounded, i.e., if the recession cone
1056 : * is zero-dimensional, then we just use inital_basis.
1057 : * Otherwise, we construct a basis whose first directions
1058 : * correspond to equalities, followed by bounded directions,
1059 : * i.e., equalities in the recession cone.
1060 : * The remaining directions are then unbounded.
1061 : */
1062 0 : int isl_tab_set_initial_basis_with_cone(struct isl_tab *tab,
1063 : struct isl_tab *tab_cone)
1064 : {
1065 : struct isl_mat *eq;
1066 : struct isl_mat *cone_eq;
1067 : struct isl_mat *U, *Q;
1068 :
1069 0 : if (!tab || !tab_cone)
1070 0 : return -1;
1071 :
1072 0 : if (tab_cone->n_col == tab_cone->n_dead) {
1073 0 : tab->basis = initial_basis(tab);
1074 0 : return tab->basis ? 0 : -1;
1075 : }
1076 :
1077 0 : eq = tab_equalities(tab);
1078 0 : if (!eq)
1079 0 : return -1;
1080 0 : tab->n_zero = eq->n_row;
1081 0 : cone_eq = tab_equalities(tab_cone);
1082 0 : eq = isl_mat_concat(eq, cone_eq);
1083 0 : if (!eq)
1084 0 : return -1;
1085 0 : tab->n_unbounded = tab->n_var - (eq->n_row - tab->n_zero);
1086 0 : eq = isl_mat_left_hermite(eq, 0, &U, &Q);
1087 0 : if (!eq)
1088 0 : return -1;
1089 0 : isl_mat_free(eq);
1090 0 : tab->basis = isl_mat_lin_to_aff(Q);
1091 0 : if (tab_shift_cone(tab, tab_cone, U) < 0)
1092 0 : return -1;
1093 0 : if (!tab->basis)
1094 0 : return -1;
1095 0 : return 0;
1096 : }
1097 :
1098 : /* Compute and return a sample point in bset using generalized basis
1099 : * reduction. We first check if the input set has a non-trivial
1100 : * recession cone. If so, we perform some extra preprocessing in
1101 : * sample_with_cone. Otherwise, we directly perform generalized basis
1102 : * reduction.
1103 : */
1104 55285451 : static __isl_give isl_vec *gbr_sample(__isl_take isl_basic_set *bset)
1105 : {
1106 : unsigned dim;
1107 : struct isl_basic_set *cone;
1108 :
1109 55285451 : dim = isl_basic_set_total_dim(bset);
1110 :
1111 55285451 : cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset));
1112 55285451 : if (!cone)
1113 0 : goto error;
1114 :
1115 55285451 : if (cone->n_eq < dim)
1116 16016813 : return isl_basic_set_sample_with_cone(bset, cone);
1117 :
1118 39268638 : isl_basic_set_free(cone);
1119 39268638 : return sample_bounded(bset);
1120 : error:
1121 0 : isl_basic_set_free(bset);
1122 0 : return NULL;
1123 : }
1124 :
1125 77648185 : static __isl_give isl_vec *basic_set_sample(__isl_take isl_basic_set *bset,
1126 : int bounded)
1127 : {
1128 : struct isl_ctx *ctx;
1129 : unsigned dim;
1130 77648185 : if (!bset)
1131 0 : return NULL;
1132 :
1133 77648185 : ctx = bset->ctx;
1134 77648185 : if (isl_basic_set_plain_is_empty(bset))
1135 166168 : return empty_sample(bset);
1136 :
1137 77482017 : dim = isl_basic_set_n_dim(bset);
1138 77482017 : isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
1139 77482017 : isl_assert(ctx, bset->n_div == 0, goto error);
1140 :
1141 77482017 : if (bset->sample && bset->sample->size == 1 + dim) {
1142 0 : int contains = isl_basic_set_contains(bset, bset->sample);
1143 0 : if (contains < 0)
1144 0 : goto error;
1145 0 : if (contains) {
1146 0 : struct isl_vec *sample = isl_vec_copy(bset->sample);
1147 0 : isl_basic_set_free(bset);
1148 0 : return sample;
1149 : }
1150 : }
1151 77482017 : isl_vec_free(bset->sample);
1152 77482017 : bset->sample = NULL;
1153 :
1154 77482017 : if (bset->n_eq > 0)
1155 22116812 : return sample_eq(bset, bounded ? isl_basic_set_sample_bounded
1156 : : isl_basic_set_sample_vec);
1157 55365205 : if (dim == 0)
1158 16473 : return zero_sample(bset);
1159 55348732 : if (dim == 1)
1160 63281 : return interval_sample(bset);
1161 :
1162 55285451 : return bounded ? sample_bounded(bset) : gbr_sample(bset);
1163 : error:
1164 0 : isl_basic_set_free(bset);
1165 0 : return NULL;
1166 : }
1167 :
1168 77648185 : __isl_give isl_vec *isl_basic_set_sample_vec(__isl_take isl_basic_set *bset)
1169 : {
1170 77648185 : return basic_set_sample(bset, 0);
1171 : }
1172 :
1173 : /* Compute an integer sample in "bset", where the caller guarantees
1174 : * that "bset" is bounded.
1175 : */
1176 0 : __isl_give isl_vec *isl_basic_set_sample_bounded(__isl_take isl_basic_set *bset)
1177 : {
1178 0 : return basic_set_sample(bset, 1);
1179 : }
1180 :
1181 2048330 : __isl_give isl_basic_set *isl_basic_set_from_vec(__isl_take isl_vec *vec)
1182 : {
1183 : int i;
1184 : int k;
1185 2048330 : struct isl_basic_set *bset = NULL;
1186 : struct isl_ctx *ctx;
1187 : unsigned dim;
1188 :
1189 2048330 : if (!vec)
1190 0 : return NULL;
1191 2048330 : ctx = vec->ctx;
1192 2048330 : isl_assert(ctx, vec->size != 0, goto error);
1193 :
1194 2048330 : bset = isl_basic_set_alloc(ctx, 0, vec->size - 1, 0, vec->size - 1, 0);
1195 2048330 : if (!bset)
1196 0 : goto error;
1197 2048330 : dim = isl_basic_set_n_dim(bset);
1198 13203600 : for (i = dim - 1; i >= 0; --i) {
1199 11155270 : k = isl_basic_set_alloc_equality(bset);
1200 11155270 : if (k < 0)
1201 0 : goto error;
1202 11155270 : isl_seq_clr(bset->eq[k], 1 + dim);
1203 11155270 : isl_int_neg(bset->eq[k][0], vec->el[1 + i]);
1204 11155270 : isl_int_set(bset->eq[k][1 + i], vec->el[0]);
1205 : }
1206 2048330 : bset->sample = vec;
1207 :
1208 2048330 : return bset;
1209 : error:
1210 0 : isl_basic_set_free(bset);
1211 0 : isl_vec_free(vec);
1212 0 : return NULL;
1213 : }
1214 :
1215 0 : __isl_give isl_basic_map *isl_basic_map_sample(__isl_take isl_basic_map *bmap)
1216 : {
1217 : struct isl_basic_set *bset;
1218 : struct isl_vec *sample_vec;
1219 :
1220 0 : bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
1221 0 : sample_vec = isl_basic_set_sample_vec(bset);
1222 0 : if (!sample_vec)
1223 0 : goto error;
1224 0 : if (sample_vec->size == 0) {
1225 0 : isl_vec_free(sample_vec);
1226 0 : return isl_basic_map_set_to_empty(bmap);
1227 : }
1228 0 : isl_vec_free(bmap->sample);
1229 0 : bmap->sample = isl_vec_copy(sample_vec);
1230 0 : bset = isl_basic_set_from_vec(sample_vec);
1231 0 : return isl_basic_map_overlying_set(bset, bmap);
1232 : error:
1233 0 : isl_basic_map_free(bmap);
1234 0 : return NULL;
1235 : }
1236 :
1237 0 : __isl_give isl_basic_set *isl_basic_set_sample(__isl_take isl_basic_set *bset)
1238 : {
1239 0 : return isl_basic_map_sample(bset);
1240 : }
1241 :
1242 0 : __isl_give isl_basic_map *isl_map_sample(__isl_take isl_map *map)
1243 : {
1244 : int i;
1245 0 : isl_basic_map *sample = NULL;
1246 :
1247 0 : if (!map)
1248 0 : goto error;
1249 :
1250 0 : for (i = 0; i < map->n; ++i) {
1251 0 : sample = isl_basic_map_sample(isl_basic_map_copy(map->p[i]));
1252 0 : if (!sample)
1253 0 : goto error;
1254 0 : if (!ISL_F_ISSET(sample, ISL_BASIC_MAP_EMPTY))
1255 0 : break;
1256 0 : isl_basic_map_free(sample);
1257 : }
1258 0 : if (i == map->n)
1259 0 : sample = isl_basic_map_empty(isl_map_get_space(map));
1260 0 : isl_map_free(map);
1261 0 : return sample;
1262 : error:
1263 0 : isl_map_free(map);
1264 0 : return NULL;
1265 : }
1266 :
1267 0 : __isl_give isl_basic_set *isl_set_sample(__isl_take isl_set *set)
1268 : {
1269 0 : return bset_from_bmap(isl_map_sample(set_to_map(set)));
1270 : }
1271 :
1272 0 : __isl_give isl_point *isl_basic_set_sample_point(__isl_take isl_basic_set *bset)
1273 : {
1274 : isl_vec *vec;
1275 : isl_space *dim;
1276 :
1277 0 : dim = isl_basic_set_get_space(bset);
1278 0 : bset = isl_basic_set_underlying_set(bset);
1279 0 : vec = isl_basic_set_sample_vec(bset);
1280 :
1281 0 : return isl_point_alloc(dim, vec);
1282 : }
1283 :
1284 0 : __isl_give isl_point *isl_set_sample_point(__isl_take isl_set *set)
1285 : {
1286 : int i;
1287 : isl_point *pnt;
1288 :
1289 0 : if (!set)
1290 0 : return NULL;
1291 :
1292 0 : for (i = 0; i < set->n; ++i) {
1293 0 : pnt = isl_basic_set_sample_point(isl_basic_set_copy(set->p[i]));
1294 0 : if (!pnt)
1295 0 : goto error;
1296 0 : if (!isl_point_is_void(pnt))
1297 0 : break;
1298 0 : isl_point_free(pnt);
1299 : }
1300 0 : if (i == set->n)
1301 0 : pnt = isl_point_void(isl_set_get_space(set));
1302 :
1303 0 : isl_set_free(set);
1304 0 : return pnt;
1305 : error:
1306 0 : isl_set_free(set);
1307 0 : return NULL;
1308 : }
|