LCOV - code coverage report
Current view: top level - metalib_isl - isl_map_subtract.c (source / functions) Hit Total Coverage
Test: 2018-11-12_point_project_unite_cov_greina31.lcov Lines: 344 483 71.2 %
Date: 2018-11-12 12:46:37 Functions: 23 31 74.2 %

          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 13398411063 : 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 13398411063 :         isl_seq_cpy(v->el, c, 1 + dim);
      38 13398411063 :         isl_seq_clr(v->el + 1 + dim, v->size - (1 + dim));
      39             : 
      40 23655997220 :         for (i = 0; i < n_div; ++i) {
      41 10257586157 :                 int pos = 1 + dim + div_map[i];
      42 10257586157 :                 isl_int_add(v->el[pos], v->el[pos], c[1 + dim + i]);
      43             :         }
      44 13398411063 : }
      45             : 
      46             : /* Add all constraints of bmap to tab.  The equalities of bmap
      47             :  * are added as a pair of inequalities.
      48             :  */
      49  2760709720 : 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  2760709720 :         if (!tab || !bmap)
      59           0 :                 return isl_stat_error;
      60             : 
      61  2760709720 :         tab_total = isl_basic_map_total_dim(tab->bmap);
      62  2760709720 :         bmap_total = isl_basic_map_total_dim(bmap);
      63  2760709720 :         dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
      64             : 
      65  2760709720 :         if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
      66           0 :                 return isl_stat_error;
      67             : 
      68  2760709720 :         v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
      69  2760709720 :         if (!v)
      70           0 :                 return isl_stat_error;
      71             : 
      72  5519213099 :         for (i = 0; i < bmap->n_eq; ++i) {
      73  4430460502 :                 expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
      74  4430460502 :                 if (isl_tab_add_ineq(tab, v->el) < 0)
      75           0 :                         goto error;
      76  4430460502 :                 isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
      77  4430460502 :                 expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
      78  4430460502 :                 if (isl_tab_add_ineq(tab, v->el) < 0)
      79           0 :                         goto error;
      80  4430460502 :                 isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
      81  4430460502 :                 if (tab->empty)
      82  1671957123 :                         break;
      83             :         }
      84             : 
      85  4341531942 :         for (i = 0; i < bmap->n_ineq; ++i) {
      86  4141239929 :                 expand_constraint(v, dim, bmap->ineq[i], div_map, bmap->n_div);
      87  4141239929 :                 if (isl_tab_add_ineq(tab, v->el) < 0)
      88           0 :                         goto error;
      89  4141239929 :                 if (tab->empty)
      90  2560417707 :                         break;
      91             :         }
      92             : 
      93  2760709720 :         isl_vec_free(v);
      94  2760709720 :         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   396250130 : 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   396250130 :         if (!tab || !bmap)
     119           0 :                 return isl_stat_error;
     120             : 
     121   396250130 :         tab_total = isl_basic_map_total_dim(tab->bmap);
     122   396250130 :         bmap_total = isl_basic_map_total_dim(bmap);
     123   396250130 :         dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
     124             : 
     125   396250130 :         v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
     126   396250130 :         if (!v)
     127           0 :                 return isl_stat_error;
     128             : 
     129   396250130 :         if (c < 2 * bmap->n_eq) {
     130   142498604 :                 if ((c % 2) != oppose)
     131    72038160 :                         isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
     132             :                                         1 + bmap_total);
     133   142498604 :                 if (oppose)
     134    74000832 :                         isl_int_sub_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
     135   142498604 :                 expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap->n_div);
     136   142498604 :                 r = isl_tab_add_ineq(tab, v->el);
     137   142498604 :                 if (oppose)
     138    74000832 :                         isl_int_add_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
     139   142498604 :                 if ((c % 2) != oppose)
     140    72038160 :                         isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
     141             :                                         1 + bmap_total);
     142             :         } else {
     143   253751526 :                 c -= 2 * bmap->n_eq;
     144   253751526 :                 if (oppose) {
     145   181035899 :                         isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
     146             :                                         1 + bmap_total);
     147   181035899 :                         isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
     148             :                 }
     149   253751526 :                 expand_constraint(v, dim, bmap->ineq[c], div_map, bmap->n_div);
     150   253751526 :                 r = isl_tab_add_ineq(tab, v->el);
     151   253751526 :                 if (oppose) {
     152   181035899 :                         isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
     153   181035899 :                         isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
     154             :                                         1 + bmap_total);
     155             :                 }
     156             :         }
     157             : 
     158   396250130 :         isl_vec_free(v);
     159   396250130 :         return r;
     160             : }
     161             : 
     162  2760709720 : 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  2760709720 :         if (!bmap)
     171           0 :                 return isl_stat_error;
     172  2760709720 :         if (!bmap->n_div)
     173  1531147770 :                 return isl_stat_ok;
     174             : 
     175  1229561950 :         if (!*div_map)
     176   180382484 :                 *div_map = isl_alloc_array(bmap->ctx, int, bmap->n_div);
     177  1229561950 :         if (!*div_map)
     178           0 :                 return isl_stat_error;
     179             : 
     180  1229561950 :         total = isl_basic_map_total_dim(tab->bmap);
     181  1229561950 :         dim = total - tab->bmap->n_div;
     182  1229561950 :         vec = isl_vec_alloc(bmap->ctx, 2 + total + bmap->n_div);
     183  1229561950 :         if (!vec)
     184           0 :                 return isl_stat_error;
     185             : 
     186  2971792514 :         for (i = 0; i < bmap->n_div; ++i) {
     187  1742230564 :                 isl_seq_cpy(vec->el, bmap->div[i], 2 + dim);
     188  1742230564 :                 isl_seq_clr(vec->el + 2 + dim, tab->bmap->n_div);
     189  2426892984 :                 for (j = 0; j < i; ++j)
     190   684662420 :                         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  5202412166 :                 for (j = 0; j < tab->bmap->n_div; ++j)
     194  4335325938 :                         if (isl_seq_eq(tab->bmap->div[j],
     195  4335325938 :                                         vec->el, 2 + dim + tab->bmap->n_div))
     196   875144336 :                                 break;
     197  1742230564 :                 (*div_map)[i] = j;
     198  1742230564 :                 if (j == tab->bmap->n_div) {
     199   867086228 :                         vec->size = 2 + dim + tab->bmap->n_div;
     200   867086228 :                         if (isl_tab_add_div(tab, vec) < 0)
     201           0 :                                 goto error;
     202             :                 }
     203             :         }
     204             : 
     205  1229561950 :         isl_vec_free(vec);
     206             : 
     207  1229561950 :         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  2760709720 : static int tab_freeze_constraints(struct isl_tab *tab)
     217             : {
     218             :         int i;
     219             : 
     220 41187894095 :         for (i = 0; i < tab->n_con; ++i)
     221 38427184375 :                 if (isl_tab_freeze_constraint(tab, i) < 0)
     222           0 :                         return -1;
     223             : 
     224  2760709720 :         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   150969559 : static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
     232             :         int offset, int **index)
     233             : {
     234             :         int i, n;
     235   150969559 :         int n_test = tab->n_con - offset;
     236             : 
     237   150969559 :         if (isl_tab_detect_redundant(tab) < 0)
     238           0 :                 return -1;
     239             : 
     240   150969559 :         if (n_test == 0)
     241      914977 :                 return 0;
     242   150054582 :         if (!*index)
     243    99627115 :                 *index = isl_alloc_array(ctx, int, n_test);
     244   150054582 :         if (!*index)
     245           0 :                 return -1;
     246             : 
     247  1305312193 :         for (n = 0, i = 0; i < n_test; ++i) {
     248             :                 int r;
     249  1155257611 :                 r = isl_tab_is_redundant(tab, offset + i);
     250  1155257611 :                 if (r < 0)
     251           0 :                         return -1;
     252  1155257611 :                 if (r)
     253   900220880 :                         continue;
     254   255036731 :                 (*index)[n++] = i;
     255             :         }
     256             : 
     257   150054582 :         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    32769834 : 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    32769834 :         struct isl_tab *tab = NULL;
     308    32769834 :         struct isl_tab_undo **snap = NULL;
     309    32769834 :         int *k = NULL;
     310    32769834 :         int *n = NULL;
     311    32769834 :         int **index = NULL;
     312    32769834 :         int **div_map = NULL;
     313             : 
     314    32769834 :         empty = isl_basic_map_is_empty(bmap);
     315    32769834 :         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    32769834 :         bmap = isl_basic_map_cow(bmap);
     322    32769834 :         map = isl_map_cow(map);
     323             : 
     324    32769834 :         if (!bmap || !map)
     325             :                 goto error;
     326             : 
     327    32769834 :         ctx = map->ctx;
     328    32769834 :         snap = isl_alloc_array(map->ctx, struct isl_tab_undo *, map->n);
     329    32769834 :         k = isl_alloc_array(map->ctx, int, map->n);
     330    32769834 :         n = isl_alloc_array(map->ctx, int, map->n);
     331    32769834 :         index = isl_calloc_array(map->ctx, int *, map->n);
     332    32769834 :         div_map = isl_calloc_array(map->ctx, int *, map->n);
     333    32769834 :         if (!snap || !k || !n || !index || !div_map)
     334             :                 goto error;
     335             : 
     336    32769834 :         bmap = isl_basic_map_order_divs(bmap);
     337    32769834 :         map = isl_map_order_divs(map);
     338             : 
     339    32769834 :         tab = isl_tab_from_basic_map(bmap, 1);
     340    32769834 :         if (!tab)
     341           0 :                 goto error;
     342             : 
     343    32769834 :         modified = 0;
     344    32769834 :         level = 0;
     345    32769834 :         init = 1;
     346             : 
     347  5738336728 :         while (level >= 0) {
     348  5681345821 :                 if (level >= map->n) {
     349             :                         int empty;
     350             :                         struct isl_basic_map *bm;
     351   136837006 :                         if (!modified) {
     352     8548761 :                                 if (dc->add(dc, isl_basic_map_copy(bmap)) < 0)
     353           0 :                                         goto error;
     354     8548761 :                                 break;
     355             :                         }
     356   128288245 :                         bm = isl_basic_map_copy(tab->bmap);
     357   128288245 :                         bm = isl_basic_map_cow(bm);
     358   128288245 :                         bm = isl_basic_map_update_from_tab(bm, tab);
     359   128288245 :                         bm = isl_basic_map_simplify(bm);
     360   128288245 :                         bm = isl_basic_map_finalize(bm);
     361   128288245 :                         empty = isl_basic_map_is_empty(bm);
     362   128288245 :                         if (empty)
     363    25989469 :                                 isl_basic_map_free(bm);
     364   102298776 :                         else if (dc->add(dc, bm) < 0)
     365           0 :                                 goto error;
     366   128288245 :                         if (empty < 0)
     367           0 :                                 goto error;
     368   128288245 :                         level--;
     369   128288245 :                         init = 0;
     370   128288245 :                         continue;
     371             :                 }
     372  5544508815 :                 if (init) {
     373             :                         int offset;
     374             :                         struct isl_tab_undo *snap2;
     375  2760709720 :                         snap2 = isl_tab_snap(tab);
     376  5521419440 :                         if (tab_add_divs(tab, map->p[level],
     377  2760709720 :                                          &div_map[level]) < 0)
     378           0 :                                 goto error;
     379  2760709720 :                         offset = tab->n_con;
     380  2760709720 :                         snap[level] = isl_tab_snap(tab);
     381  2760709720 :                         if (tab_freeze_constraints(tab) < 0)
     382           0 :                                 goto error;
     383  2760709720 :                         if (tab_add_constraints(tab, map->p[level],
     384  2760709720 :                                                 div_map[level]) < 0)
     385           0 :                                 goto error;
     386  2760709720 :                         k[level] = 0;
     387  2760709720 :                         n[level] = 0;
     388  2760709720 :                         if (tab->empty) {
     389  2609740161 :                                 if (isl_tab_rollback(tab, snap2) < 0)
     390           0 :                                         goto error;
     391  2609740161 :                                 level++;
     392  2609740161 :                                 continue;
     393             :                         }
     394   150969559 :                         modified = 1;
     395   301939118 :                         n[level] = n_non_redundant(ctx, tab, offset,
     396   150969559 :                                                     &index[level]);
     397   150969559 :                         if (n[level] < 0)
     398           0 :                                 goto error;
     399   150969559 :                         if (n[level] == 0) {
     400    37146227 :                                 level--;
     401    37146227 :                                 init = 0;
     402    37146227 :                                 continue;
     403             :                         }
     404   113823332 :                         if (isl_tab_rollback(tab, snap[level]) < 0)
     405           0 :                                 goto error;
     406   227646664 :                         if (tab_add_constraint(tab, map->p[level],
     407   227646664 :                                         div_map[level], index[level][0], 1) < 0)
     408           0 :                                 goto error;
     409   113823332 :                         level++;
     410   113823332 :                         continue;
     411             :                 } else {
     412  2783799095 :                         if (k[level] + 1 >= n[level]) {
     413  2642585696 :                                 level--;
     414  2642585696 :                                 continue;
     415             :                         }
     416   141213399 :                         if (isl_tab_rollback(tab, snap[level]) < 0)
     417           0 :                                 goto error;
     418   282426798 :                         if (tab_add_constraint(tab, map->p[level],
     419   141213399 :                                                 div_map[level],
     420   141213399 :                                                 index[level][k[level]], 0) < 0)
     421           0 :                                 goto error;
     422   141213399 :                         snap[level] = isl_tab_snap(tab);
     423   141213399 :                         k[level]++;
     424   282426798 :                         if (tab_add_constraint(tab, map->p[level],
     425   141213399 :                                                 div_map[level],
     426   141213399 :                                                 index[level][k[level]], 1) < 0)
     427           0 :                                 goto error;
     428   141213399 :                         level++;
     429   141213399 :                         init = 1;
     430   141213399 :                         continue;
     431             :                 }
     432             :         }
     433             : 
     434    32769834 :         isl_tab_free(tab);
     435    32769834 :         free(snap);
     436    32769834 :         free(n);
     437    32769834 :         free(k);
     438  1576181632 :         for (i = 0; index && i < map->n; ++i)
     439  1543411798 :                 free(index[i]);
     440    32769834 :         free(index);
     441  1576181632 :         for (i = 0; div_map && i < map->n; ++i)
     442  1543411798 :                 free(div_map[i]);
     443    32769834 :         free(div_map);
     444             : 
     445    32769834 :         isl_basic_map_free(bmap);
     446    32769834 :         isl_map_free(map);
     447             : 
     448    32769834 :         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   110847537 : 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   110847537 :         sdc = (struct isl_subtract_diff_collector *)dc;
     480             : 
     481   110847537 :         sdc->diff = isl_map_union_disjoint(sdc->diff,
     482             :                         isl_map_from_basic_map(bmap));
     483             : 
     484   110847537 :         return sdc->diff ? isl_stat_ok : isl_stat_error;
     485             : }
     486             : 
     487             : /* Return the set difference between bmap and map.
     488             :  */
     489    18774894 : 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    18774894 :         sdc.dc.add = &basic_map_subtract_add;
     494    18774894 :         sdc.diff = isl_map_empty(isl_basic_map_get_space(bmap));
     495    18774894 :         if (basic_map_collect_diff(bmap, map, &sdc.dc) < 0) {
     496           0 :                 isl_map_free(sdc.diff);
     497           0 :                 sdc.diff = NULL;
     498             :         }
     499    18774894 :         return sdc.diff;
     500             : }
     501             : 
     502             : /* Return an empty map living in the same space as "map1" and "map2".
     503             :  */
     504      617522 : 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      617522 :         space = isl_map_get_space(map1);
     510      617522 :         isl_map_free(map1);
     511      617522 :         isl_map_free(map2);
     512      617522 :         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     6911325 : 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     6911325 :         if (!map1 || !map2)
     531             :                 goto error;
     532             : 
     533     6911325 :         isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
     534             : 
     535     6911325 :         equal = isl_map_plain_is_equal(map1, map2);
     536     6911325 :         if (equal < 0)
     537           0 :                 goto error;
     538     6911325 :         if (equal)
     539      617522 :                 return replace_pair_by_empty(map1, map2);
     540             : 
     541     6293803 :         disjoint = isl_map_is_disjoint(map1, map2);
     542     6293803 :         if (disjoint < 0)
     543           0 :                 goto error;
     544     6293803 :         if (disjoint) {
     545     1726576 :                 isl_map_free(map2);
     546     1726576 :                 return map1;
     547             :         }
     548             : 
     549     4567227 :         map1 = isl_map_compute_divs(map1);
     550     4567227 :         map2 = isl_map_compute_divs(map2);
     551     4567227 :         if (!map1 || !map2)
     552             :                 goto error;
     553             : 
     554     4567227 :         map1 = isl_map_remove_empty_parts(map1);
     555     4567227 :         map2 = isl_map_remove_empty_parts(map2);
     556             : 
     557     4567227 :         diff = isl_map_empty(isl_map_get_space(map1));
     558    23342121 :         for (i = 0; i < map1->n; ++i) {
     559             :                 struct isl_map *d;
     560    18774894 :                 d = basic_map_subtract(isl_basic_map_copy(map1->p[i]),
     561             :                                        isl_map_copy(map2));
     562    18774894 :                 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT))
     563     5564806 :                         diff = isl_map_union_disjoint(diff, d);
     564             :                 else
     565    13210088 :                         diff = isl_map_union(diff, d);
     566             :         }
     567             : 
     568     4567227 :         isl_map_free(map1);
     569     4567227 :         isl_map_free(map2);
     570             : 
     571     4567227 :         return diff;
     572             : error:
     573           0 :         isl_map_free(map1);
     574           0 :         isl_map_free(map2);
     575           0 :         return NULL;
     576             : }
     577             : 
     578     6911325 : __isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
     579             :         __isl_take isl_map *map2)
     580             : {
     581     6911325 :         return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
     582             : }
     583             : 
     584     1715664 : struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
     585             : {
     586     1715664 :         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    13994940 : 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    13994940 :         empty = isl_basic_map_plain_is_empty(bmap);
     683    13994940 :         if (empty)
     684           0 :                 return empty;
     685             : 
     686    13994940 :         edc.dc.add = &basic_map_is_empty_add;
     687    13994940 :         edc.empty = isl_bool_true;
     688    13994940 :         r = basic_map_collect_diff(isl_basic_map_copy(bmap),
     689             :                                    isl_map_copy(map), &edc.dc);
     690    13994940 :         if (!edc.empty)
     691           0 :                 return isl_bool_false;
     692             : 
     693    13994940 :         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      648034 : static isl_bool map_diff_is_empty(__isl_keep isl_map *map1,
     700             :         __isl_keep isl_map *map2)
     701             : {
     702             :         int i;
     703      648034 :         isl_bool is_empty = isl_bool_true;
     704             : 
     705      648034 :         if (!map1 || !map2)
     706           0 :                 return isl_bool_error;
     707             :         
     708    14642974 :         for (i = 0; i < map1->n; ++i) {
     709    13994940 :                 is_empty = basic_map_diff_is_empty(map1->p[i], map2);
     710    13994940 :                 if (is_empty < 0 || !is_empty)
     711             :                          break;
     712             :         }
     713             : 
     714      648034 :         return is_empty;
     715             : }
     716             : 
     717             : /* Return true if "bmap" contains a single element.
     718             :  */
     719       11698 : isl_bool isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
     720             : {
     721       11698 :         if (!bmap)
     722           0 :                 return isl_bool_error;
     723       11698 :         if (bmap->n_div)
     724        2858 :                 return isl_bool_false;
     725        8840 :         if (bmap->n_ineq)
     726        3304 :                 return isl_bool_false;
     727        5536 :         return bmap->n_eq == isl_basic_map_total_dim(bmap);
     728             : }
     729             : 
     730             : /* Return true if "map" contains a single element.
     731             :  */
     732      648354 : isl_bool isl_map_plain_is_singleton(__isl_keep isl_map *map)
     733             : {
     734      648354 :         if (!map)
     735           0 :                 return isl_bool_error;
     736      648354 :         if (map->n != 1)
     737      636656 :                 return isl_bool_false;
     738             : 
     739       11698 :         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         320 : 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         320 :         if (!bmap)
     754           0 :                 return NULL;
     755             : 
     756         320 :         dim = isl_basic_map_total_dim(bmap);
     757         320 :         isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
     758         320 :         point = isl_vec_alloc(bmap->ctx, 1 + dim);
     759         320 :         if (!point)
     760           0 :                 return NULL;
     761             : 
     762         320 :         isl_int_init(m);
     763             : 
     764         320 :         isl_int_set_si(point->el[0], 1);
     765        1178 :         for (j = 0; j < bmap->n_eq; ++j) {
     766         858 :                 int i = dim - 1 - j;
     767         858 :                 isl_assert(bmap->ctx,
     768             :                     isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
     769             :                     goto error);
     770         858 :                 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         858 :                 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         858 :                 isl_int_gcd(m, point->el[0], bmap->eq[j][1 + i]);
     779         858 :                 isl_int_divexact(m, bmap->eq[j][1 + i], m);
     780         858 :                 isl_int_abs(m, m);
     781         858 :                 isl_seq_scale(point->el, point->el, m, 1 + i);
     782         858 :                 isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
     783         858 :                 isl_int_neg(m, m);
     784         858 :                 isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
     785             :         }
     786             : 
     787         320 :         isl_int_clear(m);
     788         320 :         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         320 : static isl_bool map_is_singleton_subset(__isl_keep isl_map *map1,
     800             :         __isl_keep isl_map *map2)
     801             : {
     802             :         int i;
     803         320 :         isl_bool is_subset = isl_bool_false;
     804             :         struct isl_point *point;
     805             : 
     806         320 :         if (!map1 || !map2)
     807           0 :                 return isl_bool_error;
     808         320 :         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         320 :         point = singleton_extract_point(map1->p[0]);
     814         320 :         if (!point)
     815           0 :                 return isl_bool_error;
     816             : 
     817         320 :         for (i = 0; i < map2->n; ++i) {
     818         320 :                 is_subset = isl_basic_map_contains_point(map2->p[i], point);
     819         320 :                 if (is_subset)
     820         320 :                         break;
     821             :         }
     822             : 
     823         320 :         isl_point_free(point);
     824         320 :         return is_subset;
     825             : }
     826             : 
     827      694242 : static isl_bool map_is_subset(__isl_keep isl_map *map1,
     828             :         __isl_keep isl_map *map2)
     829             : {
     830      694242 :         isl_bool is_subset = isl_bool_false;
     831             :         isl_bool empty, single;
     832             :         isl_bool rat1, rat2;
     833             : 
     834      694242 :         if (!map1 || !map2)
     835           0 :                 return isl_bool_error;
     836             : 
     837      694242 :         if (!isl_map_has_equal_space(map1, map2))
     838           0 :                 return isl_bool_false;
     839             : 
     840      694242 :         empty = isl_map_is_empty(map1);
     841      694242 :         if (empty < 0)
     842           0 :                 return isl_bool_error;
     843      694242 :         if (empty)
     844           0 :                 return isl_bool_true;
     845             : 
     846      694242 :         empty = isl_map_is_empty(map2);
     847      694242 :         if (empty < 0)
     848           0 :                 return isl_bool_error;
     849      694242 :         if (empty)
     850           0 :                 return isl_bool_false;
     851             : 
     852      694242 :         rat1 = isl_map_has_rational(map1);
     853      694242 :         rat2 = isl_map_has_rational(map2);
     854      694242 :         if (rat1 < 0 || rat2 < 0)
     855           0 :                 return isl_bool_error;
     856      694242 :         if (rat1 && !rat2)
     857           0 :                 return isl_bool_false;
     858             : 
     859      694242 :         if (isl_map_plain_is_universe(map2))
     860       45888 :                 return isl_bool_true;
     861             : 
     862      648354 :         single = isl_map_plain_is_singleton(map1);
     863      648354 :         if (single < 0)
     864           0 :                 return isl_bool_error;
     865      648354 :         map2 = isl_map_compute_divs(isl_map_copy(map2));
     866      648354 :         if (single) {
     867         320 :                 is_subset = map_is_singleton_subset(map1, map2);
     868         320 :                 isl_map_free(map2);
     869         320 :                 return is_subset;
     870             :         }
     871      648034 :         is_subset = map_diff_is_empty(map1, map2);
     872      648034 :         isl_map_free(map2);
     873             : 
     874      648034 :         return is_subset;
     875             : }
     876             : 
     877      694242 : isl_bool isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
     878             : {
     879      694242 :         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     5195661 : __isl_give isl_map *isl_map_complement(__isl_take isl_map *map)
     930             : {
     931             :         isl_map *universe;
     932             : 
     933     5195661 :         if (!map)
     934           0 :                 return NULL;
     935             : 
     936     5195661 :         universe = isl_map_universe(isl_map_get_space(map));
     937             : 
     938     5195661 :         return isl_map_subtract(universe, map);
     939             : }
     940             : 
     941     5195661 : __isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
     942             : {
     943     5195661 :         return isl_map_complement(set);
     944             : }

Generated by: LCOV version 1.12