Coverage Report

Created: 2017-06-23 12:40

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/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
226k
{
35
226k
  int i;
36
226k
37
226k
  isl_seq_cpy(v->el, c, 1 + dim);
38
226k
  isl_seq_clr(v->el + 1 + dim, v->size - (1 + dim));
39
226k
40
313k
  for (i = 0; 
i < n_div313k
;
++i87.0k
)
{87.0k
41
87.0k
    int pos = 1 + dim + div_map[i];
42
87.0k
    isl_int_add(v->el[pos], v->el[pos], c[1 + dim + i]);
43
87.0k
  }
44
226k
}
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
65.6k
{
52
65.6k
  int i;
53
65.6k
  unsigned dim;
54
65.6k
  unsigned tab_total;
55
65.6k
  unsigned bmap_total;
56
65.6k
  isl_vec *v;
57
65.6k
58
65.6k
  if (
!tab || 65.6k
!bmap65.6k
)
59
0
    return isl_stat_error;
60
65.6k
61
65.6k
  tab_total = isl_basic_map_total_dim(tab->bmap);
62
65.6k
  bmap_total = isl_basic_map_total_dim(bmap);
63
65.6k
  dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
64
65.6k
65
65.6k
  if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
66
0
    return isl_stat_error;
67
65.6k
68
65.6k
  v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
69
65.6k
  if (!v)
70
0
    return isl_stat_error;
71
65.6k
72
85.4k
  
for (i = 0; 65.6k
i < bmap->n_eq85.4k
;
++i19.7k
)
{22.4k
73
22.4k
    expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
74
22.4k
    if (isl_tab_add_ineq(tab, v->el) < 0)
75
0
      goto error;
76
22.4k
    isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
77
22.4k
    expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
78
22.4k
    if (isl_tab_add_ineq(tab, v->el) < 0)
79
0
      goto error;
80
22.4k
    isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
81
22.4k
    if (tab->empty)
82
2.69k
      break;
83
22.4k
  }
84
65.6k
85
181k
  
for (i = 0; 65.6k
i < bmap->n_ineq181k
;
++i115k
)
{142k
86
142k
    expand_constraint(v, dim, bmap->ineq[i], div_map, bmap->n_div);
87
142k
    if (isl_tab_add_ineq(tab, v->el) < 0)
88
0
      goto error;
89
142k
    
if (142k
tab->empty142k
)
90
26.9k
      break;
91
142k
  }
92
65.6k
93
65.6k
  isl_vec_free(v);
94
65.6k
  return isl_stat_ok;
95
0
error:
96
0
  isl_vec_free(v);
97
0
  return isl_stat_error;
98
65.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
39.2k
{
112
39.2k
  unsigned dim;
113
39.2k
  unsigned tab_total;
114
39.2k
  unsigned bmap_total;
115
39.2k
  isl_vec *v;
116
39.2k
  isl_stat r;
117
39.2k
118
39.2k
  if (
!tab || 39.2k
!bmap39.2k
)
119
0
    return isl_stat_error;
120
39.2k
121
39.2k
  tab_total = isl_basic_map_total_dim(tab->bmap);
122
39.2k
  bmap_total = isl_basic_map_total_dim(bmap);
123
39.2k
  dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
124
39.2k
125
39.2k
  v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
126
39.2k
  if (!v)
127
0
    return isl_stat_error;
128
39.2k
129
39.2k
  
if (39.2k
c < 2 * bmap->n_eq39.2k
)
{8.14k
130
8.14k
    if ((c % 2) != oppose)
131
4.26k
      isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
132
4.26k
          1 + bmap_total);
133
8.14k
    if (oppose)
134
6.06k
      isl_int_sub_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
135
8.14k
    expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap->n_div);
136
8.14k
    r = isl_tab_add_ineq(tab, v->el);
137
8.14k
    if (oppose)
138
6.06k
      isl_int_add_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
139
8.14k
    if ((c % 2) != oppose)
140
4.26k
      isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
141
4.26k
          1 + bmap_total);
142
31.0k
  } else {
143
31.0k
    c -= 2 * bmap->n_eq;
144
31.0k
    if (
oppose31.0k
)
{25.9k
145
25.9k
      isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
146
25.9k
          1 + bmap_total);
147
25.9k
      isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
148
25.9k
    }
149
31.0k
    expand_constraint(v, dim, bmap->ineq[c], div_map, bmap->n_div);
150
31.0k
    r = isl_tab_add_ineq(tab, v->el);
151
31.0k
    if (
oppose31.0k
)
{25.9k
152
25.9k
      isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
153
25.9k
      isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
154
25.9k
          1 + bmap_total);
155
25.9k
    }
156
31.0k
  }
157
39.2k
158
39.2k
  isl_vec_free(v);
159
39.2k
  return r;
160
39.2k
}
161
162
static isl_stat tab_add_divs(struct isl_tab *tab,
163
  __isl_keep isl_basic_map *bmap, int **div_map)
