6 #include "isl_map_private.h"
7 #include "isl_equalities.h"
8 #include "isl_sample.h"
10 struct isl_basic_map *isl_basic_map_implicit_equalities(
11 struct isl_basic_map *bmap)
20 if (F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
22 if (F_ISSET(bmap, ISL_BASIC_MAP_NO_IMPLICIT))
27 for (i = 0; i < bmap->n_ineq; ++i) {
28 enum isl_lp_result res;
29 res = isl_solve_lp(bmap, 1, bmap->ineq[i]+1, ctx->one, &opt, NULL);
30 if (res == isl_lp_unbounded)
32 if (res == isl_lp_error)
34 if (res == isl_lp_empty) {
35 bmap = isl_basic_map_set_to_empty(bmap);
38 isl_int_add(opt, opt, bmap->ineq[i][0]);
39 if (isl_int_is_zero(opt)) {
40 isl_basic_map_inequality_to_equality(bmap, i);
46 F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
50 isl_basic_map_free(bmap);
54 /* Make eq[row][col] of both bmaps equal so we can add the row
55 * add the column to the common matrix.
56 * Note that because of the echelon form, the columns of row row
57 * after column col are zero.
59 static void set_common_multiple(
60 struct isl_basic_set *bset1, struct isl_basic_set *bset2,
61 unsigned row, unsigned col)
65 if (isl_int_eq(bset1->eq[row][col], bset2->eq[row][col]))
70 isl_int_lcm(m, bset1->eq[row][col], bset2->eq[row][col]);
71 isl_int_divexact(c, m, bset1->eq[row][col]);
72 isl_seq_scale(bset1->eq[row], bset1->eq[row], c, col+1);
73 isl_int_divexact(c, m, bset2->eq[row][col]);
74 isl_seq_scale(bset2->eq[row], bset2->eq[row], c, col+1);
79 /* Delete a given equality, moving all the following equalities one up.
81 static void delete_row(struct isl_basic_set *bset, unsigned row)
88 for (r = row; r < bset->n_eq; ++r)
89 bset->eq[r] = bset->eq[r+1];
90 bset->eq[bset->n_eq] = t;
93 /* Make first row entries in column col of bset1 identical to
94 * those of bset2, using the fact that entry bset1->eq[row][col]=a
95 * is non-zero. Initially, these elements of bset1 are all zero.
96 * For each row i < row, we set
97 * A[i] = a * A[i] + B[i][col] * A[row]
100 * A[i][col] = B[i][col] = a * old(B[i][col])
102 static void construct_column(
103 struct isl_basic_set *bset1, struct isl_basic_set *bset2,
104 unsigned row, unsigned col)
113 total = 1 + bset1->dim;
114 for (r = 0; r < row; ++r) {
115 if (isl_int_is_zero(bset2->eq[r][col]))
117 isl_int_gcd(b, bset2->eq[r][col], bset1->eq[row][col]);
118 isl_int_divexact(a, bset1->eq[row][col], b);
119 isl_int_divexact(b, bset2->eq[r][col], b);
120 isl_seq_combine(bset1->eq[r], a, bset1->eq[r],
121 b, bset1->eq[row], total);
122 isl_seq_scale(bset2->eq[r], bset2->eq[r], a, total);
126 delete_row(bset1, row);
129 /* Make first row entries in column col of bset1 identical to
130 * those of bset2, using only these entries of the two matrices.
131 * Let t be the last row with different entries.
132 * For each row i < t, we set
133 * A[i] = (A[t][col]-B[t][col]) * A[i] + (B[i][col]-A[i][col) * A[t]
134 * B[i] = (A[t][col]-B[t][col]) * B[i] + (B[i][col]-A[i][col) * B[t]
136 * A[i][col] = B[i][col] = old(A[t][col]*B[i][col]-A[i][col]*B[t][col])
138 static int transform_column(
139 struct isl_basic_set *bset1, struct isl_basic_set *bset2,
140 unsigned row, unsigned col)
146 for (t = row-1; t >= 0; --t)
147 if (isl_int_ne(bset1->eq[t][col], bset2->eq[t][col]))
152 total = 1 + bset1->dim;
156 isl_int_sub(b, bset1->eq[t][col], bset2->eq[t][col]);
157 for (i = 0; i < t; ++i) {
158 isl_int_sub(a, bset2->eq[i][col], bset1->eq[i][col]);
159 isl_int_gcd(g, a, b);
160 isl_int_divexact(a, a, g);
161 isl_int_divexact(g, b, g);
162 isl_seq_combine(bset1->eq[i], g, bset1->eq[i], a, bset1->eq[t],
164 isl_seq_combine(bset2->eq[i], g, bset2->eq[i], a, bset2->eq[t],
170 delete_row(bset1, t);
171 delete_row(bset2, t);
175 /* The implementation is based on Section 5.2 of Michael Karr,
176 * "Affine Relationships Among Variables of a Program",
177 * except that the echelon form we use starts from the last column
178 * and that we are dealing with integer coefficients.
180 static struct isl_basic_set *affine_hull(
181 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
187 total = 1 + bset1->dim;
190 for (col = total-1; col >= 0; --col) {
191 int is_zero1 = row >= bset1->n_eq ||
192 isl_int_is_zero(bset1->eq[row][col]);
193 int is_zero2 = row >= bset2->n_eq ||
194 isl_int_is_zero(bset2->eq[row][col]);
195 if (!is_zero1 && !is_zero2) {
196 set_common_multiple(bset1, bset2, row, col);
198 } else if (!is_zero1 && is_zero2) {
199 construct_column(bset1, bset2, row, col);
200 } else if (is_zero1 && !is_zero2) {
201 construct_column(bset2, bset1, row, col);
203 if (transform_column(bset1, bset2, row, col))
207 isl_basic_set_free(bset2);
208 isl_assert(ctx, row == bset1->n_eq, goto error);
211 isl_basic_set_free(bset1);
215 static struct isl_basic_set *isl_basic_set_from_vec(struct isl_ctx *ctx,
220 struct isl_basic_set *bset = NULL;
224 isl_assert(ctx, vec->size != 0, goto error);
226 bset = isl_basic_set_alloc(ctx, 0, vec->size - 1, 0, vec->size - 1, 0);
227 for (i = bset->dim - 1; i >= 0; --i) {
228 k = isl_basic_set_alloc_equality(bset);
231 isl_seq_clr(bset->eq[k], 1 + bset->dim);
232 isl_int_neg(bset->eq[k][0], vec->block.data[1 + i]);
233 isl_int_set(bset->eq[k][1 + i], vec->block.data[0]);
235 isl_vec_free(ctx, vec);
239 isl_basic_set_free(bset);
240 isl_vec_free(ctx, vec);
244 static struct isl_basic_set *outside_point(struct isl_ctx *ctx,
245 struct isl_basic_set *bset, isl_int *eq, int up)
247 struct isl_basic_set *slice = NULL;
248 struct isl_vec *sample;
249 struct isl_basic_set *point;
252 slice = isl_basic_set_copy(bset);
255 slice = isl_basic_set_extend(slice, 0, slice->dim, 0, 1, 0);
256 k = isl_basic_set_alloc_equality(slice);
259 isl_seq_cpy(slice->eq[k], eq, 1 + slice->dim);
261 isl_int_add_ui(slice->eq[k][0], slice->eq[k][0], 1);
263 isl_int_sub_ui(slice->eq[k][0], slice->eq[k][0], 1);
265 sample = isl_basic_set_sample(slice);
268 if (sample->size == 0) {
269 isl_vec_free(ctx, sample);
270 point = isl_basic_set_empty(ctx, 0, bset->dim);
272 point = isl_basic_set_from_vec(ctx, sample);
276 isl_basic_set_free(slice);
280 /* After computing the rational affine hull (by detecting the implicit
281 * equalities), we remove all equalities found so far, compute
282 * the integer affine hull of what is left, and then add the original
283 * equalities back in.
285 * The integer affine hull is constructed by successively looking
286 * a point that is affinely independent of the points found so far.
287 * In particular, for each equality satisfied by the points so far,
288 * we check if there is any point on the corresponding hyperplane
289 * shifted by one (in either direction).
291 struct isl_basic_map *isl_basic_map_affine_hull(struct isl_basic_map *bmap)
294 struct isl_mat *T2 = NULL;
295 struct isl_basic_set *bset = NULL;
296 struct isl_basic_set *hull = NULL;
297 struct isl_vec *sample;
300 bmap = isl_basic_map_implicit_equalities(bmap);
304 if (bmap->n_ineq == 0)
307 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
308 bset = isl_basic_set_remove_equalities(bset, NULL, &T2);
310 sample = isl_basic_set_sample(isl_basic_set_copy(bset));
311 hull = isl_basic_set_from_vec(ctx, sample);
313 for (i = 0; i < bset->dim; ++i) {
314 struct isl_basic_set *point;
315 for (j = 0; j < hull->n_eq; ++j) {
316 point = outside_point(ctx, bset, hull->eq[j], 1);
319 if (!F_ISSET(point, ISL_BASIC_SET_EMPTY))
321 isl_basic_set_free(point);
322 point = outside_point(ctx, bset, hull->eq[j], 0);
325 if (!F_ISSET(point, ISL_BASIC_SET_EMPTY))
327 isl_basic_set_free(point);
331 hull = affine_hull(hull, point);
334 isl_basic_set_free(bset);
336 bmap = isl_basic_map_cow(bmap);
339 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
341 hull = isl_basic_set_preimage(ctx, hull, T2);
342 bmap = isl_basic_map_intersect(bmap,
343 isl_basic_map_overlying_set(hull,
344 isl_basic_map_copy(bmap)));
346 return isl_basic_map_finalize(bmap);
348 isl_mat_free(ctx, T2);
349 isl_basic_set_free(bset);
350 isl_basic_set_free(hull);
351 isl_basic_map_free(bmap);
355 struct isl_basic_set *isl_basic_set_affine_hull(struct isl_basic_set *bset)
357 return (struct isl_basic_set *)
358 isl_basic_map_affine_hull((struct isl_basic_map *)bset);
361 struct isl_basic_map *isl_map_affine_hull(struct isl_map *map)
364 struct isl_basic_map *model = NULL;
365 struct isl_basic_map *hull = NULL;
372 hull = isl_basic_map_empty(map->ctx,
373 map->nparam, map->n_in, map->n_out);
378 map = isl_map_align_divs(map);
379 model = isl_basic_map_copy(map->p[0]);
380 set = isl_map_underlying_set(map);
381 set = isl_set_cow(set);
385 for (i = 0; i < set->n; ++i) {
386 set->p[i] = isl_basic_set_cow(set->p[i]);
387 set->p[i] = isl_basic_set_affine_hull(set->p[i]);
388 set->p[i] = isl_basic_set_gauss(set->p[i], NULL);
392 set = isl_set_remove_empty_parts(set);
394 hull = isl_basic_map_empty(set->ctx,
395 model->nparam, model->n_in, model->n_out);
396 isl_basic_map_free(model);
398 struct isl_basic_set *bset;
400 set->p[0] = affine_hull(set->p[0], set->p[--set->n]);
404 bset = isl_basic_set_copy(set->p[0]);
405 hull = isl_basic_map_overlying_set(bset, model);
408 hull = isl_basic_map_simplify(hull);
409 return isl_basic_map_finalize(hull);
411 isl_basic_map_free(model);
416 struct isl_basic_set *isl_set_affine_hull(struct isl_set *set)
418 return (struct isl_basic_set *)
419 isl_map_affine_hull((struct isl_map *)set);