LCOV - code coverage report
Current view: top level - metalib_isl - isl_map_subtract.c (source / functions) Hit Total Coverage
Test: project_test.lcov Lines: 306 483 63.4 %
Date: 2018-11-06 13:10:25 Functions: 21 31 67.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008-2009 Katholieke Universiteit Leuven
       3             :  *
       4             :  * Use of this software is governed by the MIT 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             : #include <isl_vec_private.h>
      17             : 
      18             : #include <set_to_map.c>
      19             : #include <set_from_map.c>
      20             : 
      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".
      26             :  *
      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.
      31             :  */
      32    15632195 : static void expand_constraint(isl_vec *v, unsigned dim,
      33             :         isl_int *c, int *div_map, unsigned n_div)
      34             : {
      35             :         int i;
      36             : 
      37    15632195 :         isl_seq_cpy(v->el, c, 1 + dim);
      38    15632195 :         isl_seq_clr(v->el + 1 + dim, v->size - (1 + dim));
      39             : 
      40    16977565 :         for (i = 0; i < n_div; ++i) {
      41     1345370 :                 int pos = 1 + dim + div_map[i];
      42     1345370 :                 isl_int_add(v->el[pos], v->el[pos], c[1 + dim + i]);
      43             :         }
      44    15632195 : }
      45             : 
      46             : /* Add all constraints of bmap to tab.  The equalities of bmap
      47             :  * are added as a pair of inequalities.
      48             :  */
      49     5558841 : static isl_stat tab_add_constraints(struct isl_tab *tab,
      50             :         __isl_keep isl_basic_map *bmap, int *div_map)
      51             : {
      52             :         int i;
      53             :         unsigned dim;
      54             :         unsigned tab_total;
      55             :         unsigned bmap_total;
      56             :         isl_vec *v;
      57             : 
      58     5558841 :         if (!tab || !bmap)
      59           0 :                 return isl_stat_error;
      60             : 
      61     5558841 :         tab_total = isl_basic_map_total_dim(tab->bmap);
      62     5558841 :         bmap_total = isl_basic_map_total_dim(bmap);
      63     5558841 :         dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
      64             : 
      65     5558841 :         if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
      66           0 :                 return isl_stat_error;
      67             : 
      68     5558841 :         v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
      69     5558841 :         if (!v)
      70           0 :                 return isl_stat_error;
      71             : 
      72     6319997 :         for (i = 0; i < bmap->n_eq; ++i) {
      73     1422279 :                 expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
      74     1422279 :                 if (isl_tab_add_ineq(tab, v->el) < 0)
      75           0 :                         goto error;
      76     1422279 :                 isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
      77     1422279 :                 expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
      78     1422279 :                 if (isl_tab_add_ineq(tab, v->el) < 0)
      79           0 :                         goto error;
      80     1422279 :                 isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
      81     1422279 :                 if (tab->empty)
      82      661123 :                         break;
      83             :         }
      84             : 
      85    12711507 :         for (i = 0; i < bmap->n_ineq; ++i) {
      86    12526669 :                 expand_constraint(v, dim, bmap->ineq[i], div_map, bmap->n_div);
      87    12526669 :                 if (isl_tab_add_ineq(tab, v->el) < 0)
      88           0 :                         goto error;
      89    12526669 :                 if (tab->empty)
      90     5374003 :                         break;
      91             :         }
      92             : 
      93     5558841 :         isl_vec_free(v);
      94     5558841 :         return isl_stat_ok;
      95             : error:
      96           0 :         isl_vec_free(v);
      97           0 :         return isl_stat_error;
      98             : }
      99             : 
     100             : /* Add a specific constraint of bmap (or its opposite) to tab.
     101             :  * The position of the constraint is specified by "c", where
     102             :  * the equalities of bmap are counted twice, once for the inequality
     103             :  * that is equal to the equality, and once for its negation.
     104             :  *
     105             :  * Each of these constraints has been added to "tab" before by
     106             :  * tab_add_constraints (and later removed again), so there should
     107             :  * already be a row available for the constraint.
     108             :  */
     109      260968 : static isl_stat tab_add_constraint(struct isl_tab *tab,
     110             :         __isl_keep isl_basic_map *bmap, int *div_map, int c, int oppose)
     111             : {
     112             :         unsigned dim;
     113             :         unsigned tab_total;
     114             :         unsigned bmap_total;
     115             :         isl_vec *v;
     116             :         isl_stat r;
     117             : 
     118      260968 :         if (!tab || !bmap)
     119           0 :                 return isl_stat_error;
     120             : 
     121      260968 :         tab_total = isl_basic_map_total_dim(tab->bmap);
     122      260968 :         bmap_total = isl_basic_map_total_dim(bmap);
     123      260968 :         dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
     124             : 
     125      260968 :         v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
     126      260968 :         if (!v)
     127           0 :                 return isl_stat_error;
     128             : 
     129      260968 :         if (c < 2 * bmap->n_eq) {
     130       10118 :                 if ((c % 2) != oppose)
     131        4841 :                         isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
     132             :                                         1 + bmap_total);
     133       10118 :                 if (oppose)
     134        6057 :                         isl_int_sub_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
     135       10118 :                 expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap->n_div);
     136       10118 :                 r = isl_tab_add_ineq(tab, v->el);
     137       10118 :                 if (oppose)
     138        6057 :                         isl_int_add_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
     139       10118 :                 if ((c % 2) != oppose)
     140        4841 :                         isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
     141             :                                         1 + bmap_total);
     142             :         } else {
     143      250850 :                 c -= 2 * bmap->n_eq;
     144      250850 :                 if (oppose) {
     145      178559 :                         isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
     146             :                                         1 + bmap_total);
     147      178559 :                         isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
     148             :                 }
     149      250850 :                 expand_constraint(v, dim, bmap->ineq[c], div_map, bmap->n_div);
     150      250850 :                 r = isl_tab_add_ineq(tab, v->el);
     151      250850 :                 if (oppose) {
     152      178559 :                         isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
     153      178559 :                         isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
     154             :                                         1 + bmap_total);
     155             :                 }
     156             :         }
     157             : 
     158      260968 :         isl_vec_free(v);
     159      260968 :         return r;
     160             : }
     161             : 
     162     5558841 : static isl_stat tab_add_divs(struct isl_tab *tab,
     163             :         __isl_keep isl_basic_map *bmap, int **div_map)
     164             : {
     165             :         int i, j;
     166             :         struct isl_vec *vec;
     167             :         unsigned total;
     168             :         unsigned dim;
     169             : 
     170     5558841 :         if (!bmap)
     171           0 :                 return isl_stat_error;
     172     5558841 :         if (!bmap->n_div)
     173     5066566 :                 return isl_stat_ok;
     174             : 
     175      492275 :         if (!*div_map)
     176       57419 :                 *div_map = isl_alloc_array(bmap->ctx, int, bmap->n_div);
     177      492275 :         if (!*div_map)
     178           0 :                 return isl_stat_error;
     179             : 
     180      492275 :         total = isl_basic_map_total_dim(tab->bmap);
     181      492275 :         dim = total - tab->bmap->n_div;
     182      492275 :         vec = isl_vec_alloc(bmap->ctx, 2 + total + bmap->n_div);
     183      492275 :         if (!vec)
     184           0 :                 return isl_stat_error;
     185             : 
     186      986404 :         for (i = 0; i < bmap->n_div; ++i) {
     187      494129 :                 isl_seq_cpy(vec->el, bmap->div[i], 2 + dim);
     188      494129 :                 isl_seq_clr(vec->el + 2 + dim, tab->bmap->n_div);
     189      495983 :                 for (j = 0; j < i; ++j)
     190        1854 :                         isl_int_add(vec->el[2 + dim + (*div_map)[j]],
     191             :                                     vec->el[2 + dim + (*div_map)[j]],
     192             :                                         bmap->div[i][2 + dim + j]);
     193      502780 :                 for (j = 0; j < tab->bmap->n_div; ++j)
     194       70628 :                         if (isl_seq_eq(tab->bmap->div[j],
     195       70628 :                                         vec->el, 2 + dim + tab->bmap->n_div))
     196       61977 :                                 break;
     197      494129 :                 (*div_map)[i] = j;
     198      494129 :                 if (j == tab->bmap->n_div) {
     199      432152 :                         vec->size = 2 + dim + tab->bmap->n_div;
     200      432152 :                         if (isl_tab_add_div(tab, vec) < 0)
     201           0 :                                 goto error;
     202             :                 }
     203             :         }
     204             : 
     205      492275 :         isl_vec_free(vec);
     206             : 
     207      492275 :         return isl_stat_ok;
     208             : error:
     209           0 :         isl_vec_free(vec);
     210             : 
     211           0 :         return isl_stat_error;
     212             : }
     213             : 
     214             : /* Freeze all constraints of tableau tab.
     215             :  */
     216     5558841 : static int tab_freeze_constraints(struct isl_tab *tab)
     217             : {
     218             :         int i;
     219             : 
     220    56054062 :         for (i = 0; i < tab->n_con; ++i)
     221    50495221 :                 if (isl_tab_freeze_constraint(tab, i) < 0)
     222           0 :                         return -1;
     223             : 
     224     5558841 :         return 0;
     225             : }
     226             : 
     227             : /* Check for redundant constraints starting at offset.
     228             :  * Put the indices of the redundant constraints in index
     229             :  * and return the number of redundant constraints.
     230             :  */
     231      177277 : static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
     232             :         int offset, int **index)
     233             : {
     234             :         int i, n;
     235      177277 :         int n_test = tab->n_con - offset;
     236             : 
     237      177277 :         if (isl_tab_detect_redundant(tab) < 0)
     238           0 :                 return -1;
     239             : 
     240      177277 :         if (n_test == 0)
     241         806 :                 return 0;
     242      176471 :         if (!*index)
     243      115909 :                 *index = isl_alloc_array(ctx, int, n_test);
     244      176471 :         if (!*index)
     245           0 :                 return -1;
     246             : 
     247     1130130 :         for (n = 0, i = 0; i < n_test; ++i) {
     248             :                 int r;
     249      953659 :                 r = isl_tab_is_redundant(tab, offset + i);
     250      953659 :                 if (r < 0)
     251           0 :                         return -1;
     252      953659 :                 if (r)
     253      769043 :                         continue;
     254      184616 :                 (*index)[n++] = i;
     255             :         }
     256             : 
     257      176471 :         return n;
     258             : }
     259             : 
     260             : /* basic_map_collect_diff calls add on each of the pieces of
     261             :  * the set difference between bmap and map until the add method
     262             :  * return a negative value.
     263             :  */
     264             : struct isl_diff_collector {
     265             :         isl_stat (*add)(struct isl_diff_collector *dc,
     266             :                     __isl_take isl_basic_map *bmap);
     267             : };
     268             : 
     269             : /* Compute the set difference between bmap and map and call
     270             :  * dc->add on each of the piece until this function returns
     271             :  * a negative value.
     272             :  * Return 0 on success and -1 on error.  dc->add returning
     273             :  * a negative value is treated as an error, but the calling
     274             :  * function can interpret the results based on the state of dc.
     275             :  *
     276             :  * Assumes that map has known divs.
     277             :  *
     278             :  * The difference is computed by a backtracking algorithm.
     279             :  * Each level corresponds to a basic map in "map".
     280             :  * When a node in entered for the first time, we check
     281             :  * if the corresonding basic map intersects the current piece
     282             :  * of "bmap".  If not, we move to the next level.
     283             :  * Otherwise, we split the current piece into as many
     284             :  * pieces as there are non-redundant constraints of the current
     285             :  * basic map in the intersection.  Each of these pieces is
     286             :  * handled by a child of the current node.
     287             :  * In particular, if there are n non-redundant constraints,
     288             :  * then for each 0 <= i < n, a piece is cut off by adding
     289             :  * constraints 0 <= j < i and adding the opposite of constraint i.
     290             :  * If there are no non-redundant constraints, meaning that the current
     291             :  * piece is a subset of the current basic map, then we simply backtrack.
     292             :  *
     293             :  * In the leaves, we check if the remaining piece has any integer points
     294             :  * and if so, pass it along to dc->add.  As a special case, if nothing
     295             :  * has been removed when we end up in a leaf, we simply pass along
     296             :  * the original basic map.
     297             :  */
     298       47235 : static isl_stat basic_map_collect_diff(__isl_take isl_basic_map *bmap,
     299             :         __isl_take isl_map *map, struct isl_diff_collector *dc)
     300             : {
     301             :         int i;
     302             :         int modified;
     303             :         int level;
     304             :         int init;
     305             :         isl_bool empty;
     306             :         isl_ctx *ctx;
     307       47235 :         struct isl_tab *tab = NULL;
     308       47235 :         struct isl_tab_undo **snap = NULL;
     309       47235 :         int *k = NULL;
     310       47235 :         int *n = NULL;
     311       47235 :         int **index = NULL;
     312       47235 :         int **div_map = NULL;
     313             : 
     314       47235 :         empty = isl_basic_map_is_empty(bmap);
     315       47235 :         if (empty) {
     316           0 :                 isl_basic_map_free(bmap);
     317           0 :                 isl_map_free(map);
     318           0 :                 return empty < 0 ? isl_stat_error : isl_stat_ok;
     319             :         }
     320             : 
     321       47235 :         bmap = isl_basic_map_cow(bmap);
     322       47235 :         map = isl_map_cow(map);
     323             : 
     324       47235 :         if (!bmap || !map)
     325             :                 goto error;
     326             : 
     327       47235 :         ctx = map->ctx;
     328       47235 :         snap = isl_alloc_array(map->ctx, struct isl_tab_undo *, map->n);
     329       47235 :         k = isl_alloc_array(map->ctx, int, map->n);
     330       47235 :         n = isl_alloc_array(map->ctx, int, map->n);
     331       47235 :         index = isl_calloc_array(map->ctx, int *, map->n);
     332       47235 :         div_map = isl_calloc_array(map->ctx, int *, map->n);
     333       47235 :         if (!snap || !k || !n || !index || !div_map)
     334             :                 goto error;
     335             : 
     336       47235 :         bmap = isl_basic_map_order_divs(bmap);
     337       47235 :         map = isl_map_order_divs(map);
     338             : 
     339       47235 :         tab = isl_tab_from_basic_map(bmap, 1);
     340       47235 :         if (!tab)
     341           0 :                 goto error;
     342             : 
     343       47235 :         modified = 0;
     344       47235 :         level = 0;
     345       47235 :         init = 1;
     346             : 
     347    10890627 :         while (level >= 0) {
     348    10800981 :                 if (level >= map->n) {
     349             :                         int empty;
     350             :                         struct isl_basic_map *bm;
     351       54574 :                         if (!modified) {
     352        4824 :                                 if (dc->add(dc, isl_basic_map_copy(bmap)) < 0)
     353           0 :                                         goto error;
     354        4824 :                                 break;
     355             :                         }
     356       49750 :                         bm = isl_basic_map_copy(tab->bmap);
     357       49750 :                         bm = isl_basic_map_cow(bm);
     358       49750 :                         bm = isl_basic_map_update_from_tab(bm, tab);
     359       49750 :                         bm = isl_basic_map_simplify(bm);
     360       49750 :                         bm = isl_basic_map_finalize(bm);
     361       49750 :                         empty = isl_basic_map_is_empty(bm);
     362       49750 :                         if (empty)
     363        1153 :                                 isl_basic_map_free(bm);
     364       48597 :                         else if (dc->add(dc, bm) < 0)
     365           0 :                                 goto error;
     366       49750 :                         if (empty < 0)
     367           0 :                                 goto error;
     368       49750 :                         level--;
     369       49750 :                         init = 0;
     370       49750 :                         continue;
     371             :                 }
     372    10746407 :                 if (init) {
     373             :                         int offset;
     374             :                         struct isl_tab_undo *snap2;
     375     5558841 :                         snap2 = isl_tab_snap(tab);
     376    11117682 :                         if (tab_add_divs(tab, map->p[level],
     377     5558841 :                                          &div_map[level]) < 0)
     378           0 :                                 goto error;
     379     5558841 :                         offset = tab->n_con;
     380     5558841 :                         snap[level] = isl_tab_snap(tab);
     381     5558841 :                         if (tab_freeze_constraints(tab) < 0)
     382           0 :                                 goto error;
     383     5558841 :                         if (tab_add_constraints(tab, map->p[level],
     384     5558841 :                                                 div_map[level]) < 0)
     385           0 :                                 goto error;
     386     5558841 :                         k[level] = 0;
     387     5558841 :                         n[level] = 0;
     388     5558841 :                         if (tab->empty) {
     389     5381564 :                                 if (isl_tab_rollback(tab, snap2) < 0)
     390           0 :                                         goto error;
     391     5381564 :                                 level++;
     392     5381564 :                                 continue;
     393             :                         }
     394      177277 :                         modified = 1;
     395      354554 :                         n[level] = n_non_redundant(ctx, tab, offset,
     396      177277 :                                                     &index[level]);
     397      177277 :                         if (n[level] < 0)
     398           0 :                                 goto error;
     399      177277 :                         if (n[level] == 0) {
     400       69013 :                                 level--;
     401       69013 :                                 init = 0;
     402       69013 :                                 continue;
     403             :                         }
     404      108264 :                         if (isl_tab_rollback(tab, snap[level]) < 0)
     405           0 :                                 goto error;
     406      216528 :                         if (tab_add_constraint(tab, map->p[level],
     407      216528 :                                         div_map[level], index[level][0], 1) < 0)
     408           0 :                                 goto error;
     409      108264 :                         level++;
     410      108264 :                         continue;
     411             :                 } else {
     412     5187566 :                         if (k[level] + 1 >= n[level]) {
     413     5111214 :                                 level--;
     414     5111214 :                                 continue;
     415             :                         }
     416       76352 :                         if (isl_tab_rollback(tab, snap[level]) < 0)
     417           0 :                                 goto error;
     418      152704 :                         if (tab_add_constraint(tab, map->p[level],
     419       76352 :                                                 div_map[level],
     420       76352 :                                                 index[level][k[level]], 0) < 0)
     421           0 :                                 goto error;
     422       76352 :                         snap[level] = isl_tab_snap(tab);
     423       76352 :                         k[level]++;
     424      152704 :                         if (tab_add_constraint(tab, map->p[level],
     425       76352 :                                                 div_map[level],
     426       76352 :                                                 index[level][k[level]], 1) < 0)
     427           0 :                                 goto error;
     428       76352 :                         level++;
     429       76352 :                         init = 1;
     430       76352 :                         continue;
     431             :                 }
     432             :         }
     433             : 
     434       47235 :         isl_tab_free(tab);
     435       47235 :         free(snap);
     436       47235 :         free(n);
     437       47235 :         free(k);
     438     9465365 :         for (i = 0; index && i < map->n; ++i)
     439     9418130 :                 free(index[i]);
     440       47235 :         free(index);
     441     9465365 :         for (i = 0; div_map && i < map->n; ++i)
     442     9418130 :                 free(div_map[i]);
     443       47235 :         free(div_map);
     444             : 
     445       47235 :         isl_basic_map_free(bmap);
     446       47235 :         isl_map_free(map);
     447             : 
     448       47235 :         return isl_stat_ok;
     449             : error:
     450           0 :         isl_tab_free(tab);
     451           0 :         free(snap);
     452           0 :         free(n);
     453           0 :         free(k);
     454           0 :         for (i = 0; index && i < map->n; ++i)
     455           0 :                 free(index[i]);
     456           0 :         free(index);
     457           0 :         for (i = 0; div_map && i < map->n; ++i)
     458           0 :                 free(div_map[i]);
     459           0 :         free(div_map);
     460           0 :         isl_basic_map_free(bmap);
     461           0 :         isl_map_free(map);
     462           0 :         return isl_stat_error;
     463             : }
     464             : 
     465             : /* A diff collector that actually collects all parts of the
     466             :  * set difference in the field diff.
     467             :  */
     468             : struct isl_subtract_diff_collector {
     469             :         struct isl_diff_collector dc;
     470             :         struct isl_map *diff;
     471             : };
     472             : 
     473             : /* isl_subtract_diff_collector callback.
     474             :  */
     475       53421 : static isl_stat basic_map_subtract_add(struct isl_diff_collector *dc,
     476             :                             __isl_take isl_basic_map *bmap)
     477             : {
     478             :         struct isl_subtract_diff_collector *sdc;
     479       53421 :         sdc = (struct isl_subtract_diff_collector *)dc;
     480             : 
     481       53421 :         sdc->diff = isl_map_union_disjoint(sdc->diff,
     482             :                         isl_map_from_basic_map(bmap));
     483             : 
     484       53421 :         return sdc->diff ? isl_stat_ok : isl_stat_error;
     485             : }
     486             : 
     487             : /* Return the set difference between bmap and map.
     488             :  */
     489       28252 : static __isl_give isl_map *basic_map_subtract(__isl_take isl_basic_map *bmap,
     490             :         __isl_take isl_map *map)
     491             : {
     492             :         struct isl_subtract_diff_collector sdc;
     493       28252 :         sdc.dc.add = &basic_map_subtract_add;
     494       28252 :         sdc.diff = isl_map_empty(isl_basic_map_get_space(bmap));
     495       28252 :         if (basic_map_collect_diff(bmap, map, &sdc.dc) < 0) {
     496           0 :                 isl_map_free(sdc.diff);
     497           0 :                 sdc.diff = NULL;
     498             :         }
     499       28252 :         return sdc.diff;
     500             : }
     501             : 
     502             : /* Return an empty map living in the same space as "map1" and "map2".
     503             :  */
     504        1017 : static __isl_give isl_map *replace_pair_by_empty( __isl_take isl_map *map1,
     505             :         __isl_take isl_map *map2)
     506             : {
     507             :         isl_space *space;
     508             : 
     509        1017 :         space = isl_map_get_space(map1);
     510        1017 :         isl_map_free(map1);
     511        1017 :         isl_map_free(map2);
     512        1017 :         return isl_map_empty(space);
     513             : }
     514             : 
     515             : /* Return the set difference between map1 and map2.
     516             :  * (U_i A_i) \ (U_j B_j) is computed as U_i (A_i \ (U_j B_j))
     517             :  *
     518             :  * If "map1" and "map2" are obviously equal to each other,
     519             :  * then return an empty map in the same space.
     520             :  *
     521             :  * If "map1" and "map2" are disjoint, then simply return "map1".
     522             :  */
     523        5702 : static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
     524             :         __isl_take isl_map *map2)
     525             : {
     526             :         int i;
     527             :         int equal, disjoint;
     528             :         struct isl_map *diff;
     529             : 
     530        5702 :         if (!map1 || !map2)
     531             :                 goto error;
     532             : 
     533        5702 :         isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
     534             : 
     535        5702 :         equal = isl_map_plain_is_equal(map1, map2);
     536        5702 :         if (equal < 0)
     537           0 :                 goto error;
     538        5702 :         if (equal)
     539        1017 :                 return replace_pair_by_empty(map1, map2);
     540             : 
     541        4685 :         disjoint = isl_map_is_disjoint(map1, map2);
     542        4685 :         if (disjoint < 0)
     543           0 :                 goto error;
     544        4685 :         if (disjoint) {
     545        1550 :                 isl_map_free(map2);
     546        1550 :                 return map1;
     547             :         }
     548             : 
     549        3135 :         map1 = isl_map_compute_divs(map1);
     550        3135 :         map2 = isl_map_compute_divs(map2);
     551        3135 :         if (!map1 || !map2)
     552             :                 goto error;
     553             : 
     554        3135 :         map1 = isl_map_remove_empty_parts(map1);
     555        3135 :         map2 = isl_map_remove_empty_parts(map2);
     556             : 
     557        3135 :         diff = isl_map_empty(isl_map_get_space(map1));
     558       31387 :         for (i = 0; i < map1->n; ++i) {
     559             :                 struct isl_map *d;
     560       28252 :                 d = basic_map_subtract(isl_basic_map_copy(map1->p[i]),
     561             :                                        isl_map_copy(map2));
     562       28252 :                 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT))
     563       15178 :                         diff = isl_map_union_disjoint(diff, d);
     564             :                 else
     565       13074 :                         diff = isl_map_union(diff, d);
     566             :         }
     567             : 
     568        3135 :         isl_map_free(map1);
     569        3135 :         isl_map_free(map2);
     570             : 
     571        3135 :         return diff;
     572             : error:
     573           0 :         isl_map_free(map1);
     574           0 :         isl_map_free(map2);
     575           0 :         return NULL;
     576             : }
     577             : 
     578        5702 : __isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
     579             :         __isl_take isl_map *map2)
     580             : {
     581        5702 :         return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
     582             : }
     583             : 
     584        2223 : struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
     585             : {
     586        2223 :         return set_from_map(isl_map_subtract(set_to_map(set1),
     587             :                                             set_to_map(set2)));
     588             : }
     589             : 
     590             : /* Remove the elements of "dom" from the domain of "map".
     591             :  */
     592           0 : static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
     593             :         __isl_take isl_set *dom)
     594             : {
     595             :         isl_bool ok;
     596             :         isl_map *ext_dom;
     597             : 
     598           0 :         ok = isl_map_compatible_domain(map, dom);
     599           0 :         if (ok < 0)
     600           0 :                 goto error;
     601           0 :         if (!ok)
     602           0 :                 isl_die(isl_set_get_ctx(dom), isl_error_invalid,
     603             :                         "incompatible spaces", goto error);
     604             :         
     605           0 :         ext_dom = isl_map_universe(isl_map_get_space(map));
     606           0 :         ext_dom = isl_map_intersect_domain(ext_dom, dom);
     607           0 :         return isl_map_subtract(map, ext_dom);
     608             : error:
     609           0 :         isl_map_free(map);
     610           0 :         isl_set_free(dom);
     611           0 :         return NULL;
     612             : }
     613             : 
     614           0 : __isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
     615             :         __isl_take isl_set *dom)
     616             : {
     617           0 :         return isl_map_align_params_map_map_and(map, dom, &map_subtract_domain);
     618             : }
     619             : 
     620             : /* Remove the elements of "dom" from the range of "map".
     621             :  */
     622           0 : static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
     623             :         __isl_take isl_set *dom)
     624             : {
     625             :         isl_bool ok;
     626             :         isl_map *ext_dom;
     627             : 
     628           0 :         ok = isl_map_compatible_range(map, dom);
     629           0 :         if (ok < 0)
     630           0 :                 goto error;
     631           0 :         if (!ok)
     632           0 :                 isl_die(isl_set_get_ctx(dom), isl_error_invalid,
     633             :                         "incompatible spaces", goto error);
     634             :         
     635           0 :         ext_dom = isl_map_universe(isl_map_get_space(map));
     636           0 :         ext_dom = isl_map_intersect_range(ext_dom, dom);
     637           0 :         return isl_map_subtract(map, ext_dom);
     638             : error:
     639           0 :         isl_map_free(map);
     640           0 :         isl_set_free(dom);
     641           0 :         return NULL;
     642             : }
     643             : 
     644           0 : __isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
     645             :         __isl_take isl_set *dom)
     646             : {
     647           0 :         return isl_map_align_params_map_map_and(map, dom, &map_subtract_range);
     648             : }
     649             : 
     650             : /* A diff collector that aborts as soon as its add function is called,
     651             :  * setting empty to 0.
     652             :  */
     653             : struct isl_is_empty_diff_collector {
     654             :         struct isl_diff_collector dc;
     655             :         isl_bool empty;
     656             : };
     657             : 
     658             : /* isl_is_empty_diff_collector callback.
     659             :  */
     660           0 : static isl_stat basic_map_is_empty_add(struct isl_diff_collector *dc,
     661             :                             __isl_take isl_basic_map *bmap)
     662             : {
     663             :         struct isl_is_empty_diff_collector *edc;
     664           0 :         edc = (struct isl_is_empty_diff_collector *)dc;
     665             : 
     666           0 :         edc->empty = 0;
     667             : 
     668           0 :         isl_basic_map_free(bmap);
     669           0 :         return isl_stat_error;
     670             : }
     671             : 
     672             : /* Check if bmap \ map is empty by computing this set difference
     673             :  * and breaking off as soon as the difference is known to be non-empty.
     674             :  */
     675       18983 : static isl_bool basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
     676             :         __isl_keep isl_map *map)
     677             : {
     678             :         isl_bool empty;
     679             :         isl_stat r;
     680             :         struct isl_is_empty_diff_collector edc;
     681             : 
     682       18983 :         empty = isl_basic_map_plain_is_empty(bmap);
     683       18983 :         if (empty)
     684           0 :                 return empty;
     685             : 
     686       18983 :         edc.dc.add = &basic_map_is_empty_add;
     687       18983 :         edc.empty = isl_bool_true;
     688       18983 :         r = basic_map_collect_diff(isl_basic_map_copy(bmap),
     689             :                                    isl_map_copy(map), &edc.dc);
     690       18983 :         if (!edc.empty)
     691           0 :                 return isl_bool_false;
     692             : 
     693       18983 :         return r < 0 ? isl_bool_error : isl_bool_true;
     694             : }
     695             : 
     696             : /* Check if map1 \ map2 is empty by checking if the set difference is empty
     697             :  * for each of the basic maps in map1.
     698             :  */
     699         292 : static isl_bool map_diff_is_empty(__isl_keep isl_map *map1,
     700             :         __isl_keep isl_map *map2)
     701             : {
     702             :         int i;
     703         292 :         isl_bool is_empty = isl_bool_true;
     704             : 
     705         292 :         if (!map1 || !map2)
     706           0 :                 return isl_bool_error;
     707             :         
     708       19275 :         for (i = 0; i < map1->n; ++i) {
     709       18983 :                 is_empty = basic_map_diff_is_empty(map1->p[i], map2);
     710       18983 :                 if (is_empty < 0 || !is_empty)
     711             :                          break;
     712             :         }
     713             : 
     714         292 :         return is_empty;
     715             : }
     716             : 
     717             : /* Return true if "bmap" contains a single element.
     718             :  */
     719          33 : isl_bool isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
     720             : {
     721          33 :         if (!bmap)
     722           0 :                 return isl_bool_error;
     723          33 :         if (bmap->n_div)
     724           0 :                 return isl_bool_false;
     725          33 :         if (bmap->n_ineq)
     726          22 :                 return isl_bool_false;
     727          11 :         return bmap->n_eq == isl_basic_map_total_dim(bmap);
     728             : }
     729             : 
     730             : /* Return true if "map" contains a single element.
     731             :  */
     732         292 : isl_bool isl_map_plain_is_singleton(__isl_keep isl_map *map)
     733             : {
     734         292 :         if (!map)
     735           0 :                 return isl_bool_error;
     736         292 :         if (map->n != 1)
     737         259 :                 return isl_bool_false;
     738             : 
     739          33 :         return isl_basic_map_plain_is_singleton(map->p[0]);
     740             : }
     741             : 
     742             : /* Given a singleton basic map, extract the single element
     743             :  * as an isl_point.
     744             :  */
     745           0 : static __isl_give isl_point *singleton_extract_point(
     746             :         __isl_keep isl_basic_map *bmap)
     747             : {
     748             :         int j;
     749             :         unsigned dim;
     750             :         struct isl_vec *point;
     751             :         isl_int m;
     752             : 
     753           0 :         if (!bmap)
     754           0 :                 return NULL;
     755             : 
     756           0 :         dim = isl_basic_map_total_dim(bmap);
     757           0 :         isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
     758           0 :         point = isl_vec_alloc(bmap->ctx, 1 + dim);
     759           0 :         if (!point)
     760           0 :                 return NULL;
     761             : 
     762           0 :         isl_int_init(m);
     763             : 
     764           0 :         isl_int_set_si(point->el[0], 1);
     765           0 :         for (j = 0; j < bmap->n_eq; ++j) {
     766           0 :                 int i = dim - 1 - j;
     767           0 :                 isl_assert(bmap->ctx,
     768             :                     isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
     769             :                     goto error);
     770           0 :                 isl_assert(bmap->ctx,
     771             :                     isl_int_is_one(bmap->eq[j][1 + i]) ||
     772             :                     isl_int_is_negone(bmap->eq[j][1 + i]),
     773             :                     goto error);
     774           0 :                 isl_assert(bmap->ctx,
     775             :                     isl_seq_first_non_zero(bmap->eq[j]+1+i+1, dim-i-1) == -1,
     776             :                     goto error);
     777             : 
     778           0 :                 isl_int_gcd(m, point->el[0], bmap->eq[j][1 + i]);
     779           0 :                 isl_int_divexact(m, bmap->eq[j][1 + i], m);
     780           0 :                 isl_int_abs(m, m);
     781           0 :                 isl_seq_scale(point->el, point->el, m, 1 + i);
     782           0 :                 isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
     783           0 :                 isl_int_neg(m, m);
     784           0 :                 isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
     785             :         }
     786             : 
     787           0 :         isl_int_clear(m);
     788           0 :         return isl_point_alloc(isl_basic_map_get_space(bmap), point);
     789             : error:
     790           0 :         isl_int_clear(m);
     791           0 :         isl_vec_free(point);
     792           0 :         return NULL;
     793             : }
     794             : 
     795             : /* Return isl_bool_true if the singleton map "map1" is a subset of "map2",
     796             :  * i.e., if the single element of "map1" is also an element of "map2".
     797             :  * Assumes "map2" has known divs.
     798             :  */
     799           0 : static isl_bool map_is_singleton_subset(__isl_keep isl_map *map1,
     800             :         __isl_keep isl_map *map2)
     801             : {
     802             :         int i;
     803           0 :         isl_bool is_subset = isl_bool_false;
     804             :         struct isl_point *point;
     805             : 
     806           0 :         if (!map1 || !map2)
     807           0 :                 return isl_bool_error;
     808           0 :         if (map1->n != 1)
     809           0 :                 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
     810             :                         "expecting single-disjunct input",
     811             :                         return isl_bool_error);
     812             : 
     813           0 :         point = singleton_extract_point(map1->p[0]);
     814           0 :         if (!point)
     815           0 :                 return isl_bool_error;
     816             : 
     817           0 :         for (i = 0; i < map2->n; ++i) {
     818           0 :                 is_subset = isl_basic_map_contains_point(map2->p[i], point);
     819           0 :                 if (is_subset)
     820           0 :                         break;
     821             :         }
     822             : 
     823           0 :         isl_point_free(point);
     824           0 :         return is_subset;
     825             : }
     826             : 
     827         396 : static isl_bool map_is_subset(__isl_keep isl_map *map1,
     828             :         __isl_keep isl_map *map2)
     829             : {
     830         396 :         isl_bool is_subset = isl_bool_false;
     831             :         isl_bool empty, single;
     832             :         isl_bool rat1, rat2;
     833             : 
     834         396 :         if (!map1 || !map2)
     835           0 :                 return isl_bool_error;
     836             : 
     837         396 :         if (!isl_map_has_equal_space(map1, map2))
     838           0 :                 return isl_bool_false;
     839             : 
     840         396 :         empty = isl_map_is_empty(map1);
     841         396 :         if (empty < 0)
     842           0 :                 return isl_bool_error;
     843         396 :         if (empty)
     844           0 :                 return isl_bool_true;
     845             : 
     846         396 :         empty = isl_map_is_empty(map2);
     847         396 :         if (empty < 0)
     848           0 :                 return isl_bool_error;
     849         396 :         if (empty)
     850           0 :                 return isl_bool_false;
     851             : 
     852         396 :         rat1 = isl_map_has_rational(map1);
     853         396 :         rat2 = isl_map_has_rational(map2);
     854         396 :         if (rat1 < 0 || rat2 < 0)
     855           0 :                 return isl_bool_error;
     856         396 :         if (rat1 && !rat2)
     857           0 :                 return isl_bool_false;
     858             : 
     859         396 :         if (isl_map_plain_is_universe(map2))
     860         104 :                 return isl_bool_true;
     861             : 
     862         292 :         single = isl_map_plain_is_singleton(map1);
     863         292 :         if (single < 0)
     864           0 :                 return isl_bool_error;
     865         292 :         map2 = isl_map_compute_divs(isl_map_copy(map2));
     866         292 :         if (single) {
     867           0 :                 is_subset = map_is_singleton_subset(map1, map2);
     868           0 :                 isl_map_free(map2);
     869           0 :                 return is_subset;
     870             :         }
     871         292 :         is_subset = map_diff_is_empty(map1, map2);
     872         292 :         isl_map_free(map2);
     873             : 
     874         292 :         return is_subset;
     875             : }
     876             : 
     877         396 : isl_bool isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
     878             : {
     879         396 :         return isl_map_align_params_map_map_and_test(map1, map2,
     880             :                                                         &map_is_subset);
     881             : }
     882             : 
     883           0 : isl_bool isl_set_is_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
     884             : {
     885           0 :         return isl_map_is_subset(set_to_map(set1), set_to_map(set2));
     886             : }
     887             : 
     888           0 : __isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map)
     889             : {
     890             :         int i;
     891             :         struct isl_subtract_diff_collector sdc;
     892           0 :         sdc.dc.add = &basic_map_subtract_add;
     893             : 
     894           0 :         if (!map)
     895           0 :                 return NULL;
     896           0 :         if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
     897           0 :                 return map;
     898           0 :         if (map->n <= 1)
     899           0 :                 return map;
     900             : 
     901           0 :         map = isl_map_compute_divs(map);
     902           0 :         map = isl_map_remove_empty_parts(map);
     903             : 
     904           0 :         if (!map || map->n <= 1)
     905           0 :                 return map;
     906             : 
     907           0 :         sdc.diff = isl_map_from_basic_map(isl_basic_map_copy(map->p[0]));
     908             : 
     909           0 :         for (i = 1; i < map->n; ++i) {
     910           0 :                 struct isl_basic_map *bmap = isl_basic_map_copy(map->p[i]);
     911           0 :                 struct isl_map *copy = isl_map_copy(sdc.diff);
     912           0 :                 if (basic_map_collect_diff(bmap, copy, &sdc.dc) < 0) {
     913           0 :                         isl_map_free(sdc.diff);
     914           0 :                         sdc.diff = NULL;
     915           0 :                         break;
     916             :                 }
     917             :         }
     918             : 
     919           0 :         isl_map_free(map);
     920             : 
     921           0 :         return sdc.diff;
     922             : }
     923             : 
     924           0 : __isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
     925             : {
     926           0 :         return set_from_map(isl_map_make_disjoint(set_to_map(set)));
     927             : }
     928             : 
     929        3479 : __isl_give isl_map *isl_map_complement(__isl_take isl_map *map)
     930             : {
     931             :         isl_map *universe;
     932             : 
     933        3479 :         if (!map)
     934           0 :                 return NULL;
     935             : 
     936        3479 :         universe = isl_map_universe(isl_map_get_space(map));
     937             : 
     938        3479 :         return isl_map_subtract(universe, map);
     939             : }
     940             : 
     941        3479 : __isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
     942             : {
     943        3479 :         return isl_map_complement(set);
     944             : }

Generated by: LCOV version 1.12