164
65.6k
{
165
65.6k
  int i, j;
166
65.6k
  struct isl_vec *vec;
167
65.6k
  unsigned total;
168
65.6k
  unsigned dim;
169
65.6k
170
65.6k
  if (!bmap)
171
0
    return isl_stat_error;
172
65.6k
  
if (65.6k
!bmap->n_div65.6k
)
173
57.9k
    return isl_stat_ok;
174
65.6k
175
7.73k
  
if (7.73k
!*div_map7.73k
)
176
5.34k
    
*div_map = 5.34k
isl_alloc_array5.34k
(bmap->ctx, int, bmap->n_div);
177
7.73k
  if (!*div_map)
178
0
    return isl_stat_error;
179
7.73k
180
7.73k
  total = isl_basic_map_total_dim(tab->bmap);
181
7.73k
  dim = total - tab->bmap->n_div;
182
7.73k
  vec = isl_vec_alloc(bmap->ctx, 2 + total + bmap->n_div);
183
7.73k
  if (!vec)
184
0
    return isl_stat_error;
185
7.73k
186
25.3k
  
for (i = 0; 7.73k
i < bmap->n_div25.3k
;
++i17.5k
)
{17.5k
187
17.5k
    isl_seq_cpy(vec->el, bmap->div[i], 2 + dim);
188
17.5k
    isl_seq_clr(vec->el + 2 + dim, tab->bmap->n_div);
189
35.6k
    for (j = 0; 
j < i35.6k
;
++j18.1k
)
190
18.1k
      isl_int_set(vec->el[2 + dim + (*div_map)[j]],
191
17.5k
          bmap->div[i][2 + dim + j]);
192
55.9k
    for (j = 0; 
j < tab->bmap->n_div55.9k
;
++j38.4k
)
193
51.7k
      
if (51.7k
isl_seq_eq(tab->bmap->div[j],51.7k
194
51.7k
          vec->el, 2 + dim + tab->bmap->n_div))
195
13.2k
        break;
196
17.5k
    (*div_map)[i] = j;
197
17.5k
    if (
j == tab->bmap->n_div17.5k
)
{4.29k
198
4.29k
      vec->size = 2 + dim + tab->bmap->n_div;
199
4.29k
      if (isl_tab_add_div(tab, vec) < 0)
200
0
        goto error;
201
4.29k
    }
202
17.5k
  }
203
7.73k
204
7.73k
  isl_vec_free(vec);
205
7.73k
206
7.73k
  return isl_stat_ok;
207
0
error:
208
0
  isl_vec_free(vec);
209
0
210
0
  return isl_stat_error;
211
7.73k
}
212
213
/* Freeze all constraints of tableau tab.
214
 */
215
static int tab_freeze_constraints(struct isl_tab *tab)
216
65.6k
{
217
65.6k
  int i;
218
65.6k
219
429k
  for (i = 0; 
i < tab->n_con429k
;
++i363k
)
220
363k
    
if (363k
isl_tab_freeze_constraint(tab, i) < 0363k
)
221
0
      return -1;
222
65.6k
223
65.6k
  return 0;
224
65.6k
}
225
226
/* Check for redundant constraints starting at offset.
227
 * Put the indices of the redundant constraints in index
228
 * and return the number of redundant constraints.
229
 */
230
static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
231
  int offset, int **index)
232
38.1k
{
233
38.1k
  int i, n;
234
38.1k
  int n_test = tab->n_con - offset;
235
38.1k
236
38.1k
  if (isl_tab_detect_redundant(tab) < 0)
237
0
    return -1;
238
38.1k
239
38.1k
  
if (38.1k
n_test == 038.1k
)
240
1.31k
    return 0;
241
36.8k
  
if (36.8k
!*index36.8k
)
242
36.3k
    
*index = 36.3k
isl_alloc_array36.3k
(ctx, int, n_test);
243
36.8k
  if (!*index)
244
0
    return -1;
245
36.8k
246
156k
  
for (n = 0, i = 0; 36.8k
i < n_test156k
;
++i120k
)
{120k
247
120k
    int r;
248
120k
    r = isl_tab_is_redundant(tab, offset + i);
249
120k
    if (r < 0)
250
0
      return -1;
251
120k
    
if (120k
r120k
)
252
81.6k
      continue;
253
38.5k
    (*index)[n++] = i;
254
38.5k
  }
255
36.8k
256
36.8k
  return n;
257
36.8k
}
258
259
/* basic_map_collect_diff calls add on each of the pieces of
260
 * the set difference between bmap and map until the add method
261
 * return a negative value.
262
 */
