isl_basic_map_eliminate_vars: ensure variable is eliminated before dropping equality
[platform/upstream/isl.git] / isl_map.c
1 #include <string.h>
2 #include <strings.h>
3 #include "isl_ctx.h"
4 #include "isl_blk.h"
5 #include "isl_equalities.h"
6 #include "isl_lp.h"
7 #include "isl_seq.h"
8 #include "isl_set.h"
9 #include "isl_map.h"
10 #include "isl_map_private.h"
11 #include "isl_map_piplib.h"
12 #include "isl_sample.h"
13 #include "isl_vec.h"
14
15 static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
16                 struct isl_basic_map *bmap,
17                 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
18                 unsigned n_eq, unsigned n_ineq)
19 {
20         int i;
21         size_t row_size = 1 + nparam + n_in + n_out + extra;
22
23         bmap->block = isl_blk_alloc(ctx, (n_eq + n_ineq) * row_size);
24         if (isl_blk_is_error(bmap->block)) {
25                 free(bmap);
26                 return NULL;
27         }
28
29         bmap->eq = isl_alloc_array(ctx, isl_int *, n_eq + n_ineq);
30         if (!bmap->eq) {
31                 isl_blk_free(ctx, bmap->block);
32                 free(bmap);
33                 return NULL;
34         }
35
36         if (extra == 0) {
37                 bmap->block2 = isl_blk_empty();
38                 bmap->div = NULL;
39         } else {
40                 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
41                 if (isl_blk_is_error(bmap->block2)) {
42                         free(bmap->eq);
43                         isl_blk_free(ctx, bmap->block);
44                         free(bmap);
45                         return NULL;
46                 }
47
48                 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
49                 if (!bmap->div) {
50                         isl_blk_free(ctx, bmap->block2);
51                         free(bmap->eq);
52                         isl_blk_free(ctx, bmap->block);
53                         free(bmap);
54                         return NULL;
55                 }
56         }
57
58         for (i = 0; i < n_eq + n_ineq; ++i)
59                 bmap->eq[i] = bmap->block.data + i * row_size;
60
61         for (i = 0; i < extra; ++i)
62                 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
63
64         bmap->ctx = ctx;
65         isl_ctx_ref(ctx);
66         bmap->ref = 1;
67         bmap->flags = 0;
68         bmap->c_size = n_eq + n_ineq;
69         bmap->ineq = bmap->eq + n_eq;
70         bmap->nparam = nparam;
71         bmap->n_in = n_in;
72         bmap->n_out = n_out;
73         bmap->extra = extra;
74         bmap->n_eq = 0;
75         bmap->n_ineq = 0;
76         bmap->n_div = 0;
77         bmap->sample = NULL;
78
79         return bmap;
80 }
81
82 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
83                 unsigned nparam, unsigned dim, unsigned extra,
84                 unsigned n_eq, unsigned n_ineq)
85 {
86         struct isl_basic_map *bmap;
87         bmap = isl_basic_map_alloc(ctx, nparam, 0, dim, extra, n_eq, n_ineq);
88         return (struct isl_basic_set *)bmap;
89 }
90
91 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
92                 unsigned nparam, unsigned in, unsigned out, unsigned extra,
93                 unsigned n_eq, unsigned n_ineq)
94 {
95         struct isl_basic_map *bmap;
96
97         bmap = isl_alloc_type(ctx, struct isl_basic_map);
98         if (!bmap)
99                 return NULL;
100
101         return basic_map_init(ctx, bmap,
102                                nparam, in, out, extra, n_eq, n_ineq);
103 }
104
105 static void dup_constraints(
106                 struct isl_basic_map *dst, struct isl_basic_map *src)
107 {
108         int i;
109         unsigned total = src->nparam + src->n_in + src->n_out + src->n_div;
110
111         for (i = 0; i < src->n_eq; ++i) {
112                 int j = isl_basic_map_alloc_equality(dst);
113                 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
114         }
115
116         for (i = 0; i < src->n_ineq; ++i) {
117                 int j = isl_basic_map_alloc_inequality(dst);
118                 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
119         }
120
121         for (i = 0; i < src->n_div; ++i) {
122                 int j = isl_basic_map_alloc_div(dst);
123                 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
124         }
125         F_SET(dst, ISL_BASIC_SET_FINAL);
126 }
127
128 struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap)
129 {
130         struct isl_basic_map *dup;
131
132         if (!bmap)
133                 return NULL;
134         dup = isl_basic_map_alloc(bmap->ctx, bmap->nparam,
135                         bmap->n_in, bmap->n_out,
136                         bmap->n_div, bmap->n_eq, bmap->n_ineq);
137         if (!dup)
138                 return NULL;
139         dup->flags = bmap->flags;
140         dup_constraints(dup, bmap);
141         dup->sample = isl_vec_copy(bmap->ctx, bmap->sample);
142         return dup;
143 }
144
145 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
146 {
147         struct isl_basic_map *dup;
148
149         dup = isl_basic_map_dup((struct isl_basic_map *)bset);
150         return (struct isl_basic_set *)dup;
151 }
152
153 struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset)
154 {
155         if (!bset)
156                 return NULL;
157
158         if (F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
159                 bset->ref++;
160                 return bset;
161         }
162         return isl_basic_set_dup(bset);
163 }
164
165 struct isl_set *isl_set_copy(struct isl_set *set)
166 {
167         if (!set)
168                 return NULL;
169
170         set->ref++;
171         return set;
172 }
173
174 struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap)
175 {
176         if (!bmap)
177                 return NULL;
178
179         if (F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
180                 bmap->ref++;
181                 return bmap;
182         }
183         return isl_basic_map_dup(bmap);
184 }
185
186 struct isl_map *isl_map_copy(struct isl_map *map)
187 {
188         if (!map)
189                 return NULL;
190
191         map->ref++;
192         return map;
193 }
194
195 void isl_basic_map_free(struct isl_basic_map *bmap)
196 {
197         if (!bmap)
198                 return;
199
200         if (--bmap->ref > 0)
201                 return;
202
203         isl_ctx_deref(bmap->ctx);
204         free(bmap->div);
205         isl_blk_free(bmap->ctx, bmap->block2);
206         free(bmap->eq);
207         isl_blk_free(bmap->ctx, bmap->block);
208         isl_vec_free(bmap->ctx, bmap->sample);
209         free(bmap);
210 }
211
212 void isl_basic_set_free(struct isl_basic_set *bset)
213 {
214         isl_basic_map_free((struct isl_basic_map *)bset);
215 }
216
217 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
218 {
219         struct isl_ctx *ctx;
220         if (!bmap)
221                 return -1;
222         ctx = bmap->ctx;
223         isl_assert(ctx, bmap->n_eq + bmap->n_ineq < bmap->c_size, return -1);
224         isl_assert(ctx, bmap->eq + bmap->n_eq <= bmap->ineq, return -1);
225         if (bmap->eq + bmap->n_eq == bmap->ineq) {
226                 isl_int *t;
227                 int j = isl_basic_map_alloc_inequality(bmap);
228                 if (j < 0)
229                         return -1;
230                 t = bmap->ineq[0];
231                 bmap->ineq[0] = bmap->ineq[j];
232                 bmap->ineq[j] = t;
233                 bmap->n_ineq--;
234                 bmap->ineq++;
235         }
236         return bmap->n_eq++;
237 }
238
239 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
240 {
241         return isl_basic_map_alloc_equality((struct isl_basic_map *)bset);
242 }
243
244 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
245 {
246         if (!bmap)
247                 return -1;
248         isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
249         bmap->n_eq -= n;
250         return 0;
251 }
252
253 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
254 {
255         isl_int *t;
256         if (!bmap)
257                 return -1;
258         isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
259
260         if (pos != bmap->n_eq - 1) {
261                 t = bmap->eq[pos];
262                 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
263                 bmap->eq[bmap->n_eq - 1] = t;
264         }
265         bmap->n_eq--;
266         return 0;
267 }
268
269 int isl_basic_set_drop_equality(struct isl_basic_set *bset, unsigned pos)
270 {
271         return isl_basic_map_drop_equality((struct isl_basic_map *)bset, pos);
272 }
273
274 void isl_basic_map_inequality_to_equality(
275                 struct isl_basic_map *bmap, unsigned pos)
276 {
277         isl_int *t;
278
279         t = bmap->ineq[pos];
280         bmap->ineq[pos] = bmap->ineq[0];
281         bmap->ineq[0] = bmap->eq[bmap->n_eq];
282         bmap->eq[bmap->n_eq] = t;
283         bmap->n_eq++;
284         bmap->n_ineq--;
285         bmap->ineq++;
286 }
287
288 int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap)
289 {
290         struct isl_ctx *ctx;
291         if (!bmap)
292                 return -1;
293         ctx = bmap->ctx;
294         isl_assert(ctx, (bmap->ineq - bmap->eq) + bmap->n_ineq < bmap->c_size,
295                         return -1);
296         F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
297         F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
298         return bmap->n_ineq++;
299 }
300
301 int isl_basic_set_alloc_inequality(struct isl_basic_set *bset)
302 {
303         return isl_basic_map_alloc_inequality((struct isl_basic_map *)bset);
304 }
305
306 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
307 {
308         if (!bmap)
309                 return -1;
310         isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
311         bmap->n_ineq -= n;
312         return 0;
313 }
314
315 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
316 {
317         return isl_basic_map_free_inequality((struct isl_basic_map *)bset, n);
318 }
319
320 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
321 {
322         isl_int *t;
323         if (!bmap)
324                 return -1;
325         isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
326
327         if (pos != bmap->n_ineq - 1) {
328                 t = bmap->ineq[pos];
329                 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
330                 bmap->ineq[bmap->n_ineq - 1] = t;
331         }
332         bmap->n_ineq--;
333         return 0;
334 }
335
336 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
337 {
338         return isl_basic_map_drop_inequality((struct isl_basic_map *)bset, pos);
339 }
340
341 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
342 {
343         if (!bmap)
344                 return -1;
345         isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
346         return bmap->n_div++;
347 }
348
349 int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
350 {
351         if (!bmap)
352                 return -1;
353         isl_assert(bmap->ctx, n <= bmap->n_div, return -1);
354         bmap->n_div -= n;
355         return 0;
356 }
357
358 /* Copy constraint from src to dst, putting the vars of src at offset
359  * dim_off in dst and the divs of src at offset div_off in dst.
360  * If both sets are actually map, then dim_off applies to the input
361  * variables.
362  */
363 static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
364                             struct isl_basic_map *src_map, isl_int *src,
365                             unsigned in_off, unsigned out_off, unsigned div_off)
366 {
367         isl_int_set(dst[0], src[0]);
368         isl_seq_cpy(dst+1, src+1, isl_min(dst_map->nparam, src_map->nparam));
369         if (dst_map->nparam > src_map->nparam)
370                 isl_seq_clr(dst+1+src_map->nparam,
371                                 dst_map->nparam - src_map->nparam);
372         isl_seq_clr(dst+1+dst_map->nparam, in_off);
373         isl_seq_cpy(dst+1+dst_map->nparam+in_off,
374                     src+1+src_map->nparam,
375                     isl_min(dst_map->n_in-in_off, src_map->n_in));
376         if (dst_map->n_in-in_off > src_map->n_in)
377                 isl_seq_clr(dst+1+dst_map->nparam+in_off+src_map->n_in,
378                                 dst_map->n_in - in_off - src_map->n_in);
379         isl_seq_clr(dst+1+dst_map->nparam+dst_map->n_in, out_off);
380         isl_seq_cpy(dst+1+dst_map->nparam+dst_map->n_in+out_off,
381                     src+1+src_map->nparam+src_map->n_in,
382                     isl_min(dst_map->n_out-out_off, src_map->n_out));
383         if (dst_map->n_out-out_off > src_map->n_out)
384                 isl_seq_clr(dst+1+dst_map->nparam+dst_map->n_in+out_off+src_map->n_out,
385                                 dst_map->n_out - out_off - src_map->n_out);
386         isl_seq_clr(dst+1+dst_map->nparam+dst_map->n_in+dst_map->n_out, div_off);
387         isl_seq_cpy(dst+1+dst_map->nparam+dst_map->n_in+dst_map->n_out+div_off,
388                     src+1+src_map->nparam+src_map->n_in+src_map->n_out,
389                     isl_min(dst_map->extra-div_off, src_map->extra));
390         if (dst_map->extra-div_off > src_map->extra)
391                 isl_seq_clr(dst+1+dst_map->nparam+dst_map->n_in+dst_map->n_out+
392                                 div_off+src_map->extra,
393                                 dst_map->extra - div_off - src_map->extra);
394 }
395
396 static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
397                      struct isl_basic_map *src_map, isl_int *src,
398                      unsigned in_off, unsigned out_off, unsigned div_off)
399 {
400         isl_int_set(dst[0], src[0]);
401         copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
402 }
403
404 static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1,
405                 struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos)
406 {
407         int i;
408         unsigned div_off;
409
410         if (!bmap1 || !bmap2)
411                 goto error;
412
413         div_off = bmap1->n_div;
414
415         for (i = 0; i < bmap2->n_eq; ++i) {
416                 int i1 = isl_basic_map_alloc_equality(bmap1);
417                 if (i1 < 0)
418                         goto error;
419                 copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
420                                 i_pos, o_pos, div_off);
421         }
422
423         for (i = 0; i < bmap2->n_ineq; ++i) {
424                 int i1 = isl_basic_map_alloc_inequality(bmap1);
425                 if (i1 < 0)
426                         goto error;
427                 copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
428                                 i_pos, o_pos, div_off);
429         }
430
431         for (i = 0; i < bmap2->n_div; ++i) {
432                 int i1 = isl_basic_map_alloc_div(bmap1);
433                 if (i1 < 0)
434                         goto error;
435                 copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
436                          i_pos, o_pos, div_off);
437         }
438
439         isl_basic_map_free(bmap2);
440
441         return bmap1;
442
443 error:
444         isl_basic_map_free(bmap1);
445         isl_basic_map_free(bmap2);
446         return NULL;
447 }
448
449 static struct isl_basic_set *set_add_constraints(struct isl_basic_set *bset1,
450                 struct isl_basic_set *bset2, unsigned pos)
451 {
452         return (struct isl_basic_set *)
453                 add_constraints((struct isl_basic_map *)bset1,
454                                 (struct isl_basic_map *)bset2, 0, pos);
455 }
456
457 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
458                 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
459                 unsigned n_eq, unsigned n_ineq)
460 {
461         struct isl_basic_map *ext;
462         unsigned flags;
463         int dims_ok;
464
465         base = isl_basic_map_cow(base);
466         if (!base)
467                 goto error;
468
469         dims_ok = base && base->nparam == nparam &&
470                   base->n_in == n_in && base->n_out == n_out &&
471                   base->extra >= base->n_div + extra;
472
473         if (dims_ok && n_eq == 0 && n_ineq == 0)
474                 return base;
475
476         isl_assert(base->ctx, base->nparam <= nparam, goto error);
477         isl_assert(base->ctx, base->n_in <= n_in, goto error);
478         isl_assert(base->ctx, base->n_out <= n_out, goto error);
479         extra += base->extra;
480         n_eq += base->n_eq;
481         n_ineq += base->n_ineq;
482
483         ext = isl_basic_map_alloc(base->ctx, nparam, n_in, n_out,
484                                         extra, n_eq, n_ineq);
485         if (!base)
486                 return ext;
487         if (!ext)
488                 goto error;
489
490         flags = base->flags;
491         ext = add_constraints(ext, base, 0, 0);
492         if (ext) {
493                 ext->flags = flags;
494                 F_CLR(ext, ISL_BASIC_SET_FINAL);
495         }
496
497         return ext;
498
499 error:
500         isl_basic_map_free(base);
501         return NULL;
502 }
503
504 struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
505                 unsigned nparam, unsigned dim, unsigned extra,
506                 unsigned n_eq, unsigned n_ineq)
507 {
508         return (struct isl_basic_set *)
509                 isl_basic_map_extend((struct isl_basic_map *)base,
510                                         nparam, 0, dim, extra, n_eq, n_ineq);
511 }
512
513 struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset)
514 {
515         return (struct isl_basic_set *)
516                 isl_basic_map_cow((struct isl_basic_map *)bset);
517 }
518
519 struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap)
520 {
521         if (!bmap)
522                 return NULL;
523
524         if (bmap->ref > 1) {
525                 bmap->ref--;
526                 bmap = isl_basic_map_dup(bmap);
527         }
528         F_CLR(bmap, ISL_BASIC_SET_FINAL);
529         return bmap;
530 }
531
532 struct isl_set *isl_set_cow(struct isl_set *set)
533 {
534         if (!set)
535                 return NULL;
536
537         if (set->ref == 1)
538                 return set;
539         set->ref--;
540         return isl_set_dup(set);
541 }
542
543 struct isl_map *isl_map_cow(struct isl_map *map)
544 {
545         if (!map)
546                 return NULL;
547
548         if (map->ref == 1)
549                 return map;
550         map->ref--;
551         return isl_map_dup(map);
552 }
553
554 static void swap_vars(struct isl_blk blk, isl_int *a,
555                         unsigned a_len, unsigned b_len)
556 {
557         isl_seq_cpy(blk.data, a+a_len, b_len);
558         isl_seq_cpy(blk.data+b_len, a, a_len);
559         isl_seq_cpy(a, blk.data, b_len+a_len);
560 }
561
562 struct isl_basic_set *isl_basic_set_swap_vars(
563                 struct isl_basic_set *bset, unsigned n)
564 {
565         int i;
566         struct isl_blk blk;
567
568         if (!bset)
569                 goto error;
570
571         isl_assert(bset->ctx, n <= bset->dim, goto error);
572
573         if (n == bset->dim)
574                 return bset;
575
576         bset = isl_basic_set_cow(bset);
577         if (!bset)
578                 return NULL;
579
580         blk = isl_blk_alloc(bset->ctx, bset->dim);
581         if (isl_blk_is_error(blk))
582                 goto error;
583
584         for (i = 0; i < bset->n_eq; ++i)
585                 swap_vars(blk,
586                           bset->eq[i]+1+bset->nparam, n, bset->dim - n);
587
588         for (i = 0; i < bset->n_ineq; ++i)
589                 swap_vars(blk,
590                           bset->ineq[i]+1+bset->nparam, n, bset->dim - n);
591
592         for (i = 0; i < bset->n_div; ++i)
593                 swap_vars(blk,
594                           bset->div[i]+1+1+bset->nparam, n, bset->dim - n);
595
596         isl_blk_free(bset->ctx, blk);
597
598         return bset;
599
600 error:
601         isl_basic_set_free(bset);
602         return NULL;
603 }
604
605 struct isl_set *isl_set_swap_vars(struct isl_set *set, unsigned n)
606 {
607         int i;
608         set = isl_set_cow(set);
609         if (!set)
610                 return NULL;
611
612         for (i = 0; i < set->n; ++i) {
613                 set->p[i] = isl_basic_set_swap_vars(set->p[i], n);
614                 if (!set->p[i]) {
615                         isl_set_free(set);
616                         return NULL;
617                 }
618         }
619         return set;
620 }
621
622 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
623 {
624         isl_seq_cpy(c, c + n, rem);
625         isl_seq_clr(c + rem, n);
626 }
627
628 struct isl_basic_set *isl_basic_set_drop_dims(
629                 struct isl_basic_set *bset, unsigned first, unsigned n)
630 {
631         int i;
632
633         if (!bset)
634                 goto error;
635
636         isl_assert(bset->ctx, first + n <= bset->dim, goto error);
637
638         if (n == 0)
639                 return bset;
640
641         bset = isl_basic_set_cow(bset);
642         if (!bset)
643                 return NULL;
644
645         for (i = 0; i < bset->n_eq; ++i)
646                 constraint_drop_vars(bset->eq[i]+1+bset->nparam+first, n,
647                                      (bset->dim-first-n)+bset->extra);
648
649         for (i = 0; i < bset->n_ineq; ++i)
650                 constraint_drop_vars(bset->ineq[i]+1+bset->nparam+first, n,
651                                      (bset->dim-first-n)+bset->extra);
652
653         for (i = 0; i < bset->n_div; ++i)
654                 constraint_drop_vars(bset->div[i]+1+1+bset->nparam+first, n,
655                                      (bset->dim-first-n)+bset->extra);
656
657         bset->dim -= n;
658         bset->extra += n;
659
660         bset = isl_basic_set_simplify(bset);
661         return isl_basic_set_finalize(bset);
662 error:
663         isl_basic_set_free(bset);
664         return NULL;
665 }
666
667 static struct isl_set *isl_set_drop_dims(
668                 struct isl_set *set, unsigned first, unsigned n)
669 {
670         int i;
671
672         if (!set)
673                 goto error;
674
675         isl_assert(set->ctx, first + n <= set->dim, goto error);
676
677         if (n == 0)
678                 return set;
679         set = isl_set_cow(set);
680         if (!set)
681                 goto error;
682
683         for (i = 0; i < set->n; ++i) {
684                 set->p[i] = isl_basic_set_drop_dims(set->p[i], first, n);
685                 if (!set->p[i])
686                         goto error;
687         }
688         set->dim -= n;
689
690         return set;
691 error:
692         isl_set_free(set);
693         return NULL;
694 }
695
696 struct isl_basic_map *isl_basic_map_drop_inputs(
697                 struct isl_basic_map *bmap, unsigned first, unsigned n)
698 {
699         int i;
700
701         if (!bmap)
702                 goto error;
703
704         isl_assert(bmap->ctx, first + n <= bmap->n_in, goto error);
705
706         if (n == 0)
707                 return bmap;
708
709         bmap = isl_basic_map_cow(bmap);
710         if (!bmap)
711                 return NULL;
712
713         for (i = 0; i < bmap->n_eq; ++i)
714                 constraint_drop_vars(bmap->eq[i]+1+bmap->nparam+first, n,
715                                  (bmap->n_in-first-n)+bmap->n_out+bmap->extra);
716
717         for (i = 0; i < bmap->n_ineq; ++i)
718                 constraint_drop_vars(bmap->ineq[i]+1+bmap->nparam+first, n,
719                                  (bmap->n_in-first-n)+bmap->n_out+bmap->extra);
720
721         for (i = 0; i < bmap->n_div; ++i)
722                 constraint_drop_vars(bmap->div[i]+1+1+bmap->nparam+first, n,
723                                  (bmap->n_in-first-n)+bmap->n_out+bmap->extra);
724
725         bmap->n_in -= n;
726         bmap->extra += n;
727
728         bmap = isl_basic_map_simplify(bmap);
729         return isl_basic_map_finalize(bmap);
730 error:
731         isl_basic_map_free(bmap);
732         return NULL;
733 }
734
735 static struct isl_map *isl_map_drop_inputs(
736                 struct isl_map *map, unsigned first, unsigned n)
737 {
738         int i;
739
740         if (!map)
741                 goto error;
742
743         isl_assert(map->ctx, first + n <= map->n_in, goto error);
744
745         if (n == 0)
746                 return map;
747         map = isl_map_cow(map);
748         if (!map)
749                 goto error;
750
751         for (i = 0; i < map->n; ++i) {
752                 map->p[i] = isl_basic_map_drop_inputs(map->p[i], first, n);
753                 if (!map->p[i])
754                         goto error;
755         }
756         map->n_in -= n;
757
758         return map;
759 error:
760         isl_map_free(map);
761         return NULL;
762 }
763
764 /*
765  * We don't cow, as the div is assumed to be redundant.
766  */
767 static struct isl_basic_map *isl_basic_map_drop_div(
768                 struct isl_basic_map *bmap, unsigned div)
769 {
770         int i;
771         unsigned pos;
772
773         if (!bmap)
774                 goto error;
775
776         pos = 1 + bmap->nparam + bmap->n_in + bmap->n_out + div;
777
778         isl_assert(bmap->ctx, div < bmap->n_div, goto error);
779
780         for (i = 0; i < bmap->n_eq; ++i)
781                 constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
782
783         for (i = 0; i < bmap->n_ineq; ++i) {
784                 if (!isl_int_is_zero(bmap->ineq[i][pos])) {
785                         isl_basic_map_drop_inequality(bmap, i);
786                         --i;
787                         continue;
788                 }
789                 constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
790         }
791
792         for (i = 0; i < bmap->n_div; ++i)
793                 constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
794
795         if (div != bmap->n_div - 1) {
796                 int j;
797                 isl_int *t = bmap->div[div];
798
799                 for (j = div; j < bmap->n_div - 1; ++j)
800                         bmap->div[j] = bmap->div[j+1];
801
802                 bmap->div[bmap->n_div - 1] = t;
803         }
804         isl_basic_map_free_div(bmap, 1);
805
806         return bmap;
807 error:
808         isl_basic_map_free(bmap);
809         return NULL;
810 }
811
812 static void eliminate_div(struct isl_basic_map *bmap, isl_int *eq, unsigned div)
813 {
814         int i;
815         unsigned pos = 1 + bmap->nparam + bmap->n_in + bmap->n_out + div;
816         unsigned len;
817         len = 1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
818
819         for (i = 0; i < bmap->n_eq; ++i)
820                 if (bmap->eq[i] != eq)
821                         isl_seq_elim(bmap->eq[i], eq, pos, len, NULL);
822
823         for (i = 0; i < bmap->n_ineq; ++i)
824                 isl_seq_elim(bmap->ineq[i], eq, pos, len, NULL);
825
826         /* We need to be careful about circular definitions,
827          * so for now we just remove the definitions of other divs that
828          * depend on this div and (possibly) recompute them later.
829          */
830         for (i = 0; i < bmap->n_div; ++i)
831                 if (!isl_int_is_zero(bmap->div[i][0]) &&
832                     !isl_int_is_zero(bmap->div[i][1 + pos]))
833                         isl_seq_clr(bmap->div[i], 1 + len);
834
835         isl_basic_map_drop_div(bmap, div);
836 }
837
838 struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap)
839 {
840         int i = 0;
841         unsigned total;
842         if (!bmap)
843                 goto error;
844         total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra;
845         isl_basic_map_free_div(bmap, bmap->n_div);
846         isl_basic_map_free_inequality(bmap, bmap->n_ineq);
847         if (bmap->n_eq > 0)
848                 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
849         else {
850                 isl_basic_map_alloc_equality(bmap);
851                 if (i < 0)
852                         goto error;
853         }
854         isl_int_set_si(bmap->eq[i][0], 1);
855         isl_seq_clr(bmap->eq[i]+1, total);
856         F_SET(bmap, ISL_BASIC_MAP_EMPTY);
857         return isl_basic_map_finalize(bmap);
858 error:
859         isl_basic_map_free(bmap);
860         return NULL;
861 }
862
863 struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset)
864 {
865         return (struct isl_basic_set *)
866                 isl_basic_map_set_to_empty((struct isl_basic_map *)bset);
867 }
868
869 static void swap_equality(struct isl_basic_map *bmap, int a, int b)
870 {
871         isl_int *t = bmap->eq[a];
872         bmap->eq[a] = bmap->eq[b];
873         bmap->eq[b] = t;
874 }
875
876 static void swap_inequality(struct isl_basic_map *bmap, int a, int b)
877 {
878         if (a != b) {
879                 isl_int *t = bmap->ineq[a];
880                 bmap->ineq[a] = bmap->ineq[b];
881                 bmap->ineq[b] = t;
882         }
883 }
884
885 static void set_swap_inequality(struct isl_basic_set *bset, int a, int b)
886 {
887         swap_inequality((struct isl_basic_map *)bset, a, b);
888 }
889
890 static void swap_div(struct isl_basic_map *bmap, int a, int b)
891 {
892         int i;
893         unsigned off = bmap->nparam + bmap->n_in + bmap->n_out;
894         isl_int *t = bmap->div[a];
895         bmap->div[a] = bmap->div[b];
896         bmap->div[b] = t;
897
898         for (i = 0; i < bmap->n_eq; ++i)
899                 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
900
901         for (i = 0; i < bmap->n_ineq; ++i)
902                 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
903
904         for (i = 0; i < bmap->n_div; ++i)
905                 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
906 }
907
908 static void eliminate_var_using_equality(struct isl_basic_map *bmap,
909         unsigned pos, isl_int *eq, int *progress)
910 {
911         unsigned total;
912         int k;
913
914         total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
915         for (k = 0; k < bmap->n_eq; ++k) {
916                 if (bmap->eq[k] == eq)
917                         continue;
918                 if (isl_int_is_zero(bmap->eq[k][1+pos]))
919                         continue;
920                 if (progress)
921                         *progress = 1;
922                 isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL);
923         }
924
925         for (k = 0; k < bmap->n_ineq; ++k) {
926                 if (isl_int_is_zero(bmap->ineq[k][1+pos]))
927                         continue;
928                 if (progress)
929                         *progress = 1;
930                 isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL);
931         }
932
933         for (k = 0; k < bmap->n_div; ++k) {
934                 if (isl_int_is_zero(bmap->div[k][0]))
935                         continue;
936                 if (isl_int_is_zero(bmap->div[k][1+1+pos]))
937                         continue;
938                 if (progress)
939                         *progress = 1;
940                 isl_seq_elim(bmap->div[k]+1, eq,
941                                 1+pos, 1+total, &bmap->div[k][0]);
942         }
943 }
944         
945
946 struct isl_basic_map *isl_basic_map_gauss(
947         struct isl_basic_map *bmap, int *progress)
948 {
949         int k;
950         int done;
951         int last_var;
952         unsigned total_var;
953         unsigned total;
954
955         if (!bmap)
956                 return NULL;
957
958         total_var = bmap->nparam + bmap->n_in + bmap->n_out;
959         total = total_var + bmap->n_div;
960
961         last_var = total - 1;
962         for (done = 0; done < bmap->n_eq; ++done) {
963                 for (; last_var >= 0; --last_var) {
964                         for (k = done; k < bmap->n_eq; ++k)
965                                 if (!isl_int_is_zero(bmap->eq[k][1+last_var]))
966                                         break;
967                         if (k < bmap->n_eq)
968                                 break;
969                 }
970                 if (last_var < 0)
971                         break;
972                 if (k != done)
973                         swap_equality(bmap, k, done);
974                 if (isl_int_is_neg(bmap->eq[done][1+last_var]))
975                         isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total);
976
977                 eliminate_var_using_equality(bmap, last_var, bmap->eq[done],
978                                                 progress);
979
980                 if (last_var >= total_var &&
981                     isl_int_is_zero(bmap->div[last_var - total_var][0])) {
982                         unsigned div = last_var - total_var;
983                         isl_seq_neg(bmap->div[div]+1, bmap->eq[done], 1+total);
984                         isl_int_set_si(bmap->div[div][1+1+last_var], 0);
985                         isl_int_set(bmap->div[div][0],
986                                     bmap->eq[done][1+last_var]);
987                 }
988         }
989         if (done == bmap->n_eq)
990                 return bmap;
991         for (k = done; k < bmap->n_eq; ++k) {
992                 if (isl_int_is_zero(bmap->eq[k][0]))
993                         continue;
994                 return isl_basic_map_set_to_empty(bmap);
995         }
996         isl_basic_map_free_equality(bmap, bmap->n_eq-done);
997         return bmap;
998 }
999
1000 struct isl_basic_set *isl_basic_set_gauss(
1001         struct isl_basic_set *bset, int *progress)
1002 {
1003         return (struct isl_basic_set*)isl_basic_map_gauss(
1004                         (struct isl_basic_map *)bset, progress);
1005 }
1006
1007 static unsigned int round_up(unsigned int v)
1008 {
1009         int old_v = v;
1010
1011         while (v) {
1012                 old_v = v;
1013                 v ^= v & -v;
1014         }
1015         return old_v << 1;
1016 }
1017
1018 static int hash_index(int *index, unsigned int size, int bits,
1019                         struct isl_basic_map *bmap, int k)
1020 {
1021         int h;
1022         unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
1023         u_int32_t hash = isl_seq_hash(bmap->ineq[k]+1, total, bits);
1024         for (h = hash; index[h]; h = (h+1) % size)
1025                 if (k != index[h]-1 &&
1026                     isl_seq_eq(bmap->ineq[k]+1,
1027                                bmap->ineq[index[h]-1]+1, total))
1028                         break;
1029         return h;
1030 }
1031
1032 static struct isl_basic_map *remove_duplicate_constraints(
1033         struct isl_basic_map *bmap, int *progress)
1034 {
1035         unsigned int size;
1036         int *index;
1037         int k, l, h;
1038         int bits;
1039         unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
1040         isl_int sum;
1041
1042         if (bmap->n_ineq <= 1)
1043                 return bmap;
1044
1045         size = round_up(4 * (bmap->n_ineq+1) / 3 - 1);
1046         bits = ffs(size) - 1;
1047         index = isl_alloc_array(ctx, int, size);
1048         memset(index, 0, size * sizeof(int));
1049         if (!index)
1050                 return bmap;
1051
1052         index[isl_seq_hash(bmap->ineq[0]+1, total, bits)] = 1;
1053         for (k = 1; k < bmap->n_ineq; ++k) {
1054                 h = hash_index(index, size, bits, bmap, k);
1055                 if (!index[h]) {
1056                         index[h] = k+1;
1057                         continue;
1058                 }
1059                 if (progress)
1060                         *progress = 1;
1061                 l = index[h] - 1;
1062                 if (isl_int_lt(bmap->ineq[k][0], bmap->ineq[l][0]))
1063                         swap_inequality(bmap, k, l);
1064                 isl_basic_map_drop_inequality(bmap, k);
1065                 --k;
1066         }
1067         isl_int_init(sum);
1068         for (k = 0; k < bmap->n_ineq-1; ++k) {
1069                 isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
1070                 h = hash_index(index, size, bits, bmap, k);
1071                 isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
1072                 if (!index[h])
1073                         continue;
1074                 l = index[h] - 1;
1075                 isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0]);
1076                 if (isl_int_is_pos(sum))
1077                         continue;
1078                 if (isl_int_is_zero(sum)) {
1079                         /* We need to break out of the loop after these
1080                          * changes since the contents of the hash
1081                          * will no longer be valid.
1082                          * Plus, we probably we want to regauss first.
1083                          */
1084                         isl_basic_map_drop_inequality(bmap, l);
1085                         isl_basic_map_inequality_to_equality(bmap, k);
1086                 } else
1087                         bmap = isl_basic_map_set_to_empty(bmap);
1088                 break;
1089         }
1090         isl_int_clear(sum);
1091
1092         free(index);
1093         return bmap;
1094 }
1095
1096 static struct isl_basic_map *remove_duplicate_divs(
1097         struct isl_basic_map *bmap, int *progress)
1098 {
1099         unsigned int size;
1100         int *index;
1101         int k, l, h;
1102         int bits;
1103         struct isl_blk eq;
1104         unsigned total_var = bmap->nparam + bmap->n_in + bmap->n_out;
1105         unsigned total = total_var + bmap->n_div;
1106         struct isl_ctx *ctx;
1107
1108         if (bmap->n_div <= 1)
1109                 return bmap;
1110
1111         ctx = bmap->ctx;
1112         for (k = bmap->n_div - 1; k >= 0; --k)
1113                 if (!isl_int_is_zero(bmap->div[k][0]))
1114                         break;
1115         if (k <= 0)
1116                 return bmap;
1117
1118         size = round_up(4 * bmap->n_div / 3 - 1);
1119         bits = ffs(size) - 1;
1120         index = isl_alloc_array(ctx, int, size);
1121         memset(index, 0, size * sizeof(int));
1122         if (!index)
1123                 return bmap;
1124         eq = isl_blk_alloc(ctx, 1+total);
1125         if (isl_blk_is_error(eq))
1126                 goto out;
1127
1128         isl_seq_clr(eq.data, 1+total);
1129         index[isl_seq_hash(bmap->div[k], 2+total, bits)] = k + 1;
1130         for (--k; k >= 0; --k) {
1131                 u_int32_t hash;
1132
1133                 if (isl_int_is_zero(bmap->div[k][0]))
1134                         continue;
1135
1136                 hash = isl_seq_hash(bmap->div[k], 2+total, bits);
1137                 for (h = hash; index[h]; h = (h+1) % size)
1138                         if (isl_seq_eq(bmap->div[k],
1139                                        bmap->div[index[h]-1], 2+total))
1140                                 break;
1141                 if (index[h]) {
1142                         *progress = 1;
1143                         l = index[h] - 1;
1144                         isl_int_set_si(eq.data[1+total_var+k], -1);
1145                         isl_int_set_si(eq.data[1+total_var+l], 1);
1146                         eliminate_div(bmap, eq.data, l);
1147                         isl_int_set_si(eq.data[1+total_var+k], 0);
1148                         isl_int_set_si(eq.data[1+total_var+l], 0);
1149                 }
1150                 index[h] = k+1;
1151         }
1152
1153         isl_blk_free(ctx, eq);
1154 out:
1155         free(index);
1156         return bmap;
1157 }
1158
1159 /* Elimininate divs based on equalities
1160  */
1161 static struct isl_basic_map *eliminate_divs_eq(
1162                 struct isl_basic_map *bmap, int *progress)
1163 {
1164         int d;
1165         int i;
1166         int modified = 0;
1167         unsigned off;
1168
1169         if (!bmap)
1170                 return NULL;
1171
1172         off = 1 + bmap->nparam + bmap->n_in + bmap->n_out;
1173
1174         for (d = bmap->n_div - 1; d >= 0 ; --d) {
1175                 for (i = 0; i < bmap->n_eq; ++i) {
1176                         if (!isl_int_is_one(bmap->eq[i][off + d]) &&
1177                             !isl_int_is_negone(bmap->eq[i][off + d]))
1178                                 continue;
1179                         modified = 1;
1180                         *progress = 1;
1181                         eliminate_div(bmap, bmap->eq[i], d);
1182                         isl_basic_map_drop_equality(bmap, i);
1183                         break;
1184                 }
1185         }
1186         if (modified)
1187                 return eliminate_divs_eq(bmap, progress);
1188         return bmap;
1189 }
1190
1191 static struct isl_basic_map *normalize_constraints(struct isl_basic_map *bmap)
1192 {
1193         int i;
1194         isl_int gcd;
1195         unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
1196
1197         isl_int_init(gcd);
1198         for (i = bmap->n_eq - 1; i >= 0; --i) {
1199                 isl_seq_gcd(bmap->eq[i]+1, total, &gcd);
1200                 if (isl_int_is_zero(gcd)) {
1201                         if (!isl_int_is_zero(bmap->eq[i][0])) {
1202                                 bmap = isl_basic_map_set_to_empty(bmap);
1203                                 break;
1204                         }
1205                         isl_basic_map_drop_equality(bmap, i);
1206                         continue;
1207                 }
1208                 if (F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
1209                         isl_int_gcd(gcd, gcd, bmap->eq[i][0]);
1210                 if (isl_int_is_one(gcd))
1211                         continue;
1212                 if (!isl_int_is_divisible_by(bmap->eq[i][0], gcd)) {
1213                         bmap = isl_basic_map_set_to_empty(bmap);
1214                         break;
1215                 }
1216                 isl_seq_scale_down(bmap->eq[i], bmap->eq[i], gcd, 1+total);
1217         }
1218
1219         for (i = bmap->n_ineq - 1; i >= 0; --i) {
1220                 isl_seq_gcd(bmap->ineq[i]+1, total, &gcd);
1221                 if (isl_int_is_zero(gcd)) {
1222                         if (isl_int_is_neg(bmap->ineq[i][0])) {
1223                                 bmap = isl_basic_map_set_to_empty(bmap);
1224                                 break;
1225                         }
1226                         isl_basic_map_drop_inequality(bmap, i);
1227                         continue;
1228                 }
1229                 if (F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
1230                         isl_int_gcd(gcd, gcd, bmap->ineq[i][0]);
1231                 if (isl_int_is_one(gcd))
1232                         continue;
1233                 isl_int_fdiv_q(bmap->ineq[i][0], bmap->ineq[i][0], gcd);
1234                 isl_seq_scale_down(bmap->ineq[i]+1, bmap->ineq[i]+1, gcd, total);
1235         }
1236         isl_int_clear(gcd);
1237
1238         return bmap;
1239 }
1240
1241
1242 /* Eliminate the specified variables from the constraints using
1243  * Fourier-Motzkin.  The variables themselves are not removed.
1244  */
1245 struct isl_basic_map *isl_basic_map_eliminate_vars(
1246         struct isl_basic_map *bmap, int pos, unsigned n)
1247 {
1248         int d;
1249         int i, j, k;
1250         unsigned total;
1251         unsigned extra;
1252
1253         if (!bmap)
1254                 return NULL;
1255         total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
1256         extra = bmap->extra - bmap->n_div;
1257
1258         bmap = isl_basic_map_cow(bmap);
1259         for (d = pos + n - 1; d >= pos; --d) {
1260                 int n_lower, n_upper;
1261                 if (!bmap)
1262                         return NULL;
1263                 for (i = 0; i < bmap->n_eq; ++i) {
1264                         if (isl_int_is_zero(bmap->eq[i][1+d]))
1265                                 continue;
1266                         eliminate_var_using_equality(bmap, d, bmap->eq[i], NULL);
1267                         isl_basic_map_drop_equality(bmap, i);
1268                         break;
1269                 }
1270                 if (i < bmap->n_eq)
1271                         continue;
1272                 n_lower = 0;
1273                 n_upper = 0;
1274                 for (i = 0; i < bmap->n_ineq; ++i) {
1275                         if (isl_int_is_pos(bmap->ineq[i][1+d]))
1276                                 n_lower++;
1277                         else if (isl_int_is_neg(bmap->ineq[i][1+d]))
1278                                 n_upper++;
1279                 }
1280                 bmap = isl_basic_map_extend(bmap,
1281                                 bmap->nparam, bmap->n_in, bmap->n_out, 0,
1282                                 0, n_lower * n_upper);
1283                 for (i = bmap->n_ineq - 1; i >= 0; --i) {
1284                         int last;
1285                         if (isl_int_is_zero(bmap->ineq[i][1+d]))
1286                                 continue;
1287                         last = -1;
1288                         for (j = 0; j < i; ++j) {
1289                                 if (isl_int_is_zero(bmap->ineq[j][1+d]))
1290                                         continue;
1291                                 last = j;
1292                                 if (isl_int_sgn(bmap->ineq[i][1+d]) ==
1293                                     isl_int_sgn(bmap->ineq[j][1+d]))
1294                                         continue;
1295                                 k = isl_basic_map_alloc_inequality(bmap);
1296                                 if (k < 0)
1297                                         goto error;
1298                                 isl_seq_cpy(bmap->ineq[k], bmap->ineq[i],
1299                                                 1+total);
1300                                 isl_seq_clr(bmap->ineq[k]+1+total, extra);
1301                                 isl_seq_elim(bmap->ineq[k], bmap->ineq[j],
1302                                                 1+d, 1+total, NULL);
1303                         }
1304                         isl_basic_map_drop_inequality(bmap, i);
1305                         i = last + 1;
1306                 }
1307                 if (n_lower > 0 && n_upper > 0) {
1308                         bmap = normalize_constraints(bmap);
1309                         bmap = remove_duplicate_constraints(bmap, NULL);
1310                         bmap = isl_basic_map_gauss(bmap, NULL);
1311                         bmap = isl_basic_map_convex_hull(bmap);
1312                         if (!bmap)
1313                                 goto error;
1314                         if (F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
1315                                 break;
1316                 }
1317         }
1318         return bmap;
1319 error:
1320         isl_basic_map_free(bmap);
1321         return NULL;
1322 }
1323
1324 struct isl_basic_set *isl_basic_set_eliminate_vars(
1325         struct isl_basic_set *bset, unsigned pos, unsigned n)
1326 {
1327         return (struct isl_basic_set *)isl_basic_map_eliminate_vars(
1328                         (struct isl_basic_map *)bset, pos, n);
1329 }
1330
1331 /* Project out n dimensions starting at first using Fourier-Motzkin */
1332 struct isl_set *isl_set_remove_dims(struct isl_set *set,
1333         unsigned first, unsigned n)
1334 {
1335         int i;
1336
1337         if (n == 0)
1338                 return set;
1339
1340         set = isl_set_cow(set);
1341         if (!set)
1342                 return NULL;
1343         isl_assert(set->ctx, first+n <= set->dim, goto error);
1344         
1345         for (i = 0; i < set->n; ++i) {
1346                 set->p[i] = isl_basic_set_eliminate_vars(set->p[i],
1347                                                         set->nparam + first, n);
1348                 if (!set->p[i])
1349                         goto error;
1350         }
1351         set = isl_set_drop_dims(set, first, n);
1352         return set;
1353 error:
1354         isl_set_free(set);
1355         return NULL;
1356 }
1357
1358 /* Project out n inputs starting at first using Fourier-Motzkin */
1359 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
1360         unsigned first, unsigned n)
1361 {
1362         int i;
1363
1364         if (n == 0)
1365                 return map;
1366
1367         map = isl_map_cow(map);
1368         if (!map)
1369                 return NULL;
1370         isl_assert(map->ctx, first+n <= map->n_in, goto error);
1371         
1372         for (i = 0; i < map->n; ++i) {
1373                 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
1374                                                         map->nparam + first, n);
1375                 if (!map->p[i])
1376                         goto error;
1377         }
1378         map = isl_map_drop_inputs(map, first, n);
1379         return map;
1380 error:
1381         isl_map_free(map);
1382         return NULL;
1383 }
1384
1385 /* Project out n dimensions starting at first using Fourier-Motzkin */
1386 struct isl_basic_set *isl_basic_set_remove_dims(struct isl_basic_set *bset,
1387         unsigned first, unsigned n)
1388 {
1389         bset = isl_basic_set_eliminate_vars(bset, bset->nparam + first, n);
1390         bset = isl_basic_set_drop_dims(bset, first, n);
1391         return bset;
1392 }
1393
1394 /* Elimininate divs based on inequalities
1395  */
1396 static struct isl_basic_map *eliminate_divs_ineq(
1397                 struct isl_basic_map *bmap, int *progress)
1398 {
1399         int d;
1400         int i;
1401         unsigned off;
1402         struct isl_ctx *ctx;
1403
1404         if (!bmap)
1405                 return NULL;
1406
1407         ctx = bmap->ctx;
1408         off = 1 + bmap->nparam + bmap->n_in + bmap->n_out;
1409
1410         for (d = bmap->n_div - 1; d >= 0 ; --d) {
1411                 for (i = 0; i < bmap->n_eq; ++i)
1412                         if (!isl_int_is_zero(bmap->eq[i][off + d]))
1413                                 break;
1414                 if (i < bmap->n_eq)
1415                         continue;
1416                 for (i = 0; i < bmap->n_ineq; ++i)
1417                         if (isl_int_abs_gt(bmap->ineq[i][off + d], ctx->one))
1418                                 break;
1419                 if (i < bmap->n_ineq)
1420                         continue;
1421                 *progress = 1;
1422                 bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1);
1423                 if (F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
1424                         break;
1425                 bmap = isl_basic_map_drop_div(bmap, d);
1426                 if (!bmap)
1427                         break;
1428         }
1429         return bmap;
1430 }
1431
1432 struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap)
1433 {
1434         int progress = 1;
1435         if (!bmap)
1436                 return NULL;
1437         while (progress) {
1438                 progress = 0;
1439                 bmap = normalize_constraints(bmap);
1440                 bmap = eliminate_divs_eq(bmap, &progress);
1441                 bmap = eliminate_divs_ineq(bmap, &progress);
1442                 bmap = isl_basic_map_gauss(bmap, &progress);
1443                 bmap = remove_duplicate_divs(bmap, &progress);
1444                 bmap = remove_duplicate_constraints(bmap, &progress);
1445         }
1446         return bmap;
1447 }
1448
1449 struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset)
1450 {
1451         return (struct isl_basic_set *)
1452                 isl_basic_map_simplify((struct isl_basic_map *)bset);
1453 }
1454
1455 static void dump_term(struct isl_basic_map *bmap,
1456                         isl_int c, int pos, FILE *out)
1457 {
1458         unsigned in = bmap->n_in;
1459         unsigned dim = bmap->n_in + bmap->n_out;
1460         if (!pos)
1461                 isl_int_print(out, c);
1462         else {
1463                 if (!isl_int_is_one(c))
1464                         isl_int_print(out, c);
1465                 if (pos < 1 + bmap->nparam)
1466                         fprintf(out, "p%d", pos - 1);
1467                 else if (pos < 1 + bmap->nparam + in)
1468                         fprintf(out, "i%d", pos - 1 - bmap->nparam);
1469                 else if (pos < 1 + bmap->nparam + dim)
1470                         fprintf(out, "o%d", pos - 1 - bmap->nparam - in);
1471                 else
1472                         fprintf(out, "e%d", pos - 1 - bmap->nparam - dim);
1473         }
1474 }
1475
1476 static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
1477                                 int sign, FILE *out)
1478 {
1479         int i;
1480         int first;
1481         unsigned len = 1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
1482         isl_int v;
1483
1484         isl_int_init(v);
1485         for (i = 0, first = 1; i < len; ++i) {
1486                 if (isl_int_sgn(c[i]) * sign <= 0)
1487                         continue;
1488                 if (!first)
1489                         fprintf(out, " + ");
1490                 first = 0;
1491                 isl_int_abs(v, c[i]);
1492                 dump_term(bmap, v, i, out);
1493         }
1494         isl_int_clear(v);
1495         if (first)
1496                 fprintf(out, "0");
1497 }
1498
1499 static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
1500                                 const char *op, FILE *out, int indent)
1501 {
1502         int i;
1503
1504         fprintf(out, "%*s", indent, "");
1505
1506         dump_constraint_sign(bmap, c, 1, out);
1507         fprintf(out, " %s ", op);
1508         dump_constraint_sign(bmap, c, -1, out);
1509
1510         fprintf(out, "\n");
1511
1512         for (i = bmap->n_div; i < bmap->extra; ++i) {
1513                 if (isl_int_is_zero(c[1+bmap->nparam+bmap->n_in+bmap->n_out+i]))
1514                         continue;
1515                 fprintf(out, "%*s", indent, "");
1516                 fprintf(out, "ERROR: unused div coefficient not zero\n");
1517         }
1518 }
1519
1520 static void dump_constraints(struct isl_basic_map *bmap,
1521                                 isl_int **c, unsigned n,
1522                                 const char *op, FILE *out, int indent)
1523 {
1524         int i;
1525
1526         for (i = 0; i < n; ++i)
1527                 dump_constraint(bmap, c[i], op, out, indent);
1528 }
1529
1530 static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
1531 {
1532         int j;
1533         int first = 1;
1534         unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
1535
1536         for (j = 0; j < 1 + total; ++j) {
1537                 if (isl_int_is_zero(exp[j]))
1538                         continue;
1539                 if (!first && isl_int_is_pos(exp[j]))
1540                         fprintf(out, "+");
1541                 dump_term(bmap, exp[j], j, out);
1542                 first = 0;
1543         }
1544 }
1545
1546 static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
1547 {
1548         int i;
1549
1550         dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
1551         dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
1552
1553         for (i = 0; i < bmap->n_div; ++i) {
1554                 fprintf(out, "%*s", indent, "");
1555                 fprintf(out, "e%d = [(", i);
1556                 dump_affine(bmap, bmap->div[i]+1, out);
1557                 fprintf(out, ")/");
1558                 isl_int_print(out, bmap->div[i][0]);
1559                 fprintf(out, "]\n");
1560         }
1561 }
1562
1563 void isl_basic_set_dump(struct isl_basic_set *bset, FILE *out, int indent)
1564 {
1565         if (!bset) {
1566                 fprintf(out, "null basic set\n");
1567                 return;
1568         }
1569
1570         fprintf(out, "%*s", indent, "");
1571         fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
1572                         bset->ref, bset->nparam, bset->dim, bset->extra,
1573                         bset->flags);
1574         dump((struct isl_basic_map *)bset, out, indent);
1575 }
1576
1577 void isl_basic_map_dump(struct isl_basic_map *bmap, FILE *out, int indent)
1578 {
1579         if (!bmap) {
1580                 fprintf(out, "null basic map\n");
1581                 return;
1582         }
1583
1584         fprintf(out, "%*s", indent, "");
1585         fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, flags: %x\n",
1586                 bmap->ref,
1587                 bmap->nparam, bmap->n_in, bmap->n_out, bmap->extra, bmap->flags);
1588         dump(bmap, out, indent);
1589 }
1590
1591 int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
1592 {
1593         unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
1594         if (!bmap)
1595                 return -1;
1596         isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1597         isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
1598         isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
1599         return 0;
1600 }
1601
1602 struct isl_set *isl_set_alloc(struct isl_ctx *ctx,
1603                 unsigned nparam, unsigned dim, int n, unsigned flags)
1604 {
1605         struct isl_set *set;
1606
1607         isl_assert(ctx, n >= 0, return NULL);
1608         set = isl_alloc(ctx, struct isl_set,
1609                         sizeof(struct isl_set) +
1610                         n * sizeof(struct isl_basic_set *));
1611         if (!set)
1612                 return NULL;
1613
1614         set->ctx = ctx;
1615         isl_ctx_ref(ctx);
1616         set->ref = 1;
1617         set->size = n;
1618         set->n = 0;
1619         set->nparam = nparam;
1620         set->zero = 0;
1621         set->dim = dim;
1622         set->flags = flags;
1623         return set;
1624 }
1625
1626 struct isl_set *isl_set_dup(struct isl_set *set)
1627 {
1628         int i;
1629         struct isl_set *dup;
1630
1631         if (!set)
1632                 return NULL;
1633
1634         dup = isl_set_alloc(set->ctx, set->nparam, set->dim, set->n, set->flags);
1635         if (!dup)
1636                 return NULL;
1637         for (i = 0; i < set->n; ++i)
1638                 dup = isl_set_add(dup,
1639                                   isl_basic_set_dup(set->p[i]));
1640         return dup;
1641 }
1642
1643 struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset)
1644 {
1645         struct isl_set *set;
1646
1647         if (!bset)
1648                 return NULL;
1649
1650         set = isl_set_alloc(bset->ctx, bset->nparam, bset->dim, 1, ISL_MAP_DISJOINT);
1651         if (!set) {
1652                 isl_basic_set_free(bset);
1653                 return NULL;
1654         }
1655         return isl_set_add(set, bset);
1656 }
1657
1658 struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap)
1659 {
1660         struct isl_map *map;
1661
1662         if (!bmap)
1663                 return NULL;
1664
1665         map = isl_map_alloc(bmap->ctx, bmap->nparam, bmap->n_in, bmap->n_out, 1,
1666                                 ISL_MAP_DISJOINT);
1667         if (!map) {
1668                 isl_basic_map_free(bmap);
1669                 return NULL;
1670         }
1671         return isl_map_add(map, bmap);
1672 }
1673
1674 struct isl_set *isl_set_add(struct isl_set *set, struct isl_basic_set *bset)
1675 {
1676         if (!bset || !set)
1677                 goto error;
1678         isl_assert(set->ctx, set->nparam == bset->nparam, goto error);
1679         isl_assert(set->ctx, set->dim == bset->dim, goto error);
1680         isl_assert(set->ctx, set->n < set->size, goto error);
1681         set->p[set->n] = bset;
1682         set->n++;
1683         return set;
1684 error:
1685         if (set)
1686                 isl_set_free(set);
1687         if (bset)
1688                 isl_basic_set_free(bset);
1689         return NULL;
1690 }
1691
1692 void isl_set_free(struct isl_set *set)
1693 {
1694         int i;
1695
1696         if (!set)
1697                 return;
1698
1699         if (--set->ref > 0)
1700                 return;
1701
1702         isl_ctx_deref(set->ctx);
1703         for (i = 0; i < set->n; ++i)
1704                 isl_basic_set_free(set->p[i]);
1705         free(set);
1706 }
1707
1708 void isl_set_dump(struct isl_set *set, FILE *out, int indent)
1709 {
1710         int i;
1711
1712         if (!set) {
1713                 fprintf(out, "null set\n");
1714                 return;
1715         }
1716
1717         fprintf(out, "%*s", indent, "");
1718         fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
1719                         set->ref, set->n, set->nparam, set->dim, set->flags);
1720         for (i = 0; i < set->n; ++i) {
1721                 fprintf(out, "%*s", indent, "");
1722                 fprintf(out, "basic set %d:\n", i);
1723                 isl_basic_set_dump(set->p[i], out, indent+4);
1724         }
1725 }
1726
1727 void isl_map_dump(struct isl_map *map, FILE *out, int indent)
1728 {
1729         int i;
1730
1731         if (!map) {
1732                 fprintf(out, "null map\n");
1733                 return;
1734         }
1735
1736         fprintf(out, "%*s", indent, "");
1737         fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, flags: %x\n",
1738                         map->ref, map->n, map->nparam, map->n_in, map->n_out,
1739                         map->flags);
1740         for (i = 0; i < map->n; ++i) {
1741                 fprintf(out, "%*s", indent, "");
1742                 fprintf(out, "basic map %d:\n", i);
1743                 isl_basic_map_dump(map->p[i], out, indent+4);
1744         }
1745 }
1746
1747 struct isl_basic_map *isl_basic_map_intersect_domain(
1748                 struct isl_basic_map *bmap, struct isl_basic_set *bset)
1749 {
1750         struct isl_basic_map *bmap_domain;
1751
1752         if (!bmap || !bset)
1753                 goto error;
1754
1755         isl_assert(bset->ctx, bset->dim == bmap->n_in, goto error);
1756         isl_assert(bset->ctx, bset->nparam == bmap->nparam, goto error);
1757
1758         bmap = isl_basic_map_extend(bmap,
1759                         bset->nparam, bmap->n_in, bmap->n_out,
1760                         bset->n_div, bset->n_eq, bset->n_ineq);
1761         if (!bmap)
1762                 goto error;
1763         bmap_domain = isl_basic_map_from_basic_set(bset,
1764                                                 bset->dim, 0);
1765         bmap = add_constraints(bmap, bmap_domain, 0, 0);
1766
1767         bmap = isl_basic_map_simplify(bmap);
1768         return isl_basic_map_finalize(bmap);
1769 error:
1770         isl_basic_map_free(bmap);
1771         isl_basic_set_free(bset);
1772         return NULL;
1773 }
1774
1775 struct isl_basic_map *isl_basic_map_intersect_range(
1776                 struct isl_basic_map *bmap, struct isl_basic_set *bset)
1777 {
1778         struct isl_basic_map *bmap_range;
1779
1780         if (!bmap || !bset)
1781                 goto error;
1782
1783         isl_assert(bset->ctx, bset->dim == bmap->n_out, goto error);
1784         isl_assert(bset->ctx, bset->nparam == bmap->nparam, goto error);
1785
1786         bmap = isl_basic_map_extend(bmap,
1787                         bset->nparam, bmap->n_in, bmap->n_out,
1788                         bset->n_div, bset->n_eq, bset->n_ineq);
1789         if (!bmap)
1790                 goto error;
1791         bmap_range = isl_basic_map_from_basic_set(bset,
1792                                                 0, bset->dim);
1793         bmap = add_constraints(bmap, bmap_range, 0, 0);
1794
1795         bmap = isl_basic_map_simplify(bmap);
1796         return isl_basic_map_finalize(bmap);
1797 error:
1798         isl_basic_map_free(bmap);
1799         isl_basic_set_free(bset);
1800         return NULL;
1801 }
1802
1803 struct isl_basic_map *isl_basic_map_intersect(
1804                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
1805 {
1806         if (!bmap1 || !bmap2)
1807                 goto error;
1808
1809         isl_assert(bmap1->ctx, bmap1->nparam == bmap2->nparam, goto error);
1810         isl_assert(bmap1->ctx, bmap1->n_in == bmap2->n_in, goto error);
1811         isl_assert(bmap1->ctx, bmap1->n_out == bmap2->n_out, goto error);
1812
1813         bmap1 = isl_basic_map_extend(bmap1,
1814                         bmap1->nparam, bmap1->n_in, bmap1->n_out,
1815                         bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
1816         if (!bmap1)
1817                 goto error;
1818         bmap1 = add_constraints(bmap1, bmap2, 0, 0);
1819
1820         bmap1 = isl_basic_map_simplify(bmap1);
1821         return isl_basic_map_finalize(bmap1);
1822 error:
1823         isl_basic_map_free(bmap1);
1824         isl_basic_map_free(bmap2);
1825         return NULL;
1826 }
1827
1828 struct isl_basic_set *isl_basic_set_intersect(
1829                 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
1830 {
1831         return (struct isl_basic_set *)
1832                 isl_basic_map_intersect(
1833                         (struct isl_basic_map *)bset1,
1834                         (struct isl_basic_map *)bset2);
1835 }
1836
1837 struct isl_map *isl_map_intersect(struct isl_map *map1, struct isl_map *map2)
1838 {
1839         unsigned flags = 0;
1840         struct isl_map *result;
1841         int i, j;
1842
1843         if (!map1 || !map2)
1844                 goto error;
1845
1846         if (F_ISSET(map1, ISL_MAP_DISJOINT) &&
1847             F_ISSET(map2, ISL_MAP_DISJOINT))
1848                 FL_SET(flags, ISL_MAP_DISJOINT);
1849
1850         result = isl_map_alloc(map1->ctx, map1->nparam, map1->n_in, map1->n_out,
1851                                 map1->n * map2->n, flags);
1852         if (!result)
1853                 goto error;
1854         for (i = 0; i < map1->n; ++i)
1855                 for (j = 0; j < map2->n; ++j) {
1856                         struct isl_basic_map *part;
1857                         part = isl_basic_map_intersect(
1858                                     isl_basic_map_copy(map1->p[i]),
1859                                     isl_basic_map_copy(map2->p[j]));
1860                         if (isl_basic_map_is_empty(part))
1861                                 isl_basic_map_free(part);
1862                         else
1863                                 result = isl_map_add(result, part);
1864                         if (!result)
1865                                 goto error;
1866                 }
1867         isl_map_free(map1);
1868         isl_map_free(map2);
1869         return result;
1870 error:
1871         isl_map_free(map1);
1872         isl_map_free(map2);
1873         return NULL;
1874 }
1875
1876 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
1877 {
1878         return (struct isl_set *)
1879                 isl_map_intersect((struct isl_map *)set1,
1880                                   (struct isl_map *)set2);
1881 }
1882
1883 struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap)
1884 {
1885         struct isl_basic_set *bset;
1886         unsigned in;
1887
1888         if (!bmap)
1889                 return NULL;
1890         bmap = isl_basic_map_cow(bmap);
1891         if (!bmap)
1892                 return NULL;
1893         in = bmap->n_in;
1894         bset = isl_basic_set_from_basic_map(bmap);
1895         bset = isl_basic_set_swap_vars(bset, in);
1896         return isl_basic_map_from_basic_set(bset, bset->dim-in, in);
1897 }
1898
1899 /* Turn final n dimensions into existentially quantified variables.
1900  */
1901 struct isl_basic_set *isl_basic_set_project_out(
1902                 struct isl_basic_set *bset, unsigned n, unsigned flags)
1903 {
1904         int i;
1905         size_t row_size;
1906         isl_int **new_div;
1907         isl_int *old;
1908
1909         if (!bset)
1910                 return NULL;
1911
1912         isl_assert(bset->ctx, n <= bset->dim, goto error);
1913
1914         if (n == 0)
1915                 return bset;
1916
1917         bset = isl_basic_set_cow(bset);
1918
1919         row_size = 1 + bset->nparam + bset->dim + bset->extra;
1920         old = bset->block2.data;
1921         bset->block2 = isl_blk_extend(bset->ctx, bset->block2,
1922                                         (bset->extra + n) * (1 + row_size));
1923         if (!bset->block2.data)
1924                 goto error;
1925         new_div = isl_alloc_array(ctx, isl_int *, bset->extra + n);
1926         if (!new_div)
1927                 goto error;
1928         for (i = 0; i < n; ++i) {
1929                 new_div[i] = bset->block2.data +
1930                                 (bset->extra + i) * (1 + row_size);
1931                 isl_seq_clr(new_div[i], 1 + row_size);
1932         }
1933         for (i = 0; i < bset->extra; ++i)
1934                 new_div[n + i] = bset->block2.data + (bset->div[i] - old);
1935         free(bset->div);
1936         bset->div = new_div;
1937         bset->n_div += n;
1938         bset->extra += n;
1939         bset->dim -= n;
1940         bset = isl_basic_set_simplify(bset);
1941         return isl_basic_set_finalize(bset);
1942 error:
1943         isl_basic_set_free(bset);
1944         return NULL;
1945 }
1946
1947 struct isl_basic_map *isl_basic_map_apply_range(
1948                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
1949 {
1950         struct isl_basic_set *bset;
1951         unsigned n_in, n_out;
1952
1953         if (!bmap1 || !bmap2)
1954                 goto error;
1955
1956         isl_assert(bmap->ctx, bmap1->n_out == bmap2->n_in, goto error);
1957         isl_assert(bmap->ctx, bmap1->nparam == bmap2->nparam, goto error);
1958
1959         n_in = bmap1->n_in;
1960         n_out = bmap2->n_out;
1961
1962         bmap2 = isl_basic_map_reverse(bmap2);
1963         if (!bmap2)
1964                 goto error;
1965         bmap1 = isl_basic_map_extend(bmap1, bmap1->nparam,
1966                         bmap1->n_in + bmap2->n_in, bmap1->n_out,
1967                         bmap2->extra, bmap2->n_eq, bmap2->n_ineq);
1968         if (!bmap1)
1969                 goto error;
1970         bmap1 = add_constraints(bmap1, bmap2, bmap1->n_in - bmap2->n_in, 0);
1971         bmap1 = isl_basic_map_simplify(bmap1);
1972         bset = isl_basic_set_from_basic_map(bmap1);
1973         bset = isl_basic_set_project_out(bset,
1974                                                 bset->dim - (n_in + n_out), 0);
1975         return isl_basic_map_from_basic_set(bset, n_in, n_out);
1976 error:
1977         isl_basic_map_free(bmap1);
1978         isl_basic_map_free(bmap2);
1979         return NULL;
1980 }
1981
1982 struct isl_basic_set *isl_basic_set_apply(
1983                 struct isl_basic_set *bset, struct isl_basic_map *bmap)
1984 {
1985         if (!bset || !bmap)
1986                 goto error;
1987
1988         isl_assert(bset->ctx, bset->dim == bmap->n_in, goto error);
1989
1990         return (struct isl_basic_set *)
1991                 isl_basic_map_apply_range((struct isl_basic_map *)bset, bmap);
1992 error:
1993         isl_basic_set_free(bset);
1994         isl_basic_map_free(bmap);
1995         return NULL;
1996 }
1997
1998 struct isl_basic_map *isl_basic_map_apply_domain(
1999                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
2000 {
2001         if (!bmap1 || !bmap2)
2002                 goto error;
2003
2004         isl_assert(ctx, bmap1->n_in == bmap2->n_in, goto error);
2005         isl_assert(ctx, bmap1->nparam == bmap2->nparam, goto error);
2006
2007         bmap1 = isl_basic_map_reverse(bmap1);
2008         bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
2009         return isl_basic_map_reverse(bmap1);
2010 error:
2011         isl_basic_map_free(bmap1);
2012         isl_basic_map_free(bmap2);
2013         return NULL;
2014 }
2015
2016 static struct isl_basic_map *var_equal(struct isl_ctx *ctx,
2017                 struct isl_basic_map *bmap, unsigned pos)
2018 {
2019         int i;
2020         i = isl_basic_map_alloc_equality(bmap);
2021         if (i < 0)
2022                 goto error;
2023         isl_seq_clr(bmap->eq[i],
2024                     1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra);
2025         isl_int_set_si(bmap->eq[i][1+bmap->nparam+pos], -1);
2026         isl_int_set_si(bmap->eq[i][1+bmap->nparam+bmap->n_in+pos], 1);
2027         return isl_basic_map_finalize(bmap);
2028 error:
2029         isl_basic_map_free(bmap);
2030         return NULL;
2031 }
2032
2033 static struct isl_basic_map *var_more(struct isl_ctx *ctx,
2034                 struct isl_basic_map *bmap, unsigned pos)
2035 {
2036         int i;
2037         i = isl_basic_map_alloc_inequality(bmap);
2038         if (i < 0)
2039                 goto error;
2040         isl_seq_clr(bmap->ineq[i],
2041                     1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra);
2042         isl_int_set_si(bmap->ineq[i][0], -1);
2043         isl_int_set_si(bmap->ineq[i][1+bmap->nparam+pos], -1);
2044         isl_int_set_si(bmap->ineq[i][1+bmap->nparam+bmap->n_in+pos], 1);
2045         return isl_basic_map_finalize(bmap);
2046 error:
2047         isl_basic_map_free(bmap);
2048         return NULL;
2049 }
2050
2051 static struct isl_basic_map *var_less(struct isl_ctx *ctx,
2052                 struct isl_basic_map *bmap, unsigned pos)
2053 {
2054         int i;
2055         i = isl_basic_map_alloc_inequality(bmap);
2056         if (i < 0)
2057                 goto error;
2058         isl_seq_clr(bmap->ineq[i],
2059                     1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra);
2060         isl_int_set_si(bmap->ineq[i][0], -1);
2061         isl_int_set_si(bmap->ineq[i][1+bmap->nparam+pos], 1);
2062         isl_int_set_si(bmap->ineq[i][1+bmap->nparam+bmap->n_in+pos], -1);
2063         return isl_basic_map_finalize(bmap);
2064 error:
2065         isl_basic_map_free(bmap);
2066         return NULL;
2067 }
2068
2069 struct isl_basic_map *isl_basic_map_equal(struct isl_ctx *ctx,
2070                 unsigned nparam, unsigned in, unsigned out, unsigned n_equal)
2071 {
2072         int i;
2073         struct isl_basic_map *bmap;
2074         bmap = isl_basic_map_alloc(ctx, nparam, in, out, 0, n_equal, 0);
2075         if (!bmap)
2076                 return NULL;
2077         for (i = 0; i < n_equal && bmap; ++i)
2078                 bmap = var_equal(ctx, bmap, i);
2079         return isl_basic_map_finalize(bmap);
2080 }
2081
2082 struct isl_basic_map *isl_basic_map_less_at(struct isl_ctx *ctx,
2083                 unsigned nparam, unsigned in, unsigned out, unsigned pos)
2084 {
2085         int i;
2086         struct isl_basic_map *bmap;
2087         bmap = isl_basic_map_alloc(ctx, nparam, in, out, 0, pos, 1);
2088         if (!bmap)
2089                 return NULL;
2090         for (i = 0; i < pos && bmap; ++i)
2091                 bmap = var_equal(ctx, bmap, i);
2092         if (bmap)
2093                 bmap = var_less(ctx, bmap, pos);
2094         return isl_basic_map_finalize(bmap);
2095 }
2096
2097 struct isl_basic_map *isl_basic_map_more_at(struct isl_ctx *ctx,
2098                 unsigned nparam, unsigned in, unsigned out, unsigned pos)
2099 {
2100         int i;
2101         struct isl_basic_map *bmap;
2102         bmap = isl_basic_map_alloc(ctx, nparam, in, out, 0, pos, 1);
2103         if (!bmap)
2104                 return NULL;
2105         for (i = 0; i < pos && bmap; ++i)
2106                 bmap = var_equal(ctx, bmap, i);
2107         if (bmap)
2108                 bmap = var_more(ctx, bmap, pos);
2109         return isl_basic_map_finalize(bmap);
2110 }
2111
2112 struct isl_basic_map *isl_basic_map_from_basic_set(
2113                 struct isl_basic_set *bset, unsigned n_in, unsigned n_out)
2114 {
2115         struct isl_basic_map *bmap;
2116
2117         bset = isl_basic_set_cow(bset);
2118         if (!bset)
2119                 return NULL;
2120
2121         isl_assert(ctx, bset->dim == n_in + n_out, goto error);
2122         bmap = (struct isl_basic_map *) bset;
2123         bmap->n_in = n_in;
2124         bmap->n_out = n_out;
2125         return isl_basic_map_finalize(bmap);
2126 error:
2127         isl_basic_set_free(bset);
2128         return NULL;
2129 }
2130
2131 struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap)
2132 {
2133         if (!bmap)
2134                 goto error;
2135         if (bmap->n_in == 0)
2136                 return (struct isl_basic_set *)bmap;
2137         bmap = isl_basic_map_cow(bmap);
2138         if (!bmap)
2139                 goto error;
2140         bmap->n_out += bmap->n_in;
2141         bmap->n_in = 0;
2142         bmap = isl_basic_map_finalize(bmap);
2143         return (struct isl_basic_set *)bmap;
2144 error:
2145         return NULL;
2146 }
2147
2148 /* For a div d = floor(f/m), add the constraints
2149  *
2150  *              f - m d >= 0
2151  *              -(f-(n-1)) + m d >= 0
2152  *
2153  * Note that the second constraint is the negation of
2154  *
2155  *              f - m d >= n
2156  */
2157 static int add_div_constraints(struct isl_basic_map *bmap, unsigned div)
2158 {
2159         int i, j;
2160         unsigned div_pos = 1 + bmap->nparam + bmap->n_in + bmap->n_out + div;
2161         unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra;
2162
2163         i = isl_basic_map_alloc_inequality(bmap);
2164         if (i < 0)
2165                 return -1;
2166         isl_seq_cpy(bmap->ineq[i], bmap->div[div]+1, 1+total);
2167         isl_int_neg(bmap->ineq[i][div_pos], bmap->div[div][0]);
2168
2169         j = isl_basic_map_alloc_inequality(bmap);
2170         if (j < 0)
2171                 return -1;
2172         isl_seq_neg(bmap->ineq[j], bmap->ineq[i], 1 + total);
2173         isl_int_add(bmap->ineq[j][0], bmap->ineq[j][0], bmap->ineq[j][div_pos]);
2174         isl_int_sub_ui(bmap->ineq[j][0], bmap->ineq[j][0], 1);
2175         return j;
2176 }
2177
2178 struct isl_basic_set *isl_basic_map_underlying_set(
2179                 struct isl_basic_map *bmap)
2180 {
2181         if (!bmap)
2182                 goto error;
2183         if (bmap->nparam == 0 && bmap->n_in == 0 && bmap->n_div == 0)
2184                 return (struct isl_basic_set *)bmap;
2185         bmap = isl_basic_map_cow(bmap);
2186         if (!bmap)
2187                 goto error;
2188         bmap->n_out += bmap->nparam + bmap->n_in + bmap->n_div;
2189         bmap->nparam = 0;
2190         bmap->n_in = 0;
2191         bmap->extra -= bmap->n_div;
2192         bmap->n_div = 0;
2193         bmap = isl_basic_map_finalize(bmap);
2194         return (struct isl_basic_set *)bmap;
2195 error:
2196         return NULL;
2197 }
2198
2199 struct isl_basic_map *isl_basic_map_overlying_set(
2200         struct isl_basic_set *bset, struct isl_basic_map *like)
2201 {
2202         struct isl_basic_map *bmap;
2203         struct isl_ctx *ctx;
2204         unsigned total;
2205         int i, k;
2206
2207         if (!bset || !like)
2208                 goto error;
2209         ctx = bset->ctx;
2210         isl_assert(ctx, bset->dim ==
2211                         like->nparam + like->n_in + like->n_out + like->n_div,
2212                         goto error);
2213         if (like->nparam == 0 && like->n_in == 0 && like->n_div == 0) {
2214                 isl_basic_map_free(like);
2215                 return (struct isl_basic_map *)bset;
2216         }
2217         bset = isl_basic_set_cow(bset);
2218         if (!bset)
2219                 goto error;
2220         total = bset->dim + bset->extra;
2221         bmap = (struct isl_basic_map *)bset;
2222         bmap->nparam = like->nparam;
2223         bmap->n_in = like->n_in;
2224         bmap->n_out = like->n_out;
2225         bmap->extra += like->n_div;
2226         if (bmap->extra) {
2227                 unsigned ltotal;
2228                 ltotal = total - bmap->extra + like->extra;
2229                 if (ltotal > total)
2230                         ltotal = total;
2231                 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
2232                                         bmap->extra * (1 + 1 + total));
2233                 if (isl_blk_is_error(bmap->block2))
2234                         goto error;
2235                 bmap->div = isl_realloc_array(ctx, bmap->div, isl_int *,
2236                                                 bmap->extra);
2237                 if (!bmap->div)
2238                         goto error;
2239                 bmap = isl_basic_map_extend(bmap, bmap->nparam,
2240                         bmap->n_in, bmap->n_out, 0, 0, 2 * like->n_div);
2241                 for (i = 0; i < like->n_div; ++i) {
2242                         k = isl_basic_map_alloc_div(bmap);
2243                         if (k < 0)
2244                                 goto error;
2245                         isl_seq_cpy(bmap->div[k], like->div[i], 1 + 1 + ltotal);
2246                         isl_seq_clr(bmap->div[k]+1+1+ltotal, total - ltotal);
2247                         if (add_div_constraints(bmap, k) < 0)
2248                                 goto error;
2249                 }
2250         }
2251         isl_basic_map_free(like);
2252         bmap = isl_basic_map_finalize(bmap);
2253         return bmap;
2254 error:
2255         isl_basic_map_free(like);
2256         isl_basic_set_free(bset);
2257         return NULL;
2258 }
2259
2260 struct isl_basic_set *isl_basic_set_from_underlying_set(
2261         struct isl_basic_set *bset, struct isl_basic_set *like)
2262 {
2263         return (struct isl_basic_set *)
2264                 isl_basic_map_overlying_set(bset, (struct isl_basic_map *)like);
2265 }
2266
2267 struct isl_set *isl_set_from_underlying_set(
2268         struct isl_set *set, struct isl_basic_set *like)
2269 {
2270         int i;
2271
2272         if (!set || !like)
2273                 goto error;
2274         isl_assert(set->ctx, set->dim == like->nparam + like->dim + like->n_div,
2275                     goto error);
2276         if (like->nparam == 0 && like->n_div == 0) {
2277                 isl_basic_set_free(like);
2278                 return set;
2279         }
2280         set = isl_set_cow(set);
2281         if (!set)
2282                 goto error;
2283         for (i = 0; i < set->n; ++i) {
2284                 set->p[i] = isl_basic_set_from_underlying_set(set->p[i],
2285                                                       isl_basic_set_copy(like));
2286                 if (!set->p[i])
2287                         goto error;
2288         }
2289         set->nparam = like->nparam;
2290         set->dim = like->dim;
2291         isl_basic_set_free(like);
2292         return set;
2293 error:
2294         isl_basic_set_free(like);
2295         isl_set_free(set);
2296         return NULL;
2297 }
2298
2299 struct isl_set *isl_map_underlying_set(struct isl_map *map)
2300 {
2301         int i;
2302
2303         map = isl_map_align_divs(map);
2304         map = isl_map_cow(map);
2305         if (!map)
2306                 return NULL;
2307
2308         for (i = 0; i < map->n; ++i) {
2309                 map->p[i] = (struct isl_basic_map *)
2310                                 isl_basic_map_underlying_set(map->p[i]);
2311                 if (!map->p[i])
2312                         goto error;
2313         }
2314         if (map->n == 0)
2315                 map->n_out += map->nparam + map->n_in;
2316         else
2317                 map->n_out = map->p[0]->n_out;
2318         map->nparam = 0;
2319         map->n_in = 0;
2320         return (struct isl_set *)map;
2321 error:
2322         isl_map_free(map);
2323         return NULL;
2324 }
2325
2326 struct isl_set *isl_set_to_underlying_set(struct isl_set *set)
2327 {
2328         return (struct isl_set *)isl_map_underlying_set((struct isl_map *)set);
2329 }
2330
2331 struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
2332 {
2333         struct isl_basic_set *domain;
2334         unsigned n_out;
2335         if (!bmap)
2336                 return NULL;
2337         n_out = bmap->n_out;
2338         domain = isl_basic_set_from_basic_map(bmap);
2339         return isl_basic_set_project_out(domain, n_out, 0);
2340 }
2341
2342 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
2343 {
2344         return isl_basic_map_domain(isl_basic_map_reverse(bmap));
2345 }
2346
2347 struct isl_set *isl_map_range(struct isl_map *map)
2348 {
2349         int i;
2350         struct isl_set *set;
2351
2352         if (!map)
2353                 goto error;
2354         map = isl_map_cow(map);
2355         if (!map)
2356                 goto error;
2357
2358         set = (struct isl_set *) map;
2359         set->zero = 0;
2360         for (i = 0; i < map->n; ++i) {
2361                 set->p[i] = isl_basic_map_range(map->p[i]);
2362                 if (!set->p[i])
2363                         goto error;
2364         }
2365         F_CLR(set, ISL_MAP_DISJOINT);
2366         return set;
2367 error:
2368         isl_map_free(map);
2369         return NULL;
2370 }
2371
2372 struct isl_map *isl_map_from_set(struct isl_set *set,
2373                 unsigned n_in, unsigned n_out)
2374 {
2375         int i;
2376         struct isl_map *map = NULL;
2377
2378         if (!set)
2379                 return NULL;
2380         isl_assert(set->ctx, set->dim == n_in + n_out, goto error);
2381         set = isl_set_cow(set);
2382         if (!set)
2383                 return NULL;
2384         map = (struct isl_map *)set;
2385         for (i = 0; i < set->n; ++i) {
2386                 map->p[i] = isl_basic_map_from_basic_set(
2387                                 set->p[i], n_in, n_out);
2388                 if (!map->p[i])
2389                         goto error;
2390         }
2391         map->n_in = n_in;
2392         map->n_out = n_out;
2393         return map;
2394 error:
2395         isl_set_free(set);
2396         return NULL;
2397 }
2398
2399 struct isl_set *isl_set_from_map(struct isl_map *map)
2400 {
2401         int i;
2402         struct isl_set *set = NULL;
2403
2404         if (!map)
2405                 return NULL;
2406         map = isl_map_cow(map);
2407         if (!map)
2408                 return NULL;
2409         map->n_out += map->n_in;
2410         map->n_in = 0;
2411         set = (struct isl_set *)map;
2412         for (i = 0; i < map->n; ++i) {
2413                 set->p[i] = isl_basic_set_from_basic_map(map->p[i]);
2414                 if (!set->p[i])
2415                         goto error;
2416         }
2417         return set;
2418 error:
2419         isl_map_free(map);
2420         return NULL;
2421 }
2422
2423 struct isl_map *isl_map_alloc(struct isl_ctx *ctx,
2424                 unsigned nparam, unsigned in, unsigned out, int n,
2425                 unsigned flags)
2426 {
2427         struct isl_map *map;
2428
2429         map = isl_alloc(ctx, struct isl_map,
2430                         sizeof(struct isl_map) +
2431                         n * sizeof(struct isl_basic_map *));
2432         if (!map)
2433                 return NULL;
2434
2435         map->ctx = ctx;
2436         isl_ctx_ref(ctx);
2437         map->ref = 1;
2438         map->size = n;
2439         map->n = 0;
2440         map->nparam = nparam;
2441         map->n_in = in;
2442         map->n_out = out;
2443         map->flags = flags;
2444         return map;
2445 }
2446
2447 struct isl_basic_map *isl_basic_map_empty(struct isl_ctx *ctx,
2448                 unsigned nparam, unsigned in, unsigned out)
2449 {
2450         struct isl_basic_map *bmap;
2451         bmap = isl_basic_map_alloc(ctx, nparam, in, out, 0, 1, 0);
2452         bmap = isl_basic_map_set_to_empty(bmap);
2453         return bmap;
2454 }
2455
2456 struct isl_basic_set *isl_basic_set_empty(struct isl_ctx *ctx,
2457                 unsigned nparam, unsigned dim)
2458 {
2459         struct isl_basic_set *bset;
2460         bset = isl_basic_set_alloc(ctx, nparam, dim, 0, 1, 0);
2461         bset = isl_basic_set_set_to_empty(bset);
2462         return bset;
2463 }
2464
2465 struct isl_basic_map *isl_basic_map_universe(struct isl_ctx *ctx,
2466                 unsigned nparam, unsigned in, unsigned out)
2467 {
2468         struct isl_basic_map *bmap;
2469         bmap = isl_basic_map_alloc(ctx, nparam, in, out, 0, 0, 0);
2470         return bmap;
2471 }
2472
2473 struct isl_basic_set *isl_basic_set_universe(struct isl_ctx *ctx,
2474                 unsigned nparam, unsigned dim)
2475 {
2476         struct isl_basic_set *bset;
2477         bset = isl_basic_set_alloc(ctx, nparam, dim, 0, 0, 0);
2478         return bset;
2479 }
2480
2481 struct isl_map *isl_map_empty(struct isl_ctx *ctx,
2482                 unsigned nparam, unsigned in, unsigned out)
2483 {
2484         return isl_map_alloc(ctx, nparam, in, out, 0, ISL_MAP_DISJOINT);
2485 }
2486
2487 struct isl_set *isl_set_empty(struct isl_ctx *ctx,
2488                 unsigned nparam, unsigned dim)
2489 {
2490         return isl_set_alloc(ctx, nparam, dim, 0, ISL_MAP_DISJOINT);
2491 }
2492
2493 struct isl_map *isl_map_dup(struct isl_map *map)
2494 {
2495         int i;
2496         struct isl_map *dup;
2497
2498         if (!map)
2499                 return NULL;
2500         dup = isl_map_alloc(map->ctx, map->nparam, map->n_in, map->n_out, map->n,
2501                                 map->flags);
2502         for (i = 0; i < map->n; ++i)
2503                 dup = isl_map_add(dup,
2504                                   isl_basic_map_dup(map->p[i]));
2505         return dup;
2506 }
2507
2508 struct isl_map *isl_map_add(struct isl_map *map, struct isl_basic_map *bmap)
2509 {
2510         if (!bmap || !map)
2511                 goto error;
2512         isl_assert(map->ctx, map->nparam == bmap->nparam, goto error);
2513         isl_assert(map->ctx, map->n_in == bmap->n_in, goto error);
2514         isl_assert(map->ctx, map->n_out == bmap->n_out, goto error);
2515         isl_assert(map->ctx, map->n < map->size, goto error);
2516         map->p[map->n] = bmap;
2517         map->n++;
2518         return map;
2519 error:
2520         if (map)
2521                 isl_map_free(map);
2522         if (bmap)
2523                 isl_basic_map_free(bmap);
2524         return NULL;
2525 }
2526
2527 void isl_map_free(struct isl_map *map)
2528 {
2529         int i;
2530
2531         if (!map)
2532                 return;
2533
2534         if (--map->ref > 0)
2535                 return;
2536
2537         isl_ctx_deref(map->ctx);
2538         for (i = 0; i < map->n; ++i)
2539                 isl_basic_map_free(map->p[i]);
2540         free(map);
2541 }
2542
2543 struct isl_map *isl_map_extend(struct isl_map *base,
2544                 unsigned nparam, unsigned n_in, unsigned n_out)
2545 {
2546         int i;
2547
2548         base = isl_map_cow(base);
2549         if (!base)
2550                 return NULL;
2551
2552         isl_assert(base->ctx, base->nparam <= nparam, goto error);
2553         isl_assert(base->ctx, base->n_in <= n_in, goto error);
2554         isl_assert(base->ctx, base->n_out <= n_out, goto error);
2555         base->nparam = nparam;
2556         base->n_in = n_in;
2557         base->n_out = n_out;
2558         for (i = 0; i < base->n; ++i) {
2559                 base->p[i] = isl_basic_map_extend(base->p[i],
2560                                 nparam, n_in, n_out, 0, 0, 0);
2561                 if (!base->p[i])
2562                         goto error;
2563         }
2564         return base;
2565 error:
2566         isl_map_free(base);
2567         return NULL;
2568 }
2569
2570 struct isl_set *isl_set_extend(struct isl_set *base,
2571                 unsigned nparam, unsigned dim)
2572 {
2573         return (struct isl_set *)isl_map_extend((struct isl_map *)base,
2574                                                         nparam, 0, dim);
2575 }
2576
2577 static struct isl_basic_map *isl_basic_map_fix_var(struct isl_basic_map *bmap,
2578                 unsigned var, int value)
2579 {
2580         int j;
2581
2582         bmap = isl_basic_map_cow(bmap);
2583         bmap = isl_basic_map_extend(bmap,
2584                         bmap->nparam, bmap->n_in, bmap->n_out, 0, 1, 0);
2585         j = isl_basic_map_alloc_equality(bmap);
2586         if (j < 0)
2587                 goto error;
2588         isl_seq_clr(bmap->eq[j],
2589                     1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra);
2590         isl_int_set_si(bmap->eq[j][1 + var], -1);
2591         isl_int_set_si(bmap->eq[j][0], value);
2592         bmap = isl_basic_map_simplify(bmap);
2593         return isl_basic_map_finalize(bmap);
2594 error:
2595         isl_basic_map_free(bmap);
2596         return NULL;
2597 }
2598
2599 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
2600                 unsigned input, int value)
2601 {
2602         if (!bmap)
2603                 return NULL;
2604         isl_assert(bmap->ctx, input < bmap->n_in, goto error);
2605         return isl_basic_map_fix_var(bmap, bmap->nparam + input, value);
2606 error:
2607         isl_basic_map_free(bmap);
2608         return NULL;
2609 }
2610
2611 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
2612                 unsigned dim, int value)
2613 {
2614         if (!bset)
2615                 return NULL;
2616         isl_assert(bset->ctx, dim < bset->dim, goto error);
2617         return (struct isl_basic_set *)
2618                 isl_basic_map_fix_var((struct isl_basic_map *)bset,
2619                                                 bset->nparam + dim, value);
2620 error:
2621         isl_basic_set_free(bset);
2622         return NULL;
2623 }
2624
2625 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
2626                 unsigned input, int value)
2627 {
2628         int i;
2629
2630         map = isl_map_cow(map);
2631         if (!map)
2632                 return NULL;
2633
2634         isl_assert(ctx, input < map->n_in, goto error);
2635         for (i = 0; i < map->n; ++i) {
2636                 map->p[i] = isl_basic_map_fix_input_si(map->p[i], input, value);
2637                 if (!map->p[i])
2638                         goto error;
2639         }
2640         return map;
2641 error:
2642         isl_map_free(map);
2643         return NULL;
2644 }
2645
2646 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
2647 {
2648         int i;
2649
2650         set = isl_set_cow(set);
2651         if (!set)
2652                 return NULL;
2653
2654         isl_assert(set->ctx, dim < set->dim, goto error);
2655         for (i = 0; i < set->n; ++i) {
2656                 set->p[i] = isl_basic_set_fix_dim_si(set->p[i], dim, value);
2657                 if (!set->p[i])
2658                         goto error;
2659         }
2660         return set;
2661 error:
2662         isl_set_free(set);
2663         return NULL;
2664 }
2665
2666 struct isl_basic_set *isl_basic_set_lower_bound_dim(struct isl_basic_set *bset,
2667         unsigned dim, isl_int value)
2668 {
2669         int j;
2670
2671         bset = isl_basic_set_cow(bset);
2672         bset = isl_basic_set_extend(bset, bset->nparam, bset->dim, 0, 0, 1);
2673         j = isl_basic_set_alloc_inequality(bset);
2674         if (j < 0)
2675                 goto error;
2676         isl_seq_clr(bset->ineq[j], 1 + bset->nparam + bset->dim + bset->extra);
2677         isl_int_set_si(bset->ineq[j][1 + bset->nparam + dim], 1);
2678         isl_int_neg(bset->ineq[j][0], value);
2679         bset = isl_basic_set_simplify(bset);
2680         return isl_basic_set_finalize(bset);
2681 error:
2682         isl_basic_set_free(bset);
2683         return NULL;
2684 }
2685
2686 struct isl_set *isl_set_lower_bound_dim(struct isl_set *set, unsigned dim,
2687                                         isl_int value)
2688 {
2689         int i;
2690
2691         set = isl_set_cow(set);
2692         if (!set)
2693                 return NULL;
2694
2695         isl_assert(set->ctx, dim < set->dim, goto error);
2696         for (i = 0; i < set->n; ++i) {
2697                 set->p[i] = isl_basic_set_lower_bound_dim(set->p[i], dim, value);
2698                 if (!set->p[i])
2699                         goto error;
2700         }
2701         return set;
2702 error:
2703         isl_set_free(set);
2704         return NULL;
2705 }
2706
2707 struct isl_map *isl_map_reverse(struct isl_map *map)
2708 {
2709         int i;
2710         unsigned t;
2711
2712         map = isl_map_cow(map);
2713         if (!map)
2714                 return NULL;
2715
2716         t = map->n_in;
2717         map->n_in = map->n_out;
2718         map->n_out = t;
2719         for (i = 0; i < map->n; ++i) {
2720                 map->p[i] = isl_basic_map_reverse(map->p[i]);
2721                 if (!map->p[i])
2722                         goto error;
2723         }
2724         return map;
2725 error:
2726         isl_map_free(map);
2727         return NULL;
2728 }
2729
2730 struct isl_map *isl_basic_map_lexmax(
2731                 struct isl_basic_map *bmap, struct isl_basic_set *dom,
2732                 struct isl_set **empty)
2733 {
2734         return isl_pip_basic_map_lexmax(bmap, dom, empty);
2735 }
2736
2737 struct isl_map *isl_basic_map_lexmin(
2738                 struct isl_basic_map *bmap, struct isl_basic_set *dom,
2739                 struct isl_set **empty)
2740 {
2741         return isl_pip_basic_map_lexmin(bmap, dom, empty);
2742 }
2743
2744 struct isl_set *isl_basic_set_lexmin(struct isl_basic_set *bset)
2745 {
2746         struct isl_basic_map *bmap = NULL;
2747         struct isl_basic_set *dom = NULL;
2748         struct isl_map *min;
2749
2750         if (!bset)
2751                 goto error;
2752         bmap = isl_basic_map_from_basic_set(bset, 0, bset->dim);
2753         if (!bmap)
2754                 goto error;
2755         dom = isl_basic_set_alloc(bmap->ctx, bmap->nparam, 0, 0, 0, 0);
2756         if (!dom)
2757                 goto error;
2758         min = isl_basic_map_lexmin(bmap, dom, NULL);
2759         return isl_map_range(min);
2760 error:
2761         isl_basic_map_free(bmap);
2762         return NULL;
2763 }
2764
2765 struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap)
2766 {
2767         if (!bmap)
2768                 return NULL;
2769         if (bmap->n_div == 0)
2770                 return isl_map_from_basic_map(bmap);
2771         return isl_pip_basic_map_compute_divs(bmap);
2772 }
2773
2774 struct isl_map *isl_map_compute_divs(struct isl_map *map)
2775 {
2776         int i;
2777         struct isl_map *res;
2778
2779         if (!map)
2780                 return NULL;
2781         if (map->n == 0)
2782                 return map;
2783         res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
2784         for (i = 1 ; i < map->n; ++i) {
2785                 struct isl_map *r2;
2786                 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
2787                 if (F_ISSET(map, ISL_MAP_DISJOINT))
2788                         res = isl_map_union_disjoint(res, r2);
2789                 else
2790                         res = isl_map_union(res, r2);
2791         }
2792         isl_map_free(map);
2793
2794         return res;
2795 }
2796
2797 struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset)
2798 {
2799         return (struct isl_set *)
2800                 isl_basic_map_compute_divs((struct isl_basic_map *)bset);
2801 }
2802
2803 struct isl_set *isl_set_compute_divs(struct isl_set *set)
2804 {
2805         return (struct isl_set *)
2806                 isl_map_compute_divs((struct isl_map *)set);
2807 }
2808
2809 struct isl_set *isl_map_domain(struct isl_map *map)
2810 {
2811         int i;
2812         struct isl_set *set;
2813
2814         if (!map)
2815                 goto error;
2816
2817         map = isl_map_cow(map);
2818         if (!map)
2819                 return NULL;
2820
2821         set = (struct isl_set *)map;
2822         set->dim = map->n_in;
2823         set->zero = 0;
2824         for (i = 0; i < map->n; ++i) {
2825                 set->p[i] = isl_basic_map_domain(map->p[i]);
2826                 if (!set->p[i])
2827                         goto error;
2828         }
2829         F_CLR(set, ISL_MAP_DISJOINT);
2830         return set;
2831 error:
2832         isl_map_free(map);
2833         return NULL;
2834 }
2835
2836 struct isl_map *isl_map_union_disjoint(
2837                         struct isl_map *map1, struct isl_map *map2)
2838 {
2839         int i;
2840         unsigned flags = 0;
2841         struct isl_map *map = NULL;
2842
2843         if (!map1 || !map2)
2844                 goto error;
2845
2846         if (map1->n == 0) {
2847                 isl_map_free(map1);
2848                 return map2;
2849         }
2850         if (map2->n == 0) {
2851                 isl_map_free(map2);
2852                 return map1;
2853         }
2854
2855         isl_assert(map1->ctx, map1->nparam == map2->nparam, goto error);
2856         isl_assert(map1->ctx, map1->n_in == map2->n_in, goto error);
2857         isl_assert(map1->ctx, map1->n_out == map2->n_out, goto error);
2858
2859         if (F_ISSET(map1, ISL_MAP_DISJOINT) &&
2860             F_ISSET(map2, ISL_MAP_DISJOINT))
2861                 FL_SET(flags, ISL_MAP_DISJOINT);
2862
2863         map = isl_map_alloc(map1->ctx, map1->nparam, map1->n_in, map1->n_out,
2864                                 map1->n + map2->n, flags);
2865         if (!map)
2866                 goto error;
2867         for (i = 0; i < map1->n; ++i) {
2868                 map = isl_map_add(map,
2869                                   isl_basic_map_copy(map1->p[i]));
2870                 if (!map)
2871                         goto error;
2872         }
2873         for (i = 0; i < map2->n; ++i) {
2874                 map = isl_map_add(map,
2875                                   isl_basic_map_copy(map2->p[i]));
2876                 if (!map)
2877                         goto error;
2878         }
2879         isl_map_free(map1);
2880         isl_map_free(map2);
2881         return map;
2882 error:
2883         isl_map_free(map);
2884         isl_map_free(map1);
2885         isl_map_free(map2);
2886         return NULL;
2887 }
2888
2889 struct isl_map *isl_map_union(struct isl_map *map1, struct isl_map *map2)
2890 {
2891         map1 = isl_map_union_disjoint(map1, map2);
2892         if (!map1)
2893                 return NULL;
2894         if (map1->n > 1)
2895                 F_CLR(map1, ISL_MAP_DISJOINT);
2896         return map1;
2897 }
2898
2899 struct isl_set *isl_set_union_disjoint(
2900                         struct isl_set *set1, struct isl_set *set2)
2901 {
2902         return (struct isl_set *)
2903                 isl_map_union_disjoint(
2904                         (struct isl_map *)set1, (struct isl_map *)set2);
2905 }
2906
2907 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
2908 {
2909         return (struct isl_set *)
2910                 isl_map_union((struct isl_map *)set1, (struct isl_map *)set2);
2911 }
2912
2913 struct isl_map *isl_map_intersect_range(
2914                 struct isl_map *map, struct isl_set *set)
2915 {
2916         unsigned flags = 0;
2917         struct isl_map *result;
2918         int i, j;
2919
2920         if (!map || !set)
2921                 goto error;
2922
2923         if (F_ISSET(map, ISL_MAP_DISJOINT) &&
2924             F_ISSET(set, ISL_MAP_DISJOINT))
2925                 FL_SET(flags, ISL_MAP_DISJOINT);
2926
2927         result = isl_map_alloc(map->ctx, map->nparam, map->n_in, map->n_out,
2928                                 map->n * set->n, flags);
2929         if (!result)
2930                 goto error;
2931         for (i = 0; i < map->n; ++i)
2932                 for (j = 0; j < set->n; ++j) {
2933                         result = isl_map_add(result,
2934                             isl_basic_map_intersect_range(
2935                                 isl_basic_map_copy(map->p[i]),
2936                                 isl_basic_set_copy(set->p[j])));
2937                         if (!result)
2938                                 goto error;
2939                 }
2940         isl_map_free(map);
2941         isl_set_free(set);
2942         return result;
2943 error:
2944         isl_map_free(map);
2945         isl_set_free(set);
2946         return NULL;
2947 }
2948
2949 struct isl_map *isl_map_intersect_domain(
2950                 struct isl_map *map, struct isl_set *set)
2951 {
2952         return isl_map_reverse(
2953                 isl_map_intersect_range(isl_map_reverse(map), set));
2954 }
2955
2956 struct isl_map *isl_map_apply_domain(
2957                 struct isl_map *map1, struct isl_map *map2)
2958 {
2959         if (!map1 || !map2)
2960                 goto error;
2961         map1 = isl_map_reverse(map1);
2962         map1 = isl_map_apply_range(map1, map2);
2963         return isl_map_reverse(map1);
2964 error:
2965         isl_map_free(map1);
2966         isl_map_free(map2);
2967         return NULL;
2968 }
2969
2970 struct isl_map *isl_map_apply_range(
2971                 struct isl_map *map1, struct isl_map *map2)
2972 {
2973         struct isl_map *result;
2974         int i, j;
2975
2976         if (!map1 || !map2)
2977                 goto error;
2978
2979         isl_assert(map1->ctx, map1->nparam == map2->nparam, goto error);
2980         isl_assert(map1->ctx, map1->n_out == map2->n_in, goto error);
2981
2982         result = isl_map_alloc(map1->ctx, map1->nparam, map1->n_in, map2->n_out,
2983                                 map1->n * map2->n, 0);
2984         if (!result)
2985                 goto error;
2986         for (i = 0; i < map1->n; ++i)
2987                 for (j = 0; j < map2->n; ++j) {
2988                         result = isl_map_add(result,
2989                             isl_basic_map_apply_range(
2990                                 isl_basic_map_copy(map1->p[i]),
2991                                 isl_basic_map_copy(map2->p[j])));
2992                         if (!result)
2993                                 goto error;
2994                 }
2995         isl_map_free(map1);
2996         isl_map_free(map2);
2997         if (result && result->n <= 1)
2998                 F_SET(result, ISL_MAP_DISJOINT);
2999         return result;
3000 error:
3001         isl_map_free(map1);
3002         isl_map_free(map2);
3003         return NULL;
3004 }
3005
3006 /*
3007  * returns range - domain
3008  */
3009 struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap)
3010 {
3011         struct isl_basic_set *bset;
3012         unsigned dim;
3013         int i;
3014
3015         if (!bmap)
3016                 goto error;
3017         isl_assert(bmap->ctx, bmap->n_in == bmap->n_out, goto error);
3018         dim = bmap->n_in;
3019         bset = isl_basic_set_from_basic_map(bmap);
3020         bset = isl_basic_set_extend(bset, bset->nparam, 3*dim, 0,
3021                                         dim, 0);
3022         bset = isl_basic_set_swap_vars(bset, 2*dim);
3023         for (i = 0; i < dim; ++i) {
3024                 int j = isl_basic_map_alloc_equality(
3025                                             (struct isl_basic_map *)bset);
3026                 if (j < 0)
3027                         goto error;
3028                 isl_seq_clr(bset->eq[j],
3029                             1 + bset->nparam + bset->dim + bset->extra);
3030                 isl_int_set_si(bset->eq[j][1+bset->nparam+i], 1);
3031                 isl_int_set_si(bset->eq[j][1+bset->nparam+dim+i], 1);
3032                 isl_int_set_si(bset->eq[j][1+bset->nparam+2*dim+i], -1);
3033         }
3034         return isl_basic_set_project_out(bset, 2*dim, 0);
3035 error:
3036         isl_basic_map_free(bmap);
3037         return NULL;
3038 }
3039
3040 /*
3041  * returns range - domain
3042  */
3043 struct isl_set *isl_map_deltas(struct isl_map *map)
3044 {
3045         int i;
3046         struct isl_set *result;
3047
3048         if (!map)
3049                 return NULL;
3050
3051         isl_assert(map->ctx, map->n_in == map->n_out, goto error);
3052         result = isl_set_alloc(map->ctx, map->nparam, map->n_in, map->n, map->flags);
3053         if (!result)
3054                 goto error;
3055         for (i = 0; i < map->n; ++i)
3056                 result = isl_set_add(result,
3057                           isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
3058         isl_map_free(map);
3059         return result;
3060 error:
3061         isl_map_free(map);
3062         return NULL;
3063 }
3064
3065 /* If the only constraints a div d=floor(f/m)
3066  * appears in are its two defining constraints
3067  *
3068  *      f - m d >=0
3069  *      -(f - (m - 1)) + m d >= 0
3070  *
3071  * then it can safely be removed.
3072  */
3073 static int div_is_redundant(struct isl_basic_map *bmap, int div)
3074 {
3075         int i;
3076         unsigned pos = 1 + bmap->nparam + bmap->n_in + bmap->n_out + div;
3077
3078         for (i = 0; i < bmap->n_eq; ++i)
3079                 if (!isl_int_is_zero(bmap->eq[i][pos]))
3080                         return 0;
3081
3082         for (i = 0; i < bmap->n_ineq; ++i) {
3083                 if (isl_int_is_zero(bmap->ineq[i][pos]))
3084                         continue;
3085                 if (isl_int_eq(bmap->ineq[i][pos], bmap->div[div][0])) {
3086                         int neg;
3087                         isl_int_sub(bmap->div[div][1],
3088                                         bmap->div[div][1], bmap->div[div][0]);
3089                         isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1);
3090                         neg = isl_seq_is_neg(bmap->ineq[i], bmap->div[div]+1, pos);
3091                         isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
3092                         isl_int_add(bmap->div[div][1],
3093                                         bmap->div[div][1], bmap->div[div][0]);
3094                         if (!neg)
3095                                 return 0;
3096                         if (isl_seq_first_non_zero(bmap->ineq[i]+pos+1,
3097                                                     bmap->n_div-div-1) != -1)
3098                                 return 0;
3099                 } else if (isl_int_abs_eq(bmap->ineq[i][pos], bmap->div[div][0])) {
3100                         if (!isl_seq_eq(bmap->ineq[i], bmap->div[div]+1, pos))
3101                                 return 0;
3102                         if (isl_seq_first_non_zero(bmap->ineq[i]+pos+1,
3103                                                     bmap->n_div-div-1) != -1)
3104                                 return 0;
3105                 } else
3106                         return 0;
3107         }
3108
3109         for (i = 0; i < bmap->n_div; ++i)
3110                 if (!isl_int_is_zero(bmap->div[i][1+pos]))
3111                         return 0;
3112
3113         return 1;
3114 }
3115
3116 /*
3117  * Remove divs that don't occur in any of the constraints or other divs.
3118  * These can arise when dropping some of the variables in a quast
3119  * returned by piplib.
3120  */
3121 static struct isl_basic_map *remove_redundant_divs(struct isl_basic_map *bmap)
3122 {
3123         int i;
3124
3125         if (!bmap)
3126                 return NULL;
3127
3128         for (i = bmap->n_div-1; i >= 0; --i) {
3129                 if (!div_is_redundant(bmap, i))
3130                         continue;
3131                 bmap = isl_basic_map_drop_div(bmap, i);
3132         }
3133         return bmap;
3134 }
3135
3136 struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap)
3137 {
3138         bmap = remove_redundant_divs(bmap);
3139         if (!bmap)
3140                 return NULL;
3141         F_SET(bmap, ISL_BASIC_SET_FINAL);
3142         return bmap;
3143 }
3144
3145 struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset)
3146 {
3147         return (struct isl_basic_set *)
3148                 isl_basic_map_finalize((struct isl_basic_map *)bset);
3149 }
3150
3151 struct isl_set *isl_set_finalize(struct isl_set *set)
3152 {
3153         int i;
3154
3155         if (!set)
3156                 return NULL;
3157         for (i = 0; i < set->n; ++i) {
3158                 set->p[i] = isl_basic_set_finalize(set->p[i]);
3159                 if (!set->p[i])
3160                         goto error;
3161         }
3162         return set;
3163 error:
3164         isl_set_free(set);
3165         return NULL;
3166 }
3167
3168 struct isl_map *isl_map_finalize(struct isl_map *map)
3169 {
3170         int i;
3171
3172         if (!map)
3173                 return NULL;
3174         for (i = 0; i < map->n; ++i) {
3175                 map->p[i] = isl_basic_map_finalize(map->p[i]);
3176                 if (!map->p[i])
3177                         goto error;
3178         }
3179         return map;
3180 error:
3181         isl_map_free(map);
3182         return NULL;
3183 }
3184
3185 struct isl_basic_map *isl_basic_map_identity(struct isl_ctx *ctx,
3186                 unsigned nparam, unsigned dim)
3187 {
3188         struct isl_basic_map *bmap;
3189         int i;
3190
3191         bmap = isl_basic_map_alloc(ctx, nparam, dim, dim, 0, dim, 0);
3192         if (!bmap)
3193                 goto error;
3194
3195         for (i = 0; i < dim; ++i) {
3196                 int j = isl_basic_map_alloc_equality(bmap);
3197                 if (j < 0)
3198                         goto error;
3199                 isl_seq_clr(bmap->eq[j],
3200                     1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->extra);
3201                 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
3202                 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
3203         }
3204         return isl_basic_map_finalize(bmap);
3205 error:
3206         isl_basic_map_free(bmap);
3207         return NULL;
3208 }
3209
3210 struct isl_map *isl_map_identity(struct isl_ctx *ctx,
3211                 unsigned nparam, unsigned dim)
3212 {
3213         struct isl_map *map = isl_map_alloc(ctx, nparam, dim, dim, 1,
3214                                                 ISL_MAP_DISJOINT);
3215         if (!map)
3216                 goto error;
3217         map = isl_map_add(map,
3218                 isl_basic_map_identity(ctx, nparam, dim));
3219         return map;
3220 error:
3221         isl_map_free(map);
3222         return NULL;
3223 }
3224
3225 int isl_set_is_equal(struct isl_set *set1, struct isl_set *set2)
3226 {
3227         return isl_map_is_equal((struct isl_map *)set1, (struct isl_map *)set2);
3228 }
3229
3230 int isl_set_is_subset(struct isl_set *set1, struct isl_set *set2)
3231 {
3232         return isl_map_is_subset(
3233                         (struct isl_map *)set1, (struct isl_map *)set2);
3234 }
3235
3236 int isl_basic_map_is_subset(
3237                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3238 {
3239         int is_subset;
3240         struct isl_map *map1;
3241         struct isl_map *map2;
3242
3243         if (!bmap1 || !bmap2)
3244                 return -1;
3245
3246         map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
3247         map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
3248
3249         is_subset = isl_map_is_subset(map1, map2);
3250
3251         isl_map_free(map1);
3252         isl_map_free(map2);
3253
3254         return is_subset;
3255 }
3256
3257 int isl_basic_map_is_equal(
3258                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3259 {
3260         int is_subset;
3261
3262         if (!bmap1 || !bmap2)
3263                 return -1;
3264         is_subset = isl_basic_map_is_subset(bmap1, bmap2);
3265         if (is_subset != 1)
3266                 return is_subset;
3267         is_subset = isl_basic_map_is_subset(bmap2, bmap1);
3268         return is_subset;
3269 }
3270
3271 int isl_basic_set_is_equal(
3272                 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3273 {
3274         return isl_basic_map_is_equal(
3275                 (struct isl_basic_map *)bset1, (struct isl_basic_map *)bset2);
3276 }
3277
3278 int isl_map_is_empty(struct isl_map *map)
3279 {
3280         int i;
3281         int is_empty;
3282
3283         if (!map)
3284                 return -1;
3285         for (i = 0; i < map->n; ++i) {
3286                 is_empty = isl_basic_map_is_empty(map->p[i]);
3287                 if (is_empty < 0)
3288                         return -1;
3289                 if (!is_empty)
3290                         return 0;
3291         }
3292         return 1;
3293 }
3294
3295 int isl_set_is_empty(struct isl_set *set)
3296 {
3297         return isl_map_is_empty((struct isl_map *)set);
3298 }
3299
3300 int isl_map_is_subset(struct isl_map *map1, struct isl_map *map2)
3301 {
3302         int i;
3303         int is_subset = 0;
3304         struct isl_map *diff;
3305
3306         if (!map1 || !map2)
3307                 return -1;
3308
3309         if (isl_map_is_empty(map1))
3310                 return 1;
3311
3312         if (isl_map_is_empty(map2))
3313                 return 0;
3314
3315         diff = isl_map_subtract(isl_map_copy(map1), isl_map_copy(map2));
3316         if (!diff)
3317                 return -1;
3318
3319         is_subset = isl_map_is_empty(diff);
3320         isl_map_free(diff);
3321
3322         return is_subset;
3323 }
3324
3325 int isl_map_is_equal(struct isl_map *map1, struct isl_map *map2)
3326 {
3327         int is_subset;
3328
3329         if (!map1 || !map2)
3330                 return -1;
3331         is_subset = isl_map_is_subset(map1, map2);
3332         if (is_subset != 1)
3333                 return is_subset;
3334         is_subset = isl_map_is_subset(map2, map1);
3335         return is_subset;
3336 }
3337
3338 int isl_basic_map_is_strict_subset(
3339                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3340 {
3341         int is_subset;
3342
3343         if (!bmap1 || !bmap2)
3344                 return -1;
3345         is_subset = isl_basic_map_is_subset(bmap1, bmap2);
3346         if (is_subset != 1)
3347                 return is_subset;
3348         is_subset = isl_basic_map_is_subset(bmap2, bmap1);
3349         if (is_subset == -1)
3350                 return is_subset;
3351         return !is_subset;
3352 }
3353
3354 static int basic_map_contains(struct isl_basic_map *bmap, struct isl_vec *vec)
3355 {
3356         int i;
3357         unsigned total;
3358         isl_int s;
3359
3360         total = 1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
3361         if (total != vec->size)
3362                 return -1;
3363
3364         isl_int_init(s);
3365
3366         for (i = 0; i < bmap->n_eq; ++i) {
3367                 isl_seq_inner_product(vec->block.data, bmap->eq[i], total, &s);
3368                 if (!isl_int_is_zero(s)) {
3369                         isl_int_clear(s);
3370                         return 0;
3371                 }
3372         }
3373
3374         for (i = 0; i < bmap->n_ineq; ++i) {
3375                 isl_seq_inner_product(vec->block.data, bmap->ineq[i], total, &s);
3376                 if (isl_int_is_neg(s)) {
3377                         isl_int_clear(s);
3378                         return 0;
3379                 }
3380         }
3381
3382         isl_int_clear(s);
3383
3384         return 1;
3385 }
3386
3387 int isl_basic_map_is_universe(struct isl_basic_map *bmap)
3388 {
3389         if (!bmap)
3390                 return -1;
3391         return bmap->n_eq == 0 && bmap->n_ineq == 0;
3392 }
3393
3394 int isl_basic_map_is_empty(struct isl_basic_map *bmap)
3395 {
3396         struct isl_basic_set *bset = NULL;
3397         struct isl_vec *sample = NULL;
3398         int empty;
3399         unsigned total;
3400
3401         if (!bmap)
3402                 return -1;
3403
3404         if (F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
3405                 return 1;
3406
3407         if (F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
3408                 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
3409                 copy = isl_basic_map_convex_hull(copy);
3410                 empty = F_ISSET(copy, ISL_BASIC_MAP_EMPTY);
3411                 isl_basic_map_free(copy);
3412                 return empty;
3413         }
3414
3415         total = 1 + bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
3416         if (bmap->sample && bmap->sample->size == total) {
3417                 int contains = basic_map_contains(bmap, bmap->sample);
3418                 if (contains < 0)
3419                         return -1;
3420                 if (contains)
3421                         return 0;
3422         }
3423         bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
3424         if (!bset)
3425                 return -1;
3426         sample = isl_basic_set_sample(bset);
3427         if (!sample)
3428                 return -1;
3429         empty = sample->size == 0;
3430         if (bmap->sample)
3431                 isl_vec_free(bmap->ctx, bmap->sample);
3432         bmap->sample = sample;
3433
3434         return empty;
3435 }
3436
3437 struct isl_map *isl_basic_map_union(
3438         struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3439 {
3440         struct isl_map *map;
3441         if (!bmap1 || !bmap2)
3442                 return NULL;
3443
3444         isl_assert(bmap1->ctx, bmap1->nparam == bmap2->nparam, goto error);
3445         isl_assert(bmap1->ctx, bmap1->n_in == bmap2->n_in, goto error);
3446         isl_assert(bmap1->ctx, bmap1->n_out == bmap2->n_out, goto error);
3447
3448         map = isl_map_alloc(bmap1->ctx, bmap1->nparam,
3449                                 bmap1->n_in, bmap1->n_out, 2, 0);
3450         if (!map)
3451                 goto error;
3452         map = isl_map_add(map, bmap1);
3453         map = isl_map_add(map, bmap2);
3454         return map;
3455 error:
3456         isl_basic_map_free(bmap1);
3457         isl_basic_map_free(bmap2);
3458         return NULL;
3459 }
3460
3461 struct isl_set *isl_basic_set_union(
3462                 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3463 {
3464         return (struct isl_set *)isl_basic_map_union(
3465                                             (struct isl_basic_map *)bset1,
3466                                             (struct isl_basic_map *)bset2);
3467 }
3468
3469 /* Order divs such that any div only depends on previous divs */
3470 static struct isl_basic_map *order_divs(struct isl_basic_map *bmap)
3471 {
3472         int i;
3473         unsigned off = bmap->nparam + bmap->n_in + bmap->n_out;
3474
3475         for (i = 0; i < bmap->n_div; ++i) {
3476                 int pos;
3477                 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
3478                                                             bmap->n_div-i);
3479                 if (pos == -1)
3480                         continue;
3481                 swap_div(bmap, i, pos);
3482                 --i;
3483         }
3484         return bmap;
3485 }
3486
3487 static int find_div(struct isl_basic_map *dst,
3488                         struct isl_basic_map *src, unsigned div)
3489 {
3490         int i;
3491
3492         unsigned total = src->nparam + src->n_in + src->n_out + src->n_div;
3493
3494         for (i = 0; i < dst->n_div; ++i)
3495                 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total) &&
3496                     isl_seq_first_non_zero(dst->div[i]+1+1+total,
3497                                                 dst->n_div - src->n_div) == -1)
3498                         return i;
3499         return -1;
3500 }
3501
3502 struct isl_basic_map *isl_basic_map_align_divs(
3503                 struct isl_basic_map *dst, struct isl_basic_map *src)
3504 {
3505         int i;
3506         unsigned total = src->nparam + src->n_in + src->n_out + src->n_div;
3507
3508         if (src->n_div == 0)
3509                 return dst;
3510
3511         src = order_divs(src);
3512         dst = isl_basic_map_extend(dst, dst->nparam, dst->n_in,
3513                         dst->n_out, src->n_div, 0, 2 * src->n_div);
3514         if (!dst)
3515                 return NULL;
3516         for (i = 0; i < src->n_div; ++i) {
3517                 int j = find_div(dst, src, i);
3518                 if (j < 0) {
3519                         j = isl_basic_map_alloc_div(dst);
3520                         if (j < 0)
3521                                 goto error;
3522                         isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
3523                         isl_seq_clr(dst->div[j]+1+1+total,
3524                                                     dst->extra - src->n_div);
3525                         if (add_div_constraints(dst, j) < 0)
3526                                 goto error;
3527                 }
3528                 if (j != i)
3529                         swap_div(dst, i, j);
3530         }
3531         return dst;
3532 error:
3533         isl_basic_map_free(dst);
3534         return NULL;
3535 }
3536
3537 struct isl_map *isl_map_align_divs(struct isl_map *map)
3538 {
3539         int i;
3540
3541         map = isl_map_compute_divs(map);
3542         map = isl_map_cow(map);
3543         if (!map)
3544                 return NULL;
3545
3546         for (i = 1; i < map->n; ++i)
3547                 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
3548         for (i = 1; i < map->n; ++i)
3549                 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
3550
3551         return map;
3552 }
3553
3554 static struct isl_map *add_cut_constraint(struct isl_map *dst,
3555                 struct isl_basic_map *src, isl_int *c,
3556                 unsigned len, int oppose)
3557 {
3558         struct isl_basic_map *copy = NULL;
3559         int is_empty;
3560         int k;
3561         unsigned total;
3562
3563         copy = isl_basic_map_copy(src);
3564         copy = isl_basic_map_cow(copy);
3565         if (!copy)
3566                 goto error;
3567         copy = isl_basic_map_extend(copy,
3568                 copy->nparam, copy->n_in, copy->n_out, 0, 0, 1);
3569         k = isl_basic_map_alloc_inequality(copy);
3570         if (k < 0)
3571                 goto error;
3572         if (oppose)
3573                 isl_seq_neg(copy->ineq[k], c, len);
3574         else
3575                 isl_seq_cpy(copy->ineq[k], c, len);
3576         total = 1 + copy->nparam + copy->n_in + copy->n_out + copy->extra;
3577         isl_seq_clr(copy->ineq[k]+len, total - len);
3578         isl_inequality_negate(copy, k);
3579         copy = isl_basic_map_simplify(copy);
3580         copy = isl_basic_map_finalize(copy);
3581         is_empty = isl_basic_map_is_empty(copy);
3582         if (is_empty < 0)
3583                 goto error;
3584         if (!is_empty)
3585                 dst = isl_map_add(dst, copy);
3586         else
3587                 isl_basic_map_free(copy);
3588         return dst;
3589 error:
3590         isl_basic_map_free(copy);
3591         isl_map_free(dst);
3592         return NULL;
3593 }
3594
3595 static struct isl_map *subtract(struct isl_map *map, struct isl_basic_map *bmap)
3596 {
3597         int i, j, k;
3598         unsigned flags = 0;
3599         struct isl_map *rest = NULL;
3600         unsigned max;
3601         unsigned total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
3602
3603         assert(bmap);
3604
3605         if (!map)
3606                 goto error;
3607
3608         if (F_ISSET(map, ISL_MAP_DISJOINT))
3609                 FL_SET(flags, ISL_MAP_DISJOINT);
3610
3611         max = map->n * (2 * bmap->n_eq + bmap->n_ineq);
3612         rest = isl_map_alloc(map->ctx, map->nparam, map->n_in, map->n_out,
3613                                 max, flags);
3614         if (!rest)
3615                 goto error;
3616
3617         for (i = 0; i < map->n; ++i) {
3618                 map->p[i] = isl_basic_map_align_divs(map->p[i], bmap);
3619                 if (!map->p[i])
3620                         goto error;
3621         }
3622
3623         for (j = 0; j < map->n; ++j)
3624                 map->p[j] = isl_basic_map_cow(map->p[j]);
3625
3626         for (i = 0; i < bmap->n_eq; ++i) {
3627                 for (j = 0; j < map->n; ++j) {
3628                         rest = add_cut_constraint(rest,
3629                                 map->p[j], bmap->eq[i], 1+total, 0);
3630                         if (!rest)
3631                                 goto error;
3632
3633                         rest = add_cut_constraint(rest,
3634                                 map->p[j], bmap->eq[i], 1+total, 1);
3635                         if (!rest)
3636                                 goto error;
3637
3638                         map->p[j] = isl_basic_map_extend(map->p[j],
3639                                 map->p[j]->nparam, map->p[j]->n_in,
3640                                 map->p[j]->n_out, 0, 1, 0);
3641                         if (!map->p[j])
3642                                 goto error;
3643                         k = isl_basic_map_alloc_equality(map->p[j]);
3644                         if (k < 0)
3645                                 goto error;
3646                         isl_seq_cpy(map->p[j]->eq[k], bmap->eq[i], 1+total);
3647                         isl_seq_clr(map->p[j]->eq[k]+1+total,
3648                                         map->p[j]->extra - bmap->n_div);
3649                 }
3650         }
3651
3652         for (i = 0; i < bmap->n_ineq; ++i) {
3653                 for (j = 0; j < map->n; ++j) {
3654                         rest = add_cut_constraint(rest,
3655                                 map->p[j], bmap->ineq[i], 1+total, 0);
3656                         if (!rest)
3657                                 goto error;
3658
3659                         map->p[j] = isl_basic_map_extend(map->p[j],
3660                                 map->p[j]->nparam, map->p[j]->n_in,
3661                                 map->p[j]->n_out, 0, 0, 1);
3662                         if (!map->p[j])
3663                                 goto error;
3664                         k = isl_basic_map_alloc_inequality(map->p[j]);
3665                         if (k < 0)
3666                                 goto error;
3667                         isl_seq_cpy(map->p[j]->ineq[k], bmap->ineq[i], 1+total);
3668                         isl_seq_clr(map->p[j]->ineq[k]+1+total,
3669                                         map->p[j]->extra - bmap->n_div);
3670                 }
3671         }
3672
3673         isl_map_free(map);
3674         return rest;
3675 error:
3676         isl_map_free(map);
3677         isl_map_free(rest);
3678         return NULL;
3679 }
3680
3681 struct isl_map *isl_map_subtract(struct isl_map *map1, struct isl_map *map2)
3682 {
3683         int i;
3684         if (!map1 || !map2)
3685                 goto error;
3686
3687         isl_assert(map1->ctx, map1->nparam == map2->nparam, goto error);
3688         isl_assert(map1->ctx, map1->n_in == map2->n_in, goto error);
3689         isl_assert(map1->ctx, map1->n_out == map2->n_out, goto error);
3690
3691         if (isl_map_is_empty(map2)) {
3692                 isl_map_free(map2);
3693                 return map1;
3694         }
3695
3696         map1 = isl_map_compute_divs(map1);
3697         map2 = isl_map_compute_divs(map2);
3698         if (!map1 || !map2)
3699                 goto error;
3700
3701         for (i = 0; map1 && i < map2->n; ++i)
3702                 map1 = subtract(map1, map2->p[i]);
3703
3704         isl_map_free(map2);
3705         return map1;
3706 error:
3707         isl_map_free(map1);
3708         isl_map_free(map2);
3709         return NULL;
3710 }
3711
3712 struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
3713 {
3714         return (struct isl_set *)
3715                 isl_map_subtract(
3716                         (struct isl_map *)set1, (struct isl_map *)set2);
3717 }
3718
3719 struct isl_set *isl_set_apply(struct isl_set *set, struct isl_map *map)
3720 {
3721         if (!set || !map)
3722                 goto error;
3723         isl_assert(set->ctx, set->dim == map->n_in, goto error);
3724         map = isl_map_intersect_domain(map, set);
3725         set = isl_map_range(map);
3726         return set;
3727 error:
3728         isl_set_free(set);
3729         isl_map_free(map);
3730         return NULL;
3731 }
3732
3733 /* There is no need to cow as removing empty parts doesn't change
3734  * the meaning of the set.
3735  */
3736 struct isl_map *isl_map_remove_empty_parts(struct isl_map *map)
3737 {
3738         int i;
3739
3740         if (!map)
3741                 return NULL;
3742
3743         for (i = map->n-1; i >= 0; --i) {
3744                 if (!F_ISSET(map->p[i], ISL_BASIC_MAP_EMPTY))
3745                         continue;
3746                 isl_basic_map_free(map->p[i]);
3747                 if (i != map->n-1)
3748                         map->p[i] = map->p[map->n-1];
3749                 map->n--;
3750         }
3751
3752         return map;
3753 }
3754
3755 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
3756 {
3757         return (struct isl_set *)
3758                 isl_map_remove_empty_parts((struct isl_map *)set);
3759 }
3760
3761 struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set)
3762 {
3763         struct isl_basic_set *bset;
3764         if (!set || set->n == 0)
3765                 return NULL;
3766         bset = set->p[set->n-1];
3767         isl_assert(set->ctx, F_ISSET(bset, ISL_BASIC_SET_FINAL), return NULL);
3768         return isl_basic_set_copy(bset);
3769 }
3770
3771 struct isl_set *isl_set_drop_basic_set(struct isl_set *set,
3772                                                 struct isl_basic_set *bset)
3773 {
3774         int i;
3775
3776         if (!set || !bset)
3777                 goto error;
3778         for (i = set->n-1; i >= 0; --i) {
3779                 if (set->p[i] != bset)
3780                         continue;
3781                 set = isl_set_cow(set);
3782                 if (!set)
3783                         goto error;
3784                 isl_basic_set_free(set->p[i]);
3785                 if (i != set->n-1)
3786                         set->p[i] = set->p[set->n-1];
3787                 set->n--;
3788                 return set;
3789         }
3790         isl_basic_set_free(bset);
3791         return set;
3792 error:
3793         isl_set_free(set);
3794         isl_basic_set_free(bset);
3795         return NULL;
3796 }
3797
3798 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
3799  * for any common value of the parameters and dimensions preceding dim
3800  * in both basic sets, the values of dimension pos in bset1 are
3801  * smaller or larger then those in bset2.
3802  *
3803  * Returns
3804  *       1 if bset1 follows bset2
3805  *      -1 if bset1 precedes bset2
3806  *       0 if bset1 and bset2 are incomparable
3807  *      -2 if some error occurred.
3808  */
3809 int isl_basic_set_compare_at(struct isl_basic_set *bset1,
3810         struct isl_basic_set *bset2, int pos)
3811 {
3812         struct isl_basic_map *bmap1 = NULL;
3813         struct isl_basic_map *bmap2 = NULL;
3814         struct isl_ctx *ctx;
3815         struct isl_vec *obj;
3816         unsigned total;
3817         isl_int num, den;
3818         enum isl_lp_result res;
3819         int cmp;
3820
3821         if (!bset1 || !bset2)
3822                 return -2;
3823
3824         bmap1 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset1),
3825                                                 pos, bset1->dim - pos);
3826         bmap2 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset2),
3827                                                 pos, bset2->dim - pos);
3828         if (!bmap1 || !bmap2)
3829                 goto error;
3830         bmap1 = isl_basic_map_extend(bmap1, bmap1->nparam,
3831                         bmap1->n_in, bmap1->n_out + bmap2->n_out,
3832                         bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3833         if (!bmap1)
3834                 goto error;
3835         total = bmap1->nparam + bmap1->n_in + bmap1->n_out + bmap1->n_div;
3836         ctx = bmap1->ctx;
3837         obj = isl_vec_alloc(ctx, total);
3838         isl_seq_clr(obj->block.data, total);
3839         isl_int_set_si(obj->block.data[bmap1->nparam+bmap1->n_in], 1);
3840         isl_int_set_si(obj->block.data[bmap1->nparam+bmap1->n_in+
3841                                         bmap1->n_out-bmap2->n_out], -1);
3842         if (!obj)
3843                 goto error;
3844         bmap1 = add_constraints(bmap1, bmap2, 0, bmap1->n_out - bmap2->n_out);
3845         isl_int_init(num);
3846         isl_int_init(den);
3847         res = isl_solve_lp(bmap1, 0, obj->block.data, ctx->one, &num, &den);
3848         if (res == isl_lp_empty)
3849                 cmp = 0;
3850         else if (res == isl_lp_ok && isl_int_is_pos(num))
3851                 cmp = 1;
3852         else if ((res == isl_lp_ok && isl_int_is_neg(num)) ||
3853                   res == isl_lp_unbounded)
3854                 cmp = -1;
3855         else
3856                 cmp = -2;
3857         isl_int_clear(num);
3858         isl_int_clear(den);
3859         isl_basic_map_free(bmap1);
3860         isl_vec_free(ctx, obj);
3861         return cmp;
3862 error:
3863         isl_basic_map_free(bmap1);
3864         isl_basic_map_free(bmap2);
3865         return -2;
3866 }
3867
3868 static int isl_basic_map_fast_has_fixed_var(struct isl_basic_map *bmap,
3869         unsigned pos, isl_int *val)
3870 {
3871         int i;
3872         int d;
3873         unsigned total;
3874
3875         if (!bmap)
3876                 return -1;
3877         total = bmap->nparam + bmap->n_in + bmap->n_out + bmap->n_div;
3878         for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
3879                 for (; d+1 > pos; --d)
3880                         if (!isl_int_is_zero(bmap->eq[i][1+d]))
3881                                 break;
3882                 if (d != pos)
3883                         continue;
3884                 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
3885                         return 0;
3886                 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
3887                         return 0;
3888                 if (!isl_int_is_one(bmap->eq[i][1+d]))
3889                         return 0;
3890                 if (val)
3891                         isl_int_neg(*val, bmap->eq[i][0]);
3892                 return 1;
3893         }
3894         return 0;
3895 }
3896
3897 static int isl_map_fast_has_fixed_var(struct isl_map *map,
3898         unsigned pos, isl_int *val)
3899 {
3900         int i;
3901         isl_int v;
3902         isl_int tmp;
3903         int fixed;
3904
3905         if (!map)
3906                 return -1;
3907         if (map->n == 0)
3908                 return 0;
3909         if (map->n == 1)
3910                 return isl_basic_map_fast_has_fixed_var(map->p[0], pos, val); 
3911         isl_int_init(v);
3912         isl_int_init(tmp);
3913         fixed = isl_basic_map_fast_has_fixed_var(map->p[0], pos, &v); 
3914         for (i = 1; fixed == 1 && i < map->n; ++i) {
3915                 fixed = isl_basic_map_fast_has_fixed_var(map->p[i], pos, &tmp); 
3916                 if (fixed == 1 && isl_int_ne(tmp, v))
3917                         fixed = 0;
3918         }
3919         if (val)
3920                 isl_int_set(*val, v);
3921         isl_int_clear(tmp);
3922         isl_int_clear(v);
3923         return fixed;
3924 }
3925
3926 static int isl_set_fast_has_fixed_var(struct isl_set *set, unsigned pos,
3927         isl_int *val)
3928 {
3929         return isl_map_fast_has_fixed_var((struct isl_map *)set, pos, val);
3930 }
3931
3932 /* Check if dimension dim has fixed value and if so and if val is not NULL,
3933  * then return this fixed value in *val.
3934  */
3935 int isl_set_fast_dim_is_fixed(struct isl_set *set, unsigned dim, isl_int *val)
3936 {
3937         return isl_set_fast_has_fixed_var(set, set->nparam + dim, val);
3938 }
3939
3940 /* Check if input variable in has fixed value and if so and if val is not NULL,
3941  * then return this fixed value in *val.
3942  */
3943 int isl_map_fast_input_is_fixed(struct isl_map *map, unsigned in, isl_int *val)
3944 {
3945         return isl_map_fast_has_fixed_var(map, map->nparam + in, val);
3946 }
3947
3948 /* Check if dimension dim has an (obvious) fixed lower bound and if so
3949  * and if val is not NULL, then return this lower bound in *val.
3950  */
3951 int isl_basic_set_fast_dim_has_fixed_lower_bound(struct isl_basic_set *bset,
3952         unsigned dim, isl_int *val)
3953 {
3954         int i, i_eq = -1, i_ineq = -1;
3955         isl_int *c;
3956         unsigned total;
3957
3958         if (!bset)
3959                 return -1;
3960         total = bset->nparam + bset->dim + bset->n_div;
3961         for (i = 0; i < bset->n_eq; ++i) {
3962                 if (isl_int_is_zero(bset->eq[i][1+bset->nparam+dim]))
3963                         continue;
3964                 if (i_eq != -1)
3965                         return 0;
3966                 i_eq = i;
3967         }
3968         for (i = 0; i < bset->n_ineq; ++i) {
3969                 if (!isl_int_is_pos(bset->ineq[i][1+bset->nparam+dim]))
3970                         continue;
3971                 if (i_eq != -1 || i_ineq != -1)
3972                         return 0;
3973                 i_ineq = i;
3974         }
3975         if (i_eq == -1 && i_ineq == -1)
3976                 return 0;
3977         c = i_eq != -1 ? bset->eq[i_eq] : bset->ineq[i_ineq];
3978         /* The coefficient should always be one due to normalization. */
3979         if (!isl_int_is_one(c[1+bset->nparam+dim]))
3980                 return 0;
3981         if (isl_seq_first_non_zero(c+1, bset->nparam+dim) != -1)
3982                 return 0;
3983         if (isl_seq_first_non_zero(c+1+bset->nparam+dim+1,
3984                                         total - bset->nparam - dim - 1) != -1)
3985                 return 0;
3986         if (val)
3987                 isl_int_neg(*val, c[0]);
3988         return 1;
3989 }
3990
3991 int isl_set_fast_dim_has_fixed_lower_bound(struct isl_set *set,
3992         unsigned dim, isl_int *val)
3993 {
3994         int i;
3995         isl_int v;
3996         isl_int tmp;
3997         int fixed;
3998
3999         if (!set)
4000                 return -1;
4001         if (set->n == 0)
4002                 return 0;
4003         if (set->n == 1)
4004                 return isl_basic_set_fast_dim_has_fixed_lower_bound(set->p[0],
4005                                                                 dim, val);
4006         isl_int_init(v);
4007         isl_int_init(tmp);
4008         fixed = isl_basic_set_fast_dim_has_fixed_lower_bound(set->p[0],
4009                                                                 dim, &v);
4010         for (i = 1; fixed == 1 && i < set->n; ++i) {
4011                 fixed = isl_basic_set_fast_dim_has_fixed_lower_bound(set->p[i],
4012                                                                 dim, &tmp);
4013                 if (fixed == 1 && isl_int_ne(tmp, v))
4014                         fixed = 0;
4015         }
4016         if (val)
4017                 isl_int_set(*val, v);
4018         isl_int_clear(tmp);
4019         isl_int_clear(v);
4020         return fixed;
4021 }
4022
4023 /* Remove all information from bset that is redundant in the context
4024  * of context.  In particular, equalities that are linear combinations
4025  * of those in context are remobed.  Then the inequalities that are
4026  * redundant in the context of the equalities and inequalities of
4027  * context are removed.
4028  */
4029 static struct isl_basic_set *uset_gist(struct isl_basic_set *bset,
4030         struct isl_basic_set *context)
4031 {
4032         int i;
4033         isl_int opt;
4034         struct isl_basic_set *combined;
4035         struct isl_ctx *ctx;
4036         enum isl_lp_result res = isl_lp_ok;
4037
4038         if (!bset || !context)
4039                 goto error;
4040
4041         if (context->n_eq > 0) {
4042                 struct isl_mat *T;
4043                 struct isl_mat *T2;
4044                 struct isl_ctx *ctx = context->ctx;
4045                 context = isl_basic_set_remove_equalities(context, &T, &T2);
4046                 if (!context)
4047                         goto error;
4048                 bset = isl_basic_set_preimage(ctx, bset, T);
4049                 bset = uset_gist(bset, context);
4050                 bset = isl_basic_set_preimage(ctx, bset, T2);
4051                 return bset;
4052         }
4053         combined = isl_basic_set_extend(isl_basic_set_copy(bset),
4054                         0, bset->dim, 0, context->n_eq, context->n_ineq);
4055         context = set_add_constraints(combined, context, 0);
4056         if (!context)
4057                 goto error;
4058         ctx = context->ctx;
4059         isl_int_init(opt);
4060         for (i = bset->n_ineq-1; i >= 0; --i) {
4061                 set_swap_inequality(context, i, context->n_ineq-1);
4062                 context->n_ineq--;
4063                 res = isl_solve_lp((struct isl_basic_map *)context, 0,
4064                         context->ineq[context->n_ineq]+1, ctx->one, &opt, NULL);
4065                 context->n_ineq++;
4066                 set_swap_inequality(context, i, context->n_ineq-1);
4067                 if (res == isl_lp_unbounded)
4068                         continue;
4069                 if (res == isl_lp_error)
4070                         break;
4071                 if (res == isl_lp_empty) {
4072                         bset = isl_basic_set_set_to_empty(bset);
4073                         break;
4074                 }
4075                 isl_int_add(opt, opt, context->ineq[i][0]);
4076                 if (!isl_int_is_neg(opt)) {
4077                         isl_basic_set_drop_inequality(context, i);
4078                         isl_basic_set_drop_inequality(bset, i);
4079                 }
4080         }
4081         isl_int_clear(opt);
4082         if (res == isl_lp_error)
4083                 goto error;
4084         isl_basic_set_free(context);
4085         return bset;
4086 error:
4087         isl_basic_set_free(context);
4088         isl_basic_set_free(bset);
4089         return NULL;
4090 }
4091
4092 struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
4093         struct isl_basic_map *context)
4094 {
4095         struct isl_basic_set *bset;
4096
4097         if (!bmap || !context)
4098                 goto error;
4099
4100         context = isl_basic_map_align_divs(context, bmap);
4101         bmap = isl_basic_map_align_divs(bmap, context);
4102
4103         bset = uset_gist(isl_basic_map_underlying_set(isl_basic_map_copy(bmap)),
4104                          isl_basic_map_underlying_set(context));
4105
4106         return isl_basic_map_overlying_set(bset, bmap);
4107 error:
4108         isl_basic_map_free(bmap);
4109         isl_basic_map_free(context);
4110         return NULL;
4111 }
4112
4113 struct isl_map *isl_map_gist(struct isl_map *map, struct isl_basic_map *context)
4114 {
4115         int i;
4116
4117         map = isl_map_cow(map);
4118         if (!map || !context)
4119                 return NULL;
4120         isl_assert(map->ctx, map->nparam == context->nparam, goto error);
4121         isl_assert(map->ctx, map->n_in == context->n_in, goto error);
4122         isl_assert(map->ctx, map->n_out == context->n_out, goto error);
4123         for (i = 0; i < map->n; ++i)
4124                 context = isl_basic_map_align_divs(context, map->p[i]);
4125         for (i = 0; i < map->n; ++i) {
4126                 map->p[i] = isl_basic_map_gist(map->p[i],
4127                                                 isl_basic_map_copy(context));
4128                 if (!map->p[i])
4129                         goto error;
4130         }
4131         isl_basic_map_free(context);
4132         return map;
4133 error:
4134         isl_map_free(map);
4135         isl_basic_map_free(context);
4136         return NULL;
4137 }
4138
4139 struct isl_set *isl_set_gist(struct isl_set *set, struct isl_basic_set *context)
4140 {
4141         return (struct isl_set *)isl_map_gist((struct isl_map *)set,
4142                                         (struct isl_basic_map *)context);
4143 }