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