isl_sample.c: interval_sample: drop redundant argument
[isl.git] / isl_sample.c
blobb4bca122bc4f12ee8d42544a557b7aac81cef8eb
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"
9 static struct isl_vec *empty_sample(struct isl_basic_set *bset)
11 struct isl_vec *vec;
13 vec = isl_vec_alloc(bset->ctx, 0);
14 isl_basic_set_free(bset);
15 return vec;
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)
24 unsigned dim;
25 struct isl_vec *sample;
27 dim = isl_basic_set_total_dim(bset);
28 sample = isl_vec_alloc(bset->ctx, 1 + dim);
29 if (sample) {
30 isl_int_set_si(sample->el[0], 1);
31 isl_seq_clr(sample->el + 1, dim);
33 isl_basic_set_free(bset);
34 return sample;
37 static struct isl_vec *interval_sample(struct isl_basic_set *bset)
39 int i;
40 isl_int t;
41 struct isl_vec *sample;
43 bset = isl_basic_set_simplify(bset);
44 if (!bset)
45 return NULL;
46 if (isl_basic_set_fast_is_empty(bset))
47 return empty_sample(bset);
48 if (bset->n_eq == 0 && bset->n_ineq == 0)
49 return zero_sample(bset);
51 sample = isl_vec_alloc(bset->ctx, 2);
52 isl_int_set_si(sample->block.data[0], 1);
54 if (bset->n_eq > 0) {
55 isl_assert(bset->ctx, bset->n_eq == 1, goto error);
56 isl_assert(bset->ctx, bset->n_ineq == 0, goto error);
57 if (isl_int_is_one(bset->eq[0][1]))
58 isl_int_neg(sample->el[1], bset->eq[0][0]);
59 else {
60 isl_assert(bset->ctx, isl_int_is_negone(bset->eq[0][1]),
61 goto error);
62 isl_int_set(sample->el[1], bset->eq[0][0]);
64 isl_basic_set_free(bset);
65 return sample;
68 isl_int_init(t);
69 if (isl_int_is_one(bset->ineq[0][1]))
70 isl_int_neg(sample->block.data[1], bset->ineq[0][0]);
71 else
72 isl_int_set(sample->block.data[1], bset->ineq[0][0]);
73 for (i = 1; i < bset->n_ineq; ++i) {
74 isl_seq_inner_product(sample->block.data,
75 bset->ineq[i], 2, &t);
76 if (isl_int_is_neg(t))
77 break;
79 isl_int_clear(t);
80 if (i < bset->n_ineq) {
81 isl_vec_free(sample);
82 return empty_sample(bset);
85 isl_basic_set_free(bset);
86 return sample;
87 error:
88 isl_basic_set_free(bset);
89 isl_vec_free(sample);
90 return NULL;
93 static struct isl_mat *independent_bounds(struct isl_ctx *ctx,
94 struct isl_basic_set *bset)
96 int i, j, n;
97 struct isl_mat *dirs = NULL;
98 unsigned dim;
100 if (!bset)
101 return NULL;
103 dim = isl_basic_set_n_dim(bset);
104 if (bset->n_ineq == 0)
105 return isl_mat_alloc(ctx, 0, dim);
107 dirs = isl_mat_alloc(ctx, dim, dim);
108 if (!dirs)
109 return NULL;
110 isl_seq_cpy(dirs->row[0], bset->ineq[0]+1, dirs->n_col);
111 for (j = 1, n = 1; n < dim && j < bset->n_ineq; ++j) {
112 int pos;
114 isl_seq_cpy(dirs->row[n], bset->ineq[j]+1, dirs->n_col);
116 pos = isl_seq_first_non_zero(dirs->row[n], dirs->n_col);
117 if (pos < 0)
118 continue;
119 for (i = 0; i < n; ++i) {
120 int pos_i;
121 pos_i = isl_seq_first_non_zero(dirs->row[i], dirs->n_col);
122 if (pos_i < pos)
123 continue;
124 if (pos_i > pos)
125 break;
126 isl_seq_elim(dirs->row[n], dirs->row[i], pos,
127 dirs->n_col, NULL);
128 pos = isl_seq_first_non_zero(dirs->row[n], dirs->n_col);
129 if (pos < 0)
130 break;
132 if (pos < 0)
133 continue;
134 if (i < n) {
135 int k;
136 isl_int *t = dirs->row[n];
137 for (k = n; k > i; --k)
138 dirs->row[k] = dirs->row[k-1];
139 dirs->row[i] = t;
141 ++n;
143 dirs->n_row = n;
144 return dirs;
147 /* Find a sample integer point, if any, in bset, which is known
148 * to have equalities. If bset contains no integer points, then
149 * return a zero-length vector.
150 * We simply remove the known equalities, compute a sample
151 * in the resulting bset, using the specified recurse function,
152 * and then transform the sample back to the original space.
154 static struct isl_vec *sample_eq(struct isl_basic_set *bset,
155 struct isl_vec *(*recurse)(struct isl_basic_set *))
157 struct isl_mat *T;
158 struct isl_vec *sample;
159 struct isl_ctx *ctx;
161 if (!bset)
162 return NULL;
164 ctx = bset->ctx;
165 bset = isl_basic_set_remove_equalities(bset, &T, NULL);
166 sample = recurse(bset);
167 if (!sample || sample->size == 0)
168 isl_mat_free(ctx, T);
169 else
170 sample = isl_mat_vec_product(ctx, T, sample);
171 return sample;
174 static struct isl_vec *sample_no_lineality(struct isl_basic_set *bset)
176 unsigned dim;
178 if (isl_basic_set_fast_is_empty(bset))
179 return empty_sample(bset);
180 if (bset->n_eq > 0)
181 return sample_eq(bset, sample_no_lineality);
182 dim = isl_basic_set_total_dim(bset);
183 if (dim == 0)
184 return zero_sample(bset);
185 if (dim == 1)
186 return interval_sample(bset);
188 return isl_pip_basic_set_sample(bset);
191 /* Compute an integer point in "bset" with a lineality space that
192 * is orthogonal to the constraints in "bounds".
194 * We first perform a unimodular transformation on bset that
195 * make the constraints in bounds (and therefore all constraints in bset)
196 * only involve the first dimensions. The remaining dimensions
197 * then do not appear in any constraints and we can select any value
198 * for them, say zero. We therefore project out this final dimensions
199 * and plug in the value zero later. This is accomplished by simply
200 * dropping the final columns of the unimodular transformation.
202 static struct isl_vec *sample_lineality(struct isl_basic_set *bset,
203 struct isl_mat *bounds)
205 struct isl_mat *U = NULL;
206 unsigned old_dim, new_dim;
207 struct isl_vec *sample;
208 struct isl_ctx *ctx;
210 if (!bset || !bounds)
211 goto error;
213 ctx = bset->ctx;
214 old_dim = isl_basic_set_n_dim(bset);
215 new_dim = bounds->n_row;
216 bounds = isl_mat_left_hermite(ctx, bounds, 0, &U, NULL);
217 if (!bounds)
218 goto error;
219 U = isl_mat_lin_to_aff(ctx, U);
220 U = isl_mat_drop_cols(ctx, U, 1 + new_dim, old_dim - new_dim);
221 bset = isl_basic_set_preimage(bset, isl_mat_copy(ctx, U));
222 if (!bset)
223 goto error;
224 isl_mat_free(ctx, bounds);
226 sample = sample_no_lineality(bset);
227 if (sample && sample->size != 0)
228 sample = isl_mat_vec_product(ctx, U, sample);
229 else
230 isl_mat_free(ctx, U);
231 return sample;
232 error:
233 isl_mat_free(ctx, bounds);
234 isl_mat_free(ctx, U);
235 isl_basic_set_free(bset);
236 return NULL;
239 struct isl_vec *isl_basic_set_sample(struct isl_basic_set *bset)
241 struct isl_ctx *ctx;
242 struct isl_mat *bounds;
243 unsigned dim;
244 if (!bset)
245 return NULL;
247 ctx = bset->ctx;
248 if (isl_basic_set_fast_is_empty(bset))
249 return empty_sample(bset);
251 dim = isl_basic_set_n_dim(bset);
252 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
253 isl_assert(ctx, bset->n_div == 0, goto error);
255 if (bset->n_eq > 0)
256 return sample_eq(bset, isl_basic_set_sample);
257 if (dim == 0)
258 return zero_sample(bset);
259 if (dim == 1)
260 return interval_sample(bset);
261 bounds = independent_bounds(ctx, bset);
262 if (!bounds)
263 goto error;
265 if (bounds->n_row == 0) {
266 isl_mat_free(ctx, bounds);
267 return zero_sample(bset);
269 if (bounds->n_row < dim)
270 return sample_lineality(bset, bounds);
272 isl_mat_free(ctx, bounds);
273 return sample_no_lineality(bset);
274 error:
275 isl_basic_set_free(bset);
276 return NULL;