Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_map_subtract.c
Line
Count
Source (jump to first uncovered line)
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
static void expand_constraint(isl_vec *v, unsigned dim,
33
  isl_int *c, int *div_map, unsigned n_div)
34
339k
{
35
339k
  int i;
36
339k
37
339k
  isl_seq_cpy(v->el, c, 1 + dim);
38
339k
  isl_seq_clr(v->el + 1 + dim, v->size - (1 + dim));
39
339k
40
393k
  for (i = 0; i < n_div; 
++i54.1k
) {
41
54.1k
    int pos = 1 + dim + div_map[i];
42
54.1k
    isl_int_add(v->el[pos], v->el[pos], c[1 + dim + i]);
43
54.1k
  }
44
339k
}
45
46
/* Add all constraints of bmap to tab.  The equalities of bmap
47
 * are added as a pair of inequalities.
48
 */
49
static isl_stat tab_add_constraints(struct isl_tab *tab,
50
  __isl_keep isl_basic_map *bmap, int *div_map)
51
76.6k
{
52
76.6k
  int i;
53
76.6k
  unsigned dim;
54
76.6k
  unsigned tab_total;
55
76.6k
  unsigned bmap_total;
56
76.6k
  isl_vec *v;
57
76.6k
58
76.6k
  if (!tab || !bmap)
59
0
    return isl_stat_error;
60
76.6k
61
76.6k
  tab_total = isl_basic_map_total_dim(tab->bmap);
62
76.6k
  bmap_total = isl_basic_map_total_dim(bmap);
63
76.6k
  dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
64
76.6k
65
76.6k
  if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
66
0
    return isl_stat_error;
67
76.6k
68
76.6k
  v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
69
76.6k
  if (!v)
70
0
    return isl_stat_error;
71
76.6k
72
111k
  
for (i = 0; 76.6k
i < bmap->n_eq;
++i34.8k
) {
73
39.7k
    expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
74
39.7k
    if (isl_tab_add_ineq(tab, v->el) < 0)
75
0
      goto error;
76
39.7k
    isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
77
39.7k
    expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
78
39.7k
    if (isl_tab_add_ineq(tab, v->el) < 0)
79
0
      goto error;
80
39.7k
    isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
81
39.7k
    if (tab->empty)
82
4.89k
      break;
83
39.7k
  }
84
76.6k
85
258k
  
for (i = 0; 76.6k
i < bmap->n_ineq;
++i181k
) {
86
207k
    expand_constraint(v, dim, bmap->ineq[i], div_map, bmap->n_div);
87
207k
    if (isl_tab_add_ineq(tab, v->el) < 0)
88
0
      goto error;
89
207k
    if (tab->empty)
90
26.2k
      break;
91
207k
  }
92
76.6k
93
76.6k
  isl_vec_free(v);
94
76.6k
  return isl_stat_ok;
95
0
error:
96
0
  isl_vec_free(v);
97
0
  return isl_stat_error;
98
76.6k
}
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
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
52.2k
{
112
52.2k
  unsigned dim;
113
52.2k
  unsigned tab_total;
114
52.2k
  unsigned bmap_total;
115
52.2k
  isl_vec *v;
116
52.2k
  isl_stat r;
117
52.2k
118
52.2k
  if (!tab || !bmap)
119
0
    return isl_stat_error;
120
52.2k
121
52.2k
  tab_total = isl_basic_map_total_dim(tab->bmap);
122
52.2k
  bmap_total = isl_basic_map_total_dim(bmap);
123
52.2k
  dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
124
52.2k
125
52.2k
  v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
126
52.2k
  if (!v)
127
0
    return isl_stat_error;
128
52.2k
129
52.2k
  if (c < 2 * bmap->n_eq) {
130
22.6k
    if ((c % 2) != oppose)
131
9.85k
      isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
132
9.85k
          1 + bmap_total);
133
22.6k
    if (oppose)
134
22.6k
      
isl_int_sub_ui15.9k
(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
135
22.6k
    expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap->n_div);
136
22.6k
    r = isl_tab_add_ineq(tab, v->el);
137
22.6k
    if (oppose)
138
22.6k
      
isl_int_add_ui15.9k
(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
139
22.6k
    if ((c % 2) != oppose)
140
9.85k
      isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
141
9.85k
          1 + bmap_total);
142
29.6k
  } else {
143
29.6k
    c -= 2 * bmap->n_eq;
144
29.6k
    if (oppose) {
145
26.4k
      isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
146
26.4k
          1 + bmap_total);
147
26.4k
      isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
148
26.4k
    }