263
struct isl_diff_collector {
264
  isl_stat (*add)(struct isl_diff_collector *dc,
265
        __isl_take isl_basic_map *bmap);
266
};
267
268
/* Compute the set difference between bmap and map and call
269
 * dc->add on each of the piece until this function returns
270
 * a negative value.
271
 * Return 0 on success and -1 on error.  dc->add returning
272
 * a negative value is treated as an error, but the calling
273
 * function can interpret the results based on the state of dc.
274
 *
275
 * Assumes that map has known divs.
276
 *
277
 * The difference is computed by a backtracking algorithm.
278
 * Each level corresponds to a basic map in "map".
279
 * When a node in entered for the first time, we check
280
 * if the corresonding basic map intersects the current piece
281
 * of "bmap".  If not, we move to the next level.
282
 * Otherwise, we split the current piece into as many
283
 * pieces as there are non-redundant constraints of the current
284
 * basic map in the intersection.  Each of these pieces is
285
 * handled by a child of the current node.
286
 * In particular, if there are n non-redundant constraints,
287
 * then for each 0 <= i < n, a piece is cut off by adding
288
 * constraints 0 <= j < i and adding the opposite of constraint i.
289
 * If there are no non-redundant constraints, meaning that the current
290
 * piece is a subset of the current basic map, then we simply backtrack.
291
 *
292
 * In the leaves, we check if the remaining piece has any integer points
293
 * and if so, pass it along to dc->add.  As a special case, if nothing
294
 * has been removed when we end up in a leaf, we simply pass along
295
 * the original basic map.
296
 */
297
static isl_stat basic_map_collect_diff(__isl_take isl_basic_map *bmap,
298
  __isl_take isl_map *map, struct isl_diff_collector *dc)
