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