isl_scheduler.c: node_update_vmap: extract out extract_linear_schedule
[isl.git] / isl_map_subtract.c
blob3f84fef4af115f7556430178799c75ba293ac5f1
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8 */
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 #include <isl_vec_private.h>
18 #include <set_to_map.c>
19 #include <set_from_map.c>
21 /* Expand the constraint "c" into "v". The initial "dim" dimensions
22 * are the same, but "v" may have more divs than "c" and the divs of "c"
23 * may appear in different positions in "v".
24 * The number of divs in "c" is given by "n_div" and the mapping
25 * of divs in "c" to divs in "v" is given by "div_map".
27 * Although it shouldn't happen in practice, it is theoretically
28 * possible that two or more divs in "c" are mapped to the same div in "v".
29 * These divs are then necessarily the same, so we simply add their
30 * coefficients.
32 static void expand_constraint(isl_vec *v, unsigned dim,
33 isl_int *c, int *div_map, unsigned n_div)
35 int i;
37 isl_seq_cpy(v->el, c, 1 + dim);
38 isl_seq_clr(v->el + 1 + dim, v->size - (1 + dim));
40 for (i = 0; i < n_div; ++i) {
41 int pos = 1 + dim + div_map[i];
42 isl_int_add(v->el[pos], v->el[pos], c[1 + dim + i]);
46 /* Add all constraints of bmap to tab. The equalities of bmap
47 * are added as a pair of inequalities.
49 static isl_stat tab_add_constraints(struct isl_tab *tab,
50 __isl_keep isl_basic_map *bmap, int *div_map)
52 int i;
53 unsigned dim;
54 unsigned tab_total;
55 unsigned bmap_n_div;
56 unsigned bmap_total;
57 isl_vec *v;
59 if (!tab || !bmap)
60 return isl_stat_error;
62 tab_total = isl_basic_map_total_dim(tab->bmap);
63 bmap_total = isl_basic_map_total_dim(bmap);
64 bmap_n_div = isl_basic_map_dim(bmap, isl_dim_div);
65 dim = bmap_total - bmap_n_div;
67 if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
68 return isl_stat_error;
70 v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
71 if (!v)
72 return isl_stat_error;
74 for (i = 0; i < bmap->n_eq; ++i) {
75 expand_constraint(v, dim, bmap->eq[i], div_map, bmap_n_div);
76 if (isl_tab_add_ineq(tab, v->el) < 0)
77 goto error;
78 isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
79 expand_constraint(v, dim, bmap->eq[i], div_map, bmap_n_div);
80 if (isl_tab_add_ineq(tab, v->el) < 0)
81 goto error;
82 isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
83 if (tab->empty)
84 break;
87 for (i = 0; i < bmap->n_ineq; ++i) {
88 expand_constraint(v, dim, bmap->ineq[i], div_map, bmap_n_div);
89 if (isl_tab_add_ineq(tab, v->el) < 0)
90 goto error;
91 if (tab->empty)
92 break;
95 isl_vec_free(v);
96 return isl_stat_ok;
97 error:
98 isl_vec_free(v);
99 return isl_stat_error;
102 /* Add a specific constraint of bmap (or its opposite) to tab.
103 * The position of the constraint is specified by "c", where
104 * the equalities of bmap are counted twice, once for the inequality
105 * that is equal to the equality, and once for its negation.
107 * Each of these constraints has been added to "tab" before by
108 * tab_add_constraints (and later removed again), so there should
109 * already be a row available for the constraint.
111 static isl_stat tab_add_constraint(struct isl_tab *tab,
112 __isl_keep isl_basic_map *bmap, int *div_map, int c, int oppose)
114 unsigned dim;
115 unsigned tab_total;
116 unsigned bmap_n_div;
117 unsigned bmap_total;
118 isl_vec *v;
119 isl_stat r;
121 if (!tab || !bmap)
122 return isl_stat_error;
124 tab_total = isl_basic_map_total_dim(tab->bmap);
125 bmap_total = isl_basic_map_total_dim(bmap);
126 bmap_n_div = isl_basic_map_dim(bmap, isl_dim_div);
127 dim = bmap_total - bmap_n_div;
129 v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
130 if (!v)
131 return isl_stat_error;
133 if (c < 2 * bmap->n_eq) {
134 if ((c % 2) != oppose)
135 isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
136 1 + bmap_total);
137 if (oppose)
138 isl_int_sub_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
139 expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap_n_div);
140 r = isl_tab_add_ineq(tab, v->el);
141 if (oppose)
142 isl_int_add_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
143 if ((c % 2) != oppose)
144 isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
145 1 + bmap_total);
146 } else {
147 c -= 2 * bmap->n_eq;
148 if (oppose) {
149 isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
150 1 + bmap_total);
151 isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
153 expand_constraint(v, dim, bmap->ineq[c], div_map, bmap_n_div);
154 r = isl_tab_add_ineq(tab, v->el);
155 if (oppose) {
156 isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
157 isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
158 1 + bmap_total);
162 isl_vec_free(v);
163 return r;
166 static isl_stat tab_add_divs(struct isl_tab *tab,
167 __isl_keep isl_basic_map *bmap, int **div_map)
169 int i, j;
170 struct isl_vec *vec;
171 unsigned total;
172 unsigned dim;
174 if (!bmap)
175 return isl_stat_error;
176 if (!bmap->n_div)
177 return isl_stat_ok;
179 if (!*div_map)
180 *div_map = isl_alloc_array(bmap->ctx, int, bmap->n_div);
181 if (!*div_map)
182 return isl_stat_error;
184 total = isl_basic_map_total_dim(tab->bmap);
185 dim = total - tab->bmap->n_div;
186 vec = isl_vec_alloc(bmap->ctx, 2 + total + bmap->n_div);
187 if (!vec)
188 return isl_stat_error;
190 for (i = 0; i < bmap->n_div; ++i) {
191 isl_seq_cpy(vec->el, bmap->div[i], 2 + dim);
192 isl_seq_clr(vec->el + 2 + dim, tab->bmap->n_div);
193 for (j = 0; j < i; ++j)
194 isl_int_add(vec->el[2 + dim + (*div_map)[j]],
195 vec->el[2 + dim + (*div_map)[j]],
196 bmap->div[i][2 + dim + j]);
197 for (j = 0; j < tab->bmap->n_div; ++j)
198 if (isl_seq_eq(tab->bmap->div[j],
199 vec->el, 2 + dim + tab->bmap->n_div))
200 break;
201 (*div_map)[i] = j;
202 if (j == tab->bmap->n_div) {
203 vec->size = 2 + dim + tab->bmap->n_div;
204 if (isl_tab_add_div(tab, vec) < 0)
205 goto error;
209 isl_vec_free(vec);
211 return isl_stat_ok;
212 error:
213 isl_vec_free(vec);
215 return isl_stat_error;
218 /* Freeze all constraints of tableau tab.
220 static int tab_freeze_constraints(struct isl_tab *tab)
222 int i;
224 for (i = 0; i < tab->n_con; ++i)
225 if (isl_tab_freeze_constraint(tab, i) < 0)
226 return -1;
228 return 0;
231 /* Check for redundant constraints starting at offset.
232 * Put the indices of the redundant constraints in index
233 * and return the number of redundant constraints.
235 static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
236 int offset, int **index)
238 int i, n;
239 int n_test = tab->n_con - offset;
241 if (isl_tab_detect_redundant(tab) < 0)
242 return -1;
244 if (n_test == 0)
245 return 0;
246 if (!*index)
247 *index = isl_alloc_array(ctx, int, n_test);
248 if (!*index)
249 return -1;
251 for (n = 0, i = 0; i < n_test; ++i) {
252 int r;
253 r = isl_tab_is_redundant(tab, offset + i);
254 if (r < 0)
255 return -1;
256 if (r)
257 continue;
258 (*index)[n++] = i;
261 return n;
264 /* basic_map_collect_diff calls add on each of the pieces of
265 * the set difference between bmap and map until the add method
266 * return a negative value.
268 struct isl_diff_collector {
269 isl_stat (*add)(struct isl_diff_collector *dc,
270 __isl_take isl_basic_map *bmap);
273 /* Compute the set difference between bmap and map and call
274 * dc->add on each of the piece until this function returns
275 * a negative value.
276 * Return 0 on success and -1 on error. dc->add returning
277 * a negative value is treated as an error, but the calling
278 * function can interpret the results based on the state of dc.
280 * Assumes that map has known divs.
282 * The difference is computed by a backtracking algorithm.
283 * Each level corresponds to a basic map in "map".
284 * When a node in entered for the first time, we check
285 * if the corresonding basic map intersects the current piece
286 * of "bmap". If not, we move to the next level.
287 * Otherwise, we split the current piece into as many
288 * pieces as there are non-redundant constraints of the current
289 * basic map in the intersection. Each of these pieces is
290 * handled by a child of the current node.
291 * In particular, if there are n non-redundant constraints,
292 * then for each 0 <= i < n, a piece is cut off by adding
293 * constraints 0 <= j < i and adding the opposite of constraint i.
294 * If there are no non-redundant constraints, meaning that the current
295 * piece is a subset of the current basic map, then we simply backtrack.
297 * In the leaves, we check if the remaining piece has any integer points
298 * and if so, pass it along to dc->add. As a special case, if nothing
299 * has been removed when we end up in a leaf, we simply pass along
300 * the original basic map.
302 static isl_stat basic_map_collect_diff(__isl_take isl_basic_map *bmap,
303 __isl_take isl_map *map, struct isl_diff_collector *dc)
305 int i;
306 int modified;
307 int level;
308 int init;
309 isl_bool empty;
310 isl_ctx *ctx;
311 struct isl_tab *tab = NULL;
312 struct isl_tab_undo **snap = NULL;
313 int *k = NULL;
314 int *n = NULL;
315 int **index = NULL;
316 int **div_map = NULL;
318 empty = isl_basic_map_is_empty(bmap);
319 if (empty) {
320 isl_basic_map_free(bmap);
321 isl_map_free(map);
322 return empty < 0 ? isl_stat_error : isl_stat_ok;
325 bmap = isl_basic_map_cow(bmap);
326 map = isl_map_cow(map);
328 if (!bmap || !map)
329 goto error;
331 ctx = map->ctx;
332 snap = isl_alloc_array(map->ctx, struct isl_tab_undo *, map->n);
333 k = isl_alloc_array(map->ctx, int, map->n);
334 n = isl_alloc_array(map->ctx, int, map->n);
335 index = isl_calloc_array(map->ctx, int *, map->n);
336 div_map = isl_calloc_array(map->ctx, int *, map->n);
337 if (!snap || !k || !n || !index || !div_map)
338 goto error;
340 bmap = isl_basic_map_order_divs(bmap);
341 map = isl_map_order_divs(map);
343 tab = isl_tab_from_basic_map(bmap, 1);
344 if (!tab)
345 goto error;
347 modified = 0;
348 level = 0;
349 init = 1;
351 while (level >= 0) {
352 if (level >= map->n) {
353 int empty;
354 struct isl_basic_map *bm;
355 if (!modified) {
356 if (dc->add(dc, isl_basic_map_copy(bmap)) < 0)
357 goto error;
358 break;
360 bm = isl_basic_map_copy(tab->bmap);
361 bm = isl_basic_map_cow(bm);
362 bm = isl_basic_map_update_from_tab(bm, tab);
363 bm = isl_basic_map_simplify(bm);
364 bm = isl_basic_map_finalize(bm);
365 empty = isl_basic_map_is_empty(bm);
366 if (empty)
367 isl_basic_map_free(bm);
368 else if (dc->add(dc, bm) < 0)
369 goto error;
370 if (empty < 0)
371 goto error;
372 level--;
373 init = 0;
374 continue;
376 if (init) {
377 int offset;
378 struct isl_tab_undo *snap2;
379 snap2 = isl_tab_snap(tab);
380 if (tab_add_divs(tab, map->p[level],
381 &div_map[level]) < 0)
382 goto error;
383 offset = tab->n_con;
384 snap[level] = isl_tab_snap(tab);
385 if (tab_freeze_constraints(tab) < 0)
386 goto error;
387 if (tab_add_constraints(tab, map->p[level],
388 div_map[level]) < 0)
389 goto error;
390 k[level] = 0;
391 n[level] = 0;
392 if (tab->empty) {
393 if (isl_tab_rollback(tab, snap2) < 0)
394 goto error;
395 level++;
396 continue;
398 modified = 1;
399 n[level] = n_non_redundant(ctx, tab, offset,
400 &index[level]);
401 if (n[level] < 0)
402 goto error;
403 if (n[level] == 0) {
404 level--;
405 init = 0;
406 continue;
408 if (isl_tab_rollback(tab, snap[level]) < 0)
409 goto error;
410 if (tab_add_constraint(tab, map->p[level],
411 div_map[level], index[level][0], 1) < 0)
412 goto error;
413 level++;
414 continue;
415 } else {
416 if (k[level] + 1 >= n[level]) {
417 level--;
418 continue;
420 if (isl_tab_rollback(tab, snap[level]) < 0)
421 goto error;
422 if (tab_add_constraint(tab, map->p[level],
423 div_map[level],
424 index[level][k[level]], 0) < 0)
425 goto error;
426 snap[level] = isl_tab_snap(tab);
427 k[level]++;
428 if (tab_add_constraint(tab, map->p[level],
429 div_map[level],
430 index[level][k[level]], 1) < 0)
431 goto error;
432 level++;
433 init = 1;
434 continue;
438 isl_tab_free(tab);
439 free(snap);
440 free(n);
441 free(k);
442 for (i = 0; index && i < map->n; ++i)
443 free(index[i]);
444 free(index);
445 for (i = 0; div_map && i < map->n; ++i)
446 free(div_map[i]);
447 free(div_map);
449 isl_basic_map_free(bmap);
450 isl_map_free(map);
452 return isl_stat_ok;
453 error:
454 isl_tab_free(tab);
455 free(snap);
456 free(n);
457 free(k);
458 for (i = 0; index && i < map->n; ++i)
459 free(index[i]);
460 free(index);
461 for (i = 0; div_map && i < map->n; ++i)
462 free(div_map[i]);
463 free(div_map);
464 isl_basic_map_free(bmap);
465 isl_map_free(map);
466 return isl_stat_error;
469 /* A diff collector that actually collects all parts of the
470 * set difference in the field diff.
472 struct isl_subtract_diff_collector {
473 struct isl_diff_collector dc;
474 struct isl_map *diff;
477 /* isl_subtract_diff_collector callback.
479 static isl_stat basic_map_subtract_add(struct isl_diff_collector *dc,
480 __isl_take isl_basic_map *bmap)
482 struct isl_subtract_diff_collector *sdc;
483 sdc = (struct isl_subtract_diff_collector *)dc;
485 sdc->diff = isl_map_union_disjoint(sdc->diff,
486 isl_map_from_basic_map(bmap));
488 return sdc->diff ? isl_stat_ok : isl_stat_error;
491 /* Return the set difference between bmap and map.
493 static __isl_give isl_map *basic_map_subtract(__isl_take isl_basic_map *bmap,
494 __isl_take isl_map *map)
496 struct isl_subtract_diff_collector sdc;
497 sdc.dc.add = &basic_map_subtract_add;
498 sdc.diff = isl_map_empty(isl_basic_map_get_space(bmap));
499 if (basic_map_collect_diff(bmap, map, &sdc.dc) < 0) {
500 isl_map_free(sdc.diff);
501 sdc.diff = NULL;
503 return sdc.diff;
506 /* Return an empty map living in the same space as "map1" and "map2".
508 static __isl_give isl_map *replace_pair_by_empty( __isl_take isl_map *map1,
509 __isl_take isl_map *map2)
511 isl_space *space;
513 space = isl_map_get_space(map1);
514 isl_map_free(map1);
515 isl_map_free(map2);
516 return isl_map_empty(space);
519 /* Return the set difference between map1 and map2.
520 * (U_i A_i) \ (U_j B_j) is computed as U_i (A_i \ (U_j B_j))
522 * If "map1" and "map2" are obviously equal to each other,
523 * then return an empty map in the same space.
525 * If "map1" and "map2" are disjoint, then simply return "map1".
527 static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
528 __isl_take isl_map *map2)
530 int i;
531 int equal, disjoint;
532 struct isl_map *diff;
534 if (!map1 || !map2)
535 goto error;
537 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
539 equal = isl_map_plain_is_equal(map1, map2);
540 if (equal < 0)
541 goto error;
542 if (equal)
543 return replace_pair_by_empty(map1, map2);
545 disjoint = isl_map_is_disjoint(map1, map2);
546 if (disjoint < 0)
547 goto error;
548 if (disjoint) {
549 isl_map_free(map2);
550 return map1;
553 map1 = isl_map_compute_divs(map1);
554 map2 = isl_map_compute_divs(map2);
555 if (!map1 || !map2)
556 goto error;
558 map1 = isl_map_remove_empty_parts(map1);
559 map2 = isl_map_remove_empty_parts(map2);
561 diff = isl_map_empty(isl_map_get_space(map1));
562 for (i = 0; i < map1->n; ++i) {
563 struct isl_map *d;
564 d = basic_map_subtract(isl_basic_map_copy(map1->p[i]),
565 isl_map_copy(map2));
566 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT))
567 diff = isl_map_union_disjoint(diff, d);
568 else
569 diff = isl_map_union(diff, d);
572 isl_map_free(map1);
573 isl_map_free(map2);
575 return diff;
576 error:
577 isl_map_free(map1);
578 isl_map_free(map2);
579 return NULL;
582 __isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
583 __isl_take isl_map *map2)
585 return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
588 struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
590 return set_from_map(isl_map_subtract(set_to_map(set1),
591 set_to_map(set2)));
594 /* Remove the elements of "dom" from the domain of "map".
596 static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
597 __isl_take isl_set *dom)
599 isl_bool ok;
600 isl_map *ext_dom;
602 ok = isl_map_compatible_domain(map, dom);
603 if (ok < 0)
604 goto error;
605 if (!ok)
606 isl_die(isl_set_get_ctx(dom), isl_error_invalid,
607 "incompatible spaces", goto error);
609 ext_dom = isl_map_universe(isl_map_get_space(map));
610 ext_dom = isl_map_intersect_domain(ext_dom, dom);
611 return isl_map_subtract(map, ext_dom);
612 error:
613 isl_map_free(map);
614 isl_set_free(dom);
615 return NULL;
618 __isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
619 __isl_take isl_set *dom)
621 return isl_map_align_params_map_map_and(map, dom, &map_subtract_domain);
624 /* Remove the elements of "dom" from the range of "map".
626 static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
627 __isl_take isl_set *dom)
629 isl_bool ok;
630 isl_map *ext_dom;
632 ok = isl_map_compatible_range(map, dom);
633 if (ok < 0)
634 goto error;
635 if (!ok)
636 isl_die(isl_set_get_ctx(dom), isl_error_invalid,
637 "incompatible spaces", goto error);
639 ext_dom = isl_map_universe(isl_map_get_space(map));
640 ext_dom = isl_map_intersect_range(ext_dom, dom);
641 return isl_map_subtract(map, ext_dom);
642 error:
643 isl_map_free(map);
644 isl_set_free(dom);
645 return NULL;
648 __isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
649 __isl_take isl_set *dom)
651 return isl_map_align_params_map_map_and(map, dom, &map_subtract_range);
654 /* A diff collector that aborts as soon as its add function is called,
655 * setting empty to 0.
657 struct isl_is_empty_diff_collector {
658 struct isl_diff_collector dc;
659 isl_bool empty;
662 /* isl_is_empty_diff_collector callback.
664 static isl_stat basic_map_is_empty_add(struct isl_diff_collector *dc,
665 __isl_take isl_basic_map *bmap)
667 struct isl_is_empty_diff_collector *edc;
668 edc = (struct isl_is_empty_diff_collector *)dc;
670 edc->empty = isl_bool_false;
672 isl_basic_map_free(bmap);
673 return isl_stat_error;
676 /* Check if bmap \ map is empty by computing this set difference
677 * and breaking off as soon as the difference is known to be non-empty.
679 static isl_bool basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
680 __isl_keep isl_map *map)
682 isl_bool empty;
683 isl_stat r;
684 struct isl_is_empty_diff_collector edc;
686 empty = isl_basic_map_plain_is_empty(bmap);
687 if (empty)
688 return empty;
690 edc.dc.add = &basic_map_is_empty_add;
691 edc.empty = isl_bool_true;
692 r = basic_map_collect_diff(isl_basic_map_copy(bmap),
693 isl_map_copy(map), &edc.dc);
694 if (!edc.empty)
695 return isl_bool_false;
697 return r < 0 ? isl_bool_error : isl_bool_true;
700 /* Check if map1 \ map2 is empty by checking if the set difference is empty
701 * for each of the basic maps in map1.
703 static isl_bool map_diff_is_empty(__isl_keep isl_map *map1,
704 __isl_keep isl_map *map2)
706 int i;
707 isl_bool is_empty = isl_bool_true;
709 if (!map1 || !map2)
710 return isl_bool_error;
712 for (i = 0; i < map1->n; ++i) {
713 is_empty = basic_map_diff_is_empty(map1->p[i], map2);
714 if (is_empty < 0 || !is_empty)
715 break;
718 return is_empty;
721 /* Return true if "bmap" contains a single element.
723 isl_bool isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
725 if (!bmap)
726 return isl_bool_error;
727 if (bmap->n_div)
728 return isl_bool_false;
729 if (bmap->n_ineq)
730 return isl_bool_false;
731 return bmap->n_eq == isl_basic_map_total_dim(bmap);
734 /* Return true if "map" contains a single element.
736 isl_bool isl_map_plain_is_singleton(__isl_keep isl_map *map)
738 if (!map)
739 return isl_bool_error;
740 if (map->n != 1)
741 return isl_bool_false;
743 return isl_basic_map_plain_is_singleton(map->p[0]);
746 /* Given a singleton basic map, extract the single element
747 * as an isl_point.
749 static __isl_give isl_point *singleton_extract_point(
750 __isl_keep isl_basic_map *bmap)
752 int j;
753 unsigned dim;
754 struct isl_vec *point;
755 isl_int m;
757 if (!bmap)
758 return NULL;
760 dim = isl_basic_map_total_dim(bmap);
761 isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
762 point = isl_vec_alloc(bmap->ctx, 1 + dim);
763 if (!point)
764 return NULL;
766 isl_int_init(m);
768 isl_int_set_si(point->el[0], 1);
769 for (j = 0; j < bmap->n_eq; ++j) {
770 int i = dim - 1 - j;
771 isl_assert(bmap->ctx,
772 isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
773 goto error);
774 isl_assert(bmap->ctx,
775 isl_int_is_one(bmap->eq[j][1 + i]) ||
776 isl_int_is_negone(bmap->eq[j][1 + i]),
777 goto error);
778 isl_assert(bmap->ctx,
779 isl_seq_first_non_zero(bmap->eq[j]+1+i+1, dim-i-1) == -1,
780 goto error);
782 isl_int_gcd(m, point->el[0], bmap->eq[j][1 + i]);
783 isl_int_divexact(m, bmap->eq[j][1 + i], m);
784 isl_int_abs(m, m);
785 isl_seq_scale(point->el, point->el, m, 1 + i);
786 isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
787 isl_int_neg(m, m);
788 isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
791 isl_int_clear(m);
792 return isl_point_alloc(isl_basic_map_get_space(bmap), point);
793 error:
794 isl_int_clear(m);
795 isl_vec_free(point);
796 return NULL;
799 /* Return isl_bool_true if the singleton map "map1" is a subset of "map2",
800 * i.e., if the single element of "map1" is also an element of "map2".
801 * Assumes "map2" has known divs.
803 static isl_bool map_is_singleton_subset(__isl_keep isl_map *map1,
804 __isl_keep isl_map *map2)
806 int i;
807 isl_bool is_subset = isl_bool_false;
808 struct isl_point *point;
810 if (!map1 || !map2)
811 return isl_bool_error;
812 if (map1->n != 1)
813 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
814 "expecting single-disjunct input",
815 return isl_bool_error);
817 point = singleton_extract_point(map1->p[0]);
818 if (!point)
819 return isl_bool_error;
821 for (i = 0; i < map2->n; ++i) {
822 is_subset = isl_basic_map_contains_point(map2->p[i], point);
823 if (is_subset)
824 break;
827 isl_point_free(point);
828 return is_subset;
831 static isl_bool map_is_subset(__isl_keep isl_map *map1,
832 __isl_keep isl_map *map2)
834 isl_bool is_subset = isl_bool_false;
835 isl_bool empty, single;
836 isl_bool rat1, rat2;
838 if (!map1 || !map2)
839 return isl_bool_error;
841 if (!isl_map_has_equal_space(map1, map2))
842 return isl_bool_false;
844 empty = isl_map_is_empty(map1);
845 if (empty < 0)
846 return isl_bool_error;
847 if (empty)
848 return isl_bool_true;
850 empty = isl_map_is_empty(map2);
851 if (empty < 0)
852 return isl_bool_error;
853 if (empty)
854 return isl_bool_false;
856 rat1 = isl_map_has_rational(map1);
857 rat2 = isl_map_has_rational(map2);
858 if (rat1 < 0 || rat2 < 0)
859 return isl_bool_error;
860 if (rat1 && !rat2)
861 return isl_bool_false;
863 if (isl_map_plain_is_universe(map2))
864 return isl_bool_true;
866 single = isl_map_plain_is_singleton(map1);
867 if (single < 0)
868 return isl_bool_error;
869 map2 = isl_map_compute_divs(isl_map_copy(map2));
870 if (single) {
871 is_subset = map_is_singleton_subset(map1, map2);
872 isl_map_free(map2);
873 return is_subset;
875 is_subset = map_diff_is_empty(map1, map2);
876 isl_map_free(map2);
878 return is_subset;
881 isl_bool isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
883 return isl_map_align_params_map_map_and_test(map1, map2,
884 &map_is_subset);
887 isl_bool isl_set_is_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
889 return isl_map_is_subset(set_to_map(set1), set_to_map(set2));
892 __isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map)
894 int i;
895 struct isl_subtract_diff_collector sdc;
896 sdc.dc.add = &basic_map_subtract_add;
898 if (!map)
899 return NULL;
900 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
901 return map;
902 if (map->n <= 1)
903 return map;
905 map = isl_map_compute_divs(map);
906 map = isl_map_remove_empty_parts(map);
908 if (!map || map->n <= 1)
909 return map;
911 sdc.diff = isl_map_from_basic_map(isl_basic_map_copy(map->p[0]));
913 for (i = 1; i < map->n; ++i) {
914 struct isl_basic_map *bmap = isl_basic_map_copy(map->p[i]);
915 struct isl_map *copy = isl_map_copy(sdc.diff);
916 if (basic_map_collect_diff(bmap, copy, &sdc.dc) < 0) {
917 isl_map_free(sdc.diff);
918 sdc.diff = NULL;
919 break;
923 isl_map_free(map);
925 return sdc.diff;
928 __isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
930 return set_from_map(isl_map_make_disjoint(set_to_map(set)));
933 __isl_give isl_map *isl_map_complement(__isl_take isl_map *map)
935 isl_map *universe;
937 if (!map)
938 return NULL;
940 universe = isl_map_universe(isl_map_get_space(map));
942 return isl_map_subtract(universe, map);
945 __isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
947 return isl_map_complement(set);