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