add isl_multi_*_factor_range
[isl.git] / isl_map_simplify.c
blobb085538a7439330236f48e858857c1c7cd4b660b
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2012-2013 Ecole Normale Superieure
4 * Copyright 2014 INRIA Rocquencourt
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege, K.U.Leuven, Departement
9 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
11 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
12 * B.P. 105 - 78153 Le Chesnay, France
15 #include <isl_ctx_private.h>
16 #include <isl_map_private.h>
17 #include "isl_equalities.h"
18 #include <isl/map.h>
19 #include <isl_seq.h>
20 #include "isl_tab.h"
21 #include <isl_space_private.h>
22 #include <isl_mat_private.h>
23 #include <isl_vec_private.h>
25 static void swap_equality(struct isl_basic_map *bmap, int a, int b)
27 isl_int *t = bmap->eq[a];
28 bmap->eq[a] = bmap->eq[b];
29 bmap->eq[b] = t;
32 static void swap_inequality(struct isl_basic_map *bmap, int a, int b)
34 if (a != b) {
35 isl_int *t = bmap->ineq[a];
36 bmap->ineq[a] = bmap->ineq[b];
37 bmap->ineq[b] = t;
41 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
43 isl_seq_cpy(c, c + n, rem);
44 isl_seq_clr(c + rem, n);
47 /* Drop n dimensions starting at first.
49 * In principle, this frees up some extra variables as the number
50 * of columns remains constant, but we would have to extend
51 * the div array too as the number of rows in this array is assumed
52 * to be equal to extra.
54 struct isl_basic_set *isl_basic_set_drop_dims(
55 struct isl_basic_set *bset, unsigned first, unsigned n)
57 int i;
59 if (!bset)
60 goto error;
62 isl_assert(bset->ctx, first + n <= bset->dim->n_out, goto error);
64 if (n == 0 && !isl_space_get_tuple_name(bset->dim, isl_dim_set))
65 return bset;
67 bset = isl_basic_set_cow(bset);
68 if (!bset)
69 return NULL;
71 for (i = 0; i < bset->n_eq; ++i)
72 constraint_drop_vars(bset->eq[i]+1+bset->dim->nparam+first, n,
73 (bset->dim->n_out-first-n)+bset->extra);
75 for (i = 0; i < bset->n_ineq; ++i)
76 constraint_drop_vars(bset->ineq[i]+1+bset->dim->nparam+first, n,
77 (bset->dim->n_out-first-n)+bset->extra);
79 for (i = 0; i < bset->n_div; ++i)
80 constraint_drop_vars(bset->div[i]+1+1+bset->dim->nparam+first, n,
81 (bset->dim->n_out-first-n)+bset->extra);
83 bset->dim = isl_space_drop_outputs(bset->dim, first, n);
84 if (!bset->dim)
85 goto error;
87 ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
88 bset = isl_basic_set_simplify(bset);
89 return isl_basic_set_finalize(bset);
90 error:
91 isl_basic_set_free(bset);
92 return NULL;
95 struct isl_set *isl_set_drop_dims(
96 struct isl_set *set, unsigned first, unsigned n)
98 int i;
100 if (!set)
101 goto error;
103 isl_assert(set->ctx, first + n <= set->dim->n_out, goto error);
105 if (n == 0 && !isl_space_get_tuple_name(set->dim, isl_dim_set))
106 return set;
107 set = isl_set_cow(set);
108 if (!set)
109 goto error;
110 set->dim = isl_space_drop_outputs(set->dim, first, n);
111 if (!set->dim)
112 goto error;
114 for (i = 0; i < set->n; ++i) {
115 set->p[i] = isl_basic_set_drop_dims(set->p[i], first, n);
116 if (!set->p[i])
117 goto error;
120 ISL_F_CLR(set, ISL_SET_NORMALIZED);
121 return set;
122 error:
123 isl_set_free(set);
124 return NULL;
127 /* Move "n" divs starting at "first" to the end of the list of divs.
129 static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
130 unsigned first, unsigned n)
132 isl_int **div;
133 int i;
135 if (first + n == bmap->n_div)
136 return bmap;
138 div = isl_alloc_array(bmap->ctx, isl_int *, n);
139 if (!div)
140 goto error;
141 for (i = 0; i < n; ++i)
142 div[i] = bmap->div[first + i];
143 for (i = 0; i < bmap->n_div - first - n; ++i)
144 bmap->div[first + i] = bmap->div[first + n + i];
145 for (i = 0; i < n; ++i)
146 bmap->div[bmap->n_div - n + i] = div[i];
147 free(div);
148 return bmap;
149 error:
150 isl_basic_map_free(bmap);
151 return NULL;
154 /* Drop "n" dimensions of type "type" starting at "first".
156 * In principle, this frees up some extra variables as the number
157 * of columns remains constant, but we would have to extend
158 * the div array too as the number of rows in this array is assumed
159 * to be equal to extra.
161 struct isl_basic_map *isl_basic_map_drop(struct isl_basic_map *bmap,
162 enum isl_dim_type type, unsigned first, unsigned n)
164 int i;
165 unsigned dim;
166 unsigned offset;
167 unsigned left;
169 if (!bmap)
170 goto error;
172 dim = isl_basic_map_dim(bmap, type);
173 isl_assert(bmap->ctx, first + n <= dim, goto error);
175 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
176 return bmap;
178 bmap = isl_basic_map_cow(bmap);
179 if (!bmap)
180 return NULL;
182 offset = isl_basic_map_offset(bmap, type) + first;
183 left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
184 for (i = 0; i < bmap->n_eq; ++i)
185 constraint_drop_vars(bmap->eq[i]+offset, n, left);
187 for (i = 0; i < bmap->n_ineq; ++i)
188 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
190 for (i = 0; i < bmap->n_div; ++i)
191 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
193 if (type == isl_dim_div) {
194 bmap = move_divs_last(bmap, first, n);
195 if (!bmap)
196 goto error;
197 isl_basic_map_free_div(bmap, n);
198 } else
199 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
200 if (!bmap->dim)
201 goto error;
203 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
204 bmap = isl_basic_map_simplify(bmap);
205 return isl_basic_map_finalize(bmap);
206 error:
207 isl_basic_map_free(bmap);
208 return NULL;
211 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
212 enum isl_dim_type type, unsigned first, unsigned n)
214 return (isl_basic_set *)isl_basic_map_drop((isl_basic_map *)bset,
215 type, first, n);
218 struct isl_basic_map *isl_basic_map_drop_inputs(
219 struct isl_basic_map *bmap, unsigned first, unsigned n)
221 return isl_basic_map_drop(bmap, isl_dim_in, first, n);
224 struct isl_map *isl_map_drop(struct isl_map *map,
225 enum isl_dim_type type, unsigned first, unsigned n)
227 int i;
229 if (!map)
230 goto error;
232 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
234 if (n == 0 && !isl_space_get_tuple_name(map->dim, type))
235 return map;
236 map = isl_map_cow(map);
237 if (!map)
238 goto error;
239 map->dim = isl_space_drop_dims(map->dim, type, first, n);
240 if (!map->dim)
241 goto error;
243 for (i = 0; i < map->n; ++i) {
244 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
245 if (!map->p[i])
246 goto error;
248 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
250 return map;
251 error:
252 isl_map_free(map);
253 return NULL;
256 struct isl_set *isl_set_drop(struct isl_set *set,
257 enum isl_dim_type type, unsigned first, unsigned n)
259 return (isl_set *)isl_map_drop((isl_map *)set, type, first, n);
262 struct isl_map *isl_map_drop_inputs(
263 struct isl_map *map, unsigned first, unsigned n)
265 return isl_map_drop(map, isl_dim_in, first, n);
269 * We don't cow, as the div is assumed to be redundant.
271 static struct isl_basic_map *isl_basic_map_drop_div(
272 struct isl_basic_map *bmap, unsigned div)
274 int i;
275 unsigned pos;
277 if (!bmap)
278 goto error;
280 pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
282 isl_assert(bmap->ctx, div < bmap->n_div, goto error);
284 for (i = 0; i < bmap->n_eq; ++i)
285 constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
287 for (i = 0; i < bmap->n_ineq; ++i) {
288 if (!isl_int_is_zero(bmap->ineq[i][pos])) {
289 isl_basic_map_drop_inequality(bmap, i);
290 --i;
291 continue;
293 constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
296 for (i = 0; i < bmap->n_div; ++i)
297 constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
299 if (div != bmap->n_div - 1) {
300 int j;
301 isl_int *t = bmap->div[div];
303 for (j = div; j < bmap->n_div - 1; ++j)
304 bmap->div[j] = bmap->div[j+1];
306 bmap->div[bmap->n_div - 1] = t;
308 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
309 isl_basic_map_free_div(bmap, 1);
311 return bmap;
312 error:
313 isl_basic_map_free(bmap);
314 return NULL;
317 struct isl_basic_map *isl_basic_map_normalize_constraints(
318 struct isl_basic_map *bmap)
320 int i;
321 isl_int gcd;
322 unsigned total = isl_basic_map_total_dim(bmap);
324 if (!bmap)
325 return NULL;
327 isl_int_init(gcd);
328 for (i = bmap->n_eq - 1; i >= 0; --i) {
329 isl_seq_gcd(bmap->eq[i]+1, total, &gcd);
330 if (isl_int_is_zero(gcd)) {
331 if (!isl_int_is_zero(bmap->eq[i][0])) {
332 bmap = isl_basic_map_set_to_empty(bmap);
333 break;
335 isl_basic_map_drop_equality(bmap, i);
336 continue;
338 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
339 isl_int_gcd(gcd, gcd, bmap->eq[i][0]);
340 if (isl_int_is_one(gcd))
341 continue;
342 if (!isl_int_is_divisible_by(bmap->eq[i][0], gcd)) {
343 bmap = isl_basic_map_set_to_empty(bmap);
344 break;
346 isl_seq_scale_down(bmap->eq[i], bmap->eq[i], gcd, 1+total);
349 for (i = bmap->n_ineq - 1; i >= 0; --i) {
350 isl_seq_gcd(bmap->ineq[i]+1, total, &gcd);
351 if (isl_int_is_zero(gcd)) {
352 if (isl_int_is_neg(bmap->ineq[i][0])) {
353 bmap = isl_basic_map_set_to_empty(bmap);
354 break;
356 isl_basic_map_drop_inequality(bmap, i);
357 continue;
359 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
360 isl_int_gcd(gcd, gcd, bmap->ineq[i][0]);
361 if (isl_int_is_one(gcd))
362 continue;
363 isl_int_fdiv_q(bmap->ineq[i][0], bmap->ineq[i][0], gcd);
364 isl_seq_scale_down(bmap->ineq[i]+1, bmap->ineq[i]+1, gcd, total);
366 isl_int_clear(gcd);
368 return bmap;
371 struct isl_basic_set *isl_basic_set_normalize_constraints(
372 struct isl_basic_set *bset)
374 return (struct isl_basic_set *)isl_basic_map_normalize_constraints(
375 (struct isl_basic_map *)bset);
378 /* Remove any common factor in numerator and denominator of the div expression,
379 * not taking into account the constant term.
380 * That is, if the div is of the form
382 * floor((a + m f(x))/(m d))
384 * then replace it by
386 * floor((floor(a/m) + f(x))/d)
388 * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
389 * and can therefore not influence the result of the floor.
391 static void normalize_div_expression(__isl_keep isl_basic_map *bmap, int div)
393 unsigned total = isl_basic_map_total_dim(bmap);
394 isl_ctx *ctx = bmap->ctx;
396 if (isl_int_is_zero(bmap->div[div][0]))
397 return;
398 isl_seq_gcd(bmap->div[div] + 2, total, &ctx->normalize_gcd);
399 isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, bmap->div[div][0]);
400 if (isl_int_is_one(ctx->normalize_gcd))
401 return;
402 isl_int_fdiv_q(bmap->div[div][1], bmap->div[div][1],
403 ctx->normalize_gcd);
404 isl_int_divexact(bmap->div[div][0], bmap->div[div][0],
405 ctx->normalize_gcd);
406 isl_seq_scale_down(bmap->div[div] + 2, bmap->div[div] + 2,
407 ctx->normalize_gcd, total);
410 /* Remove any common factor in numerator and denominator of a div expression,
411 * not taking into account the constant term.
412 * That is, look for any div of the form
414 * floor((a + m f(x))/(m d))
416 * and replace it by
418 * floor((floor(a/m) + f(x))/d)
420 * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
421 * and can therefore not influence the result of the floor.
423 static __isl_give isl_basic_map *normalize_div_expressions(
424 __isl_take isl_basic_map *bmap)
426 int i;
428 if (!bmap)
429 return NULL;
430 if (bmap->n_div == 0)
431 return bmap;
433 for (i = 0; i < bmap->n_div; ++i)
434 normalize_div_expression(bmap, i);
436 return bmap;
439 /* Assumes divs have been ordered if keep_divs is set.
441 static void eliminate_var_using_equality(struct isl_basic_map *bmap,
442 unsigned pos, isl_int *eq, int keep_divs, int *progress)
444 unsigned total;
445 unsigned space_total;
446 int k;
447 int last_div;
449 total = isl_basic_map_total_dim(bmap);
450 space_total = isl_space_dim(bmap->dim, isl_dim_all);
451 last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
452 for (k = 0; k < bmap->n_eq; ++k) {
453 if (bmap->eq[k] == eq)
454 continue;
455 if (isl_int_is_zero(bmap->eq[k][1+pos]))
456 continue;
457 if (progress)
458 *progress = 1;
459 isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL);
460 isl_seq_normalize(bmap->ctx, bmap->eq[k], 1 + total);
463 for (k = 0; k < bmap->n_ineq; ++k) {
464 if (isl_int_is_zero(bmap->ineq[k][1+pos]))
465 continue;
466 if (progress)
467 *progress = 1;
468 isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL);
469 isl_seq_normalize(bmap->ctx, bmap->ineq[k], 1 + total);
470 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
473 for (k = 0; k < bmap->n_div; ++k) {
474 if (isl_int_is_zero(bmap->div[k][0]))
475 continue;
476 if (isl_int_is_zero(bmap->div[k][1+1+pos]))
477 continue;
478 if (progress)
479 *progress = 1;
480 /* We need to be careful about circular definitions,
481 * so for now we just remove the definition of div k
482 * if the equality contains any divs.
483 * If keep_divs is set, then the divs have been ordered
484 * and we can keep the definition as long as the result
485 * is still ordered.
487 if (last_div == -1 || (keep_divs && last_div < k)) {
488 isl_seq_elim(bmap->div[k]+1, eq,
489 1+pos, 1+total, &bmap->div[k][0]);
490 normalize_div_expression(bmap, k);
491 } else
492 isl_seq_clr(bmap->div[k], 1 + total);
493 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
497 /* Assumes divs have been ordered if keep_divs is set.
499 static __isl_give isl_basic_map *eliminate_div(__isl_take isl_basic_map *bmap,
500 isl_int *eq, unsigned div, int keep_divs)
502 unsigned pos = isl_space_dim(bmap->dim, isl_dim_all) + div;
504 eliminate_var_using_equality(bmap, pos, eq, keep_divs, NULL);
506 bmap = isl_basic_map_drop_div(bmap, div);
508 return bmap;
511 /* Check if elimination of div "div" using equality "eq" would not
512 * result in a div depending on a later div.
514 static int ok_to_eliminate_div(struct isl_basic_map *bmap, isl_int *eq,
515 unsigned div)
517 int k;
518 int last_div;
519 unsigned space_total = isl_space_dim(bmap->dim, isl_dim_all);
520 unsigned pos = space_total + div;
522 last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
523 if (last_div < 0 || last_div <= div)
524 return 1;
526 for (k = 0; k <= last_div; ++k) {
527 if (isl_int_is_zero(bmap->div[k][0]))
528 return 1;
529 if (!isl_int_is_zero(bmap->div[k][1 + 1 + pos]))
530 return 0;
533 return 1;
536 /* Elimininate divs based on equalities
538 static struct isl_basic_map *eliminate_divs_eq(
539 struct isl_basic_map *bmap, int *progress)
541 int d;
542 int i;
543 int modified = 0;
544 unsigned off;
546 bmap = isl_basic_map_order_divs(bmap);
548 if (!bmap)
549 return NULL;
551 off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
553 for (d = bmap->n_div - 1; d >= 0 ; --d) {
554 for (i = 0; i < bmap->n_eq; ++i) {
555 if (!isl_int_is_one(bmap->eq[i][off + d]) &&
556 !isl_int_is_negone(bmap->eq[i][off + d]))
557 continue;
558 if (!ok_to_eliminate_div(bmap, bmap->eq[i], d))
559 continue;
560 modified = 1;
561 *progress = 1;
562 bmap = eliminate_div(bmap, bmap->eq[i], d, 1);
563 if (isl_basic_map_drop_equality(bmap, i) < 0)
564 return isl_basic_map_free(bmap);
565 break;
568 if (modified)
569 return eliminate_divs_eq(bmap, progress);
570 return bmap;
573 /* Elimininate divs based on inequalities
575 static struct isl_basic_map *eliminate_divs_ineq(
576 struct isl_basic_map *bmap, int *progress)
578 int d;
579 int i;
580 unsigned off;
581 struct isl_ctx *ctx;
583 if (!bmap)
584 return NULL;
586 ctx = bmap->ctx;
587 off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
589 for (d = bmap->n_div - 1; d >= 0 ; --d) {
590 for (i = 0; i < bmap->n_eq; ++i)
591 if (!isl_int_is_zero(bmap->eq[i][off + d]))
592 break;
593 if (i < bmap->n_eq)
594 continue;
595 for (i = 0; i < bmap->n_ineq; ++i)
596 if (isl_int_abs_gt(bmap->ineq[i][off + d], ctx->one))
597 break;
598 if (i < bmap->n_ineq)
599 continue;
600 *progress = 1;
601 bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1);
602 if (!bmap || ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
603 break;
604 bmap = isl_basic_map_drop_div(bmap, d);
605 if (!bmap)
606 break;
608 return bmap;
611 struct isl_basic_map *isl_basic_map_gauss(
612 struct isl_basic_map *bmap, int *progress)
614 int k;
615 int done;
616 int last_var;
617 unsigned total_var;
618 unsigned total;
620 bmap = isl_basic_map_order_divs(bmap);
622 if (!bmap)
623 return NULL;
625 total = isl_basic_map_total_dim(bmap);
626 total_var = total - bmap->n_div;
628 last_var = total - 1;
629 for (done = 0; done < bmap->n_eq; ++done) {
630 for (; last_var >= 0; --last_var) {
631 for (k = done; k < bmap->n_eq; ++k)
632 if (!isl_int_is_zero(bmap->eq[k][1+last_var]))
633 break;
634 if (k < bmap->n_eq)
635 break;
637 if (last_var < 0)
638 break;
639 if (k != done)
640 swap_equality(bmap, k, done);
641 if (isl_int_is_neg(bmap->eq[done][1+last_var]))
642 isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total);
644 eliminate_var_using_equality(bmap, last_var, bmap->eq[done], 1,
645 progress);
647 if (last_var >= total_var &&
648 isl_int_is_zero(bmap->div[last_var - total_var][0])) {
649 unsigned div = last_var - total_var;
650 isl_seq_neg(bmap->div[div]+1, bmap->eq[done], 1+total);
651 isl_int_set_si(bmap->div[div][1+1+last_var], 0);
652 isl_int_set(bmap->div[div][0],
653 bmap->eq[done][1+last_var]);
654 if (progress)
655 *progress = 1;
656 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
659 if (done == bmap->n_eq)
660 return bmap;
661 for (k = done; k < bmap->n_eq; ++k) {
662 if (isl_int_is_zero(bmap->eq[k][0]))
663 continue;
664 return isl_basic_map_set_to_empty(bmap);
666 isl_basic_map_free_equality(bmap, bmap->n_eq-done);
667 return bmap;
670 struct isl_basic_set *isl_basic_set_gauss(
671 struct isl_basic_set *bset, int *progress)
673 return (struct isl_basic_set*)isl_basic_map_gauss(
674 (struct isl_basic_map *)bset, progress);
678 static unsigned int round_up(unsigned int v)
680 int old_v = v;
682 while (v) {
683 old_v = v;
684 v ^= v & -v;
686 return old_v << 1;
689 static int hash_index(isl_int ***index, unsigned int size, int bits,
690 struct isl_basic_map *bmap, int k)
692 int h;
693 unsigned total = isl_basic_map_total_dim(bmap);
694 uint32_t hash = isl_seq_get_hash_bits(bmap->ineq[k]+1, total, bits);
695 for (h = hash; index[h]; h = (h+1) % size)
696 if (&bmap->ineq[k] != index[h] &&
697 isl_seq_eq(bmap->ineq[k]+1, index[h][0]+1, total))
698 break;
699 return h;
702 static int set_hash_index(isl_int ***index, unsigned int size, int bits,
703 struct isl_basic_set *bset, int k)
705 return hash_index(index, size, bits, (struct isl_basic_map *)bset, k);
708 /* If we can eliminate more than one div, then we need to make
709 * sure we do it from last div to first div, in order not to
710 * change the position of the other divs that still need to
711 * be removed.
713 static struct isl_basic_map *remove_duplicate_divs(
714 struct isl_basic_map *bmap, int *progress)
716 unsigned int size;
717 int *index;
718 int *elim_for;
719 int k, l, h;
720 int bits;
721 struct isl_blk eq;
722 unsigned total_var;
723 unsigned total;
724 struct isl_ctx *ctx;
726 bmap = isl_basic_map_order_divs(bmap);
727 if (!bmap || bmap->n_div <= 1)
728 return bmap;
730 total_var = isl_space_dim(bmap->dim, isl_dim_all);
731 total = total_var + bmap->n_div;
733 ctx = bmap->ctx;
734 for (k = bmap->n_div - 1; k >= 0; --k)
735 if (!isl_int_is_zero(bmap->div[k][0]))
736 break;
737 if (k <= 0)
738 return bmap;
740 size = round_up(4 * bmap->n_div / 3 - 1);
741 if (size == 0)
742 return bmap;
743 elim_for = isl_calloc_array(ctx, int, bmap->n_div);
744 bits = ffs(size) - 1;
745 index = isl_calloc_array(ctx, int, size);
746 if (!elim_for || !index)
747 goto out;
748 eq = isl_blk_alloc(ctx, 1+total);
749 if (isl_blk_is_error(eq))
750 goto out;
752 isl_seq_clr(eq.data, 1+total);
753 index[isl_seq_get_hash_bits(bmap->div[k], 2+total, bits)] = k + 1;
754 for (--k; k >= 0; --k) {
755 uint32_t hash;
757 if (isl_int_is_zero(bmap->div[k][0]))
758 continue;
760 hash = isl_seq_get_hash_bits(bmap->div[k], 2+total, bits);
761 for (h = hash; index[h]; h = (h+1) % size)
762 if (isl_seq_eq(bmap->div[k],
763 bmap->div[index[h]-1], 2+total))
764 break;
765 if (index[h]) {
766 *progress = 1;
767 l = index[h] - 1;
768 elim_for[l] = k + 1;
770 index[h] = k+1;
772 for (l = bmap->n_div - 1; l >= 0; --l) {
773 if (!elim_for[l])
774 continue;
775 k = elim_for[l] - 1;
776 isl_int_set_si(eq.data[1+total_var+k], -1);
777 isl_int_set_si(eq.data[1+total_var+l], 1);
778 bmap = eliminate_div(bmap, eq.data, l, 1);
779 if (!bmap)
780 break;
781 isl_int_set_si(eq.data[1+total_var+k], 0);
782 isl_int_set_si(eq.data[1+total_var+l], 0);
785 isl_blk_free(ctx, eq);
786 out:
787 free(index);
788 free(elim_for);
789 return bmap;
792 static int n_pure_div_eq(struct isl_basic_map *bmap)
794 int i, j;
795 unsigned total;
797 total = isl_space_dim(bmap->dim, isl_dim_all);
798 for (i = 0, j = bmap->n_div-1; i < bmap->n_eq; ++i) {
799 while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
800 --j;
801 if (j < 0)
802 break;
803 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, j) != -1)
804 return 0;
806 return i;
809 /* Normalize divs that appear in equalities.
811 * In particular, we assume that bmap contains some equalities
812 * of the form
814 * a x = m * e_i
816 * and we want to replace the set of e_i by a minimal set and
817 * such that the new e_i have a canonical representation in terms
818 * of the vector x.
819 * If any of the equalities involves more than one divs, then
820 * we currently simply bail out.
822 * Let us first additionally assume that all equalities involve
823 * a div. The equalities then express modulo constraints on the
824 * remaining variables and we can use "parameter compression"
825 * to find a minimal set of constraints. The result is a transformation
827 * x = T(x') = x_0 + G x'
829 * with G a lower-triangular matrix with all elements below the diagonal
830 * non-negative and smaller than the diagonal element on the same row.
831 * We first normalize x_0 by making the same property hold in the affine
832 * T matrix.
833 * The rows i of G with a 1 on the diagonal do not impose any modulo
834 * constraint and simply express x_i = x'_i.
835 * For each of the remaining rows i, we introduce a div and a corresponding
836 * equality. In particular
838 * g_ii e_j = x_i - g_i(x')
840 * where each x'_k is replaced either by x_k (if g_kk = 1) or the
841 * corresponding div (if g_kk != 1).
843 * If there are any equalities not involving any div, then we
844 * first apply a variable compression on the variables x:
846 * x = C x'' x'' = C_2 x
848 * and perform the above parameter compression on A C instead of on A.
849 * The resulting compression is then of the form
851 * x'' = T(x') = x_0 + G x'
853 * and in constructing the new divs and the corresponding equalities,
854 * we have to replace each x'', i.e., the x'_k with (g_kk = 1),
855 * by the corresponding row from C_2.
857 static struct isl_basic_map *normalize_divs(
858 struct isl_basic_map *bmap, int *progress)
860 int i, j, k;
861 int total;
862 int div_eq;
863 struct isl_mat *B;
864 struct isl_vec *d;
865 struct isl_mat *T = NULL;
866 struct isl_mat *C = NULL;
867 struct isl_mat *C2 = NULL;
868 isl_int v;
869 int *pos;
870 int dropped, needed;
872 if (!bmap)
873 return NULL;
875 if (bmap->n_div == 0)
876 return bmap;
878 if (bmap->n_eq == 0)
879 return bmap;
881 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS))
882 return bmap;
884 total = isl_space_dim(bmap->dim, isl_dim_all);
885 div_eq = n_pure_div_eq(bmap);
886 if (div_eq == 0)
887 return bmap;
889 if (div_eq < bmap->n_eq) {
890 B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, div_eq,
891 bmap->n_eq - div_eq, 0, 1 + total);
892 C = isl_mat_variable_compression(B, &C2);
893 if (!C || !C2)
894 goto error;
895 if (C->n_col == 0) {
896 bmap = isl_basic_map_set_to_empty(bmap);
897 isl_mat_free(C);
898 isl_mat_free(C2);
899 goto done;
903 d = isl_vec_alloc(bmap->ctx, div_eq);
904 if (!d)
905 goto error;
906 for (i = 0, j = bmap->n_div-1; i < div_eq; ++i) {
907 while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
908 --j;
909 isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j]);
911 B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total);
913 if (C) {
914 B = isl_mat_product(B, C);
915 C = NULL;
918 T = isl_mat_parameter_compression(B, d);
919 if (!T)
920 goto error;
921 if (T->n_col == 0) {
922 bmap = isl_basic_map_set_to_empty(bmap);
923 isl_mat_free(C2);
924 isl_mat_free(T);
925 goto done;
927 isl_int_init(v);
928 for (i = 0; i < T->n_row - 1; ++i) {
929 isl_int_fdiv_q(v, T->row[1 + i][0], T->row[1 + i][1 + i]);
930 if (isl_int_is_zero(v))
931 continue;
932 isl_mat_col_submul(T, 0, v, 1 + i);
934 isl_int_clear(v);
935 pos = isl_alloc_array(bmap->ctx, int, T->n_row);
936 if (!pos)
937 goto error;
938 /* We have to be careful because dropping equalities may reorder them */
939 dropped = 0;
940 for (j = bmap->n_div - 1; j >= 0; --j) {
941 for (i = 0; i < bmap->n_eq; ++i)
942 if (!isl_int_is_zero(bmap->eq[i][1 + total + j]))
943 break;
944 if (i < bmap->n_eq) {
945 bmap = isl_basic_map_drop_div(bmap, j);
946 isl_basic_map_drop_equality(bmap, i);
947 ++dropped;
950 pos[0] = 0;
951 needed = 0;
952 for (i = 1; i < T->n_row; ++i) {
953 if (isl_int_is_one(T->row[i][i]))
954 pos[i] = i;
955 else
956 needed++;
958 if (needed > dropped) {
959 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
960 needed, needed, 0);
961 if (!bmap)
962 goto error;
964 for (i = 1; i < T->n_row; ++i) {
965 if (isl_int_is_one(T->row[i][i]))
966 continue;
967 k = isl_basic_map_alloc_div(bmap);
968 pos[i] = 1 + total + k;
969 isl_seq_clr(bmap->div[k] + 1, 1 + total + bmap->n_div);
970 isl_int_set(bmap->div[k][0], T->row[i][i]);
971 if (C2)
972 isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + total);
973 else
974 isl_int_set_si(bmap->div[k][1 + i], 1);
975 for (j = 0; j < i; ++j) {
976 if (isl_int_is_zero(T->row[i][j]))
977 continue;
978 if (pos[j] < T->n_row && C2)
979 isl_seq_submul(bmap->div[k] + 1, T->row[i][j],
980 C2->row[pos[j]], 1 + total);
981 else
982 isl_int_neg(bmap->div[k][1 + pos[j]],
983 T->row[i][j]);
985 j = isl_basic_map_alloc_equality(bmap);
986 isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+total+bmap->n_div);
987 isl_int_set(bmap->eq[j][pos[i]], bmap->div[k][0]);
989 free(pos);
990 isl_mat_free(C2);
991 isl_mat_free(T);
993 if (progress)
994 *progress = 1;
995 done:
996 ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
998 return bmap;
999 error:
1000 isl_mat_free(C);
1001 isl_mat_free(C2);
1002 isl_mat_free(T);
1003 return bmap;
1006 static struct isl_basic_map *set_div_from_lower_bound(
1007 struct isl_basic_map *bmap, int div, int ineq)
1009 unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1011 isl_seq_neg(bmap->div[div] + 1, bmap->ineq[ineq], total + bmap->n_div);
1012 isl_int_set(bmap->div[div][0], bmap->ineq[ineq][total + div]);
1013 isl_int_add(bmap->div[div][1], bmap->div[div][1], bmap->div[div][0]);
1014 isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
1015 isl_int_set_si(bmap->div[div][1 + total + div], 0);
1017 return bmap;
1020 /* Check whether it is ok to define a div based on an inequality.
1021 * To avoid the introduction of circular definitions of divs, we
1022 * do not allow such a definition if the resulting expression would refer to
1023 * any other undefined divs or if any known div is defined in
1024 * terms of the unknown div.
1026 static int ok_to_set_div_from_bound(struct isl_basic_map *bmap,
1027 int div, int ineq)
1029 int j;
1030 unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1032 /* Not defined in terms of unknown divs */
1033 for (j = 0; j < bmap->n_div; ++j) {
1034 if (div == j)
1035 continue;
1036 if (isl_int_is_zero(bmap->ineq[ineq][total + j]))
1037 continue;
1038 if (isl_int_is_zero(bmap->div[j][0]))
1039 return 0;
1042 /* No other div defined in terms of this one => avoid loops */
1043 for (j = 0; j < bmap->n_div; ++j) {
1044 if (div == j)
1045 continue;
1046 if (isl_int_is_zero(bmap->div[j][0]))
1047 continue;
1048 if (!isl_int_is_zero(bmap->div[j][1 + total + div]))
1049 return 0;
1052 return 1;
1055 /* Would an expression for div "div" based on inequality "ineq" of "bmap"
1056 * be a better expression than the current one?
1058 * If we do not have any expression yet, then any expression would be better.
1059 * Otherwise we check if the last variable involved in the inequality
1060 * (disregarding the div that it would define) is in an earlier position
1061 * than the last variable involved in the current div expression.
1063 static int better_div_constraint(__isl_keep isl_basic_map *bmap,
1064 int div, int ineq)
1066 unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1067 int last_div;
1068 int last_ineq;
1070 if (isl_int_is_zero(bmap->div[div][0]))
1071 return 1;
1073 if (isl_seq_last_non_zero(bmap->ineq[ineq] + total + div + 1,
1074 bmap->n_div - (div + 1)) >= 0)
1075 return 0;
1077 last_ineq = isl_seq_last_non_zero(bmap->ineq[ineq], total + div);
1078 last_div = isl_seq_last_non_zero(bmap->div[div] + 1,
1079 total + bmap->n_div);
1081 return last_ineq < last_div;
1084 /* Given two constraints "k" and "l" that are opposite to each other,
1085 * except for the constant term, check if we can use them
1086 * to obtain an expression for one of the hitherto unknown divs or
1087 * a "better" expression for a div for which we already have an expression.
1088 * "sum" is the sum of the constant terms of the constraints.
1089 * If this sum is strictly smaller than the coefficient of one
1090 * of the divs, then this pair can be used define the div.
1091 * To avoid the introduction of circular definitions of divs, we
1092 * do not use the pair if the resulting expression would refer to
1093 * any other undefined divs or if any known div is defined in
1094 * terms of the unknown div.
1096 static struct isl_basic_map *check_for_div_constraints(
1097 struct isl_basic_map *bmap, int k, int l, isl_int sum, int *progress)
1099 int i;
1100 unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1102 for (i = 0; i < bmap->n_div; ++i) {
1103 if (isl_int_is_zero(bmap->ineq[k][total + i]))
1104 continue;
1105 if (isl_int_abs_ge(sum, bmap->ineq[k][total + i]))
1106 continue;
1107 if (!better_div_constraint(bmap, i, k))
1108 continue;
1109 if (!ok_to_set_div_from_bound(bmap, i, k))
1110 break;
1111 if (isl_int_is_pos(bmap->ineq[k][total + i]))
1112 bmap = set_div_from_lower_bound(bmap, i, k);
1113 else
1114 bmap = set_div_from_lower_bound(bmap, i, l);
1115 if (progress)
1116 *progress = 1;
1117 break;
1119 return bmap;
1122 __isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
1123 __isl_take isl_basic_map *bmap, int *progress, int detect_divs)
1125 unsigned int size;
1126 isl_int ***index;
1127 int k, l, h;
1128 int bits;
1129 unsigned total = isl_basic_map_total_dim(bmap);
1130 isl_int sum;
1131 isl_ctx *ctx;
1133 if (!bmap || bmap->n_ineq <= 1)
1134 return bmap;
1136 size = round_up(4 * (bmap->n_ineq+1) / 3 - 1);
1137 if (size == 0)
1138 return bmap;
1139 bits = ffs(size) - 1;
1140 ctx = isl_basic_map_get_ctx(bmap);
1141 index = isl_calloc_array(ctx, isl_int **, size);
1142 if (!index)
1143 return bmap;
1145 index[isl_seq_get_hash_bits(bmap->ineq[0]+1, total, bits)] = &bmap->ineq[0];
1146 for (k = 1; k < bmap->n_ineq; ++k) {
1147 h = hash_index(index, size, bits, bmap, k);
1148 if (!index[h]) {
1149 index[h] = &bmap->ineq[k];
1150 continue;
1152 if (progress)
1153 *progress = 1;
1154 l = index[h] - &bmap->ineq[0];
1155 if (isl_int_lt(bmap->ineq[k][0], bmap->ineq[l][0]))
1156 swap_inequality(bmap, k, l);
1157 isl_basic_map_drop_inequality(bmap, k);
1158 --k;
1160 isl_int_init(sum);
1161 for (k = 0; k < bmap->n_ineq-1; ++k) {
1162 isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
1163 h = hash_index(index, size, bits, bmap, k);
1164 isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
1165 if (!index[h])
1166 continue;
1167 l = index[h] - &bmap->ineq[0];
1168 isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0]);
1169 if (isl_int_is_pos(sum)) {
1170 if (detect_divs)
1171 bmap = check_for_div_constraints(bmap, k, l,
1172 sum, progress);
1173 continue;
1175 if (isl_int_is_zero(sum)) {
1176 /* We need to break out of the loop after these
1177 * changes since the contents of the hash
1178 * will no longer be valid.
1179 * Plus, we probably we want to regauss first.
1181 if (progress)
1182 *progress = 1;
1183 isl_basic_map_drop_inequality(bmap, l);
1184 isl_basic_map_inequality_to_equality(bmap, k);
1185 } else
1186 bmap = isl_basic_map_set_to_empty(bmap);
1187 break;
1189 isl_int_clear(sum);
1191 free(index);
1192 return bmap;
1195 /* Detect all pairs of inequalities that form an equality.
1197 * isl_basic_map_remove_duplicate_constraints detects at most one such pair.
1198 * Call it repeatedly while it is making progress.
1200 __isl_give isl_basic_map *isl_basic_map_detect_inequality_pairs(
1201 __isl_take isl_basic_map *bmap, int *progress)
1203 int duplicate;
1205 do {
1206 duplicate = 0;
1207 bmap = isl_basic_map_remove_duplicate_constraints(bmap,
1208 &duplicate, 0);
1209 if (progress && duplicate)
1210 *progress = 1;
1211 } while (duplicate);
1213 return bmap;
1216 /* Eliminate knowns divs from constraints where they appear with
1217 * a (positive or negative) unit coefficient.
1219 * That is, replace
1221 * floor(e/m) + f >= 0
1223 * by
1225 * e + m f >= 0
1227 * and
1229 * -floor(e/m) + f >= 0
1231 * by
1233 * -e + m f + m - 1 >= 0
1235 * The first conversion is valid because floor(e/m) >= -f is equivalent
1236 * to e/m >= -f because -f is an integral expression.
1237 * The second conversion follows from the fact that
1239 * -floor(e/m) = ceil(-e/m) = floor((-e + m - 1)/m)
1242 * Note that one of the div constraints may have been eliminated
1243 * due to being redundant with respect to the constraint that is
1244 * being modified by this function. The modified constraint may
1245 * no longer imply this div constraint, so we add it back to make
1246 * sure we do not lose any information.
1248 * We skip integral divs, i.e., those with denominator 1, as we would
1249 * risk eliminating the div from the div constraints. We do not need
1250 * to handle those divs here anyway since the div constraints will turn
1251 * out to form an equality and this equality can then be use to eliminate
1252 * the div from all constraints.
1254 static __isl_give isl_basic_map *eliminate_unit_divs(
1255 __isl_take isl_basic_map *bmap, int *progress)
1257 int i, j;
1258 isl_ctx *ctx;
1259 unsigned total;
1261 if (!bmap)
1262 return NULL;
1264 ctx = isl_basic_map_get_ctx(bmap);
1265 total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
1267 for (i = 0; i < bmap->n_div; ++i) {
1268 if (isl_int_is_zero(bmap->div[i][0]))
1269 continue;
1270 if (isl_int_is_one(bmap->div[i][0]))
1271 continue;
1272 for (j = 0; j < bmap->n_ineq; ++j) {
1273 int s;
1275 if (!isl_int_is_one(bmap->ineq[j][total + i]) &&
1276 !isl_int_is_negone(bmap->ineq[j][total + i]))
1277 continue;
1279 *progress = 1;
1281 s = isl_int_sgn(bmap->ineq[j][total + i]);
1282 isl_int_set_si(bmap->ineq[j][total + i], 0);
1283 if (s < 0)
1284 isl_seq_combine(bmap->ineq[j],
1285 ctx->negone, bmap->div[i] + 1,
1286 bmap->div[i][0], bmap->ineq[j],
1287 total + bmap->n_div);
1288 else
1289 isl_seq_combine(bmap->ineq[j],
1290 ctx->one, bmap->div[i] + 1,
1291 bmap->div[i][0], bmap->ineq[j],
1292 total + bmap->n_div);
1293 if (s < 0) {
1294 isl_int_add(bmap->ineq[j][0],
1295 bmap->ineq[j][0], bmap->div[i][0]);
1296 isl_int_sub_ui(bmap->ineq[j][0],
1297 bmap->ineq[j][0], 1);
1300 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1301 if (isl_basic_map_add_div_constraint(bmap, i, s) < 0)
1302 return isl_basic_map_free(bmap);
1306 return bmap;
1309 struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap)
1311 int progress = 1;
1312 if (!bmap)
1313 return NULL;
1314 while (progress) {
1315 progress = 0;
1316 if (!bmap)
1317 break;
1318 if (isl_basic_map_plain_is_empty(bmap))
1319 break;
1320 bmap = isl_basic_map_normalize_constraints(bmap);
1321 bmap = normalize_div_expressions(bmap);
1322 bmap = remove_duplicate_divs(bmap, &progress);
1323 bmap = eliminate_unit_divs(bmap, &progress);
1324 bmap = eliminate_divs_eq(bmap, &progress);
1325 bmap = eliminate_divs_ineq(bmap, &progress);
1326 bmap = isl_basic_map_gauss(bmap, &progress);
1327 /* requires equalities in normal form */
1328 bmap = normalize_divs(bmap, &progress);
1329 bmap = isl_basic_map_remove_duplicate_constraints(bmap,
1330 &progress, 1);
1331 if (bmap && progress)
1332 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1334 return bmap;
1337 struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset)
1339 return (struct isl_basic_set *)
1340 isl_basic_map_simplify((struct isl_basic_map *)bset);
1344 int isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap,
1345 isl_int *constraint, unsigned div)
1347 unsigned pos;
1349 if (!bmap)
1350 return -1;
1352 pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
1354 if (isl_int_eq(constraint[pos], bmap->div[div][0])) {
1355 int neg;
1356 isl_int_sub(bmap->div[div][1],
1357 bmap->div[div][1], bmap->div[div][0]);
1358 isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1);
1359 neg = isl_seq_is_neg(constraint, bmap->div[div]+1, pos);
1360 isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
1361 isl_int_add(bmap->div[div][1],
1362 bmap->div[div][1], bmap->div[div][0]);
1363 if (!neg)
1364 return 0;
1365 if (isl_seq_first_non_zero(constraint+pos+1,
1366 bmap->n_div-div-1) != -1)
1367 return 0;
1368 } else if (isl_int_abs_eq(constraint[pos], bmap->div[div][0])) {
1369 if (!isl_seq_eq(constraint, bmap->div[div]+1, pos))
1370 return 0;
1371 if (isl_seq_first_non_zero(constraint+pos+1,
1372 bmap->n_div-div-1) != -1)
1373 return 0;
1374 } else
1375 return 0;
1377 return 1;
1380 int isl_basic_set_is_div_constraint(__isl_keep isl_basic_set *bset,
1381 isl_int *constraint, unsigned div)
1383 return isl_basic_map_is_div_constraint(bset, constraint, div);
1387 /* If the only constraints a div d=floor(f/m)
1388 * appears in are its two defining constraints
1390 * f - m d >=0
1391 * -(f - (m - 1)) + m d >= 0
1393 * then it can safely be removed.
1395 static int div_is_redundant(struct isl_basic_map *bmap, int div)
1397 int i;
1398 unsigned pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
1400 for (i = 0; i < bmap->n_eq; ++i)
1401 if (!isl_int_is_zero(bmap->eq[i][pos]))
1402 return 0;
1404 for (i = 0; i < bmap->n_ineq; ++i) {
1405 if (isl_int_is_zero(bmap->ineq[i][pos]))
1406 continue;
1407 if (!isl_basic_map_is_div_constraint(bmap, bmap->ineq[i], div))
1408 return 0;
1411 for (i = 0; i < bmap->n_div; ++i) {
1412 if (isl_int_is_zero(bmap->div[i][0]))
1413 continue;
1414 if (!isl_int_is_zero(bmap->div[i][1+pos]))
1415 return 0;
1418 return 1;
1422 * Remove divs that don't occur in any of the constraints or other divs.
1423 * These can arise when dropping constraints from a basic map or
1424 * when the divs of a basic map have been temporarily aligned
1425 * with the divs of another basic map.
1427 static struct isl_basic_map *remove_redundant_divs(struct isl_basic_map *bmap)
1429 int i;
1431 if (!bmap)
1432 return NULL;
1434 for (i = bmap->n_div-1; i >= 0; --i) {
1435 if (!div_is_redundant(bmap, i))
1436 continue;
1437 bmap = isl_basic_map_drop_div(bmap, i);
1439 return bmap;
1442 struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap)
1444 bmap = remove_redundant_divs(bmap);
1445 if (!bmap)
1446 return NULL;
1447 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1448 return bmap;
1451 struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset)
1453 return (struct isl_basic_set *)
1454 isl_basic_map_finalize((struct isl_basic_map *)bset);
1457 struct isl_set *isl_set_finalize(struct isl_set *set)
1459 int i;
1461 if (!set)
1462 return NULL;
1463 for (i = 0; i < set->n; ++i) {
1464 set->p[i] = isl_basic_set_finalize(set->p[i]);
1465 if (!set->p[i])
1466 goto error;
1468 return set;
1469 error:
1470 isl_set_free(set);
1471 return NULL;
1474 struct isl_map *isl_map_finalize(struct isl_map *map)
1476 int i;
1478 if (!map)
1479 return NULL;
1480 for (i = 0; i < map->n; ++i) {
1481 map->p[i] = isl_basic_map_finalize(map->p[i]);
1482 if (!map->p[i])
1483 goto error;
1485 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
1486 return map;
1487 error:
1488 isl_map_free(map);
1489 return NULL;
1493 /* Remove definition of any div that is defined in terms of the given variable.
1494 * The div itself is not removed. Functions such as
1495 * eliminate_divs_ineq depend on the other divs remaining in place.
1497 static struct isl_basic_map *remove_dependent_vars(struct isl_basic_map *bmap,
1498 int pos)
1500 int i;
1502 if (!bmap)
1503 return NULL;
1505 for (i = 0; i < bmap->n_div; ++i) {
1506 if (isl_int_is_zero(bmap->div[i][0]))
1507 continue;
1508 if (isl_int_is_zero(bmap->div[i][1+1+pos]))
1509 continue;
1510 isl_int_set_si(bmap->div[i][0], 0);
1512 return bmap;
1515 /* Eliminate the specified variables from the constraints using
1516 * Fourier-Motzkin. The variables themselves are not removed.
1518 struct isl_basic_map *isl_basic_map_eliminate_vars(
1519 struct isl_basic_map *bmap, unsigned pos, unsigned n)
1521 int d;
1522 int i, j, k;
1523 unsigned total;
1524 int need_gauss = 0;
1526 if (n == 0)
1527 return bmap;
1528 if (!bmap)
1529 return NULL;
1530 total = isl_basic_map_total_dim(bmap);
1532 bmap = isl_basic_map_cow(bmap);
1533 for (d = pos + n - 1; d >= 0 && d >= pos; --d)
1534 bmap = remove_dependent_vars(bmap, d);
1535 if (!bmap)
1536 return NULL;
1538 for (d = pos + n - 1;
1539 d >= 0 && d >= total - bmap->n_div && d >= pos; --d)
1540 isl_seq_clr(bmap->div[d-(total-bmap->n_div)], 2+total);
1541 for (d = pos + n - 1; d >= 0 && d >= pos; --d) {
1542 int n_lower, n_upper;
1543 if (!bmap)
1544 return NULL;
1545 for (i = 0; i < bmap->n_eq; ++i) {
1546 if (isl_int_is_zero(bmap->eq[i][1+d]))
1547 continue;
1548 eliminate_var_using_equality(bmap, d, bmap->eq[i], 0, NULL);
1549 isl_basic_map_drop_equality(bmap, i);
1550 need_gauss = 1;
1551 break;
1553 if (i < bmap->n_eq)
1554 continue;
1555 n_lower = 0;
1556 n_upper = 0;
1557 for (i = 0; i < bmap->n_ineq; ++i) {
1558 if (isl_int_is_pos(bmap->ineq[i][1+d]))
1559 n_lower++;
1560 else if (isl_int_is_neg(bmap->ineq[i][1+d]))
1561 n_upper++;
1563 bmap = isl_basic_map_extend_constraints(bmap,
1564 0, n_lower * n_upper);
1565 if (!bmap)
1566 goto error;
1567 for (i = bmap->n_ineq - 1; i >= 0; --i) {
1568 int last;
1569 if (isl_int_is_zero(bmap->ineq[i][1+d]))
1570 continue;
1571 last = -1;
1572 for (j = 0; j < i; ++j) {
1573 if (isl_int_is_zero(bmap->ineq[j][1+d]))
1574 continue;
1575 last = j;
1576 if (isl_int_sgn(bmap->ineq[i][1+d]) ==
1577 isl_int_sgn(bmap->ineq[j][1+d]))
1578 continue;
1579 k = isl_basic_map_alloc_inequality(bmap);
1580 if (k < 0)
1581 goto error;
1582 isl_seq_cpy(bmap->ineq[k], bmap->ineq[i],
1583 1+total);
1584 isl_seq_elim(bmap->ineq[k], bmap->ineq[j],
1585 1+d, 1+total, NULL);
1587 isl_basic_map_drop_inequality(bmap, i);
1588 i = last + 1;
1590 if (n_lower > 0 && n_upper > 0) {
1591 bmap = isl_basic_map_normalize_constraints(bmap);
1592 bmap = isl_basic_map_remove_duplicate_constraints(bmap,
1593 NULL, 0);
1594 bmap = isl_basic_map_gauss(bmap, NULL);
1595 bmap = isl_basic_map_remove_redundancies(bmap);
1596 need_gauss = 0;
1597 if (!bmap)
1598 goto error;
1599 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
1600 break;
1603 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1604 if (need_gauss)
1605 bmap = isl_basic_map_gauss(bmap, NULL);
1606 return bmap;
1607 error:
1608 isl_basic_map_free(bmap);
1609 return NULL;
1612 struct isl_basic_set *isl_basic_set_eliminate_vars(
1613 struct isl_basic_set *bset, unsigned pos, unsigned n)
1615 return (struct isl_basic_set *)isl_basic_map_eliminate_vars(
1616 (struct isl_basic_map *)bset, pos, n);
1619 /* Eliminate the specified n dimensions starting at first from the
1620 * constraints, without removing the dimensions from the space.
1621 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1622 * Otherwise, they are projected out and the original space is restored.
1624 __isl_give isl_basic_map *isl_basic_map_eliminate(
1625 __isl_take isl_basic_map *bmap,
1626 enum isl_dim_type type, unsigned first, unsigned n)
1628 isl_space *space;
1630 if (!bmap)
1631 return NULL;
1632 if (n == 0)
1633 return bmap;
1635 if (first + n > isl_basic_map_dim(bmap, type) || first + n < first)
1636 isl_die(bmap->ctx, isl_error_invalid,
1637 "index out of bounds", goto error);
1639 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
1640 first += isl_basic_map_offset(bmap, type) - 1;
1641 bmap = isl_basic_map_eliminate_vars(bmap, first, n);
1642 return isl_basic_map_finalize(bmap);
1645 space = isl_basic_map_get_space(bmap);
1646 bmap = isl_basic_map_project_out(bmap, type, first, n);
1647 bmap = isl_basic_map_insert_dims(bmap, type, first, n);
1648 bmap = isl_basic_map_reset_space(bmap, space);
1649 return bmap;
1650 error:
1651 isl_basic_map_free(bmap);
1652 return NULL;
1655 __isl_give isl_basic_set *isl_basic_set_eliminate(
1656 __isl_take isl_basic_set *bset,
1657 enum isl_dim_type type, unsigned first, unsigned n)
1659 return isl_basic_map_eliminate(bset, type, first, n);
1662 /* Don't assume equalities are in order, because align_divs
1663 * may have changed the order of the divs.
1665 static void compute_elimination_index(struct isl_basic_map *bmap, int *elim)
1667 int d, i;
1668 unsigned total;
1670 total = isl_space_dim(bmap->dim, isl_dim_all);
1671 for (d = 0; d < total; ++d)
1672 elim[d] = -1;
1673 for (i = 0; i < bmap->n_eq; ++i) {
1674 for (d = total - 1; d >= 0; --d) {
1675 if (isl_int_is_zero(bmap->eq[i][1+d]))
1676 continue;
1677 elim[d] = i;
1678 break;
1683 static void set_compute_elimination_index(struct isl_basic_set *bset, int *elim)
1685 compute_elimination_index((struct isl_basic_map *)bset, elim);
1688 static int reduced_using_equalities(isl_int *dst, isl_int *src,
1689 struct isl_basic_map *bmap, int *elim)
1691 int d;
1692 int copied = 0;
1693 unsigned total;
1695 total = isl_space_dim(bmap->dim, isl_dim_all);
1696 for (d = total - 1; d >= 0; --d) {
1697 if (isl_int_is_zero(src[1+d]))
1698 continue;
1699 if (elim[d] == -1)
1700 continue;
1701 if (!copied) {
1702 isl_seq_cpy(dst, src, 1 + total);
1703 copied = 1;
1705 isl_seq_elim(dst, bmap->eq[elim[d]], 1 + d, 1 + total, NULL);
1707 return copied;
1710 static int set_reduced_using_equalities(isl_int *dst, isl_int *src,
1711 struct isl_basic_set *bset, int *elim)
1713 return reduced_using_equalities(dst, src,
1714 (struct isl_basic_map *)bset, elim);
1717 static struct isl_basic_set *isl_basic_set_reduce_using_equalities(
1718 struct isl_basic_set *bset, struct isl_basic_set *context)
1720 int i;
1721 int *elim;
1723 if (!bset || !context)
1724 goto error;
1726 if (context->n_eq == 0) {
1727 isl_basic_set_free(context);
1728 return bset;
1731 bset = isl_basic_set_cow(bset);
1732 if (!bset)
1733 goto error;
1735 elim = isl_alloc_array(bset->ctx, int, isl_basic_set_n_dim(bset));
1736 if (!elim)
1737 goto error;
1738 set_compute_elimination_index(context, elim);
1739 for (i = 0; i < bset->n_eq; ++i)
1740 set_reduced_using_equalities(bset->eq[i], bset->eq[i],
1741 context, elim);
1742 for (i = 0; i < bset->n_ineq; ++i)
1743 set_reduced_using_equalities(bset->ineq[i], bset->ineq[i],
1744 context, elim);
1745 isl_basic_set_free(context);
1746 free(elim);
1747 bset = isl_basic_set_simplify(bset);
1748 bset = isl_basic_set_finalize(bset);
1749 return bset;
1750 error:
1751 isl_basic_set_free(bset);
1752 isl_basic_set_free(context);
1753 return NULL;
1756 static struct isl_basic_set *remove_shifted_constraints(
1757 struct isl_basic_set *bset, struct isl_basic_set *context)
1759 unsigned int size;
1760 isl_int ***index;
1761 int bits;
1762 int k, h, l;
1763 isl_ctx *ctx;
1765 if (!bset || !context)
1766 return bset;
1768 size = round_up(4 * (context->n_ineq+1) / 3 - 1);
1769 if (size == 0)
1770 return bset;
1771 bits = ffs(size) - 1;
1772 ctx = isl_basic_set_get_ctx(bset);
1773 index = isl_calloc_array(ctx, isl_int **, size);
1774 if (!index)
1775 return bset;
1777 for (k = 0; k < context->n_ineq; ++k) {
1778 h = set_hash_index(index, size, bits, context, k);
1779 index[h] = &context->ineq[k];
1781 for (k = 0; k < bset->n_ineq; ++k) {
1782 h = set_hash_index(index, size, bits, bset, k);
1783 if (!index[h])
1784 continue;
1785 l = index[h] - &context->ineq[0];
1786 if (isl_int_lt(bset->ineq[k][0], context->ineq[l][0]))
1787 continue;
1788 bset = isl_basic_set_cow(bset);
1789 if (!bset)
1790 goto error;
1791 isl_basic_set_drop_inequality(bset, k);
1792 --k;
1794 free(index);
1795 return bset;
1796 error:
1797 free(index);
1798 return bset;
1801 /* Remove constraints from "bmap" that are identical to constraints
1802 * in "context" or that are more relaxed (greater constant term).
1804 * We perform the test for shifted copies on the pure constraints
1805 * in remove_shifted_constraints.
1807 static __isl_give isl_basic_map *isl_basic_map_remove_shifted_constraints(
1808 __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context)
1810 isl_basic_set *bset, *bset_context;
1812 if (!bmap || !context)
1813 goto error;
1815 if (bmap->n_ineq == 0 || context->n_ineq == 0) {
1816 isl_basic_map_free(context);
1817 return bmap;
1820 context = isl_basic_map_align_divs(context, bmap);
1821 bmap = isl_basic_map_align_divs(bmap, context);
1823 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
1824 bset_context = isl_basic_map_underlying_set(context);
1825 bset = remove_shifted_constraints(bset, bset_context);
1826 isl_basic_set_free(bset_context);
1828 bmap = isl_basic_map_overlying_set(bset, bmap);
1830 return bmap;
1831 error:
1832 isl_basic_map_free(bmap);
1833 isl_basic_map_free(context);
1834 return NULL;
1837 /* Does the (linear part of a) constraint "c" involve any of the "len"
1838 * "relevant" dimensions?
1840 static int is_related(isl_int *c, int len, int *relevant)
1842 int i;
1844 for (i = 0; i < len; ++i) {
1845 if (!relevant[i])
1846 continue;
1847 if (!isl_int_is_zero(c[i]))
1848 return 1;
1851 return 0;
1854 /* Drop constraints from "bset" that do not involve any of
1855 * the dimensions marked "relevant".
1857 static __isl_give isl_basic_set *drop_unrelated_constraints(
1858 __isl_take isl_basic_set *bset, int *relevant)
1860 int i, dim;
1862 dim = isl_basic_set_dim(bset, isl_dim_set);
1863 for (i = 0; i < dim; ++i)
1864 if (!relevant[i])
1865 break;
1866 if (i >= dim)
1867 return bset;
1869 for (i = bset->n_eq - 1; i >= 0; --i)
1870 if (!is_related(bset->eq[i] + 1, dim, relevant))
1871 isl_basic_set_drop_equality(bset, i);
1873 for (i = bset->n_ineq - 1; i >= 0; --i)
1874 if (!is_related(bset->ineq[i] + 1, dim, relevant))
1875 isl_basic_set_drop_inequality(bset, i);
1877 return bset;
1880 /* Update the groups in "group" based on the (linear part of a) constraint "c".
1882 * In particular, for any variable involved in the constraint,
1883 * find the actual group id from before and replace the group
1884 * of the corresponding variable by the minimal group of all
1885 * the variables involved in the constraint considered so far
1886 * (if this minimum is smaller) or replace the minimum by this group
1887 * (if the minimum is larger).
1889 * At the end, all the variables in "c" will (indirectly) point
1890 * to the minimal of the groups that they referred to originally.
1892 static void update_groups(int dim, int *group, isl_int *c)
1894 int j;
1895 int min = dim;
1897 for (j = 0; j < dim; ++j) {
1898 if (isl_int_is_zero(c[j]))
1899 continue;
1900 while (group[j] >= 0 && group[group[j]] != group[j])
1901 group[j] = group[group[j]];
1902 if (group[j] == min)
1903 continue;
1904 if (group[j] < min) {
1905 if (min >= 0 && min < dim)
1906 group[min] = group[j];
1907 min = group[j];
1908 } else
1909 group[group[j]] = min;
1913 /* Drop constraints from "context" that are irrelevant for computing
1914 * the gist of "bset".
1916 * In particular, drop constraints in variables that are not related
1917 * to any of the variables involved in the constraints of "bset"
1918 * in the sense that there is no sequence of constraints that connects them.
1920 * We construct groups of variables that collect variables that
1921 * (indirectly) appear in some common constraint of "context".
1922 * Each group is identified by the first variable in the group,
1923 * except for the special group of variables that appear in "bset"
1924 * (or are related to those variables), which is identified by -1.
1925 * If group[i] is equal to i (or -1), then the group of i is i (or -1),
1926 * otherwise the group of i is the group of group[i].
1928 * We first initialize the -1 group with the variables that appear in "bset".
1929 * Then we initialize groups for the remaining variables.
1930 * Then we iterate over the constraints of "context" and update the
1931 * group of the variables in the constraint by the smallest group.
1932 * Finally, we resolve indirect references to groups by running over
1933 * the variables.
1935 * After computing the groups, we drop constraints that do not involve
1936 * any variables in the -1 group.
1938 static __isl_give isl_basic_set *drop_irrelevant_constraints(
1939 __isl_take isl_basic_set *context, __isl_keep isl_basic_set *bset)
1941 isl_ctx *ctx;
1942 int *group;
1943 int dim;
1944 int i, j;
1945 int last;
1947 if (!context || !bset)
1948 return isl_basic_set_free(context);
1950 dim = isl_basic_set_dim(bset, isl_dim_set);
1951 ctx = isl_basic_set_get_ctx(bset);
1952 group = isl_calloc_array(ctx, int, dim);
1954 if (!group)
1955 goto error;
1957 for (i = 0; i < dim; ++i) {
1958 for (j = 0; j < bset->n_eq; ++j)
1959 if (!isl_int_is_zero(bset->eq[j][1 + i]))
1960 break;
1961 if (j < bset->n_eq) {
1962 group[i] = -1;
1963 continue;
1965 for (j = 0; j < bset->n_ineq; ++j)
1966 if (!isl_int_is_zero(bset->ineq[j][1 + i]))
1967 break;
1968 if (j < bset->n_ineq)
1969 group[i] = -1;
1972 last = -1;
1973 for (i = 0; i < dim; ++i)
1974 if (group[i] >= 0)
1975 last = group[i] = i;
1976 if (last < 0) {
1977 free(group);
1978 return context;
1981 for (i = 0; i < context->n_eq; ++i)
1982 update_groups(dim, group, context->eq[i] + 1);
1983 for (i = 0; i < context->n_ineq; ++i)
1984 update_groups(dim, group, context->ineq[i] + 1);
1986 for (i = 0; i < dim; ++i)
1987 if (group[i] >= 0)
1988 group[i] = group[group[i]];
1990 for (i = 0; i < dim; ++i)
1991 group[i] = group[i] == -1;
1993 context = drop_unrelated_constraints(context, group);
1995 free(group);
1996 return context;
1997 error:
1998 free(group);
1999 return isl_basic_set_free(context);
2002 /* Remove all information from bset that is redundant in the context
2003 * of context. Both bset and context are assumed to be full-dimensional.
2005 * We first remove the inequalities from "bset"
2006 * that are obviously redundant with respect to some inequality in "context".
2007 * Then we remove those constraints from "context" that have become
2008 * irrelevant for computing the gist of "bset".
2009 * Note that this removal of constraints cannot be replaced by
2010 * a factorization because factors in "bset" may still be connected
2011 * to each other through constraints in "context".
2013 * If there are any inequalities left, we construct a tableau for
2014 * the context and then add the inequalities of "bset".
2015 * Before adding these inequalities, we freeze all constraints such that
2016 * they won't be considered redundant in terms of the constraints of "bset".
2017 * Then we detect all redundant constraints (among the
2018 * constraints that weren't frozen), first by checking for redundancy in the
2019 * the tableau and then by checking if replacing a constraint by its negation
2020 * would lead to an empty set. This last step is fairly expensive
2021 * and could be optimized by more reuse of the tableau.
2022 * Finally, we update bset according to the results.
2024 static __isl_give isl_basic_set *uset_gist_full(__isl_take isl_basic_set *bset,
2025 __isl_take isl_basic_set *context)
2027 int i, k;
2028 isl_basic_set *combined = NULL;
2029 struct isl_tab *tab = NULL;
2030 unsigned context_ineq;
2031 unsigned total;
2033 if (!bset || !context)
2034 goto error;
2036 if (isl_basic_set_is_universe(bset)) {
2037 isl_basic_set_free(context);
2038 return bset;
2041 if (isl_basic_set_is_universe(context)) {
2042 isl_basic_set_free(context);
2043 return bset;
2046 bset = remove_shifted_constraints(bset, context);
2047 if (!bset)
2048 goto error;
2049 if (bset->n_ineq == 0)
2050 goto done;
2052 context = drop_irrelevant_constraints(context, bset);
2053 if (!context)
2054 goto error;
2055 if (isl_basic_set_is_universe(context)) {
2056 isl_basic_set_free(context);
2057 return bset;
2060 context_ineq = context->n_ineq;
2061 combined = isl_basic_set_cow(isl_basic_set_copy(context));
2062 combined = isl_basic_set_extend_constraints(combined, 0, bset->n_ineq);
2063 tab = isl_tab_from_basic_set(combined, 0);
2064 for (i = 0; i < context_ineq; ++i)
2065 if (isl_tab_freeze_constraint(tab, i) < 0)
2066 goto error;
2067 if (isl_tab_extend_cons(tab, bset->n_ineq) < 0)
2068 goto error;
2069 for (i = 0; i < bset->n_ineq; ++i)
2070 if (isl_tab_add_ineq(tab, bset->ineq[i]) < 0)
2071 goto error;
2072 bset = isl_basic_set_add_constraints(combined, bset, 0);
2073 combined = NULL;
2074 if (!bset)
2075 goto error;
2076 if (isl_tab_detect_redundant(tab) < 0)
2077 goto error;
2078 total = isl_basic_set_total_dim(bset);
2079 for (i = context_ineq; i < bset->n_ineq; ++i) {
2080 int is_empty;
2081 if (tab->con[i].is_redundant)
2082 continue;
2083 tab->con[i].is_redundant = 1;
2084 combined = isl_basic_set_dup(bset);
2085 combined = isl_basic_set_update_from_tab(combined, tab);
2086 combined = isl_basic_set_extend_constraints(combined, 0, 1);
2087 k = isl_basic_set_alloc_inequality(combined);
2088 if (k < 0)
2089 goto error;
2090 isl_seq_neg(combined->ineq[k], bset->ineq[i], 1 + total);
2091 isl_int_sub_ui(combined->ineq[k][0], combined->ineq[k][0], 1);
2092 is_empty = isl_basic_set_is_empty(combined);
2093 if (is_empty < 0)
2094 goto error;
2095 isl_basic_set_free(combined);
2096 combined = NULL;
2097 if (!is_empty)
2098 tab->con[i].is_redundant = 0;
2100 for (i = 0; i < context_ineq; ++i)
2101 tab->con[i].is_redundant = 1;
2102 bset = isl_basic_set_update_from_tab(bset, tab);
2103 if (bset) {
2104 ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT);
2105 ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT);
2108 isl_tab_free(tab);
2109 done:
2110 bset = isl_basic_set_simplify(bset);
2111 bset = isl_basic_set_finalize(bset);
2112 isl_basic_set_free(context);
2113 return bset;
2114 error:
2115 isl_tab_free(tab);
2116 isl_basic_set_free(combined);
2117 isl_basic_set_free(context);
2118 isl_basic_set_free(bset);
2119 return NULL;
2122 /* Remove all information from bset that is redundant in the context
2123 * of context. In particular, equalities that are linear combinations
2124 * of those in context are removed. Then the inequalities that are
2125 * redundant in the context of the equalities and inequalities of
2126 * context are removed.
2128 * First of all, we drop those constraints from "context"
2129 * that are irrelevant for computing the gist of "bset".
2130 * Alternatively, we could factorize the intersection of "context" and "bset".
2132 * We first compute the integer affine hull of the intersection,
2133 * compute the gist inside this affine hull and then add back
2134 * those equalities that are not implied by the context.
2136 * If two constraints are mutually redundant, then uset_gist_full
2137 * will remove the second of those constraints. We therefore first
2138 * sort the constraints so that constraints not involving existentially
2139 * quantified variables are given precedence over those that do.
2140 * We have to perform this sorting before the variable compression,
2141 * because that may effect the order of the variables.
2143 static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
2144 __isl_take isl_basic_set *context)
2146 isl_mat *eq;
2147 isl_mat *T, *T2;
2148 isl_basic_set *aff;
2149 isl_basic_set *aff_context;
2150 unsigned total;
2152 if (!bset || !context)
2153 goto error;
2155 context = drop_irrelevant_constraints(context, bset);
2157 aff = isl_basic_set_copy(bset);
2158 aff = isl_basic_set_intersect(aff, isl_basic_set_copy(context));
2159 aff = isl_basic_set_affine_hull(aff);
2160 if (!aff)
2161 goto error;
2162 if (isl_basic_set_plain_is_empty(aff)) {
2163 isl_basic_set_free(bset);
2164 isl_basic_set_free(context);
2165 return aff;
2167 bset = isl_basic_set_sort_constraints(bset);
2168 if (aff->n_eq == 0) {
2169 isl_basic_set_free(aff);
2170 return uset_gist_full(bset, context);
2172 total = isl_basic_set_total_dim(bset);
2173 eq = isl_mat_sub_alloc6(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total);
2174 eq = isl_mat_cow(eq);
2175 T = isl_mat_variable_compression(eq, &T2);
2176 if (T && T->n_col == 0) {
2177 isl_mat_free(T);
2178 isl_mat_free(T2);
2179 isl_basic_set_free(context);
2180 isl_basic_set_free(aff);
2181 return isl_basic_set_set_to_empty(bset);
2184 aff_context = isl_basic_set_affine_hull(isl_basic_set_copy(context));
2186 bset = isl_basic_set_preimage(bset, isl_mat_copy(T));
2187 context = isl_basic_set_preimage(context, T);
2189 bset = uset_gist_full(bset, context);
2190 bset = isl_basic_set_preimage(bset, T2);
2191 bset = isl_basic_set_intersect(bset, aff);
2192 bset = isl_basic_set_reduce_using_equalities(bset, aff_context);
2194 if (bset) {
2195 ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT);
2196 ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT);
2199 return bset;
2200 error:
2201 isl_basic_set_free(bset);
2202 isl_basic_set_free(context);
2203 return NULL;
2206 /* Normalize the divs in "bmap" in the context of the equalities in "context".
2207 * We simply add the equalities in context to bmap and then do a regular
2208 * div normalizations. Better results can be obtained by normalizing
2209 * only the divs in bmap than do not also appear in context.
2210 * We need to be careful to reduce the divs using the equalities
2211 * so that later calls to isl_basic_map_overlying_set wouldn't introduce
2212 * spurious constraints.
2214 static struct isl_basic_map *normalize_divs_in_context(
2215 struct isl_basic_map *bmap, struct isl_basic_map *context)
2217 int i;
2218 unsigned total_context;
2219 int div_eq;
2221 div_eq = n_pure_div_eq(bmap);
2222 if (div_eq == 0)
2223 return bmap;
2225 bmap = isl_basic_map_cow(bmap);
2226 if (context->n_div > 0)
2227 bmap = isl_basic_map_align_divs(bmap, context);
2229 total_context = isl_basic_map_total_dim(context);
2230 bmap = isl_basic_map_extend_constraints(bmap, context->n_eq, 0);
2231 for (i = 0; i < context->n_eq; ++i) {
2232 int k;
2233 k = isl_basic_map_alloc_equality(bmap);
2234 if (k < 0)
2235 return isl_basic_map_free(bmap);
2236 isl_seq_cpy(bmap->eq[k], context->eq[i], 1 + total_context);
2237 isl_seq_clr(bmap->eq[k] + 1 + total_context,
2238 isl_basic_map_total_dim(bmap) - total_context);
2240 bmap = isl_basic_map_gauss(bmap, NULL);
2241 bmap = normalize_divs(bmap, NULL);
2242 bmap = isl_basic_map_gauss(bmap, NULL);
2243 return bmap;
2246 /* Return a basic map that has the same intersection with "context" as "bmap"
2247 * and that is as "simple" as possible.
2249 * The core computation is performed on the pure constraints.
2250 * When we add back the meaning of the integer divisions, we need
2251 * to (re)introduce the div constraints. If we happen to have
2252 * discovered that some of these integer divisions are equal to
2253 * some affine combination of other variables, then these div
2254 * constraints may end up getting simplified in terms of the equalities,
2255 * resulting in extra inequalities on the other variables that
2256 * may have been removed already or that may not even have been
2257 * part of the input. We try and remove those constraints of
2258 * this form that are most obviously redundant with respect to
2259 * the context. We also remove those div constraints that are
2260 * redundant with respect to the other constraints in the result.
2262 struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
2263 struct isl_basic_map *context)
2265 isl_basic_set *bset, *eq;
2266 isl_basic_map *eq_bmap;
2267 unsigned n_div, n_eq, n_ineq;
2269 if (!bmap || !context)
2270 goto error;
2272 if (isl_basic_map_is_universe(bmap)) {
2273 isl_basic_map_free(context);
2274 return bmap;
2276 if (isl_basic_map_plain_is_empty(context)) {
2277 isl_space *space = isl_basic_map_get_space(bmap);
2278 isl_basic_map_free(bmap);
2279 isl_basic_map_free(context);
2280 return isl_basic_map_universe(space);
2282 if (isl_basic_map_plain_is_empty(bmap)) {
2283 isl_basic_map_free(context);
2284 return bmap;
2287 bmap = isl_basic_map_remove_redundancies(bmap);
2288 context = isl_basic_map_remove_redundancies(context);
2289 if (!context)
2290 goto error;
2292 if (context->n_eq)
2293 bmap = normalize_divs_in_context(bmap, context);
2295 context = isl_basic_map_align_divs(context, bmap);
2296 bmap = isl_basic_map_align_divs(bmap, context);
2297 n_div = isl_basic_map_dim(bmap, isl_dim_div);
2299 bset = uset_gist(isl_basic_map_underlying_set(isl_basic_map_copy(bmap)),
2300 isl_basic_map_underlying_set(isl_basic_map_copy(context)));
2302 if (!bset || bset->n_eq == 0 || n_div == 0 ||
2303 isl_basic_set_plain_is_empty(bset)) {
2304 isl_basic_map_free(context);
2305 return isl_basic_map_overlying_set(bset, bmap);
2308 n_eq = bset->n_eq;
2309 n_ineq = bset->n_ineq;
2310 eq = isl_basic_set_copy(bset);
2311 eq = isl_basic_set_cow(eq);
2312 if (isl_basic_set_free_inequality(eq, n_ineq) < 0)
2313 eq = isl_basic_set_free(eq);
2314 if (isl_basic_set_free_equality(bset, n_eq) < 0)
2315 bset = isl_basic_set_free(bset);
2317 eq_bmap = isl_basic_map_overlying_set(eq, isl_basic_map_copy(bmap));
2318 eq_bmap = isl_basic_map_remove_shifted_constraints(eq_bmap, context);
2319 bmap = isl_basic_map_overlying_set(bset, bmap);
2320 bmap = isl_basic_map_intersect(bmap, eq_bmap);
2321 bmap = isl_basic_map_remove_redundancies(bmap);
2323 return bmap;
2324 error:
2325 isl_basic_map_free(bmap);
2326 isl_basic_map_free(context);
2327 return NULL;
2331 * Assumes context has no implicit divs.
2333 __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
2334 __isl_take isl_basic_map *context)
2336 int i;
2338 if (!map || !context)
2339 goto error;
2341 if (isl_basic_map_plain_is_empty(context)) {
2342 isl_space *space = isl_map_get_space(map);
2343 isl_map_free(map);
2344 isl_basic_map_free(context);
2345 return isl_map_universe(space);
2348 context = isl_basic_map_remove_redundancies(context);
2349 map = isl_map_cow(map);
2350 if (!map || !context)
2351 goto error;
2352 isl_assert(map->ctx, isl_space_is_equal(map->dim, context->dim), goto error);
2353 map = isl_map_compute_divs(map);
2354 if (!map)
2355 goto error;
2356 for (i = map->n - 1; i >= 0; --i) {
2357 map->p[i] = isl_basic_map_gist(map->p[i],
2358 isl_basic_map_copy(context));
2359 if (!map->p[i])
2360 goto error;
2361 if (isl_basic_map_plain_is_empty(map->p[i])) {
2362 isl_basic_map_free(map->p[i]);
2363 if (i != map->n - 1)
2364 map->p[i] = map->p[map->n - 1];
2365 map->n--;
2368 isl_basic_map_free(context);
2369 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2370 return map;
2371 error:
2372 isl_map_free(map);
2373 isl_basic_map_free(context);
2374 return NULL;
2377 /* Return a map that has the same intersection with "context" as "map"
2378 * and that is as "simple" as possible.
2380 * If "map" is already the universe, then we cannot make it any simpler.
2381 * Similarly, if "context" is the universe, then we cannot exploit it
2382 * to simplify "map"
2383 * If "map" and "context" are identical to each other, then we can
2384 * return the corresponding universe.
2386 * If none of these cases apply, we have to work a bit harder.
2387 * During this computation, we make use of a single disjunct context,
2388 * so if the original context consists of more than one disjunct
2389 * then we need to approximate the context by a single disjunct set.
2390 * Simply taking the simple hull may drop constraints that are
2391 * only implicitly available in each disjunct. We therefore also
2392 * look for constraints among those defining "map" that are valid
2393 * for the context. These can then be used to simplify away
2394 * the corresponding constraints in "map".
2396 static __isl_give isl_map *map_gist(__isl_take isl_map *map,
2397 __isl_take isl_map *context)
2399 int equal;
2400 int is_universe;
2401 isl_basic_map *hull;
2403 is_universe = isl_map_plain_is_universe(map);
2404 if (is_universe >= 0 && !is_universe)
2405 is_universe = isl_map_plain_is_universe(context);
2406 if (is_universe < 0)
2407 goto error;
2408 if (is_universe) {
2409 isl_map_free(context);
2410 return map;
2413 equal = isl_map_plain_is_equal(map, context);
2414 if (equal < 0)
2415 goto error;
2416 if (equal) {
2417 isl_map *res = isl_map_universe(isl_map_get_space(map));
2418 isl_map_free(map);
2419 isl_map_free(context);
2420 return res;
2423 context = isl_map_compute_divs(context);
2424 if (!context)
2425 goto error;
2426 if (isl_map_n_basic_map(context) == 1) {
2427 hull = isl_map_simple_hull(context);
2428 } else {
2429 isl_ctx *ctx;
2430 isl_map_list *list;
2432 ctx = isl_map_get_ctx(map);
2433 list = isl_map_list_alloc(ctx, 2);
2434 list = isl_map_list_add(list, isl_map_copy(context));
2435 list = isl_map_list_add(list, isl_map_copy(map));
2436 hull = isl_map_unshifted_simple_hull_from_map_list(context,
2437 list);
2439 return isl_map_gist_basic_map(map, hull);
2440 error:
2441 isl_map_free(map);
2442 isl_map_free(context);
2443 return NULL;
2446 __isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
2447 __isl_take isl_map *context)
2449 return isl_map_align_params_map_map_and(map, context, &map_gist);
2452 struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset,
2453 struct isl_basic_set *context)
2455 return (struct isl_basic_set *)isl_basic_map_gist(
2456 (struct isl_basic_map *)bset, (struct isl_basic_map *)context);
2459 __isl_give isl_set *isl_set_gist_basic_set(__isl_take isl_set *set,
2460 __isl_take isl_basic_set *context)
2462 return (struct isl_set *)isl_map_gist_basic_map((struct isl_map *)set,
2463 (struct isl_basic_map *)context);
2466 __isl_give isl_set *isl_set_gist_params_basic_set(__isl_take isl_set *set,
2467 __isl_take isl_basic_set *context)
2469 isl_space *space = isl_set_get_space(set);
2470 isl_basic_set *dom_context = isl_basic_set_universe(space);
2471 dom_context = isl_basic_set_intersect_params(dom_context, context);
2472 return isl_set_gist_basic_set(set, dom_context);
2475 __isl_give isl_set *isl_set_gist(__isl_take isl_set *set,
2476 __isl_take isl_set *context)
2478 return (struct isl_set *)isl_map_gist((struct isl_map *)set,
2479 (struct isl_map *)context);
2482 /* Compute the gist of "bmap" with respect to the constraints "context"
2483 * on the domain.
2485 __isl_give isl_basic_map *isl_basic_map_gist_domain(
2486 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *context)
2488 isl_space *space = isl_basic_map_get_space(bmap);
2489 isl_basic_map *bmap_context = isl_basic_map_universe(space);
2491 bmap_context = isl_basic_map_intersect_domain(bmap_context, context);
2492 return isl_basic_map_gist(bmap, bmap_context);
2495 __isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map,
2496 __isl_take isl_set *context)
2498 isl_map *map_context = isl_map_universe(isl_map_get_space(map));
2499 map_context = isl_map_intersect_domain(map_context, context);
2500 return isl_map_gist(map, map_context);
2503 __isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map,
2504 __isl_take isl_set *context)
2506 isl_map *map_context = isl_map_universe(isl_map_get_space(map));
2507 map_context = isl_map_intersect_range(map_context, context);
2508 return isl_map_gist(map, map_context);
2511 __isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map,
2512 __isl_take isl_set *context)
2514 isl_map *map_context = isl_map_universe(isl_map_get_space(map));
2515 map_context = isl_map_intersect_params(map_context, context);
2516 return isl_map_gist(map, map_context);
2519 __isl_give isl_set *isl_set_gist_params(__isl_take isl_set *set,
2520 __isl_take isl_set *context)
2522 return isl_map_gist_params(set, context);
2525 /* Quick check to see if two basic maps are disjoint.
2526 * In particular, we reduce the equalities and inequalities of
2527 * one basic map in the context of the equalities of the other
2528 * basic map and check if we get a contradiction.
2530 isl_bool isl_basic_map_plain_is_disjoint(__isl_keep isl_basic_map *bmap1,
2531 __isl_keep isl_basic_map *bmap2)
2533 struct isl_vec *v = NULL;
2534 int *elim = NULL;
2535 unsigned total;
2536 int i;
2538 if (!bmap1 || !bmap2)
2539 return isl_bool_error;
2540 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
2541 return isl_bool_error);
2542 if (bmap1->n_div || bmap2->n_div)
2543 return isl_bool_false;
2544 if (!bmap1->n_eq && !bmap2->n_eq)
2545 return isl_bool_false;
2547 total = isl_space_dim(bmap1->dim, isl_dim_all);
2548 if (total == 0)
2549 return isl_bool_false;
2550 v = isl_vec_alloc(bmap1->ctx, 1 + total);
2551 if (!v)
2552 goto error;
2553 elim = isl_alloc_array(bmap1->ctx, int, total);
2554 if (!elim)
2555 goto error;
2556 compute_elimination_index(bmap1, elim);
2557 for (i = 0; i < bmap2->n_eq; ++i) {
2558 int reduced;
2559 reduced = reduced_using_equalities(v->block.data, bmap2->eq[i],
2560 bmap1, elim);
2561 if (reduced && !isl_int_is_zero(v->block.data[0]) &&
2562 isl_seq_first_non_zero(v->block.data + 1, total) == -1)
2563 goto disjoint;
2565 for (i = 0; i < bmap2->n_ineq; ++i) {
2566 int reduced;
2567 reduced = reduced_using_equalities(v->block.data,
2568 bmap2->ineq[i], bmap1, elim);
2569 if (reduced && isl_int_is_neg(v->block.data[0]) &&
2570 isl_seq_first_non_zero(v->block.data + 1, total) == -1)
2571 goto disjoint;
2573 compute_elimination_index(bmap2, elim);
2574 for (i = 0; i < bmap1->n_ineq; ++i) {
2575 int reduced;
2576 reduced = reduced_using_equalities(v->block.data,
2577 bmap1->ineq[i], bmap2, elim);
2578 if (reduced && isl_int_is_neg(v->block.data[0]) &&
2579 isl_seq_first_non_zero(v->block.data + 1, total) == -1)
2580 goto disjoint;
2582 isl_vec_free(v);
2583 free(elim);
2584 return isl_bool_false;
2585 disjoint:
2586 isl_vec_free(v);
2587 free(elim);
2588 return isl_bool_true;
2589 error:
2590 isl_vec_free(v);
2591 free(elim);
2592 return isl_bool_error;
2595 int isl_basic_set_plain_is_disjoint(__isl_keep isl_basic_set *bset1,
2596 __isl_keep isl_basic_set *bset2)
2598 return isl_basic_map_plain_is_disjoint((struct isl_basic_map *)bset1,
2599 (struct isl_basic_map *)bset2);
2602 /* Are "map1" and "map2" obviously disjoint?
2604 * If one of them is empty or if they live in different spaces (ignoring
2605 * parameters), then they are clearly disjoint.
2607 * If they have different parameters, then we skip any further tests.
2609 * If they are obviously equal, but not obviously empty, then we will
2610 * not be able to detect if they are disjoint.
2612 * Otherwise we check if each basic map in "map1" is obviously disjoint
2613 * from each basic map in "map2".
2615 isl_bool isl_map_plain_is_disjoint(__isl_keep isl_map *map1,
2616 __isl_keep isl_map *map2)
2618 int i, j;
2619 isl_bool disjoint;
2620 isl_bool intersect;
2621 isl_bool match;
2623 if (!map1 || !map2)
2624 return isl_bool_error;
2626 disjoint = isl_map_plain_is_empty(map1);
2627 if (disjoint < 0 || disjoint)
2628 return disjoint;
2630 disjoint = isl_map_plain_is_empty(map2);
2631 if (disjoint < 0 || disjoint)
2632 return disjoint;
2634 match = isl_space_tuple_is_equal(map1->dim, isl_dim_in,
2635 map2->dim, isl_dim_in);
2636 if (match < 0 || !match)
2637 return match < 0 ? isl_bool_error : isl_bool_true;
2639 match = isl_space_tuple_is_equal(map1->dim, isl_dim_out,
2640 map2->dim, isl_dim_out);
2641 if (match < 0 || !match)
2642 return match < 0 ? isl_bool_error : isl_bool_true;
2644 match = isl_space_match(map1->dim, isl_dim_param,
2645 map2->dim, isl_dim_param);
2646 if (match < 0 || !match)
2647 return match < 0 ? isl_bool_error : isl_bool_false;
2649 intersect = isl_map_plain_is_equal(map1, map2);
2650 if (intersect < 0 || intersect)
2651 return intersect < 0 ? isl_bool_error : isl_bool_false;
2653 for (i = 0; i < map1->n; ++i) {
2654 for (j = 0; j < map2->n; ++j) {
2655 isl_bool d = isl_basic_map_plain_is_disjoint(map1->p[i],
2656 map2->p[j]);
2657 if (d != isl_bool_true)
2658 return d;
2661 return isl_bool_true;
2664 /* Are "map1" and "map2" disjoint?
2666 * They are disjoint if they are "obviously disjoint" or if one of them
2667 * is empty. Otherwise, they are not disjoint if one of them is universal.
2668 * If none of these cases apply, we compute the intersection and see if
2669 * the result is empty.
2671 isl_bool isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
2673 isl_bool disjoint;
2674 isl_bool intersect;
2675 isl_map *test;
2677 disjoint = isl_map_plain_is_disjoint(map1, map2);
2678 if (disjoint < 0 || disjoint)
2679 return disjoint;
2681 disjoint = isl_map_is_empty(map1);
2682 if (disjoint < 0 || disjoint)
2683 return disjoint;
2685 disjoint = isl_map_is_empty(map2);
2686 if (disjoint < 0 || disjoint)
2687 return disjoint;
2689 intersect = isl_map_plain_is_universe(map1);
2690 if (intersect < 0 || intersect)
2691 return intersect < 0 ? isl_bool_error : isl_bool_false;
2693 intersect = isl_map_plain_is_universe(map2);
2694 if (intersect < 0 || intersect)
2695 return intersect < 0 ? isl_bool_error : isl_bool_false;
2697 test = isl_map_intersect(isl_map_copy(map1), isl_map_copy(map2));
2698 disjoint = isl_map_is_empty(test);
2699 isl_map_free(test);
2701 return disjoint;
2704 /* Are "bmap1" and "bmap2" disjoint?
2706 * They are disjoint if they are "obviously disjoint" or if one of them
2707 * is empty. Otherwise, they are not disjoint if one of them is universal.
2708 * If none of these cases apply, we compute the intersection and see if
2709 * the result is empty.
2711 isl_bool isl_basic_map_is_disjoint(__isl_keep isl_basic_map *bmap1,
2712 __isl_keep isl_basic_map *bmap2)
2714 isl_bool disjoint;
2715 isl_bool intersect;
2716 isl_basic_map *test;
2718 disjoint = isl_basic_map_plain_is_disjoint(bmap1, bmap2);
2719 if (disjoint < 0 || disjoint)
2720 return disjoint;
2722 disjoint = isl_basic_map_is_empty(bmap1);
2723 if (disjoint < 0 || disjoint)
2724 return disjoint;
2726 disjoint = isl_basic_map_is_empty(bmap2);
2727 if (disjoint < 0 || disjoint)
2728 return disjoint;
2730 intersect = isl_basic_map_is_universe(bmap1);
2731 if (intersect < 0 || intersect)
2732 return intersect < 0 ? isl_bool_error : isl_bool_false;
2734 intersect = isl_basic_map_is_universe(bmap2);
2735 if (intersect < 0 || intersect)
2736 return intersect < 0 ? isl_bool_error : isl_bool_false;
2738 test = isl_basic_map_intersect(isl_basic_map_copy(bmap1),
2739 isl_basic_map_copy(bmap2));
2740 disjoint = isl_basic_map_is_empty(test);
2741 isl_basic_map_free(test);
2743 return disjoint;
2746 /* Are "bset1" and "bset2" disjoint?
2748 isl_bool isl_basic_set_is_disjoint(__isl_keep isl_basic_set *bset1,
2749 __isl_keep isl_basic_set *bset2)
2751 return isl_basic_map_is_disjoint(bset1, bset2);
2754 isl_bool isl_set_plain_is_disjoint(__isl_keep isl_set *set1,
2755 __isl_keep isl_set *set2)
2757 return isl_map_plain_is_disjoint((struct isl_map *)set1,
2758 (struct isl_map *)set2);
2761 /* Are "set1" and "set2" disjoint?
2763 isl_bool isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
2765 return isl_map_is_disjoint(set1, set2);
2768 /* Check if we can combine a given div with lower bound l and upper
2769 * bound u with some other div and if so return that other div.
2770 * Otherwise return -1.
2772 * We first check that
2773 * - the bounds are opposites of each other (except for the constant
2774 * term)
2775 * - the bounds do not reference any other div
2776 * - no div is defined in terms of this div
2778 * Let m be the size of the range allowed on the div by the bounds.
2779 * That is, the bounds are of the form
2781 * e <= a <= e + m - 1
2783 * with e some expression in the other variables.
2784 * We look for another div b such that no third div is defined in terms
2785 * of this second div b and such that in any constraint that contains
2786 * a (except for the given lower and upper bound), also contains b
2787 * with a coefficient that is m times that of b.
2788 * That is, all constraints (execpt for the lower and upper bound)
2789 * are of the form
2791 * e + f (a + m b) >= 0
2793 * If so, we return b so that "a + m b" can be replaced by
2794 * a single div "c = a + m b".
2796 static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs,
2797 unsigned div, unsigned l, unsigned u)
2799 int i, j;
2800 unsigned dim;
2801 int coalesce = -1;
2803 if (bmap->n_div <= 1)
2804 return -1;
2805 dim = isl_space_dim(bmap->dim, isl_dim_all);
2806 if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim, div) != -1)
2807 return -1;
2808 if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim + div + 1,
2809 bmap->n_div - div - 1) != -1)
2810 return -1;
2811 if (!isl_seq_is_neg(bmap->ineq[l] + 1, bmap->ineq[u] + 1,
2812 dim + bmap->n_div))
2813 return -1;
2815 for (i = 0; i < bmap->n_div; ++i) {
2816 if (isl_int_is_zero(bmap->div[i][0]))
2817 continue;
2818 if (!isl_int_is_zero(bmap->div[i][1 + 1 + dim + div]))
2819 return -1;
2822 isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
2823 if (isl_int_is_neg(bmap->ineq[l][0])) {
2824 isl_int_sub(bmap->ineq[l][0],
2825 bmap->ineq[l][0], bmap->ineq[u][0]);
2826 bmap = isl_basic_map_copy(bmap);
2827 bmap = isl_basic_map_set_to_empty(bmap);
2828 isl_basic_map_free(bmap);
2829 return -1;
2831 isl_int_add_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
2832 for (i = 0; i < bmap->n_div; ++i) {
2833 if (i == div)
2834 continue;
2835 if (!pairs[i])
2836 continue;
2837 for (j = 0; j < bmap->n_div; ++j) {
2838 if (isl_int_is_zero(bmap->div[j][0]))
2839 continue;
2840 if (!isl_int_is_zero(bmap->div[j][1 + 1 + dim + i]))
2841 break;
2843 if (j < bmap->n_div)
2844 continue;
2845 for (j = 0; j < bmap->n_ineq; ++j) {
2846 int valid;
2847 if (j == l || j == u)
2848 continue;
2849 if (isl_int_is_zero(bmap->ineq[j][1 + dim + div]))
2850 continue;
2851 if (isl_int_is_zero(bmap->ineq[j][1 + dim + i]))
2852 break;
2853 isl_int_mul(bmap->ineq[j][1 + dim + div],
2854 bmap->ineq[j][1 + dim + div],
2855 bmap->ineq[l][0]);
2856 valid = isl_int_eq(bmap->ineq[j][1 + dim + div],
2857 bmap->ineq[j][1 + dim + i]);
2858 isl_int_divexact(bmap->ineq[j][1 + dim + div],
2859 bmap->ineq[j][1 + dim + div],
2860 bmap->ineq[l][0]);
2861 if (!valid)
2862 break;
2864 if (j < bmap->n_ineq)
2865 continue;
2866 coalesce = i;
2867 break;
2869 isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
2870 isl_int_sub(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
2871 return coalesce;
2874 /* Given a lower and an upper bound on div i, construct an inequality
2875 * that when nonnegative ensures that this pair of bounds always allows
2876 * for an integer value of the given div.
2877 * The lower bound is inequality l, while the upper bound is inequality u.
2878 * The constructed inequality is stored in ineq.
2879 * g, fl, fu are temporary scalars.
2881 * Let the upper bound be
2883 * -n_u a + e_u >= 0
2885 * and the lower bound
2887 * n_l a + e_l >= 0
2889 * Let n_u = f_u g and n_l = f_l g, with g = gcd(n_u, n_l).
2890 * We have
2892 * - f_u e_l <= f_u f_l g a <= f_l e_u
2894 * Since all variables are integer valued, this is equivalent to
2896 * - f_u e_l - (f_u - 1) <= f_u f_l g a <= f_l e_u + (f_l - 1)
2898 * If this interval is at least f_u f_l g, then it contains at least
2899 * one integer value for a.
2900 * That is, the test constraint is
2902 * f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 >= f_u f_l g
2904 static void construct_test_ineq(struct isl_basic_map *bmap, int i,
2905 int l, int u, isl_int *ineq, isl_int g, isl_int fl, isl_int fu)
2907 unsigned dim;
2908 dim = isl_space_dim(bmap->dim, isl_dim_all);
2910 isl_int_gcd(g, bmap->ineq[l][1 + dim + i], bmap->ineq[u][1 + dim + i]);
2911 isl_int_divexact(fl, bmap->ineq[l][1 + dim + i], g);
2912 isl_int_divexact(fu, bmap->ineq[u][1 + dim + i], g);
2913 isl_int_neg(fu, fu);
2914 isl_seq_combine(ineq, fl, bmap->ineq[u], fu, bmap->ineq[l],
2915 1 + dim + bmap->n_div);
2916 isl_int_add(ineq[0], ineq[0], fl);
2917 isl_int_add(ineq[0], ineq[0], fu);
2918 isl_int_sub_ui(ineq[0], ineq[0], 1);
2919 isl_int_mul(g, g, fl);
2920 isl_int_mul(g, g, fu);
2921 isl_int_sub(ineq[0], ineq[0], g);
2924 /* Remove more kinds of divs that are not strictly needed.
2925 * In particular, if all pairs of lower and upper bounds on a div
2926 * are such that they allow at least one integer value of the div,
2927 * the we can eliminate the div using Fourier-Motzkin without
2928 * introducing any spurious solutions.
2930 static struct isl_basic_map *drop_more_redundant_divs(
2931 struct isl_basic_map *bmap, int *pairs, int n)
2933 struct isl_tab *tab = NULL;
2934 struct isl_vec *vec = NULL;
2935 unsigned dim;
2936 int remove = -1;
2937 isl_int g, fl, fu;
2939 isl_int_init(g);
2940 isl_int_init(fl);
2941 isl_int_init(fu);
2943 if (!bmap)
2944 goto error;
2946 dim = isl_space_dim(bmap->dim, isl_dim_all);
2947 vec = isl_vec_alloc(bmap->ctx, 1 + dim + bmap->n_div);
2948 if (!vec)
2949 goto error;
2951 tab = isl_tab_from_basic_map(bmap, 0);
2953 while (n > 0) {
2954 int i, l, u;
2955 int best = -1;
2956 enum isl_lp_result res;
2958 for (i = 0; i < bmap->n_div; ++i) {
2959 if (!pairs[i])
2960 continue;
2961 if (best >= 0 && pairs[best] <= pairs[i])
2962 continue;
2963 best = i;
2966 i = best;
2967 for (l = 0; l < bmap->n_ineq; ++l) {
2968 if (!isl_int_is_pos(bmap->ineq[l][1 + dim + i]))
2969 continue;
2970 for (u = 0; u < bmap->n_ineq; ++u) {
2971 if (!isl_int_is_neg(bmap->ineq[u][1 + dim + i]))
2972 continue;
2973 construct_test_ineq(bmap, i, l, u,
2974 vec->el, g, fl, fu);
2975 res = isl_tab_min(tab, vec->el,
2976 bmap->ctx->one, &g, NULL, 0);
2977 if (res == isl_lp_error)
2978 goto error;
2979 if (res == isl_lp_empty) {
2980 bmap = isl_basic_map_set_to_empty(bmap);
2981 break;
2983 if (res != isl_lp_ok || isl_int_is_neg(g))
2984 break;
2986 if (u < bmap->n_ineq)
2987 break;
2989 if (l == bmap->n_ineq) {
2990 remove = i;
2991 break;
2993 pairs[i] = 0;
2994 --n;
2997 isl_tab_free(tab);
2998 isl_vec_free(vec);
3000 isl_int_clear(g);
3001 isl_int_clear(fl);
3002 isl_int_clear(fu);
3004 free(pairs);
3006 if (remove < 0)
3007 return bmap;
3009 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, remove, 1);
3010 return isl_basic_map_drop_redundant_divs(bmap);
3011 error:
3012 free(pairs);
3013 isl_basic_map_free(bmap);
3014 isl_tab_free(tab);
3015 isl_vec_free(vec);
3016 isl_int_clear(g);
3017 isl_int_clear(fl);
3018 isl_int_clear(fu);
3019 return NULL;
3022 /* Given a pair of divs div1 and div2 such that, expect for the lower bound l
3023 * and the upper bound u, div1 always occurs together with div2 in the form
3024 * (div1 + m div2), where m is the constant range on the variable div1
3025 * allowed by l and u, replace the pair div1 and div2 by a single
3026 * div that is equal to div1 + m div2.
3028 * The new div will appear in the location that contains div2.
3029 * We need to modify all constraints that contain
3030 * div2 = (div - div1) / m
3031 * (If a constraint does not contain div2, it will also not contain div1.)
3032 * If the constraint also contains div1, then we know they appear
3033 * as f (div1 + m div2) and we can simply replace (div1 + m div2) by div,
3034 * i.e., the coefficient of div is f.
3036 * Otherwise, we first need to introduce div1 into the constraint.
3037 * Let the l be
3039 * div1 + f >=0
3041 * and u
3043 * -div1 + f' >= 0
3045 * A lower bound on div2
3047 * n div2 + t >= 0
3049 * can be replaced by
3051 * (n * (m div 2 + div1) + m t + n f)/g >= 0
3053 * with g = gcd(m,n).
3054 * An upper bound
3056 * -n div2 + t >= 0
3058 * can be replaced by
3060 * (-n * (m div2 + div1) + m t + n f')/g >= 0
3062 * These constraint are those that we would obtain from eliminating
3063 * div1 using Fourier-Motzkin.
3065 * After all constraints have been modified, we drop the lower and upper
3066 * bound and then drop div1.
3068 static struct isl_basic_map *coalesce_divs(struct isl_basic_map *bmap,
3069 unsigned div1, unsigned div2, unsigned l, unsigned u)
3071 isl_int a;
3072 isl_int b;
3073 isl_int m;
3074 unsigned dim, total;
3075 int i;
3077 dim = isl_space_dim(bmap->dim, isl_dim_all);
3078 total = 1 + dim + bmap->n_div;
3080 isl_int_init(a);
3081 isl_int_init(b);
3082 isl_int_init(m);
3083 isl_int_add(m, bmap->ineq[l][0], bmap->ineq[u][0]);
3084 isl_int_add_ui(m, m, 1);
3086 for (i = 0; i < bmap->n_ineq; ++i) {
3087 if (i == l || i == u)
3088 continue;
3089 if (isl_int_is_zero(bmap->ineq[i][1 + dim + div2]))
3090 continue;
3091 if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1])) {
3092 isl_int_gcd(b, m, bmap->ineq[i][1 + dim + div2]);
3093 isl_int_divexact(a, m, b);
3094 isl_int_divexact(b, bmap->ineq[i][1 + dim + div2], b);
3095 if (isl_int_is_pos(b)) {
3096 isl_seq_combine(bmap->ineq[i], a, bmap->ineq[i],
3097 b, bmap->ineq[l], total);
3098 } else {
3099 isl_int_neg(b, b);
3100 isl_seq_combine(bmap->ineq[i], a, bmap->ineq[i],
3101 b, bmap->ineq[u], total);
3104 isl_int_set(bmap->ineq[i][1 + dim + div2],
3105 bmap->ineq[i][1 + dim + div1]);
3106 isl_int_set_si(bmap->ineq[i][1 + dim + div1], 0);
3109 isl_int_clear(a);
3110 isl_int_clear(b);
3111 isl_int_clear(m);
3112 if (l > u) {
3113 isl_basic_map_drop_inequality(bmap, l);
3114 isl_basic_map_drop_inequality(bmap, u);
3115 } else {
3116 isl_basic_map_drop_inequality(bmap, u);
3117 isl_basic_map_drop_inequality(bmap, l);
3119 bmap = isl_basic_map_drop_div(bmap, div1);
3120 return bmap;
3123 /* First check if we can coalesce any pair of divs and
3124 * then continue with dropping more redundant divs.
3126 * We loop over all pairs of lower and upper bounds on a div
3127 * with coefficient 1 and -1, respectively, check if there
3128 * is any other div "c" with which we can coalesce the div
3129 * and if so, perform the coalescing.
3131 static struct isl_basic_map *coalesce_or_drop_more_redundant_divs(
3132 struct isl_basic_map *bmap, int *pairs, int n)
3134 int i, l, u;
3135 unsigned dim;
3137 dim = isl_space_dim(bmap->dim, isl_dim_all);
3139 for (i = 0; i < bmap->n_div; ++i) {
3140 if (!pairs[i])
3141 continue;
3142 for (l = 0; l < bmap->n_ineq; ++l) {
3143 if (!isl_int_is_one(bmap->ineq[l][1 + dim + i]))
3144 continue;
3145 for (u = 0; u < bmap->n_ineq; ++u) {
3146 int c;
3148 if (!isl_int_is_negone(bmap->ineq[u][1+dim+i]))
3149 continue;
3150 c = div_find_coalesce(bmap, pairs, i, l, u);
3151 if (c < 0)
3152 continue;
3153 free(pairs);
3154 bmap = coalesce_divs(bmap, i, c, l, u);
3155 return isl_basic_map_drop_redundant_divs(bmap);
3160 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
3161 return bmap;
3163 return drop_more_redundant_divs(bmap, pairs, n);
3166 /* Remove divs that are not strictly needed.
3167 * In particular, if a div only occurs positively (or negatively)
3168 * in constraints, then it can simply be dropped.
3169 * Also, if a div occurs in only two constraints and if moreover
3170 * those two constraints are opposite to each other, except for the constant
3171 * term and if the sum of the constant terms is such that for any value
3172 * of the other values, there is always at least one integer value of the
3173 * div, i.e., if one plus this sum is greater than or equal to
3174 * the (absolute value) of the coefficent of the div in the constraints,
3175 * then we can also simply drop the div.
3177 * We skip divs that appear in equalities or in the definition of other divs.
3178 * Divs that appear in the definition of other divs usually occur in at least
3179 * 4 constraints, but the constraints may have been simplified.
3181 * If any divs are left after these simple checks then we move on
3182 * to more complicated cases in drop_more_redundant_divs.
3184 struct isl_basic_map *isl_basic_map_drop_redundant_divs(
3185 struct isl_basic_map *bmap)
3187 int i, j;
3188 unsigned off;
3189 int *pairs = NULL;
3190 int n = 0;
3192 if (!bmap)
3193 goto error;
3194 if (bmap->n_div == 0)
3195 return bmap;
3197 off = isl_space_dim(bmap->dim, isl_dim_all);
3198 pairs = isl_calloc_array(bmap->ctx, int, bmap->n_div);
3199 if (!pairs)
3200 goto error;
3202 for (i = 0; i < bmap->n_div; ++i) {
3203 int pos, neg;
3204 int last_pos, last_neg;
3205 int redundant;
3206 int defined;
3208 defined = !isl_int_is_zero(bmap->div[i][0]);
3209 for (j = i; j < bmap->n_div; ++j)
3210 if (!isl_int_is_zero(bmap->div[j][1 + 1 + off + i]))
3211 break;
3212 if (j < bmap->n_div)
3213 continue;
3214 for (j = 0; j < bmap->n_eq; ++j)
3215 if (!isl_int_is_zero(bmap->eq[j][1 + off + i]))
3216 break;
3217 if (j < bmap->n_eq)
3218 continue;
3219 ++n;
3220 pos = neg = 0;
3221 for (j = 0; j < bmap->n_ineq; ++j) {
3222 if (isl_int_is_pos(bmap->ineq[j][1 + off + i])) {
3223 last_pos = j;
3224 ++pos;
3226 if (isl_int_is_neg(bmap->ineq[j][1 + off + i])) {
3227 last_neg = j;
3228 ++neg;
3231 pairs[i] = pos * neg;
3232 if (pairs[i] == 0) {
3233 for (j = bmap->n_ineq - 1; j >= 0; --j)
3234 if (!isl_int_is_zero(bmap->ineq[j][1+off+i]))
3235 isl_basic_map_drop_inequality(bmap, j);
3236 bmap = isl_basic_map_drop_div(bmap, i);
3237 free(pairs);
3238 return isl_basic_map_drop_redundant_divs(bmap);
3240 if (pairs[i] != 1)
3241 continue;
3242 if (!isl_seq_is_neg(bmap->ineq[last_pos] + 1,
3243 bmap->ineq[last_neg] + 1,
3244 off + bmap->n_div))
3245 continue;
3247 isl_int_add(bmap->ineq[last_pos][0],
3248 bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]);
3249 isl_int_add_ui(bmap->ineq[last_pos][0],
3250 bmap->ineq[last_pos][0], 1);
3251 redundant = isl_int_ge(bmap->ineq[last_pos][0],
3252 bmap->ineq[last_pos][1+off+i]);
3253 isl_int_sub_ui(bmap->ineq[last_pos][0],
3254 bmap->ineq[last_pos][0], 1);
3255 isl_int_sub(bmap->ineq[last_pos][0],
3256 bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]);
3257 if (!redundant) {
3258 if (defined ||
3259 !ok_to_set_div_from_bound(bmap, i, last_pos)) {
3260 pairs[i] = 0;
3261 --n;
3262 continue;
3264 bmap = set_div_from_lower_bound(bmap, i, last_pos);
3265 bmap = isl_basic_map_simplify(bmap);
3266 free(pairs);
3267 return isl_basic_map_drop_redundant_divs(bmap);
3269 if (last_pos > last_neg) {
3270 isl_basic_map_drop_inequality(bmap, last_pos);
3271 isl_basic_map_drop_inequality(bmap, last_neg);
3272 } else {
3273 isl_basic_map_drop_inequality(bmap, last_neg);
3274 isl_basic_map_drop_inequality(bmap, last_pos);
3276 bmap = isl_basic_map_drop_div(bmap, i);
3277 free(pairs);
3278 return isl_basic_map_drop_redundant_divs(bmap);
3281 if (n > 0)
3282 return coalesce_or_drop_more_redundant_divs(bmap, pairs, n);
3284 free(pairs);
3285 return bmap;
3286 error:
3287 free(pairs);
3288 isl_basic_map_free(bmap);
3289 return NULL;
3292 struct isl_basic_set *isl_basic_set_drop_redundant_divs(
3293 struct isl_basic_set *bset)
3295 return (struct isl_basic_set *)
3296 isl_basic_map_drop_redundant_divs((struct isl_basic_map *)bset);
3299 struct isl_map *isl_map_drop_redundant_divs(struct isl_map *map)
3301 int i;
3303 if (!map)
3304 return NULL;
3305 for (i = 0; i < map->n; ++i) {
3306 map->p[i] = isl_basic_map_drop_redundant_divs(map->p[i]);
3307 if (!map->p[i])
3308 goto error;
3310 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
3311 return map;
3312 error:
3313 isl_map_free(map);
3314 return NULL;
3317 struct isl_set *isl_set_drop_redundant_divs(struct isl_set *set)
3319 return (struct isl_set *)
3320 isl_map_drop_redundant_divs((struct isl_map *)set);
3323 /* Does "bmap" satisfy any equality that involves more than 2 variables
3324 * and/or has coefficients different from -1 and 1?
3326 static int has_multiple_var_equality(__isl_keep isl_basic_map *bmap)
3328 int i;
3329 unsigned total;
3331 total = isl_basic_map_dim(bmap, isl_dim_all);
3333 for (i = 0; i < bmap->n_eq; ++i) {
3334 int j, k;
3336 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
3337 if (j < 0)
3338 continue;
3339 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
3340 !isl_int_is_negone(bmap->eq[i][1 + j]))
3341 return 1;
3343 j += 1;
3344 k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j);
3345 if (k < 0)
3346 continue;
3347 j += k;
3348 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
3349 !isl_int_is_negone(bmap->eq[i][1 + j]))
3350 return 1;
3352 j += 1;
3353 k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j);
3354 if (k >= 0)
3355 return 1;
3358 return 0;
3361 /* Remove any common factor g from the constraint coefficients in "v".
3362 * The constant term is stored in the first position and is replaced
3363 * by floor(c/g). If any common factor is removed and if this results
3364 * in a tightening of the constraint, then set *tightened.
3366 static __isl_give isl_vec *normalize_constraint(__isl_take isl_vec *v,
3367 int *tightened)
3369 isl_ctx *ctx;
3371 if (!v)
3372 return NULL;
3373 ctx = isl_vec_get_ctx(v);
3374 isl_seq_gcd(v->el + 1, v->size - 1, &ctx->normalize_gcd);
3375 if (isl_int_is_zero(ctx->normalize_gcd))
3376 return v;
3377 if (isl_int_is_one(ctx->normalize_gcd))
3378 return v;
3379 v = isl_vec_cow(v);
3380 if (!v)
3381 return NULL;
3382 if (tightened && !isl_int_is_divisible_by(v->el[0], ctx->normalize_gcd))
3383 *tightened = 1;
3384 isl_int_fdiv_q(v->el[0], v->el[0], ctx->normalize_gcd);
3385 isl_seq_scale_down(v->el + 1, v->el + 1, ctx->normalize_gcd,
3386 v->size - 1);
3387 return v;
3390 /* If "bmap" is an integer set that satisfies any equality involving
3391 * more than 2 variables and/or has coefficients different from -1 and 1,
3392 * then use variable compression to reduce the coefficients by removing
3393 * any (hidden) common factor.
3394 * In particular, apply the variable compression to each constraint,
3395 * factor out any common factor in the non-constant coefficients and
3396 * then apply the inverse of the compression.
3397 * At the end, we mark the basic map as having reduced constants.
3398 * If this flag is still set on the next invocation of this function,
3399 * then we skip the computation.
3401 * Removing a common factor may result in a tightening of some of
3402 * the constraints. If this happens, then we may end up with two
3403 * opposite inequalities that can be replaced by an equality.
3404 * We therefore call isl_basic_map_detect_inequality_pairs,
3405 * which checks for such pairs of inequalities as well as eliminate_divs_eq
3406 * and isl_basic_map_gauss if such a pair was found.
3408 __isl_give isl_basic_map *isl_basic_map_reduce_coefficients(
3409 __isl_take isl_basic_map *bmap)
3411 unsigned total;
3412 isl_ctx *ctx;
3413 isl_vec *v;
3414 isl_mat *eq, *T, *T2;
3415 int i;
3416 int tightened;
3418 if (!bmap)
3419 return NULL;
3420 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS))
3421 return bmap;
3422 if (isl_basic_map_is_rational(bmap))
3423 return bmap;
3424 if (bmap->n_eq == 0)
3425 return bmap;
3426 if (!has_multiple_var_equality(bmap))
3427 return bmap;
3429 total = isl_basic_map_dim(bmap, isl_dim_all);
3430 ctx = isl_basic_map_get_ctx(bmap);
3431 v = isl_vec_alloc(ctx, 1 + total);
3432 if (!v)
3433 return isl_basic_map_free(bmap);
3435 eq = isl_mat_sub_alloc6(ctx, bmap->eq, 0, bmap->n_eq, 0, 1 + total);
3436 T = isl_mat_variable_compression(eq, &T2);
3437 if (!T || !T2)
3438 goto error;
3439 if (T->n_col == 0) {
3440 isl_mat_free(T);
3441 isl_mat_free(T2);
3442 isl_vec_free(v);
3443 return isl_basic_map_set_to_empty(bmap);
3446 tightened = 0;
3447 for (i = 0; i < bmap->n_ineq; ++i) {
3448 isl_seq_cpy(v->el, bmap->ineq[i], 1 + total);
3449 v = isl_vec_mat_product(v, isl_mat_copy(T));
3450 v = normalize_constraint(v, &tightened);
3451 v = isl_vec_mat_product(v, isl_mat_copy(T2));
3452 if (!v)
3453 goto error;
3454 isl_seq_cpy(bmap->ineq[i], v->el, 1 + total);
3457 isl_mat_free(T);
3458 isl_mat_free(T2);
3459 isl_vec_free(v);
3461 ISL_F_SET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
3463 if (tightened) {
3464 int progress = 0;
3466 bmap = isl_basic_map_detect_inequality_pairs(bmap, &progress);
3467 if (progress) {
3468 bmap = eliminate_divs_eq(bmap, &progress);
3469 bmap = isl_basic_map_gauss(bmap, NULL);
3473 return bmap;
3474 error:
3475 isl_mat_free(T);
3476 isl_mat_free(T2);
3477 isl_vec_free(v);
3478 return isl_basic_map_free(bmap);
3481 /* Shift the integer division at position "div" of "bmap" by "shift".
3483 * That is, if the integer division has the form
3485 * floor(f(x)/d)
3487 * then replace it by
3489 * floor((f(x) + shift * d)/d) - shift
3491 __isl_give isl_basic_map *isl_basic_map_shift_div(
3492 __isl_take isl_basic_map *bmap, int div, isl_int shift)
3494 int i;
3495 unsigned total;
3497 if (!bmap)
3498 return NULL;
3500 total = isl_basic_map_dim(bmap, isl_dim_all);
3501 total -= isl_basic_map_dim(bmap, isl_dim_div);
3503 isl_int_addmul(bmap->div[div][1], shift, bmap->div[div][0]);
3505 for (i = 0; i < bmap->n_eq; ++i) {
3506 if (isl_int_is_zero(bmap->eq[i][1 + total + div]))
3507 continue;
3508 isl_int_submul(bmap->eq[i][0],
3509 shift, bmap->eq[i][1 + total + div]);
3511 for (i = 0; i < bmap->n_ineq; ++i) {
3512 if (isl_int_is_zero(bmap->ineq[i][1 + total + div]))
3513 continue;
3514 isl_int_submul(bmap->ineq[i][0],
3515 shift, bmap->ineq[i][1 + total + div]);
3517 for (i = 0; i < bmap->n_div; ++i) {
3518 if (isl_int_is_zero(bmap->div[i][0]))
3519 continue;
3520 if (isl_int_is_zero(bmap->div[i][1 + 1 + total + div]))
3521 continue;
3522 isl_int_submul(bmap->div[i][1],
3523 shift, bmap->div[i][1 + 1 + total + div]);
3526 return bmap;