149
29.6k
    expand_constraint(v, dim, bmap->ineq[c], div_map, bmap->n_div);
150
29.6k
    r = isl_tab_add_ineq(tab, v->el);
151
29.6k
    if (oppose) {
152
26.4k
      isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
153
26.4k
      isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
154
26.4k
          1 + bmap_total);
155
26.4k
    }
156
29.6k
  }
157
52.2k
158
52.2k
  isl_vec_free(v);
159
52.2k
  return r;
160
52.2k
}
161
162
static isl_stat tab_add_divs(struct isl_tab *tab,
163
  __isl_keep isl_basic_map *bmap, int **div_map)
164
76.6k
{
165
76.6k
  int i, j;
166
76.6k
  struct isl_vec *vec;
167
76.6k
  unsigned total;
168
76.6k
  unsigned dim;
169
76.6k
170
76.6k
  if (!bmap)
171
0
    return isl_stat_error;
172
76.6k
  if (!bmap->n_div)
173
70.7k
    return isl_stat_ok;
174
5.86k
175
5.86k
  if (!*div_map)
176
4.71k
    *div_map = isl_alloc_array(bmap->ctx, int, bmap->n_div);
177
5.86k
  if (!*div_map)
178
0
    return isl_stat_error;
179
5.86k
180
5.86k
  total = isl_basic_map_total_dim(tab->bmap);
181
5.86k
  dim = total - tab->bmap->n_div;
182
5.86k
  vec = isl_vec_alloc(bmap->ctx, 2 + total + bmap->n_div);
183
5.86k
  if (!vec)
184
0
    return isl_stat_error;
185
5.86k
186
14.9k
  
for (i = 0; 5.86k
i < bmap->n_div;
++i9.10k
) {
187
9.10k
    isl_seq_cpy(vec->el, bmap->div[i], 2 + dim);
188
9.10k
    isl_seq_clr(vec->el + 2 + dim, tab->bmap->n_div);
189
13.0k
    for (j = 0; j < i; 
++j3.89k
)
190
9.10k
      
isl_int_add3.89k
(vec->el[2 + dim + (*div_map)[j]],
191
9.10k
            vec->el[2 + dim + (*div_map)[j]],
192
9.10k
          bmap->div[i][2 + dim + j]);
193
16.8k
    for (j = 0; j < tab->bmap->n_div; 
++j7.71k
)
194
13.4k
      if (isl_seq_eq(tab->bmap->div[j],
195
13.4k
          vec->el, 2 + dim + tab->bmap->n_div))
196
5.71k
        break;
197
9.10k
    (*div_map)[i] = j;
198
9.10k
    if (j == tab->bmap->n_div) {
199
3.38k
      vec->size = 2 + dim + tab->bmap->n_div;
200
3.38k
      if (isl_tab_add_div(tab, vec) < 0)
201
0
        goto error;
202
3.38k
    }
203
9.10k
  }
204
5.86k
205
5.86k
  isl_vec_free(vec);
206
5.86k
207
5.86k
  return isl_stat_ok;
208
0
error:
209
0
  isl_vec_free(vec);
210
0
211
0
  return isl_stat_error;
212
5.86k
}
213
214
/* Freeze all constraints of tableau tab.
215
 */
216
static int tab_freeze_constraints(struct isl_tab *tab)
217
76.6k
{
218
76.6k
  int i;
219
76.6k
220
500k
  for (i = 0; i < tab->n_con; 
++i424k
)
221
424k
    if (isl_tab_freeze_constraint(tab, i) < 0)
222
0
      return -1;
223
76.6k
224
76.6k
  return 0;
225
76.6k
}
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
static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
232
  int offset, int **index)
