add isl_set_gist_params
[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_space_dim(tab->bmap->dim, isl_dim_all);
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_space_dim(tab->bmap->dim, isl_dim_all);
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 static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
482         __isl_take isl_map *map2)
483 {
484         int i;
485         struct isl_map *diff;
486
487         if (!map1 || !map2)
488                 goto error;
489
490         isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
491
492         if (isl_map_is_empty(map2)) {
493                 isl_map_free(map2);
494                 return map1;
495         }
496
497         map1 = isl_map_compute_divs(map1);
498         map2 = isl_map_compute_divs(map2);
499         if (!map1 || !map2)
500                 goto error;
501
502         map1 = isl_map_remove_empty_parts(map1);
503         map2 = isl_map_remove_empty_parts(map2);
504
505         diff = isl_map_empty_like(map1);
506         for (i = 0; i < map1->n; ++i) {
507                 struct isl_map *d;
508                 d = basic_map_subtract(isl_basic_map_copy(map1->p[i]),
509                                        isl_map_copy(map2));
510                 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT))
511                         diff = isl_map_union_disjoint(diff, d);
512                 else
513                         diff = isl_map_union(diff, d);
514         }
515
516         isl_map_free(map1);
517         isl_map_free(map2);
518
519         return diff;
520 error:
521         isl_map_free(map1);
522         isl_map_free(map2);
523         return NULL;
524 }
525
526 __isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
527         __isl_take isl_map *map2)
528 {
529         return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
530 }
531
532 struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
533 {
534         return (struct isl_set *)
535                 isl_map_subtract(
536                         (struct isl_map *)set1, (struct isl_map *)set2);
537 }
538
539 /* A diff collector that aborts as soon as its add function is called,
540  * setting empty to 0.
541  */
542 struct isl_is_empty_diff_collector {
543         struct isl_diff_collector dc;
544         int empty;
545 };
546
547 /* isl_is_empty_diff_collector callback.
548  */
549 static int basic_map_is_empty_add(struct isl_diff_collector *dc,
550                             __isl_take isl_basic_map *bmap)
551 {
552         struct isl_is_empty_diff_collector *edc;
553         edc = (struct isl_is_empty_diff_collector *)dc;
554
555         edc->empty = 0;
556
557         isl_basic_map_free(bmap);
558         return -1;
559 }
560
561 /* Check if bmap \ map is empty by computing this set difference
562  * and breaking off as soon as the difference is known to be non-empty.
563  */
564 static int basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
565         __isl_keep isl_map *map)
566 {
567         int r;
568         struct isl_is_empty_diff_collector edc;
569
570         r = isl_basic_map_plain_is_empty(bmap);
571         if (r)
572                 return r;
573
574         edc.dc.add = &basic_map_is_empty_add;
575         edc.empty = 1;
576         r = basic_map_collect_diff(isl_basic_map_copy(bmap),
577                                    isl_map_copy(map), &edc.dc);
578         if (!edc.empty)
579                 return 0;
580
581         return r < 0 ? -1 : 1;
582 }
583
584 /* Check if map1 \ map2 is empty by checking if the set difference is empty
585  * for each of the basic maps in map1.
586  */
587 static int map_diff_is_empty(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
588 {
589         int i;
590         int is_empty = 1;
591
592         if (!map1 || !map2)
593                 return -1;
594         
595         for (i = 0; i < map1->n; ++i) {
596                 is_empty = basic_map_diff_is_empty(map1->p[i], map2);
597                 if (is_empty < 0 || !is_empty)
598                          break;
599         }
600
601         return is_empty;
602 }
603
604 /* Return 1 if "bmap" contains a single element.
605  */
606 int isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
607 {
608         if (!bmap)
609                 return -1;
610         if (bmap->n_div)
611                 return 0;
612         if (bmap->n_ineq)
613                 return 0;
614         return bmap->n_eq == isl_basic_map_total_dim(bmap);
615 }
616
617 /* Return 1 if "map" contains a single element.
618  */
619 int isl_map_plain_is_singleton(__isl_keep isl_map *map)
620 {
621         if (!map)
622                 return -1;
623         if (map->n != 1)
624                 return 0;
625
626         return isl_basic_map_plain_is_singleton(map->p[0]);
627 }
628
629 /* Given a singleton basic map, extract the single element
630  * as an isl_point.
631  */
632 static __isl_give isl_point *singleton_extract_point(
633         __isl_keep isl_basic_map *bmap)
634 {
635         int j;
636         unsigned dim;
637         struct isl_vec *point;
638         isl_int m;
639
640         if (!bmap)
641                 return NULL;
642
643         dim = isl_basic_map_total_dim(bmap);
644         isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
645         point = isl_vec_alloc(bmap->ctx, 1 + dim);
646         if (!point)
647                 return NULL;
648
649         isl_int_init(m);
650
651         isl_int_set_si(point->el[0], 1);
652         for (j = 0; j < bmap->n_eq; ++j) {
653                 int i = dim - 1 - j;
654                 isl_assert(bmap->ctx,
655                     isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
656                     goto error);
657                 isl_assert(bmap->ctx,
658                     isl_int_is_one(bmap->eq[j][1 + i]) ||
659                     isl_int_is_negone(bmap->eq[j][1 + i]),
660                     goto error);
661                 isl_assert(bmap->ctx,
662                     isl_seq_first_non_zero(bmap->eq[j]+1+i+1, dim-i-1) == -1,
663                     goto error);
664
665                 isl_int_gcd(m, point->el[0], bmap->eq[j][1 + i]);
666                 isl_int_divexact(m, bmap->eq[j][1 + i], m);
667                 isl_int_abs(m, m);
668                 isl_seq_scale(point->el, point->el, m, 1 + i);
669                 isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
670                 isl_int_neg(m, m);
671                 isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
672         }
673
674         isl_int_clear(m);
675         return isl_point_alloc(isl_basic_map_get_space(bmap), point);
676 error:
677         isl_int_clear(m);
678         isl_vec_free(point);
679         return NULL;
680 }
681
682 /* Return 1 is the singleton map "map1" is a subset of "map2",
683  * i.e., if the single element of "map1" is also an element of "map2".
684  * Assumes "map2" has known divs.
685  */
686 static int map_is_singleton_subset(__isl_keep isl_map *map1,
687         __isl_keep isl_map *map2)
688 {
689         int i;
690         int is_subset = 0;
691         struct isl_point *point;
692
693         if (!map1 || !map2)
694                 return -1;
695         if (map1->n != 1)
696                 return -1;
697
698         point = singleton_extract_point(map1->p[0]);
699         if (!point)
700                 return -1;
701
702         for (i = 0; i < map2->n; ++i) {
703                 is_subset = isl_basic_map_contains_point(map2->p[i], point);
704                 if (is_subset)
705                         break;
706         }
707
708         isl_point_free(point);
709         return is_subset;
710 }
711
712 int isl_map_is_subset(struct isl_map *map1, struct isl_map *map2)
713 {
714         int is_subset = 0;
715
716         if (!map1 || !map2)
717                 return -1;
718
719         if (!isl_map_has_equal_space(map1, map2))
720                 return 0;
721
722         if (isl_map_is_empty(map1))
723                 return 1;
724
725         if (isl_map_is_empty(map2))
726                 return 0;
727
728         if (isl_map_plain_is_universe(map2))
729                 return 1;
730
731         map2 = isl_map_compute_divs(isl_map_copy(map2));
732         if (isl_map_plain_is_singleton(map1)) {
733                 is_subset = map_is_singleton_subset(map1, map2);
734                 isl_map_free(map2);
735                 return is_subset;
736         }
737         is_subset = map_diff_is_empty(map1, map2);
738         isl_map_free(map2);
739
740         return is_subset;
741 }
742
743 int isl_set_is_subset(struct isl_set *set1, struct isl_set *set2)
744 {
745         return isl_map_is_subset(
746                         (struct isl_map *)set1, (struct isl_map *)set2);
747 }
748
749 __isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map)
750 {
751         int i;
752         struct isl_subtract_diff_collector sdc;
753         sdc.dc.add = &basic_map_subtract_add;
754
755         if (!map)
756                 return NULL;
757         if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
758                 return map;
759         if (map->n <= 1)
760                 return map;
761
762         map = isl_map_compute_divs(map);
763         map = isl_map_remove_empty_parts(map);
764
765         if (!map || map->n <= 1)
766                 return map;
767
768         sdc.diff = isl_map_from_basic_map(isl_basic_map_copy(map->p[0]));
769
770         for (i = 1; i < map->n; ++i) {
771                 struct isl_basic_map *bmap = isl_basic_map_copy(map->p[i]);
772                 struct isl_map *copy = isl_map_copy(sdc.diff);
773                 if (basic_map_collect_diff(bmap, copy, &sdc.dc) < 0) {
774                         isl_map_free(sdc.diff);
775                         sdc.diff = NULL;
776                         break;
777                 }
778         }
779
780         isl_map_free(map);
781
782         return sdc.diff;
783 }
784
785 __isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
786 {
787         return (struct isl_set *)isl_map_make_disjoint((struct isl_map *)set);
788 }
789
790 __isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
791 {
792         isl_set *universe;
793
794         if (!set)
795                 return NULL;
796
797         universe = isl_set_universe(isl_set_get_space(set));
798
799         return isl_set_subtract(universe, set);
800 }