Line data Source code
1 : /*
2 : * Copyright 2008-2009 Katholieke Universiteit Leuven
3 : * Copyright 2010 INRIA Saclay
4 : * Copyright 2012-2014 Ecole Normale Superieure
5 : * Copyright 2014 INRIA Rocquencourt
6 : * Copyright 2016 INRIA Paris
7 : * Copyright 2016 Sven Verdoolaege
8 : *
9 : * Use of this software is governed by the MIT license
10 : *
11 : * Written by Sven Verdoolaege, K.U.Leuven, Departement
12 : * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
13 : * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
14 : * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
15 : * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
16 : * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
17 : * B.P. 105 - 78153 Le Chesnay, France
18 : * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
19 : * CS 42112, 75589 Paris Cedex 12, France
20 : */
21 :
22 : #include <string.h>
23 : #include <isl_ctx_private.h>
24 : #include <isl_map_private.h>
25 : #include <isl_blk.h>
26 : #include <isl/id.h>
27 : #include <isl/constraint.h>
28 : #include "isl_space_private.h"
29 : #include "isl_equalities.h"
30 : #include <isl_lp_private.h>
31 : #include <isl_seq.h>
32 : #include <isl/set.h>
33 : #include <isl/map.h>
34 : #include <isl_reordering.h>
35 : #include "isl_sample.h"
36 : #include <isl_sort.h>
37 : #include "isl_tab.h"
38 : #include <isl/vec.h>
39 : #include <isl_mat_private.h>
40 : #include <isl_vec_private.h>
41 : #include <isl_dim_map.h>
42 : #include <isl_local_space_private.h>
43 : #include <isl_aff_private.h>
44 : #include <isl_options_private.h>
45 : #include <isl_morph.h>
46 : #include <isl_val_private.h>
47 :
48 : #include <bset_to_bmap.c>
49 : #include <bset_from_bmap.c>
50 : #include <set_to_map.c>
51 : #include <set_from_map.c>
52 :
53 : #undef TYPE
54 : #define TYPE isl_basic_map
55 : #include "has_single_reference_templ.c"
56 :
57 7006220366 : static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
58 : {
59 7006220366 : switch (type) {
60 112944 : case isl_dim_param: return dim->nparam;
61 0 : case isl_dim_in: return dim->n_in;
62 7006107422 : case isl_dim_out: return dim->n_out;
63 0 : case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
64 0 : default: return 0;
65 : }
66 : }
67 :
68 0 : static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
69 : {
70 0 : switch (type) {
71 0 : case isl_dim_param: return 1;
72 0 : case isl_dim_in: return 1 + dim->nparam;
73 0 : case isl_dim_out: return 1 + dim->nparam + dim->n_in;
74 0 : default: return 0;
75 : }
76 : }
77 :
78 >13075*10^7 : unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
79 : enum isl_dim_type type)
80 : {
81 >13075*10^7 : if (!bmap)
82 0 : return 0;
83 >13075*10^7 : switch (type) {
84 0 : case isl_dim_cst: return 1;
85 : case isl_dim_param:
86 : case isl_dim_in:
87 >12320*10^7 : case isl_dim_out: return isl_space_dim(bmap->dim, type);
88 7547212309 : case isl_dim_div: return bmap->n_div;
89 1149450 : case isl_dim_all: return isl_basic_map_total_dim(bmap);
90 0 : default: return 0;
91 : }
92 : }
93 :
94 : /* Return the space of "map".
95 : */
96 115239480 : __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
97 : {
98 115239480 : return map ? map->dim : NULL;
99 : }
100 :
101 0 : unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
102 : {
103 0 : return map ? n(map->dim, type) : 0;
104 : }
105 :
106 7006220366 : unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
107 : {
108 7006220366 : return set ? n(set->dim, type) : 0;
109 : }
110 :
111 18906741 : unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
112 : enum isl_dim_type type)
113 : {
114 : isl_space *space;
115 :
116 18906741 : if (!bmap)
117 0 : return 0;
118 :
119 18906741 : space = bmap->dim;
120 18906741 : switch (type) {
121 0 : case isl_dim_cst: return 0;
122 0 : case isl_dim_param: return 1;
123 0 : case isl_dim_in: return 1 + space->nparam;
124 17789123 : case isl_dim_out: return 1 + space->nparam + space->n_in;
125 2235236 : case isl_dim_div: return 1 + space->nparam + space->n_in +
126 1117618 : space->n_out;
127 0 : default: return 0;
128 : }
129 : }
130 :
131 0 : unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
132 : enum isl_dim_type type)
133 : {
134 0 : return isl_basic_map_offset(bset, type);
135 : }
136 :
137 0 : static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
138 : {
139 0 : return pos(map->dim, type);
140 : }
141 :
142 12550787499 : unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
143 : enum isl_dim_type type)
144 : {
145 12550787499 : return isl_basic_map_dim(bset, type);
146 : }
147 :
148 7078525128 : unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
149 : {
150 7078525128 : return isl_basic_set_dim(bset, isl_dim_set);
151 : }
152 :
153 5382797331 : unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
154 : {
155 5382797331 : return isl_basic_set_dim(bset, isl_dim_param);
156 : }
157 :
158 2204713082 : unsigned isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
159 : {
160 2204713082 : if (!bset)
161 0 : return 0;
162 2204713082 : return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
163 : }
164 :
165 7005994478 : unsigned isl_set_n_dim(__isl_keep isl_set *set)
166 : {
167 7005994478 : return isl_set_dim(set, isl_dim_set);
168 : }
169 :
170 0 : unsigned isl_set_n_param(__isl_keep isl_set *set)
171 : {
172 0 : return isl_set_dim(set, isl_dim_param);
173 : }
174 :
175 0 : unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap)
176 : {
177 0 : return bmap ? bmap->dim->n_in : 0;
178 : }
179 :
180 0 : unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap)
181 : {
182 0 : return bmap ? bmap->dim->n_out : 0;
183 : }
184 :
185 0 : unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap)
186 : {
187 0 : return bmap ? bmap->dim->nparam : 0;
188 : }
189 :
190 0 : unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap)
191 : {
192 0 : return bmap ? bmap->n_div : 0;
193 : }
194 :
195 >26899*10^7 : unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
196 : {
197 >26899*10^7 : return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
198 : }
199 :
200 0 : unsigned isl_map_n_in(__isl_keep const isl_map *map)
201 : {
202 0 : return map ? map->dim->n_in : 0;
203 : }
204 :
205 0 : unsigned isl_map_n_out(__isl_keep const isl_map *map)
206 : {
207 0 : return map ? map->dim->n_out : 0;
208 : }
209 :
210 0 : unsigned isl_map_n_param(__isl_keep const isl_map *map)
211 : {
212 0 : return map ? map->dim->nparam : 0;
213 : }
214 :
215 : /* Return the number of equality constraints in the description of "bmap".
216 : * Return -1 on error.
217 : */
218 8206588573 : int isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
219 : {
220 8206588573 : if (!bmap)
221 0 : return -1;
222 8206588573 : return bmap->n_eq;
223 : }
224 :
225 : /* Return the number of equality constraints in the description of "bset".
226 : * Return -1 on error.
227 : */
228 1211723574 : int isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
229 : {
230 1211723574 : return isl_basic_map_n_equality(bset_to_bmap(bset));
231 : }
232 :
233 : /* Return the number of inequality constraints in the description of "bmap".
234 : * Return -1 on error.
235 : */
236 9350011720 : int isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
237 : {
238 9350011720 : if (!bmap)
239 0 : return -1;
240 9350011720 : return bmap->n_ineq;
241 : }
242 :
243 : /* Return the number of inequality constraints in the description of "bset".
244 : * Return -1 on error.
245 : */
246 0 : int isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
247 : {
248 0 : return isl_basic_map_n_inequality(bset_to_bmap(bset));
249 : }
250 :
251 : /* Do "bmap1" and "bmap2" have the same parameters?
252 : */
253 110183997 : static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
254 : __isl_keep isl_basic_map *bmap2)
255 : {
256 : isl_space *space1, *space2;
257 :
258 110183997 : space1 = isl_basic_map_peek_space(bmap1);
259 110183997 : space2 = isl_basic_map_peek_space(bmap2);
260 110183997 : return isl_space_has_equal_params(space1, space2);
261 : }
262 :
263 : /* Do "map1" and "map2" have the same parameters?
264 : */
265 55124743 : isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
266 : __isl_keep isl_map *map2)
267 : {
268 : isl_space *space1, *space2;
269 :
270 55124743 : space1 = isl_map_peek_space(map1);
271 55124743 : space2 = isl_map_peek_space(map2);
272 55124743 : return isl_space_has_equal_params(space1, space2);
273 : }
274 :
275 : /* Do "map" and "set" have the same parameters?
276 : */
277 0 : static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
278 : __isl_keep isl_set *set)
279 : {
280 0 : return isl_map_has_equal_params(map, set_to_map(set));
281 : }
282 :
283 0 : isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
284 : __isl_keep isl_set *set)
285 : {
286 : isl_bool m;
287 0 : if (!map || !set)
288 0 : return isl_bool_error;
289 0 : m = isl_map_has_equal_params(map, set_to_map(set));
290 0 : if (m < 0 || !m)
291 0 : return m;
292 0 : return isl_space_tuple_is_equal(map->dim, isl_dim_in,
293 : set->dim, isl_dim_set);
294 : }
295 :
296 0 : isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
297 : __isl_keep isl_basic_set *bset)
298 : {
299 : isl_bool m;
300 0 : if (!bmap || !bset)
301 0 : return isl_bool_error;
302 0 : m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
303 0 : if (m < 0 || !m)
304 0 : return m;
305 0 : return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
306 : bset->dim, isl_dim_set);
307 : }
308 :
309 0 : isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
310 : __isl_keep isl_set *set)
311 : {
312 : isl_bool m;
313 0 : if (!map || !set)
314 0 : return isl_bool_error;
315 0 : m = isl_map_has_equal_params(map, set_to_map(set));
316 0 : if (m < 0 || !m)
317 0 : return m;
318 0 : return isl_space_tuple_is_equal(map->dim, isl_dim_out,
319 : set->dim, isl_dim_set);
320 : }
321 :
322 0 : isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
323 : __isl_keep isl_basic_set *bset)
324 : {
325 : isl_bool m;
326 0 : if (!bmap || !bset)
327 0 : return isl_bool_error;
328 0 : m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
329 0 : if (m < 0 || !m)
330 0 : return m;
331 0 : return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
332 : bset->dim, isl_dim_set);
333 : }
334 :
335 18208849539 : isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
336 : {
337 18208849539 : return bmap ? bmap->ctx : NULL;
338 : }
339 :
340 43381213 : isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
341 : {
342 43381213 : return bset ? bset->ctx : NULL;
343 : }
344 :
345 1208338725 : isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
346 : {
347 1208338725 : return map ? map->ctx : NULL;
348 : }
349 :
350 225888 : isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
351 : {
352 225888 : return set ? set->ctx : NULL;
353 : }
354 :
355 : /* Return the space of "bmap".
356 : */
357 2994676980 : __isl_keep isl_space *isl_basic_map_peek_space(
358 : __isl_keep const isl_basic_map *bmap)
359 : {
360 2994676980 : return bmap ? bmap->dim : NULL;
361 : }
362 :
363 : /* Return the space of "bset".
364 : */
365 0 : __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
366 : {
367 0 : return isl_basic_map_peek_space(bset_to_bmap(bset));
368 : }
369 :
370 662155962 : __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
371 : {
372 662155962 : return isl_space_copy(isl_basic_map_peek_space(bmap));
373 : }
374 :
375 7938506 : __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
376 : {
377 7938506 : return isl_basic_map_get_space(bset_to_bmap(bset));
378 : }
379 :
380 : /* Extract the divs in "bmap" as a matrix.
381 : */
382 1117618 : __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
383 : {
384 : int i;
385 : isl_ctx *ctx;
386 : isl_mat *div;
387 : unsigned total;
388 : unsigned cols;
389 :
390 1117618 : if (!bmap)
391 0 : return NULL;
392 :
393 1117618 : ctx = isl_basic_map_get_ctx(bmap);
394 1117618 : total = isl_space_dim(bmap->dim, isl_dim_all);
395 1117618 : cols = 1 + 1 + total + bmap->n_div;
396 1117618 : div = isl_mat_alloc(ctx, bmap->n_div, cols);
397 1117618 : if (!div)
398 0 : return NULL;
399 :
400 1117618 : for (i = 0; i < bmap->n_div; ++i)
401 0 : isl_seq_cpy(div->row[i], bmap->div[i], cols);
402 :
403 1117618 : return div;
404 : }
405 :
406 : /* Extract the divs in "bset" as a matrix.
407 : */
408 0 : __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
409 : {
410 0 : return isl_basic_map_get_divs(bset);
411 : }
412 :
413 0 : __isl_give isl_local_space *isl_basic_map_get_local_space(
414 : __isl_keep isl_basic_map *bmap)
415 : {
416 : isl_mat *div;
417 :
418 0 : if (!bmap)
419 0 : return NULL;
420 :
421 0 : div = isl_basic_map_get_divs(bmap);
422 0 : return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
423 : }
424 :
425 0 : __isl_give isl_local_space *isl_basic_set_get_local_space(
426 : __isl_keep isl_basic_set *bset)
427 : {
428 0 : return isl_basic_map_get_local_space(bset);
429 : }
430 :
431 : /* For each known div d = floor(f/m), add the constraints
432 : *
433 : * f - m d >= 0
434 : * -(f-(m-1)) + m d >= 0
435 : *
436 : * Do not finalize the result.
437 : */
438 0 : static __isl_give isl_basic_map *add_known_div_constraints(
439 : __isl_take isl_basic_map *bmap)
440 : {
441 : int i;
442 : unsigned n_div;
443 :
444 0 : if (!bmap)
445 0 : return NULL;
446 0 : n_div = isl_basic_map_dim(bmap, isl_dim_div);
447 0 : if (n_div == 0)
448 0 : return bmap;
449 0 : bmap = isl_basic_map_cow(bmap);
450 0 : bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
451 0 : if (!bmap)
452 0 : return NULL;
453 0 : for (i = 0; i < n_div; ++i) {
454 0 : if (isl_int_is_zero(bmap->div[i][0]))
455 0 : continue;
456 0 : if (isl_basic_map_add_div_constraints(bmap, i) < 0)
457 0 : return isl_basic_map_free(bmap);
458 : }
459 :
460 0 : return bmap;
461 : }
462 :
463 0 : __isl_give isl_basic_map *isl_basic_map_from_local_space(
464 : __isl_take isl_local_space *ls)
465 : {
466 : int i;
467 : int n_div;
468 : isl_basic_map *bmap;
469 :
470 0 : if (!ls)
471 0 : return NULL;
472 :
473 0 : n_div = isl_local_space_dim(ls, isl_dim_div);
474 0 : bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
475 0 : n_div, 0, 2 * n_div);
476 :
477 0 : for (i = 0; i < n_div; ++i)
478 0 : if (isl_basic_map_alloc_div(bmap) < 0)
479 0 : goto error;
480 :
481 0 : for (i = 0; i < n_div; ++i)
482 0 : isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
483 0 : bmap = add_known_div_constraints(bmap);
484 :
485 0 : isl_local_space_free(ls);
486 0 : return bmap;
487 : error:
488 0 : isl_local_space_free(ls);
489 0 : isl_basic_map_free(bmap);
490 0 : return NULL;
491 : }
492 :
493 0 : __isl_give isl_basic_set *isl_basic_set_from_local_space(
494 : __isl_take isl_local_space *ls)
495 : {
496 0 : return isl_basic_map_from_local_space(ls);
497 : }
498 :
499 4989994 : __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
500 : {
501 4989994 : return isl_space_copy(isl_map_peek_space(map));
502 : }
503 :
504 0 : __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
505 : {
506 0 : if (!set)
507 0 : return NULL;
508 0 : return isl_space_copy(set->dim);
509 : }
510 :
511 0 : __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
512 : __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
513 : {
514 0 : bmap = isl_basic_map_cow(bmap);
515 0 : if (!bmap)
516 0 : return NULL;
517 0 : bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
518 0 : if (!bmap->dim)
519 0 : goto error;
520 0 : bmap = isl_basic_map_finalize(bmap);
521 0 : return bmap;
522 : error:
523 0 : isl_basic_map_free(bmap);
524 0 : return NULL;
525 : }
526 :
527 0 : __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
528 : __isl_take isl_basic_set *bset, const char *s)
529 : {
530 0 : return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
531 : }
532 :
533 0 : const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
534 : enum isl_dim_type type)
535 : {
536 0 : return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
537 : }
538 :
539 0 : __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
540 : enum isl_dim_type type, const char *s)
541 : {
542 : int i;
543 :
544 0 : map = isl_map_cow(map);
545 0 : if (!map)
546 0 : return NULL;
547 :
548 0 : map->dim = isl_space_set_tuple_name(map->dim, type, s);
549 0 : if (!map->dim)
550 0 : goto error;
551 :
552 0 : for (i = 0; i < map->n; ++i) {
553 0 : map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
554 0 : if (!map->p[i])
555 0 : goto error;
556 : }
557 :
558 0 : return map;
559 : error:
560 0 : isl_map_free(map);
561 0 : return NULL;
562 : }
563 :
564 : /* Replace the identifier of the tuple of type "type" by "id".
565 : */
566 0 : __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
567 : __isl_take isl_basic_map *bmap,
568 : enum isl_dim_type type, __isl_take isl_id *id)
569 : {
570 0 : bmap = isl_basic_map_cow(bmap);
571 0 : if (!bmap)
572 0 : goto error;
573 0 : bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
574 0 : if (!bmap->dim)
575 0 : return isl_basic_map_free(bmap);
576 0 : bmap = isl_basic_map_finalize(bmap);
577 0 : return bmap;
578 : error:
579 0 : isl_id_free(id);
580 0 : return NULL;
581 : }
582 :
583 : /* Replace the identifier of the tuple by "id".
584 : */
585 0 : __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
586 : __isl_take isl_basic_set *bset, __isl_take isl_id *id)
587 : {
588 0 : return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
589 : }
590 :
591 : /* Does the input or output tuple have a name?
592 : */
593 0 : isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
594 : {
595 0 : return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
596 : }
597 :
598 0 : const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
599 : enum isl_dim_type type)
600 : {
601 0 : return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
602 : }
603 :
604 0 : __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
605 : const char *s)
606 : {
607 0 : return set_from_map(isl_map_set_tuple_name(set_to_map(set),
608 : isl_dim_set, s));
609 : }
610 :
611 0 : __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
612 : enum isl_dim_type type, __isl_take isl_id *id)
613 : {
614 0 : map = isl_map_cow(map);
615 0 : if (!map)
616 0 : goto error;
617 :
618 0 : map->dim = isl_space_set_tuple_id(map->dim, type, id);
619 :
620 0 : return isl_map_reset_space(map, isl_space_copy(map->dim));
621 : error:
622 0 : isl_id_free(id);
623 0 : return NULL;
624 : }
625 :
626 0 : __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
627 : __isl_take isl_id *id)
628 : {
629 0 : return isl_map_set_tuple_id(set, isl_dim_set, id);
630 : }
631 :
632 0 : __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
633 : enum isl_dim_type type)
634 : {
635 0 : map = isl_map_cow(map);
636 0 : if (!map)
637 0 : return NULL;
638 :
639 0 : map->dim = isl_space_reset_tuple_id(map->dim, type);
640 :
641 0 : return isl_map_reset_space(map, isl_space_copy(map->dim));
642 : }
643 :
644 0 : __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
645 : {
646 0 : return isl_map_reset_tuple_id(set, isl_dim_set);
647 : }
648 :
649 0 : isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
650 : {
651 0 : return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
652 : }
653 :
654 0 : __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
655 : enum isl_dim_type type)
656 : {
657 0 : return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
658 : }
659 :
660 0 : isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
661 : {
662 0 : return isl_map_has_tuple_id(set, isl_dim_set);
663 : }
664 :
665 0 : __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
666 : {
667 0 : return isl_map_get_tuple_id(set, isl_dim_set);
668 : }
669 :
670 : /* Does the set tuple have a name?
671 : */
672 0 : isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
673 : {
674 0 : if (!set)
675 0 : return isl_bool_error;
676 0 : return isl_space_has_tuple_name(set->dim, isl_dim_set);
677 : }
678 :
679 :
680 0 : const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
681 : {
682 0 : return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
683 : }
684 :
685 0 : const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
686 : {
687 0 : return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
688 : }
689 :
690 0 : const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
691 : enum isl_dim_type type, unsigned pos)
692 : {
693 0 : return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
694 : }
695 :
696 0 : const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
697 : enum isl_dim_type type, unsigned pos)
698 : {
699 0 : return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
700 : }
701 :
702 : /* Does the given dimension have a name?
703 : */
704 0 : isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
705 : enum isl_dim_type type, unsigned pos)
706 : {
707 0 : if (!map)
708 0 : return isl_bool_error;
709 0 : return isl_space_has_dim_name(map->dim, type, pos);
710 : }
711 :
712 0 : const char *isl_map_get_dim_name(__isl_keep isl_map *map,
713 : enum isl_dim_type type, unsigned pos)
714 : {
715 0 : return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
716 : }
717 :
718 0 : const char *isl_set_get_dim_name(__isl_keep isl_set *set,
719 : enum isl_dim_type type, unsigned pos)
720 : {
721 0 : return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
722 : }
723 :
724 : /* Does the given dimension have a name?
725 : */
726 0 : isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
727 : enum isl_dim_type type, unsigned pos)
728 : {
729 0 : if (!set)
730 0 : return isl_bool_error;
731 0 : return isl_space_has_dim_name(set->dim, type, pos);
732 : }
733 :
734 0 : __isl_give isl_basic_map *isl_basic_map_set_dim_name(
735 : __isl_take isl_basic_map *bmap,
736 : enum isl_dim_type type, unsigned pos, const char *s)
737 : {
738 0 : bmap = isl_basic_map_cow(bmap);
739 0 : if (!bmap)
740 0 : return NULL;
741 0 : bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
742 0 : if (!bmap->dim)
743 0 : goto error;
744 0 : return isl_basic_map_finalize(bmap);
745 : error:
746 0 : isl_basic_map_free(bmap);
747 0 : return NULL;
748 : }
749 :
750 0 : __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
751 : enum isl_dim_type type, unsigned pos, const char *s)
752 : {
753 : int i;
754 :
755 0 : map = isl_map_cow(map);
756 0 : if (!map)
757 0 : return NULL;
758 :
759 0 : map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
760 0 : if (!map->dim)
761 0 : goto error;
762 :
763 0 : for (i = 0; i < map->n; ++i) {
764 0 : map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
765 0 : if (!map->p[i])
766 0 : goto error;
767 : }
768 :
769 0 : return map;
770 : error:
771 0 : isl_map_free(map);
772 0 : return NULL;
773 : }
774 :
775 0 : __isl_give isl_basic_set *isl_basic_set_set_dim_name(
776 : __isl_take isl_basic_set *bset,
777 : enum isl_dim_type type, unsigned pos, const char *s)
778 : {
779 0 : return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
780 : type, pos, s));
781 : }
782 :
783 0 : __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
784 : enum isl_dim_type type, unsigned pos, const char *s)
785 : {
786 0 : return set_from_map(isl_map_set_dim_name(set_to_map(set),
787 : type, pos, s));
788 : }
789 :
790 0 : isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
791 : enum isl_dim_type type, unsigned pos)
792 : {
793 0 : if (!bmap)
794 0 : return isl_bool_error;
795 0 : return isl_space_has_dim_id(bmap->dim, type, pos);
796 : }
797 :
798 0 : __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
799 : enum isl_dim_type type, unsigned pos)
800 : {
801 0 : return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
802 : }
803 :
804 0 : isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
805 : enum isl_dim_type type, unsigned pos)
806 : {
807 0 : return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
808 : }
809 :
810 0 : __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
811 : enum isl_dim_type type, unsigned pos)
812 : {
813 0 : return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
814 : }
815 :
816 0 : isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
817 : enum isl_dim_type type, unsigned pos)
818 : {
819 0 : return isl_map_has_dim_id(set, type, pos);
820 : }
821 :
822 0 : __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
823 : enum isl_dim_type type, unsigned pos)
824 : {
825 0 : return isl_map_get_dim_id(set, type, pos);
826 : }
827 :
828 0 : __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
829 : enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
830 : {
831 0 : map = isl_map_cow(map);
832 0 : if (!map)
833 0 : goto error;
834 :
835 0 : map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
836 :
837 0 : return isl_map_reset_space(map, isl_space_copy(map->dim));
838 : error:
839 0 : isl_id_free(id);
840 0 : return NULL;
841 : }
842 :
843 0 : __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
844 : enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
845 : {
846 0 : return isl_map_set_dim_id(set, type, pos, id);
847 : }
848 :
849 0 : int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
850 : __isl_keep isl_id *id)
851 : {
852 0 : if (!map)
853 0 : return -1;
854 0 : return isl_space_find_dim_by_id(map->dim, type, id);
855 : }
856 :
857 0 : int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
858 : __isl_keep isl_id *id)
859 : {
860 0 : return isl_map_find_dim_by_id(set, type, id);
861 : }
862 :
863 : /* Return the position of the dimension of the given type and name
864 : * in "bmap".
865 : * Return -1 if no such dimension can be found.
866 : */
867 0 : int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
868 : enum isl_dim_type type, const char *name)
869 : {
870 0 : if (!bmap)
871 0 : return -1;
872 0 : return isl_space_find_dim_by_name(bmap->dim, type, name);
873 : }
874 :
875 0 : int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
876 : const char *name)
877 : {
878 0 : if (!map)
879 0 : return -1;
880 0 : return isl_space_find_dim_by_name(map->dim, type, name);
881 : }
882 :
883 0 : int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
884 : const char *name)
885 : {
886 0 : return isl_map_find_dim_by_name(set, type, name);
887 : }
888 :
889 : /* Check whether equality i of bset is a pure stride constraint
890 : * on a single dimension, i.e., of the form
891 : *
892 : * v = k e
893 : *
894 : * with k a constant and e an existentially quantified variable.
895 : */
896 0 : isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
897 : {
898 : unsigned nparam;
899 : unsigned d;
900 : unsigned n_div;
901 : int pos1;
902 : int pos2;
903 :
904 0 : if (!bset)
905 0 : return isl_bool_error;
906 :
907 0 : if (!isl_int_is_zero(bset->eq[i][0]))
908 0 : return isl_bool_false;
909 :
910 0 : nparam = isl_basic_set_dim(bset, isl_dim_param);
911 0 : d = isl_basic_set_dim(bset, isl_dim_set);
912 0 : n_div = isl_basic_set_dim(bset, isl_dim_div);
913 :
914 0 : if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
915 0 : return isl_bool_false;
916 0 : pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
917 0 : if (pos1 == -1)
918 0 : return isl_bool_false;
919 0 : if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
920 0 : d - pos1 - 1) != -1)
921 0 : return isl_bool_false;
922 :
923 0 : pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
924 0 : if (pos2 == -1)
925 0 : return isl_bool_false;
926 0 : if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
927 0 : n_div - pos2 - 1) != -1)
928 0 : return isl_bool_false;
929 0 : if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
930 0 : !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
931 0 : return isl_bool_false;
932 :
933 0 : return isl_bool_true;
934 : }
935 :
936 : /* Reset the user pointer on all identifiers of parameters and tuples
937 : * of the space of "map".
938 : */
939 0 : __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
940 : {
941 : isl_space *space;
942 :
943 0 : space = isl_map_get_space(map);
944 0 : space = isl_space_reset_user(space);
945 0 : map = isl_map_reset_space(map, space);
946 :
947 0 : return map;
948 : }
949 :
950 : /* Reset the user pointer on all identifiers of parameters and tuples
951 : * of the space of "set".
952 : */
953 0 : __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
954 : {
955 0 : return isl_map_reset_user(set);
956 : }
957 :
958 2909068323 : isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
959 : {
960 2909068323 : if (!bmap)
961 0 : return isl_bool_error;
962 2909068323 : return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
963 : }
964 :
965 : /* Has "map" been marked as a rational map?
966 : * In particular, have all basic maps in "map" been marked this way?
967 : * An empty map is not considered to be rational.
968 : * Maps where only some of the basic maps are marked rational
969 : * are not allowed.
970 : */
971 0 : isl_bool isl_map_is_rational(__isl_keep isl_map *map)
972 : {
973 : int i;
974 : isl_bool rational;
975 :
976 0 : if (!map)
977 0 : return isl_bool_error;
978 0 : if (map->n == 0)
979 0 : return isl_bool_false;
980 0 : rational = isl_basic_map_is_rational(map->p[0]);
981 0 : if (rational < 0)
982 0 : return rational;
983 0 : for (i = 1; i < map->n; ++i) {
984 : isl_bool rational_i;
985 :
986 0 : rational_i = isl_basic_map_is_rational(map->p[i]);
987 0 : if (rational_i < 0)
988 0 : return rational_i;
989 0 : if (rational != rational_i)
990 0 : isl_die(isl_map_get_ctx(map), isl_error_unsupported,
991 : "mixed rational and integer basic maps "
992 : "not supported", return isl_bool_error);
993 : }
994 :
995 0 : return rational;
996 : }
997 :
998 : /* Has "set" been marked as a rational set?
999 : * In particular, have all basic set in "set" been marked this way?
1000 : * An empty set is not considered to be rational.
1001 : * Sets where only some of the basic sets are marked rational
1002 : * are not allowed.
1003 : */
1004 0 : isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1005 : {
1006 0 : return isl_map_is_rational(set);
1007 : }
1008 :
1009 129106 : int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1010 : {
1011 129106 : return isl_basic_map_is_rational(bset);
1012 : }
1013 :
1014 : /* Does "bmap" contain any rational points?
1015 : *
1016 : * If "bmap" has an equality for each dimension, equating the dimension
1017 : * to an integer constant, then it has no rational points, even if it
1018 : * is marked as rational.
1019 : */
1020 10019410 : isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1021 : {
1022 10019410 : isl_bool has_rational = isl_bool_true;
1023 : unsigned total;
1024 :
1025 10019410 : if (!bmap)
1026 0 : return isl_bool_error;
1027 10019410 : if (isl_basic_map_plain_is_empty(bmap))
1028 0 : return isl_bool_false;
1029 10019410 : if (!isl_basic_map_is_rational(bmap))
1030 10019410 : return isl_bool_false;
1031 0 : bmap = isl_basic_map_copy(bmap);
1032 0 : bmap = isl_basic_map_implicit_equalities(bmap);
1033 0 : if (!bmap)
1034 0 : return isl_bool_error;
1035 0 : total = isl_basic_map_total_dim(bmap);
1036 0 : if (bmap->n_eq == total) {
1037 : int i, j;
1038 0 : for (i = 0; i < bmap->n_eq; ++i) {
1039 0 : j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1040 0 : if (j < 0)
1041 0 : break;
1042 0 : if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1043 0 : !isl_int_is_negone(bmap->eq[i][1 + j]))
1044 0 : break;
1045 0 : j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1046 0 : total - j - 1);
1047 0 : if (j >= 0)
1048 0 : break;
1049 : }
1050 0 : if (i == bmap->n_eq)
1051 0 : has_rational = isl_bool_false;
1052 : }
1053 0 : isl_basic_map_free(bmap);
1054 :
1055 0 : return has_rational;
1056 : }
1057 :
1058 : /* Does "map" contain any rational points?
1059 : */
1060 406980 : isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1061 : {
1062 : int i;
1063 : isl_bool has_rational;
1064 :
1065 406980 : if (!map)
1066 0 : return isl_bool_error;
1067 10426390 : for (i = 0; i < map->n; ++i) {
1068 10019410 : has_rational = isl_basic_map_has_rational(map->p[i]);
1069 10019410 : if (has_rational < 0 || has_rational)
1070 0 : return has_rational;
1071 : }
1072 406980 : return isl_bool_false;
1073 : }
1074 :
1075 : /* Does "set" contain any rational points?
1076 : */
1077 0 : isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1078 : {
1079 0 : return isl_map_has_rational(set);
1080 : }
1081 :
1082 : /* Is this basic set a parameter domain?
1083 : */
1084 0 : isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1085 : {
1086 0 : if (!bset)
1087 0 : return isl_bool_error;
1088 0 : return isl_space_is_params(bset->dim);
1089 : }
1090 :
1091 : /* Is this set a parameter domain?
1092 : */
1093 0 : isl_bool isl_set_is_params(__isl_keep isl_set *set)
1094 : {
1095 0 : if (!set)
1096 0 : return isl_bool_error;
1097 0 : return isl_space_is_params(set->dim);
1098 : }
1099 :
1100 : /* Is this map actually a parameter domain?
1101 : * Users should never call this function. Outside of isl,
1102 : * a map can never be a parameter domain.
1103 : */
1104 0 : isl_bool isl_map_is_params(__isl_keep isl_map *map)
1105 : {
1106 0 : if (!map)
1107 0 : return isl_bool_error;
1108 0 : return isl_space_is_params(map->dim);
1109 : }
1110 :
1111 26025648161 : static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
1112 : struct isl_basic_map *bmap, unsigned extra,
1113 : unsigned n_eq, unsigned n_ineq)
1114 : {
1115 : int i;
1116 26025648161 : size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
1117 :
1118 26025648161 : bmap->ctx = ctx;
1119 26025648161 : isl_ctx_ref(ctx);
1120 :
1121 26025648161 : bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1122 26025648161 : if (isl_blk_is_error(bmap->block))
1123 0 : goto error;
1124 :
1125 26025648161 : bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1126 26025648161 : if ((n_ineq + n_eq) && !bmap->ineq)
1127 0 : goto error;
1128 :
1129 26025648161 : if (extra == 0) {
1130 26025648161 : bmap->block2 = isl_blk_empty();
1131 26025648161 : bmap->div = NULL;
1132 : } else {
1133 0 : bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1134 0 : if (isl_blk_is_error(bmap->block2))
1135 0 : goto error;
1136 :
1137 0 : bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1138 0 : if (!bmap->div)
1139 0 : goto error;
1140 : }
1141 :
1142 >11666*10^7 : for (i = 0; i < n_ineq + n_eq; ++i)
1143 90642263631 : bmap->ineq[i] = bmap->block.data + i * row_size;
1144 :
1145 26025648161 : for (i = 0; i < extra; ++i)
1146 0 : bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1147 :
1148 26025648161 : bmap->ref = 1;
1149 26025648161 : bmap->flags = 0;
1150 26025648161 : bmap->c_size = n_eq + n_ineq;
1151 26025648161 : bmap->eq = bmap->ineq + n_ineq;
1152 26025648161 : bmap->extra = extra;
1153 26025648161 : bmap->n_eq = 0;
1154 26025648161 : bmap->n_ineq = 0;
1155 26025648161 : bmap->n_div = 0;
1156 26025648161 : bmap->sample = NULL;
1157 :
1158 26025648161 : return bmap;
1159 : error:
1160 0 : isl_basic_map_free(bmap);
1161 0 : return NULL;
1162 : }
1163 :
1164 1971025537 : struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1165 : unsigned nparam, unsigned dim, unsigned extra,
1166 : unsigned n_eq, unsigned n_ineq)
1167 : {
1168 : struct isl_basic_map *bmap;
1169 : isl_space *space;
1170 :
1171 1971025537 : space = isl_space_set_alloc(ctx, nparam, dim);
1172 1971025537 : if (!space)
1173 0 : return NULL;
1174 :
1175 1971025537 : bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1176 1971025537 : return bset_from_bmap(bmap);
1177 : }
1178 :
1179 421428521 : __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1180 : unsigned extra, unsigned n_eq, unsigned n_ineq)
1181 : {
1182 : struct isl_basic_map *bmap;
1183 421428521 : if (!dim)
1184 0 : return NULL;
1185 421428521 : isl_assert(dim->ctx, dim->n_in == 0, goto error);
1186 421428521 : bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1187 421428521 : return bset_from_bmap(bmap);
1188 : error:
1189 0 : isl_space_free(dim);
1190 0 : return NULL;
1191 : }
1192 :
1193 26025648161 : struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
1194 : unsigned extra, unsigned n_eq, unsigned n_ineq)
1195 : {
1196 : struct isl_basic_map *bmap;
1197 :
1198 26025648161 : if (!dim)
1199 0 : return NULL;
1200 26025648161 : bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
1201 26025648161 : if (!bmap)
1202 0 : goto error;
1203 26025648161 : bmap->dim = dim;
1204 :
1205 26025648161 : return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
1206 : error:
1207 0 : isl_space_free(dim);
1208 0 : return NULL;
1209 : }
1210 :
1211 0 : struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1212 : unsigned nparam, unsigned in, unsigned out, unsigned extra,
1213 : unsigned n_eq, unsigned n_ineq)
1214 : {
1215 : struct isl_basic_map *bmap;
1216 : isl_space *dim;
1217 :
1218 0 : dim = isl_space_alloc(ctx, nparam, in, out);
1219 0 : if (!dim)
1220 0 : return NULL;
1221 :
1222 0 : bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1223 0 : return bmap;
1224 : }
1225 :
1226 17551941943 : static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1227 : __isl_keep isl_basic_map *src)
1228 : {
1229 : int i;
1230 17551941943 : unsigned total = isl_basic_map_total_dim(src);
1231 :
1232 17551941943 : if (!dst)
1233 0 : return NULL;
1234 :
1235 57372485222 : for (i = 0; i < src->n_eq; ++i) {
1236 39820543279 : int j = isl_basic_map_alloc_equality(dst);
1237 39820543279 : if (j < 0)
1238 0 : return isl_basic_map_free(dst);
1239 39820543279 : isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1240 : }
1241 :
1242 24880468187 : for (i = 0; i < src->n_ineq; ++i) {
1243 7328526244 : int j = isl_basic_map_alloc_inequality(dst);
1244 7328526244 : if (j < 0)
1245 0 : return isl_basic_map_free(dst);
1246 7328526244 : isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1247 : }
1248 :
1249 17551941943 : for (i = 0; i < src->n_div; ++i) {
1250 0 : int j = isl_basic_map_alloc_div(dst);
1251 0 : if (j < 0)
1252 0 : return isl_basic_map_free(dst);
1253 0 : isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1254 : }
1255 17551941943 : ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1256 17551941943 : return dst;
1257 : }
1258 :
1259 17551941943 : __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1260 : {
1261 : struct isl_basic_map *dup;
1262 :
1263 17551941943 : if (!bmap)
1264 0 : return NULL;
1265 17551941943 : dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1266 : bmap->n_div, bmap->n_eq, bmap->n_ineq);
1267 17551941943 : dup = dup_constraints(dup, bmap);
1268 17551941943 : if (!dup)
1269 0 : return NULL;
1270 17551941943 : dup->flags = bmap->flags;
1271 17551941943 : dup->sample = isl_vec_copy(bmap->sample);
1272 17551941943 : return dup;
1273 : }
1274 :
1275 850267412 : struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1276 : {
1277 : struct isl_basic_map *dup;
1278 :
1279 850267412 : dup = isl_basic_map_dup(bset_to_bmap(bset));
1280 850267412 : return bset_from_bmap(dup);
1281 : }
1282 :
1283 1990293972 : __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1284 : {
1285 1990293972 : if (!bset)
1286 0 : return NULL;
1287 :
1288 1990293972 : if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1289 1140026560 : bset->ref++;
1290 1140026560 : return bset;
1291 : }
1292 850267412 : return isl_basic_set_dup(bset);
1293 : }
1294 :
1295 3013848416 : __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1296 : {
1297 3013848416 : if (!set)
1298 0 : return NULL;
1299 :
1300 3013848416 : set->ref++;
1301 3013848416 : return set;
1302 : }
1303 :
1304 26979508049 : __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1305 : {
1306 26979508049 : if (!bmap)
1307 0 : return NULL;
1308 :
1309 26979508049 : if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1310 24749313886 : bmap->ref++;
1311 24749313886 : return bmap;
1312 : }
1313 2230194163 : bmap = isl_basic_map_dup(bmap);
1314 2230194163 : if (bmap)
1315 2230194163 : ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1316 2230194163 : return bmap;
1317 : }
1318 :
1319 39254002 : __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1320 : {
1321 39254002 : if (!map)
1322 0 : return NULL;
1323 :
1324 39254002 : map->ref++;
1325 39254002 : return map;
1326 : }
1327 :
1328 66791347963 : __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1329 : {
1330 66791347963 : if (!bmap)
1331 29347839724 : return NULL;
1332 :
1333 37443508239 : if (--bmap->ref > 0)
1334 11417860078 : return NULL;
1335 :
1336 26025648161 : isl_ctx_deref(bmap->ctx);
1337 26025648161 : free(bmap->div);
1338 26025648161 : isl_blk_free(bmap->ctx, bmap->block2);
1339 26025648161 : free(bmap->ineq);
1340 26025648161 : isl_blk_free(bmap->ctx, bmap->block);
1341 26025648161 : isl_vec_free(bmap->sample);
1342 26025648161 : isl_space_free(bmap->dim);
1343 26025648161 : free(bmap);
1344 :
1345 26025648161 : return NULL;
1346 : }
1347 :
1348 4978110151 : __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1349 : {
1350 4978110151 : return isl_basic_map_free(bset_to_bmap(bset));
1351 : }
1352 :
1353 71228679587 : static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1354 : {
1355 71228679587 : return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1356 : }
1357 :
1358 : /* Check that "map" has only named parameters, reporting an error
1359 : * if it does not.
1360 : */
1361 0 : isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
1362 : {
1363 0 : return isl_space_check_named_params(isl_map_peek_space(map));
1364 : }
1365 :
1366 : /* Check that "bmap" has only named parameters, reporting an error
1367 : * if it does not.
1368 : */
1369 0 : static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
1370 : {
1371 0 : return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
1372 : }
1373 :
1374 : /* Check that "bmap1" and "bmap2" have the same parameters,
1375 : * reporting an error if they do not.
1376 : */
1377 110183997 : static isl_stat isl_basic_map_check_equal_params(
1378 : __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1379 : {
1380 : isl_bool match;
1381 :
1382 110183997 : match = isl_basic_map_has_equal_params(bmap1, bmap2);
1383 110183997 : if (match < 0)
1384 0 : return isl_stat_error;
1385 110183997 : if (!match)
1386 0 : isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1387 : "parameters don't match", return isl_stat_error);
1388 110183997 : return isl_stat_ok;
1389 : }
1390 :
1391 54491026 : __isl_give isl_map *isl_map_align_params_map_map_and(
1392 : __isl_take isl_map *map1, __isl_take isl_map *map2,
1393 : __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1394 : __isl_take isl_map *map2))
1395 : {
1396 54491026 : if (!map1 || !map2)
1397 : goto error;
1398 54491026 : if (isl_map_has_equal_params(map1, map2))
1399 54491026 : return fn(map1, map2);
1400 0 : if (isl_map_check_named_params(map1) < 0)
1401 0 : goto error;
1402 0 : if (isl_map_check_named_params(map2) < 0)
1403 0 : goto error;
1404 0 : map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1405 0 : map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1406 0 : return fn(map1, map2);
1407 : error:
1408 0 : isl_map_free(map1);
1409 0 : isl_map_free(map2);
1410 0 : return NULL;
1411 : }
1412 :
1413 633717 : isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1414 : __isl_keep isl_map *map2,
1415 : isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1416 : {
1417 : isl_bool r;
1418 :
1419 633717 : if (!map1 || !map2)
1420 0 : return isl_bool_error;
1421 633717 : if (isl_map_has_equal_params(map1, map2))
1422 633717 : return fn(map1, map2);
1423 0 : if (isl_map_check_named_params(map1) < 0)
1424 0 : return isl_bool_error;
1425 0 : if (isl_map_check_named_params(map2) < 0)
1426 0 : return isl_bool_error;
1427 0 : map1 = isl_map_copy(map1);
1428 0 : map2 = isl_map_copy(map2);
1429 0 : map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1430 0 : map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1431 0 : r = fn(map1, map2);
1432 0 : isl_map_free(map1);
1433 0 : isl_map_free(map2);
1434 0 : return r;
1435 : }
1436 :
1437 61460575396 : int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1438 : {
1439 : struct isl_ctx *ctx;
1440 61460575396 : if (!bmap)
1441 0 : return -1;
1442 61460575396 : ctx = bmap->ctx;
1443 61460575396 : isl_assert(ctx, room_for_con(bmap, 1), return -1);
1444 61460575396 : isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1445 : return -1);
1446 61460575396 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1447 61460575396 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1448 61460575396 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1449 61460575396 : ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1450 61460575396 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1451 61460575396 : if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1452 : isl_int *t;
1453 51661544 : int j = isl_basic_map_alloc_inequality(bmap);
1454 51661544 : if (j < 0)
1455 0 : return -1;
1456 51661544 : t = bmap->ineq[j];
1457 51661544 : bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1458 51661544 : bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1459 51661544 : bmap->eq[-1] = t;
1460 51661544 : bmap->n_eq++;
1461 51661544 : bmap->n_ineq--;
1462 51661544 : bmap->eq--;
1463 51661544 : return 0;
1464 : }
1465 61408913852 : isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1466 61408913852 : bmap->extra - bmap->n_div);
1467 61408913852 : return bmap->n_eq++;
1468 : }
1469 :
1470 15874318875 : int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1471 : {
1472 15874318875 : return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1473 : }
1474 :
1475 5847702420 : int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1476 : {
1477 5847702420 : if (!bmap)
1478 0 : return -1;
1479 5847702420 : isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1480 5847702420 : bmap->n_eq -= n;
1481 5847702420 : return 0;
1482 : }
1483 :
1484 0 : int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1485 : {
1486 0 : return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1487 : }
1488 :
1489 1103466289 : int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1490 : {
1491 : isl_int *t;
1492 1103466289 : if (!bmap)
1493 0 : return -1;
1494 1103466289 : isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1495 :
1496 1103466289 : if (pos != bmap->n_eq - 1) {
1497 661936717 : t = bmap->eq[pos];
1498 661936717 : bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1499 661936717 : bmap->eq[bmap->n_eq - 1] = t;
1500 : }
1501 1103466289 : bmap->n_eq--;
1502 1103466289 : return 0;
1503 : }
1504 :
1505 : /* Turn inequality "pos" of "bmap" into an equality.
1506 : *
1507 : * In particular, we move the inequality in front of the equalities
1508 : * and move the last inequality in the position of the moved inequality.
1509 : * Note that isl_tab_make_equalities_explicit depends on this particular
1510 : * change in the ordering of the constraints.
1511 : */
1512 621411189 : void isl_basic_map_inequality_to_equality(
1513 : struct isl_basic_map *bmap, unsigned pos)
1514 : {
1515 : isl_int *t;
1516 :
1517 621411189 : t = bmap->ineq[pos];
1518 621411189 : bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1519 621411189 : bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1520 621411189 : bmap->eq[-1] = t;
1521 621411189 : bmap->n_eq++;
1522 621411189 : bmap->n_ineq--;
1523 621411189 : bmap->eq--;
1524 621411189 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1525 621411189 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1526 621411189 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1527 621411189 : ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1528 621411189 : }
1529 :
1530 35826352771 : static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1531 : {
1532 35826352771 : return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1533 : }
1534 :
1535 30918441926 : int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1536 : {
1537 : struct isl_ctx *ctx;
1538 30918441926 : if (!bmap)
1539 0 : return -1;
1540 30918441926 : ctx = bmap->ctx;
1541 30918441926 : isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1542 30918441926 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1543 30918441926 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1544 30918441926 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1545 30918441926 : ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1546 61836883852 : isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1547 30918441926 : 1 + isl_basic_map_total_dim(bmap),
1548 30918441926 : bmap->extra - bmap->n_div);
1549 30918441926 : return bmap->n_ineq++;
1550 : }
1551 :
1552 6978651350 : int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1553 : {
1554 6978651350 : return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1555 : }
1556 :
1557 12840401547 : int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1558 : {
1559 12840401547 : if (!bmap)
1560 0 : return -1;
1561 12840401547 : isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1562 12840401547 : bmap->n_ineq -= n;
1563 12840401547 : return 0;
1564 : }
1565 :
1566 0 : int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1567 : {
1568 0 : return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1569 : }
1570 :
1571 1868725399 : int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1572 : {
1573 : isl_int *t;
1574 1868725399 : if (!bmap)
1575 0 : return -1;
1576 1868725399 : isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1577 :
1578 1868725399 : if (pos != bmap->n_ineq - 1) {
1579 863271881 : t = bmap->ineq[pos];
1580 863271881 : bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1581 863271881 : bmap->ineq[bmap->n_ineq - 1] = t;
1582 863271881 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1583 : }
1584 1868725399 : bmap->n_ineq--;
1585 1868725399 : return 0;
1586 : }
1587 :
1588 0 : int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1589 : {
1590 0 : return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1591 : }
1592 :
1593 0 : __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1594 : isl_int *eq)
1595 : {
1596 : int k;
1597 :
1598 0 : bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1599 0 : if (!bmap)
1600 0 : return NULL;
1601 0 : k = isl_basic_map_alloc_equality(bmap);
1602 0 : if (k < 0)
1603 0 : goto error;
1604 0 : isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1605 0 : return bmap;
1606 : error:
1607 0 : isl_basic_map_free(bmap);
1608 0 : return NULL;
1609 : }
1610 :
1611 0 : __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1612 : isl_int *eq)
1613 : {
1614 0 : return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1615 : }
1616 :
1617 3825163776 : __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1618 : isl_int *ineq)
1619 : {
1620 : int k;
1621 :
1622 3825163776 : bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1623 3825163776 : if (!bmap)
1624 0 : return NULL;
1625 3825163776 : k = isl_basic_map_alloc_inequality(bmap);
1626 3825163776 : if (k < 0)
1627 0 : goto error;
1628 3825163776 : isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1629 3825163776 : return bmap;
1630 : error:
1631 0 : isl_basic_map_free(bmap);
1632 0 : return NULL;
1633 : }
1634 :
1635 0 : __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1636 : isl_int *ineq)
1637 : {
1638 0 : return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1639 : }
1640 :
1641 0 : int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1642 : {
1643 0 : if (!bmap)
1644 0 : return -1;
1645 0 : isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1646 0 : isl_seq_clr(bmap->div[bmap->n_div] +
1647 0 : 1 + 1 + isl_basic_map_total_dim(bmap),
1648 0 : bmap->extra - bmap->n_div);
1649 0 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1650 0 : return bmap->n_div++;
1651 : }
1652 :
1653 0 : int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1654 : {
1655 0 : return isl_basic_map_alloc_div(bset_to_bmap(bset));
1656 : }
1657 :
1658 : /* Check that there are "n" dimensions of type "type" starting at "first"
1659 : * in "bmap".
1660 : */
1661 7702949 : static isl_stat isl_basic_map_check_range(__isl_keep isl_basic_map *bmap,
1662 : enum isl_dim_type type, unsigned first, unsigned n)
1663 : {
1664 : unsigned dim;
1665 :
1666 7702949 : if (!bmap)
1667 0 : return isl_stat_error;
1668 7702949 : dim = isl_basic_map_dim(bmap, type);
1669 7702949 : if (first + n > dim || first + n < first)
1670 0 : isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1671 : "position or range out of bounds",
1672 : return isl_stat_error);
1673 7702949 : return isl_stat_ok;
1674 : }
1675 :
1676 : /* Insert an extra integer division, prescribed by "div", to "bmap"
1677 : * at (integer division) position "pos".
1678 : *
1679 : * The integer division is first added at the end and then moved
1680 : * into the right position.
1681 : */
1682 0 : __isl_give isl_basic_map *isl_basic_map_insert_div(
1683 : __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1684 : {
1685 : int i, k;
1686 :
1687 0 : bmap = isl_basic_map_cow(bmap);
1688 0 : if (!bmap || !div)
1689 0 : return isl_basic_map_free(bmap);
1690 :
1691 0 : if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1692 0 : isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1693 : "unexpected size", return isl_basic_map_free(bmap));
1694 0 : if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1695 0 : return isl_basic_map_free(bmap);
1696 :
1697 0 : bmap = isl_basic_map_extend_space(bmap,
1698 : isl_basic_map_get_space(bmap), 1, 0, 2);
1699 0 : k = isl_basic_map_alloc_div(bmap);
1700 0 : if (k < 0)
1701 0 : return isl_basic_map_free(bmap);
1702 0 : isl_seq_cpy(bmap->div[k], div->el, div->size);
1703 0 : isl_int_set_si(bmap->div[k][div->size], 0);
1704 :
1705 0 : for (i = k; i > pos; --i)
1706 0 : isl_basic_map_swap_div(bmap, i, i - 1);
1707 :
1708 0 : return bmap;
1709 : }
1710 :
1711 2845818736 : isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1712 : {
1713 2845818736 : if (!bmap)
1714 0 : return isl_stat_error;
1715 2845818736 : isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1716 2845818736 : bmap->n_div -= n;
1717 2845818736 : return isl_stat_ok;
1718 : }
1719 :
1720 : /* Copy constraint from src to dst, putting the vars of src at offset
1721 : * dim_off in dst and the divs of src at offset div_off in dst.
1722 : * If both sets are actually map, then dim_off applies to the input
1723 : * variables.
1724 : */
1725 18445940278 : static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
1726 : struct isl_basic_map *src_map, isl_int *src,
1727 : unsigned in_off, unsigned out_off, unsigned div_off)
1728 : {
1729 18445940278 : unsigned src_nparam = isl_basic_map_dim(src_map, isl_dim_param);
1730 18445940278 : unsigned dst_nparam = isl_basic_map_dim(dst_map, isl_dim_param);
1731 18445940278 : unsigned src_in = isl_basic_map_dim(src_map, isl_dim_in);
1732 18445940278 : unsigned dst_in = isl_basic_map_dim(dst_map, isl_dim_in);
1733 18445940278 : unsigned src_out = isl_basic_map_dim(src_map, isl_dim_out);
1734 18445940278 : unsigned dst_out = isl_basic_map_dim(dst_map, isl_dim_out);
1735 18445940278 : isl_int_set(dst[0], src[0]);
1736 18445940278 : isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
1737 18445940278 : if (dst_nparam > src_nparam)
1738 0 : isl_seq_clr(dst+1+src_nparam,
1739 : dst_nparam - src_nparam);
1740 18445940278 : isl_seq_clr(dst+1+dst_nparam, in_off);
1741 36891880556 : isl_seq_cpy(dst+1+dst_nparam+in_off,
1742 18445940278 : src+1+src_nparam,
1743 18445940278 : isl_min(dst_in-in_off, src_in));
1744 18445940278 : if (dst_in-in_off > src_in)
1745 0 : isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
1746 0 : dst_in - in_off - src_in);
1747 18445940278 : isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
1748 36891880556 : isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
1749 18445940278 : src+1+src_nparam+src_in,
1750 18445940278 : isl_min(dst_out-out_off, src_out));
1751 18445940278 : if (dst_out-out_off > src_out)
1752 2919590919 : isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
1753 2919590919 : dst_out - out_off - src_out);
1754 18445940278 : isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
1755 36891880556 : isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
1756 18445940278 : src+1+src_nparam+src_in+src_out,
1757 18445940278 : isl_min(dst_map->extra-div_off, src_map->n_div));
1758 18445940278 : if (dst_map->n_div-div_off > src_map->n_div)
1759 0 : isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
1760 0 : div_off+src_map->n_div,
1761 0 : dst_map->n_div - div_off - src_map->n_div);
1762 18445940278 : }
1763 :
1764 0 : static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
1765 : struct isl_basic_map *src_map, isl_int *src,
1766 : unsigned in_off, unsigned out_off, unsigned div_off)
1767 : {
1768 0 : isl_int_set(dst[0], src[0]);
1769 0 : copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
1770 0 : }
1771 :
1772 6188865966 : static __isl_give isl_basic_map *add_constraints(
1773 : __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1774 : unsigned i_pos, unsigned o_pos)
1775 : {
1776 : int i;
1777 : unsigned div_off;
1778 :
1779 6188865966 : if (!bmap1 || !bmap2)
1780 : goto error;
1781 :
1782 6188865966 : div_off = bmap1->n_div;
1783 :
1784 11901085198 : for (i = 0; i < bmap2->n_eq; ++i) {
1785 5712219232 : int i1 = isl_basic_map_alloc_equality(bmap1);
1786 5712219232 : if (i1 < 0)
1787 0 : goto error;
1788 5712219232 : copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
1789 : i_pos, o_pos, div_off);
1790 : }
1791 :
1792 18922587012 : for (i = 0; i < bmap2->n_ineq; ++i) {
1793 12733721046 : int i1 = isl_basic_map_alloc_inequality(bmap1);
1794 12733721046 : if (i1 < 0)
1795 0 : goto error;
1796 12733721046 : copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
1797 : i_pos, o_pos, div_off);
1798 : }
1799 :
1800 6188865966 : for (i = 0; i < bmap2->n_div; ++i) {
1801 0 : int i1 = isl_basic_map_alloc_div(bmap1);
1802 0 : if (i1 < 0)
1803 0 : goto error;
1804 0 : copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
1805 : i_pos, o_pos, div_off);
1806 : }
1807 :
1808 6188865966 : isl_basic_map_free(bmap2);
1809 :
1810 6188865966 : return bmap1;
1811 :
1812 : error:
1813 0 : isl_basic_map_free(bmap1);
1814 0 : isl_basic_map_free(bmap2);
1815 0 : return NULL;
1816 : }
1817 :
1818 0 : struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1819 : struct isl_basic_set *bset2, unsigned pos)
1820 : {
1821 0 : return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1822 : bset_to_bmap(bset2), 0, pos));
1823 : }
1824 :
1825 10986592814 : __isl_give isl_basic_map *isl_basic_map_extend_space(
1826 : __isl_take isl_basic_map *base, __isl_take isl_space *dim,
1827 : unsigned extra, unsigned n_eq, unsigned n_ineq)
1828 : {
1829 : struct isl_basic_map *ext;
1830 : unsigned flags;
1831 : int dims_ok;
1832 :
1833 10986592814 : if (!dim)
1834 0 : goto error;
1835 :
1836 10986592814 : if (!base)
1837 0 : goto error;
1838 :
1839 20754697005 : dims_ok = isl_space_is_equal(base->dim, dim) &&
1840 9768104191 : base->extra >= base->n_div + extra;
1841 :
1842 15894503659 : if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1843 4907910845 : room_for_ineq(base, n_ineq)) {
1844 4907910845 : isl_space_free(dim);
1845 4907910845 : return base;
1846 : }
1847 :
1848 6078681969 : isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
1849 6078681969 : isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
1850 6078681969 : isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
1851 6078681969 : extra += base->extra;
1852 6078681969 : n_eq += base->n_eq;
1853 6078681969 : n_ineq += base->n_ineq;
1854 :
1855 6078681969 : ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1856 6078681969 : dim = NULL;
1857 6078681969 : if (!ext)
1858 0 : goto error;
1859 :
1860 6078681969 : if (dims_ok)
1861 4860193346 : ext->sample = isl_vec_copy(base->sample);
1862 6078681969 : flags = base->flags;
1863 6078681969 : ext = add_constraints(ext, base, 0, 0);
1864 6078681969 : if (ext) {
1865 6078681969 : ext->flags = flags;
1866 6078681969 : ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1867 : }
1868 :
1869 6078681969 : return ext;
1870 :
1871 : error:
1872 0 : isl_space_free(dim);
1873 0 : isl_basic_map_free(base);
1874 0 : return NULL;
1875 : }
1876 :
1877 1218270283 : __isl_give isl_basic_set *isl_basic_set_extend_space(
1878 : __isl_take isl_basic_set *base,
1879 : __isl_take isl_space *dim, unsigned extra,
1880 : unsigned n_eq, unsigned n_ineq)
1881 : {
1882 1218270283 : return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1883 : dim, extra, n_eq, n_ineq));
1884 : }
1885 :
1886 3826054768 : struct isl_basic_map *isl_basic_map_extend_constraints(
1887 : struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1888 : {
1889 3826054768 : if (!base)
1890 0 : return NULL;
1891 3826054768 : return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1892 : 0, n_eq, n_ineq);
1893 : }
1894 :
1895 5831859936 : struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1896 : unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1897 : unsigned n_eq, unsigned n_ineq)
1898 : {
1899 : struct isl_basic_map *bmap;
1900 : isl_space *dim;
1901 :
1902 5831859936 : if (!base)
1903 0 : return NULL;
1904 5831859936 : dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1905 5831859936 : if (!dim)
1906 0 : goto error;
1907 :
1908 5831859936 : bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1909 5831859936 : return bmap;
1910 : error:
1911 0 : isl_basic_map_free(base);
1912 0 : return NULL;
1913 : }
1914 :
1915 5831859936 : struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
1916 : unsigned nparam, unsigned dim, unsigned extra,
1917 : unsigned n_eq, unsigned n_ineq)
1918 : {
1919 5831859936 : return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
1920 : nparam, 0, dim, extra, n_eq, n_ineq));
1921 : }
1922 :
1923 0 : struct isl_basic_set *isl_basic_set_extend_constraints(
1924 : struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1925 : {
1926 0 : isl_basic_map *bmap = bset_to_bmap(base);
1927 0 : bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1928 0 : return bset_from_bmap(bmap);
1929 : }
1930 :
1931 15253739189 : __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1932 : {
1933 15253739189 : return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1934 : }
1935 :
1936 24157891949 : __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1937 : {
1938 24157891949 : if (!bmap)
1939 0 : return NULL;
1940 :
1941 24157891949 : if (bmap->ref > 1) {
1942 14471480368 : bmap->ref--;
1943 14471480368 : bmap = isl_basic_map_dup(bmap);
1944 : }
1945 24157891949 : if (bmap) {
1946 24157891949 : ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1947 24157891949 : ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1948 : }
1949 24157891949 : return bmap;
1950 : }
1951 :
1952 : /* Clear all cached information in "map", either because it is about
1953 : * to be modified or because it is being freed.
1954 : * Always return the same pointer that is passed in.
1955 : * This is needed for the use in isl_map_free.
1956 : */
1957 10528261078 : static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1958 : {
1959 10528261078 : isl_basic_map_free(map->cached_simple_hull[0]);
1960 10528261078 : isl_basic_map_free(map->cached_simple_hull[1]);
1961 10528261078 : map->cached_simple_hull[0] = NULL;
1962 10528261078 : map->cached_simple_hull[1] = NULL;
1963 10528261078 : return map;
1964 : }
1965 :
1966 3638559013 : __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
1967 : {
1968 3638559013 : return isl_map_cow(set);
1969 : }
1970 :
1971 : /* Return an isl_map that is equal to "map" and that has only
1972 : * a single reference.
1973 : *
1974 : * If the original input already has only one reference, then
1975 : * simply return it, but clear all cached information, since
1976 : * it may be rendered invalid by the operations that will be
1977 : * performed on the result.
1978 : *
1979 : * Otherwise, create a duplicate (without any cached information).
1980 : */
1981 10435146687 : __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
1982 : {
1983 10435146687 : if (!map)
1984 0 : return NULL;
1985 :
1986 10435146687 : if (map->ref == 1)
1987 7430417647 : return clear_caches(map);
1988 3004729040 : map->ref--;
1989 3004729040 : return isl_map_dup(map);
1990 : }
1991 :
1992 0 : static void swap_vars(struct isl_blk blk, isl_int *a,
1993 : unsigned a_len, unsigned b_len)
1994 : {
1995 0 : isl_seq_cpy(blk.data, a+a_len, b_len);
1996 0 : isl_seq_cpy(blk.data+b_len, a, a_len);
1997 0 : isl_seq_cpy(a, blk.data, b_len+a_len);
1998 0 : }
1999 :
2000 0 : static __isl_give isl_basic_map *isl_basic_map_swap_vars(
2001 : __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
2002 : {
2003 : int i;
2004 : struct isl_blk blk;
2005 :
2006 0 : if (!bmap)
2007 0 : goto error;
2008 :
2009 0 : isl_assert(bmap->ctx,
2010 : pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
2011 :
2012 0 : if (n1 == 0 || n2 == 0)
2013 0 : return bmap;
2014 :
2015 0 : bmap = isl_basic_map_cow(bmap);
2016 0 : if (!bmap)
2017 0 : return NULL;
2018 :
2019 0 : blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2020 0 : if (isl_blk_is_error(blk))
2021 0 : goto error;
2022 :
2023 0 : for (i = 0; i < bmap->n_eq; ++i)
2024 0 : swap_vars(blk,
2025 0 : bmap->eq[i] + pos, n1, n2);
2026 :
2027 0 : for (i = 0; i < bmap->n_ineq; ++i)
2028 0 : swap_vars(blk,
2029 0 : bmap->ineq[i] + pos, n1, n2);
2030 :
2031 0 : for (i = 0; i < bmap->n_div; ++i)
2032 0 : swap_vars(blk,
2033 0 : bmap->div[i]+1 + pos, n1, n2);
2034 :
2035 0 : isl_blk_free(bmap->ctx, blk);
2036 :
2037 0 : ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
2038 0 : bmap = isl_basic_map_gauss(bmap, NULL);
2039 0 : return isl_basic_map_finalize(bmap);
2040 : error:
2041 0 : isl_basic_map_free(bmap);
2042 0 : return NULL;
2043 : }
2044 :
2045 2845818736 : __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2046 : __isl_take isl_basic_map *bmap)
2047 : {
2048 2845818736 : int i = 0;
2049 : unsigned total;
2050 2845818736 : if (!bmap)
2051 0 : goto error;
2052 2845818736 : total = isl_basic_map_total_dim(bmap);
2053 2845818736 : if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2054 0 : return isl_basic_map_free(bmap);
2055 2845818736 : isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2056 2845818736 : if (bmap->n_eq > 0)
2057 2792646113 : isl_basic_map_free_equality(bmap, bmap->n_eq-1);
2058 : else {
2059 53172623 : i = isl_basic_map_alloc_equality(bmap);
2060 53172623 : if (i < 0)
2061 0 : goto error;
2062 : }
2063 2845818736 : isl_int_set_si(bmap->eq[i][0], 1);
2064 2845818736 : isl_seq_clr(bmap->eq[i]+1, total);
2065 2845818736 : ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2066 2845818736 : isl_vec_free(bmap->sample);
2067 2845818736 : bmap->sample = NULL;
2068 2845818736 : return isl_basic_map_finalize(bmap);
2069 : error:
2070 0 : isl_basic_map_free(bmap);
2071 0 : return NULL;
2072 : }
2073 :
2074 1419589 : __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2075 : __isl_take isl_basic_set *bset)
2076 : {
2077 1419589 : return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2078 : }
2079 :
2080 10423960158 : __isl_give isl_basic_map *isl_basic_map_set_rational(
2081 : __isl_take isl_basic_map *bmap)
2082 : {
2083 10423960158 : if (!bmap)
2084 0 : return NULL;
2085 :
2086 10423960158 : if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2087 8085459516 : return bmap;
2088 :
2089 2338500642 : bmap = isl_basic_map_cow(bmap);
2090 2338500642 : if (!bmap)
2091 0 : return NULL;
2092 :
2093 2338500642 : ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2094 :
2095 2338500642 : return isl_basic_map_finalize(bmap);
2096 : }
2097 :
2098 2336980258 : __isl_give isl_basic_set *isl_basic_set_set_rational(
2099 : __isl_take isl_basic_set *bset)
2100 : {
2101 2336980258 : return isl_basic_map_set_rational(bset);
2102 : }
2103 :
2104 0 : __isl_give isl_basic_set *isl_basic_set_set_integral(
2105 : __isl_take isl_basic_set *bset)
2106 : {
2107 0 : if (!bset)
2108 0 : return NULL;
2109 :
2110 0 : if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2111 0 : return bset;
2112 :
2113 0 : bset = isl_basic_set_cow(bset);
2114 0 : if (!bset)
2115 0 : return NULL;
2116 :
2117 0 : ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2118 :
2119 0 : return isl_basic_set_finalize(bset);
2120 : }
2121 :
2122 2347048276 : __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2123 : {
2124 : int i;
2125 :
2126 2347048276 : map = isl_map_cow(map);
2127 2347048276 : if (!map)
2128 0 : return NULL;
2129 10434028176 : for (i = 0; i < map->n; ++i) {
2130 8086979900 : map->p[i] = isl_basic_map_set_rational(map->p[i]);
2131 8086979900 : if (!map->p[i])
2132 0 : goto error;
2133 : }
2134 2347048276 : return map;
2135 : error:
2136 0 : isl_map_free(map);
2137 0 : return NULL;
2138 : }
2139 :
2140 2347048276 : __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2141 : {
2142 2347048276 : return isl_map_set_rational(set);
2143 : }
2144 :
2145 : /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2146 : * of "bmap").
2147 : */
2148 0 : static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2149 : {
2150 0 : isl_int *t = bmap->div[a];
2151 0 : bmap->div[a] = bmap->div[b];
2152 0 : bmap->div[b] = t;
2153 0 : }
2154 :
2155 : /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2156 : * div definitions accordingly.
2157 : */
2158 0 : void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
2159 : {
2160 : int i;
2161 0 : unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
2162 :
2163 0 : swap_div(bmap, a, b);
2164 :
2165 0 : for (i = 0; i < bmap->n_eq; ++i)
2166 0 : isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2167 :
2168 0 : for (i = 0; i < bmap->n_ineq; ++i)
2169 0 : isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2170 :
2171 0 : for (i = 0; i < bmap->n_div; ++i)
2172 0 : isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2173 0 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2174 0 : }
2175 :
2176 : /* Swap divs "a" and "b" in "bset" and adjust the constraints and
2177 : * div definitions accordingly.
2178 : */
2179 0 : void isl_basic_set_swap_div(__isl_keep isl_basic_set *bset, int a, int b)
2180 : {
2181 0 : isl_basic_map_swap_div(bset, a, b);
2182 0 : }
2183 :
2184 36691185 : static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2185 : {
2186 36691185 : isl_seq_cpy(c, c + n, rem);
2187 36691185 : isl_seq_clr(c + rem, n);
2188 36691185 : }
2189 :
2190 : /* Drop n dimensions starting at first.
2191 : *
2192 : * In principle, this frees up some extra variables as the number
2193 : * of columns remains constant, but we would have to extend
2194 : * the div array too as the number of rows in this array is assumed
2195 : * to be equal to extra.
2196 : */
2197 16043818 : __isl_give isl_basic_set *isl_basic_set_drop_dims(
2198 : __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2199 : {
2200 16043818 : return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2201 : }
2202 :
2203 : /* Move "n" divs starting at "first" to the end of the list of divs.
2204 : */
2205 0 : static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
2206 : unsigned first, unsigned n)
2207 : {
2208 : isl_int **div;
2209 : int i;
2210 :
2211 0 : if (first + n == bmap->n_div)
2212 0 : return bmap;
2213 :
2214 0 : div = isl_alloc_array(bmap->ctx, isl_int *, n);
2215 0 : if (!div)
2216 0 : goto error;
2217 0 : for (i = 0; i < n; ++i)
2218 0 : div[i] = bmap->div[first + i];
2219 0 : for (i = 0; i < bmap->n_div - first - n; ++i)
2220 0 : bmap->div[first + i] = bmap->div[first + n + i];
2221 0 : for (i = 0; i < n; ++i)
2222 0 : bmap->div[bmap->n_div - n + i] = div[i];
2223 0 : free(div);
2224 0 : return bmap;
2225 : error:
2226 0 : isl_basic_map_free(bmap);
2227 0 : return NULL;
2228 : }
2229 :
2230 : /* Check that there are "n" dimensions of type "type" starting at "first"
2231 : * in "map".
2232 : */
2233 0 : static isl_stat isl_map_check_range(__isl_keep isl_map *map,
2234 : enum isl_dim_type type, unsigned first, unsigned n)
2235 : {
2236 0 : if (!map)
2237 0 : return isl_stat_error;
2238 0 : if (first + n > isl_map_dim(map, type) || first + n < first)
2239 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
2240 : "position or range out of bounds",
2241 : return isl_stat_error);
2242 0 : return isl_stat_ok;
2243 : }
2244 :
2245 : /* Drop "n" dimensions of type "type" starting at "first".
2246 : *
2247 : * In principle, this frees up some extra variables as the number
2248 : * of columns remains constant, but we would have to extend
2249 : * the div array too as the number of rows in this array is assumed
2250 : * to be equal to extra.
2251 : */
2252 17273171 : __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2253 : enum isl_dim_type type, unsigned first, unsigned n)
2254 : {
2255 : int i;
2256 : unsigned dim;
2257 : unsigned offset;
2258 : unsigned left;
2259 :
2260 17273171 : if (!bmap)
2261 0 : goto error;
2262 :
2263 17273171 : dim = isl_basic_map_dim(bmap, type);
2264 17273171 : isl_assert(bmap->ctx, first + n <= dim, goto error);
2265 :
2266 17273171 : if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2267 236773 : return bmap;
2268 :
2269 17036398 : bmap = isl_basic_map_cow(bmap);
2270 17036398 : if (!bmap)
2271 0 : return NULL;
2272 :
2273 17036398 : offset = isl_basic_map_offset(bmap, type) + first;
2274 17036398 : left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
2275 17036556 : for (i = 0; i < bmap->n_eq; ++i)
2276 158 : constraint_drop_vars(bmap->eq[i]+offset, n, left);
2277 :
2278 53727425 : for (i = 0; i < bmap->n_ineq; ++i)
2279 36691027 : constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2280 :
2281 17036398 : for (i = 0; i < bmap->n_div; ++i)
2282 0 : constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2283 :
2284 17036398 : if (type == isl_dim_div) {
2285 0 : bmap = move_divs_last(bmap, first, n);
2286 0 : if (!bmap)
2287 0 : goto error;
2288 0 : if (isl_basic_map_free_div(bmap, n) < 0)
2289 0 : return isl_basic_map_free(bmap);
2290 : } else
2291 17036398 : bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2292 17036398 : if (!bmap->dim)
2293 0 : goto error;
2294 :
2295 17036398 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2296 17036398 : bmap = isl_basic_map_simplify(bmap);
2297 17036398 : return isl_basic_map_finalize(bmap);
2298 : error:
2299 0 : isl_basic_map_free(bmap);
2300 0 : return NULL;
2301 : }
2302 :
2303 476628 : __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2304 : enum isl_dim_type type, unsigned first, unsigned n)
2305 : {
2306 476628 : return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2307 : type, first, n));
2308 : }
2309 :
2310 : /* No longer consider "map" to be normalized.
2311 : */
2312 14162872024 : static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2313 : {
2314 14162872024 : if (!map)
2315 0 : return NULL;
2316 14162872024 : ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2317 14162872024 : return map;
2318 : }
2319 :
2320 0 : __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2321 : enum isl_dim_type type, unsigned first, unsigned n)
2322 : {
2323 : int i;
2324 :
2325 0 : if (isl_map_check_range(map, type, first, n) < 0)
2326 0 : return isl_map_free(map);
2327 :
2328 0 : if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2329 0 : return map;
2330 0 : map = isl_map_cow(map);
2331 0 : if (!map)
2332 0 : goto error;
2333 0 : map->dim = isl_space_drop_dims(map->dim, type, first, n);
2334 0 : if (!map->dim)
2335 0 : goto error;
2336 :
2337 0 : for (i = 0; i < map->n; ++i) {
2338 0 : map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2339 0 : if (!map->p[i])
2340 0 : goto error;
2341 : }
2342 0 : map = isl_map_unmark_normalized(map);
2343 :
2344 0 : return map;
2345 : error:
2346 0 : isl_map_free(map);
2347 0 : return NULL;
2348 : }
2349 :
2350 0 : __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2351 : enum isl_dim_type type, unsigned first, unsigned n)
2352 : {
2353 0 : return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2354 : }
2355 :
2356 : /*
2357 : * We don't cow, as the div is assumed to be redundant.
2358 : */
2359 0 : __isl_give isl_basic_map *isl_basic_map_drop_div(
2360 : __isl_take isl_basic_map *bmap, unsigned div)
2361 : {
2362 : int i;
2363 : unsigned pos;
2364 :
2365 0 : if (!bmap)
2366 0 : goto error;
2367 :
2368 0 : pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
2369 :
2370 0 : isl_assert(bmap->ctx, div < bmap->n_div, goto error);
2371 :
2372 0 : for (i = 0; i < bmap->n_eq; ++i)
2373 0 : constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
2374 :
2375 0 : for (i = 0; i < bmap->n_ineq; ++i) {
2376 0 : if (!isl_int_is_zero(bmap->ineq[i][pos])) {
2377 0 : isl_basic_map_drop_inequality(bmap, i);
2378 0 : --i;
2379 0 : continue;
2380 : }
2381 0 : constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
2382 : }
2383 :
2384 0 : for (i = 0; i < bmap->n_div; ++i)
2385 0 : constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
2386 :
2387 0 : if (div != bmap->n_div - 1) {
2388 : int j;
2389 0 : isl_int *t = bmap->div[div];
2390 :
2391 0 : for (j = div; j < bmap->n_div - 1; ++j)
2392 0 : bmap->div[j] = bmap->div[j+1];
2393 :
2394 0 : bmap->div[bmap->n_div - 1] = t;
2395 : }
2396 0 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2397 0 : if (isl_basic_map_free_div(bmap, 1) < 0)
2398 0 : return isl_basic_map_free(bmap);
2399 :
2400 0 : return bmap;
2401 : error:
2402 0 : isl_basic_map_free(bmap);
2403 0 : return NULL;
2404 : }
2405 :
2406 : /* Eliminate the specified n dimensions starting at first from the
2407 : * constraints, without removing the dimensions from the space.
2408 : * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2409 : */
2410 0 : __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2411 : enum isl_dim_type type, unsigned first, unsigned n)
2412 : {
2413 : int i;
2414 :
2415 0 : if (n == 0)
2416 0 : return map;
2417 :
2418 0 : if (isl_map_check_range(map, type, first, n) < 0)
2419 0 : return isl_map_free(map);
2420 :
2421 0 : map = isl_map_cow(map);
2422 0 : if (!map)
2423 0 : return NULL;
2424 :
2425 0 : for (i = 0; i < map->n; ++i) {
2426 0 : map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2427 0 : if (!map->p[i])
2428 0 : goto error;
2429 : }
2430 0 : return map;
2431 : error:
2432 0 : isl_map_free(map);
2433 0 : return NULL;
2434 : }
2435 :
2436 : /* Eliminate the specified n dimensions starting at first from the
2437 : * constraints, without removing the dimensions from the space.
2438 : * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2439 : */
2440 0 : __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2441 : enum isl_dim_type type, unsigned first, unsigned n)
2442 : {
2443 0 : return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2444 : }
2445 :
2446 : /* Eliminate the specified n dimensions starting at first from the
2447 : * constraints, without removing the dimensions from the space.
2448 : * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2449 : */
2450 0 : __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2451 : unsigned first, unsigned n)
2452 : {
2453 0 : return isl_set_eliminate(set, isl_dim_set, first, n);
2454 : }
2455 :
2456 0 : __isl_give isl_basic_map *isl_basic_map_remove_divs(
2457 : __isl_take isl_basic_map *bmap)
2458 : {
2459 0 : if (!bmap)
2460 0 : return NULL;
2461 0 : bmap = isl_basic_map_eliminate_vars(bmap,
2462 : isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
2463 0 : if (!bmap)
2464 0 : return NULL;
2465 0 : bmap->n_div = 0;
2466 0 : return isl_basic_map_finalize(bmap);
2467 : }
2468 :
2469 0 : __isl_give isl_basic_set *isl_basic_set_remove_divs(
2470 : __isl_take isl_basic_set *bset)
2471 : {
2472 0 : return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2473 : }
2474 :
2475 0 : __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2476 : {
2477 : int i;
2478 :
2479 0 : if (!map)
2480 0 : return NULL;
2481 0 : if (map->n == 0)
2482 0 : return map;
2483 :
2484 0 : map = isl_map_cow(map);
2485 0 : if (!map)
2486 0 : return NULL;
2487 :
2488 0 : for (i = 0; i < map->n; ++i) {
2489 0 : map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2490 0 : if (!map->p[i])
2491 0 : goto error;
2492 : }
2493 0 : return map;
2494 : error:
2495 0 : isl_map_free(map);
2496 0 : return NULL;
2497 : }
2498 :
2499 0 : __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2500 : {
2501 0 : return isl_map_remove_divs(set);
2502 : }
2503 :
2504 7702949 : __isl_give isl_basic_map *isl_basic_map_remove_dims(
2505 : __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2506 : unsigned first, unsigned n)
2507 : {
2508 7702949 : if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2509 0 : return isl_basic_map_free(bmap);
2510 7702949 : if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2511 6950224 : return bmap;
2512 752725 : bmap = isl_basic_map_eliminate_vars(bmap,
2513 752725 : isl_basic_map_offset(bmap, type) - 1 + first, n);
2514 752725 : if (!bmap)
2515 0 : return bmap;
2516 752725 : if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2517 0 : return bmap;
2518 752725 : bmap = isl_basic_map_drop(bmap, type, first, n);
2519 752725 : return bmap;
2520 : }
2521 :
2522 : /* Return true if the definition of the given div (recursively) involves
2523 : * any of the given variables.
2524 : */
2525 0 : static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2526 : unsigned first, unsigned n)
2527 : {
2528 : int i;
2529 0 : unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2530 :
2531 0 : if (isl_int_is_zero(bmap->div[div][0]))
2532 0 : return isl_bool_false;
2533 0 : if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2534 0 : return isl_bool_true;
2535 :
2536 0 : for (i = bmap->n_div - 1; i >= 0; --i) {
2537 : isl_bool involves;
2538 :
2539 0 : if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2540 0 : continue;
2541 0 : involves = div_involves_vars(bmap, i, first, n);
2542 0 : if (involves < 0 || involves)
2543 0 : return involves;
2544 : }
2545 :
2546 0 : return isl_bool_false;
2547 : }
2548 :
2549 : /* Try and add a lower and/or upper bound on "div" to "bmap"
2550 : * based on inequality "i".
2551 : * "total" is the total number of variables (excluding the divs).
2552 : * "v" is a temporary object that can be used during the calculations.
2553 : * If "lb" is set, then a lower bound should be constructed.
2554 : * If "ub" is set, then an upper bound should be constructed.
2555 : *
2556 : * The calling function has already checked that the inequality does not
2557 : * reference "div", but we still need to check that the inequality is
2558 : * of the right form. We'll consider the case where we want to construct
2559 : * a lower bound. The construction of upper bounds is similar.
2560 : *
2561 : * Let "div" be of the form
2562 : *
2563 : * q = floor((a + f(x))/d)
2564 : *
2565 : * We essentially check if constraint "i" is of the form
2566 : *
2567 : * b + f(x) >= 0
2568 : *
2569 : * so that we can use it to derive a lower bound on "div".
2570 : * However, we allow a slightly more general form
2571 : *
2572 : * b + g(x) >= 0
2573 : *
2574 : * with the condition that the coefficients of g(x) - f(x) are all
2575 : * divisible by d.
2576 : * Rewriting this constraint as
2577 : *
2578 : * 0 >= -b - g(x)
2579 : *
2580 : * adding a + f(x) to both sides and dividing by d, we obtain
2581 : *
2582 : * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2583 : *
2584 : * Taking the floor on both sides, we obtain
2585 : *
2586 : * q >= floor((a-b)/d) + (f(x)-g(x))/d
2587 : *
2588 : * or
2589 : *
2590 : * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2591 : *
2592 : * In the case of an upper bound, we construct the constraint
2593 : *
2594 : * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2595 : *
2596 : */
2597 0 : static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2598 : __isl_take isl_basic_map *bmap, int div, int i,
2599 : unsigned total, isl_int v, int lb, int ub)
2600 : {
2601 : int j;
2602 :
2603 0 : for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2604 0 : if (lb) {
2605 0 : isl_int_sub(v, bmap->ineq[i][1 + j],
2606 : bmap->div[div][1 + 1 + j]);
2607 0 : lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2608 : }
2609 0 : if (ub) {
2610 0 : isl_int_add(v, bmap->ineq[i][1 + j],
2611 : bmap->div[div][1 + 1 + j]);
2612 0 : ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2613 : }
2614 : }
2615 0 : if (!lb && !ub)
2616 0 : return bmap;
2617 :
2618 0 : bmap = isl_basic_map_cow(bmap);
2619 0 : bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2620 0 : if (lb) {
2621 0 : int k = isl_basic_map_alloc_inequality(bmap);
2622 0 : if (k < 0)
2623 0 : goto error;
2624 0 : for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2625 0 : isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2626 : bmap->div[div][1 + j]);
2627 0 : isl_int_cdiv_q(bmap->ineq[k][j],
2628 : bmap->ineq[k][j], bmap->div[div][0]);
2629 : }
2630 0 : isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2631 : }
2632 0 : if (ub) {
2633 0 : int k = isl_basic_map_alloc_inequality(bmap);
2634 0 : if (k < 0)
2635 0 : goto error;
2636 0 : for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2637 0 : isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2638 : bmap->div[div][1 + j]);
2639 0 : isl_int_fdiv_q(bmap->ineq[k][j],
2640 : bmap->ineq[k][j], bmap->div[div][0]);
2641 : }
2642 0 : isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2643 : }
2644 :
2645 0 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2646 0 : return bmap;
2647 : error:
2648 0 : isl_basic_map_free(bmap);
2649 0 : return NULL;
2650 : }
2651 :
2652 : /* This function is called right before "div" is eliminated from "bmap"
2653 : * using Fourier-Motzkin.
2654 : * Look through the constraints of "bmap" for constraints on the argument
2655 : * of the integer division and use them to construct constraints on the
2656 : * integer division itself. These constraints can then be combined
2657 : * during the Fourier-Motzkin elimination.
2658 : * Note that it is only useful to introduce lower bounds on "div"
2659 : * if "bmap" already contains upper bounds on "div" as the newly
2660 : * introduce lower bounds can then be combined with the pre-existing
2661 : * upper bounds. Similarly for upper bounds.
2662 : * We therefore first check if "bmap" contains any lower and/or upper bounds
2663 : * on "div".
2664 : *
2665 : * It is interesting to note that the introduction of these constraints
2666 : * can indeed lead to more accurate results, even when compared to
2667 : * deriving constraints on the argument of "div" from constraints on "div".
2668 : * Consider, for example, the set
2669 : *
2670 : * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2671 : *
2672 : * The second constraint can be rewritten as
2673 : *
2674 : * 2 * [(-i-2j+3)/4] + k >= 0
2675 : *
2676 : * from which we can derive
2677 : *
2678 : * -i - 2j + 3 >= -2k
2679 : *
2680 : * or
2681 : *
2682 : * i + 2j <= 3 + 2k
2683 : *
2684 : * Combined with the first constraint, we obtain
2685 : *
2686 : * -3 <= 3 + 2k or k >= -3
2687 : *
2688 : * If, on the other hand we derive a constraint on [(i+2j)/4] from
2689 : * the first constraint, we obtain
2690 : *
2691 : * [(i + 2j)/4] >= [-3/4] = -1
2692 : *
2693 : * Combining this constraint with the second constraint, we obtain
2694 : *
2695 : * k >= -2
2696 : */
2697 0 : static __isl_give isl_basic_map *insert_bounds_on_div(
2698 : __isl_take isl_basic_map *bmap, int div)
2699 : {
2700 : int i;
2701 : int check_lb, check_ub;
2702 : isl_int v;
2703 : unsigned total;
2704 :
2705 0 : if (!bmap)
2706 0 : return NULL;
2707 :
2708 0 : if (isl_int_is_zero(bmap->div[div][0]))
2709 0 : return bmap;
2710 :
2711 0 : total = isl_space_dim(bmap->dim, isl_dim_all);
2712 :
2713 0 : check_lb = 0;
2714 0 : check_ub = 0;
2715 0 : for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2716 0 : int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2717 0 : if (s > 0)
2718 0 : check_ub = 1;
2719 0 : if (s < 0)
2720 0 : check_lb = 1;
2721 : }
2722 :
2723 0 : if (!check_lb && !check_ub)
2724 0 : return bmap;
2725 :
2726 0 : isl_int_init(v);
2727 :
2728 0 : for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2729 0 : if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2730 0 : continue;
2731 :
2732 0 : bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2733 : check_lb, check_ub);
2734 : }
2735 :
2736 0 : isl_int_clear(v);
2737 :
2738 0 : return bmap;
2739 : }
2740 :
2741 : /* Remove all divs (recursively) involving any of the given dimensions
2742 : * in their definitions.
2743 : */
2744 0 : __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2745 : __isl_take isl_basic_map *bmap,
2746 : enum isl_dim_type type, unsigned first, unsigned n)
2747 : {
2748 : int i;
2749 :
2750 0 : if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2751 0 : return isl_basic_map_free(bmap);
2752 0 : first += isl_basic_map_offset(bmap, type);
2753 :
2754 0 : for (i = bmap->n_div - 1; i >= 0; --i) {
2755 : isl_bool involves;
2756 :
2757 0 : involves = div_involves_vars(bmap, i, first, n);
2758 0 : if (involves < 0)
2759 0 : return isl_basic_map_free(bmap);
2760 0 : if (!involves)
2761 0 : continue;
2762 0 : bmap = insert_bounds_on_div(bmap, i);
2763 0 : bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2764 0 : if (!bmap)
2765 0 : return NULL;
2766 0 : i = bmap->n_div;
2767 : }
2768 :
2769 0 : return bmap;
2770 : }
2771 :
2772 0 : __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2773 : __isl_take isl_basic_set *bset,
2774 : enum isl_dim_type type, unsigned first, unsigned n)
2775 : {
2776 0 : return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2777 : }
2778 :
2779 0 : __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2780 : enum isl_dim_type type, unsigned first, unsigned n)
2781 : {
2782 : int i;
2783 :
2784 0 : if (!map)
2785 0 : return NULL;
2786 0 : if (map->n == 0)
2787 0 : return map;
2788 :
2789 0 : map = isl_map_cow(map);
2790 0 : if (!map)
2791 0 : return NULL;
2792 :
2793 0 : for (i = 0; i < map->n; ++i) {
2794 0 : map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2795 : type, first, n);
2796 0 : if (!map->p[i])
2797 0 : goto error;
2798 : }
2799 0 : return map;
2800 : error:
2801 0 : isl_map_free(map);
2802 0 : return NULL;
2803 : }
2804 :
2805 0 : __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2806 : enum isl_dim_type type, unsigned first, unsigned n)
2807 : {
2808 0 : return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2809 : type, first, n));
2810 : }
2811 :
2812 : /* Does the description of "bmap" depend on the specified dimensions?
2813 : * We also check whether the dimensions appear in any of the div definitions.
2814 : * In principle there is no need for this check. If the dimensions appear
2815 : * in a div definition, they also appear in the defining constraints of that
2816 : * div.
2817 : */
2818 0 : isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2819 : enum isl_dim_type type, unsigned first, unsigned n)
2820 : {
2821 : int i;
2822 :
2823 0 : if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2824 0 : return isl_bool_error;
2825 :
2826 0 : first += isl_basic_map_offset(bmap, type);
2827 0 : for (i = 0; i < bmap->n_eq; ++i)
2828 0 : if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2829 0 : return isl_bool_true;
2830 0 : for (i = 0; i < bmap->n_ineq; ++i)
2831 0 : if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2832 0 : return isl_bool_true;
2833 0 : for (i = 0; i < bmap->n_div; ++i) {
2834 0 : if (isl_int_is_zero(bmap->div[i][0]))
2835 0 : continue;
2836 0 : if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2837 0 : return isl_bool_true;
2838 : }
2839 :
2840 0 : return isl_bool_false;
2841 : }
2842 :
2843 0 : isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2844 : enum isl_dim_type type, unsigned first, unsigned n)
2845 : {
2846 : int i;
2847 :
2848 0 : if (isl_map_check_range(map, type, first, n) < 0)
2849 0 : return isl_bool_error;
2850 :
2851 0 : for (i = 0; i < map->n; ++i) {
2852 0 : isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2853 : type, first, n);
2854 0 : if (involves < 0 || involves)
2855 0 : return involves;
2856 : }
2857 :
2858 0 : return isl_bool_false;
2859 : }
2860 :
2861 0 : isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2862 : enum isl_dim_type type, unsigned first, unsigned n)
2863 : {
2864 0 : return isl_basic_map_involves_dims(bset, type, first, n);
2865 : }
2866 :
2867 0 : isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2868 : enum isl_dim_type type, unsigned first, unsigned n)
2869 : {
2870 0 : return isl_map_involves_dims(set, type, first, n);
2871 : }
2872 :
2873 : /* Drop all constraints in bmap that involve any of the dimensions
2874 : * first to first+n-1.
2875 : */
2876 16520446 : static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2877 : __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2878 : {
2879 : int i;
2880 :
2881 16520446 : if (n == 0)
2882 236773 : return bmap;
2883 :
2884 16283673 : bmap = isl_basic_map_cow(bmap);
2885 :
2886 16283673 : if (!bmap)
2887 0 : return NULL;
2888 :
2889 16283831 : for (i = bmap->n_eq - 1; i >= 0; --i) {
2890 158 : if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2891 158 : continue;
2892 0 : isl_basic_map_drop_equality(bmap, i);
2893 : }
2894 :
2895 127042799 : for (i = bmap->n_ineq - 1; i >= 0; --i) {
2896 110759126 : if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2897 33790740 : continue;
2898 76968386 : isl_basic_map_drop_inequality(bmap, i);
2899 : }
2900 :
2901 16283673 : bmap = isl_basic_map_add_known_div_constraints(bmap);
2902 16283673 : return bmap;
2903 : }
2904 :
2905 : /* Drop all constraints in bset that involve any of the dimensions
2906 : * first to first+n-1.
2907 : */
2908 16520446 : __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2909 : __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2910 : {
2911 16520446 : return isl_basic_map_drop_constraints_involving(bset, first, n);
2912 : }
2913 :
2914 : /* Drop all constraints in bmap that do not involve any of the dimensions
2915 : * first to first + n - 1 of the given type.
2916 : */
2917 0 : __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2918 : __isl_take isl_basic_map *bmap,
2919 : enum isl_dim_type type, unsigned first, unsigned n)
2920 : {
2921 : int i;
2922 :
2923 0 : if (n == 0) {
2924 0 : isl_space *space = isl_basic_map_get_space(bmap);
2925 0 : isl_basic_map_free(bmap);
2926 0 : return isl_basic_map_universe(space);
2927 : }
2928 0 : bmap = isl_basic_map_cow(bmap);
2929 0 : if (!bmap)
2930 0 : return NULL;
2931 :
2932 0 : if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2933 0 : return isl_basic_map_free(bmap);
2934 :
2935 0 : first += isl_basic_map_offset(bmap, type) - 1;
2936 :
2937 0 : for (i = bmap->n_eq - 1; i >= 0; --i) {
2938 0 : if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2939 0 : continue;
2940 0 : isl_basic_map_drop_equality(bmap, i);
2941 : }
2942 :
2943 0 : for (i = bmap->n_ineq - 1; i >= 0; --i) {
2944 0 : if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2945 0 : continue;
2946 0 : isl_basic_map_drop_inequality(bmap, i);
2947 : }
2948 :
2949 0 : bmap = isl_basic_map_add_known_div_constraints(bmap);
2950 0 : return bmap;
2951 : }
2952 :
2953 : /* Drop all constraints in bset that do not involve any of the dimensions
2954 : * first to first + n - 1 of the given type.
2955 : */
2956 0 : __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2957 : __isl_take isl_basic_set *bset,
2958 : enum isl_dim_type type, unsigned first, unsigned n)
2959 : {
2960 0 : return isl_basic_map_drop_constraints_not_involving_dims(bset,
2961 : type, first, n);
2962 : }
2963 :
2964 : /* Drop all constraints in bmap that involve any of the dimensions
2965 : * first to first + n - 1 of the given type.
2966 : */
2967 2898920016 : __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2968 : __isl_take isl_basic_map *bmap,
2969 : enum isl_dim_type type, unsigned first, unsigned n)
2970 : {
2971 2898920016 : if (!bmap)
2972 0 : return NULL;
2973 2898920016 : if (n == 0)
2974 2898920016 : return bmap;
2975 :
2976 0 : if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2977 0 : return isl_basic_map_free(bmap);
2978 :
2979 0 : bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2980 0 : first += isl_basic_map_offset(bmap, type) - 1;
2981 0 : return isl_basic_map_drop_constraints_involving(bmap, first, n);
2982 : }
2983 :
2984 : /* Drop all constraints in bset that involve any of the dimensions
2985 : * first to first + n - 1 of the given type.
2986 : */
2987 0 : __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2988 : __isl_take isl_basic_set *bset,
2989 : enum isl_dim_type type, unsigned first, unsigned n)
2990 : {
2991 0 : return isl_basic_map_drop_constraints_involving_dims(bset,
2992 : type, first, n);
2993 : }
2994 :
2995 : /* Drop constraints from "map" by applying "drop" to each basic map.
2996 : */
2997 0 : static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2998 : enum isl_dim_type type, unsigned first, unsigned n,
2999 : __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
3000 : enum isl_dim_type type, unsigned first, unsigned n))
3001 : {
3002 : int i;
3003 :
3004 0 : if (isl_map_check_range(map, type, first, n) < 0)
3005 0 : return isl_map_free(map);
3006 :
3007 0 : map = isl_map_cow(map);
3008 0 : if (!map)
3009 0 : return NULL;
3010 :
3011 0 : for (i = 0; i < map->n; ++i) {
3012 0 : map->p[i] = drop(map->p[i], type, first, n);
3013 0 : if (!map->p[i])
3014 0 : return isl_map_free(map);
3015 : }
3016 :
3017 0 : if (map->n > 1)
3018 0 : ISL_F_CLR(map, ISL_MAP_DISJOINT);
3019 :
3020 0 : return map;
3021 : }
3022 :
3023 : /* Drop all constraints in map that involve any of the dimensions
3024 : * first to first + n - 1 of the given type.
3025 : */
3026 0 : __isl_give isl_map *isl_map_drop_constraints_involving_dims(
3027 : __isl_take isl_map *map,
3028 : enum isl_dim_type type, unsigned first, unsigned n)
3029 : {
3030 0 : if (n == 0)
3031 0 : return map;
3032 0 : return drop_constraints(map, type, first, n,
3033 : &isl_basic_map_drop_constraints_involving_dims);
3034 : }
3035 :
3036 : /* Drop all constraints in "map" that do not involve any of the dimensions
3037 : * first to first + n - 1 of the given type.
3038 : */
3039 0 : __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3040 : __isl_take isl_map *map,
3041 : enum isl_dim_type type, unsigned first, unsigned n)
3042 : {
3043 0 : if (n == 0) {
3044 0 : isl_space *space = isl_map_get_space(map);
3045 0 : isl_map_free(map);
3046 0 : return isl_map_universe(space);
3047 : }
3048 0 : return drop_constraints(map, type, first, n,
3049 : &isl_basic_map_drop_constraints_not_involving_dims);
3050 : }
3051 :
3052 : /* Drop all constraints in set that involve any of the dimensions
3053 : * first to first + n - 1 of the given type.
3054 : */
3055 0 : __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3056 : __isl_take isl_set *set,
3057 : enum isl_dim_type type, unsigned first, unsigned n)
3058 : {
3059 0 : return isl_map_drop_constraints_involving_dims(set, type, first, n);
3060 : }
3061 :
3062 : /* Drop all constraints in "set" that do not involve any of the dimensions
3063 : * first to first + n - 1 of the given type.
3064 : */
3065 0 : __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3066 : __isl_take isl_set *set,
3067 : enum isl_dim_type type, unsigned first, unsigned n)
3068 : {
3069 0 : return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3070 : }
3071 :
3072 : /* Does local variable "div" of "bmap" have a complete explicit representation?
3073 : * Having a complete explicit representation requires not only
3074 : * an explicit representation, but also that all local variables
3075 : * that appear in this explicit representation in turn have
3076 : * a complete explicit representation.
3077 : */
3078 0 : isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3079 : {
3080 : int i;
3081 0 : unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3082 : isl_bool marked;
3083 :
3084 0 : marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3085 0 : if (marked < 0 || marked)
3086 0 : return isl_bool_not(marked);
3087 :
3088 0 : for (i = bmap->n_div - 1; i >= 0; --i) {
3089 : isl_bool known;
3090 :
3091 0 : if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3092 0 : continue;
3093 0 : known = isl_basic_map_div_is_known(bmap, i);
3094 0 : if (known < 0 || !known)
3095 0 : return known;
3096 : }
3097 :
3098 0 : return isl_bool_true;
3099 : }
3100 :
3101 : /* Remove all divs that are unknown or defined in terms of unknown divs.
3102 : */
3103 1188543038 : __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3104 : __isl_take isl_basic_map *bmap)
3105 : {
3106 : int i;
3107 :
3108 1188543038 : if (!bmap)
3109 0 : return NULL;
3110 :
3111 1188543038 : for (i = bmap->n_div - 1; i >= 0; --i) {
3112 0 : if (isl_basic_map_div_is_known(bmap, i))
3113 0 : continue;
3114 0 : bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3115 0 : if (!bmap)
3116 0 : return NULL;
3117 0 : i = bmap->n_div;
3118 : }
3119 :
3120 1188543038 : return bmap;
3121 : }
3122 :
3123 : /* Remove all divs that are unknown or defined in terms of unknown divs.
3124 : */
3125 0 : __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3126 : __isl_take isl_basic_set *bset)
3127 : {
3128 0 : return isl_basic_map_remove_unknown_divs(bset);
3129 : }
3130 :
3131 645829553 : __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3132 : {
3133 : int i;
3134 :
3135 645829553 : if (!map)
3136 0 : return NULL;
3137 645829553 : if (map->n == 0)
3138 0 : return map;
3139 :
3140 645829553 : map = isl_map_cow(map);
3141 645829553 : if (!map)
3142 0 : return NULL;
3143 :
3144 1834372591 : for (i = 0; i < map->n; ++i) {
3145 1188543038 : map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3146 1188543038 : if (!map->p[i])
3147 0 : goto error;
3148 : }
3149 645829553 : return map;
3150 : error:
3151 0 : isl_map_free(map);
3152 0 : return NULL;
3153 : }
3154 :
3155 0 : __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3156 : {
3157 0 : return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3158 : }
3159 :
3160 7702949 : __isl_give isl_basic_set *isl_basic_set_remove_dims(
3161 : __isl_take isl_basic_set *bset,
3162 : enum isl_dim_type type, unsigned first, unsigned n)
3163 : {
3164 7702949 : isl_basic_map *bmap = bset_to_bmap(bset);
3165 7702949 : bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3166 7702949 : return bset_from_bmap(bmap);
3167 : }
3168 :
3169 0 : __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3170 : enum isl_dim_type type, unsigned first, unsigned n)
3171 : {
3172 : int i;
3173 :
3174 0 : if (n == 0)
3175 0 : return map;
3176 :
3177 0 : map = isl_map_cow(map);
3178 0 : if (isl_map_check_range(map, type, first, n) < 0)
3179 0 : return isl_map_free(map);
3180 :
3181 0 : for (i = 0; i < map->n; ++i) {
3182 0 : map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3183 0 : isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3184 0 : if (!map->p[i])
3185 0 : goto error;
3186 : }
3187 0 : map = isl_map_drop(map, type, first, n);
3188 0 : return map;
3189 : error:
3190 0 : isl_map_free(map);
3191 0 : return NULL;
3192 : }
3193 :
3194 0 : __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3195 : enum isl_dim_type type, unsigned first, unsigned n)
3196 : {
3197 0 : return set_from_map(isl_map_remove_dims(set_to_map(bset),
3198 : type, first, n));
3199 : }
3200 :
3201 : /* Project out n inputs starting at first using Fourier-Motzkin */
3202 0 : struct isl_map *isl_map_remove_inputs(struct isl_map *map,
3203 : unsigned first, unsigned n)
3204 : {
3205 0 : return isl_map_remove_dims(map, isl_dim_in, first, n);
3206 : }
3207 :
3208 0 : static void dump_term(struct isl_basic_map *bmap,
3209 : isl_int c, int pos, FILE *out)
3210 : {
3211 : const char *name;
3212 0 : unsigned in = isl_basic_map_dim(bmap, isl_dim_in);
3213 0 : unsigned dim = in + isl_basic_map_dim(bmap, isl_dim_out);
3214 0 : unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
3215 0 : if (!pos)
3216 0 : isl_int_print(out, c, 0);
3217 : else {
3218 0 : if (!isl_int_is_one(c))
3219 0 : isl_int_print(out, c, 0);
3220 0 : if (pos < 1 + nparam) {
3221 0 : name = isl_space_get_dim_name(bmap->dim,
3222 0 : isl_dim_param, pos - 1);
3223 0 : if (name)
3224 0 : fprintf(out, "%s", name);
3225 : else
3226 0 : fprintf(out, "p%d", pos - 1);
3227 0 : } else if (pos < 1 + nparam + in)
3228 0 : fprintf(out, "i%d", pos - 1 - nparam);
3229 0 : else if (pos < 1 + nparam + dim)
3230 0 : fprintf(out, "o%d", pos - 1 - nparam - in);
3231 : else
3232 0 : fprintf(out, "e%d", pos - 1 - nparam - dim);
3233 : }
3234 0 : }
3235 :
3236 0 : static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
3237 : int sign, FILE *out)
3238 : {
3239 : int i;
3240 : int first;
3241 0 : unsigned len = 1 + isl_basic_map_total_dim(bmap);
3242 : isl_int v;
3243 :
3244 0 : isl_int_init(v);
3245 0 : for (i = 0, first = 1; i < len; ++i) {
3246 0 : if (isl_int_sgn(c[i]) * sign <= 0)
3247 0 : continue;
3248 0 : if (!first)
3249 0 : fprintf(out, " + ");
3250 0 : first = 0;
3251 0 : isl_int_abs(v, c[i]);
3252 0 : dump_term(bmap, v, i, out);
3253 : }
3254 0 : isl_int_clear(v);
3255 0 : if (first)
3256 0 : fprintf(out, "0");
3257 0 : }
3258 :
3259 0 : static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
3260 : const char *op, FILE *out, int indent)
3261 : {
3262 : int i;
3263 :
3264 0 : fprintf(out, "%*s", indent, "");
3265 :
3266 0 : dump_constraint_sign(bmap, c, 1, out);
3267 0 : fprintf(out, " %s ", op);
3268 0 : dump_constraint_sign(bmap, c, -1, out);
3269 :
3270 0 : fprintf(out, "\n");
3271 :
3272 0 : for (i = bmap->n_div; i < bmap->extra; ++i) {
3273 0 : if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
3274 0 : continue;
3275 0 : fprintf(out, "%*s", indent, "");
3276 0 : fprintf(out, "ERROR: unused div coefficient not zero\n");
3277 0 : abort();
3278 : }
3279 0 : }
3280 :
3281 0 : static void dump_constraints(struct isl_basic_map *bmap,
3282 : isl_int **c, unsigned n,
3283 : const char *op, FILE *out, int indent)
3284 : {
3285 : int i;
3286 :
3287 0 : for (i = 0; i < n; ++i)
3288 0 : dump_constraint(bmap, c[i], op, out, indent);
3289 0 : }
3290 :
3291 0 : static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
3292 : {
3293 : int j;
3294 0 : int first = 1;
3295 0 : unsigned total = isl_basic_map_total_dim(bmap);
3296 :
3297 0 : for (j = 0; j < 1 + total; ++j) {
3298 0 : if (isl_int_is_zero(exp[j]))
3299 0 : continue;
3300 0 : if (!first && isl_int_is_pos(exp[j]))
3301 0 : fprintf(out, "+");
3302 0 : dump_term(bmap, exp[j], j, out);
3303 0 : first = 0;
3304 : }
3305 0 : }
3306 :
3307 0 : static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
3308 : {
3309 : int i;
3310 :
3311 0 : dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
3312 0 : dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
3313 :
3314 0 : for (i = 0; i < bmap->n_div; ++i) {
3315 0 : fprintf(out, "%*s", indent, "");
3316 0 : fprintf(out, "e%d = [(", i);
3317 0 : dump_affine(bmap, bmap->div[i]+1, out);
3318 0 : fprintf(out, ")/");
3319 0 : isl_int_print(out, bmap->div[i][0], 0);
3320 0 : fprintf(out, "]\n");
3321 : }
3322 0 : }
3323 :
3324 0 : void isl_basic_set_print_internal(struct isl_basic_set *bset,
3325 : FILE *out, int indent)
3326 : {
3327 0 : if (!bset) {
3328 0 : fprintf(out, "null basic set\n");
3329 0 : return;
3330 : }
3331 :
3332 0 : fprintf(out, "%*s", indent, "");
3333 0 : fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3334 0 : bset->ref, bset->dim->nparam, bset->dim->n_out,
3335 : bset->extra, bset->flags);
3336 0 : dump(bset_to_bmap(bset), out, indent);
3337 : }
3338 :
3339 0 : void isl_basic_map_print_internal(struct isl_basic_map *bmap,
3340 : FILE *out, int indent)
3341 : {
3342 0 : if (!bmap) {
3343 0 : fprintf(out, "null basic map\n");
3344 0 : return;
3345 : }
3346 :
3347 0 : fprintf(out, "%*s", indent, "");
3348 0 : fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3349 : "flags: %x, n_name: %d\n",
3350 : bmap->ref,
3351 0 : bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3352 0 : bmap->extra, bmap->flags, bmap->dim->n_id);
3353 0 : dump(bmap, out, indent);
3354 : }
3355 :
3356 0 : int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
3357 : {
3358 : unsigned total;
3359 0 : if (!bmap)
3360 0 : return -1;
3361 0 : total = isl_basic_map_total_dim(bmap);
3362 0 : isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
3363 0 : isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3364 0 : isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3365 0 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
3366 0 : return 0;
3367 : }
3368 :
3369 112944 : __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3370 : unsigned flags)
3371 : {
3372 112944 : if (!space)
3373 0 : return NULL;
3374 112944 : if (isl_space_dim(space, isl_dim_in) != 0)
3375 0 : isl_die(isl_space_get_ctx(space), isl_error_invalid,
3376 : "set cannot have input dimensions", goto error);
3377 112944 : return isl_map_alloc_space(space, n, flags);
3378 : error:
3379 0 : isl_space_free(space);
3380 0 : return NULL;
3381 : }
3382 :
3383 : /* Make sure "map" has room for at least "n" more basic maps.
3384 : */
3385 0 : __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3386 : {
3387 : int i;
3388 0 : struct isl_map *grown = NULL;
3389 :
3390 0 : if (!map)
3391 0 : return NULL;
3392 0 : isl_assert(map->ctx, n >= 0, goto error);
3393 0 : if (map->n + n <= map->size)
3394 0 : return map;
3395 0 : grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3396 0 : if (!grown)
3397 0 : goto error;
3398 0 : for (i = 0; i < map->n; ++i) {
3399 0 : grown->p[i] = isl_basic_map_copy(map->p[i]);
3400 0 : if (!grown->p[i])
3401 0 : goto error;
3402 0 : grown->n++;
3403 : }
3404 0 : isl_map_free(map);
3405 0 : return grown;
3406 : error:
3407 0 : isl_map_free(grown);
3408 0 : isl_map_free(map);
3409 0 : return NULL;
3410 : }
3411 :
3412 : /* Make sure "set" has room for at least "n" more basic sets.
3413 : */
3414 0 : struct isl_set *isl_set_grow(struct isl_set *set, int n)
3415 : {
3416 0 : return set_from_map(isl_map_grow(set_to_map(set), n));
3417 : }
3418 :
3419 2571461 : __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3420 : {
3421 2571461 : return isl_map_from_basic_map(bset);
3422 : }
3423 :
3424 40834706 : __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3425 : {
3426 : struct isl_map *map;
3427 :
3428 40834706 : if (!bmap)
3429 0 : return NULL;
3430 :
3431 40834706 : map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3432 40834706 : return isl_map_add_basic_map(map, bmap);
3433 : }
3434 :
3435 0 : __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3436 : __isl_take isl_basic_set *bset)
3437 : {
3438 0 : return set_from_map(isl_map_add_basic_map(set_to_map(set),
3439 : bset_to_bmap(bset)));
3440 : }
3441 :
3442 3009682364 : __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3443 : {
3444 3009682364 : return isl_map_free(set);
3445 : }
3446 :
3447 0 : void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
3448 : {
3449 : int i;
3450 :
3451 0 : if (!set) {
3452 0 : fprintf(out, "null set\n");
3453 0 : return;
3454 : }
3455 :
3456 0 : fprintf(out, "%*s", indent, "");
3457 0 : fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3458 0 : set->ref, set->n, set->dim->nparam, set->dim->n_out,
3459 : set->flags);
3460 0 : for (i = 0; i < set->n; ++i) {
3461 0 : fprintf(out, "%*s", indent, "");
3462 0 : fprintf(out, "basic set %d:\n", i);
3463 0 : isl_basic_set_print_internal(set->p[i], out, indent+4);
3464 : }
3465 : }
3466 :
3467 0 : void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3468 : {
3469 : int i;
3470 :
3471 0 : if (!map) {
3472 0 : fprintf(out, "null map\n");
3473 0 : return;
3474 : }
3475 :
3476 0 : fprintf(out, "%*s", indent, "");
3477 0 : fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3478 : "flags: %x, n_name: %d\n",
3479 0 : map->ref, map->n, map->dim->nparam, map->dim->n_in,
3480 0 : map->dim->n_out, map->flags, map->dim->n_id);
3481 0 : for (i = 0; i < map->n; ++i) {
3482 0 : fprintf(out, "%*s", indent, "");
3483 0 : fprintf(out, "basic map %d:\n", i);
3484 0 : isl_basic_map_print_internal(map->p[i], out, indent+4);
3485 : }
3486 : }
3487 :
3488 0 : __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3489 : __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3490 : {
3491 : struct isl_basic_map *bmap_domain;
3492 :
3493 0 : if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3494 0 : goto error;
3495 :
3496 0 : if (isl_space_dim(bset->dim, isl_dim_set) != 0)
3497 0 : isl_assert(bset->ctx,
3498 : isl_basic_map_compatible_domain(bmap, bset), goto error);
3499 :
3500 0 : bmap = isl_basic_map_cow(bmap);
3501 0 : if (!bmap)
3502 0 : goto error;
3503 0 : bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3504 : bset->n_div, bset->n_eq, bset->n_ineq);
3505 0 : bmap_domain = isl_basic_map_from_domain(bset);
3506 0 : bmap = add_constraints(bmap, bmap_domain, 0, 0);
3507 :
3508 0 : bmap = isl_basic_map_simplify(bmap);
3509 0 : return isl_basic_map_finalize(bmap);
3510 : error:
3511 0 : isl_basic_map_free(bmap);
3512 0 : isl_basic_set_free(bset);
3513 0 : return NULL;
3514 : }
3515 :
3516 : /* Check that the space of "bset" is the same as that of the range of "bmap".
3517 : */
3518 0 : static isl_stat isl_basic_map_check_compatible_range(
3519 : __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3520 : {
3521 : isl_bool ok;
3522 :
3523 0 : ok = isl_basic_map_compatible_range(bmap, bset);
3524 0 : if (ok < 0)
3525 0 : return isl_stat_error;
3526 0 : if (!ok)
3527 0 : isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3528 : "incompatible spaces", return isl_stat_error);
3529 :
3530 0 : return isl_stat_ok;
3531 : }
3532 :
3533 0 : __isl_give isl_basic_map *isl_basic_map_intersect_range(
3534 : __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3535 : {
3536 : struct isl_basic_map *bmap_range;
3537 :
3538 0 : if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3539 0 : goto error;
3540 :
3541 0 : if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
3542 0 : isl_basic_map_check_compatible_range(bmap, bset) < 0)
3543 0 : goto error;
3544 :
3545 0 : if (isl_basic_set_plain_is_universe(bset)) {
3546 0 : isl_basic_set_free(bset);
3547 0 : return bmap;
3548 : }
3549 :
3550 0 : bmap = isl_basic_map_cow(bmap);
3551 0 : if (!bmap)
3552 0 : goto error;
3553 0 : bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3554 : bset->n_div, bset->n_eq, bset->n_ineq);
3555 0 : bmap_range = bset_to_bmap(bset);
3556 0 : bmap = add_constraints(bmap, bmap_range, 0, 0);
3557 :
3558 0 : bmap = isl_basic_map_simplify(bmap);
3559 0 : return isl_basic_map_finalize(bmap);
3560 : error:
3561 0 : isl_basic_map_free(bmap);
3562 0 : isl_basic_set_free(bset);
3563 0 : return NULL;
3564 : }
3565 :
3566 406736124 : isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3567 : __isl_keep isl_vec *vec)
3568 : {
3569 : int i;
3570 : unsigned total;
3571 : isl_int s;
3572 :
3573 406736124 : if (!bmap || !vec)
3574 0 : return isl_bool_error;
3575 :
3576 406736124 : total = 1 + isl_basic_map_total_dim(bmap);
3577 406736124 : if (total != vec->size)
3578 0 : return isl_bool_false;
3579 :
3580 406736124 : isl_int_init(s);
3581 :
3582 663412738 : for (i = 0; i < bmap->n_eq; ++i) {
3583 328637149 : isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3584 328637149 : if (!isl_int_is_zero(s)) {
3585 71960535 : isl_int_clear(s);
3586 71960535 : return isl_bool_false;
3587 : }
3588 : }
3589 :
3590 2087255628 : for (i = 0; i < bmap->n_ineq; ++i) {
3591 1925713169 : isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3592 1925713169 : if (isl_int_is_neg(s)) {
3593 173233130 : isl_int_clear(s);
3594 173233130 : return isl_bool_false;
3595 : }
3596 : }
3597 :
3598 161542459 : isl_int_clear(s);
3599 :
3600 161542459 : return isl_bool_true;
3601 : }
3602 :
3603 3188338 : isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3604 : __isl_keep isl_vec *vec)
3605 : {
3606 3188338 : return isl_basic_map_contains(bset_to_bmap(bset), vec);
3607 : }
3608 :
3609 110183997 : __isl_give isl_basic_map *isl_basic_map_intersect(
3610 : __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3611 : {
3612 110183997 : struct isl_vec *sample = NULL;
3613 :
3614 110183997 : if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3615 0 : goto error;
3616 220367994 : if (isl_space_dim(bmap1->dim, isl_dim_all) ==
3617 110183997 : isl_space_dim(bmap1->dim, isl_dim_param) &&
3618 0 : isl_space_dim(bmap2->dim, isl_dim_all) !=
3619 0 : isl_space_dim(bmap2->dim, isl_dim_param))
3620 0 : return isl_basic_map_intersect(bmap2, bmap1);
3621 :
3622 220367994 : if (isl_space_dim(bmap2->dim, isl_dim_all) !=
3623 110183997 : isl_space_dim(bmap2->dim, isl_dim_param))
3624 110183997 : isl_assert(bmap1->ctx,
3625 : isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3626 :
3627 110183997 : if (isl_basic_map_plain_is_empty(bmap1)) {
3628 0 : isl_basic_map_free(bmap2);
3629 0 : return bmap1;
3630 : }
3631 110183997 : if (isl_basic_map_plain_is_empty(bmap2)) {
3632 0 : isl_basic_map_free(bmap1);
3633 0 : return bmap2;
3634 : }
3635 :
3636 219984580 : if (bmap1->sample &&
3637 219564605 : isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3638 109764022 : isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3639 4965551 : sample = isl_vec_copy(bmap1->sample);
3640 210227554 : else if (bmap2->sample &&
3641 106269363 : isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3642 1260255 : isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3643 1260013 : sample = isl_vec_copy(bmap2->sample);
3644 :
3645 110183997 : bmap1 = isl_basic_map_cow(bmap1);
3646 110183997 : if (!bmap1)
3647 0 : goto error;
3648 110183997 : bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3649 : bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3650 110183997 : bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3651 :
3652 110183997 : if (!bmap1)
3653 0 : isl_vec_free(sample);
3654 110183997 : else if (sample) {
3655 6225564 : isl_vec_free(bmap1->sample);
3656 6225564 : bmap1->sample = sample;
3657 : }
3658 :
3659 110183997 : bmap1 = isl_basic_map_simplify(bmap1);
3660 110183997 : return isl_basic_map_finalize(bmap1);
3661 : error:
3662 0 : if (sample)
3663 0 : isl_vec_free(sample);
3664 0 : isl_basic_map_free(bmap1);
3665 0 : isl_basic_map_free(bmap2);
3666 0 : return NULL;
3667 : }
3668 :
3669 200179 : struct isl_basic_set *isl_basic_set_intersect(
3670 : struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3671 : {
3672 200179 : return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3673 : bset_to_bmap(bset2)));
3674 : }
3675 :
3676 0 : __isl_give isl_basic_set *isl_basic_set_intersect_params(
3677 : __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3678 : {
3679 0 : return isl_basic_set_intersect(bset1, bset2);
3680 : }
3681 :
3682 : /* Special case of isl_map_intersect, where both map1 and map2
3683 : * are convex, without any divs and such that either map1 or map2
3684 : * contains a single constraint. This constraint is then simply
3685 : * added to the other map.
3686 : */
3687 0 : static __isl_give isl_map *map_intersect_add_constraint(
3688 : __isl_take isl_map *map1, __isl_take isl_map *map2)
3689 : {
3690 0 : isl_assert(map1->ctx, map1->n == 1, goto error);
3691 0 : isl_assert(map2->ctx, map1->n == 1, goto error);
3692 0 : isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3693 0 : isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3694 :
3695 0 : if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3696 0 : return isl_map_intersect(map2, map1);
3697 :
3698 0 : map1 = isl_map_cow(map1);
3699 0 : if (!map1)
3700 0 : goto error;
3701 0 : if (isl_map_plain_is_empty(map1)) {
3702 0 : isl_map_free(map2);
3703 0 : return map1;
3704 : }
3705 0 : map1->p[0] = isl_basic_map_cow(map1->p[0]);
3706 0 : if (map2->p[0]->n_eq == 1)
3707 0 : map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3708 : else
3709 0 : map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3710 0 : map2->p[0]->ineq[0]);
3711 :
3712 0 : map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3713 0 : map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3714 0 : if (!map1->p[0])
3715 0 : goto error;
3716 :
3717 0 : if (isl_basic_map_plain_is_empty(map1->p[0])) {
3718 0 : isl_basic_map_free(map1->p[0]);
3719 0 : map1->n = 0;
3720 : }
3721 :
3722 0 : isl_map_free(map2);
3723 :
3724 0 : map1 = isl_map_unmark_normalized(map1);
3725 0 : return map1;
3726 : error:
3727 0 : isl_map_free(map1);
3728 0 : isl_map_free(map2);
3729 0 : return NULL;
3730 : }
3731 :
3732 : /* map2 may be either a parameter domain or a map living in the same
3733 : * space as map1.
3734 : */
3735 2294503 : static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3736 : __isl_take isl_map *map2)
3737 : {
3738 2294503 : unsigned flags = 0;
3739 : isl_bool equal;
3740 : isl_map *result;
3741 : int i, j;
3742 :
3743 2294503 : if (!map1 || !map2)
3744 : goto error;
3745 :
3746 4095141 : if ((isl_map_plain_is_empty(map1) ||
3747 2323064 : isl_map_plain_is_universe(map2)) &&
3748 522426 : isl_space_is_equal(map1->dim, map2->dim)) {
3749 522426 : isl_map_free(map2);
3750 522426 : return map1;
3751 : }
3752 3257539 : if ((isl_map_plain_is_empty(map2) ||
3753 1840618 : isl_map_plain_is_universe(map1)) &&
3754 355156 : isl_space_is_equal(map1->dim, map2->dim)) {
3755 355156 : isl_map_free(map1);
3756 355156 : return map2;
3757 : }
3758 :
3759 2068400 : if (map1->n == 1 && map2->n == 1 &&
3760 1954437 : map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3761 1302958 : isl_space_is_equal(map1->dim, map2->dim) &&
3762 1302958 : (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3763 651479 : map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3764 0 : return map_intersect_add_constraint(map1, map2);
3765 :
3766 1416921 : equal = isl_map_plain_is_equal(map1, map2);
3767 1416921 : if (equal < 0)
3768 0 : goto error;
3769 1416921 : if (equal) {
3770 113348 : isl_map_free(map2);
3771 113348 : return map1;
3772 : }
3773 :
3774 2607146 : if (isl_space_dim(map2->dim, isl_dim_all) !=
3775 1303573 : isl_space_dim(map2->dim, isl_dim_param))
3776 1303573 : isl_assert(map1->ctx,
3777 : isl_space_is_equal(map1->dim, map2->dim), goto error);
3778 :
3779 2306528 : if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3780 1002955 : ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3781 927384 : ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3782 :
3783 1303573 : result = isl_map_alloc_space(isl_space_copy(map1->dim),
3784 1303573 : map1->n * map2->n, flags);
3785 1303573 : if (!result)
3786 0 : goto error;
3787 10332144 : for (i = 0; i < map1->n; ++i)
3788 113899147 : for (j = 0; j < map2->n; ++j) {
3789 : struct isl_basic_map *part;
3790 209741152 : part = isl_basic_map_intersect(
3791 104870576 : isl_basic_map_copy(map1->p[i]),
3792 104870576 : isl_basic_map_copy(map2->p[j]));
3793 104870576 : if (isl_basic_map_is_empty(part) < 0)
3794 0 : part = isl_basic_map_free(part);
3795 104870576 : result = isl_map_add_basic_map(result, part);
3796 104870576 : if (!result)
3797 0 : goto error;
3798 : }
3799 1303573 : isl_map_free(map1);
3800 1303573 : isl_map_free(map2);
3801 1303573 : return result;
3802 : error:
3803 0 : isl_map_free(map1);
3804 0 : isl_map_free(map2);
3805 0 : return NULL;
3806 : }
3807 :
3808 2294503 : static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3809 : __isl_take isl_map *map2)
3810 : {
3811 2294503 : if (!map1 || !map2)
3812 : goto error;
3813 2294503 : if (!isl_space_is_equal(map1->dim, map2->dim))
3814 0 : isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3815 : "spaces don't match", goto error);
3816 2294503 : return map_intersect_internal(map1, map2);
3817 : error:
3818 0 : isl_map_free(map1);
3819 0 : isl_map_free(map2);
3820 0 : return NULL;
3821 : }
3822 :
3823 2294503 : __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3824 : __isl_take isl_map *map2)
3825 : {
3826 2294503 : return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3827 : }
3828 :
3829 2294503 : struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3830 : {
3831 2294503 : return set_from_map(isl_map_intersect(set_to_map(set1),
3832 : set_to_map(set2)));
3833 : }
3834 :
3835 : /* map_intersect_internal accepts intersections
3836 : * with parameter domains, so we can just call that function.
3837 : */
3838 0 : static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3839 : __isl_take isl_set *params)
3840 : {
3841 0 : return map_intersect_internal(map, params);
3842 : }
3843 :
3844 0 : __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3845 : __isl_take isl_map *map2)
3846 : {
3847 0 : return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3848 : }
3849 :
3850 0 : __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3851 : __isl_take isl_set *params)
3852 : {
3853 0 : return isl_map_intersect_params(set, params);
3854 : }
3855 :
3856 0 : __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3857 : {
3858 : isl_space *space;
3859 : unsigned pos, n1, n2;
3860 :
3861 0 : if (!bmap)
3862 0 : return NULL;
3863 0 : bmap = isl_basic_map_cow(bmap);
3864 0 : if (!bmap)
3865 0 : return NULL;
3866 0 : space = isl_space_reverse(isl_space_copy(bmap->dim));
3867 0 : pos = isl_basic_map_offset(bmap, isl_dim_in);
3868 0 : n1 = isl_basic_map_dim(bmap, isl_dim_in);
3869 0 : n2 = isl_basic_map_dim(bmap, isl_dim_out);
3870 0 : bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3871 0 : return isl_basic_map_reset_space(bmap, space);
3872 : }
3873 :
3874 0 : static __isl_give isl_basic_map *basic_map_space_reset(
3875 : __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3876 : {
3877 : isl_space *space;
3878 :
3879 0 : if (!bmap)
3880 0 : return NULL;
3881 0 : if (!isl_space_is_named_or_nested(bmap->dim, type))
3882 0 : return bmap;
3883 :
3884 0 : space = isl_basic_map_get_space(bmap);
3885 0 : space = isl_space_reset(space, type);
3886 0 : bmap = isl_basic_map_reset_space(bmap, space);
3887 0 : return bmap;
3888 : }
3889 :
3890 0 : __isl_give isl_basic_map *isl_basic_map_insert_dims(
3891 : __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3892 : unsigned pos, unsigned n)
3893 : {
3894 : isl_bool rational;
3895 : isl_space *res_space;
3896 : struct isl_basic_map *res;
3897 : struct isl_dim_map *dim_map;
3898 : unsigned total, off;
3899 : enum isl_dim_type t;
3900 :
3901 0 : if (n == 0)
3902 0 : return basic_map_space_reset(bmap, type);
3903 :
3904 0 : res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3905 : type, pos, n);
3906 0 : if (!res_space)
3907 0 : return isl_basic_map_free(bmap);
3908 :
3909 0 : total = isl_basic_map_total_dim(bmap) + n;
3910 0 : dim_map = isl_dim_map_alloc(bmap->ctx, total);
3911 0 : off = 0;
3912 0 : for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3913 0 : if (t != type) {
3914 0 : isl_dim_map_dim(dim_map, bmap->dim, t, off);
3915 : } else {
3916 0 : unsigned size = isl_basic_map_dim(bmap, t);
3917 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
3918 : 0, pos, off);
3919 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
3920 0 : pos, size - pos, off + pos + n);
3921 : }
3922 0 : off += isl_space_dim(res_space, t);
3923 : }
3924 0 : isl_dim_map_div(dim_map, bmap, off);
3925 :
3926 0 : res = isl_basic_map_alloc_space(res_space,
3927 : bmap->n_div, bmap->n_eq, bmap->n_ineq);
3928 0 : rational = isl_basic_map_is_rational(bmap);
3929 0 : if (rational < 0)
3930 0 : res = isl_basic_map_free(res);
3931 0 : if (rational)
3932 0 : res = isl_basic_map_set_rational(res);
3933 0 : if (isl_basic_map_plain_is_empty(bmap)) {
3934 0 : isl_basic_map_free(bmap);
3935 0 : free(dim_map);
3936 0 : return isl_basic_map_set_to_empty(res);
3937 : }
3938 0 : res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3939 0 : return isl_basic_map_finalize(res);
3940 : }
3941 :
3942 0 : __isl_give isl_basic_set *isl_basic_set_insert_dims(
3943 : __isl_take isl_basic_set *bset,
3944 : enum isl_dim_type type, unsigned pos, unsigned n)
3945 : {
3946 0 : return isl_basic_map_insert_dims(bset, type, pos, n);
3947 : }
3948 :
3949 0 : __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3950 : enum isl_dim_type type, unsigned n)
3951 : {
3952 0 : if (!bmap)
3953 0 : return NULL;
3954 0 : return isl_basic_map_insert_dims(bmap, type,
3955 : isl_basic_map_dim(bmap, type), n);
3956 : }
3957 :
3958 0 : __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3959 : enum isl_dim_type type, unsigned n)
3960 : {
3961 0 : if (!bset)
3962 0 : return NULL;
3963 0 : isl_assert(bset->ctx, type != isl_dim_in, goto error);
3964 0 : return isl_basic_map_add_dims(bset, type, n);
3965 : error:
3966 0 : isl_basic_set_free(bset);
3967 0 : return NULL;
3968 : }
3969 :
3970 0 : static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3971 : enum isl_dim_type type)
3972 : {
3973 : isl_space *space;
3974 :
3975 0 : if (!map || !isl_space_is_named_or_nested(map->dim, type))
3976 0 : return map;
3977 :
3978 0 : space = isl_map_get_space(map);
3979 0 : space = isl_space_reset(space, type);
3980 0 : map = isl_map_reset_space(map, space);
3981 0 : return map;
3982 : }
3983 :
3984 0 : __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3985 : enum isl_dim_type type, unsigned pos, unsigned n)
3986 : {
3987 : int i;
3988 :
3989 0 : if (n == 0)
3990 0 : return map_space_reset(map, type);
3991 :
3992 0 : map = isl_map_cow(map);
3993 0 : if (!map)
3994 0 : return NULL;
3995 :
3996 0 : map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3997 0 : if (!map->dim)
3998 0 : goto error;
3999 :
4000 0 : for (i = 0; i < map->n; ++i) {
4001 0 : map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
4002 0 : if (!map->p[i])
4003 0 : goto error;
4004 : }
4005 :
4006 0 : return map;
4007 : error:
4008 0 : isl_map_free(map);
4009 0 : return NULL;
4010 : }
4011 :
4012 0 : __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
4013 : enum isl_dim_type type, unsigned pos, unsigned n)
4014 : {
4015 0 : return isl_map_insert_dims(set, type, pos, n);
4016 : }
4017 :
4018 0 : __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
4019 : enum isl_dim_type type, unsigned n)
4020 : {
4021 0 : if (!map)
4022 0 : return NULL;
4023 0 : return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
4024 : }
4025 :
4026 0 : __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
4027 : enum isl_dim_type type, unsigned n)
4028 : {
4029 0 : if (!set)
4030 0 : return NULL;
4031 0 : isl_assert(set->ctx, type != isl_dim_in, goto error);
4032 0 : return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
4033 : error:
4034 0 : isl_set_free(set);
4035 0 : return NULL;
4036 : }
4037 :
4038 0 : __isl_give isl_basic_map *isl_basic_map_move_dims(
4039 : __isl_take isl_basic_map *bmap,
4040 : enum isl_dim_type dst_type, unsigned dst_pos,
4041 : enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4042 : {
4043 : struct isl_dim_map *dim_map;
4044 : struct isl_basic_map *res;
4045 : enum isl_dim_type t;
4046 : unsigned total, off;
4047 :
4048 0 : if (!bmap)
4049 0 : return NULL;
4050 0 : if (n == 0) {
4051 0 : bmap = isl_basic_map_reset(bmap, src_type);
4052 0 : bmap = isl_basic_map_reset(bmap, dst_type);
4053 0 : return bmap;
4054 : }
4055 :
4056 0 : if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
4057 0 : return isl_basic_map_free(bmap);
4058 :
4059 0 : if (dst_type == src_type && dst_pos == src_pos)
4060 0 : return bmap;
4061 :
4062 0 : isl_assert(bmap->ctx, dst_type != src_type, goto error);
4063 :
4064 0 : if (pos(bmap->dim, dst_type) + dst_pos ==
4065 0 : pos(bmap->dim, src_type) + src_pos +
4066 0 : ((src_type < dst_type) ? n : 0)) {
4067 0 : bmap = isl_basic_map_cow(bmap);
4068 0 : if (!bmap)
4069 0 : return NULL;
4070 :
4071 0 : bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4072 : src_type, src_pos, n);
4073 0 : if (!bmap->dim)
4074 0 : goto error;
4075 :
4076 0 : bmap = isl_basic_map_finalize(bmap);
4077 :
4078 0 : return bmap;
4079 : }
4080 :
4081 0 : total = isl_basic_map_total_dim(bmap);
4082 0 : dim_map = isl_dim_map_alloc(bmap->ctx, total);
4083 :
4084 0 : off = 0;
4085 0 : for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4086 0 : unsigned size = isl_space_dim(bmap->dim, t);
4087 0 : if (t == dst_type) {
4088 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
4089 : 0, dst_pos, off);
4090 0 : off += dst_pos;
4091 0 : isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
4092 : src_pos, n, off);
4093 0 : off += n;
4094 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
4095 : dst_pos, size - dst_pos, off);
4096 0 : off += size - dst_pos;
4097 0 : } else if (t == src_type) {
4098 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
4099 : 0, src_pos, off);
4100 0 : off += src_pos;
4101 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
4102 0 : src_pos + n, size - src_pos - n, off);
4103 0 : off += size - src_pos - n;
4104 : } else {
4105 0 : isl_dim_map_dim(dim_map, bmap->dim, t, off);
4106 0 : off += size;
4107 : }
4108 : }
4109 0 : isl_dim_map_div(dim_map, bmap, off);
4110 :
4111 0 : res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4112 : bmap->n_div, bmap->n_eq, bmap->n_ineq);
4113 0 : bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4114 0 : if (!bmap)
4115 0 : goto error;
4116 :
4117 0 : bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
4118 : src_type, src_pos, n);
4119 0 : if (!bmap->dim)
4120 0 : goto error;
4121 :
4122 0 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
4123 0 : bmap = isl_basic_map_gauss(bmap, NULL);
4124 0 : bmap = isl_basic_map_finalize(bmap);
4125 :
4126 0 : return bmap;
4127 : error:
4128 0 : isl_basic_map_free(bmap);
4129 0 : return NULL;
4130 : }
4131 :
4132 0 : __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4133 : enum isl_dim_type dst_type, unsigned dst_pos,
4134 : enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4135 : {
4136 0 : isl_basic_map *bmap = bset_to_bmap(bset);
4137 0 : bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4138 : src_type, src_pos, n);
4139 0 : return bset_from_bmap(bmap);
4140 : }
4141 :
4142 0 : __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4143 : enum isl_dim_type dst_type, unsigned dst_pos,
4144 : enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4145 : {
4146 0 : if (!set)
4147 0 : return NULL;
4148 0 : isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4149 0 : return set_from_map(isl_map_move_dims(set_to_map(set),
4150 : dst_type, dst_pos, src_type, src_pos, n));
4151 : error:
4152 0 : isl_set_free(set);
4153 0 : return NULL;
4154 : }
4155 :
4156 0 : __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4157 : enum isl_dim_type dst_type, unsigned dst_pos,
4158 : enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4159 : {
4160 : int i;
4161 :
4162 0 : if (n == 0) {
4163 0 : map = isl_map_reset(map, src_type);
4164 0 : map = isl_map_reset(map, dst_type);
4165 0 : return map;
4166 : }
4167 :
4168 0 : if (isl_map_check_range(map, src_type, src_pos, n))
4169 0 : return isl_map_free(map);
4170 :
4171 0 : if (dst_type == src_type && dst_pos == src_pos)
4172 0 : return map;
4173 :
4174 0 : isl_assert(map->ctx, dst_type != src_type, goto error);
4175 :
4176 0 : map = isl_map_cow(map);
4177 0 : if (!map)
4178 0 : return NULL;
4179 :
4180 0 : map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
4181 0 : if (!map->dim)
4182 0 : goto error;
4183 :
4184 0 : for (i = 0; i < map->n; ++i) {
4185 0 : map->p[i] = isl_basic_map_move_dims(map->p[i],
4186 : dst_type, dst_pos,
4187 : src_type, src_pos, n);
4188 0 : if (!map->p[i])
4189 0 : goto error;
4190 : }
4191 :
4192 0 : return map;
4193 : error:
4194 0 : isl_map_free(map);
4195 0 : return NULL;
4196 : }
4197 :
4198 : /* Move the specified dimensions to the last columns right before
4199 : * the divs. Don't change the dimension specification of bmap.
4200 : * That's the responsibility of the caller.
4201 : */
4202 0 : static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4203 : enum isl_dim_type type, unsigned first, unsigned n)
4204 : {
4205 : struct isl_dim_map *dim_map;
4206 : struct isl_basic_map *res;
4207 : enum isl_dim_type t;
4208 : unsigned total, off;
4209 :
4210 0 : if (!bmap)
4211 0 : return NULL;
4212 0 : if (pos(bmap->dim, type) + first + n ==
4213 0 : 1 + isl_space_dim(bmap->dim, isl_dim_all))
4214 0 : return bmap;
4215 :
4216 0 : total = isl_basic_map_total_dim(bmap);
4217 0 : dim_map = isl_dim_map_alloc(bmap->ctx, total);
4218 :
4219 0 : off = 0;
4220 0 : for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4221 0 : unsigned size = isl_space_dim(bmap->dim, t);
4222 0 : if (t == type) {
4223 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
4224 : 0, first, off);
4225 0 : off += first;
4226 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
4227 0 : first, n, total - bmap->n_div - n);
4228 0 : isl_dim_map_dim_range(dim_map, bmap->dim, t,
4229 0 : first + n, size - (first + n), off);
4230 0 : off += size - (first + n);
4231 : } else {
4232 0 : isl_dim_map_dim(dim_map, bmap->dim, t, off);
4233 0 : off += size;
4234 : }
4235 : }
4236 0 : isl_dim_map_div(dim_map, bmap, off + n);
4237 :
4238 0 : res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4239 : bmap->n_div, bmap->n_eq, bmap->n_ineq);
4240 0 : res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4241 0 : return res;
4242 : }
4243 :
4244 : /* Insert "n" rows in the divs of "bmap".
4245 : *
4246 : * The number of columns is not changed, which means that the last
4247 : * dimensions of "bmap" are being reintepreted as the new divs.
4248 : * The space of "bmap" is not adjusted, however, which means
4249 : * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4250 : * from the space of "bmap" is the responsibility of the caller.
4251 : */
4252 0 : static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4253 : int n)
4254 : {
4255 : int i;
4256 : size_t row_size;
4257 : isl_int **new_div;
4258 : isl_int *old;
4259 :
4260 0 : bmap = isl_basic_map_cow(bmap);
4261 0 : if (!bmap)
4262 0 : return NULL;
4263 :
4264 0 : row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
4265 0 : old = bmap->block2.data;
4266 0 : bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4267 0 : (bmap->extra + n) * (1 + row_size));
4268 0 : if (!bmap->block2.data)
4269 0 : return isl_basic_map_free(bmap);
4270 0 : new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4271 0 : if (!new_div)
4272 0 : return isl_basic_map_free(bmap);
4273 0 : for (i = 0; i < n; ++i) {
4274 0 : new_div[i] = bmap->block2.data +
4275 0 : (bmap->extra + i) * (1 + row_size);
4276 0 : isl_seq_clr(new_div[i], 1 + row_size);
4277 : }
4278 0 : for (i = 0; i < bmap->extra; ++i)
4279 0 : new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4280 0 : free(bmap->div);
4281 0 : bmap->div = new_div;
4282 0 : bmap->n_div += n;
4283 0 : bmap->extra += n;
4284 :
4285 0 : return bmap;
4286 : }
4287 :
4288 : /* Drop constraints from "bmap" that only involve the variables
4289 : * of "type" in the range [first, first + n] that are not related
4290 : * to any of the variables outside that interval.
4291 : * These constraints cannot influence the values for the variables
4292 : * outside the interval, except in case they cause "bmap" to be empty.
4293 : * Only drop the constraints if "bmap" is known to be non-empty.
4294 : */
4295 0 : static __isl_give isl_basic_map *drop_irrelevant_constraints(
4296 : __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4297 : unsigned first, unsigned n)
4298 : {
4299 : int i;
4300 : int *groups;
4301 : unsigned dim, n_div;
4302 : isl_bool non_empty;
4303 :
4304 0 : non_empty = isl_basic_map_plain_is_non_empty(bmap);
4305 0 : if (non_empty < 0)
4306 0 : return isl_basic_map_free(bmap);
4307 0 : if (!non_empty)
4308 0 : return bmap;
4309 :
4310 0 : dim = isl_basic_map_dim(bmap, isl_dim_all);
4311 0 : n_div = isl_basic_map_dim(bmap, isl_dim_div);
4312 0 : groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4313 0 : if (!groups)
4314 0 : return isl_basic_map_free(bmap);
4315 0 : first += isl_basic_map_offset(bmap, type) - 1;
4316 0 : for (i = 0; i < first; ++i)
4317 0 : groups[i] = -1;
4318 0 : for (i = first + n; i < dim - n_div; ++i)
4319 0 : groups[i] = -1;
4320 :
4321 0 : bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4322 :
4323 0 : return bmap;
4324 : }
4325 :
4326 : /* Turn the n dimensions of type type, starting at first
4327 : * into existentially quantified variables.
4328 : *
4329 : * If a subset of the projected out variables are unrelated
4330 : * to any of the variables that remain, then the constraints
4331 : * involving this subset are simply dropped first.
4332 : */
4333 0 : __isl_give isl_basic_map *isl_basic_map_project_out(
4334 : __isl_take isl_basic_map *bmap,
4335 : enum isl_dim_type type, unsigned first, unsigned n)
4336 : {
4337 : isl_bool empty;
4338 :
4339 0 : if (n == 0)
4340 0 : return basic_map_space_reset(bmap, type);
4341 0 : if (type == isl_dim_div)
4342 0 : isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4343 : "cannot project out existentially quantified variables",
4344 : return isl_basic_map_free(bmap));
4345 :
4346 0 : empty = isl_basic_map_plain_is_empty(bmap);
4347 0 : if (empty < 0)
4348 0 : return isl_basic_map_free(bmap);
4349 0 : if (empty)
4350 0 : bmap = isl_basic_map_set_to_empty(bmap);
4351 :
4352 0 : bmap = drop_irrelevant_constraints(bmap, type, first, n);
4353 0 : if (!bmap)
4354 0 : return NULL;
4355 :
4356 0 : if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4357 0 : return isl_basic_map_remove_dims(bmap, type, first, n);
4358 :
4359 0 : if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4360 0 : return isl_basic_map_free(bmap);
4361 :
4362 0 : bmap = move_last(bmap, type, first, n);
4363 0 : bmap = isl_basic_map_cow(bmap);
4364 0 : bmap = insert_div_rows(bmap, n);
4365 0 : if (!bmap)
4366 0 : return NULL;
4367 :
4368 0 : bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
4369 0 : if (!bmap->dim)
4370 0 : goto error;
4371 0 : bmap = isl_basic_map_simplify(bmap);
4372 0 : bmap = isl_basic_map_drop_redundant_divs(bmap);
4373 0 : return isl_basic_map_finalize(bmap);
4374 : error:
4375 0 : isl_basic_map_free(bmap);
4376 0 : return NULL;
4377 : }
4378 :
4379 : /* Turn the n dimensions of type type, starting at first
4380 : * into existentially quantified variables.
4381 : */
4382 0 : struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
4383 : enum isl_dim_type type, unsigned first, unsigned n)
4384 : {
4385 0 : return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4386 : type, first, n));
4387 : }
4388 :
4389 : /* Turn the n dimensions of type type, starting at first
4390 : * into existentially quantified variables.
4391 : */
4392 0 : __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4393 : enum isl_dim_type type, unsigned first, unsigned n)
4394 : {
4395 : int i;
4396 :
4397 0 : if (n == 0)
4398 0 : return map_space_reset(map, type);
4399 :
4400 0 : if (isl_map_check_range(map, type, first, n) < 0)
4401 0 : return isl_map_free(map);
4402 :
4403 0 : map = isl_map_cow(map);
4404 0 : if (!map)
4405 0 : return NULL;
4406 :
4407 0 : map->dim = isl_space_drop_dims(map->dim, type, first, n);
4408 0 : if (!map->dim)
4409 0 : goto error;
4410 :
4411 0 : for (i = 0; i < map->n; ++i) {
4412 0 : map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4413 0 : if (!map->p[i])
4414 0 : goto error;
4415 : }
4416 :
4417 0 : return map;
4418 : error:
4419 0 : isl_map_free(map);
4420 0 : return NULL;
4421 : }
4422 :
4423 : /* Turn all the dimensions of type "type", except the "n" starting at "first"
4424 : * into existentially quantified variables.
4425 : */
4426 0 : __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4427 : enum isl_dim_type type, unsigned first, unsigned n)
4428 : {
4429 : unsigned dim;
4430 :
4431 0 : if (isl_map_check_range(map, type, first, n) < 0)
4432 0 : return isl_map_free(map);
4433 0 : dim = isl_map_dim(map, type);
4434 0 : map = isl_map_project_out(map, type, first + n, dim - (first + n));
4435 0 : map = isl_map_project_out(map, type, 0, first);
4436 0 : return map;
4437 : }
4438 :
4439 : /* Turn the n dimensions of type type, starting at first
4440 : * into existentially quantified variables.
4441 : */
4442 0 : __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4443 : enum isl_dim_type type, unsigned first, unsigned n)
4444 : {
4445 0 : return set_from_map(isl_map_project_out(set_to_map(set),
4446 : type, first, n));
4447 : }
4448 :
4449 : /* Return a map that projects the elements in "set" onto their
4450 : * "n" set dimensions starting at "first".
4451 : * "type" should be equal to isl_dim_set.
4452 : */
4453 0 : __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4454 : enum isl_dim_type type, unsigned first, unsigned n)
4455 : {
4456 : int i;
4457 : int dim;
4458 : isl_map *map;
4459 :
4460 0 : if (!set)
4461 0 : return NULL;
4462 0 : if (type != isl_dim_set)
4463 0 : isl_die(isl_set_get_ctx(set), isl_error_invalid,
4464 : "only set dimensions can be projected out", goto error);
4465 0 : dim = isl_set_dim(set, isl_dim_set);
4466 0 : if (first + n > dim || first + n < first)
4467 0 : isl_die(isl_set_get_ctx(set), isl_error_invalid,
4468 : "index out of bounds", goto error);
4469 :
4470 0 : map = isl_map_from_domain(set);
4471 0 : map = isl_map_add_dims(map, isl_dim_out, n);
4472 0 : for (i = 0; i < n; ++i)
4473 0 : map = isl_map_equate(map, isl_dim_in, first + i,
4474 : isl_dim_out, i);
4475 0 : return map;
4476 : error:
4477 0 : isl_set_free(set);
4478 0 : return NULL;
4479 : }
4480 :
4481 0 : static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
4482 : {
4483 : int i, j;
4484 :
4485 0 : for (i = 0; i < n; ++i) {
4486 0 : j = isl_basic_map_alloc_div(bmap);
4487 0 : if (j < 0)
4488 0 : goto error;
4489 0 : isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4490 : }
4491 0 : return bmap;
4492 : error:
4493 0 : isl_basic_map_free(bmap);
4494 0 : return NULL;
4495 : }
4496 :
4497 0 : struct isl_basic_map *isl_basic_map_apply_range(
4498 : struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4499 : {
4500 0 : isl_space *dim_result = NULL;
4501 : struct isl_basic_map *bmap;
4502 : unsigned n_in, n_out, n, nparam, total, pos;
4503 : struct isl_dim_map *dim_map1, *dim_map2;
4504 :
4505 0 : if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4506 0 : goto error;
4507 0 : if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4508 : bmap2->dim, isl_dim_in))
4509 0 : isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4510 : "spaces don't match", goto error);
4511 :
4512 0 : dim_result = isl_space_join(isl_space_copy(bmap1->dim),
4513 : isl_space_copy(bmap2->dim));
4514 :
4515 0 : n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4516 0 : n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4517 0 : n = isl_basic_map_dim(bmap1, isl_dim_out);
4518 0 : nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4519 :
4520 0 : total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4521 0 : dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4522 0 : dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4523 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4524 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4525 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4526 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4527 0 : isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4528 0 : isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4529 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4530 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4531 :
4532 0 : bmap = isl_basic_map_alloc_space(dim_result,
4533 0 : bmap1->n_div + bmap2->n_div + n,
4534 0 : bmap1->n_eq + bmap2->n_eq,
4535 0 : bmap1->n_ineq + bmap2->n_ineq);
4536 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4537 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4538 0 : bmap = add_divs(bmap, n);
4539 0 : bmap = isl_basic_map_simplify(bmap);
4540 0 : bmap = isl_basic_map_drop_redundant_divs(bmap);
4541 0 : return isl_basic_map_finalize(bmap);
4542 : error:
4543 0 : isl_basic_map_free(bmap1);
4544 0 : isl_basic_map_free(bmap2);
4545 0 : return NULL;
4546 : }
4547 :
4548 0 : struct isl_basic_set *isl_basic_set_apply(
4549 : struct isl_basic_set *bset, struct isl_basic_map *bmap)
4550 : {
4551 0 : if (!bset || !bmap)
4552 : goto error;
4553 :
4554 0 : isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4555 : goto error);
4556 :
4557 0 : return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4558 : bmap));
4559 : error:
4560 0 : isl_basic_set_free(bset);
4561 0 : isl_basic_map_free(bmap);
4562 0 : return NULL;
4563 : }
4564 :
4565 0 : struct isl_basic_map *isl_basic_map_apply_domain(
4566 : struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4567 : {
4568 0 : if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4569 0 : goto error;
4570 0 : if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4571 : bmap2->dim, isl_dim_in))
4572 0 : isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4573 : "spaces don't match", goto error);
4574 :
4575 0 : bmap1 = isl_basic_map_reverse(bmap1);
4576 0 : bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4577 0 : return isl_basic_map_reverse(bmap1);
4578 : error:
4579 0 : isl_basic_map_free(bmap1);
4580 0 : isl_basic_map_free(bmap2);
4581 0 : return NULL;
4582 : }
4583 :
4584 : /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4585 : * A \cap B -> f(A) + f(B)
4586 : */
4587 0 : __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4588 : __isl_take isl_basic_map *bmap2)
4589 : {
4590 : unsigned n_in, n_out, nparam, total, pos;
4591 0 : struct isl_basic_map *bmap = NULL;
4592 : struct isl_dim_map *dim_map1, *dim_map2;
4593 : int i;
4594 :
4595 0 : if (!bmap1 || !bmap2)
4596 : goto error;
4597 :
4598 0 : isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4599 : goto error);
4600 :
4601 0 : nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4602 0 : n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4603 0 : n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4604 :
4605 0 : total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4606 0 : dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4607 0 : dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4608 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4609 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4610 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4611 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4612 0 : isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4613 0 : isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4614 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4615 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4616 :
4617 0 : bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4618 0 : bmap1->n_div + bmap2->n_div + 2 * n_out,
4619 0 : bmap1->n_eq + bmap2->n_eq + n_out,
4620 0 : bmap1->n_ineq + bmap2->n_ineq);
4621 0 : for (i = 0; i < n_out; ++i) {
4622 0 : int j = isl_basic_map_alloc_equality(bmap);
4623 0 : if (j < 0)
4624 0 : goto error;
4625 0 : isl_seq_clr(bmap->eq[j], 1+total);
4626 0 : isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4627 0 : isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4628 0 : isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4629 : }
4630 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4631 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4632 0 : bmap = add_divs(bmap, 2 * n_out);
4633 :
4634 0 : bmap = isl_basic_map_simplify(bmap);
4635 0 : return isl_basic_map_finalize(bmap);
4636 : error:
4637 0 : isl_basic_map_free(bmap);
4638 0 : isl_basic_map_free(bmap1);
4639 0 : isl_basic_map_free(bmap2);
4640 0 : return NULL;
4641 : }
4642 :
4643 : /* Given two maps A -> f(A) and B -> g(B), construct a map
4644 : * A \cap B -> f(A) + f(B)
4645 : */
4646 0 : __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4647 : __isl_take isl_map *map2)
4648 : {
4649 : struct isl_map *result;
4650 : int i, j;
4651 :
4652 0 : if (!map1 || !map2)
4653 : goto error;
4654 :
4655 0 : isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4656 :
4657 0 : result = isl_map_alloc_space(isl_space_copy(map1->dim),
4658 0 : map1->n * map2->n, 0);
4659 0 : if (!result)
4660 0 : goto error;
4661 0 : for (i = 0; i < map1->n; ++i)
4662 0 : for (j = 0; j < map2->n; ++j) {
4663 : struct isl_basic_map *part;
4664 0 : part = isl_basic_map_sum(
4665 0 : isl_basic_map_copy(map1->p[i]),
4666 0 : isl_basic_map_copy(map2->p[j]));
4667 0 : if (isl_basic_map_is_empty(part))
4668 0 : isl_basic_map_free(part);
4669 : else
4670 0 : result = isl_map_add_basic_map(result, part);
4671 0 : if (!result)
4672 0 : goto error;
4673 : }
4674 0 : isl_map_free(map1);
4675 0 : isl_map_free(map2);
4676 0 : return result;
4677 : error:
4678 0 : isl_map_free(map1);
4679 0 : isl_map_free(map2);
4680 0 : return NULL;
4681 : }
4682 :
4683 0 : __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4684 : __isl_take isl_set *set2)
4685 : {
4686 0 : return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4687 : }
4688 :
4689 : /* Given a basic map A -> f(A), construct A -> -f(A).
4690 : */
4691 0 : __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4692 : {
4693 : int i, j;
4694 : unsigned off, n;
4695 :
4696 0 : bmap = isl_basic_map_cow(bmap);
4697 0 : if (!bmap)
4698 0 : return NULL;
4699 :
4700 0 : n = isl_basic_map_dim(bmap, isl_dim_out);
4701 0 : off = isl_basic_map_offset(bmap, isl_dim_out);
4702 0 : for (i = 0; i < bmap->n_eq; ++i)
4703 0 : for (j = 0; j < n; ++j)
4704 0 : isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4705 0 : for (i = 0; i < bmap->n_ineq; ++i)
4706 0 : for (j = 0; j < n; ++j)
4707 0 : isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4708 0 : for (i = 0; i < bmap->n_div; ++i)
4709 0 : for (j = 0; j < n; ++j)
4710 0 : isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4711 0 : bmap = isl_basic_map_gauss(bmap, NULL);
4712 0 : return isl_basic_map_finalize(bmap);
4713 : }
4714 :
4715 0 : __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4716 : {
4717 0 : return isl_basic_map_neg(bset);
4718 : }
4719 :
4720 : /* Given a map A -> f(A), construct A -> -f(A).
4721 : */
4722 0 : __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4723 : {
4724 : int i;
4725 :
4726 0 : map = isl_map_cow(map);
4727 0 : if (!map)
4728 0 : return NULL;
4729 :
4730 0 : for (i = 0; i < map->n; ++i) {
4731 0 : map->p[i] = isl_basic_map_neg(map->p[i]);
4732 0 : if (!map->p[i])
4733 0 : goto error;
4734 : }
4735 :
4736 0 : return map;
4737 : error:
4738 0 : isl_map_free(map);
4739 0 : return NULL;
4740 : }
4741 :
4742 0 : __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4743 : {
4744 0 : return set_from_map(isl_map_neg(set_to_map(set)));
4745 : }
4746 :
4747 : /* Given a basic map A -> f(A) and an integer d, construct a basic map
4748 : * A -> floor(f(A)/d).
4749 : */
4750 0 : __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4751 : isl_int d)
4752 : {
4753 : unsigned n_in, n_out, nparam, total, pos;
4754 0 : struct isl_basic_map *result = NULL;
4755 : struct isl_dim_map *dim_map;
4756 : int i;
4757 :
4758 0 : if (!bmap)
4759 0 : return NULL;
4760 :
4761 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
4762 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
4763 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
4764 :
4765 0 : total = nparam + n_in + n_out + bmap->n_div + n_out;
4766 0 : dim_map = isl_dim_map_alloc(bmap->ctx, total);
4767 0 : isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4768 0 : isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4769 0 : isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4770 0 : isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4771 :
4772 0 : result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4773 0 : bmap->n_div + n_out,
4774 0 : bmap->n_eq, bmap->n_ineq + 2 * n_out);
4775 0 : result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4776 0 : result = add_divs(result, n_out);
4777 0 : for (i = 0; i < n_out; ++i) {
4778 : int j;
4779 0 : j = isl_basic_map_alloc_inequality(result);
4780 0 : if (j < 0)
4781 0 : goto error;
4782 0 : isl_seq_clr(result->ineq[j], 1+total);
4783 0 : isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4784 0 : isl_int_set_si(result->ineq[j][1+pos+i], 1);
4785 0 : j = isl_basic_map_alloc_inequality(result);
4786 0 : if (j < 0)
4787 0 : goto error;
4788 0 : isl_seq_clr(result->ineq[j], 1+total);
4789 0 : isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4790 0 : isl_int_set_si(result->ineq[j][1+pos+i], -1);
4791 0 : isl_int_sub_ui(result->ineq[j][0], d, 1);
4792 : }
4793 :
4794 0 : result = isl_basic_map_simplify(result);
4795 0 : return isl_basic_map_finalize(result);
4796 : error:
4797 0 : isl_basic_map_free(result);
4798 0 : return NULL;
4799 : }
4800 :
4801 : /* Given a map A -> f(A) and an integer d, construct a map
4802 : * A -> floor(f(A)/d).
4803 : */
4804 0 : __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4805 : {
4806 : int i;
4807 :
4808 0 : map = isl_map_cow(map);
4809 0 : if (!map)
4810 0 : return NULL;
4811 :
4812 0 : ISL_F_CLR(map, ISL_MAP_DISJOINT);
4813 0 : for (i = 0; i < map->n; ++i) {
4814 0 : map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4815 0 : if (!map->p[i])
4816 0 : goto error;
4817 : }
4818 0 : map = isl_map_unmark_normalized(map);
4819 :
4820 0 : return map;
4821 : error:
4822 0 : isl_map_free(map);
4823 0 : return NULL;
4824 : }
4825 :
4826 : /* Given a map A -> f(A) and an integer d, construct a map
4827 : * A -> floor(f(A)/d).
4828 : */
4829 0 : __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4830 : __isl_take isl_val *d)
4831 : {
4832 0 : if (!map || !d)
4833 : goto error;
4834 0 : if (!isl_val_is_int(d))
4835 0 : isl_die(isl_val_get_ctx(d), isl_error_invalid,
4836 : "expecting integer denominator", goto error);
4837 0 : map = isl_map_floordiv(map, d->n);
4838 0 : isl_val_free(d);
4839 0 : return map;
4840 : error:
4841 0 : isl_map_free(map);
4842 0 : isl_val_free(d);
4843 0 : return NULL;
4844 : }
4845 :
4846 0 : static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
4847 : unsigned pos)
4848 : {
4849 : int i;
4850 : unsigned nparam;
4851 : unsigned n_in;
4852 :
4853 0 : i = isl_basic_map_alloc_equality(bmap);
4854 0 : if (i < 0)
4855 0 : goto error;
4856 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
4857 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
4858 0 : isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4859 0 : isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4860 0 : isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4861 0 : return isl_basic_map_finalize(bmap);
4862 : error:
4863 0 : isl_basic_map_free(bmap);
4864 0 : return NULL;
4865 : }
4866 :
4867 : /* Add a constraint to "bmap" expressing i_pos < o_pos
4868 : */
4869 0 : static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
4870 : unsigned pos)
4871 : {
4872 : int i;
4873 : unsigned nparam;
4874 : unsigned n_in;
4875 :
4876 0 : i = isl_basic_map_alloc_inequality(bmap);
4877 0 : if (i < 0)
4878 0 : goto error;
4879 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
4880 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
4881 0 : isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4882 0 : isl_int_set_si(bmap->ineq[i][0], -1);
4883 0 : isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4884 0 : isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4885 0 : return isl_basic_map_finalize(bmap);
4886 : error:
4887 0 : isl_basic_map_free(bmap);
4888 0 : return NULL;
4889 : }
4890 :
4891 : /* Add a constraint to "bmap" expressing i_pos <= o_pos
4892 : */
4893 0 : static __isl_give isl_basic_map *var_less_or_equal(
4894 : __isl_take isl_basic_map *bmap, unsigned pos)
4895 : {
4896 : int i;
4897 : unsigned nparam;
4898 : unsigned n_in;
4899 :
4900 0 : i = isl_basic_map_alloc_inequality(bmap);
4901 0 : if (i < 0)
4902 0 : goto error;
4903 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
4904 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
4905 0 : isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4906 0 : isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4907 0 : isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4908 0 : return isl_basic_map_finalize(bmap);
4909 : error:
4910 0 : isl_basic_map_free(bmap);
4911 0 : return NULL;
4912 : }
4913 :
4914 : /* Add a constraint to "bmap" expressing i_pos > o_pos
4915 : */
4916 0 : static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
4917 : unsigned pos)
4918 : {
4919 : int i;
4920 : unsigned nparam;
4921 : unsigned n_in;
4922 :
4923 0 : i = isl_basic_map_alloc_inequality(bmap);
4924 0 : if (i < 0)
4925 0 : goto error;
4926 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
4927 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
4928 0 : isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4929 0 : isl_int_set_si(bmap->ineq[i][0], -1);
4930 0 : isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4931 0 : isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4932 0 : return isl_basic_map_finalize(bmap);
4933 : error:
4934 0 : isl_basic_map_free(bmap);
4935 0 : return NULL;
4936 : }
4937 :
4938 : /* Add a constraint to "bmap" expressing i_pos >= o_pos
4939 : */
4940 0 : static __isl_give isl_basic_map *var_more_or_equal(
4941 : __isl_take isl_basic_map *bmap, unsigned pos)
4942 : {
4943 : int i;
4944 : unsigned nparam;
4945 : unsigned n_in;
4946 :
4947 0 : i = isl_basic_map_alloc_inequality(bmap);
4948 0 : if (i < 0)
4949 0 : goto error;
4950 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
4951 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
4952 0 : isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4953 0 : isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4954 0 : isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4955 0 : return isl_basic_map_finalize(bmap);
4956 : error:
4957 0 : isl_basic_map_free(bmap);
4958 0 : return NULL;
4959 : }
4960 :
4961 0 : __isl_give isl_basic_map *isl_basic_map_equal(
4962 : __isl_take isl_space *dim, unsigned n_equal)
4963 : {
4964 : int i;
4965 : struct isl_basic_map *bmap;
4966 0 : bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
4967 0 : if (!bmap)
4968 0 : return NULL;
4969 0 : for (i = 0; i < n_equal && bmap; ++i)
4970 0 : bmap = var_equal(bmap, i);
4971 0 : return isl_basic_map_finalize(bmap);
4972 : }
4973 :
4974 : /* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
4975 : */
4976 0 : __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
4977 : unsigned pos)
4978 : {
4979 : int i;
4980 : struct isl_basic_map *bmap;
4981 0 : bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4982 0 : if (!bmap)
4983 0 : return NULL;
4984 0 : for (i = 0; i < pos && bmap; ++i)
4985 0 : bmap = var_equal(bmap, i);
4986 0 : if (bmap)
4987 0 : bmap = var_less(bmap, pos);
4988 0 : return isl_basic_map_finalize(bmap);
4989 : }
4990 :
4991 : /* Return a relation on "dim" expressing i_[0..pos] <<= o_[0..pos]
4992 : */
4993 0 : __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4994 : __isl_take isl_space *dim, unsigned pos)
4995 : {
4996 : int i;
4997 : isl_basic_map *bmap;
4998 :
4999 0 : bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
5000 0 : for (i = 0; i < pos; ++i)
5001 0 : bmap = var_equal(bmap, i);
5002 0 : bmap = var_less_or_equal(bmap, pos);
5003 0 : return isl_basic_map_finalize(bmap);
5004 : }
5005 :
5006 : /* Return a relation on "dim" expressing i_pos > o_pos
5007 : */
5008 0 : __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
5009 : unsigned pos)
5010 : {
5011 : int i;
5012 : struct isl_basic_map *bmap;
5013 0 : bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
5014 0 : if (!bmap)
5015 0 : return NULL;
5016 0 : for (i = 0; i < pos && bmap; ++i)
5017 0 : bmap = var_equal(bmap, i);
5018 0 : if (bmap)
5019 0 : bmap = var_more(bmap, pos);
5020 0 : return isl_basic_map_finalize(bmap);
5021 : }
5022 :
5023 : /* Return a relation on "dim" expressing i_[0..pos] >>= o_[0..pos]
5024 : */
5025 0 : __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
5026 : __isl_take isl_space *dim, unsigned pos)
5027 : {
5028 : int i;
5029 : isl_basic_map *bmap;
5030 :
5031 0 : bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
5032 0 : for (i = 0; i < pos; ++i)
5033 0 : bmap = var_equal(bmap, i);
5034 0 : bmap = var_more_or_equal(bmap, pos);
5035 0 : return isl_basic_map_finalize(bmap);
5036 : }
5037 :
5038 0 : static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
5039 : unsigned n, int equal)
5040 : {
5041 : struct isl_map *map;
5042 : int i;
5043 :
5044 0 : if (n == 0 && equal)
5045 0 : return isl_map_universe(dims);
5046 :
5047 0 : map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
5048 :
5049 0 : for (i = 0; i + 1 < n; ++i)
5050 0 : map = isl_map_add_basic_map(map,
5051 : isl_basic_map_less_at(isl_space_copy(dims), i));
5052 0 : if (n > 0) {
5053 0 : if (equal)
5054 0 : map = isl_map_add_basic_map(map,
5055 : isl_basic_map_less_or_equal_at(dims, n - 1));
5056 : else
5057 0 : map = isl_map_add_basic_map(map,
5058 : isl_basic_map_less_at(dims, n - 1));
5059 : } else
5060 0 : isl_space_free(dims);
5061 :
5062 0 : return map;
5063 : }
5064 :
5065 0 : static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
5066 : {
5067 0 : if (!dims)
5068 0 : return NULL;
5069 0 : return map_lex_lte_first(dims, dims->n_out, equal);
5070 : }
5071 :
5072 0 : __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
5073 : {
5074 0 : return map_lex_lte_first(dim, n, 0);
5075 : }
5076 :
5077 0 : __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
5078 : {
5079 0 : return map_lex_lte_first(dim, n, 1);
5080 : }
5081 :
5082 0 : __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
5083 : {
5084 0 : return map_lex_lte(isl_space_map_from_set(set_dim), 0);
5085 : }
5086 :
5087 0 : __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
5088 : {
5089 0 : return map_lex_lte(isl_space_map_from_set(set_dim), 1);
5090 : }
5091 :
5092 0 : static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
5093 : unsigned n, int equal)
5094 : {
5095 : struct isl_map *map;
5096 : int i;
5097 :
5098 0 : if (n == 0 && equal)
5099 0 : return isl_map_universe(dims);
5100 :
5101 0 : map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
5102 :
5103 0 : for (i = 0; i + 1 < n; ++i)
5104 0 : map = isl_map_add_basic_map(map,
5105 : isl_basic_map_more_at(isl_space_copy(dims), i));
5106 0 : if (n > 0) {
5107 0 : if (equal)
5108 0 : map = isl_map_add_basic_map(map,
5109 : isl_basic_map_more_or_equal_at(dims, n - 1));
5110 : else
5111 0 : map = isl_map_add_basic_map(map,
5112 : isl_basic_map_more_at(dims, n - 1));
5113 : } else
5114 0 : isl_space_free(dims);
5115 :
5116 0 : return map;
5117 : }
5118 :
5119 0 : static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
5120 : {
5121 0 : if (!dims)
5122 0 : return NULL;
5123 0 : return map_lex_gte_first(dims, dims->n_out, equal);
5124 : }
5125 :
5126 0 : __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
5127 : {
5128 0 : return map_lex_gte_first(dim, n, 0);
5129 : }
5130 :
5131 0 : __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
5132 : {
5133 0 : return map_lex_gte_first(dim, n, 1);
5134 : }
5135 :
5136 0 : __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
5137 : {
5138 0 : return map_lex_gte(isl_space_map_from_set(set_dim), 0);
5139 : }
5140 :
5141 0 : __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
5142 : {
5143 0 : return map_lex_gte(isl_space_map_from_set(set_dim), 1);
5144 : }
5145 :
5146 0 : __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5147 : __isl_take isl_set *set2)
5148 : {
5149 : isl_map *map;
5150 0 : map = isl_map_lex_le(isl_set_get_space(set1));
5151 0 : map = isl_map_intersect_domain(map, set1);
5152 0 : map = isl_map_intersect_range(map, set2);
5153 0 : return map;
5154 : }
5155 :
5156 0 : __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5157 : __isl_take isl_set *set2)
5158 : {
5159 : isl_map *map;
5160 0 : map = isl_map_lex_lt(isl_set_get_space(set1));
5161 0 : map = isl_map_intersect_domain(map, set1);
5162 0 : map = isl_map_intersect_range(map, set2);
5163 0 : return map;
5164 : }
5165 :
5166 0 : __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5167 : __isl_take isl_set *set2)
5168 : {
5169 : isl_map *map;
5170 0 : map = isl_map_lex_ge(isl_set_get_space(set1));
5171 0 : map = isl_map_intersect_domain(map, set1);
5172 0 : map = isl_map_intersect_range(map, set2);
5173 0 : return map;
5174 : }
5175 :
5176 0 : __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5177 : __isl_take isl_set *set2)
5178 : {
5179 : isl_map *map;
5180 0 : map = isl_map_lex_gt(isl_set_get_space(set1));
5181 0 : map = isl_map_intersect_domain(map, set1);
5182 0 : map = isl_map_intersect_range(map, set2);
5183 0 : return map;
5184 : }
5185 :
5186 0 : __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5187 : __isl_take isl_map *map2)
5188 : {
5189 : isl_map *map;
5190 0 : map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5191 0 : map = isl_map_apply_domain(map, isl_map_reverse(map1));
5192 0 : map = isl_map_apply_range(map, isl_map_reverse(map2));
5193 0 : return map;
5194 : }
5195 :
5196 0 : __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5197 : __isl_take isl_map *map2)
5198 : {
5199 : isl_map *map;
5200 0 : map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5201 0 : map = isl_map_apply_domain(map, isl_map_reverse(map1));
5202 0 : map = isl_map_apply_range(map, isl_map_reverse(map2));
5203 0 : return map;
5204 : }
5205 :
5206 0 : __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5207 : __isl_take isl_map *map2)
5208 : {
5209 : isl_map *map;
5210 0 : map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5211 0 : map = isl_map_apply_domain(map, isl_map_reverse(map1));
5212 0 : map = isl_map_apply_range(map, isl_map_reverse(map2));
5213 0 : return map;
5214 : }
5215 :
5216 0 : __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5217 : __isl_take isl_map *map2)
5218 : {
5219 : isl_map *map;
5220 0 : map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5221 0 : map = isl_map_apply_domain(map, isl_map_reverse(map1));
5222 0 : map = isl_map_apply_range(map, isl_map_reverse(map2));
5223 0 : return map;
5224 : }
5225 :
5226 : /* For a div d = floor(f/m), add the constraint
5227 : *
5228 : * f - m d >= 0
5229 : */
5230 0 : static isl_stat add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
5231 : unsigned pos, isl_int *div)
5232 : {
5233 : int i;
5234 0 : unsigned total = isl_basic_map_total_dim(bmap);
5235 :
5236 0 : i = isl_basic_map_alloc_inequality(bmap);
5237 0 : if (i < 0)
5238 0 : return isl_stat_error;
5239 0 : isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
5240 0 : isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
5241 :
5242 0 : return isl_stat_ok;
5243 : }
5244 :
5245 : /* For a div d = floor(f/m), add the constraint
5246 : *
5247 : * -(f-(m-1)) + m d >= 0
5248 : */
5249 0 : static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
5250 : unsigned pos, isl_int *div)
5251 : {
5252 : int i;
5253 0 : unsigned total = isl_basic_map_total_dim(bmap);
5254 :
5255 0 : i = isl_basic_map_alloc_inequality(bmap);
5256 0 : if (i < 0)
5257 0 : return isl_stat_error;
5258 0 : isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
5259 0 : isl_int_set(bmap->ineq[i][1 + pos], div[0]);
5260 0 : isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5261 0 : isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5262 :
5263 0 : return isl_stat_ok;
5264 : }
5265 :
5266 : /* For a div d = floor(f/m), add the constraints
5267 : *
5268 : * f - m d >= 0
5269 : * -(f-(m-1)) + m d >= 0
5270 : *
5271 : * Note that the second constraint is the negation of
5272 : *
5273 : * f - m d >= m
5274 : */
5275 0 : int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
5276 : unsigned pos, isl_int *div)
5277 : {
5278 0 : if (add_upper_div_constraint(bmap, pos, div) < 0)
5279 0 : return -1;
5280 0 : if (add_lower_div_constraint(bmap, pos, div) < 0)
5281 0 : return -1;
5282 0 : return 0;
5283 : }
5284 :
5285 0 : int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
5286 : unsigned pos, isl_int *div)
5287 : {
5288 0 : return isl_basic_map_add_div_constraints_var(bset_to_bmap(bset),
5289 : pos, div);
5290 : }
5291 :
5292 0 : int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
5293 : {
5294 0 : unsigned total = isl_basic_map_total_dim(bmap);
5295 0 : unsigned div_pos = total - bmap->n_div + div;
5296 :
5297 0 : return isl_basic_map_add_div_constraints_var(bmap, div_pos,
5298 0 : bmap->div[div]);
5299 : }
5300 :
5301 : /* For each known div d = floor(f/m), add the constraints
5302 : *
5303 : * f - m d >= 0
5304 : * -(f-(m-1)) + m d >= 0
5305 : *
5306 : * Remove duplicate constraints in case of some these div constraints
5307 : * already appear in "bmap".
5308 : */
5309 16283673 : __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5310 : __isl_take isl_basic_map *bmap)
5311 : {
5312 : unsigned n_div;
5313 :
5314 16283673 : if (!bmap)
5315 0 : return NULL;
5316 16283673 : n_div = isl_basic_map_dim(bmap, isl_dim_div);
5317 16283673 : if (n_div == 0)
5318 16283673 : return bmap;
5319 :
5320 0 : bmap = add_known_div_constraints(bmap);
5321 0 : bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5322 0 : bmap = isl_basic_map_finalize(bmap);
5323 0 : return bmap;
5324 : }
5325 :
5326 : /* Add the div constraint of sign "sign" for div "div" of "bmap".
5327 : *
5328 : * In particular, if this div is of the form d = floor(f/m),
5329 : * then add the constraint
5330 : *
5331 : * f - m d >= 0
5332 : *
5333 : * if sign < 0 or the constraint
5334 : *
5335 : * -(f-(m-1)) + m d >= 0
5336 : *
5337 : * if sign > 0.
5338 : */
5339 0 : int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
5340 : unsigned div, int sign)
5341 : {
5342 : unsigned total;
5343 : unsigned div_pos;
5344 :
5345 0 : if (!bmap)
5346 0 : return -1;
5347 :
5348 0 : total = isl_basic_map_total_dim(bmap);
5349 0 : div_pos = total - bmap->n_div + div;
5350 :
5351 0 : if (sign < 0)
5352 0 : return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
5353 : else
5354 0 : return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
5355 : }
5356 :
5357 1246363237 : __isl_give isl_basic_set *isl_basic_map_underlying_set(
5358 : __isl_take isl_basic_map *bmap)
5359 : {
5360 1246363237 : if (!bmap)
5361 0 : goto error;
5362 2492726474 : if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5363 2492726474 : bmap->n_div == 0 &&
5364 2435001936 : !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5365 1188638699 : !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5366 1188638699 : return bset_from_bmap(bmap);
5367 57724538 : bmap = isl_basic_map_cow(bmap);
5368 57724538 : if (!bmap)
5369 0 : goto error;
5370 57724538 : bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
5371 57724538 : if (!bmap->dim)
5372 0 : goto error;
5373 57724538 : bmap->extra -= bmap->n_div;
5374 57724538 : bmap->n_div = 0;
5375 57724538 : bmap = isl_basic_map_finalize(bmap);
5376 57724538 : return bset_from_bmap(bmap);
5377 : error:
5378 0 : isl_basic_map_free(bmap);
5379 0 : return NULL;
5380 : }
5381 :
5382 0 : __isl_give isl_basic_set *isl_basic_set_underlying_set(
5383 : __isl_take isl_basic_set *bset)
5384 : {
5385 0 : return isl_basic_map_underlying_set(bset_to_bmap(bset));
5386 : }
5387 :
5388 : /* Replace each element in "list" by the result of applying
5389 : * isl_basic_map_underlying_set to the element.
5390 : */
5391 0 : __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5392 : __isl_take isl_basic_map_list *list)
5393 : {
5394 : int i, n;
5395 :
5396 0 : if (!list)
5397 0 : return NULL;
5398 :
5399 0 : n = isl_basic_map_list_n_basic_map(list);
5400 0 : for (i = 0; i < n; ++i) {
5401 : isl_basic_map *bmap;
5402 : isl_basic_set *bset;
5403 :
5404 0 : bmap = isl_basic_map_list_get_basic_map(list, i);
5405 0 : bset = isl_basic_set_underlying_set(bmap);
5406 0 : list = isl_basic_set_list_set_basic_set(list, i, bset);
5407 : }
5408 :
5409 0 : return list;
5410 : }
5411 :
5412 647337746 : __isl_give isl_basic_map *isl_basic_map_overlying_set(
5413 : __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5414 : {
5415 : struct isl_basic_map *bmap;
5416 : struct isl_ctx *ctx;
5417 : unsigned total;
5418 : int i;
5419 :
5420 647337746 : if (!bset || !like)
5421 : goto error;
5422 647337746 : ctx = bset->ctx;
5423 647337746 : isl_assert(ctx, bset->n_div == 0, goto error);
5424 647337746 : isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
5425 647337746 : isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
5426 : goto error);
5427 647337746 : if (like->n_div == 0) {
5428 647337746 : isl_space *space = isl_basic_map_get_space(like);
5429 647337746 : isl_basic_map_free(like);
5430 647337746 : return isl_basic_map_reset_space(bset, space);
5431 : }
5432 0 : bset = isl_basic_set_cow(bset);
5433 0 : if (!bset)
5434 0 : goto error;
5435 0 : total = bset->dim->n_out + bset->extra;
5436 0 : bmap = bset_to_bmap(bset);
5437 0 : isl_space_free(bmap->dim);
5438 0 : bmap->dim = isl_space_copy(like->dim);
5439 0 : if (!bmap->dim)
5440 0 : goto error;
5441 0 : bmap->n_div = like->n_div;
5442 0 : bmap->extra += like->n_div;
5443 0 : if (bmap->extra) {
5444 : unsigned ltotal;
5445 : isl_int **div;
5446 0 : ltotal = total - bmap->extra + like->extra;
5447 0 : if (ltotal > total)
5448 0 : ltotal = total;
5449 0 : bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5450 0 : bmap->extra * (1 + 1 + total));
5451 0 : if (isl_blk_is_error(bmap->block2))
5452 0 : goto error;
5453 0 : div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5454 0 : if (!div)
5455 0 : goto error;
5456 0 : bmap->div = div;
5457 0 : for (i = 0; i < bmap->extra; ++i)
5458 0 : bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5459 0 : for (i = 0; i < like->n_div; ++i) {
5460 0 : isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5461 0 : isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5462 : }
5463 0 : bmap = isl_basic_map_add_known_div_constraints(bmap);
5464 : }
5465 0 : isl_basic_map_free(like);
5466 0 : bmap = isl_basic_map_simplify(bmap);
5467 0 : bmap = isl_basic_map_finalize(bmap);
5468 0 : return bmap;
5469 : error:
5470 0 : isl_basic_map_free(like);
5471 0 : isl_basic_set_free(bset);
5472 0 : return NULL;
5473 : }
5474 :
5475 1395249 : struct isl_basic_set *isl_basic_set_from_underlying_set(
5476 : struct isl_basic_set *bset, struct isl_basic_set *like)
5477 : {
5478 1395249 : return bset_from_bmap(isl_basic_map_overlying_set(bset,
5479 : bset_to_bmap(like)));
5480 : }
5481 :
5482 645942497 : __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5483 : {
5484 : int i;
5485 :
5486 645942497 : map = isl_map_cow(map);
5487 645942497 : if (!map)
5488 0 : return NULL;
5489 645942497 : map->dim = isl_space_cow(map->dim);
5490 645942497 : if (!map->dim)
5491 0 : goto error;
5492 :
5493 1189547712 : for (i = 1; i < map->n; ++i)
5494 543605215 : isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5495 : goto error);
5496 1835490209 : for (i = 0; i < map->n; ++i) {
5497 1189547712 : map->p[i] = bset_to_bmap(
5498 1189547712 : isl_basic_map_underlying_set(map->p[i]));
5499 1189547712 : if (!map->p[i])
5500 0 : goto error;
5501 : }
5502 645942497 : if (map->n == 0)
5503 0 : map->dim = isl_space_underlying(map->dim, 0);
5504 : else {
5505 645942497 : isl_space_free(map->dim);
5506 645942497 : map->dim = isl_space_copy(map->p[0]->dim);
5507 : }
5508 645942497 : if (!map->dim)
5509 0 : goto error;
5510 645942497 : return set_from_map(map);
5511 : error:
5512 0 : isl_map_free(map);
5513 0 : return NULL;
5514 : }
5515 :
5516 : /* Replace the space of "bmap" by "space".
5517 : *
5518 : * If the space of "bmap" is identical to "space" (including the identifiers
5519 : * of the input and output dimensions), then simply return the original input.
5520 : */
5521 647337746 : __isl_give isl_basic_map *isl_basic_map_reset_space(
5522 : __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5523 : {
5524 : isl_bool equal;
5525 : isl_space *bmap_space;
5526 :
5527 647337746 : bmap_space = isl_basic_map_peek_space(bmap);
5528 647337746 : equal = isl_space_is_equal(bmap_space, space);
5529 647337746 : if (equal >= 0 && equal)
5530 647224802 : equal = isl_space_has_equal_ids(bmap_space, space);
5531 647337746 : if (equal < 0)
5532 0 : goto error;
5533 647337746 : if (equal) {
5534 647224802 : isl_space_free(space);
5535 647224802 : return bmap;
5536 : }
5537 112944 : bmap = isl_basic_map_cow(bmap);
5538 112944 : if (!bmap || !space)
5539 : goto error;
5540 :
5541 112944 : isl_space_free(bmap->dim);
5542 112944 : bmap->dim = space;
5543 :
5544 112944 : bmap = isl_basic_map_finalize(bmap);
5545 :
5546 112944 : return bmap;
5547 : error:
5548 0 : isl_basic_map_free(bmap);
5549 0 : isl_space_free(space);
5550 0 : return NULL;
5551 : }
5552 :
5553 0 : __isl_give isl_basic_set *isl_basic_set_reset_space(
5554 : __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5555 : {
5556 0 : return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5557 : dim));
5558 : }
5559 :
5560 : /* Check that the total dimensions of "map" and "space" are the same.
5561 : */
5562 0 : static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5563 : __isl_keep isl_space *space)
5564 : {
5565 : unsigned dim1, dim2;
5566 :
5567 0 : if (!map || !space)
5568 0 : return isl_stat_error;
5569 0 : dim1 = isl_map_dim(map, isl_dim_all);
5570 0 : dim2 = isl_space_dim(space, isl_dim_all);
5571 0 : if (dim1 == dim2)
5572 0 : return isl_stat_ok;
5573 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
5574 : "total dimensions do not match", return isl_stat_error);
5575 : }
5576 :
5577 0 : __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5578 : __isl_take isl_space *dim)
5579 : {
5580 : int i;
5581 :
5582 0 : map = isl_map_cow(map);
5583 0 : if (!map || !dim)
5584 : goto error;
5585 :
5586 0 : for (i = 0; i < map->n; ++i) {
5587 0 : map->p[i] = isl_basic_map_reset_space(map->p[i],
5588 : isl_space_copy(dim));
5589 0 : if (!map->p[i])
5590 0 : goto error;
5591 : }
5592 0 : isl_space_free(map->dim);
5593 0 : map->dim = dim;
5594 :
5595 0 : return map;
5596 : error:
5597 0 : isl_map_free(map);
5598 0 : isl_space_free(dim);
5599 0 : return NULL;
5600 : }
5601 :
5602 : /* Replace the space of "map" by "space", without modifying
5603 : * the dimension of "map".
5604 : *
5605 : * If the space of "map" is identical to "space" (including the identifiers
5606 : * of the input and output dimensions), then simply return the original input.
5607 : */
5608 0 : __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5609 : __isl_take isl_space *space)
5610 : {
5611 : isl_bool equal;
5612 : isl_space *map_space;
5613 :
5614 0 : map_space = isl_map_peek_space(map);
5615 0 : equal = isl_space_is_equal(map_space, space);
5616 0 : if (equal >= 0 && equal)
5617 0 : equal = isl_space_has_equal_ids(map_space, space);
5618 0 : if (equal < 0)
5619 0 : goto error;
5620 0 : if (equal) {
5621 0 : isl_space_free(space);
5622 0 : return map;
5623 : }
5624 0 : if (check_map_space_equal_total_dim(map, space) < 0)
5625 0 : goto error;
5626 0 : return isl_map_reset_space(map, space);
5627 : error:
5628 0 : isl_map_free(map);
5629 0 : isl_space_free(space);
5630 0 : return NULL;
5631 : }
5632 :
5633 0 : __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5634 : __isl_take isl_space *dim)
5635 : {
5636 0 : return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5637 : }
5638 :
5639 : /* Compute the parameter domain of the given basic set.
5640 : */
5641 0 : __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5642 : {
5643 : isl_bool is_params;
5644 : isl_space *space;
5645 : unsigned n;
5646 :
5647 0 : is_params = isl_basic_set_is_params(bset);
5648 0 : if (is_params < 0)
5649 0 : return isl_basic_set_free(bset);
5650 0 : if (is_params)
5651 0 : return bset;
5652 :
5653 0 : n = isl_basic_set_dim(bset, isl_dim_set);
5654 0 : bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5655 0 : space = isl_basic_set_get_space(bset);
5656 0 : space = isl_space_params(space);
5657 0 : bset = isl_basic_set_reset_space(bset, space);
5658 0 : return bset;
5659 : }
5660 :
5661 : /* Construct a zero-dimensional basic set with the given parameter domain.
5662 : */
5663 0 : __isl_give isl_basic_set *isl_basic_set_from_params(
5664 : __isl_take isl_basic_set *bset)
5665 : {
5666 : isl_space *space;
5667 0 : space = isl_basic_set_get_space(bset);
5668 0 : space = isl_space_set_from_params(space);
5669 0 : bset = isl_basic_set_reset_space(bset, space);
5670 0 : return bset;
5671 : }
5672 :
5673 : /* Compute the parameter domain of the given set.
5674 : */
5675 0 : __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5676 : {
5677 : isl_space *space;
5678 : unsigned n;
5679 :
5680 0 : if (isl_set_is_params(set))
5681 0 : return set;
5682 :
5683 0 : n = isl_set_dim(set, isl_dim_set);
5684 0 : set = isl_set_project_out(set, isl_dim_set, 0, n);
5685 0 : space = isl_set_get_space(set);
5686 0 : space = isl_space_params(space);
5687 0 : set = isl_set_reset_space(set, space);
5688 0 : return set;
5689 : }
5690 :
5691 : /* Construct a zero-dimensional set with the given parameter domain.
5692 : */
5693 0 : __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5694 : {
5695 : isl_space *space;
5696 0 : space = isl_set_get_space(set);
5697 0 : space = isl_space_set_from_params(space);
5698 0 : set = isl_set_reset_space(set, space);
5699 0 : return set;
5700 : }
5701 :
5702 : /* Compute the parameter domain of the given map.
5703 : */
5704 0 : __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5705 : {
5706 : isl_space *space;
5707 : unsigned n;
5708 :
5709 0 : n = isl_map_dim(map, isl_dim_in);
5710 0 : map = isl_map_project_out(map, isl_dim_in, 0, n);
5711 0 : n = isl_map_dim(map, isl_dim_out);
5712 0 : map = isl_map_project_out(map, isl_dim_out, 0, n);
5713 0 : space = isl_map_get_space(map);
5714 0 : space = isl_space_params(space);
5715 0 : map = isl_map_reset_space(map, space);
5716 0 : return map;
5717 : }
5718 :
5719 0 : struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
5720 : {
5721 : isl_space *space;
5722 : unsigned n_out;
5723 :
5724 0 : if (!bmap)
5725 0 : return NULL;
5726 0 : space = isl_space_domain(isl_basic_map_get_space(bmap));
5727 :
5728 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
5729 0 : bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5730 :
5731 0 : return isl_basic_map_reset_space(bmap, space);
5732 : }
5733 :
5734 0 : isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5735 : {
5736 0 : if (!bmap)
5737 0 : return isl_bool_error;
5738 0 : return isl_space_may_be_set(bmap->dim);
5739 : }
5740 :
5741 : /* Is this basic map actually a set?
5742 : * Users should never call this function. Outside of isl,
5743 : * the type should indicate whether something is a set or a map.
5744 : */
5745 0 : isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5746 : {
5747 0 : if (!bmap)
5748 0 : return isl_bool_error;
5749 0 : return isl_space_is_set(bmap->dim);
5750 : }
5751 :
5752 0 : struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5753 : {
5754 : isl_bool is_set;
5755 :
5756 0 : is_set = isl_basic_map_is_set(bmap);
5757 0 : if (is_set < 0)
5758 0 : goto error;
5759 0 : if (is_set)
5760 0 : return bmap;
5761 0 : return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5762 : error:
5763 0 : isl_basic_map_free(bmap);
5764 0 : return NULL;
5765 : }
5766 :
5767 0 : __isl_give isl_basic_map *isl_basic_map_domain_map(
5768 : __isl_take isl_basic_map *bmap)
5769 : {
5770 : int i;
5771 : isl_space *dim;
5772 : isl_basic_map *domain;
5773 : int nparam, n_in, n_out;
5774 :
5775 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
5776 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
5777 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
5778 :
5779 0 : dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
5780 0 : domain = isl_basic_map_universe(dim);
5781 :
5782 0 : bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5783 0 : bmap = isl_basic_map_apply_range(bmap, domain);
5784 0 : bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5785 :
5786 0 : for (i = 0; i < n_in; ++i)
5787 0 : bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5788 : isl_dim_out, i);
5789 :
5790 0 : bmap = isl_basic_map_gauss(bmap, NULL);
5791 0 : return isl_basic_map_finalize(bmap);
5792 : }
5793 :
5794 0 : __isl_give isl_basic_map *isl_basic_map_range_map(
5795 : __isl_take isl_basic_map *bmap)
5796 : {
5797 : int i;
5798 : isl_space *dim;
5799 : isl_basic_map *range;
5800 : int nparam, n_in, n_out;
5801 :
5802 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
5803 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
5804 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
5805 :
5806 0 : dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
5807 0 : range = isl_basic_map_universe(dim);
5808 :
5809 0 : bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5810 0 : bmap = isl_basic_map_apply_range(bmap, range);
5811 0 : bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5812 :
5813 0 : for (i = 0; i < n_out; ++i)
5814 0 : bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5815 : isl_dim_out, i);
5816 :
5817 0 : bmap = isl_basic_map_gauss(bmap, NULL);
5818 0 : return isl_basic_map_finalize(bmap);
5819 : }
5820 :
5821 0 : int isl_map_may_be_set(__isl_keep isl_map *map)
5822 : {
5823 0 : if (!map)
5824 0 : return -1;
5825 0 : return isl_space_may_be_set(map->dim);
5826 : }
5827 :
5828 : /* Is this map actually a set?
5829 : * Users should never call this function. Outside of isl,
5830 : * the type should indicate whether something is a set or a map.
5831 : */
5832 0 : isl_bool isl_map_is_set(__isl_keep isl_map *map)
5833 : {
5834 0 : if (!map)
5835 0 : return isl_bool_error;
5836 0 : return isl_space_is_set(map->dim);
5837 : }
5838 :
5839 0 : __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
5840 : {
5841 : int i;
5842 : isl_bool is_set;
5843 : struct isl_set *set;
5844 :
5845 0 : is_set = isl_map_is_set(map);
5846 0 : if (is_set < 0)
5847 0 : goto error;
5848 0 : if (is_set)
5849 0 : return set_from_map(map);
5850 :
5851 0 : map = isl_map_cow(map);
5852 0 : if (!map)
5853 0 : goto error;
5854 :
5855 0 : set = set_from_map(map);
5856 0 : set->dim = isl_space_range(set->dim);
5857 0 : if (!set->dim)
5858 0 : goto error;
5859 0 : for (i = 0; i < map->n; ++i) {
5860 0 : set->p[i] = isl_basic_map_range(map->p[i]);
5861 0 : if (!set->p[i])
5862 0 : goto error;
5863 : }
5864 0 : ISL_F_CLR(set, ISL_MAP_DISJOINT);
5865 0 : ISL_F_CLR(set, ISL_SET_NORMALIZED);
5866 0 : return set;
5867 : error:
5868 0 : isl_map_free(map);
5869 0 : return NULL;
5870 : }
5871 :
5872 0 : __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5873 : {
5874 : int i;
5875 :
5876 0 : map = isl_map_cow(map);
5877 0 : if (!map)
5878 0 : return NULL;
5879 :
5880 0 : map->dim = isl_space_domain_map(map->dim);
5881 0 : if (!map->dim)
5882 0 : goto error;
5883 0 : for (i = 0; i < map->n; ++i) {
5884 0 : map->p[i] = isl_basic_map_domain_map(map->p[i]);
5885 0 : if (!map->p[i])
5886 0 : goto error;
5887 : }
5888 0 : ISL_F_CLR(map, ISL_MAP_DISJOINT);
5889 0 : map = isl_map_unmark_normalized(map);
5890 0 : return map;
5891 : error:
5892 0 : isl_map_free(map);
5893 0 : return NULL;
5894 : }
5895 :
5896 0 : __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5897 : {
5898 : int i;
5899 : isl_space *range_dim;
5900 :
5901 0 : map = isl_map_cow(map);
5902 0 : if (!map)
5903 0 : return NULL;
5904 :
5905 0 : range_dim = isl_space_range(isl_map_get_space(map));
5906 0 : range_dim = isl_space_from_range(range_dim);
5907 0 : map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5908 0 : map->dim = isl_space_join(map->dim, range_dim);
5909 0 : if (!map->dim)
5910 0 : goto error;
5911 0 : for (i = 0; i < map->n; ++i) {
5912 0 : map->p[i] = isl_basic_map_range_map(map->p[i]);
5913 0 : if (!map->p[i])
5914 0 : goto error;
5915 : }
5916 0 : ISL_F_CLR(map, ISL_MAP_DISJOINT);
5917 0 : map = isl_map_unmark_normalized(map);
5918 0 : return map;
5919 : error:
5920 0 : isl_map_free(map);
5921 0 : return NULL;
5922 : }
5923 :
5924 : /* Given a wrapped map of the form A[B -> C],
5925 : * return the map A[B -> C] -> B.
5926 : */
5927 0 : __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5928 : {
5929 : isl_id *id;
5930 : isl_map *map;
5931 :
5932 0 : if (!set)
5933 0 : return NULL;
5934 0 : if (!isl_set_has_tuple_id(set))
5935 0 : return isl_map_domain_map(isl_set_unwrap(set));
5936 :
5937 0 : id = isl_set_get_tuple_id(set);
5938 0 : map = isl_map_domain_map(isl_set_unwrap(set));
5939 0 : map = isl_map_set_tuple_id(map, isl_dim_in, id);
5940 :
5941 0 : return map;
5942 : }
5943 :
5944 0 : __isl_give isl_basic_map *isl_basic_map_from_domain(
5945 : __isl_take isl_basic_set *bset)
5946 : {
5947 0 : return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5948 : }
5949 :
5950 0 : __isl_give isl_basic_map *isl_basic_map_from_range(
5951 : __isl_take isl_basic_set *bset)
5952 : {
5953 : isl_space *space;
5954 0 : space = isl_basic_set_get_space(bset);
5955 0 : space = isl_space_from_range(space);
5956 0 : bset = isl_basic_set_reset_space(bset, space);
5957 0 : return bset_to_bmap(bset);
5958 : }
5959 :
5960 : /* Create a relation with the given set as range.
5961 : * The domain of the created relation is a zero-dimensional
5962 : * flat anonymous space.
5963 : */
5964 0 : __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5965 : {
5966 : isl_space *space;
5967 0 : space = isl_set_get_space(set);
5968 0 : space = isl_space_from_range(space);
5969 0 : set = isl_set_reset_space(set, space);
5970 0 : return set_to_map(set);
5971 : }
5972 :
5973 : /* Create a relation with the given set as domain.
5974 : * The range of the created relation is a zero-dimensional
5975 : * flat anonymous space.
5976 : */
5977 0 : __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5978 : {
5979 0 : return isl_map_reverse(isl_map_from_range(set));
5980 : }
5981 :
5982 0 : __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5983 : __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5984 : {
5985 0 : return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5986 : }
5987 :
5988 0 : __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5989 : __isl_take isl_set *range)
5990 : {
5991 0 : return isl_map_apply_range(isl_map_reverse(domain), range);
5992 : }
5993 :
5994 : /* Return a newly allocated isl_map with given space and flags and
5995 : * room for "n" basic maps.
5996 : * Make sure that all cached information is cleared.
5997 : */
5998 3097843431 : __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5999 : unsigned flags)
6000 : {
6001 : struct isl_map *map;
6002 :
6003 3097843431 : if (!space)
6004 0 : return NULL;
6005 3097843431 : if (n < 0)
6006 0 : isl_die(space->ctx, isl_error_internal,
6007 : "negative number of basic maps", goto error);
6008 3097843431 : map = isl_calloc(space->ctx, struct isl_map,
6009 : sizeof(struct isl_map) +
6010 : (n - 1) * sizeof(struct isl_basic_map *));
6011 3097843431 : if (!map)
6012 0 : goto error;
6013 :
6014 3097843431 : map->ctx = space->ctx;
6015 3097843431 : isl_ctx_ref(map->ctx);
6016 3097843431 : map->ref = 1;
6017 3097843431 : map->size = n;
6018 3097843431 : map->n = 0;
6019 3097843431 : map->dim = space;
6020 3097843431 : map->flags = flags;
6021 3097843431 : return map;
6022 : error:
6023 0 : isl_space_free(space);
6024 0 : return NULL;
6025 : }
6026 :
6027 0 : __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
6028 : {
6029 : struct isl_basic_map *bmap;
6030 0 : bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
6031 0 : bmap = isl_basic_map_set_to_empty(bmap);
6032 0 : return bmap;
6033 : }
6034 :
6035 1395249 : __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
6036 : {
6037 : struct isl_basic_set *bset;
6038 1395249 : bset = isl_basic_set_alloc_space(space, 0, 1, 0);
6039 1395249 : bset = isl_basic_set_set_to_empty(bset);
6040 1395249 : return bset;
6041 : }
6042 :
6043 2497658 : __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6044 : {
6045 : struct isl_basic_map *bmap;
6046 2497658 : bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6047 2497658 : bmap = isl_basic_map_finalize(bmap);
6048 2497658 : return bmap;
6049 : }
6050 :
6051 44198346 : __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6052 : {
6053 : struct isl_basic_set *bset;
6054 44198346 : bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6055 44198346 : bset = isl_basic_set_finalize(bset);
6056 44198346 : return bset;
6057 : }
6058 :
6059 0 : __isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
6060 : {
6061 : int i;
6062 0 : unsigned total = isl_space_dim(dim, isl_dim_all);
6063 : isl_basic_map *bmap;
6064 :
6065 0 : bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
6066 0 : for (i = 0; i < total; ++i) {
6067 0 : int k = isl_basic_map_alloc_inequality(bmap);
6068 0 : if (k < 0)
6069 0 : goto error;
6070 0 : isl_seq_clr(bmap->ineq[k], 1 + total);
6071 0 : isl_int_set_si(bmap->ineq[k][1 + i], 1);
6072 : }
6073 0 : return bmap;
6074 : error:
6075 0 : isl_basic_map_free(bmap);
6076 0 : return NULL;
6077 : }
6078 :
6079 0 : __isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
6080 : {
6081 0 : return isl_basic_map_nat_universe(dim);
6082 : }
6083 :
6084 0 : __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
6085 : {
6086 0 : return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
6087 : }
6088 :
6089 0 : __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
6090 : {
6091 0 : return isl_map_nat_universe(dim);
6092 : }
6093 :
6094 9372002 : __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6095 : {
6096 9372002 : return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6097 : }
6098 :
6099 112944 : __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6100 : {
6101 112944 : return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6102 : }
6103 :
6104 2497658 : __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6105 : {
6106 : struct isl_map *map;
6107 2497658 : if (!space)
6108 0 : return NULL;
6109 2497658 : map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6110 2497658 : map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6111 2497658 : return map;
6112 : }
6113 :
6114 0 : __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6115 : {
6116 : struct isl_set *set;
6117 0 : if (!space)
6118 0 : return NULL;
6119 0 : set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6120 0 : set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6121 0 : return set;
6122 : }
6123 :
6124 3004729040 : struct isl_map *isl_map_dup(struct isl_map *map)
6125 : {
6126 : int i;
6127 : struct isl_map *dup;
6128 :
6129 3004729040 : if (!map)
6130 0 : return NULL;
6131 3004729040 : dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6132 13794417009 : for (i = 0; i < map->n; ++i)
6133 10789687969 : dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6134 3004729040 : return dup;
6135 : }
6136 :
6137 12132986604 : __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6138 : __isl_take isl_basic_map *bmap)
6139 : {
6140 12132986604 : if (!bmap || !map)
6141 : goto error;
6142 12132986604 : if (isl_basic_map_plain_is_empty(bmap)) {
6143 93152530 : isl_basic_map_free(bmap);
6144 93152530 : return map;
6145 : }
6146 12039834074 : isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
6147 12039834074 : isl_assert(map->ctx, map->n < map->size, goto error);
6148 12039834074 : map->p[map->n] = bmap;
6149 12039834074 : map->n++;
6150 12039834074 : map = isl_map_unmark_normalized(map);
6151 12039834074 : return map;
6152 : error:
6153 0 : if (map)
6154 0 : isl_map_free(map);
6155 0 : if (bmap)
6156 0 : isl_basic_map_free(bmap);
6157 0 : return NULL;
6158 : }
6159 :
6160 3146216809 : __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6161 : {
6162 : int i;
6163 :
6164 3146216809 : if (!map)
6165 0 : return NULL;
6166 :
6167 3146216809 : if (--map->ref > 0)
6168 48373378 : return NULL;
6169 :
6170 3097843431 : clear_caches(map);
6171 3097843431 : isl_ctx_deref(map->ctx);
6172 12345747275 : for (i = 0; i < map->n; ++i)
6173 9247903844 : isl_basic_map_free(map->p[i]);
6174 3097843431 : isl_space_free(map->dim);
6175 3097843431 : free(map);
6176 :
6177 3097843431 : return NULL;
6178 : }
6179 :
6180 0 : static struct isl_basic_map *isl_basic_map_fix_pos_si(
6181 : struct isl_basic_map *bmap, unsigned pos, int value)
6182 : {
6183 : int j;
6184 :
6185 0 : bmap = isl_basic_map_cow(bmap);
6186 0 : bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6187 0 : j = isl_basic_map_alloc_equality(bmap);
6188 0 : if (j < 0)
6189 0 : goto error;
6190 0 : isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6191 0 : isl_int_set_si(bmap->eq[j][pos], -1);
6192 0 : isl_int_set_si(bmap->eq[j][0], value);
6193 0 : bmap = isl_basic_map_simplify(bmap);
6194 0 : return isl_basic_map_finalize(bmap);
6195 : error:
6196 0 : isl_basic_map_free(bmap);
6197 0 : return NULL;
6198 : }
6199 :
6200 0 : static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6201 : __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6202 : {
6203 : int j;
6204 :
6205 0 : bmap = isl_basic_map_cow(bmap);
6206 0 : bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6207 0 : j = isl_basic_map_alloc_equality(bmap);
6208 0 : if (j < 0)
6209 0 : goto error;
6210 0 : isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
6211 0 : isl_int_set_si(bmap->eq[j][pos], -1);
6212 0 : isl_int_set(bmap->eq[j][0], value);
6213 0 : bmap = isl_basic_map_simplify(bmap);
6214 0 : return isl_basic_map_finalize(bmap);
6215 : error:
6216 0 : isl_basic_map_free(bmap);
6217 0 : return NULL;
6218 : }
6219 :
6220 0 : __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6221 : enum isl_dim_type type, unsigned pos, int value)
6222 : {
6223 0 : if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6224 0 : return isl_basic_map_free(bmap);
6225 0 : return isl_basic_map_fix_pos_si(bmap,
6226 0 : isl_basic_map_offset(bmap, type) + pos, value);
6227 : }
6228 :
6229 0 : __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6230 : enum isl_dim_type type, unsigned pos, isl_int value)
6231 : {
6232 0 : if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6233 0 : return isl_basic_map_free(bmap);
6234 0 : return isl_basic_map_fix_pos(bmap,
6235 0 : isl_basic_map_offset(bmap, type) + pos, value);
6236 : }
6237 :
6238 : /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6239 : * to be equal to "v".
6240 : */
6241 0 : __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6242 : enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6243 : {
6244 0 : if (!bmap || !v)
6245 : goto error;
6246 0 : if (!isl_val_is_int(v))
6247 0 : isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6248 : "expecting integer value", goto error);
6249 0 : if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6250 0 : goto error;
6251 0 : pos += isl_basic_map_offset(bmap, type);
6252 0 : bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6253 0 : isl_val_free(v);
6254 0 : return bmap;
6255 : error:
6256 0 : isl_basic_map_free(bmap);
6257 0 : isl_val_free(v);
6258 0 : return NULL;
6259 : }
6260 :
6261 : /* Fix the value of the variable at position "pos" of type "type" of "bset"
6262 : * to be equal to "v".
6263 : */
6264 0 : __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6265 : enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6266 : {
6267 0 : return isl_basic_map_fix_val(bset, type, pos, v);
6268 : }
6269 :
6270 0 : struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
6271 : enum isl_dim_type type, unsigned pos, int value)
6272 : {
6273 0 : return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6274 : type, pos, value));
6275 : }
6276 :
6277 0 : __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6278 : enum isl_dim_type type, unsigned pos, isl_int value)
6279 : {
6280 0 : return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6281 : type, pos, value));
6282 : }
6283 :
6284 0 : struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
6285 : unsigned input, int value)
6286 : {
6287 0 : return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
6288 : }
6289 :
6290 0 : struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
6291 : unsigned dim, int value)
6292 : {
6293 0 : return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6294 : isl_dim_set, dim, value));
6295 : }
6296 :
6297 : /* Remove the basic map at position "i" from "map" if this basic map
6298 : * is (obviously) empty.
6299 : */
6300 13325972331 : static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6301 : {
6302 : isl_bool empty;
6303 :
6304 13325972331 : if (!map)
6305 0 : return NULL;
6306 :
6307 13325972331 : empty = isl_basic_map_plain_is_empty(map->p[i]);
6308 13325972331 : if (empty < 0)
6309 0 : return isl_map_free(map);
6310 13325972331 : if (!empty)
6311 11078470650 : return map;
6312 :
6313 2247501681 : isl_basic_map_free(map->p[i]);
6314 2247501681 : map->n--;
6315 2247501681 : if (i != map->n) {
6316 1477095453 : map->p[i] = map->p[map->n];
6317 1477095453 : map = isl_map_unmark_normalized(map);
6318 :
6319 : }
6320 :
6321 2247501681 : return map;
6322 : }
6323 :
6324 : /* Perform "fn" on each basic map of "map", where we may not be holding
6325 : * the only reference to "map".
6326 : * In particular, "fn" should be a semantics preserving operation
6327 : * that we want to apply to all copies of "map". We therefore need
6328 : * to be careful not to modify "map" in a way that breaks "map"
6329 : * in case anything goes wrong.
6330 : */
6331 1854329904 : __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6332 : __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6333 : {
6334 : struct isl_basic_map *bmap;
6335 : int i;
6336 :
6337 1854329904 : if (!map)
6338 0 : return NULL;
6339 :
6340 6932353310 : for (i = map->n - 1; i >= 0; --i) {
6341 5078023406 : bmap = isl_basic_map_copy(map->p[i]);
6342 5078023406 : bmap = fn(bmap);
6343 5078023406 : if (!bmap)
6344 0 : goto error;
6345 5078023406 : isl_basic_map_free(map->p[i]);
6346 5078023406 : map->p[i] = bmap;
6347 5078023406 : map = remove_if_empty(map, i);
6348 5078023406 : if (!map)
6349 0 : return NULL;
6350 : }
6351 :
6352 1854329904 : return map;
6353 : error:
6354 0 : isl_map_free(map);
6355 0 : return NULL;
6356 : }
6357 :
6358 0 : __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6359 : enum isl_dim_type type, unsigned pos, int value)
6360 : {
6361 : int i;
6362 :
6363 0 : map = isl_map_cow(map);
6364 0 : if (!map)
6365 0 : return NULL;
6366 :
6367 0 : isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6368 0 : for (i = map->n - 1; i >= 0; --i) {
6369 0 : map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6370 0 : map = remove_if_empty(map, i);
6371 0 : if (!map)
6372 0 : return NULL;
6373 : }
6374 0 : map = isl_map_unmark_normalized(map);
6375 0 : return map;
6376 : error:
6377 0 : isl_map_free(map);
6378 0 : return NULL;
6379 : }
6380 :
6381 0 : __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6382 : enum isl_dim_type type, unsigned pos, int value)
6383 : {
6384 0 : return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6385 : }
6386 :
6387 0 : __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6388 : enum isl_dim_type type, unsigned pos, isl_int value)
6389 : {
6390 : int i;
6391 :
6392 0 : map = isl_map_cow(map);
6393 0 : if (!map)
6394 0 : return NULL;
6395 :
6396 0 : isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6397 0 : for (i = 0; i < map->n; ++i) {
6398 0 : map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6399 0 : if (!map->p[i])
6400 0 : goto error;
6401 : }
6402 0 : map = isl_map_unmark_normalized(map);
6403 0 : return map;
6404 : error:
6405 0 : isl_map_free(map);
6406 0 : return NULL;
6407 : }
6408 :
6409 0 : __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6410 : enum isl_dim_type type, unsigned pos, isl_int value)
6411 : {
6412 0 : return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6413 : }
6414 :
6415 : /* Fix the value of the variable at position "pos" of type "type" of "map"
6416 : * to be equal to "v".
6417 : */
6418 0 : __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6419 : enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6420 : {
6421 : int i;
6422 :
6423 0 : map = isl_map_cow(map);
6424 0 : if (!map || !v)
6425 : goto error;
6426 :
6427 0 : if (!isl_val_is_int(v))
6428 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
6429 : "expecting integer value", goto error);
6430 0 : if (pos >= isl_map_dim(map, type))
6431 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
6432 : "index out of bounds", goto error);
6433 0 : for (i = map->n - 1; i >= 0; --i) {
6434 0 : map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6435 : isl_val_copy(v));
6436 0 : map = remove_if_empty(map, i);
6437 0 : if (!map)
6438 0 : goto error;
6439 : }
6440 0 : map = isl_map_unmark_normalized(map);
6441 0 : isl_val_free(v);
6442 0 : return map;
6443 : error:
6444 0 : isl_map_free(map);
6445 0 : isl_val_free(v);
6446 0 : return NULL;
6447 : }
6448 :
6449 : /* Fix the value of the variable at position "pos" of type "type" of "set"
6450 : * to be equal to "v".
6451 : */
6452 0 : __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6453 : enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6454 : {
6455 0 : return isl_map_fix_val(set, type, pos, v);
6456 : }
6457 :
6458 0 : struct isl_map *isl_map_fix_input_si(struct isl_map *map,
6459 : unsigned input, int value)
6460 : {
6461 0 : return isl_map_fix_si(map, isl_dim_in, input, value);
6462 : }
6463 :
6464 0 : struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
6465 : {
6466 0 : return set_from_map(isl_map_fix_si(set_to_map(set),
6467 : isl_dim_set, dim, value));
6468 : }
6469 :
6470 0 : static __isl_give isl_basic_map *basic_map_bound_si(
6471 : __isl_take isl_basic_map *bmap,
6472 : enum isl_dim_type type, unsigned pos, int value, int upper)
6473 : {
6474 : int j;
6475 :
6476 0 : if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6477 0 : return isl_basic_map_free(bmap);
6478 0 : pos += isl_basic_map_offset(bmap, type);
6479 0 : bmap = isl_basic_map_cow(bmap);
6480 0 : bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6481 0 : j = isl_basic_map_alloc_inequality(bmap);
6482 0 : if (j < 0)
6483 0 : goto error;
6484 0 : isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6485 0 : if (upper) {
6486 0 : isl_int_set_si(bmap->ineq[j][pos], -1);
6487 0 : isl_int_set_si(bmap->ineq[j][0], value);
6488 : } else {
6489 0 : isl_int_set_si(bmap->ineq[j][pos], 1);
6490 0 : isl_int_set_si(bmap->ineq[j][0], -value);
6491 : }
6492 0 : bmap = isl_basic_map_simplify(bmap);
6493 0 : return isl_basic_map_finalize(bmap);
6494 : error:
6495 0 : isl_basic_map_free(bmap);
6496 0 : return NULL;
6497 : }
6498 :
6499 0 : __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6500 : __isl_take isl_basic_map *bmap,
6501 : enum isl_dim_type type, unsigned pos, int value)
6502 : {
6503 0 : return basic_map_bound_si(bmap, type, pos, value, 0);
6504 : }
6505 :
6506 : /* Constrain the values of the given dimension to be no greater than "value".
6507 : */
6508 0 : __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6509 : __isl_take isl_basic_map *bmap,
6510 : enum isl_dim_type type, unsigned pos, int value)
6511 : {
6512 0 : return basic_map_bound_si(bmap, type, pos, value, 1);
6513 : }
6514 :
6515 0 : static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6516 : enum isl_dim_type type, unsigned pos, int value, int upper)
6517 : {
6518 : int i;
6519 :
6520 0 : map = isl_map_cow(map);
6521 0 : if (!map)
6522 0 : return NULL;
6523 :
6524 0 : isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
6525 0 : for (i = 0; i < map->n; ++i) {
6526 0 : map->p[i] = basic_map_bound_si(map->p[i],
6527 : type, pos, value, upper);
6528 0 : if (!map->p[i])
6529 0 : goto error;
6530 : }
6531 0 : map = isl_map_unmark_normalized(map);
6532 0 : return map;
6533 : error:
6534 0 : isl_map_free(map);
6535 0 : return NULL;
6536 : }
6537 :
6538 0 : __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6539 : enum isl_dim_type type, unsigned pos, int value)
6540 : {
6541 0 : return map_bound_si(map, type, pos, value, 0);
6542 : }
6543 :
6544 0 : __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6545 : enum isl_dim_type type, unsigned pos, int value)
6546 : {
6547 0 : return map_bound_si(map, type, pos, value, 1);
6548 : }
6549 :
6550 0 : __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6551 : enum isl_dim_type type, unsigned pos, int value)
6552 : {
6553 0 : return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6554 : type, pos, value));
6555 : }
6556 :
6557 0 : __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6558 : enum isl_dim_type type, unsigned pos, int value)
6559 : {
6560 0 : return isl_map_upper_bound_si(set, type, pos, value);
6561 : }
6562 :
6563 : /* Bound the given variable of "bmap" from below (or above is "upper"
6564 : * is set) to "value".
6565 : */
6566 0 : static __isl_give isl_basic_map *basic_map_bound(
6567 : __isl_take isl_basic_map *bmap,
6568 : enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6569 : {
6570 : int j;
6571 :
6572 0 : if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6573 0 : return isl_basic_map_free(bmap);
6574 0 : pos += isl_basic_map_offset(bmap, type);
6575 0 : bmap = isl_basic_map_cow(bmap);
6576 0 : bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6577 0 : j = isl_basic_map_alloc_inequality(bmap);
6578 0 : if (j < 0)
6579 0 : goto error;
6580 0 : isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6581 0 : if (upper) {
6582 0 : isl_int_set_si(bmap->ineq[j][pos], -1);
6583 0 : isl_int_set(bmap->ineq[j][0], value);
6584 : } else {
6585 0 : isl_int_set_si(bmap->ineq[j][pos], 1);
6586 0 : isl_int_neg(bmap->ineq[j][0], value);
6587 : }
6588 0 : bmap = isl_basic_map_simplify(bmap);
6589 0 : return isl_basic_map_finalize(bmap);
6590 : error:
6591 0 : isl_basic_map_free(bmap);
6592 0 : return NULL;
6593 : }
6594 :
6595 : /* Bound the given variable of "map" from below (or above is "upper"
6596 : * is set) to "value".
6597 : */
6598 0 : static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6599 : enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6600 : {
6601 : int i;
6602 :
6603 0 : map = isl_map_cow(map);
6604 0 : if (!map)
6605 0 : return NULL;
6606 :
6607 0 : if (pos >= isl_map_dim(map, type))
6608 0 : isl_die(map->ctx, isl_error_invalid,
6609 : "index out of bounds", goto error);
6610 0 : for (i = map->n - 1; i >= 0; --i) {
6611 0 : map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6612 0 : map = remove_if_empty(map, i);
6613 0 : if (!map)
6614 0 : return NULL;
6615 : }
6616 0 : map = isl_map_unmark_normalized(map);
6617 0 : return map;
6618 : error:
6619 0 : isl_map_free(map);
6620 0 : return NULL;
6621 : }
6622 :
6623 0 : __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6624 : enum isl_dim_type type, unsigned pos, isl_int value)
6625 : {
6626 0 : return map_bound(map, type, pos, value, 0);
6627 : }
6628 :
6629 0 : __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6630 : enum isl_dim_type type, unsigned pos, isl_int value)
6631 : {
6632 0 : return map_bound(map, type, pos, value, 1);
6633 : }
6634 :
6635 0 : __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6636 : enum isl_dim_type type, unsigned pos, isl_int value)
6637 : {
6638 0 : return isl_map_lower_bound(set, type, pos, value);
6639 : }
6640 :
6641 0 : __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6642 : enum isl_dim_type type, unsigned pos, isl_int value)
6643 : {
6644 0 : return isl_map_upper_bound(set, type, pos, value);
6645 : }
6646 :
6647 : /* Force the values of the variable at position "pos" of type "type" of "set"
6648 : * to be no smaller than "value".
6649 : */
6650 0 : __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6651 : enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6652 : {
6653 0 : if (!value)
6654 0 : goto error;
6655 0 : if (!isl_val_is_int(value))
6656 0 : isl_die(isl_set_get_ctx(set), isl_error_invalid,
6657 : "expecting integer value", goto error);
6658 0 : set = isl_set_lower_bound(set, type, pos, value->n);
6659 0 : isl_val_free(value);
6660 0 : return set;
6661 : error:
6662 0 : isl_val_free(value);
6663 0 : isl_set_free(set);
6664 0 : return NULL;
6665 : }
6666 :
6667 : /* Force the values of the variable at position "pos" of type "type" of "set"
6668 : * to be no greater than "value".
6669 : */
6670 0 : __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6671 : enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6672 : {
6673 0 : if (!value)
6674 0 : goto error;
6675 0 : if (!isl_val_is_int(value))
6676 0 : isl_die(isl_set_get_ctx(set), isl_error_invalid,
6677 : "expecting integer value", goto error);
6678 0 : set = isl_set_upper_bound(set, type, pos, value->n);
6679 0 : isl_val_free(value);
6680 0 : return set;
6681 : error:
6682 0 : isl_val_free(value);
6683 0 : isl_set_free(set);
6684 0 : return NULL;
6685 : }
6686 :
6687 : /* Bound the given variable of "bset" from below (or above is "upper"
6688 : * is set) to "value".
6689 : */
6690 0 : static __isl_give isl_basic_set *isl_basic_set_bound(
6691 : __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6692 : isl_int value, int upper)
6693 : {
6694 0 : return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
6695 : type, pos, value, upper));
6696 : }
6697 :
6698 : /* Bound the given variable of "bset" from below (or above is "upper"
6699 : * is set) to "value".
6700 : */
6701 0 : static __isl_give isl_basic_set *isl_basic_set_bound_val(
6702 : __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6703 : __isl_take isl_val *value, int upper)
6704 : {
6705 0 : if (!value)
6706 0 : goto error;
6707 0 : if (!isl_val_is_int(value))
6708 0 : isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
6709 : "expecting integer value", goto error);
6710 0 : bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
6711 0 : isl_val_free(value);
6712 0 : return bset;
6713 : error:
6714 0 : isl_val_free(value);
6715 0 : isl_basic_set_free(bset);
6716 0 : return NULL;
6717 : }
6718 :
6719 : /* Bound the given variable of "bset" from below to "value".
6720 : */
6721 0 : __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
6722 : __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6723 : __isl_take isl_val *value)
6724 : {
6725 0 : return isl_basic_set_bound_val(bset, type, pos, value, 0);
6726 : }
6727 :
6728 : /* Bound the given variable of "bset" from above to "value".
6729 : */
6730 0 : __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
6731 : __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
6732 : __isl_take isl_val *value)
6733 : {
6734 0 : return isl_basic_set_bound_val(bset, type, pos, value, 1);
6735 : }
6736 :
6737 0 : __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
6738 : {
6739 : int i;
6740 :
6741 0 : map = isl_map_cow(map);
6742 0 : if (!map)
6743 0 : return NULL;
6744 :
6745 0 : map->dim = isl_space_reverse(map->dim);
6746 0 : if (!map->dim)
6747 0 : goto error;
6748 0 : for (i = 0; i < map->n; ++i) {
6749 0 : map->p[i] = isl_basic_map_reverse(map->p[i]);
6750 0 : if (!map->p[i])
6751 0 : goto error;
6752 : }
6753 0 : map = isl_map_unmark_normalized(map);
6754 0 : return map;
6755 : error:
6756 0 : isl_map_free(map);
6757 0 : return NULL;
6758 : }
6759 :
6760 : #undef TYPE
6761 : #define TYPE isl_pw_multi_aff
6762 : #undef SUFFIX
6763 : #define SUFFIX _pw_multi_aff
6764 : #undef EMPTY
6765 : #define EMPTY isl_pw_multi_aff_empty
6766 : #undef ADD
6767 : #define ADD isl_pw_multi_aff_union_add
6768 : #include "isl_map_lexopt_templ.c"
6769 :
6770 : /* Given a map "map", compute the lexicographically minimal
6771 : * (or maximal) image element for each domain element in dom,
6772 : * in the form of an isl_pw_multi_aff.
6773 : * If "empty" is not NULL, then set *empty to those elements in dom that
6774 : * do not have an image element.
6775 : * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6776 : * should be computed over the domain of "map". "empty" is also NULL
6777 : * in this case.
6778 : *
6779 : * We first compute the lexicographically minimal or maximal element
6780 : * in the first basic map. This results in a partial solution "res"
6781 : * and a subset "todo" of dom that still need to be handled.
6782 : * We then consider each of the remaining maps in "map" and successively
6783 : * update both "res" and "todo".
6784 : * If "empty" is NULL, then the todo sets are not needed and therefore
6785 : * also not computed.
6786 : */
6787 0 : static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6788 : __isl_take isl_map *map, __isl_take isl_set *dom,
6789 : __isl_give isl_set **empty, unsigned flags)
6790 : {
6791 : int i;
6792 : int full;
6793 : isl_pw_multi_aff *res;
6794 : isl_set *todo;
6795 :
6796 0 : full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6797 0 : if (!map || (!full && !dom))
6798 : goto error;
6799 :
6800 0 : if (isl_map_plain_is_empty(map)) {
6801 0 : if (empty)
6802 0 : *empty = dom;
6803 : else
6804 0 : isl_set_free(dom);
6805 0 : return isl_pw_multi_aff_from_map(map);
6806 : }
6807 :
6808 0 : res = basic_map_partial_lexopt_pw_multi_aff(
6809 0 : isl_basic_map_copy(map->p[0]),
6810 : isl_set_copy(dom), empty, flags);
6811 :
6812 0 : if (empty)
6813 0 : todo = *empty;
6814 0 : for (i = 1; i < map->n; ++i) {
6815 : isl_pw_multi_aff *res_i;
6816 :
6817 0 : res_i = basic_map_partial_lexopt_pw_multi_aff(
6818 0 : isl_basic_map_copy(map->p[i]),
6819 : isl_set_copy(dom), empty, flags);
6820 :
6821 0 : if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6822 0 : res = isl_pw_multi_aff_union_lexmax(res, res_i);
6823 : else
6824 0 : res = isl_pw_multi_aff_union_lexmin(res, res_i);
6825 :
6826 0 : if (empty)
6827 0 : todo = isl_set_intersect(todo, *empty);
6828 : }
6829 :
6830 0 : isl_set_free(dom);
6831 0 : isl_map_free(map);
6832 :
6833 0 : if (empty)
6834 0 : *empty = todo;
6835 :
6836 0 : return res;
6837 : error:
6838 0 : if (empty)
6839 0 : *empty = NULL;
6840 0 : isl_set_free(dom);
6841 0 : isl_map_free(map);
6842 0 : return NULL;
6843 : }
6844 :
6845 : #undef TYPE
6846 : #define TYPE isl_map
6847 : #undef SUFFIX
6848 : #define SUFFIX
6849 : #undef EMPTY
6850 : #define EMPTY isl_map_empty
6851 : #undef ADD
6852 : #define ADD isl_map_union_disjoint
6853 : #include "isl_map_lexopt_templ.c"
6854 :
6855 : /* Given a map "map", compute the lexicographically minimal
6856 : * (or maximal) image element for each domain element in "dom",
6857 : * in the form of an isl_map.
6858 : * If "empty" is not NULL, then set *empty to those elements in "dom" that
6859 : * do not have an image element.
6860 : * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6861 : * should be computed over the domain of "map". "empty" is also NULL
6862 : * in this case.
6863 : *
6864 : * If the input consists of more than one disjunct, then first
6865 : * compute the desired result in the form of an isl_pw_multi_aff and
6866 : * then convert that into an isl_map.
6867 : *
6868 : * This function used to have an explicit implementation in terms
6869 : * of isl_maps, but it would continually intersect the domains of
6870 : * partial results with the complement of the domain of the next
6871 : * partial solution, potentially leading to an explosion in the number
6872 : * of disjuncts if there are several disjuncts in the input.
6873 : * An even earlier implementation of this function would look for
6874 : * better results in the domain of the partial result and for extra
6875 : * results in the complement of this domain, which would lead to
6876 : * even more splintering.
6877 : */
6878 0 : static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6879 : __isl_take isl_map *map, __isl_take isl_set *dom,
6880 : __isl_give isl_set **empty, unsigned flags)
6881 : {
6882 : int full;
6883 : struct isl_map *res;
6884 : isl_pw_multi_aff *pma;
6885 :
6886 0 : full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6887 0 : if (!map || (!full && !dom))
6888 : goto error;
6889 :
6890 0 : if (isl_map_plain_is_empty(map)) {
6891 0 : if (empty)
6892 0 : *empty = dom;
6893 : else
6894 0 : isl_set_free(dom);
6895 0 : return map;
6896 : }
6897 :
6898 0 : if (map->n == 1) {
6899 0 : res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6900 : dom, empty, flags);
6901 0 : isl_map_free(map);
6902 0 : return res;
6903 : }
6904 :
6905 0 : pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6906 : flags);
6907 0 : return isl_map_from_pw_multi_aff(pma);
6908 : error:
6909 0 : if (empty)
6910 0 : *empty = NULL;
6911 0 : isl_set_free(dom);
6912 0 : isl_map_free(map);
6913 0 : return NULL;
6914 : }
6915 :
6916 0 : __isl_give isl_map *isl_map_partial_lexmax(
6917 : __isl_take isl_map *map, __isl_take isl_set *dom,
6918 : __isl_give isl_set **empty)
6919 : {
6920 0 : return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6921 : }
6922 :
6923 0 : __isl_give isl_map *isl_map_partial_lexmin(
6924 : __isl_take isl_map *map, __isl_take isl_set *dom,
6925 : __isl_give isl_set **empty)
6926 : {
6927 0 : return isl_map_partial_lexopt(map, dom, empty, 0);
6928 : }
6929 :
6930 0 : __isl_give isl_set *isl_set_partial_lexmin(
6931 : __isl_take isl_set *set, __isl_take isl_set *dom,
6932 : __isl_give isl_set **empty)
6933 : {
6934 0 : return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6935 : dom, empty));
6936 : }
6937 :
6938 0 : __isl_give isl_set *isl_set_partial_lexmax(
6939 : __isl_take isl_set *set, __isl_take isl_set *dom,
6940 : __isl_give isl_set **empty)
6941 : {
6942 0 : return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6943 : dom, empty));
6944 : }
6945 :
6946 : /* Compute the lexicographic minimum (or maximum if "flags" includes
6947 : * ISL_OPT_MAX) of "bset" over its parametric domain.
6948 : */
6949 0 : __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6950 : unsigned flags)
6951 : {
6952 0 : return isl_basic_map_lexopt(bset, flags);
6953 : }
6954 :
6955 0 : __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6956 : {
6957 0 : return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6958 : }
6959 :
6960 0 : __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6961 : {
6962 0 : return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6963 : }
6964 :
6965 0 : __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6966 : {
6967 0 : return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6968 : }
6969 :
6970 : /* Compute the lexicographic minimum of "bset" over its parametric domain
6971 : * for the purpose of quantifier elimination.
6972 : * That is, find an explicit representation for all the existentially
6973 : * quantified variables in "bset" by computing their lexicographic
6974 : * minimum.
6975 : */
6976 0 : static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6977 : __isl_take isl_basic_set *bset)
6978 : {
6979 0 : return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6980 : }
6981 :
6982 : /* Given a basic map with one output dimension, compute the minimum or
6983 : * maximum of that dimension as an isl_pw_aff.
6984 : *
6985 : * Compute the optimum as a lexicographic optimum over the single
6986 : * output dimension and extract the single isl_pw_aff from the result.
6987 : */
6988 0 : static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6989 : int max)
6990 : {
6991 : isl_pw_multi_aff *pma;
6992 : isl_pw_aff *pwaff;
6993 :
6994 0 : bmap = isl_basic_map_copy(bmap);
6995 0 : pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
6996 0 : pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
6997 0 : isl_pw_multi_aff_free(pma);
6998 :
6999 0 : return pwaff;
7000 : }
7001 :
7002 : /* Compute the minimum or maximum of the given output dimension
7003 : * as a function of the parameters and the input dimensions,
7004 : * but independently of the other output dimensions.
7005 : *
7006 : * We first project out the other output dimension and then compute
7007 : * the "lexicographic" maximum in each basic map, combining the results
7008 : * using isl_pw_aff_union_max.
7009 : */
7010 0 : static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
7011 : int max)
7012 : {
7013 : int i;
7014 : isl_pw_aff *pwaff;
7015 : unsigned n_out;
7016 :
7017 0 : n_out = isl_map_dim(map, isl_dim_out);
7018 0 : map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7019 0 : map = isl_map_project_out(map, isl_dim_out, 0, pos);
7020 0 : if (!map)
7021 0 : return NULL;
7022 :
7023 0 : if (map->n == 0) {
7024 0 : isl_space *dim = isl_map_get_space(map);
7025 0 : isl_map_free(map);
7026 0 : return isl_pw_aff_empty(dim);
7027 : }
7028 :
7029 0 : pwaff = basic_map_dim_opt(map->p[0], max);
7030 0 : for (i = 1; i < map->n; ++i) {
7031 : isl_pw_aff *pwaff_i;
7032 :
7033 0 : pwaff_i = basic_map_dim_opt(map->p[i], max);
7034 0 : pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7035 : }
7036 :
7037 0 : isl_map_free(map);
7038 :
7039 0 : return pwaff;
7040 : }
7041 :
7042 : /* Compute the minimum of the given output dimension as a function of the
7043 : * parameters and input dimensions, but independently of
7044 : * the other output dimensions.
7045 : */
7046 0 : __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7047 : {
7048 0 : return map_dim_opt(map, pos, 0);
7049 : }
7050 :
7051 : /* Compute the maximum of the given output dimension as a function of the
7052 : * parameters and input dimensions, but independently of
7053 : * the other output dimensions.
7054 : */
7055 0 : __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7056 : {
7057 0 : return map_dim_opt(map, pos, 1);
7058 : }
7059 :
7060 : /* Compute the minimum or maximum of the given set dimension
7061 : * as a function of the parameters,
7062 : * but independently of the other set dimensions.
7063 : */
7064 0 : static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7065 : int max)
7066 : {
7067 0 : return map_dim_opt(set, pos, max);
7068 : }
7069 :
7070 : /* Compute the maximum of the given set dimension as a function of the
7071 : * parameters, but independently of the other set dimensions.
7072 : */
7073 0 : __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7074 : {
7075 0 : return set_dim_opt(set, pos, 1);
7076 : }
7077 :
7078 : /* Compute the minimum of the given set dimension as a function of the
7079 : * parameters, but independently of the other set dimensions.
7080 : */
7081 0 : __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7082 : {
7083 0 : return set_dim_opt(set, pos, 0);
7084 : }
7085 :
7086 : /* Apply a preimage specified by "mat" on the parameters of "bset".
7087 : * bset is assumed to have only parameters and divs.
7088 : */
7089 0 : static __isl_give isl_basic_set *basic_set_parameter_preimage(
7090 : __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7091 : {
7092 : unsigned nparam;
7093 :
7094 0 : if (!bset || !mat)
7095 : goto error;
7096 :
7097 0 : bset->dim = isl_space_cow(bset->dim);
7098 0 : if (!bset->dim)
7099 0 : goto error;
7100 :
7101 0 : nparam = isl_basic_set_dim(bset, isl_dim_param);
7102 :
7103 0 : isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7104 :
7105 0 : bset->dim->nparam = 0;
7106 0 : bset->dim->n_out = nparam;
7107 0 : bset = isl_basic_set_preimage(bset, mat);
7108 0 : if (bset) {
7109 0 : bset->dim->nparam = bset->dim->n_out;
7110 0 : bset->dim->n_out = 0;
7111 : }
7112 0 : return bset;
7113 : error:
7114 0 : isl_mat_free(mat);
7115 0 : isl_basic_set_free(bset);
7116 0 : return NULL;
7117 : }
7118 :
7119 : /* Apply a preimage specified by "mat" on the parameters of "set".
7120 : * set is assumed to have only parameters and divs.
7121 : */
7122 0 : static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7123 : __isl_take isl_mat *mat)
7124 : {
7125 : isl_space *space;
7126 : unsigned nparam;
7127 :
7128 0 : if (!set || !mat)
7129 : goto error;
7130 :
7131 0 : nparam = isl_set_dim(set, isl_dim_param);
7132 :
7133 0 : if (mat->n_row != 1 + nparam)
7134 0 : isl_die(isl_set_get_ctx(set), isl_error_internal,
7135 : "unexpected number of rows", goto error);
7136 :
7137 0 : space = isl_set_get_space(set);
7138 0 : space = isl_space_move_dims(space, isl_dim_set, 0,
7139 : isl_dim_param, 0, nparam);
7140 0 : set = isl_set_reset_space(set, space);
7141 0 : set = isl_set_preimage(set, mat);
7142 0 : nparam = isl_set_dim(set, isl_dim_out);
7143 0 : space = isl_set_get_space(set);
7144 0 : space = isl_space_move_dims(space, isl_dim_param, 0,
7145 : isl_dim_out, 0, nparam);
7146 0 : set = isl_set_reset_space(set, space);
7147 0 : return set;
7148 : error:
7149 0 : isl_mat_free(mat);
7150 0 : isl_set_free(set);
7151 0 : return NULL;
7152 : }
7153 :
7154 : /* Intersect the basic set "bset" with the affine space specified by the
7155 : * equalities in "eq".
7156 : */
7157 0 : static __isl_give isl_basic_set *basic_set_append_equalities(
7158 : __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7159 : {
7160 : int i, k;
7161 : unsigned len;
7162 :
7163 0 : if (!bset || !eq)
7164 : goto error;
7165 :
7166 0 : bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
7167 : eq->n_row, 0);
7168 0 : if (!bset)
7169 0 : goto error;
7170 :
7171 0 : len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
7172 0 : for (i = 0; i < eq->n_row; ++i) {
7173 0 : k = isl_basic_set_alloc_equality(bset);
7174 0 : if (k < 0)
7175 0 : goto error;
7176 0 : isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7177 0 : isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7178 : }
7179 0 : isl_mat_free(eq);
7180 :
7181 0 : bset = isl_basic_set_gauss(bset, NULL);
7182 0 : bset = isl_basic_set_finalize(bset);
7183 :
7184 0 : return bset;
7185 : error:
7186 0 : isl_mat_free(eq);
7187 0 : isl_basic_set_free(bset);
7188 0 : return NULL;
7189 : }
7190 :
7191 : /* Intersect the set "set" with the affine space specified by the
7192 : * equalities in "eq".
7193 : */
7194 0 : static struct isl_set *set_append_equalities(struct isl_set *set,
7195 : struct isl_mat *eq)
7196 : {
7197 : int i;
7198 :
7199 0 : if (!set || !eq)
7200 : goto error;
7201 :
7202 0 : for (i = 0; i < set->n; ++i) {
7203 0 : set->p[i] = basic_set_append_equalities(set->p[i],
7204 : isl_mat_copy(eq));
7205 0 : if (!set->p[i])
7206 0 : goto error;
7207 : }
7208 0 : isl_mat_free(eq);
7209 0 : return set;
7210 : error:
7211 0 : isl_mat_free(eq);
7212 0 : isl_set_free(set);
7213 0 : return NULL;
7214 : }
7215 :
7216 : /* Given a basic set "bset" that only involves parameters and existentially
7217 : * quantified variables, return the index of the first equality
7218 : * that only involves parameters. If there is no such equality then
7219 : * return bset->n_eq.
7220 : *
7221 : * This function assumes that isl_basic_set_gauss has been called on "bset".
7222 : */
7223 0 : static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7224 : {
7225 : int i, j;
7226 : unsigned nparam, n_div;
7227 :
7228 0 : if (!bset)
7229 0 : return -1;
7230 :
7231 0 : nparam = isl_basic_set_dim(bset, isl_dim_param);
7232 0 : n_div = isl_basic_set_dim(bset, isl_dim_div);
7233 :
7234 0 : for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7235 0 : if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7236 0 : ++i;
7237 : }
7238 :
7239 0 : return i;
7240 : }
7241 :
7242 : /* Compute an explicit representation for the existentially quantified
7243 : * variables in "bset" by computing the "minimal value" of the set
7244 : * variables. Since there are no set variables, the computation of
7245 : * the minimal value essentially computes an explicit representation
7246 : * of the non-empty part(s) of "bset".
7247 : *
7248 : * The input only involves parameters and existentially quantified variables.
7249 : * All equalities among parameters have been removed.
7250 : *
7251 : * Since the existentially quantified variables in the result are in general
7252 : * going to be different from those in the input, we first replace
7253 : * them by the minimal number of variables based on their equalities.
7254 : * This should simplify the parametric integer programming.
7255 : */
7256 0 : static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7257 : {
7258 : isl_morph *morph1, *morph2;
7259 : isl_set *set;
7260 : unsigned n;
7261 :
7262 0 : if (!bset)
7263 0 : return NULL;
7264 0 : if (bset->n_eq == 0)
7265 0 : return isl_basic_set_lexmin_compute_divs(bset);
7266 :
7267 0 : morph1 = isl_basic_set_parameter_compression(bset);
7268 0 : bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7269 0 : bset = isl_basic_set_lift(bset);
7270 0 : morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7271 0 : bset = isl_morph_basic_set(morph2, bset);
7272 0 : n = isl_basic_set_dim(bset, isl_dim_set);
7273 0 : bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7274 :
7275 0 : set = isl_basic_set_lexmin_compute_divs(bset);
7276 :
7277 0 : set = isl_morph_set(isl_morph_inverse(morph1), set);
7278 :
7279 0 : return set;
7280 : }
7281 :
7282 : /* Project the given basic set onto its parameter domain, possibly introducing
7283 : * new, explicit, existential variables in the constraints.
7284 : * The input has parameters and (possibly implicit) existential variables.
7285 : * The output has the same parameters, but only
7286 : * explicit existentially quantified variables.
7287 : *
7288 : * The actual projection is performed by pip, but pip doesn't seem
7289 : * to like equalities very much, so we first remove the equalities
7290 : * among the parameters by performing a variable compression on
7291 : * the parameters. Afterward, an inverse transformation is performed
7292 : * and the equalities among the parameters are inserted back in.
7293 : *
7294 : * The variable compression on the parameters may uncover additional
7295 : * equalities that were only implicit before. We therefore check
7296 : * if there are any new parameter equalities in the result and
7297 : * if so recurse. The removal of parameter equalities is required
7298 : * for the parameter compression performed by base_compute_divs.
7299 : */
7300 0 : static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
7301 : {
7302 : int i;
7303 : struct isl_mat *eq;
7304 : struct isl_mat *T, *T2;
7305 : struct isl_set *set;
7306 : unsigned nparam;
7307 :
7308 0 : bset = isl_basic_set_cow(bset);
7309 0 : if (!bset)
7310 0 : return NULL;
7311 :
7312 0 : if (bset->n_eq == 0)
7313 0 : return base_compute_divs(bset);
7314 :
7315 0 : bset = isl_basic_set_gauss(bset, NULL);
7316 0 : if (!bset)
7317 0 : return NULL;
7318 0 : if (isl_basic_set_plain_is_empty(bset))
7319 0 : return isl_set_from_basic_set(bset);
7320 :
7321 0 : i = first_parameter_equality(bset);
7322 0 : if (i == bset->n_eq)
7323 0 : return base_compute_divs(bset);
7324 :
7325 0 : nparam = isl_basic_set_dim(bset, isl_dim_param);
7326 0 : eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7327 : 0, 1 + nparam);
7328 0 : eq = isl_mat_cow(eq);
7329 0 : T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7330 0 : if (T && T->n_col == 0) {
7331 0 : isl_mat_free(T);
7332 0 : isl_mat_free(T2);
7333 0 : isl_mat_free(eq);
7334 0 : bset = isl_basic_set_set_to_empty(bset);
7335 0 : return isl_set_from_basic_set(bset);
7336 : }
7337 0 : bset = basic_set_parameter_preimage(bset, T);
7338 :
7339 0 : i = first_parameter_equality(bset);
7340 0 : if (!bset)
7341 0 : set = NULL;
7342 0 : else if (i == bset->n_eq)
7343 0 : set = base_compute_divs(bset);
7344 : else
7345 0 : set = parameter_compute_divs(bset);
7346 0 : set = set_parameter_preimage(set, T2);
7347 0 : set = set_append_equalities(set, eq);
7348 0 : return set;
7349 : }
7350 :
7351 : /* Insert the divs from "ls" before those of "bmap".
7352 : *
7353 : * The number of columns is not changed, which means that the last
7354 : * dimensions of "bmap" are being reintepreted as the divs from "ls".
7355 : * The caller is responsible for removing the same number of dimensions
7356 : * from the space of "bmap".
7357 : */
7358 0 : static __isl_give isl_basic_map *insert_divs_from_local_space(
7359 : __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7360 : {
7361 : int i;
7362 : int n_div;
7363 : int old_n_div;
7364 :
7365 0 : n_div = isl_local_space_dim(ls, isl_dim_div);
7366 0 : if (n_div == 0)
7367 0 : return bmap;
7368 :
7369 0 : old_n_div = bmap->n_div;
7370 0 : bmap = insert_div_rows(bmap, n_div);
7371 0 : if (!bmap)
7372 0 : return NULL;
7373 :
7374 0 : for (i = 0; i < n_div; ++i) {
7375 0 : isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7376 0 : isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7377 : }
7378 :
7379 0 : return bmap;
7380 : }
7381 :
7382 : /* Replace the space of "bmap" by the space and divs of "ls".
7383 : *
7384 : * If "ls" has any divs, then we simplify the result since we may
7385 : * have discovered some additional equalities that could simplify
7386 : * the div expressions.
7387 : */
7388 0 : static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7389 : __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7390 : {
7391 : int n_div;
7392 :
7393 0 : bmap = isl_basic_map_cow(bmap);
7394 0 : if (!bmap || !ls)
7395 : goto error;
7396 :
7397 0 : n_div = isl_local_space_dim(ls, isl_dim_div);
7398 0 : bmap = insert_divs_from_local_space(bmap, ls);
7399 0 : if (!bmap)
7400 0 : goto error;
7401 :
7402 0 : isl_space_free(bmap->dim);
7403 0 : bmap->dim = isl_local_space_get_space(ls);
7404 0 : if (!bmap->dim)
7405 0 : goto error;
7406 :
7407 0 : isl_local_space_free(ls);
7408 0 : if (n_div > 0)
7409 0 : bmap = isl_basic_map_simplify(bmap);
7410 0 : bmap = isl_basic_map_finalize(bmap);
7411 0 : return bmap;
7412 : error:
7413 0 : isl_basic_map_free(bmap);
7414 0 : isl_local_space_free(ls);
7415 0 : return NULL;
7416 : }
7417 :
7418 : /* Replace the space of "map" by the space and divs of "ls".
7419 : */
7420 0 : static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7421 : __isl_take isl_local_space *ls)
7422 : {
7423 : int i;
7424 :
7425 0 : map = isl_map_cow(map);
7426 0 : if (!map || !ls)
7427 : goto error;
7428 :
7429 0 : for (i = 0; i < map->n; ++i) {
7430 0 : map->p[i] = basic_replace_space_by_local_space(map->p[i],
7431 : isl_local_space_copy(ls));
7432 0 : if (!map->p[i])
7433 0 : goto error;
7434 : }
7435 0 : isl_space_free(map->dim);
7436 0 : map->dim = isl_local_space_get_space(ls);
7437 0 : if (!map->dim)
7438 0 : goto error;
7439 :
7440 0 : isl_local_space_free(ls);
7441 0 : return map;
7442 : error:
7443 0 : isl_local_space_free(ls);
7444 0 : isl_map_free(map);
7445 0 : return NULL;
7446 : }
7447 :
7448 : /* Compute an explicit representation for the existentially
7449 : * quantified variables for which do not know any explicit representation yet.
7450 : *
7451 : * We first sort the existentially quantified variables so that the
7452 : * existentially quantified variables for which we already have an explicit
7453 : * representation are placed before those for which we do not.
7454 : * The input dimensions, the output dimensions and the existentially
7455 : * quantified variables for which we already have an explicit
7456 : * representation are then turned into parameters.
7457 : * compute_divs returns a map with the same parameters and
7458 : * no input or output dimensions and the dimension specification
7459 : * is reset to that of the input, including the existentially quantified
7460 : * variables for which we already had an explicit representation.
7461 : */
7462 0 : static struct isl_map *compute_divs(struct isl_basic_map *bmap)
7463 : {
7464 : struct isl_basic_set *bset;
7465 : struct isl_set *set;
7466 : struct isl_map *map;
7467 : isl_space *dim;
7468 : isl_local_space *ls;
7469 : unsigned nparam;
7470 : unsigned n_in;
7471 : unsigned n_out;
7472 : int n_known;
7473 : int i;
7474 :
7475 0 : bmap = isl_basic_map_sort_divs(bmap);
7476 0 : bmap = isl_basic_map_cow(bmap);
7477 0 : if (!bmap)
7478 0 : return NULL;
7479 :
7480 0 : n_known = isl_basic_map_first_unknown_div(bmap);
7481 0 : if (n_known < 0)
7482 0 : return isl_map_from_basic_map(isl_basic_map_free(bmap));
7483 :
7484 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
7485 0 : n_in = isl_basic_map_dim(bmap, isl_dim_in);
7486 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
7487 0 : dim = isl_space_set_alloc(bmap->ctx,
7488 0 : nparam + n_in + n_out + n_known, 0);
7489 0 : if (!dim)
7490 0 : goto error;
7491 :
7492 0 : ls = isl_basic_map_get_local_space(bmap);
7493 0 : ls = isl_local_space_drop_dims(ls, isl_dim_div,
7494 0 : n_known, bmap->n_div - n_known);
7495 0 : if (n_known > 0) {
7496 0 : for (i = n_known; i < bmap->n_div; ++i)
7497 0 : swap_div(bmap, i - n_known, i);
7498 0 : bmap->n_div -= n_known;
7499 0 : bmap->extra -= n_known;
7500 : }
7501 0 : bmap = isl_basic_map_reset_space(bmap, dim);
7502 0 : bset = bset_from_bmap(bmap);
7503 :
7504 0 : set = parameter_compute_divs(bset);
7505 0 : map = set_to_map(set);
7506 0 : map = replace_space_by_local_space(map, ls);
7507 :
7508 0 : return map;
7509 : error:
7510 0 : isl_basic_map_free(bmap);
7511 0 : return NULL;
7512 : }
7513 :
7514 : /* Remove the explicit representation of local variable "div",
7515 : * if there is any.
7516 : */
7517 0 : __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7518 : __isl_take isl_basic_map *bmap, int div)
7519 : {
7520 : isl_bool unknown;
7521 :
7522 0 : unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7523 0 : if (unknown < 0)
7524 0 : return isl_basic_map_free(bmap);
7525 0 : if (unknown)
7526 0 : return bmap;
7527 :
7528 0 : bmap = isl_basic_map_cow(bmap);
7529 0 : if (!bmap)
7530 0 : return NULL;
7531 0 : isl_int_set_si(bmap->div[div][0], 0);
7532 0 : return bmap;
7533 : }
7534 :
7535 : /* Is local variable "div" of "bmap" marked as not having an explicit
7536 : * representation?
7537 : * Note that even if "div" is not marked in this way and therefore
7538 : * has an explicit representation, this representation may still
7539 : * depend (indirectly) on other local variables that do not
7540 : * have an explicit representation.
7541 : */
7542 0 : isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7543 : int div)
7544 : {
7545 0 : if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7546 0 : return isl_bool_error;
7547 0 : return isl_int_is_zero(bmap->div[div][0]);
7548 : }
7549 :
7550 : /* Return the position of the first local variable that does not
7551 : * have an explicit representation.
7552 : * Return the total number of local variables if they all have
7553 : * an explicit representation.
7554 : * Return -1 on error.
7555 : */
7556 4588052277 : int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7557 : {
7558 : int i;
7559 :
7560 4588052277 : if (!bmap)
7561 0 : return -1;
7562 :
7563 4588052277 : for (i = 0; i < bmap->n_div; ++i) {
7564 0 : if (!isl_basic_map_div_is_known(bmap, i))
7565 0 : return i;
7566 : }
7567 4588052277 : return bmap->n_div;
7568 : }
7569 :
7570 : /* Return the position of the first local variable that does not
7571 : * have an explicit representation.
7572 : * Return the total number of local variables if they all have
7573 : * an explicit representation.
7574 : * Return -1 on error.
7575 : */
7576 0 : int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7577 : {
7578 0 : return isl_basic_map_first_unknown_div(bset);
7579 : }
7580 :
7581 : /* Does "bmap" have an explicit representation for all local variables?
7582 : */
7583 4588052277 : isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7584 : {
7585 : int first, n;
7586 :
7587 4588052277 : n = isl_basic_map_dim(bmap, isl_dim_div);
7588 4588052277 : first = isl_basic_map_first_unknown_div(bmap);
7589 4588052277 : if (first < 0)
7590 0 : return isl_bool_error;
7591 4588052277 : return first == n;
7592 : }
7593 :
7594 : /* Do all basic maps in "map" have an explicit representation
7595 : * for all local variables?
7596 : */
7597 650525751 : isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7598 : {
7599 : int i;
7600 :
7601 650525751 : if (!map)
7602 0 : return isl_bool_error;
7603 :
7604 1877974205 : for (i = 0; i < map->n; ++i) {
7605 1227448454 : int known = isl_basic_map_divs_known(map->p[i]);
7606 1227448454 : if (known <= 0)
7607 0 : return known;
7608 : }
7609 :
7610 650525751 : return isl_bool_true;
7611 : }
7612 :
7613 : /* If bmap contains any unknown divs, then compute explicit
7614 : * expressions for them. However, this computation may be
7615 : * quite expensive, so first try to remove divs that aren't
7616 : * strictly needed.
7617 : */
7618 0 : __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7619 : {
7620 : int known;
7621 : struct isl_map *map;
7622 :
7623 0 : known = isl_basic_map_divs_known(bmap);
7624 0 : if (known < 0)
7625 0 : goto error;
7626 0 : if (known)
7627 0 : return isl_map_from_basic_map(bmap);
7628 :
7629 0 : bmap = isl_basic_map_drop_redundant_divs(bmap);
7630 :
7631 0 : known = isl_basic_map_divs_known(bmap);
7632 0 : if (known < 0)
7633 0 : goto error;
7634 0 : if (known)
7635 0 : return isl_map_from_basic_map(bmap);
7636 :
7637 0 : map = compute_divs(bmap);
7638 0 : return map;
7639 : error:
7640 0 : isl_basic_map_free(bmap);
7641 0 : return NULL;
7642 : }
7643 :
7644 650525751 : __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7645 : {
7646 : int i;
7647 : int known;
7648 : struct isl_map *res;
7649 :
7650 650525751 : if (!map)
7651 0 : return NULL;
7652 650525751 : if (map->n == 0)
7653 0 : return map;
7654 :
7655 650525751 : known = isl_map_divs_known(map);
7656 650525751 : if (known < 0) {
7657 0 : isl_map_free(map);
7658 0 : return NULL;
7659 : }
7660 650525751 : if (known)
7661 650525751 : return map;
7662 :
7663 0 : res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7664 0 : for (i = 1 ; i < map->n; ++i) {
7665 : struct isl_map *r2;
7666 0 : r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7667 0 : if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7668 0 : res = isl_map_union_disjoint(res, r2);
7669 : else
7670 0 : res = isl_map_union(res, r2);
7671 : }
7672 0 : isl_map_free(map);
7673 :
7674 0 : return res;
7675 : }
7676 :
7677 0 : __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
7678 : {
7679 0 : return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7680 : }
7681 :
7682 0 : struct isl_set *isl_set_compute_divs(struct isl_set *set)
7683 : {
7684 0 : return set_from_map(isl_map_compute_divs(set_to_map(set)));
7685 : }
7686 :
7687 0 : __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
7688 : {
7689 : int i;
7690 : struct isl_set *set;
7691 :
7692 0 : if (!map)
7693 0 : goto error;
7694 :
7695 0 : map = isl_map_cow(map);
7696 0 : if (!map)
7697 0 : return NULL;
7698 :
7699 0 : set = set_from_map(map);
7700 0 : set->dim = isl_space_domain(set->dim);
7701 0 : if (!set->dim)
7702 0 : goto error;
7703 0 : for (i = 0; i < map->n; ++i) {
7704 0 : set->p[i] = isl_basic_map_domain(map->p[i]);
7705 0 : if (!set->p[i])
7706 0 : goto error;
7707 : }
7708 0 : ISL_F_CLR(set, ISL_MAP_DISJOINT);
7709 0 : ISL_F_CLR(set, ISL_SET_NORMALIZED);
7710 0 : return set;
7711 : error:
7712 0 : isl_map_free(map);
7713 0 : return NULL;
7714 : }
7715 :
7716 : /* Return the union of "map1" and "map2", where we assume for now that
7717 : * "map1" and "map2" are disjoint. Note that the basic maps inside
7718 : * "map1" or "map2" may not be disjoint from each other.
7719 : * Also note that this function is also called from isl_map_union,
7720 : * which takes care of handling the situation where "map1" and "map2"
7721 : * may not be disjoint.
7722 : *
7723 : * If one of the inputs is empty, we can simply return the other input.
7724 : * Similarly, if one of the inputs is universal, then it is equal to the union.
7725 : */
7726 47714600 : static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7727 : __isl_take isl_map *map2)
7728 : {
7729 : int i;
7730 47714600 : unsigned flags = 0;
7731 47714600 : struct isl_map *map = NULL;
7732 : int is_universe;
7733 :
7734 47714600 : if (!map1 || !map2)
7735 : goto error;
7736 :
7737 47714600 : if (!isl_space_is_equal(map1->dim, map2->dim))
7738 0 : isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7739 : "spaces don't match", goto error);
7740 :
7741 47714600 : if (map1->n == 0) {
7742 7870890 : isl_map_free(map1);
7743 7870890 : return map2;
7744 : }
7745 39843710 : if (map2->n == 0) {
7746 662968 : isl_map_free(map2);
7747 662968 : return map1;
7748 : }
7749 :
7750 39180742 : is_universe = isl_map_plain_is_universe(map1);
7751 39180742 : if (is_universe < 0)
7752 0 : goto error;
7753 39180742 : if (is_universe) {
7754 80471 : isl_map_free(map2);
7755 80471 : return map1;
7756 : }
7757 :
7758 39100271 : is_universe = isl_map_plain_is_universe(map2);
7759 39100271 : if (is_universe < 0)
7760 0 : goto error;
7761 39100271 : if (is_universe) {
7762 106763 : isl_map_free(map1);
7763 106763 : return map2;
7764 : }
7765 :
7766 73780174 : if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7767 34786666 : ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7768 34557533 : ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7769 :
7770 38993508 : map = isl_map_alloc_space(isl_space_copy(map1->dim),
7771 38993508 : map1->n + map2->n, flags);
7772 38993508 : if (!map)
7773 0 : goto error;
7774 1183790987 : for (i = 0; i < map1->n; ++i) {
7775 1144797479 : map = isl_map_add_basic_map(map,
7776 1144797479 : isl_basic_map_copy(map1->p[i]));
7777 1144797479 : if (!map)
7778 0 : goto error;
7779 : }
7780 89291724 : for (i = 0; i < map2->n; ++i) {
7781 50298216 : map = isl_map_add_basic_map(map,
7782 50298216 : isl_basic_map_copy(map2->p[i]));
7783 50298216 : if (!map)
7784 0 : goto error;
7785 : }
7786 38993508 : isl_map_free(map1);
7787 38993508 : isl_map_free(map2);
7788 38993508 : return map;
7789 : error:
7790 0 : isl_map_free(map);
7791 0 : isl_map_free(map1);
7792 0 : isl_map_free(map2);
7793 0 : return NULL;
7794 : }
7795 :
7796 : /* Return the union of "map1" and "map2", where "map1" and "map2" are
7797 : * guaranteed to be disjoint by the caller.
7798 : *
7799 : * Note that this functions is called from within isl_map_make_disjoint,
7800 : * so we have to be careful not to touch the constraints of the inputs
7801 : * in any way.
7802 : */
7803 40752044 : __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7804 : __isl_take isl_map *map2)
7805 : {
7806 40752044 : return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7807 : }
7808 :
7809 : /* Return the union of "map1" and "map2", where "map1" and "map2" may
7810 : * not be disjoint. The parameters are assumed to have been aligned.
7811 : *
7812 : * We currently simply call map_union_disjoint, the internal operation
7813 : * of which does not really depend on the inputs being disjoint.
7814 : * If the result contains more than one basic map, then we clear
7815 : * the disjoint flag since the result may contain basic maps from
7816 : * both inputs and these are not guaranteed to be disjoint.
7817 : *
7818 : * As a special case, if "map1" and "map2" are obviously equal,
7819 : * then we simply return "map1".
7820 : */
7821 8119776 : static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7822 : __isl_take isl_map *map2)
7823 : {
7824 : int equal;
7825 :
7826 8119776 : if (!map1 || !map2)
7827 : goto error;
7828 :
7829 8119776 : equal = isl_map_plain_is_equal(map1, map2);
7830 8119776 : if (equal < 0)
7831 0 : goto error;
7832 8119776 : if (equal) {
7833 1157220 : isl_map_free(map2);
7834 1157220 : return map1;
7835 : }
7836 :
7837 6962556 : map1 = map_union_disjoint(map1, map2);
7838 6962556 : if (!map1)
7839 0 : return NULL;
7840 6962556 : if (map1->n > 1)
7841 6041431 : ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7842 6962556 : return map1;
7843 : error:
7844 0 : isl_map_free(map1);
7845 0 : isl_map_free(map2);
7846 0 : return NULL;
7847 : }
7848 :
7849 : /* Return the union of "map1" and "map2", where "map1" and "map2" may
7850 : * not be disjoint.
7851 : */
7852 8119776 : __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7853 : __isl_take isl_map *map2)
7854 : {
7855 8119776 : return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7856 : }
7857 :
7858 0 : __isl_give isl_set *isl_set_union_disjoint(
7859 : __isl_take isl_set *set1, __isl_take isl_set *set2)
7860 : {
7861 0 : return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7862 : set_to_map(set2)));
7863 : }
7864 :
7865 3728909 : struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7866 : {
7867 3728909 : return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7868 : }
7869 :
7870 : /* Apply "fn" to pairs of elements from "map" and "set" and collect
7871 : * the results.
7872 : *
7873 : * "map" and "set" are assumed to be compatible and non-NULL.
7874 : */
7875 0 : static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7876 : __isl_take isl_set *set,
7877 : __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7878 : __isl_take isl_basic_set *bset))
7879 : {
7880 0 : unsigned flags = 0;
7881 : struct isl_map *result;
7882 : int i, j;
7883 :
7884 0 : if (isl_set_plain_is_universe(set)) {
7885 0 : isl_set_free(set);
7886 0 : return map;
7887 : }
7888 :
7889 0 : if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7890 0 : ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7891 0 : ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7892 :
7893 0 : result = isl_map_alloc_space(isl_space_copy(map->dim),
7894 0 : map->n * set->n, flags);
7895 0 : for (i = 0; result && i < map->n; ++i)
7896 0 : for (j = 0; j < set->n; ++j) {
7897 0 : result = isl_map_add_basic_map(result,
7898 0 : fn(isl_basic_map_copy(map->p[i]),
7899 0 : isl_basic_set_copy(set->p[j])));
7900 0 : if (!result)
7901 0 : break;
7902 : }
7903 :
7904 0 : isl_map_free(map);
7905 0 : isl_set_free(set);
7906 0 : return result;
7907 : }
7908 :
7909 0 : static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7910 : __isl_take isl_set *set)
7911 : {
7912 : isl_bool ok;
7913 :
7914 0 : ok = isl_map_compatible_range(map, set);
7915 0 : if (ok < 0)
7916 0 : goto error;
7917 0 : if (!ok)
7918 0 : isl_die(set->ctx, isl_error_invalid,
7919 : "incompatible spaces", goto error);
7920 :
7921 0 : return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7922 : error:
7923 0 : isl_map_free(map);
7924 0 : isl_set_free(set);
7925 0 : return NULL;
7926 : }
7927 :
7928 0 : __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7929 : __isl_take isl_set *set)
7930 : {
7931 0 : return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7932 : }
7933 :
7934 0 : static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7935 : __isl_take isl_set *set)
7936 : {
7937 : isl_bool ok;
7938 :
7939 0 : ok = isl_map_compatible_domain(map, set);
7940 0 : if (ok < 0)
7941 0 : goto error;
7942 0 : if (!ok)
7943 0 : isl_die(set->ctx, isl_error_invalid,
7944 : "incompatible spaces", goto error);
7945 :
7946 0 : return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7947 : error:
7948 0 : isl_map_free(map);
7949 0 : isl_set_free(set);
7950 0 : return NULL;
7951 : }
7952 :
7953 0 : __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7954 : __isl_take isl_set *set)
7955 : {
7956 0 : return isl_map_align_params_map_map_and(map, set,
7957 : &map_intersect_domain);
7958 : }
7959 :
7960 : /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7961 : * in the space B -> C, return the intersection.
7962 : * The parameters are assumed to have been aligned.
7963 : *
7964 : * The map "factor" is first extended to a map living in the space
7965 : * [A -> B] -> C and then a regular intersection is computed.
7966 : */
7967 0 : static __isl_give isl_map *map_intersect_domain_factor_range(
7968 : __isl_take isl_map *map, __isl_take isl_map *factor)
7969 : {
7970 : isl_space *space;
7971 : isl_map *ext_factor;
7972 :
7973 0 : space = isl_space_domain_factor_domain(isl_map_get_space(map));
7974 0 : ext_factor = isl_map_universe(space);
7975 0 : ext_factor = isl_map_domain_product(ext_factor, factor);
7976 0 : return map_intersect(map, ext_factor);
7977 : }
7978 :
7979 : /* Given a map "map" in a space [A -> B] -> C and a map "factor"
7980 : * in the space B -> C, return the intersection.
7981 : */
7982 0 : __isl_give isl_map *isl_map_intersect_domain_factor_range(
7983 : __isl_take isl_map *map, __isl_take isl_map *factor)
7984 : {
7985 0 : return isl_map_align_params_map_map_and(map, factor,
7986 : &map_intersect_domain_factor_range);
7987 : }
7988 :
7989 : /* Given a map "map" in a space A -> [B -> C] and a map "factor"
7990 : * in the space A -> C, return the intersection.
7991 : *
7992 : * The map "factor" is first extended to a map living in the space
7993 : * A -> [B -> C] and then a regular intersection is computed.
7994 : */
7995 0 : static __isl_give isl_map *map_intersect_range_factor_range(
7996 : __isl_take isl_map *map, __isl_take isl_map *factor)
7997 : {
7998 : isl_space *space;
7999 : isl_map *ext_factor;
8000 :
8001 0 : space = isl_space_range_factor_domain(isl_map_get_space(map));
8002 0 : ext_factor = isl_map_universe(space);
8003 0 : ext_factor = isl_map_range_product(ext_factor, factor);
8004 0 : return isl_map_intersect(map, ext_factor);
8005 : }
8006 :
8007 : /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8008 : * in the space A -> C, return the intersection.
8009 : */
8010 0 : __isl_give isl_map *isl_map_intersect_range_factor_range(
8011 : __isl_take isl_map *map, __isl_take isl_map *factor)
8012 : {
8013 0 : return isl_map_align_params_map_map_and(map, factor,
8014 : &map_intersect_range_factor_range);
8015 : }
8016 :
8017 0 : static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
8018 : __isl_take isl_map *map2)
8019 : {
8020 0 : if (!map1 || !map2)
8021 : goto error;
8022 0 : map1 = isl_map_reverse(map1);
8023 0 : map1 = isl_map_apply_range(map1, map2);
8024 0 : return isl_map_reverse(map1);
8025 : error:
8026 0 : isl_map_free(map1);
8027 0 : isl_map_free(map2);
8028 0 : return NULL;
8029 : }
8030 :
8031 0 : __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8032 : __isl_take isl_map *map2)
8033 : {
8034 0 : return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
8035 : }
8036 :
8037 0 : static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
8038 : __isl_take isl_map *map2)
8039 : {
8040 : isl_space *dim_result;
8041 : struct isl_map *result;
8042 : int i, j;
8043 :
8044 0 : if (!map1 || !map2)
8045 : goto error;
8046 :
8047 0 : dim_result = isl_space_join(isl_space_copy(map1->dim),
8048 : isl_space_copy(map2->dim));
8049 :
8050 0 : result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
8051 0 : if (!result)
8052 0 : goto error;
8053 0 : for (i = 0; i < map1->n; ++i)
8054 0 : for (j = 0; j < map2->n; ++j) {
8055 0 : result = isl_map_add_basic_map(result,
8056 : isl_basic_map_apply_range(
8057 0 : isl_basic_map_copy(map1->p[i]),
8058 0 : isl_basic_map_copy(map2->p[j])));
8059 0 : if (!result)
8060 0 : goto error;
8061 : }
8062 0 : isl_map_free(map1);
8063 0 : isl_map_free(map2);
8064 0 : if (result && result->n <= 1)
8065 0 : ISL_F_SET(result, ISL_MAP_DISJOINT);
8066 0 : return result;
8067 : error:
8068 0 : isl_map_free(map1);
8069 0 : isl_map_free(map2);
8070 0 : return NULL;
8071 : }
8072 :
8073 0 : __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8074 : __isl_take isl_map *map2)
8075 : {
8076 0 : return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
8077 : }
8078 :
8079 : /*
8080 : * returns range - domain
8081 : */
8082 0 : __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8083 : {
8084 : isl_space *target_space;
8085 : struct isl_basic_set *bset;
8086 : unsigned dim;
8087 : unsigned nparam;
8088 : int i;
8089 :
8090 0 : if (!bmap)
8091 0 : goto error;
8092 0 : isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8093 : bmap->dim, isl_dim_out),
8094 : goto error);
8095 0 : target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8096 0 : dim = isl_basic_map_dim(bmap, isl_dim_in);
8097 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
8098 0 : bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8099 0 : bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8100 0 : bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8101 0 : for (i = 0; i < dim; ++i) {
8102 0 : int j = isl_basic_map_alloc_equality(bmap);
8103 0 : if (j < 0) {
8104 0 : bmap = isl_basic_map_free(bmap);
8105 0 : break;
8106 : }
8107 0 : isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
8108 0 : isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8109 0 : isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8110 0 : isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8111 : }
8112 0 : bset = isl_basic_map_domain(bmap);
8113 0 : bset = isl_basic_set_reset_space(bset, target_space);
8114 0 : return bset;
8115 : error:
8116 0 : isl_basic_map_free(bmap);
8117 0 : return NULL;
8118 : }
8119 :
8120 : /*
8121 : * returns range - domain
8122 : */
8123 0 : __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8124 : {
8125 : int i;
8126 : isl_space *dim;
8127 : struct isl_set *result;
8128 :
8129 0 : if (!map)
8130 0 : return NULL;
8131 :
8132 0 : isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
8133 : map->dim, isl_dim_out),
8134 : goto error);
8135 0 : dim = isl_map_get_space(map);
8136 0 : dim = isl_space_domain(dim);
8137 0 : result = isl_set_alloc_space(dim, map->n, 0);
8138 0 : if (!result)
8139 0 : goto error;
8140 0 : for (i = 0; i < map->n; ++i)
8141 0 : result = isl_set_add_basic_set(result,
8142 0 : isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8143 0 : isl_map_free(map);
8144 0 : return result;
8145 : error:
8146 0 : isl_map_free(map);
8147 0 : return NULL;
8148 : }
8149 :
8150 : /*
8151 : * returns [domain -> range] -> range - domain
8152 : */
8153 0 : __isl_give isl_basic_map *isl_basic_map_deltas_map(
8154 : __isl_take isl_basic_map *bmap)
8155 : {
8156 : int i, k;
8157 : isl_space *dim;
8158 : isl_basic_map *domain;
8159 : int nparam, n;
8160 : unsigned total;
8161 :
8162 0 : if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
8163 : bmap->dim, isl_dim_out))
8164 0 : isl_die(bmap->ctx, isl_error_invalid,
8165 : "domain and range don't match", goto error);
8166 :
8167 0 : nparam = isl_basic_map_dim(bmap, isl_dim_param);
8168 0 : n = isl_basic_map_dim(bmap, isl_dim_in);
8169 :
8170 0 : dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
8171 0 : domain = isl_basic_map_universe(dim);
8172 :
8173 0 : bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8174 0 : bmap = isl_basic_map_apply_range(bmap, domain);
8175 0 : bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8176 :
8177 0 : total = isl_basic_map_total_dim(bmap);
8178 :
8179 0 : for (i = 0; i < n; ++i) {
8180 0 : k = isl_basic_map_alloc_equality(bmap);
8181 0 : if (k < 0)
8182 0 : goto error;
8183 0 : isl_seq_clr(bmap->eq[k], 1 + total);
8184 0 : isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8185 0 : isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8186 0 : isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8187 : }
8188 :
8189 0 : bmap = isl_basic_map_gauss(bmap, NULL);
8190 0 : return isl_basic_map_finalize(bmap);
8191 : error:
8192 0 : isl_basic_map_free(bmap);
8193 0 : return NULL;
8194 : }
8195 :
8196 : /*
8197 : * returns [domain -> range] -> range - domain
8198 : */
8199 0 : __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8200 : {
8201 : int i;
8202 : isl_space *domain_dim;
8203 :
8204 0 : if (!map)
8205 0 : return NULL;
8206 :
8207 0 : if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
8208 : map->dim, isl_dim_out))
8209 0 : isl_die(map->ctx, isl_error_invalid,
8210 : "domain and range don't match", goto error);
8211 :
8212 0 : map = isl_map_cow(map);
8213 0 : if (!map)
8214 0 : return NULL;
8215 :
8216 0 : domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
8217 0 : map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
8218 0 : map->dim = isl_space_join(map->dim, domain_dim);
8219 0 : if (!map->dim)
8220 0 : goto error;
8221 0 : for (i = 0; i < map->n; ++i) {
8222 0 : map->p[i] = isl_basic_map_deltas_map(map->p[i]);
8223 0 : if (!map->p[i])
8224 0 : goto error;
8225 : }
8226 0 : map = isl_map_unmark_normalized(map);
8227 0 : return map;
8228 : error:
8229 0 : isl_map_free(map);
8230 0 : return NULL;
8231 : }
8232 :
8233 0 : static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
8234 : {
8235 : struct isl_basic_map *bmap;
8236 : unsigned nparam;
8237 : unsigned dim;
8238 : int i;
8239 :
8240 0 : if (!dims)
8241 0 : return NULL;
8242 :
8243 0 : nparam = dims->nparam;
8244 0 : dim = dims->n_out;
8245 0 : bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
8246 0 : if (!bmap)
8247 0 : goto error;
8248 :
8249 0 : for (i = 0; i < dim; ++i) {
8250 0 : int j = isl_basic_map_alloc_equality(bmap);
8251 0 : if (j < 0)
8252 0 : goto error;
8253 0 : isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
8254 0 : isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8255 0 : isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
8256 : }
8257 0 : return isl_basic_map_finalize(bmap);
8258 : error:
8259 0 : isl_basic_map_free(bmap);
8260 0 : return NULL;
8261 : }
8262 :
8263 0 : __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
8264 : {
8265 0 : if (!dim)
8266 0 : return NULL;
8267 0 : if (dim->n_in != dim->n_out)
8268 0 : isl_die(dim->ctx, isl_error_invalid,
8269 : "number of input and output dimensions needs to be "
8270 : "the same", goto error);
8271 0 : return basic_map_identity(dim);
8272 : error:
8273 0 : isl_space_free(dim);
8274 0 : return NULL;
8275 : }
8276 :
8277 0 : __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
8278 : {
8279 0 : return isl_map_from_basic_map(isl_basic_map_identity(dim));
8280 : }
8281 :
8282 0 : __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8283 : {
8284 0 : isl_space *dim = isl_set_get_space(set);
8285 : isl_map *id;
8286 0 : id = isl_map_identity(isl_space_map_from_set(dim));
8287 0 : return isl_map_intersect_range(id, set);
8288 : }
8289 :
8290 : /* Construct a basic set with all set dimensions having only non-negative
8291 : * values.
8292 : */
8293 0 : __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8294 : __isl_take isl_space *space)
8295 : {
8296 : int i;
8297 : unsigned nparam;
8298 : unsigned dim;
8299 : struct isl_basic_set *bset;
8300 :
8301 0 : if (!space)
8302 0 : return NULL;
8303 0 : nparam = space->nparam;
8304 0 : dim = space->n_out;
8305 0 : bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8306 0 : if (!bset)
8307 0 : return NULL;
8308 0 : for (i = 0; i < dim; ++i) {
8309 0 : int k = isl_basic_set_alloc_inequality(bset);
8310 0 : if (k < 0)
8311 0 : goto error;
8312 0 : isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
8313 0 : isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8314 : }
8315 0 : return bset;
8316 : error:
8317 0 : isl_basic_set_free(bset);
8318 0 : return NULL;
8319 : }
8320 :
8321 : /* Construct the half-space x_pos >= 0.
8322 : */
8323 0 : static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
8324 : int pos)
8325 : {
8326 : int k;
8327 : isl_basic_set *nonneg;
8328 :
8329 0 : nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
8330 0 : k = isl_basic_set_alloc_inequality(nonneg);
8331 0 : if (k < 0)
8332 0 : goto error;
8333 0 : isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
8334 0 : isl_int_set_si(nonneg->ineq[k][pos], 1);
8335 :
8336 0 : return isl_basic_set_finalize(nonneg);
8337 : error:
8338 0 : isl_basic_set_free(nonneg);
8339 0 : return NULL;
8340 : }
8341 :
8342 : /* Construct the half-space x_pos <= -1.
8343 : */
8344 0 : static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
8345 : {
8346 : int k;
8347 : isl_basic_set *neg;
8348 :
8349 0 : neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
8350 0 : k = isl_basic_set_alloc_inequality(neg);
8351 0 : if (k < 0)
8352 0 : goto error;
8353 0 : isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
8354 0 : isl_int_set_si(neg->ineq[k][0], -1);
8355 0 : isl_int_set_si(neg->ineq[k][pos], -1);
8356 :
8357 0 : return isl_basic_set_finalize(neg);
8358 : error:
8359 0 : isl_basic_set_free(neg);
8360 0 : return NULL;
8361 : }
8362 :
8363 0 : __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8364 : enum isl_dim_type type, unsigned first, unsigned n)
8365 : {
8366 : int i;
8367 : unsigned offset;
8368 : isl_basic_set *nonneg;
8369 : isl_basic_set *neg;
8370 :
8371 0 : if (!set)
8372 0 : return NULL;
8373 0 : if (n == 0)
8374 0 : return set;
8375 :
8376 0 : isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
8377 :
8378 0 : offset = pos(set->dim, type);
8379 0 : for (i = 0; i < n; ++i) {
8380 0 : nonneg = nonneg_halfspace(isl_set_get_space(set),
8381 0 : offset + first + i);
8382 0 : neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8383 :
8384 0 : set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8385 : }
8386 :
8387 0 : return set;
8388 : error:
8389 0 : isl_set_free(set);
8390 0 : return NULL;
8391 : }
8392 :
8393 0 : static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8394 : int len,
8395 : isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8396 : void *user)
8397 : {
8398 : isl_set *half;
8399 :
8400 0 : if (!set)
8401 0 : return isl_stat_error;
8402 0 : if (isl_set_plain_is_empty(set)) {
8403 0 : isl_set_free(set);
8404 0 : return isl_stat_ok;
8405 : }
8406 0 : if (first == len)
8407 0 : return fn(set, signs, user);
8408 :
8409 0 : signs[first] = 1;
8410 0 : half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8411 : 1 + first));
8412 0 : half = isl_set_intersect(half, isl_set_copy(set));
8413 0 : if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8414 0 : goto error;
8415 :
8416 0 : signs[first] = -1;
8417 0 : half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8418 : 1 + first));
8419 0 : half = isl_set_intersect(half, set);
8420 0 : return foreach_orthant(half, signs, first + 1, len, fn, user);
8421 : error:
8422 0 : isl_set_free(set);
8423 0 : return isl_stat_error;
8424 : }
8425 :
8426 : /* Call "fn" on the intersections of "set" with each of the orthants
8427 : * (except for obviously empty intersections). The orthant is identified
8428 : * by the signs array, with each entry having value 1 or -1 according
8429 : * to the sign of the corresponding variable.
8430 : */
8431 0 : isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8432 : isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8433 : void *user)
8434 : {
8435 : unsigned nparam;
8436 : unsigned nvar;
8437 : int *signs;
8438 : isl_stat r;
8439 :
8440 0 : if (!set)
8441 0 : return isl_stat_error;
8442 0 : if (isl_set_plain_is_empty(set))
8443 0 : return isl_stat_ok;
8444 :
8445 0 : nparam = isl_set_dim(set, isl_dim_param);
8446 0 : nvar = isl_set_dim(set, isl_dim_set);
8447 :
8448 0 : signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8449 :
8450 0 : r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8451 : fn, user);
8452 :
8453 0 : free(signs);
8454 :
8455 0 : return r;
8456 : }
8457 :
8458 752960 : isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8459 : {
8460 752960 : return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8461 : }
8462 :
8463 0 : isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8464 : __isl_keep isl_basic_map *bmap2)
8465 : {
8466 : int is_subset;
8467 : struct isl_map *map1;
8468 : struct isl_map *map2;
8469 :
8470 0 : if (!bmap1 || !bmap2)
8471 0 : return isl_bool_error;
8472 :
8473 0 : map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8474 0 : map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8475 :
8476 0 : is_subset = isl_map_is_subset(map1, map2);
8477 :
8478 0 : isl_map_free(map1);
8479 0 : isl_map_free(map2);
8480 :
8481 0 : return is_subset;
8482 : }
8483 :
8484 0 : isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8485 : __isl_keep isl_basic_set *bset2)
8486 : {
8487 0 : return isl_basic_map_is_subset(bset1, bset2);
8488 : }
8489 :
8490 0 : isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8491 : __isl_keep isl_basic_map *bmap2)
8492 : {
8493 : isl_bool is_subset;
8494 :
8495 0 : if (!bmap1 || !bmap2)
8496 0 : return isl_bool_error;
8497 0 : is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8498 0 : if (is_subset != isl_bool_true)
8499 0 : return is_subset;
8500 0 : is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8501 0 : return is_subset;
8502 : }
8503 :
8504 0 : isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8505 : __isl_keep isl_basic_set *bset2)
8506 : {
8507 0 : return isl_basic_map_is_equal(
8508 : bset_to_bmap(bset1), bset_to_bmap(bset2));
8509 : }
8510 :
8511 5085426 : isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8512 : {
8513 : int i;
8514 : int is_empty;
8515 :
8516 5085426 : if (!map)
8517 0 : return isl_bool_error;
8518 5085426 : for (i = 0; i < map->n; ++i) {
8519 5085426 : is_empty = isl_basic_map_is_empty(map->p[i]);
8520 5085426 : if (is_empty < 0)
8521 0 : return isl_bool_error;
8522 5085426 : if (!is_empty)
8523 5085426 : return isl_bool_false;
8524 : }
8525 0 : return isl_bool_true;
8526 : }
8527 :
8528 10026360 : isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8529 : {
8530 10026360 : return map ? map->n == 0 : isl_bool_error;
8531 : }
8532 :
8533 0 : isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8534 : {
8535 0 : return set ? set->n == 0 : isl_bool_error;
8536 : }
8537 :
8538 119390 : isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8539 : {
8540 119390 : return isl_map_is_empty(set_to_map(set));
8541 : }
8542 :
8543 203490 : isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
8544 : __isl_keep isl_map *map2)
8545 : {
8546 203490 : if (!map1 || !map2)
8547 0 : return isl_bool_error;
8548 :
8549 203490 : return isl_space_is_equal(map1->dim, map2->dim);
8550 : }
8551 :
8552 0 : isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
8553 : __isl_keep isl_set *set2)
8554 : {
8555 0 : if (!set1 || !set2)
8556 0 : return isl_bool_error;
8557 :
8558 0 : return isl_space_is_equal(set1->dim, set2->dim);
8559 : }
8560 :
8561 101745 : static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8562 : {
8563 : isl_bool is_subset;
8564 :
8565 101745 : if (!map1 || !map2)
8566 0 : return isl_bool_error;
8567 101745 : is_subset = isl_map_is_subset(map1, map2);
8568 101745 : if (is_subset != isl_bool_true)
8569 0 : return is_subset;
8570 101745 : is_subset = isl_map_is_subset(map2, map1);
8571 101745 : return is_subset;
8572 : }
8573 :
8574 : /* Is "map1" equal to "map2"?
8575 : *
8576 : * First check if they are obviously equal.
8577 : * If not, then perform a more detailed analysis.
8578 : */
8579 752960 : isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
8580 : {
8581 : isl_bool equal;
8582 :
8583 752960 : equal = isl_map_plain_is_equal(map1, map2);
8584 752960 : if (equal < 0 || equal)
8585 651215 : return equal;
8586 101745 : return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
8587 : }
8588 :
8589 0 : isl_bool isl_basic_map_is_strict_subset(
8590 : struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8591 : {
8592 : isl_bool is_subset;
8593 :
8594 0 : if (!bmap1 || !bmap2)
8595 0 : return isl_bool_error;
8596 0 : is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8597 0 : if (is_subset != isl_bool_true)
8598 0 : return is_subset;
8599 0 : is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8600 0 : if (is_subset == isl_bool_error)
8601 0 : return is_subset;
8602 0 : return !is_subset;
8603 : }
8604 :
8605 0 : isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8606 : __isl_keep isl_map *map2)
8607 : {
8608 : isl_bool is_subset;
8609 :
8610 0 : if (!map1 || !map2)
8611 0 : return isl_bool_error;
8612 0 : is_subset = isl_map_is_subset(map1, map2);
8613 0 : if (is_subset != isl_bool_true)
8614 0 : return is_subset;
8615 0 : is_subset = isl_map_is_subset(map2, map1);
8616 0 : if (is_subset == isl_bool_error)
8617 0 : return is_subset;
8618 0 : return !is_subset;
8619 : }
8620 :
8621 0 : isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8622 : __isl_keep isl_set *set2)
8623 : {
8624 0 : return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8625 : }
8626 :
8627 : /* Is "bmap" obviously equal to the universe with the same space?
8628 : *
8629 : * That is, does it not have any constraints?
8630 : */
8631 1346532020 : isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8632 : {
8633 1346532020 : if (!bmap)
8634 0 : return isl_bool_error;
8635 1346532020 : return bmap->n_eq == 0 && bmap->n_ineq == 0;
8636 : }
8637 :
8638 : /* Is "bset" obviously equal to the universe with the same space?
8639 : */
8640 0 : isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8641 : {
8642 0 : return isl_basic_map_plain_is_universe(bset);
8643 : }
8644 :
8645 : /* If "c" does not involve any existentially quantified variables,
8646 : * then set *univ to false and abort
8647 : */
8648 0 : static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8649 : {
8650 0 : isl_bool *univ = user;
8651 : unsigned n;
8652 :
8653 0 : n = isl_constraint_dim(c, isl_dim_div);
8654 0 : *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8655 0 : isl_constraint_free(c);
8656 0 : if (*univ < 0 || !*univ)
8657 0 : return isl_stat_error;
8658 0 : return isl_stat_ok;
8659 : }
8660 :
8661 : /* Is "bmap" equal to the universe with the same space?
8662 : *
8663 : * First check if it is obviously equal to the universe.
8664 : * If not and if there are any constraints not involving
8665 : * existentially quantified variables, then it is certainly
8666 : * not equal to the universe.
8667 : * Otherwise, check if the universe is a subset of "bmap".
8668 : */
8669 0 : isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8670 : {
8671 : isl_bool univ;
8672 : isl_basic_map *test;
8673 :
8674 0 : univ = isl_basic_map_plain_is_universe(bmap);
8675 0 : if (univ < 0 || univ)
8676 0 : return univ;
8677 0 : if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8678 0 : return isl_bool_false;
8679 0 : univ = isl_bool_true;
8680 0 : if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8681 : univ)
8682 0 : return isl_bool_error;
8683 0 : if (univ < 0 || !univ)
8684 0 : return univ;
8685 0 : test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8686 0 : univ = isl_basic_map_is_subset(test, bmap);
8687 0 : isl_basic_map_free(test);
8688 0 : return univ;
8689 : }
8690 :
8691 : /* Is "bset" equal to the universe with the same space?
8692 : */
8693 0 : isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8694 : {
8695 0 : return isl_basic_map_is_universe(bset);
8696 : }
8697 :
8698 84864156 : isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8699 : {
8700 : int i;
8701 :
8702 84864156 : if (!map)
8703 0 : return isl_bool_error;
8704 :
8705 1316076933 : for (i = 0; i < map->n; ++i) {
8706 1233451023 : isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8707 1233451023 : if (r < 0 || r)
8708 2238246 : return r;
8709 : }
8710 :
8711 82625910 : return isl_bool_false;
8712 : }
8713 :
8714 0 : isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8715 : {
8716 0 : return isl_map_plain_is_universe(set_to_map(set));
8717 : }
8718 :
8719 173528979 : isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8720 : {
8721 173528979 : struct isl_basic_set *bset = NULL;
8722 173528979 : struct isl_vec *sample = NULL;
8723 : isl_bool empty, non_empty;
8724 :
8725 173528979 : if (!bmap)
8726 0 : return isl_bool_error;
8727 :
8728 173528979 : if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8729 70674466 : return isl_bool_true;
8730 :
8731 102854513 : if (isl_basic_map_plain_is_universe(bmap))
8732 3883363 : return isl_bool_false;
8733 :
8734 98971150 : if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8735 0 : struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8736 0 : copy = isl_basic_map_remove_redundancies(copy);
8737 0 : empty = isl_basic_map_plain_is_empty(copy);
8738 0 : isl_basic_map_free(copy);
8739 0 : return empty;
8740 : }
8741 :
8742 98971150 : non_empty = isl_basic_map_plain_is_non_empty(bmap);
8743 98971150 : if (non_empty < 0)
8744 0 : return isl_bool_error;
8745 98971150 : if (non_empty)
8746 43442723 : return isl_bool_false;
8747 55528427 : isl_vec_free(bmap->sample);
8748 55528427 : bmap->sample = NULL;
8749 55528427 : bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8750 55528427 : if (!bset)
8751 0 : return isl_bool_error;
8752 55528427 : sample = isl_basic_set_sample_vec(bset);
8753 55528427 : if (!sample)
8754 0 : return isl_bool_error;
8755 55528427 : empty = sample->size == 0;
8756 55528427 : isl_vec_free(bmap->sample);
8757 55528427 : bmap->sample = sample;
8758 55528427 : if (empty)
8759 28606928 : ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8760 :
8761 55528427 : return empty;
8762 : }
8763 :
8764 42735581661 : isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8765 : {
8766 42735581661 : if (!bmap)
8767 0 : return isl_bool_error;
8768 42735581661 : return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8769 : }
8770 :
8771 135474501 : isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8772 : {
8773 135474501 : if (!bset)
8774 0 : return isl_bool_error;
8775 135474501 : return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8776 : }
8777 :
8778 : /* Is "bmap" known to be non-empty?
8779 : *
8780 : * That is, is the cached sample still valid?
8781 : */
8782 98971150 : isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8783 : {
8784 : unsigned total;
8785 :
8786 98971150 : if (!bmap)
8787 0 : return isl_bool_error;
8788 98971150 : if (!bmap->sample)
8789 21455809 : return isl_bool_false;
8790 77515341 : total = 1 + isl_basic_map_total_dim(bmap);
8791 77515341 : if (bmap->sample->size != total)
8792 0 : return isl_bool_false;
8793 77515341 : return isl_basic_map_contains(bmap, bmap->sample);
8794 : }
8795 :
8796 0 : isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8797 : {
8798 0 : return isl_basic_map_is_empty(bset_to_bmap(bset));
8799 : }
8800 :
8801 0 : __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
8802 : __isl_take isl_basic_map *bmap2)
8803 : {
8804 : struct isl_map *map;
8805 0 : if (!bmap1 || !bmap2)
8806 : goto error;
8807 :
8808 0 : isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8809 :
8810 0 : map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8811 0 : if (!map)
8812 0 : goto error;
8813 0 : map = isl_map_add_basic_map(map, bmap1);
8814 0 : map = isl_map_add_basic_map(map, bmap2);
8815 0 : return map;
8816 : error:
8817 0 : isl_basic_map_free(bmap1);
8818 0 : isl_basic_map_free(bmap2);
8819 0 : return NULL;
8820 : }
8821 :
8822 0 : struct isl_set *isl_basic_set_union(
8823 : struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8824 : {
8825 0 : return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8826 : bset_to_bmap(bset2)));
8827 : }
8828 :
8829 : /* Order divs such that any div only depends on previous divs */
8830 66312699388 : __isl_give isl_basic_map *isl_basic_map_order_divs(
8831 : __isl_take isl_basic_map *bmap)
8832 : {
8833 : int i;
8834 : unsigned off;
8835 :
8836 66312699388 : if (!bmap)
8837 0 : return NULL;
8838 :
8839 66312699388 : off = isl_space_dim(bmap->dim, isl_dim_all);
8840 :
8841 66312699388 : for (i = 0; i < bmap->n_div; ++i) {
8842 : int pos;
8843 0 : if (isl_int_is_zero(bmap->div[i][0]))
8844 0 : continue;
8845 0 : pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8846 0 : bmap->n_div-i);
8847 0 : if (pos == -1)
8848 0 : continue;
8849 0 : if (pos == 0)
8850 0 : isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8851 : "integer division depends on itself",
8852 : return isl_basic_map_free(bmap));
8853 0 : isl_basic_map_swap_div(bmap, i, i + pos);
8854 0 : --i;
8855 : }
8856 66312699388 : return bmap;
8857 : }
8858 :
8859 0 : struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8860 : {
8861 0 : return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8862 : }
8863 :
8864 11827020 : __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8865 : {
8866 : int i;
8867 :
8868 11827020 : if (!map)
8869 0 : return 0;
8870 :
8871 536370494 : for (i = 0; i < map->n; ++i) {
8872 524543474 : map->p[i] = isl_basic_map_order_divs(map->p[i]);
8873 524543474 : if (!map->p[i])
8874 0 : goto error;
8875 : }
8876 :
8877 11827020 : return map;
8878 : error:
8879 0 : isl_map_free(map);
8880 0 : return NULL;
8881 : }
8882 :
8883 : /* Sort the local variables of "bset".
8884 : */
8885 0 : __isl_give isl_basic_set *isl_basic_set_sort_divs(
8886 : __isl_take isl_basic_set *bset)
8887 : {
8888 0 : return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8889 : }
8890 :
8891 : /* Apply the expansion computed by isl_merge_divs.
8892 : * The expansion itself is given by "exp" while the resulting
8893 : * list of divs is given by "div".
8894 : *
8895 : * Move the integer divisions of "bmap" into the right position
8896 : * according to "exp" and then introduce the additional integer
8897 : * divisions, adding div constraints.
8898 : * The moving should be done first to avoid moving coefficients
8899 : * in the definitions of the extra integer divisions.
8900 : */
8901 0 : __isl_give isl_basic_map *isl_basic_map_expand_divs(
8902 : __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8903 : {
8904 : int i, j;
8905 : int n_div;
8906 :
8907 0 : bmap = isl_basic_map_cow(bmap);
8908 0 : if (!bmap || !div)
8909 : goto error;
8910 :
8911 0 : if (div->n_row < bmap->n_div)
8912 0 : isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8913 : "not an expansion", goto error);
8914 :
8915 0 : n_div = bmap->n_div;
8916 0 : bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8917 0 : div->n_row - n_div, 0,
8918 0 : 2 * (div->n_row - n_div));
8919 :
8920 0 : for (i = n_div; i < div->n_row; ++i)
8921 0 : if (isl_basic_map_alloc_div(bmap) < 0)
8922 0 : goto error;
8923 :
8924 0 : for (j = n_div - 1; j >= 0; --j) {
8925 0 : if (exp[j] == j)
8926 0 : break;
8927 0 : isl_basic_map_swap_div(bmap, j, exp[j]);
8928 : }
8929 0 : j = 0;
8930 0 : for (i = 0; i < div->n_row; ++i) {
8931 0 : if (j < n_div && exp[j] == i) {
8932 0 : j++;
8933 : } else {
8934 0 : isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8935 0 : if (isl_basic_map_div_is_marked_unknown(bmap, i))
8936 0 : continue;
8937 0 : if (isl_basic_map_add_div_constraints(bmap, i) < 0)
8938 0 : goto error;
8939 : }
8940 : }
8941 :
8942 0 : isl_mat_free(div);
8943 0 : return bmap;
8944 : error:
8945 0 : isl_basic_map_free(bmap);
8946 0 : isl_mat_free(div);
8947 0 : return NULL;
8948 : }
8949 :
8950 : /* Apply the expansion computed by isl_merge_divs.
8951 : * The expansion itself is given by "exp" while the resulting
8952 : * list of divs is given by "div".
8953 : */
8954 0 : __isl_give isl_basic_set *isl_basic_set_expand_divs(
8955 : __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8956 : {
8957 0 : return isl_basic_map_expand_divs(bset, div, exp);
8958 : }
8959 :
8960 : /* Look for a div in dst that corresponds to the div "div" in src.
8961 : * The divs before "div" in src and dst are assumed to be the same.
8962 : *
8963 : * Returns -1 if no corresponding div was found and the position
8964 : * of the corresponding div in dst otherwise.
8965 : */
8966 0 : static int find_div(__isl_keep isl_basic_map *dst,
8967 : __isl_keep isl_basic_map *src, unsigned div)
8968 : {
8969 : int i;
8970 :
8971 0 : unsigned total = isl_space_dim(src->dim, isl_dim_all);
8972 :
8973 0 : isl_assert(dst->ctx, div <= dst->n_div, return -1);
8974 0 : for (i = div; i < dst->n_div; ++i)
8975 0 : if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8976 0 : isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8977 0 : dst->n_div - div) == -1)
8978 0 : return i;
8979 0 : return -1;
8980 : }
8981 :
8982 : /* Align the divs of "dst" to those of "src", adding divs from "src"
8983 : * if needed. That is, make sure that the first src->n_div divs
8984 : * of the result are equal to those of src.
8985 : *
8986 : * The result is not finalized as by design it will have redundant
8987 : * divs if any divs from "src" were copied.
8988 : */
8989 1087210430 : __isl_give isl_basic_map *isl_basic_map_align_divs(
8990 : __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8991 : {
8992 : int i;
8993 : int known, extended;
8994 : unsigned total;
8995 :
8996 1087210430 : if (!dst || !src)
8997 0 : return isl_basic_map_free(dst);
8998 :
8999 1087210430 : if (src->n_div == 0)
9000 1087210430 : return dst;
9001 :
9002 0 : known = isl_basic_map_divs_known(src);
9003 0 : if (known < 0)
9004 0 : return isl_basic_map_free(dst);
9005 0 : if (!known)
9006 0 : isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9007 : "some src divs are unknown",
9008 : return isl_basic_map_free(dst));
9009 :
9010 0 : src = isl_basic_map_order_divs(isl_basic_map_copy(src));
9011 0 : if (!src)
9012 0 : return isl_basic_map_free(dst);
9013 :
9014 0 : extended = 0;
9015 0 : total = isl_space_dim(src->dim, isl_dim_all);
9016 0 : for (i = 0; i < src->n_div; ++i) {
9017 0 : int j = find_div(dst, src, i);
9018 0 : if (j < 0) {
9019 0 : if (!extended) {
9020 0 : int extra = src->n_div - i;
9021 0 : dst = isl_basic_map_cow(dst);
9022 0 : if (!dst)
9023 0 : goto error;
9024 0 : dst = isl_basic_map_extend_space(dst,
9025 : isl_space_copy(dst->dim),
9026 0 : extra, 0, 2 * extra);
9027 0 : extended = 1;
9028 : }
9029 0 : j = isl_basic_map_alloc_div(dst);
9030 0 : if (j < 0)
9031 0 : goto error;
9032 0 : isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
9033 0 : isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
9034 0 : if (isl_basic_map_add_div_constraints(dst, j) < 0)
9035 0 : goto error;
9036 : }
9037 0 : if (j != i)
9038 0 : isl_basic_map_swap_div(dst, i, j);
9039 : }
9040 0 : isl_basic_map_free(src);
9041 0 : return dst;
9042 : error:
9043 0 : isl_basic_map_free(src);
9044 0 : isl_basic_map_free(dst);
9045 0 : return NULL;
9046 : }
9047 :
9048 645942497 : __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9049 : {
9050 : int i;
9051 :
9052 645942497 : if (!map)
9053 0 : return NULL;
9054 645942497 : if (map->n == 0)
9055 0 : return map;
9056 645942497 : map = isl_map_compute_divs(map);
9057 645942497 : map = isl_map_cow(map);
9058 645942497 : if (!map)
9059 0 : return NULL;
9060 :
9061 1189547712 : for (i = 1; i < map->n; ++i)
9062 543605215 : map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9063 1189547712 : for (i = 1; i < map->n; ++i) {
9064 543605215 : map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9065 543605215 : if (!map->p[i])
9066 0 : return isl_map_free(map);
9067 : }
9068 :
9069 645942497 : map = isl_map_unmark_normalized(map);
9070 645942497 : return map;
9071 : }
9072 :
9073 0 : __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9074 : {
9075 0 : return isl_map_align_divs_internal(map);
9076 : }
9077 :
9078 0 : struct isl_set *isl_set_align_divs(struct isl_set *set)
9079 : {
9080 0 : return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9081 : }
9082 :
9083 : /* Align the divs of the basic maps in "map" to those
9084 : * of the basic maps in "list", as well as to the other basic maps in "map".
9085 : * The elements in "list" are assumed to have known divs.
9086 : */
9087 0 : __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9088 : __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9089 : {
9090 : int i, n;
9091 :
9092 0 : map = isl_map_compute_divs(map);
9093 0 : map = isl_map_cow(map);
9094 0 : if (!map || !list)
9095 0 : return isl_map_free(map);
9096 0 : if (map->n == 0)
9097 0 : return map;
9098 :
9099 0 : n = isl_basic_map_list_n_basic_map(list);
9100 0 : for (i = 0; i < n; ++i) {
9101 : isl_basic_map *bmap;
9102 :
9103 0 : bmap = isl_basic_map_list_get_basic_map(list, i);
9104 0 : map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9105 0 : isl_basic_map_free(bmap);
9106 : }
9107 0 : if (!map->p[0])
9108 0 : return isl_map_free(map);
9109 :
9110 0 : return isl_map_align_divs_internal(map);
9111 : }
9112 :
9113 : /* Align the divs of each element of "list" to those of "bmap".
9114 : * Both "bmap" and the elements of "list" are assumed to have known divs.
9115 : */
9116 0 : __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9117 : __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9118 : {
9119 : int i, n;
9120 :
9121 0 : if (!list || !bmap)
9122 0 : return isl_basic_map_list_free(list);
9123 :
9124 0 : n = isl_basic_map_list_n_basic_map(list);
9125 0 : for (i = 0; i < n; ++i) {
9126 : isl_basic_map *bmap_i;
9127 :
9128 0 : bmap_i = isl_basic_map_list_get_basic_map(list, i);
9129 0 : bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9130 0 : list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9131 : }
9132 :
9133 0 : return list;
9134 : }
9135 :
9136 0 : static __isl_give isl_set *set_apply( __isl_take isl_set *set,
9137 : __isl_take isl_map *map)
9138 : {
9139 : isl_bool ok;
9140 :
9141 0 : ok = isl_map_compatible_domain(map, set);
9142 0 : if (ok < 0)
9143 0 : goto error;
9144 0 : if (!ok)
9145 0 : isl_die(isl_set_get_ctx(set), isl_error_invalid,
9146 : "incompatible spaces", goto error);
9147 0 : map = isl_map_intersect_domain(map, set);
9148 0 : set = isl_map_range(map);
9149 0 : return set;
9150 : error:
9151 0 : isl_set_free(set);
9152 0 : isl_map_free(map);
9153 0 : return NULL;
9154 : }
9155 :
9156 0 : __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9157 : __isl_take isl_map *map)
9158 : {
9159 0 : return isl_map_align_params_map_map_and(set, map, &set_apply);
9160 : }
9161 :
9162 : /* There is no need to cow as removing empty parts doesn't change
9163 : * the meaning of the set.
9164 : */
9165 2726435354 : __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9166 : {
9167 : int i;
9168 :
9169 2726435354 : if (!map)
9170 0 : return NULL;
9171 :
9172 10974384279 : for (i = map->n - 1; i >= 0; --i)
9173 8247948925 : map = remove_if_empty(map, i);
9174 :
9175 2726435354 : return map;
9176 : }
9177 :
9178 840305892 : struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
9179 : {
9180 840305892 : return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9181 : }
9182 :
9183 : /* Create a binary relation that maps the shared initial "pos" dimensions
9184 : * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9185 : */
9186 0 : static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9187 : __isl_keep isl_basic_set *bset2, int pos)
9188 : {
9189 : isl_basic_map *bmap1;
9190 : isl_basic_map *bmap2;
9191 :
9192 0 : bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9193 0 : bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9194 0 : bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9195 : isl_dim_out, 0, pos);
9196 0 : bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9197 : isl_dim_out, 0, pos);
9198 0 : return isl_basic_map_range_product(bmap1, bmap2);
9199 : }
9200 :
9201 : /* Given two basic sets bset1 and bset2, compute the maximal difference
9202 : * between the values of dimension pos in bset1 and those in bset2
9203 : * for any common value of the parameters and dimensions preceding pos.
9204 : */
9205 0 : static enum isl_lp_result basic_set_maximal_difference_at(
9206 : __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9207 : int pos, isl_int *opt)
9208 : {
9209 : isl_basic_map *bmap1;
9210 : struct isl_ctx *ctx;
9211 : struct isl_vec *obj;
9212 : unsigned total;
9213 : unsigned nparam;
9214 : unsigned dim1;
9215 : enum isl_lp_result res;
9216 :
9217 0 : if (!bset1 || !bset2)
9218 0 : return isl_lp_error;
9219 :
9220 0 : nparam = isl_basic_set_n_param(bset1);
9221 0 : dim1 = isl_basic_set_n_dim(bset1);
9222 :
9223 0 : bmap1 = join_initial(bset1, bset2, pos);
9224 0 : if (!bmap1)
9225 0 : return isl_lp_error;
9226 :
9227 0 : total = isl_basic_map_total_dim(bmap1);
9228 0 : ctx = bmap1->ctx;
9229 0 : obj = isl_vec_alloc(ctx, 1 + total);
9230 0 : if (!obj)
9231 0 : goto error;
9232 0 : isl_seq_clr(obj->block.data, 1 + total);
9233 0 : isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9234 0 : isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9235 0 : res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9236 : opt, NULL, NULL);
9237 0 : isl_basic_map_free(bmap1);
9238 0 : isl_vec_free(obj);
9239 0 : return res;
9240 : error:
9241 0 : isl_basic_map_free(bmap1);
9242 0 : return isl_lp_error;
9243 : }
9244 :
9245 : /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9246 : * for any common value of the parameters and dimensions preceding pos
9247 : * in both basic sets, the values of dimension pos in bset1 are
9248 : * smaller or larger than those in bset2.
9249 : *
9250 : * Returns
9251 : * 1 if bset1 follows bset2
9252 : * -1 if bset1 precedes bset2
9253 : * 0 if bset1 and bset2 are incomparable
9254 : * -2 if some error occurred.
9255 : */
9256 0 : int isl_basic_set_compare_at(struct isl_basic_set *bset1,
9257 : struct isl_basic_set *bset2, int pos)
9258 : {
9259 : isl_int opt;
9260 : enum isl_lp_result res;
9261 : int cmp;
9262 :
9263 0 : isl_int_init(opt);
9264 :
9265 0 : res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9266 :
9267 0 : if (res == isl_lp_empty)
9268 0 : cmp = 0;
9269 0 : else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9270 : res == isl_lp_unbounded)
9271 0 : cmp = 1;
9272 0 : else if (res == isl_lp_ok && isl_int_is_neg(opt))
9273 0 : cmp = -1;
9274 : else
9275 0 : cmp = -2;
9276 :
9277 0 : isl_int_clear(opt);
9278 0 : return cmp;
9279 : }
9280 :
9281 : /* Given two basic sets bset1 and bset2, check whether
9282 : * for any common value of the parameters and dimensions preceding pos
9283 : * there is a value of dimension pos in bset1 that is larger
9284 : * than a value of the same dimension in bset2.
9285 : *
9286 : * Return
9287 : * 1 if there exists such a pair
9288 : * 0 if there is no such pair, but there is a pair of equal values
9289 : * -1 otherwise
9290 : * -2 if some error occurred.
9291 : */
9292 0 : int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9293 : __isl_keep isl_basic_set *bset2, int pos)
9294 : {
9295 : isl_bool empty;
9296 : isl_basic_map *bmap;
9297 : unsigned dim1;
9298 :
9299 0 : dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9300 0 : bmap = join_initial(bset1, bset2, pos);
9301 0 : bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9302 0 : isl_dim_out, dim1 - pos);
9303 0 : empty = isl_basic_map_is_empty(bmap);
9304 0 : if (empty < 0)
9305 0 : goto error;
9306 0 : if (empty) {
9307 0 : isl_basic_map_free(bmap);
9308 0 : return -1;
9309 : }
9310 0 : bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9311 0 : isl_dim_out, dim1 - pos);
9312 0 : empty = isl_basic_map_is_empty(bmap);
9313 0 : if (empty < 0)
9314 0 : goto error;
9315 0 : isl_basic_map_free(bmap);
9316 0 : if (empty)
9317 0 : return 0;
9318 0 : return 1;
9319 : error:
9320 0 : isl_basic_map_free(bmap);
9321 0 : return -2;
9322 : }
9323 :
9324 : /* Given two sets set1 and set2, check whether
9325 : * for any common value of the parameters and dimensions preceding pos
9326 : * there is a value of dimension pos in set1 that is larger
9327 : * than a value of the same dimension in set2.
9328 : *
9329 : * Return
9330 : * 1 if there exists such a pair
9331 : * 0 if there is no such pair, but there is a pair of equal values
9332 : * -1 otherwise
9333 : * -2 if some error occurred.
9334 : */
9335 0 : int isl_set_follows_at(__isl_keep isl_set *set1,
9336 : __isl_keep isl_set *set2, int pos)
9337 : {
9338 : int i, j;
9339 0 : int follows = -1;
9340 :
9341 0 : if (!set1 || !set2)
9342 0 : return -2;
9343 :
9344 0 : for (i = 0; i < set1->n; ++i)
9345 0 : for (j = 0; j < set2->n; ++j) {
9346 : int f;
9347 0 : f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9348 0 : if (f == 1 || f == -2)
9349 0 : return f;
9350 0 : if (f > follows)
9351 0 : follows = f;
9352 : }
9353 :
9354 0 : return follows;
9355 : }
9356 :
9357 0 : static isl_bool isl_basic_map_plain_has_fixed_var(
9358 : __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9359 : {
9360 : int i;
9361 : int d;
9362 : unsigned total;
9363 :
9364 0 : if (!bmap)
9365 0 : return isl_bool_error;
9366 0 : total = isl_basic_map_total_dim(bmap);
9367 0 : for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9368 0 : for (; d+1 > pos; --d)
9369 0 : if (!isl_int_is_zero(bmap->eq[i][1+d]))
9370 : break;
9371 0 : if (d != pos)
9372 0 : continue;
9373 0 : if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9374 0 : return isl_bool_false;
9375 0 : if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9376 0 : return isl_bool_false;
9377 0 : if (!isl_int_is_one(bmap->eq[i][1+d]))
9378 0 : return isl_bool_false;
9379 0 : if (val)
9380 0 : isl_int_neg(*val, bmap->eq[i][0]);
9381 0 : return isl_bool_true;
9382 : }
9383 0 : return isl_bool_false;
9384 : }
9385 :
9386 0 : static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9387 : unsigned pos, isl_int *val)
9388 : {
9389 : int i;
9390 : isl_int v;
9391 : isl_int tmp;
9392 : isl_bool fixed;
9393 :
9394 0 : if (!map)
9395 0 : return isl_bool_error;
9396 0 : if (map->n == 0)
9397 0 : return isl_bool_false;
9398 0 : if (map->n == 1)
9399 0 : return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9400 0 : isl_int_init(v);
9401 0 : isl_int_init(tmp);
9402 0 : fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9403 0 : for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9404 0 : fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9405 0 : if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9406 0 : fixed = isl_bool_false;
9407 : }
9408 0 : if (val)
9409 0 : isl_int_set(*val, v);
9410 0 : isl_int_clear(tmp);
9411 0 : isl_int_clear(v);
9412 0 : return fixed;
9413 : }
9414 :
9415 0 : static isl_bool isl_basic_set_plain_has_fixed_var(
9416 : __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9417 : {
9418 0 : return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9419 : pos, val);
9420 : }
9421 :
9422 0 : isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9423 : enum isl_dim_type type, unsigned pos, isl_int *val)
9424 : {
9425 0 : if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9426 0 : return isl_bool_error;
9427 0 : return isl_basic_map_plain_has_fixed_var(bmap,
9428 0 : isl_basic_map_offset(bmap, type) - 1 + pos, val);
9429 : }
9430 :
9431 : /* If "bmap" obviously lies on a hyperplane where the given dimension
9432 : * has a fixed value, then return that value.
9433 : * Otherwise return NaN.
9434 : */
9435 0 : __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9436 : __isl_keep isl_basic_map *bmap,
9437 : enum isl_dim_type type, unsigned pos)
9438 : {
9439 : isl_ctx *ctx;
9440 : isl_val *v;
9441 : isl_bool fixed;
9442 :
9443 0 : if (!bmap)
9444 0 : return NULL;
9445 0 : ctx = isl_basic_map_get_ctx(bmap);
9446 0 : v = isl_val_alloc(ctx);
9447 0 : if (!v)
9448 0 : return NULL;
9449 0 : fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9450 0 : if (fixed < 0)
9451 0 : return isl_val_free(v);
9452 0 : if (fixed) {
9453 0 : isl_int_set_si(v->d, 1);
9454 0 : return v;
9455 : }
9456 0 : isl_val_free(v);
9457 0 : return isl_val_nan(ctx);
9458 : }
9459 :
9460 0 : isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9461 : enum isl_dim_type type, unsigned pos, isl_int *val)
9462 : {
9463 0 : if (pos >= isl_map_dim(map, type))
9464 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
9465 : "position out of bounds", return isl_bool_error);
9466 0 : return isl_map_plain_has_fixed_var(map,
9467 0 : map_offset(map, type) - 1 + pos, val);
9468 : }
9469 :
9470 : /* If "map" obviously lies on a hyperplane where the given dimension
9471 : * has a fixed value, then return that value.
9472 : * Otherwise return NaN.
9473 : */
9474 0 : __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9475 : enum isl_dim_type type, unsigned pos)
9476 : {
9477 : isl_ctx *ctx;
9478 : isl_val *v;
9479 : isl_bool fixed;
9480 :
9481 0 : if (!map)
9482 0 : return NULL;
9483 0 : ctx = isl_map_get_ctx(map);
9484 0 : v = isl_val_alloc(ctx);
9485 0 : if (!v)
9486 0 : return NULL;
9487 0 : fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9488 0 : if (fixed < 0)
9489 0 : return isl_val_free(v);
9490 0 : if (fixed) {
9491 0 : isl_int_set_si(v->d, 1);
9492 0 : return v;
9493 : }
9494 0 : isl_val_free(v);
9495 0 : return isl_val_nan(ctx);
9496 : }
9497 :
9498 : /* If "set" obviously lies on a hyperplane where the given dimension
9499 : * has a fixed value, then return that value.
9500 : * Otherwise return NaN.
9501 : */
9502 0 : __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
9503 : enum isl_dim_type type, unsigned pos)
9504 : {
9505 0 : return isl_map_plain_get_val_if_fixed(set, type, pos);
9506 : }
9507 :
9508 : /* Check if dimension dim has fixed value and if so and if val is not NULL,
9509 : * then return this fixed value in *val.
9510 : */
9511 0 : isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
9512 : unsigned dim, isl_int *val)
9513 : {
9514 0 : return isl_basic_set_plain_has_fixed_var(bset,
9515 0 : isl_basic_set_n_param(bset) + dim, val);
9516 : }
9517 :
9518 : /* Return -1 if the constraint "c1" should be sorted before "c2"
9519 : * and 1 if it should be sorted after "c2".
9520 : * Return 0 if the two constraints are the same (up to the constant term).
9521 : *
9522 : * In particular, if a constraint involves later variables than another
9523 : * then it is sorted after this other constraint.
9524 : * uset_gist depends on constraints without existentially quantified
9525 : * variables sorting first.
9526 : *
9527 : * For constraints that have the same latest variable, those
9528 : * with the same coefficient for this latest variable (first in absolute value
9529 : * and then in actual value) are grouped together.
9530 : * This is useful for detecting pairs of constraints that can
9531 : * be chained in their printed representation.
9532 : *
9533 : * Finally, within a group, constraints are sorted according to
9534 : * their coefficients (excluding the constant term).
9535 : */
9536 1373361679 : static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
9537 : {
9538 1373361679 : isl_int **c1 = (isl_int **) p1;
9539 1373361679 : isl_int **c2 = (isl_int **) p2;
9540 : int l1, l2;
9541 1373361679 : unsigned size = *(unsigned *) arg;
9542 : int cmp;
9543 :
9544 1373361679 : l1 = isl_seq_last_non_zero(*c1 + 1, size);
9545 1373361679 : l2 = isl_seq_last_non_zero(*c2 + 1, size);
9546 :
9547 1373361679 : if (l1 != l2)
9548 550522862 : return l1 - l2;
9549 :
9550 822838817 : cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9551 822838817 : if (cmp != 0)
9552 657556559 : return cmp;
9553 165282258 : cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
9554 165282258 : if (cmp != 0)
9555 76621626 : return -cmp;
9556 :
9557 88660632 : return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
9558 : }
9559 :
9560 : /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
9561 : * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
9562 : * and 0 if the two constraints are the same (up to the constant term).
9563 : */
9564 0 : int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
9565 : isl_int *c1, isl_int *c2)
9566 : {
9567 : unsigned total;
9568 :
9569 0 : if (!bmap)
9570 0 : return -2;
9571 0 : total = isl_basic_map_total_dim(bmap);
9572 0 : return sort_constraint_cmp(&c1, &c2, &total);
9573 : }
9574 :
9575 2996082145 : __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9576 : __isl_take isl_basic_map *bmap)
9577 : {
9578 : unsigned total;
9579 :
9580 2996082145 : if (!bmap)
9581 0 : return NULL;
9582 2996082145 : if (bmap->n_ineq == 0)
9583 2902432119 : return bmap;
9584 93650026 : if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9585 0 : return bmap;
9586 93650026 : total = isl_basic_map_total_dim(bmap);
9587 93650026 : if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9588 : &sort_constraint_cmp, &total) < 0)
9589 0 : return isl_basic_map_free(bmap);
9590 93650026 : return bmap;
9591 : }
9592 :
9593 0 : __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9594 : __isl_take isl_basic_set *bset)
9595 : {
9596 0 : isl_basic_map *bmap = bset_to_bmap(bset);
9597 0 : return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9598 : }
9599 :
9600 3087899880 : __isl_give isl_basic_map *isl_basic_map_normalize(
9601 : __isl_take isl_basic_map *bmap)
9602 : {
9603 3087899880 : if (!bmap)
9604 0 : return NULL;
9605 3087899880 : if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9606 140543858 : return bmap;
9607 2947356022 : bmap = isl_basic_map_remove_redundancies(bmap);
9608 2947356022 : bmap = isl_basic_map_sort_constraints(bmap);
9609 2947356022 : if (bmap)
9610 2947356022 : ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
9611 2947356022 : return bmap;
9612 : }
9613 734560829 : int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9614 : __isl_keep isl_basic_map *bmap2)
9615 : {
9616 : int i, cmp;
9617 : unsigned total;
9618 : isl_space *space1, *space2;
9619 :
9620 734560829 : if (!bmap1 || !bmap2)
9621 0 : return -1;
9622 :
9623 734560829 : if (bmap1 == bmap2)
9624 2153190 : return 0;
9625 732407639 : space1 = isl_basic_map_peek_space(bmap1);
9626 732407639 : space2 = isl_basic_map_peek_space(bmap2);
9627 732407639 : cmp = isl_space_cmp(space1, space2);
9628 732407639 : if (cmp)
9629 0 : return cmp;
9630 1464815278 : if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9631 732407639 : ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9632 0 : return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9633 732407639 : if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9634 0 : ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9635 0 : return 0;
9636 732407639 : if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9637 0 : return 1;
9638 732407639 : if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9639 0 : return -1;
9640 732407639 : if (bmap1->n_eq != bmap2->n_eq)
9641 86665875 : return bmap1->n_eq - bmap2->n_eq;
9642 645741764 : if (bmap1->n_ineq != bmap2->n_ineq)
9643 265343721 : return bmap1->n_ineq - bmap2->n_ineq;
9644 380398043 : if (bmap1->n_div != bmap2->n_div)
9645 0 : return bmap1->n_div - bmap2->n_div;
9646 380398043 : total = isl_basic_map_total_dim(bmap1);
9647 570221926 : for (i = 0; i < bmap1->n_eq; ++i) {
9648 225702282 : cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9649 225702282 : if (cmp)
9650 35878399 : return cmp;
9651 : }
9652 802704874 : for (i = 0; i < bmap1->n_ineq; ++i) {
9653 797669532 : cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9654 797669532 : if (cmp)
9655 339484302 : return cmp;
9656 : }
9657 5035342 : for (i = 0; i < bmap1->n_div; ++i) {
9658 0 : cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9659 0 : if (cmp)
9660 0 : return cmp;
9661 : }
9662 5035342 : return 0;
9663 : }
9664 :
9665 0 : int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9666 : __isl_keep isl_basic_set *bset2)
9667 : {
9668 0 : return isl_basic_map_plain_cmp(bset1, bset2);
9669 : }
9670 :
9671 0 : int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9672 : {
9673 : int i, cmp;
9674 :
9675 0 : if (set1 == set2)
9676 0 : return 0;
9677 0 : if (set1->n != set2->n)
9678 0 : return set1->n - set2->n;
9679 :
9680 0 : for (i = 0; i < set1->n; ++i) {
9681 0 : cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9682 0 : if (cmp)
9683 0 : return cmp;
9684 : }
9685 :
9686 0 : return 0;
9687 : }
9688 :
9689 181131617 : isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9690 : __isl_keep isl_basic_map *bmap2)
9691 : {
9692 181131617 : if (!bmap1 || !bmap2)
9693 0 : return isl_bool_error;
9694 181131617 : return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9695 : }
9696 :
9697 0 : isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9698 : __isl_keep isl_basic_set *bset2)
9699 : {
9700 0 : return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9701 : bset_to_bmap(bset2));
9702 : }
9703 :
9704 553429212 : static int qsort_bmap_cmp(const void *p1, const void *p2)
9705 : {
9706 553429212 : isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9707 553429212 : isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9708 :
9709 553429212 : return isl_basic_map_plain_cmp(bmap1, bmap2);
9710 : }
9711 :
9712 : /* Sort the basic maps of "map" and remove duplicate basic maps.
9713 : *
9714 : * While removing basic maps, we make sure that the basic maps remain
9715 : * sorted because isl_map_normalize expects the basic maps of the result
9716 : * to be sorted.
9717 : */
9718 17491798 : static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9719 : {
9720 : int i, j;
9721 :
9722 17491798 : map = isl_map_remove_empty_parts(map);
9723 17491798 : if (!map)
9724 0 : return NULL;
9725 17491798 : qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9726 191771641 : for (i = map->n - 1; i >= 1; --i) {
9727 174279843 : if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9728 172739681 : continue;
9729 1540162 : isl_basic_map_free(map->p[i-1]);
9730 38600045 : for (j = i; j < map->n; ++j)
9731 37059883 : map->p[j - 1] = map->p[j];
9732 1540162 : map->n--;
9733 : }
9734 :
9735 17491798 : return map;
9736 : }
9737 :
9738 : /* Remove obvious duplicates among the basic maps of "map".
9739 : *
9740 : * Unlike isl_map_normalize, this function does not remove redundant
9741 : * constraints and only removes duplicates that have exactly the same
9742 : * constraints in the input. It does sort the constraints and
9743 : * the basic maps to ease the detection of duplicates.
9744 : *
9745 : * If "map" has already been normalized or if the basic maps are
9746 : * disjoint, then there can be no duplicates.
9747 : */
9748 0 : __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9749 : {
9750 : int i;
9751 : isl_basic_map *bmap;
9752 :
9753 0 : if (!map)
9754 0 : return NULL;
9755 0 : if (map->n <= 1)
9756 0 : return map;
9757 0 : if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9758 0 : return map;
9759 0 : for (i = 0; i < map->n; ++i) {
9760 0 : bmap = isl_basic_map_copy(map->p[i]);
9761 0 : bmap = isl_basic_map_sort_constraints(bmap);
9762 0 : if (!bmap)
9763 0 : return isl_map_free(map);
9764 0 : isl_basic_map_free(map->p[i]);
9765 0 : map->p[i] = bmap;
9766 : }
9767 :
9768 0 : map = sort_and_remove_duplicates(map);
9769 0 : return map;
9770 : }
9771 :
9772 : /* We normalize in place, but if anything goes wrong we need
9773 : * to return NULL, so we need to make sure we don't change the
9774 : * meaning of any possible other copies of map.
9775 : */
9776 27226356 : __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9777 : {
9778 : int i;
9779 : struct isl_basic_map *bmap;
9780 :
9781 27226356 : if (!map)
9782 0 : return NULL;
9783 27226356 : if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9784 9734558 : return map;
9785 206471662 : for (i = 0; i < map->n; ++i) {
9786 188979864 : bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9787 188979864 : if (!bmap)
9788 0 : goto error;
9789 188979864 : isl_basic_map_free(map->p[i]);
9790 188979864 : map->p[i] = bmap;
9791 : }
9792 :
9793 17491798 : map = sort_and_remove_duplicates(map);
9794 17491798 : if (map)
9795 17491798 : ISL_F_SET(map, ISL_MAP_NORMALIZED);
9796 17491798 : return map;
9797 : error:
9798 0 : isl_map_free(map);
9799 0 : return NULL;
9800 : }
9801 :
9802 0 : struct isl_set *isl_set_normalize(struct isl_set *set)
9803 : {
9804 0 : return set_from_map(isl_map_normalize(set_to_map(set)));
9805 : }
9806 :
9807 13942842 : isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9808 : __isl_keep isl_map *map2)
9809 : {
9810 : int i;
9811 : isl_bool equal;
9812 :
9813 13942842 : if (!map1 || !map2)
9814 0 : return isl_bool_error;
9815 :
9816 13942842 : if (map1 == map2)
9817 329664 : return isl_bool_true;
9818 13613178 : if (!isl_space_is_equal(map1->dim, map2->dim))
9819 0 : return isl_bool_false;
9820 :
9821 13613178 : map1 = isl_map_copy(map1);
9822 13613178 : map2 = isl_map_copy(map2);
9823 13613178 : map1 = isl_map_normalize(map1);
9824 13613178 : map2 = isl_map_normalize(map2);
9825 13613178 : if (!map1 || !map2)
9826 : goto error;
9827 13613178 : equal = map1->n == map2->n;
9828 20464952 : for (i = 0; equal && i < map1->n; ++i) {
9829 6851774 : equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9830 6851774 : if (equal < 0)
9831 0 : goto error;
9832 : }
9833 13613178 : isl_map_free(map1);
9834 13613178 : isl_map_free(map2);
9835 13613178 : return equal;
9836 : error:
9837 0 : isl_map_free(map1);
9838 0 : isl_map_free(map2);
9839 0 : return isl_bool_error;
9840 : }
9841 :
9842 0 : isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9843 : __isl_keep isl_set *set2)
9844 : {
9845 0 : return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9846 : }
9847 :
9848 : /* Return the basic maps in "map" as a list.
9849 : */
9850 0 : __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9851 : __isl_keep isl_map *map)
9852 : {
9853 : int i;
9854 : isl_ctx *ctx;
9855 : isl_basic_map_list *list;
9856 :
9857 0 : if (!map)
9858 0 : return NULL;
9859 0 : ctx = isl_map_get_ctx(map);
9860 0 : list = isl_basic_map_list_alloc(ctx, map->n);
9861 :
9862 0 : for (i = 0; i < map->n; ++i) {
9863 : isl_basic_map *bmap;
9864 :
9865 0 : bmap = isl_basic_map_copy(map->p[i]);
9866 0 : list = isl_basic_map_list_add(list, bmap);
9867 : }
9868 :
9869 0 : return list;
9870 : }
9871 :
9872 : /* Return the intersection of the elements in the non-empty list "list".
9873 : * All elements are assumed to live in the same space.
9874 : */
9875 0 : __isl_give isl_basic_map *isl_basic_map_list_intersect(
9876 : __isl_take isl_basic_map_list *list)
9877 : {
9878 : int i, n;
9879 : isl_basic_map *bmap;
9880 :
9881 0 : if (!list)
9882 0 : return NULL;
9883 0 : n = isl_basic_map_list_n_basic_map(list);
9884 0 : if (n < 1)
9885 0 : isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9886 : "expecting non-empty list", goto error);
9887 :
9888 0 : bmap = isl_basic_map_list_get_basic_map(list, 0);
9889 0 : for (i = 1; i < n; ++i) {
9890 : isl_basic_map *bmap_i;
9891 :
9892 0 : bmap_i = isl_basic_map_list_get_basic_map(list, i);
9893 0 : bmap = isl_basic_map_intersect(bmap, bmap_i);
9894 : }
9895 :
9896 0 : isl_basic_map_list_free(list);
9897 0 : return bmap;
9898 : error:
9899 0 : isl_basic_map_list_free(list);
9900 0 : return NULL;
9901 : }
9902 :
9903 : /* Return the intersection of the elements in the non-empty list "list".
9904 : * All elements are assumed to live in the same space.
9905 : */
9906 0 : __isl_give isl_basic_set *isl_basic_set_list_intersect(
9907 : __isl_take isl_basic_set_list *list)
9908 : {
9909 0 : return isl_basic_map_list_intersect(list);
9910 : }
9911 :
9912 : /* Return the union of the elements of "list".
9913 : * The list is required to have at least one element.
9914 : */
9915 0 : __isl_give isl_set *isl_basic_set_list_union(
9916 : __isl_take isl_basic_set_list *list)
9917 : {
9918 : int i, n;
9919 : isl_space *space;
9920 : isl_basic_set *bset;
9921 : isl_set *set;
9922 :
9923 0 : if (!list)
9924 0 : return NULL;
9925 0 : n = isl_basic_set_list_n_basic_set(list);
9926 0 : if (n < 1)
9927 0 : isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9928 : "expecting non-empty list", goto error);
9929 :
9930 0 : bset = isl_basic_set_list_get_basic_set(list, 0);
9931 0 : space = isl_basic_set_get_space(bset);
9932 0 : isl_basic_set_free(bset);
9933 :
9934 0 : set = isl_set_alloc_space(space, n, 0);
9935 0 : for (i = 0; i < n; ++i) {
9936 0 : bset = isl_basic_set_list_get_basic_set(list, i);
9937 0 : set = isl_set_add_basic_set(set, bset);
9938 : }
9939 :
9940 0 : isl_basic_set_list_free(list);
9941 0 : return set;
9942 : error:
9943 0 : isl_basic_set_list_free(list);
9944 0 : return NULL;
9945 : }
9946 :
9947 : /* Return the union of the elements in the non-empty list "list".
9948 : * All elements are assumed to live in the same space.
9949 : */
9950 0 : __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9951 : {
9952 : int i, n;
9953 : isl_set *set;
9954 :
9955 0 : if (!list)
9956 0 : return NULL;
9957 0 : n = isl_set_list_n_set(list);
9958 0 : if (n < 1)
9959 0 : isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9960 : "expecting non-empty list", goto error);
9961 :
9962 0 : set = isl_set_list_get_set(list, 0);
9963 0 : for (i = 1; i < n; ++i) {
9964 : isl_set *set_i;
9965 :
9966 0 : set_i = isl_set_list_get_set(list, i);
9967 0 : set = isl_set_union(set, set_i);
9968 : }
9969 :
9970 0 : isl_set_list_free(list);
9971 0 : return set;
9972 : error:
9973 0 : isl_set_list_free(list);
9974 0 : return NULL;
9975 : }
9976 :
9977 0 : __isl_give isl_basic_map *isl_basic_map_product(
9978 : __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9979 : {
9980 0 : isl_space *dim_result = NULL;
9981 : struct isl_basic_map *bmap;
9982 : unsigned in1, in2, out1, out2, nparam, total, pos;
9983 : struct isl_dim_map *dim_map1, *dim_map2;
9984 :
9985 0 : if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
9986 0 : goto error;
9987 0 : dim_result = isl_space_product(isl_space_copy(bmap1->dim),
9988 : isl_space_copy(bmap2->dim));
9989 :
9990 0 : in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9991 0 : in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9992 0 : out1 = isl_basic_map_dim(bmap1, isl_dim_out);
9993 0 : out2 = isl_basic_map_dim(bmap2, isl_dim_out);
9994 0 : nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9995 :
9996 0 : total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9997 0 : dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9998 0 : dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9999 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10000 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10001 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10002 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10003 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10004 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10005 0 : isl_dim_map_div(dim_map1, bmap1, pos += out2);
10006 0 : isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10007 :
10008 0 : bmap = isl_basic_map_alloc_space(dim_result,
10009 0 : bmap1->n_div + bmap2->n_div,
10010 0 : bmap1->n_eq + bmap2->n_eq,
10011 0 : bmap1->n_ineq + bmap2->n_ineq);
10012 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10013 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10014 0 : bmap = isl_basic_map_simplify(bmap);
10015 0 : return isl_basic_map_finalize(bmap);
10016 : error:
10017 0 : isl_basic_map_free(bmap1);
10018 0 : isl_basic_map_free(bmap2);
10019 0 : return NULL;
10020 : }
10021 :
10022 0 : __isl_give isl_basic_map *isl_basic_map_flat_product(
10023 : __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10024 : {
10025 : isl_basic_map *prod;
10026 :
10027 0 : prod = isl_basic_map_product(bmap1, bmap2);
10028 0 : prod = isl_basic_map_flatten(prod);
10029 0 : return prod;
10030 : }
10031 :
10032 0 : __isl_give isl_basic_set *isl_basic_set_flat_product(
10033 : __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10034 : {
10035 0 : return isl_basic_map_flat_range_product(bset1, bset2);
10036 : }
10037 :
10038 0 : __isl_give isl_basic_map *isl_basic_map_domain_product(
10039 : __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10040 : {
10041 0 : isl_space *space_result = NULL;
10042 : isl_basic_map *bmap;
10043 : unsigned in1, in2, out, nparam, total, pos;
10044 : struct isl_dim_map *dim_map1, *dim_map2;
10045 :
10046 0 : if (!bmap1 || !bmap2)
10047 : goto error;
10048 :
10049 0 : space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
10050 : isl_space_copy(bmap2->dim));
10051 :
10052 0 : in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10053 0 : in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10054 0 : out = isl_basic_map_dim(bmap1, isl_dim_out);
10055 0 : nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10056 :
10057 0 : total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10058 0 : dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10059 0 : dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10060 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10061 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10062 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10063 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10064 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10065 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10066 0 : isl_dim_map_div(dim_map1, bmap1, pos += out);
10067 0 : isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10068 :
10069 0 : bmap = isl_basic_map_alloc_space(space_result,
10070 0 : bmap1->n_div + bmap2->n_div,
10071 0 : bmap1->n_eq + bmap2->n_eq,
10072 0 : bmap1->n_ineq + bmap2->n_ineq);
10073 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10074 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10075 0 : bmap = isl_basic_map_simplify(bmap);
10076 0 : return isl_basic_map_finalize(bmap);
10077 : error:
10078 0 : isl_basic_map_free(bmap1);
10079 0 : isl_basic_map_free(bmap2);
10080 0 : return NULL;
10081 : }
10082 :
10083 0 : __isl_give isl_basic_map *isl_basic_map_range_product(
10084 : __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10085 : {
10086 : isl_bool rational;
10087 0 : isl_space *dim_result = NULL;
10088 : isl_basic_map *bmap;
10089 : unsigned in, out1, out2, nparam, total, pos;
10090 : struct isl_dim_map *dim_map1, *dim_map2;
10091 :
10092 0 : rational = isl_basic_map_is_rational(bmap1);
10093 0 : if (rational >= 0 && rational)
10094 0 : rational = isl_basic_map_is_rational(bmap2);
10095 0 : if (!bmap1 || !bmap2 || rational < 0)
10096 : goto error;
10097 :
10098 0 : if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10099 0 : goto error;
10100 :
10101 0 : dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10102 : isl_space_copy(bmap2->dim));
10103 :
10104 0 : in = isl_basic_map_dim(bmap1, isl_dim_in);
10105 0 : out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10106 0 : out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10107 0 : nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10108 :
10109 0 : total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10110 0 : dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10111 0 : dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10112 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10113 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10114 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10115 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10116 0 : isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10117 0 : isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10118 0 : isl_dim_map_div(dim_map1, bmap1, pos += out2);
10119 0 : isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10120 :
10121 0 : bmap = isl_basic_map_alloc_space(dim_result,
10122 0 : bmap1->n_div + bmap2->n_div,
10123 0 : bmap1->n_eq + bmap2->n_eq,
10124 0 : bmap1->n_ineq + bmap2->n_ineq);
10125 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10126 0 : bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10127 0 : if (rational)
10128 0 : bmap = isl_basic_map_set_rational(bmap);
10129 0 : bmap = isl_basic_map_simplify(bmap);
10130 0 : return isl_basic_map_finalize(bmap);
10131 : error:
10132 0 : isl_basic_map_free(bmap1);
10133 0 : isl_basic_map_free(bmap2);
10134 0 : return NULL;
10135 : }
10136 :
10137 0 : __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10138 : __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10139 : {
10140 : isl_basic_map *prod;
10141 :
10142 0 : prod = isl_basic_map_range_product(bmap1, bmap2);
10143 0 : prod = isl_basic_map_flatten_range(prod);
10144 0 : return prod;
10145 : }
10146 :
10147 : /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10148 : * and collect the results.
10149 : * The result live in the space obtained by calling "space_product"
10150 : * on the spaces of "map1" and "map2".
10151 : * If "remove_duplicates" is set then the result may contain duplicates
10152 : * (even if the inputs do not) and so we try and remove the obvious
10153 : * duplicates.
10154 : */
10155 0 : static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10156 : __isl_take isl_map *map2,
10157 : __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10158 : __isl_take isl_space *right),
10159 : __isl_give isl_basic_map *(*basic_map_product)(
10160 : __isl_take isl_basic_map *left,
10161 : __isl_take isl_basic_map *right),
10162 : int remove_duplicates)
10163 : {
10164 0 : unsigned flags = 0;
10165 : struct isl_map *result;
10166 : int i, j;
10167 : isl_bool m;
10168 :
10169 0 : m = isl_map_has_equal_params(map1, map2);
10170 0 : if (m < 0)
10171 0 : goto error;
10172 0 : if (!m)
10173 0 : isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10174 : "parameters don't match", goto error);
10175 :
10176 0 : if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10177 0 : ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10178 0 : ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10179 :
10180 0 : result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10181 : isl_space_copy(map2->dim)),
10182 0 : map1->n * map2->n, flags);
10183 0 : if (!result)
10184 0 : goto error;
10185 0 : for (i = 0; i < map1->n; ++i)
10186 0 : for (j = 0; j < map2->n; ++j) {
10187 : struct isl_basic_map *part;
10188 0 : part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10189 0 : isl_basic_map_copy(map2->p[j]));
10190 0 : if (isl_basic_map_is_empty(part))
10191 0 : isl_basic_map_free(part);
10192 : else
10193 0 : result = isl_map_add_basic_map(result, part);
10194 0 : if (!result)
10195 0 : goto error;
10196 : }
10197 0 : if (remove_duplicates)
10198 0 : result = isl_map_remove_obvious_duplicates(result);
10199 0 : isl_map_free(map1);
10200 0 : isl_map_free(map2);
10201 0 : return result;
10202 : error:
10203 0 : isl_map_free(map1);
10204 0 : isl_map_free(map2);
10205 0 : return NULL;
10206 : }
10207 :
10208 : /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10209 : */
10210 0 : static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
10211 : __isl_take isl_map *map2)
10212 : {
10213 0 : return map_product(map1, map2, &isl_space_product,
10214 : &isl_basic_map_product, 0);
10215 : }
10216 :
10217 0 : __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10218 : __isl_take isl_map *map2)
10219 : {
10220 0 : return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
10221 : }
10222 :
10223 : /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10224 : */
10225 0 : __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10226 : __isl_take isl_map *map2)
10227 : {
10228 : isl_map *prod;
10229 :
10230 0 : prod = isl_map_product(map1, map2);
10231 0 : prod = isl_map_flatten(prod);
10232 0 : return prod;
10233 : }
10234 :
10235 : /* Given two set A and B, construct its Cartesian product A x B.
10236 : */
10237 0 : struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
10238 : {
10239 0 : return isl_map_range_product(set1, set2);
10240 : }
10241 :
10242 0 : __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10243 : __isl_take isl_set *set2)
10244 : {
10245 0 : return isl_map_flat_range_product(set1, set2);
10246 : }
10247 :
10248 : /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10249 : */
10250 0 : static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
10251 : __isl_take isl_map *map2)
10252 : {
10253 0 : return map_product(map1, map2, &isl_space_domain_product,
10254 : &isl_basic_map_domain_product, 1);
10255 : }
10256 :
10257 : /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10258 : */
10259 0 : static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
10260 : __isl_take isl_map *map2)
10261 : {
10262 0 : return map_product(map1, map2, &isl_space_range_product,
10263 : &isl_basic_map_range_product, 1);
10264 : }
10265 :
10266 0 : __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10267 : __isl_take isl_map *map2)
10268 : {
10269 0 : return isl_map_align_params_map_map_and(map1, map2,
10270 : &map_domain_product_aligned);
10271 : }
10272 :
10273 0 : __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10274 : __isl_take isl_map *map2)
10275 : {
10276 0 : return isl_map_align_params_map_map_and(map1, map2,
10277 : &map_range_product_aligned);
10278 : }
10279 :
10280 : /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10281 : */
10282 0 : __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10283 : {
10284 : isl_space *space;
10285 : int total1, keep1, total2, keep2;
10286 :
10287 0 : if (!map)
10288 0 : return NULL;
10289 0 : if (!isl_space_domain_is_wrapping(map->dim) ||
10290 0 : !isl_space_range_is_wrapping(map->dim))
10291 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
10292 : "not a product", return isl_map_free(map));
10293 :
10294 0 : space = isl_map_get_space(map);
10295 0 : total1 = isl_space_dim(space, isl_dim_in);
10296 0 : total2 = isl_space_dim(space, isl_dim_out);
10297 0 : space = isl_space_factor_domain(space);
10298 0 : keep1 = isl_space_dim(space, isl_dim_in);
10299 0 : keep2 = isl_space_dim(space, isl_dim_out);
10300 0 : map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10301 0 : map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10302 0 : map = isl_map_reset_space(map, space);
10303 :
10304 0 : return map;
10305 : }
10306 :
10307 : /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10308 : */
10309 0 : __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10310 : {
10311 : isl_space *space;
10312 : int total1, keep1, total2, keep2;
10313 :
10314 0 : if (!map)
10315 0 : return NULL;
10316 0 : if (!isl_space_domain_is_wrapping(map->dim) ||
10317 0 : !isl_space_range_is_wrapping(map->dim))
10318 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
10319 : "not a product", return isl_map_free(map));
10320 :
10321 0 : space = isl_map_get_space(map);
10322 0 : total1 = isl_space_dim(space, isl_dim_in);
10323 0 : total2 = isl_space_dim(space, isl_dim_out);
10324 0 : space = isl_space_factor_range(space);
10325 0 : keep1 = isl_space_dim(space, isl_dim_in);
10326 0 : keep2 = isl_space_dim(space, isl_dim_out);
10327 0 : map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10328 0 : map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10329 0 : map = isl_map_reset_space(map, space);
10330 :
10331 0 : return map;
10332 : }
10333 :
10334 : /* Given a map of the form [A -> B] -> C, return the map A -> C.
10335 : */
10336 0 : __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10337 : {
10338 : isl_space *space;
10339 : int total, keep;
10340 :
10341 0 : if (!map)
10342 0 : return NULL;
10343 0 : if (!isl_space_domain_is_wrapping(map->dim))
10344 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
10345 : "domain is not a product", return isl_map_free(map));
10346 :
10347 0 : space = isl_map_get_space(map);
10348 0 : total = isl_space_dim(space, isl_dim_in);
10349 0 : space = isl_space_domain_factor_domain(space);
10350 0 : keep = isl_space_dim(space, isl_dim_in);
10351 0 : map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10352 0 : map = isl_map_reset_space(map, space);
10353 :
10354 0 : return map;
10355 : }
10356 :
10357 : /* Given a map of the form [A -> B] -> C, return the map B -> C.
10358 : */
10359 0 : __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10360 : {
10361 : isl_space *space;
10362 : int total, keep;
10363 :
10364 0 : if (!map)
10365 0 : return NULL;
10366 0 : if (!isl_space_domain_is_wrapping(map->dim))
10367 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
10368 : "domain is not a product", return isl_map_free(map));
10369 :
10370 0 : space = isl_map_get_space(map);
10371 0 : total = isl_space_dim(space, isl_dim_in);
10372 0 : space = isl_space_domain_factor_range(space);
10373 0 : keep = isl_space_dim(space, isl_dim_in);
10374 0 : map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10375 0 : map = isl_map_reset_space(map, space);
10376 :
10377 0 : return map;
10378 : }
10379 :
10380 : /* Given a map A -> [B -> C], extract the map A -> B.
10381 : */
10382 0 : __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10383 : {
10384 : isl_space *space;
10385 : int total, keep;
10386 :
10387 0 : if (!map)
10388 0 : return NULL;
10389 0 : if (!isl_space_range_is_wrapping(map->dim))
10390 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
10391 : "range is not a product", return isl_map_free(map));
10392 :
10393 0 : space = isl_map_get_space(map);
10394 0 : total = isl_space_dim(space, isl_dim_out);
10395 0 : space = isl_space_range_factor_domain(space);
10396 0 : keep = isl_space_dim(space, isl_dim_out);
10397 0 : map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10398 0 : map = isl_map_reset_space(map, space);
10399 :
10400 0 : return map;
10401 : }
10402 :
10403 : /* Given a map A -> [B -> C], extract the map A -> C.
10404 : */
10405 0 : __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10406 : {
10407 : isl_space *space;
10408 : int total, keep;
10409 :
10410 0 : if (!map)
10411 0 : return NULL;
10412 0 : if (!isl_space_range_is_wrapping(map->dim))
10413 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
10414 : "range is not a product", return isl_map_free(map));
10415 :
10416 0 : space = isl_map_get_space(map);
10417 0 : total = isl_space_dim(space, isl_dim_out);
10418 0 : space = isl_space_range_factor_range(space);
10419 0 : keep = isl_space_dim(space, isl_dim_out);
10420 0 : map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10421 0 : map = isl_map_reset_space(map, space);
10422 :
10423 0 : return map;
10424 : }
10425 :
10426 : /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10427 : */
10428 0 : __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10429 : __isl_take isl_map *map2)
10430 : {
10431 : isl_map *prod;
10432 :
10433 0 : prod = isl_map_domain_product(map1, map2);
10434 0 : prod = isl_map_flatten_domain(prod);
10435 0 : return prod;
10436 : }
10437 :
10438 : /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10439 : */
10440 0 : __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10441 : __isl_take isl_map *map2)
10442 : {
10443 : isl_map *prod;
10444 :
10445 0 : prod = isl_map_range_product(map1, map2);
10446 0 : prod = isl_map_flatten_range(prod);
10447 0 : return prod;
10448 : }
10449 :
10450 2898920016 : uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10451 : {
10452 : int i;
10453 2898920016 : uint32_t hash = isl_hash_init();
10454 : unsigned total;
10455 :
10456 2898920016 : if (!bmap)
10457 0 : return 0;
10458 2898920016 : bmap = isl_basic_map_copy(bmap);
10459 2898920016 : bmap = isl_basic_map_normalize(bmap);
10460 2898920016 : if (!bmap)
10461 0 : return 0;
10462 2898920016 : total = isl_basic_map_total_dim(bmap);
10463 2898920016 : isl_hash_byte(hash, bmap->n_eq & 0xFF);
10464 7457623895 : for (i = 0; i < bmap->n_eq; ++i) {
10465 : uint32_t c_hash;
10466 4558703879 : c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
10467 4558703879 : isl_hash_hash(hash, c_hash);
10468 : }
10469 2898920016 : isl_hash_byte(hash, bmap->n_ineq & 0xFF);
10470 2898920016 : for (i = 0; i < bmap->n_ineq; ++i) {
10471 : uint32_t c_hash;
10472 0 : c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
10473 0 : isl_hash_hash(hash, c_hash);
10474 : }
10475 2898920016 : isl_hash_byte(hash, bmap->n_div & 0xFF);
10476 2898920016 : for (i = 0; i < bmap->n_div; ++i) {
10477 : uint32_t c_hash;
10478 0 : if (isl_int_is_zero(bmap->div[i][0]))
10479 0 : continue;
10480 0 : isl_hash_byte(hash, i & 0xFF);
10481 0 : c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
10482 0 : isl_hash_hash(hash, c_hash);
10483 : }
10484 2898920016 : isl_basic_map_free(bmap);
10485 2898920016 : return hash;
10486 : }
10487 :
10488 0 : uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
10489 : {
10490 0 : return isl_basic_map_get_hash(bset_to_bmap(bset));
10491 : }
10492 :
10493 0 : uint32_t isl_map_get_hash(__isl_keep isl_map *map)
10494 : {
10495 : int i;
10496 : uint32_t hash;
10497 :
10498 0 : if (!map)
10499 0 : return 0;
10500 0 : map = isl_map_copy(map);
10501 0 : map = isl_map_normalize(map);
10502 0 : if (!map)
10503 0 : return 0;
10504 :
10505 0 : hash = isl_hash_init();
10506 0 : for (i = 0; i < map->n; ++i) {
10507 : uint32_t bmap_hash;
10508 0 : bmap_hash = isl_basic_map_get_hash(map->p[i]);
10509 0 : isl_hash_hash(hash, bmap_hash);
10510 : }
10511 :
10512 0 : isl_map_free(map);
10513 :
10514 0 : return hash;
10515 : }
10516 :
10517 0 : uint32_t isl_set_get_hash(__isl_keep isl_set *set)
10518 : {
10519 0 : return isl_map_get_hash(set_to_map(set));
10520 : }
10521 :
10522 : /* Return the number of basic maps in the (current) representation of "map".
10523 : */
10524 0 : int isl_map_n_basic_map(__isl_keep isl_map *map)
10525 : {
10526 0 : return map ? map->n : 0;
10527 : }
10528 :
10529 112944 : int isl_set_n_basic_set(__isl_keep isl_set *set)
10530 : {
10531 112944 : return set ? set->n : 0;
10532 : }
10533 :
10534 0 : isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
10535 : isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
10536 : {
10537 : int i;
10538 :
10539 0 : if (!map)
10540 0 : return isl_stat_error;
10541 :
10542 0 : for (i = 0; i < map->n; ++i)
10543 0 : if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
10544 0 : return isl_stat_error;
10545 :
10546 0 : return isl_stat_ok;
10547 : }
10548 :
10549 112944 : isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10550 : isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10551 : {
10552 : int i;
10553 :
10554 112944 : if (!set)
10555 0 : return isl_stat_error;
10556 :
10557 225888 : for (i = 0; i < set->n; ++i)
10558 112944 : if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10559 0 : return isl_stat_error;
10560 :
10561 112944 : return isl_stat_ok;
10562 : }
10563 :
10564 : /* Return a list of basic sets, the union of which is equal to "set".
10565 : */
10566 0 : __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10567 : __isl_keep isl_set *set)
10568 : {
10569 : int i;
10570 : isl_basic_set_list *list;
10571 :
10572 0 : if (!set)
10573 0 : return NULL;
10574 :
10575 0 : list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10576 0 : for (i = 0; i < set->n; ++i) {
10577 : isl_basic_set *bset;
10578 :
10579 0 : bset = isl_basic_set_copy(set->p[i]);
10580 0 : list = isl_basic_set_list_add(list, bset);
10581 : }
10582 :
10583 0 : return list;
10584 : }
10585 :
10586 0 : __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10587 : {
10588 : isl_space *dim;
10589 :
10590 0 : if (!bset)
10591 0 : return NULL;
10592 :
10593 0 : bset = isl_basic_set_cow(bset);
10594 0 : if (!bset)
10595 0 : return NULL;
10596 :
10597 0 : dim = isl_basic_set_get_space(bset);
10598 0 : dim = isl_space_lift(dim, bset->n_div);
10599 0 : if (!dim)
10600 0 : goto error;
10601 0 : isl_space_free(bset->dim);
10602 0 : bset->dim = dim;
10603 0 : bset->extra -= bset->n_div;
10604 0 : bset->n_div = 0;
10605 :
10606 0 : bset = isl_basic_set_finalize(bset);
10607 :
10608 0 : return bset;
10609 : error:
10610 0 : isl_basic_set_free(bset);
10611 0 : return NULL;
10612 : }
10613 :
10614 0 : __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10615 : {
10616 : int i;
10617 : isl_space *dim;
10618 : unsigned n_div;
10619 :
10620 0 : set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
10621 :
10622 0 : if (!set)
10623 0 : return NULL;
10624 :
10625 0 : set = isl_set_cow(set);
10626 0 : if (!set)
10627 0 : return NULL;
10628 :
10629 0 : n_div = set->p[0]->n_div;
10630 0 : dim = isl_set_get_space(set);
10631 0 : dim = isl_space_lift(dim, n_div);
10632 0 : if (!dim)
10633 0 : goto error;
10634 0 : isl_space_free(set->dim);
10635 0 : set->dim = dim;
10636 :
10637 0 : for (i = 0; i < set->n; ++i) {
10638 0 : set->p[i] = isl_basic_set_lift(set->p[i]);
10639 0 : if (!set->p[i])
10640 0 : goto error;
10641 : }
10642 :
10643 0 : return set;
10644 : error:
10645 0 : isl_set_free(set);
10646 0 : return NULL;
10647 : }
10648 :
10649 0 : int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10650 : {
10651 : unsigned dim;
10652 0 : int size = 0;
10653 :
10654 0 : if (!bset)
10655 0 : return -1;
10656 :
10657 0 : dim = isl_basic_set_total_dim(bset);
10658 0 : size += bset->n_eq * (1 + dim);
10659 0 : size += bset->n_ineq * (1 + dim);
10660 0 : size += bset->n_div * (2 + dim);
10661 :
10662 0 : return size;
10663 : }
10664 :
10665 0 : int isl_set_size(__isl_keep isl_set *set)
10666 : {
10667 : int i;
10668 0 : int size = 0;
10669 :
10670 0 : if (!set)
10671 0 : return -1;
10672 :
10673 0 : for (i = 0; i < set->n; ++i)
10674 0 : size += isl_basic_set_size(set->p[i]);
10675 :
10676 0 : return size;
10677 : }
10678 :
10679 : /* Check if there is any lower bound (if lower == 0) and/or upper
10680 : * bound (if upper == 0) on the specified dim.
10681 : */
10682 0 : static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10683 : enum isl_dim_type type, unsigned pos, int lower, int upper)
10684 : {
10685 : int i;
10686 :
10687 0 : if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10688 0 : return isl_bool_error;
10689 :
10690 0 : pos += isl_basic_map_offset(bmap, type);
10691 :
10692 0 : for (i = 0; i < bmap->n_div; ++i) {
10693 0 : if (isl_int_is_zero(bmap->div[i][0]))
10694 0 : continue;
10695 0 : if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10696 0 : return isl_bool_true;
10697 : }
10698 :
10699 0 : for (i = 0; i < bmap->n_eq; ++i)
10700 0 : if (!isl_int_is_zero(bmap->eq[i][pos]))
10701 0 : return isl_bool_true;
10702 :
10703 0 : for (i = 0; i < bmap->n_ineq; ++i) {
10704 0 : int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10705 0 : if (sgn > 0)
10706 0 : lower = 1;
10707 0 : if (sgn < 0)
10708 0 : upper = 1;
10709 : }
10710 :
10711 0 : return lower && upper;
10712 : }
10713 :
10714 0 : isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10715 : enum isl_dim_type type, unsigned pos)
10716 : {
10717 0 : return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10718 : }
10719 :
10720 0 : isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10721 : enum isl_dim_type type, unsigned pos)
10722 : {
10723 0 : return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10724 : }
10725 :
10726 0 : isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10727 : enum isl_dim_type type, unsigned pos)
10728 : {
10729 0 : return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10730 : }
10731 :
10732 0 : isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10733 : enum isl_dim_type type, unsigned pos)
10734 : {
10735 : int i;
10736 :
10737 0 : if (!map)
10738 0 : return isl_bool_error;
10739 :
10740 0 : for (i = 0; i < map->n; ++i) {
10741 : isl_bool bounded;
10742 0 : bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10743 0 : if (bounded < 0 || !bounded)
10744 0 : return bounded;
10745 : }
10746 :
10747 0 : return isl_bool_true;
10748 : }
10749 :
10750 : /* Return true if the specified dim is involved in both an upper bound
10751 : * and a lower bound.
10752 : */
10753 0 : isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10754 : enum isl_dim_type type, unsigned pos)
10755 : {
10756 0 : return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10757 : }
10758 :
10759 : /* Does "map" have a bound (according to "fn") for any of its basic maps?
10760 : */
10761 0 : static isl_bool has_any_bound(__isl_keep isl_map *map,
10762 : enum isl_dim_type type, unsigned pos,
10763 : isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10764 : enum isl_dim_type type, unsigned pos))
10765 : {
10766 : int i;
10767 :
10768 0 : if (!map)
10769 0 : return isl_bool_error;
10770 :
10771 0 : for (i = 0; i < map->n; ++i) {
10772 : isl_bool bounded;
10773 0 : bounded = fn(map->p[i], type, pos);
10774 0 : if (bounded < 0 || bounded)
10775 0 : return bounded;
10776 : }
10777 :
10778 0 : return isl_bool_false;
10779 : }
10780 :
10781 : /* Return 1 if the specified dim is involved in any lower bound.
10782 : */
10783 0 : isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10784 : enum isl_dim_type type, unsigned pos)
10785 : {
10786 0 : return has_any_bound(set, type, pos,
10787 : &isl_basic_map_dim_has_lower_bound);
10788 : }
10789 :
10790 : /* Return 1 if the specified dim is involved in any upper bound.
10791 : */
10792 0 : isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10793 : enum isl_dim_type type, unsigned pos)
10794 : {
10795 0 : return has_any_bound(set, type, pos,
10796 : &isl_basic_map_dim_has_upper_bound);
10797 : }
10798 :
10799 : /* Does "map" have a bound (according to "fn") for all of its basic maps?
10800 : */
10801 0 : static isl_bool has_bound(__isl_keep isl_map *map,
10802 : enum isl_dim_type type, unsigned pos,
10803 : isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10804 : enum isl_dim_type type, unsigned pos))
10805 : {
10806 : int i;
10807 :
10808 0 : if (!map)
10809 0 : return isl_bool_error;
10810 :
10811 0 : for (i = 0; i < map->n; ++i) {
10812 : isl_bool bounded;
10813 0 : bounded = fn(map->p[i], type, pos);
10814 0 : if (bounded < 0 || !bounded)
10815 0 : return bounded;
10816 : }
10817 :
10818 0 : return isl_bool_true;
10819 : }
10820 :
10821 : /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10822 : */
10823 0 : isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10824 : enum isl_dim_type type, unsigned pos)
10825 : {
10826 0 : return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10827 : }
10828 :
10829 : /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10830 : */
10831 0 : isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10832 : enum isl_dim_type type, unsigned pos)
10833 : {
10834 0 : return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10835 : }
10836 :
10837 : /* For each of the "n" variables starting at "first", determine
10838 : * the sign of the variable and put the results in the first "n"
10839 : * elements of the array "signs".
10840 : * Sign
10841 : * 1 means that the variable is non-negative
10842 : * -1 means that the variable is non-positive
10843 : * 0 means the variable attains both positive and negative values.
10844 : */
10845 0 : isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10846 : unsigned first, unsigned n, int *signs)
10847 : {
10848 0 : isl_vec *bound = NULL;
10849 0 : struct isl_tab *tab = NULL;
10850 : struct isl_tab_undo *snap;
10851 : int i;
10852 :
10853 0 : if (!bset || !signs)
10854 0 : return isl_stat_error;
10855 :
10856 0 : bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10857 0 : tab = isl_tab_from_basic_set(bset, 0);
10858 0 : if (!bound || !tab)
10859 : goto error;
10860 :
10861 0 : isl_seq_clr(bound->el, bound->size);
10862 0 : isl_int_set_si(bound->el[0], -1);
10863 :
10864 0 : snap = isl_tab_snap(tab);
10865 0 : for (i = 0; i < n; ++i) {
10866 : int empty;
10867 :
10868 0 : isl_int_set_si(bound->el[1 + first + i], -1);
10869 0 : if (isl_tab_add_ineq(tab, bound->el) < 0)
10870 0 : goto error;
10871 0 : empty = tab->empty;
10872 0 : isl_int_set_si(bound->el[1 + first + i], 0);
10873 0 : if (isl_tab_rollback(tab, snap) < 0)
10874 0 : goto error;
10875 :
10876 0 : if (empty) {
10877 0 : signs[i] = 1;
10878 0 : continue;
10879 : }
10880 :
10881 0 : isl_int_set_si(bound->el[1 + first + i], 1);
10882 0 : if (isl_tab_add_ineq(tab, bound->el) < 0)
10883 0 : goto error;
10884 0 : empty = tab->empty;
10885 0 : isl_int_set_si(bound->el[1 + first + i], 0);
10886 0 : if (isl_tab_rollback(tab, snap) < 0)
10887 0 : goto error;
10888 :
10889 0 : signs[i] = empty ? -1 : 0;
10890 : }
10891 :
10892 0 : isl_tab_free(tab);
10893 0 : isl_vec_free(bound);
10894 0 : return isl_stat_ok;
10895 : error:
10896 0 : isl_tab_free(tab);
10897 0 : isl_vec_free(bound);
10898 0 : return isl_stat_error;
10899 : }
10900 :
10901 0 : isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10902 : enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10903 : {
10904 0 : if (!bset || !signs)
10905 0 : return isl_stat_error;
10906 0 : isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
10907 : return isl_stat_error);
10908 :
10909 0 : first += pos(bset->dim, type) - 1;
10910 0 : return isl_basic_set_vars_get_sign(bset, first, n, signs);
10911 : }
10912 :
10913 : /* Is it possible for the integer division "div" to depend (possibly
10914 : * indirectly) on any output dimensions?
10915 : *
10916 : * If the div is undefined, then we conservatively assume that it
10917 : * may depend on them.
10918 : * Otherwise, we check if it actually depends on them or on any integer
10919 : * divisions that may depend on them.
10920 : */
10921 0 : static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10922 : {
10923 : int i;
10924 : unsigned n_out, o_out;
10925 : unsigned n_div, o_div;
10926 :
10927 0 : if (isl_int_is_zero(bmap->div[div][0]))
10928 0 : return isl_bool_true;
10929 :
10930 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
10931 0 : o_out = isl_basic_map_offset(bmap, isl_dim_out);
10932 :
10933 0 : if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10934 0 : return isl_bool_true;
10935 :
10936 0 : n_div = isl_basic_map_dim(bmap, isl_dim_div);
10937 0 : o_div = isl_basic_map_offset(bmap, isl_dim_div);
10938 :
10939 0 : for (i = 0; i < n_div; ++i) {
10940 : isl_bool may_involve;
10941 :
10942 0 : if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10943 0 : continue;
10944 0 : may_involve = div_may_involve_output(bmap, i);
10945 0 : if (may_involve < 0 || may_involve)
10946 0 : return may_involve;
10947 : }
10948 :
10949 0 : return isl_bool_false;
10950 : }
10951 :
10952 : /* Return the first integer division of "bmap" in the range
10953 : * [first, first + n[ that may depend on any output dimensions and
10954 : * that has a non-zero coefficient in "c" (where the first coefficient
10955 : * in "c" corresponds to integer division "first").
10956 : */
10957 0 : static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10958 : isl_int *c, int first, int n)
10959 : {
10960 : int k;
10961 :
10962 0 : if (!bmap)
10963 0 : return -1;
10964 :
10965 0 : for (k = first; k < first + n; ++k) {
10966 : isl_bool may_involve;
10967 :
10968 0 : if (isl_int_is_zero(c[k]))
10969 0 : continue;
10970 0 : may_involve = div_may_involve_output(bmap, k);
10971 0 : if (may_involve < 0)
10972 0 : return -1;
10973 0 : if (may_involve)
10974 0 : return k;
10975 : }
10976 :
10977 0 : return first + n;
10978 : }
10979 :
10980 : /* Look for a pair of inequality constraints in "bmap" of the form
10981 : *
10982 : * -l + i >= 0 or i >= l
10983 : * and
10984 : * n + l - i >= 0 or i <= l + n
10985 : *
10986 : * with n < "m" and i the output dimension at position "pos".
10987 : * (Note that n >= 0 as otherwise the two constraints would conflict.)
10988 : * Furthermore, "l" is only allowed to involve parameters, input dimensions
10989 : * and earlier output dimensions, as well as integer divisions that do
10990 : * not involve any of the output dimensions.
10991 : *
10992 : * Return the index of the first inequality constraint or bmap->n_ineq
10993 : * if no such pair can be found.
10994 : */
10995 0 : static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10996 : int pos, isl_int m)
10997 : {
10998 : int i, j;
10999 : isl_ctx *ctx;
11000 : unsigned total;
11001 : unsigned n_div, o_div;
11002 : unsigned n_out, o_out;
11003 : int less;
11004 :
11005 0 : if (!bmap)
11006 0 : return -1;
11007 :
11008 0 : ctx = isl_basic_map_get_ctx(bmap);
11009 0 : total = isl_basic_map_total_dim(bmap);
11010 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
11011 0 : o_out = isl_basic_map_offset(bmap, isl_dim_out);
11012 0 : n_div = isl_basic_map_dim(bmap, isl_dim_div);
11013 0 : o_div = isl_basic_map_offset(bmap, isl_dim_div);
11014 0 : for (i = 0; i < bmap->n_ineq; ++i) {
11015 0 : if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
11016 0 : continue;
11017 0 : if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
11018 0 : n_out - (pos + 1)) != -1)
11019 0 : continue;
11020 0 : if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11021 0 : 0, n_div) < n_div)
11022 0 : continue;
11023 0 : for (j = i + 1; j < bmap->n_ineq; ++j) {
11024 0 : if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11025 : ctx->one))
11026 0 : continue;
11027 0 : if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11028 0 : bmap->ineq[j] + 1, total))
11029 0 : continue;
11030 0 : break;
11031 : }
11032 0 : if (j >= bmap->n_ineq)
11033 0 : continue;
11034 0 : isl_int_add(bmap->ineq[i][0],
11035 : bmap->ineq[i][0], bmap->ineq[j][0]);
11036 0 : less = isl_int_abs_lt(bmap->ineq[i][0], m);
11037 0 : isl_int_sub(bmap->ineq[i][0],
11038 : bmap->ineq[i][0], bmap->ineq[j][0]);
11039 0 : if (!less)
11040 0 : continue;
11041 0 : if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11042 0 : return i;
11043 : else
11044 0 : return j;
11045 : }
11046 :
11047 0 : return bmap->n_ineq;
11048 : }
11049 :
11050 : /* Return the index of the equality of "bmap" that defines
11051 : * the output dimension "pos" in terms of earlier dimensions.
11052 : * The equality may also involve integer divisions, as long
11053 : * as those integer divisions are defined in terms of
11054 : * parameters or input dimensions.
11055 : * In this case, *div is set to the number of integer divisions and
11056 : * *ineq is set to the number of inequality constraints (provided
11057 : * div and ineq are not NULL).
11058 : *
11059 : * The equality may also involve a single integer division involving
11060 : * the output dimensions (typically only output dimension "pos") as
11061 : * long as the coefficient of output dimension "pos" is 1 or -1 and
11062 : * there is a pair of constraints i >= l and i <= l + n, with i referring
11063 : * to output dimension "pos", l an expression involving only earlier
11064 : * dimensions and n smaller than the coefficient of the integer division
11065 : * in the equality. In this case, the output dimension can be defined
11066 : * in terms of a modulo expression that does not involve the integer division.
11067 : * *div is then set to this single integer division and
11068 : * *ineq is set to the index of constraint i >= l.
11069 : *
11070 : * Return bmap->n_eq if there is no such equality.
11071 : * Return -1 on error.
11072 : */
11073 0 : int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11074 : int pos, int *div, int *ineq)
11075 : {
11076 : int j, k, l;
11077 : unsigned n_out, o_out;
11078 : unsigned n_div, o_div;
11079 :
11080 0 : if (!bmap)
11081 0 : return -1;
11082 :
11083 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
11084 0 : o_out = isl_basic_map_offset(bmap, isl_dim_out);
11085 0 : n_div = isl_basic_map_dim(bmap, isl_dim_div);
11086 0 : o_div = isl_basic_map_offset(bmap, isl_dim_div);
11087 :
11088 0 : if (ineq)
11089 0 : *ineq = bmap->n_ineq;
11090 0 : if (div)
11091 0 : *div = n_div;
11092 0 : for (j = 0; j < bmap->n_eq; ++j) {
11093 0 : if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11094 0 : continue;
11095 0 : if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11096 0 : n_out - (pos + 1)) != -1)
11097 0 : continue;
11098 0 : k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11099 : 0, n_div);
11100 0 : if (k >= n_div)
11101 0 : return j;
11102 0 : if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11103 0 : !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11104 0 : continue;
11105 0 : if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11106 0 : k + 1, n_div - (k+1)) < n_div)
11107 0 : continue;
11108 0 : l = find_modulo_constraint_pair(bmap, pos,
11109 0 : bmap->eq[j][o_div + k]);
11110 0 : if (l < 0)
11111 0 : return -1;
11112 0 : if (l >= bmap->n_ineq)
11113 0 : continue;
11114 0 : if (div)
11115 0 : *div = k;
11116 0 : if (ineq)
11117 0 : *ineq = l;
11118 0 : return j;
11119 : }
11120 :
11121 0 : return bmap->n_eq;
11122 : }
11123 :
11124 : /* Check if the given basic map is obviously single-valued.
11125 : * In particular, for each output dimension, check that there is
11126 : * an equality that defines the output dimension in terms of
11127 : * earlier dimensions.
11128 : */
11129 0 : isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11130 : {
11131 : int i;
11132 : unsigned n_out;
11133 :
11134 0 : if (!bmap)
11135 0 : return isl_bool_error;
11136 :
11137 0 : n_out = isl_basic_map_dim(bmap, isl_dim_out);
11138 :
11139 0 : for (i = 0; i < n_out; ++i) {
11140 : int eq;
11141 :
11142 0 : eq = isl_basic_map_output_defining_equality(bmap, i,
11143 : NULL, NULL);
11144 0 : if (eq < 0)
11145 0 : return isl_bool_error;
11146 0 : if (eq >= bmap->n_eq)
11147 0 : return isl_bool_false;
11148 : }
11149 :
11150 0 : return isl_bool_true;
11151 : }
11152 :
11153 : /* Check if the given basic map is single-valued.
11154 : * We simply compute
11155 : *
11156 : * M \circ M^-1
11157 : *
11158 : * and check if the result is a subset of the identity mapping.
11159 : */
11160 0 : isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11161 : {
11162 : isl_space *space;
11163 : isl_basic_map *test;
11164 : isl_basic_map *id;
11165 : isl_bool sv;
11166 :
11167 0 : sv = isl_basic_map_plain_is_single_valued(bmap);
11168 0 : if (sv < 0 || sv)
11169 0 : return sv;
11170 :
11171 0 : test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11172 0 : test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11173 :
11174 0 : space = isl_basic_map_get_space(bmap);
11175 0 : space = isl_space_map_from_set(isl_space_range(space));
11176 0 : id = isl_basic_map_identity(space);
11177 :
11178 0 : sv = isl_basic_map_is_subset(test, id);
11179 :
11180 0 : isl_basic_map_free(test);
11181 0 : isl_basic_map_free(id);
11182 :
11183 0 : return sv;
11184 : }
11185 :
11186 : /* Check if the given map is obviously single-valued.
11187 : */
11188 0 : isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11189 : {
11190 0 : if (!map)
11191 0 : return isl_bool_error;
11192 0 : if (map->n == 0)
11193 0 : return isl_bool_true;
11194 0 : if (map->n >= 2)
11195 0 : return isl_bool_false;
11196 :
11197 0 : return isl_basic_map_plain_is_single_valued(map->p[0]);
11198 : }
11199 :
11200 : /* Check if the given map is single-valued.
11201 : * We simply compute
11202 : *
11203 : * M \circ M^-1
11204 : *
11205 : * and check if the result is a subset of the identity mapping.
11206 : */
11207 0 : isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11208 : {
11209 : isl_space *dim;
11210 : isl_map *test;
11211 : isl_map *id;
11212 : isl_bool sv;
11213 :
11214 0 : sv = isl_map_plain_is_single_valued(map);
11215 0 : if (sv < 0 || sv)
11216 0 : return sv;
11217 :
11218 0 : test = isl_map_reverse(isl_map_copy(map));
11219 0 : test = isl_map_apply_range(test, isl_map_copy(map));
11220 :
11221 0 : dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11222 0 : id = isl_map_identity(dim);
11223 :
11224 0 : sv = isl_map_is_subset(test, id);
11225 :
11226 0 : isl_map_free(test);
11227 0 : isl_map_free(id);
11228 :
11229 0 : return sv;
11230 : }
11231 :
11232 0 : isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11233 : {
11234 : isl_bool in;
11235 :
11236 0 : map = isl_map_copy(map);
11237 0 : map = isl_map_reverse(map);
11238 0 : in = isl_map_is_single_valued(map);
11239 0 : isl_map_free(map);
11240 :
11241 0 : return in;
11242 : }
11243 :
11244 : /* Check if the given map is obviously injective.
11245 : */
11246 0 : isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11247 : {
11248 : isl_bool in;
11249 :
11250 0 : map = isl_map_copy(map);
11251 0 : map = isl_map_reverse(map);
11252 0 : in = isl_map_plain_is_single_valued(map);
11253 0 : isl_map_free(map);
11254 :
11255 0 : return in;
11256 : }
11257 :
11258 0 : isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11259 : {
11260 : isl_bool sv;
11261 :
11262 0 : sv = isl_map_is_single_valued(map);
11263 0 : if (sv < 0 || !sv)
11264 0 : return sv;
11265 :
11266 0 : return isl_map_is_injective(map);
11267 : }
11268 :
11269 0 : isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11270 : {
11271 0 : return isl_map_is_single_valued(set_to_map(set));
11272 : }
11273 :
11274 : /* Does "map" only map elements to themselves?
11275 : *
11276 : * If the domain and range spaces are different, then "map"
11277 : * is considered not to be an identity relation, even if it is empty.
11278 : * Otherwise, construct the maximal identity relation and
11279 : * check whether "map" is a subset of this relation.
11280 : */
11281 0 : isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11282 : {
11283 : isl_space *space;
11284 : isl_map *id;
11285 : isl_bool equal, is_identity;
11286 :
11287 0 : space = isl_map_get_space(map);
11288 0 : equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
11289 0 : isl_space_free(space);
11290 0 : if (equal < 0 || !equal)
11291 0 : return equal;
11292 :
11293 0 : id = isl_map_identity(isl_map_get_space(map));
11294 0 : is_identity = isl_map_is_subset(map, id);
11295 0 : isl_map_free(id);
11296 :
11297 0 : return is_identity;
11298 : }
11299 :
11300 0 : int isl_map_is_translation(__isl_keep isl_map *map)
11301 : {
11302 : int ok;
11303 : isl_set *delta;
11304 :
11305 0 : delta = isl_map_deltas(isl_map_copy(map));
11306 0 : ok = isl_set_is_singleton(delta);
11307 0 : isl_set_free(delta);
11308 :
11309 0 : return ok;
11310 : }
11311 :
11312 0 : static int unique(isl_int *p, unsigned pos, unsigned len)
11313 : {
11314 0 : if (isl_seq_first_non_zero(p, pos) != -1)
11315 0 : return 0;
11316 0 : if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11317 0 : return 0;
11318 0 : return 1;
11319 : }
11320 :
11321 0 : isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11322 : {
11323 : int i, j;
11324 : unsigned nvar;
11325 : unsigned ovar;
11326 :
11327 0 : if (!bset)
11328 0 : return isl_bool_error;
11329 :
11330 0 : if (isl_basic_set_dim(bset, isl_dim_div) != 0)
11331 0 : return isl_bool_false;
11332 :
11333 0 : nvar = isl_basic_set_dim(bset, isl_dim_set);
11334 0 : ovar = isl_space_offset(bset->dim, isl_dim_set);
11335 0 : for (j = 0; j < nvar; ++j) {
11336 0 : int lower = 0, upper = 0;
11337 0 : for (i = 0; i < bset->n_eq; ++i) {
11338 0 : if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11339 0 : continue;
11340 0 : if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11341 0 : return isl_bool_false;
11342 0 : break;
11343 : }
11344 0 : if (i < bset->n_eq)
11345 0 : continue;
11346 0 : for (i = 0; i < bset->n_ineq; ++i) {
11347 0 : if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11348 0 : continue;
11349 0 : if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11350 0 : return isl_bool_false;
11351 0 : if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11352 0 : lower = 1;
11353 : else
11354 0 : upper = 1;
11355 : }
11356 0 : if (!lower || !upper)
11357 0 : return isl_bool_false;
11358 : }
11359 :
11360 0 : return isl_bool_true;
11361 : }
11362 :
11363 0 : isl_bool isl_set_is_box(__isl_keep isl_set *set)
11364 : {
11365 0 : if (!set)
11366 0 : return isl_bool_error;
11367 0 : if (set->n != 1)
11368 0 : return isl_bool_false;
11369 :
11370 0 : return isl_basic_set_is_box(set->p[0]);
11371 : }
11372 :
11373 0 : isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11374 : {
11375 0 : if (!bset)
11376 0 : return isl_bool_error;
11377 :
11378 0 : return isl_space_is_wrapping(bset->dim);
11379 : }
11380 :
11381 0 : isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11382 : {
11383 0 : if (!set)
11384 0 : return isl_bool_error;
11385 :
11386 0 : return isl_space_is_wrapping(set->dim);
11387 : }
11388 :
11389 : /* Modify the space of "map" through a call to "change".
11390 : * If "can_change" is set (not NULL), then first call it to check
11391 : * if the modification is allowed, printing the error message "cannot_change"
11392 : * if it is not.
11393 : */
11394 0 : static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11395 : isl_bool (*can_change)(__isl_keep isl_map *map),
11396 : const char *cannot_change,
11397 : __isl_give isl_space *(*change)(__isl_take isl_space *space))
11398 : {
11399 : isl_bool ok;
11400 : isl_space *space;
11401 :
11402 0 : if (!map)
11403 0 : return NULL;
11404 :
11405 0 : ok = can_change ? can_change(map) : isl_bool_true;
11406 0 : if (ok < 0)
11407 0 : return isl_map_free(map);
11408 0 : if (!ok)
11409 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11410 : return isl_map_free(map));
11411 :
11412 0 : space = change(isl_map_get_space(map));
11413 0 : map = isl_map_reset_space(map, space);
11414 :
11415 0 : return map;
11416 : }
11417 :
11418 : /* Is the domain of "map" a wrapped relation?
11419 : */
11420 0 : isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11421 : {
11422 0 : if (!map)
11423 0 : return isl_bool_error;
11424 :
11425 0 : return isl_space_domain_is_wrapping(map->dim);
11426 : }
11427 :
11428 : /* Does "map" have a wrapped relation in both domain and range?
11429 : */
11430 0 : isl_bool isl_map_is_product(__isl_keep isl_map *map)
11431 : {
11432 0 : return isl_space_is_product(isl_map_peek_space(map));
11433 : }
11434 :
11435 : /* Is the range of "map" a wrapped relation?
11436 : */
11437 0 : isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
11438 : {
11439 0 : if (!map)
11440 0 : return isl_bool_error;
11441 :
11442 0 : return isl_space_range_is_wrapping(map->dim);
11443 : }
11444 :
11445 0 : __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
11446 : {
11447 0 : bmap = isl_basic_map_cow(bmap);
11448 0 : if (!bmap)
11449 0 : return NULL;
11450 :
11451 0 : bmap->dim = isl_space_wrap(bmap->dim);
11452 0 : if (!bmap->dim)
11453 0 : goto error;
11454 :
11455 0 : bmap = isl_basic_map_finalize(bmap);
11456 :
11457 0 : return bset_from_bmap(bmap);
11458 : error:
11459 0 : isl_basic_map_free(bmap);
11460 0 : return NULL;
11461 : }
11462 :
11463 : /* Given a map A -> B, return the set (A -> B).
11464 : */
11465 0 : __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
11466 : {
11467 0 : return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
11468 : }
11469 :
11470 0 : __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
11471 : {
11472 0 : bset = isl_basic_set_cow(bset);
11473 0 : if (!bset)
11474 0 : return NULL;
11475 :
11476 0 : bset->dim = isl_space_unwrap(bset->dim);
11477 0 : if (!bset->dim)
11478 0 : goto error;
11479 :
11480 0 : bset = isl_basic_set_finalize(bset);
11481 :
11482 0 : return bset_to_bmap(bset);
11483 : error:
11484 0 : isl_basic_set_free(bset);
11485 0 : return NULL;
11486 : }
11487 :
11488 : /* Given a set (A -> B), return the map A -> B.
11489 : * Error out if "set" is not of the form (A -> B).
11490 : */
11491 0 : __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
11492 : {
11493 0 : return isl_map_change_space(set, &isl_set_is_wrapping,
11494 : "not a wrapping set", &isl_space_unwrap);
11495 : }
11496 :
11497 0 : __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
11498 : enum isl_dim_type type)
11499 : {
11500 0 : if (!bmap)
11501 0 : return NULL;
11502 :
11503 0 : if (!isl_space_is_named_or_nested(bmap->dim, type))
11504 0 : return bmap;
11505 :
11506 0 : bmap = isl_basic_map_cow(bmap);
11507 0 : if (!bmap)
11508 0 : return NULL;
11509 :
11510 0 : bmap->dim = isl_space_reset(bmap->dim, type);
11511 0 : if (!bmap->dim)
11512 0 : goto error;
11513 :
11514 0 : bmap = isl_basic_map_finalize(bmap);
11515 :
11516 0 : return bmap;
11517 : error:
11518 0 : isl_basic_map_free(bmap);
11519 0 : return NULL;
11520 : }
11521 :
11522 0 : __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
11523 : enum isl_dim_type type)
11524 : {
11525 : int i;
11526 :
11527 0 : if (!map)
11528 0 : return NULL;
11529 :
11530 0 : if (!isl_space_is_named_or_nested(map->dim, type))
11531 0 : return map;
11532 :
11533 0 : map = isl_map_cow(map);
11534 0 : if (!map)
11535 0 : return NULL;
11536 :
11537 0 : for (i = 0; i < map->n; ++i) {
11538 0 : map->p[i] = isl_basic_map_reset(map->p[i], type);
11539 0 : if (!map->p[i])
11540 0 : goto error;
11541 : }
11542 0 : map->dim = isl_space_reset(map->dim, type);
11543 0 : if (!map->dim)
11544 0 : goto error;
11545 :
11546 0 : return map;
11547 : error:
11548 0 : isl_map_free(map);
11549 0 : return NULL;
11550 : }
11551 :
11552 0 : __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11553 : {
11554 0 : if (!bmap)
11555 0 : return NULL;
11556 :
11557 0 : if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11558 0 : return bmap;
11559 :
11560 0 : bmap = isl_basic_map_cow(bmap);
11561 0 : if (!bmap)
11562 0 : return NULL;
11563 :
11564 0 : bmap->dim = isl_space_flatten(bmap->dim);
11565 0 : if (!bmap->dim)
11566 0 : goto error;
11567 :
11568 0 : bmap = isl_basic_map_finalize(bmap);
11569 :
11570 0 : return bmap;
11571 : error:
11572 0 : isl_basic_map_free(bmap);
11573 0 : return NULL;
11574 : }
11575 :
11576 0 : __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11577 : {
11578 0 : return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11579 : }
11580 :
11581 0 : __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11582 : __isl_take isl_basic_map *bmap)
11583 : {
11584 0 : if (!bmap)
11585 0 : return NULL;
11586 :
11587 0 : if (!bmap->dim->nested[0])
11588 0 : return bmap;
11589 :
11590 0 : bmap = isl_basic_map_cow(bmap);
11591 0 : if (!bmap)
11592 0 : return NULL;
11593 :
11594 0 : bmap->dim = isl_space_flatten_domain(bmap->dim);
11595 0 : if (!bmap->dim)
11596 0 : goto error;
11597 :
11598 0 : bmap = isl_basic_map_finalize(bmap);
11599 :
11600 0 : return bmap;
11601 : error:
11602 0 : isl_basic_map_free(bmap);
11603 0 : return NULL;
11604 : }
11605 :
11606 0 : __isl_give isl_basic_map *isl_basic_map_flatten_range(
11607 : __isl_take isl_basic_map *bmap)
11608 : {
11609 0 : if (!bmap)
11610 0 : return NULL;
11611 :
11612 0 : if (!bmap->dim->nested[1])
11613 0 : return bmap;
11614 :
11615 0 : bmap = isl_basic_map_cow(bmap);
11616 0 : if (!bmap)
11617 0 : return NULL;
11618 :
11619 0 : bmap->dim = isl_space_flatten_range(bmap->dim);
11620 0 : if (!bmap->dim)
11621 0 : goto error;
11622 :
11623 0 : bmap = isl_basic_map_finalize(bmap);
11624 :
11625 0 : return bmap;
11626 : error:
11627 0 : isl_basic_map_free(bmap);
11628 0 : return NULL;
11629 : }
11630 :
11631 : /* Remove any internal structure from the spaces of domain and range of "map".
11632 : */
11633 0 : __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11634 : {
11635 0 : if (!map)
11636 0 : return NULL;
11637 :
11638 0 : if (!map->dim->nested[0] && !map->dim->nested[1])
11639 0 : return map;
11640 :
11641 0 : return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11642 : }
11643 :
11644 0 : __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11645 : {
11646 0 : return set_from_map(isl_map_flatten(set_to_map(set)));
11647 : }
11648 :
11649 0 : __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11650 : {
11651 : isl_space *dim, *flat_dim;
11652 : isl_map *map;
11653 :
11654 0 : dim = isl_set_get_space(set);
11655 0 : flat_dim = isl_space_flatten(isl_space_copy(dim));
11656 0 : map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
11657 0 : map = isl_map_intersect_domain(map, set);
11658 :
11659 0 : return map;
11660 : }
11661 :
11662 : /* Remove any internal structure from the space of the domain of "map".
11663 : */
11664 0 : __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11665 : {
11666 0 : if (!map)
11667 0 : return NULL;
11668 :
11669 0 : if (!map->dim->nested[0])
11670 0 : return map;
11671 :
11672 0 : return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11673 : }
11674 :
11675 : /* Remove any internal structure from the space of the range of "map".
11676 : */
11677 0 : __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11678 : {
11679 0 : if (!map)
11680 0 : return NULL;
11681 :
11682 0 : if (!map->dim->nested[1])
11683 0 : return map;
11684 :
11685 0 : return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11686 : }
11687 :
11688 : /* Reorder the dimensions of "bmap" according to the given dim_map
11689 : * and set the dimension specification to "space" and
11690 : * perform Gaussian elimination on the result.
11691 : */
11692 0 : __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11693 : __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
11694 : {
11695 : isl_basic_map *res;
11696 : unsigned flags;
11697 : unsigned n_div;
11698 :
11699 0 : if (!bmap || !space || !dim_map)
11700 : goto error;
11701 :
11702 0 : flags = bmap->flags;
11703 0 : ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11704 0 : ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
11705 0 : ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11706 0 : n_div = isl_basic_map_dim(bmap, isl_dim_div);
11707 0 : res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
11708 0 : res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11709 0 : if (res)
11710 0 : res->flags = flags;
11711 0 : res = isl_basic_map_gauss(res, NULL);
11712 0 : res = isl_basic_map_finalize(res);
11713 0 : return res;
11714 : error:
11715 0 : free(dim_map);
11716 0 : isl_basic_map_free(bmap);
11717 0 : isl_space_free(space);
11718 0 : return NULL;
11719 : }
11720 :
11721 : /* Reorder the dimensions of "map" according to given reordering.
11722 : */
11723 0 : __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11724 : __isl_take isl_reordering *r)
11725 : {
11726 : int i;
11727 : struct isl_dim_map *dim_map;
11728 :
11729 0 : map = isl_map_cow(map);
11730 0 : dim_map = isl_dim_map_from_reordering(r);
11731 0 : if (!map || !r || !dim_map)
11732 : goto error;
11733 :
11734 0 : for (i = 0; i < map->n; ++i) {
11735 : struct isl_dim_map *dim_map_i;
11736 : isl_space *space;
11737 :
11738 0 : dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11739 :
11740 0 : space = isl_reordering_get_space(r);
11741 0 : map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
11742 :
11743 0 : if (!map->p[i])
11744 0 : goto error;
11745 : }
11746 :
11747 0 : map = isl_map_reset_space(map, isl_reordering_get_space(r));
11748 0 : map = isl_map_unmark_normalized(map);
11749 :
11750 0 : isl_reordering_free(r);
11751 0 : free(dim_map);
11752 0 : return map;
11753 : error:
11754 0 : free(dim_map);
11755 0 : isl_map_free(map);
11756 0 : isl_reordering_free(r);
11757 0 : return NULL;
11758 : }
11759 :
11760 0 : __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11761 : __isl_take isl_reordering *r)
11762 : {
11763 0 : return set_from_map(isl_map_realign(set_to_map(set), r));
11764 : }
11765 :
11766 0 : __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11767 : __isl_take isl_space *model)
11768 : {
11769 : isl_ctx *ctx;
11770 : isl_bool aligned;
11771 :
11772 0 : if (!map || !model)
11773 : goto error;
11774 :
11775 0 : ctx = isl_space_get_ctx(model);
11776 0 : if (!isl_space_has_named_params(model))
11777 0 : isl_die(ctx, isl_error_invalid,
11778 : "model has unnamed parameters", goto error);
11779 0 : if (isl_map_check_named_params(map) < 0)
11780 0 : goto error;
11781 0 : aligned = isl_map_space_has_equal_params(map, model);
11782 0 : if (aligned < 0)
11783 0 : goto error;
11784 0 : if (!aligned) {
11785 : isl_reordering *exp;
11786 :
11787 0 : exp = isl_parameter_alignment_reordering(map->dim, model);
11788 0 : exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11789 0 : map = isl_map_realign(map, exp);
11790 : }
11791 :
11792 0 : isl_space_free(model);
11793 0 : return map;
11794 : error:
11795 0 : isl_space_free(model);
11796 0 : isl_map_free(map);
11797 0 : return NULL;
11798 : }
11799 :
11800 0 : __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11801 : __isl_take isl_space *model)
11802 : {
11803 0 : return isl_map_align_params(set, model);
11804 : }
11805 :
11806 : /* Align the parameters of "bmap" to those of "model", introducing
11807 : * additional parameters if needed.
11808 : */
11809 0 : __isl_give isl_basic_map *isl_basic_map_align_params(
11810 : __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11811 : {
11812 : isl_ctx *ctx;
11813 : isl_bool equal_params;
11814 :
11815 0 : if (!bmap || !model)
11816 : goto error;
11817 :
11818 0 : ctx = isl_space_get_ctx(model);
11819 0 : if (!isl_space_has_named_params(model))
11820 0 : isl_die(ctx, isl_error_invalid,
11821 : "model has unnamed parameters", goto error);
11822 0 : if (isl_basic_map_check_named_params(bmap) < 0)
11823 0 : goto error;
11824 0 : equal_params = isl_space_has_equal_params(bmap->dim, model);
11825 0 : if (equal_params < 0)
11826 0 : goto error;
11827 0 : if (!equal_params) {
11828 : isl_reordering *exp;
11829 : struct isl_dim_map *dim_map;
11830 :
11831 0 : exp = isl_parameter_alignment_reordering(bmap->dim, model);
11832 0 : exp = isl_reordering_extend_space(exp,
11833 : isl_basic_map_get_space(bmap));
11834 0 : dim_map = isl_dim_map_from_reordering(exp);
11835 0 : bmap = isl_basic_map_realign(bmap,
11836 : isl_reordering_get_space(exp),
11837 0 : isl_dim_map_extend(dim_map, bmap));
11838 0 : isl_reordering_free(exp);
11839 0 : free(dim_map);
11840 : }
11841 :
11842 0 : isl_space_free(model);
11843 0 : return bmap;
11844 : error:
11845 0 : isl_space_free(model);
11846 0 : isl_basic_map_free(bmap);
11847 0 : return NULL;
11848 : }
11849 :
11850 : /* Do "bset" and "space" have the same parameters?
11851 : */
11852 0 : isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
11853 : __isl_keep isl_space *space)
11854 : {
11855 : isl_space *bset_space;
11856 :
11857 0 : bset_space = isl_basic_set_peek_space(bset);
11858 0 : return isl_space_has_equal_params(bset_space, space);
11859 : }
11860 :
11861 : /* Do "map" and "space" have the same parameters?
11862 : */
11863 0 : isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
11864 : __isl_keep isl_space *space)
11865 : {
11866 : isl_space *map_space;
11867 :
11868 0 : map_space = isl_map_peek_space(map);
11869 0 : return isl_space_has_equal_params(map_space, space);
11870 : }
11871 :
11872 : /* Do "set" and "space" have the same parameters?
11873 : */
11874 0 : isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
11875 : __isl_keep isl_space *space)
11876 : {
11877 0 : return isl_map_space_has_equal_params(set_to_map(set), space);
11878 : }
11879 :
11880 : /* Align the parameters of "bset" to those of "model", introducing
11881 : * additional parameters if needed.
11882 : */
11883 0 : __isl_give isl_basic_set *isl_basic_set_align_params(
11884 : __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11885 : {
11886 0 : return isl_basic_map_align_params(bset, model);
11887 : }
11888 :
11889 : /* Drop all parameters not referenced by "map".
11890 : */
11891 0 : __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
11892 : {
11893 : int i;
11894 :
11895 0 : if (isl_map_check_named_params(map) < 0)
11896 0 : return isl_map_free(map);
11897 :
11898 0 : for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
11899 : isl_bool involves;
11900 :
11901 0 : involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
11902 0 : if (involves < 0)
11903 0 : return isl_map_free(map);
11904 0 : if (!involves)
11905 0 : map = isl_map_project_out(map, isl_dim_param, i, 1);
11906 : }
11907 :
11908 0 : return map;
11909 : }
11910 :
11911 : /* Drop all parameters not referenced by "set".
11912 : */
11913 0 : __isl_give isl_set *isl_set_drop_unused_params(
11914 : __isl_take isl_set *set)
11915 : {
11916 0 : return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
11917 : }
11918 :
11919 : /* Drop all parameters not referenced by "bmap".
11920 : */
11921 0 : __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
11922 : __isl_take isl_basic_map *bmap)
11923 : {
11924 : int i;
11925 :
11926 0 : if (isl_basic_map_check_named_params(bmap) < 0)
11927 0 : return isl_basic_map_free(bmap);
11928 :
11929 0 : for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
11930 : isl_bool involves;
11931 :
11932 0 : involves = isl_basic_map_involves_dims(bmap,
11933 : isl_dim_param, i, 1);
11934 0 : if (involves < 0)
11935 0 : return isl_basic_map_free(bmap);
11936 0 : if (!involves)
11937 0 : bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
11938 : }
11939 :
11940 0 : return bmap;
11941 : }
11942 :
11943 : /* Drop all parameters not referenced by "bset".
11944 : */
11945 0 : __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
11946 : __isl_take isl_basic_set *bset)
11947 : {
11948 0 : return bset_from_bmap(isl_basic_map_drop_unused_params(
11949 : bset_to_bmap(bset)));
11950 : }
11951 :
11952 0 : __isl_give isl_mat *isl_basic_map_equalities_matrix(
11953 : __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11954 : enum isl_dim_type c2, enum isl_dim_type c3,
11955 : enum isl_dim_type c4, enum isl_dim_type c5)
11956 : {
11957 0 : enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11958 : struct isl_mat *mat;
11959 : int i, j, k;
11960 : int pos;
11961 :
11962 0 : if (!bmap)
11963 0 : return NULL;
11964 0 : mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11965 0 : isl_basic_map_total_dim(bmap) + 1);
11966 0 : if (!mat)
11967 0 : return NULL;
11968 0 : for (i = 0; i < bmap->n_eq; ++i)
11969 0 : for (j = 0, pos = 0; j < 5; ++j) {
11970 0 : int off = isl_basic_map_offset(bmap, c[j]);
11971 0 : for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11972 0 : isl_int_set(mat->row[i][pos],
11973 : bmap->eq[i][off + k]);
11974 0 : ++pos;
11975 : }
11976 : }
11977 :
11978 0 : return mat;
11979 : }
11980 :
11981 0 : __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11982 : __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11983 : enum isl_dim_type c2, enum isl_dim_type c3,
11984 : enum isl_dim_type c4, enum isl_dim_type c5)
11985 : {
11986 0 : enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11987 : struct isl_mat *mat;
11988 : int i, j, k;
11989 : int pos;
11990 :
11991 0 : if (!bmap)
11992 0 : return NULL;
11993 0 : mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11994 0 : isl_basic_map_total_dim(bmap) + 1);
11995 0 : if (!mat)
11996 0 : return NULL;
11997 0 : for (i = 0; i < bmap->n_ineq; ++i)
11998 0 : for (j = 0, pos = 0; j < 5; ++j) {
11999 0 : int off = isl_basic_map_offset(bmap, c[j]);
12000 0 : for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
12001 0 : isl_int_set(mat->row[i][pos],
12002 : bmap->ineq[i][off + k]);
12003 0 : ++pos;
12004 : }
12005 : }
12006 :
12007 0 : return mat;
12008 : }
12009 :
12010 0 : __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
12011 : __isl_take isl_space *dim,
12012 : __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12013 : enum isl_dim_type c2, enum isl_dim_type c3,
12014 : enum isl_dim_type c4, enum isl_dim_type c5)
12015 : {
12016 0 : enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12017 0 : isl_basic_map *bmap = NULL;
12018 : unsigned total;
12019 : unsigned extra;
12020 : int i, j, k, l;
12021 : int pos;
12022 :
12023 0 : if (!dim || !eq || !ineq)
12024 : goto error;
12025 :
12026 0 : if (eq->n_col != ineq->n_col)
12027 0 : isl_die(dim->ctx, isl_error_invalid,
12028 : "equalities and inequalities matrices should have "
12029 : "same number of columns", goto error);
12030 :
12031 0 : total = 1 + isl_space_dim(dim, isl_dim_all);
12032 :
12033 0 : if (eq->n_col < total)
12034 0 : isl_die(dim->ctx, isl_error_invalid,
12035 : "number of columns too small", goto error);
12036 :
12037 0 : extra = eq->n_col - total;
12038 :
12039 0 : bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
12040 : eq->n_row, ineq->n_row);
12041 0 : if (!bmap)
12042 0 : goto error;
12043 0 : for (i = 0; i < extra; ++i) {
12044 0 : k = isl_basic_map_alloc_div(bmap);
12045 0 : if (k < 0)
12046 0 : goto error;
12047 0 : isl_int_set_si(bmap->div[k][0], 0);
12048 : }
12049 0 : for (i = 0; i < eq->n_row; ++i) {
12050 0 : l = isl_basic_map_alloc_equality(bmap);
12051 0 : if (l < 0)
12052 0 : goto error;
12053 0 : for (j = 0, pos = 0; j < 5; ++j) {
12054 0 : int off = isl_basic_map_offset(bmap, c[j]);
12055 0 : for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
12056 0 : isl_int_set(bmap->eq[l][off + k],
12057 : eq->row[i][pos]);
12058 0 : ++pos;
12059 : }
12060 : }
12061 : }
12062 0 : for (i = 0; i < ineq->n_row; ++i) {
12063 0 : l = isl_basic_map_alloc_inequality(bmap);
12064 0 : if (l < 0)
12065 0 : goto error;
12066 0 : for (j = 0, pos = 0; j < 5; ++j) {
12067 0 : int off = isl_basic_map_offset(bmap, c[j]);
12068 0 : for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
12069 0 : isl_int_set(bmap->ineq[l][off + k],
12070 : ineq->row[i][pos]);
12071 0 : ++pos;
12072 : }
12073 : }
12074 : }
12075 :
12076 0 : isl_space_free(dim);
12077 0 : isl_mat_free(eq);
12078 0 : isl_mat_free(ineq);
12079 :
12080 0 : bmap = isl_basic_map_simplify(bmap);
12081 0 : return isl_basic_map_finalize(bmap);
12082 : error:
12083 0 : isl_space_free(dim);
12084 0 : isl_mat_free(eq);
12085 0 : isl_mat_free(ineq);
12086 0 : isl_basic_map_free(bmap);
12087 0 : return NULL;
12088 : }
12089 :
12090 0 : __isl_give isl_mat *isl_basic_set_equalities_matrix(
12091 : __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12092 : enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12093 : {
12094 0 : return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12095 : c1, c2, c3, c4, isl_dim_in);
12096 : }
12097 :
12098 0 : __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12099 : __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12100 : enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12101 : {
12102 0 : return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12103 : c1, c2, c3, c4, isl_dim_in);
12104 : }
12105 :
12106 0 : __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12107 : __isl_take isl_space *dim,
12108 : __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12109 : enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12110 : {
12111 : isl_basic_map *bmap;
12112 0 : bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
12113 : c1, c2, c3, c4, isl_dim_in);
12114 0 : return bset_from_bmap(bmap);
12115 : }
12116 :
12117 0 : isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12118 : {
12119 0 : if (!bmap)
12120 0 : return isl_bool_error;
12121 :
12122 0 : return isl_space_can_zip(bmap->dim);
12123 : }
12124 :
12125 0 : isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12126 : {
12127 0 : if (!map)
12128 0 : return isl_bool_error;
12129 :
12130 0 : return isl_space_can_zip(map->dim);
12131 : }
12132 :
12133 : /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12134 : * (A -> C) -> (B -> D).
12135 : */
12136 0 : __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12137 : {
12138 : unsigned pos;
12139 : unsigned n1;
12140 : unsigned n2;
12141 :
12142 0 : if (!bmap)
12143 0 : return NULL;
12144 :
12145 0 : if (!isl_basic_map_can_zip(bmap))
12146 0 : isl_die(bmap->ctx, isl_error_invalid,
12147 : "basic map cannot be zipped", goto error);
12148 0 : pos = isl_basic_map_offset(bmap, isl_dim_in) +
12149 0 : isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12150 0 : n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12151 0 : n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12152 0 : bmap = isl_basic_map_cow(bmap);
12153 0 : bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12154 0 : if (!bmap)
12155 0 : return NULL;
12156 0 : bmap->dim = isl_space_zip(bmap->dim);
12157 0 : if (!bmap->dim)
12158 0 : goto error;
12159 0 : bmap = isl_basic_map_mark_final(bmap);
12160 0 : return bmap;
12161 : error:
12162 0 : isl_basic_map_free(bmap);
12163 0 : return NULL;
12164 : }
12165 :
12166 : /* Given a map (A -> B) -> (C -> D), return the corresponding map
12167 : * (A -> C) -> (B -> D).
12168 : */
12169 0 : __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12170 : {
12171 : int i;
12172 :
12173 0 : if (!map)
12174 0 : return NULL;
12175 :
12176 0 : if (!isl_map_can_zip(map))
12177 0 : isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12178 : goto error);
12179 :
12180 0 : map = isl_map_cow(map);
12181 0 : if (!map)
12182 0 : return NULL;
12183 :
12184 0 : for (i = 0; i < map->n; ++i) {
12185 0 : map->p[i] = isl_basic_map_zip(map->p[i]);
12186 0 : if (!map->p[i])
12187 0 : goto error;
12188 : }
12189 :
12190 0 : map->dim = isl_space_zip(map->dim);
12191 0 : if (!map->dim)
12192 0 : goto error;
12193 :
12194 0 : return map;
12195 : error:
12196 0 : isl_map_free(map);
12197 0 : return NULL;
12198 : }
12199 :
12200 : /* Can we apply isl_basic_map_curry to "bmap"?
12201 : * That is, does it have a nested relation in its domain?
12202 : */
12203 0 : isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12204 : {
12205 0 : if (!bmap)
12206 0 : return isl_bool_error;
12207 :
12208 0 : return isl_space_can_curry(bmap->dim);
12209 : }
12210 :
12211 : /* Can we apply isl_map_curry to "map"?
12212 : * That is, does it have a nested relation in its domain?
12213 : */
12214 0 : isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12215 : {
12216 0 : if (!map)
12217 0 : return isl_bool_error;
12218 :
12219 0 : return isl_space_can_curry(map->dim);
12220 : }
12221 :
12222 : /* Given a basic map (A -> B) -> C, return the corresponding basic map
12223 : * A -> (B -> C).
12224 : */
12225 0 : __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12226 : {
12227 :
12228 0 : if (!bmap)
12229 0 : return NULL;
12230 :
12231 0 : if (!isl_basic_map_can_curry(bmap))
12232 0 : isl_die(bmap->ctx, isl_error_invalid,
12233 : "basic map cannot be curried", goto error);
12234 0 : bmap = isl_basic_map_cow(bmap);
12235 0 : if (!bmap)
12236 0 : return NULL;
12237 0 : bmap->dim = isl_space_curry(bmap->dim);
12238 0 : if (!bmap->dim)
12239 0 : goto error;
12240 0 : bmap = isl_basic_map_mark_final(bmap);
12241 0 : return bmap;
12242 : error:
12243 0 : isl_basic_map_free(bmap);
12244 0 : return NULL;
12245 : }
12246 :
12247 : /* Given a map (A -> B) -> C, return the corresponding map
12248 : * A -> (B -> C).
12249 : */
12250 0 : __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
12251 : {
12252 0 : return isl_map_change_space(map, &isl_map_can_curry,
12253 : "map cannot be curried", &isl_space_curry);
12254 : }
12255 :
12256 : /* Can isl_map_range_curry be applied to "map"?
12257 : * That is, does it have a nested relation in its range,
12258 : * the domain of which is itself a nested relation?
12259 : */
12260 0 : isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
12261 : {
12262 0 : if (!map)
12263 0 : return isl_bool_error;
12264 :
12265 0 : return isl_space_can_range_curry(map->dim);
12266 : }
12267 :
12268 : /* Given a map A -> ((B -> C) -> D), return the corresponding map
12269 : * A -> (B -> (C -> D)).
12270 : */
12271 0 : __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
12272 : {
12273 0 : return isl_map_change_space(map, &isl_map_can_range_curry,
12274 : "map range cannot be curried",
12275 : &isl_space_range_curry);
12276 : }
12277 :
12278 : /* Can we apply isl_basic_map_uncurry to "bmap"?
12279 : * That is, does it have a nested relation in its domain?
12280 : */
12281 0 : isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
12282 : {
12283 0 : if (!bmap)
12284 0 : return isl_bool_error;
12285 :
12286 0 : return isl_space_can_uncurry(bmap->dim);
12287 : }
12288 :
12289 : /* Can we apply isl_map_uncurry to "map"?
12290 : * That is, does it have a nested relation in its domain?
12291 : */
12292 0 : isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
12293 : {
12294 0 : if (!map)
12295 0 : return isl_bool_error;
12296 :
12297 0 : return isl_space_can_uncurry(map->dim);
12298 : }
12299 :
12300 : /* Given a basic map A -> (B -> C), return the corresponding basic map
12301 : * (A -> B) -> C.
12302 : */
12303 0 : __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
12304 : {
12305 :
12306 0 : if (!bmap)
12307 0 : return NULL;
12308 :
12309 0 : if (!isl_basic_map_can_uncurry(bmap))
12310 0 : isl_die(bmap->ctx, isl_error_invalid,
12311 : "basic map cannot be uncurried",
12312 : return isl_basic_map_free(bmap));
12313 0 : bmap = isl_basic_map_cow(bmap);
12314 0 : if (!bmap)
12315 0 : return NULL;
12316 0 : bmap->dim = isl_space_uncurry(bmap->dim);
12317 0 : if (!bmap->dim)
12318 0 : return isl_basic_map_free(bmap);
12319 0 : bmap = isl_basic_map_mark_final(bmap);
12320 0 : return bmap;
12321 : }
12322 :
12323 : /* Given a map A -> (B -> C), return the corresponding map
12324 : * (A -> B) -> C.
12325 : */
12326 0 : __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
12327 : {
12328 0 : return isl_map_change_space(map, &isl_map_can_uncurry,
12329 : "map cannot be uncurried", &isl_space_uncurry);
12330 : }
12331 :
12332 0 : __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
12333 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12334 : {
12335 0 : return isl_map_equate(set, type1, pos1, type2, pos2);
12336 : }
12337 :
12338 : /* Construct a basic map where the given dimensions are equal to each other.
12339 : */
12340 0 : static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
12341 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12342 : {
12343 0 : isl_basic_map *bmap = NULL;
12344 : int i;
12345 :
12346 0 : if (!space)
12347 0 : return NULL;
12348 :
12349 0 : if (pos1 >= isl_space_dim(space, type1))
12350 0 : isl_die(isl_space_get_ctx(space), isl_error_invalid,
12351 : "index out of bounds", goto error);
12352 0 : if (pos2 >= isl_space_dim(space, type2))
12353 0 : isl_die(isl_space_get_ctx(space), isl_error_invalid,
12354 : "index out of bounds", goto error);
12355 :
12356 0 : if (type1 == type2 && pos1 == pos2)
12357 0 : return isl_basic_map_universe(space);
12358 :
12359 0 : bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
12360 0 : i = isl_basic_map_alloc_equality(bmap);
12361 0 : if (i < 0)
12362 0 : goto error;
12363 0 : isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12364 0 : pos1 += isl_basic_map_offset(bmap, type1);
12365 0 : pos2 += isl_basic_map_offset(bmap, type2);
12366 0 : isl_int_set_si(bmap->eq[i][pos1], -1);
12367 0 : isl_int_set_si(bmap->eq[i][pos2], 1);
12368 0 : bmap = isl_basic_map_finalize(bmap);
12369 0 : isl_space_free(space);
12370 0 : return bmap;
12371 : error:
12372 0 : isl_space_free(space);
12373 0 : isl_basic_map_free(bmap);
12374 0 : return NULL;
12375 : }
12376 :
12377 : /* Add a constraint imposing that the given two dimensions are equal.
12378 : */
12379 0 : __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
12380 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12381 : {
12382 : isl_basic_map *eq;
12383 :
12384 0 : eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12385 :
12386 0 : bmap = isl_basic_map_intersect(bmap, eq);
12387 :
12388 0 : return bmap;
12389 : }
12390 :
12391 : /* Add a constraint imposing that the given two dimensions are equal.
12392 : */
12393 0 : __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
12394 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12395 : {
12396 : isl_basic_map *bmap;
12397 :
12398 0 : bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
12399 :
12400 0 : map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12401 :
12402 0 : return map;
12403 : }
12404 :
12405 : /* Add a constraint imposing that the given two dimensions have opposite values.
12406 : */
12407 0 : __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
12408 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12409 : {
12410 0 : isl_basic_map *bmap = NULL;
12411 : int i;
12412 :
12413 0 : if (!map)
12414 0 : return NULL;
12415 :
12416 0 : if (pos1 >= isl_map_dim(map, type1))
12417 0 : isl_die(map->ctx, isl_error_invalid,
12418 : "index out of bounds", goto error);
12419 0 : if (pos2 >= isl_map_dim(map, type2))
12420 0 : isl_die(map->ctx, isl_error_invalid,
12421 : "index out of bounds", goto error);
12422 :
12423 0 : bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
12424 0 : i = isl_basic_map_alloc_equality(bmap);
12425 0 : if (i < 0)
12426 0 : goto error;
12427 0 : isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
12428 0 : pos1 += isl_basic_map_offset(bmap, type1);
12429 0 : pos2 += isl_basic_map_offset(bmap, type2);
12430 0 : isl_int_set_si(bmap->eq[i][pos1], 1);
12431 0 : isl_int_set_si(bmap->eq[i][pos2], 1);
12432 0 : bmap = isl_basic_map_finalize(bmap);
12433 :
12434 0 : map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12435 :
12436 0 : return map;
12437 : error:
12438 0 : isl_basic_map_free(bmap);
12439 0 : isl_map_free(map);
12440 0 : return NULL;
12441 : }
12442 :
12443 : /* Construct a constraint imposing that the value of the first dimension is
12444 : * greater than or equal to that of the second.
12445 : */
12446 0 : static __isl_give isl_constraint *constraint_order_ge(
12447 : __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
12448 : enum isl_dim_type type2, int pos2)
12449 : {
12450 : isl_constraint *c;
12451 :
12452 0 : if (!space)
12453 0 : return NULL;
12454 :
12455 0 : c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
12456 :
12457 0 : if (pos1 >= isl_constraint_dim(c, type1))
12458 0 : isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
12459 : "index out of bounds", return isl_constraint_free(c));
12460 0 : if (pos2 >= isl_constraint_dim(c, type2))
12461 0 : isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
12462 : "index out of bounds", return isl_constraint_free(c));
12463 :
12464 0 : if (type1 == type2 && pos1 == pos2)
12465 0 : return c;
12466 :
12467 0 : c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
12468 0 : c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
12469 :
12470 0 : return c;
12471 : }
12472 :
12473 : /* Add a constraint imposing that the value of the first dimension is
12474 : * greater than or equal to that of the second.
12475 : */
12476 0 : __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
12477 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12478 : {
12479 : isl_constraint *c;
12480 : isl_space *space;
12481 :
12482 0 : if (type1 == type2 && pos1 == pos2)
12483 0 : return bmap;
12484 0 : space = isl_basic_map_get_space(bmap);
12485 0 : c = constraint_order_ge(space, type1, pos1, type2, pos2);
12486 0 : bmap = isl_basic_map_add_constraint(bmap, c);
12487 :
12488 0 : return bmap;
12489 : }
12490 :
12491 : /* Add a constraint imposing that the value of the first dimension is
12492 : * greater than or equal to that of the second.
12493 : */
12494 0 : __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12495 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12496 : {
12497 : isl_constraint *c;
12498 : isl_space *space;
12499 :
12500 0 : if (type1 == type2 && pos1 == pos2)
12501 0 : return map;
12502 0 : space = isl_map_get_space(map);
12503 0 : c = constraint_order_ge(space, type1, pos1, type2, pos2);
12504 0 : map = isl_map_add_constraint(map, c);
12505 :
12506 0 : return map;
12507 : }
12508 :
12509 : /* Add a constraint imposing that the value of the first dimension is
12510 : * less than or equal to that of the second.
12511 : */
12512 0 : __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12513 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12514 : {
12515 0 : return isl_map_order_ge(map, type2, pos2, type1, pos1);
12516 : }
12517 :
12518 : /* Construct a basic map where the value of the first dimension is
12519 : * greater than that of the second.
12520 : */
12521 0 : static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12522 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12523 : {
12524 0 : isl_basic_map *bmap = NULL;
12525 : int i;
12526 :
12527 0 : if (!space)
12528 0 : return NULL;
12529 :
12530 0 : if (pos1 >= isl_space_dim(space, type1))
12531 0 : isl_die(isl_space_get_ctx(space), isl_error_invalid,
12532 : "index out of bounds", goto error);
12533 0 : if (pos2 >= isl_space_dim(space, type2))
12534 0 : isl_die(isl_space_get_ctx(space), isl_error_invalid,
12535 : "index out of bounds", goto error);
12536 :
12537 0 : if (type1 == type2 && pos1 == pos2)
12538 0 : return isl_basic_map_empty(space);
12539 :
12540 0 : bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12541 0 : i = isl_basic_map_alloc_inequality(bmap);
12542 0 : if (i < 0)
12543 0 : return isl_basic_map_free(bmap);
12544 0 : isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12545 0 : pos1 += isl_basic_map_offset(bmap, type1);
12546 0 : pos2 += isl_basic_map_offset(bmap, type2);
12547 0 : isl_int_set_si(bmap->ineq[i][pos1], 1);
12548 0 : isl_int_set_si(bmap->ineq[i][pos2], -1);
12549 0 : isl_int_set_si(bmap->ineq[i][0], -1);
12550 0 : bmap = isl_basic_map_finalize(bmap);
12551 :
12552 0 : return bmap;
12553 : error:
12554 0 : isl_space_free(space);
12555 0 : isl_basic_map_free(bmap);
12556 0 : return NULL;
12557 : }
12558 :
12559 : /* Add a constraint imposing that the value of the first dimension is
12560 : * greater than that of the second.
12561 : */
12562 0 : __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12563 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12564 : {
12565 : isl_basic_map *gt;
12566 :
12567 0 : gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12568 :
12569 0 : bmap = isl_basic_map_intersect(bmap, gt);
12570 :
12571 0 : return bmap;
12572 : }
12573 :
12574 : /* Add a constraint imposing that the value of the first dimension is
12575 : * greater than that of the second.
12576 : */
12577 0 : __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12578 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12579 : {
12580 : isl_basic_map *bmap;
12581 :
12582 0 : bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12583 :
12584 0 : map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12585 :
12586 0 : return map;
12587 : }
12588 :
12589 : /* Add a constraint imposing that the value of the first dimension is
12590 : * smaller than that of the second.
12591 : */
12592 0 : __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12593 : enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12594 : {
12595 0 : return isl_map_order_gt(map, type2, pos2, type1, pos1);
12596 : }
12597 :
12598 0 : __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12599 : int pos)
12600 : {
12601 : isl_aff *div;
12602 : isl_local_space *ls;
12603 :
12604 0 : if (!bmap)
12605 0 : return NULL;
12606 :
12607 0 : if (!isl_basic_map_divs_known(bmap))
12608 0 : isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12609 : "some divs are unknown", return NULL);
12610 :
12611 0 : ls = isl_basic_map_get_local_space(bmap);
12612 0 : div = isl_local_space_get_div(ls, pos);
12613 0 : isl_local_space_free(ls);
12614 :
12615 0 : return div;
12616 : }
12617 :
12618 0 : __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12619 : int pos)
12620 : {
12621 0 : return isl_basic_map_get_div(bset, pos);
12622 : }
12623 :
12624 : /* Plug in "subs" for dimension "type", "pos" of "bset".
12625 : *
12626 : * Let i be the dimension to replace and let "subs" be of the form
12627 : *
12628 : * f/d
12629 : *
12630 : * Any integer division with a non-zero coefficient for i,
12631 : *
12632 : * floor((a i + g)/m)
12633 : *
12634 : * is replaced by
12635 : *
12636 : * floor((a f + d g)/(m d))
12637 : *
12638 : * Constraints of the form
12639 : *
12640 : * a i + g
12641 : *
12642 : * are replaced by
12643 : *
12644 : * a f + d g
12645 : *
12646 : * We currently require that "subs" is an integral expression.
12647 : * Handling rational expressions may require us to add stride constraints
12648 : * as we do in isl_basic_set_preimage_multi_aff.
12649 : */
12650 0 : __isl_give isl_basic_set *isl_basic_set_substitute(
12651 : __isl_take isl_basic_set *bset,
12652 : enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12653 : {
12654 : int i;
12655 : isl_int v;
12656 : isl_ctx *ctx;
12657 :
12658 0 : if (bset && isl_basic_set_plain_is_empty(bset))
12659 0 : return bset;
12660 :
12661 0 : bset = isl_basic_set_cow(bset);
12662 0 : if (!bset || !subs)
12663 : goto error;
12664 :
12665 0 : ctx = isl_basic_set_get_ctx(bset);
12666 0 : if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12667 0 : isl_die(ctx, isl_error_invalid,
12668 : "spaces don't match", goto error);
12669 0 : if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12670 0 : isl_die(ctx, isl_error_unsupported,
12671 : "cannot handle divs yet", goto error);
12672 0 : if (!isl_int_is_one(subs->v->el[0]))
12673 0 : isl_die(ctx, isl_error_invalid,
12674 : "can only substitute integer expressions", goto error);
12675 :
12676 0 : pos += isl_basic_set_offset(bset, type);
12677 :
12678 0 : isl_int_init(v);
12679 :
12680 0 : for (i = 0; i < bset->n_eq; ++i) {
12681 0 : if (isl_int_is_zero(bset->eq[i][pos]))
12682 0 : continue;
12683 0 : isl_int_set(v, bset->eq[i][pos]);
12684 0 : isl_int_set_si(bset->eq[i][pos], 0);
12685 0 : isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12686 0 : v, subs->v->el + 1, subs->v->size - 1);
12687 : }
12688 :
12689 0 : for (i = 0; i < bset->n_ineq; ++i) {
12690 0 : if (isl_int_is_zero(bset->ineq[i][pos]))
12691 0 : continue;
12692 0 : isl_int_set(v, bset->ineq[i][pos]);
12693 0 : isl_int_set_si(bset->ineq[i][pos], 0);
12694 0 : isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12695 0 : v, subs->v->el + 1, subs->v->size - 1);
12696 : }
12697 :
12698 0 : for (i = 0; i < bset->n_div; ++i) {
12699 0 : if (isl_int_is_zero(bset->div[i][1 + pos]))
12700 0 : continue;
12701 0 : isl_int_set(v, bset->div[i][1 + pos]);
12702 0 : isl_int_set_si(bset->div[i][1 + pos], 0);
12703 0 : isl_seq_combine(bset->div[i] + 1,
12704 0 : subs->v->el[0], bset->div[i] + 1,
12705 0 : v, subs->v->el + 1, subs->v->size - 1);
12706 0 : isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12707 : }
12708 :
12709 0 : isl_int_clear(v);
12710 :
12711 0 : bset = isl_basic_set_simplify(bset);
12712 0 : return isl_basic_set_finalize(bset);
12713 : error:
12714 0 : isl_basic_set_free(bset);
12715 0 : return NULL;
12716 : }
12717 :
12718 : /* Plug in "subs" for dimension "type", "pos" of "set".
12719 : */
12720 0 : __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12721 : enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12722 : {
12723 : int i;
12724 :
12725 0 : if (set && isl_set_plain_is_empty(set))
12726 0 : return set;
12727 :
12728 0 : set = isl_set_cow(set);
12729 0 : if (!set || !subs)
12730 : goto error;
12731 :
12732 0 : for (i = set->n - 1; i >= 0; --i) {
12733 0 : set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12734 0 : set = set_from_map(remove_if_empty(set_to_map(set), i));
12735 0 : if (!set)
12736 0 : return NULL;
12737 : }
12738 :
12739 0 : return set;
12740 : error:
12741 0 : isl_set_free(set);
12742 0 : return NULL;
12743 : }
12744 :
12745 : /* Check if the range of "ma" is compatible with the domain or range
12746 : * (depending on "type") of "bmap".
12747 : */
12748 0 : static isl_stat check_basic_map_compatible_range_multi_aff(
12749 : __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12750 : __isl_keep isl_multi_aff *ma)
12751 : {
12752 : isl_bool m;
12753 : isl_space *ma_space;
12754 :
12755 0 : ma_space = isl_multi_aff_get_space(ma);
12756 :
12757 0 : m = isl_space_has_equal_params(bmap->dim, ma_space);
12758 0 : if (m < 0)
12759 0 : goto error;
12760 0 : if (!m)
12761 0 : isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12762 : "parameters don't match", goto error);
12763 0 : m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12764 0 : if (m < 0)
12765 0 : goto error;
12766 0 : if (!m)
12767 0 : isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12768 : "spaces don't match", goto error);
12769 :
12770 0 : isl_space_free(ma_space);
12771 0 : return isl_stat_ok;
12772 : error:
12773 0 : isl_space_free(ma_space);
12774 0 : return isl_stat_error;
12775 : }
12776 :
12777 : /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12778 : * coefficients before the transformed range of dimensions,
12779 : * the "n_after" coefficients after the transformed range of dimensions
12780 : * and the coefficients of the other divs in "bmap".
12781 : */
12782 0 : static int set_ma_divs(__isl_keep isl_basic_map *bmap,
12783 : __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12784 : {
12785 : int i;
12786 : int n_param;
12787 : int n_set;
12788 : isl_local_space *ls;
12789 :
12790 0 : if (n_div == 0)
12791 0 : return 0;
12792 :
12793 0 : ls = isl_aff_get_domain_local_space(ma->u.p[0]);
12794 0 : if (!ls)
12795 0 : return -1;
12796 :
12797 0 : n_param = isl_local_space_dim(ls, isl_dim_param);
12798 0 : n_set = isl_local_space_dim(ls, isl_dim_set);
12799 0 : for (i = 0; i < n_div; ++i) {
12800 0 : int o_bmap = 0, o_ls = 0;
12801 :
12802 0 : isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12803 0 : o_bmap += 1 + 1 + n_param;
12804 0 : o_ls += 1 + 1 + n_param;
12805 0 : isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12806 0 : o_bmap += n_before;
12807 0 : isl_seq_cpy(bmap->div[i] + o_bmap,
12808 0 : ls->div->row[i] + o_ls, n_set);
12809 0 : o_bmap += n_set;
12810 0 : o_ls += n_set;
12811 0 : isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12812 0 : o_bmap += n_after;
12813 0 : isl_seq_cpy(bmap->div[i] + o_bmap,
12814 0 : ls->div->row[i] + o_ls, n_div);
12815 0 : o_bmap += n_div;
12816 0 : o_ls += n_div;
12817 0 : isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12818 0 : if (isl_basic_map_add_div_constraints(bmap, i) < 0)
12819 0 : goto error;
12820 : }
12821 :
12822 0 : isl_local_space_free(ls);
12823 0 : return 0;
12824 : error:
12825 0 : isl_local_space_free(ls);
12826 0 : return -1;
12827 : }
12828 :
12829 : /* How many stride constraints does "ma" enforce?
12830 : * That is, how many of the affine expressions have a denominator
12831 : * different from one?
12832 : */
12833 0 : static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12834 : {
12835 : int i;
12836 0 : int strides = 0;
12837 :
12838 0 : for (i = 0; i < ma->n; ++i)
12839 0 : if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
12840 0 : strides++;
12841 :
12842 0 : return strides;
12843 : }
12844 :
12845 : /* For each affine expression in ma of the form
12846 : *
12847 : * x_i = (f_i y + h_i)/m_i
12848 : *
12849 : * with m_i different from one, add a constraint to "bmap"
12850 : * of the form
12851 : *
12852 : * f_i y + h_i = m_i alpha_i
12853 : *
12854 : * with alpha_i an additional existentially quantified variable.
12855 : *
12856 : * The input variables of "ma" correspond to a subset of the variables
12857 : * of "bmap". There are "n_before" variables in "bmap" before this
12858 : * subset and "n_after" variables after this subset.
12859 : * The integer divisions of the affine expressions in "ma" are assumed
12860 : * to have been aligned. There are "n_div_ma" of them and
12861 : * they appear first in "bmap", straight after the "n_after" variables.
12862 : */
12863 0 : static __isl_give isl_basic_map *add_ma_strides(
12864 : __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12865 : int n_before, int n_after, int n_div_ma)
12866 : {
12867 : int i, k;
12868 : int div;
12869 : int total;
12870 : int n_param;
12871 : int n_in;
12872 :
12873 0 : total = isl_basic_map_total_dim(bmap);
12874 0 : n_param = isl_multi_aff_dim(ma, isl_dim_param);
12875 0 : n_in = isl_multi_aff_dim(ma, isl_dim_in);
12876 0 : for (i = 0; i < ma->n; ++i) {
12877 0 : int o_bmap = 0, o_ma = 1;
12878 :
12879 0 : if (isl_int_is_one(ma->u.p[i]->v->el[0]))
12880 0 : continue;
12881 0 : div = isl_basic_map_alloc_div(bmap);
12882 0 : k = isl_basic_map_alloc_equality(bmap);
12883 0 : if (div < 0 || k < 0)
12884 : goto error;
12885 0 : isl_int_set_si(bmap->div[div][0], 0);
12886 0 : isl_seq_cpy(bmap->eq[k] + o_bmap,
12887 0 : ma->u.p[i]->v->el + o_ma, 1 + n_param);
12888 0 : o_bmap += 1 + n_param;
12889 0 : o_ma += 1 + n_param;
12890 0 : isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12891 0 : o_bmap += n_before;
12892 0 : isl_seq_cpy(bmap->eq[k] + o_bmap,
12893 0 : ma->u.p[i]->v->el + o_ma, n_in);
12894 0 : o_bmap += n_in;
12895 0 : o_ma += n_in;
12896 0 : isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12897 0 : o_bmap += n_after;
12898 0 : isl_seq_cpy(bmap->eq[k] + o_bmap,
12899 0 : ma->u.p[i]->v->el + o_ma, n_div_ma);
12900 0 : o_bmap += n_div_ma;
12901 0 : o_ma += n_div_ma;
12902 0 : isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12903 0 : isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
12904 0 : total++;
12905 : }
12906 :
12907 0 : return bmap;
12908 : error:
12909 0 : isl_basic_map_free(bmap);
12910 0 : return NULL;
12911 : }
12912 :
12913 : /* Replace the domain or range space (depending on "type) of "space" by "set".
12914 : */
12915 0 : static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12916 : enum isl_dim_type type, __isl_take isl_space *set)
12917 : {
12918 0 : if (type == isl_dim_in) {
12919 0 : space = isl_space_range(space);
12920 0 : space = isl_space_map_from_domain_and_range(set, space);
12921 : } else {
12922 0 : space = isl_space_domain(space);
12923 0 : space = isl_space_map_from_domain_and_range(space, set);
12924 : }
12925 :
12926 0 : return space;
12927 : }
12928 :
12929 : /* Compute the preimage of the domain or range (depending on "type")
12930 : * of "bmap" under the function represented by "ma".
12931 : * In other words, plug in "ma" in the domain or range of "bmap".
12932 : * The result is a basic map that lives in the same space as "bmap"
12933 : * except that the domain or range has been replaced by
12934 : * the domain space of "ma".
12935 : *
12936 : * If bmap is represented by
12937 : *
12938 : * A(p) + S u + B x + T v + C(divs) >= 0,
12939 : *
12940 : * where u and x are input and output dimensions if type == isl_dim_out
12941 : * while x and v are input and output dimensions if type == isl_dim_in,
12942 : * and ma is represented by
12943 : *
12944 : * x = D(p) + F(y) + G(divs')
12945 : *
12946 : * then the result is
12947 : *
12948 : * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12949 : *
12950 : * The divs in the input set are similarly adjusted.
12951 : * In particular
12952 : *
12953 : * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12954 : *
12955 : * becomes
12956 : *
12957 : * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12958 : * B_i G(divs') + c_i(divs))/n_i)
12959 : *
12960 : * If bmap is not a rational map and if F(y) involves any denominators
12961 : *
12962 : * x_i = (f_i y + h_i)/m_i
12963 : *
12964 : * then additional constraints are added to ensure that we only
12965 : * map back integer points. That is we enforce
12966 : *
12967 : * f_i y + h_i = m_i alpha_i
12968 : *
12969 : * with alpha_i an additional existentially quantified variable.
12970 : *
12971 : * We first copy over the divs from "ma".
12972 : * Then we add the modified constraints and divs from "bmap".
12973 : * Finally, we add the stride constraints, if needed.
12974 : */
12975 0 : __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12976 : __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12977 : __isl_take isl_multi_aff *ma)
12978 : {
12979 : int i, k;
12980 : isl_space *space;
12981 0 : isl_basic_map *res = NULL;
12982 : int n_before, n_after, n_div_bmap, n_div_ma;
12983 : isl_int f, c1, c2, g;
12984 : isl_bool rational;
12985 : int strides;
12986 :
12987 0 : isl_int_init(f);
12988 0 : isl_int_init(c1);
12989 0 : isl_int_init(c2);
12990 0 : isl_int_init(g);
12991 :
12992 0 : ma = isl_multi_aff_align_divs(ma);
12993 0 : if (!bmap || !ma)
12994 : goto error;
12995 0 : if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12996 0 : goto error;
12997 :
12998 0 : if (type == isl_dim_in) {
12999 0 : n_before = 0;
13000 0 : n_after = isl_basic_map_dim(bmap, isl_dim_out);
13001 : } else {
13002 0 : n_before = isl_basic_map_dim(bmap, isl_dim_in);
13003 0 : n_after = 0;
13004 : }
13005 0 : n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
13006 0 : n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
13007 :
13008 0 : space = isl_multi_aff_get_domain_space(ma);
13009 0 : space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
13010 0 : rational = isl_basic_map_is_rational(bmap);
13011 0 : strides = rational ? 0 : multi_aff_strides(ma);
13012 0 : res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
13013 0 : bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
13014 0 : if (rational)
13015 0 : res = isl_basic_map_set_rational(res);
13016 :
13017 0 : for (i = 0; i < n_div_ma + n_div_bmap; ++i)
13018 0 : if (isl_basic_map_alloc_div(res) < 0)
13019 0 : goto error;
13020 :
13021 0 : if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
13022 0 : goto error;
13023 :
13024 0 : for (i = 0; i < bmap->n_eq; ++i) {
13025 0 : k = isl_basic_map_alloc_equality(res);
13026 0 : if (k < 0)
13027 0 : goto error;
13028 0 : isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13029 : n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
13030 : }
13031 :
13032 0 : for (i = 0; i < bmap->n_ineq; ++i) {
13033 0 : k = isl_basic_map_alloc_inequality(res);
13034 0 : if (k < 0)
13035 0 : goto error;
13036 0 : isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13037 : n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
13038 : }
13039 :
13040 0 : for (i = 0; i < bmap->n_div; ++i) {
13041 0 : if (isl_int_is_zero(bmap->div[i][0])) {
13042 0 : isl_int_set_si(res->div[n_div_ma + i][0], 0);
13043 0 : continue;
13044 : }
13045 0 : isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13046 : n_before, n_after, n_div_ma, n_div_bmap,
13047 : f, c1, c2, g, 1);
13048 : }
13049 :
13050 0 : if (strides)
13051 0 : res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13052 :
13053 0 : isl_int_clear(f);
13054 0 : isl_int_clear(c1);
13055 0 : isl_int_clear(c2);
13056 0 : isl_int_clear(g);
13057 0 : isl_basic_map_free(bmap);
13058 0 : isl_multi_aff_free(ma);
13059 0 : res = isl_basic_map_simplify(res);
13060 0 : return isl_basic_map_finalize(res);
13061 : error:
13062 0 : isl_int_clear(f);
13063 0 : isl_int_clear(c1);
13064 0 : isl_int_clear(c2);
13065 0 : isl_int_clear(g);
13066 0 : isl_basic_map_free(bmap);
13067 0 : isl_multi_aff_free(ma);
13068 0 : isl_basic_map_free(res);
13069 0 : return NULL;
13070 : }
13071 :
13072 : /* Compute the preimage of "bset" under the function represented by "ma".
13073 : * In other words, plug in "ma" in "bset". The result is a basic set
13074 : * that lives in the domain space of "ma".
13075 : */
13076 0 : __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13077 : __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13078 : {
13079 0 : return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13080 : }
13081 :
13082 : /* Compute the preimage of the domain of "bmap" under the function
13083 : * represented by "ma".
13084 : * In other words, plug in "ma" in the domain of "bmap".
13085 : * The result is a basic map that lives in the same space as "bmap"
13086 : * except that the domain has been replaced by the domain space of "ma".
13087 : */
13088 0 : __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13089 : __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13090 : {
13091 0 : return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13092 : }
13093 :
13094 : /* Compute the preimage of the range of "bmap" under the function
13095 : * represented by "ma".
13096 : * In other words, plug in "ma" in the range of "bmap".
13097 : * The result is a basic map that lives in the same space as "bmap"
13098 : * except that the range has been replaced by the domain space of "ma".
13099 : */
13100 0 : __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13101 : __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13102 : {
13103 0 : return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13104 : }
13105 :
13106 : /* Check if the range of "ma" is compatible with the domain or range
13107 : * (depending on "type") of "map".
13108 : * Return isl_stat_error if anything is wrong.
13109 : */
13110 0 : static isl_stat check_map_compatible_range_multi_aff(
13111 : __isl_keep isl_map *map, enum isl_dim_type type,
13112 : __isl_keep isl_multi_aff *ma)
13113 : {
13114 : isl_bool m;
13115 : isl_space *ma_space;
13116 :
13117 0 : ma_space = isl_multi_aff_get_space(ma);
13118 0 : m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
13119 0 : isl_space_free(ma_space);
13120 0 : if (m < 0)
13121 0 : return isl_stat_error;
13122 0 : if (!m)
13123 0 : isl_die(isl_map_get_ctx(map), isl_error_invalid,
13124 : "spaces don't match", return isl_stat_error);
13125 0 : return isl_stat_ok;
13126 : }
13127 :
13128 : /* Compute the preimage of the domain or range (depending on "type")
13129 : * of "map" under the function represented by "ma".
13130 : * In other words, plug in "ma" in the domain or range of "map".
13131 : * The result is a map that lives in the same space as "map"
13132 : * except that the domain or range has been replaced by
13133 : * the domain space of "ma".
13134 : *
13135 : * The parameters are assumed to have been aligned.
13136 : */
13137 0 : static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13138 : enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13139 : {
13140 : int i;
13141 : isl_space *space;
13142 :
13143 0 : map = isl_map_cow(map);
13144 0 : ma = isl_multi_aff_align_divs(ma);
13145 0 : if (!map || !ma)
13146 : goto error;
13147 0 : if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13148 0 : goto error;
13149 :
13150 0 : for (i = 0; i < map->n; ++i) {
13151 0 : map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13152 : isl_multi_aff_copy(ma));
13153 0 : if (!map->p[i])
13154 0 : goto error;
13155 : }
13156 :
13157 0 : space = isl_multi_aff_get_domain_space(ma);
13158 0 : space = isl_space_set(isl_map_get_space(map), type, space);
13159 :
13160 0 : isl_space_free(map->dim);
13161 0 : map->dim = space;
13162 0 : if (!map->dim)
13163 0 : goto error;
13164 :
13165 0 : isl_multi_aff_free(ma);
13166 0 : if (map->n > 1)
13167 0 : ISL_F_CLR(map, ISL_MAP_DISJOINT);
13168 0 : ISL_F_CLR(map, ISL_SET_NORMALIZED);
13169 0 : return map;
13170 : error:
13171 0 : isl_multi_aff_free(ma);
13172 0 : isl_map_free(map);
13173 0 : return NULL;
13174 : }
13175 :
13176 : /* Compute the preimage of the domain or range (depending on "type")
13177 : * of "map" under the function represented by "ma".
13178 : * In other words, plug in "ma" in the domain or range of "map".
13179 : * The result is a map that lives in the same space as "map"
13180 : * except that the domain or range has been replaced by
13181 : * the domain space of "ma".
13182 : */
13183 0 : __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13184 : enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13185 : {
13186 : isl_bool aligned;
13187 :
13188 0 : if (!map || !ma)
13189 : goto error;
13190 :
13191 0 : aligned = isl_map_space_has_equal_params(map, ma->space);
13192 0 : if (aligned < 0)
13193 0 : goto error;
13194 0 : if (aligned)
13195 0 : return map_preimage_multi_aff(map, type, ma);
13196 :
13197 0 : if (isl_map_check_named_params(map) < 0)
13198 0 : goto error;
13199 0 : if (!isl_space_has_named_params(ma->space))
13200 0 : isl_die(map->ctx, isl_error_invalid,
13201 : "unaligned unnamed parameters", goto error);
13202 0 : map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13203 0 : ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13204 :
13205 0 : return map_preimage_multi_aff(map, type, ma);
13206 : error:
13207 0 : isl_multi_aff_free(ma);
13208 0 : return isl_map_free(map);
13209 : }
13210 :
13211 : /* Compute the preimage of "set" under the function represented by "ma".
13212 : * In other words, plug in "ma" in "set". The result is a set
13213 : * that lives in the domain space of "ma".
13214 : */
13215 0 : __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13216 : __isl_take isl_multi_aff *ma)
13217 : {
13218 0 : return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13219 : }
13220 :
13221 : /* Compute the preimage of the domain of "map" under the function
13222 : * represented by "ma".
13223 : * In other words, plug in "ma" in the domain of "map".
13224 : * The result is a map that lives in the same space as "map"
13225 : * except that the domain has been replaced by the domain space of "ma".
13226 : */
13227 0 : __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13228 : __isl_take isl_multi_aff *ma)
13229 : {
13230 0 : return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13231 : }
13232 :
13233 : /* Compute the preimage of the range of "map" under the function
13234 : * represented by "ma".
13235 : * In other words, plug in "ma" in the range of "map".
13236 : * The result is a map that lives in the same space as "map"
13237 : * except that the range has been replaced by the domain space of "ma".
13238 : */
13239 0 : __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13240 : __isl_take isl_multi_aff *ma)
13241 : {
13242 0 : return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
13243 : }
13244 :
13245 : /* Compute the preimage of "map" under the function represented by "pma".
13246 : * In other words, plug in "pma" in the domain or range of "map".
13247 : * The result is a map that lives in the same space as "map",
13248 : * except that the space of type "type" has been replaced by
13249 : * the domain space of "pma".
13250 : *
13251 : * The parameters of "map" and "pma" are assumed to have been aligned.
13252 : */
13253 0 : static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
13254 : __isl_take isl_map *map, enum isl_dim_type type,
13255 : __isl_take isl_pw_multi_aff *pma)
13256 : {
13257 : int i;
13258 : isl_map *res;
13259 :
13260 0 : if (!pma)
13261 0 : goto error;
13262 :
13263 0 : if (pma->n == 0) {
13264 0 : isl_pw_multi_aff_free(pma);
13265 0 : res = isl_map_empty(isl_map_get_space(map));
13266 0 : isl_map_free(map);
13267 0 : return res;
13268 : }
13269 :
13270 0 : res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13271 : isl_multi_aff_copy(pma->p[0].maff));
13272 0 : if (type == isl_dim_in)
13273 0 : res = isl_map_intersect_domain(res,
13274 : isl_map_copy(pma->p[0].set));
13275 : else
13276 0 : res = isl_map_intersect_range(res,
13277 : isl_map_copy(pma->p[0].set));
13278 :
13279 0 : for (i = 1; i < pma->n; ++i) {
13280 : isl_map *res_i;
13281 :
13282 0 : res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
13283 : isl_multi_aff_copy(pma->p[i].maff));
13284 0 : if (type == isl_dim_in)
13285 0 : res_i = isl_map_intersect_domain(res_i,
13286 : isl_map_copy(pma->p[i].set));
13287 : else
13288 0 : res_i = isl_map_intersect_range(res_i,
13289 : isl_map_copy(pma->p[i].set));
13290 0 : res = isl_map_union(res, res_i);
13291 : }
13292 :
13293 0 : isl_pw_multi_aff_free(pma);
13294 0 : isl_map_free(map);
13295 0 : return res;
13296 : error:
13297 0 : isl_pw_multi_aff_free(pma);
13298 0 : isl_map_free(map);
13299 0 : return NULL;
13300 : }
13301 :
13302 : /* Compute the preimage of "map" under the function represented by "pma".
13303 : * In other words, plug in "pma" in the domain or range of "map".
13304 : * The result is a map that lives in the same space as "map",
13305 : * except that the space of type "type" has been replaced by
13306 : * the domain space of "pma".
13307 : */
13308 0 : __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
13309 : enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
13310 : {
13311 : isl_bool aligned;
13312 :
13313 0 : if (!map || !pma)
13314 : goto error;
13315 :
13316 0 : aligned = isl_map_space_has_equal_params(map, pma->dim);
13317 0 : if (aligned < 0)
13318 0 : goto error;
13319 0 : if (aligned)
13320 0 : return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13321 :
13322 0 : if (isl_map_check_named_params(map) < 0)
13323 0 : goto error;
13324 0 : if (isl_pw_multi_aff_check_named_params(pma) < 0)
13325 0 : goto error;
13326 0 : map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
13327 0 : pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
13328 :
13329 0 : return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
13330 : error:
13331 0 : isl_pw_multi_aff_free(pma);
13332 0 : return isl_map_free(map);
13333 : }
13334 :
13335 : /* Compute the preimage of "set" under the function represented by "pma".
13336 : * In other words, plug in "pma" in "set". The result is a set
13337 : * that lives in the domain space of "pma".
13338 : */
13339 0 : __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
13340 : __isl_take isl_pw_multi_aff *pma)
13341 : {
13342 0 : return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
13343 : }
13344 :
13345 : /* Compute the preimage of the domain of "map" under the function
13346 : * represented by "pma".
13347 : * In other words, plug in "pma" in the domain of "map".
13348 : * The result is a map that lives in the same space as "map",
13349 : * except that domain space has been replaced by the domain space of "pma".
13350 : */
13351 0 : __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
13352 : __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13353 : {
13354 0 : return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
13355 : }
13356 :
13357 : /* Compute the preimage of the range of "map" under the function
13358 : * represented by "pma".
13359 : * In other words, plug in "pma" in the range of "map".
13360 : * The result is a map that lives in the same space as "map",
13361 : * except that range space has been replaced by the domain space of "pma".
13362 : */
13363 0 : __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
13364 : __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
13365 : {
13366 0 : return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
13367 : }
13368 :
13369 : /* Compute the preimage of "map" under the function represented by "mpa".
13370 : * In other words, plug in "mpa" in the domain or range of "map".
13371 : * The result is a map that lives in the same space as "map",
13372 : * except that the space of type "type" has been replaced by
13373 : * the domain space of "mpa".
13374 : *
13375 : * If the map does not involve any constraints that refer to the
13376 : * dimensions of the substituted space, then the only possible
13377 : * effect of "mpa" on the map is to map the space to a different space.
13378 : * We create a separate isl_multi_aff to effectuate this change
13379 : * in order to avoid spurious splitting of the map along the pieces
13380 : * of "mpa".
13381 : * If "mpa" has a non-trivial explicit domain, however,
13382 : * then the full substitution should be performed.
13383 : */
13384 0 : __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
13385 : enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
13386 : {
13387 : int n;
13388 : isl_bool full;
13389 : isl_pw_multi_aff *pma;
13390 :
13391 0 : if (!map || !mpa)
13392 : goto error;
13393 :
13394 0 : n = isl_map_dim(map, type);
13395 0 : full = isl_map_involves_dims(map, type, 0, n);
13396 0 : if (full >= 0 && !full)
13397 0 : full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
13398 0 : if (full < 0)
13399 0 : goto error;
13400 0 : if (!full) {
13401 : isl_space *space;
13402 : isl_multi_aff *ma;
13403 :
13404 0 : space = isl_multi_pw_aff_get_space(mpa);
13405 0 : isl_multi_pw_aff_free(mpa);
13406 0 : ma = isl_multi_aff_zero(space);
13407 0 : return isl_map_preimage_multi_aff(map, type, ma);
13408 : }
13409 :
13410 0 : pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
13411 0 : return isl_map_preimage_pw_multi_aff(map, type, pma);
13412 : error:
13413 0 : isl_map_free(map);
13414 0 : isl_multi_pw_aff_free(mpa);
13415 0 : return NULL;
13416 : }
13417 :
13418 : /* Compute the preimage of "map" under the function represented by "mpa".
13419 : * In other words, plug in "mpa" in the domain "map".
13420 : * The result is a map that lives in the same space as "map",
13421 : * except that domain space has been replaced by the domain space of "mpa".
13422 : */
13423 0 : __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
13424 : __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
13425 : {
13426 0 : return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
13427 : }
13428 :
13429 : /* Compute the preimage of "set" by the function represented by "mpa".
13430 : * In other words, plug in "mpa" in "set".
13431 : */
13432 0 : __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
13433 : __isl_take isl_multi_pw_aff *mpa)
13434 : {
13435 0 : return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
13436 : }
13437 :
13438 : /* Return a copy of the equality constraints of "bset" as a matrix.
13439 : */
13440 0 : __isl_give isl_mat *isl_basic_set_extract_equalities(
13441 : __isl_keep isl_basic_set *bset)
13442 : {
13443 : isl_ctx *ctx;
13444 : unsigned total;
13445 :
13446 0 : if (!bset)
13447 0 : return NULL;
13448 :
13449 0 : ctx = isl_basic_set_get_ctx(bset);
13450 0 : total = 1 + isl_basic_set_dim(bset, isl_dim_all);
13451 0 : return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
13452 : }
13453 :
13454 : /* Are the "n" "coefficients" starting at "first" of the integer division
13455 : * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
13456 : * to each other?
13457 : * The "coefficient" at position 0 is the denominator.
13458 : * The "coefficient" at position 1 is the constant term.
13459 : */
13460 0 : isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
13461 : int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
13462 : unsigned first, unsigned n)
13463 : {
13464 0 : if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
13465 0 : return isl_bool_error;
13466 0 : if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
13467 0 : return isl_bool_error;
13468 0 : return isl_seq_eq(bmap1->div[pos1] + first,
13469 0 : bmap2->div[pos2] + first, n);
13470 : }
13471 :
13472 : /* Are the integer division expressions at position "pos1" in "bmap1" and
13473 : * "pos2" in "bmap2" equal to each other, except that the constant terms
13474 : * are different?
13475 : */
13476 0 : isl_bool isl_basic_map_equal_div_expr_except_constant(
13477 : __isl_keep isl_basic_map *bmap1, int pos1,
13478 : __isl_keep isl_basic_map *bmap2, int pos2)
13479 : {
13480 : isl_bool equal;
13481 : unsigned total;
13482 :
13483 0 : if (!bmap1 || !bmap2)
13484 0 : return isl_bool_error;
13485 0 : total = isl_basic_map_total_dim(bmap1);
13486 0 : if (total != isl_basic_map_total_dim(bmap2))
13487 0 : isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
13488 : "incomparable div expressions", return isl_bool_error);
13489 0 : equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13490 : 0, 1);
13491 0 : if (equal < 0 || !equal)
13492 0 : return equal;
13493 0 : equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13494 : 1, 1);
13495 0 : if (equal < 0 || equal)
13496 0 : return isl_bool_not(equal);
13497 0 : return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
13498 : 2, total);
13499 : }
13500 :
13501 : /* Replace the numerator of the constant term of the integer division
13502 : * expression at position "div" in "bmap" by "value".
13503 : * The caller guarantees that this does not change the meaning
13504 : * of the input.
13505 : */
13506 0 : __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
13507 : __isl_take isl_basic_map *bmap, int div, int value)
13508 : {
13509 0 : if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
13510 0 : return isl_basic_map_free(bmap);
13511 :
13512 0 : isl_int_set_si(bmap->div[div][1], value);
13513 :
13514 0 : return bmap;
13515 : }
13516 :
13517 : /* Is the point "inner" internal to inequality constraint "ineq"
13518 : * of "bset"?
13519 : * The point is considered to be internal to the inequality constraint,
13520 : * if it strictly lies on the positive side of the inequality constraint,
13521 : * or if it lies on the constraint and the constraint is lexico-positive.
13522 : */
13523 0 : static isl_bool is_internal(__isl_keep isl_vec *inner,
13524 : __isl_keep isl_basic_set *bset, int ineq)
13525 : {
13526 : isl_ctx *ctx;
13527 : int pos;
13528 : unsigned total;
13529 :
13530 0 : if (!inner || !bset)
13531 0 : return isl_bool_error;
13532 :
13533 0 : ctx = isl_basic_set_get_ctx(bset);
13534 0 : isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13535 : &ctx->normalize_gcd);
13536 0 : if (!isl_int_is_zero(ctx->normalize_gcd))
13537 0 : return isl_int_is_nonneg(ctx->normalize_gcd);
13538 :
13539 0 : total = isl_basic_set_dim(bset, isl_dim_all);
13540 0 : pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13541 0 : return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13542 : }
13543 :
13544 : /* Tighten the inequality constraints of "bset" that are outward with respect
13545 : * to the point "vec".
13546 : * That is, tighten the constraints that are not satisfied by "vec".
13547 : *
13548 : * "vec" is a point internal to some superset S of "bset" that is used
13549 : * to make the subsets of S disjoint, by tightening one half of the constraints
13550 : * that separate two subsets. In particular, the constraints of S
13551 : * are all satisfied by "vec" and should not be tightened.
13552 : * Of the internal constraints, those that have "vec" on the outside
13553 : * are tightened. The shared facet is included in the adjacent subset
13554 : * with the opposite constraint.
13555 : * For constraints that saturate "vec", this criterion cannot be used
13556 : * to determine which of the two sides should be tightened.
13557 : * Instead, the sign of the first non-zero coefficient is used
13558 : * to make this choice. Note that this second criterion is never used
13559 : * on the constraints of S since "vec" is interior to "S".
13560 : */
13561 0 : __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13562 : __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13563 : {
13564 : int j;
13565 :
13566 0 : bset = isl_basic_set_cow(bset);
13567 0 : if (!bset)
13568 0 : return NULL;
13569 0 : for (j = 0; j < bset->n_ineq; ++j) {
13570 : isl_bool internal;
13571 :
13572 0 : internal = is_internal(vec, bset, j);
13573 0 : if (internal < 0)
13574 0 : return isl_basic_set_free(bset);
13575 0 : if (internal)
13576 0 : continue;
13577 0 : isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13578 : }
13579 :
13580 0 : return bset;
13581 : }
13582 :
13583 : /* Replace the variables x of type "type" starting at "first" in "bmap"
13584 : * by x' with x = M x' with M the matrix trans.
13585 : * That is, replace the corresponding coefficients c by c M.
13586 : *
13587 : * The transformation matrix should be a square matrix.
13588 : */
13589 0 : __isl_give isl_basic_map *isl_basic_map_transform_dims(
13590 : __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
13591 : __isl_take isl_mat *trans)
13592 : {
13593 : unsigned pos;
13594 :
13595 0 : bmap = isl_basic_map_cow(bmap);
13596 0 : if (!bmap || !trans)
13597 : goto error;
13598 :
13599 0 : if (trans->n_row != trans->n_col)
13600 0 : isl_die(trans->ctx, isl_error_invalid,
13601 : "expecting square transformation matrix", goto error);
13602 0 : if (first + trans->n_row > isl_basic_map_dim(bmap, type))
13603 0 : isl_die(trans->ctx, isl_error_invalid,
13604 : "oversized transformation matrix", goto error);
13605 :
13606 0 : pos = isl_basic_map_offset(bmap, type) + first;
13607 :
13608 0 : if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
13609 : isl_mat_copy(trans)) < 0)
13610 0 : goto error;
13611 0 : if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
13612 : isl_mat_copy(trans)) < 0)
13613 0 : goto error;
13614 0 : if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
13615 : isl_mat_copy(trans)) < 0)
13616 0 : goto error;
13617 :
13618 0 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
13619 0 : ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
13620 :
13621 0 : isl_mat_free(trans);
13622 0 : return bmap;
13623 : error:
13624 0 : isl_mat_free(trans);
13625 0 : isl_basic_map_free(bmap);
13626 0 : return NULL;
13627 : }
13628 :
13629 : /* Replace the variables x of type "type" starting at "first" in "bset"
13630 : * by x' with x = M x' with M the matrix trans.
13631 : * That is, replace the corresponding coefficients c by c M.
13632 : *
13633 : * The transformation matrix should be a square matrix.
13634 : */
13635 0 : __isl_give isl_basic_set *isl_basic_set_transform_dims(
13636 : __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
13637 : __isl_take isl_mat *trans)
13638 : {
13639 0 : return isl_basic_map_transform_dims(bset, type, first, trans);
13640 : }
|