233
49.7k
{
234
49.7k
  int i, n;
235
49.7k
  int n_test = tab->n_con - offset;
236
49.7k
237
49.7k
  if (isl_tab_detect_redundant(tab) < 0)
238
0
    return -1;
239
49.7k
240
49.7k
  if (n_test == 0)
241
2.46k
    return 0;
242
47.2k
  if (!*index)
243
46.7k
    *index = isl_alloc_array(ctx, int, n_test);
244
47.2k
  if (!*index)
245
0
    return -1;
246
47.2k
247
261k
  
for (n = 0, i = 0; 47.2k
i < n_test;
++i214k
) {
248
214k
    int r;
249
214k
    r = isl_tab_is_redundant(tab, offset + i);
250
214k
    if (r < 0)
251
0
      return -1;
252
214k
    if (r)
253
163k
      continue;
254
51.3k
    (*index)[n++] = i;
255
51.3k
  }
256
47.2k
257
47.2k
  return n;
258
47.2k
}
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
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
47.7k
{
301
47.7k
  int i;
302
47.7k
  int modified;
303
47.7k
  int level;
304
47.7k
  int init;
305
47.7k
  isl_bool empty;
306
47.7k
  isl_ctx *ctx;
307
47.7k
  struct isl_tab *tab = NULL;
308
47.7k
  struct isl_tab_undo **snap = NULL;
309
47.7k
  int *k = NULL;
310
47.7k
  int *n = NULL;
311
47.7k
  int **index = NULL;
312
47.7k
  int **div_map = NULL;
313
47.7k
314
47.7k
  empty = isl_basic_map_is_empty(bmap);
315
47.7k
  if (empty) {
316
6
    isl_basic_map_free(bmap);
317
6
    isl_map_free(map);
318
6
    return empty < 0 ? 
isl_stat_error0
: isl_stat_ok;
319
6
  }
320
47.7k
321
47.7k
  bmap = isl_basic_map_cow(bmap);
322
47.7k
  map = isl_map_cow(map);
323
47.7k
324
47.7k
  if (!bmap || !map)
325
0
    goto error;
326
47.7k
327
47.7k
  ctx = map->ctx;
328
47.7k
  snap = isl_alloc_array(map->ctx, struct isl_tab_undo *, map->n);
329
47.7k
  k = isl_alloc_array(map->ctx, int, map->n);
330
47.7k
  n = isl_alloc_array(map->ctx, int, map->n);
331
47.7k
  index = isl_calloc_array(map->ctx, int *, map->n);
332
47.7k
  div_map = isl_calloc_array(map->ctx, int *, map->n);
333
47.7k
  if (!snap || !k || !n || !index || !div_map)
334
0
    goto error;
335
47.7k
336
47.7k
  bmap = isl_basic_map_order_divs(bmap);
337
47.7k
  map = isl_map_order_divs(map);
338
47.7k
339
47.7k
  tab = isl_tab_from_basic_map(bmap, 1);
340
47.7k
  if (!tab)
341
0
    goto error;
342
47.7k
343
47.7k
  modified = 0;
344
47.7k
  level = 0;
345
47.7k
  init = 1;
346
47.7k
347
196k
  while (level >= 0) {
348
163k
    if (level >= map->n) {
349
40.3k
      int empty;
350
40.3k
      struct isl_basic_map *bm;
351
40.3k
      if (!modified) {
352
6.46k
        if (dc->add(dc, isl_basic_map_copy(bmap)) < 0)
353
1.64k
          goto error;
354
4.82k
        break;
355
4.82k
      }
356
33.8k
      bm = isl_basic_map_copy(tab->bmap);
357
33.8k
      bm = isl_basic_map_cow(bm);
358
33.8k
      bm = isl_basic_map_update_from_tab(bm, tab);
359
33.8k
      bm = isl_basic_map_simplify(bm);
360
33.8k
      bm = isl_basic_map_finalize(bm);
361
33.8k
      empty = isl_basic_map_is_empty(bm);
362
33.8k
      if (empty)
363
1.04k
        isl_basic_map_free(bm);
364
32.8k
      else if (dc->add(dc, bm) < 0)
365
8.16k
        goto error;
366
25.7k
      if (empty < 0)
367
0
        goto error;
368
25.7k
      level--;
369
25.7k
      init = 0;
370
25.7k
      continue;
371
25.7k
    }
372
123k
    if (init) {
373
76.6k
      int offset;
374
76.6k
      struct isl_tab_undo *snap2;
375
76.6k
      snap2 = isl_tab_snap(tab);
376
76.6k
      if (tab_add_divs(tab, map->p[level],
377
76.6k
           &div_map[level]) < 0)
378
0
        goto error;
379
76.6k
      offset = tab->n_con;
380
76.6k
      snap[level] = isl_tab_snap(tab);
381
76.6k
      if (tab_freeze_constraints(tab) < 0)
382
0
        goto error;
383
76.6k
      if (tab_add_constraints(tab, map->p[level],
384
76.6k
            div_map[level]) < 0)
385
0
        goto error;
386
76.6k
      k[level] = 0;
387
76.6k
      n[level] = 0;
388
76.6k
      if (tab->empty) {
389
26.8k
        if (isl_tab_rollback(tab, snap2) < 0)
390
0
          goto error;
391
26.8k
        level++;
392
26.8k
        continue;
393
26.8k
      }
394
49.7k
      modified = 1;
395
49.7k
      n[level] = n_non_redundant(ctx, tab, offset,
396
49.7k
                &index[level]);
397
49.7k
      if (n[level] < 0)
398
0
        goto error;
399
49.7k
      if (n[level] == 0) {
400
17.3k
        level--;
401
17.3k
        init = 0;
402
17.3k
        continue;
403
17.3k
      }
404
32.4k
      if (isl_tab_rollback(tab, snap[level]) < 0)
405
0
        goto error;
406
32.4k
      if (tab_add_constraint(tab, map->p[level],
407
32.4k
          div_map[level], index[level][0], 1) < 0)
408
0
        goto error;
409
32.4k
      level++;
410
32.4k
      continue;
411
46.9k
    } else {
412
46.9k
      if (k[level] + 1 >= n[level]) {
413
36.9k
        level--;
414
36.9k
        continue;
415
36.9k
      }
416
9.93k
      if (isl_tab_rollback(tab, snap[level]) < 0)
417
0
        goto error;
418
9.93k
      if (tab_add_constraint(tab, map->p[level],
419
9.93k
            div_map[level],
420
9.93k
            index[level][k[level]], 0) < 0)
421
0
        goto error;
422
9.93k
      snap[level] = isl_tab_snap(tab);
423
9.93k
      k[level]++;
424
9.93k
      if (tab_add_constraint(tab, map->p[level],
425
9.93k
            div_map[level],
426
9.93k
            index[level][k[level]], 1) < 0)
427
0
        goto error;
428
9.93k
      level++;
429
9.93k
      init = 1;
430
9.93k
      continue;
431
9.93k
    }
432
123k
  }
433
47.7k
434
47.7k
  isl_tab_free(tab);
435
37.8k
  free(snap);
436
37.8k
  free(n);
437
37.8k
  free(k);
438
94.7k
  for (i = 0; index && i < map->n; 
++i56.8k
)
439
56.8k
    free(index[i]);
440
37.8k
  free(index);
441
94.7k
  for (i = 0; div_map && i < map->n; 
++i56.8k
)
442
56.8k
    free(div_map[i]);
443
37.8k
  free(div_map);
444
37.8k
445
37.8k
  isl_basic_map_free(bmap);
446
37.8k
  isl_map_free(map);
447
37.8k
448
37.8k
  return isl_stat_ok;
449
9.81k
error:
450
9.81k
  isl_tab_free(tab);
451
9.81k
  free(snap);
452
9.81k
  free(n);
453
9.81k
  free(k);
454
26.7k
  for (i = 0; index && i < map->n; 
++i16.9k
)
455
16.9k
    free(index[i]);
456
9.81k
  free(index);
457
26.7k
  for (i = 0; div_map && i < map->n; 
++i16.9k
)
458
16.9k
    free(div_map[i]);
459
9.81k
  free(div_map);
460
9.81k
  isl_basic_map_free(bmap);
461
9.81k
  isl_map_free(map);
462
9.81k
  return isl_stat_error;
463
47.7k
}
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
static isl_stat basic_map_subtract_add(struct isl_diff_collector *dc,
476
          __isl_take isl_basic_map *bmap)
