isl_basic_set_sample: check sample stored by isl_basic_map_is_empty first
[platform/upstream/isl.git] / isl_sample.c
1 #include "isl_sample.h"
2 #include "isl_sample_piplib.h"
3 #include "isl_vec.h"
4 #include "isl_mat.h"
5 #include "isl_seq.h"
6 #include "isl_map_private.h"
7 #include "isl_equalities.h"
8 #include "isl_tab.h"
9 #include "isl_basis_reduction.h"
10
11 static struct isl_vec *empty_sample(struct isl_basic_set *bset)
12 {
13         struct isl_vec *vec;
14
15         vec = isl_vec_alloc(bset->ctx, 0);
16         isl_basic_set_free(bset);
17         return vec;
18 }
19
20 /* Construct a zero sample of the same dimension as bset.
21  * As a special case, if bset is zero-dimensional, this
22  * function creates a zero-dimensional sample point.
23  */
24 static struct isl_vec *zero_sample(struct isl_basic_set *bset)
25 {
26         unsigned dim;
27         struct isl_vec *sample;
28
29         dim = isl_basic_set_total_dim(bset);
30         sample = isl_vec_alloc(bset->ctx, 1 + dim);
31         if (sample) {
32                 isl_int_set_si(sample->el[0], 1);
33                 isl_seq_clr(sample->el + 1, dim);
34         }
35         isl_basic_set_free(bset);
36         return sample;
37 }
38
39 static struct isl_vec *interval_sample(struct isl_basic_set *bset)
40 {
41         int i;
42         isl_int t;
43         struct isl_vec *sample;
44
45         bset = isl_basic_set_simplify(bset);
46         if (!bset)
47                 return NULL;
48         if (isl_basic_set_fast_is_empty(bset))
49                 return empty_sample(bset);
50         if (bset->n_eq == 0 && bset->n_ineq == 0)
51                 return zero_sample(bset);
52
53         sample = isl_vec_alloc(bset->ctx, 2);
54         isl_int_set_si(sample->block.data[0], 1);
55
56         if (bset->n_eq > 0) {
57                 isl_assert(bset->ctx, bset->n_eq == 1, goto error);
58                 isl_assert(bset->ctx, bset->n_ineq == 0, goto error);
59                 if (isl_int_is_one(bset->eq[0][1]))
60                         isl_int_neg(sample->el[1], bset->eq[0][0]);
61                 else {
62                         isl_assert(bset->ctx, isl_int_is_negone(bset->eq[0][1]),
63                                    goto error);
64                         isl_int_set(sample->el[1], bset->eq[0][0]);
65                 }
66                 isl_basic_set_free(bset);
67                 return sample;
68         }
69
70         isl_int_init(t);
71         if (isl_int_is_one(bset->ineq[0][1]))
72                 isl_int_neg(sample->block.data[1], bset->ineq[0][0]);
73         else
74                 isl_int_set(sample->block.data[1], bset->ineq[0][0]);
75         for (i = 1; i < bset->n_ineq; ++i) {
76                 isl_seq_inner_product(sample->block.data,
77                                         bset->ineq[i], 2, &t);
78                 if (isl_int_is_neg(t))
79                         break;
80         }
81         isl_int_clear(t);
82         if (i < bset->n_ineq) {
83                 isl_vec_free(sample);
84                 return empty_sample(bset);
85         }
86
87         isl_basic_set_free(bset);
88         return sample;
89 error:
90         isl_basic_set_free(bset);
91         isl_vec_free(sample);
92         return NULL;
93 }
94
95 static struct isl_mat *independent_bounds(struct isl_ctx *ctx,
96         struct isl_basic_set *bset)
97 {
98         int i, j, n;
99         struct isl_mat *dirs = NULL;
100         unsigned dim;
101
102         if (!bset)
103                 return NULL;
104
105         dim = isl_basic_set_n_dim(bset);
106         if (bset->n_ineq == 0)
107                 return isl_mat_alloc(ctx, 0, dim);
108
109         dirs = isl_mat_alloc(ctx, dim, dim);
110         if (!dirs)
111                 return NULL;
112         isl_seq_cpy(dirs->row[0], bset->ineq[0]+1, dirs->n_col);
113         for (j = 1, n = 1; n < dim && j < bset->n_ineq; ++j) {
114                 int pos;
115
116                 isl_seq_cpy(dirs->row[n], bset->ineq[j]+1, dirs->n_col);
117
118                 pos = isl_seq_first_non_zero(dirs->row[n], dirs->n_col);
119                 if (pos < 0)
120                         continue;
121                 for (i = 0; i < n; ++i) {
122                         int pos_i;
123                         pos_i = isl_seq_first_non_zero(dirs->row[i], dirs->n_col);
124                         if (pos_i < pos)
125                                 continue;
126                         if (pos_i > pos)
127                                 break;
128                         isl_seq_elim(dirs->row[n], dirs->row[i], pos,
129                                         dirs->n_col, NULL);
130                         pos = isl_seq_first_non_zero(dirs->row[n], dirs->n_col);
131                         if (pos < 0)
132                                 break;
133                 }
134                 if (pos < 0)
135                         continue;
136                 if (i < n) {
137                         int k;
138                         isl_int *t = dirs->row[n];
139                         for (k = n; k > i; --k)
140                                 dirs->row[k] = dirs->row[k-1];
141                         dirs->row[i] = t;
142                 }
143                 ++n;
144         }
145         dirs->n_row = n;
146         return dirs;
147 }
148
149 /* Find a sample integer point, if any, in bset, which is known
150  * to have equalities.  If bset contains no integer points, then
151  * return a zero-length vector.
152  * We simply remove the known equalities, compute a sample
153  * in the resulting bset, using the specified recurse function,
154  * and then transform the sample back to the original space.
155  */
156 static struct isl_vec *sample_eq(struct isl_basic_set *bset,
157         struct isl_vec *(*recurse)(struct isl_basic_set *))
158 {
159         struct isl_mat *T;
160         struct isl_vec *sample;
161         struct isl_ctx *ctx;
162
163         if (!bset)
164                 return NULL;
165
166         ctx = bset->ctx;
167         bset = isl_basic_set_remove_equalities(bset, &T, NULL);
168         sample = recurse(bset);
169         if (!sample || sample->size == 0)
170                 isl_mat_free(ctx, T);
171         else
172                 sample = isl_mat_vec_product(ctx, T, sample);
173         return sample;
174 }
175
176 /* Given a basic set "bset" and an affine function "f"/"denom",
177  * check if bset is bounded and non-empty and if so, return the minimal
178  * and maximal value attained by the affine function in "min" and "max".
179  * The minimal value is rounded up to the nearest integer, while the
180  * maximal value is rounded down.
181  * The return value indicates whether the set was empty or unbounded.
182  */
183 static enum isl_lp_result basic_set_range(struct isl_basic_set *bset,
184         isl_int *f, isl_int denom, isl_int *min, isl_int *max)
185 {
186         unsigned dim;
187         struct isl_tab *tab;
188         enum isl_lp_result res;
189
190         if (!bset)
191                 return isl_lp_error;
192         if (isl_basic_set_fast_is_empty(bset))
193                 return isl_lp_empty;
194
195         tab = isl_tab_from_basic_set(bset);
196         res = isl_tab_min(bset->ctx, tab, f, denom, min, NULL, 0);
197         if (res != isl_lp_ok) {
198                 isl_tab_free(bset->ctx, tab);
199                 return res;
200         }
201         dim = isl_basic_set_total_dim(bset);
202         isl_seq_neg(f, f, 1 + dim);
203         res = isl_tab_min(bset->ctx, tab, f, denom, max, NULL, 0);
204         isl_seq_neg(f, f, 1 + dim);
205         isl_int_neg(*max, *max);
206
207         isl_tab_free(bset->ctx, tab);
208         return res;
209 }
210
211 /* Perform a basis reduction on "bset" and return the inverse of
212  * the new basis, i.e., an affine mapping from the new coordinates to the old,
213  * in *T.
214  */
215 static struct isl_basic_set *basic_set_reduced(struct isl_basic_set *bset,
216         struct isl_mat **T)
217 {
218         struct isl_ctx *ctx;
219         unsigned gbr_only_first;
220
221         *T = NULL;
222         if (!bset)
223                 return NULL;
224
225         ctx = bset->ctx;
226
227         gbr_only_first = ctx->gbr_only_first;
228         ctx->gbr_only_first = 1;
229         *T = isl_basic_set_reduced_basis(bset);
230         ctx->gbr_only_first = gbr_only_first;
231
232         *T = isl_mat_lin_to_aff(bset->ctx, *T);
233         *T = isl_mat_right_inverse(bset->ctx, *T);
234
235         bset = isl_basic_set_preimage(bset, isl_mat_copy(bset->ctx, *T));
236         if (!bset)
237                 goto error;
238
239         return bset;
240 error:
241         isl_mat_free(ctx, *T);
242         *T = NULL;
243         return NULL;
244 }
245
246 static struct isl_vec *sample_bounded(struct isl_basic_set *bset);
247
248 /* Given a basic set "bset" whose first coordinate ranges between
249  * "min" and "max", step through all values from min to max, until
250  * the slice of bset with the first coordinate fixed to one of these
251  * values contains an integer point.  If such a point is found, return it.
252  * If none of the slices contains any integer point, then bset itself
253  * doesn't contain any integer point and an empty sample is returned.
254  */
255 static struct isl_vec *sample_scan(struct isl_basic_set *bset,
256         isl_int min, isl_int max)
257 {
258         unsigned total;
259         struct isl_basic_set *slice = NULL;
260         struct isl_vec *sample = NULL;
261         isl_int tmp;
262
263         total = isl_basic_set_total_dim(bset);
264
265         isl_int_init(tmp);
266         for (isl_int_set(tmp, min); isl_int_le(tmp, max);
267              isl_int_add_ui(tmp, tmp, 1)) {
268                 int k;
269
270                 slice = isl_basic_set_copy(bset);
271                 slice = isl_basic_set_cow(slice);
272                 slice = isl_basic_set_extend_constraints(slice, 1, 0);
273                 k = isl_basic_set_alloc_equality(slice);
274                 if (k < 0)
275                         goto error;
276                 isl_int_set(slice->eq[k][0], tmp);
277                 isl_int_set_si(slice->eq[k][1], -1);
278                 isl_seq_clr(slice->eq[k] + 2, total - 1);
279                 slice = isl_basic_set_simplify(slice);
280                 sample = sample_bounded(slice);
281                 slice = NULL;
282                 if (!sample)
283                         goto error;
284                 if (sample->size > 0)
285                         break;
286                 isl_vec_free(sample);
287                 sample = NULL;
288         }
289         if (!sample)
290                 sample = empty_sample(bset);
291         else
292                 isl_basic_set_free(bset);
293         isl_int_clear(tmp);
294         return sample;
295 error:
296         isl_basic_set_free(bset);
297         isl_basic_set_free(slice);
298         isl_int_clear(tmp);
299         return NULL;
300 }
301
302 /* Given a basic set that is known to be bounded, find and return
303  * an integer point in the basic set, if there is any.
304  *
305  * After handling some trivial cases, we check the range of the
306  * first coordinate.  If this coordinate can only attain one integer
307  * value, we are happy.  Otherwise, we perform basis reduction and
308  * determine the new range.
309  *
310  * Then we step through all possible values in the range in sample_scan.
311  *
312  * If any basis reduction was performed, the sample value found, if any,
313  * is transformed back to the original space.
314  */ 
315 static struct isl_vec *sample_bounded(struct isl_basic_set *bset)
316 {
317         unsigned dim;
318         struct isl_ctx *ctx;
319         struct isl_vec *sample;
320         struct isl_vec *obj = NULL;
321         struct isl_mat *T = NULL;
322         isl_int min, max;
323         enum isl_lp_result res;
324
325         if (!bset)
326                 return NULL;
327
328         if (isl_basic_set_fast_is_empty(bset))
329                 return empty_sample(bset);
330
331         ctx = bset->ctx;
332         dim = isl_basic_set_total_dim(bset);
333         if (dim == 0)
334                 return zero_sample(bset);
335         if (dim == 1)
336                 return interval_sample(bset);
337         if (bset->n_eq > 0)
338                 return sample_eq(bset, sample_bounded);
339
340         isl_int_init(min);
341         isl_int_init(max);
342         obj = isl_vec_alloc(bset->ctx, 1 + dim);
343         if (!obj)
344                 goto error;
345         isl_seq_clr(obj->el, 1+ dim);
346         isl_int_set_si(obj->el[1], 1);
347
348         res = basic_set_range(bset, obj->el, bset->ctx->one, &min, &max);
349         if (res == isl_lp_error)
350                 goto error;
351         isl_assert(bset->ctx, res != isl_lp_unbounded, goto error);
352         if (res == isl_lp_empty || isl_int_lt(max, min)) {
353                 sample = empty_sample(bset);
354                 goto out;
355         }
356
357         if (isl_int_ne(min, max)) {
358                 bset = basic_set_reduced(bset, &T);
359                 if (!bset)
360                         goto error;
361
362                 res = basic_set_range(bset, obj->el, bset->ctx->one, &min, &max);
363                 if (res == isl_lp_error)
364                         goto error;
365                 isl_assert(bset->ctx, res != isl_lp_unbounded, goto error);
366                 if (res == isl_lp_empty || isl_int_lt(max, min)) {
367                         sample = empty_sample(bset);
368                         goto out;
369                 }
370         }
371
372         sample = sample_scan(bset, min, max);
373 out:
374         if (T) {
375                 if (!sample || sample->size == 0)
376                         isl_mat_free(ctx, T);
377                 else
378                         sample = isl_mat_vec_product(ctx, T, sample);
379         }
380         isl_vec_free(obj);
381         isl_int_clear(min);
382         isl_int_clear(max);
383         return sample;
384 error:
385         isl_mat_free(ctx, T);
386         isl_basic_set_free(bset);
387         isl_vec_free(obj);
388         isl_int_clear(min);
389         isl_int_clear(max);
390         return NULL;
391 }
392
393 /* Given a basic set "bset" and a value "sample" for the first coordinates
394  * of bset, plug in these values and drop the corresponding coordinates.
395  *
396  * We do this by computing the preimage of the transformation
397  *
398  *           [ 1 0 ]
399  *      x =  [ s 0 ] x'
400  *           [ 0 I ]
401  *
402  * where [1 s] is the sample value and I is the identity matrix of the
403  * appropriate dimension.
404  */
405 static struct isl_basic_set *plug_in(struct isl_basic_set *bset,
406         struct isl_vec *sample)
407 {
408         int i;
409         unsigned total;
410         struct isl_mat *T;
411
412         if (!bset || !sample)
413                 goto error;
414
415         total = isl_basic_set_total_dim(bset);
416         T = isl_mat_alloc(bset->ctx, 1 + total, 1 + total - (sample->size - 1));
417         if (!T)
418                 goto error;
419
420         for (i = 0; i < sample->size; ++i) {
421                 isl_int_set(T->row[i][0], sample->el[i]);
422                 isl_seq_clr(T->row[i] + 1, T->n_col - 1);
423         }
424         for (i = 0; i < T->n_col - 1; ++i) {
425                 isl_seq_clr(T->row[sample->size + i], T->n_col);
426                 isl_int_set_si(T->row[sample->size + i][1 + i], 1);
427         }
428         isl_vec_free(sample);
429
430         bset = isl_basic_set_preimage(bset, T);
431         return bset;
432 error:
433         isl_basic_set_free(bset);
434         isl_vec_free(sample);
435         return NULL;
436 }
437
438 /* Given a basic set "bset", return any (possibly non-integer) point
439  * in the basic set.
440  */
441 static struct isl_vec *rational_sample(struct isl_basic_set *bset)
442 {
443         struct isl_tab *tab;
444         struct isl_vec *sample;
445
446         if (!bset)
447                 return NULL;
448
449         tab = isl_tab_from_basic_set(bset);
450         sample = isl_tab_get_sample_value(bset->ctx, tab);
451         isl_tab_free(bset->ctx, tab);
452
453         isl_basic_set_free(bset);
454
455         return sample;
456 }
457
458 /* Given a rational vector, with the denominator in the first element
459  * of the vector, round up all coordinates.
460  */
461 struct isl_vec *isl_vec_ceil(struct isl_vec *vec)
462 {
463         int i;
464
465         vec = isl_vec_cow(vec);
466         if (!vec)
467                 return NULL;
468
469         isl_seq_cdiv_q(vec->el + 1, vec->el + 1, vec->el[0], vec->size - 1);
470
471         isl_int_set_si(vec->el[0], 1);
472
473         return vec;
474 }
475
476 /* Given a linear cone "cone" and a rational point "vec",
477  * construct a polyhedron with shifted copies of the constraints in "cone",
478  * i.e., a polyhedron with "cone" as its recession cone, such that each
479  * point x in this polyhedron is such that the unit box positioned at x
480  * lies entirely inside the affine cone 'vec + cone'.
481  * Any rational point in this polyhedron may therefore be rounded up
482  * to yield an integer point that lies inside said affine cone.
483  *
484  * Denote the constraints of cone by "<a_i, x> >= 0" and the rational
485  * point "vec" by v/d.
486  * Let b_i = <a_i, v>.  Then the affine cone 'vec + cone' is given
487  * by <a_i, x> - b/d >= 0.
488  * The polyhedron <a_i, x> - ceil{b/d} >= 0 is a subset of this affine cone.
489  * We prefer this polyhedron over the actual affine cone because it doesn't
490  * require a scaling of the constraints.
491  * If each of the vertices of the unit cube positioned at x lies inside
492  * this polyhedron, then the whole unit cube at x lies inside the affine cone.
493  * We therefore impose that x' = x + \sum e_i, for any selection of unit
494  * vectors lies inside the polyhedron, i.e.,
495  *
496  *      <a_i, x'> - ceil{b/d} = <a_i, x> + sum a_i - ceil{b/d} >= 0
497  *
498  * The most stringent of these constraints is the one that selects
499  * all negative a_i, so the polyhedron we are looking for has constraints
500  *
501  *      <a_i, x> + sum_{a_i < 0} a_i - ceil{b/d} >= 0
502  *
503  * Note that if cone were known to have only non-negative rays
504  * (which can be accomplished by a unimodular transformation),
505  * then we would only have to check the points x' = x + e_i
506  * and we only have to add the smallest negative a_i (if any)
507  * instead of the sum of all negative a_i.
508  */
509 static struct isl_basic_set *shift_cone(struct isl_basic_set *cone,
510         struct isl_vec *vec)
511 {
512         int i, j, k;
513         unsigned total;
514
515         struct isl_basic_set *shift = NULL;
516
517         if (!cone || !vec)
518                 goto error;
519
520         isl_assert(cone->ctx, cone->n_eq == 0, goto error);
521
522         total = isl_basic_set_total_dim(cone);
523
524         shift = isl_basic_set_alloc_dim(isl_basic_set_get_dim(cone),
525                                         0, 0, cone->n_ineq);
526
527         for (i = 0; i < cone->n_ineq; ++i) {
528                 k = isl_basic_set_alloc_inequality(shift);
529                 if (k < 0)
530                         goto error;
531                 isl_seq_cpy(shift->ineq[k] + 1, cone->ineq[i] + 1, total);
532                 isl_seq_inner_product(shift->ineq[k] + 1, vec->el + 1, total,
533                                       &shift->ineq[k][0]);
534                 isl_int_cdiv_q(shift->ineq[k][0],
535                                shift->ineq[k][0], vec->el[0]);
536                 isl_int_neg(shift->ineq[k][0], shift->ineq[k][0]);
537                 for (j = 0; j < total; ++j) {
538                         if (isl_int_is_nonneg(shift->ineq[k][1 + j]))
539                                 continue;
540                         isl_int_add(shift->ineq[k][0],
541                                     shift->ineq[k][0], shift->ineq[k][1 + j]);
542                 }
543         }
544
545         isl_basic_set_free(cone);
546         isl_vec_free(vec);
547
548         return isl_basic_set_finalize(shift);
549 error:
550         isl_basic_set_free(shift);
551         isl_basic_set_free(cone);
552         isl_vec_free(vec);
553         return NULL;
554 }
555
556 /* Given a rational point vec in a (transformed) basic set,
557  * such that cone is the recession cone of the original basic set,
558  * "round up" the rational point to an integer point.
559  *
560  * We first check if the rational point just happens to be integer.
561  * If not, we transform the cone in the same way as the basic set,
562  * pick a point x in this cone shifted to the rational point such that
563  * the whole unit cube at x is also inside this affine cone.
564  * Then we simply round up the coordinates of x and return the
565  * resulting integer point.
566  */
567 static struct isl_vec *round_up_in_cone(struct isl_vec *vec,
568         struct isl_basic_set *cone, struct isl_mat *U)
569 {
570         unsigned total;
571
572         if (!vec || !cone || !U)
573                 goto error;
574
575         isl_assert(vec->ctx, vec->size != 0, goto error);
576         if (isl_int_is_one(vec->el[0])) {
577                 isl_mat_free(vec->ctx, U);
578                 isl_basic_set_free(cone);
579                 return vec;
580         }
581
582         total = isl_basic_set_total_dim(cone);
583         cone = isl_basic_set_preimage(cone, U);
584         cone = isl_basic_set_remove_dims(cone, 0, total - (vec->size - 1));
585
586         cone = shift_cone(cone, vec);
587
588         vec = rational_sample(cone);
589         vec = isl_vec_ceil(vec);
590         return vec;
591 error:
592         isl_mat_free(vec ? vec->ctx : cone ? cone->ctx : NULL, U);
593         isl_vec_free(vec);
594         isl_basic_set_free(cone);
595         return NULL;
596 }
597
598 /* Concatenate two integer vectors, i.e., two vectors with denominator
599  * (stored in element 0) equal to 1.
600  */
601 static struct isl_vec *vec_concat(struct isl_vec *vec1, struct isl_vec *vec2)
602 {
603         struct isl_vec *vec;
604
605         if (!vec1 || !vec2)
606                 goto error;
607         isl_assert(vec1->ctx, vec1->size > 0, goto error);
608         isl_assert(vec2->ctx, vec2->size > 0, goto error);
609         isl_assert(vec1->ctx, isl_int_is_one(vec1->el[0]), goto error);
610         isl_assert(vec2->ctx, isl_int_is_one(vec2->el[0]), goto error);
611
612         vec = isl_vec_alloc(vec1->ctx, vec1->size + vec2->size - 1);
613         if (!vec)
614                 goto error;
615
616         isl_seq_cpy(vec->el, vec1->el, vec1->size);
617         isl_seq_cpy(vec->el + vec1->size, vec2->el + 1, vec2->size - 1);
618
619         isl_vec_free(vec1);
620         isl_vec_free(vec2);
621
622         return vec;
623 error:
624         isl_vec_free(vec1);
625         isl_vec_free(vec2);
626         return NULL;
627 }
628
629 /* Drop all constraints in bset that involve any of the dimensions
630  * first to first+n-1.
631  */
632 static struct isl_basic_set *drop_constraints_involving
633         (struct isl_basic_set *bset, unsigned first, unsigned n)
634 {
635         int i;
636
637         if (!bset)
638                 return NULL;
639
640         bset = isl_basic_set_cow(bset);
641
642         for (i = bset->n_ineq - 1; i >= 0; --i) {
643                 if (isl_seq_first_non_zero(bset->ineq[i] + 1 + first, n) == -1)
644                         continue;
645                 isl_basic_set_drop_inequality(bset, i);
646         }
647
648         return bset;
649 }
650
651 /* Give a basic set "bset" with recession cone "cone", compute and
652  * return an integer point in bset, if any.
653  *
654  * If the recession cone is full-dimensional, then we know that
655  * bset contains an infinite number of integer points and it is
656  * fairly easy to pick one of them.
657  * If the recession cone is not full-dimensional, then we first
658  * transform bset such that the bounded directions appear as
659  * the first dimensions of the transformed basic set.
660  * We do this by using a unimodular transformation that transforms
661  * the equalities in the recession cone to equalities on the first
662  * dimensions.
663  *
664  * The transformed set is then projected onto its bounded dimensions.
665  * Note that to compute this projection, we can simply drop all constraints
666  * involving any of the unbounded dimensions since these constraints
667  * cannot be combined to produce a constraint on the bounded dimensions.
668  * To see this, assume that there is such a combination of constraints
669  * that produces a constraint on the bounded dimensions.  This means
670  * that some combination of the unbounded dimensions has both an upper
671  * bound and a lower bound in terms of the bounded dimensions, but then
672  * this combination would be a bounded direction too and would have been
673  * transformed into a bounded dimensions.
674  *
675  * We then compute a sample value in the bounded dimensions.
676  * If no such value can be found, then the original set did not contain
677  * any integer points and we are done.
678  * Otherwise, we plug in the value we found in the bounded dimensions,
679  * project out these bounded dimensions and end up with a set with
680  * a full-dimensional recession cone.
681  * A sample point in this set is computed by "rounding up" any
682  * rational point in the set.
683  *
684  * The sample points in the bounded and unbounded dimensions are
685  * then combined into a single sample point and transformed back
686  * to the original space.
687  */
688 static struct isl_vec *sample_with_cone(struct isl_basic_set *bset,
689         struct isl_basic_set *cone)
690 {
691         unsigned total;
692         unsigned cone_dim;
693         struct isl_mat *M, *U;
694         struct isl_vec *sample;
695         struct isl_vec *cone_sample;
696         struct isl_ctx *ctx;
697         struct isl_basic_set *bounded;
698
699         if (!bset || !cone)
700                 goto error;
701
702         ctx = bset->ctx;
703         total = isl_basic_set_total_dim(cone);
704         cone_dim = total - cone->n_eq;
705
706         M = isl_mat_sub_alloc(bset->ctx, cone->eq, 0, cone->n_eq, 1, total);
707         M = isl_mat_left_hermite(bset->ctx, M, 0, &U, NULL);
708         if (!M)
709                 goto error;
710         isl_mat_free(bset->ctx, M);
711
712         U = isl_mat_lin_to_aff(bset->ctx, U);
713         bset = isl_basic_set_preimage(bset, isl_mat_copy(bset->ctx, U));
714
715         bounded = isl_basic_set_copy(bset);
716         bounded = drop_constraints_involving(bounded, total - cone_dim, cone_dim);
717         bounded = isl_basic_set_drop_dims(bounded, total - cone_dim, cone_dim);
718         sample = sample_bounded(bounded);
719         if (!sample || sample->size == 0) {
720                 isl_basic_set_free(bset);
721                 isl_basic_set_free(cone);
722                 isl_mat_free(ctx, U);
723                 return sample;
724         }
725         bset = plug_in(bset, isl_vec_copy(sample));
726         cone_sample = rational_sample(bset);
727         cone_sample = round_up_in_cone(cone_sample, cone, isl_mat_copy(ctx, U));
728         sample = vec_concat(sample, cone_sample);
729         sample = isl_mat_vec_product(ctx, U, sample);
730         return sample;
731 error:
732         isl_basic_set_free(cone);
733         isl_basic_set_free(bset);
734         return NULL;
735 }
736
737 /* Compute and return a sample point in bset using generalized basis
738  * reduction.  We first check if the input set has a non-trivial
739  * recession cone.  If so, we perform some extra preprocessing in
740  * sample_with_cone.  Otherwise, we directly perform generalized basis
741  * reduction.
742  */
743 static struct isl_vec *gbr_sample_no_lineality(struct isl_basic_set *bset)
744 {
745         unsigned dim;
746         struct isl_basic_set *cone;
747
748         dim = isl_basic_set_total_dim(bset);
749
750         cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset));
751
752         if (cone->n_eq < dim)
753                 return sample_with_cone(bset, cone);
754
755         isl_basic_set_free(cone);
756         return sample_bounded(bset);
757 }
758
759 static struct isl_vec *sample_no_lineality(struct isl_basic_set *bset)
760 {
761         unsigned dim;
762
763         if (isl_basic_set_fast_is_empty(bset))
764                 return empty_sample(bset);
765         if (bset->n_eq > 0)
766                 return sample_eq(bset, sample_no_lineality);
767         dim = isl_basic_set_total_dim(bset);
768         if (dim == 0)
769                 return zero_sample(bset);
770         if (dim == 1)
771                 return interval_sample(bset);
772
773         switch (bset->ctx->ilp_solver) {
774         case ISL_ILP_PIP:
775                 return isl_pip_basic_set_sample(bset);
776         case ISL_ILP_GBR:
777                 return gbr_sample_no_lineality(bset);
778         }
779         isl_assert(bset->ctx, 0, );
780         isl_basic_set_free(bset);
781         return NULL;
782 }
783
784 /* Compute an integer point in "bset" with a lineality space that
785  * is orthogonal to the constraints in "bounds".
786  *
787  * We first perform a unimodular transformation on bset that
788  * make the constraints in bounds (and therefore all constraints in bset)
789  * only involve the first dimensions.  The remaining dimensions
790  * then do not appear in any constraints and we can select any value
791  * for them, say zero.  We therefore project out this final dimensions
792  * and plug in the value zero later.  This is accomplished by simply
793  * dropping the final columns of the unimodular transformation.
794  */
795 static struct isl_vec *sample_lineality(struct isl_basic_set *bset,
796         struct isl_mat *bounds)
797 {
798         struct isl_mat *U = NULL;
799         unsigned old_dim, new_dim;
800         struct isl_vec *sample;
801         struct isl_ctx *ctx;
802
803         if (!bset || !bounds)
804                 goto error;
805
806         ctx = bset->ctx;
807         old_dim = isl_basic_set_n_dim(bset);
808         new_dim = bounds->n_row;
809         bounds = isl_mat_left_hermite(ctx, bounds, 0, &U, NULL);
810         if (!bounds)
811                 goto error;
812         U = isl_mat_lin_to_aff(ctx, U);
813         U = isl_mat_drop_cols(ctx, U, 1 + new_dim, old_dim - new_dim);
814         bset = isl_basic_set_preimage(bset, isl_mat_copy(ctx, U));
815         if (!bset)
816                 goto error;
817         isl_mat_free(ctx, bounds);
818
819         sample = sample_no_lineality(bset);
820         if (sample && sample->size != 0)
821                 sample = isl_mat_vec_product(ctx, U, sample);
822         else
823                 isl_mat_free(ctx, U);
824         return sample;
825 error:
826         isl_mat_free(ctx, bounds);
827         isl_mat_free(ctx, U);
828         isl_basic_set_free(bset);
829         return NULL;
830 }
831
832 struct isl_vec *isl_basic_set_sample(struct isl_basic_set *bset)
833 {
834         struct isl_ctx *ctx;
835         struct isl_mat *bounds;
836         unsigned dim;
837         if (!bset)
838                 return NULL;
839
840         ctx = bset->ctx;
841         if (isl_basic_set_fast_is_empty(bset))
842                 return empty_sample(bset);
843
844         dim = isl_basic_set_n_dim(bset);
845         isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
846         isl_assert(ctx, bset->n_div == 0, goto error);
847
848         if (bset->sample && bset->sample->size == 1 + dim) {
849                 int contains = isl_basic_set_contains(bset, bset->sample);
850                 if (contains < 0)
851                         goto error;
852                 if (contains) {
853                         struct isl_vec *sample = isl_vec_copy(bset->sample);
854                         isl_basic_set_free(bset);
855                         return sample;
856                 }
857         }
858         isl_vec_free(bset->sample);
859         bset->sample = NULL;
860
861         if (bset->n_eq > 0)
862                 return sample_eq(bset, isl_basic_set_sample);
863         if (dim == 0)
864                 return zero_sample(bset);
865         if (dim == 1)
866                 return interval_sample(bset);
867         bounds = independent_bounds(ctx, bset);
868         if (!bounds)
869                 goto error;
870
871         if (bounds->n_row == 0) {
872                 isl_mat_free(ctx, bounds);
873                 return zero_sample(bset);
874         }
875         if (bounds->n_row < dim)
876                 return sample_lineality(bset, bounds);
877
878         isl_mat_free(ctx, bounds);
879         return sample_no_lineality(bset);
880 error:
881         isl_basic_set_free(bset);
882         return NULL;
883 }