isl_stream_read_map: fix handling of divs in tuples
[platform/upstream/isl.git] / isl_map_subtract.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 license
5  *
6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8  */
9
10 #include <isl_map_private.h>
11 #include <isl/seq.h>
12 #include <isl/set.h>
13 #include <isl/map.h>
14 #include "isl_tab.h"
15 #include <isl_point_private.h>
16
17 static void expand_constraint(isl_vec *v, unsigned dim,
18         isl_int *c, int *div_map, unsigned n_div)
19 {
20         int i;
21
22         isl_seq_cpy(v->el, c, 1 + dim);
23         isl_seq_clr(v->el + 1 + dim, v->size - (1 + dim));
24
25         for (i = 0; i < n_div; ++i)
26                 isl_int_set(v->el[1 + dim + div_map[i]], c[1 + dim + i]);
27 }
28
29 /* Add all constraints of bmap to tab.  The equalities of bmap
30  * are added as a pair of inequalities.
31  */
32 static int tab_add_constraints(struct isl_tab *tab,
33         __isl_keep isl_basic_map *bmap, int *div_map)
34 {
35         int i;
36         unsigned dim;
37         unsigned tab_total;
38         unsigned bmap_total;
39         isl_vec *v;
40
41         if (!tab || !bmap)
42                 return -1;
43
44         tab_total = isl_basic_map_total_dim(tab->bmap);
45         bmap_total = isl_basic_map_total_dim(bmap);
46         dim = isl_dim_total(tab->bmap->dim);
47
48         if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
49                 return -1;
50
51         v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
52         if (!v)
53                 return -1;
54
55         for (i = 0; i < bmap->n_eq; ++i) {
56                 expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
57                 if (isl_tab_add_ineq(tab, v->el) < 0)
58                         goto error;
59                 isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
60                 expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
61                 if (isl_tab_add_ineq(tab, v->el) < 0)
62                         goto error;
63                 isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
64                 if (tab->empty)
65                         break;
66         }
67
68         for (i = 0; i < bmap->n_ineq; ++i) {
69                 expand_constraint(v, dim, bmap->ineq[i], div_map, bmap->n_div);
70                 if (isl_tab_add_ineq(tab, v->el) < 0)
71                         goto error;
72                 if (tab->empty)
73                         break;
74         }
75
76         isl_vec_free(v);
77         return 0;
78 error:
79         isl_vec_free(v);
80         return -1;
81 }
82
83 /* Add a specific constraint of bmap (or its opposite) to tab.
84  * The position of the constraint is specified by "c", where
85  * the equalities of bmap are counted twice, once for the inequality
86  * that is equal to the equality, and once for its negation.
87  */
88 static int tab_add_constraint(struct isl_tab *tab,
89         __isl_keep isl_basic_map *bmap, int *div_map, int c, int oppose)
90 {
91         unsigned dim;
92         unsigned tab_total;
93         unsigned bmap_total;
94         isl_vec *v;
95         int r;
96
97         if (!tab || !bmap)
98                 return -1;
99
100         tab_total = isl_basic_map_total_dim(tab->bmap);
101         bmap_total = isl_basic_map_total_dim(bmap);
102         dim = isl_dim_total(tab->bmap->dim);
103
104         v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
105         if (!v)
106                 return -1;
107
108         if (c < 2 * bmap->n_eq) {
109                 if ((c % 2) != oppose)
110                         isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
111                                         1 + bmap_total);
112                 if (oppose)
113                         isl_int_sub_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
114                 expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap->n_div);
115                 r = isl_tab_add_ineq(tab, v->el);
116                 if (oppose)
117                         isl_int_add_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
118                 if ((c % 2) != oppose)
119                         isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
120                                         1 + bmap_total);
121         } else {
122                 c -= 2 * bmap->n_eq;
123                 if (oppose) {
124                         isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
125                                         1 + bmap_total);
126                         isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
127                 }
128                 expand_constraint(v, dim, bmap->ineq[c], div_map, bmap->n_div);
129                 r = isl_tab_add_ineq(tab, v->el);
130                 if (oppose) {
131                         isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
132                         isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
133                                         1 + bmap_total);
134                 }
135         }
136
137         isl_vec_free(v);
138         return r;
139 }
140
141 static int tab_add_divs(struct isl_tab *tab, __isl_keep isl_basic_map *bmap,
142         int **div_map)
143 {
144         int i, j;
145         struct isl_vec *vec;
146         unsigned total;
147         unsigned dim;
148
149         if (!bmap)
150                 return -1;
151         if (!bmap->n_div)
152                 return 0;
153
154         if (!*div_map)
155                 *div_map = isl_alloc_array(bmap->ctx, int, bmap->n_div);
156         if (!*div_map)
157                 return -1;
158
159         total = isl_basic_map_total_dim(tab->bmap);
160         dim = total - tab->bmap->n_div;
161         vec = isl_vec_alloc(bmap->ctx, 2 + total + bmap->n_div);
162         if (!vec)
163                 return -1;
164
165         for (i = 0; i < bmap->n_div; ++i) {
166                 isl_seq_cpy(vec->el, bmap->div[i], 2 + dim);
167                 isl_seq_clr(vec->el + 2 + dim, tab->bmap->n_div);
168                 for (j = 0; j < i; ++j)
169                         isl_int_set(vec->el[2 + dim + (*div_map)[j]],
170                                         bmap->div[i][2 + dim + j]);
171                 for (j = 0; j < tab->bmap->n_div; ++j)
172                         if (isl_seq_eq(tab->bmap->div[j],
173                                         vec->el, 2 + dim + tab->bmap->n_div))
174                                 break;
175                 (*div_map)[i] = j;
176                 if (j == tab->bmap->n_div) {
177                         vec->size = 2 + dim + tab->bmap->n_div;
178                         if (isl_tab_add_div(tab, vec, NULL, NULL) < 0)
179                                 goto error;
180                 }
181         }
182
183         isl_vec_free(vec);
184
185         return 0;
186 error:
187         isl_vec_free(vec);
188
189         return -1;
190 }
191
192 /* Freeze all constraints of tableau tab.
193  */
194 static int tab_freeze_constraints(struct isl_tab *tab)
195 {
196         int i;
197
198         for (i = 0; i < tab->n_con; ++i)
199                 if (isl_tab_freeze_constraint(tab, i) < 0)
200                         return -1;
201
202         return 0;
203 }
204
205 /* Check for redundant constraints starting at offset.
206  * Put the indices of the redundant constraints in index
207  * and return the number of redundant constraints.
208  */
209 static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
210         int offset, int **index)
211 {
212         int i, n;
213         int n_test = tab->n_con - offset;
214
215         if (isl_tab_detect_redundant(tab) < 0)
216                 return -1;
217
218         if (!*index)
219                 *index = isl_alloc_array(ctx, int, n_test);
220         if (!*index)
221                 return -1;
222
223         for (n = 0, i = 0; i < n_test; ++i) {
224                 int r;
225                 r = isl_tab_is_redundant(tab, offset + i);
226                 if (r < 0)
227                         return -1;
228                 if (r)
229                         continue;
230                 (*index)[n++] = i;
231         }
232
233         return n;
234 }
235
236 /* basic_map_collect_diff calls add on each of the pieces of
237  * the set difference between bmap and map until the add method
238  * return a negative value.
239  */
240 struct isl_diff_collector {
241         int (*add)(struct isl_diff_collector *dc,
242                     __isl_take isl_basic_map *bmap);
243 };
244
245 /* Compute the set difference between bmap and map and call
246  * dc->add on each of the piece until this function returns
247  * a negative value.
248  * Return 0 on success and -1 on error.  dc->add returning
249  * a negative value is treated as an error, but the calling
250  * function can interpret the results based on the state of dc.
251  *
252  * Assumes that map has known divs.
253  *
254  * The difference is computed by a backtracking algorithm.
255  * Each level corresponds to a basic map in "map".
256  * When a node in entered for the first time, we check
257  * if the corresonding basic map intersects the current piece
258  * of "bmap".  If not, we move to the next level.
259  * Otherwise, we split the current piece into as many
260  * pieces as there are non-redundant constraints of the current
261  * basic map in the intersection.  Each of these pieces is
262  * handled by a child of the current node.
263  * In particular, if there are n non-redundant constraints,
264  * then for each 0 <= i < n, a piece is cut off by adding
265  * constraints 0 <= j < i and adding the opposite of constraint i.
266  * If there are no non-redundant constraints, meaning that the current
267  * piece is a subset of the current basic map, then we simply backtrack.
268  *
269  * In the leaves, we check if the remaining piece has any integer points
270  * and if so, pass it along to dc->add.  As a special case, if nothing
271  * has been removed when we end up in a leaf, we simply pass along
272  * the original basic map.
273  */
274 static int basic_map_collect_diff(__isl_take isl_basic_map *bmap,
275         __isl_take isl_map *map, struct isl_diff_collector *dc)
276 {
277         int i;
278         int modified;
279         int level;
280         int init;
281         int empty;
282         isl_ctx *ctx;
283         struct isl_tab *tab = NULL;
284         struct isl_tab_undo **snap = NULL;
285         int *k = NULL;
286         int *n = NULL;
287         int **index = NULL;
288         int **div_map = NULL;
289
290         empty = isl_basic_map_is_empty(bmap);
291         if (empty) {
292                 isl_basic_map_free(bmap);
293                 isl_map_free(map);
294                 return empty < 0 ? -1 : 0;
295         }
296
297         bmap = isl_basic_map_cow(bmap);
298         map = isl_map_cow(map);
299
300         if (!bmap || !map)
301                 goto error;
302
303         ctx = map->ctx;
304         snap = isl_alloc_array(map->ctx, struct isl_tab_undo *, map->n);
305         k = isl_alloc_array(map->ctx, int, map->n);
306         n = isl_alloc_array(map->ctx, int, map->n);
307         index = isl_calloc_array(map->ctx, int *, map->n);
308         div_map = isl_calloc_array(map->ctx, int *, map->n);
309         if (!snap || !k || !n || !index || !div_map)
310                 goto error;
311
312         bmap = isl_basic_map_order_divs(bmap);
313         map = isl_map_order_divs(map);
314
315         tab = isl_tab_from_basic_map(bmap);
316         if (isl_tab_track_bmap(tab, isl_basic_map_copy(bmap)) < 0)
317                 goto error;
318
319         modified = 0;
320         level = 0;
321         init = 1;
322
323         while (level >= 0) {
324                 if (level >= map->n) {
325                         int empty;
326                         struct isl_basic_map *bm;
327                         if (!modified) {
328                                 if (dc->add(dc, isl_basic_map_copy(bmap)) < 0)
329                                         goto error;
330                                 break;
331                         }
332                         bm = isl_basic_map_copy(tab->bmap);
333                         bm = isl_basic_map_cow(bm);
334                         bm = isl_basic_map_update_from_tab(bm, tab);
335                         bm = isl_basic_map_simplify(bm);
336                         bm = isl_basic_map_finalize(bm);
337                         empty = isl_basic_map_is_empty(bm);
338                         if (empty)
339                                 isl_basic_map_free(bm);
340                         else if (dc->add(dc, bm) < 0)
341                                 goto error;
342                         if (empty < 0)
343                                 goto error;
344                         level--;
345                         init = 0;
346                         continue;
347                 }
348                 if (init) {
349                         int offset;
350                         struct isl_tab_undo *snap2;
351                         snap2 = isl_tab_snap(tab);
352                         if (tab_add_divs(tab, map->p[level],
353                                          &div_map[level]) < 0)
354                                 goto error;
355                         offset = tab->n_con;
356                         snap[level] = isl_tab_snap(tab);
357                         if (tab_freeze_constraints(tab) < 0)
358                                 goto error;
359                         if (tab_add_constraints(tab, map->p[level],
360                                                 div_map[level]) < 0)
361                                 goto error;
362                         k[level] = 0;
363                         n[level] = 0;
364                         if (tab->empty) {
365                                 if (isl_tab_rollback(tab, snap2) < 0)
366                                         goto error;
367                                 level++;
368                                 continue;
369                         }
370                         modified = 1;
371                         n[level] = n_non_redundant(ctx, tab, offset,
372                                                     &index[level]);
373                         if (n[level] < 0)
374                                 goto error;
375                         if (n[level] == 0) {
376                                 level--;
377                                 init = 0;
378                                 continue;
379                         }
380                         if (isl_tab_rollback(tab, snap[level]) < 0)
381                                 goto error;
382                         if (tab_add_constraint(tab, map->p[level],
383                                         div_map[level], index[level][0], 1) < 0)
384                                 goto error;
385                         level++;
386                         continue;
387                 } else {
388                         if (k[level] + 1 >= n[level]) {
389                                 level--;
390                                 continue;
391                         }
392                         if (isl_tab_rollback(tab, snap[level]) < 0)
393                                 goto error;
394                         if (tab_add_constraint(tab, map->p[level],
395                                                 div_map[level],
396                                                 index[level][k[level]], 0) < 0)
397                                 goto error;
398                         snap[level] = isl_tab_snap(tab);
399                         k[level]++;
400                         if (tab_add_constraint(tab, map->p[level],
401                                                 div_map[level],
402                                                 index[level][k[level]], 1) < 0)
403                                 goto error;
404                         level++;
405                         init = 1;
406                         continue;
407                 }
408         }
409
410         isl_tab_free(tab);
411         free(snap);
412         free(n);
413         free(k);
414         for (i = 0; index && i < map->n; ++i)
415                 free(index[i]);
416         free(index);
417         for (i = 0; div_map && i < map->n; ++i)
418                 free(div_map[i]);
419         free(div_map);
420
421         isl_basic_map_free(bmap);
422         isl_map_free(map);
423
424         return 0;
425 error:
426         isl_tab_free(tab);
427         free(snap);
428         free(n);
429         free(k);
430         for (i = 0; index && i < map->n; ++i)
431                 free(index[i]);
432         free(index);
433         for (i = 0; div_map && i < map->n; ++i)
434                 free(div_map[i]);
435         free(div_map);
436         isl_basic_map_free(bmap);
437         isl_map_free(map);
438         return -1;
439 }
440
441 /* A diff collector that actually collects all parts of the
442  * set difference in the field diff.
443  */
444 struct isl_subtract_diff_collector {
445         struct isl_diff_collector dc;
446         struct isl_map *diff;
447 };
448
449 /* isl_subtract_diff_collector callback.
450  */
451 static int basic_map_subtract_add(struct isl_diff_collector *dc,
452                             __isl_take isl_basic_map *bmap)
453 {
454         struct isl_subtract_diff_collector *sdc;
455         sdc = (struct isl_subtract_diff_collector *)dc;
456
457         sdc->diff = isl_map_union_disjoint(sdc->diff,
458                         isl_map_from_basic_map(bmap));
459
460         return sdc->diff ? 0 : -1;
461 }
462
463 /* Return the set difference between bmap and map.
464  */
465 static __isl_give isl_map *basic_map_subtract(__isl_take isl_basic_map *bmap,
466         __isl_take isl_map *map)
467 {
468         struct isl_subtract_diff_collector sdc;
469         sdc.dc.add = &basic_map_subtract_add;
470         sdc.diff = isl_map_empty_like_basic_map(bmap);
471         if (basic_map_collect_diff(bmap, map, &sdc.dc) < 0) {
472                 isl_map_free(sdc.diff);
473                 sdc.diff = NULL;
474         }
475         return sdc.diff;
476 }
477
478 /* Return the set difference between map1 and map2.
479  * (U_i A_i) \ (U_j B_j) is computed as U_i (A_i \ (U_j B_j))
480  */
481 struct isl_map *isl_map_subtract(struct isl_map *map1, struct isl_map *map2)
482 {
483         int i;
484         struct isl_map *diff;
485
486         if (!map1 || !map2)
487                 goto error;
488
489         isl_assert(map1->ctx, isl_dim_equal(map1->dim, map2->dim), goto error);
490
491         if (isl_map_is_empty(map2)) {
492                 isl_map_free(map2);
493                 return map1;
494         }
495
496         map1 = isl_map_compute_divs(map1);
497         map2 = isl_map_compute_divs(map2);
498         if (!map1 || !map2)
499                 goto error;
500
501         map1 = isl_map_remove_empty_parts(map1);
502         map2 = isl_map_remove_empty_parts(map2);
503
504         diff = isl_map_empty_like(map1);
505         for (i = 0; i < map1->n; ++i) {
506                 struct isl_map *d;
507                 d = basic_map_subtract(isl_basic_map_copy(map1->p[i]),
508                                        isl_map_copy(map2));
509                 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT))
510                         diff = isl_map_union_disjoint(diff, d);
511                 else
512                         diff = isl_map_union(diff, d);
513         }
514
515         isl_map_free(map1);
516         isl_map_free(map2);
517
518         return diff;
519 error:
520         isl_map_free(map1);
521         isl_map_free(map2);
522         return NULL;
523 }
524
525 struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
526 {
527         return (struct isl_set *)
528                 isl_map_subtract(
529                         (struct isl_map *)set1, (struct isl_map *)set2);
530 }
531
532 /* A diff collector that aborts as soon as its add function is called,
533  * setting empty to 0.
534  */
535 struct isl_is_empty_diff_collector {
536         struct isl_diff_collector dc;
537         int empty;
538 };
539
540 /* isl_is_empty_diff_collector callback.
541  */
542 static int basic_map_is_empty_add(struct isl_diff_collector *dc,
543                             __isl_take isl_basic_map *bmap)
544 {
545         struct isl_is_empty_diff_collector *edc;
546         edc = (struct isl_is_empty_diff_collector *)dc;
547
548         edc->empty = 0;
549
550         isl_basic_map_free(bmap);
551         return -1;
552 }
553
554 /* Check if bmap \ map is empty by computing this set difference
555  * and breaking off as soon as the difference is known to be non-empty.
556  */
557 static int basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
558         __isl_keep isl_map *map)
559 {
560         int r;
561         struct isl_is_empty_diff_collector edc;
562
563         r = isl_basic_map_fast_is_empty(bmap);
564         if (r)
565                 return r;
566
567         edc.dc.add = &basic_map_is_empty_add;
568         edc.empty = 1;
569         r = basic_map_collect_diff(isl_basic_map_copy(bmap),
570                                    isl_map_copy(map), &edc.dc);
571         if (!edc.empty)
572                 return 0;
573
574         return r < 0 ? -1 : 1;
575 }
576
577 /* Check if map1 \ map2 is empty by checking if the set difference is empty
578  * for each of the basic maps in map1.
579  */
580 static int map_diff_is_empty(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
581 {
582         int i;
583         int is_empty = 1;
584
585         if (!map1 || !map2)
586                 return -1;
587         
588         for (i = 0; i < map1->n; ++i) {
589                 is_empty = basic_map_diff_is_empty(map1->p[i], map2);
590                 if (is_empty < 0 || !is_empty)
591                          break;
592         }
593
594         return is_empty;
595 }
596
597 /* Return 1 if "bmap" contains a single element.
598  */
599 int isl_basic_map_fast_is_singleton(__isl_keep isl_basic_map *bmap)
600 {
601         if (!bmap)
602                 return -1;
603         if (bmap->n_div)
604                 return 0;
605         if (bmap->n_ineq)
606                 return 0;
607         return bmap->n_eq == isl_basic_map_total_dim(bmap);
608 }
609
610 /* Return 1 if "map" contains a single element.
611  */
612 int isl_map_fast_is_singleton(__isl_keep isl_map *map)
613 {
614         if (!map)
615                 return -1;
616         if (map->n != 1)
617                 return 0;
618
619         return isl_basic_map_fast_is_singleton(map->p[0]);
620 }
621
622 /* Given a singleton basic map, extract the single element
623  * as an isl_point.
624  */
625 static __isl_give isl_point *singleton_extract_point(
626         __isl_keep isl_basic_map *bmap)
627 {
628         int i, j;
629         unsigned dim;
630         struct isl_vec *point;
631         isl_int m;
632
633         if (!bmap)
634                 return NULL;
635
636         dim = isl_basic_map_total_dim(bmap);
637         isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
638         point = isl_vec_alloc(bmap->ctx, 1 + dim);
639         if (!point)
640                 return NULL;
641
642         isl_int_init(m);
643
644         isl_int_set_si(point->el[0], 1);
645         for (j = 0; j < bmap->n_eq; ++j) {
646                 int s;
647                 int i = dim - 1 - j;
648                 isl_assert(bmap->ctx,
649                     isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
650                     goto error);
651                 isl_assert(bmap->ctx,
652                     isl_int_is_one(bmap->eq[j][1 + i]) ||
653                     isl_int_is_negone(bmap->eq[j][1 + i]),
654                     goto error);
655                 isl_assert(bmap->ctx,
656                     isl_seq_first_non_zero(bmap->eq[j]+1+i+1, dim-i-1) == -1,
657                     goto error);
658
659                 isl_int_gcd(m, point->el[0], bmap->eq[j][1 + i]);
660                 isl_int_divexact(m, bmap->eq[j][1 + i], m);
661                 isl_int_abs(m, m);
662                 isl_seq_scale(point->el, point->el, m, 1 + i);
663                 isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
664                 isl_int_neg(m, m);
665                 isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
666         }
667
668         isl_int_clear(m);
669         return isl_point_alloc(isl_basic_map_get_dim(bmap), point);
670 error:
671         isl_int_clear(m);
672         isl_vec_free(point);
673         return NULL;
674 }
675
676 /* Return 1 is the singleton map "map1" is a subset of "map2",
677  * i.e., if the single element of "map1" is also an element of "map2".
678  * Assumes "map2" has known divs.
679  */
680 static int map_is_singleton_subset(__isl_keep isl_map *map1,
681         __isl_keep isl_map *map2)
682 {
683         int i;
684         int is_subset = 0;
685         struct isl_point *point;
686
687         if (!map1 || !map2)
688                 return -1;
689         if (map1->n != 1)
690                 return -1;
691
692         point = singleton_extract_point(map1->p[0]);
693         if (!point)
694                 return -1;
695
696         for (i = 0; i < map2->n; ++i) {
697                 is_subset = isl_basic_map_contains_point(map2->p[i], point);
698                 if (is_subset)
699                         break;
700         }
701
702         isl_point_free(point);
703         return is_subset;
704 }
705
706 int isl_map_is_subset(struct isl_map *map1, struct isl_map *map2)
707 {
708         int is_subset = 0;
709         struct isl_map *diff;
710
711         if (!map1 || !map2)
712                 return -1;
713
714         if (isl_map_is_empty(map1))
715                 return 1;
716
717         if (isl_map_is_empty(map2))
718                 return 0;
719
720         if (isl_map_fast_is_universe(map2))
721                 return 1;
722
723         map2 = isl_map_compute_divs(isl_map_copy(map2));
724         if (isl_map_fast_is_singleton(map1)) {
725                 is_subset = map_is_singleton_subset(map1, map2);
726                 isl_map_free(map2);
727                 return is_subset;
728         }
729         is_subset = map_diff_is_empty(map1, map2);
730         isl_map_free(map2);
731
732         return is_subset;
733 }
734
735 int isl_set_is_subset(struct isl_set *set1, struct isl_set *set2)
736 {
737         return isl_map_is_subset(
738                         (struct isl_map *)set1, (struct isl_map *)set2);
739 }
740
741 __isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map)
742 {
743         int i;
744         struct isl_subtract_diff_collector sdc;
745         sdc.dc.add = &basic_map_subtract_add;
746
747         if (!map)
748                 return NULL;
749         if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
750                 return map;
751         if (map->n <= 1)
752                 return map;
753
754         map = isl_map_compute_divs(map);
755         map = isl_map_remove_empty_parts(map);
756
757         if (!map || map->n <= 1)
758                 return map;
759
760         sdc.diff = isl_map_from_basic_map(isl_basic_map_copy(map->p[0]));
761
762         for (i = 1; i < map->n; ++i) {
763                 struct isl_basic_map *bmap = isl_basic_map_copy(map->p[i]);
764                 struct isl_map *copy = isl_map_copy(sdc.diff);
765                 if (basic_map_collect_diff(bmap, copy, &sdc.dc) < 0) {
766                         isl_map_free(sdc.diff);
767                         sdc.diff = NULL;
768                         break;
769                 }
770         }
771
772         isl_map_free(map);
773
774         return sdc.diff;
775 }
776
777 __isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
778 {
779         return (struct isl_set *)isl_map_make_disjoint((struct isl_map *)set);
780 }
781
782 __isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
783 {
784         isl_set *universe;
785
786         if (!set)
787                 return NULL;
788
789         universe = isl_set_universe(isl_set_get_dim(set));
790
791         return isl_set_subtract(universe, set);
792 }