299
36.1k
{
300
36.1k
  int i;
301
36.1k
  int modified;
302
36.1k
  int level;
303
36.1k
  int init;
304
36.1k
  isl_bool empty;
305
36.1k
  isl_ctx *ctx;
306
36.1k
  struct isl_tab *tab = NULL;
307
36.1k
  struct isl_tab_undo **snap = NULL;
308
36.1k
  int *k = NULL;
309
36.1k
  int *n = NULL;
310
36.1k
  int **index = NULL;
311
36.1k
  int **div_map = NULL;
312
36.1k
313
36.1k
  empty = isl_basic_map_is_empty(bmap);
314
36.1k
  if (
empty36.1k
)
{0
315
0
    isl_basic_map_free(bmap);
316
0
    isl_map_free(map);
317
0
    return empty < 0 ? 
isl_stat_error0
:
isl_stat_ok0
;
318
0
  }
319
36.1k
320
36.1k
  bmap = isl_basic_map_cow(bmap);
321
36.1k
  map = isl_map_cow(map);
322
36.1k
323
36.1k
  if (
!bmap || 36.1k
!map36.1k
)
324
0
    goto error;
325
36.1k
326
36.1k
  ctx = map->ctx;
327
36.1k
  snap = isl_alloc_array(map->ctx, struct isl_tab_undo *, map->n);
328
36.1k
  k = isl_alloc_array(map->ctx, int, map->n);
329
36.1k
  n = isl_alloc_array(map->ctx, int, map->n);
330
36.1k
  index = isl_calloc_array(map->ctx, int *, map->n);
331
36.1k
  div_map = isl_calloc_array(map->ctx, int *, map->n);
332
36.1k
  if (
!snap || 36.1k
!k36.1k
||
!n36.1k
||
!index36.1k
||
!div_map36.1k
)
333
0
    goto error;
334
36.1k
335
36.1k
  bmap = isl_basic_map_order_divs(bmap);
336
36.1k
  map = isl_map_order_divs(map);
337
36.1k
338
36.1k
  tab = isl_tab_from_basic_map(bmap, 1);
339
36.1k
  if (!tab)
340
0
    goto error;
341
36.1k
342
36.1k
  modified = 0;
343
36.1k
  level = 0;
344
36.1k
  init = 1;
345
36.1k
346
158k
  while (
level >= 0158k
)
{135k
347
135k
    if (
level >= map->n135k
)
{30.0k
348
30.0k
      int empty;
349
30.0k
      struct isl_basic_map *bm;
350
30.0k
      if (
!modified30.0k
)
{5.71k
351
5.71k
        if (dc->add(dc, isl_basic_map_copy(bmap)) < 0)
352
1.16k
          goto error;
353
4.54k
        break;
354
5.71k
      }
355
24.3k
      bm = isl_basic_map_copy(tab->bmap);
356
24.3k
      bm = isl_basic_map_cow(bm);
357
24.3k
      bm = isl_basic_map_update_from_tab(bm, tab);
358
24.3k
      bm = isl_basic_map_simplify(bm);
359
24.3k
      bm = isl_basic_map_finalize(bm);
360
24.3k
      empty = isl_basic_map_is_empty(bm);
361
24.3k
      if (empty)
362
1.30k
        isl_basic_map_free(bm);
363
23.0k
      else 
if (23.0k
dc->add(dc, bm) < 023.0k
)
364
6.72k
        goto error;
365
17.6k
      
if (17.6k
empty < 017.6k
)
366
0
        goto error;
367
17.6k
      level--;
368
17.6k
      init = 0;
369
17.6k
      continue;
370
17.6k
    }
371
105k
    
if (105k
init105k
)
{65.6k
372
65.6k
      int offset;
373
65.6k
      struct isl_tab_undo *snap2;
374
65.6k
      snap2 = isl_tab_snap(tab);
375
65.6k
      if (tab_add_divs(tab, map->p[level],
376
65.6k
           &div_map[level]) < 0)
377
0
        goto error;
378
65.6k
      offset = tab->n_con;
379
65.6k
      snap[level] = isl_tab_snap(tab);
380
65.6k
      if (tab_freeze_constraints(tab) < 0)
381
0
        goto error;
382
65.6k
      
if (65.6k
tab_add_constraints(tab, map->p[level],65.6k
383
65.6k
            div_map[level]) < 0)
384
0
        goto error;
385
65.6k
      k[level] = 0;
386
65.6k
      n[level] = 0;
387
65.6k
      if (
tab->empty65.6k
)
{27.5k
388
27.5k
        if (isl_tab_rollback(tab, snap2) < 0)
389
0
          goto error;
390
27.5k
        level++;
391
27.5k
        continue;
392
27.5k
      }
393
38.1k
      modified = 1;
394
38.1k
      n[level] = n_non_redundant(ctx, tab, offset,
395
38.1k
                &index[level]);
396
38.1k
      if (n[level] < 0)
397
0
        goto error;
398
38.1k
      
if (38.1k
n[level] == 038.1k
)
{13.3k
399
13.3k
        level--;
400
13.3k
        init = 0;
401
13.3k
        continue;
402
13.3k
      }
403
24.8k
      
if (24.8k
isl_tab_rollback(tab, snap[level]) < 024.8k
)
404
0
        goto error;
405
24.8k
      
if (24.8k
tab_add_constraint(tab, map->p[level],24.8k
406
24.8k
          div_map[level], index[level][0], 1) < 0)
407
0
        goto error;
408
24.8k
      level++;
409
24.8k
      continue;
410
39.5k
    } else {
411
39.5k
      if (
k[level] + 1 >= n[level]39.5k
)
{32.3k
412
32.3k
        level--;
413
32.3k
        continue;
414
32.3k
      }
415
7.21k
      
if (7.21k
isl_tab_rollback(tab, snap[level]) < 07.21k
)
416
0
        goto error;
417
7.21k
      
if (7.21k
tab_add_constraint(tab, map->p[level],7.21k
418
7.21k
            div_map[level],
419
7.21k
            index[level][k[level]], 0) < 0)
420
0
        goto error;
421
7.21k
      snap[level] = isl_tab_snap(tab);
422
7.21k
      k[level]++;
423
7.21k
      if (tab_add_constraint(tab, map->p[level],
424
7.21k
            div_map[level],
425
7.21k
            index[level][k[level]], 1) < 0)
426
0
        goto error;
427
7.21k
      level++;
428
7.21k
      init = 1;
429
7.21k
      continue;
430
7.21k
    }
431
105k
  }
432
36.1k
433
28.2k
  isl_tab_free(tab);
434
28.2k
  free(snap);
435
28.2k
  free(n);
436
28.2k
  free(k);
437
74.9k
  for (i = 0; 
index && 74.9k
i < map->n74.9k
;
++i46.7k
)
438
46.7k
    free(index[i]);
439
28.2k
  free(index);
440
74.9k
  for (i = 0; 
div_map && 74.9k
i < map->n74.9k
;
++i46.7k
)
441
46.7k
    free(div_map[i]);
442
28.2k
  free(div_map);
443
28.2k
444
28.2k
  isl_basic_map_free(bmap);
445
28.2k
  isl_map_free(map);
446
28.2k
447
28.2k
  return isl_stat_ok;
448
7.89k
error:
449
7.89k
  isl_tab_free(tab);
450
7.89k
  free(snap);
451
7.89k
  free(n);
452
7.89k
  free(k);
453
22.3k
  for (i = 0; 
index && 22.3k
i < map->n22.3k
;
++i14.4k
)
454
14.4k
    free(index[i]);
455
7.89k
  free(index);
456
22.3k
  for (i = 0; 
div_map && 22.3k
i < map->n22.3k
;
++i14.4k
)
457
14.4k
    free(div_map[i]);
458
7.89k
  free(div_map);
459
7.89k
  isl_basic_map_free(bmap);
460
7.89k
  isl_map_free(map);
461
7.89k
  return isl_stat_error;
462
36.1k
}
463
464
/* A diff collector that actually collects all parts of the
465
 * set difference in the field diff.
466
 */
467
struct isl_subtract_diff_collector {
468
  struct isl_diff_collector dc;
469
  struct isl_map *diff;
470
};
471
472
/* isl_subtract_diff_collector callback.
473
 */