477
29.4k
{
478
29.4k
  struct isl_subtract_diff_collector *sdc;
479
29.4k
  sdc = (struct isl_subtract_diff_collector *)dc;
480
29.4k
481
29.4k
  sdc->diff = isl_map_union_disjoint(sdc->diff,
482
29.4k
      isl_map_from_basic_map(bmap));
483
29.4k
484
29.4k
  return sdc->diff ? isl_stat_ok : 
isl_stat_error0
;
485
29.4k
}
486
487
/* Return the set difference between bmap and map.
488
 */
489
static __isl_give isl_map *basic_map_subtract(__isl_take isl_basic_map *bmap,
490
  __isl_take isl_map *map)
491
26.0k
{
492
26.0k
  struct isl_subtract_diff_collector sdc;
493
26.0k
  sdc.dc.add = &basic_map_subtract_add;
494
26.0k
  sdc.diff = isl_map_empty(isl_basic_map_get_space(bmap));
495
26.0k
  if (basic_map_collect_diff(bmap, map, &sdc.dc) < 0) {
496
0
    isl_map_free(sdc.diff);
497
0
    sdc.diff = NULL;
498
0
  }
499
26.0k
  return sdc.diff;
500
26.0k
}
501
502
/* Return an empty map living in the same space as "map1" and "map2".
503
 */
