isl_solve_lp: accept affine object function instead of linear function
[isl.git] / isl_map_simplify.c
blob1fdb88fb18b13794ed89bd3afa32b7e675733cb5
1 #include "isl_equalities.h"
2 #include "isl_map.h"
3 #include "isl_map_private.h"
5 static void swap_equality(struct isl_basic_map *bmap, int a, int b)
7 isl_int *t = bmap->eq[a];
8 bmap->eq[a] = bmap->eq[b];
9 bmap->eq[b] = t;
12 static void swap_inequality(struct isl_basic_map *bmap, int a, int b)
14 if (a != b) {
15 isl_int *t = bmap->ineq[a];
16 bmap->ineq[a] = bmap->ineq[b];
17 bmap->ineq[b] = t;
21 static void set_swap_inequality(struct isl_basic_set *bset, int a, int b)
23 swap_inequality((struct isl_basic_map *)bset, a, b);
26 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
28 isl_seq_cpy(c, c + n, rem);
29 isl_seq_clr(c + rem, n);
32 /* Drop n dimensions starting at first.
34 * In principle, this frees up some extra variables as the number
35 * of columns remains constant, but we would have to extend
36 * the div array too as the number of rows in this array is assumed
37 * to be equal to extra.
39 struct isl_basic_set *isl_basic_set_drop_dims(
40 struct isl_basic_set *bset, unsigned first, unsigned n)
42 int i;
44 if (!bset)
45 goto error;
47 isl_assert(bset->ctx, first + n <= bset->dim->n_out, goto error);
49 if (n == 0)
50 return bset;
52 bset = isl_basic_set_cow(bset);
53 if (!bset)
54 return NULL;
56 for (i = 0; i < bset->n_eq; ++i)
57 constraint_drop_vars(bset->eq[i]+1+bset->dim->nparam+first, n,
58 (bset->dim->n_out-first-n)+bset->extra);
60 for (i = 0; i < bset->n_ineq; ++i)
61 constraint_drop_vars(bset->ineq[i]+1+bset->dim->nparam+first, n,
62 (bset->dim->n_out-first-n)+bset->extra);
64 for (i = 0; i < bset->n_div; ++i)
65 constraint_drop_vars(bset->div[i]+1+1+bset->dim->nparam+first, n,
66 (bset->dim->n_out-first-n)+bset->extra);
68 bset->dim = isl_dim_drop_outputs(bset->dim, first, n);
69 if (!bset->dim)
70 goto error;
72 ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
73 bset = isl_basic_set_simplify(bset);
74 return isl_basic_set_finalize(bset);
75 error:
76 isl_basic_set_free(bset);
77 return NULL;
80 struct isl_set *isl_set_drop_dims(
81 struct isl_set *set, unsigned first, unsigned n)
83 int i;
85 if (!set)
86 goto error;
88 isl_assert(set->ctx, first + n <= set->dim->n_out, goto error);
90 if (n == 0)
91 return set;
92 set = isl_set_cow(set);
93 if (!set)
94 goto error;
95 set->dim = isl_dim_drop_outputs(set->dim, first, n);
96 if (!set->dim)
97 goto error;
99 for (i = 0; i < set->n; ++i) {
100 set->p[i] = isl_basic_set_drop_dims(set->p[i], first, n);
101 if (!set->p[i])
102 goto error;
105 ISL_F_CLR(set, ISL_SET_NORMALIZED);
106 return set;
107 error:
108 isl_set_free(set);
109 return NULL;
112 /* Drop n input dimensions starting at first.
114 * In principle, this frees up some extra variables as the number
115 * of columns remains constant, but we would have to extend
116 * the div array too as the number of rows in this array is assumed
117 * to be equal to extra.
119 struct isl_basic_map *isl_basic_map_drop(struct isl_basic_map *bmap,
120 enum isl_dim_type type, unsigned first, unsigned n)
122 int i;
123 unsigned dim;
124 unsigned offset;
125 unsigned left;
127 if (!bmap)
128 goto error;
130 dim = isl_basic_map_dim(bmap, type);
131 isl_assert(bmap->ctx, first + n <= dim, goto error);
133 if (n == 0)
134 return bmap;
136 bmap = isl_basic_map_cow(bmap);
137 if (!bmap)
138 return NULL;
140 offset = isl_basic_map_offset(bmap, type) + first;
141 left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
142 for (i = 0; i < bmap->n_eq; ++i)
143 constraint_drop_vars(bmap->eq[i]+offset, n, left);
145 for (i = 0; i < bmap->n_ineq; ++i)
146 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
148 for (i = 0; i < bmap->n_div; ++i)
149 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
151 bmap->dim = isl_dim_drop(bmap->dim, type, first, n);
152 if (!bmap->dim)
153 goto error;
155 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
156 bmap = isl_basic_map_simplify(bmap);
157 return isl_basic_map_finalize(bmap);
158 error:
159 isl_basic_map_free(bmap);
160 return NULL;
163 struct isl_basic_map *isl_basic_map_drop_inputs(
164 struct isl_basic_map *bmap, unsigned first, unsigned n)
166 return isl_basic_map_drop(bmap, isl_dim_in, first, n);
169 struct isl_map *isl_map_drop(struct isl_map *map,
170 enum isl_dim_type type, unsigned first, unsigned n)
172 int i;
174 if (!map)
175 goto error;
177 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
179 if (n == 0)
180 return map;
181 map = isl_map_cow(map);
182 if (!map)
183 goto error;
184 map->dim = isl_dim_drop(map->dim, type, first, n);
185 if (!map->dim)
186 goto error;
188 for (i = 0; i < map->n; ++i) {
189 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
190 if (!map->p[i])
191 goto error;
193 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
195 return map;
196 error:
197 isl_map_free(map);
198 return NULL;
201 struct isl_map *isl_map_drop_inputs(
202 struct isl_map *map, unsigned first, unsigned n)
204 return isl_map_drop(map, isl_dim_in, first, n);
208 * We don't cow, as the div is assumed to be redundant.
210 static struct isl_basic_map *isl_basic_map_drop_div(
211 struct isl_basic_map *bmap, unsigned div)
213 int i;
214 unsigned pos;
216 if (!bmap)
217 goto error;
219 pos = 1 + isl_dim_total(bmap->dim) + div;
221 isl_assert(bmap->ctx, div < bmap->n_div, goto error);
223 for (i = 0; i < bmap->n_eq; ++i)
224 constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
226 for (i = 0; i < bmap->n_ineq; ++i) {
227 if (!isl_int_is_zero(bmap->ineq[i][pos])) {
228 isl_basic_map_drop_inequality(bmap, i);
229 --i;
230 continue;
232 constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
235 for (i = 0; i < bmap->n_div; ++i)
236 constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
238 if (div != bmap->n_div - 1) {
239 int j;
240 isl_int *t = bmap->div[div];
242 for (j = div; j < bmap->n_div - 1; ++j)
243 bmap->div[j] = bmap->div[j+1];
245 bmap->div[bmap->n_div - 1] = t;
247 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
248 isl_basic_map_free_div(bmap, 1);
250 return bmap;
251 error:
252 isl_basic_map_free(bmap);
253 return NULL;
256 struct isl_basic_map *isl_basic_map_normalize_constraints(
257 struct isl_basic_map *bmap)
259 int i;
260 isl_int gcd;
261 unsigned total = isl_basic_map_total_dim(bmap);
263 isl_int_init(gcd);
264 for (i = bmap->n_eq - 1; i >= 0; --i) {
265 isl_seq_gcd(bmap->eq[i]+1, total, &gcd);
266 if (isl_int_is_zero(gcd)) {
267 if (!isl_int_is_zero(bmap->eq[i][0])) {
268 bmap = isl_basic_map_set_to_empty(bmap);
269 break;
271 isl_basic_map_drop_equality(bmap, i);
272 continue;
274 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
275 isl_int_gcd(gcd, gcd, bmap->eq[i][0]);
276 if (isl_int_is_one(gcd))
277 continue;
278 if (!isl_int_is_divisible_by(bmap->eq[i][0], gcd)) {
279 bmap = isl_basic_map_set_to_empty(bmap);
280 break;
282 isl_seq_scale_down(bmap->eq[i], bmap->eq[i], gcd, 1+total);
285 for (i = bmap->n_ineq - 1; i >= 0; --i) {
286 isl_seq_gcd(bmap->ineq[i]+1, total, &gcd);
287 if (isl_int_is_zero(gcd)) {
288 if (isl_int_is_neg(bmap->ineq[i][0])) {
289 bmap = isl_basic_map_set_to_empty(bmap);
290 break;
292 isl_basic_map_drop_inequality(bmap, i);
293 continue;
295 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
296 isl_int_gcd(gcd, gcd, bmap->ineq[i][0]);
297 if (isl_int_is_one(gcd))
298 continue;
299 isl_int_fdiv_q(bmap->ineq[i][0], bmap->ineq[i][0], gcd);
300 isl_seq_scale_down(bmap->ineq[i]+1, bmap->ineq[i]+1, gcd, total);
302 isl_int_clear(gcd);
304 return bmap;
307 struct isl_basic_set *isl_basic_set_normalize_constraints(
308 struct isl_basic_set *bset)
310 (struct isl_basic_set *)isl_basic_map_normalize_constraints(
311 (struct isl_basic_map *)bset);
314 static void eliminate_div(struct isl_basic_map *bmap, isl_int *eq, unsigned div)
316 int i;
317 unsigned pos = 1 + isl_dim_total(bmap->dim) + div;
318 unsigned len;
319 len = 1 + isl_basic_map_total_dim(bmap);
321 for (i = 0; i < bmap->n_eq; ++i)
322 if (bmap->eq[i] != eq)
323 isl_seq_elim(bmap->eq[i], eq, pos, len, NULL);
325 for (i = 0; i < bmap->n_ineq; ++i)
326 isl_seq_elim(bmap->ineq[i], eq, pos, len, NULL);
328 /* We need to be careful about circular definitions,
329 * so for now we just remove the definitions of other divs that
330 * depend on this div and (possibly) recompute them later.
332 for (i = 0; i < bmap->n_div; ++i)
333 if (!isl_int_is_zero(bmap->div[i][0]) &&
334 !isl_int_is_zero(bmap->div[i][1 + pos]))
335 isl_seq_clr(bmap->div[i], 1 + len);
337 isl_basic_map_drop_div(bmap, div);
340 /* Elimininate divs based on equalities
342 static struct isl_basic_map *eliminate_divs_eq(
343 struct isl_basic_map *bmap, int *progress)
345 int d;
346 int i;
347 int modified = 0;
348 unsigned off;
350 if (!bmap)
351 return NULL;
353 off = 1 + isl_dim_total(bmap->dim);
355 for (d = bmap->n_div - 1; d >= 0 ; --d) {
356 for (i = 0; i < bmap->n_eq; ++i) {
357 if (!isl_int_is_one(bmap->eq[i][off + d]) &&
358 !isl_int_is_negone(bmap->eq[i][off + d]))
359 continue;
360 modified = 1;
361 *progress = 1;
362 eliminate_div(bmap, bmap->eq[i], d);
363 isl_basic_map_drop_equality(bmap, i);
364 break;
367 if (modified)
368 return eliminate_divs_eq(bmap, progress);
369 return bmap;
372 /* Elimininate divs based on inequalities
374 static struct isl_basic_map *eliminate_divs_ineq(
375 struct isl_basic_map *bmap, int *progress)
377 int d;
378 int i;
379 unsigned off;
380 struct isl_ctx *ctx;
382 if (!bmap)
383 return NULL;
385 ctx = bmap->ctx;
386 off = 1 + isl_dim_total(bmap->dim);
388 for (d = bmap->n_div - 1; d >= 0 ; --d) {
389 for (i = 0; i < bmap->n_eq; ++i)
390 if (!isl_int_is_zero(bmap->eq[i][off + d]))
391 break;
392 if (i < bmap->n_eq)
393 continue;
394 for (i = 0; i < bmap->n_ineq; ++i)
395 if (isl_int_abs_gt(bmap->ineq[i][off + d], ctx->one))
396 break;
397 if (i < bmap->n_ineq)
398 continue;
399 *progress = 1;
400 bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1);
401 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
402 break;
403 bmap = isl_basic_map_drop_div(bmap, d);
404 if (!bmap)
405 break;
407 return bmap;
410 static void eliminate_var_using_equality(struct isl_basic_map *bmap,
411 unsigned pos, isl_int *eq, int *progress)
413 unsigned total;
414 int k;
415 int contains_divs;
417 total = isl_basic_map_total_dim(bmap);
418 contains_divs =
419 isl_seq_first_non_zero(eq + 1 + isl_dim_total(bmap->dim),
420 bmap->n_div) != -1;
421 for (k = 0; k < bmap->n_eq; ++k) {
422 if (bmap->eq[k] == eq)
423 continue;
424 if (isl_int_is_zero(bmap->eq[k][1+pos]))
425 continue;
426 if (progress)
427 *progress = 1;
428 isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL);
431 for (k = 0; k < bmap->n_ineq; ++k) {
432 if (isl_int_is_zero(bmap->ineq[k][1+pos]))
433 continue;
434 if (progress)
435 *progress = 1;
436 isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL);
437 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
440 for (k = 0; k < bmap->n_div; ++k) {
441 if (isl_int_is_zero(bmap->div[k][0]))
442 continue;
443 if (isl_int_is_zero(bmap->div[k][1+1+pos]))
444 continue;
445 if (progress)
446 *progress = 1;
447 /* We need to be careful about circular definitions,
448 * so for now we just remove the definition of div k
449 * if the equality contains any divs.
451 if (contains_divs)
452 isl_seq_clr(bmap->div[k], 1 + total);
453 else
454 isl_seq_elim(bmap->div[k]+1, eq,
455 1+pos, 1+total, &bmap->div[k][0]);
456 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
460 struct isl_basic_map *isl_basic_map_gauss(
461 struct isl_basic_map *bmap, int *progress)
463 int k;
464 int done;
465 int last_var;
466 unsigned total_var;
467 unsigned total;
469 if (!bmap)
470 return NULL;
472 total = isl_basic_map_total_dim(bmap);
473 total_var = total - bmap->n_div;
475 last_var = total - 1;
476 for (done = 0; done < bmap->n_eq; ++done) {
477 for (; last_var >= 0; --last_var) {
478 for (k = done; k < bmap->n_eq; ++k)
479 if (!isl_int_is_zero(bmap->eq[k][1+last_var]))
480 break;
481 if (k < bmap->n_eq)
482 break;
484 if (last_var < 0)
485 break;
486 if (k != done)
487 swap_equality(bmap, k, done);
488 if (isl_int_is_neg(bmap->eq[done][1+last_var]))
489 isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total);
491 eliminate_var_using_equality(bmap, last_var, bmap->eq[done],
492 progress);
494 if (last_var >= total_var &&
495 isl_int_is_zero(bmap->div[last_var - total_var][0])) {
496 unsigned div = last_var - total_var;
497 isl_seq_neg(bmap->div[div]+1, bmap->eq[done], 1+total);
498 isl_int_set_si(bmap->div[div][1+1+last_var], 0);
499 isl_int_set(bmap->div[div][0],
500 bmap->eq[done][1+last_var]);
501 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
504 if (done == bmap->n_eq)
505 return bmap;
506 for (k = done; k < bmap->n_eq; ++k) {
507 if (isl_int_is_zero(bmap->eq[k][0]))
508 continue;
509 return isl_basic_map_set_to_empty(bmap);
511 isl_basic_map_free_equality(bmap, bmap->n_eq-done);
512 return bmap;
515 struct isl_basic_set *isl_basic_set_gauss(
516 struct isl_basic_set *bset, int *progress)
518 return (struct isl_basic_set*)isl_basic_map_gauss(
519 (struct isl_basic_map *)bset, progress);
523 static unsigned int round_up(unsigned int v)
525 int old_v = v;
527 while (v) {
528 old_v = v;
529 v ^= v & -v;
531 return old_v << 1;
534 static int hash_index(isl_int ***index, unsigned int size, int bits,
535 struct isl_basic_map *bmap, int k)
537 int h;
538 unsigned total = isl_basic_map_total_dim(bmap);
539 uint32_t hash = isl_seq_get_hash_bits(bmap->ineq[k]+1, total, bits);
540 for (h = hash; index[h]; h = (h+1) % size)
541 if (&bmap->ineq[k] != index[h] &&
542 isl_seq_eq(bmap->ineq[k]+1, index[h][0]+1, total))
543 break;
544 return h;
547 static int set_hash_index(isl_int ***index, unsigned int size, int bits,
548 struct isl_basic_set *bset, int k)
550 return hash_index(index, size, bits, (struct isl_basic_map *)bset, k);
553 /* If we can eliminate more than one div, then we need to make
554 * sure we do it from last div to first div, in order not to
555 * change the position of the other divs that still need to
556 * be removed.
558 static struct isl_basic_map *remove_duplicate_divs(
559 struct isl_basic_map *bmap, int *progress)
561 unsigned int size;
562 int *index;
563 int *elim_for;
564 int k, l, h;
565 int bits;
566 struct isl_blk eq;
567 unsigned total_var = isl_dim_total(bmap->dim);
568 unsigned total = total_var + bmap->n_div;
569 struct isl_ctx *ctx;
571 if (bmap->n_div <= 1)
572 return bmap;
574 ctx = bmap->ctx;
575 for (k = bmap->n_div - 1; k >= 0; --k)
576 if (!isl_int_is_zero(bmap->div[k][0]))
577 break;
578 if (k <= 0)
579 return bmap;
581 elim_for = isl_calloc_array(ctx, int, bmap->n_div);
582 size = round_up(4 * bmap->n_div / 3 - 1);
583 bits = ffs(size) - 1;
584 index = isl_calloc_array(ctx, int, size);
585 if (!index)
586 return bmap;
587 eq = isl_blk_alloc(ctx, 1+total);
588 if (isl_blk_is_error(eq))
589 goto out;
591 isl_seq_clr(eq.data, 1+total);
592 index[isl_seq_get_hash_bits(bmap->div[k], 2+total, bits)] = k + 1;
593 for (--k; k >= 0; --k) {
594 uint32_t hash;
596 if (isl_int_is_zero(bmap->div[k][0]))
597 continue;
599 hash = isl_seq_get_hash_bits(bmap->div[k], 2+total, bits);
600 for (h = hash; index[h]; h = (h+1) % size)
601 if (isl_seq_eq(bmap->div[k],
602 bmap->div[index[h]-1], 2+total))
603 break;
604 if (index[h]) {
605 *progress = 1;
606 l = index[h] - 1;
607 elim_for[l] = k + 1;
609 index[h] = k+1;
611 for (l = bmap->n_div - 1; l >= 0; --l) {
612 if (!elim_for[l])
613 continue;
614 k = elim_for[l] - 1;
615 isl_int_set_si(eq.data[1+total_var+k], -1);
616 isl_int_set_si(eq.data[1+total_var+l], 1);
617 eliminate_div(bmap, eq.data, l);
618 isl_int_set_si(eq.data[1+total_var+k], 0);
619 isl_int_set_si(eq.data[1+total_var+l], 0);
622 isl_blk_free(ctx, eq);
623 out:
624 free(index);
625 free(elim_for);
626 return bmap;
629 /* Normalize divs that appear in equalities.
631 * In particular, we assume that bmap contains some equalities
632 * of the form
634 * a x = m * e_i
636 * and we want to replace the set of e_i by a minimal set and
637 * such that the new e_i have a canonical representation in terms
638 * of the vector x.
639 * If any of the equalities involves more than one divs, then
640 * we currently simply bail out.
642 * Let us first additionally assume that all equalities involve
643 * a div. The equalities then express modulo constraints on the
644 * remaining variables and we can use "parameter compression"
645 * to find a minimal set of constraints. The result is a transformation
647 * x = T(x') = x_0 + G x'
649 * with G a lower-triangular matrix with all elements below the diagonal
650 * non-negative and smaller than the diagonal element on the same row.
651 * We first normalize x_0 by making the same property hold in the affine
652 * T matrix.
653 * The rows i of G with a 1 on the diagonal do not impose any modulo
654 * constraint and simply express x_i = x'_i.
655 * For each of the remaining rows i, we introduce a div and a corresponding
656 * equality. In particular
658 * g_ii e_j = x_i - g_i(x')
660 * where each x'_k is replaced either by x_k (if g_kk = 1) or the
661 * corresponding div (if g_kk != 1).
663 * If there are any equalities not involving any div, then we
664 * first apply a variable compression on the variables x:
666 * x = C x'' x'' = C_2 x
668 * and perform the above parameter compression on A C instead of on A.
669 * The resulting compression is then of the form
671 * x'' = T(x') = x_0 + G x'
673 * and in constructing the new divs and the corresponding equalities,
674 * we have to replace each x'', i.e., the x'_k with (g_kk = 1),
675 * by the corresponding row from C_2.
677 static struct isl_basic_map *normalize_divs(
678 struct isl_basic_map *bmap, int *progress)
680 int i, j, k;
681 int total;
682 int div_eq;
683 struct isl_mat *B;
684 struct isl_vec *d;
685 struct isl_mat *T = NULL;
686 struct isl_mat *C = NULL;
687 struct isl_mat *C2 = NULL;
688 isl_int v;
689 int *pos;
690 int dropped, needed;
692 if (!bmap)
693 return NULL;
695 if (bmap->n_div == 0)
696 return bmap;
698 if (bmap->n_eq == 0)
699 return bmap;
701 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS))
702 return bmap;
704 total = isl_dim_total(bmap->dim);
705 for (i = 0, j = bmap->n_div-1; i < bmap->n_eq; ++i) {
706 while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
707 --j;
708 if (j < 0)
709 break;
710 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, j) != -1)
711 goto done;
713 div_eq = i;
714 if (div_eq == 0)
715 return bmap;
717 if (div_eq < bmap->n_eq) {
718 B = isl_mat_sub_alloc(bmap->ctx, bmap->eq, div_eq,
719 bmap->n_eq - div_eq, 0, 1 + total);
720 C = isl_mat_variable_compression(bmap->ctx, B, &C2);
721 if (!C || !C2)
722 goto error;
723 if (C->n_col == 0) {
724 bmap = isl_basic_map_set_to_empty(bmap);
725 isl_mat_free(bmap->ctx, C);
726 isl_mat_free(bmap->ctx, C2);
727 goto done;
731 d = isl_vec_alloc(bmap->ctx, div_eq);
732 if (!d)
733 goto error;
734 for (i = 0, j = bmap->n_div-1; i < div_eq; ++i) {
735 while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
736 --j;
737 isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j]);
739 B = isl_mat_sub_alloc(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total);
741 if (C) {
742 B = isl_mat_product(bmap->ctx, B, C);
743 C = NULL;
746 T = isl_mat_parameter_compression(bmap->ctx, B, d);
747 if (!T)
748 goto error;
749 if (T->n_col == 0) {
750 bmap = isl_basic_map_set_to_empty(bmap);
751 isl_mat_free(bmap->ctx, C2);
752 isl_mat_free(bmap->ctx, T);
753 goto done;
755 isl_int_init(v);
756 for (i = 0; i < T->n_row - 1; ++i) {
757 isl_int_fdiv_q(v, T->row[1 + i][0], T->row[1 + i][1 + i]);
758 if (isl_int_is_zero(v))
759 continue;
760 isl_mat_col_submul(T, 0, v, 1 + i);
762 isl_int_clear(v);
763 pos = isl_alloc_array(bmap->ctx, int, T->n_row);
764 /* We have to be careful because dropping equalities may reorder them */
765 dropped = 0;
766 for (j = bmap->n_div - 1; j >= 0; --j) {
767 for (i = 0; i < bmap->n_eq; ++i)
768 if (!isl_int_is_zero(bmap->eq[i][1 + total + j]))
769 break;
770 if (i < bmap->n_eq) {
771 bmap = isl_basic_map_drop_div(bmap, j);
772 isl_basic_map_drop_equality(bmap, i);
773 ++dropped;
776 pos[0] = 0;
777 needed = 0;
778 for (i = 1; i < T->n_row; ++i) {
779 if (isl_int_is_one(T->row[i][i]))
780 pos[i] = i;
781 else
782 needed++;
784 if (needed > dropped) {
785 bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim),
786 needed, needed, 0);
787 if (!bmap)
788 goto error;
790 for (i = 1; i < T->n_row; ++i) {
791 if (isl_int_is_one(T->row[i][i]))
792 continue;
793 k = isl_basic_map_alloc_div(bmap);
794 pos[i] = 1 + total + k;
795 isl_seq_clr(bmap->div[k] + 1, 1 + total + bmap->n_div);
796 isl_int_set(bmap->div[k][0], T->row[i][i]);
797 if (C2)
798 isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + total);
799 else
800 isl_int_set_si(bmap->div[k][1 + i], 1);
801 for (j = 0; j < i; ++j) {
802 if (isl_int_is_zero(T->row[i][j]))
803 continue;
804 if (pos[j] < T->n_row && C2)
805 isl_seq_submul(bmap->div[k] + 1, T->row[i][j],
806 C2->row[pos[j]], 1 + total);
807 else
808 isl_int_neg(bmap->div[k][1 + pos[j]],
809 T->row[i][j]);
811 j = isl_basic_map_alloc_equality(bmap);
812 isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+total+bmap->n_div);
813 isl_int_set(bmap->eq[j][pos[i]], bmap->div[k][0]);
815 free(pos);
816 isl_mat_free(bmap->ctx, C2);
817 isl_mat_free(bmap->ctx, T);
819 *progress = 1;
820 done:
821 ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
823 return bmap;
824 error:
825 isl_mat_free(bmap->ctx, C);
826 isl_mat_free(bmap->ctx, C2);
827 isl_mat_free(bmap->ctx, T);
828 return bmap;
831 static struct isl_basic_map *remove_duplicate_constraints(
832 struct isl_basic_map *bmap, int *progress)
834 unsigned int size;
835 isl_int ***index;
836 int k, l, h;
837 int bits;
838 unsigned total = isl_basic_map_total_dim(bmap);
839 isl_int sum;
841 if (bmap->n_ineq <= 1)
842 return bmap;
844 size = round_up(4 * (bmap->n_ineq+1) / 3 - 1);
845 bits = ffs(size) - 1;
846 index = isl_calloc_array(ctx, isl_int **, size);
847 if (!index)
848 return bmap;
850 index[isl_seq_get_hash_bits(bmap->ineq[0]+1, total, bits)] = &bmap->ineq[0];
851 for (k = 1; k < bmap->n_ineq; ++k) {
852 h = hash_index(index, size, bits, bmap, k);
853 if (!index[h]) {
854 index[h] = &bmap->ineq[k];
855 continue;
857 if (progress)
858 *progress = 1;
859 l = index[h] - &bmap->ineq[0];
860 if (isl_int_lt(bmap->ineq[k][0], bmap->ineq[l][0]))
861 swap_inequality(bmap, k, l);
862 isl_basic_map_drop_inequality(bmap, k);
863 --k;
865 isl_int_init(sum);
866 for (k = 0; k < bmap->n_ineq-1; ++k) {
867 isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
868 h = hash_index(index, size, bits, bmap, k);
869 isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
870 if (!index[h])
871 continue;
872 l = index[h] - &bmap->ineq[0];
873 isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0]);
874 if (isl_int_is_pos(sum))
875 continue;
876 if (isl_int_is_zero(sum)) {
877 /* We need to break out of the loop after these
878 * changes since the contents of the hash
879 * will no longer be valid.
880 * Plus, we probably we want to regauss first.
882 isl_basic_map_drop_inequality(bmap, l);
883 isl_basic_map_inequality_to_equality(bmap, k);
884 } else
885 bmap = isl_basic_map_set_to_empty(bmap);
886 break;
888 isl_int_clear(sum);
890 free(index);
891 return bmap;
895 struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap)
897 int progress = 1;
898 if (!bmap)
899 return NULL;
900 while (progress) {
901 progress = 0;
902 bmap = isl_basic_map_normalize_constraints(bmap);
903 bmap = eliminate_divs_eq(bmap, &progress);
904 bmap = eliminate_divs_ineq(bmap, &progress);
905 bmap = isl_basic_map_gauss(bmap, &progress);
906 /* requires equalities in normal form */
907 bmap = normalize_divs(bmap, &progress);
908 bmap = remove_duplicate_divs(bmap, &progress);
909 bmap = remove_duplicate_constraints(bmap, &progress);
911 return bmap;
914 struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset)
916 return (struct isl_basic_set *)
917 isl_basic_map_simplify((struct isl_basic_map *)bset);
921 /* If the only constraints a div d=floor(f/m)
922 * appears in are its two defining constraints
924 * f - m d >=0
925 * -(f - (m - 1)) + m d >= 0
927 * then it can safely be removed.
929 static int div_is_redundant(struct isl_basic_map *bmap, int div)
931 int i;
932 unsigned pos = 1 + isl_dim_total(bmap->dim) + div;
934 for (i = 0; i < bmap->n_eq; ++i)
935 if (!isl_int_is_zero(bmap->eq[i][pos]))
936 return 0;
938 for (i = 0; i < bmap->n_ineq; ++i) {
939 if (isl_int_is_zero(bmap->ineq[i][pos]))
940 continue;
941 if (isl_int_eq(bmap->ineq[i][pos], bmap->div[div][0])) {
942 int neg;
943 isl_int_sub(bmap->div[div][1],
944 bmap->div[div][1], bmap->div[div][0]);
945 isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1);
946 neg = isl_seq_is_neg(bmap->ineq[i], bmap->div[div]+1, pos);
947 isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
948 isl_int_add(bmap->div[div][1],
949 bmap->div[div][1], bmap->div[div][0]);
950 if (!neg)
951 return 0;
952 if (isl_seq_first_non_zero(bmap->ineq[i]+pos+1,
953 bmap->n_div-div-1) != -1)
954 return 0;
955 } else if (isl_int_abs_eq(bmap->ineq[i][pos], bmap->div[div][0])) {
956 if (!isl_seq_eq(bmap->ineq[i], bmap->div[div]+1, pos))
957 return 0;
958 if (isl_seq_first_non_zero(bmap->ineq[i]+pos+1,
959 bmap->n_div-div-1) != -1)
960 return 0;
961 } else
962 return 0;
965 for (i = 0; i < bmap->n_div; ++i)
966 if (!isl_int_is_zero(bmap->div[i][1+pos]))
967 return 0;
969 return 1;
973 * Remove divs that don't occur in any of the constraints or other divs.
974 * These can arise when dropping some of the variables in a quast
975 * returned by piplib.
977 static struct isl_basic_map *remove_redundant_divs(struct isl_basic_map *bmap)
979 int i;
981 if (!bmap)
982 return NULL;
984 for (i = bmap->n_div-1; i >= 0; --i) {
985 if (!div_is_redundant(bmap, i))
986 continue;
987 bmap = isl_basic_map_drop_div(bmap, i);
989 return bmap;
992 struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap)
994 bmap = remove_redundant_divs(bmap);
995 if (!bmap)
996 return NULL;
997 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
998 return bmap;
1001 struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset)
1003 return (struct isl_basic_set *)
1004 isl_basic_map_finalize((struct isl_basic_map *)bset);
1007 struct isl_set *isl_set_finalize(struct isl_set *set)
1009 int i;
1011 if (!set)
1012 return NULL;
1013 for (i = 0; i < set->n; ++i) {
1014 set->p[i] = isl_basic_set_finalize(set->p[i]);
1015 if (!set->p[i])
1016 goto error;
1018 return set;
1019 error:
1020 isl_set_free(set);
1021 return NULL;
1024 struct isl_map *isl_map_finalize(struct isl_map *map)
1026 int i;
1028 if (!map)
1029 return NULL;
1030 for (i = 0; i < map->n; ++i) {
1031 map->p[i] = isl_basic_map_finalize(map->p[i]);
1032 if (!map->p[i])
1033 goto error;
1035 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
1036 return map;
1037 error:
1038 isl_map_free(map);
1039 return NULL;
1043 /* Remove any div that is defined in terms of the given variable.
1045 static struct isl_basic_map *remove_dependent_vars(struct isl_basic_map *bmap,
1046 int pos)
1048 int i;
1049 unsigned dim = isl_dim_total(bmap->dim);
1051 for (i = 0; i < bmap->n_div; ++i) {
1052 if (isl_int_is_zero(bmap->div[i][0]))
1053 continue;
1054 if (isl_int_is_zero(bmap->div[i][1+1+pos]))
1055 continue;
1056 bmap = isl_basic_map_eliminate_vars(bmap, dim + i, 1);
1057 if (!bmap)
1058 return NULL;
1060 return bmap;
1063 /* Eliminate the specified variables from the constraints using
1064 * Fourier-Motzkin. The variables themselves are not removed.
1066 struct isl_basic_map *isl_basic_map_eliminate_vars(
1067 struct isl_basic_map *bmap, unsigned pos, unsigned n)
1069 int d;
1070 int i, j, k;
1071 unsigned total;
1073 if (n == 0)
1074 return bmap;
1075 if (!bmap)
1076 return NULL;
1077 total = isl_basic_map_total_dim(bmap);
1079 bmap = isl_basic_map_cow(bmap);
1080 for (d = pos + n - 1; d >= 0 && d >= pos; --d)
1081 bmap = remove_dependent_vars(bmap, d);
1083 for (d = pos + n - 1;
1084 d >= 0 && d >= total - bmap->n_div && d >= pos; --d)
1085 isl_seq_clr(bmap->div[d-(total-bmap->n_div)], 2+total);
1086 for (d = pos + n - 1; d >= 0 && d >= pos; --d) {
1087 int n_lower, n_upper;
1088 if (!bmap)
1089 return NULL;
1090 for (i = 0; i < bmap->n_eq; ++i) {
1091 if (isl_int_is_zero(bmap->eq[i][1+d]))
1092 continue;
1093 eliminate_var_using_equality(bmap, d, bmap->eq[i], NULL);
1094 isl_basic_map_drop_equality(bmap, i);
1095 break;
1097 if (i < bmap->n_eq)
1098 continue;
1099 n_lower = 0;
1100 n_upper = 0;
1101 for (i = 0; i < bmap->n_ineq; ++i) {
1102 if (isl_int_is_pos(bmap->ineq[i][1+d]))
1103 n_lower++;
1104 else if (isl_int_is_neg(bmap->ineq[i][1+d]))
1105 n_upper++;
1107 bmap = isl_basic_map_extend_constraints(bmap,
1108 0, n_lower * n_upper);
1109 for (i = bmap->n_ineq - 1; i >= 0; --i) {
1110 int last;
1111 if (isl_int_is_zero(bmap->ineq[i][1+d]))
1112 continue;
1113 last = -1;
1114 for (j = 0; j < i; ++j) {
1115 if (isl_int_is_zero(bmap->ineq[j][1+d]))
1116 continue;
1117 last = j;
1118 if (isl_int_sgn(bmap->ineq[i][1+d]) ==
1119 isl_int_sgn(bmap->ineq[j][1+d]))
1120 continue;
1121 k = isl_basic_map_alloc_inequality(bmap);
1122 if (k < 0)
1123 goto error;
1124 isl_seq_cpy(bmap->ineq[k], bmap->ineq[i],
1125 1+total);
1126 isl_seq_elim(bmap->ineq[k], bmap->ineq[j],
1127 1+d, 1+total, NULL);
1129 isl_basic_map_drop_inequality(bmap, i);
1130 i = last + 1;
1132 if (n_lower > 0 && n_upper > 0) {
1133 bmap = isl_basic_map_normalize_constraints(bmap);
1134 bmap = remove_duplicate_constraints(bmap, NULL);
1135 bmap = isl_basic_map_gauss(bmap, NULL);
1136 bmap = isl_basic_map_convex_hull(bmap);
1137 if (!bmap)
1138 goto error;
1139 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
1140 break;
1143 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1144 return bmap;
1145 error:
1146 isl_basic_map_free(bmap);
1147 return NULL;
1150 struct isl_basic_set *isl_basic_set_eliminate_vars(
1151 struct isl_basic_set *bset, unsigned pos, unsigned n)
1153 return (struct isl_basic_set *)isl_basic_map_eliminate_vars(
1154 (struct isl_basic_map *)bset, pos, n);
1157 static void compute_elimination_index(struct isl_basic_map *bmap, int *elim)
1159 int d, i;
1160 unsigned total;
1162 total = isl_dim_total(bmap->dim);
1163 for (d = 0; d < total; ++d)
1164 elim[d] = -1;
1165 for (d = total - 1, i = 0; d >= 0 && i < bmap->n_eq; ++i) {
1166 for (; d >= 0; --d) {
1167 if (isl_int_is_zero(bmap->eq[i][1+d]))
1168 continue;
1169 elim[d] = i;
1170 break;
1175 static void set_compute_elimination_index(struct isl_basic_set *bset, int *elim)
1177 return compute_elimination_index((struct isl_basic_map *)bset, elim);
1180 static int reduced_using_equalities(isl_int *dst, isl_int *src,
1181 struct isl_basic_map *bmap, int *elim)
1183 int d, i;
1184 int copied = 0;
1185 unsigned total;
1187 total = isl_dim_total(bmap->dim);
1188 for (d = total - 1; d >= 0; --d) {
1189 if (isl_int_is_zero(src[1+d]))
1190 continue;
1191 if (elim[d] == -1)
1192 continue;
1193 if (!copied) {
1194 isl_seq_cpy(dst, src, 1 + total);
1195 copied = 1;
1197 isl_seq_elim(dst, bmap->eq[elim[d]], 1 + d, 1 + total, NULL);
1199 return copied;
1202 static int set_reduced_using_equalities(isl_int *dst, isl_int *src,
1203 struct isl_basic_set *bset, int *elim)
1205 return reduced_using_equalities(dst, src,
1206 (struct isl_basic_map *)bset, elim);
1209 static struct isl_basic_set *isl_basic_set_reduce_using_equalities(
1210 struct isl_basic_set *bset, struct isl_basic_set *context)
1212 int i;
1213 int *elim;
1215 if (!bset || !context)
1216 goto error;
1218 bset = isl_basic_set_cow(bset);
1219 if (!bset)
1220 goto error;
1222 elim = isl_alloc_array(ctx, int, isl_basic_set_n_dim(bset));
1223 if (!elim)
1224 goto error;
1225 set_compute_elimination_index(context, elim);
1226 for (i = 0; i < bset->n_eq; ++i)
1227 set_reduced_using_equalities(bset->eq[i], bset->eq[i],
1228 context, elim);
1229 for (i = 0; i < bset->n_ineq; ++i)
1230 set_reduced_using_equalities(bset->ineq[i], bset->ineq[i],
1231 context, elim);
1232 isl_basic_set_free(context);
1233 free(elim);
1234 bset = isl_basic_set_simplify(bset);
1235 bset = isl_basic_set_finalize(bset);
1236 return bset;
1237 error:
1238 isl_basic_set_free(bset);
1239 isl_basic_set_free(context);
1240 return NULL;
1243 static struct isl_basic_set *remove_shifted_constraints(
1244 struct isl_basic_set *bset, struct isl_basic_set *context)
1246 unsigned int size;
1247 isl_int ***index;
1248 int bits;
1249 int k, h, l;
1251 if (!bset)
1252 return NULL;
1254 size = round_up(4 * (context->n_ineq+1) / 3 - 1);
1255 bits = ffs(size) - 1;
1256 index = isl_calloc_array(ctx, isl_int **, size);
1257 if (!index)
1258 return bset;
1260 for (k = 0; k < context->n_ineq; ++k) {
1261 h = set_hash_index(index, size, bits, context, k);
1262 index[h] = &context->ineq[k];
1264 for (k = 0; k < bset->n_ineq; ++k) {
1265 h = set_hash_index(index, size, bits, bset, k);
1266 if (!index[h])
1267 continue;
1268 l = index[h] - &context->ineq[0];
1269 if (isl_int_lt(bset->ineq[k][0], context->ineq[l][0]))
1270 continue;
1271 bset = isl_basic_set_cow(bset);
1272 if (!bset)
1273 goto error;
1274 isl_basic_set_drop_inequality(bset, k);
1275 --k;
1277 free(index);
1278 return bset;
1279 error:
1280 free(index);
1281 return bset;
1284 static struct isl_basic_set *uset_gist(struct isl_basic_set *bset,
1285 struct isl_basic_set *context);
1287 static struct isl_basic_set *uset_gist_context_eq(struct isl_basic_set *bset,
1288 struct isl_basic_set *context)
1290 struct isl_mat *T;
1291 struct isl_mat *T2;
1292 struct isl_ctx *ctx = context->ctx;
1293 struct isl_basic_set *reduced_context;
1294 reduced_context = isl_basic_set_remove_equalities(
1295 isl_basic_set_copy(context), &T, &T2);
1296 if (!reduced_context)
1297 goto error;
1298 bset = isl_basic_set_preimage(bset, T);
1299 bset = uset_gist(bset, reduced_context);
1300 bset = isl_basic_set_preimage(bset, T2);
1301 bset = isl_basic_set_reduce_using_equalities(bset, context);
1302 return bset;
1303 error:
1304 isl_basic_set_free(context);
1305 isl_basic_set_free(bset);
1306 return NULL;
1309 static struct isl_basic_set *uset_gist_set_eq(struct isl_basic_set *bset,
1310 struct isl_basic_set *context)
1312 struct isl_mat *T;
1313 struct isl_mat *T2;
1314 struct isl_ctx *ctx = context->ctx;
1315 struct isl_basic_set *affine_hull = NULL;
1317 affine_hull = isl_basic_set_copy(bset);
1318 affine_hull = isl_basic_set_cow(affine_hull);
1319 if (!affine_hull)
1320 goto error;
1321 isl_basic_set_free_inequality(affine_hull, affine_hull->n_ineq);
1323 bset = isl_basic_set_remove_equalities(bset, &T, &T2);
1324 if (!bset)
1325 goto error;
1326 context = isl_basic_set_preimage(context, T);
1327 bset = uset_gist(bset, context);
1328 bset = isl_basic_set_preimage(bset, T2);
1329 bset = isl_basic_set_intersect(bset, affine_hull);
1330 return bset;
1331 error:
1332 isl_basic_set_free(affine_hull);
1333 isl_basic_set_free(context);
1334 isl_basic_set_free(bset);
1335 return NULL;
1338 /* Remove all information from bset that is redundant in the context
1339 * of context. In particular, equalities that are linear combinations
1340 * of those in context are removed. Then the inequalities that are
1341 * redundant in the context of the equalities and inequalities of
1342 * context are removed.
1344 static struct isl_basic_set *uset_gist(struct isl_basic_set *bset,
1345 struct isl_basic_set *context)
1347 int i;
1348 isl_int opt;
1349 struct isl_basic_set *combined;
1350 struct isl_ctx *ctx;
1352 if (!bset || !context)
1353 goto error;
1355 if (context->n_eq > 0)
1356 return uset_gist_context_eq(bset, context);
1357 if (!context->n_ineq)
1358 goto done;
1359 if (bset->n_eq > 0)
1360 return uset_gist_set_eq(bset, context);
1361 bset = remove_shifted_constraints(bset, context);
1362 combined = isl_basic_set_extend_constraints(isl_basic_set_copy(bset),
1363 context->n_eq, context->n_ineq);
1364 context = isl_basic_set_add_constraints(combined, context, 0);
1365 if (!context)
1366 goto error;
1367 ctx = context->ctx;
1368 isl_int_init(opt);
1369 for (i = bset->n_ineq-1; i >= 0; --i) {
1370 int redundant;
1371 set_swap_inequality(context, i, context->n_ineq-1);
1372 context->n_ineq--;
1373 redundant = isl_basic_set_constraint_is_redundant(&context,
1374 context->ineq[context->n_ineq], &opt, NULL);
1375 if (redundant == -1) {
1376 isl_int_clear(opt);
1377 goto error;
1379 if (ISL_F_ISSET(context, ISL_BASIC_MAP_EMPTY)) {
1380 bset = isl_basic_set_set_to_empty(bset);
1381 break;
1383 context->n_ineq++;
1384 set_swap_inequality(context, i, context->n_ineq-1);
1385 if (redundant) {
1386 isl_basic_set_drop_inequality(context, i);
1387 isl_basic_set_drop_inequality(bset, i);
1390 isl_int_clear(opt);
1391 done:
1392 isl_basic_set_free(context);
1393 return bset;
1394 error:
1395 isl_basic_set_free(context);
1396 isl_basic_set_free(bset);
1397 return NULL;
1400 struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
1401 struct isl_basic_map *context)
1403 struct isl_basic_set *bset;
1405 if (!bmap || !context)
1406 goto error;
1408 context = isl_basic_map_align_divs(context, bmap);
1409 bmap = isl_basic_map_align_divs(bmap, context);
1411 bset = uset_gist(isl_basic_map_underlying_set(isl_basic_map_copy(bmap)),
1412 isl_basic_map_underlying_set(context));
1414 return isl_basic_map_overlying_set(bset, bmap);
1415 error:
1416 isl_basic_map_free(bmap);
1417 isl_basic_map_free(context);
1418 return NULL;
1422 * Assumes context has no implicit divs.
1424 struct isl_map *isl_map_gist(struct isl_map *map, struct isl_basic_map *context)
1426 int i;
1428 map = isl_map_cow(map);
1429 if (!map || !context)
1430 return NULL;
1431 isl_assert(map->ctx, isl_dim_equal(map->dim, context->dim), goto error);
1432 map = isl_map_compute_divs(map);
1433 for (i = 0; i < map->n; ++i)
1434 context = isl_basic_map_align_divs(context, map->p[i]);
1435 for (i = 0; i < map->n; ++i) {
1436 map->p[i] = isl_basic_map_gist(map->p[i],
1437 isl_basic_map_copy(context));
1438 if (!map->p[i])
1439 goto error;
1441 isl_basic_map_free(context);
1442 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
1443 return map;
1444 error:
1445 isl_map_free(map);
1446 isl_basic_map_free(context);
1447 return NULL;
1450 struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset,
1451 struct isl_basic_set *context)
1453 return (struct isl_basic_set *)isl_basic_map_gist(
1454 (struct isl_basic_map *)bset, (struct isl_basic_map *)context);
1457 struct isl_set *isl_set_gist(struct isl_set *set, struct isl_basic_set *context)
1459 return (struct isl_set *)isl_map_gist((struct isl_map *)set,
1460 (struct isl_basic_map *)context);
1463 /* Quick check to see if two basic maps are disjoint.
1464 * In particular, we reduce the equalities and inequalities of
1465 * one basic map in the context of the equalities of the other
1466 * basic map and check if we get a contradiction.
1468 int isl_basic_map_fast_is_disjoint(struct isl_basic_map *bmap1,
1469 struct isl_basic_map *bmap2)
1471 struct isl_vec *v = NULL;
1472 int *elim = NULL;
1473 unsigned total;
1474 int d, i;
1476 if (!bmap1 || !bmap2)
1477 return -1;
1478 isl_assert(bmap1->ctx, isl_dim_equal(bmap1->dim, bmap2->dim),
1479 return -1);
1480 if (bmap1->n_div || bmap2->n_div)
1481 return 0;
1482 if (!bmap1->n_eq && !bmap2->n_eq)
1483 return 0;
1485 total = isl_dim_total(bmap1->dim);
1486 if (total == 0)
1487 return 0;
1488 v = isl_vec_alloc(bmap1->ctx, 1 + total);
1489 if (!v)
1490 goto error;
1491 elim = isl_alloc_array(bmap1->ctx, int, total);
1492 if (!elim)
1493 goto error;
1494 compute_elimination_index(bmap1, elim);
1495 for (i = 0; i < bmap2->n_eq; ++i) {
1496 int reduced;
1497 reduced = reduced_using_equalities(v->block.data, bmap2->eq[i],
1498 bmap1, elim);
1499 if (reduced && !isl_int_is_zero(v->block.data[0]) &&
1500 isl_seq_first_non_zero(v->block.data + 1, total) == -1)
1501 goto disjoint;
1503 for (i = 0; i < bmap2->n_ineq; ++i) {
1504 int reduced;
1505 reduced = reduced_using_equalities(v->block.data,
1506 bmap2->ineq[i], bmap1, elim);
1507 if (reduced && isl_int_is_neg(v->block.data[0]) &&
1508 isl_seq_first_non_zero(v->block.data + 1, total) == -1)
1509 goto disjoint;
1511 compute_elimination_index(bmap2, elim);
1512 for (i = 0; i < bmap1->n_ineq; ++i) {
1513 int reduced;
1514 reduced = reduced_using_equalities(v->block.data,
1515 bmap1->ineq[i], bmap2, elim);
1516 if (reduced && isl_int_is_neg(v->block.data[0]) &&
1517 isl_seq_first_non_zero(v->block.data + 1, total) == -1)
1518 goto disjoint;
1520 isl_vec_free(bmap1->ctx, v);
1521 free(elim);
1522 return 0;
1523 disjoint:
1524 isl_vec_free(bmap1->ctx, v);
1525 free(elim);
1526 return 1;
1527 error:
1528 isl_vec_free(bmap1->ctx, v);
1529 free(elim);
1530 return -1;
1533 int isl_basic_set_fast_is_disjoint(struct isl_basic_set *bset1,
1534 struct isl_basic_set *bset2)
1536 return isl_basic_map_fast_is_disjoint((struct isl_basic_map *)bset1,
1537 (struct isl_basic_map *)bset2);
1540 int isl_map_fast_is_disjoint(struct isl_map *map1, struct isl_map *map2)
1542 int i, j;
1544 if (!map1 || !map2)
1545 return -1;
1547 if (isl_map_fast_is_equal(map1, map2))
1548 return 0;
1550 for (i = 0; i < map1->n; ++i) {
1551 for (j = 0; j < map2->n; ++j) {
1552 int d = isl_basic_map_fast_is_disjoint(map1->p[i],
1553 map2->p[j]);
1554 if (d != 1)
1555 return d;
1558 return 1;
1561 int isl_set_fast_is_disjoint(struct isl_set *set1, struct isl_set *set2)
1563 return isl_map_fast_is_disjoint((struct isl_map *)set1,
1564 (struct isl_map *)set2);