474
static isl_stat basic_map_subtract_add(struct isl_diff_collector *dc,
475
          __isl_take isl_basic_map *bmap)
476
20.8k
{
477
20.8k
  struct isl_subtract_diff_collector *sdc;
478
20.8k
  sdc = (struct isl_subtract_diff_collector *)dc;
479
20.8k
480
20.8k
  sdc->diff = isl_map_union_disjoint(sdc->diff,
481
20.8k
      isl_map_from_basic_map(bmap));
482
20.8k
483
20.8k
  return sdc->diff ? 
isl_stat_ok20.8k
:
isl_stat_error0
;
484
20.8k
}
485
486
/* Return the set difference between bmap and map.
487
 */
488
static __isl_give isl_map *basic_map_subtract(__isl_take isl_basic_map *bmap,
489
  __isl_take isl_map *map)
490
18.2k
{
491
18.2k
  struct isl_subtract_diff_collector sdc;
492
18.2k
  sdc.dc.add = &basic_map_subtract_add;
493
18.2k
  sdc.diff = isl_map_empty(isl_basic_map_get_space(bmap));
494
18.2k
  if (
basic_map_collect_diff(bmap, map, &sdc.dc) < 018.2k
)
{0
495
0
    isl_map_free(sdc.diff);
496
0
    sdc.diff = NULL;
497
0
  }
498
18.2k
  return sdc.diff;
499
18.2k
}
500
501
/* Return an empty map living in the same space as "map1" and "map2".
502
 */
503
static __isl_give isl_map *replace_pair_by_empty( __isl_take isl_map *map1,
504
  __isl_take isl_map *map2)
505
3.97k
{
506
3.97k
  isl_space *space;
507
3.97k
508
3.97k
  space = isl_map_get_space(map1);
509
3.97k
  isl_map_free(map1);
510
3.97k
  isl_map_free(map2);
511
3.97k
  return isl_map_empty(space);
512
3.97k
}
513
514
/* Return the set difference between map1 and map2.
515
 * (U_i A_i) \ (U_j B_j) is computed as U_i (A_i \ (U_j B_j))
516
 *
517
 * If "map1" and "map2" are obviously equal to each other,
518
 * then return an empty map in the same space.
519
 *
520
 * If "map1" and "map2" are disjoint, then simply return "map1".
521
 */
522
static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
523
  __isl_take isl_map *map2)
524
23.0k
{
525
23.0k
  int i;
526
23.0k
  int equal, disjoint;
527
23.0k
  struct isl_map *diff;
528
23.0k
529
23.0k
  if (
!map1 || 23.0k
!map223.0k
)
530
0
    goto error;
531
23.0k
532
23.0k
  
isl_assert23.0k
(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);23.0k
533
23.0k
534
23.0k
  equal = isl_map_plain_is_equal(map1, map2);
535
23.0k
  if (equal < 0)
536
0
    goto error;
537
23.0k
  
if (23.0k
equal23.0k
)
538
3.97k
    return replace_pair_by_empty(map1, map2);
539
23.0k
540
19.1k
  disjoint = isl_map_is_disjoint(map1, map2);
541
19.1k
  if (disjoint < 0)
542
1
    goto error;
543
19.1k
  
if (19.1k
disjoint19.1k
)
{10.0k
544
10.0k
    isl_map_free(map2);
545
10.0k
    return map1;
546
10.0k
  }
547
19.1k
548
9.06k
  map1 = isl_map_compute_divs(map1);
549
9.06k
  map2 = isl_map_compute_divs(map2);
550
9.06k
  if (
!map1 || 9.06k
!map29.06k
)
551
0
    goto error;
552
9.06k
553
9.06k
  map1 = isl_map_remove_empty_parts(map1);
554
9.06k
  map2 = isl_map_remove_empty_parts(map2);
555
9.06k
556
9.06k
  diff = isl_map_empty(isl_map_get_space(map1));
557
27.2k
  for (i = 0; 
i < map1->n27.2k
;
++i18.2k
)
{18.2k
558
18.2k
    struct isl_map *d;
559
18.2k
    d = basic_map_subtract(isl_basic_map_copy(map1->p[i]),
560
18.2k
               isl_map_copy(map2));
561
18.2k
    if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT))
562
7.58k
      diff = isl_map_union_disjoint(diff, d);
563
18.2k
    else
564
10.6k
      diff = isl_map_union(diff, d);
565
18.2k
  }
566
9.06k
567
9.06k
  isl_map_free(map1);
568
9.06k
  isl_map_free(map2);
569
9.06k
570
9.06k
  return diff;
571
1
error:
572
1
  isl_map_free(map1);
573
1
  isl_map_free(map2);
574
1
  return NULL;
575
9.06k
}
576
577
__isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
578
  __isl_take isl_map *map2)
579
23.0k
{
580
23.0k
  return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
581
23.0k
}
582
583
struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
584
16.1k
{
585
16.1k
  return set_from_map(isl_map_subtract(set_to_map(set1),
586
16.1k
              set_to_map(set2)));
587
16.1k
}
588
589
/* Remove the elements of "dom" from the domain of "map".
590
 */