504
static __isl_give isl_map *replace_pair_by_empty( __isl_take isl_map *map1,
505
  __isl_take isl_map *map2)
506
4.65k
{
507
4.65k
  isl_space *space;
508
4.65k
509
4.65k
  space = isl_map_get_space(map1);
510
4.65k
  isl_map_free(map1);
511
4.65k
  isl_map_free(map2);
512
4.65k
  return isl_map_empty(space);
513
4.65k
}
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
static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
524
  __isl_take isl_map *map2)
525
32.9k
{
526
32.9k
  int i;
527
32.9k
  int equal, disjoint;
528
32.9k
  struct isl_map *diff;
529
32.9k
530
32.9k
  if (!map1 || !map2)
531
0
    goto error;
532
32.9k
533
32.9k
  isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
534
32.9k
535
32.9k
  equal = isl_map_plain_is_equal(map1, map2);
536
32.9k
  if (equal < 0)
537
0
    goto error;
538
32.9k
  if (equal)
539
4.65k
    return replace_pair_by_empty(map1, map2);
540
28.2k
541
28.2k
  disjoint = isl_map_is_disjoint(map1, map2);
542
28.2k
  if (disjoint < 0)
543
0
    goto error;
544
28.2k
  if (disjoint) {
545
16.1k
    isl_map_free(map2);
546
16.1k
    return map1;
547
16.1k
  }
548
12.1k
549
12.1k
  map1 = isl_map_compute_divs(map1);
550
12.1k
  map2 = isl_map_compute_divs(map2);
551
12.1k
  if (!map1 || !map2)
552
0
    goto error;
553
12.1k
554
12.1k
  map1 = isl_map_remove_empty_parts(map1);
555
12.1k
  map2 = isl_map_remove_empty_parts(map2);
556
12.1k
557
12.1k
  diff = isl_map_empty(isl_map_get_space(map1));
558
38.1k
  for (i = 0; i < map1->n; 
++i26.0k
) {
559
26.0k
    struct isl_map *d;
560
26.0k
    d = basic_map_subtract(isl_basic_map_copy(map1->p[i]),
561
26.0k
               isl_map_copy(map2));
562
26.0k
    if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT))
563
26.0k
      
diff = isl_map_union_disjoint(diff, d)9.81k
;
564
16.2k
    else
565
16.2k
      diff = isl_map_union(diff, d);
566
26.0k
  }
567
12.1k
568
12.1k
  isl_map_free(map1);
569
12.1k
  isl_map_free(map2);
570
12.1k
571
12.1k
  return diff;
572
0
error:
573
0
  isl_map_free(map1);
574
0
  isl_map_free(map2);
575
0
  return NULL;
576
12.1k
}
577
578
__isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
579
  __isl_take isl_map *map2)
580
32.9k
{
581
32.9k
  return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
582
32.9k
}
583
584
struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
585
21.9k
{
586
21.9k
  return set_from_map(isl_map_subtract(set_to_map(set1),
587
21.9k
              set_to_map(set2)));
588
21.9k
}
589
590
/* Remove the elements of "dom" from the domain of "map".
591
 */
592
static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
593
  __isl_take isl_set *dom)
