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