591
static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
592
  __isl_take isl_set *dom)
593
2
{
594
2
  isl_bool ok;
595
2
  isl_map *ext_dom;
596
2
597
2
  ok = isl_map_compatible_domain(map, dom);
598
2
  if (ok < 0)
599
0
    goto error;
600
2
  
if (2
!ok2
)
601
0
    isl_die(isl_set_get_ctx(dom), isl_error_invalid,
602
2
      "incompatible spaces", goto error);
603
2
  
604
2
  ext_dom = isl_map_universe(isl_map_get_space(map));
605
2
  ext_dom = isl_map_intersect_domain(ext_dom, dom);
606
2
  return isl_map_subtract(map, ext_dom);
607
0
error:
608
0
  isl_map_free(map);
609
0
  isl_set_free(dom);
610
0
  return NULL;
611
2
}
612
613
__isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
614
  __isl_take isl_set *dom)
615
2
{
616
2
  return isl_map_align_params_map_map_and(map, dom, &map_subtract_domain);
617
2
}
618
619
/* Remove the elements of "dom" from the range of "map".
620
 */
621
static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
622
  __isl_take isl_set *dom)
623
2
{
624
2
  isl_bool ok;
625
2
  isl_map *ext_dom;
626
2
627
2
  ok = isl_map_compatible_range(map, dom);
628
2
  if (ok < 0)
629
0
    goto error;
630
2
  
if (2
!ok2
)
631
0
    isl_die(isl_set_get_ctx(dom), isl_error_invalid,
632
2
      "incompatible spaces", goto error);
633
2
  
634
2
  ext_dom = isl_map_universe(isl_map_get_space(map));
635
2
  ext_dom = isl_map_intersect_range(ext_dom, dom);
636
2
  return isl_map_subtract(map, ext_dom);
637
0
error:
638
0
  isl_map_free(map);
639
0
  isl_set_free(dom);
640
0
  return NULL;
641
2
}
642
643
__isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
644
  __isl_take isl_set *dom)
645
2
{
646
2
  return isl_map_align_params_map_map_and(map, dom, &map_subtract_range);
647
2
}
648
649
/* A diff collector that aborts as soon as its add function is called,
650
 * setting empty to 0.
651
 */
652
struct isl_is_empty_diff_collector {
653
  struct isl_diff_collector dc;
654
  isl_bool empty;
655
};
656
657
/* isl_is_empty_diff_collector callback.
658
 */
659
static isl_stat basic_map_is_empty_add(struct isl_diff_collector *dc,
660
          __isl_take isl_basic_map *bmap)
661
7.89k
{
662
7.89k
  struct isl_is_empty_diff_collector *edc;
663
7.89k
  edc = (struct isl_is_empty_diff_collector *)dc;
664
7.89k
665
7.89k
  edc->empty = 0;
666
7.89k
667
7.89k
  isl_basic_map_free(bmap);
668
7.89k
  return isl_stat_error;
669
7.89k
}
670
671
/* Check if bmap \ map is empty by computing this set difference
672
 * and breaking off as soon as the difference is known to be non-empty.
673
 */
674
static isl_bool basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
675
  __isl_keep isl_map *map)
676
16.8k
{
677
16.8k
  isl_bool empty;
678
16.8k
  isl_stat r;
679
16.8k
  struct isl_is_empty_diff_collector edc;
680
16.8k
681
16.8k
  empty = isl_basic_map_plain_is_empty(bmap);
682
16.8k
  if (empty)
683
1
    return empty;
684
16.8k
685
16.8k
  edc.dc.add = &basic_map_is_empty_add;
686
16.8k
  edc.empty = isl_bool_true;
687
16.8k
  r = basic_map_collect_diff(isl_basic_map_copy(bmap),
688
16.8k
           isl_map_copy(map), &edc.dc);
689
16.8k
  if (!edc.empty)
690
7.89k
    return isl_bool_false;
691
16.8k
692
8.99k
  
return r < 0 ? 8.99k
isl_bool_error0
:
isl_bool_true8.99k
;
693
16.8k
}
694
695
/* Check if map1 \ map2 is empty by checking if the set difference is empty
696
 * for each of the basic maps in map1.
697
 */
698
static isl_bool map_diff_is_empty(__isl_keep isl_map *map1,
699
  __isl_keep isl_map *map2)
700
15.8k
{
701
15.8k
  int i;
702
15.8k
  isl_bool is_empty = isl_bool_true;
703
15.8k
704
15.8k
  if (
!map1 || 15.8k
!map215.8k
)
705
0
    return isl_bool_error;
706
15.8k
  
707
24.8k
  
for (i = 0; 15.8k
i < map1->n24.8k
;
++i8.99k
)
{16.8k
708
16.8k
    is_empty = basic_map_diff_is_empty(map1->p[i], map2);
709
16.8k
    if (
is_empty < 0 || 16.8k
!is_empty16.8k
)
710
7.89k
       break;
711
16.8k
  }
712
15.8k
713
15.8k
  return is_empty;
714
15.8k
}
715
716
/* Return true if "bmap" contains a single element.
717
 */