594
96
{
595
96
  isl_bool ok;
596
96
  isl_map *ext_dom;
597
96
598
96
  ok = isl_map_compatible_domain(map, dom);
599
96
  if (ok < 0)
600
0
    goto error;
601
96
  if (!ok)
602
96
    
isl_die0
(isl_set_get_ctx(dom), isl_error_invalid,
603
96
      "incompatible spaces", goto error);
604
96
  
605
96
  ext_dom = isl_map_universe(isl_map_get_space(map));
606
96
  ext_dom = isl_map_intersect_domain(ext_dom, dom);
607
96
  return isl_map_subtract(map, ext_dom);
608
0
error:
609
0
  isl_map_free(map);
610
0
  isl_set_free(dom);
611
0
  return NULL;
612
96
}
613
614
__isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
615
  __isl_take isl_set *dom)
616
96
{
617
96
  return isl_map_align_params_map_map_and(map, dom, &map_subtract_domain);
618
96
}
619
620
/* Remove the elements of "dom" from the range of "map".
621
 */
622
static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
623
  __isl_take isl_set *dom)
624
2
{
625
2
  isl_bool ok;
626
2
  isl_map *ext_dom;
627
2
628
2
  ok = isl_map_compatible_range(map, dom);
629
2
  if (ok < 0)
630
0
    goto error;
631
2
  if (!ok)
632
2
    
isl_die0
(isl_set_get_ctx(dom), isl_error_invalid,
633
2
      "incompatible spaces", goto error);
634
2
  
635
2
  ext_dom = isl_map_universe(isl_map_get_space(map));
636
2
  ext_dom = isl_map_intersect_range(ext_dom, dom);
637
2
  return isl_map_subtract(map, ext_dom);
638
0
error:
639
0
  isl_map_free(map);
640
0
  isl_set_free(dom);
641
0
  return NULL;
642
2
}
643
644
__isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
645
  __isl_take isl_set *dom)
646
2
{
647
2
  return isl_map_align_params_map_map_and(map, dom, &map_subtract_range);
648
2
}
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
static isl_stat basic_map_is_empty_add(struct isl_diff_collector *dc,
661
          __isl_take isl_basic_map *bmap)
662
9.81k
{
663
9.81k
  struct isl_is_empty_diff_collector *edc;
664
9.81k
  edc = (struct isl_is_empty_diff_collector *)dc;
665
9.81k
666
9.81k
  edc->empty = 0;
667
9.81k
668
9.81k
  isl_basic_map_free(bmap);
669
9.81k
  return isl_stat_error;
670
9.81k
}
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
static isl_bool basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
676
  __isl_keep isl_map *map)
677
21.2k
{
678
21.2k
  isl_bool empty;
679
21.2k
  isl_stat r;
680
21.2k
  struct isl_is_empty_diff_collector edc;
681
21.2k
682
21.2k
  empty = isl_basic_map_plain_is_empty(bmap);
683
21.2k
  if (empty)
684
1
    return empty;
685
21.2k
686
21.2k
  edc.dc.add = &basic_map_is_empty_add;
687
21.2k
  edc.empty = isl_bool_true;
688
21.2k
  r = basic_map_collect_diff(isl_basic_map_copy(bmap),
689
21.2k
           isl_map_copy(map), &edc.dc);
690
21.2k
  if (!edc.empty)
691
9.81k
    return isl_bool_false;
692
11.4k
693
11.4k
  return r < 0 ? 
isl_bool_error0
: isl_bool_true;
694
11.4k
}
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
static isl_bool map_diff_is_empty(__isl_keep isl_map *map1,
700
  __isl_keep isl_map *map2)
701
19.7k
{
702
19.7k
  int i;
703
19.7k
  isl_bool is_empty = isl_bool_true;
704
19.7k
705
19.7k
  if (!map1 || !map2)
706
0
    return isl_bool_error;
707
19.7k
  
708
31.2k
  
for (i = 0; 19.7k
i < map1->n;
++i11.4k
) {
709
21.2k
    is_empty = basic_map_diff_is_empty(map1->p[i], map2);
710
21.2k
    if (is_empty < 0 || !is_empty)
711
9.81k
       break;
712
21.2k
  }
713
19.7k
714
19.7k
  return is_empty;
715
19.7k
}
716
717
/* Return true if "bmap" contains a single element.
718
 */
