1 #include "isl_sample.h"
2 #include "isl_sample_piplib.h"
6 #include "isl_map_private.h"
7 #include "isl_equalities.h"
9 static struct isl_vec *empty_sample(struct isl_basic_set *bset)
13 vec = isl_vec_alloc(bset->ctx, 0);
14 isl_basic_set_free(bset);
18 /* Construct a zero sample of the same dimension as bset.
19 * As a special case, if bset is zero-dimensional, this
20 * function creates a zero-dimensional sample point.
22 static struct isl_vec *zero_sample(struct isl_basic_set *bset)
25 struct isl_vec *sample;
27 dim = isl_basic_set_total_dim(bset);
28 sample = isl_vec_alloc(bset->ctx, 1 + dim);
30 isl_int_set_si(sample->el[0], 1);
31 isl_seq_clr(sample->el + 1, dim);
33 isl_basic_set_free(bset);
37 static struct isl_vec *interval_sample(struct isl_ctx *ctx,
38 struct isl_basic_set *bset)
42 struct isl_vec *sample;
44 bset = isl_basic_set_simplify(bset);
47 if (isl_basic_set_fast_is_empty(bset))
48 return empty_sample(bset);
49 if (bset->n_eq == 0 && bset->n_ineq == 0)
50 return zero_sample(bset);
52 sample = isl_vec_alloc(ctx, 2);
53 isl_int_set_si(sample->block.data[0], 1);
56 isl_assert(bset->ctx, bset->n_eq == 1, goto error);
57 isl_assert(bset->ctx, bset->n_ineq == 0, goto error);
58 if (isl_int_is_one(bset->eq[0][1]))
59 isl_int_neg(sample->el[1], bset->eq[0][0]);
61 isl_assert(bset->ctx, isl_int_is_negone(bset->eq[0][1]),
63 isl_int_set(sample->el[1], bset->eq[0][0]);
65 isl_basic_set_free(bset);
70 if (isl_int_is_one(bset->ineq[0][1]))
71 isl_int_neg(sample->block.data[1], bset->ineq[0][0]);
73 isl_int_set(sample->block.data[1], bset->ineq[0][0]);
74 for (i = 1; i < bset->n_ineq; ++i) {
75 isl_seq_inner_product(sample->block.data,
76 bset->ineq[i], 2, &t);
77 if (isl_int_is_neg(t))
81 if (i < bset->n_ineq) {
83 return empty_sample(bset);
86 isl_basic_set_free(bset);
89 isl_basic_set_free(bset);
94 static struct isl_mat *independent_bounds(struct isl_ctx *ctx,
95 struct isl_basic_set *bset)
98 struct isl_mat *dirs = NULL;
104 dim = isl_basic_set_n_dim(bset);
105 if (bset->n_ineq == 0)
106 return isl_mat_alloc(ctx, 0, dim);
108 dirs = isl_mat_alloc(ctx, dim, dim);
111 isl_seq_cpy(dirs->row[0], bset->ineq[0]+1, dirs->n_col);
112 for (j = 1, n = 1; n < dim && j < bset->n_ineq; ++j) {
115 isl_seq_cpy(dirs->row[n], bset->ineq[j]+1, dirs->n_col);
117 pos = isl_seq_first_non_zero(dirs->row[n], dirs->n_col);
120 for (i = 0; i < n; ++i) {
122 pos_i = isl_seq_first_non_zero(dirs->row[i], dirs->n_col);
127 isl_seq_elim(dirs->row[n], dirs->row[i], pos,
129 pos = isl_seq_first_non_zero(dirs->row[n], dirs->n_col);
137 isl_int *t = dirs->row[n];
138 for (k = n; k > i; --k)
139 dirs->row[k] = dirs->row[k-1];
148 /* Find a sample integer point, if any, in bset, which is known
149 * to have equalities. If bset contains no integer points, then
150 * return a zero-length vector.
151 * We simply remove the known equalities, compute a sample
152 * in the resulting bset, using the specified recurse function,
153 * and then transform the sample back to the original space.
155 static struct isl_vec *sample_eq(struct isl_basic_set *bset,
156 struct isl_vec *(*recurse)(struct isl_basic_set *))
159 struct isl_vec *sample;
166 bset = isl_basic_set_remove_equalities(bset, &T, NULL);
167 sample = recurse(bset);
168 if (!sample || sample->size == 0)
169 isl_mat_free(ctx, T);
171 sample = isl_mat_vec_product(ctx, T, sample);
175 static struct isl_vec *sample_no_lineality(struct isl_basic_set *bset)
179 if (isl_basic_set_fast_is_empty(bset))
180 return empty_sample(bset);
182 return sample_eq(bset, sample_no_lineality);
183 dim = isl_basic_set_total_dim(bset);
185 return zero_sample(bset);
187 return interval_sample(bset->ctx, bset);
189 return isl_pip_basic_set_sample(bset);
192 /* Compute an integer point in "bset" with a lineality space that
193 * is orthogonal to the constraints in "bounds".
195 * We first perform a unimodular transformation on bset that
196 * make the constraints in bounds (and therefore all constraints in bset)
197 * only involve the first dimensions. The remaining dimensions
198 * then do not appear in any constraints and we can select any value
199 * for them, say zero. We therefore project out this final dimensions
200 * and plug in the value zero later. This is accomplished by simply
201 * dropping the final columns of the unimodular transformation.
203 static struct isl_vec *sample_lineality(struct isl_basic_set *bset,
204 struct isl_mat *bounds)
206 struct isl_mat *U = NULL;
207 unsigned old_dim, new_dim;
208 struct isl_vec *sample;
211 if (!bset || !bounds)
215 old_dim = isl_basic_set_n_dim(bset);
216 new_dim = bounds->n_row;
217 bounds = isl_mat_left_hermite(ctx, bounds, 0, &U, NULL);
220 U = isl_mat_lin_to_aff(ctx, U);
221 U = isl_mat_drop_cols(ctx, U, 1 + new_dim, old_dim - new_dim);
222 bset = isl_basic_set_preimage(bset, isl_mat_copy(ctx, U));
225 isl_mat_free(ctx, bounds);
227 sample = sample_no_lineality(bset);
228 if (sample && sample->size != 0)
229 sample = isl_mat_vec_product(ctx, U, sample);
231 isl_mat_free(ctx, U);
234 isl_mat_free(ctx, bounds);
235 isl_mat_free(ctx, U);
236 isl_basic_set_free(bset);
240 struct isl_vec *isl_basic_set_sample(struct isl_basic_set *bset)
243 struct isl_mat *bounds;
249 if (isl_basic_set_fast_is_empty(bset))
250 return empty_sample(bset);
252 dim = isl_basic_set_n_dim(bset);
253 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
254 isl_assert(ctx, bset->n_div == 0, goto error);
257 return sample_eq(bset, isl_basic_set_sample);
259 return zero_sample(bset);
261 return interval_sample(ctx, bset);
262 bounds = independent_bounds(ctx, bset);
266 if (bounds->n_row == 0) {
267 isl_mat_free(ctx, bounds);
268 return zero_sample(bset);
270 if (bounds->n_row < dim)
271 return sample_lineality(bset, bounds);
273 isl_mat_free(ctx, bounds);
274 return sample_no_lineality(bset);
276 isl_basic_set_free(bset);