1fd408683cda56c7e9ae5e1effcb397c51d198d7
[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 /* Remove the elements of "dom" from the domain of "map".
540  */
541 static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
542         __isl_take isl_set *dom)
543 {
544         isl_map *ext_dom;
545
546         if (!isl_map_compatible_domain(map, dom))
547                 isl_die(isl_set_get_ctx(dom), isl_error_invalid,
548                         "incompatible spaces", goto error);
549         
550         ext_dom = isl_map_universe(isl_map_get_space(map));
551         ext_dom = isl_map_intersect_domain(ext_dom, dom);
552         return isl_map_subtract(map, ext_dom);
553 error:
554         isl_map_free(map);
555         isl_set_free(dom);
556         return NULL;
557 }
558
559 __isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
560         __isl_take isl_set *dom)
561 {
562         return isl_map_align_params_map_map_and(map, dom, &map_subtract_domain);
563 }
564
565 /* Remove the elements of "dom" from the range of "map".
566  */
567 static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
568         __isl_take isl_set *dom)
569 {
570         isl_map *ext_dom;
571
572         if (!isl_map_compatible_range(map, dom))
573                 isl_die(isl_set_get_ctx(dom), isl_error_invalid,
574                         "incompatible spaces", goto error);
575         
576         ext_dom = isl_map_universe(isl_map_get_space(map));
577         ext_dom = isl_map_intersect_range(ext_dom, dom);
578         return isl_map_subtract(map, ext_dom);
579 error:
580         isl_map_free(map);
581         isl_set_free(dom);
582         return NULL;
583 }
584
585 __isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
586         __isl_take isl_set *dom)
587 {
588         return isl_map_align_params_map_map_and(map, dom, &map_subtract_range);
589 }
590
591 /* A diff collector that aborts as soon as its add function is called,
592  * setting empty to 0.
593  */
594 struct isl_is_empty_diff_collector {
595         struct isl_diff_collector dc;
596         int empty;
597 };
598
599 /* isl_is_empty_diff_collector callback.
600  */
601 static int basic_map_is_empty_add(struct isl_diff_collector *dc,
602                             __isl_take isl_basic_map *bmap)
603 {
604         struct isl_is_empty_diff_collector *edc;
605         edc = (struct isl_is_empty_diff_collector *)dc;
606
607         edc->empty = 0;
608
609         isl_basic_map_free(bmap);
610         return -1;
611 }
612
613 /* Check if bmap \ map is empty by computing this set difference
614  * and breaking off as soon as the difference is known to be non-empty.
615  */
616 static int basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
617         __isl_keep isl_map *map)
618 {
619         int r;
620         struct isl_is_empty_diff_collector edc;
621
622         r = isl_basic_map_plain_is_empty(bmap);
623         if (r)
624                 return r;
625
626         edc.dc.add = &basic_map_is_empty_add;
627         edc.empty = 1;
628         r = basic_map_collect_diff(isl_basic_map_copy(bmap),
629                                    isl_map_copy(map), &edc.dc);
630         if (!edc.empty)
631                 return 0;
632
633         return r < 0 ? -1 : 1;
634 }
635
636 /* Check if map1 \ map2 is empty by checking if the set difference is empty
637  * for each of the basic maps in map1.
638  */
639 static int map_diff_is_empty(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
640 {
641         int i;
642         int is_empty = 1;
643
644         if (!map1 || !map2)
645                 return -1;
646         
647         for (i = 0; i < map1->n; ++i) {
648                 is_empty = basic_map_diff_is_empty(map1->p[i], map2);
649                 if (is_empty < 0 || !is_empty)
650                          break;
651         }
652
653         return is_empty;
654 }
655
656 /* Return 1 if "bmap" contains a single element.
657  */
658 int isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
659 {
660         if (!bmap)
661                 return -1;
662         if (bmap->n_div)
663                 return 0;
664         if (bmap->n_ineq)
665                 return 0;
666         return bmap->n_eq == isl_basic_map_total_dim(bmap);
667 }
668
669 /* Return 1 if "map" contains a single element.
670  */
671 int isl_map_plain_is_singleton(__isl_keep isl_map *map)
672 {
673         if (!map)
674                 return -1;
675         if (map->n != 1)
676                 return 0;
677
678         return isl_basic_map_plain_is_singleton(map->p[0]);
679 }
680
681 /* Given a singleton basic map, extract the single element
682  * as an isl_point.
683  */
684 static __isl_give isl_point *singleton_extract_point(
685         __isl_keep isl_basic_map *bmap)
686 {
687         int j;
688         unsigned dim;
689         struct isl_vec *point;
690         isl_int m;
691
692         if (!bmap)
693                 return NULL;
694
695         dim = isl_basic_map_total_dim(bmap);
696         isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
697         point = isl_vec_alloc(bmap->ctx, 1 + dim);
698         if (!point)
699                 return NULL;
700
701         isl_int_init(m);
702
703         isl_int_set_si(point->el[0], 1);
704         for (j = 0; j < bmap->n_eq; ++j) {
705                 int i = dim - 1 - j;
706                 isl_assert(bmap->ctx,
707                     isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
708                     goto error);
709                 isl_assert(bmap->ctx,
710                     isl_int_is_one(bmap->eq[j][1 + i]) ||
711                     isl_int_is_negone(bmap->eq[j][1 + i]),
712                     goto error);
713                 isl_assert(bmap->ctx,
714                     isl_seq_first_non_zero(bmap->eq[j]+1+i+1, dim-i-1) == -1,
715                     goto error);
716
717                 isl_int_gcd(m, point->el[0], bmap->eq[j][1 + i]);
718                 isl_int_divexact(m, bmap->eq[j][1 + i], m);
719                 isl_int_abs(m, m);
720                 isl_seq_scale(point->el, point->el, m, 1 + i);
721                 isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
722                 isl_int_neg(m, m);
723                 isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
724         }
725
726         isl_int_clear(m);
727         return isl_point_alloc(isl_basic_map_get_space(bmap), point);
728 error:
729         isl_int_clear(m);
730         isl_vec_free(point);
731         return NULL;
732 }
733
734 /* Return 1 is the singleton map "map1" is a subset of "map2",
735  * i.e., if the single element of "map1" is also an element of "map2".
736  * Assumes "map2" has known divs.
737  */
738 static int map_is_singleton_subset(__isl_keep isl_map *map1,
739         __isl_keep isl_map *map2)
740 {
741         int i;
742         int is_subset = 0;
743         struct isl_point *point;
744
745         if (!map1 || !map2)
746                 return -1;
747         if (map1->n != 1)
748                 return -1;
749
750         point = singleton_extract_point(map1->p[0]);
751         if (!point)
752                 return -1;
753
754         for (i = 0; i < map2->n; ++i) {
755                 is_subset = isl_basic_map_contains_point(map2->p[i], point);
756                 if (is_subset)
757                         break;
758         }
759
760         isl_point_free(point);
761         return is_subset;
762 }
763
764 static int map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
765 {
766         int is_subset = 0;
767
768         if (!map1 || !map2)
769                 return -1;
770
771         if (!isl_map_has_equal_space(map1, map2))
772                 return 0;
773
774         if (isl_map_is_empty(map1))
775                 return 1;
776
777         if (isl_map_is_empty(map2))
778                 return 0;
779
780         if (isl_map_plain_is_universe(map2))
781                 return 1;
782
783         map2 = isl_map_compute_divs(isl_map_copy(map2));
784         if (isl_map_plain_is_singleton(map1)) {
785                 is_subset = map_is_singleton_subset(map1, map2);
786                 isl_map_free(map2);
787                 return is_subset;
788         }
789         is_subset = map_diff_is_empty(map1, map2);
790         isl_map_free(map2);
791
792         return is_subset;
793 }
794
795 int isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
796 {
797         return isl_map_align_params_map_map_and_test(map1, map2,
798                                                         &map_is_subset);
799 }
800
801 int isl_set_is_subset(struct isl_set *set1, struct isl_set *set2)
802 {
803         return isl_map_is_subset(
804                         (struct isl_map *)set1, (struct isl_map *)set2);
805 }
806
807 __isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map)
808 {
809         int i;
810         struct isl_subtract_diff_collector sdc;
811         sdc.dc.add = &basic_map_subtract_add;
812
813         if (!map)
814                 return NULL;
815         if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
816                 return map;
817         if (map->n <= 1)
818                 return map;
819
820         map = isl_map_compute_divs(map);
821         map = isl_map_remove_empty_parts(map);
822
823         if (!map || map->n <= 1)
824                 return map;
825
826         sdc.diff = isl_map_from_basic_map(isl_basic_map_copy(map->p[0]));
827
828         for (i = 1; i < map->n; ++i) {
829                 struct isl_basic_map *bmap = isl_basic_map_copy(map->p[i]);
830                 struct isl_map *copy = isl_map_copy(sdc.diff);
831                 if (basic_map_collect_diff(bmap, copy, &sdc.dc) < 0) {
832                         isl_map_free(sdc.diff);
833                         sdc.diff = NULL;
834                         break;
835                 }
836         }
837
838         isl_map_free(map);
839
840         return sdc.diff;
841 }
842
843 __isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
844 {
845         return (struct isl_set *)isl_map_make_disjoint((struct isl_map *)set);
846 }
847
848 __isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
849 {
850         isl_set *universe;
851
852         if (!set)
853                 return NULL;
854
855         universe = isl_set_universe(isl_set_get_space(set));
856
857         return isl_set_subtract(universe, set);
858 }