719
isl_bool isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
720
17.6k
{
721
17.6k
  if (!bmap)
722
0
    return isl_bool_error;
723
17.6k
  if (bmap->n_div)
724
1.92k
    return isl_bool_false;
725
15.6k
  if (bmap->n_ineq)
726
13.3k
    return isl_bool_false;
727
2.33k
  return bmap->n_eq == isl_basic_map_total_dim(bmap);
728
2.33k
}
729
730
/* Return true if "map" contains a single element.
731
 */
732
isl_bool isl_map_plain_is_singleton(__isl_keep isl_map *map)
733
20.1k
{
734
20.1k
  if (!map)
735
0
    return isl_bool_error;
736
20.1k
  if (map->n != 1)
737
2.54k
    return isl_bool_false;
738
17.6k
739
17.6k
  return isl_basic_map_plain_is_singleton(map->p[0]);
740
17.6k
}
741
742
/* Given a singleton basic map, extract the single element
743
 * as an isl_point.
744
 */
745
static __isl_give isl_point *singleton_extract_point(
746
  __isl_keep isl_basic_map *bmap)
747
404
{
748
404
  int j;
749
404
  unsigned dim;
750
404
  struct isl_vec *point;
751
404
  isl_int m;
752
404
753
404
  if (!bmap)
754
0
    return NULL;
755
404
756
404
  dim = isl_basic_map_total_dim(bmap);
757
404
  isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
758
404
  point = isl_vec_alloc(bmap->ctx, 1 + dim);
759
404
  if (!point)
760
0
    return NULL;
761
404
762
404
  isl_int_init(m);
763
404
764
404
  isl_int_set_si(point->el[0], 1);
765
892
  for (j = 0; j < bmap->n_eq; 
++j488
) {
766
488
    int i = dim - 1 - j;
767
488
    isl_assert(bmap->ctx,
768
488
        isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
769
488
        goto error);
770
488
    isl_assert(bmap->ctx,
771
488
        isl_int_is_one(bmap->eq[j][1 + i]) ||
772
488
        isl_int_is_negone(bmap->eq[j][1 + i]),
773
488
        goto error);
774
488
    isl_assert(bmap->ctx,
775
488
        isl_seq_first_non_zero(bmap->eq[j]+1+i+1, dim-i-1) == -1,
776
488
        goto error);
777
488
778
488
    isl_int_gcd(m, point->el[0], bmap->eq[j][1 + i]);
779
488
    isl_int_divexact(m, bmap->eq[j][1 + i], m);
780
488
    isl_int_abs(m, m);
781
488
    isl_seq_scale(point->el, point->el, m, 1 + i);
782
488
    isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
783
488
    isl_int_neg(m, m);
784
488
    isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
785
488
  }
786
404
787
404
  isl_int_clear(m);
788
404
  return isl_point_alloc(isl_basic_map_get_space(bmap), point);
789
0
error:
790
0
  isl_int_clear(m);
791
0
  isl_vec_free(point);
792
0
  return NULL;
793
404
}
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
static isl_bool map_is_singleton_subset(__isl_keep isl_map *map1,
800
  __isl_keep isl_map *map2)
801
404
{
802
404
  int i;
803
404
  isl_bool is_subset = isl_bool_false;
804
404
  struct isl_point *point;
805
404
806
404
  if (!map1 || !map2)
807
0
    return isl_bool_error;
808
404
  if (map1->n != 1)
809
404
    
isl_die0
(isl_map_get_ctx(map1), isl_error_invalid,
810
404
      "expecting single-disjunct input",
811
404
      return isl_bool_error);
812
404
813
404
  point = singleton_extract_point(map1->p[0]);
814
404
  if (!point)
815
0
    return isl_bool_error;
816
404
817
470
  
for (i = 0; 404
i < map2->n;
++i66
) {
818
426
    is_subset = isl_basic_map_contains_point(map2->p[i], point);
819
426
    if (is_subset)
820
360
      break;
821
426
  }
822
404
823
404
  isl_point_free(point);
824
404
  return is_subset;
825
404
}
826
827
static isl_bool map_is_subset(__isl_keep isl_map *map1,
828
  __isl_keep isl_map *map2)