718
isl_bool isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
719
14.5k
{
720
14.5k
  if (!bmap)
721
0
    return isl_bool_error;
722
14.5k
  
if (14.5k
bmap->n_div14.5k
)
723
1.68k
    return isl_bool_false;
724
12.8k
  
if (12.8k
bmap->n_ineq12.8k
)
725
10.8k
    return isl_bool_false;
726
2.04k
  return bmap->n_eq == isl_basic_map_total_dim(bmap);
727
12.8k
}
728
729
/* Return true if "map" contains a single element.
730
 */
731
isl_bool isl_map_plain_is_singleton(__isl_keep isl_map *map)
732
16.1k
{
733
16.1k
  if (!map)
734
0
    return isl_bool_error;
735
16.1k
  
if (16.1k
map->n != 116.1k
)
736
1.65k
    return isl_bool_false;
737
16.1k
738
14.5k
  return isl_basic_map_plain_is_singleton(map->p[0]);
739
16.1k
}
740
741
/* Given a singleton basic map, extract the single element
742
 * as an isl_point.
743
 */
744
static __isl_give isl_point *singleton_extract_point(
745
  __isl_keep isl_basic_map *bmap)
746
387
{
747
387
  int j;
748
387
  unsigned dim;
749
387
  struct isl_vec *point;
750
387
  isl_int m;
751
387
752
387
  if (!bmap)
753
0
    return NULL;
754
387
755
387
  dim = isl_basic_map_total_dim(bmap);
756
387
  isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
757
387
  point = isl_vec_alloc(bmap->ctx, 1 + dim);
758
387
  if (!point)
759
0
    return NULL;
760
387
761
387
  
isl_int_init387
(m);387
762
387
763
387
  isl_int_set_si(point->el[0], 1);
764
856
  for (j = 0; 
j < bmap->n_eq856
;
++j469
)
{469
765
469
    int i = dim - 1 - j;
766
469
    isl_assert(bmap->ctx,
767
469
        isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
768
469
        goto error);
769
469
    
isl_assert469
(bmap->ctx,469
770
469
        isl_int_is_one(bmap->eq[j][1 + i]) ||
771
469
        isl_int_is_negone(bmap->eq[j][1 + i]),
772
469
        goto error);
773
469
    
isl_assert469
(bmap->ctx,469
774
469
        isl_seq_first_non_zero(bmap->eq[j]+1+i+1, dim-i-1) == -1,
775
469
        goto error);
776
469
777
469
    
isl_int_gcd469
(m, point->el[0], bmap->eq[j][1 + i]);469
778
469
    isl_int_divexact(m, bmap->eq[j][1 + i], m);
779
469
    isl_int_abs(m, m);
780
469
    isl_seq_scale(point->el, point->el, m, 1 + i);
781
469
    isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
782
469
    isl_int_neg(m, m);
783
469
    isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
784
469
  }
785
387
786
387
  
isl_int_clear387
(m);387
787
387
  return isl_point_alloc(isl_basic_map_get_space(bmap), point);
788
0
error:
789
0
  isl_int_clear(m);
790
0
  isl_vec_free(point);
791
0
  return NULL;
792
387
}
793
794
/* Return isl_bool_true if the singleton map "map1" is a subset of "map2",
795
 * i.e., if the single element of "map1" is also an element of "map2".
796
 * Assumes "map2" has known divs.
797
 */
798
static isl_bool map_is_singleton_subset(__isl_keep isl_map *map1,
799
  __isl_keep isl_map *map2)
800
387
{
801
387
  int i;
802
387
  isl_bool is_subset = isl_bool_false;
803
387
  struct isl_point *point;
804
387
805
387
  if (
!map1 || 387
!map2387
)
806
0
    return isl_bool_error;
807
387
  
if (387
map1->n != 1387
)
808
0
    isl_die(isl_map_get_ctx(map1), isl_error_invalid,
809
387
      "expecting single-disjunct input",
810
387
      return isl_bool_error);
811
387
812
387
  point = singleton_extract_point(map1->p[0]);
813
387
  if (!point)
814
0
    return isl_bool_error;
815
387
816
453
  
for (i = 0; 387
i < map2->n453
;
++i66
)
{409
817
409
    is_subset = isl_basic_map_contains_point(map2->p[i], point);
818
409
    if (is_subset)
819
343
      break;
820
409
  }
821
387
822
387
  isl_point_free(point);
823
387
  return is_subset;
824
387
}
825
826
static isl_bool map_is_subset(__isl_keep isl_map *map1,
827
  __isl_keep isl_map *map2)
828
37.0k
{
829
37.0k
  isl_bool is_subset = isl_bool_false;
830
37.0k
  isl_bool empty, single;
831
37.0k
  isl_bool rat1, rat2;
832
37.0k
833
37.0k
  if (
!map1 || 37.0k
!map237.0k
)
834
0
    return isl_bool_error;
835
37.0k
836
37.0k
  
if (37.0k
!isl_map_has_equal_space(map1, map2)37.0k
)
837
117
    return isl_bool_false;
838
37.0k
839
36.8k
  empty = isl_map_is_empty(map1);
840
36.8k
  if (empty < 0)
841
0
    return isl_bool_error;
842
36.8k
  
if (36.8k
empty36.8k
)
843
128
    return isl_bool_true;
844
36.8k
845
36.7k
  empty = isl_map_is_empty(map2);
846
36.7k
  if (empty < 0)
847
0
    return isl_bool_error;
848
36.7k
  
if (36.7k
empty36.7k
)
849
14.3k
    return isl_bool_false;
850
36.7k
851
22.3k
  rat1 = isl_map_has_rational(map1);
852
22.3k
  rat2 = isl_map_has_rational(map2);
853
22.3k
  if (
rat1 < 0 || 22.3k
rat2 < 022.3k
)
854
0
    return isl_bool_error;
855
22.3k
  
if (22.3k
rat1 && 22.3k
!rat214
)
856
2
    return isl_bool_false;
857
22.3k
858
22.3k
  
if (22.3k
isl_map_plain_is_universe(map2)22.3k
)
859
6.19k
    return isl_bool_true;
860
22.3k
861
16.1k
  single = isl_map_plain_is_singleton(map1);
862
16.1k
  if (single < 0)
863
0
    return isl_bool_error;
864
16.1k
  map2 = isl_map_compute_divs(isl_map_copy(map2));
865
16.1k
  if (
single16.1k
)
{387
866
387
    is_subset = map_is_singleton_subset(map1, map2);
867
387
    isl_map_free(map2);
868
387
    return is_subset;
869
387
  }
870
15.8k
  is_subset = map_diff_is_empty(map1, map2);
871
15.8k
  isl_map_free(map2);
872
15.8k
873
15.8k
  return is_subset;
874
16.1k
}
875
876
isl_bool isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
877
37.0k
{
878
37.0k
  return isl_map_align_params_map_map_and_test(map1, map2,
879
37.0k
              &map_is_subset);
880
37.0k
}
881
882
isl_bool isl_set_is_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
883
21.1k
{
884
21.1k
  return isl_map_is_subset(set_to_map(set1), set_to_map(set2));
885
21.1k
}
886
887
__isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map)
888
5.38k
{
889
5.38k
  int i;
890
5.38k
  struct isl_subtract_diff_collector sdc;
891
5.38k
  sdc.dc.add = &basic_map_subtract_add;
892
5.38k
893
5.38k
  if (!map)
894
0
    return NULL;
895
5.38k
  
if (5.38k
ISL_F_ISSET5.38k
(map, ISL_MAP_DISJOINT))
896
2.73k
    return map;
897
2.65k
  
if (2.65k
map->n <= 12.65k
)
898
2.31k
    return map;
899
2.65k
900
342
  map = isl_map_compute_divs(map);
901
342
  map = isl_map_remove_empty_parts(map);
902
342
903
342
  if (
!map || 342
map->n <= 1342
)
904
0
    return map;
905
342
906
342
  sdc.diff = isl_map_from_basic_map(isl_basic_map_copy(map->p[0]));
907
342
908
1.40k
  for (i = 1; 
i < map->n1.40k
;
++i1.06k
)
{1.06k
909
1.06k
    struct isl_basic_map *bmap = isl_basic_map_copy(map->p[i]);
910
1.06k
    struct isl_map *copy = isl_map_copy(sdc.diff);
911
1.06k
    if (
basic_map_collect_diff(bmap, copy, &sdc.dc) < 01.06k
)
{0
912
0
      isl_map_free(sdc.diff);
913
0
      sdc.diff = NULL;
914
0
      break;
915
0
    }
916
1.06k
  }
917
342
918
342
  isl_map_free(map);
919
342
920
342
  return sdc.diff;
921
342
}
922
923
__isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
924
5.37k
{
925
5.37k
  return set_from_map(isl_map_make_disjoint(set_to_map(set)));
926
5.37k
}
927
928
__isl_give isl_map *isl_map_complement(__isl_take isl_map *map)
929
5.44k
{
930
5.44k
  isl_map *universe;
931
5.44k
932
5.44k
  if (!map)
933
0
    return NULL;
934
5.44k
935
5.44k
  universe = isl_map_universe(isl_map_get_space(map));
936
5.44k
937
5.44k
  return isl_map_subtract(universe, map);
938
5.44k
}
939
940
__isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
941
5.44k
{
942
5.44k
  return isl_map_complement(set);
943
5.44k
}