829
45.0k
{
830
45.0k
  isl_bool is_subset = isl_bool_false;
831
45.0k
  isl_bool empty, single;
832
45.0k
  isl_bool rat1, rat2;
833
45.0k
834
45.0k
  if (!map1 || !map2)
835
0
    return isl_bool_error;
836
45.0k
837
45.0k
  if (!isl_map_has_equal_space(map1, map2))
838
159
    return isl_bool_false;
839
44.9k
840
44.9k
  empty = isl_map_is_empty(map1);
841
44.9k
  if (empty < 0)
842
0
    return isl_bool_error;
843
44.9k
  if (empty)
844
133
    return isl_bool_true;
845
44.7k
846
44.7k
  empty = isl_map_is_empty(map2);
847
44.7k
  if (empty < 0)
848
0
    return isl_bool_error;
849
44.7k
  if (empty)
850
17.6k
    return isl_bool_false;
851
27.1k
852
27.1k
  rat1 = isl_map_has_rational(map1);
853
27.1k
  rat2 = isl_map_has_rational(map2);
854
27.1k
  if (rat1 < 0 || rat2 < 0)
855
0
    return isl_bool_error;
856
27.1k
  if (rat1 && 
!rat214
)
857
2
    return isl_bool_false;
858
27.1k
859
27.1k
  if (isl_map_plain_is_universe(map2))
860
6.99k
    return isl_bool_true;
861
20.1k
862
20.1k
  single = isl_map_plain_is_singleton(map1);
863
20.1k
  if (single < 0)
864
0
    return isl_bool_error;
865
20.1k
  map2 = isl_map_compute_divs(isl_map_copy(map2));
866
20.1k
  if (single) {
867
404
    is_subset = map_is_singleton_subset(map1, map2);
868
404
    isl_map_free(map2);
869
404
    return is_subset;
870
404
  }
871
19.7k
  is_subset = map_diff_is_empty(map1, map2);
872
19.7k
  isl_map_free(map2);
873
19.7k
874
19.7k
  return is_subset;
875
19.7k
}
876
877
isl_bool isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
878
45.0k
{
879
45.0k
  return isl_map_align_params_map_map_and_test(map1, map2,
880
45.0k
              &map_is_subset);
881
45.0k
}
882
883
isl_bool isl_set_is_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
884
24.8k
{
885
24.8k
  return isl_map_is_subset(set_to_map(set1), set_to_map(set2));
886
24.8k
}
887
888
__isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map)
889
6.69k
{
890
6.69k
  int i;
891
6.69k
  struct isl_subtract_diff_collector sdc;
892
6.69k
  sdc.dc.add = &basic_map_subtract_add;
893
6.69k
894
6.69k
  if (!map)
895
0
    return NULL;
896
6.69k
  if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
897
6.69k
    
return map3.57k
;
898
3.12k
  if (map->n <= 1)
899
2.87k
    return map;
900
252
901
252
  map = isl_map_compute_divs(map);
902
252
  map = isl_map_remove_empty_parts(map);
903
252
904
252
  if (!map || map->n <= 1)
905
0
    return map;
906
252
907
252
  sdc.diff = isl_map_from_basic_map(isl_basic_map_copy(map->p[0]));
908
252
909
682
  for (i = 1; i < map->n; 
++i430
) {
910
430
    struct isl_basic_map *bmap = isl_basic_map_copy(map->p[i]);
911
430
    struct isl_map *copy = isl_map_copy(sdc.diff);
912
430
    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
0
    }
917
430
  }
918
252
919
252
  isl_map_free(map);
920
252
921
252
  return sdc.diff;
922
252
}
923
924
__isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
925
6.66k
{
926
6.66k
  return set_from_map(isl_map_make_disjoint(set_to_map(set)));
927
6.66k
}
928
929
__isl_give isl_map *isl_map_complement(__isl_take isl_map *map)
930
6.50k
{
931
6.50k
  isl_map *universe;
932
6.50k
933
6.50k
  if (!map)
934
0
    return NULL;
935
6.50k
936
6.50k
  universe = isl_map_universe(isl_map_get_space(map));
937
6.50k
938
6.50k
  return isl_map_subtract(universe, map);
939
6.50k
}
940
941
__isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
942
6.50k
{
943
6.50k
  return isl_map_complement(set);
944
6.50k
}