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 * Copyright 2018-2019 Cerebras Systems
9 *
10 * Use of this software is governed by the MIT license
11 *
12 * Written by Sven Verdoolaege, K.U.Leuven, Departement
13 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
14 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
15 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
16 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
17 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
18 * B.P. 105 - 78153 Le Chesnay, France
19 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
20 * CS 42112, 75589 Paris Cedex 12, France
21 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
22 */
23
24 #include <string.h>
25 #include <isl_ctx_private.h>
26 #include <isl_map_private.h>
27 #include <isl_blk.h>
28 #include <isl_id_private.h>
29 #include <isl/constraint.h>
30 #include "isl_space_private.h"
31 #include "isl_equalities.h"
32 #include <isl_lp_private.h>
33 #include <isl_seq.h>
34 #include <isl/set.h>
35 #include <isl/map.h>
36 #include <isl_reordering.h>
37 #include "isl_sample.h"
38 #include <isl_sort.h>
39 #include "isl_tab.h"
40 #include <isl/vec.h>
41 #include <isl_mat_private.h>
42 #include <isl_vec_private.h>
43 #include <isl_dim_map.h>
44 #include <isl_local_space_private.h>
45 #include <isl_aff_private.h>
46 #include <isl_options_private.h>
47 #include <isl_morph.h>
48 #include <isl_val_private.h>
49 #include <isl_printer_private.h>
50
51 #include <bset_to_bmap.c>
52 #include <bset_from_bmap.c>
53 #include <set_to_map.c>
54 #include <set_from_map.c>
55
56 /* Treat "bset" as a basic map.
57 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
58 * this function performs a redundant cast.
59 */
const_bset_to_bmap(__isl_keep const isl_basic_set * bset)60 static __isl_keep const isl_basic_map *const_bset_to_bmap(
61 __isl_keep const isl_basic_set *bset)
62 {
63 return (const isl_basic_map *) bset;
64 }
65
66 #undef TYPE
67 #define TYPE isl_basic_map
68 #include "has_single_reference_templ.c"
69
pos(__isl_keep isl_space * space,enum isl_dim_type type)70 static unsigned pos(__isl_keep isl_space *space, enum isl_dim_type type)
71 {
72 switch (type) {
73 case isl_dim_param: return 1;
74 case isl_dim_in: return 1 + space->nparam;
75 case isl_dim_out: return 1 + space->nparam + space->n_in;
76 default: return 0;
77 }
78 }
79
isl_basic_map_dim(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)80 isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
81 enum isl_dim_type type)
82 {
83 if (!bmap)
84 return isl_size_error;
85 switch (type) {
86 case isl_dim_cst: return 1;
87 case isl_dim_param:
88 case isl_dim_in:
89 case isl_dim_out: return isl_space_dim(bmap->dim, type);
90 case isl_dim_div: return bmap->n_div;
91 case isl_dim_all: return isl_basic_map_total_dim(bmap);
92 default: return 0;
93 }
94 }
95
96 /* Return the space of "map".
97 */
isl_map_peek_space(__isl_keep const isl_map * map)98 __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
99 {
100 return map ? map->dim : NULL;
101 }
102
103 /* Return the space of "set".
104 */
isl_set_peek_space(__isl_keep isl_set * set)105 __isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
106 {
107 return isl_map_peek_space(set_to_map(set));
108 }
109
isl_map_dim(__isl_keep isl_map * map,enum isl_dim_type type)110 isl_size isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
111 {
112 return isl_space_dim(isl_map_peek_space(map), type);
113 }
114
isl_set_dim(__isl_keep isl_set * set,enum isl_dim_type type)115 isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
116 {
117 return isl_map_dim(set_to_map(set), type);
118 }
119
120 /* Return the position of the variables of the given type
121 * within the sequence of variables of "bmap".
122 */
isl_basic_map_var_offset(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)123 isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
124 enum isl_dim_type type)
125 {
126 isl_space *space;
127
128 space = isl_basic_map_peek_space(bmap);
129 if (!space)
130 return isl_size_error;
131
132 switch (type) {
133 case isl_dim_param:
134 case isl_dim_in:
135 case isl_dim_out: return isl_space_offset(space, type);
136 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
137 case isl_dim_cst:
138 default:
139 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
140 "invalid dimension type", return isl_size_error);
141 }
142 }
143
144 /* Return the position of the variables of the given type
145 * within the sequence of variables of "bset".
146 */
isl_basic_set_var_offset(__isl_keep isl_basic_set * bset,enum isl_dim_type type)147 isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
148 enum isl_dim_type type)
149 {
150 return isl_basic_map_var_offset(bset_to_bmap(bset), type);
151 }
152
153 /* Return the position of the coefficients of the variables of the given type
154 * within the sequence of coefficients of "bmap".
155 */
isl_basic_map_offset(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)156 unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
157 enum isl_dim_type type)
158 {
159 switch (type) {
160 case isl_dim_cst: return 0;
161 case isl_dim_param:
162 case isl_dim_in:
163 case isl_dim_out:
164 case isl_dim_div: return 1 + isl_basic_map_var_offset(bmap, type);
165 default: return 0;
166 }
167 }
168
isl_basic_set_offset(__isl_keep isl_basic_set * bset,enum isl_dim_type type)169 unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
170 enum isl_dim_type type)
171 {
172 return isl_basic_map_offset(bset, type);
173 }
174
map_offset(__isl_keep isl_map * map,enum isl_dim_type type)175 static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
176 {
177 return pos(map->dim, type);
178 }
179
isl_basic_set_dim(__isl_keep isl_basic_set * bset,enum isl_dim_type type)180 isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,
181 enum isl_dim_type type)
182 {
183 return isl_basic_map_dim(bset, type);
184 }
185
isl_basic_set_n_dim(__isl_keep isl_basic_set * bset)186 isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
187 {
188 return isl_basic_set_dim(bset, isl_dim_set);
189 }
190
isl_basic_set_n_param(__isl_keep isl_basic_set * bset)191 isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
192 {
193 return isl_basic_set_dim(bset, isl_dim_param);
194 }
195
isl_basic_set_total_dim(__isl_keep const isl_basic_set * bset)196 isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
197 {
198 return isl_basic_map_total_dim(const_bset_to_bmap(bset));
199 }
200
isl_set_n_dim(__isl_keep isl_set * set)201 isl_size isl_set_n_dim(__isl_keep isl_set *set)
202 {
203 return isl_set_dim(set, isl_dim_set);
204 }
205
isl_set_n_param(__isl_keep isl_set * set)206 isl_size isl_set_n_param(__isl_keep isl_set *set)
207 {
208 return isl_set_dim(set, isl_dim_param);
209 }
210
isl_basic_map_total_dim(__isl_keep const isl_basic_map * bmap)211 isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
212 {
213 isl_size dim;
214
215 if (!bmap)
216 return isl_size_error;
217 dim = isl_space_dim(bmap->dim, isl_dim_all);
218 if (dim < 0)
219 return isl_size_error;
220 return dim + bmap->n_div;
221 }
222
223 /* Return the number of equality constraints in the description of "bmap".
224 * Return isl_size_error on error.
225 */
isl_basic_map_n_equality(__isl_keep isl_basic_map * bmap)226 isl_size isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
227 {
228 if (!bmap)
229 return isl_size_error;
230 return bmap->n_eq;
231 }
232
233 /* Return the number of equality constraints in the description of "bset".
234 * Return isl_size_error on error.
235 */
isl_basic_set_n_equality(__isl_keep isl_basic_set * bset)236 isl_size isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
237 {
238 return isl_basic_map_n_equality(bset_to_bmap(bset));
239 }
240
241 /* Return the number of inequality constraints in the description of "bmap".
242 * Return isl_size_error on error.
243 */
isl_basic_map_n_inequality(__isl_keep isl_basic_map * bmap)244 isl_size isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
245 {
246 if (!bmap)
247 return isl_size_error;
248 return bmap->n_ineq;
249 }
250
251 /* Return the number of inequality constraints in the description of "bset".
252 * Return isl_size_error on error.
253 */
isl_basic_set_n_inequality(__isl_keep isl_basic_set * bset)254 isl_size isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
255 {
256 return isl_basic_map_n_inequality(bset_to_bmap(bset));
257 }
258
259 /* Do "bmap1" and "bmap2" have the same parameters?
260 */
isl_basic_map_has_equal_params(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)261 static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
262 __isl_keep isl_basic_map *bmap2)
263 {
264 isl_space *space1, *space2;
265
266 space1 = isl_basic_map_peek_space(bmap1);
267 space2 = isl_basic_map_peek_space(bmap2);
268 return isl_space_has_equal_params(space1, space2);
269 }
270
271 /* Do "map1" and "map2" have the same parameters?
272 */
isl_map_has_equal_params(__isl_keep isl_map * map1,__isl_keep isl_map * map2)273 isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
274 __isl_keep isl_map *map2)
275 {
276 isl_space *space1, *space2;
277
278 space1 = isl_map_peek_space(map1);
279 space2 = isl_map_peek_space(map2);
280 return isl_space_has_equal_params(space1, space2);
281 }
282
283 /* Do "map" and "set" have the same parameters?
284 */
isl_map_set_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_set * set)285 static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
286 __isl_keep isl_set *set)
287 {
288 return isl_map_has_equal_params(map, set_to_map(set));
289 }
290
291 /* Is the tuple of type "type" of "bmap" the same as the single tuple of "bset"?
292 */
isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_basic_set * bset)293 static isl_bool isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map *bmap,
294 enum isl_dim_type type, __isl_keep isl_basic_set *bset)
295 {
296 isl_space *bmap_space, *bset_space;
297
298 bmap_space = isl_basic_map_peek_space(bmap);
299 bset_space = isl_basic_set_peek_space(bset);
300 return isl_space_tuple_is_equal(bmap_space, type,
301 bset_space, isl_dim_set);
302 }
303
304 /* Is the tuple of type "type" of "map" the same as the single tuple of "set"?
305 */
isl_map_set_tuple_is_equal(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_set * set)306 static isl_bool isl_map_set_tuple_is_equal(__isl_keep isl_map *map,
307 enum isl_dim_type type, __isl_keep isl_set *set)
308 {
309 return isl_map_tuple_is_equal(map, type, set_to_map(set), isl_dim_set);
310 }
311
isl_map_compatible_domain(__isl_keep isl_map * map,__isl_keep isl_set * set)312 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
313 __isl_keep isl_set *set)
314 {
315 isl_bool m;
316 if (!map || !set)
317 return isl_bool_error;
318 m = isl_map_has_equal_params(map, set_to_map(set));
319 if (m < 0 || !m)
320 return m;
321 return isl_map_set_tuple_is_equal(map, isl_dim_in, set);
322 }
323
isl_basic_map_compatible_domain(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)324 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
325 __isl_keep isl_basic_set *bset)
326 {
327 isl_bool m;
328 if (!bmap || !bset)
329 return isl_bool_error;
330 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
331 if (m < 0 || !m)
332 return m;
333 return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_in, bset);
334 }
335
isl_map_compatible_range(__isl_keep isl_map * map,__isl_keep isl_set * set)336 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
337 __isl_keep isl_set *set)
338 {
339 isl_bool m;
340 if (!map || !set)
341 return isl_bool_error;
342 m = isl_map_has_equal_params(map, set_to_map(set));
343 if (m < 0 || !m)
344 return m;
345 return isl_map_set_tuple_is_equal(map, isl_dim_out, set);
346 }
347
isl_basic_map_compatible_range(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)348 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
349 __isl_keep isl_basic_set *bset)
350 {
351 isl_bool m;
352 if (!bmap || !bset)
353 return isl_bool_error;
354 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
355 if (m < 0 || !m)
356 return m;
357 return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_out, bset);
358 }
359
isl_basic_map_get_ctx(__isl_keep isl_basic_map * bmap)360 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
361 {
362 return bmap ? bmap->ctx : NULL;
363 }
364
isl_basic_set_get_ctx(__isl_keep isl_basic_set * bset)365 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
366 {
367 return bset ? bset->ctx : NULL;
368 }
369
isl_map_get_ctx(__isl_keep isl_map * map)370 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
371 {
372 return map ? map->ctx : NULL;
373 }
374
isl_set_get_ctx(__isl_keep isl_set * set)375 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
376 {
377 return set ? set->ctx : NULL;
378 }
379
380 /* Return the space of "bmap".
381 */
isl_basic_map_peek_space(__isl_keep const isl_basic_map * bmap)382 __isl_keep isl_space *isl_basic_map_peek_space(
383 __isl_keep const isl_basic_map *bmap)
384 {
385 return bmap ? bmap->dim : NULL;
386 }
387
388 /* Return the space of "bset".
389 */
isl_basic_set_peek_space(__isl_keep isl_basic_set * bset)390 __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
391 {
392 return isl_basic_map_peek_space(bset_to_bmap(bset));
393 }
394
isl_basic_map_get_space(__isl_keep isl_basic_map * bmap)395 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
396 {
397 return isl_space_copy(isl_basic_map_peek_space(bmap));
398 }
399
isl_basic_set_get_space(__isl_keep isl_basic_set * bset)400 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
401 {
402 return isl_basic_map_get_space(bset_to_bmap(bset));
403 }
404
405 /* Return the space of "bmap".
406 * This may be either a copy or the space itself
407 * if there is only one reference to "bmap".
408 * This allows the space to be modified inplace
409 * if both the basic map and its space have only a single reference.
410 * The caller is not allowed to modify "bmap" between this call and
411 * a subsequent call to isl_basic_map_restore_space.
412 * The only exception is that isl_basic_map_free can be called instead.
413 */
isl_basic_map_take_space(__isl_keep isl_basic_map * bmap)414 static __isl_give isl_space *isl_basic_map_take_space(
415 __isl_keep isl_basic_map *bmap)
416 {
417 isl_space *space;
418
419 if (!bmap)
420 return NULL;
421 if (bmap->ref != 1)
422 return isl_basic_map_get_space(bmap);
423 space = bmap->dim;
424 bmap->dim = NULL;
425 return space;
426 }
427
428 /* Set the space of "bmap" to "space", where the space of "bmap" may be missing
429 * due to a preceding call to isl_basic_map_take_space.
430 * However, in this case, "bmap" only has a single reference and
431 * then the call to isl_basic_map_cow has no effect.
432 */
isl_basic_map_restore_space(__isl_take isl_basic_map * bmap,__isl_take isl_space * space)433 static __isl_give isl_basic_map *isl_basic_map_restore_space(
434 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
435 {
436 if (!bmap || !space)
437 goto error;
438
439 if (bmap->dim == space) {
440 isl_space_free(space);
441 return bmap;
442 }
443
444 bmap = isl_basic_map_cow(bmap);
445 if (!bmap)
446 goto error;
447 isl_space_free(bmap->dim);
448 bmap->dim = space;
449
450 return bmap;
451 error:
452 isl_basic_map_free(bmap);
453 isl_space_free(space);
454 return NULL;
455 }
456
457 /* Extract the divs in "bmap" as a matrix.
458 */
isl_basic_map_get_divs(__isl_keep isl_basic_map * bmap)459 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
460 {
461 int i;
462 isl_ctx *ctx;
463 isl_mat *div;
464 isl_size v_div;
465 unsigned cols;
466
467 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
468 if (v_div < 0)
469 return NULL;
470
471 ctx = isl_basic_map_get_ctx(bmap);
472 cols = 1 + 1 + v_div + bmap->n_div;
473 div = isl_mat_alloc(ctx, bmap->n_div, cols);
474 if (!div)
475 return NULL;
476
477 for (i = 0; i < bmap->n_div; ++i)
478 isl_seq_cpy(div->row[i], bmap->div[i], cols);
479
480 return div;
481 }
482
483 /* Extract the divs in "bset" as a matrix.
484 */
isl_basic_set_get_divs(__isl_keep isl_basic_set * bset)485 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
486 {
487 return isl_basic_map_get_divs(bset);
488 }
489
isl_basic_map_get_local_space(__isl_keep isl_basic_map * bmap)490 __isl_give isl_local_space *isl_basic_map_get_local_space(
491 __isl_keep isl_basic_map *bmap)
492 {
493 isl_mat *div;
494
495 if (!bmap)
496 return NULL;
497
498 div = isl_basic_map_get_divs(bmap);
499 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
500 }
501
isl_basic_set_get_local_space(__isl_keep isl_basic_set * bset)502 __isl_give isl_local_space *isl_basic_set_get_local_space(
503 __isl_keep isl_basic_set *bset)
504 {
505 return isl_basic_map_get_local_space(bset);
506 }
507
508 /* For each known div d = floor(f/m), add the constraints
509 *
510 * f - m d >= 0
511 * -(f-(m-1)) + m d >= 0
512 *
513 * Do not finalize the result.
514 */
add_known_div_constraints(__isl_take isl_basic_map * bmap)515 static __isl_give isl_basic_map *add_known_div_constraints(
516 __isl_take isl_basic_map *bmap)
517 {
518 int i;
519 isl_size n_div;
520
521 n_div = isl_basic_map_dim(bmap, isl_dim_div);
522 if (n_div < 0)
523 return isl_basic_map_free(bmap);
524 if (n_div == 0)
525 return bmap;
526 bmap = isl_basic_map_cow(bmap);
527 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
528 if (!bmap)
529 return NULL;
530 for (i = 0; i < n_div; ++i) {
531 if (isl_int_is_zero(bmap->div[i][0]))
532 continue;
533 bmap = isl_basic_map_add_div_constraints(bmap, i);
534 }
535
536 return bmap;
537 }
538
isl_basic_map_from_local_space(__isl_take isl_local_space * ls)539 __isl_give isl_basic_map *isl_basic_map_from_local_space(
540 __isl_take isl_local_space *ls)
541 {
542 int i;
543 isl_size n_div;
544 isl_basic_map *bmap;
545
546 n_div = isl_local_space_dim(ls, isl_dim_div);
547 if (n_div < 0)
548 ls = isl_local_space_free(ls);
549 if (!ls)
550 return NULL;
551
552 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
553 n_div, 0, 2 * n_div);
554
555 for (i = 0; i < n_div; ++i)
556 if (isl_basic_map_alloc_div(bmap) < 0)
557 goto error;
558
559 for (i = 0; i < n_div; ++i)
560 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
561 bmap = add_known_div_constraints(bmap);
562
563 isl_local_space_free(ls);
564 return bmap;
565 error:
566 isl_local_space_free(ls);
567 isl_basic_map_free(bmap);
568 return NULL;
569 }
570
isl_basic_set_from_local_space(__isl_take isl_local_space * ls)571 __isl_give isl_basic_set *isl_basic_set_from_local_space(
572 __isl_take isl_local_space *ls)
573 {
574 return isl_basic_map_from_local_space(ls);
575 }
576
isl_map_get_space(__isl_keep isl_map * map)577 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
578 {
579 return isl_space_copy(isl_map_peek_space(map));
580 }
581
isl_set_get_space(__isl_keep isl_set * set)582 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
583 {
584 if (!set)
585 return NULL;
586 return isl_space_copy(set->dim);
587 }
588
589 /* Return the space of "map".
590 * This may be either a copy or the space itself
591 * if there is only one reference to "map".
592 * This allows the space to be modified inplace
593 * if both the map and its space have only a single reference.
594 * The caller is not allowed to modify "map" between this call and
595 * a subsequent call to isl_map_restore_space.
596 * The only exception is that isl_map_free can be called instead.
597 */
isl_map_take_space(__isl_keep isl_map * map)598 static __isl_give isl_space *isl_map_take_space(__isl_keep isl_map *map)
599 {
600 isl_space *space;
601
602 if (!map)
603 return NULL;
604 if (map->ref != 1)
605 return isl_map_get_space(map);
606 space = map->dim;
607 map->dim = NULL;
608 return space;
609 }
610
611 /* Set the space of "map" to "space", where the space of "map" may be missing
612 * due to a preceding call to isl_map_take_space.
613 * However, in this case, "map" only has a single reference and
614 * then the call to isl_map_cow has no effect.
615 */
isl_map_restore_space(__isl_take isl_map * map,__isl_take isl_space * space)616 static __isl_give isl_map *isl_map_restore_space(__isl_take isl_map *map,
617 __isl_take isl_space *space)
618 {
619 if (!map || !space)
620 goto error;
621
622 if (map->dim == space) {
623 isl_space_free(space);
624 return map;
625 }
626
627 map = isl_map_cow(map);
628 if (!map)
629 goto error;
630 isl_space_free(map->dim);
631 map->dim = space;
632
633 return map;
634 error:
635 isl_map_free(map);
636 isl_space_free(space);
637 return NULL;
638 }
639
isl_basic_map_set_tuple_name(__isl_take isl_basic_map * bmap,enum isl_dim_type type,const char * s)640 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
641 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
642 {
643 isl_space *space;
644
645 space = isl_basic_map_take_space(bmap);
646 space = isl_space_set_tuple_name(space, type, s);
647 bmap = isl_basic_map_restore_space(bmap, space);
648 bmap = isl_basic_map_finalize(bmap);
649 return bmap;
650 }
651
isl_basic_set_set_tuple_name(__isl_take isl_basic_set * bset,const char * s)652 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
653 __isl_take isl_basic_set *bset, const char *s)
654 {
655 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
656 }
657
isl_basic_map_get_tuple_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type)658 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
659 enum isl_dim_type type)
660 {
661 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
662 }
663
isl_map_set_tuple_name(__isl_take isl_map * map,enum isl_dim_type type,const char * s)664 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
665 enum isl_dim_type type, const char *s)
666 {
667 int i;
668 isl_space *space;
669
670 map = isl_map_cow(map);
671 if (!map)
672 return NULL;
673
674 for (i = 0; i < map->n; ++i) {
675 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
676 if (!map->p[i])
677 goto error;
678 }
679
680 space = isl_map_take_space(map);
681 space = isl_space_set_tuple_name(space, type, s);
682 map = isl_map_restore_space(map, space);
683
684 return map;
685 error:
686 isl_map_free(map);
687 return NULL;
688 }
689
690 /* Replace the identifier of the tuple of type "type" by "id".
691 */
isl_basic_map_set_tuple_id(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_id * id)692 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
693 __isl_take isl_basic_map *bmap,
694 enum isl_dim_type type, __isl_take isl_id *id)
695 {
696 isl_space *space;
697
698 space = isl_basic_map_take_space(bmap);
699 space = isl_space_set_tuple_id(space, type, id);
700 bmap = isl_basic_map_restore_space(bmap, space);
701 bmap = isl_basic_map_finalize(bmap);
702 return bmap;
703 }
704
705 /* Replace the identifier of the tuple by "id".
706 */
isl_basic_set_set_tuple_id(__isl_take isl_basic_set * bset,__isl_take isl_id * id)707 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
708 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
709 {
710 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
711 }
712
713 /* Does the input or output tuple have a name?
714 */
isl_map_has_tuple_name(__isl_keep isl_map * map,enum isl_dim_type type)715 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
716 {
717 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
718 }
719
isl_map_get_tuple_name(__isl_keep isl_map * map,enum isl_dim_type type)720 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
721 enum isl_dim_type type)
722 {
723 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
724 }
725
isl_set_set_tuple_name(__isl_take isl_set * set,const char * s)726 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
727 const char *s)
728 {
729 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
730 isl_dim_set, s));
731 }
732
isl_map_set_tuple_id(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_id * id)733 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
734 enum isl_dim_type type, __isl_take isl_id *id)
735 {
736 isl_space *space;
737
738 space = isl_map_take_space(map);
739 space = isl_space_set_tuple_id(space, type, id);
740 map = isl_map_restore_space(map, space);
741
742 return isl_map_reset_space(map, isl_map_get_space(map));
743 }
744
isl_set_set_tuple_id(__isl_take isl_set * set,__isl_take isl_id * id)745 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
746 __isl_take isl_id *id)
747 {
748 return isl_map_set_tuple_id(set, isl_dim_set, id);
749 }
750
isl_map_reset_tuple_id(__isl_take isl_map * map,enum isl_dim_type type)751 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
752 enum isl_dim_type type)
753 {
754 isl_space *space;
755
756 space = isl_map_take_space(map);
757 space = isl_space_reset_tuple_id(space, type);
758 map = isl_map_restore_space(map, space);
759
760 return isl_map_reset_space(map, isl_map_get_space(map));
761 }
762
isl_set_reset_tuple_id(__isl_take isl_set * set)763 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
764 {
765 return isl_map_reset_tuple_id(set, isl_dim_set);
766 }
767
isl_map_has_tuple_id(__isl_keep isl_map * map,enum isl_dim_type type)768 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
769 {
770 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
771 }
772
isl_map_get_tuple_id(__isl_keep isl_map * map,enum isl_dim_type type)773 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
774 enum isl_dim_type type)
775 {
776 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
777 }
778
isl_set_has_tuple_id(__isl_keep isl_set * set)779 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
780 {
781 return isl_map_has_tuple_id(set, isl_dim_set);
782 }
783
isl_set_get_tuple_id(__isl_keep isl_set * set)784 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
785 {
786 return isl_map_get_tuple_id(set, isl_dim_set);
787 }
788
789 /* Does the set tuple have a name?
790 */
isl_set_has_tuple_name(__isl_keep isl_set * set)791 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
792 {
793 if (!set)
794 return isl_bool_error;
795 return isl_space_has_tuple_name(set->dim, isl_dim_set);
796 }
797
798
isl_basic_set_get_tuple_name(__isl_keep isl_basic_set * bset)799 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
800 {
801 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
802 }
803
isl_set_get_tuple_name(__isl_keep isl_set * set)804 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
805 {
806 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
807 }
808
isl_basic_map_get_dim_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)809 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
810 enum isl_dim_type type, unsigned pos)
811 {
812 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
813 }
814
isl_basic_set_get_dim_name(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned pos)815 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
816 enum isl_dim_type type, unsigned pos)
817 {
818 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
819 }
820
821 /* Does the given dimension have a name?
822 */
isl_map_has_dim_name(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)823 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
824 enum isl_dim_type type, unsigned pos)
825 {
826 if (!map)
827 return isl_bool_error;
828 return isl_space_has_dim_name(map->dim, type, pos);
829 }
830
isl_map_get_dim_name(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)831 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
832 enum isl_dim_type type, unsigned pos)
833 {
834 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
835 }
836
isl_set_get_dim_name(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)837 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
838 enum isl_dim_type type, unsigned pos)
839 {
840 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
841 }
842
843 /* Does the given dimension have a name?
844 */
isl_set_has_dim_name(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)845 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
846 enum isl_dim_type type, unsigned pos)
847 {
848 if (!set)
849 return isl_bool_error;
850 return isl_space_has_dim_name(set->dim, type, pos);
851 }
852
isl_basic_map_set_dim_name(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,const char * s)853 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
854 __isl_take isl_basic_map *bmap,
855 enum isl_dim_type type, unsigned pos, const char *s)
856 {
857 isl_space *space;
858
859 space = isl_basic_map_take_space(bmap);
860 space = isl_space_set_dim_name(space, type, pos, s);
861 bmap = isl_basic_map_restore_space(bmap, space);
862 return isl_basic_map_finalize(bmap);
863 }
864
isl_map_set_dim_name(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,const char * s)865 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
866 enum isl_dim_type type, unsigned pos, const char *s)
867 {
868 int i;
869 isl_space *space;
870
871 map = isl_map_cow(map);
872 if (!map)
873 return NULL;
874
875 for (i = 0; i < map->n; ++i) {
876 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
877 if (!map->p[i])
878 goto error;
879 }
880
881 space = isl_map_take_space(map);
882 space = isl_space_set_dim_name(space, type, pos, s);
883 map = isl_map_restore_space(map, space);
884
885 return map;
886 error:
887 isl_map_free(map);
888 return NULL;
889 }
890
isl_basic_set_set_dim_name(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,const char * s)891 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
892 __isl_take isl_basic_set *bset,
893 enum isl_dim_type type, unsigned pos, const char *s)
894 {
895 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
896 type, pos, s));
897 }
898
isl_set_set_dim_name(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,const char * s)899 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
900 enum isl_dim_type type, unsigned pos, const char *s)
901 {
902 return set_from_map(isl_map_set_dim_name(set_to_map(set),
903 type, pos, s));
904 }
905
isl_basic_map_has_dim_id(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)906 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
907 enum isl_dim_type type, unsigned pos)
908 {
909 if (!bmap)
910 return isl_bool_error;
911 return isl_space_has_dim_id(bmap->dim, type, pos);
912 }
913
isl_basic_set_get_dim_id(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned pos)914 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
915 enum isl_dim_type type, unsigned pos)
916 {
917 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
918 }
919
isl_map_has_dim_id(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)920 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
921 enum isl_dim_type type, unsigned pos)
922 {
923 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
924 }
925
isl_map_get_dim_id(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)926 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
927 enum isl_dim_type type, unsigned pos)
928 {
929 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
930 }
931
isl_set_has_dim_id(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)932 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
933 enum isl_dim_type type, unsigned pos)
934 {
935 return isl_map_has_dim_id(set, type, pos);
936 }
937
isl_set_get_dim_id(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)938 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
939 enum isl_dim_type type, unsigned pos)
940 {
941 return isl_map_get_dim_id(set, type, pos);
942 }
943
isl_map_set_dim_id(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_id * id)944 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
945 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
946 {
947 isl_space *space;
948
949 space = isl_map_take_space(map);
950 space = isl_space_set_dim_id(space, type, pos, id);
951 map = isl_map_restore_space(map, space);
952
953 return isl_map_reset_space(map, isl_map_get_space(map));
954 }
955
isl_set_set_dim_id(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_id * id)956 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
957 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
958 {
959 return isl_map_set_dim_id(set, type, pos, id);
960 }
961
isl_map_find_dim_by_id(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_id * id)962 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
963 __isl_keep isl_id *id)
964 {
965 if (!map)
966 return -1;
967 return isl_space_find_dim_by_id(map->dim, type, id);
968 }
969
isl_set_find_dim_by_id(__isl_keep isl_set * set,enum isl_dim_type type,__isl_keep isl_id * id)970 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
971 __isl_keep isl_id *id)
972 {
973 return isl_map_find_dim_by_id(set, type, id);
974 }
975
976 /* Return the position of the dimension of the given type and name
977 * in "bmap".
978 * Return -1 if no such dimension can be found.
979 */
isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,const char * name)980 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
981 enum isl_dim_type type, const char *name)
982 {
983 if (!bmap)
984 return -1;
985 return isl_space_find_dim_by_name(bmap->dim, type, name);
986 }
987
isl_map_find_dim_by_name(__isl_keep isl_map * map,enum isl_dim_type type,const char * name)988 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
989 const char *name)
990 {
991 if (!map)
992 return -1;
993 return isl_space_find_dim_by_name(map->dim, type, name);
994 }
995
isl_set_find_dim_by_name(__isl_keep isl_set * set,enum isl_dim_type type,const char * name)996 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
997 const char *name)
998 {
999 return isl_map_find_dim_by_name(set, type, name);
1000 }
1001
1002 /* Check whether equality i of bset is a pure stride constraint
1003 * on a single dimension, i.e., of the form
1004 *
1005 * v = k e
1006 *
1007 * with k a constant and e an existentially quantified variable.
1008 */
isl_basic_set_eq_is_stride(__isl_keep isl_basic_set * bset,int i)1009 isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
1010 {
1011 isl_size nparam;
1012 isl_size d;
1013 isl_size n_div;
1014 int pos1;
1015 int pos2;
1016
1017 nparam = isl_basic_set_dim(bset, isl_dim_param);
1018 d = isl_basic_set_dim(bset, isl_dim_set);
1019 n_div = isl_basic_set_dim(bset, isl_dim_div);
1020 if (nparam < 0 || d < 0 || n_div < 0)
1021 return isl_bool_error;
1022
1023 if (!isl_int_is_zero(bset->eq[i][0]))
1024 return isl_bool_false;
1025
1026 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
1027 return isl_bool_false;
1028 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
1029 if (pos1 == -1)
1030 return isl_bool_false;
1031 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
1032 d - pos1 - 1) != -1)
1033 return isl_bool_false;
1034
1035 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
1036 if (pos2 == -1)
1037 return isl_bool_false;
1038 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
1039 n_div - pos2 - 1) != -1)
1040 return isl_bool_false;
1041 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
1042 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
1043 return isl_bool_false;
1044
1045 return isl_bool_true;
1046 }
1047
1048 /* Reset the user pointer on all identifiers of parameters and tuples
1049 * of the space of "map".
1050 */
isl_map_reset_user(__isl_take isl_map * map)1051 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
1052 {
1053 isl_space *space;
1054
1055 space = isl_map_get_space(map);
1056 space = isl_space_reset_user(space);
1057 map = isl_map_reset_space(map, space);
1058
1059 return map;
1060 }
1061
1062 /* Reset the user pointer on all identifiers of parameters and tuples
1063 * of the space of "set".
1064 */
isl_set_reset_user(__isl_take isl_set * set)1065 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
1066 {
1067 return isl_map_reset_user(set);
1068 }
1069
isl_basic_map_is_rational(__isl_keep isl_basic_map * bmap)1070 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
1071 {
1072 if (!bmap)
1073 return isl_bool_error;
1074 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
1075 }
1076
1077 /* Has "map" been marked as a rational map?
1078 * In particular, have all basic maps in "map" been marked this way?
1079 * An empty map is not considered to be rational.
1080 * Maps where only some of the basic maps are marked rational
1081 * are not allowed.
1082 */
isl_map_is_rational(__isl_keep isl_map * map)1083 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
1084 {
1085 int i;
1086 isl_bool rational;
1087
1088 if (!map)
1089 return isl_bool_error;
1090 if (map->n == 0)
1091 return isl_bool_false;
1092 rational = isl_basic_map_is_rational(map->p[0]);
1093 if (rational < 0)
1094 return rational;
1095 for (i = 1; i < map->n; ++i) {
1096 isl_bool rational_i;
1097
1098 rational_i = isl_basic_map_is_rational(map->p[i]);
1099 if (rational_i < 0)
1100 return rational_i;
1101 if (rational != rational_i)
1102 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1103 "mixed rational and integer basic maps "
1104 "not supported", return isl_bool_error);
1105 }
1106
1107 return rational;
1108 }
1109
1110 /* Has "set" been marked as a rational set?
1111 * In particular, have all basic set in "set" been marked this way?
1112 * An empty set is not considered to be rational.
1113 * Sets where only some of the basic sets are marked rational
1114 * are not allowed.
1115 */
isl_set_is_rational(__isl_keep isl_set * set)1116 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1117 {
1118 return isl_map_is_rational(set);
1119 }
1120
isl_basic_set_is_rational(__isl_keep isl_basic_set * bset)1121 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1122 {
1123 return isl_basic_map_is_rational(bset);
1124 }
1125
1126 /* Does "bmap" contain any rational points?
1127 *
1128 * If "bmap" has an equality for each dimension, equating the dimension
1129 * to an integer constant, then it has no rational points, even if it
1130 * is marked as rational.
1131 */
isl_basic_map_has_rational(__isl_keep isl_basic_map * bmap)1132 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1133 {
1134 isl_bool has_rational = isl_bool_true;
1135 isl_size total;
1136
1137 if (!bmap)
1138 return isl_bool_error;
1139 if (isl_basic_map_plain_is_empty(bmap))
1140 return isl_bool_false;
1141 if (!isl_basic_map_is_rational(bmap))
1142 return isl_bool_false;
1143 bmap = isl_basic_map_copy(bmap);
1144 bmap = isl_basic_map_implicit_equalities(bmap);
1145 total = isl_basic_map_dim(bmap, isl_dim_all);
1146 if (total < 0)
1147 return isl_bool_error;
1148 if (bmap->n_eq == total) {
1149 int i, j;
1150 for (i = 0; i < bmap->n_eq; ++i) {
1151 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1152 if (j < 0)
1153 break;
1154 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1155 !isl_int_is_negone(bmap->eq[i][1 + j]))
1156 break;
1157 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1158 total - j - 1);
1159 if (j >= 0)
1160 break;
1161 }
1162 if (i == bmap->n_eq)
1163 has_rational = isl_bool_false;
1164 }
1165 isl_basic_map_free(bmap);
1166
1167 return has_rational;
1168 }
1169
1170 /* Does "map" contain any rational points?
1171 */
isl_map_has_rational(__isl_keep isl_map * map)1172 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1173 {
1174 int i;
1175 isl_bool has_rational;
1176
1177 if (!map)
1178 return isl_bool_error;
1179 for (i = 0; i < map->n; ++i) {
1180 has_rational = isl_basic_map_has_rational(map->p[i]);
1181 if (has_rational < 0 || has_rational)
1182 return has_rational;
1183 }
1184 return isl_bool_false;
1185 }
1186
1187 /* Does "set" contain any rational points?
1188 */
isl_set_has_rational(__isl_keep isl_set * set)1189 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1190 {
1191 return isl_map_has_rational(set);
1192 }
1193
1194 /* Is this basic set a parameter domain?
1195 */
isl_basic_set_is_params(__isl_keep isl_basic_set * bset)1196 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1197 {
1198 if (!bset)
1199 return isl_bool_error;
1200 return isl_space_is_params(bset->dim);
1201 }
1202
1203 /* Is this set a parameter domain?
1204 */
isl_set_is_params(__isl_keep isl_set * set)1205 isl_bool isl_set_is_params(__isl_keep isl_set *set)
1206 {
1207 if (!set)
1208 return isl_bool_error;
1209 return isl_space_is_params(set->dim);
1210 }
1211
1212 /* Is this map actually a parameter domain?
1213 * Users should never call this function. Outside of isl,
1214 * a map can never be a parameter domain.
1215 */
isl_map_is_params(__isl_keep isl_map * map)1216 isl_bool isl_map_is_params(__isl_keep isl_map *map)
1217 {
1218 if (!map)
1219 return isl_bool_error;
1220 return isl_space_is_params(map->dim);
1221 }
1222
basic_map_init(isl_ctx * ctx,__isl_take isl_basic_map * bmap,unsigned extra,unsigned n_eq,unsigned n_ineq)1223 static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1224 __isl_take isl_basic_map *bmap, unsigned extra,
1225 unsigned n_eq, unsigned n_ineq)
1226 {
1227 int i;
1228 isl_space *space = isl_basic_map_peek_space(bmap);
1229 isl_size n_var = isl_space_dim(space, isl_dim_all);
1230 size_t row_size = 1 + n_var + extra;
1231
1232 bmap->ctx = ctx;
1233 isl_ctx_ref(ctx);
1234
1235 if (n_var < 0)
1236 return isl_basic_map_free(bmap);
1237
1238 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1239 if (isl_blk_is_error(bmap->block))
1240 goto error;
1241
1242 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1243 if ((n_ineq + n_eq) && !bmap->ineq)
1244 goto error;
1245
1246 if (extra == 0) {
1247 bmap->block2 = isl_blk_empty();
1248 bmap->div = NULL;
1249 } else {
1250 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1251 if (isl_blk_is_error(bmap->block2))
1252 goto error;
1253
1254 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1255 if (!bmap->div)
1256 goto error;
1257 }
1258
1259 for (i = 0; i < n_ineq + n_eq; ++i)
1260 bmap->ineq[i] = bmap->block.data + i * row_size;
1261
1262 for (i = 0; i < extra; ++i)
1263 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1264
1265 bmap->ref = 1;
1266 bmap->flags = 0;
1267 bmap->c_size = n_eq + n_ineq;
1268 bmap->eq = bmap->ineq + n_ineq;
1269 bmap->extra = extra;
1270 bmap->n_eq = 0;
1271 bmap->n_ineq = 0;
1272 bmap->n_div = 0;
1273 bmap->sample = NULL;
1274
1275 return bmap;
1276 error:
1277 isl_basic_map_free(bmap);
1278 return NULL;
1279 }
1280
isl_basic_set_alloc(isl_ctx * ctx,unsigned nparam,unsigned dim,unsigned extra,unsigned n_eq,unsigned n_ineq)1281 __isl_give isl_basic_set *isl_basic_set_alloc(isl_ctx *ctx,
1282 unsigned nparam, unsigned dim, unsigned extra,
1283 unsigned n_eq, unsigned n_ineq)
1284 {
1285 struct isl_basic_map *bmap;
1286 isl_space *space;
1287
1288 space = isl_space_set_alloc(ctx, nparam, dim);
1289 if (!space)
1290 return NULL;
1291
1292 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1293 return bset_from_bmap(bmap);
1294 }
1295
isl_basic_set_alloc_space(__isl_take isl_space * space,unsigned extra,unsigned n_eq,unsigned n_ineq)1296 __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *space,
1297 unsigned extra, unsigned n_eq, unsigned n_ineq)
1298 {
1299 struct isl_basic_map *bmap;
1300 if (!space)
1301 return NULL;
1302 isl_assert(space->ctx, space->n_in == 0, goto error);
1303 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1304 return bset_from_bmap(bmap);
1305 error:
1306 isl_space_free(space);
1307 return NULL;
1308 }
1309
isl_basic_map_alloc_space(__isl_take isl_space * space,unsigned extra,unsigned n_eq,unsigned n_ineq)1310 __isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1311 unsigned extra, unsigned n_eq, unsigned n_ineq)
1312 {
1313 struct isl_basic_map *bmap;
1314
1315 if (!space)
1316 return NULL;
1317 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1318 if (!bmap)
1319 goto error;
1320 bmap->dim = space;
1321
1322 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1323 error:
1324 isl_space_free(space);
1325 return NULL;
1326 }
1327
isl_basic_map_alloc(isl_ctx * ctx,unsigned nparam,unsigned in,unsigned out,unsigned extra,unsigned n_eq,unsigned n_ineq)1328 __isl_give isl_basic_map *isl_basic_map_alloc(isl_ctx *ctx,
1329 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1330 unsigned n_eq, unsigned n_ineq)
1331 {
1332 struct isl_basic_map *bmap;
1333 isl_space *space;
1334
1335 space = isl_space_alloc(ctx, nparam, in, out);
1336 if (!space)
1337 return NULL;
1338
1339 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1340 return bmap;
1341 }
1342
dup_constraints(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)1343 static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1344 __isl_keep isl_basic_map *src)
1345 {
1346 int i;
1347 isl_size total = isl_basic_map_dim(src, isl_dim_all);
1348
1349 if (!dst || total < 0)
1350 return isl_basic_map_free(dst);
1351
1352 for (i = 0; i < src->n_eq; ++i) {
1353 int j = isl_basic_map_alloc_equality(dst);
1354 if (j < 0)
1355 return isl_basic_map_free(dst);
1356 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1357 }
1358
1359 for (i = 0; i < src->n_ineq; ++i) {
1360 int j = isl_basic_map_alloc_inequality(dst);
1361 if (j < 0)
1362 return isl_basic_map_free(dst);
1363 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1364 }
1365
1366 for (i = 0; i < src->n_div; ++i) {
1367 int j = isl_basic_map_alloc_div(dst);
1368 if (j < 0)
1369 return isl_basic_map_free(dst);
1370 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1371 }
1372 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1373 return dst;
1374 }
1375
isl_basic_map_dup(__isl_keep isl_basic_map * bmap)1376 __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1377 {
1378 struct isl_basic_map *dup;
1379
1380 if (!bmap)
1381 return NULL;
1382 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1383 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1384 dup = dup_constraints(dup, bmap);
1385 if (!dup)
1386 return NULL;
1387 dup->flags = bmap->flags;
1388 dup->sample = isl_vec_copy(bmap->sample);
1389 return dup;
1390 }
1391
isl_basic_set_dup(__isl_keep isl_basic_set * bset)1392 __isl_give isl_basic_set *isl_basic_set_dup(__isl_keep isl_basic_set *bset)
1393 {
1394 struct isl_basic_map *dup;
1395
1396 dup = isl_basic_map_dup(bset_to_bmap(bset));
1397 return bset_from_bmap(dup);
1398 }
1399
isl_basic_set_copy(__isl_keep isl_basic_set * bset)1400 __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1401 {
1402 if (!bset)
1403 return NULL;
1404
1405 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1406 bset->ref++;
1407 return bset;
1408 }
1409 return isl_basic_set_dup(bset);
1410 }
1411
isl_set_copy(__isl_keep isl_set * set)1412 __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1413 {
1414 if (!set)
1415 return NULL;
1416
1417 set->ref++;
1418 return set;
1419 }
1420
isl_basic_map_copy(__isl_keep isl_basic_map * bmap)1421 __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1422 {
1423 if (!bmap)
1424 return NULL;
1425
1426 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1427 bmap->ref++;
1428 return bmap;
1429 }
1430 bmap = isl_basic_map_dup(bmap);
1431 if (bmap)
1432 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1433 return bmap;
1434 }
1435
isl_map_copy(__isl_keep isl_map * map)1436 __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1437 {
1438 if (!map)
1439 return NULL;
1440
1441 map->ref++;
1442 return map;
1443 }
1444
isl_basic_map_free(__isl_take isl_basic_map * bmap)1445 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1446 {
1447 if (!bmap)
1448 return NULL;
1449
1450 if (--bmap->ref > 0)
1451 return NULL;
1452
1453 isl_ctx_deref(bmap->ctx);
1454 free(bmap->div);
1455 isl_blk_free(bmap->ctx, bmap->block2);
1456 free(bmap->ineq);
1457 isl_blk_free(bmap->ctx, bmap->block);
1458 isl_vec_free(bmap->sample);
1459 isl_space_free(bmap->dim);
1460 free(bmap);
1461
1462 return NULL;
1463 }
1464
isl_basic_set_free(__isl_take isl_basic_set * bset)1465 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1466 {
1467 return isl_basic_map_free(bset_to_bmap(bset));
1468 }
1469
room_for_con(__isl_keep isl_basic_map * bmap,unsigned n)1470 static int room_for_con(__isl_keep isl_basic_map *bmap, unsigned n)
1471 {
1472 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1473 }
1474
1475 /* Check that "bset" does not involve any parameters.
1476 */
isl_basic_set_check_no_params(__isl_keep isl_basic_set * bset)1477 isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1478 {
1479 isl_size nparam;
1480
1481 nparam = isl_basic_set_dim(bset, isl_dim_param);
1482 if (nparam < 0)
1483 return isl_stat_error;
1484 if (nparam != 0)
1485 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1486 "basic set should not have any parameters",
1487 return isl_stat_error);
1488 return isl_stat_ok;
1489 }
1490
1491 /* Check that "bset" does not involve any local variables.
1492 */
isl_basic_set_check_no_locals(__isl_keep isl_basic_set * bset)1493 isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1494 {
1495 isl_size n_div;
1496
1497 n_div = isl_basic_set_dim(bset, isl_dim_div);
1498 if (n_div < 0)
1499 return isl_stat_error;
1500 if (n_div != 0)
1501 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1502 "basic set should not have any local variables",
1503 return isl_stat_error);
1504 return isl_stat_ok;
1505 }
1506
1507 #undef TYPE
1508 #define TYPE isl_map
1509
1510 #include "isl_check_named_params_templ.c"
1511
1512 #undef TYPE
1513 #define TYPE isl_basic_map
1514
1515 static
1516 #include "isl_check_named_params_templ.c"
1517
1518 /* Check that "bmap1" and "bmap2" have the same parameters,
1519 * reporting an error if they do not.
1520 */
isl_basic_map_check_equal_params(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)1521 static isl_stat isl_basic_map_check_equal_params(
1522 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1523 {
1524 isl_bool match;
1525
1526 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1527 if (match < 0)
1528 return isl_stat_error;
1529 if (!match)
1530 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1531 "parameters don't match", return isl_stat_error);
1532 return isl_stat_ok;
1533 }
1534
1535 #undef TYPE
1536 #define TYPE isl_map
1537
1538 #include "isl_align_params_bin_templ.c"
1539
1540 #undef SUFFIX
1541 #define SUFFIX set
1542 #undef ARG1
1543 #define ARG1 isl_map
1544 #undef ARG2
1545 #define ARG2 isl_set
1546
1547 #include "isl_align_params_templ.c"
1548
isl_map_align_params_map_map_and_test(__isl_keep isl_map * map1,__isl_keep isl_map * map2,isl_bool (* fn)(__isl_keep isl_map * map1,__isl_keep isl_map * map2))1549 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1550 __isl_keep isl_map *map2,
1551 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1552 {
1553 isl_bool r;
1554
1555 if (!map1 || !map2)
1556 return isl_bool_error;
1557 if (isl_map_has_equal_params(map1, map2))
1558 return fn(map1, map2);
1559 if (isl_map_check_named_params(map1) < 0)
1560 return isl_bool_error;
1561 if (isl_map_check_named_params(map2) < 0)
1562 return isl_bool_error;
1563 map1 = isl_map_copy(map1);
1564 map2 = isl_map_copy(map2);
1565 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1566 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1567 r = fn(map1, map2);
1568 isl_map_free(map1);
1569 isl_map_free(map2);
1570 return r;
1571 }
1572
isl_basic_map_alloc_equality(__isl_keep isl_basic_map * bmap)1573 int isl_basic_map_alloc_equality(__isl_keep isl_basic_map *bmap)
1574 {
1575 isl_size total;
1576 struct isl_ctx *ctx;
1577
1578 total = isl_basic_map_dim(bmap, isl_dim_all);
1579 if (total < 0)
1580 return -1;
1581 ctx = bmap->ctx;
1582 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1583 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1584 return -1);
1585 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1586 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1587 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1588 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1589 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1590 isl_int *t;
1591 int j = isl_basic_map_alloc_inequality(bmap);
1592 if (j < 0)
1593 return -1;
1594 t = bmap->ineq[j];
1595 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1596 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1597 bmap->eq[-1] = t;
1598 bmap->n_eq++;
1599 bmap->n_ineq--;
1600 bmap->eq--;
1601 return 0;
1602 }
1603 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + total,
1604 bmap->extra - bmap->n_div);
1605 return bmap->n_eq++;
1606 }
1607
isl_basic_set_alloc_equality(__isl_keep isl_basic_set * bset)1608 int isl_basic_set_alloc_equality(__isl_keep isl_basic_set *bset)
1609 {
1610 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1611 }
1612
isl_basic_map_free_equality(__isl_take isl_basic_map * bmap,unsigned n)1613 __isl_give isl_basic_map *isl_basic_map_free_equality(
1614 __isl_take isl_basic_map *bmap, unsigned n)
1615 {
1616 if (!bmap)
1617 return NULL;
1618 if (n > bmap->n_eq)
1619 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1620 "invalid number of equalities",
1621 isl_basic_map_free(bmap));
1622 bmap->n_eq -= n;
1623 return bmap;
1624 }
1625
isl_basic_set_free_equality(__isl_take isl_basic_set * bset,unsigned n)1626 __isl_give isl_basic_set *isl_basic_set_free_equality(
1627 __isl_take isl_basic_set *bset, unsigned n)
1628 {
1629 return bset_from_bmap(isl_basic_map_free_equality(bset_to_bmap(bset),
1630 n));
1631 }
1632
1633 /* Drop the equality constraint at position "pos",
1634 * preserving the order of the other equality constraints.
1635 */
isl_basic_map_drop_equality(__isl_keep isl_basic_map * bmap,unsigned pos)1636 int isl_basic_map_drop_equality(__isl_keep isl_basic_map *bmap, unsigned pos)
1637 {
1638 isl_int *t;
1639 int r;
1640
1641 if (!bmap)
1642 return -1;
1643 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1644
1645 t = bmap->eq[pos];
1646 bmap->n_eq--;
1647 for (r = pos; r < bmap->n_eq; ++r)
1648 bmap->eq[r] = bmap->eq[r + 1];
1649 bmap->eq[bmap->n_eq] = t;
1650
1651 return 0;
1652 }
1653
1654 /* Turn inequality "pos" of "bmap" into an equality.
1655 *
1656 * In particular, we move the inequality in front of the equalities
1657 * and move the last inequality in the position of the moved inequality.
1658 * Note that isl_tab_make_equalities_explicit depends on this particular
1659 * change in the ordering of the constraints.
1660 */
isl_basic_map_inequality_to_equality(__isl_keep isl_basic_map * bmap,unsigned pos)1661 void isl_basic_map_inequality_to_equality(
1662 __isl_keep isl_basic_map *bmap, unsigned pos)
1663 {
1664 isl_int *t;
1665
1666 t = bmap->ineq[pos];
1667 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1668 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1669 bmap->eq[-1] = t;
1670 bmap->n_eq++;
1671 bmap->n_ineq--;
1672 bmap->eq--;
1673 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1674 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1675 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1676 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1677 }
1678
room_for_ineq(__isl_keep isl_basic_map * bmap,unsigned n)1679 static int room_for_ineq(__isl_keep isl_basic_map *bmap, unsigned n)
1680 {
1681 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1682 }
1683
isl_basic_map_alloc_inequality(__isl_keep isl_basic_map * bmap)1684 int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1685 {
1686 isl_size total;
1687 struct isl_ctx *ctx;
1688
1689 total = isl_basic_map_dim(bmap, isl_dim_all);
1690 if (total < 0)
1691 return -1;
1692 ctx = bmap->ctx;
1693 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1694 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1695 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1696 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1697 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1698 isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1 + total,
1699 bmap->extra - bmap->n_div);
1700 return bmap->n_ineq++;
1701 }
1702
isl_basic_set_alloc_inequality(__isl_keep isl_basic_set * bset)1703 int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1704 {
1705 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1706 }
1707
isl_basic_map_free_inequality(__isl_take isl_basic_map * bmap,unsigned n)1708 __isl_give isl_basic_map *isl_basic_map_free_inequality(
1709 __isl_take isl_basic_map *bmap, unsigned n)
1710 {
1711 if (!bmap)
1712 return NULL;
1713 if (n > bmap->n_ineq)
1714 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1715 "invalid number of inequalities",
1716 return isl_basic_map_free(bmap));
1717 bmap->n_ineq -= n;
1718 return bmap;
1719 }
1720
isl_basic_set_free_inequality(__isl_take isl_basic_set * bset,unsigned n)1721 __isl_give isl_basic_set *isl_basic_set_free_inequality(
1722 __isl_take isl_basic_set *bset, unsigned n)
1723 {
1724 return bset_from_bmap(isl_basic_map_free_inequality(bset_to_bmap(bset),
1725 n));
1726 }
1727
isl_basic_map_drop_inequality(__isl_keep isl_basic_map * bmap,unsigned pos)1728 int isl_basic_map_drop_inequality(__isl_keep isl_basic_map *bmap, unsigned pos)
1729 {
1730 isl_int *t;
1731 if (!bmap)
1732 return -1;
1733 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1734
1735 if (pos != bmap->n_ineq - 1) {
1736 t = bmap->ineq[pos];
1737 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1738 bmap->ineq[bmap->n_ineq - 1] = t;
1739 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1740 }
1741 bmap->n_ineq--;
1742 return 0;
1743 }
1744
isl_basic_set_drop_inequality(__isl_keep isl_basic_set * bset,unsigned pos)1745 int isl_basic_set_drop_inequality(__isl_keep isl_basic_set *bset, unsigned pos)
1746 {
1747 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1748 }
1749
isl_basic_map_add_eq(__isl_take isl_basic_map * bmap,isl_int * eq)1750 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1751 isl_int *eq)
1752 {
1753 isl_bool empty;
1754 isl_size total;
1755 int k;
1756
1757 empty = isl_basic_map_plain_is_empty(bmap);
1758 if (empty < 0)
1759 return isl_basic_map_free(bmap);
1760 if (empty)
1761 return bmap;
1762
1763 bmap = isl_basic_map_cow(bmap);
1764 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1765 total = isl_basic_map_dim(bmap, isl_dim_all);
1766 if (total < 0)
1767 return isl_basic_map_free(bmap);
1768 k = isl_basic_map_alloc_equality(bmap);
1769 if (k < 0)
1770 goto error;
1771 isl_seq_cpy(bmap->eq[k], eq, 1 + total);
1772 return bmap;
1773 error:
1774 isl_basic_map_free(bmap);
1775 return NULL;
1776 }
1777
isl_basic_set_add_eq(__isl_take isl_basic_set * bset,isl_int * eq)1778 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1779 isl_int *eq)
1780 {
1781 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1782 }
1783
isl_basic_map_add_ineq(__isl_take isl_basic_map * bmap,isl_int * ineq)1784 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1785 isl_int *ineq)
1786 {
1787 isl_size total;
1788 int k;
1789
1790 bmap = isl_basic_map_cow(bmap);
1791 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1792 total = isl_basic_map_dim(bmap, isl_dim_all);
1793 if (total < 0)
1794 return isl_basic_map_free(bmap);
1795 k = isl_basic_map_alloc_inequality(bmap);
1796 if (k < 0)
1797 goto error;
1798 isl_seq_cpy(bmap->ineq[k], ineq, 1 + total);
1799 return bmap;
1800 error:
1801 isl_basic_map_free(bmap);
1802 return NULL;
1803 }
1804
isl_basic_set_add_ineq(__isl_take isl_basic_set * bset,isl_int * ineq)1805 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1806 isl_int *ineq)
1807 {
1808 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1809 }
1810
isl_basic_map_alloc_div(__isl_keep isl_basic_map * bmap)1811 int isl_basic_map_alloc_div(__isl_keep isl_basic_map *bmap)
1812 {
1813 isl_size total;
1814
1815 total = isl_basic_map_dim(bmap, isl_dim_all);
1816 if (total < 0)
1817 return -1;
1818 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1819 isl_seq_clr(bmap->div[bmap->n_div] + 1 + 1 + total,
1820 bmap->extra - bmap->n_div);
1821 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1822 return bmap->n_div++;
1823 }
1824
isl_basic_set_alloc_div(__isl_keep isl_basic_set * bset)1825 int isl_basic_set_alloc_div(__isl_keep isl_basic_set *bset)
1826 {
1827 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1828 }
1829
1830 #undef TYPE
1831 #define TYPE isl_basic_map
1832 #include "check_type_range_templ.c"
1833
1834 /* Check that there are "n" dimensions of type "type" starting at "first"
1835 * in "bset".
1836 */
isl_basic_set_check_range(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)1837 isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1838 enum isl_dim_type type, unsigned first, unsigned n)
1839 {
1840 return isl_basic_map_check_range(bset_to_bmap(bset),
1841 type, first, n);
1842 }
1843
1844 /* Insert an extra integer division, prescribed by "div", to "bmap"
1845 * at (integer division) position "pos".
1846 *
1847 * The integer division is first added at the end and then moved
1848 * into the right position.
1849 */
isl_basic_map_insert_div(__isl_take isl_basic_map * bmap,int pos,__isl_keep isl_vec * div)1850 __isl_give isl_basic_map *isl_basic_map_insert_div(
1851 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1852 {
1853 int i, k;
1854 isl_size total;
1855
1856 bmap = isl_basic_map_cow(bmap);
1857 total = isl_basic_map_dim(bmap, isl_dim_all);
1858 if (total < 0 || !div)
1859 return isl_basic_map_free(bmap);
1860
1861 if (div->size != 1 + 1 + total)
1862 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1863 "unexpected size", return isl_basic_map_free(bmap));
1864 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1865 return isl_basic_map_free(bmap);
1866
1867 bmap = isl_basic_map_extend(bmap, 1, 0, 2);
1868 k = isl_basic_map_alloc_div(bmap);
1869 if (k < 0)
1870 return isl_basic_map_free(bmap);
1871 isl_seq_cpy(bmap->div[k], div->el, div->size);
1872 isl_int_set_si(bmap->div[k][div->size], 0);
1873
1874 for (i = k; i > pos; --i)
1875 bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1876
1877 return bmap;
1878 }
1879
isl_basic_map_free_div(__isl_keep isl_basic_map * bmap,unsigned n)1880 isl_stat isl_basic_map_free_div(__isl_keep isl_basic_map *bmap, unsigned n)
1881 {
1882 if (!bmap)
1883 return isl_stat_error;
1884 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1885 bmap->n_div -= n;
1886 return isl_stat_ok;
1887 }
1888
add_constraints(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2,unsigned i_pos,unsigned o_pos)1889 static __isl_give isl_basic_map *add_constraints(
1890 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1891 unsigned i_pos, unsigned o_pos)
1892 {
1893 isl_size total, n_param, n_in, n_out, n_div;
1894 unsigned o_in, o_out;
1895 isl_ctx *ctx;
1896 isl_space *space;
1897 struct isl_dim_map *dim_map;
1898
1899 space = isl_basic_map_peek_space(bmap2);
1900 if (!bmap1 || !space)
1901 goto error;
1902
1903 total = isl_basic_map_dim(bmap1, isl_dim_all);
1904 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1905 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1906 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1907 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1908 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1909 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1910 if (total < 0 || n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
1911 goto error;
1912 ctx = isl_basic_map_get_ctx(bmap1);
1913 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1914 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1915 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1916 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1917 isl_dim_map_div(dim_map, bmap2, total);
1918
1919 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1920 error:
1921 isl_basic_map_free(bmap1);
1922 isl_basic_map_free(bmap2);
1923 return NULL;
1924 }
1925
isl_basic_map_extend(__isl_take isl_basic_map * base,unsigned extra,unsigned n_eq,unsigned n_ineq)1926 __isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
1927 unsigned extra, unsigned n_eq, unsigned n_ineq)
1928 {
1929 isl_space *space;
1930 struct isl_basic_map *ext;
1931 unsigned flags;
1932 int dims_ok;
1933
1934 if (!base)
1935 goto error;
1936
1937 dims_ok = base->extra >= base->n_div + extra;
1938
1939 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1940 room_for_ineq(base, n_ineq))
1941 return base;
1942
1943 extra += base->extra;
1944 n_eq += base->n_eq;
1945 n_ineq += base->n_ineq;
1946
1947 space = isl_basic_map_get_space(base);
1948 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1949 if (!ext)
1950 goto error;
1951
1952 if (dims_ok)
1953 ext->sample = isl_vec_copy(base->sample);
1954 flags = base->flags;
1955 ext = add_constraints(ext, base, 0, 0);
1956 if (ext) {
1957 ext->flags = flags;
1958 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1959 }
1960
1961 return ext;
1962
1963 error:
1964 isl_basic_map_free(base);
1965 return NULL;
1966 }
1967
isl_basic_set_extend(__isl_take isl_basic_set * base,unsigned extra,unsigned n_eq,unsigned n_ineq)1968 __isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,
1969 unsigned extra, unsigned n_eq, unsigned n_ineq)
1970 {
1971 return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
1972 extra, n_eq, n_ineq));
1973 }
1974
isl_basic_map_extend_constraints(__isl_take isl_basic_map * base,unsigned n_eq,unsigned n_ineq)1975 __isl_give isl_basic_map *isl_basic_map_extend_constraints(
1976 __isl_take isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1977 {
1978 return isl_basic_map_extend(base, 0, n_eq, n_ineq);
1979 }
1980
isl_basic_set_extend_constraints(__isl_take isl_basic_set * base,unsigned n_eq,unsigned n_ineq)1981 __isl_give isl_basic_set *isl_basic_set_extend_constraints(
1982 __isl_take isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1983 {
1984 isl_basic_map *bmap = bset_to_bmap(base);
1985 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1986 return bset_from_bmap(bmap);
1987 }
1988
isl_basic_set_cow(__isl_take isl_basic_set * bset)1989 __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1990 {
1991 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1992 }
1993
isl_basic_map_cow(__isl_take isl_basic_map * bmap)1994 __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1995 {
1996 if (!bmap)
1997 return NULL;
1998
1999 if (bmap->ref > 1) {
2000 bmap->ref--;
2001 bmap = isl_basic_map_dup(bmap);
2002 }
2003 if (bmap) {
2004 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
2005 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
2006 }
2007 return bmap;
2008 }
2009
2010 /* Clear all cached information in "map", either because it is about
2011 * to be modified or because it is being freed.
2012 * Always return the same pointer that is passed in.
2013 * This is needed for the use in isl_map_free.
2014 */
clear_caches(__isl_take isl_map * map)2015 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
2016 {
2017 isl_basic_map_free(map->cached_simple_hull[0]);
2018 isl_basic_map_free(map->cached_simple_hull[1]);
2019 map->cached_simple_hull[0] = NULL;
2020 map->cached_simple_hull[1] = NULL;
2021 return map;
2022 }
2023
isl_set_cow(__isl_take isl_set * set)2024 __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
2025 {
2026 return isl_map_cow(set);
2027 }
2028
2029 /* Return an isl_map that is equal to "map" and that has only
2030 * a single reference.
2031 *
2032 * If the original input already has only one reference, then
2033 * simply return it, but clear all cached information, since
2034 * it may be rendered invalid by the operations that will be
2035 * performed on the result.
2036 *
2037 * Otherwise, create a duplicate (without any cached information).
2038 */
isl_map_cow(__isl_take isl_map * map)2039 __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
2040 {
2041 if (!map)
2042 return NULL;
2043
2044 if (map->ref == 1)
2045 return clear_caches(map);
2046 map->ref--;
2047 return isl_map_dup(map);
2048 }
2049
swap_vars(struct isl_blk blk,isl_int * a,unsigned a_len,unsigned b_len)2050 static void swap_vars(struct isl_blk blk, isl_int *a,
2051 unsigned a_len, unsigned b_len)
2052 {
2053 isl_seq_cpy(blk.data, a+a_len, b_len);
2054 isl_seq_cpy(blk.data+b_len, a, a_len);
2055 isl_seq_cpy(a, blk.data, b_len+a_len);
2056 }
2057
isl_basic_map_swap_vars(__isl_take isl_basic_map * bmap,unsigned pos,unsigned n1,unsigned n2)2058 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
2059 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
2060 {
2061 int i;
2062 struct isl_blk blk;
2063
2064 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
2065 goto error;
2066
2067 if (n1 == 0 || n2 == 0)
2068 return bmap;
2069
2070 bmap = isl_basic_map_cow(bmap);
2071 if (!bmap)
2072 return NULL;
2073
2074 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2075 if (isl_blk_is_error(blk))
2076 goto error;
2077
2078 for (i = 0; i < bmap->n_eq; ++i)
2079 swap_vars(blk,
2080 bmap->eq[i] + pos, n1, n2);
2081
2082 for (i = 0; i < bmap->n_ineq; ++i)
2083 swap_vars(blk,
2084 bmap->ineq[i] + pos, n1, n2);
2085
2086 for (i = 0; i < bmap->n_div; ++i)
2087 swap_vars(blk,
2088 bmap->div[i]+1 + pos, n1, n2);
2089
2090 isl_blk_free(bmap->ctx, blk);
2091
2092 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2093 bmap = isl_basic_map_gauss(bmap, NULL);
2094 return isl_basic_map_finalize(bmap);
2095 error:
2096 isl_basic_map_free(bmap);
2097 return NULL;
2098 }
2099
2100 /* The given basic map has turned out to be empty.
2101 * Explicitly mark it as such and change the representation
2102 * to a canonical representation of the empty basic map.
2103 * Since the basic map has conflicting constraints,
2104 * it must have at least one constraint, except perhaps
2105 * if it was already explicitly marked as being empty.
2106 * Do nothing in the latter case.
2107 */
isl_basic_map_set_to_empty(__isl_take isl_basic_map * bmap)2108 __isl_give isl_basic_map *isl_basic_map_set_to_empty(
2109 __isl_take isl_basic_map *bmap)
2110 {
2111 int i = 0;
2112 isl_bool empty;
2113 isl_size total;
2114
2115 empty = isl_basic_map_plain_is_empty(bmap);
2116 if (empty < 0)
2117 return isl_basic_map_free(bmap);
2118 if (empty)
2119 return bmap;
2120 total = isl_basic_map_dim(bmap, isl_dim_all);
2121 if (total < 0)
2122 return isl_basic_map_free(bmap);
2123 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2124 return isl_basic_map_free(bmap);
2125 bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2126 if (!bmap)
2127 return NULL;
2128 if (bmap->n_eq > 0) {
2129 bmap = isl_basic_map_free_equality(bmap, bmap->n_eq - 1);
2130 if (!bmap)
2131 return NULL;
2132 } else {
2133 i = isl_basic_map_alloc_equality(bmap);
2134 if (i < 0)
2135 goto error;
2136 }
2137 isl_int_set_si(bmap->eq[i][0], 1);
2138 isl_seq_clr(bmap->eq[i]+1, total);
2139 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2140 isl_vec_free(bmap->sample);
2141 bmap->sample = NULL;
2142 return isl_basic_map_finalize(bmap);
2143 error:
2144 isl_basic_map_free(bmap);
2145 return NULL;
2146 }
2147
isl_basic_set_set_to_empty(__isl_take isl_basic_set * bset)2148 __isl_give isl_basic_set *isl_basic_set_set_to_empty(
2149 __isl_take isl_basic_set *bset)
2150 {
2151 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2152 }
2153
isl_basic_map_set_rational(__isl_take isl_basic_map * bmap)2154 __isl_give isl_basic_map *isl_basic_map_set_rational(
2155 __isl_take isl_basic_map *bmap)
2156 {
2157 if (!bmap)
2158 return NULL;
2159
2160 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2161 return bmap;
2162
2163 bmap = isl_basic_map_cow(bmap);
2164 if (!bmap)
2165 return NULL;
2166
2167 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2168
2169 return isl_basic_map_finalize(bmap);
2170 }
2171
isl_basic_set_set_rational(__isl_take isl_basic_set * bset)2172 __isl_give isl_basic_set *isl_basic_set_set_rational(
2173 __isl_take isl_basic_set *bset)
2174 {
2175 return isl_basic_map_set_rational(bset);
2176 }
2177
isl_basic_set_set_integral(__isl_take isl_basic_set * bset)2178 __isl_give isl_basic_set *isl_basic_set_set_integral(
2179 __isl_take isl_basic_set *bset)
2180 {
2181 if (!bset)
2182 return NULL;
2183
2184 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2185 return bset;
2186
2187 bset = isl_basic_set_cow(bset);
2188 if (!bset)
2189 return NULL;
2190
2191 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2192
2193 return isl_basic_set_finalize(bset);
2194 }
2195
isl_map_set_rational(__isl_take isl_map * map)2196 __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2197 {
2198 int i;
2199
2200 map = isl_map_cow(map);
2201 if (!map)
2202 return NULL;
2203 for (i = 0; i < map->n; ++i) {
2204 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2205 if (!map->p[i])
2206 goto error;
2207 }
2208 return map;
2209 error:
2210 isl_map_free(map);
2211 return NULL;
2212 }
2213
isl_set_set_rational(__isl_take isl_set * set)2214 __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2215 {
2216 return isl_map_set_rational(set);
2217 }
2218
2219 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2220 * of "bmap").
2221 */
swap_div(__isl_keep isl_basic_map * bmap,int a,int b)2222 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2223 {
2224 isl_int *t = bmap->div[a];
2225 bmap->div[a] = bmap->div[b];
2226 bmap->div[b] = t;
2227 }
2228
2229 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2230 * div definitions accordingly.
2231 */
isl_basic_map_swap_div(__isl_take isl_basic_map * bmap,int a,int b)2232 __isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2233 int a, int b)
2234 {
2235 int i;
2236 isl_size off;
2237
2238 off = isl_basic_map_var_offset(bmap, isl_dim_div);
2239 if (off < 0)
2240 return isl_basic_map_free(bmap);
2241
2242 swap_div(bmap, a, b);
2243
2244 for (i = 0; i < bmap->n_eq; ++i)
2245 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2246
2247 for (i = 0; i < bmap->n_ineq; ++i)
2248 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2249
2250 for (i = 0; i < bmap->n_div; ++i)
2251 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2252 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2253
2254 return bmap;
2255 }
2256
constraint_drop_vars(isl_int * c,unsigned n,unsigned rem)2257 static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2258 {
2259 isl_seq_cpy(c, c + n, rem);
2260 isl_seq_clr(c + rem, n);
2261 }
2262
2263 /* Drop n dimensions starting at first.
2264 *
2265 * In principle, this frees up some extra variables as the number
2266 * of columns remains constant, but we would have to extend
2267 * the div array too as the number of rows in this array is assumed
2268 * to be equal to extra.
2269 */
isl_basic_set_drop_dims(__isl_take isl_basic_set * bset,unsigned first,unsigned n)2270 __isl_give isl_basic_set *isl_basic_set_drop_dims(
2271 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2272 {
2273 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2274 }
2275
2276 /* Move "n" divs starting at "first" to the end of the list of divs.
2277 */
move_divs_last(__isl_take isl_basic_map * bmap,unsigned first,unsigned n)2278 static __isl_give isl_basic_map *move_divs_last(__isl_take isl_basic_map *bmap,
2279 unsigned first, unsigned n)
2280 {
2281 isl_int **div;
2282 int i;
2283
2284 if (first + n == bmap->n_div)
2285 return bmap;
2286
2287 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2288 if (!div)
2289 goto error;
2290 for (i = 0; i < n; ++i)
2291 div[i] = bmap->div[first + i];
2292 for (i = 0; i < bmap->n_div - first - n; ++i)
2293 bmap->div[first + i] = bmap->div[first + n + i];
2294 for (i = 0; i < n; ++i)
2295 bmap->div[bmap->n_div - n + i] = div[i];
2296 free(div);
2297 return bmap;
2298 error:
2299 isl_basic_map_free(bmap);
2300 return NULL;
2301 }
2302
2303 #undef TYPE
2304 #define TYPE isl_map
2305 static
2306 #include "check_type_range_templ.c"
2307
2308 /* Check that there are "n" dimensions of type "type" starting at "first"
2309 * in "set".
2310 */
isl_set_check_range(__isl_keep isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2311 isl_stat isl_set_check_range(__isl_keep isl_set *set,
2312 enum isl_dim_type type, unsigned first, unsigned n)
2313 {
2314 return isl_map_check_range(set_to_map(set), type, first, n);
2315 }
2316
2317 /* Drop "n" dimensions of type "type" starting at "first".
2318 * Perform the core computation, without cowing or
2319 * simplifying and finalizing the result.
2320 *
2321 * In principle, this frees up some extra variables as the number
2322 * of columns remains constant, but we would have to extend
2323 * the div array too as the number of rows in this array is assumed
2324 * to be equal to extra.
2325 */
isl_basic_map_drop_core(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2326 __isl_give isl_basic_map *isl_basic_map_drop_core(
2327 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2328 unsigned first, unsigned n)
2329 {
2330 int i;
2331 unsigned offset;
2332 unsigned left;
2333 isl_size total;
2334
2335 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2336 return isl_basic_map_free(bmap);
2337
2338 total = isl_basic_map_dim(bmap, isl_dim_all);
2339 if (total < 0)
2340 return isl_basic_map_free(bmap);
2341
2342 offset = isl_basic_map_offset(bmap, type) + first;
2343 left = total - (offset - 1) - n;
2344 for (i = 0; i < bmap->n_eq; ++i)
2345 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2346
2347 for (i = 0; i < bmap->n_ineq; ++i)
2348 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2349
2350 for (i = 0; i < bmap->n_div; ++i)
2351 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2352
2353 if (type == isl_dim_div) {
2354 bmap = move_divs_last(bmap, first, n);
2355 if (!bmap)
2356 return NULL;
2357 if (isl_basic_map_free_div(bmap, n) < 0)
2358 return isl_basic_map_free(bmap);
2359 } else
2360 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2361 if (!bmap->dim)
2362 return isl_basic_map_free(bmap);
2363
2364 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2365 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2366 return bmap;
2367 }
2368
2369 /* Drop "n" dimensions of type "type" starting at "first".
2370 *
2371 * In principle, this frees up some extra variables as the number
2372 * of columns remains constant, but we would have to extend
2373 * the div array too as the number of rows in this array is assumed
2374 * to be equal to extra.
2375 */
isl_basic_map_drop(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2376 __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2377 enum isl_dim_type type, unsigned first, unsigned n)
2378 {
2379 if (!bmap)
2380 return NULL;
2381 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2382 return bmap;
2383
2384 bmap = isl_basic_map_cow(bmap);
2385 if (!bmap)
2386 return NULL;
2387
2388 bmap = isl_basic_map_drop_core(bmap, type, first, n);
2389
2390 bmap = isl_basic_map_simplify(bmap);
2391 return isl_basic_map_finalize(bmap);
2392 }
2393
isl_basic_set_drop(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2394 __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2395 enum isl_dim_type type, unsigned first, unsigned n)
2396 {
2397 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2398 type, first, n));
2399 }
2400
2401 /* No longer consider "map" to be normalized.
2402 */
isl_map_unmark_normalized(__isl_take isl_map * map)2403 static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2404 {
2405 if (!map)
2406 return NULL;
2407 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2408 return map;
2409 }
2410
isl_map_drop(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2411 __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2412 enum isl_dim_type type, unsigned first, unsigned n)
2413 {
2414 int i;
2415 isl_space *space;
2416
2417 if (isl_map_check_range(map, type, first, n) < 0)
2418 return isl_map_free(map);
2419
2420 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2421 return map;
2422 map = isl_map_cow(map);
2423 if (!map)
2424 goto error;
2425
2426 for (i = 0; i < map->n; ++i) {
2427 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2428 if (!map->p[i])
2429 goto error;
2430 }
2431 map = isl_map_unmark_normalized(map);
2432
2433 space = isl_map_take_space(map);
2434 space = isl_space_drop_dims(space, type, first, n);
2435 map = isl_map_restore_space(map, space);
2436
2437 return map;
2438 error:
2439 isl_map_free(map);
2440 return NULL;
2441 }
2442
isl_set_drop(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2443 __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2444 enum isl_dim_type type, unsigned first, unsigned n)
2445 {
2446 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2447 }
2448
2449 /* Drop the integer division at position "div", which is assumed
2450 * not to appear in any of the constraints or
2451 * in any of the other integer divisions.
2452 *
2453 * Since the integer division is redundant, there is no need to cow.
2454 */
isl_basic_map_drop_div(__isl_take isl_basic_map * bmap,unsigned div)2455 __isl_give isl_basic_map *isl_basic_map_drop_div(
2456 __isl_take isl_basic_map *bmap, unsigned div)
2457 {
2458 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2459 }
2460
2461 /* Eliminate the specified n dimensions starting at first from the
2462 * constraints, without removing the dimensions from the space.
2463 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2464 */
isl_map_eliminate(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2465 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2466 enum isl_dim_type type, unsigned first, unsigned n)
2467 {
2468 int i;
2469
2470 if (n == 0)
2471 return map;
2472
2473 if (isl_map_check_range(map, type, first, n) < 0)
2474 return isl_map_free(map);
2475
2476 map = isl_map_cow(map);
2477 if (!map)
2478 return NULL;
2479
2480 for (i = 0; i < map->n; ++i) {
2481 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2482 if (!map->p[i])
2483 goto error;
2484 }
2485 return map;
2486 error:
2487 isl_map_free(map);
2488 return NULL;
2489 }
2490
2491 /* Eliminate the specified n dimensions starting at first from the
2492 * constraints, without removing the dimensions from the space.
2493 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2494 */
isl_set_eliminate(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2495 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2496 enum isl_dim_type type, unsigned first, unsigned n)
2497 {
2498 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2499 }
2500
2501 /* Eliminate the specified n dimensions starting at first from the
2502 * constraints, without removing the dimensions from the space.
2503 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2504 */
isl_set_eliminate_dims(__isl_take isl_set * set,unsigned first,unsigned n)2505 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2506 unsigned first, unsigned n)
2507 {
2508 return isl_set_eliminate(set, isl_dim_set, first, n);
2509 }
2510
isl_basic_map_remove_divs(__isl_take isl_basic_map * bmap)2511 __isl_give isl_basic_map *isl_basic_map_remove_divs(
2512 __isl_take isl_basic_map *bmap)
2513 {
2514 isl_size v_div;
2515
2516 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2517 if (v_div < 0)
2518 return isl_basic_map_free(bmap);
2519 bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);
2520 if (!bmap)
2521 return NULL;
2522 bmap->n_div = 0;
2523 return isl_basic_map_finalize(bmap);
2524 }
2525
isl_basic_set_remove_divs(__isl_take isl_basic_set * bset)2526 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2527 __isl_take isl_basic_set *bset)
2528 {
2529 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2530 }
2531
isl_map_remove_divs(__isl_take isl_map * map)2532 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2533 {
2534 int i;
2535
2536 if (!map)
2537 return NULL;
2538 if (map->n == 0)
2539 return map;
2540
2541 map = isl_map_cow(map);
2542 if (!map)
2543 return NULL;
2544
2545 for (i = 0; i < map->n; ++i) {
2546 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2547 if (!map->p[i])
2548 goto error;
2549 }
2550 return map;
2551 error:
2552 isl_map_free(map);
2553 return NULL;
2554 }
2555
isl_set_remove_divs(__isl_take isl_set * set)2556 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2557 {
2558 return isl_map_remove_divs(set);
2559 }
2560
isl_basic_map_remove_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2561 __isl_give isl_basic_map *isl_basic_map_remove_dims(
2562 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2563 unsigned first, unsigned n)
2564 {
2565 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2566 return isl_basic_map_free(bmap);
2567 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2568 return bmap;
2569 bmap = isl_basic_map_eliminate_vars(bmap,
2570 isl_basic_map_offset(bmap, type) - 1 + first, n);
2571 if (!bmap)
2572 return bmap;
2573 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2574 return bmap;
2575 bmap = isl_basic_map_drop(bmap, type, first, n);
2576 return bmap;
2577 }
2578
2579 /* Return true if the definition of the given div (recursively) involves
2580 * any of the given variables.
2581 */
div_involves_vars(__isl_keep isl_basic_map * bmap,int div,unsigned first,unsigned n)2582 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2583 unsigned first, unsigned n)
2584 {
2585 int i;
2586 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2587
2588 if (isl_int_is_zero(bmap->div[div][0]))
2589 return isl_bool_false;
2590 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2591 return isl_bool_true;
2592
2593 for (i = bmap->n_div - 1; i >= 0; --i) {
2594 isl_bool involves;
2595
2596 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2597 continue;
2598 involves = div_involves_vars(bmap, i, first, n);
2599 if (involves < 0 || involves)
2600 return involves;
2601 }
2602
2603 return isl_bool_false;
2604 }
2605
2606 /* Try and add a lower and/or upper bound on "div" to "bmap"
2607 * based on inequality "i".
2608 * "total" is the total number of variables (excluding the divs).
2609 * "v" is a temporary object that can be used during the calculations.
2610 * If "lb" is set, then a lower bound should be constructed.
2611 * If "ub" is set, then an upper bound should be constructed.
2612 *
2613 * The calling function has already checked that the inequality does not
2614 * reference "div", but we still need to check that the inequality is
2615 * of the right form. We'll consider the case where we want to construct
2616 * a lower bound. The construction of upper bounds is similar.
2617 *
2618 * Let "div" be of the form
2619 *
2620 * q = floor((a + f(x))/d)
2621 *
2622 * We essentially check if constraint "i" is of the form
2623 *
2624 * b + f(x) >= 0
2625 *
2626 * so that we can use it to derive a lower bound on "div".
2627 * However, we allow a slightly more general form
2628 *
2629 * b + g(x) >= 0
2630 *
2631 * with the condition that the coefficients of g(x) - f(x) are all
2632 * divisible by d.
2633 * Rewriting this constraint as
2634 *
2635 * 0 >= -b - g(x)
2636 *
2637 * adding a + f(x) to both sides and dividing by d, we obtain
2638 *
2639 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2640 *
2641 * Taking the floor on both sides, we obtain
2642 *
2643 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2644 *
2645 * or
2646 *
2647 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2648 *
2649 * In the case of an upper bound, we construct the constraint
2650 *
2651 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2652 *
2653 */
insert_bounds_on_div_from_ineq(__isl_take isl_basic_map * bmap,int div,int i,unsigned total,isl_int v,int lb,int ub)2654 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2655 __isl_take isl_basic_map *bmap, int div, int i,
2656 unsigned total, isl_int v, int lb, int ub)
2657 {
2658 int j;
2659
2660 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2661 if (lb) {
2662 isl_int_sub(v, bmap->ineq[i][1 + j],
2663 bmap->div[div][1 + 1 + j]);
2664 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2665 }
2666 if (ub) {
2667 isl_int_add(v, bmap->ineq[i][1 + j],
2668 bmap->div[div][1 + 1 + j]);
2669 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2670 }
2671 }
2672 if (!lb && !ub)
2673 return bmap;
2674
2675 bmap = isl_basic_map_cow(bmap);
2676 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2677 if (lb) {
2678 int k = isl_basic_map_alloc_inequality(bmap);
2679 if (k < 0)
2680 goto error;
2681 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2682 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2683 bmap->div[div][1 + j]);
2684 isl_int_cdiv_q(bmap->ineq[k][j],
2685 bmap->ineq[k][j], bmap->div[div][0]);
2686 }
2687 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2688 }
2689 if (ub) {
2690 int k = isl_basic_map_alloc_inequality(bmap);
2691 if (k < 0)
2692 goto error;
2693 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2694 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2695 bmap->div[div][1 + j]);
2696 isl_int_fdiv_q(bmap->ineq[k][j],
2697 bmap->ineq[k][j], bmap->div[div][0]);
2698 }
2699 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2700 }
2701
2702 return bmap;
2703 error:
2704 isl_basic_map_free(bmap);
2705 return NULL;
2706 }
2707
2708 /* This function is called right before "div" is eliminated from "bmap"
2709 * using Fourier-Motzkin.
2710 * Look through the constraints of "bmap" for constraints on the argument
2711 * of the integer division and use them to construct constraints on the
2712 * integer division itself. These constraints can then be combined
2713 * during the Fourier-Motzkin elimination.
2714 * Note that it is only useful to introduce lower bounds on "div"
2715 * if "bmap" already contains upper bounds on "div" as the newly
2716 * introduce lower bounds can then be combined with the pre-existing
2717 * upper bounds. Similarly for upper bounds.
2718 * We therefore first check if "bmap" contains any lower and/or upper bounds
2719 * on "div".
2720 *
2721 * It is interesting to note that the introduction of these constraints
2722 * can indeed lead to more accurate results, even when compared to
2723 * deriving constraints on the argument of "div" from constraints on "div".
2724 * Consider, for example, the set
2725 *
2726 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2727 *
2728 * The second constraint can be rewritten as
2729 *
2730 * 2 * [(-i-2j+3)/4] + k >= 0
2731 *
2732 * from which we can derive
2733 *
2734 * -i - 2j + 3 >= -2k
2735 *
2736 * or
2737 *
2738 * i + 2j <= 3 + 2k
2739 *
2740 * Combined with the first constraint, we obtain
2741 *
2742 * -3 <= 3 + 2k or k >= -3
2743 *
2744 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2745 * the first constraint, we obtain
2746 *
2747 * [(i + 2j)/4] >= [-3/4] = -1
2748 *
2749 * Combining this constraint with the second constraint, we obtain
2750 *
2751 * k >= -2
2752 */
insert_bounds_on_div(__isl_take isl_basic_map * bmap,int div)2753 static __isl_give isl_basic_map *insert_bounds_on_div(
2754 __isl_take isl_basic_map *bmap, int div)
2755 {
2756 int i;
2757 int check_lb, check_ub;
2758 isl_int v;
2759 isl_size v_div;
2760
2761 if (!bmap)
2762 return NULL;
2763
2764 if (isl_int_is_zero(bmap->div[div][0]))
2765 return bmap;
2766
2767 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2768 if (v_div < 0)
2769 return isl_basic_map_free(bmap);
2770
2771 check_lb = 0;
2772 check_ub = 0;
2773 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2774 int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);
2775 if (s > 0)
2776 check_ub = 1;
2777 if (s < 0)
2778 check_lb = 1;
2779 }
2780
2781 if (!check_lb && !check_ub)
2782 return bmap;
2783
2784 isl_int_init(v);
2785
2786 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2787 if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))
2788 continue;
2789
2790 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,
2791 check_lb, check_ub);
2792 }
2793
2794 isl_int_clear(v);
2795
2796 return bmap;
2797 }
2798
2799 /* Remove all divs (recursively) involving any of the given dimensions
2800 * in their definitions.
2801 */
isl_basic_map_remove_divs_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2802 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2803 __isl_take isl_basic_map *bmap,
2804 enum isl_dim_type type, unsigned first, unsigned n)
2805 {
2806 int i;
2807
2808 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2809 return isl_basic_map_free(bmap);
2810 first += isl_basic_map_offset(bmap, type);
2811
2812 for (i = bmap->n_div - 1; i >= 0; --i) {
2813 isl_bool involves;
2814
2815 involves = div_involves_vars(bmap, i, first, n);
2816 if (involves < 0)
2817 return isl_basic_map_free(bmap);
2818 if (!involves)
2819 continue;
2820 bmap = insert_bounds_on_div(bmap, i);
2821 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2822 if (!bmap)
2823 return NULL;
2824 i = bmap->n_div;
2825 }
2826
2827 return bmap;
2828 }
2829
isl_basic_set_remove_divs_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2830 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2831 __isl_take isl_basic_set *bset,
2832 enum isl_dim_type type, unsigned first, unsigned n)
2833 {
2834 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2835 }
2836
isl_map_remove_divs_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2837 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2838 enum isl_dim_type type, unsigned first, unsigned n)
2839 {
2840 int i;
2841
2842 if (!map)
2843 return NULL;
2844 if (map->n == 0)
2845 return map;
2846
2847 map = isl_map_cow(map);
2848 if (!map)
2849 return NULL;
2850
2851 for (i = 0; i < map->n; ++i) {
2852 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2853 type, first, n);
2854 if (!map->p[i])
2855 goto error;
2856 }
2857 return map;
2858 error:
2859 isl_map_free(map);
2860 return NULL;
2861 }
2862
isl_set_remove_divs_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2863 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2864 enum isl_dim_type type, unsigned first, unsigned n)
2865 {
2866 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2867 type, first, n));
2868 }
2869
2870 /* Does the description of "bmap" depend on the specified dimensions?
2871 * We also check whether the dimensions appear in any of the div definitions.
2872 * In principle there is no need for this check. If the dimensions appear
2873 * in a div definition, they also appear in the defining constraints of that
2874 * div.
2875 */
isl_basic_map_involves_dims(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)2876 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2877 enum isl_dim_type type, unsigned first, unsigned n)
2878 {
2879 int i;
2880
2881 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2882 return isl_bool_error;
2883
2884 first += isl_basic_map_offset(bmap, type);
2885 for (i = 0; i < bmap->n_eq; ++i)
2886 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2887 return isl_bool_true;
2888 for (i = 0; i < bmap->n_ineq; ++i)
2889 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2890 return isl_bool_true;
2891 for (i = 0; i < bmap->n_div; ++i) {
2892 if (isl_int_is_zero(bmap->div[i][0]))
2893 continue;
2894 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2895 return isl_bool_true;
2896 }
2897
2898 return isl_bool_false;
2899 }
2900
isl_map_involves_dims(__isl_keep isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)2901 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2902 enum isl_dim_type type, unsigned first, unsigned n)
2903 {
2904 int i;
2905
2906 if (isl_map_check_range(map, type, first, n) < 0)
2907 return isl_bool_error;
2908
2909 for (i = 0; i < map->n; ++i) {
2910 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2911 type, first, n);
2912 if (involves < 0 || involves)
2913 return involves;
2914 }
2915
2916 return isl_bool_false;
2917 }
2918
isl_basic_set_involves_dims(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)2919 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2920 enum isl_dim_type type, unsigned first, unsigned n)
2921 {
2922 return isl_basic_map_involves_dims(bset, type, first, n);
2923 }
2924
isl_set_involves_dims(__isl_keep isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)2925 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2926 enum isl_dim_type type, unsigned first, unsigned n)
2927 {
2928 return isl_map_involves_dims(set, type, first, n);
2929 }
2930
2931 /* Does "bset" involve any local variables, i.e., integer divisions?
2932 */
isl_basic_set_involves_locals(__isl_keep isl_basic_set * bset)2933 static isl_bool isl_basic_set_involves_locals(__isl_keep isl_basic_set *bset)
2934 {
2935 isl_size n;
2936
2937 n = isl_basic_set_dim(bset, isl_dim_div);
2938 if (n < 0)
2939 return isl_bool_error;
2940 return isl_bool_ok(n > 0);
2941 }
2942
2943 /* isl_set_every_basic_set callback that checks whether "bset"
2944 * is free of local variables.
2945 */
basic_set_no_locals(__isl_keep isl_basic_set * bset,void * user)2946 static isl_bool basic_set_no_locals(__isl_keep isl_basic_set *bset, void *user)
2947 {
2948 return isl_bool_not(isl_basic_set_involves_locals(bset));
2949 }
2950
2951 /* Does "set" involve any local variables, i.e., integer divisions?
2952 */
isl_set_involves_locals(__isl_keep isl_set * set)2953 isl_bool isl_set_involves_locals(__isl_keep isl_set *set)
2954 {
2955 isl_bool no_locals;
2956
2957 no_locals = isl_set_every_basic_set(set, &basic_set_no_locals, NULL);
2958 return isl_bool_not(no_locals);
2959 }
2960
2961 /* Drop all constraints in bmap that involve any of the dimensions
2962 * first to first+n-1.
2963 * This function only performs the actual removal of constraints.
2964 *
2965 * This function should not call finalize since it is used by
2966 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
2967 */
isl_basic_map_drop_constraints_involving(__isl_take isl_basic_map * bmap,unsigned first,unsigned n)2968 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2969 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2970 {
2971 int i;
2972
2973 if (n == 0)
2974 return bmap;
2975
2976 bmap = isl_basic_map_cow(bmap);
2977
2978 if (!bmap)
2979 return NULL;
2980
2981 for (i = bmap->n_eq - 1; i >= 0; --i) {
2982 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2983 continue;
2984 if (isl_basic_map_drop_equality(bmap, i) < 0)
2985 return isl_basic_map_free(bmap);
2986 }
2987
2988 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2989 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2990 continue;
2991 if (isl_basic_map_drop_inequality(bmap, i) < 0)
2992 return isl_basic_map_free(bmap);
2993 }
2994
2995 return bmap;
2996 }
2997
2998 /* Drop all constraints in bset that involve any of the dimensions
2999 * first to first+n-1.
3000 * This function only performs the actual removal of constraints.
3001 */
isl_basic_set_drop_constraints_involving(__isl_take isl_basic_set * bset,unsigned first,unsigned n)3002 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
3003 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
3004 {
3005 return isl_basic_map_drop_constraints_involving(bset, first, n);
3006 }
3007
3008 /* Drop all constraints in bmap that do not involve any of the dimensions
3009 * first to first + n - 1 of the given type.
3010 */
isl_basic_map_drop_constraints_not_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)3011 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
3012 __isl_take isl_basic_map *bmap,
3013 enum isl_dim_type type, unsigned first, unsigned n)
3014 {
3015 int i;
3016
3017 if (n == 0) {
3018 isl_space *space = isl_basic_map_get_space(bmap);
3019 isl_basic_map_free(bmap);
3020 return isl_basic_map_universe(space);
3021 }
3022 bmap = isl_basic_map_cow(bmap);
3023 if (!bmap)
3024 return NULL;
3025
3026 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3027 return isl_basic_map_free(bmap);
3028
3029 first += isl_basic_map_offset(bmap, type) - 1;
3030
3031 for (i = bmap->n_eq - 1; i >= 0; --i) {
3032 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
3033 continue;
3034 if (isl_basic_map_drop_equality(bmap, i) < 0)
3035 return isl_basic_map_free(bmap);
3036 }
3037
3038 for (i = bmap->n_ineq - 1; i >= 0; --i) {
3039 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
3040 continue;
3041 if (isl_basic_map_drop_inequality(bmap, i) < 0)
3042 return isl_basic_map_free(bmap);
3043 }
3044
3045 bmap = isl_basic_map_add_known_div_constraints(bmap);
3046 return bmap;
3047 }
3048
3049 /* Drop all constraints in bset that do not involve any of the dimensions
3050 * first to first + n - 1 of the given type.
3051 */
isl_basic_set_drop_constraints_not_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3052 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
3053 __isl_take isl_basic_set *bset,
3054 enum isl_dim_type type, unsigned first, unsigned n)
3055 {
3056 return isl_basic_map_drop_constraints_not_involving_dims(bset,
3057 type, first, n);
3058 }
3059
3060 /* Drop all constraints in bmap that involve any of the dimensions
3061 * first to first + n - 1 of the given type.
3062 */
isl_basic_map_drop_constraints_involving_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)3063 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
3064 __isl_take isl_basic_map *bmap,
3065 enum isl_dim_type type, unsigned first, unsigned n)
3066 {
3067 if (!bmap)
3068 return NULL;
3069 if (n == 0)
3070 return bmap;
3071
3072 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3073 return isl_basic_map_free(bmap);
3074
3075 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
3076 first += isl_basic_map_offset(bmap, type) - 1;
3077 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
3078 bmap = isl_basic_map_add_known_div_constraints(bmap);
3079 return bmap;
3080 }
3081
3082 /* Drop all constraints in bset that involve any of the dimensions
3083 * first to first + n - 1 of the given type.
3084 */
isl_basic_set_drop_constraints_involving_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3085 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
3086 __isl_take isl_basic_set *bset,
3087 enum isl_dim_type type, unsigned first, unsigned n)
3088 {
3089 return isl_basic_map_drop_constraints_involving_dims(bset,
3090 type, first, n);
3091 }
3092
3093 /* Drop constraints from "map" by applying "drop" to each basic map.
3094 */
drop_constraints(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n,__isl_give isl_basic_map * (* drop)(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n))3095 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
3096 enum isl_dim_type type, unsigned first, unsigned n,
3097 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
3098 enum isl_dim_type type, unsigned first, unsigned n))
3099 {
3100 int i;
3101
3102 if (isl_map_check_range(map, type, first, n) < 0)
3103 return isl_map_free(map);
3104
3105 map = isl_map_cow(map);
3106 if (!map)
3107 return NULL;
3108
3109 for (i = 0; i < map->n; ++i) {
3110 map->p[i] = drop(map->p[i], type, first, n);
3111 if (!map->p[i])
3112 return isl_map_free(map);
3113 }
3114
3115 if (map->n > 1)
3116 ISL_F_CLR(map, ISL_MAP_DISJOINT);
3117
3118 return map;
3119 }
3120
3121 /* Drop all constraints in map that involve any of the dimensions
3122 * first to first + n - 1 of the given type.
3123 */
isl_map_drop_constraints_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3124 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
3125 __isl_take isl_map *map,
3126 enum isl_dim_type type, unsigned first, unsigned n)
3127 {
3128 if (n == 0)
3129 return map;
3130 return drop_constraints(map, type, first, n,
3131 &isl_basic_map_drop_constraints_involving_dims);
3132 }
3133
3134 /* Drop all constraints in "map" that do not involve any of the dimensions
3135 * first to first + n - 1 of the given type.
3136 */
isl_map_drop_constraints_not_involving_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3137 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3138 __isl_take isl_map *map,
3139 enum isl_dim_type type, unsigned first, unsigned n)
3140 {
3141 if (n == 0) {
3142 isl_space *space = isl_map_get_space(map);
3143 isl_map_free(map);
3144 return isl_map_universe(space);
3145 }
3146 return drop_constraints(map, type, first, n,
3147 &isl_basic_map_drop_constraints_not_involving_dims);
3148 }
3149
3150 /* Drop all constraints in set that involve any of the dimensions
3151 * first to first + n - 1 of the given type.
3152 */
isl_set_drop_constraints_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)3153 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
3154 __isl_take isl_set *set,
3155 enum isl_dim_type type, unsigned first, unsigned n)
3156 {
3157 return isl_map_drop_constraints_involving_dims(set, type, first, n);
3158 }
3159
3160 /* Drop all constraints in "set" that do not involve any of the dimensions
3161 * first to first + n - 1 of the given type.
3162 */
isl_set_drop_constraints_not_involving_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)3163 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3164 __isl_take isl_set *set,
3165 enum isl_dim_type type, unsigned first, unsigned n)
3166 {
3167 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3168 }
3169
3170 /* Does local variable "div" of "bmap" have a complete explicit representation?
3171 * Having a complete explicit representation requires not only
3172 * an explicit representation, but also that all local variables
3173 * that appear in this explicit representation in turn have
3174 * a complete explicit representation.
3175 */
isl_basic_map_div_is_known(__isl_keep isl_basic_map * bmap,int div)3176 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3177 {
3178 int i;
3179 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3180 isl_bool marked;
3181
3182 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3183 if (marked < 0 || marked)
3184 return isl_bool_not(marked);
3185
3186 for (i = bmap->n_div - 1; i >= 0; --i) {
3187 isl_bool known;
3188
3189 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3190 continue;
3191 known = isl_basic_map_div_is_known(bmap, i);
3192 if (known < 0 || !known)
3193 return known;
3194 }
3195
3196 return isl_bool_true;
3197 }
3198
3199 /* Remove all divs that are unknown or defined in terms of unknown divs.
3200 */
isl_basic_map_remove_unknown_divs(__isl_take isl_basic_map * bmap)3201 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3202 __isl_take isl_basic_map *bmap)
3203 {
3204 int i;
3205
3206 if (!bmap)
3207 return NULL;
3208
3209 for (i = bmap->n_div - 1; i >= 0; --i) {
3210 if (isl_basic_map_div_is_known(bmap, i))
3211 continue;
3212 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3213 if (!bmap)
3214 return NULL;
3215 i = bmap->n_div;
3216 }
3217
3218 return bmap;
3219 }
3220
3221 /* Remove all divs that are unknown or defined in terms of unknown divs.
3222 */
isl_basic_set_remove_unknown_divs(__isl_take isl_basic_set * bset)3223 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3224 __isl_take isl_basic_set *bset)
3225 {
3226 return isl_basic_map_remove_unknown_divs(bset);
3227 }
3228
isl_map_remove_unknown_divs(__isl_take isl_map * map)3229 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3230 {
3231 int i;
3232
3233 if (!map)
3234 return NULL;
3235 if (map->n == 0)
3236 return map;
3237
3238 map = isl_map_cow(map);
3239 if (!map)
3240 return NULL;
3241
3242 for (i = 0; i < map->n; ++i) {
3243 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3244 if (!map->p[i])
3245 goto error;
3246 }
3247 return map;
3248 error:
3249 isl_map_free(map);
3250 return NULL;
3251 }
3252
isl_set_remove_unknown_divs(__isl_take isl_set * set)3253 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3254 {
3255 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3256 }
3257
isl_basic_set_remove_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3258 __isl_give isl_basic_set *isl_basic_set_remove_dims(
3259 __isl_take isl_basic_set *bset,
3260 enum isl_dim_type type, unsigned first, unsigned n)
3261 {
3262 isl_basic_map *bmap = bset_to_bmap(bset);
3263 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3264 return bset_from_bmap(bmap);
3265 }
3266
isl_map_remove_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)3267 __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3268 enum isl_dim_type type, unsigned first, unsigned n)
3269 {
3270 int i;
3271
3272 if (n == 0)
3273 return map;
3274
3275 map = isl_map_cow(map);
3276 if (isl_map_check_range(map, type, first, n) < 0)
3277 return isl_map_free(map);
3278
3279 for (i = 0; i < map->n; ++i) {
3280 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3281 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3282 if (!map->p[i])
3283 goto error;
3284 }
3285 map = isl_map_drop(map, type, first, n);
3286 return map;
3287 error:
3288 isl_map_free(map);
3289 return NULL;
3290 }
3291
isl_set_remove_dims(__isl_take isl_set * bset,enum isl_dim_type type,unsigned first,unsigned n)3292 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3293 enum isl_dim_type type, unsigned first, unsigned n)
3294 {
3295 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3296 type, first, n));
3297 }
3298
3299 /* Project out n inputs starting at first using Fourier-Motzkin */
isl_map_remove_inputs(__isl_take isl_map * map,unsigned first,unsigned n)3300 __isl_give isl_map *isl_map_remove_inputs(__isl_take isl_map *map,
3301 unsigned first, unsigned n)
3302 {
3303 return isl_map_remove_dims(map, isl_dim_in, first, n);
3304 }
3305
isl_basic_set_print_internal(__isl_keep isl_basic_set * bset,FILE * out,int indent)3306 void isl_basic_set_print_internal(__isl_keep isl_basic_set *bset,
3307 FILE *out, int indent)
3308 {
3309 isl_printer *p;
3310
3311 if (!bset) {
3312 fprintf(out, "null basic set\n");
3313 return;
3314 }
3315
3316 fprintf(out, "%*s", indent, "");
3317 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3318 bset->ref, bset->dim->nparam, bset->dim->n_out,
3319 bset->extra, bset->flags);
3320
3321 p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
3322 p = isl_printer_set_dump(p, 1);
3323 p = isl_printer_set_indent(p, indent);
3324 p = isl_printer_start_line(p);
3325 p = isl_printer_print_basic_set(p, bset);
3326 p = isl_printer_end_line(p);
3327 isl_printer_free(p);
3328 }
3329
isl_basic_map_print_internal(__isl_keep isl_basic_map * bmap,FILE * out,int indent)3330 void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,
3331 FILE *out, int indent)
3332 {
3333 isl_printer *p;
3334
3335 if (!bmap) {
3336 fprintf(out, "null basic map\n");
3337 return;
3338 }
3339
3340 fprintf(out, "%*s", indent, "");
3341 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3342 "flags: %x, n_name: %d\n",
3343 bmap->ref,
3344 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3345 bmap->extra, bmap->flags, bmap->dim->n_id);
3346
3347 p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
3348 p = isl_printer_set_dump(p, 1);
3349 p = isl_printer_set_indent(p, indent);
3350 p = isl_printer_start_line(p);
3351 p = isl_printer_print_basic_map(p, bmap);
3352 p = isl_printer_end_line(p);
3353 isl_printer_free(p);
3354 }
3355
isl_inequality_negate(__isl_take isl_basic_map * bmap,unsigned pos)3356 __isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3357 unsigned pos)
3358 {
3359 isl_size total;
3360
3361 total = isl_basic_map_dim(bmap, isl_dim_all);
3362 if (total < 0)
3363 return isl_basic_map_free(bmap);
3364 if (pos >= bmap->n_ineq)
3365 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3366 "invalid position", return isl_basic_map_free(bmap));
3367 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3368 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3369 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3370 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3371 return bmap;
3372 }
3373
isl_set_alloc_space(__isl_take isl_space * space,int n,unsigned flags)3374 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3375 unsigned flags)
3376 {
3377 if (isl_space_check_is_set(space) < 0)
3378 goto error;
3379 return isl_map_alloc_space(space, n, flags);
3380 error:
3381 isl_space_free(space);
3382 return NULL;
3383 }
3384
3385 /* Make sure "map" has room for at least "n" more basic maps.
3386 */
isl_map_grow(__isl_take isl_map * map,int n)3387 __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3388 {
3389 int i;
3390 struct isl_map *grown = NULL;
3391
3392 if (!map)
3393 return NULL;
3394 isl_assert(map->ctx, n >= 0, goto error);
3395 if (map->n + n <= map->size)
3396 return map;
3397 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3398 if (!grown)
3399 goto error;
3400 for (i = 0; i < map->n; ++i) {
3401 grown->p[i] = isl_basic_map_copy(map->p[i]);
3402 if (!grown->p[i])
3403 goto error;
3404 grown->n++;
3405 }
3406 isl_map_free(map);
3407 return grown;
3408 error:
3409 isl_map_free(grown);
3410 isl_map_free(map);
3411 return NULL;
3412 }
3413
3414 /* Make sure "set" has room for at least "n" more basic sets.
3415 */
isl_set_grow(__isl_take isl_set * set,int n)3416 __isl_give isl_set *isl_set_grow(__isl_take isl_set *set, int n)
3417 {
3418 return set_from_map(isl_map_grow(set_to_map(set), n));
3419 }
3420
isl_set_from_basic_set(__isl_take isl_basic_set * bset)3421 __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3422 {
3423 return isl_map_from_basic_map(bset);
3424 }
3425
isl_map_from_basic_map(__isl_take isl_basic_map * bmap)3426 __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3427 {
3428 struct isl_map *map;
3429
3430 if (!bmap)
3431 return NULL;
3432
3433 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3434 return isl_map_add_basic_map(map, bmap);
3435 }
3436
isl_set_add_basic_set(__isl_take isl_set * set,__isl_take isl_basic_set * bset)3437 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3438 __isl_take isl_basic_set *bset)
3439 {
3440 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3441 bset_to_bmap(bset)));
3442 }
3443
isl_set_free(__isl_take isl_set * set)3444 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3445 {
3446 return isl_map_free(set);
3447 }
3448
isl_set_print_internal(__isl_keep isl_set * set,FILE * out,int indent)3449 void isl_set_print_internal(__isl_keep isl_set *set, FILE *out, int indent)
3450 {
3451 int i;
3452
3453 if (!set) {
3454 fprintf(out, "null set\n");
3455 return;
3456 }
3457
3458 fprintf(out, "%*s", indent, "");
3459 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3460 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3461 set->flags);
3462 for (i = 0; i < set->n; ++i) {
3463 fprintf(out, "%*s", indent, "");
3464 fprintf(out, "basic set %d:\n", i);
3465 isl_basic_set_print_internal(set->p[i], out, indent+4);
3466 }
3467 }
3468
isl_map_print_internal(__isl_keep isl_map * map,FILE * out,int indent)3469 void isl_map_print_internal(__isl_keep isl_map *map, FILE *out, int indent)
3470 {
3471 int i;
3472
3473 if (!map) {
3474 fprintf(out, "null map\n");
3475 return;
3476 }
3477
3478 fprintf(out, "%*s", indent, "");
3479 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3480 "flags: %x, n_name: %d\n",
3481 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3482 map->dim->n_out, map->flags, map->dim->n_id);
3483 for (i = 0; i < map->n; ++i) {
3484 fprintf(out, "%*s", indent, "");
3485 fprintf(out, "basic map %d:\n", i);
3486 isl_basic_map_print_internal(map->p[i], out, indent+4);
3487 }
3488 }
3489
3490 /* Check that the space of "bset" is the same as that of the domain of "bmap".
3491 */
isl_basic_map_check_compatible_domain(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)3492 static isl_stat isl_basic_map_check_compatible_domain(
3493 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3494 {
3495 isl_bool ok;
3496
3497 ok = isl_basic_map_compatible_domain(bmap, bset);
3498 if (ok < 0)
3499 return isl_stat_error;
3500 if (!ok)
3501 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3502 "incompatible spaces", return isl_stat_error);
3503
3504 return isl_stat_ok;
3505 }
3506
isl_basic_map_intersect_domain(__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset)3507 __isl_give isl_basic_map *isl_basic_map_intersect_domain(
3508 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3509 {
3510 struct isl_basic_map *bmap_domain;
3511 isl_size dim;
3512
3513 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3514 goto error;
3515
3516 dim = isl_basic_set_dim(bset, isl_dim_set);
3517 if (dim < 0)
3518 goto error;
3519 if (dim != 0 &&
3520 isl_basic_map_check_compatible_domain(bmap, bset) < 0)
3521 goto error;
3522
3523 bmap = isl_basic_map_cow(bmap);
3524 if (!bmap)
3525 goto error;
3526 bmap = isl_basic_map_extend(bmap,
3527 bset->n_div, bset->n_eq, bset->n_ineq);
3528 bmap_domain = isl_basic_map_from_domain(bset);
3529 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3530
3531 bmap = isl_basic_map_simplify(bmap);
3532 return isl_basic_map_finalize(bmap);
3533 error:
3534 isl_basic_map_free(bmap);
3535 isl_basic_set_free(bset);
3536 return NULL;
3537 }
3538
3539 /* Check that the space of "bset" is the same as that of the range of "bmap".
3540 */
isl_basic_map_check_compatible_range(__isl_keep isl_basic_map * bmap,__isl_keep isl_basic_set * bset)3541 static isl_stat isl_basic_map_check_compatible_range(
3542 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3543 {
3544 isl_bool ok;
3545
3546 ok = isl_basic_map_compatible_range(bmap, bset);
3547 if (ok < 0)
3548 return isl_stat_error;
3549 if (!ok)
3550 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3551 "incompatible spaces", return isl_stat_error);
3552
3553 return isl_stat_ok;
3554 }
3555
isl_basic_map_intersect_range(__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset)3556 __isl_give isl_basic_map *isl_basic_map_intersect_range(
3557 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3558 {
3559 struct isl_basic_map *bmap_range;
3560 isl_size dim;
3561
3562 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3563 goto error;
3564
3565 dim = isl_basic_set_dim(bset, isl_dim_set);
3566 if (dim < 0)
3567 goto error;
3568 if (dim != 0 && isl_basic_map_check_compatible_range(bmap, bset) < 0)
3569 goto error;
3570
3571 if (isl_basic_set_plain_is_universe(bset)) {
3572 isl_basic_set_free(bset);
3573 return bmap;
3574 }
3575
3576 bmap = isl_basic_map_cow(bmap);
3577 if (!bmap)
3578 goto error;
3579 bmap = isl_basic_map_extend(bmap,
3580 bset->n_div, bset->n_eq, bset->n_ineq);
3581 bmap_range = bset_to_bmap(bset);
3582 bmap = add_constraints(bmap, bmap_range, 0, 0);
3583
3584 bmap = isl_basic_map_simplify(bmap);
3585 return isl_basic_map_finalize(bmap);
3586 error:
3587 isl_basic_map_free(bmap);
3588 isl_basic_set_free(bset);
3589 return NULL;
3590 }
3591
isl_basic_map_contains(__isl_keep isl_basic_map * bmap,__isl_keep isl_vec * vec)3592 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3593 __isl_keep isl_vec *vec)
3594 {
3595 int i;
3596 isl_size total;
3597 isl_int s;
3598
3599 total = isl_basic_map_dim(bmap, isl_dim_all);
3600 if (total < 0 || !vec)
3601 return isl_bool_error;
3602
3603 if (1 + total != vec->size)
3604 return isl_bool_false;
3605
3606 isl_int_init(s);
3607
3608 for (i = 0; i < bmap->n_eq; ++i) {
3609 isl_seq_inner_product(vec->el, bmap->eq[i], 1 + total, &s);
3610 if (!isl_int_is_zero(s)) {
3611 isl_int_clear(s);
3612 return isl_bool_false;
3613 }
3614 }
3615
3616 for (i = 0; i < bmap->n_ineq; ++i) {
3617 isl_seq_inner_product(vec->el, bmap->ineq[i], 1 + total, &s);
3618 if (isl_int_is_neg(s)) {
3619 isl_int_clear(s);
3620 return isl_bool_false;
3621 }
3622 }
3623
3624 isl_int_clear(s);
3625
3626 return isl_bool_true;
3627 }
3628
isl_basic_set_contains(__isl_keep isl_basic_set * bset,__isl_keep isl_vec * vec)3629 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3630 __isl_keep isl_vec *vec)
3631 {
3632 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3633 }
3634
isl_basic_map_intersect(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)3635 __isl_give isl_basic_map *isl_basic_map_intersect(
3636 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3637 {
3638 struct isl_vec *sample = NULL;
3639 isl_space *space1, *space2;
3640 isl_size dim1, dim2, nparam1, nparam2;
3641
3642 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3643 goto error;
3644 space1 = isl_basic_map_peek_space(bmap1);
3645 space2 = isl_basic_map_peek_space(bmap2);
3646 dim1 = isl_space_dim(space1, isl_dim_all);
3647 dim2 = isl_space_dim(space2, isl_dim_all);
3648 nparam1 = isl_space_dim(space1, isl_dim_param);
3649 nparam2 = isl_space_dim(space2, isl_dim_param);
3650 if (dim1 < 0 || dim2 < 0 || nparam1 < 0 || nparam2 < 0)
3651 goto error;
3652 if (dim1 == nparam1 && dim2 != nparam2)
3653 return isl_basic_map_intersect(bmap2, bmap1);
3654
3655 if (dim2 != nparam2 &&
3656 isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
3657 goto error;
3658
3659 if (isl_basic_map_plain_is_empty(bmap1)) {
3660 isl_basic_map_free(bmap2);
3661 return bmap1;
3662 }
3663 if (isl_basic_map_plain_is_empty(bmap2)) {
3664 isl_basic_map_free(bmap1);
3665 return bmap2;
3666 }
3667
3668 if (bmap1->sample &&
3669 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3670 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3671 sample = isl_vec_copy(bmap1->sample);
3672 else if (bmap2->sample &&
3673 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3674 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3675 sample = isl_vec_copy(bmap2->sample);
3676
3677 bmap1 = isl_basic_map_cow(bmap1);
3678 if (!bmap1)
3679 goto error;
3680 bmap1 = isl_basic_map_extend(bmap1,
3681 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3682 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3683
3684 if (!bmap1)
3685 isl_vec_free(sample);
3686 else if (sample) {
3687 isl_vec_free(bmap1->sample);
3688 bmap1->sample = sample;
3689 }
3690
3691 bmap1 = isl_basic_map_simplify(bmap1);
3692 return isl_basic_map_finalize(bmap1);
3693 error:
3694 if (sample)
3695 isl_vec_free(sample);
3696 isl_basic_map_free(bmap1);
3697 isl_basic_map_free(bmap2);
3698 return NULL;
3699 }
3700
isl_basic_set_intersect(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)3701 __isl_give isl_basic_set *isl_basic_set_intersect(
3702 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3703 {
3704 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3705 bset_to_bmap(bset2)));
3706 }
3707
isl_basic_set_intersect_params(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)3708 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3709 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3710 {
3711 return isl_basic_set_intersect(bset1, bset2);
3712 }
3713
3714 /* Special case of isl_map_intersect, where both map1 and map2
3715 * are convex, without any divs and such that either map1 or map2
3716 * contains a single constraint. This constraint is then simply
3717 * added to the other map.
3718 */
map_intersect_add_constraint(__isl_take isl_map * map1,__isl_take isl_map * map2)3719 static __isl_give isl_map *map_intersect_add_constraint(
3720 __isl_take isl_map *map1, __isl_take isl_map *map2)
3721 {
3722 isl_assert(map1->ctx, map1->n == 1, goto error);
3723 isl_assert(map2->ctx, map1->n == 1, goto error);
3724 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3725 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3726
3727 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3728 return isl_map_intersect(map2, map1);
3729
3730 map1 = isl_map_cow(map1);
3731 if (!map1)
3732 goto error;
3733 if (isl_map_plain_is_empty(map1)) {
3734 isl_map_free(map2);
3735 return map1;
3736 }
3737 if (map2->p[0]->n_eq == 1)
3738 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3739 else
3740 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3741 map2->p[0]->ineq[0]);
3742
3743 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3744 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3745 if (!map1->p[0])
3746 goto error;
3747
3748 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3749 isl_basic_map_free(map1->p[0]);
3750 map1->n = 0;
3751 }
3752
3753 isl_map_free(map2);
3754
3755 map1 = isl_map_unmark_normalized(map1);
3756 return map1;
3757 error:
3758 isl_map_free(map1);
3759 isl_map_free(map2);
3760 return NULL;
3761 }
3762
3763 /* map2 may be either a parameter domain or a map living in the same
3764 * space as map1.
3765 */
map_intersect_internal(__isl_take isl_map * map1,__isl_take isl_map * map2)3766 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3767 __isl_take isl_map *map2)
3768 {
3769 unsigned flags = 0;
3770 isl_bool equal;
3771 isl_map *result;
3772 int i, j;
3773 isl_size dim2, nparam2;
3774
3775 if (!map1 || !map2)
3776 goto error;
3777
3778 if ((isl_map_plain_is_empty(map1) ||
3779 isl_map_plain_is_universe(map2)) &&
3780 isl_space_is_equal(map1->dim, map2->dim)) {
3781 isl_map_free(map2);
3782 return map1;
3783 }
3784 if ((isl_map_plain_is_empty(map2) ||
3785 isl_map_plain_is_universe(map1)) &&
3786 isl_space_is_equal(map1->dim, map2->dim)) {
3787 isl_map_free(map1);
3788 return map2;
3789 }
3790
3791 if (map1->n == 1 && map2->n == 1 &&
3792 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3793 isl_space_is_equal(map1->dim, map2->dim) &&
3794 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3795 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3796 return map_intersect_add_constraint(map1, map2);
3797
3798 equal = isl_map_plain_is_equal(map1, map2);
3799 if (equal < 0)
3800 goto error;
3801 if (equal) {
3802 isl_map_free(map2);
3803 return map1;
3804 }
3805
3806 dim2 = isl_map_dim(map2, isl_dim_all);
3807 nparam2 = isl_map_dim(map2, isl_dim_param);
3808 if (dim2 < 0 || nparam2 < 0)
3809 goto error;
3810 if (dim2 != nparam2)
3811 isl_assert(map1->ctx,
3812 isl_space_is_equal(map1->dim, map2->dim), goto error);
3813
3814 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3815 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3816 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3817
3818 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3819 map1->n * map2->n, flags);
3820 if (!result)
3821 goto error;
3822 for (i = 0; i < map1->n; ++i)
3823 for (j = 0; j < map2->n; ++j) {
3824 struct isl_basic_map *part;
3825 part = isl_basic_map_intersect(
3826 isl_basic_map_copy(map1->p[i]),
3827 isl_basic_map_copy(map2->p[j]));
3828 if (isl_basic_map_is_empty(part) < 0)
3829 part = isl_basic_map_free(part);
3830 result = isl_map_add_basic_map(result, part);
3831 if (!result)
3832 goto error;
3833 }
3834 isl_map_free(map1);
3835 isl_map_free(map2);
3836 return result;
3837 error:
3838 isl_map_free(map1);
3839 isl_map_free(map2);
3840 return NULL;
3841 }
3842
map_intersect(__isl_take isl_map * map1,__isl_take isl_map * map2)3843 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3844 __isl_take isl_map *map2)
3845 {
3846 if (isl_map_check_equal_space(map1, map2) < 0)
3847 goto error;
3848 return map_intersect_internal(map1, map2);
3849 error:
3850 isl_map_free(map1);
3851 isl_map_free(map2);
3852 return NULL;
3853 }
3854
isl_map_intersect(__isl_take isl_map * map1,__isl_take isl_map * map2)3855 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3856 __isl_take isl_map *map2)
3857 {
3858 isl_map_align_params_bin(&map1, &map2);
3859 return map_intersect(map1, map2);
3860 }
3861
isl_set_intersect(__isl_take isl_set * set1,__isl_take isl_set * set2)3862 __isl_give isl_set *isl_set_intersect(__isl_take isl_set *set1,
3863 __isl_take isl_set *set2)
3864 {
3865 return set_from_map(isl_map_intersect(set_to_map(set1),
3866 set_to_map(set2)));
3867 }
3868
3869 /* map_intersect_internal accepts intersections
3870 * with parameter domains, so we can just call that function.
3871 */
isl_map_intersect_params(__isl_take isl_map * map,__isl_take isl_set * params)3872 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
3873 __isl_take isl_set *params)
3874 {
3875 isl_map_align_params_set(&map, ¶ms);
3876 return map_intersect_internal(map, params);
3877 }
3878
isl_set_intersect_params(__isl_take isl_set * set,__isl_take isl_set * params)3879 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3880 __isl_take isl_set *params)
3881 {
3882 return isl_map_intersect_params(set, params);
3883 }
3884
isl_basic_map_reverse(__isl_take isl_basic_map * bmap)3885 __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3886 {
3887 isl_space *space;
3888 unsigned pos;
3889 isl_size n1, n2;
3890
3891 if (!bmap)
3892 return NULL;
3893 bmap = isl_basic_map_cow(bmap);
3894 if (!bmap)
3895 return NULL;
3896 space = isl_space_reverse(isl_space_copy(bmap->dim));
3897 pos = isl_basic_map_offset(bmap, isl_dim_in);
3898 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3899 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3900 if (n1 < 0 || n2 < 0)
3901 bmap = isl_basic_map_free(bmap);
3902 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3903 return isl_basic_map_reset_space(bmap, space);
3904 }
3905
3906 /* Given a basic map A -> (B -> C), return the corresponding basic map
3907 * A -> (C -> B).
3908 */
isl_basic_map_range_reverse(__isl_take isl_basic_map * bmap)3909 static __isl_give isl_basic_map *isl_basic_map_range_reverse(
3910 __isl_take isl_basic_map *bmap)
3911 {
3912 isl_space *space;
3913 isl_size offset, n1, n2;
3914
3915 space = isl_basic_map_peek_space(bmap);
3916 if (isl_space_check_range_is_wrapping(space) < 0)
3917 return isl_basic_map_free(bmap);
3918 offset = isl_basic_map_var_offset(bmap, isl_dim_out);
3919 n1 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_in);
3920 n2 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_out);
3921 if (offset < 0 || n1 < 0 || n2 < 0)
3922 return isl_basic_map_free(bmap);
3923
3924 bmap = isl_basic_map_swap_vars(bmap, 1 + offset, n1, n2);
3925
3926 space = isl_basic_map_take_space(bmap);
3927 space = isl_space_range_reverse(space);
3928 bmap = isl_basic_map_restore_space(bmap, space);
3929
3930 return bmap;
3931 }
3932
basic_map_space_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)3933 static __isl_give isl_basic_map *basic_map_space_reset(
3934 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3935 {
3936 isl_space *space;
3937
3938 if (!bmap)
3939 return NULL;
3940 if (!isl_space_is_named_or_nested(bmap->dim, type))
3941 return bmap;
3942
3943 space = isl_basic_map_get_space(bmap);
3944 space = isl_space_reset(space, type);
3945 bmap = isl_basic_map_reset_space(bmap, space);
3946 return bmap;
3947 }
3948
isl_basic_map_insert_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,unsigned n)3949 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3950 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3951 unsigned pos, unsigned n)
3952 {
3953 isl_bool rational, is_empty;
3954 isl_space *res_space;
3955 struct isl_basic_map *res;
3956 struct isl_dim_map *dim_map;
3957 isl_size total;
3958 unsigned off;
3959 enum isl_dim_type t;
3960
3961 if (n == 0)
3962 return basic_map_space_reset(bmap, type);
3963
3964 is_empty = isl_basic_map_plain_is_empty(bmap);
3965 total = isl_basic_map_dim(bmap, isl_dim_all);
3966 if (is_empty < 0 || total < 0)
3967 return isl_basic_map_free(bmap);
3968 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3969 type, pos, n);
3970 if (!res_space)
3971 return isl_basic_map_free(bmap);
3972 if (is_empty) {
3973 isl_basic_map_free(bmap);
3974 return isl_basic_map_empty(res_space);
3975 }
3976
3977 dim_map = isl_dim_map_alloc(bmap->ctx, total + n);
3978 off = 0;
3979 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3980 isl_size dim;
3981
3982 if (t != type) {
3983 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3984 } else {
3985 isl_size size = isl_basic_map_dim(bmap, t);
3986 if (size < 0)
3987 dim_map = isl_dim_map_free(dim_map);
3988 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3989 0, pos, off);
3990 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3991 pos, size - pos, off + pos + n);
3992 }
3993 dim = isl_space_dim(res_space, t);
3994 if (dim < 0)
3995 dim_map = isl_dim_map_free(dim_map);
3996 off += dim;
3997 }
3998 isl_dim_map_div(dim_map, bmap, off);
3999
4000 res = isl_basic_map_alloc_space(res_space,
4001 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4002 rational = isl_basic_map_is_rational(bmap);
4003 if (rational < 0)
4004 res = isl_basic_map_free(res);
4005 if (rational)
4006 res = isl_basic_map_set_rational(res);
4007 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4008 return isl_basic_map_finalize(res);
4009 }
4010
isl_basic_set_insert_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,unsigned n)4011 __isl_give isl_basic_set *isl_basic_set_insert_dims(
4012 __isl_take isl_basic_set *bset,
4013 enum isl_dim_type type, unsigned pos, unsigned n)
4014 {
4015 return isl_basic_map_insert_dims(bset, type, pos, n);
4016 }
4017
isl_basic_map_add_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned n)4018 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
4019 enum isl_dim_type type, unsigned n)
4020 {
4021 isl_size dim;
4022
4023 dim = isl_basic_map_dim(bmap, type);
4024 if (dim < 0)
4025 return isl_basic_map_free(bmap);
4026 return isl_basic_map_insert_dims(bmap, type, dim, n);
4027 }
4028
isl_basic_set_add_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned n)4029 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
4030 enum isl_dim_type type, unsigned n)
4031 {
4032 if (!bset)
4033 return NULL;
4034 isl_assert(bset->ctx, type != isl_dim_in, goto error);
4035 return isl_basic_map_add_dims(bset, type, n);
4036 error:
4037 isl_basic_set_free(bset);
4038 return NULL;
4039 }
4040
map_space_reset(__isl_take isl_map * map,enum isl_dim_type type)4041 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
4042 enum isl_dim_type type)
4043 {
4044 isl_space *space;
4045
4046 if (!map || !isl_space_is_named_or_nested(map->dim, type))
4047 return map;
4048
4049 space = isl_map_get_space(map);
4050 space = isl_space_reset(space, type);
4051 map = isl_map_reset_space(map, space);
4052 return map;
4053 }
4054
isl_map_insert_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,unsigned n)4055 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
4056 enum isl_dim_type type, unsigned pos, unsigned n)
4057 {
4058 int i;
4059 isl_space *space;
4060
4061 if (n == 0)
4062 return map_space_reset(map, type);
4063
4064 map = isl_map_cow(map);
4065 if (!map)
4066 return NULL;
4067
4068 for (i = 0; i < map->n; ++i) {
4069 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
4070 if (!map->p[i])
4071 goto error;
4072 }
4073
4074 space = isl_map_take_space(map);
4075 space = isl_space_insert_dims(space, type, pos, n);
4076 map = isl_map_restore_space(map, space);
4077
4078 return map;
4079 error:
4080 isl_map_free(map);
4081 return NULL;
4082 }
4083
isl_set_insert_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,unsigned n)4084 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
4085 enum isl_dim_type type, unsigned pos, unsigned n)
4086 {
4087 return isl_map_insert_dims(set, type, pos, n);
4088 }
4089
isl_map_add_dims(__isl_take isl_map * map,enum isl_dim_type type,unsigned n)4090 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
4091 enum isl_dim_type type, unsigned n)
4092 {
4093 isl_size dim;
4094
4095 dim = isl_map_dim(map, type);
4096 if (dim < 0)
4097 return isl_map_free(map);
4098 return isl_map_insert_dims(map, type, dim, n);
4099 }
4100
isl_set_add_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned n)4101 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
4102 enum isl_dim_type type, unsigned n)
4103 {
4104 if (!set)
4105 return NULL;
4106 isl_assert(set->ctx, type != isl_dim_in, goto error);
4107 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
4108 error:
4109 isl_set_free(set);
4110 return NULL;
4111 }
4112
isl_basic_map_move_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type dst_type,unsigned dst_pos,enum isl_dim_type src_type,unsigned src_pos,unsigned n)4113 __isl_give isl_basic_map *isl_basic_map_move_dims(
4114 __isl_take isl_basic_map *bmap,
4115 enum isl_dim_type dst_type, unsigned dst_pos,
4116 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4117 {
4118 isl_space *space;
4119 struct isl_dim_map *dim_map;
4120 struct isl_basic_map *res;
4121 enum isl_dim_type t;
4122 isl_size total;
4123 unsigned off;
4124
4125 if (!bmap)
4126 return NULL;
4127 if (n == 0) {
4128 bmap = isl_basic_map_reset(bmap, src_type);
4129 bmap = isl_basic_map_reset(bmap, dst_type);
4130 return bmap;
4131 }
4132
4133 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
4134 return isl_basic_map_free(bmap);
4135
4136 if (dst_type == src_type && dst_pos == src_pos)
4137 return bmap;
4138
4139 isl_assert(bmap->ctx, dst_type != src_type, goto error);
4140
4141 if (pos(bmap->dim, dst_type) + dst_pos ==
4142 pos(bmap->dim, src_type) + src_pos +
4143 ((src_type < dst_type) ? n : 0)) {
4144 space = isl_basic_map_take_space(bmap);
4145 space = isl_space_move_dims(space, dst_type, dst_pos,
4146 src_type, src_pos, n);
4147 bmap = isl_basic_map_restore_space(bmap, space);
4148 bmap = isl_basic_map_finalize(bmap);
4149
4150 return bmap;
4151 }
4152
4153 total = isl_basic_map_dim(bmap, isl_dim_all);
4154 if (total < 0)
4155 return isl_basic_map_free(bmap);
4156 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4157
4158 off = 0;
4159 space = isl_basic_map_peek_space(bmap);
4160 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4161 isl_size size = isl_space_dim(space, t);
4162 if (size < 0)
4163 dim_map = isl_dim_map_free(dim_map);
4164 if (t == dst_type) {
4165 isl_dim_map_dim_range(dim_map, space, t,
4166 0, dst_pos, off);
4167 off += dst_pos;
4168 isl_dim_map_dim_range(dim_map, space, src_type,
4169 src_pos, n, off);
4170 off += n;
4171 isl_dim_map_dim_range(dim_map, space, t,
4172 dst_pos, size - dst_pos, off);
4173 off += size - dst_pos;
4174 } else if (t == src_type) {
4175 isl_dim_map_dim_range(dim_map, space, t,
4176 0, src_pos, off);
4177 off += src_pos;
4178 isl_dim_map_dim_range(dim_map, space, t,
4179 src_pos + n, size - src_pos - n, off);
4180 off += size - src_pos - n;
4181 } else {
4182 isl_dim_map_dim(dim_map, space, t, off);
4183 off += size;
4184 }
4185 }
4186 isl_dim_map_div(dim_map, bmap, off);
4187
4188 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4189 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4190 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4191 space = isl_basic_map_take_space(bmap);
4192 space = isl_space_move_dims(space, dst_type, dst_pos,
4193 src_type, src_pos, n);
4194 bmap = isl_basic_map_restore_space(bmap, space);
4195 if (!bmap)
4196 goto error;
4197
4198 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4199 bmap = isl_basic_map_gauss(bmap, NULL);
4200 bmap = isl_basic_map_finalize(bmap);
4201
4202 return bmap;
4203 error:
4204 isl_basic_map_free(bmap);
4205 return NULL;
4206 }
4207
isl_basic_set_move_dims(__isl_take isl_basic_set * bset,enum isl_dim_type dst_type,unsigned dst_pos,enum isl_dim_type src_type,unsigned src_pos,unsigned n)4208 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4209 enum isl_dim_type dst_type, unsigned dst_pos,
4210 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4211 {
4212 isl_basic_map *bmap = bset_to_bmap(bset);
4213 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4214 src_type, src_pos, n);
4215 return bset_from_bmap(bmap);
4216 }
4217
isl_set_move_dims(__isl_take isl_set * set,enum isl_dim_type dst_type,unsigned dst_pos,enum isl_dim_type src_type,unsigned src_pos,unsigned n)4218 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4219 enum isl_dim_type dst_type, unsigned dst_pos,
4220 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4221 {
4222 if (!set)
4223 return NULL;
4224 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4225 return set_from_map(isl_map_move_dims(set_to_map(set),
4226 dst_type, dst_pos, src_type, src_pos, n));
4227 error:
4228 isl_set_free(set);
4229 return NULL;
4230 }
4231
isl_map_move_dims(__isl_take isl_map * map,enum isl_dim_type dst_type,unsigned dst_pos,enum isl_dim_type src_type,unsigned src_pos,unsigned n)4232 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4233 enum isl_dim_type dst_type, unsigned dst_pos,
4234 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4235 {
4236 int i;
4237 isl_space *space;
4238
4239 if (n == 0) {
4240 map = isl_map_reset(map, src_type);
4241 map = isl_map_reset(map, dst_type);
4242 return map;
4243 }
4244
4245 if (isl_map_check_range(map, src_type, src_pos, n))
4246 return isl_map_free(map);
4247
4248 if (dst_type == src_type && dst_pos == src_pos)
4249 return map;
4250
4251 isl_assert(map->ctx, dst_type != src_type, goto error);
4252
4253 map = isl_map_cow(map);
4254 if (!map)
4255 return NULL;
4256
4257 for (i = 0; i < map->n; ++i) {
4258 map->p[i] = isl_basic_map_move_dims(map->p[i],
4259 dst_type, dst_pos,
4260 src_type, src_pos, n);
4261 if (!map->p[i])
4262 goto error;
4263 }
4264
4265 space = isl_map_take_space(map);
4266 space = isl_space_move_dims(space, dst_type, dst_pos,
4267 src_type, src_pos, n);
4268 map = isl_map_restore_space(map, space);
4269
4270 return map;
4271 error:
4272 isl_map_free(map);
4273 return NULL;
4274 }
4275
4276 /* Move the specified dimensions to the last columns right before
4277 * the divs. Don't change the dimension specification of bmap.
4278 * That's the responsibility of the caller.
4279 */
move_last(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4280 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4281 enum isl_dim_type type, unsigned first, unsigned n)
4282 {
4283 isl_space *space;
4284 struct isl_dim_map *dim_map;
4285 struct isl_basic_map *res;
4286 enum isl_dim_type t;
4287 isl_size total;
4288 unsigned off;
4289
4290 if (!bmap)
4291 return NULL;
4292 if (isl_basic_map_offset(bmap, type) + first + n ==
4293 isl_basic_map_offset(bmap, isl_dim_div))
4294 return bmap;
4295
4296 total = isl_basic_map_dim(bmap, isl_dim_all);
4297 if (total < 0)
4298 return isl_basic_map_free(bmap);
4299 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4300
4301 off = 0;
4302 space = isl_basic_map_peek_space(bmap);
4303 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4304 isl_size size = isl_space_dim(space, t);
4305 if (size < 0)
4306 dim_map = isl_dim_map_free(dim_map);
4307 if (t == type) {
4308 isl_dim_map_dim_range(dim_map, space, t,
4309 0, first, off);
4310 off += first;
4311 isl_dim_map_dim_range(dim_map, space, t,
4312 first, n, total - bmap->n_div - n);
4313 isl_dim_map_dim_range(dim_map, space, t,
4314 first + n, size - (first + n), off);
4315 off += size - (first + n);
4316 } else {
4317 isl_dim_map_dim(dim_map, space, t, off);
4318 off += size;
4319 }
4320 }
4321 isl_dim_map_div(dim_map, bmap, off + n);
4322
4323 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4324 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4325 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4326 return res;
4327 }
4328
4329 /* Insert "n" rows in the divs of "bmap".
4330 *
4331 * The number of columns is not changed, which means that the last
4332 * dimensions of "bmap" are being reintepreted as the new divs.
4333 * The space of "bmap" is not adjusted, however, which means
4334 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4335 * from the space of "bmap" is the responsibility of the caller.
4336 */
insert_div_rows(__isl_take isl_basic_map * bmap,int n)4337 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4338 int n)
4339 {
4340 int i;
4341 size_t row_size;
4342 isl_int **new_div;
4343 isl_int *old;
4344
4345 bmap = isl_basic_map_cow(bmap);
4346 if (!bmap)
4347 return NULL;
4348
4349 row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;
4350 old = bmap->block2.data;
4351 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4352 (bmap->extra + n) * (1 + row_size));
4353 if (!bmap->block2.data)
4354 return isl_basic_map_free(bmap);
4355 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4356 if (!new_div)
4357 return isl_basic_map_free(bmap);
4358 for (i = 0; i < n; ++i) {
4359 new_div[i] = bmap->block2.data +
4360 (bmap->extra + i) * (1 + row_size);
4361 isl_seq_clr(new_div[i], 1 + row_size);
4362 }
4363 for (i = 0; i < bmap->extra; ++i)
4364 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4365 free(bmap->div);
4366 bmap->div = new_div;
4367 bmap->n_div += n;
4368 bmap->extra += n;
4369
4370 return bmap;
4371 }
4372
4373 /* Drop constraints from "bmap" that only involve the variables
4374 * of "type" in the range [first, first + n] that are not related
4375 * to any of the variables outside that interval.
4376 * These constraints cannot influence the values for the variables
4377 * outside the interval, except in case they cause "bmap" to be empty.
4378 * Only drop the constraints if "bmap" is known to be non-empty.
4379 */
drop_irrelevant_constraints(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4380 static __isl_give isl_basic_map *drop_irrelevant_constraints(
4381 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4382 unsigned first, unsigned n)
4383 {
4384 int i;
4385 int *groups;
4386 isl_size dim, n_div;
4387 isl_bool non_empty;
4388
4389 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4390 if (non_empty < 0)
4391 return isl_basic_map_free(bmap);
4392 if (!non_empty)
4393 return bmap;
4394
4395 dim = isl_basic_map_dim(bmap, isl_dim_all);
4396 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4397 if (dim < 0 || n_div < 0)
4398 return isl_basic_map_free(bmap);
4399 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4400 if (!groups)
4401 return isl_basic_map_free(bmap);
4402 first += isl_basic_map_offset(bmap, type) - 1;
4403 for (i = 0; i < first; ++i)
4404 groups[i] = -1;
4405 for (i = first + n; i < dim - n_div; ++i)
4406 groups[i] = -1;
4407
4408 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4409
4410 return bmap;
4411 }
4412
4413 /* Turn the n dimensions of type type, starting at first
4414 * into existentially quantified variables.
4415 *
4416 * If a subset of the projected out variables are unrelated
4417 * to any of the variables that remain, then the constraints
4418 * involving this subset are simply dropped first.
4419 */
isl_basic_map_project_out(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,unsigned n)4420 __isl_give isl_basic_map *isl_basic_map_project_out(
4421 __isl_take isl_basic_map *bmap,
4422 enum isl_dim_type type, unsigned first, unsigned n)
4423 {
4424 isl_bool empty;
4425 isl_space *space;
4426
4427 if (n == 0)
4428 return basic_map_space_reset(bmap, type);
4429 if (type == isl_dim_div)
4430 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4431 "cannot project out existentially quantified variables",
4432 return isl_basic_map_free(bmap));
4433
4434 empty = isl_basic_map_plain_is_empty(bmap);
4435 if (empty < 0)
4436 return isl_basic_map_free(bmap);
4437 if (empty)
4438 bmap = isl_basic_map_set_to_empty(bmap);
4439
4440 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4441 if (!bmap)
4442 return NULL;
4443
4444 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4445 return isl_basic_map_remove_dims(bmap, type, first, n);
4446
4447 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4448 return isl_basic_map_free(bmap);
4449
4450 bmap = move_last(bmap, type, first, n);
4451 bmap = isl_basic_map_cow(bmap);
4452 bmap = insert_div_rows(bmap, n);
4453
4454 space = isl_basic_map_take_space(bmap);
4455 space = isl_space_drop_dims(space, type, first, n);
4456 bmap = isl_basic_map_restore_space(bmap, space);
4457 bmap = isl_basic_map_simplify(bmap);
4458 bmap = isl_basic_map_drop_redundant_divs(bmap);
4459 return isl_basic_map_finalize(bmap);
4460 }
4461
4462 /* Turn the n dimensions of type type, starting at first
4463 * into existentially quantified variables.
4464 */
isl_basic_set_project_out(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n)4465 __isl_give isl_basic_set *isl_basic_set_project_out(
4466 __isl_take isl_basic_set *bset, enum isl_dim_type type,
4467 unsigned first, unsigned n)
4468 {
4469 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4470 type, first, n));
4471 }
4472
4473 /* Turn the n dimensions of type type, starting at first
4474 * into existentially quantified variables.
4475 */
isl_map_project_out(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)4476 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4477 enum isl_dim_type type, unsigned first, unsigned n)
4478 {
4479 int i;
4480 isl_space *space;
4481
4482 if (n == 0)
4483 return map_space_reset(map, type);
4484
4485 if (isl_map_check_range(map, type, first, n) < 0)
4486 return isl_map_free(map);
4487
4488 map = isl_map_cow(map);
4489 if (!map)
4490 return NULL;
4491
4492 for (i = 0; i < map->n; ++i) {
4493 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4494 if (!map->p[i])
4495 goto error;
4496 }
4497
4498 if (map->n > 1)
4499 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4500 map = isl_map_unmark_normalized(map);
4501
4502 space = isl_map_take_space(map);
4503 space = isl_space_drop_dims(space, type, first, n);
4504 map = isl_map_restore_space(map, space);
4505
4506 return map;
4507 error:
4508 isl_map_free(map);
4509 return NULL;
4510 }
4511
4512 #undef TYPE
4513 #define TYPE isl_map
4514 #include "isl_project_out_all_params_templ.c"
4515
4516 /* Turn all the dimensions of type "type", except the "n" starting at "first"
4517 * into existentially quantified variables.
4518 */
isl_map_project_onto(__isl_take isl_map * map,enum isl_dim_type type,unsigned first,unsigned n)4519 __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4520 enum isl_dim_type type, unsigned first, unsigned n)
4521 {
4522 isl_size dim;
4523
4524 dim = isl_map_dim(map, type);
4525 if (isl_map_check_range(map, type, first, n) < 0 || dim < 0)
4526 return isl_map_free(map);
4527 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4528 map = isl_map_project_out(map, type, 0, first);
4529 return map;
4530 }
4531
4532 /* Turn the n dimensions of type type, starting at first
4533 * into existentially quantified variables.
4534 */
isl_set_project_out(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)4535 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4536 enum isl_dim_type type, unsigned first, unsigned n)
4537 {
4538 return set_from_map(isl_map_project_out(set_to_map(set),
4539 type, first, n));
4540 }
4541
4542 /* If "set" involves a parameter with identifier "id",
4543 * then turn it into an existentially quantified variable.
4544 */
isl_set_project_out_param_id(__isl_take isl_set * set,__isl_take isl_id * id)4545 __isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,
4546 __isl_take isl_id *id)
4547 {
4548 int pos;
4549
4550 if (!set || !id)
4551 goto error;
4552 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
4553 isl_id_free(id);
4554 if (pos < 0)
4555 return set;
4556 return isl_set_project_out(set, isl_dim_param, pos, 1);
4557 error:
4558 isl_set_free(set);
4559 isl_id_free(id);
4560 return NULL;
4561 }
4562
4563 /* If "set" involves any of the parameters with identifiers in "list",
4564 * then turn them into existentially quantified variables.
4565 */
isl_set_project_out_param_id_list(__isl_take isl_set * set,__isl_take isl_id_list * list)4566 __isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,
4567 __isl_take isl_id_list *list)
4568 {
4569 int i;
4570 isl_size n;
4571
4572 n = isl_id_list_size(list);
4573 if (n < 0)
4574 goto error;
4575 for (i = 0; i < n; ++i) {
4576 isl_id *id;
4577
4578 id = isl_id_list_get_at(list, i);
4579 set = isl_set_project_out_param_id(set, id);
4580 }
4581
4582 isl_id_list_free(list);
4583 return set;
4584 error:
4585 isl_id_list_free(list);
4586 isl_set_free(set);
4587 return NULL;
4588 }
4589
4590 /* Project out all parameters from "set" by existentially quantifying
4591 * over them.
4592 */
isl_set_project_out_all_params(__isl_take isl_set * set)4593 __isl_give isl_set *isl_set_project_out_all_params(__isl_take isl_set *set)
4594 {
4595 return set_from_map(isl_map_project_out_all_params(set_to_map(set)));
4596 }
4597
4598 /* Return a map that projects the elements in "set" onto their
4599 * "n" set dimensions starting at "first".
4600 * "type" should be equal to isl_dim_set.
4601 */
isl_set_project_onto_map(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)4602 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4603 enum isl_dim_type type, unsigned first, unsigned n)
4604 {
4605 int i;
4606 isl_map *map;
4607
4608 if (type != isl_dim_set)
4609 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4610 "only set dimensions can be projected out", goto error);
4611 if (isl_set_check_range(set, type, first, n) < 0)
4612 return isl_set_free(set);
4613
4614 map = isl_map_from_domain(set);
4615 map = isl_map_add_dims(map, isl_dim_out, n);
4616 for (i = 0; i < n; ++i)
4617 map = isl_map_equate(map, isl_dim_in, first + i,
4618 isl_dim_out, i);
4619 return map;
4620 error:
4621 isl_set_free(set);
4622 return NULL;
4623 }
4624
add_divs(__isl_take isl_basic_map * bmap,unsigned n)4625 static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4626 unsigned n)
4627 {
4628 int i, j;
4629 isl_size total;
4630
4631 total = isl_basic_map_dim(bmap, isl_dim_all);
4632 if (total < 0)
4633 return isl_basic_map_free(bmap);
4634 for (i = 0; i < n; ++i) {
4635 j = isl_basic_map_alloc_div(bmap);
4636 if (j < 0)
4637 goto error;
4638 isl_seq_clr(bmap->div[j], 1 + 1 + total);
4639 }
4640 return bmap;
4641 error:
4642 isl_basic_map_free(bmap);
4643 return NULL;
4644 }
4645
4646 /* Does "bmap2" apply to the range of "bmap1" (ignoring parameters)?
4647 */
isl_basic_map_applies_range(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)4648 isl_bool isl_basic_map_applies_range(__isl_keep isl_basic_map *bmap1,
4649 __isl_keep isl_basic_map *bmap2)
4650 {
4651 isl_space *space1, *space2;
4652
4653 space1 = isl_basic_map_peek_space(bmap1);
4654 space2 = isl_basic_map_peek_space(bmap2);
4655 return isl_space_tuple_is_equal(space1, isl_dim_out,
4656 space2, isl_dim_in);
4657 }
4658
4659 /* Check that "bmap2" applies to the range of "bmap1" (ignoring parameters).
4660 */
isl_basic_map_check_applies_range(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)4661 static isl_stat isl_basic_map_check_applies_range(
4662 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
4663 {
4664 isl_bool equal;
4665
4666 equal = isl_basic_map_applies_range(bmap1, bmap2);
4667 if (equal < 0)
4668 return isl_stat_error;
4669 if (!equal)
4670 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4671 "spaces don't match", return isl_stat_error);
4672 return isl_stat_ok;
4673 }
4674
isl_basic_map_apply_range(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4675 __isl_give isl_basic_map *isl_basic_map_apply_range(
4676 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
4677 {
4678 isl_space *space_result = NULL;
4679 struct isl_basic_map *bmap;
4680 isl_size n_in, n_out, n, nparam;
4681 unsigned total, pos;
4682 struct isl_dim_map *dim_map1, *dim_map2;
4683
4684 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4685 goto error;
4686 if (isl_basic_map_check_applies_range(bmap1, bmap2) < 0)
4687 goto error;
4688
4689 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4690 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4691 n = isl_basic_map_dim(bmap1, isl_dim_out);
4692 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4693 if (n_in < 0 || n_out < 0 || n < 0 || nparam < 0)
4694 goto error;
4695
4696 space_result = isl_space_join(isl_basic_map_get_space(bmap1),
4697 isl_basic_map_get_space(bmap2));
4698
4699 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4700 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4701 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4702 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4703 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4704 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4705 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4706 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4707 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4708 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4709 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4710
4711 bmap = isl_basic_map_alloc_space(space_result,
4712 bmap1->n_div + bmap2->n_div + n,
4713 bmap1->n_eq + bmap2->n_eq,
4714 bmap1->n_ineq + bmap2->n_ineq);
4715 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4716 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4717 bmap = add_divs(bmap, n);
4718 bmap = isl_basic_map_simplify(bmap);
4719 bmap = isl_basic_map_drop_redundant_divs(bmap);
4720 return isl_basic_map_finalize(bmap);
4721 error:
4722 isl_basic_map_free(bmap1);
4723 isl_basic_map_free(bmap2);
4724 return NULL;
4725 }
4726
isl_basic_set_apply(__isl_take isl_basic_set * bset,__isl_take isl_basic_map * bmap)4727 __isl_give isl_basic_set *isl_basic_set_apply(__isl_take isl_basic_set *bset,
4728 __isl_take isl_basic_map *bmap)
4729 {
4730 if (isl_basic_map_check_compatible_domain(bmap, bset) < 0)
4731 goto error;
4732
4733 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4734 bmap));
4735 error:
4736 isl_basic_set_free(bset);
4737 isl_basic_map_free(bmap);
4738 return NULL;
4739 }
4740
isl_basic_map_apply_domain(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4741 __isl_give isl_basic_map *isl_basic_map_apply_domain(
4742 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
4743 {
4744 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4745 goto error;
4746 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4747 bmap2->dim, isl_dim_in))
4748 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4749 "spaces don't match", goto error);
4750
4751 bmap1 = isl_basic_map_reverse(bmap1);
4752 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4753 return isl_basic_map_reverse(bmap1);
4754 error:
4755 isl_basic_map_free(bmap1);
4756 isl_basic_map_free(bmap2);
4757 return NULL;
4758 }
4759
4760 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4761 * A \cap B -> f(A) + f(B)
4762 */
isl_basic_map_sum(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)4763 __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4764 __isl_take isl_basic_map *bmap2)
4765 {
4766 isl_size n_in, n_out, nparam;
4767 unsigned total, pos;
4768 struct isl_basic_map *bmap = NULL;
4769 struct isl_dim_map *dim_map1, *dim_map2;
4770 int i;
4771
4772 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
4773 goto error;
4774
4775 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4776 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4777 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4778 if (nparam < 0 || n_in < 0 || n_out < 0)
4779 goto error;
4780
4781 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4782 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4783 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4784 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4785 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4786 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4787 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4788 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4789 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4790 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4791 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4792
4793 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4794 bmap1->n_div + bmap2->n_div + 2 * n_out,
4795 bmap1->n_eq + bmap2->n_eq + n_out,
4796 bmap1->n_ineq + bmap2->n_ineq);
4797 for (i = 0; i < n_out; ++i) {
4798 int j = isl_basic_map_alloc_equality(bmap);
4799 if (j < 0)
4800 goto error;
4801 isl_seq_clr(bmap->eq[j], 1+total);
4802 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4803 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4804 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4805 }
4806 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4807 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4808 bmap = add_divs(bmap, 2 * n_out);
4809
4810 bmap = isl_basic_map_simplify(bmap);
4811 return isl_basic_map_finalize(bmap);
4812 error:
4813 isl_basic_map_free(bmap);
4814 isl_basic_map_free(bmap1);
4815 isl_basic_map_free(bmap2);
4816 return NULL;
4817 }
4818
4819 /* Given two maps A -> f(A) and B -> g(B), construct a map
4820 * A \cap B -> f(A) + f(B)
4821 */
isl_map_sum(__isl_take isl_map * map1,__isl_take isl_map * map2)4822 __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4823 __isl_take isl_map *map2)
4824 {
4825 struct isl_map *result;
4826 int i, j;
4827
4828 if (isl_map_check_equal_space(map1, map2) < 0)
4829 goto error;
4830
4831 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4832 map1->n * map2->n, 0);
4833 if (!result)
4834 goto error;
4835 for (i = 0; i < map1->n; ++i)
4836 for (j = 0; j < map2->n; ++j) {
4837 struct isl_basic_map *part;
4838 part = isl_basic_map_sum(
4839 isl_basic_map_copy(map1->p[i]),
4840 isl_basic_map_copy(map2->p[j]));
4841 if (isl_basic_map_is_empty(part))
4842 isl_basic_map_free(part);
4843 else
4844 result = isl_map_add_basic_map(result, part);
4845 if (!result)
4846 goto error;
4847 }
4848 isl_map_free(map1);
4849 isl_map_free(map2);
4850 return result;
4851 error:
4852 isl_map_free(map1);
4853 isl_map_free(map2);
4854 return NULL;
4855 }
4856
isl_set_sum(__isl_take isl_set * set1,__isl_take isl_set * set2)4857 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4858 __isl_take isl_set *set2)
4859 {
4860 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4861 }
4862
4863 /* Given a basic map A -> f(A), construct A -> -f(A).
4864 */
isl_basic_map_neg(__isl_take isl_basic_map * bmap)4865 __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4866 {
4867 int i, j;
4868 unsigned off;
4869 isl_size n;
4870
4871 bmap = isl_basic_map_cow(bmap);
4872 n = isl_basic_map_dim(bmap, isl_dim_out);
4873 if (n < 0)
4874 return isl_basic_map_free(bmap);
4875
4876 off = isl_basic_map_offset(bmap, isl_dim_out);
4877 for (i = 0; i < bmap->n_eq; ++i)
4878 for (j = 0; j < n; ++j)
4879 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4880 for (i = 0; i < bmap->n_ineq; ++i)
4881 for (j = 0; j < n; ++j)
4882 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4883 for (i = 0; i < bmap->n_div; ++i)
4884 for (j = 0; j < n; ++j)
4885 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4886 bmap = isl_basic_map_gauss(bmap, NULL);
4887 return isl_basic_map_finalize(bmap);
4888 }
4889
isl_basic_set_neg(__isl_take isl_basic_set * bset)4890 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4891 {
4892 return isl_basic_map_neg(bset);
4893 }
4894
4895 /* Given a map A -> f(A), construct A -> -f(A).
4896 */
isl_map_neg(__isl_take isl_map * map)4897 __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4898 {
4899 int i;
4900
4901 map = isl_map_cow(map);
4902 if (!map)
4903 return NULL;
4904
4905 for (i = 0; i < map->n; ++i) {
4906 map->p[i] = isl_basic_map_neg(map->p[i]);
4907 if (!map->p[i])
4908 goto error;
4909 }
4910
4911 return map;
4912 error:
4913 isl_map_free(map);
4914 return NULL;
4915 }
4916
isl_set_neg(__isl_take isl_set * set)4917 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4918 {
4919 return set_from_map(isl_map_neg(set_to_map(set)));
4920 }
4921
4922 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4923 * A -> floor(f(A)/d).
4924 */
isl_basic_map_floordiv(__isl_take isl_basic_map * bmap,isl_int d)4925 __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4926 isl_int d)
4927 {
4928 isl_size n_in, n_out, nparam;
4929 unsigned total, pos;
4930 struct isl_basic_map *result = NULL;
4931 struct isl_dim_map *dim_map;
4932 int i;
4933
4934 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4935 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4936 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4937 if (nparam < 0 || n_in < 0 || n_out < 0)
4938 return isl_basic_map_free(bmap);
4939
4940 total = nparam + n_in + n_out + bmap->n_div + n_out;
4941 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4942 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4943 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4944 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4945 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4946
4947 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4948 bmap->n_div + n_out,
4949 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4950 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4951 result = add_divs(result, n_out);
4952 for (i = 0; i < n_out; ++i) {
4953 int j;
4954 j = isl_basic_map_alloc_inequality(result);
4955 if (j < 0)
4956 goto error;
4957 isl_seq_clr(result->ineq[j], 1+total);
4958 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4959 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4960 j = isl_basic_map_alloc_inequality(result);
4961 if (j < 0)
4962 goto error;
4963 isl_seq_clr(result->ineq[j], 1+total);
4964 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4965 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4966 isl_int_sub_ui(result->ineq[j][0], d, 1);
4967 }
4968
4969 result = isl_basic_map_simplify(result);
4970 return isl_basic_map_finalize(result);
4971 error:
4972 isl_basic_map_free(result);
4973 return NULL;
4974 }
4975
4976 /* Given a map A -> f(A) and an integer d, construct a map
4977 * A -> floor(f(A)/d).
4978 */
isl_map_floordiv(__isl_take isl_map * map,isl_int d)4979 __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4980 {
4981 int i;
4982
4983 map = isl_map_cow(map);
4984 if (!map)
4985 return NULL;
4986
4987 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4988 for (i = 0; i < map->n; ++i) {
4989 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4990 if (!map->p[i])
4991 goto error;
4992 }
4993 map = isl_map_unmark_normalized(map);
4994
4995 return map;
4996 error:
4997 isl_map_free(map);
4998 return NULL;
4999 }
5000
5001 /* Given a map A -> f(A) and an integer d, construct a map
5002 * A -> floor(f(A)/d).
5003 */
isl_map_floordiv_val(__isl_take isl_map * map,__isl_take isl_val * d)5004 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
5005 __isl_take isl_val *d)
5006 {
5007 if (!map || !d)
5008 goto error;
5009 if (!isl_val_is_int(d))
5010 isl_die(isl_val_get_ctx(d), isl_error_invalid,
5011 "expecting integer denominator", goto error);
5012 map = isl_map_floordiv(map, d->n);
5013 isl_val_free(d);
5014 return map;
5015 error:
5016 isl_map_free(map);
5017 isl_val_free(d);
5018 return NULL;
5019 }
5020
var_equal(__isl_take isl_basic_map * bmap,unsigned pos)5021 static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
5022 unsigned pos)
5023 {
5024 int i;
5025 isl_size nparam;
5026 isl_size n_in;
5027 isl_size total;
5028
5029 total = isl_basic_map_dim(bmap, isl_dim_all);
5030 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5031 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5032 if (total < 0 || nparam < 0 || n_in < 0)
5033 return isl_basic_map_free(bmap);
5034 i = isl_basic_map_alloc_equality(bmap);
5035 if (i < 0)
5036 goto error;
5037 isl_seq_clr(bmap->eq[i], 1 + total);
5038 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
5039 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
5040 return isl_basic_map_finalize(bmap);
5041 error:
5042 isl_basic_map_free(bmap);
5043 return NULL;
5044 }
5045
5046 /* Add a constraint to "bmap" expressing i_pos < o_pos
5047 */
var_less(__isl_take isl_basic_map * bmap,unsigned pos)5048 static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
5049 unsigned pos)
5050 {
5051 int i;
5052 isl_size nparam;
5053 isl_size n_in;
5054 isl_size total;
5055
5056 total = isl_basic_map_dim(bmap, isl_dim_all);
5057 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5058 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5059 if (total < 0 || nparam < 0 || n_in < 0)
5060 return isl_basic_map_free(bmap);
5061 i = isl_basic_map_alloc_inequality(bmap);
5062 if (i < 0)
5063 goto error;
5064 isl_seq_clr(bmap->ineq[i], 1 + total);
5065 isl_int_set_si(bmap->ineq[i][0], -1);
5066 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5067 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5068 return isl_basic_map_finalize(bmap);
5069 error:
5070 isl_basic_map_free(bmap);
5071 return NULL;
5072 }
5073
5074 /* Add a constraint to "bmap" expressing i_pos <= o_pos
5075 */
var_less_or_equal(__isl_take isl_basic_map * bmap,unsigned pos)5076 static __isl_give isl_basic_map *var_less_or_equal(
5077 __isl_take isl_basic_map *bmap, unsigned pos)
5078 {
5079 int i;
5080 isl_size nparam;
5081 isl_size n_in;
5082 isl_size total;
5083
5084 total = isl_basic_map_dim(bmap, isl_dim_all);
5085 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5086 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5087 if (total < 0 || nparam < 0 || n_in < 0)
5088 return isl_basic_map_free(bmap);
5089 i = isl_basic_map_alloc_inequality(bmap);
5090 if (i < 0)
5091 goto error;
5092 isl_seq_clr(bmap->ineq[i], 1 + total);
5093 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5094 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5095 return isl_basic_map_finalize(bmap);
5096 error:
5097 isl_basic_map_free(bmap);
5098 return NULL;
5099 }
5100
5101 /* Add a constraint to "bmap" expressing i_pos > o_pos
5102 */
var_more(__isl_take isl_basic_map * bmap,unsigned pos)5103 static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
5104 unsigned pos)
5105 {
5106 int i;
5107 isl_size nparam;
5108 isl_size n_in;
5109 isl_size total;
5110
5111 total = isl_basic_map_dim(bmap, isl_dim_all);
5112 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5113 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5114 if (total < 0 || nparam < 0 || n_in < 0)
5115 return isl_basic_map_free(bmap);
5116 i = isl_basic_map_alloc_inequality(bmap);
5117 if (i < 0)
5118 goto error;
5119 isl_seq_clr(bmap->ineq[i], 1 + total);
5120 isl_int_set_si(bmap->ineq[i][0], -1);
5121 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5122 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5123 return isl_basic_map_finalize(bmap);
5124 error:
5125 isl_basic_map_free(bmap);
5126 return NULL;
5127 }
5128
5129 /* Add a constraint to "bmap" expressing i_pos >= o_pos
5130 */
var_more_or_equal(__isl_take isl_basic_map * bmap,unsigned pos)5131 static __isl_give isl_basic_map *var_more_or_equal(
5132 __isl_take isl_basic_map *bmap, unsigned pos)
5133 {
5134 int i;
5135 isl_size nparam;
5136 isl_size n_in;
5137 isl_size total;
5138
5139 total = isl_basic_map_dim(bmap, isl_dim_all);
5140 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5141 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5142 if (total < 0 || nparam < 0 || n_in < 0)
5143 return isl_basic_map_free(bmap);
5144 i = isl_basic_map_alloc_inequality(bmap);
5145 if (i < 0)
5146 goto error;
5147 isl_seq_clr(bmap->ineq[i], 1 + total);
5148 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5149 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5150 return isl_basic_map_finalize(bmap);
5151 error:
5152 isl_basic_map_free(bmap);
5153 return NULL;
5154 }
5155
isl_basic_map_equal(__isl_take isl_space * space,unsigned n_equal)5156 __isl_give isl_basic_map *isl_basic_map_equal(
5157 __isl_take isl_space *space, unsigned n_equal)
5158 {
5159 int i;
5160 struct isl_basic_map *bmap;
5161 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
5162 if (!bmap)
5163 return NULL;
5164 for (i = 0; i < n_equal && bmap; ++i)
5165 bmap = var_equal(bmap, i);
5166 return isl_basic_map_finalize(bmap);
5167 }
5168
5169 /* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
5170 */
isl_basic_map_less_at(__isl_take isl_space * space,unsigned pos)5171 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
5172 unsigned pos)
5173 {
5174 int i;
5175 struct isl_basic_map *bmap;
5176 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5177 if (!bmap)
5178 return NULL;
5179 for (i = 0; i < pos && bmap; ++i)
5180 bmap = var_equal(bmap, i);
5181 if (bmap)
5182 bmap = var_less(bmap, pos);
5183 return isl_basic_map_finalize(bmap);
5184 }
5185
5186 /* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
5187 */
isl_basic_map_less_or_equal_at(__isl_take isl_space * space,unsigned pos)5188 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
5189 __isl_take isl_space *space, unsigned pos)
5190 {
5191 int i;
5192 isl_basic_map *bmap;
5193
5194 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5195 for (i = 0; i < pos; ++i)
5196 bmap = var_equal(bmap, i);
5197 bmap = var_less_or_equal(bmap, pos);
5198 return isl_basic_map_finalize(bmap);
5199 }
5200
5201 /* Return a relation on "space" expressing i_pos > o_pos
5202 */
isl_basic_map_more_at(__isl_take isl_space * space,unsigned pos)5203 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
5204 unsigned pos)
5205 {
5206 int i;
5207 struct isl_basic_map *bmap;
5208 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5209 if (!bmap)
5210 return NULL;
5211 for (i = 0; i < pos && bmap; ++i)
5212 bmap = var_equal(bmap, i);
5213 if (bmap)
5214 bmap = var_more(bmap, pos);
5215 return isl_basic_map_finalize(bmap);
5216 }
5217
5218 /* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
5219 */
isl_basic_map_more_or_equal_at(__isl_take isl_space * space,unsigned pos)5220 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
5221 __isl_take isl_space *space, unsigned pos)
5222 {
5223 int i;
5224 isl_basic_map *bmap;
5225
5226 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5227 for (i = 0; i < pos; ++i)
5228 bmap = var_equal(bmap, i);
5229 bmap = var_more_or_equal(bmap, pos);
5230 return isl_basic_map_finalize(bmap);
5231 }
5232
map_lex_lte_first(__isl_take isl_space * space,unsigned n,int equal)5233 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
5234 unsigned n, int equal)
5235 {
5236 struct isl_map *map;
5237 int i;
5238
5239 if (n == 0 && equal)
5240 return isl_map_universe(space);
5241
5242 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5243
5244 for (i = 0; i + 1 < n; ++i)
5245 map = isl_map_add_basic_map(map,
5246 isl_basic_map_less_at(isl_space_copy(space), i));
5247 if (n > 0) {
5248 if (equal)
5249 map = isl_map_add_basic_map(map,
5250 isl_basic_map_less_or_equal_at(space, n - 1));
5251 else
5252 map = isl_map_add_basic_map(map,
5253 isl_basic_map_less_at(space, n - 1));
5254 } else
5255 isl_space_free(space);
5256
5257 return map;
5258 }
5259
map_lex_lte(__isl_take isl_space * space,int equal)5260 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
5261 {
5262 if (!space)
5263 return NULL;
5264 return map_lex_lte_first(space, space->n_out, equal);
5265 }
5266
isl_map_lex_lt_first(__isl_take isl_space * space,unsigned n)5267 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *space,
5268 unsigned n)
5269 {
5270 return map_lex_lte_first(space, n, 0);
5271 }
5272
isl_map_lex_le_first(__isl_take isl_space * space,unsigned n)5273 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *space,
5274 unsigned n)
5275 {
5276 return map_lex_lte_first(space, n, 1);
5277 }
5278
isl_map_lex_lt(__isl_take isl_space * set_space)5279 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_space)
5280 {
5281 return map_lex_lte(isl_space_map_from_set(set_space), 0);
5282 }
5283
isl_map_lex_le(__isl_take isl_space * set_space)5284 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_space)
5285 {
5286 return map_lex_lte(isl_space_map_from_set(set_space), 1);
5287 }
5288
map_lex_gte_first(__isl_take isl_space * space,unsigned n,int equal)5289 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5290 unsigned n, int equal)
5291 {
5292 struct isl_map *map;
5293 int i;
5294
5295 if (n == 0 && equal)
5296 return isl_map_universe(space);
5297
5298 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5299
5300 for (i = 0; i + 1 < n; ++i)
5301 map = isl_map_add_basic_map(map,
5302 isl_basic_map_more_at(isl_space_copy(space), i));
5303 if (n > 0) {
5304 if (equal)
5305 map = isl_map_add_basic_map(map,
5306 isl_basic_map_more_or_equal_at(space, n - 1));
5307 else
5308 map = isl_map_add_basic_map(map,
5309 isl_basic_map_more_at(space, n - 1));
5310 } else
5311 isl_space_free(space);
5312
5313 return map;
5314 }
5315
map_lex_gte(__isl_take isl_space * space,int equal)5316 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5317 {
5318 if (!space)
5319 return NULL;
5320 return map_lex_gte_first(space, space->n_out, equal);
5321 }
5322
isl_map_lex_gt_first(__isl_take isl_space * space,unsigned n)5323 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *space,
5324 unsigned n)
5325 {
5326 return map_lex_gte_first(space, n, 0);
5327 }
5328
isl_map_lex_ge_first(__isl_take isl_space * space,unsigned n)5329 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *space,
5330 unsigned n)
5331 {
5332 return map_lex_gte_first(space, n, 1);
5333 }
5334
isl_map_lex_gt(__isl_take isl_space * set_space)5335 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_space)
5336 {
5337 return map_lex_gte(isl_space_map_from_set(set_space), 0);
5338 }
5339
isl_map_lex_ge(__isl_take isl_space * set_space)5340 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_space)
5341 {
5342 return map_lex_gte(isl_space_map_from_set(set_space), 1);
5343 }
5344
isl_set_lex_le_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5345 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5346 __isl_take isl_set *set2)
5347 {
5348 isl_map *map;
5349 map = isl_map_lex_le(isl_set_get_space(set1));
5350 map = isl_map_intersect_domain(map, set1);
5351 map = isl_map_intersect_range(map, set2);
5352 return map;
5353 }
5354
isl_set_lex_lt_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5355 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5356 __isl_take isl_set *set2)
5357 {
5358 isl_map *map;
5359 map = isl_map_lex_lt(isl_set_get_space(set1));
5360 map = isl_map_intersect_domain(map, set1);
5361 map = isl_map_intersect_range(map, set2);
5362 return map;
5363 }
5364
isl_set_lex_ge_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5365 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5366 __isl_take isl_set *set2)
5367 {
5368 isl_map *map;
5369 map = isl_map_lex_ge(isl_set_get_space(set1));
5370 map = isl_map_intersect_domain(map, set1);
5371 map = isl_map_intersect_range(map, set2);
5372 return map;
5373 }
5374
isl_set_lex_gt_set(__isl_take isl_set * set1,__isl_take isl_set * set2)5375 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5376 __isl_take isl_set *set2)
5377 {
5378 isl_map *map;
5379 map = isl_map_lex_gt(isl_set_get_space(set1));
5380 map = isl_map_intersect_domain(map, set1);
5381 map = isl_map_intersect_range(map, set2);
5382 return map;
5383 }
5384
isl_map_lex_le_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5385 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5386 __isl_take isl_map *map2)
5387 {
5388 isl_map *map;
5389 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5390 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5391 map = isl_map_apply_range(map, isl_map_reverse(map2));
5392 return map;
5393 }
5394
isl_map_lex_lt_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5395 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5396 __isl_take isl_map *map2)
5397 {
5398 isl_map *map;
5399 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5400 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5401 map = isl_map_apply_range(map, isl_map_reverse(map2));
5402 return map;
5403 }
5404
isl_map_lex_ge_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5405 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5406 __isl_take isl_map *map2)
5407 {
5408 isl_map *map;
5409 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5410 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5411 map = isl_map_apply_range(map, isl_map_reverse(map2));
5412 return map;
5413 }
5414
isl_map_lex_gt_map(__isl_take isl_map * map1,__isl_take isl_map * map2)5415 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5416 __isl_take isl_map *map2)
5417 {
5418 isl_map *map;
5419 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5420 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5421 map = isl_map_apply_range(map, isl_map_reverse(map2));
5422 return map;
5423 }
5424
5425 /* For the div d = floor(f/m) at position "div", add the constraint
5426 *
5427 * f - m d >= 0
5428 */
add_upper_div_constraint(__isl_take isl_basic_map * bmap,unsigned div)5429 static __isl_give isl_basic_map *add_upper_div_constraint(
5430 __isl_take isl_basic_map *bmap, unsigned div)
5431 {
5432 int i;
5433 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5434 isl_size n_div;
5435 unsigned pos;
5436
5437 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5438 if (v_div < 0 || n_div < 0)
5439 return isl_basic_map_free(bmap);
5440 pos = v_div + div;
5441 i = isl_basic_map_alloc_inequality(bmap);
5442 if (i < 0)
5443 return isl_basic_map_free(bmap);
5444 isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5445 isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5446
5447 return bmap;
5448 }
5449
5450 /* For the div d = floor(f/m) at position "div", add the constraint
5451 *
5452 * -(f-(m-1)) + m d >= 0
5453 */
add_lower_div_constraint(__isl_take isl_basic_map * bmap,unsigned div)5454 static __isl_give isl_basic_map *add_lower_div_constraint(
5455 __isl_take isl_basic_map *bmap, unsigned div)
5456 {
5457 int i;
5458 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5459 isl_size n_div;
5460 unsigned pos;
5461
5462 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5463 if (v_div < 0 || n_div < 0)
5464 return isl_basic_map_free(bmap);
5465 pos = v_div + div;
5466 i = isl_basic_map_alloc_inequality(bmap);
5467 if (i < 0)
5468 return isl_basic_map_free(bmap);
5469 isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5470 isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5471 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5472 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5473
5474 return bmap;
5475 }
5476
5477 /* For the div d = floor(f/m) at position "pos", add the constraints
5478 *
5479 * f - m d >= 0
5480 * -(f-(m-1)) + m d >= 0
5481 *
5482 * Note that the second constraint is the negation of
5483 *
5484 * f - m d >= m
5485 */
isl_basic_map_add_div_constraints(__isl_take isl_basic_map * bmap,unsigned pos)5486 __isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5487 __isl_take isl_basic_map *bmap, unsigned pos)
5488 {
5489 bmap = add_upper_div_constraint(bmap, pos);
5490 bmap = add_lower_div_constraint(bmap, pos);
5491 return bmap;
5492 }
5493
5494 /* For each known div d = floor(f/m), add the constraints
5495 *
5496 * f - m d >= 0
5497 * -(f-(m-1)) + m d >= 0
5498 *
5499 * Remove duplicate constraints in case of some these div constraints
5500 * already appear in "bmap".
5501 */
isl_basic_map_add_known_div_constraints(__isl_take isl_basic_map * bmap)5502 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5503 __isl_take isl_basic_map *bmap)
5504 {
5505 isl_size n_div;
5506
5507 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5508 if (n_div < 0)
5509 return isl_basic_map_free(bmap);
5510 if (n_div == 0)
5511 return bmap;
5512
5513 bmap = add_known_div_constraints(bmap);
5514 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5515 bmap = isl_basic_map_finalize(bmap);
5516 return bmap;
5517 }
5518
5519 /* Add the div constraint of sign "sign" for div "div" of "bmap".
5520 *
5521 * In particular, if this div is of the form d = floor(f/m),
5522 * then add the constraint
5523 *
5524 * f - m d >= 0
5525 *
5526 * if sign < 0 or the constraint
5527 *
5528 * -(f-(m-1)) + m d >= 0
5529 *
5530 * if sign > 0.
5531 */
isl_basic_map_add_div_constraint(__isl_take isl_basic_map * bmap,unsigned div,int sign)5532 __isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5533 __isl_take isl_basic_map *bmap, unsigned div, int sign)
5534 {
5535 if (sign < 0)
5536 return add_upper_div_constraint(bmap, div);
5537 else
5538 return add_lower_div_constraint(bmap, div);
5539 }
5540
isl_basic_map_underlying_set(__isl_take isl_basic_map * bmap)5541 __isl_give isl_basic_set *isl_basic_map_underlying_set(
5542 __isl_take isl_basic_map *bmap)
5543 {
5544 isl_space *space;
5545
5546 if (!bmap)
5547 goto error;
5548 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5549 bmap->n_div == 0 &&
5550 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5551 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5552 return bset_from_bmap(bmap);
5553 bmap = isl_basic_map_cow(bmap);
5554 if (!bmap)
5555 return NULL;
5556 space = isl_basic_map_take_space(bmap);
5557 space = isl_space_underlying(space, bmap->n_div);
5558 bmap = isl_basic_map_restore_space(bmap, space);
5559 if (!bmap)
5560 return NULL;
5561 bmap->extra -= bmap->n_div;
5562 bmap->n_div = 0;
5563 bmap = isl_basic_map_finalize(bmap);
5564 return bset_from_bmap(bmap);
5565 error:
5566 isl_basic_map_free(bmap);
5567 return NULL;
5568 }
5569
isl_basic_set_underlying_set(__isl_take isl_basic_set * bset)5570 __isl_give isl_basic_set *isl_basic_set_underlying_set(
5571 __isl_take isl_basic_set *bset)
5572 {
5573 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5574 }
5575
5576 /* Replace each element in "list" by the result of applying
5577 * isl_basic_map_underlying_set to the element.
5578 */
isl_basic_map_list_underlying_set(__isl_take isl_basic_map_list * list)5579 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5580 __isl_take isl_basic_map_list *list)
5581 {
5582 int i;
5583 isl_size n;
5584
5585 n = isl_basic_map_list_n_basic_map(list);
5586 if (n < 0)
5587 goto error;
5588
5589 for (i = 0; i < n; ++i) {
5590 isl_basic_map *bmap;
5591 isl_basic_set *bset;
5592
5593 bmap = isl_basic_map_list_get_basic_map(list, i);
5594 bset = isl_basic_set_underlying_set(bmap);
5595 list = isl_basic_set_list_set_basic_set(list, i, bset);
5596 }
5597
5598 return list;
5599 error:
5600 isl_basic_map_list_free(list);
5601 return NULL;
5602 }
5603
isl_basic_map_overlying_set(__isl_take isl_basic_set * bset,__isl_take isl_basic_map * like)5604 __isl_give isl_basic_map *isl_basic_map_overlying_set(
5605 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5606 {
5607 struct isl_basic_map *bmap;
5608 struct isl_ctx *ctx;
5609 isl_size dim, bmap_total;
5610 unsigned total;
5611 int i;
5612
5613 if (!bset || !like)
5614 goto error;
5615 ctx = bset->ctx;
5616 if (isl_basic_set_check_no_params(bset) < 0 ||
5617 isl_basic_set_check_no_locals(bset) < 0)
5618 goto error;
5619 dim = isl_basic_set_dim(bset, isl_dim_set);
5620 bmap_total = isl_basic_map_dim(like, isl_dim_all);
5621 if (dim < 0 || bmap_total < 0)
5622 goto error;
5623 isl_assert(ctx, dim == bmap_total, goto error);
5624 if (like->n_div == 0) {
5625 isl_space *space = isl_basic_map_get_space(like);
5626 isl_basic_map_free(like);
5627 return isl_basic_map_reset_space(bset, space);
5628 }
5629 bset = isl_basic_set_cow(bset);
5630 if (!bset)
5631 goto error;
5632 total = dim + bset->extra;
5633 bmap = bset_to_bmap(bset);
5634 isl_space_free(isl_basic_map_take_space(bmap));
5635 bmap = isl_basic_map_restore_space(bmap, isl_basic_map_get_space(like));
5636 if (!bmap)
5637 goto error;
5638 bmap->n_div = like->n_div;
5639 bmap->extra += like->n_div;
5640 if (bmap->extra) {
5641 unsigned ltotal;
5642 isl_int **div;
5643 ltotal = total - bmap->extra + like->extra;
5644 if (ltotal > total)
5645 ltotal = total;
5646 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5647 bmap->extra * (1 + 1 + total));
5648 if (isl_blk_is_error(bmap->block2))
5649 goto error;
5650 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5651 if (!div)
5652 goto error;
5653 bmap->div = div;
5654 for (i = 0; i < bmap->extra; ++i)
5655 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5656 for (i = 0; i < like->n_div; ++i) {
5657 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5658 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5659 }
5660 bmap = isl_basic_map_add_known_div_constraints(bmap);
5661 }
5662 isl_basic_map_free(like);
5663 bmap = isl_basic_map_simplify(bmap);
5664 bmap = isl_basic_map_finalize(bmap);
5665 return bmap;
5666 error:
5667 isl_basic_map_free(like);
5668 isl_basic_set_free(bset);
5669 return NULL;
5670 }
5671
isl_basic_set_from_underlying_set(__isl_take isl_basic_set * bset,__isl_take isl_basic_set * like)5672 __isl_give isl_basic_set *isl_basic_set_from_underlying_set(
5673 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *like)
5674 {
5675 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5676 bset_to_bmap(like)));
5677 }
5678
isl_map_underlying_set(__isl_take isl_map * map)5679 __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5680 {
5681 int i;
5682
5683 map = isl_map_cow(map);
5684 if (!map)
5685 return NULL;
5686 map->dim = isl_space_cow(map->dim);
5687 if (!map->dim)
5688 goto error;
5689
5690 for (i = 1; i < map->n; ++i)
5691 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5692 goto error);
5693 for (i = 0; i < map->n; ++i) {
5694 map->p[i] = bset_to_bmap(
5695 isl_basic_map_underlying_set(map->p[i]));
5696 if (!map->p[i])
5697 goto error;
5698 }
5699 if (map->n == 0)
5700 map->dim = isl_space_underlying(map->dim, 0);
5701 else {
5702 isl_space_free(map->dim);
5703 map->dim = isl_space_copy(map->p[0]->dim);
5704 }
5705 if (!map->dim)
5706 goto error;
5707 return set_from_map(map);
5708 error:
5709 isl_map_free(map);
5710 return NULL;
5711 }
5712
5713 /* Replace the space of "bmap" by "space".
5714 *
5715 * If the space of "bmap" is identical to "space" (including the identifiers
5716 * of the input and output dimensions), then simply return the original input.
5717 */
isl_basic_map_reset_space(__isl_take isl_basic_map * bmap,__isl_take isl_space * space)5718 __isl_give isl_basic_map *isl_basic_map_reset_space(
5719 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5720 {
5721 isl_bool equal;
5722 isl_space *bmap_space;
5723
5724 bmap_space = isl_basic_map_peek_space(bmap);
5725 equal = isl_space_is_equal(bmap_space, space);
5726 if (equal >= 0 && equal)
5727 equal = isl_space_has_equal_ids(bmap_space, space);
5728 if (equal < 0)
5729 goto error;
5730 if (equal) {
5731 isl_space_free(space);
5732 return bmap;
5733 }
5734 isl_space_free(isl_basic_map_take_space(bmap));
5735 bmap = isl_basic_map_restore_space(bmap, space);
5736
5737 bmap = isl_basic_map_finalize(bmap);
5738
5739 return bmap;
5740 error:
5741 isl_basic_map_free(bmap);
5742 isl_space_free(space);
5743 return NULL;
5744 }
5745
isl_basic_set_reset_space(__isl_take isl_basic_set * bset,__isl_take isl_space * space)5746 __isl_give isl_basic_set *isl_basic_set_reset_space(
5747 __isl_take isl_basic_set *bset, __isl_take isl_space *space)
5748 {
5749 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5750 space));
5751 }
5752
5753 /* Check that the total dimensions of "map" and "space" are the same.
5754 */
check_map_space_equal_total_dim(__isl_keep isl_map * map,__isl_keep isl_space * space)5755 static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5756 __isl_keep isl_space *space)
5757 {
5758 isl_size dim1, dim2;
5759
5760 dim1 = isl_map_dim(map, isl_dim_all);
5761 dim2 = isl_space_dim(space, isl_dim_all);
5762 if (dim1 < 0 || dim2 < 0)
5763 return isl_stat_error;
5764 if (dim1 == dim2)
5765 return isl_stat_ok;
5766 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5767 "total dimensions do not match", return isl_stat_error);
5768 }
5769
isl_map_reset_space(__isl_take isl_map * map,__isl_take isl_space * space)5770 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5771 __isl_take isl_space *space)
5772 {
5773 int i;
5774
5775 map = isl_map_cow(map);
5776 if (!map || !space)
5777 goto error;
5778
5779 for (i = 0; i < map->n; ++i) {
5780 map->p[i] = isl_basic_map_reset_space(map->p[i],
5781 isl_space_copy(space));
5782 if (!map->p[i])
5783 goto error;
5784 }
5785 isl_space_free(isl_map_take_space(map));
5786 map = isl_map_restore_space(map, space);
5787
5788 return map;
5789 error:
5790 isl_map_free(map);
5791 isl_space_free(space);
5792 return NULL;
5793 }
5794
5795 /* Replace the space of "map" by "space", without modifying
5796 * the dimension of "map".
5797 *
5798 * If the space of "map" is identical to "space" (including the identifiers
5799 * of the input and output dimensions), then simply return the original input.
5800 */
isl_map_reset_equal_dim_space(__isl_take isl_map * map,__isl_take isl_space * space)5801 __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5802 __isl_take isl_space *space)
5803 {
5804 isl_bool equal;
5805 isl_space *map_space;
5806
5807 map_space = isl_map_peek_space(map);
5808 equal = isl_space_is_equal(map_space, space);
5809 if (equal >= 0 && equal)
5810 equal = isl_space_has_equal_ids(map_space, space);
5811 if (equal < 0)
5812 goto error;
5813 if (equal) {
5814 isl_space_free(space);
5815 return map;
5816 }
5817 if (check_map_space_equal_total_dim(map, space) < 0)
5818 goto error;
5819 return isl_map_reset_space(map, space);
5820 error:
5821 isl_map_free(map);
5822 isl_space_free(space);
5823 return NULL;
5824 }
5825
isl_set_reset_space(__isl_take isl_set * set,__isl_take isl_space * space)5826 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5827 __isl_take isl_space *space)
5828 {
5829 return set_from_map(isl_map_reset_space(set_to_map(set), space));
5830 }
5831
5832 /* Compute the parameter domain of the given basic set.
5833 */
isl_basic_set_params(__isl_take isl_basic_set * bset)5834 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5835 {
5836 isl_bool is_params;
5837 isl_space *space;
5838 isl_size n;
5839
5840 is_params = isl_basic_set_is_params(bset);
5841 if (is_params < 0)
5842 return isl_basic_set_free(bset);
5843 if (is_params)
5844 return bset;
5845
5846 n = isl_basic_set_dim(bset, isl_dim_set);
5847 if (n < 0)
5848 return isl_basic_set_free(bset);
5849 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5850 space = isl_basic_set_get_space(bset);
5851 space = isl_space_params(space);
5852 bset = isl_basic_set_reset_space(bset, space);
5853 return bset;
5854 }
5855
5856 /* Construct a zero-dimensional basic set with the given parameter domain.
5857 */
isl_basic_set_from_params(__isl_take isl_basic_set * bset)5858 __isl_give isl_basic_set *isl_basic_set_from_params(
5859 __isl_take isl_basic_set *bset)
5860 {
5861 isl_space *space;
5862 space = isl_basic_set_get_space(bset);
5863 space = isl_space_set_from_params(space);
5864 bset = isl_basic_set_reset_space(bset, space);
5865 return bset;
5866 }
5867
5868 /* Compute the parameter domain of the given set.
5869 */
isl_set_params(__isl_take isl_set * set)5870 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5871 {
5872 return isl_map_params(set_to_map(set));
5873 }
5874
5875 /* Construct a zero-dimensional set with the given parameter domain.
5876 */
isl_set_from_params(__isl_take isl_set * set)5877 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5878 {
5879 isl_space *space;
5880 space = isl_set_get_space(set);
5881 space = isl_space_set_from_params(space);
5882 set = isl_set_reset_space(set, space);
5883 return set;
5884 }
5885
5886 /* Compute the parameter domain of the given map.
5887 */
isl_map_params(__isl_take isl_map * map)5888 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5889 {
5890 isl_space *space;
5891 isl_size n_in, n_out;
5892
5893 n_in = isl_map_dim(map, isl_dim_in);
5894 n_out = isl_map_dim(map, isl_dim_out);
5895 if (n_in < 0 || n_out < 0)
5896 return isl_map_free(map);
5897 map = isl_map_project_out(map, isl_dim_in, 0, n_in);
5898 map = isl_map_project_out(map, isl_dim_out, 0, n_out);
5899 space = isl_map_get_space(map);
5900 space = isl_space_params(space);
5901 map = isl_map_reset_space(map, space);
5902 return map;
5903 }
5904
isl_basic_map_domain(__isl_take isl_basic_map * bmap)5905 __isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5906 {
5907 isl_space *space;
5908 isl_size n_out;
5909
5910 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5911 if (n_out < 0)
5912 return isl_basic_map_free(bmap);
5913 space = isl_space_domain(isl_basic_map_get_space(bmap));
5914
5915 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5916
5917 return isl_basic_map_reset_space(bmap, space);
5918 }
5919
isl_basic_map_may_be_set(__isl_keep isl_basic_map * bmap)5920 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5921 {
5922 if (!bmap)
5923 return isl_bool_error;
5924 return isl_space_may_be_set(bmap->dim);
5925 }
5926
5927 /* Is this basic map actually a set?
5928 * Users should never call this function. Outside of isl,
5929 * the type should indicate whether something is a set or a map.
5930 */
isl_basic_map_is_set(__isl_keep isl_basic_map * bmap)5931 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5932 {
5933 if (!bmap)
5934 return isl_bool_error;
5935 return isl_space_is_set(bmap->dim);
5936 }
5937
isl_basic_map_range(__isl_take isl_basic_map * bmap)5938 __isl_give isl_basic_set *isl_basic_map_range(__isl_take isl_basic_map *bmap)
5939 {
5940 isl_bool is_set;
5941
5942 is_set = isl_basic_map_is_set(bmap);
5943 if (is_set < 0)
5944 goto error;
5945 if (is_set)
5946 return bmap;
5947 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5948 error:
5949 isl_basic_map_free(bmap);
5950 return NULL;
5951 }
5952
isl_basic_map_domain_map(__isl_take isl_basic_map * bmap)5953 __isl_give isl_basic_map *isl_basic_map_domain_map(
5954 __isl_take isl_basic_map *bmap)
5955 {
5956 int i;
5957 isl_space *space;
5958 isl_basic_map *domain;
5959 isl_size nparam, n_in, n_out;
5960
5961 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5962 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5963 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5964 if (nparam < 0 || n_in < 0 || n_out < 0)
5965 return isl_basic_map_free(bmap);
5966
5967 space = isl_basic_map_get_space(bmap);
5968 space = isl_space_from_range(isl_space_domain(space));
5969 domain = isl_basic_map_universe(space);
5970
5971 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5972 bmap = isl_basic_map_apply_range(bmap, domain);
5973 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5974
5975 for (i = 0; i < n_in; ++i)
5976 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5977 isl_dim_out, i);
5978
5979 bmap = isl_basic_map_gauss(bmap, NULL);
5980 return isl_basic_map_finalize(bmap);
5981 }
5982
isl_basic_map_range_map(__isl_take isl_basic_map * bmap)5983 __isl_give isl_basic_map *isl_basic_map_range_map(
5984 __isl_take isl_basic_map *bmap)
5985 {
5986 int i;
5987 isl_space *space;
5988 isl_basic_map *range;
5989 isl_size nparam, n_in, n_out;
5990
5991 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5992 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5993 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5994 if (nparam < 0 || n_in < 0 || n_out < 0)
5995 return isl_basic_map_free(bmap);
5996
5997 space = isl_basic_map_get_space(bmap);
5998 space = isl_space_from_range(isl_space_range(space));
5999 range = isl_basic_map_universe(space);
6000
6001 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
6002 bmap = isl_basic_map_apply_range(bmap, range);
6003 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
6004
6005 for (i = 0; i < n_out; ++i)
6006 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
6007 isl_dim_out, i);
6008
6009 bmap = isl_basic_map_gauss(bmap, NULL);
6010 return isl_basic_map_finalize(bmap);
6011 }
6012
isl_map_may_be_set(__isl_keep isl_map * map)6013 int isl_map_may_be_set(__isl_keep isl_map *map)
6014 {
6015 if (!map)
6016 return -1;
6017 return isl_space_may_be_set(map->dim);
6018 }
6019
6020 /* Is this map actually a set?
6021 * Users should never call this function. Outside of isl,
6022 * the type should indicate whether something is a set or a map.
6023 */
isl_map_is_set(__isl_keep isl_map * map)6024 isl_bool isl_map_is_set(__isl_keep isl_map *map)
6025 {
6026 if (!map)
6027 return isl_bool_error;
6028 return isl_space_is_set(map->dim);
6029 }
6030
isl_map_range(__isl_take isl_map * map)6031 __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
6032 {
6033 isl_space *space;
6034 isl_size n_in;
6035
6036 n_in = isl_map_dim(map, isl_dim_in);
6037 if (n_in < 0)
6038 return set_from_map(isl_map_free(map));
6039 space = isl_space_range(isl_map_get_space(map));
6040
6041 map = isl_map_project_out(map, isl_dim_in, 0, n_in);
6042
6043 return set_from_map(isl_map_reset_space(map, space));
6044 }
6045
6046 /* Transform "map" by applying "fn_space" to its space and "fn_bmap"
6047 * to each of its basic maps.
6048 */
isl_map_transform(__isl_take isl_map * map,__isl_give isl_space * (* fn_space)(__isl_take isl_space * space),__isl_give isl_basic_map * (* fn_bmap)(__isl_take isl_basic_map * bmap))6049 static __isl_give isl_map *isl_map_transform(__isl_take isl_map *map,
6050 __isl_give isl_space *(*fn_space)(__isl_take isl_space *space),
6051 __isl_give isl_basic_map *(*fn_bmap)(__isl_take isl_basic_map *bmap))
6052 {
6053 int i;
6054 isl_space *space;
6055
6056 map = isl_map_cow(map);
6057 if (!map)
6058 return NULL;
6059
6060 for (i = 0; i < map->n; ++i) {
6061 map->p[i] = fn_bmap(map->p[i]);
6062 if (!map->p[i])
6063 return isl_map_free(map);
6064 }
6065 map = isl_map_unmark_normalized(map);
6066
6067 space = isl_map_take_space(map);
6068 space = fn_space(space);
6069 map = isl_map_restore_space(map, space);
6070
6071 return map;
6072 }
6073
isl_map_domain_map(__isl_take isl_map * map)6074 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
6075 {
6076 return isl_map_transform(map, &isl_space_domain_map,
6077 &isl_basic_map_domain_map);
6078 }
6079
isl_map_range_map(__isl_take isl_map * map)6080 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
6081 {
6082 return isl_map_transform(map, &isl_space_range_map,
6083 &isl_basic_map_range_map);
6084 }
6085
6086 /* Given a wrapped map of the form A[B -> C],
6087 * return the map A[B -> C] -> B.
6088 */
isl_set_wrapped_domain_map(__isl_take isl_set * set)6089 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
6090 {
6091 isl_id *id;
6092 isl_map *map;
6093
6094 if (!set)
6095 return NULL;
6096 if (!isl_set_has_tuple_id(set))
6097 return isl_map_domain_map(isl_set_unwrap(set));
6098
6099 id = isl_set_get_tuple_id(set);
6100 map = isl_map_domain_map(isl_set_unwrap(set));
6101 map = isl_map_set_tuple_id(map, isl_dim_in, id);
6102
6103 return map;
6104 }
6105
isl_basic_map_from_domain(__isl_take isl_basic_set * bset)6106 __isl_give isl_basic_map *isl_basic_map_from_domain(
6107 __isl_take isl_basic_set *bset)
6108 {
6109 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
6110 }
6111
isl_basic_map_from_range(__isl_take isl_basic_set * bset)6112 __isl_give isl_basic_map *isl_basic_map_from_range(
6113 __isl_take isl_basic_set *bset)
6114 {
6115 isl_space *space;
6116 space = isl_basic_set_get_space(bset);
6117 space = isl_space_from_range(space);
6118 bset = isl_basic_set_reset_space(bset, space);
6119 return bset_to_bmap(bset);
6120 }
6121
6122 /* Create a relation with the given set as range.
6123 * The domain of the created relation is a zero-dimensional
6124 * flat anonymous space.
6125 */
isl_map_from_range(__isl_take isl_set * set)6126 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
6127 {
6128 isl_space *space;
6129 space = isl_set_get_space(set);
6130 space = isl_space_from_range(space);
6131 set = isl_set_reset_space(set, space);
6132 return set_to_map(set);
6133 }
6134
6135 /* Create a relation with the given set as domain.
6136 * The range of the created relation is a zero-dimensional
6137 * flat anonymous space.
6138 */
isl_map_from_domain(__isl_take isl_set * set)6139 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
6140 {
6141 return isl_map_reverse(isl_map_from_range(set));
6142 }
6143
isl_basic_map_from_domain_and_range(__isl_take isl_basic_set * domain,__isl_take isl_basic_set * range)6144 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
6145 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
6146 {
6147 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
6148 }
6149
isl_map_from_domain_and_range(__isl_take isl_set * domain,__isl_take isl_set * range)6150 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
6151 __isl_take isl_set *range)
6152 {
6153 return isl_map_apply_range(isl_map_reverse(domain), range);
6154 }
6155
6156 /* Return a newly allocated isl_map with given space and flags and
6157 * room for "n" basic maps.
6158 * Make sure that all cached information is cleared.
6159 */
isl_map_alloc_space(__isl_take isl_space * space,int n,unsigned flags)6160 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
6161 unsigned flags)
6162 {
6163 struct isl_map *map;
6164
6165 if (!space)
6166 return NULL;
6167 if (n < 0)
6168 isl_die(space->ctx, isl_error_internal,
6169 "negative number of basic maps", goto error);
6170 map = isl_calloc(space->ctx, struct isl_map,
6171 sizeof(struct isl_map) +
6172 (n - 1) * sizeof(struct isl_basic_map *));
6173 if (!map)
6174 goto error;
6175
6176 map->ctx = space->ctx;
6177 isl_ctx_ref(map->ctx);
6178 map->ref = 1;
6179 map->size = n;
6180 map->n = 0;
6181 map->dim = space;
6182 map->flags = flags;
6183 return map;
6184 error:
6185 isl_space_free(space);
6186 return NULL;
6187 }
6188
isl_basic_map_empty(__isl_take isl_space * space)6189 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
6190 {
6191 struct isl_basic_map *bmap;
6192 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
6193 bmap = isl_basic_map_set_to_empty(bmap);
6194 return bmap;
6195 }
6196
isl_basic_set_empty(__isl_take isl_space * space)6197 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
6198 {
6199 struct isl_basic_set *bset;
6200 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
6201 bset = isl_basic_set_set_to_empty(bset);
6202 return bset;
6203 }
6204
isl_basic_map_universe(__isl_take isl_space * space)6205 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6206 {
6207 struct isl_basic_map *bmap;
6208 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6209 bmap = isl_basic_map_finalize(bmap);
6210 return bmap;
6211 }
6212
isl_basic_set_universe(__isl_take isl_space * space)6213 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6214 {
6215 struct isl_basic_set *bset;
6216 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6217 bset = isl_basic_set_finalize(bset);
6218 return bset;
6219 }
6220
isl_basic_map_nat_universe(__isl_take isl_space * space)6221 __isl_give isl_basic_map *isl_basic_map_nat_universe(
6222 __isl_take isl_space *space)
6223 {
6224 int i;
6225 isl_size total = isl_space_dim(space, isl_dim_all);
6226 isl_basic_map *bmap;
6227
6228 if (total < 0)
6229 space = isl_space_free(space);
6230 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
6231 for (i = 0; i < total; ++i) {
6232 int k = isl_basic_map_alloc_inequality(bmap);
6233 if (k < 0)
6234 goto error;
6235 isl_seq_clr(bmap->ineq[k], 1 + total);
6236 isl_int_set_si(bmap->ineq[k][1 + i], 1);
6237 }
6238 return bmap;
6239 error:
6240 isl_basic_map_free(bmap);
6241 return NULL;
6242 }
6243
isl_basic_set_nat_universe(__isl_take isl_space * space)6244 __isl_give isl_basic_set *isl_basic_set_nat_universe(
6245 __isl_take isl_space *space)
6246 {
6247 return isl_basic_map_nat_universe(space);
6248 }
6249
isl_map_nat_universe(__isl_take isl_space * space)6250 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *space)
6251 {
6252 return isl_map_from_basic_map(isl_basic_map_nat_universe(space));
6253 }
6254
isl_set_nat_universe(__isl_take isl_space * space)6255 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *space)
6256 {
6257 return isl_map_nat_universe(space);
6258 }
6259
isl_map_empty(__isl_take isl_space * space)6260 __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6261 {
6262 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6263 }
6264
isl_set_empty(__isl_take isl_space * space)6265 __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6266 {
6267 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6268 }
6269
isl_map_universe(__isl_take isl_space * space)6270 __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6271 {
6272 struct isl_map *map;
6273 if (!space)
6274 return NULL;
6275 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6276 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6277 return map;
6278 }
6279
isl_set_universe(__isl_take isl_space * space)6280 __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6281 {
6282 struct isl_set *set;
6283 if (!space)
6284 return NULL;
6285 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6286 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6287 return set;
6288 }
6289
isl_map_dup(__isl_keep isl_map * map)6290 __isl_give isl_map *isl_map_dup(__isl_keep isl_map *map)
6291 {
6292 int i;
6293 struct isl_map *dup;
6294
6295 if (!map)
6296 return NULL;
6297 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6298 for (i = 0; i < map->n; ++i)
6299 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6300 return dup;
6301 }
6302
isl_map_add_basic_map(__isl_take isl_map * map,__isl_take isl_basic_map * bmap)6303 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6304 __isl_take isl_basic_map *bmap)
6305 {
6306 if (!bmap || !map)
6307 goto error;
6308 if (isl_basic_map_plain_is_empty(bmap)) {
6309 isl_basic_map_free(bmap);
6310 return map;
6311 }
6312 if (isl_map_basic_map_check_equal_space(map, bmap) < 0)
6313 goto error;
6314 isl_assert(map->ctx, map->n < map->size, goto error);
6315 map->p[map->n] = bmap;
6316 map->n++;
6317 map = isl_map_unmark_normalized(map);
6318 return map;
6319 error:
6320 if (map)
6321 isl_map_free(map);
6322 if (bmap)
6323 isl_basic_map_free(bmap);
6324 return NULL;
6325 }
6326
isl_map_free(__isl_take isl_map * map)6327 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6328 {
6329 int i;
6330
6331 if (!map)
6332 return NULL;
6333
6334 if (--map->ref > 0)
6335 return NULL;
6336
6337 clear_caches(map);
6338 isl_ctx_deref(map->ctx);
6339 for (i = 0; i < map->n; ++i)
6340 isl_basic_map_free(map->p[i]);
6341 isl_space_free(map->dim);
6342 free(map);
6343
6344 return NULL;
6345 }
6346
isl_basic_map_fix_pos_si(__isl_take isl_basic_map * bmap,unsigned pos,int value)6347 static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6348 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6349 {
6350 int j;
6351 isl_size total;
6352
6353 total = isl_basic_map_dim(bmap, isl_dim_all);
6354 if (total < 0)
6355 return isl_basic_map_free(bmap);
6356
6357 bmap = isl_basic_map_cow(bmap);
6358 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6359 j = isl_basic_map_alloc_equality(bmap);
6360 if (j < 0)
6361 goto error;
6362 isl_seq_clr(bmap->eq[j] + 1, total);
6363 isl_int_set_si(bmap->eq[j][pos], -1);
6364 isl_int_set_si(bmap->eq[j][0], value);
6365 bmap = isl_basic_map_simplify(bmap);
6366 return isl_basic_map_finalize(bmap);
6367 error:
6368 isl_basic_map_free(bmap);
6369 return NULL;
6370 }
6371
isl_basic_map_fix_pos(__isl_take isl_basic_map * bmap,unsigned pos,isl_int value)6372 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6373 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6374 {
6375 int j;
6376 isl_size total;
6377
6378 total = isl_basic_map_dim(bmap, isl_dim_all);
6379 if (total < 0)
6380 return isl_basic_map_free(bmap);
6381
6382 bmap = isl_basic_map_cow(bmap);
6383 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6384 j = isl_basic_map_alloc_equality(bmap);
6385 if (j < 0)
6386 goto error;
6387 isl_seq_clr(bmap->eq[j] + 1, total);
6388 isl_int_set_si(bmap->eq[j][pos], -1);
6389 isl_int_set(bmap->eq[j][0], value);
6390 bmap = isl_basic_map_simplify(bmap);
6391 return isl_basic_map_finalize(bmap);
6392 error:
6393 isl_basic_map_free(bmap);
6394 return NULL;
6395 }
6396
isl_basic_map_fix_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6397 __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6398 enum isl_dim_type type, unsigned pos, int value)
6399 {
6400 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6401 return isl_basic_map_free(bmap);
6402 return isl_basic_map_fix_pos_si(bmap,
6403 isl_basic_map_offset(bmap, type) + pos, value);
6404 }
6405
isl_basic_map_fix(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int value)6406 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6407 enum isl_dim_type type, unsigned pos, isl_int value)
6408 {
6409 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6410 return isl_basic_map_free(bmap);
6411 return isl_basic_map_fix_pos(bmap,
6412 isl_basic_map_offset(bmap, type) + pos, value);
6413 }
6414
6415 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
6416 * to be equal to "v".
6417 */
isl_basic_map_fix_val(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6418 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6419 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6420 {
6421 if (!bmap || !v)
6422 goto error;
6423 if (!isl_val_is_int(v))
6424 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6425 "expecting integer value", goto error);
6426 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6427 goto error;
6428 pos += isl_basic_map_offset(bmap, type);
6429 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6430 isl_val_free(v);
6431 return bmap;
6432 error:
6433 isl_basic_map_free(bmap);
6434 isl_val_free(v);
6435 return NULL;
6436 }
6437
6438 /* Fix the value of the variable at position "pos" of type "type" of "bset"
6439 * to be equal to "v".
6440 */
isl_basic_set_fix_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6441 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6442 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6443 {
6444 return isl_basic_map_fix_val(bset, type, pos, v);
6445 }
6446
isl_basic_set_fix_si(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,int value)6447 __isl_give isl_basic_set *isl_basic_set_fix_si(__isl_take isl_basic_set *bset,
6448 enum isl_dim_type type, unsigned pos, int value)
6449 {
6450 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6451 type, pos, value));
6452 }
6453
isl_basic_set_fix(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value)6454 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6455 enum isl_dim_type type, unsigned pos, isl_int value)
6456 {
6457 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6458 type, pos, value));
6459 }
6460
6461 /* Remove the basic map at position "i" from "map" if this basic map
6462 * is (obviously) empty.
6463 */
remove_if_empty(__isl_take isl_map * map,int i)6464 static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6465 {
6466 isl_bool empty;
6467
6468 if (!map)
6469 return NULL;
6470
6471 empty = isl_basic_map_plain_is_empty(map->p[i]);
6472 if (empty < 0)
6473 return isl_map_free(map);
6474 if (!empty)
6475 return map;
6476
6477 isl_basic_map_free(map->p[i]);
6478 map->n--;
6479 if (i != map->n) {
6480 map->p[i] = map->p[map->n];
6481 map = isl_map_unmark_normalized(map);
6482
6483 }
6484
6485 return map;
6486 }
6487
6488 /* Perform "fn" on each basic map of "map", where we may not be holding
6489 * the only reference to "map".
6490 * In particular, "fn" should be a semantics preserving operation
6491 * that we want to apply to all copies of "map". We therefore need
6492 * to be careful not to modify "map" in a way that breaks "map"
6493 * in case anything goes wrong.
6494 */
isl_map_inline_foreach_basic_map(__isl_take isl_map * map,__isl_give isl_basic_map * (* fn)(__isl_take isl_basic_map * bmap))6495 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6496 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6497 {
6498 struct isl_basic_map *bmap;
6499 int i;
6500
6501 if (!map)
6502 return NULL;
6503
6504 for (i = map->n - 1; i >= 0; --i) {
6505 bmap = isl_basic_map_copy(map->p[i]);
6506 bmap = fn(bmap);
6507 if (!bmap)
6508 goto error;
6509 isl_basic_map_free(map->p[i]);
6510 map->p[i] = bmap;
6511 map = remove_if_empty(map, i);
6512 if (!map)
6513 return NULL;
6514 }
6515
6516 return map;
6517 error:
6518 isl_map_free(map);
6519 return NULL;
6520 }
6521
isl_map_fix_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6522 __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6523 enum isl_dim_type type, unsigned pos, int value)
6524 {
6525 int i;
6526
6527 map = isl_map_cow(map);
6528 if (isl_map_check_range(map, type, pos, 1) < 0)
6529 return isl_map_free(map);
6530 for (i = map->n - 1; i >= 0; --i) {
6531 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6532 map = remove_if_empty(map, i);
6533 if (!map)
6534 return NULL;
6535 }
6536 map = isl_map_unmark_normalized(map);
6537 return map;
6538 }
6539
isl_set_fix_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6540 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6541 enum isl_dim_type type, unsigned pos, int value)
6542 {
6543 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6544 }
6545
isl_map_fix(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6546 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6547 enum isl_dim_type type, unsigned pos, isl_int value)
6548 {
6549 int i;
6550
6551 map = isl_map_cow(map);
6552 if (isl_map_check_range(map, type, pos, 1) < 0)
6553 return isl_map_free(map);
6554 for (i = 0; i < map->n; ++i) {
6555 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6556 if (!map->p[i])
6557 goto error;
6558 }
6559 map = isl_map_unmark_normalized(map);
6560 return map;
6561 error:
6562 isl_map_free(map);
6563 return NULL;
6564 }
6565
isl_set_fix(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6566 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6567 enum isl_dim_type type, unsigned pos, isl_int value)
6568 {
6569 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6570 }
6571
6572 /* Fix the value of the variable at position "pos" of type "type" of "map"
6573 * to be equal to "v".
6574 */
isl_map_fix_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6575 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6576 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6577 {
6578 int i;
6579
6580 map = isl_map_cow(map);
6581 if (!map || !v)
6582 goto error;
6583
6584 if (!isl_val_is_int(v))
6585 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6586 "expecting integer value", goto error);
6587 if (isl_map_check_range(map, type, pos, 1) < 0)
6588 goto error;
6589 for (i = map->n - 1; i >= 0; --i) {
6590 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6591 isl_val_copy(v));
6592 map = remove_if_empty(map, i);
6593 if (!map)
6594 goto error;
6595 }
6596 map = isl_map_unmark_normalized(map);
6597 isl_val_free(v);
6598 return map;
6599 error:
6600 isl_map_free(map);
6601 isl_val_free(v);
6602 return NULL;
6603 }
6604
6605 /* Fix the value of the variable at position "pos" of type "type" of "set"
6606 * to be equal to "v".
6607 */
isl_set_fix_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * v)6608 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6609 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6610 {
6611 return isl_map_fix_val(set, type, pos, v);
6612 }
6613
isl_map_fix_input_si(__isl_take isl_map * map,unsigned input,int value)6614 __isl_give isl_map *isl_map_fix_input_si(__isl_take isl_map *map,
6615 unsigned input, int value)
6616 {
6617 return isl_map_fix_si(map, isl_dim_in, input, value);
6618 }
6619
isl_set_fix_dim_si(__isl_take isl_set * set,unsigned dim,int value)6620 __isl_give isl_set *isl_set_fix_dim_si(__isl_take isl_set *set, unsigned dim,
6621 int value)
6622 {
6623 return set_from_map(isl_map_fix_si(set_to_map(set),
6624 isl_dim_set, dim, value));
6625 }
6626
basic_map_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value,int upper)6627 static __isl_give isl_basic_map *basic_map_bound_si(
6628 __isl_take isl_basic_map *bmap,
6629 enum isl_dim_type type, unsigned pos, int value, int upper)
6630 {
6631 int j;
6632 isl_size total;
6633
6634 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6635 return isl_basic_map_free(bmap);
6636 total = isl_basic_map_dim(bmap, isl_dim_all);
6637 if (total < 0)
6638 return isl_basic_map_free(bmap);
6639 pos += isl_basic_map_offset(bmap, type);
6640 bmap = isl_basic_map_cow(bmap);
6641 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6642 j = isl_basic_map_alloc_inequality(bmap);
6643 if (j < 0)
6644 goto error;
6645 isl_seq_clr(bmap->ineq[j], 1 + total);
6646 if (upper) {
6647 isl_int_set_si(bmap->ineq[j][pos], -1);
6648 isl_int_set_si(bmap->ineq[j][0], value);
6649 } else {
6650 isl_int_set_si(bmap->ineq[j][pos], 1);
6651 isl_int_set_si(bmap->ineq[j][0], -value);
6652 }
6653 bmap = isl_basic_map_simplify(bmap);
6654 return isl_basic_map_finalize(bmap);
6655 error:
6656 isl_basic_map_free(bmap);
6657 return NULL;
6658 }
6659
isl_basic_map_lower_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6660 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6661 __isl_take isl_basic_map *bmap,
6662 enum isl_dim_type type, unsigned pos, int value)
6663 {
6664 return basic_map_bound_si(bmap, type, pos, value, 0);
6665 }
6666
6667 /* Constrain the values of the given dimension to be no greater than "value".
6668 */
isl_basic_map_upper_bound_si(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int value)6669 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6670 __isl_take isl_basic_map *bmap,
6671 enum isl_dim_type type, unsigned pos, int value)
6672 {
6673 return basic_map_bound_si(bmap, type, pos, value, 1);
6674 }
6675
map_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value,int upper)6676 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6677 enum isl_dim_type type, unsigned pos, int value, int upper)
6678 {
6679 int i;
6680
6681 map = isl_map_cow(map);
6682 if (isl_map_check_range(map, type, pos, 1) < 0)
6683 return isl_map_free(map);
6684 for (i = 0; i < map->n; ++i) {
6685 map->p[i] = basic_map_bound_si(map->p[i],
6686 type, pos, value, upper);
6687 if (!map->p[i])
6688 goto error;
6689 }
6690 map = isl_map_unmark_normalized(map);
6691 return map;
6692 error:
6693 isl_map_free(map);
6694 return NULL;
6695 }
6696
isl_map_lower_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6697 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6698 enum isl_dim_type type, unsigned pos, int value)
6699 {
6700 return map_bound_si(map, type, pos, value, 0);
6701 }
6702
isl_map_upper_bound_si(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,int value)6703 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6704 enum isl_dim_type type, unsigned pos, int value)
6705 {
6706 return map_bound_si(map, type, pos, value, 1);
6707 }
6708
isl_set_lower_bound_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6709 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6710 enum isl_dim_type type, unsigned pos, int value)
6711 {
6712 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6713 type, pos, value));
6714 }
6715
isl_set_upper_bound_si(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,int value)6716 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6717 enum isl_dim_type type, unsigned pos, int value)
6718 {
6719 return isl_map_upper_bound_si(set, type, pos, value);
6720 }
6721
6722 /* Bound the given variable of "bmap" from below (or above is "upper"
6723 * is set) to "value".
6724 */
basic_map_bound(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6725 static __isl_give isl_basic_map *basic_map_bound(
6726 __isl_take isl_basic_map *bmap,
6727 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6728 {
6729 int j;
6730 isl_size total;
6731
6732 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6733 return isl_basic_map_free(bmap);
6734 total = isl_basic_map_dim(bmap, isl_dim_all);
6735 if (total < 0)
6736 return isl_basic_map_free(bmap);
6737 pos += isl_basic_map_offset(bmap, type);
6738 bmap = isl_basic_map_cow(bmap);
6739 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6740 j = isl_basic_map_alloc_inequality(bmap);
6741 if (j < 0)
6742 goto error;
6743 isl_seq_clr(bmap->ineq[j], 1 + total);
6744 if (upper) {
6745 isl_int_set_si(bmap->ineq[j][pos], -1);
6746 isl_int_set(bmap->ineq[j][0], value);
6747 } else {
6748 isl_int_set_si(bmap->ineq[j][pos], 1);
6749 isl_int_neg(bmap->ineq[j][0], value);
6750 }
6751 bmap = isl_basic_map_simplify(bmap);
6752 return isl_basic_map_finalize(bmap);
6753 error:
6754 isl_basic_map_free(bmap);
6755 return NULL;
6756 }
6757
6758 /* Bound the given variable of "map" from below (or above is "upper"
6759 * is set) to "value".
6760 */
map_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value,int upper)6761 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6762 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6763 {
6764 int i;
6765
6766 map = isl_map_cow(map);
6767 if (isl_map_check_range(map, type, pos, 1) < 0)
6768 return isl_map_free(map);
6769 for (i = map->n - 1; i >= 0; --i) {
6770 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6771 map = remove_if_empty(map, i);
6772 if (!map)
6773 return NULL;
6774 }
6775 map = isl_map_unmark_normalized(map);
6776 return map;
6777 }
6778
isl_map_lower_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6779 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6780 enum isl_dim_type type, unsigned pos, isl_int value)
6781 {
6782 return map_bound(map, type, pos, value, 0);
6783 }
6784
isl_map_upper_bound(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,isl_int value)6785 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6786 enum isl_dim_type type, unsigned pos, isl_int value)
6787 {
6788 return map_bound(map, type, pos, value, 1);
6789 }
6790
isl_set_lower_bound(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6791 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6792 enum isl_dim_type type, unsigned pos, isl_int value)
6793 {
6794 return isl_map_lower_bound(set, type, pos, value);
6795 }
6796
isl_set_upper_bound(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,isl_int value)6797 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6798 enum isl_dim_type type, unsigned pos, isl_int value)
6799 {
6800 return isl_map_upper_bound(set, type, pos, value);
6801 }
6802
6803 /* Force the values of the variable at position "pos" of type "type" of "map"
6804 * to be no smaller than "value".
6805 */
isl_map_lower_bound_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6806 __isl_give isl_map *isl_map_lower_bound_val(__isl_take isl_map *map,
6807 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6808 {
6809 if (!value)
6810 goto error;
6811 if (!isl_val_is_int(value))
6812 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6813 "expecting integer value", goto error);
6814 map = isl_map_lower_bound(map, type, pos, value->n);
6815 isl_val_free(value);
6816 return map;
6817 error:
6818 isl_val_free(value);
6819 isl_map_free(map);
6820 return NULL;
6821 }
6822
6823 /* Force the values of the variable at position "pos" of type "type" of "set"
6824 * to be no smaller than "value".
6825 */
isl_set_lower_bound_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6826 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6827 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6828 {
6829 isl_map *map;
6830
6831 map = set_to_map(set);
6832 return set_from_map(isl_map_lower_bound_val(map, type, pos, value));
6833 }
6834
6835 /* Force the values of the variable at position "pos" of type "type" of "map"
6836 * to be no greater than "value".
6837 */
isl_map_upper_bound_val(__isl_take isl_map * map,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6838 __isl_give isl_map *isl_map_upper_bound_val(__isl_take isl_map *map,
6839 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6840 {
6841 if (!value)
6842 goto error;
6843 if (!isl_val_is_int(value))
6844 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6845 "expecting integer value", goto error);
6846 map = isl_map_upper_bound(map, type, pos, value->n);
6847 isl_val_free(value);
6848 return map;
6849 error:
6850 isl_val_free(value);
6851 isl_map_free(map);
6852 return NULL;
6853 }
6854
6855 /* Force the values of the variable at position "pos" of type "type" of "set"
6856 * to be no greater than "value".
6857 */
isl_set_upper_bound_val(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)6858 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6859 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6860 {
6861 isl_map *map;
6862
6863 map = set_to_map(set);
6864 return set_from_map(isl_map_upper_bound_val(map, type, pos, value));
6865 }
6866
6867 /* If "mv" has an explicit domain, then intersect the domain of "map"
6868 * with this explicit domain.
6869 *
6870 * An isl_multi_val object never has an explicit domain,
6871 * so simply return "map".
6872 */
isl_map_intersect_multi_val_explicit_domain(__isl_take isl_map * map,__isl_keep isl_multi_val * mv)6873 static __isl_give isl_map *isl_map_intersect_multi_val_explicit_domain(
6874 __isl_take isl_map *map, __isl_keep isl_multi_val *mv)
6875 {
6876 return map;
6877 }
6878
6879 #undef BASE
6880 #define BASE val
6881 #include "isl_map_bound_templ.c"
6882
6883 /* Apply "map_bound" to "set" with the corresponding value in "bound"
6884 * for each set dimension, by treating the set as a map.
6885 */
set_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * bound,__isl_give isl_map * map_bound (__isl_take isl_map * map,unsigned pos,__isl_take isl_val * value))6886 static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,
6887 __isl_take isl_multi_val *bound,
6888 __isl_give isl_map *map_bound(__isl_take isl_map *map,
6889 unsigned pos, __isl_take isl_val *value))
6890 {
6891 isl_map *map;
6892
6893 map = set_to_map(set);
6894 return set_from_map(map_bound_multi_val(map, bound, map_bound));
6895 }
6896
6897 #undef BASE
6898 #define BASE pw_aff
6899 #include "isl_map_bound_templ.c"
6900
6901 /* Apply "map_bound" to "set" with the corresponding value in "bound"
6902 * for each set dimension, by converting the set and the bound
6903 * to objects living in a map space.
6904 */
set_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * bound,__isl_give isl_map * set_bound (__isl_take isl_map * map,unsigned pos,__isl_take TYPE * value))6905 static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,
6906 __isl_take isl_multi_pw_aff *bound,
6907 __isl_give isl_map *set_bound(__isl_take isl_map *map,
6908 unsigned pos, __isl_take TYPE *value))
6909 {
6910 isl_map *map;
6911
6912 map = isl_map_from_range(set);
6913 bound = isl_multi_pw_aff_from_range(bound);
6914 map = map_bound_multi_pw_aff(map, bound, set_bound);
6915 return isl_map_range(map);
6916 }
6917
6918 /* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,
6919 * setting a bound on the given output dimension.
6920 */
map_lower_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)6921 static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,
6922 unsigned pos, __isl_take isl_val *v)
6923 {
6924 return isl_map_lower_bound_val(map, isl_dim_out, pos, v);
6925 }
6926
6927 /* Force the values of the set dimensions of "set"
6928 * to be no smaller than the corresponding values in "lower".
6929 */
isl_set_lower_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * lower)6930 __isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
6931 __isl_take isl_multi_val *lower)
6932 {
6933 return set_bound_multi_val(set, lower, &map_lower_bound_val);
6934 }
6935
6936 /* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,
6937 * setting a bound on the given output dimension.
6938 */
map_upper_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)6939 static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,
6940 unsigned pos, __isl_take isl_val *v)
6941 {
6942 return isl_map_upper_bound_val(map, isl_dim_out, pos, v);
6943 }
6944
6945 /* Force the values of the set dimensions of "set"
6946 * to be no greater than the corresponding values in "upper".
6947 */
isl_set_upper_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * upper)6948 __isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
6949 __isl_take isl_multi_val *upper)
6950 {
6951 return set_bound_multi_val(set, upper, &map_upper_bound_val);
6952 }
6953
6954 /* Force the symbolic constant expression "bound"
6955 * to satisfy the relation "order" with respect to
6956 * the output variable at position "pos" of "map".
6957 *
6958 * Create an affine expression representing the output variable
6959 * in terms of the range and
6960 * compare it using "order" to "bound" (defined on the domain).
6961 * The result is a relation between elements in domain and range that
6962 * can be intersected with "map".
6963 */
map_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * bound,__isl_give isl_map * (* order)(__isl_take isl_pw_aff * pa1,__isl_take isl_pw_aff * pa2))6964 static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,
6965 unsigned pos, __isl_take isl_pw_aff *bound,
6966 __isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,
6967 __isl_take isl_pw_aff *pa2))
6968 {
6969 isl_space *space;
6970 isl_local_space *ls;
6971 isl_pw_aff *var;
6972
6973 space = isl_space_range(isl_map_get_space(map));
6974 ls = isl_local_space_from_space(space);
6975 var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);
6976 map = isl_map_intersect(map, order(bound, var));
6977 return map;
6978 }
6979
6980 /* Force the values of the output variable at position "pos" of "map"
6981 * to be no smaller than the symbolic constant expression "lower".
6982 */
map_lower_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * lower)6983 static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,
6984 unsigned pos, __isl_take isl_pw_aff *lower)
6985 {
6986 return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);
6987 }
6988
6989 /* Force the values of the output variable at position "pos" of "map"
6990 * to be no greater than the symbolic constant expression "upper".
6991 */
map_upper_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * upper)6992 static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,
6993 unsigned pos, __isl_take isl_pw_aff *upper)
6994 {
6995 return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);
6996 }
6997
6998 /* Force the values of the set dimensions of "set"
6999 * to be no smaller than the corresponding constant symbolic expressions
7000 * in "lower".
7001 */
isl_set_lower_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * lower)7002 __isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
7003 __isl_take isl_multi_pw_aff *lower)
7004 {
7005 return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);
7006 }
7007
7008 /* Force the values of the set dimensions of "set"
7009 * to be no greater than the corresponding constant symbolic expressions
7010 * in "upper".
7011 */
isl_set_upper_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * upper)7012 __isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
7013 __isl_take isl_multi_pw_aff *upper)
7014 {
7015 return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);
7016 }
7017
7018 /* Force the values of the output dimensions of "map"
7019 * to be no smaller than the corresponding constant symbolic expressions
7020 * in "lower".
7021 */
isl_map_lower_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * lower)7022 __isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
7023 __isl_take isl_multi_pw_aff *lower)
7024 {
7025 return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);
7026 }
7027
7028 /* Force the values of the output dimensions of "map"
7029 * to be no greater than the corresponding constant symbolic expressions
7030 * in "upper".
7031 */
isl_map_upper_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * upper)7032 __isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
7033 __isl_take isl_multi_pw_aff *upper)
7034 {
7035 return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);
7036 }
7037
7038 /* Bound the given variable of "bset" from below (or above is "upper"
7039 * is set) to "value".
7040 */
isl_basic_set_bound(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value,int upper)7041 static __isl_give isl_basic_set *isl_basic_set_bound(
7042 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7043 isl_int value, int upper)
7044 {
7045 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
7046 type, pos, value, upper));
7047 }
7048
7049 /* Bound the given variable of "bset" from below (or above is "upper"
7050 * is set) to "value".
7051 */
isl_basic_set_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value,int upper)7052 static __isl_give isl_basic_set *isl_basic_set_bound_val(
7053 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7054 __isl_take isl_val *value, int upper)
7055 {
7056 if (!value)
7057 goto error;
7058 if (!isl_val_is_int(value))
7059 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
7060 "expecting integer value", goto error);
7061 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
7062 isl_val_free(value);
7063 return bset;
7064 error:
7065 isl_val_free(value);
7066 isl_basic_set_free(bset);
7067 return NULL;
7068 }
7069
7070 /* Bound the given variable of "bset" from below to "value".
7071 */
isl_basic_set_lower_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7072 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
7073 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7074 __isl_take isl_val *value)
7075 {
7076 return isl_basic_set_bound_val(bset, type, pos, value, 0);
7077 }
7078
7079 /* Bound the given variable of "bset" from above to "value".
7080 */
isl_basic_set_upper_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7081 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
7082 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7083 __isl_take isl_val *value)
7084 {
7085 return isl_basic_set_bound_val(bset, type, pos, value, 1);
7086 }
7087
isl_map_reverse(__isl_take isl_map * map)7088 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
7089 {
7090 return isl_map_transform(map, &isl_space_reverse,
7091 &isl_basic_map_reverse);
7092 }
7093
7094 /* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).
7095 */
isl_map_range_reverse(__isl_take isl_map * map)7096 __isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)
7097 {
7098 return isl_map_transform(map, &isl_space_range_reverse,
7099 &isl_basic_map_range_reverse);
7100 }
7101
7102 #undef TYPE
7103 #define TYPE isl_pw_multi_aff
7104 #undef SUFFIX
7105 #define SUFFIX _pw_multi_aff
7106 #undef EMPTY
7107 #define EMPTY isl_pw_multi_aff_empty
7108 #undef ADD
7109 #define ADD isl_pw_multi_aff_union_add
7110 #include "isl_map_lexopt_templ.c"
7111
7112 /* Given a map "map", compute the lexicographically minimal
7113 * (or maximal) image element for each domain element in dom,
7114 * in the form of an isl_pw_multi_aff.
7115 * If "empty" is not NULL, then set *empty to those elements in dom that
7116 * do not have an image element.
7117 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7118 * should be computed over the domain of "map". "empty" is also NULL
7119 * in this case.
7120 *
7121 * We first compute the lexicographically minimal or maximal element
7122 * in the first basic map. This results in a partial solution "res"
7123 * and a subset "todo" of dom that still need to be handled.
7124 * We then consider each of the remaining maps in "map" and successively
7125 * update both "res" and "todo".
7126 * If "empty" is NULL, then the todo sets are not needed and therefore
7127 * also not computed.
7128 */
isl_map_partial_lexopt_aligned_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty,unsigned flags)7129 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
7130 __isl_take isl_map *map, __isl_take isl_set *dom,
7131 __isl_give isl_set **empty, unsigned flags)
7132 {
7133 int i;
7134 int full;
7135 isl_pw_multi_aff *res;
7136 isl_set *todo;
7137
7138 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7139 if (!map || (!full && !dom))
7140 goto error;
7141
7142 if (isl_map_plain_is_empty(map)) {
7143 if (empty)
7144 *empty = dom;
7145 else
7146 isl_set_free(dom);
7147 return isl_pw_multi_aff_from_map(map);
7148 }
7149
7150 res = basic_map_partial_lexopt_pw_multi_aff(
7151 isl_basic_map_copy(map->p[0]),
7152 isl_set_copy(dom), empty, flags);
7153
7154 if (empty)
7155 todo = *empty;
7156 for (i = 1; i < map->n; ++i) {
7157 isl_pw_multi_aff *res_i;
7158
7159 res_i = basic_map_partial_lexopt_pw_multi_aff(
7160 isl_basic_map_copy(map->p[i]),
7161 isl_set_copy(dom), empty, flags);
7162
7163 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
7164 res = isl_pw_multi_aff_union_lexmax(res, res_i);
7165 else
7166 res = isl_pw_multi_aff_union_lexmin(res, res_i);
7167
7168 if (empty)
7169 todo = isl_set_intersect(todo, *empty);
7170 }
7171
7172 isl_set_free(dom);
7173 isl_map_free(map);
7174
7175 if (empty)
7176 *empty = todo;
7177
7178 return res;
7179 error:
7180 if (empty)
7181 *empty = NULL;
7182 isl_set_free(dom);
7183 isl_map_free(map);
7184 return NULL;
7185 }
7186
7187 #undef TYPE
7188 #define TYPE isl_map
7189 #undef SUFFIX
7190 #define SUFFIX
7191 #undef EMPTY
7192 #define EMPTY isl_map_empty
7193 #undef ADD
7194 #define ADD isl_map_union_disjoint
7195 #include "isl_map_lexopt_templ.c"
7196
7197 /* Given a map "map", compute the lexicographically minimal
7198 * (or maximal) image element for each domain element in "dom",
7199 * in the form of an isl_map.
7200 * If "empty" is not NULL, then set *empty to those elements in "dom" that
7201 * do not have an image element.
7202 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7203 * should be computed over the domain of "map". "empty" is also NULL
7204 * in this case.
7205 *
7206 * If the input consists of more than one disjunct, then first
7207 * compute the desired result in the form of an isl_pw_multi_aff and
7208 * then convert that into an isl_map.
7209 *
7210 * This function used to have an explicit implementation in terms
7211 * of isl_maps, but it would continually intersect the domains of
7212 * partial results with the complement of the domain of the next
7213 * partial solution, potentially leading to an explosion in the number
7214 * of disjuncts if there are several disjuncts in the input.
7215 * An even earlier implementation of this function would look for
7216 * better results in the domain of the partial result and for extra
7217 * results in the complement of this domain, which would lead to
7218 * even more splintering.
7219 */
isl_map_partial_lexopt_aligned(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty,unsigned flags)7220 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
7221 __isl_take isl_map *map, __isl_take isl_set *dom,
7222 __isl_give isl_set **empty, unsigned flags)
7223 {
7224 int full;
7225 struct isl_map *res;
7226 isl_pw_multi_aff *pma;
7227
7228 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7229 if (!map || (!full && !dom))
7230 goto error;
7231
7232 if (isl_map_plain_is_empty(map)) {
7233 if (empty)
7234 *empty = dom;
7235 else
7236 isl_set_free(dom);
7237 return map;
7238 }
7239
7240 if (map->n == 1) {
7241 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
7242 dom, empty, flags);
7243 isl_map_free(map);
7244 return res;
7245 }
7246
7247 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
7248 flags);
7249 return isl_map_from_pw_multi_aff_internal(pma);
7250 error:
7251 if (empty)
7252 *empty = NULL;
7253 isl_set_free(dom);
7254 isl_map_free(map);
7255 return NULL;
7256 }
7257
isl_map_partial_lexmax(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7258 __isl_give isl_map *isl_map_partial_lexmax(
7259 __isl_take isl_map *map, __isl_take isl_set *dom,
7260 __isl_give isl_set **empty)
7261 {
7262 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
7263 }
7264
isl_map_partial_lexmin(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7265 __isl_give isl_map *isl_map_partial_lexmin(
7266 __isl_take isl_map *map, __isl_take isl_set *dom,
7267 __isl_give isl_set **empty)
7268 {
7269 return isl_map_partial_lexopt(map, dom, empty, 0);
7270 }
7271
isl_set_partial_lexmin(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7272 __isl_give isl_set *isl_set_partial_lexmin(
7273 __isl_take isl_set *set, __isl_take isl_set *dom,
7274 __isl_give isl_set **empty)
7275 {
7276 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
7277 dom, empty));
7278 }
7279
isl_set_partial_lexmax(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7280 __isl_give isl_set *isl_set_partial_lexmax(
7281 __isl_take isl_set *set, __isl_take isl_set *dom,
7282 __isl_give isl_set **empty)
7283 {
7284 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
7285 dom, empty));
7286 }
7287
7288 /* Compute the lexicographic minimum (or maximum if "flags" includes
7289 * ISL_OPT_MAX) of "bset" over its parametric domain.
7290 */
isl_basic_set_lexopt(__isl_take isl_basic_set * bset,unsigned flags)7291 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
7292 unsigned flags)
7293 {
7294 return isl_basic_map_lexopt(bset, flags);
7295 }
7296
isl_basic_map_lexmax(__isl_take isl_basic_map * bmap)7297 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
7298 {
7299 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
7300 }
7301
isl_basic_set_lexmin(__isl_take isl_basic_set * bset)7302 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
7303 {
7304 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
7305 }
7306
isl_basic_set_lexmax(__isl_take isl_basic_set * bset)7307 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
7308 {
7309 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
7310 }
7311
7312 /* Compute the lexicographic minimum of "bset" over its parametric domain
7313 * for the purpose of quantifier elimination.
7314 * That is, find an explicit representation for all the existentially
7315 * quantified variables in "bset" by computing their lexicographic
7316 * minimum.
7317 */
isl_basic_set_lexmin_compute_divs(__isl_take isl_basic_set * bset)7318 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
7319 __isl_take isl_basic_set *bset)
7320 {
7321 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
7322 }
7323
7324 /* Given a basic map with one output dimension, compute the minimum or
7325 * maximum of that dimension as an isl_pw_aff.
7326 *
7327 * Compute the optimum as a lexicographic optimum over the single
7328 * output dimension and extract the single isl_pw_aff from the result.
7329 */
basic_map_dim_opt(__isl_keep isl_basic_map * bmap,int max)7330 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
7331 int max)
7332 {
7333 isl_pw_multi_aff *pma;
7334 isl_pw_aff *pwaff;
7335
7336 bmap = isl_basic_map_copy(bmap);
7337 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
7338 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
7339 isl_pw_multi_aff_free(pma);
7340
7341 return pwaff;
7342 }
7343
7344 /* Compute the minimum or maximum of the given output dimension
7345 * as a function of the parameters and the input dimensions,
7346 * but independently of the other output dimensions.
7347 *
7348 * We first project out the other output dimension and then compute
7349 * the "lexicographic" maximum in each basic map, combining the results
7350 * using isl_pw_aff_union_max.
7351 */
map_dim_opt(__isl_take isl_map * map,int pos,int max)7352 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
7353 int max)
7354 {
7355 int i;
7356 isl_pw_aff *pwaff;
7357 isl_size n_out;
7358
7359 n_out = isl_map_dim(map, isl_dim_out);
7360 if (n_out < 0)
7361 map = isl_map_free(map);
7362 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7363 map = isl_map_project_out(map, isl_dim_out, 0, pos);
7364 if (!map)
7365 return NULL;
7366
7367 if (map->n == 0) {
7368 isl_space *space = isl_map_get_space(map);
7369 isl_map_free(map);
7370 return isl_pw_aff_empty(space);
7371 }
7372
7373 pwaff = basic_map_dim_opt(map->p[0], max);
7374 for (i = 1; i < map->n; ++i) {
7375 isl_pw_aff *pwaff_i;
7376
7377 pwaff_i = basic_map_dim_opt(map->p[i], max);
7378 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7379 }
7380
7381 isl_map_free(map);
7382
7383 return pwaff;
7384 }
7385
7386 /* Compute the minimum of the given output dimension as a function of the
7387 * parameters and input dimensions, but independently of
7388 * the other output dimensions.
7389 */
isl_map_dim_min(__isl_take isl_map * map,int pos)7390 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7391 {
7392 return map_dim_opt(map, pos, 0);
7393 }
7394
7395 /* Compute the maximum of the given output dimension as a function of the
7396 * parameters and input dimensions, but independently of
7397 * the other output dimensions.
7398 */
isl_map_dim_max(__isl_take isl_map * map,int pos)7399 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7400 {
7401 return map_dim_opt(map, pos, 1);
7402 }
7403
7404 /* Compute the minimum or maximum of the given set dimension
7405 * as a function of the parameters,
7406 * but independently of the other set dimensions.
7407 */
set_dim_opt(__isl_take isl_set * set,int pos,int max)7408 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7409 int max)
7410 {
7411 return map_dim_opt(set, pos, max);
7412 }
7413
7414 /* Compute the maximum of the given set dimension as a function of the
7415 * parameters, but independently of the other set dimensions.
7416 */
isl_set_dim_max(__isl_take isl_set * set,int pos)7417 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7418 {
7419 return set_dim_opt(set, pos, 1);
7420 }
7421
7422 /* Compute the minimum of the given set dimension as a function of the
7423 * parameters, but independently of the other set dimensions.
7424 */
isl_set_dim_min(__isl_take isl_set * set,int pos)7425 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7426 {
7427 return set_dim_opt(set, pos, 0);
7428 }
7429
7430 /* Apply a preimage specified by "mat" on the parameters of "bset".
7431 * bset is assumed to have only parameters and divs.
7432 */
basic_set_parameter_preimage(__isl_take isl_basic_set * bset,__isl_take isl_mat * mat)7433 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7434 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7435 {
7436 isl_size nparam;
7437
7438 nparam = isl_basic_set_dim(bset, isl_dim_param);
7439 if (nparam < 0 || !mat)
7440 goto error;
7441
7442 bset->dim = isl_space_cow(bset->dim);
7443 if (!bset->dim)
7444 goto error;
7445
7446 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7447
7448 bset->dim->nparam = 0;
7449 bset->dim->n_out = nparam;
7450 bset = isl_basic_set_preimage(bset, mat);
7451 if (bset) {
7452 bset->dim->nparam = bset->dim->n_out;
7453 bset->dim->n_out = 0;
7454 }
7455 return bset;
7456 error:
7457 isl_mat_free(mat);
7458 isl_basic_set_free(bset);
7459 return NULL;
7460 }
7461
7462 /* Apply a preimage specified by "mat" on the parameters of "set".
7463 * set is assumed to have only parameters and divs.
7464 */
set_parameter_preimage(__isl_take isl_set * set,__isl_take isl_mat * mat)7465 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7466 __isl_take isl_mat *mat)
7467 {
7468 isl_space *space;
7469 isl_size nparam;
7470
7471 nparam = isl_set_dim(set, isl_dim_param);
7472 if (nparam < 0 || !mat)
7473 goto error;
7474
7475 if (mat->n_row != 1 + nparam)
7476 isl_die(isl_set_get_ctx(set), isl_error_internal,
7477 "unexpected number of rows", goto error);
7478
7479 space = isl_set_get_space(set);
7480 space = isl_space_move_dims(space, isl_dim_set, 0,
7481 isl_dim_param, 0, nparam);
7482 set = isl_set_reset_space(set, space);
7483 set = isl_set_preimage(set, mat);
7484 nparam = isl_set_dim(set, isl_dim_out);
7485 if (nparam < 0)
7486 set = isl_set_free(set);
7487 space = isl_set_get_space(set);
7488 space = isl_space_move_dims(space, isl_dim_param, 0,
7489 isl_dim_out, 0, nparam);
7490 set = isl_set_reset_space(set, space);
7491 return set;
7492 error:
7493 isl_mat_free(mat);
7494 isl_set_free(set);
7495 return NULL;
7496 }
7497
7498 /* Intersect the basic set "bset" with the affine space specified by the
7499 * equalities in "eq".
7500 */
basic_set_append_equalities(__isl_take isl_basic_set * bset,__isl_take isl_mat * eq)7501 static __isl_give isl_basic_set *basic_set_append_equalities(
7502 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7503 {
7504 int i, k;
7505 unsigned len;
7506
7507 if (!bset || !eq)
7508 goto error;
7509
7510 bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);
7511 if (!bset)
7512 goto error;
7513
7514 len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7515 for (i = 0; i < eq->n_row; ++i) {
7516 k = isl_basic_set_alloc_equality(bset);
7517 if (k < 0)
7518 goto error;
7519 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7520 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7521 }
7522 isl_mat_free(eq);
7523
7524 bset = isl_basic_set_gauss(bset, NULL);
7525 bset = isl_basic_set_finalize(bset);
7526
7527 return bset;
7528 error:
7529 isl_mat_free(eq);
7530 isl_basic_set_free(bset);
7531 return NULL;
7532 }
7533
7534 /* Intersect the set "set" with the affine space specified by the
7535 * equalities in "eq".
7536 */
set_append_equalities(__isl_take isl_set * set,__isl_take isl_mat * eq)7537 static __isl_give isl_set *set_append_equalities(__isl_take isl_set *set,
7538 __isl_take isl_mat *eq)
7539 {
7540 int i;
7541
7542 if (!set || !eq)
7543 goto error;
7544
7545 for (i = 0; i < set->n; ++i) {
7546 set->p[i] = basic_set_append_equalities(set->p[i],
7547 isl_mat_copy(eq));
7548 if (!set->p[i])
7549 goto error;
7550 }
7551 isl_mat_free(eq);
7552 return set;
7553 error:
7554 isl_mat_free(eq);
7555 isl_set_free(set);
7556 return NULL;
7557 }
7558
7559 /* Given a basic set "bset" that only involves parameters and existentially
7560 * quantified variables, return the index of the first equality
7561 * that only involves parameters. If there is no such equality then
7562 * return bset->n_eq.
7563 *
7564 * This function assumes that isl_basic_set_gauss has been called on "bset".
7565 */
first_parameter_equality(__isl_keep isl_basic_set * bset)7566 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7567 {
7568 int i, j;
7569 isl_size nparam, n_div;
7570
7571 nparam = isl_basic_set_dim(bset, isl_dim_param);
7572 n_div = isl_basic_set_dim(bset, isl_dim_div);
7573 if (nparam < 0 || n_div < 0)
7574 return -1;
7575
7576 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7577 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7578 ++i;
7579 }
7580
7581 return i;
7582 }
7583
7584 /* Compute an explicit representation for the existentially quantified
7585 * variables in "bset" by computing the "minimal value" of the set
7586 * variables. Since there are no set variables, the computation of
7587 * the minimal value essentially computes an explicit representation
7588 * of the non-empty part(s) of "bset".
7589 *
7590 * The input only involves parameters and existentially quantified variables.
7591 * All equalities among parameters have been removed.
7592 *
7593 * Since the existentially quantified variables in the result are in general
7594 * going to be different from those in the input, we first replace
7595 * them by the minimal number of variables based on their equalities.
7596 * This should simplify the parametric integer programming.
7597 */
base_compute_divs(__isl_take isl_basic_set * bset)7598 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7599 {
7600 isl_morph *morph1, *morph2;
7601 isl_set *set;
7602 isl_size n;
7603
7604 if (!bset)
7605 return NULL;
7606 if (bset->n_eq == 0)
7607 return isl_basic_set_lexmin_compute_divs(bset);
7608
7609 morph1 = isl_basic_set_parameter_compression(bset);
7610 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7611 bset = isl_basic_set_lift(bset);
7612 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7613 bset = isl_morph_basic_set(morph2, bset);
7614 n = isl_basic_set_dim(bset, isl_dim_set);
7615 if (n < 0)
7616 bset = isl_basic_set_free(bset);
7617 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7618
7619 set = isl_basic_set_lexmin_compute_divs(bset);
7620
7621 set = isl_morph_set(isl_morph_inverse(morph1), set);
7622
7623 return set;
7624 }
7625
7626 /* Project the given basic set onto its parameter domain, possibly introducing
7627 * new, explicit, existential variables in the constraints.
7628 * The input has parameters and (possibly implicit) existential variables.
7629 * The output has the same parameters, but only
7630 * explicit existentially quantified variables.
7631 *
7632 * The actual projection is performed by pip, but pip doesn't seem
7633 * to like equalities very much, so we first remove the equalities
7634 * among the parameters by performing a variable compression on
7635 * the parameters. Afterward, an inverse transformation is performed
7636 * and the equalities among the parameters are inserted back in.
7637 *
7638 * The variable compression on the parameters may uncover additional
7639 * equalities that were only implicit before. We therefore check
7640 * if there are any new parameter equalities in the result and
7641 * if so recurse. The removal of parameter equalities is required
7642 * for the parameter compression performed by base_compute_divs.
7643 */
parameter_compute_divs(__isl_take isl_basic_set * bset)7644 static __isl_give isl_set *parameter_compute_divs(
7645 __isl_take isl_basic_set *bset)
7646 {
7647 int i;
7648 struct isl_mat *eq;
7649 struct isl_mat *T, *T2;
7650 struct isl_set *set;
7651 isl_size nparam;
7652
7653 bset = isl_basic_set_cow(bset);
7654 if (!bset)
7655 return NULL;
7656
7657 if (bset->n_eq == 0)
7658 return base_compute_divs(bset);
7659
7660 bset = isl_basic_set_gauss(bset, NULL);
7661 if (!bset)
7662 return NULL;
7663 if (isl_basic_set_plain_is_empty(bset))
7664 return isl_set_from_basic_set(bset);
7665
7666 i = first_parameter_equality(bset);
7667 if (i == bset->n_eq)
7668 return base_compute_divs(bset);
7669
7670 nparam = isl_basic_set_dim(bset, isl_dim_param);
7671 if (nparam < 0)
7672 return isl_set_from_basic_set(isl_basic_set_free(bset));
7673 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7674 0, 1 + nparam);
7675 eq = isl_mat_cow(eq);
7676 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7677 if (T && T->n_col == 0) {
7678 isl_mat_free(T);
7679 isl_mat_free(T2);
7680 isl_mat_free(eq);
7681 bset = isl_basic_set_set_to_empty(bset);
7682 return isl_set_from_basic_set(bset);
7683 }
7684 bset = basic_set_parameter_preimage(bset, T);
7685
7686 i = first_parameter_equality(bset);
7687 if (!bset)
7688 set = NULL;
7689 else if (i == bset->n_eq)
7690 set = base_compute_divs(bset);
7691 else
7692 set = parameter_compute_divs(bset);
7693 set = set_parameter_preimage(set, T2);
7694 set = set_append_equalities(set, eq);
7695 return set;
7696 }
7697
7698 /* Insert the divs from "ls" before those of "bmap".
7699 *
7700 * The number of columns is not changed, which means that the last
7701 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7702 * The caller is responsible for removing the same number of dimensions
7703 * from the space of "bmap".
7704 */
insert_divs_from_local_space(__isl_take isl_basic_map * bmap,__isl_keep isl_local_space * ls)7705 static __isl_give isl_basic_map *insert_divs_from_local_space(
7706 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7707 {
7708 int i;
7709 isl_size n_div;
7710 int old_n_div;
7711
7712 n_div = isl_local_space_dim(ls, isl_dim_div);
7713 if (n_div < 0)
7714 return isl_basic_map_free(bmap);
7715 if (n_div == 0)
7716 return bmap;
7717
7718 old_n_div = bmap->n_div;
7719 bmap = insert_div_rows(bmap, n_div);
7720 if (!bmap)
7721 return NULL;
7722
7723 for (i = 0; i < n_div; ++i) {
7724 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7725 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7726 }
7727
7728 return bmap;
7729 }
7730
7731 /* Replace the space of "bmap" by the space and divs of "ls".
7732 *
7733 * If "ls" has any divs, then we simplify the result since we may
7734 * have discovered some additional equalities that could simplify
7735 * the div expressions.
7736 */
basic_replace_space_by_local_space(__isl_take isl_basic_map * bmap,__isl_take isl_local_space * ls)7737 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7738 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7739 {
7740 isl_size n_div;
7741
7742 bmap = isl_basic_map_cow(bmap);
7743 n_div = isl_local_space_dim(ls, isl_dim_div);
7744 if (!bmap || n_div < 0)
7745 goto error;
7746
7747 bmap = insert_divs_from_local_space(bmap, ls);
7748 if (!bmap)
7749 goto error;
7750
7751 isl_space_free(bmap->dim);
7752 bmap->dim = isl_local_space_get_space(ls);
7753 if (!bmap->dim)
7754 goto error;
7755
7756 isl_local_space_free(ls);
7757 if (n_div > 0)
7758 bmap = isl_basic_map_simplify(bmap);
7759 bmap = isl_basic_map_finalize(bmap);
7760 return bmap;
7761 error:
7762 isl_basic_map_free(bmap);
7763 isl_local_space_free(ls);
7764 return NULL;
7765 }
7766
7767 /* Replace the space of "map" by the space and divs of "ls".
7768 */
replace_space_by_local_space(__isl_take isl_map * map,__isl_take isl_local_space * ls)7769 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7770 __isl_take isl_local_space *ls)
7771 {
7772 int i;
7773
7774 map = isl_map_cow(map);
7775 if (!map || !ls)
7776 goto error;
7777
7778 for (i = 0; i < map->n; ++i) {
7779 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7780 isl_local_space_copy(ls));
7781 if (!map->p[i])
7782 goto error;
7783 }
7784 isl_space_free(isl_map_take_space(map));
7785 map = isl_map_restore_space(map, isl_local_space_get_space(ls));
7786
7787 isl_local_space_free(ls);
7788 return map;
7789 error:
7790 isl_local_space_free(ls);
7791 isl_map_free(map);
7792 return NULL;
7793 }
7794
7795 /* Compute an explicit representation for the existentially
7796 * quantified variables for which do not know any explicit representation yet.
7797 *
7798 * We first sort the existentially quantified variables so that the
7799 * existentially quantified variables for which we already have an explicit
7800 * representation are placed before those for which we do not.
7801 * The input dimensions, the output dimensions and the existentially
7802 * quantified variables for which we already have an explicit
7803 * representation are then turned into parameters.
7804 * compute_divs returns a map with the same parameters and
7805 * no input or output dimensions and the dimension specification
7806 * is reset to that of the input, including the existentially quantified
7807 * variables for which we already had an explicit representation.
7808 */
compute_divs(__isl_take isl_basic_map * bmap)7809 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7810 {
7811 struct isl_basic_set *bset;
7812 struct isl_set *set;
7813 struct isl_map *map;
7814 isl_space *space;
7815 isl_local_space *ls;
7816 isl_size nparam;
7817 isl_size n_in;
7818 isl_size n_out;
7819 int n_known;
7820 int i;
7821
7822 bmap = isl_basic_map_sort_divs(bmap);
7823 bmap = isl_basic_map_cow(bmap);
7824 if (!bmap)
7825 return NULL;
7826
7827 n_known = isl_basic_map_first_unknown_div(bmap);
7828 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7829 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7830 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7831 if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
7832 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7833
7834 space = isl_space_set_alloc(bmap->ctx,
7835 nparam + n_in + n_out + n_known, 0);
7836 if (!space)
7837 goto error;
7838
7839 ls = isl_basic_map_get_local_space(bmap);
7840 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7841 n_known, bmap->n_div - n_known);
7842 if (n_known > 0) {
7843 for (i = n_known; i < bmap->n_div; ++i)
7844 swap_div(bmap, i - n_known, i);
7845 bmap->n_div -= n_known;
7846 bmap->extra -= n_known;
7847 }
7848 bmap = isl_basic_map_reset_space(bmap, space);
7849 bset = bset_from_bmap(bmap);
7850
7851 set = parameter_compute_divs(bset);
7852 map = set_to_map(set);
7853 map = replace_space_by_local_space(map, ls);
7854
7855 return map;
7856 error:
7857 isl_basic_map_free(bmap);
7858 return NULL;
7859 }
7860
7861 /* Remove the explicit representation of local variable "div",
7862 * if there is any.
7863 */
isl_basic_map_mark_div_unknown(__isl_take isl_basic_map * bmap,int div)7864 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7865 __isl_take isl_basic_map *bmap, int div)
7866 {
7867 isl_bool unknown;
7868
7869 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7870 if (unknown < 0)
7871 return isl_basic_map_free(bmap);
7872 if (unknown)
7873 return bmap;
7874
7875 bmap = isl_basic_map_cow(bmap);
7876 if (!bmap)
7877 return NULL;
7878 isl_int_set_si(bmap->div[div][0], 0);
7879 return bmap;
7880 }
7881
7882 /* Is local variable "div" of "bmap" marked as not having an explicit
7883 * representation?
7884 * Note that even if "div" is not marked in this way and therefore
7885 * has an explicit representation, this representation may still
7886 * depend (indirectly) on other local variables that do not
7887 * have an explicit representation.
7888 */
isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map * bmap,int div)7889 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7890 int div)
7891 {
7892 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7893 return isl_bool_error;
7894 return isl_int_is_zero(bmap->div[div][0]);
7895 }
7896
7897 /* Return the position of the first local variable that does not
7898 * have an explicit representation.
7899 * Return the total number of local variables if they all have
7900 * an explicit representation.
7901 * Return -1 on error.
7902 */
isl_basic_map_first_unknown_div(__isl_keep isl_basic_map * bmap)7903 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7904 {
7905 int i;
7906
7907 if (!bmap)
7908 return -1;
7909
7910 for (i = 0; i < bmap->n_div; ++i) {
7911 if (!isl_basic_map_div_is_known(bmap, i))
7912 return i;
7913 }
7914 return bmap->n_div;
7915 }
7916
7917 /* Return the position of the first local variable that does not
7918 * have an explicit representation.
7919 * Return the total number of local variables if they all have
7920 * an explicit representation.
7921 * Return -1 on error.
7922 */
isl_basic_set_first_unknown_div(__isl_keep isl_basic_set * bset)7923 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7924 {
7925 return isl_basic_map_first_unknown_div(bset);
7926 }
7927
7928 /* Does "bmap" have an explicit representation for all local variables?
7929 */
isl_basic_map_divs_known(__isl_keep isl_basic_map * bmap)7930 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7931 {
7932 int first;
7933 isl_size n;
7934
7935 n = isl_basic_map_dim(bmap, isl_dim_div);
7936 first = isl_basic_map_first_unknown_div(bmap);
7937 if (n < 0 || first < 0)
7938 return isl_bool_error;
7939 return first == n;
7940 }
7941
7942 /* Do all basic maps in "map" have an explicit representation
7943 * for all local variables?
7944 */
isl_map_divs_known(__isl_keep isl_map * map)7945 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7946 {
7947 int i;
7948
7949 if (!map)
7950 return isl_bool_error;
7951
7952 for (i = 0; i < map->n; ++i) {
7953 int known = isl_basic_map_divs_known(map->p[i]);
7954 if (known <= 0)
7955 return known;
7956 }
7957
7958 return isl_bool_true;
7959 }
7960
7961 /* If bmap contains any unknown divs, then compute explicit
7962 * expressions for them. However, this computation may be
7963 * quite expensive, so first try to remove divs that aren't
7964 * strictly needed.
7965 */
isl_basic_map_compute_divs(__isl_take isl_basic_map * bmap)7966 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7967 {
7968 int known;
7969 struct isl_map *map;
7970
7971 known = isl_basic_map_divs_known(bmap);
7972 if (known < 0)
7973 goto error;
7974 if (known)
7975 return isl_map_from_basic_map(bmap);
7976
7977 bmap = isl_basic_map_drop_redundant_divs(bmap);
7978
7979 known = isl_basic_map_divs_known(bmap);
7980 if (known < 0)
7981 goto error;
7982 if (known)
7983 return isl_map_from_basic_map(bmap);
7984
7985 map = compute_divs(bmap);
7986 return map;
7987 error:
7988 isl_basic_map_free(bmap);
7989 return NULL;
7990 }
7991
isl_map_compute_divs(__isl_take isl_map * map)7992 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7993 {
7994 int i;
7995 int known;
7996 struct isl_map *res;
7997
7998 if (!map)
7999 return NULL;
8000 if (map->n == 0)
8001 return map;
8002
8003 known = isl_map_divs_known(map);
8004 if (known < 0) {
8005 isl_map_free(map);
8006 return NULL;
8007 }
8008 if (known)
8009 return map;
8010
8011 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
8012 for (i = 1 ; i < map->n; ++i) {
8013 struct isl_map *r2;
8014 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
8015 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
8016 res = isl_map_union_disjoint(res, r2);
8017 else
8018 res = isl_map_union(res, r2);
8019 }
8020 isl_map_free(map);
8021
8022 return res;
8023 }
8024
isl_basic_set_compute_divs(__isl_take isl_basic_set * bset)8025 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
8026 {
8027 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
8028 }
8029
isl_set_compute_divs(__isl_take isl_set * set)8030 __isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set)
8031 {
8032 return set_from_map(isl_map_compute_divs(set_to_map(set)));
8033 }
8034
isl_map_domain(__isl_take isl_map * map)8035 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
8036 {
8037 isl_space *space;
8038 isl_size n_out;
8039
8040 n_out = isl_map_dim(map, isl_dim_out);
8041 if (n_out < 0)
8042 return set_from_map(isl_map_free(map));
8043 space = isl_space_domain(isl_map_get_space(map));
8044
8045 map = isl_map_project_out(map, isl_dim_out, 0, n_out);
8046
8047 return set_from_map(isl_map_reset_space(map, space));
8048 }
8049
8050 /* Return the union of "map1" and "map2", where we assume for now that
8051 * "map1" and "map2" are disjoint. Note that the basic maps inside
8052 * "map1" or "map2" may not be disjoint from each other.
8053 * Also note that this function is also called from isl_map_union,
8054 * which takes care of handling the situation where "map1" and "map2"
8055 * may not be disjoint.
8056 *
8057 * If one of the inputs is empty, we can simply return the other input.
8058 * Similarly, if one of the inputs is universal, then it is equal to the union.
8059 */
map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8060 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
8061 __isl_take isl_map *map2)
8062 {
8063 int i;
8064 unsigned flags = 0;
8065 struct isl_map *map = NULL;
8066 int is_universe;
8067
8068 if (isl_map_check_equal_space(map1, map2) < 0)
8069 goto error;
8070
8071 if (map1->n == 0) {
8072 isl_map_free(map1);
8073 return map2;
8074 }
8075 if (map2->n == 0) {
8076 isl_map_free(map2);
8077 return map1;
8078 }
8079
8080 is_universe = isl_map_plain_is_universe(map1);
8081 if (is_universe < 0)
8082 goto error;
8083 if (is_universe) {
8084 isl_map_free(map2);
8085 return map1;
8086 }
8087
8088 is_universe = isl_map_plain_is_universe(map2);
8089 if (is_universe < 0)
8090 goto error;
8091 if (is_universe) {
8092 isl_map_free(map1);
8093 return map2;
8094 }
8095
8096 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
8097 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
8098 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8099
8100 map = isl_map_alloc_space(isl_space_copy(map1->dim),
8101 map1->n + map2->n, flags);
8102 if (!map)
8103 goto error;
8104 for (i = 0; i < map1->n; ++i) {
8105 map = isl_map_add_basic_map(map,
8106 isl_basic_map_copy(map1->p[i]));
8107 if (!map)
8108 goto error;
8109 }
8110 for (i = 0; i < map2->n; ++i) {
8111 map = isl_map_add_basic_map(map,
8112 isl_basic_map_copy(map2->p[i]));
8113 if (!map)
8114 goto error;
8115 }
8116 isl_map_free(map1);
8117 isl_map_free(map2);
8118 return map;
8119 error:
8120 isl_map_free(map);
8121 isl_map_free(map1);
8122 isl_map_free(map2);
8123 return NULL;
8124 }
8125
8126 /* Return the union of "map1" and "map2", where "map1" and "map2" are
8127 * guaranteed to be disjoint by the caller.
8128 *
8129 * Note that this functions is called from within isl_map_make_disjoint,
8130 * so we have to be careful not to touch the constraints of the inputs
8131 * in any way.
8132 */
isl_map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8133 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
8134 __isl_take isl_map *map2)
8135 {
8136 isl_map_align_params_bin(&map1, &map2);
8137 return map_union_disjoint(map1, map2);
8138 }
8139
8140 /* Return the union of "map1" and "map2", where "map1" and "map2" may
8141 * not be disjoint.
8142 *
8143 * We currently simply call map_union_disjoint, the internal operation
8144 * of which does not really depend on the inputs being disjoint.
8145 * If the result contains more than one basic map, then we clear
8146 * the disjoint flag since the result may contain basic maps from
8147 * both inputs and these are not guaranteed to be disjoint.
8148 *
8149 * As a special case, if "map1" and "map2" are obviously equal,
8150 * then we simply return "map1".
8151 */
isl_map_union(__isl_take isl_map * map1,__isl_take isl_map * map2)8152 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
8153 __isl_take isl_map *map2)
8154 {
8155 int equal;
8156
8157 if (isl_map_align_params_bin(&map1, &map2) < 0)
8158 goto error;
8159
8160 equal = isl_map_plain_is_equal(map1, map2);
8161 if (equal < 0)
8162 goto error;
8163 if (equal) {
8164 isl_map_free(map2);
8165 return map1;
8166 }
8167
8168 map1 = map_union_disjoint(map1, map2);
8169 if (!map1)
8170 return NULL;
8171 if (map1->n > 1)
8172 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
8173 return map1;
8174 error:
8175 isl_map_free(map1);
8176 isl_map_free(map2);
8177 return NULL;
8178 }
8179
isl_set_union_disjoint(__isl_take isl_set * set1,__isl_take isl_set * set2)8180 __isl_give isl_set *isl_set_union_disjoint(
8181 __isl_take isl_set *set1, __isl_take isl_set *set2)
8182 {
8183 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
8184 set_to_map(set2)));
8185 }
8186
isl_set_union(__isl_take isl_set * set1,__isl_take isl_set * set2)8187 __isl_give isl_set *isl_set_union(__isl_take isl_set *set1,
8188 __isl_take isl_set *set2)
8189 {
8190 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
8191 }
8192
8193 /* Apply "fn" to pairs of elements from "map" and "set" and collect
8194 * the results in a map living in "space".
8195 *
8196 * "map" and "set" are assumed to be compatible and non-NULL.
8197 */
map_intersect_set(__isl_take isl_map * map,__isl_take isl_space * space,__isl_take isl_set * set,__isl_give isl_basic_map * fn (__isl_take isl_basic_map * bmap,__isl_take isl_basic_set * bset))8198 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
8199 __isl_take isl_space *space, __isl_take isl_set *set,
8200 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
8201 __isl_take isl_basic_set *bset))
8202 {
8203 unsigned flags = 0;
8204 struct isl_map *result;
8205 int i, j;
8206
8207 if (isl_set_plain_is_universe(set)) {
8208 isl_set_free(set);
8209 return isl_map_reset_equal_dim_space(map, space);
8210 }
8211
8212 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
8213 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
8214 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8215
8216 result = isl_map_alloc_space(space, map->n * set->n, flags);
8217 for (i = 0; result && i < map->n; ++i)
8218 for (j = 0; j < set->n; ++j) {
8219 result = isl_map_add_basic_map(result,
8220 fn(isl_basic_map_copy(map->p[i]),
8221 isl_basic_set_copy(set->p[j])));
8222 if (!result)
8223 break;
8224 }
8225
8226 isl_map_free(map);
8227 isl_set_free(set);
8228 return result;
8229 }
8230
isl_map_intersect_range(__isl_take isl_map * map,__isl_take isl_set * set)8231 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
8232 __isl_take isl_set *set)
8233 {
8234 isl_bool ok;
8235 isl_space *space;
8236
8237 isl_map_align_params_set(&map, &set);
8238 ok = isl_map_compatible_range(map, set);
8239 if (ok < 0)
8240 goto error;
8241 if (!ok)
8242 isl_die(set->ctx, isl_error_invalid,
8243 "incompatible spaces", goto error);
8244
8245 space = isl_map_get_space(map);
8246 return map_intersect_set(map, space, set,
8247 &isl_basic_map_intersect_range);
8248 error:
8249 isl_map_free(map);
8250 isl_set_free(set);
8251 return NULL;
8252 }
8253
8254 /* Intersect the domain of "map" with "set".
8255 *
8256 * If the domain dimensions of "map" do not have any identifiers,
8257 * then copy them over from "set".
8258 */
isl_map_intersect_domain(__isl_take isl_map * map,__isl_take isl_set * set)8259 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
8260 __isl_take isl_set *set)
8261 {
8262 isl_bool ok;
8263 isl_space *space;
8264
8265 isl_map_align_params_set(&map, &set);
8266 ok = isl_map_compatible_domain(map, set);
8267 if (ok < 0)
8268 goto error;
8269 if (!ok)
8270 isl_die(set->ctx, isl_error_invalid,
8271 "incompatible spaces", goto error);
8272
8273 space = isl_map_get_space(map);
8274 space = isl_space_copy_ids_if_unset(space, isl_dim_in,
8275 isl_set_peek_space(set), isl_dim_set);
8276 return map_intersect_set(map, space, set,
8277 &isl_basic_map_intersect_domain);
8278 error:
8279 isl_map_free(map);
8280 isl_set_free(set);
8281 return NULL;
8282 }
8283
8284 #undef TYPE
8285 #define TYPE isl_map
8286 static
8287 #include "isl_copy_tuple_id_templ.c"
8288
8289 /* Data structure that specifies how isl_map_intersect_factor
8290 * should operate.
8291 *
8292 * "preserve_type" is the tuple where the factor differs from
8293 * the input map and of which the identifiers needs
8294 * to be preserved explicitly.
8295 * "other_factor" is used to extract the space of the other factor
8296 * from the space of the product ("map").
8297 * "product" is used to combine the given factor and a universe map
8298 * in the space returned by "other_factor" to produce a map
8299 * that lives in the same space as the input map.
8300 */
8301 struct isl_intersect_factor_control {
8302 enum isl_dim_type preserve_type;
8303 __isl_give isl_space *(*other_factor)(__isl_take isl_space *space);
8304 __isl_give isl_map *(*product)(__isl_take isl_map *factor,
8305 __isl_take isl_map *other);
8306 };
8307
8308 /* Given a map "map" in some product space and a map "factor"
8309 * living in some factor space, return the intersection.
8310 *
8311 * After aligning the parameters,
8312 * the map "factor" is first extended to a map living in the same space
8313 * as "map" and then a regular intersection is computed.
8314 *
8315 * Note that the extension is computed as a product, which is anonymous
8316 * by default. If "map" has an identifier on the corresponding tuple,
8317 * then this identifier needs to be set on the product
8318 * before the intersection is computed.
8319 */
isl_map_intersect_factor(__isl_take isl_map * map,__isl_take isl_map * factor,struct isl_intersect_factor_control * control)8320 static __isl_give isl_map *isl_map_intersect_factor(
8321 __isl_take isl_map *map, __isl_take isl_map *factor,
8322 struct isl_intersect_factor_control *control)
8323 {
8324 isl_bool equal;
8325 isl_space *space;
8326 isl_map *other, *product;
8327
8328 equal = isl_map_has_equal_params(map, factor);
8329 if (equal < 0)
8330 goto error;
8331 if (!equal) {
8332 map = isl_map_align_params(map, isl_map_get_space(factor));
8333 factor = isl_map_align_params(factor, isl_map_get_space(map));
8334 }
8335
8336 space = isl_map_get_space(map);
8337 other = isl_map_universe(control->other_factor(space));
8338 product = control->product(factor, other);
8339
8340 space = isl_map_peek_space(map);
8341 product = isl_map_copy_tuple_id(product, control->preserve_type,
8342 space, control->preserve_type);
8343 return map_intersect(map, product);
8344 error:
8345 isl_map_free(map);
8346 isl_map_free(factor);
8347 return NULL;
8348 }
8349
8350 /* Return the domain product of "map2" and "map1".
8351 */
isl_map_reverse_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8352 static __isl_give isl_map *isl_map_reverse_domain_product(
8353 __isl_take isl_map *map1, __isl_take isl_map *map2)
8354 {
8355 return isl_map_domain_product(map2, map1);
8356 }
8357
8358 /* Return the range product of "map2" and "map1".
8359 */
isl_map_reverse_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8360 static __isl_give isl_map *isl_map_reverse_range_product(
8361 __isl_take isl_map *map1, __isl_take isl_map *map2)
8362 {
8363 return isl_map_range_product(map2, map1);
8364 }
8365
8366 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8367 * in the space A -> C, return the intersection.
8368 */
isl_map_intersect_domain_factor_domain(__isl_take isl_map * map,__isl_take isl_map * factor)8369 __isl_give isl_map *isl_map_intersect_domain_factor_domain(
8370 __isl_take isl_map *map, __isl_take isl_map *factor)
8371 {
8372 struct isl_intersect_factor_control control = {
8373 .preserve_type = isl_dim_in,
8374 .other_factor = isl_space_domain_factor_range,
8375 .product = isl_map_domain_product,
8376 };
8377
8378 return isl_map_intersect_factor(map, factor, &control);
8379 }
8380
8381 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8382 * in the space B -> C, return the intersection.
8383 */
isl_map_intersect_domain_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8384 __isl_give isl_map *isl_map_intersect_domain_factor_range(
8385 __isl_take isl_map *map, __isl_take isl_map *factor)
8386 {
8387 struct isl_intersect_factor_control control = {
8388 .preserve_type = isl_dim_in,
8389 .other_factor = isl_space_domain_factor_domain,
8390 .product = isl_map_reverse_domain_product,
8391 };
8392
8393 return isl_map_intersect_factor(map, factor, &control);
8394 }
8395
8396 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8397 * in the space A -> B, return the intersection.
8398 */
isl_map_intersect_range_factor_domain(__isl_take isl_map * map,__isl_take isl_map * factor)8399 __isl_give isl_map *isl_map_intersect_range_factor_domain(
8400 __isl_take isl_map *map, __isl_take isl_map *factor)
8401 {
8402 struct isl_intersect_factor_control control = {
8403 .preserve_type = isl_dim_out,
8404 .other_factor = isl_space_range_factor_range,
8405 .product = isl_map_range_product,
8406 };
8407
8408 return isl_map_intersect_factor(map, factor, &control);
8409 }
8410
8411 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8412 * in the space A -> C, return the intersection.
8413 */
isl_map_intersect_range_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8414 __isl_give isl_map *isl_map_intersect_range_factor_range(
8415 __isl_take isl_map *map, __isl_take isl_map *factor)
8416 {
8417 struct isl_intersect_factor_control control = {
8418 .preserve_type = isl_dim_out,
8419 .other_factor = isl_space_range_factor_domain,
8420 .product = isl_map_reverse_range_product,
8421 };
8422
8423 return isl_map_intersect_factor(map, factor, &control);
8424 }
8425
8426 /* Given a set "set" in a space [A -> B] and a set "domain"
8427 * in the space A, return the intersection.
8428 *
8429 * The set "domain" is first extended to a set living in the space
8430 * [A -> B] and then a regular intersection is computed.
8431 */
isl_set_intersect_factor_domain(__isl_take isl_set * set,__isl_take isl_set * domain)8432 __isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
8433 __isl_take isl_set *domain)
8434 {
8435 struct isl_intersect_factor_control control = {
8436 .preserve_type = isl_dim_set,
8437 .other_factor = isl_space_factor_range,
8438 .product = isl_map_range_product,
8439 };
8440
8441 return set_from_map(isl_map_intersect_factor(set_to_map(set),
8442 set_to_map(domain), &control));
8443 }
8444
8445 /* Given a set "set" in a space [A -> B] and a set "range"
8446 * in the space B, return the intersection.
8447 *
8448 * The set "range" is first extended to a set living in the space
8449 * [A -> B] and then a regular intersection is computed.
8450 */
isl_set_intersect_factor_range(__isl_take isl_set * set,__isl_take isl_set * range)8451 __isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
8452 __isl_take isl_set *range)
8453 {
8454 struct isl_intersect_factor_control control = {
8455 .preserve_type = isl_dim_set,
8456 .other_factor = isl_space_factor_domain,
8457 .product = isl_map_reverse_range_product,
8458 };
8459
8460 return set_from_map(isl_map_intersect_factor(set_to_map(set),
8461 set_to_map(range), &control));
8462 }
8463
isl_map_apply_domain(__isl_take isl_map * map1,__isl_take isl_map * map2)8464 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8465 __isl_take isl_map *map2)
8466 {
8467 if (isl_map_align_params_bin(&map1, &map2) < 0)
8468 goto error;
8469 map1 = isl_map_reverse(map1);
8470 map1 = isl_map_apply_range(map1, map2);
8471 return isl_map_reverse(map1);
8472 error:
8473 isl_map_free(map1);
8474 isl_map_free(map2);
8475 return NULL;
8476 }
8477
isl_map_apply_range(__isl_take isl_map * map1,__isl_take isl_map * map2)8478 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8479 __isl_take isl_map *map2)
8480 {
8481 isl_space *space;
8482 struct isl_map *result;
8483 int i, j;
8484
8485 if (isl_map_align_params_bin(&map1, &map2) < 0)
8486 goto error;
8487
8488 space = isl_space_join(isl_space_copy(map1->dim),
8489 isl_space_copy(map2->dim));
8490
8491 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
8492 if (!result)
8493 goto error;
8494 for (i = 0; i < map1->n; ++i)
8495 for (j = 0; j < map2->n; ++j) {
8496 result = isl_map_add_basic_map(result,
8497 isl_basic_map_apply_range(
8498 isl_basic_map_copy(map1->p[i]),
8499 isl_basic_map_copy(map2->p[j])));
8500 if (!result)
8501 goto error;
8502 }
8503 isl_map_free(map1);
8504 isl_map_free(map2);
8505 if (result && result->n <= 1)
8506 ISL_F_SET(result, ISL_MAP_DISJOINT);
8507 return result;
8508 error:
8509 isl_map_free(map1);
8510 isl_map_free(map2);
8511 return NULL;
8512 }
8513
8514 /* Is "bmap" a transformation, i.e.,
8515 * does it relate elements from the same space.
8516 */
isl_basic_map_is_transformation(__isl_keep isl_basic_map * bmap)8517 isl_bool isl_basic_map_is_transformation(__isl_keep isl_basic_map *bmap)
8518 {
8519 isl_space *space;
8520
8521 space = isl_basic_map_peek_space(bmap);
8522 return isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8523 }
8524
8525 /* Check that "bmap" is a transformation, i.e.,
8526 * that it relates elements from the same space.
8527 */
isl_basic_map_check_transformation(__isl_keep isl_basic_map * bmap)8528 static isl_stat isl_basic_map_check_transformation(
8529 __isl_keep isl_basic_map *bmap)
8530 {
8531 isl_bool equal;
8532
8533 equal = isl_basic_map_is_transformation(bmap);
8534 if (equal < 0)
8535 return isl_stat_error;
8536 if (!equal)
8537 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
8538 "domain and range don't match", return isl_stat_error);
8539 return isl_stat_ok;
8540 }
8541
8542 /*
8543 * returns range - domain
8544 */
isl_basic_map_deltas(__isl_take isl_basic_map * bmap)8545 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8546 {
8547 isl_space *target_space;
8548 struct isl_basic_set *bset;
8549 isl_size dim;
8550 isl_size nparam;
8551 isl_size total;
8552 int i;
8553
8554 if (isl_basic_map_check_transformation(bmap) < 0)
8555 return isl_basic_map_free(bmap);
8556 dim = isl_basic_map_dim(bmap, isl_dim_in);
8557 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8558 if (dim < 0 || nparam < 0)
8559 goto error;
8560 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8561 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8562 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8563 total = isl_basic_map_dim(bmap, isl_dim_all);
8564 if (total < 0)
8565 bmap = isl_basic_map_free(bmap);
8566 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8567 for (i = 0; i < dim; ++i) {
8568 int j = isl_basic_map_alloc_equality(bmap);
8569 if (j < 0) {
8570 bmap = isl_basic_map_free(bmap);
8571 break;
8572 }
8573 isl_seq_clr(bmap->eq[j], 1 + total);
8574 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8575 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8576 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8577 }
8578 bset = isl_basic_map_domain(bmap);
8579 bset = isl_basic_set_reset_space(bset, target_space);
8580 return bset;
8581 error:
8582 isl_basic_map_free(bmap);
8583 return NULL;
8584 }
8585
8586 /* Is the tuple of type "type1" of "map" the same as
8587 * the tuple of type "type2" of "space"?
8588 */
isl_map_space_tuple_is_equal(__isl_keep isl_map * map,enum isl_dim_type type1,__isl_keep isl_space * space,enum isl_dim_type type2)8589 isl_bool isl_map_space_tuple_is_equal(__isl_keep isl_map *map,
8590 enum isl_dim_type type1, __isl_keep isl_space *space,
8591 enum isl_dim_type type2)
8592 {
8593 isl_space *map_space;
8594
8595 map_space = isl_map_peek_space(map);
8596 return isl_space_tuple_is_equal(map_space, type1, space, type2);
8597 }
8598
8599 /* Is the tuple of type "type1" of "map1" the same as
8600 * the tuple of type "type2" of "map2"?
8601 */
isl_map_tuple_is_equal(__isl_keep isl_map * map1,enum isl_dim_type type1,__isl_keep isl_map * map2,enum isl_dim_type type2)8602 isl_bool isl_map_tuple_is_equal(__isl_keep isl_map *map1,
8603 enum isl_dim_type type1, __isl_keep isl_map *map2,
8604 enum isl_dim_type type2)
8605 {
8606 isl_space *space1, *space2;
8607
8608 space1 = isl_map_peek_space(map1);
8609 space2 = isl_map_peek_space(map2);
8610 return isl_space_tuple_is_equal(space1, type1, space2, type2);
8611 }
8612
8613 /* Is the space of "obj" equal to "space", ignoring parameters?
8614 */
isl_map_has_space_tuples(__isl_keep isl_map * map,__isl_keep isl_space * space)8615 isl_bool isl_map_has_space_tuples(__isl_keep isl_map *map,
8616 __isl_keep isl_space *space)
8617 {
8618 isl_space *map_space;
8619
8620 map_space = isl_map_peek_space(map);
8621 return isl_space_has_equal_tuples(map_space, space);
8622 }
8623
8624 /* Check that "map" is a transformation, i.e.,
8625 * that it relates elements from the same space.
8626 */
isl_map_check_transformation(__isl_keep isl_map * map)8627 isl_stat isl_map_check_transformation(__isl_keep isl_map *map)
8628 {
8629 isl_bool equal;
8630
8631 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
8632 if (equal < 0)
8633 return isl_stat_error;
8634 if (!equal)
8635 isl_die(isl_map_get_ctx(map), isl_error_invalid,
8636 "domain and range don't match", return isl_stat_error);
8637 return isl_stat_ok;
8638 }
8639
8640 /*
8641 * returns range - domain
8642 */
isl_map_deltas(__isl_take isl_map * map)8643 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8644 {
8645 int i;
8646 isl_space *space;
8647 struct isl_set *result;
8648
8649 if (isl_map_check_transformation(map) < 0)
8650 goto error;
8651 space = isl_map_get_space(map);
8652 space = isl_space_domain(space);
8653 result = isl_set_alloc_space(space, map->n, 0);
8654 if (!result)
8655 goto error;
8656 for (i = 0; i < map->n; ++i)
8657 result = isl_set_add_basic_set(result,
8658 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8659 isl_map_free(map);
8660 return result;
8661 error:
8662 isl_map_free(map);
8663 return NULL;
8664 }
8665
8666 /*
8667 * returns [domain -> range] -> range - domain
8668 */
isl_basic_map_deltas_map(__isl_take isl_basic_map * bmap)8669 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8670 __isl_take isl_basic_map *bmap)
8671 {
8672 int i, k;
8673 isl_space *space;
8674 isl_basic_map *domain;
8675 isl_size nparam, n;
8676 isl_size total;
8677
8678 if (isl_basic_map_check_transformation(bmap) < 0)
8679 return isl_basic_map_free(bmap);
8680
8681 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8682 n = isl_basic_map_dim(bmap, isl_dim_in);
8683 if (nparam < 0 || n < 0)
8684 return isl_basic_map_free(bmap);
8685
8686 space = isl_basic_map_get_space(bmap);
8687 space = isl_space_from_range(isl_space_domain(space));
8688 domain = isl_basic_map_universe(space);
8689
8690 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8691 bmap = isl_basic_map_apply_range(bmap, domain);
8692 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8693
8694 total = isl_basic_map_dim(bmap, isl_dim_all);
8695 if (total < 0)
8696 return isl_basic_map_free(bmap);
8697
8698 for (i = 0; i < n; ++i) {
8699 k = isl_basic_map_alloc_equality(bmap);
8700 if (k < 0)
8701 goto error;
8702 isl_seq_clr(bmap->eq[k], 1 + total);
8703 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8704 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8705 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8706 }
8707
8708 bmap = isl_basic_map_gauss(bmap, NULL);
8709 return isl_basic_map_finalize(bmap);
8710 error:
8711 isl_basic_map_free(bmap);
8712 return NULL;
8713 }
8714
8715 /*
8716 * returns [domain -> range] -> range - domain
8717 */
isl_map_deltas_map(__isl_take isl_map * map)8718 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8719 {
8720 if (isl_map_check_transformation(map) < 0)
8721 return isl_map_free(map);
8722
8723 return isl_map_transform(map, &isl_space_range_map,
8724 &isl_basic_map_deltas_map);
8725 }
8726
8727 /* Return pairs of elements { x -> y } such that y - x is in "deltas".
8728 */
isl_set_translation(__isl_take isl_set * deltas)8729 __isl_give isl_map *isl_set_translation(__isl_take isl_set *deltas)
8730 {
8731 isl_space *space;
8732 isl_map *map;
8733
8734 space = isl_space_map_from_set(isl_set_get_space(deltas));
8735 map = isl_map_deltas_map(isl_map_universe(space));
8736 map = isl_map_intersect_range(map, deltas);
8737
8738 return isl_set_unwrap(isl_map_domain(map));
8739 }
8740
isl_basic_map_identity(__isl_take isl_space * space)8741 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8742 {
8743 isl_size n_in, n_out;
8744
8745 n_in = isl_space_dim(space, isl_dim_in);
8746 n_out = isl_space_dim(space, isl_dim_out);
8747 if (n_in < 0 || n_out < 0)
8748 goto error;
8749 if (n_in != n_out)
8750 isl_die(space->ctx, isl_error_invalid,
8751 "number of input and output dimensions needs to be "
8752 "the same", goto error);
8753 return isl_basic_map_equal(space, n_in);
8754 error:
8755 isl_space_free(space);
8756 return NULL;
8757 }
8758
isl_map_identity(__isl_take isl_space * space)8759 __isl_give isl_map *isl_map_identity(__isl_take isl_space *space)
8760 {
8761 return isl_map_from_basic_map(isl_basic_map_identity(space));
8762 }
8763
isl_set_identity(__isl_take isl_set * set)8764 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8765 {
8766 isl_space *space = isl_set_get_space(set);
8767 isl_map *id;
8768 id = isl_map_identity(isl_space_map_from_set(space));
8769 return isl_map_intersect_range(id, set);
8770 }
8771
8772 /* Construct a basic set with all set dimensions having only non-negative
8773 * values.
8774 */
isl_basic_set_positive_orthant(__isl_take isl_space * space)8775 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8776 __isl_take isl_space *space)
8777 {
8778 int i;
8779 isl_size nparam;
8780 isl_size dim;
8781 isl_size total;
8782 struct isl_basic_set *bset;
8783
8784 nparam = isl_space_dim(space, isl_dim_param);
8785 dim = isl_space_dim(space, isl_dim_set);
8786 total = isl_space_dim(space, isl_dim_all);
8787 if (nparam < 0 || dim < 0 || total < 0)
8788 space = isl_space_free(space);
8789 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8790 if (!bset)
8791 return NULL;
8792 for (i = 0; i < dim; ++i) {
8793 int k = isl_basic_set_alloc_inequality(bset);
8794 if (k < 0)
8795 goto error;
8796 isl_seq_clr(bset->ineq[k], 1 + total);
8797 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8798 }
8799 return bset;
8800 error:
8801 isl_basic_set_free(bset);
8802 return NULL;
8803 }
8804
8805 /* Construct the half-space x_pos >= 0.
8806 */
nonneg_halfspace(__isl_take isl_space * space,int pos)8807 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8808 int pos)
8809 {
8810 int k;
8811 isl_size total;
8812 isl_basic_set *nonneg;
8813
8814 total = isl_space_dim(space, isl_dim_all);
8815 if (total < 0)
8816 space = isl_space_free(space);
8817 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8818 k = isl_basic_set_alloc_inequality(nonneg);
8819 if (k < 0)
8820 goto error;
8821 isl_seq_clr(nonneg->ineq[k], 1 + total);
8822 isl_int_set_si(nonneg->ineq[k][pos], 1);
8823
8824 return isl_basic_set_finalize(nonneg);
8825 error:
8826 isl_basic_set_free(nonneg);
8827 return NULL;
8828 }
8829
8830 /* Construct the half-space x_pos <= -1.
8831 */
neg_halfspace(__isl_take isl_space * space,int pos)8832 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8833 int pos)
8834 {
8835 int k;
8836 isl_size total;
8837 isl_basic_set *neg;
8838
8839 total = isl_space_dim(space, isl_dim_all);
8840 if (total < 0)
8841 space = isl_space_free(space);
8842 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8843 k = isl_basic_set_alloc_inequality(neg);
8844 if (k < 0)
8845 goto error;
8846 isl_seq_clr(neg->ineq[k], 1 + total);
8847 isl_int_set_si(neg->ineq[k][0], -1);
8848 isl_int_set_si(neg->ineq[k][pos], -1);
8849
8850 return isl_basic_set_finalize(neg);
8851 error:
8852 isl_basic_set_free(neg);
8853 return NULL;
8854 }
8855
isl_set_split_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)8856 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8857 enum isl_dim_type type, unsigned first, unsigned n)
8858 {
8859 int i;
8860 unsigned offset;
8861 isl_basic_set *nonneg;
8862 isl_basic_set *neg;
8863
8864 if (n == 0)
8865 return set;
8866
8867 if (isl_set_check_range(set, type, first, n) < 0)
8868 return isl_set_free(set);
8869
8870 offset = pos(set->dim, type);
8871 for (i = 0; i < n; ++i) {
8872 nonneg = nonneg_halfspace(isl_set_get_space(set),
8873 offset + first + i);
8874 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8875
8876 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8877 }
8878
8879 return set;
8880 }
8881
foreach_orthant(__isl_take isl_set * set,int * signs,int first,int len,isl_stat (* fn)(__isl_take isl_set * orthant,int * signs,void * user),void * user)8882 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8883 int len,
8884 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8885 void *user)
8886 {
8887 isl_set *half;
8888
8889 if (!set)
8890 return isl_stat_error;
8891 if (isl_set_plain_is_empty(set)) {
8892 isl_set_free(set);
8893 return isl_stat_ok;
8894 }
8895 if (first == len)
8896 return fn(set, signs, user);
8897
8898 signs[first] = 1;
8899 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8900 1 + first));
8901 half = isl_set_intersect(half, isl_set_copy(set));
8902 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8903 goto error;
8904
8905 signs[first] = -1;
8906 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8907 1 + first));
8908 half = isl_set_intersect(half, set);
8909 return foreach_orthant(half, signs, first + 1, len, fn, user);
8910 error:
8911 isl_set_free(set);
8912 return isl_stat_error;
8913 }
8914
8915 /* Call "fn" on the intersections of "set" with each of the orthants
8916 * (except for obviously empty intersections). The orthant is identified
8917 * by the signs array, with each entry having value 1 or -1 according
8918 * to the sign of the corresponding variable.
8919 */
isl_set_foreach_orthant(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_set * orthant,int * signs,void * user),void * user)8920 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8921 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8922 void *user)
8923 {
8924 isl_size nparam;
8925 isl_size nvar;
8926 int *signs;
8927 isl_stat r;
8928
8929 if (!set)
8930 return isl_stat_error;
8931 if (isl_set_plain_is_empty(set))
8932 return isl_stat_ok;
8933
8934 nparam = isl_set_dim(set, isl_dim_param);
8935 nvar = isl_set_dim(set, isl_dim_set);
8936 if (nparam < 0 || nvar < 0)
8937 return isl_stat_error;
8938
8939 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8940
8941 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8942 fn, user);
8943
8944 free(signs);
8945
8946 return r;
8947 }
8948
isl_set_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)8949 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8950 {
8951 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8952 }
8953
isl_basic_map_is_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8954 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8955 __isl_keep isl_basic_map *bmap2)
8956 {
8957 isl_bool is_subset;
8958 struct isl_map *map1;
8959 struct isl_map *map2;
8960
8961 if (!bmap1 || !bmap2)
8962 return isl_bool_error;
8963
8964 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8965 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8966
8967 is_subset = isl_map_is_subset(map1, map2);
8968
8969 isl_map_free(map1);
8970 isl_map_free(map2);
8971
8972 return is_subset;
8973 }
8974
isl_basic_set_is_subset(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8975 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8976 __isl_keep isl_basic_set *bset2)
8977 {
8978 return isl_basic_map_is_subset(bset1, bset2);
8979 }
8980
isl_basic_map_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8981 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8982 __isl_keep isl_basic_map *bmap2)
8983 {
8984 isl_bool is_subset;
8985
8986 if (!bmap1 || !bmap2)
8987 return isl_bool_error;
8988 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8989 if (is_subset != isl_bool_true)
8990 return is_subset;
8991 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8992 return is_subset;
8993 }
8994
isl_basic_set_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8995 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8996 __isl_keep isl_basic_set *bset2)
8997 {
8998 return isl_basic_map_is_equal(
8999 bset_to_bmap(bset1), bset_to_bmap(bset2));
9000 }
9001
isl_map_is_empty(__isl_keep isl_map * map)9002 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
9003 {
9004 int i;
9005 int is_empty;
9006
9007 if (!map)
9008 return isl_bool_error;
9009 for (i = 0; i < map->n; ++i) {
9010 is_empty = isl_basic_map_is_empty(map->p[i]);
9011 if (is_empty < 0)
9012 return isl_bool_error;
9013 if (!is_empty)
9014 return isl_bool_false;
9015 }
9016 return isl_bool_true;
9017 }
9018
isl_map_plain_is_empty(__isl_keep isl_map * map)9019 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
9020 {
9021 return map ? map->n == 0 : isl_bool_error;
9022 }
9023
isl_set_plain_is_empty(__isl_keep isl_set * set)9024 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
9025 {
9026 return set ? set->n == 0 : isl_bool_error;
9027 }
9028
isl_set_is_empty(__isl_keep isl_set * set)9029 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
9030 {
9031 return isl_map_is_empty(set_to_map(set));
9032 }
9033
9034 #undef TYPE
9035 #define TYPE isl_basic_map
9036
9037 static
9038 #include "isl_type_has_equal_space_bin_templ.c"
9039 #include "isl_type_check_equal_space_templ.c"
9040
9041 /* Check that "bset1" and "bset2" live in the same space,
9042 * reporting an error if they do not.
9043 */
isl_basic_set_check_equal_space(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9044 isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
9045 __isl_keep isl_basic_set *bset2)
9046 {
9047 return isl_basic_map_check_equal_space(bset_to_bmap(bset1),
9048 bset_to_bmap(bset1));
9049 }
9050
9051 #undef TYPE
9052 #define TYPE isl_map
9053
9054 #include "isl_type_has_equal_space_bin_templ.c"
9055 #include "isl_type_check_equal_space_templ.c"
9056 #include "isl_type_has_space_templ.c"
9057
isl_set_has_equal_space(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9058 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
9059 __isl_keep isl_set *set2)
9060 {
9061 return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));
9062 }
9063
9064 #undef TYPE1
9065 #define TYPE1 isl_map
9066 #undef TYPE2
9067 #define TYPE2 isl_basic_map
9068 #undef TYPE_PAIR
9069 #define TYPE_PAIR isl_map_basic_map
9070
9071 static
9072 #include "isl_type_has_equal_space_templ.c"
9073 #include "isl_type_check_equal_space_templ.c"
9074
9075 /* Check that "set" and "bset" live in the same space,
9076 * reporting an error if they do not.
9077 */
isl_set_basic_set_check_equal_space(__isl_keep isl_set * set,__isl_keep isl_basic_set * bset)9078 isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
9079 __isl_keep isl_basic_set *bset)
9080 {
9081 return isl_map_basic_map_check_equal_space(set_to_map(set),
9082 bset_to_bmap(bset));
9083 }
9084
map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9085 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9086 {
9087 isl_bool is_subset;
9088
9089 if (!map1 || !map2)
9090 return isl_bool_error;
9091 is_subset = isl_map_is_subset(map1, map2);
9092 if (is_subset != isl_bool_true)
9093 return is_subset;
9094 is_subset = isl_map_is_subset(map2, map1);
9095 return is_subset;
9096 }
9097
9098 /* Is "map1" equal to "map2"?
9099 *
9100 * First check if they are obviously equal.
9101 * If not, then perform a more detailed analysis.
9102 */
isl_map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9103 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9104 {
9105 isl_bool equal;
9106
9107 equal = isl_map_plain_is_equal(map1, map2);
9108 if (equal < 0 || equal)
9109 return equal;
9110 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
9111 }
9112
isl_basic_map_is_strict_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9113 isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
9114 __isl_keep isl_basic_map *bmap2)
9115 {
9116 isl_bool is_subset;
9117
9118 if (!bmap1 || !bmap2)
9119 return isl_bool_error;
9120 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9121 if (is_subset != isl_bool_true)
9122 return is_subset;
9123 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9124 return isl_bool_not(is_subset);
9125 }
9126
isl_map_is_strict_subset(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9127 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
9128 __isl_keep isl_map *map2)
9129 {
9130 isl_bool is_subset;
9131
9132 if (!map1 || !map2)
9133 return isl_bool_error;
9134 is_subset = isl_map_is_subset(map1, map2);
9135 if (is_subset != isl_bool_true)
9136 return is_subset;
9137 is_subset = isl_map_is_subset(map2, map1);
9138 return isl_bool_not(is_subset);
9139 }
9140
isl_set_is_strict_subset(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9141 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
9142 __isl_keep isl_set *set2)
9143 {
9144 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
9145 }
9146
9147 /* Is "bmap" obviously equal to the universe with the same space?
9148 *
9149 * That is, does it not have any constraints?
9150 */
isl_basic_map_plain_is_universe(__isl_keep isl_basic_map * bmap)9151 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
9152 {
9153 if (!bmap)
9154 return isl_bool_error;
9155 return bmap->n_eq == 0 && bmap->n_ineq == 0;
9156 }
9157
9158 /* Is "bset" obviously equal to the universe with the same space?
9159 */
isl_basic_set_plain_is_universe(__isl_keep isl_basic_set * bset)9160 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
9161 {
9162 return isl_basic_map_plain_is_universe(bset);
9163 }
9164
9165 /* If "c" does not involve any existentially quantified variables,
9166 * then set *univ to false and abort
9167 */
involves_divs(__isl_take isl_constraint * c,void * user)9168 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
9169 {
9170 isl_bool *univ = user;
9171 isl_size n;
9172
9173 n = isl_constraint_dim(c, isl_dim_div);
9174 if (n < 0)
9175 c = isl_constraint_free(c);
9176 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
9177 isl_constraint_free(c);
9178 if (*univ < 0 || !*univ)
9179 return isl_stat_error;
9180 return isl_stat_ok;
9181 }
9182
9183 /* Is "bmap" equal to the universe with the same space?
9184 *
9185 * First check if it is obviously equal to the universe.
9186 * If not and if there are any constraints not involving
9187 * existentially quantified variables, then it is certainly
9188 * not equal to the universe.
9189 * Otherwise, check if the universe is a subset of "bmap".
9190 */
isl_basic_map_is_universe(__isl_keep isl_basic_map * bmap)9191 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
9192 {
9193 isl_size n_div;
9194 isl_bool univ;
9195 isl_basic_map *test;
9196
9197 univ = isl_basic_map_plain_is_universe(bmap);
9198 if (univ < 0 || univ)
9199 return univ;
9200 n_div = isl_basic_map_dim(bmap, isl_dim_div);
9201 if (n_div < 0)
9202 return isl_bool_error;
9203 if (n_div == 0)
9204 return isl_bool_false;
9205 univ = isl_bool_true;
9206 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
9207 univ)
9208 return isl_bool_error;
9209 if (univ < 0 || !univ)
9210 return univ;
9211 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
9212 univ = isl_basic_map_is_subset(test, bmap);
9213 isl_basic_map_free(test);
9214 return univ;
9215 }
9216
9217 /* Is "bset" equal to the universe with the same space?
9218 */
isl_basic_set_is_universe(__isl_keep isl_basic_set * bset)9219 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
9220 {
9221 return isl_basic_map_is_universe(bset);
9222 }
9223
isl_map_plain_is_universe(__isl_keep isl_map * map)9224 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
9225 {
9226 int i;
9227
9228 if (!map)
9229 return isl_bool_error;
9230
9231 for (i = 0; i < map->n; ++i) {
9232 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
9233 if (r < 0 || r)
9234 return r;
9235 }
9236
9237 return isl_bool_false;
9238 }
9239
isl_set_plain_is_universe(__isl_keep isl_set * set)9240 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
9241 {
9242 return isl_map_plain_is_universe(set_to_map(set));
9243 }
9244
isl_basic_map_is_empty(__isl_keep isl_basic_map * bmap)9245 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
9246 {
9247 struct isl_basic_set *bset = NULL;
9248 struct isl_vec *sample = NULL;
9249 isl_bool empty, non_empty;
9250
9251 if (!bmap)
9252 return isl_bool_error;
9253
9254 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
9255 return isl_bool_true;
9256
9257 if (isl_basic_map_plain_is_universe(bmap))
9258 return isl_bool_false;
9259
9260 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
9261 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
9262 copy = isl_basic_map_remove_redundancies(copy);
9263 empty = isl_basic_map_plain_is_empty(copy);
9264 isl_basic_map_free(copy);
9265 return empty;
9266 }
9267
9268 non_empty = isl_basic_map_plain_is_non_empty(bmap);
9269 if (non_empty < 0)
9270 return isl_bool_error;
9271 if (non_empty)
9272 return isl_bool_false;
9273 isl_vec_free(bmap->sample);
9274 bmap->sample = NULL;
9275 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
9276 if (!bset)
9277 return isl_bool_error;
9278 sample = isl_basic_set_sample_vec(bset);
9279 if (!sample)
9280 return isl_bool_error;
9281 empty = sample->size == 0;
9282 isl_vec_free(bmap->sample);
9283 bmap->sample = sample;
9284 if (empty)
9285 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
9286
9287 return empty;
9288 }
9289
isl_basic_map_plain_is_empty(__isl_keep isl_basic_map * bmap)9290 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
9291 {
9292 if (!bmap)
9293 return isl_bool_error;
9294 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
9295 }
9296
isl_basic_set_plain_is_empty(__isl_keep isl_basic_set * bset)9297 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
9298 {
9299 if (!bset)
9300 return isl_bool_error;
9301 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
9302 }
9303
9304 /* Is "bmap" known to be non-empty?
9305 *
9306 * That is, is the cached sample still valid?
9307 */
isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map * bmap)9308 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
9309 {
9310 isl_size total;
9311
9312 if (!bmap)
9313 return isl_bool_error;
9314 if (!bmap->sample)
9315 return isl_bool_false;
9316 total = isl_basic_map_dim(bmap, isl_dim_all);
9317 if (total < 0)
9318 return isl_bool_error;
9319 if (bmap->sample->size != 1 + total)
9320 return isl_bool_false;
9321 return isl_basic_map_contains(bmap, bmap->sample);
9322 }
9323
isl_basic_set_is_empty(__isl_keep isl_basic_set * bset)9324 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
9325 {
9326 return isl_basic_map_is_empty(bset_to_bmap(bset));
9327 }
9328
isl_basic_map_union(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)9329 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
9330 __isl_take isl_basic_map *bmap2)
9331 {
9332 struct isl_map *map;
9333
9334 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
9335 goto error;
9336
9337 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
9338 if (!map)
9339 goto error;
9340 map = isl_map_add_basic_map(map, bmap1);
9341 map = isl_map_add_basic_map(map, bmap2);
9342 return map;
9343 error:
9344 isl_basic_map_free(bmap1);
9345 isl_basic_map_free(bmap2);
9346 return NULL;
9347 }
9348
isl_basic_set_union(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)9349 __isl_give isl_set *isl_basic_set_union(__isl_take isl_basic_set *bset1,
9350 __isl_take isl_basic_set *bset2)
9351 {
9352 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
9353 bset_to_bmap(bset2)));
9354 }
9355
9356 /* Order divs such that any div only depends on previous divs */
isl_basic_map_order_divs(__isl_take isl_basic_map * bmap)9357 __isl_give isl_basic_map *isl_basic_map_order_divs(
9358 __isl_take isl_basic_map *bmap)
9359 {
9360 int i;
9361 isl_size off;
9362
9363 off = isl_basic_map_var_offset(bmap, isl_dim_div);
9364 if (off < 0)
9365 return isl_basic_map_free(bmap);
9366
9367 for (i = 0; i < bmap->n_div; ++i) {
9368 int pos;
9369 if (isl_int_is_zero(bmap->div[i][0]))
9370 continue;
9371 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
9372 bmap->n_div-i);
9373 if (pos == -1)
9374 continue;
9375 if (pos == 0)
9376 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
9377 "integer division depends on itself",
9378 return isl_basic_map_free(bmap));
9379 bmap = isl_basic_map_swap_div(bmap, i, i + pos);
9380 if (!bmap)
9381 return NULL;
9382 --i;
9383 }
9384 return bmap;
9385 }
9386
isl_map_order_divs(__isl_take isl_map * map)9387 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
9388 {
9389 int i;
9390
9391 if (!map)
9392 return 0;
9393
9394 for (i = 0; i < map->n; ++i) {
9395 map->p[i] = isl_basic_map_order_divs(map->p[i]);
9396 if (!map->p[i])
9397 goto error;
9398 }
9399
9400 return map;
9401 error:
9402 isl_map_free(map);
9403 return NULL;
9404 }
9405
9406 /* Sort the local variables of "bset".
9407 */
isl_basic_set_sort_divs(__isl_take isl_basic_set * bset)9408 __isl_give isl_basic_set *isl_basic_set_sort_divs(
9409 __isl_take isl_basic_set *bset)
9410 {
9411 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
9412 }
9413
9414 /* Apply the expansion computed by isl_merge_divs.
9415 * The expansion itself is given by "exp" while the resulting
9416 * list of divs is given by "div".
9417 *
9418 * Move the integer divisions of "bmap" into the right position
9419 * according to "exp" and then introduce the additional integer
9420 * divisions, adding div constraints.
9421 * The moving should be done first to avoid moving coefficients
9422 * in the definitions of the extra integer divisions.
9423 */
isl_basic_map_expand_divs(__isl_take isl_basic_map * bmap,__isl_take isl_mat * div,int * exp)9424 __isl_give isl_basic_map *isl_basic_map_expand_divs(
9425 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
9426 {
9427 int i, j;
9428 int n_div;
9429
9430 bmap = isl_basic_map_cow(bmap);
9431 if (!bmap || !div)
9432 goto error;
9433
9434 if (div->n_row < bmap->n_div)
9435 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
9436 "not an expansion", goto error);
9437
9438 n_div = bmap->n_div;
9439 bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,
9440 2 * (div->n_row - n_div));
9441
9442 for (i = n_div; i < div->n_row; ++i)
9443 if (isl_basic_map_alloc_div(bmap) < 0)
9444 goto error;
9445
9446 for (j = n_div - 1; j >= 0; --j) {
9447 if (exp[j] == j)
9448 break;
9449 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
9450 if (!bmap)
9451 goto error;
9452 }
9453 j = 0;
9454 for (i = 0; i < div->n_row; ++i) {
9455 if (j < n_div && exp[j] == i) {
9456 j++;
9457 } else {
9458 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
9459 if (isl_basic_map_div_is_marked_unknown(bmap, i))
9460 continue;
9461 bmap = isl_basic_map_add_div_constraints(bmap, i);
9462 if (!bmap)
9463 goto error;
9464 }
9465 }
9466
9467 isl_mat_free(div);
9468 return bmap;
9469 error:
9470 isl_basic_map_free(bmap);
9471 isl_mat_free(div);
9472 return NULL;
9473 }
9474
9475 /* Apply the expansion computed by isl_merge_divs.
9476 * The expansion itself is given by "exp" while the resulting
9477 * list of divs is given by "div".
9478 */
isl_basic_set_expand_divs(__isl_take isl_basic_set * bset,__isl_take isl_mat * div,int * exp)9479 __isl_give isl_basic_set *isl_basic_set_expand_divs(
9480 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
9481 {
9482 return isl_basic_map_expand_divs(bset, div, exp);
9483 }
9484
9485 /* Look for a div in dst that corresponds to the div "div" in src.
9486 * The divs before "div" in src and dst are assumed to be the same.
9487 *
9488 * Return the position of the corresponding div in dst
9489 * if there is one. Otherwise, return a position beyond the integer divisions.
9490 * Return -1 on error.
9491 */
find_div(__isl_keep isl_basic_map * dst,__isl_keep isl_basic_map * src,unsigned div)9492 static int find_div(__isl_keep isl_basic_map *dst,
9493 __isl_keep isl_basic_map *src, unsigned div)
9494 {
9495 int i;
9496 isl_size n_div;
9497 isl_size v_div;
9498
9499 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9500 n_div = isl_basic_map_dim(dst, isl_dim_div);
9501 if (n_div < 0 || v_div < 0)
9502 return -1;
9503 isl_assert(dst->ctx, div <= n_div, return -1);
9504 for (i = div; i < n_div; ++i)
9505 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
9506 isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
9507 n_div - div) == -1)
9508 return i;
9509 return n_div;
9510 }
9511
9512 /* Align the divs of "dst" to those of "src", adding divs from "src"
9513 * if needed. That is, make sure that the first src->n_div divs
9514 * of the result are equal to those of src.
9515 * The integer division of "src" are assumed to be ordered.
9516 *
9517 * The integer divisions are swapped into the right position
9518 * (possibly after adding them first). This may result
9519 * in the remaining integer divisions appearing in the wrong order,
9520 * i.e., with some integer division appearing before
9521 * some other integer division on which it depends.
9522 * The integer divisions therefore need to be ordered.
9523 * This will not affect the integer divisions aligned to those of "src",
9524 * since "src" is assumed to have ordered integer divisions.
9525 *
9526 * The result is not finalized as by design it will have redundant
9527 * divs if any divs from "src" were copied.
9528 */
isl_basic_map_align_divs(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)9529 __isl_give isl_basic_map *isl_basic_map_align_divs(
9530 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
9531 {
9532 int i;
9533 isl_bool known;
9534 int extended;
9535 isl_size v_div;
9536 isl_size dst_n_div;
9537
9538 if (!dst || !src)
9539 return isl_basic_map_free(dst);
9540
9541 if (src->n_div == 0)
9542 return dst;
9543
9544 known = isl_basic_map_divs_known(src);
9545 if (known < 0)
9546 return isl_basic_map_free(dst);
9547 if (!known)
9548 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9549 "some src divs are unknown",
9550 return isl_basic_map_free(dst));
9551
9552 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9553 if (v_div < 0)
9554 return isl_basic_map_free(dst);
9555
9556 extended = 0;
9557 dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
9558 if (dst_n_div < 0)
9559 dst = isl_basic_map_free(dst);
9560 for (i = 0; i < src->n_div; ++i) {
9561 int j = find_div(dst, src, i);
9562 if (j < 0)
9563 dst = isl_basic_map_free(dst);
9564 if (j == dst_n_div) {
9565 if (!extended) {
9566 int extra = src->n_div - i;
9567 dst = isl_basic_map_cow(dst);
9568 if (!dst)
9569 return isl_basic_map_free(dst);
9570 dst = isl_basic_map_extend(dst,
9571 extra, 0, 2 * extra);
9572 extended = 1;
9573 }
9574 j = isl_basic_map_alloc_div(dst);
9575 if (j < 0)
9576 return isl_basic_map_free(dst);
9577 isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
9578 isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
9579 dst_n_div++;
9580 dst = isl_basic_map_add_div_constraints(dst, j);
9581 if (!dst)
9582 return isl_basic_map_free(dst);
9583 }
9584 if (j != i)
9585 dst = isl_basic_map_swap_div(dst, i, j);
9586 if (!dst)
9587 return isl_basic_map_free(dst);
9588 }
9589 return isl_basic_map_order_divs(dst);
9590 }
9591
isl_map_align_divs_internal(__isl_take isl_map * map)9592 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9593 {
9594 int i;
9595
9596 if (!map)
9597 return NULL;
9598 if (map->n == 0)
9599 return map;
9600 map = isl_map_compute_divs(map);
9601 map = isl_map_order_divs(map);
9602 map = isl_map_cow(map);
9603 if (!map)
9604 return NULL;
9605
9606 for (i = 1; i < map->n; ++i)
9607 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9608 for (i = 1; i < map->n; ++i) {
9609 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9610 if (!map->p[i])
9611 return isl_map_free(map);
9612 }
9613
9614 map = isl_map_unmark_normalized(map);
9615 return map;
9616 }
9617
isl_map_align_divs(__isl_take isl_map * map)9618 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9619 {
9620 return isl_map_align_divs_internal(map);
9621 }
9622
isl_set_align_divs(__isl_take isl_set * set)9623 __isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set)
9624 {
9625 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9626 }
9627
9628 /* Align the divs of the basic maps in "map" to those
9629 * of the basic maps in "list", as well as to the other basic maps in "map".
9630 * The elements in "list" are assumed to have known divs.
9631 */
isl_map_align_divs_to_basic_map_list(__isl_take isl_map * map,__isl_keep isl_basic_map_list * list)9632 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9633 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9634 {
9635 int i;
9636 isl_size n;
9637
9638 n = isl_basic_map_list_n_basic_map(list);
9639 map = isl_map_compute_divs(map);
9640 map = isl_map_cow(map);
9641 if (!map || n < 0)
9642 return isl_map_free(map);
9643 if (map->n == 0)
9644 return map;
9645
9646 for (i = 0; i < n; ++i) {
9647 isl_basic_map *bmap;
9648
9649 bmap = isl_basic_map_list_get_basic_map(list, i);
9650 bmap = isl_basic_map_order_divs(bmap);
9651 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9652 isl_basic_map_free(bmap);
9653 }
9654 if (!map->p[0])
9655 return isl_map_free(map);
9656
9657 return isl_map_align_divs_internal(map);
9658 }
9659
9660 /* Align the divs of each element of "list" to those of "bmap".
9661 * Both "bmap" and the elements of "list" are assumed to have known divs.
9662 */
isl_basic_map_list_align_divs_to_basic_map(__isl_take isl_basic_map_list * list,__isl_keep isl_basic_map * bmap)9663 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9664 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9665 {
9666 int i;
9667 isl_size n;
9668
9669 n = isl_basic_map_list_n_basic_map(list);
9670 if (n < 0 || !bmap)
9671 return isl_basic_map_list_free(list);
9672
9673 for (i = 0; i < n; ++i) {
9674 isl_basic_map *bmap_i;
9675
9676 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9677 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9678 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9679 }
9680
9681 return list;
9682 }
9683
isl_set_apply(__isl_take isl_set * set,__isl_take isl_map * map)9684 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9685 __isl_take isl_map *map)
9686 {
9687 isl_bool ok;
9688
9689 isl_map_align_params_set(&map, &set);
9690 ok = isl_map_compatible_domain(map, set);
9691 if (ok < 0)
9692 goto error;
9693 if (!ok)
9694 isl_die(isl_set_get_ctx(set), isl_error_invalid,
9695 "incompatible spaces", goto error);
9696 map = isl_map_intersect_domain(map, set);
9697 set = isl_map_range(map);
9698 return set;
9699 error:
9700 isl_set_free(set);
9701 isl_map_free(map);
9702 return NULL;
9703 }
9704
9705 /* There is no need to cow as removing empty parts doesn't change
9706 * the meaning of the set.
9707 */
isl_map_remove_empty_parts(__isl_take isl_map * map)9708 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9709 {
9710 int i;
9711
9712 if (!map)
9713 return NULL;
9714
9715 for (i = map->n - 1; i >= 0; --i)
9716 map = remove_if_empty(map, i);
9717
9718 return map;
9719 }
9720
isl_set_remove_empty_parts(__isl_take isl_set * set)9721 __isl_give isl_set *isl_set_remove_empty_parts(__isl_take isl_set *set)
9722 {
9723 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9724 }
9725
9726 /* Create a binary relation that maps the shared initial "pos" dimensions
9727 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9728 */
join_initial(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9729 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9730 __isl_keep isl_basic_set *bset2, int pos)
9731 {
9732 isl_basic_map *bmap1;
9733 isl_basic_map *bmap2;
9734
9735 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9736 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9737 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9738 isl_dim_out, 0, pos);
9739 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9740 isl_dim_out, 0, pos);
9741 return isl_basic_map_range_product(bmap1, bmap2);
9742 }
9743
9744 /* Given two basic sets bset1 and bset2, compute the maximal difference
9745 * between the values of dimension pos in bset1 and those in bset2
9746 * for any common value of the parameters and dimensions preceding pos.
9747 */
basic_set_maximal_difference_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos,isl_int * opt)9748 static enum isl_lp_result basic_set_maximal_difference_at(
9749 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9750 int pos, isl_int *opt)
9751 {
9752 isl_basic_map *bmap1;
9753 struct isl_ctx *ctx;
9754 struct isl_vec *obj;
9755 isl_size total;
9756 isl_size nparam;
9757 isl_size dim1;
9758 enum isl_lp_result res;
9759
9760 nparam = isl_basic_set_dim(bset1, isl_dim_param);
9761 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9762 if (nparam < 0 || dim1 < 0 || !bset2)
9763 return isl_lp_error;
9764
9765 bmap1 = join_initial(bset1, bset2, pos);
9766 total = isl_basic_map_dim(bmap1, isl_dim_all);
9767 if (total < 0)
9768 return isl_lp_error;
9769
9770 ctx = bmap1->ctx;
9771 obj = isl_vec_alloc(ctx, 1 + total);
9772 if (!obj)
9773 goto error;
9774 isl_seq_clr(obj->block.data, 1 + total);
9775 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9776 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9777 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9778 opt, NULL, NULL);
9779 isl_basic_map_free(bmap1);
9780 isl_vec_free(obj);
9781 return res;
9782 error:
9783 isl_basic_map_free(bmap1);
9784 return isl_lp_error;
9785 }
9786
9787 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9788 * for any common value of the parameters and dimensions preceding pos
9789 * in both basic sets, the values of dimension pos in bset1 are
9790 * smaller or larger than those in bset2.
9791 *
9792 * Returns
9793 * 1 if bset1 follows bset2
9794 * -1 if bset1 precedes bset2
9795 * 0 if bset1 and bset2 are incomparable
9796 * -2 if some error occurred.
9797 */
isl_basic_set_compare_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9798 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9799 __isl_keep isl_basic_set *bset2, int pos)
9800 {
9801 isl_int opt;
9802 enum isl_lp_result res;
9803 int cmp;
9804
9805 isl_int_init(opt);
9806
9807 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9808
9809 if (res == isl_lp_empty)
9810 cmp = 0;
9811 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9812 res == isl_lp_unbounded)
9813 cmp = 1;
9814 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9815 cmp = -1;
9816 else
9817 cmp = -2;
9818
9819 isl_int_clear(opt);
9820 return cmp;
9821 }
9822
9823 /* Given two basic sets bset1 and bset2, check whether
9824 * for any common value of the parameters and dimensions preceding pos
9825 * there is a value of dimension pos in bset1 that is larger
9826 * than a value of the same dimension in bset2.
9827 *
9828 * Return
9829 * 1 if there exists such a pair
9830 * 0 if there is no such pair, but there is a pair of equal values
9831 * -1 otherwise
9832 * -2 if some error occurred.
9833 */
isl_basic_set_follows_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9834 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9835 __isl_keep isl_basic_set *bset2, int pos)
9836 {
9837 isl_bool empty;
9838 isl_basic_map *bmap;
9839 isl_size dim1;
9840
9841 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9842 if (dim1 < 0)
9843 return -2;
9844 bmap = join_initial(bset1, bset2, pos);
9845 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9846 isl_dim_out, dim1 - pos);
9847 empty = isl_basic_map_is_empty(bmap);
9848 if (empty < 0)
9849 goto error;
9850 if (empty) {
9851 isl_basic_map_free(bmap);
9852 return -1;
9853 }
9854 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9855 isl_dim_out, dim1 - pos);
9856 empty = isl_basic_map_is_empty(bmap);
9857 if (empty < 0)
9858 goto error;
9859 isl_basic_map_free(bmap);
9860 if (empty)
9861 return 0;
9862 return 1;
9863 error:
9864 isl_basic_map_free(bmap);
9865 return -2;
9866 }
9867
9868 /* Given two sets set1 and set2, check whether
9869 * for any common value of the parameters and dimensions preceding pos
9870 * there is a value of dimension pos in set1 that is larger
9871 * than a value of the same dimension in set2.
9872 *
9873 * Return
9874 * 1 if there exists such a pair
9875 * 0 if there is no such pair, but there is a pair of equal values
9876 * -1 otherwise
9877 * -2 if some error occurred.
9878 */
isl_set_follows_at(__isl_keep isl_set * set1,__isl_keep isl_set * set2,int pos)9879 int isl_set_follows_at(__isl_keep isl_set *set1,
9880 __isl_keep isl_set *set2, int pos)
9881 {
9882 int i, j;
9883 int follows = -1;
9884
9885 if (!set1 || !set2)
9886 return -2;
9887
9888 for (i = 0; i < set1->n; ++i)
9889 for (j = 0; j < set2->n; ++j) {
9890 int f;
9891 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9892 if (f == 1 || f == -2)
9893 return f;
9894 if (f > follows)
9895 follows = f;
9896 }
9897
9898 return follows;
9899 }
9900
isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * val)9901 static isl_bool isl_basic_map_plain_has_fixed_var(
9902 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9903 {
9904 int i;
9905 int d;
9906 isl_size total;
9907
9908 total = isl_basic_map_dim(bmap, isl_dim_all);
9909 if (total < 0)
9910 return isl_bool_error;
9911 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9912 for (; d+1 > pos; --d)
9913 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9914 break;
9915 if (d != pos)
9916 continue;
9917 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9918 return isl_bool_false;
9919 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9920 return isl_bool_false;
9921 if (!isl_int_is_one(bmap->eq[i][1+d]))
9922 return isl_bool_false;
9923 if (val)
9924 isl_int_neg(*val, bmap->eq[i][0]);
9925 return isl_bool_true;
9926 }
9927 return isl_bool_false;
9928 }
9929
isl_map_plain_has_fixed_var(__isl_keep isl_map * map,unsigned pos,isl_int * val)9930 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9931 unsigned pos, isl_int *val)
9932 {
9933 int i;
9934 isl_int v;
9935 isl_int tmp;
9936 isl_bool fixed;
9937
9938 if (!map)
9939 return isl_bool_error;
9940 if (map->n == 0)
9941 return isl_bool_false;
9942 if (map->n == 1)
9943 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9944 isl_int_init(v);
9945 isl_int_init(tmp);
9946 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9947 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9948 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9949 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9950 fixed = isl_bool_false;
9951 }
9952 if (val)
9953 isl_int_set(*val, v);
9954 isl_int_clear(tmp);
9955 isl_int_clear(v);
9956 return fixed;
9957 }
9958
isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set * bset,unsigned pos,isl_int * val)9959 static isl_bool isl_basic_set_plain_has_fixed_var(
9960 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9961 {
9962 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9963 pos, val);
9964 }
9965
isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int * val)9966 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9967 enum isl_dim_type type, unsigned pos, isl_int *val)
9968 {
9969 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9970 return isl_bool_error;
9971 return isl_basic_map_plain_has_fixed_var(bmap,
9972 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9973 }
9974
9975 /* If "bmap" obviously lies on a hyperplane where the given dimension
9976 * has a fixed value, then return that value.
9977 * Otherwise return NaN.
9978 */
isl_basic_map_plain_get_val_if_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)9979 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9980 __isl_keep isl_basic_map *bmap,
9981 enum isl_dim_type type, unsigned pos)
9982 {
9983 isl_ctx *ctx;
9984 isl_val *v;
9985 isl_bool fixed;
9986
9987 if (!bmap)
9988 return NULL;
9989 ctx = isl_basic_map_get_ctx(bmap);
9990 v = isl_val_alloc(ctx);
9991 if (!v)
9992 return NULL;
9993 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9994 if (fixed < 0)
9995 return isl_val_free(v);
9996 if (fixed) {
9997 isl_int_set_si(v->d, 1);
9998 return v;
9999 }
10000 isl_val_free(v);
10001 return isl_val_nan(ctx);
10002 }
10003
isl_map_plain_is_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_int * val)10004 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
10005 enum isl_dim_type type, unsigned pos, isl_int *val)
10006 {
10007 if (isl_map_check_range(map, type, pos, 1) < 0)
10008 return isl_bool_error;
10009 return isl_map_plain_has_fixed_var(map,
10010 map_offset(map, type) - 1 + pos, val);
10011 }
10012
10013 /* If "map" obviously lies on a hyperplane where the given dimension
10014 * has a fixed value, then return that value.
10015 * Otherwise return NaN.
10016 */
isl_map_plain_get_val_if_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)10017 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
10018 enum isl_dim_type type, unsigned pos)
10019 {
10020 isl_ctx *ctx;
10021 isl_val *v;
10022 isl_bool fixed;
10023
10024 if (!map)
10025 return NULL;
10026 ctx = isl_map_get_ctx(map);
10027 v = isl_val_alloc(ctx);
10028 if (!v)
10029 return NULL;
10030 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
10031 if (fixed < 0)
10032 return isl_val_free(v);
10033 if (fixed) {
10034 isl_int_set_si(v->d, 1);
10035 return v;
10036 }
10037 isl_val_free(v);
10038 return isl_val_nan(ctx);
10039 }
10040
10041 /* If "set" obviously lies on a hyperplane where the given dimension
10042 * has a fixed value, then return that value.
10043 * Otherwise return NaN.
10044 */
isl_set_plain_get_val_if_fixed(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10045 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
10046 enum isl_dim_type type, unsigned pos)
10047 {
10048 return isl_map_plain_get_val_if_fixed(set, type, pos);
10049 }
10050
10051 /* Return a sequence of values in the same space as "set"
10052 * that are equal to the corresponding set dimensions of "set"
10053 * for those set dimensions that obviously lie on a hyperplane
10054 * where the dimension has a fixed value.
10055 * The other elements are set to NaN.
10056 */
isl_set_get_plain_multi_val_if_fixed(__isl_keep isl_set * set)10057 __isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
10058 __isl_keep isl_set *set)
10059 {
10060 int i;
10061 isl_size n;
10062 isl_space *space;
10063 isl_multi_val *mv;
10064
10065 space = isl_space_drop_all_params(isl_set_get_space(set));
10066 mv = isl_multi_val_alloc(space);
10067 n = isl_multi_val_size(mv);
10068 if (n < 0)
10069 return isl_multi_val_free(mv);
10070
10071 for (i = 0; i < n; ++i) {
10072 isl_val *v;
10073
10074 v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);
10075 mv = isl_multi_val_set_val(mv, i, v);
10076 }
10077
10078 return mv;
10079 }
10080
10081 /* Check if dimension dim has fixed value and if so and if val is not NULL,
10082 * then return this fixed value in *val.
10083 */
isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set * bset,unsigned dim,isl_int * val)10084 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
10085 unsigned dim, isl_int *val)
10086 {
10087 isl_size nparam;
10088
10089 nparam = isl_basic_set_dim(bset, isl_dim_param);
10090 if (nparam < 0)
10091 return isl_bool_error;
10092 return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
10093 }
10094
10095 /* Return -1 if the constraint "c1" should be sorted before "c2"
10096 * and 1 if it should be sorted after "c2".
10097 * Return 0 if the two constraints are the same (up to the constant term).
10098 *
10099 * In particular, if a constraint involves later variables than another
10100 * then it is sorted after this other constraint.
10101 * uset_gist depends on constraints without existentially quantified
10102 * variables sorting first.
10103 *
10104 * For constraints that have the same latest variable, those
10105 * with the same coefficient for this latest variable (first in absolute value
10106 * and then in actual value) are grouped together.
10107 * This is useful for detecting pairs of constraints that can
10108 * be chained in their printed representation.
10109 *
10110 * Finally, within a group, constraints are sorted according to
10111 * their coefficients (excluding the constant term).
10112 */
sort_constraint_cmp(const void * p1,const void * p2,void * arg)10113 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
10114 {
10115 isl_int **c1 = (isl_int **) p1;
10116 isl_int **c2 = (isl_int **) p2;
10117 int l1, l2;
10118 unsigned size = *(unsigned *) arg;
10119 int cmp;
10120
10121 l1 = isl_seq_last_non_zero(*c1 + 1, size);
10122 l2 = isl_seq_last_non_zero(*c2 + 1, size);
10123
10124 if (l1 != l2)
10125 return l1 - l2;
10126
10127 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10128 if (cmp != 0)
10129 return cmp;
10130 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10131 if (cmp != 0)
10132 return -cmp;
10133
10134 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
10135 }
10136
10137 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
10138 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
10139 * and 0 if the two constraints are the same (up to the constant term).
10140 */
isl_basic_map_constraint_cmp(__isl_keep isl_basic_map * bmap,isl_int * c1,isl_int * c2)10141 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
10142 isl_int *c1, isl_int *c2)
10143 {
10144 isl_size total;
10145 unsigned size;
10146
10147 total = isl_basic_map_dim(bmap, isl_dim_all);
10148 if (total < 0)
10149 return -2;
10150 size = total;
10151 return sort_constraint_cmp(&c1, &c2, &size);
10152 }
10153
isl_basic_map_sort_constraints(__isl_take isl_basic_map * bmap)10154 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
10155 __isl_take isl_basic_map *bmap)
10156 {
10157 isl_size total;
10158 unsigned size;
10159
10160 if (!bmap)
10161 return NULL;
10162 if (bmap->n_ineq == 0)
10163 return bmap;
10164 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
10165 return bmap;
10166 total = isl_basic_map_dim(bmap, isl_dim_all);
10167 if (total < 0)
10168 return isl_basic_map_free(bmap);
10169 size = total;
10170 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
10171 &sort_constraint_cmp, &size) < 0)
10172 return isl_basic_map_free(bmap);
10173 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
10174 return bmap;
10175 }
10176
isl_basic_set_sort_constraints(__isl_take isl_basic_set * bset)10177 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
10178 __isl_take isl_basic_set *bset)
10179 {
10180 isl_basic_map *bmap = bset_to_bmap(bset);
10181 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
10182 }
10183
isl_basic_map_normalize(__isl_take isl_basic_map * bmap)10184 __isl_give isl_basic_map *isl_basic_map_normalize(
10185 __isl_take isl_basic_map *bmap)
10186 {
10187 bmap = isl_basic_map_remove_redundancies(bmap);
10188 bmap = isl_basic_map_sort_constraints(bmap);
10189 return bmap;
10190 }
isl_basic_map_plain_cmp(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10191 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
10192 __isl_keep isl_basic_map *bmap2)
10193 {
10194 int i, cmp;
10195 isl_size total;
10196 isl_space *space1, *space2;
10197
10198 if (!bmap1 || !bmap2)
10199 return -1;
10200
10201 if (bmap1 == bmap2)
10202 return 0;
10203 space1 = isl_basic_map_peek_space(bmap1);
10204 space2 = isl_basic_map_peek_space(bmap2);
10205 cmp = isl_space_cmp(space1, space2);
10206 if (cmp)
10207 return cmp;
10208 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
10209 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
10210 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
10211 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
10212 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10213 return 0;
10214 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
10215 return 1;
10216 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10217 return -1;
10218 if (bmap1->n_eq != bmap2->n_eq)
10219 return bmap1->n_eq - bmap2->n_eq;
10220 if (bmap1->n_ineq != bmap2->n_ineq)
10221 return bmap1->n_ineq - bmap2->n_ineq;
10222 if (bmap1->n_div != bmap2->n_div)
10223 return bmap1->n_div - bmap2->n_div;
10224 total = isl_basic_map_dim(bmap1, isl_dim_all);
10225 if (total < 0)
10226 return -1;
10227 for (i = 0; i < bmap1->n_eq; ++i) {
10228 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
10229 if (cmp)
10230 return cmp;
10231 }
10232 for (i = 0; i < bmap1->n_ineq; ++i) {
10233 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
10234 if (cmp)
10235 return cmp;
10236 }
10237 for (i = 0; i < bmap1->n_div; ++i) {
10238 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
10239 if (cmp)
10240 return cmp;
10241 }
10242 return 0;
10243 }
10244
isl_basic_set_plain_cmp(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10245 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
10246 __isl_keep isl_basic_set *bset2)
10247 {
10248 return isl_basic_map_plain_cmp(bset1, bset2);
10249 }
10250
isl_set_plain_cmp(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10251 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
10252 {
10253 int i, cmp;
10254
10255 if (set1 == set2)
10256 return 0;
10257 if (set1->n != set2->n)
10258 return set1->n - set2->n;
10259
10260 for (i = 0; i < set1->n; ++i) {
10261 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
10262 if (cmp)
10263 return cmp;
10264 }
10265
10266 return 0;
10267 }
10268
isl_basic_map_plain_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10269 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
10270 __isl_keep isl_basic_map *bmap2)
10271 {
10272 if (!bmap1 || !bmap2)
10273 return isl_bool_error;
10274 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
10275 }
10276
isl_basic_set_plain_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10277 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
10278 __isl_keep isl_basic_set *bset2)
10279 {
10280 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
10281 bset_to_bmap(bset2));
10282 }
10283
qsort_bmap_cmp(const void * p1,const void * p2)10284 static int qsort_bmap_cmp(const void *p1, const void *p2)
10285 {
10286 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
10287 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
10288
10289 return isl_basic_map_plain_cmp(bmap1, bmap2);
10290 }
10291
10292 /* Sort the basic maps of "map" and remove duplicate basic maps.
10293 *
10294 * While removing basic maps, we make sure that the basic maps remain
10295 * sorted because isl_map_normalize expects the basic maps of the result
10296 * to be sorted.
10297 */
sort_and_remove_duplicates(__isl_take isl_map * map)10298 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
10299 {
10300 int i, j;
10301
10302 map = isl_map_remove_empty_parts(map);
10303 if (!map)
10304 return NULL;
10305 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
10306 for (i = map->n - 1; i >= 1; --i) {
10307 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
10308 continue;
10309 isl_basic_map_free(map->p[i-1]);
10310 for (j = i; j < map->n; ++j)
10311 map->p[j - 1] = map->p[j];
10312 map->n--;
10313 }
10314
10315 return map;
10316 }
10317
10318 /* Remove obvious duplicates among the basic maps of "map".
10319 *
10320 * Unlike isl_map_normalize, this function does not remove redundant
10321 * constraints and only removes duplicates that have exactly the same
10322 * constraints in the input. It does sort the constraints and
10323 * the basic maps to ease the detection of duplicates.
10324 *
10325 * If "map" has already been normalized or if the basic maps are
10326 * disjoint, then there can be no duplicates.
10327 */
isl_map_remove_obvious_duplicates(__isl_take isl_map * map)10328 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
10329 {
10330 int i;
10331 isl_basic_map *bmap;
10332
10333 if (!map)
10334 return NULL;
10335 if (map->n <= 1)
10336 return map;
10337 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
10338 return map;
10339 for (i = 0; i < map->n; ++i) {
10340 bmap = isl_basic_map_copy(map->p[i]);
10341 bmap = isl_basic_map_sort_constraints(bmap);
10342 if (!bmap)
10343 return isl_map_free(map);
10344 isl_basic_map_free(map->p[i]);
10345 map->p[i] = bmap;
10346 }
10347
10348 map = sort_and_remove_duplicates(map);
10349 return map;
10350 }
10351
10352 /* We normalize in place, but if anything goes wrong we need
10353 * to return NULL, so we need to make sure we don't change the
10354 * meaning of any possible other copies of map.
10355 */
isl_map_normalize(__isl_take isl_map * map)10356 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
10357 {
10358 int i;
10359 struct isl_basic_map *bmap;
10360
10361 if (!map)
10362 return NULL;
10363 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
10364 return map;
10365 for (i = 0; i < map->n; ++i) {
10366 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
10367 if (!bmap)
10368 goto error;
10369 isl_basic_map_free(map->p[i]);
10370 map->p[i] = bmap;
10371 }
10372
10373 map = sort_and_remove_duplicates(map);
10374 if (map)
10375 ISL_F_SET(map, ISL_MAP_NORMALIZED);
10376 return map;
10377 error:
10378 isl_map_free(map);
10379 return NULL;
10380 }
10381
isl_set_normalize(__isl_take isl_set * set)10382 __isl_give isl_set *isl_set_normalize(__isl_take isl_set *set)
10383 {
10384 return set_from_map(isl_map_normalize(set_to_map(set)));
10385 }
10386
isl_map_plain_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)10387 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
10388 __isl_keep isl_map *map2)
10389 {
10390 int i;
10391 isl_bool equal;
10392
10393 if (!map1 || !map2)
10394 return isl_bool_error;
10395
10396 if (map1 == map2)
10397 return isl_bool_true;
10398 equal = isl_map_has_equal_space(map1, map2);
10399 if (equal < 0 || !equal)
10400 return equal;
10401
10402 map1 = isl_map_copy(map1);
10403 map2 = isl_map_copy(map2);
10404 map1 = isl_map_normalize(map1);
10405 map2 = isl_map_normalize(map2);
10406 if (!map1 || !map2)
10407 goto error;
10408 equal = map1->n == map2->n;
10409 for (i = 0; equal && i < map1->n; ++i) {
10410 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
10411 if (equal < 0)
10412 goto error;
10413 }
10414 isl_map_free(map1);
10415 isl_map_free(map2);
10416 return equal;
10417 error:
10418 isl_map_free(map1);
10419 isl_map_free(map2);
10420 return isl_bool_error;
10421 }
10422
isl_set_plain_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10423 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
10424 __isl_keep isl_set *set2)
10425 {
10426 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
10427 }
10428
10429 /* Return the basic maps in "map" as a list.
10430 */
isl_map_get_basic_map_list(__isl_keep isl_map * map)10431 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
10432 __isl_keep isl_map *map)
10433 {
10434 int i;
10435 isl_ctx *ctx;
10436 isl_basic_map_list *list;
10437
10438 if (!map)
10439 return NULL;
10440 ctx = isl_map_get_ctx(map);
10441 list = isl_basic_map_list_alloc(ctx, map->n);
10442
10443 for (i = 0; i < map->n; ++i) {
10444 isl_basic_map *bmap;
10445
10446 bmap = isl_basic_map_copy(map->p[i]);
10447 list = isl_basic_map_list_add(list, bmap);
10448 }
10449
10450 return list;
10451 }
10452
10453 /* Return the intersection of the elements in the non-empty list "list".
10454 * All elements are assumed to live in the same space.
10455 */
isl_basic_map_list_intersect(__isl_take isl_basic_map_list * list)10456 __isl_give isl_basic_map *isl_basic_map_list_intersect(
10457 __isl_take isl_basic_map_list *list)
10458 {
10459 int i;
10460 isl_size n;
10461 isl_basic_map *bmap;
10462
10463 n = isl_basic_map_list_n_basic_map(list);
10464 if (n < 0)
10465 goto error;
10466 if (n < 1)
10467 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
10468 "expecting non-empty list", goto error);
10469
10470 bmap = isl_basic_map_list_get_basic_map(list, 0);
10471 for (i = 1; i < n; ++i) {
10472 isl_basic_map *bmap_i;
10473
10474 bmap_i = isl_basic_map_list_get_basic_map(list, i);
10475 bmap = isl_basic_map_intersect(bmap, bmap_i);
10476 }
10477
10478 isl_basic_map_list_free(list);
10479 return bmap;
10480 error:
10481 isl_basic_map_list_free(list);
10482 return NULL;
10483 }
10484
10485 /* Return the intersection of the elements in the non-empty list "list".
10486 * All elements are assumed to live in the same space.
10487 */
isl_basic_set_list_intersect(__isl_take isl_basic_set_list * list)10488 __isl_give isl_basic_set *isl_basic_set_list_intersect(
10489 __isl_take isl_basic_set_list *list)
10490 {
10491 return isl_basic_map_list_intersect(list);
10492 }
10493
10494 /* Return the union of the elements of "list".
10495 * The list is required to have at least one element.
10496 */
isl_basic_set_list_union(__isl_take isl_basic_set_list * list)10497 __isl_give isl_set *isl_basic_set_list_union(
10498 __isl_take isl_basic_set_list *list)
10499 {
10500 int i;
10501 isl_size n;
10502 isl_space *space;
10503 isl_basic_set *bset;
10504 isl_set *set;
10505
10506 n = isl_basic_set_list_n_basic_set(list);
10507 if (n < 0)
10508 goto error;
10509 if (n < 1)
10510 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
10511 "expecting non-empty list", goto error);
10512
10513 bset = isl_basic_set_list_get_basic_set(list, 0);
10514 space = isl_basic_set_get_space(bset);
10515 isl_basic_set_free(bset);
10516
10517 set = isl_set_alloc_space(space, n, 0);
10518 for (i = 0; i < n; ++i) {
10519 bset = isl_basic_set_list_get_basic_set(list, i);
10520 set = isl_set_add_basic_set(set, bset);
10521 }
10522
10523 isl_basic_set_list_free(list);
10524 return set;
10525 error:
10526 isl_basic_set_list_free(list);
10527 return NULL;
10528 }
10529
10530 /* Return the union of the elements in the non-empty list "list".
10531 * All elements are assumed to live in the same space.
10532 */
isl_set_list_union(__isl_take isl_set_list * list)10533 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
10534 {
10535 int i;
10536 isl_size n;
10537 isl_set *set;
10538
10539 n = isl_set_list_n_set(list);
10540 if (n < 0)
10541 goto error;
10542 if (n < 1)
10543 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
10544 "expecting non-empty list", goto error);
10545
10546 set = isl_set_list_get_set(list, 0);
10547 for (i = 1; i < n; ++i) {
10548 isl_set *set_i;
10549
10550 set_i = isl_set_list_get_set(list, i);
10551 set = isl_set_union(set, set_i);
10552 }
10553
10554 isl_set_list_free(list);
10555 return set;
10556 error:
10557 isl_set_list_free(list);
10558 return NULL;
10559 }
10560
isl_basic_map_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10561 __isl_give isl_basic_map *isl_basic_map_product(
10562 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10563 {
10564 isl_space *space_result = NULL;
10565 struct isl_basic_map *bmap;
10566 unsigned in1, in2, out1, out2, nparam, total, pos;
10567 struct isl_dim_map *dim_map1, *dim_map2;
10568
10569 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10570 goto error;
10571 space_result = isl_space_product(isl_space_copy(bmap1->dim),
10572 isl_space_copy(bmap2->dim));
10573
10574 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10575 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10576 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10577 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10578 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10579
10580 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
10581 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10582 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10583 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10584 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10585 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10586 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10587 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10588 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10589 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10590 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10591
10592 bmap = isl_basic_map_alloc_space(space_result,
10593 bmap1->n_div + bmap2->n_div,
10594 bmap1->n_eq + bmap2->n_eq,
10595 bmap1->n_ineq + bmap2->n_ineq);
10596 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10597 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10598 bmap = isl_basic_map_simplify(bmap);
10599 return isl_basic_map_finalize(bmap);
10600 error:
10601 isl_basic_map_free(bmap1);
10602 isl_basic_map_free(bmap2);
10603 return NULL;
10604 }
10605
isl_basic_map_flat_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10606 __isl_give isl_basic_map *isl_basic_map_flat_product(
10607 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10608 {
10609 isl_basic_map *prod;
10610
10611 prod = isl_basic_map_product(bmap1, bmap2);
10612 prod = isl_basic_map_flatten(prod);
10613 return prod;
10614 }
10615
isl_basic_set_flat_product(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)10616 __isl_give isl_basic_set *isl_basic_set_flat_product(
10617 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10618 {
10619 return isl_basic_map_flat_range_product(bset1, bset2);
10620 }
10621
isl_basic_map_domain_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10622 __isl_give isl_basic_map *isl_basic_map_domain_product(
10623 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10624 {
10625 isl_space *space1, *space2;
10626 isl_space *space_result = NULL;
10627 isl_basic_map *bmap;
10628 isl_size in1, in2, out, nparam;
10629 unsigned total, pos;
10630 struct isl_dim_map *dim_map1, *dim_map2;
10631
10632 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10633 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10634 out = isl_basic_map_dim(bmap1, isl_dim_out);
10635 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10636 if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
10637 goto error;
10638
10639 space1 = isl_basic_map_get_space(bmap1);
10640 space2 = isl_basic_map_get_space(bmap2);
10641 space_result = isl_space_domain_product(space1, space2);
10642
10643 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10644 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10645 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10646 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10647 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10648 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10649 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10650 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10651 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10652 isl_dim_map_div(dim_map1, bmap1, pos += out);
10653 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10654
10655 bmap = isl_basic_map_alloc_space(space_result,
10656 bmap1->n_div + bmap2->n_div,
10657 bmap1->n_eq + bmap2->n_eq,
10658 bmap1->n_ineq + bmap2->n_ineq);
10659 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10660 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10661 bmap = isl_basic_map_simplify(bmap);
10662 return isl_basic_map_finalize(bmap);
10663 error:
10664 isl_basic_map_free(bmap1);
10665 isl_basic_map_free(bmap2);
10666 return NULL;
10667 }
10668
isl_basic_map_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10669 __isl_give isl_basic_map *isl_basic_map_range_product(
10670 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10671 {
10672 isl_bool rational;
10673 isl_space *space_result = NULL;
10674 isl_basic_map *bmap;
10675 isl_size in, out1, out2, nparam;
10676 unsigned total, pos;
10677 struct isl_dim_map *dim_map1, *dim_map2;
10678
10679 rational = isl_basic_map_is_rational(bmap1);
10680 if (rational >= 0 && rational)
10681 rational = isl_basic_map_is_rational(bmap2);
10682 in = isl_basic_map_dim(bmap1, isl_dim_in);
10683 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10684 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10685 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10686 if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
10687 goto error;
10688
10689 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10690 goto error;
10691
10692 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10693 isl_space_copy(bmap2->dim));
10694
10695 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10696 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10697 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10698 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10699 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10700 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10701 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10702 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10703 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10704 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10705 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10706
10707 bmap = isl_basic_map_alloc_space(space_result,
10708 bmap1->n_div + bmap2->n_div,
10709 bmap1->n_eq + bmap2->n_eq,
10710 bmap1->n_ineq + bmap2->n_ineq);
10711 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10712 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10713 if (rational)
10714 bmap = isl_basic_map_set_rational(bmap);
10715 bmap = isl_basic_map_simplify(bmap);
10716 return isl_basic_map_finalize(bmap);
10717 error:
10718 isl_basic_map_free(bmap1);
10719 isl_basic_map_free(bmap2);
10720 return NULL;
10721 }
10722
isl_basic_map_flat_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10723 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10724 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10725 {
10726 isl_basic_map *prod;
10727
10728 prod = isl_basic_map_range_product(bmap1, bmap2);
10729 prod = isl_basic_map_flatten_range(prod);
10730 return prod;
10731 }
10732
10733 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10734 * and collect the results.
10735 * The result live in the space obtained by calling "space_product"
10736 * on the spaces of "map1" and "map2".
10737 * If "remove_duplicates" is set then the result may contain duplicates
10738 * (even if the inputs do not) and so we try and remove the obvious
10739 * duplicates.
10740 */
map_product(__isl_take isl_map * map1,__isl_take isl_map * map2,__isl_give isl_space * (* space_product)(__isl_take isl_space * left,__isl_take isl_space * right),__isl_give isl_basic_map * (* basic_map_product)(__isl_take isl_basic_map * left,__isl_take isl_basic_map * right),int remove_duplicates)10741 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10742 __isl_take isl_map *map2,
10743 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10744 __isl_take isl_space *right),
10745 __isl_give isl_basic_map *(*basic_map_product)(
10746 __isl_take isl_basic_map *left,
10747 __isl_take isl_basic_map *right),
10748 int remove_duplicates)
10749 {
10750 unsigned flags = 0;
10751 struct isl_map *result;
10752 int i, j;
10753 isl_bool m;
10754
10755 m = isl_map_has_equal_params(map1, map2);
10756 if (m < 0)
10757 goto error;
10758 if (!m)
10759 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10760 "parameters don't match", goto error);
10761
10762 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10763 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10764 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10765
10766 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10767 isl_space_copy(map2->dim)),
10768 map1->n * map2->n, flags);
10769 if (!result)
10770 goto error;
10771 for (i = 0; i < map1->n; ++i)
10772 for (j = 0; j < map2->n; ++j) {
10773 struct isl_basic_map *part;
10774 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10775 isl_basic_map_copy(map2->p[j]));
10776 if (isl_basic_map_is_empty(part))
10777 isl_basic_map_free(part);
10778 else
10779 result = isl_map_add_basic_map(result, part);
10780 if (!result)
10781 goto error;
10782 }
10783 if (remove_duplicates)
10784 result = isl_map_remove_obvious_duplicates(result);
10785 isl_map_free(map1);
10786 isl_map_free(map2);
10787 return result;
10788 error:
10789 isl_map_free(map1);
10790 isl_map_free(map2);
10791 return NULL;
10792 }
10793
10794 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10795 */
isl_map_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10796 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10797 __isl_take isl_map *map2)
10798 {
10799 isl_map_align_params_bin(&map1, &map2);
10800 return map_product(map1, map2, &isl_space_product,
10801 &isl_basic_map_product, 0);
10802 }
10803
10804 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10805 */
isl_map_flat_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10806 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10807 __isl_take isl_map *map2)
10808 {
10809 isl_map *prod;
10810
10811 prod = isl_map_product(map1, map2);
10812 prod = isl_map_flatten(prod);
10813 return prod;
10814 }
10815
10816 /* Given two set A and B, construct its Cartesian product A x B.
10817 */
isl_set_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10818 __isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
10819 __isl_take isl_set *set2)
10820 {
10821 return isl_map_range_product(set1, set2);
10822 }
10823
isl_set_flat_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10824 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10825 __isl_take isl_set *set2)
10826 {
10827 return isl_map_flat_range_product(set1, set2);
10828 }
10829
10830 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10831 */
isl_map_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10832 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10833 __isl_take isl_map *map2)
10834 {
10835 isl_map_align_params_bin(&map1, &map2);
10836 return map_product(map1, map2, &isl_space_domain_product,
10837 &isl_basic_map_domain_product, 1);
10838 }
10839
10840 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10841 */
isl_map_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10842 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10843 __isl_take isl_map *map2)
10844 {
10845 isl_map_align_params_bin(&map1, &map2);
10846 return map_product(map1, map2, &isl_space_range_product,
10847 &isl_basic_map_range_product, 1);
10848 }
10849
10850 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10851 */
isl_map_factor_domain(__isl_take isl_map * map)10852 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10853 {
10854 isl_space *space;
10855 isl_size total1, keep1, total2, keep2;
10856
10857 total1 = isl_map_dim(map, isl_dim_in);
10858 total2 = isl_map_dim(map, isl_dim_out);
10859 if (total1 < 0 || total2 < 0)
10860 return isl_map_free(map);
10861 if (!isl_space_domain_is_wrapping(map->dim) ||
10862 !isl_space_range_is_wrapping(map->dim))
10863 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10864 "not a product", return isl_map_free(map));
10865
10866 space = isl_map_get_space(map);
10867 space = isl_space_factor_domain(space);
10868 keep1 = isl_space_dim(space, isl_dim_in);
10869 keep2 = isl_space_dim(space, isl_dim_out);
10870 if (keep1 < 0 || keep2 < 0)
10871 map = isl_map_free(map);
10872 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10873 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10874 map = isl_map_reset_space(map, space);
10875
10876 return map;
10877 }
10878
10879 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10880 */
isl_map_factor_range(__isl_take isl_map * map)10881 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10882 {
10883 isl_space *space;
10884 isl_size total1, keep1, total2, keep2;
10885
10886 total1 = isl_map_dim(map, isl_dim_in);
10887 total2 = isl_map_dim(map, isl_dim_out);
10888 if (total1 < 0 || total2 < 0)
10889 return isl_map_free(map);
10890 if (!isl_space_domain_is_wrapping(map->dim) ||
10891 !isl_space_range_is_wrapping(map->dim))
10892 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10893 "not a product", return isl_map_free(map));
10894
10895 space = isl_map_get_space(map);
10896 space = isl_space_factor_range(space);
10897 keep1 = isl_space_dim(space, isl_dim_in);
10898 keep2 = isl_space_dim(space, isl_dim_out);
10899 if (keep1 < 0 || keep2 < 0)
10900 map = isl_map_free(map);
10901 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10902 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10903 map = isl_map_reset_space(map, space);
10904
10905 return map;
10906 }
10907
10908 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10909 */
isl_map_domain_factor_domain(__isl_take isl_map * map)10910 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10911 {
10912 isl_space *space;
10913 isl_size total, keep;
10914
10915 total = isl_map_dim(map, isl_dim_in);
10916 if (total < 0)
10917 return isl_map_free(map);
10918 if (!isl_space_domain_is_wrapping(map->dim))
10919 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10920 "domain is not a product", return isl_map_free(map));
10921
10922 space = isl_map_get_space(map);
10923 space = isl_space_domain_factor_domain(space);
10924 keep = isl_space_dim(space, isl_dim_in);
10925 if (keep < 0)
10926 map = isl_map_free(map);
10927 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10928 map = isl_map_reset_space(map, space);
10929
10930 return map;
10931 }
10932
10933 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10934 */
isl_map_domain_factor_range(__isl_take isl_map * map)10935 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10936 {
10937 isl_space *space;
10938 isl_size total, keep;
10939
10940 total = isl_map_dim(map, isl_dim_in);
10941 if (total < 0)
10942 return isl_map_free(map);
10943 if (!isl_space_domain_is_wrapping(map->dim))
10944 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10945 "domain is not a product", return isl_map_free(map));
10946
10947 space = isl_map_get_space(map);
10948 space = isl_space_domain_factor_range(space);
10949 keep = isl_space_dim(space, isl_dim_in);
10950 if (keep < 0)
10951 map = isl_map_free(map);
10952 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10953 map = isl_map_reset_space(map, space);
10954
10955 return map;
10956 }
10957
10958 /* Given a map A -> [B -> C], extract the map A -> B.
10959 */
isl_map_range_factor_domain(__isl_take isl_map * map)10960 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10961 {
10962 isl_space *space;
10963 isl_size total, keep;
10964
10965 total = isl_map_dim(map, isl_dim_out);
10966 if (total < 0)
10967 return isl_map_free(map);
10968 if (!isl_space_range_is_wrapping(map->dim))
10969 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10970 "range is not a product", return isl_map_free(map));
10971
10972 space = isl_map_get_space(map);
10973 space = isl_space_range_factor_domain(space);
10974 keep = isl_space_dim(space, isl_dim_out);
10975 if (keep < 0)
10976 map = isl_map_free(map);
10977 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10978 map = isl_map_reset_space(map, space);
10979
10980 return map;
10981 }
10982
10983 /* Given a map A -> [B -> C], extract the map A -> C.
10984 */
isl_map_range_factor_range(__isl_take isl_map * map)10985 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10986 {
10987 isl_space *space;
10988 isl_size total, keep;
10989
10990 total = isl_map_dim(map, isl_dim_out);
10991 if (total < 0)
10992 return isl_map_free(map);
10993 if (!isl_space_range_is_wrapping(map->dim))
10994 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10995 "range is not a product", return isl_map_free(map));
10996
10997 space = isl_map_get_space(map);
10998 space = isl_space_range_factor_range(space);
10999 keep = isl_space_dim(space, isl_dim_out);
11000 if (keep < 0)
11001 map = isl_map_free(map);
11002 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
11003 map = isl_map_reset_space(map, space);
11004
11005 return map;
11006 }
11007
11008 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
11009 */
isl_map_flat_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)11010 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
11011 __isl_take isl_map *map2)
11012 {
11013 isl_map *prod;
11014
11015 prod = isl_map_domain_product(map1, map2);
11016 prod = isl_map_flatten_domain(prod);
11017 return prod;
11018 }
11019
11020 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
11021 */
isl_map_flat_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)11022 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
11023 __isl_take isl_map *map2)
11024 {
11025 isl_map *prod;
11026
11027 prod = isl_map_range_product(map1, map2);
11028 prod = isl_map_flatten_range(prod);
11029 return prod;
11030 }
11031
isl_basic_map_get_hash(__isl_keep isl_basic_map * bmap)11032 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
11033 {
11034 int i;
11035 uint32_t hash = isl_hash_init();
11036 isl_size total;
11037
11038 if (!bmap)
11039 return 0;
11040 bmap = isl_basic_map_copy(bmap);
11041 bmap = isl_basic_map_normalize(bmap);
11042 total = isl_basic_map_dim(bmap, isl_dim_all);
11043 if (total < 0)
11044 return 0;
11045 isl_hash_byte(hash, bmap->n_eq & 0xFF);
11046 for (i = 0; i < bmap->n_eq; ++i) {
11047 uint32_t c_hash;
11048 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
11049 isl_hash_hash(hash, c_hash);
11050 }
11051 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
11052 for (i = 0; i < bmap->n_ineq; ++i) {
11053 uint32_t c_hash;
11054 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
11055 isl_hash_hash(hash, c_hash);
11056 }
11057 isl_hash_byte(hash, bmap->n_div & 0xFF);
11058 for (i = 0; i < bmap->n_div; ++i) {
11059 uint32_t c_hash;
11060 if (isl_int_is_zero(bmap->div[i][0]))
11061 continue;
11062 isl_hash_byte(hash, i & 0xFF);
11063 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
11064 isl_hash_hash(hash, c_hash);
11065 }
11066 isl_basic_map_free(bmap);
11067 return hash;
11068 }
11069
isl_basic_set_get_hash(__isl_keep isl_basic_set * bset)11070 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
11071 {
11072 return isl_basic_map_get_hash(bset_to_bmap(bset));
11073 }
11074
isl_map_get_hash(__isl_keep isl_map * map)11075 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
11076 {
11077 int i;
11078 uint32_t hash;
11079
11080 if (!map)
11081 return 0;
11082 map = isl_map_copy(map);
11083 map = isl_map_normalize(map);
11084 if (!map)
11085 return 0;
11086
11087 hash = isl_hash_init();
11088 for (i = 0; i < map->n; ++i) {
11089 uint32_t bmap_hash;
11090 bmap_hash = isl_basic_map_get_hash(map->p[i]);
11091 isl_hash_hash(hash, bmap_hash);
11092 }
11093
11094 isl_map_free(map);
11095
11096 return hash;
11097 }
11098
isl_set_get_hash(__isl_keep isl_set * set)11099 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
11100 {
11101 return isl_map_get_hash(set_to_map(set));
11102 }
11103
11104 /* Return the number of basic maps in the (current) representation of "map".
11105 */
isl_map_n_basic_map(__isl_keep isl_map * map)11106 isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
11107 {
11108 return map ? map->n : isl_size_error;
11109 }
11110
isl_set_n_basic_set(__isl_keep isl_set * set)11111 isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
11112 {
11113 return set ? set->n : isl_size_error;
11114 }
11115
isl_map_foreach_basic_map(__isl_keep isl_map * map,isl_stat (* fn)(__isl_take isl_basic_map * bmap,void * user),void * user)11116 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
11117 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
11118 {
11119 int i;
11120
11121 if (!map)
11122 return isl_stat_error;
11123
11124 for (i = 0; i < map->n; ++i)
11125 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
11126 return isl_stat_error;
11127
11128 return isl_stat_ok;
11129 }
11130
isl_set_foreach_basic_set(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_basic_set * bset,void * user),void * user)11131 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
11132 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
11133 {
11134 int i;
11135
11136 if (!set)
11137 return isl_stat_error;
11138
11139 for (i = 0; i < set->n; ++i)
11140 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
11141 return isl_stat_error;
11142
11143 return isl_stat_ok;
11144 }
11145
11146 /* Does "test" succeed on every basic set in "set"?
11147 */
isl_set_every_basic_set(__isl_keep isl_set * set,isl_bool (* test)(__isl_keep isl_basic_set * bset,void * user),void * user)11148 isl_bool isl_set_every_basic_set(__isl_keep isl_set *set,
11149 isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),
11150 void *user)
11151 {
11152 int i;
11153
11154 if (!set)
11155 return isl_bool_error;
11156
11157 for (i = 0; i < set->n; ++i) {
11158 isl_bool r;
11159
11160 r = test(set->p[i], user);
11161 if (r < 0 || !r)
11162 return r;
11163 }
11164
11165 return isl_bool_true;
11166 }
11167
11168 /* Return a list of basic sets, the union of which is equal to "set".
11169 */
isl_set_get_basic_set_list(__isl_keep isl_set * set)11170 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
11171 __isl_keep isl_set *set)
11172 {
11173 int i;
11174 isl_basic_set_list *list;
11175
11176 if (!set)
11177 return NULL;
11178
11179 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
11180 for (i = 0; i < set->n; ++i) {
11181 isl_basic_set *bset;
11182
11183 bset = isl_basic_set_copy(set->p[i]);
11184 list = isl_basic_set_list_add(list, bset);
11185 }
11186
11187 return list;
11188 }
11189
isl_basic_set_lift(__isl_take isl_basic_set * bset)11190 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
11191 {
11192 isl_space *space;
11193
11194 if (!bset)
11195 return NULL;
11196
11197 bset = isl_basic_set_cow(bset);
11198 if (!bset)
11199 return NULL;
11200
11201 space = isl_basic_set_get_space(bset);
11202 space = isl_space_lift(space, bset->n_div);
11203 if (!space)
11204 goto error;
11205 isl_space_free(bset->dim);
11206 bset->dim = space;
11207 bset->extra -= bset->n_div;
11208 bset->n_div = 0;
11209
11210 bset = isl_basic_set_finalize(bset);
11211
11212 return bset;
11213 error:
11214 isl_basic_set_free(bset);
11215 return NULL;
11216 }
11217
isl_set_lift(__isl_take isl_set * set)11218 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
11219 {
11220 int i;
11221 isl_space *space;
11222 unsigned n_div;
11223
11224 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
11225
11226 if (!set)
11227 return NULL;
11228
11229 set = isl_set_cow(set);
11230 if (!set)
11231 return NULL;
11232
11233 n_div = set->p[0]->n_div;
11234 space = isl_set_get_space(set);
11235 space = isl_space_lift(space, n_div);
11236 if (!space)
11237 goto error;
11238 isl_space_free(set->dim);
11239 set->dim = space;
11240
11241 for (i = 0; i < set->n; ++i) {
11242 set->p[i] = isl_basic_set_lift(set->p[i]);
11243 if (!set->p[i])
11244 goto error;
11245 }
11246
11247 return set;
11248 error:
11249 isl_set_free(set);
11250 return NULL;
11251 }
11252
isl_basic_set_size(__isl_keep isl_basic_set * bset)11253 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
11254 {
11255 isl_size dim;
11256 int size = 0;
11257
11258 dim = isl_basic_set_dim(bset, isl_dim_all);
11259 if (dim < 0)
11260 return -1;
11261 size += bset->n_eq * (1 + dim);
11262 size += bset->n_ineq * (1 + dim);
11263 size += bset->n_div * (2 + dim);
11264
11265 return size;
11266 }
11267
isl_set_size(__isl_keep isl_set * set)11268 int isl_set_size(__isl_keep isl_set *set)
11269 {
11270 int i;
11271 int size = 0;
11272
11273 if (!set)
11274 return -1;
11275
11276 for (i = 0; i < set->n; ++i)
11277 size += isl_basic_set_size(set->p[i]);
11278
11279 return size;
11280 }
11281
11282 /* Check if there is any lower bound (if lower == 0) and/or upper
11283 * bound (if upper == 0) on the specified dim.
11284 */
basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int lower,int upper)11285 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11286 enum isl_dim_type type, unsigned pos, int lower, int upper)
11287 {
11288 int i;
11289
11290 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
11291 return isl_bool_error;
11292
11293 pos += isl_basic_map_offset(bmap, type);
11294
11295 for (i = 0; i < bmap->n_div; ++i) {
11296 if (isl_int_is_zero(bmap->div[i][0]))
11297 continue;
11298 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
11299 return isl_bool_true;
11300 }
11301
11302 for (i = 0; i < bmap->n_eq; ++i)
11303 if (!isl_int_is_zero(bmap->eq[i][pos]))
11304 return isl_bool_true;
11305
11306 for (i = 0; i < bmap->n_ineq; ++i) {
11307 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
11308 if (sgn > 0)
11309 lower = 1;
11310 if (sgn < 0)
11311 upper = 1;
11312 }
11313
11314 return lower && upper;
11315 }
11316
isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11317 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11318 enum isl_dim_type type, unsigned pos)
11319 {
11320 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
11321 }
11322
isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11323 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
11324 enum isl_dim_type type, unsigned pos)
11325 {
11326 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
11327 }
11328
isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11329 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
11330 enum isl_dim_type type, unsigned pos)
11331 {
11332 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
11333 }
11334
isl_map_dim_is_bounded(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)11335 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
11336 enum isl_dim_type type, unsigned pos)
11337 {
11338 int i;
11339
11340 if (!map)
11341 return isl_bool_error;
11342
11343 for (i = 0; i < map->n; ++i) {
11344 isl_bool bounded;
11345 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
11346 if (bounded < 0 || !bounded)
11347 return bounded;
11348 }
11349
11350 return isl_bool_true;
11351 }
11352
11353 /* Return true if the specified dim is involved in both an upper bound
11354 * and a lower bound.
11355 */
isl_set_dim_is_bounded(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11356 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
11357 enum isl_dim_type type, unsigned pos)
11358 {
11359 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
11360 }
11361
11362 /* Does "map" have a bound (according to "fn") for any of its basic maps?
11363 */
has_any_bound(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_bool (* fn)(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos))11364 static isl_bool has_any_bound(__isl_keep isl_map *map,
11365 enum isl_dim_type type, unsigned pos,
11366 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11367 enum isl_dim_type type, unsigned pos))
11368 {
11369 int i;
11370
11371 if (!map)
11372 return isl_bool_error;
11373
11374 for (i = 0; i < map->n; ++i) {
11375 isl_bool bounded;
11376 bounded = fn(map->p[i], type, pos);
11377 if (bounded < 0 || bounded)
11378 return bounded;
11379 }
11380
11381 return isl_bool_false;
11382 }
11383
11384 /* Return 1 if the specified dim is involved in any lower bound.
11385 */
isl_set_dim_has_any_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11386 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
11387 enum isl_dim_type type, unsigned pos)
11388 {
11389 return has_any_bound(set, type, pos,
11390 &isl_basic_map_dim_has_lower_bound);
11391 }
11392
11393 /* Return 1 if the specified dim is involved in any upper bound.
11394 */
isl_set_dim_has_any_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11395 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
11396 enum isl_dim_type type, unsigned pos)
11397 {
11398 return has_any_bound(set, type, pos,
11399 &isl_basic_map_dim_has_upper_bound);
11400 }
11401
11402 /* Does "map" have a bound (according to "fn") for all of its basic maps?
11403 */
has_bound(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_bool (* fn)(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos))11404 static isl_bool has_bound(__isl_keep isl_map *map,
11405 enum isl_dim_type type, unsigned pos,
11406 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11407 enum isl_dim_type type, unsigned pos))
11408 {
11409 int i;
11410
11411 if (!map)
11412 return isl_bool_error;
11413
11414 for (i = 0; i < map->n; ++i) {
11415 isl_bool bounded;
11416 bounded = fn(map->p[i], type, pos);
11417 if (bounded < 0 || !bounded)
11418 return bounded;
11419 }
11420
11421 return isl_bool_true;
11422 }
11423
11424 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
11425 */
isl_set_dim_has_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11426 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
11427 enum isl_dim_type type, unsigned pos)
11428 {
11429 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
11430 }
11431
11432 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
11433 */
isl_set_dim_has_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11434 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
11435 enum isl_dim_type type, unsigned pos)
11436 {
11437 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
11438 }
11439
11440 /* For each of the "n" variables starting at "first", determine
11441 * the sign of the variable and put the results in the first "n"
11442 * elements of the array "signs".
11443 * Sign
11444 * 1 means that the variable is non-negative
11445 * -1 means that the variable is non-positive
11446 * 0 means the variable attains both positive and negative values.
11447 */
isl_basic_set_vars_get_sign(__isl_keep isl_basic_set * bset,unsigned first,unsigned n,int * signs)11448 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
11449 unsigned first, unsigned n, int *signs)
11450 {
11451 isl_vec *bound = NULL;
11452 struct isl_tab *tab = NULL;
11453 struct isl_tab_undo *snap;
11454 int i;
11455 isl_size total;
11456
11457 total = isl_basic_set_dim(bset, isl_dim_all);
11458 if (total < 0 || !signs)
11459 return isl_stat_error;
11460
11461 bound = isl_vec_alloc(bset->ctx, 1 + total);
11462 tab = isl_tab_from_basic_set(bset, 0);
11463 if (!bound || !tab)
11464 goto error;
11465
11466 isl_seq_clr(bound->el, bound->size);
11467 isl_int_set_si(bound->el[0], -1);
11468
11469 snap = isl_tab_snap(tab);
11470 for (i = 0; i < n; ++i) {
11471 int empty;
11472
11473 isl_int_set_si(bound->el[1 + first + i], -1);
11474 if (isl_tab_add_ineq(tab, bound->el) < 0)
11475 goto error;
11476 empty = tab->empty;
11477 isl_int_set_si(bound->el[1 + first + i], 0);
11478 if (isl_tab_rollback(tab, snap) < 0)
11479 goto error;
11480
11481 if (empty) {
11482 signs[i] = 1;
11483 continue;
11484 }
11485
11486 isl_int_set_si(bound->el[1 + first + i], 1);
11487 if (isl_tab_add_ineq(tab, bound->el) < 0)
11488 goto error;
11489 empty = tab->empty;
11490 isl_int_set_si(bound->el[1 + first + i], 0);
11491 if (isl_tab_rollback(tab, snap) < 0)
11492 goto error;
11493
11494 signs[i] = empty ? -1 : 0;
11495 }
11496
11497 isl_tab_free(tab);
11498 isl_vec_free(bound);
11499 return isl_stat_ok;
11500 error:
11501 isl_tab_free(tab);
11502 isl_vec_free(bound);
11503 return isl_stat_error;
11504 }
11505
isl_basic_set_dims_get_sign(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n,int * signs)11506 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
11507 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
11508 {
11509 if (!bset || !signs)
11510 return isl_stat_error;
11511 if (isl_basic_set_check_range(bset, type, first, n) < 0)
11512 return isl_stat_error;
11513
11514 first += pos(bset->dim, type) - 1;
11515 return isl_basic_set_vars_get_sign(bset, first, n, signs);
11516 }
11517
11518 /* Is it possible for the integer division "div" to depend (possibly
11519 * indirectly) on any output dimensions?
11520 *
11521 * If the div is undefined, then we conservatively assume that it
11522 * may depend on them.
11523 * Otherwise, we check if it actually depends on them or on any integer
11524 * divisions that may depend on them.
11525 */
div_may_involve_output(__isl_keep isl_basic_map * bmap,int div)11526 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
11527 {
11528 int i;
11529 isl_size n_out, n_div;
11530 unsigned o_out, o_div;
11531
11532 if (isl_int_is_zero(bmap->div[div][0]))
11533 return isl_bool_true;
11534
11535 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11536 if (n_out < 0)
11537 return isl_bool_error;
11538 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11539
11540 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
11541 return isl_bool_true;
11542
11543 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11544 if (n_div < 0)
11545 return isl_bool_error;
11546 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11547
11548 for (i = 0; i < n_div; ++i) {
11549 isl_bool may_involve;
11550
11551 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
11552 continue;
11553 may_involve = div_may_involve_output(bmap, i);
11554 if (may_involve < 0 || may_involve)
11555 return may_involve;
11556 }
11557
11558 return isl_bool_false;
11559 }
11560
11561 /* Return the first integer division of "bmap" in the range
11562 * [first, first + n[ that may depend on any output dimensions and
11563 * that has a non-zero coefficient in "c" (where the first coefficient
11564 * in "c" corresponds to integer division "first").
11565 */
first_div_may_involve_output(__isl_keep isl_basic_map * bmap,isl_int * c,int first,int n)11566 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
11567 isl_int *c, int first, int n)
11568 {
11569 int k;
11570
11571 if (!bmap)
11572 return -1;
11573
11574 for (k = first; k < first + n; ++k) {
11575 isl_bool may_involve;
11576
11577 if (isl_int_is_zero(c[k]))
11578 continue;
11579 may_involve = div_may_involve_output(bmap, k);
11580 if (may_involve < 0)
11581 return -1;
11582 if (may_involve)
11583 return k;
11584 }
11585
11586 return first + n;
11587 }
11588
11589 /* Look for a pair of inequality constraints in "bmap" of the form
11590 *
11591 * -l + i >= 0 or i >= l
11592 * and
11593 * n + l - i >= 0 or i <= l + n
11594 *
11595 * with n < "m" and i the output dimension at position "pos".
11596 * (Note that n >= 0 as otherwise the two constraints would conflict.)
11597 * Furthermore, "l" is only allowed to involve parameters, input dimensions
11598 * and earlier output dimensions, as well as integer divisions that do
11599 * not involve any of the output dimensions.
11600 *
11601 * Return the index of the first inequality constraint or bmap->n_ineq
11602 * if no such pair can be found.
11603 */
find_modulo_constraint_pair(__isl_keep isl_basic_map * bmap,int pos,isl_int m)11604 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
11605 int pos, isl_int m)
11606 {
11607 int i, j;
11608 isl_ctx *ctx;
11609 isl_size total;
11610 isl_size n_div, n_out;
11611 unsigned o_div, o_out;
11612 int less;
11613
11614 total = isl_basic_map_dim(bmap, isl_dim_all);
11615 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11616 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11617 if (total < 0 || n_out < 0 || n_div < 0)
11618 return -1;
11619
11620 ctx = isl_basic_map_get_ctx(bmap);
11621 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11622 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11623 for (i = 0; i < bmap->n_ineq; ++i) {
11624 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
11625 continue;
11626 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
11627 n_out - (pos + 1)) != -1)
11628 continue;
11629 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11630 0, n_div) < n_div)
11631 continue;
11632 for (j = i + 1; j < bmap->n_ineq; ++j) {
11633 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11634 ctx->one))
11635 continue;
11636 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11637 bmap->ineq[j] + 1, total))
11638 continue;
11639 break;
11640 }
11641 if (j >= bmap->n_ineq)
11642 continue;
11643 isl_int_add(bmap->ineq[i][0],
11644 bmap->ineq[i][0], bmap->ineq[j][0]);
11645 less = isl_int_abs_lt(bmap->ineq[i][0], m);
11646 isl_int_sub(bmap->ineq[i][0],
11647 bmap->ineq[i][0], bmap->ineq[j][0]);
11648 if (!less)
11649 continue;
11650 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11651 return i;
11652 else
11653 return j;
11654 }
11655
11656 return bmap->n_ineq;
11657 }
11658
11659 /* Return the index of the equality of "bmap" that defines
11660 * the output dimension "pos" in terms of earlier dimensions.
11661 * The equality may also involve integer divisions, as long
11662 * as those integer divisions are defined in terms of
11663 * parameters or input dimensions.
11664 * In this case, *div is set to the number of integer divisions and
11665 * *ineq is set to the number of inequality constraints (provided
11666 * div and ineq are not NULL).
11667 *
11668 * The equality may also involve a single integer division involving
11669 * the output dimensions (typically only output dimension "pos") as
11670 * long as the coefficient of output dimension "pos" is 1 or -1 and
11671 * there is a pair of constraints i >= l and i <= l + n, with i referring
11672 * to output dimension "pos", l an expression involving only earlier
11673 * dimensions and n smaller than the coefficient of the integer division
11674 * in the equality. In this case, the output dimension can be defined
11675 * in terms of a modulo expression that does not involve the integer division.
11676 * *div is then set to this single integer division and
11677 * *ineq is set to the index of constraint i >= l.
11678 *
11679 * Return bmap->n_eq if there is no such equality.
11680 * Return -1 on error.
11681 */
isl_basic_map_output_defining_equality(__isl_keep isl_basic_map * bmap,int pos,int * div,int * ineq)11682 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11683 int pos, int *div, int *ineq)
11684 {
11685 int j, k, l;
11686 isl_size n_div, n_out;
11687 unsigned o_div, o_out;
11688
11689 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11690 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11691 if (n_out < 0 || n_div < 0)
11692 return -1;
11693
11694 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11695 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11696
11697 if (ineq)
11698 *ineq = bmap->n_ineq;
11699 if (div)
11700 *div = n_div;
11701 for (j = 0; j < bmap->n_eq; ++j) {
11702 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11703 continue;
11704 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11705 n_out - (pos + 1)) != -1)
11706 continue;
11707 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11708 0, n_div);
11709 if (k >= n_div)
11710 return j;
11711 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11712 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11713 continue;
11714 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11715 k + 1, n_div - (k+1)) < n_div)
11716 continue;
11717 l = find_modulo_constraint_pair(bmap, pos,
11718 bmap->eq[j][o_div + k]);
11719 if (l < 0)
11720 return -1;
11721 if (l >= bmap->n_ineq)
11722 continue;
11723 if (div)
11724 *div = k;
11725 if (ineq)
11726 *ineq = l;
11727 return j;
11728 }
11729
11730 return bmap->n_eq;
11731 }
11732
11733 /* Check if the given basic map is obviously single-valued.
11734 * In particular, for each output dimension, check that there is
11735 * an equality that defines the output dimension in terms of
11736 * earlier dimensions.
11737 */
isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map * bmap)11738 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11739 {
11740 int i;
11741 isl_size n_out;
11742
11743 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11744 if (n_out < 0)
11745 return isl_bool_error;
11746
11747 for (i = 0; i < n_out; ++i) {
11748 int eq;
11749
11750 eq = isl_basic_map_output_defining_equality(bmap, i,
11751 NULL, NULL);
11752 if (eq < 0)
11753 return isl_bool_error;
11754 if (eq >= bmap->n_eq)
11755 return isl_bool_false;
11756 }
11757
11758 return isl_bool_true;
11759 }
11760
11761 /* Check if the given basic map is single-valued.
11762 * We simply compute
11763 *
11764 * M \circ M^-1
11765 *
11766 * and check if the result is a subset of the identity mapping.
11767 */
isl_basic_map_is_single_valued(__isl_keep isl_basic_map * bmap)11768 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11769 {
11770 isl_space *space;
11771 isl_basic_map *test;
11772 isl_basic_map *id;
11773 isl_bool sv;
11774
11775 sv = isl_basic_map_plain_is_single_valued(bmap);
11776 if (sv < 0 || sv)
11777 return sv;
11778
11779 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11780 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11781
11782 space = isl_basic_map_get_space(bmap);
11783 space = isl_space_map_from_set(isl_space_range(space));
11784 id = isl_basic_map_identity(space);
11785
11786 sv = isl_basic_map_is_subset(test, id);
11787
11788 isl_basic_map_free(test);
11789 isl_basic_map_free(id);
11790
11791 return sv;
11792 }
11793
11794 /* Check if the given map is obviously single-valued.
11795 */
isl_map_plain_is_single_valued(__isl_keep isl_map * map)11796 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11797 {
11798 if (!map)
11799 return isl_bool_error;
11800 if (map->n == 0)
11801 return isl_bool_true;
11802 if (map->n >= 2)
11803 return isl_bool_false;
11804
11805 return isl_basic_map_plain_is_single_valued(map->p[0]);
11806 }
11807
11808 /* Check if the given map is single-valued.
11809 * We simply compute
11810 *
11811 * M \circ M^-1
11812 *
11813 * and check if the result is a subset of the identity mapping.
11814 */
isl_map_is_single_valued(__isl_keep isl_map * map)11815 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11816 {
11817 isl_space *space;
11818 isl_map *test;
11819 isl_map *id;
11820 isl_bool sv;
11821
11822 sv = isl_map_plain_is_single_valued(map);
11823 if (sv < 0 || sv)
11824 return sv;
11825
11826 test = isl_map_reverse(isl_map_copy(map));
11827 test = isl_map_apply_range(test, isl_map_copy(map));
11828
11829 space = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11830 id = isl_map_identity(space);
11831
11832 sv = isl_map_is_subset(test, id);
11833
11834 isl_map_free(test);
11835 isl_map_free(id);
11836
11837 return sv;
11838 }
11839
isl_map_is_injective(__isl_keep isl_map * map)11840 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11841 {
11842 isl_bool in;
11843
11844 map = isl_map_copy(map);
11845 map = isl_map_reverse(map);
11846 in = isl_map_is_single_valued(map);
11847 isl_map_free(map);
11848
11849 return in;
11850 }
11851
11852 /* Check if the given map is obviously injective.
11853 */
isl_map_plain_is_injective(__isl_keep isl_map * map)11854 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11855 {
11856 isl_bool in;
11857
11858 map = isl_map_copy(map);
11859 map = isl_map_reverse(map);
11860 in = isl_map_plain_is_single_valued(map);
11861 isl_map_free(map);
11862
11863 return in;
11864 }
11865
isl_map_is_bijective(__isl_keep isl_map * map)11866 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11867 {
11868 isl_bool sv;
11869
11870 sv = isl_map_is_single_valued(map);
11871 if (sv < 0 || !sv)
11872 return sv;
11873
11874 return isl_map_is_injective(map);
11875 }
11876
isl_set_is_singleton(__isl_keep isl_set * set)11877 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11878 {
11879 return isl_map_is_single_valued(set_to_map(set));
11880 }
11881
11882 /* Does "map" only map elements to themselves?
11883 *
11884 * If the domain and range spaces are different, then "map"
11885 * is considered not to be an identity relation, even if it is empty.
11886 * Otherwise, construct the maximal identity relation and
11887 * check whether "map" is a subset of this relation.
11888 */
isl_map_is_identity(__isl_keep isl_map * map)11889 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11890 {
11891 isl_map *id;
11892 isl_bool equal, is_identity;
11893
11894 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
11895 if (equal < 0 || !equal)
11896 return equal;
11897
11898 id = isl_map_identity(isl_map_get_space(map));
11899 is_identity = isl_map_is_subset(map, id);
11900 isl_map_free(id);
11901
11902 return is_identity;
11903 }
11904
isl_map_is_translation(__isl_keep isl_map * map)11905 int isl_map_is_translation(__isl_keep isl_map *map)
11906 {
11907 int ok;
11908 isl_set *delta;
11909
11910 delta = isl_map_deltas(isl_map_copy(map));
11911 ok = isl_set_is_singleton(delta);
11912 isl_set_free(delta);
11913
11914 return ok;
11915 }
11916
unique(isl_int * p,unsigned pos,unsigned len)11917 static int unique(isl_int *p, unsigned pos, unsigned len)
11918 {
11919 if (isl_seq_first_non_zero(p, pos) != -1)
11920 return 0;
11921 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11922 return 0;
11923 return 1;
11924 }
11925
isl_basic_set_is_box(__isl_keep isl_basic_set * bset)11926 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11927 {
11928 int i, j;
11929 isl_size nvar, n_div;
11930 unsigned ovar;
11931
11932 n_div = isl_basic_set_dim(bset, isl_dim_div);
11933 if (n_div < 0)
11934 return isl_bool_error;
11935 if (n_div != 0)
11936 return isl_bool_false;
11937
11938 nvar = isl_basic_set_dim(bset, isl_dim_set);
11939 if (nvar < 0)
11940 return isl_bool_error;
11941 ovar = isl_space_offset(bset->dim, isl_dim_set);
11942 for (j = 0; j < nvar; ++j) {
11943 int lower = 0, upper = 0;
11944 for (i = 0; i < bset->n_eq; ++i) {
11945 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11946 continue;
11947 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11948 return isl_bool_false;
11949 break;
11950 }
11951 if (i < bset->n_eq)
11952 continue;
11953 for (i = 0; i < bset->n_ineq; ++i) {
11954 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11955 continue;
11956 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11957 return isl_bool_false;
11958 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11959 lower = 1;
11960 else
11961 upper = 1;
11962 }
11963 if (!lower || !upper)
11964 return isl_bool_false;
11965 }
11966
11967 return isl_bool_true;
11968 }
11969
isl_set_is_box(__isl_keep isl_set * set)11970 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11971 {
11972 if (!set)
11973 return isl_bool_error;
11974 if (set->n != 1)
11975 return isl_bool_false;
11976
11977 return isl_basic_set_is_box(set->p[0]);
11978 }
11979
isl_basic_set_is_wrapping(__isl_keep isl_basic_set * bset)11980 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11981 {
11982 if (!bset)
11983 return isl_bool_error;
11984
11985 return isl_space_is_wrapping(bset->dim);
11986 }
11987
isl_set_is_wrapping(__isl_keep isl_set * set)11988 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11989 {
11990 if (!set)
11991 return isl_bool_error;
11992
11993 return isl_space_is_wrapping(set->dim);
11994 }
11995
11996 /* Modify the space of "map" through a call to "change".
11997 * If "can_change" is set (not NULL), then first call it to check
11998 * if the modification is allowed, printing the error message "cannot_change"
11999 * if it is not.
12000 */
isl_map_change_space(__isl_take isl_map * map,isl_bool (* can_change)(__isl_keep isl_map * map),const char * cannot_change,__isl_give isl_space * (* change)(__isl_take isl_space * space))12001 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
12002 isl_bool (*can_change)(__isl_keep isl_map *map),
12003 const char *cannot_change,
12004 __isl_give isl_space *(*change)(__isl_take isl_space *space))
12005 {
12006 isl_bool ok;
12007 isl_space *space;
12008
12009 if (!map)
12010 return NULL;
12011
12012 ok = can_change ? can_change(map) : isl_bool_true;
12013 if (ok < 0)
12014 return isl_map_free(map);
12015 if (!ok)
12016 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
12017 return isl_map_free(map));
12018
12019 space = change(isl_map_get_space(map));
12020 map = isl_map_reset_space(map, space);
12021
12022 return map;
12023 }
12024
12025 /* Is the domain of "map" a wrapped relation?
12026 */
isl_map_domain_is_wrapping(__isl_keep isl_map * map)12027 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
12028 {
12029 if (!map)
12030 return isl_bool_error;
12031
12032 return isl_space_domain_is_wrapping(map->dim);
12033 }
12034
12035 /* Does "map" have a wrapped relation in both domain and range?
12036 */
isl_map_is_product(__isl_keep isl_map * map)12037 isl_bool isl_map_is_product(__isl_keep isl_map *map)
12038 {
12039 return isl_space_is_product(isl_map_peek_space(map));
12040 }
12041
12042 /* Is the range of "map" a wrapped relation?
12043 */
isl_map_range_is_wrapping(__isl_keep isl_map * map)12044 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
12045 {
12046 if (!map)
12047 return isl_bool_error;
12048
12049 return isl_space_range_is_wrapping(map->dim);
12050 }
12051
isl_basic_map_wrap(__isl_take isl_basic_map * bmap)12052 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
12053 {
12054 isl_space *space;
12055
12056 space = isl_basic_map_take_space(bmap);
12057 space = isl_space_wrap(space);
12058 bmap = isl_basic_map_restore_space(bmap, space);
12059
12060 bmap = isl_basic_map_finalize(bmap);
12061
12062 return bset_from_bmap(bmap);
12063 }
12064
12065 /* Given a map A -> B, return the set (A -> B).
12066 */
isl_map_wrap(__isl_take isl_map * map)12067 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
12068 {
12069 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
12070 }
12071
isl_basic_set_unwrap(__isl_take isl_basic_set * bset)12072 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
12073 {
12074 bset = isl_basic_set_cow(bset);
12075 if (!bset)
12076 return NULL;
12077
12078 bset->dim = isl_space_unwrap(bset->dim);
12079 if (!bset->dim)
12080 goto error;
12081
12082 bset = isl_basic_set_finalize(bset);
12083
12084 return bset_to_bmap(bset);
12085 error:
12086 isl_basic_set_free(bset);
12087 return NULL;
12088 }
12089
12090 /* Given a set (A -> B), return the map A -> B.
12091 * Error out if "set" is not of the form (A -> B).
12092 */
isl_set_unwrap(__isl_take isl_set * set)12093 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
12094 {
12095 return isl_map_change_space(set, &isl_set_is_wrapping,
12096 "not a wrapping set", &isl_space_unwrap);
12097 }
12098
isl_basic_map_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)12099 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
12100 enum isl_dim_type type)
12101 {
12102 isl_space *space;
12103
12104 space = isl_basic_map_take_space(bmap);
12105 space = isl_space_reset(space, type);
12106 bmap = isl_basic_map_restore_space(bmap, space);
12107
12108 bmap = isl_basic_map_mark_final(bmap);
12109
12110 return bmap;
12111 }
12112
isl_map_reset(__isl_take isl_map * map,enum isl_dim_type type)12113 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
12114 enum isl_dim_type type)
12115 {
12116 int i;
12117 isl_space *space;
12118
12119 if (!map)
12120 return NULL;
12121
12122 if (!isl_space_is_named_or_nested(map->dim, type))
12123 return map;
12124
12125 map = isl_map_cow(map);
12126 if (!map)
12127 return NULL;
12128
12129 for (i = 0; i < map->n; ++i) {
12130 map->p[i] = isl_basic_map_reset(map->p[i], type);
12131 if (!map->p[i])
12132 goto error;
12133 }
12134
12135 space = isl_map_take_space(map);
12136 space = isl_space_reset(space, type);
12137 map = isl_map_restore_space(map, space);
12138
12139 return map;
12140 error:
12141 isl_map_free(map);
12142 return NULL;
12143 }
12144
isl_basic_map_flatten(__isl_take isl_basic_map * bmap)12145 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
12146 {
12147 isl_space *space;
12148
12149 space = isl_basic_map_take_space(bmap);
12150 space = isl_space_flatten(space);
12151 bmap = isl_basic_map_restore_space(bmap, space);
12152
12153 bmap = isl_basic_map_mark_final(bmap);
12154
12155 return bmap;
12156 }
12157
isl_basic_set_flatten(__isl_take isl_basic_set * bset)12158 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
12159 {
12160 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
12161 }
12162
isl_basic_map_flatten_domain(__isl_take isl_basic_map * bmap)12163 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
12164 __isl_take isl_basic_map *bmap)
12165 {
12166 isl_space *space;
12167
12168 space = isl_basic_map_take_space(bmap);
12169 space = isl_space_flatten_domain(space);
12170 bmap = isl_basic_map_restore_space(bmap, space);
12171
12172 bmap = isl_basic_map_mark_final(bmap);
12173
12174 return bmap;
12175 }
12176
isl_basic_map_flatten_range(__isl_take isl_basic_map * bmap)12177 __isl_give isl_basic_map *isl_basic_map_flatten_range(
12178 __isl_take isl_basic_map *bmap)
12179 {
12180 isl_space *space;
12181
12182 space = isl_basic_map_take_space(bmap);
12183 space = isl_space_flatten_range(space);
12184 bmap = isl_basic_map_restore_space(bmap, space);
12185
12186 bmap = isl_basic_map_mark_final(bmap);
12187
12188 return bmap;
12189 }
12190
12191 /* Remove any internal structure from the spaces of domain and range of "map".
12192 */
isl_map_flatten(__isl_take isl_map * map)12193 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
12194 {
12195 if (!map)
12196 return NULL;
12197
12198 if (!map->dim->nested[0] && !map->dim->nested[1])
12199 return map;
12200
12201 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
12202 }
12203
isl_set_flatten(__isl_take isl_set * set)12204 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
12205 {
12206 return set_from_map(isl_map_flatten(set_to_map(set)));
12207 }
12208
isl_set_flatten_map(__isl_take isl_set * set)12209 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
12210 {
12211 isl_space *space, *flat_space;
12212 isl_map *map;
12213
12214 space = isl_set_get_space(set);
12215 flat_space = isl_space_flatten(isl_space_copy(space));
12216 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
12217 flat_space));
12218 map = isl_map_intersect_domain(map, set);
12219
12220 return map;
12221 }
12222
12223 /* Remove any internal structure from the space of the domain of "map".
12224 */
isl_map_flatten_domain(__isl_take isl_map * map)12225 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
12226 {
12227 if (!map)
12228 return NULL;
12229
12230 if (!map->dim->nested[0])
12231 return map;
12232
12233 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
12234 }
12235
12236 /* Remove any internal structure from the space of the range of "map".
12237 */
isl_map_flatten_range(__isl_take isl_map * map)12238 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
12239 {
12240 if (!map)
12241 return NULL;
12242
12243 if (!map->dim->nested[1])
12244 return map;
12245
12246 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
12247 }
12248
12249 /* Reorder the dimensions of "bmap" according to the given dim_map
12250 * and set the dimension specification to "space" and
12251 * perform Gaussian elimination on the result.
12252 */
isl_basic_map_realign(__isl_take isl_basic_map * bmap,__isl_take isl_space * space,__isl_take struct isl_dim_map * dim_map)12253 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
12254 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
12255 {
12256 isl_basic_map *res;
12257 unsigned flags;
12258 isl_size n_div;
12259
12260 n_div = isl_basic_map_dim(bmap, isl_dim_div);
12261 if (n_div < 0 || !space || !dim_map)
12262 goto error;
12263
12264 flags = bmap->flags;
12265 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
12266 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
12267 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
12268 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
12269 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
12270 if (res)
12271 res->flags = flags;
12272 res = isl_basic_map_gauss(res, NULL);
12273 res = isl_basic_map_finalize(res);
12274 return res;
12275 error:
12276 isl_dim_map_free(dim_map);
12277 isl_basic_map_free(bmap);
12278 isl_space_free(space);
12279 return NULL;
12280 }
12281
12282 /* Reorder the dimensions of "map" according to given reordering.
12283 */
isl_map_realign(__isl_take isl_map * map,__isl_take isl_reordering * r)12284 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
12285 __isl_take isl_reordering *r)
12286 {
12287 int i;
12288 struct isl_dim_map *dim_map;
12289
12290 map = isl_map_cow(map);
12291 dim_map = isl_dim_map_from_reordering(r);
12292 if (!map || !r || !dim_map)
12293 goto error;
12294
12295 for (i = 0; i < map->n; ++i) {
12296 struct isl_dim_map *dim_map_i;
12297 isl_space *space;
12298
12299 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
12300
12301 space = isl_reordering_get_space(r);
12302 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
12303
12304 if (!map->p[i])
12305 goto error;
12306 }
12307
12308 map = isl_map_reset_space(map, isl_reordering_get_space(r));
12309 map = isl_map_unmark_normalized(map);
12310
12311 isl_reordering_free(r);
12312 isl_dim_map_free(dim_map);
12313 return map;
12314 error:
12315 isl_dim_map_free(dim_map);
12316 isl_map_free(map);
12317 isl_reordering_free(r);
12318 return NULL;
12319 }
12320
isl_set_realign(__isl_take isl_set * set,__isl_take isl_reordering * r)12321 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
12322 __isl_take isl_reordering *r)
12323 {
12324 return set_from_map(isl_map_realign(set_to_map(set), r));
12325 }
12326
isl_map_align_params(__isl_take isl_map * map,__isl_take isl_space * model)12327 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
12328 __isl_take isl_space *model)
12329 {
12330 isl_ctx *ctx;
12331 isl_bool aligned;
12332
12333 if (!map || !model)
12334 goto error;
12335
12336 ctx = isl_space_get_ctx(model);
12337 if (!isl_space_has_named_params(model))
12338 isl_die(ctx, isl_error_invalid,
12339 "model has unnamed parameters", goto error);
12340 if (isl_map_check_named_params(map) < 0)
12341 goto error;
12342 aligned = isl_map_space_has_equal_params(map, model);
12343 if (aligned < 0)
12344 goto error;
12345 if (!aligned) {
12346 isl_reordering *exp;
12347
12348 exp = isl_parameter_alignment_reordering(map->dim, model);
12349 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
12350 map = isl_map_realign(map, exp);
12351 }
12352
12353 isl_space_free(model);
12354 return map;
12355 error:
12356 isl_space_free(model);
12357 isl_map_free(map);
12358 return NULL;
12359 }
12360
isl_set_align_params(__isl_take isl_set * set,__isl_take isl_space * model)12361 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
12362 __isl_take isl_space *model)
12363 {
12364 return isl_map_align_params(set, model);
12365 }
12366
12367 /* Align the parameters of "bmap" to those of "model", introducing
12368 * additional parameters if needed.
12369 */
isl_basic_map_align_params(__isl_take isl_basic_map * bmap,__isl_take isl_space * model)12370 __isl_give isl_basic_map *isl_basic_map_align_params(
12371 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
12372 {
12373 isl_ctx *ctx;
12374 isl_bool equal_params;
12375
12376 if (!bmap || !model)
12377 goto error;
12378
12379 ctx = isl_space_get_ctx(model);
12380 if (!isl_space_has_named_params(model))
12381 isl_die(ctx, isl_error_invalid,
12382 "model has unnamed parameters", goto error);
12383 if (isl_basic_map_check_named_params(bmap) < 0)
12384 goto error;
12385 equal_params = isl_space_has_equal_params(bmap->dim, model);
12386 if (equal_params < 0)
12387 goto error;
12388 if (!equal_params) {
12389 isl_reordering *exp;
12390 struct isl_dim_map *dim_map;
12391
12392 exp = isl_parameter_alignment_reordering(bmap->dim, model);
12393 exp = isl_reordering_extend_space(exp,
12394 isl_basic_map_get_space(bmap));
12395 dim_map = isl_dim_map_from_reordering(exp);
12396 bmap = isl_basic_map_realign(bmap,
12397 isl_reordering_get_space(exp),
12398 isl_dim_map_extend(dim_map, bmap));
12399 isl_reordering_free(exp);
12400 isl_dim_map_free(dim_map);
12401 }
12402
12403 isl_space_free(model);
12404 return bmap;
12405 error:
12406 isl_space_free(model);
12407 isl_basic_map_free(bmap);
12408 return NULL;
12409 }
12410
12411 /* Do "bset" and "space" have the same parameters?
12412 */
isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set * bset,__isl_keep isl_space * space)12413 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
12414 __isl_keep isl_space *space)
12415 {
12416 isl_space *bset_space;
12417
12418 bset_space = isl_basic_set_peek_space(bset);
12419 return isl_space_has_equal_params(bset_space, space);
12420 }
12421
12422 /* Do "map" and "space" have the same parameters?
12423 */
isl_map_space_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_space * space)12424 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
12425 __isl_keep isl_space *space)
12426 {
12427 isl_space *map_space;
12428
12429 map_space = isl_map_peek_space(map);
12430 return isl_space_has_equal_params(map_space, space);
12431 }
12432
12433 /* Do "set" and "space" have the same parameters?
12434 */
isl_set_space_has_equal_params(__isl_keep isl_set * set,__isl_keep isl_space * space)12435 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
12436 __isl_keep isl_space *space)
12437 {
12438 return isl_map_space_has_equal_params(set_to_map(set), space);
12439 }
12440
12441 /* Align the parameters of "bset" to those of "model", introducing
12442 * additional parameters if needed.
12443 */
isl_basic_set_align_params(__isl_take isl_basic_set * bset,__isl_take isl_space * model)12444 __isl_give isl_basic_set *isl_basic_set_align_params(
12445 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
12446 {
12447 return isl_basic_map_align_params(bset, model);
12448 }
12449
12450 /* Drop all parameters not referenced by "map".
12451 */
isl_map_drop_unused_params(__isl_take isl_map * map)12452 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
12453 {
12454 int i;
12455 isl_size n;
12456
12457 n = isl_map_dim(map, isl_dim_param);
12458 if (isl_map_check_named_params(map) < 0 || n < 0)
12459 return isl_map_free(map);
12460
12461 for (i = n - 1; i >= 0; i--) {
12462 isl_bool involves;
12463
12464 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
12465 if (involves < 0)
12466 return isl_map_free(map);
12467 if (!involves)
12468 map = isl_map_project_out(map, isl_dim_param, i, 1);
12469 }
12470
12471 return map;
12472 }
12473
12474 /* Drop all parameters not referenced by "set".
12475 */
isl_set_drop_unused_params(__isl_take isl_set * set)12476 __isl_give isl_set *isl_set_drop_unused_params(
12477 __isl_take isl_set *set)
12478 {
12479 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
12480 }
12481
12482 /* Drop all parameters not referenced by "bmap".
12483 */
isl_basic_map_drop_unused_params(__isl_take isl_basic_map * bmap)12484 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
12485 __isl_take isl_basic_map *bmap)
12486 {
12487 isl_size nparam;
12488 int i;
12489
12490 nparam = isl_basic_map_dim(bmap, isl_dim_param);
12491 if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)
12492 return isl_basic_map_free(bmap);
12493
12494 for (i = nparam - 1; i >= 0; i--) {
12495 isl_bool involves;
12496
12497 involves = isl_basic_map_involves_dims(bmap,
12498 isl_dim_param, i, 1);
12499 if (involves < 0)
12500 return isl_basic_map_free(bmap);
12501 if (!involves)
12502 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
12503 }
12504
12505 return bmap;
12506 }
12507
12508 /* Drop all parameters not referenced by "bset".
12509 */
isl_basic_set_drop_unused_params(__isl_take isl_basic_set * bset)12510 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
12511 __isl_take isl_basic_set *bset)
12512 {
12513 return bset_from_bmap(isl_basic_map_drop_unused_params(
12514 bset_to_bmap(bset)));
12515 }
12516
12517 /* Given a tuple of identifiers "tuple" in a space that corresponds
12518 * to that of "set", if any of those identifiers appear as parameters
12519 * in "set", then equate those parameters with the corresponding
12520 * set dimensions and project out the parameters.
12521 * The result therefore has no such parameters.
12522 */
equate_params(__isl_take isl_set * set,__isl_keep isl_multi_id * tuple)12523 static __isl_give isl_set *equate_params(__isl_take isl_set *set,
12524 __isl_keep isl_multi_id *tuple)
12525 {
12526 int i;
12527 isl_size n;
12528 isl_space *set_space, *tuple_space;
12529
12530 set_space = isl_set_peek_space(set);
12531 tuple_space = isl_multi_id_peek_space(tuple);
12532 if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
12533 return isl_set_free(set);
12534 n = isl_multi_id_size(tuple);
12535 if (n < 0)
12536 return isl_set_free(set);
12537 for (i = 0; i < n; ++i) {
12538 isl_id *id;
12539 int pos;
12540
12541 id = isl_multi_id_get_at(tuple, i);
12542 if (!id)
12543 return isl_set_free(set);
12544 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
12545 isl_id_free(id);
12546 if (pos < 0)
12547 continue;
12548 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
12549 set = isl_set_project_out(set, isl_dim_param, pos, 1);
12550 }
12551 return set;
12552 }
12553
12554 /* Bind the set dimensions of "set" to parameters with identifiers
12555 * specified by "tuple", living in the same space as "set".
12556 *
12557 * If no parameters with these identifiers appear in "set" already,
12558 * then the set dimensions are simply reinterpreted as parameters.
12559 * Otherwise, the parameters are first equated to the corresponding
12560 * set dimensions.
12561 */
isl_set_bind(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12562 __isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
12563 __isl_take isl_multi_id *tuple)
12564 {
12565 isl_space *space;
12566
12567 set = equate_params(set, tuple);
12568 space = isl_set_get_space(set);
12569 space = isl_space_bind_set(space, tuple);
12570 isl_multi_id_free(tuple);
12571 set = isl_set_reset_space(set, space);
12572
12573 return set;
12574 }
12575
12576 /* Given a tuple of identifiers "tuple" in a space that corresponds
12577 * to the domain of "map", if any of those identifiers appear as parameters
12578 * in "map", then equate those parameters with the corresponding
12579 * input dimensions and project out the parameters.
12580 * The result therefore has no such parameters.
12581 */
map_equate_params(__isl_take isl_map * map,__isl_keep isl_multi_id * tuple)12582 static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
12583 __isl_keep isl_multi_id *tuple)
12584 {
12585 int i;
12586 isl_size n;
12587 isl_space *map_space, *tuple_space;
12588
12589 map_space = isl_map_peek_space(map);
12590 tuple_space = isl_multi_id_peek_space(tuple);
12591 if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
12592 return isl_map_free(map);
12593 n = isl_multi_id_size(tuple);
12594 if (n < 0)
12595 return isl_map_free(map);
12596 for (i = 0; i < n; ++i) {
12597 isl_id *id;
12598 int pos;
12599
12600 id = isl_multi_id_get_at(tuple, i);
12601 if (!id)
12602 return isl_map_free(map);
12603 pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
12604 isl_id_free(id);
12605 if (pos < 0)
12606 continue;
12607 map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
12608 map = isl_map_project_out(map, isl_dim_param, pos, 1);
12609 }
12610 return map;
12611 }
12612
12613 /* Bind the input dimensions of "map" to parameters with identifiers
12614 * specified by "tuple", living in the domain space of "map".
12615 *
12616 * If no parameters with these identifiers appear in "map" already,
12617 * then the input dimensions are simply reinterpreted as parameters.
12618 * Otherwise, the parameters are first equated to the corresponding
12619 * input dimensions.
12620 */
isl_map_bind_domain(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12621 __isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
12622 __isl_take isl_multi_id *tuple)
12623 {
12624 isl_space *space;
12625 isl_set *set;
12626
12627 map = map_equate_params(map, tuple);
12628 space = isl_map_get_space(map);
12629 space = isl_space_bind_map_domain(space, tuple);
12630 isl_multi_id_free(tuple);
12631 set = set_from_map(isl_map_reset_space(map, space));
12632
12633 return set;
12634 }
12635
12636 /* Bind the output dimensions of "map" to parameters with identifiers
12637 * specified by "tuple", living in the range space of "map".
12638 *
12639 * Since binding is more easily implemented on the domain,
12640 * bind the input dimensions of the inverse of "map".
12641 */
isl_map_bind_range(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12642 __isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
12643 __isl_take isl_multi_id *tuple)
12644 {
12645 return isl_map_bind_domain(isl_map_reverse(map), tuple);
12646 }
12647
12648 /* Insert a domain corresponding to "tuple"
12649 * into the nullary or unary relation "set".
12650 * The result has an extra initial tuple and is therefore
12651 * either a unary or binary relation.
12652 * Any parameters with identifiers in "tuple" are reinterpreted
12653 * as the corresponding domain dimensions.
12654 */
unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12655 static __isl_give isl_map *unbind_params_insert_domain(
12656 __isl_take isl_set *set, __isl_take isl_multi_id *tuple)
12657 {
12658 isl_space *space;
12659 isl_reordering *r;
12660
12661 space = isl_set_peek_space(set);
12662 r = isl_reordering_unbind_params_insert_domain(space, tuple);
12663 isl_multi_id_free(tuple);
12664
12665 return isl_map_realign(set_to_map(set), r);
12666 }
12667
12668 /* Construct a set with "tuple" as domain from the parameter domain "set".
12669 * Any parameters with identifiers in "tuple" are reinterpreted
12670 * as the corresponding set dimensions.
12671 */
isl_set_unbind_params(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12672 __isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
12673 __isl_take isl_multi_id *tuple)
12674 {
12675 isl_bool is_params;
12676
12677 is_params = isl_set_is_params(set);
12678 if (is_params < 0)
12679 set = isl_set_free(set);
12680 else if (!is_params)
12681 isl_die(isl_set_get_ctx(set), isl_error_invalid,
12682 "expecting parameter domain", set = isl_set_free(set));
12683 return set_from_map(unbind_params_insert_domain(set, tuple));
12684 }
12685
12686 /* Check that "set" is a proper set, i.e., that it is not a parameter domain.
12687 */
isl_set_check_is_set(__isl_keep isl_set * set)12688 static isl_stat isl_set_check_is_set(__isl_keep isl_set *set)
12689 {
12690 isl_bool is_params;
12691
12692 is_params = isl_set_is_params(set);
12693 if (is_params < 0)
12694 return isl_stat_error;
12695 else if (is_params)
12696 isl_die(isl_set_get_ctx(set), isl_error_invalid,
12697 "expecting proper set", return isl_stat_error);
12698
12699 return isl_stat_ok;
12700 }
12701
12702 /* Construct a map with "domain" as domain and "set" as range.
12703 * Any parameters with identifiers in "domain" are reinterpreted
12704 * as the corresponding domain dimensions.
12705 */
isl_set_unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * domain)12706 __isl_give isl_map *isl_set_unbind_params_insert_domain(
12707 __isl_take isl_set *set, __isl_take isl_multi_id *domain)
12708 {
12709 if (isl_set_check_is_set(set) < 0)
12710 set = isl_set_free(set);
12711 return unbind_params_insert_domain(set, domain);
12712 }
12713
12714 /* Construct a map with "domain" as domain and "set" as range.
12715 */
isl_set_insert_domain(__isl_take isl_set * set,__isl_take isl_space * domain)12716 __isl_give isl_map *isl_set_insert_domain(__isl_take isl_set *set,
12717 __isl_take isl_space *domain)
12718 {
12719 isl_size dim;
12720 isl_space *space;
12721 isl_map *map;
12722
12723 if (isl_set_check_is_set(set) < 0 || isl_space_check_is_set(domain) < 0)
12724 domain = isl_space_free(domain);
12725 dim = isl_space_dim(domain, isl_dim_set);
12726 if (dim < 0)
12727 domain = isl_space_free(domain);
12728 space = isl_set_get_space(set);
12729 domain = isl_space_replace_params(domain, space);
12730 space = isl_space_map_from_domain_and_range(domain, space);
12731
12732 map = isl_map_from_range(set);
12733 map = isl_map_add_dims(map, isl_dim_in, dim);
12734 map = isl_map_reset_space(map, space);
12735
12736 return map;
12737 }
12738
isl_basic_map_equalities_matrix(__isl_keep isl_basic_map * bmap,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4,enum isl_dim_type c5)12739 __isl_give isl_mat *isl_basic_map_equalities_matrix(
12740 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12741 enum isl_dim_type c2, enum isl_dim_type c3,
12742 enum isl_dim_type c4, enum isl_dim_type c5)
12743 {
12744 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12745 struct isl_mat *mat;
12746 int i, j, k;
12747 int pos;
12748 isl_size total;
12749
12750 total = isl_basic_map_dim(bmap, isl_dim_all);
12751 if (total < 0)
12752 return NULL;
12753 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
12754 if (!mat)
12755 return NULL;
12756 for (i = 0; i < bmap->n_eq; ++i)
12757 for (j = 0, pos = 0; j < 5; ++j) {
12758 int off = isl_basic_map_offset(bmap, c[j]);
12759 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12760 if (dim < 0)
12761 return isl_mat_free(mat);
12762 for (k = 0; k < dim; ++k) {
12763 isl_int_set(mat->row[i][pos],
12764 bmap->eq[i][off + k]);
12765 ++pos;
12766 }
12767 }
12768
12769 return mat;
12770 }
12771
isl_basic_map_inequalities_matrix(__isl_keep isl_basic_map * bmap,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4,enum isl_dim_type c5)12772 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
12773 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12774 enum isl_dim_type c2, enum isl_dim_type c3,
12775 enum isl_dim_type c4, enum isl_dim_type c5)
12776 {
12777 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12778 struct isl_mat *mat;
12779 int i, j, k;
12780 int pos;
12781 isl_size total;
12782
12783 total = isl_basic_map_dim(bmap, isl_dim_all);
12784 if (total < 0)
12785 return NULL;
12786 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
12787 if (!mat)
12788 return NULL;
12789 for (i = 0; i < bmap->n_ineq; ++i)
12790 for (j = 0, pos = 0; j < 5; ++j) {
12791 int off = isl_basic_map_offset(bmap, c[j]);
12792 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12793 if (dim < 0)
12794 return isl_mat_free(mat);
12795 for (k = 0; k < dim; ++k) {
12796 isl_int_set(mat->row[i][pos],
12797 bmap->ineq[i][off + k]);
12798 ++pos;
12799 }
12800 }
12801
12802 return mat;
12803 }
12804
isl_basic_map_from_constraint_matrices(__isl_take isl_space * space,__isl_take isl_mat * eq,__isl_take isl_mat * ineq,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4,enum isl_dim_type c5)12805 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
12806 __isl_take isl_space *space,
12807 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12808 enum isl_dim_type c2, enum isl_dim_type c3,
12809 enum isl_dim_type c4, enum isl_dim_type c5)
12810 {
12811 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12812 isl_basic_map *bmap = NULL;
12813 isl_size dim;
12814 unsigned total;
12815 unsigned extra;
12816 int i, j, k, l;
12817 int pos;
12818
12819 dim = isl_space_dim(space, isl_dim_all);
12820 if (dim < 0 || !eq || !ineq)
12821 goto error;
12822
12823 if (eq->n_col != ineq->n_col)
12824 isl_die(space->ctx, isl_error_invalid,
12825 "equalities and inequalities matrices should have "
12826 "same number of columns", goto error);
12827
12828 total = 1 + dim;
12829
12830 if (eq->n_col < total)
12831 isl_die(space->ctx, isl_error_invalid,
12832 "number of columns too small", goto error);
12833
12834 extra = eq->n_col - total;
12835
12836 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
12837 eq->n_row, ineq->n_row);
12838 if (!bmap)
12839 goto error;
12840 for (i = 0; i < extra; ++i) {
12841 k = isl_basic_map_alloc_div(bmap);
12842 if (k < 0)
12843 goto error;
12844 isl_int_set_si(bmap->div[k][0], 0);
12845 }
12846 for (i = 0; i < eq->n_row; ++i) {
12847 l = isl_basic_map_alloc_equality(bmap);
12848 if (l < 0)
12849 goto error;
12850 for (j = 0, pos = 0; j < 5; ++j) {
12851 int off = isl_basic_map_offset(bmap, c[j]);
12852 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12853 if (dim < 0)
12854 goto error;
12855 for (k = 0; k < dim; ++k) {
12856 isl_int_set(bmap->eq[l][off + k],
12857 eq->row[i][pos]);
12858 ++pos;
12859 }
12860 }
12861 }
12862 for (i = 0; i < ineq->n_row; ++i) {
12863 l = isl_basic_map_alloc_inequality(bmap);
12864 if (l < 0)
12865 goto error;
12866 for (j = 0, pos = 0; j < 5; ++j) {
12867 int off = isl_basic_map_offset(bmap, c[j]);
12868 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12869 if (dim < 0)
12870 goto error;
12871 for (k = 0; k < dim; ++k) {
12872 isl_int_set(bmap->ineq[l][off + k],
12873 ineq->row[i][pos]);
12874 ++pos;
12875 }
12876 }
12877 }
12878
12879 isl_space_free(space);
12880 isl_mat_free(eq);
12881 isl_mat_free(ineq);
12882
12883 bmap = isl_basic_map_simplify(bmap);
12884 return isl_basic_map_finalize(bmap);
12885 error:
12886 isl_space_free(space);
12887 isl_mat_free(eq);
12888 isl_mat_free(ineq);
12889 isl_basic_map_free(bmap);
12890 return NULL;
12891 }
12892
isl_basic_set_equalities_matrix(__isl_keep isl_basic_set * bset,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4)12893 __isl_give isl_mat *isl_basic_set_equalities_matrix(
12894 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12895 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12896 {
12897 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12898 c1, c2, c3, c4, isl_dim_in);
12899 }
12900
isl_basic_set_inequalities_matrix(__isl_keep isl_basic_set * bset,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4)12901 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12902 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12903 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12904 {
12905 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12906 c1, c2, c3, c4, isl_dim_in);
12907 }
12908
isl_basic_set_from_constraint_matrices(__isl_take isl_space * space,__isl_take isl_mat * eq,__isl_take isl_mat * ineq,enum isl_dim_type c1,enum isl_dim_type c2,enum isl_dim_type c3,enum isl_dim_type c4)12909 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12910 __isl_take isl_space *space,
12911 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12912 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12913 {
12914 isl_basic_map *bmap;
12915 bmap = isl_basic_map_from_constraint_matrices(space, eq, ineq,
12916 c1, c2, c3, c4, isl_dim_in);
12917 return bset_from_bmap(bmap);
12918 }
12919
isl_basic_map_can_zip(__isl_keep isl_basic_map * bmap)12920 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12921 {
12922 if (!bmap)
12923 return isl_bool_error;
12924
12925 return isl_space_can_zip(bmap->dim);
12926 }
12927
isl_map_can_zip(__isl_keep isl_map * map)12928 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12929 {
12930 if (!map)
12931 return isl_bool_error;
12932
12933 return isl_space_can_zip(map->dim);
12934 }
12935
12936 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12937 * (A -> C) -> (B -> D).
12938 */
isl_basic_map_zip(__isl_take isl_basic_map * bmap)12939 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12940 {
12941 unsigned pos;
12942 isl_size n_in;
12943 isl_size n1;
12944 isl_size n2;
12945
12946 if (!bmap)
12947 return NULL;
12948
12949 if (!isl_basic_map_can_zip(bmap))
12950 isl_die(bmap->ctx, isl_error_invalid,
12951 "basic map cannot be zipped", goto error);
12952 n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12953 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12954 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12955 if (n_in < 0 || n1 < 0 || n2 < 0)
12956 return isl_basic_map_free(bmap);
12957 pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
12958 bmap = isl_basic_map_cow(bmap);
12959 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12960 if (!bmap)
12961 return NULL;
12962 bmap->dim = isl_space_zip(bmap->dim);
12963 if (!bmap->dim)
12964 goto error;
12965 bmap = isl_basic_map_mark_final(bmap);
12966 return bmap;
12967 error:
12968 isl_basic_map_free(bmap);
12969 return NULL;
12970 }
12971
12972 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12973 * (A -> C) -> (B -> D).
12974 */
isl_map_zip(__isl_take isl_map * map)12975 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12976 {
12977 if (!map)
12978 return NULL;
12979
12980 if (!isl_map_can_zip(map))
12981 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12982 goto error);
12983
12984 return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);
12985 error:
12986 isl_map_free(map);
12987 return NULL;
12988 }
12989
12990 /* Can we apply isl_basic_map_curry to "bmap"?
12991 * That is, does it have a nested relation in its domain?
12992 */
isl_basic_map_can_curry(__isl_keep isl_basic_map * bmap)12993 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12994 {
12995 if (!bmap)
12996 return isl_bool_error;
12997
12998 return isl_space_can_curry(bmap->dim);
12999 }
13000
13001 /* Can we apply isl_map_curry to "map"?
13002 * That is, does it have a nested relation in its domain?
13003 */
isl_map_can_curry(__isl_keep isl_map * map)13004 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
13005 {
13006 if (!map)
13007 return isl_bool_error;
13008
13009 return isl_space_can_curry(map->dim);
13010 }
13011
13012 /* Given a basic map (A -> B) -> C, return the corresponding basic map
13013 * A -> (B -> C).
13014 */
isl_basic_map_curry(__isl_take isl_basic_map * bmap)13015 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
13016 {
13017
13018 if (!bmap)
13019 return NULL;
13020
13021 if (!isl_basic_map_can_curry(bmap))
13022 isl_die(bmap->ctx, isl_error_invalid,
13023 "basic map cannot be curried", goto error);
13024 bmap = isl_basic_map_cow(bmap);
13025 if (!bmap)
13026 return NULL;
13027 bmap->dim = isl_space_curry(bmap->dim);
13028 if (!bmap->dim)
13029 goto error;
13030 bmap = isl_basic_map_mark_final(bmap);
13031 return bmap;
13032 error:
13033 isl_basic_map_free(bmap);
13034 return NULL;
13035 }
13036
13037 /* Given a map (A -> B) -> C, return the corresponding map
13038 * A -> (B -> C).
13039 */
isl_map_curry(__isl_take isl_map * map)13040 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
13041 {
13042 return isl_map_change_space(map, &isl_map_can_curry,
13043 "map cannot be curried", &isl_space_curry);
13044 }
13045
13046 /* Can isl_map_range_curry be applied to "map"?
13047 * That is, does it have a nested relation in its range,
13048 * the domain of which is itself a nested relation?
13049 */
isl_map_can_range_curry(__isl_keep isl_map * map)13050 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
13051 {
13052 if (!map)
13053 return isl_bool_error;
13054
13055 return isl_space_can_range_curry(map->dim);
13056 }
13057
13058 /* Given a map A -> ((B -> C) -> D), return the corresponding map
13059 * A -> (B -> (C -> D)).
13060 */
isl_map_range_curry(__isl_take isl_map * map)13061 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
13062 {
13063 return isl_map_change_space(map, &isl_map_can_range_curry,
13064 "map range cannot be curried",
13065 &isl_space_range_curry);
13066 }
13067
13068 /* Can we apply isl_basic_map_uncurry to "bmap"?
13069 * That is, does it have a nested relation in its domain?
13070 */
isl_basic_map_can_uncurry(__isl_keep isl_basic_map * bmap)13071 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
13072 {
13073 if (!bmap)
13074 return isl_bool_error;
13075
13076 return isl_space_can_uncurry(bmap->dim);
13077 }
13078
13079 /* Can we apply isl_map_uncurry to "map"?
13080 * That is, does it have a nested relation in its domain?
13081 */
isl_map_can_uncurry(__isl_keep isl_map * map)13082 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
13083 {
13084 if (!map)
13085 return isl_bool_error;
13086
13087 return isl_space_can_uncurry(map->dim);
13088 }
13089
13090 /* Given a basic map A -> (B -> C), return the corresponding basic map
13091 * (A -> B) -> C.
13092 */
isl_basic_map_uncurry(__isl_take isl_basic_map * bmap)13093 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
13094 {
13095
13096 if (!bmap)
13097 return NULL;
13098
13099 if (!isl_basic_map_can_uncurry(bmap))
13100 isl_die(bmap->ctx, isl_error_invalid,
13101 "basic map cannot be uncurried",
13102 return isl_basic_map_free(bmap));
13103 bmap = isl_basic_map_cow(bmap);
13104 if (!bmap)
13105 return NULL;
13106 bmap->dim = isl_space_uncurry(bmap->dim);
13107 if (!bmap->dim)
13108 return isl_basic_map_free(bmap);
13109 bmap = isl_basic_map_mark_final(bmap);
13110 return bmap;
13111 }
13112
13113 /* Given a map A -> (B -> C), return the corresponding map
13114 * (A -> B) -> C.
13115 */
isl_map_uncurry(__isl_take isl_map * map)13116 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
13117 {
13118 return isl_map_change_space(map, &isl_map_can_uncurry,
13119 "map cannot be uncurried", &isl_space_uncurry);
13120 }
13121
isl_set_equate(__isl_take isl_set * set,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13122 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
13123 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13124 {
13125 return isl_map_equate(set, type1, pos1, type2, pos2);
13126 }
13127
13128 /* Construct a basic map where the given dimensions are equal to each other.
13129 */
equator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13130 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
13131 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13132 {
13133 isl_basic_map *bmap = NULL;
13134 int i;
13135 isl_size total;
13136
13137 total = isl_space_dim(space, isl_dim_all);
13138 if (total < 0 ||
13139 isl_space_check_range(space, type1, pos1, 1) < 0 ||
13140 isl_space_check_range(space, type2, pos2, 1) < 0)
13141 goto error;
13142
13143 if (type1 == type2 && pos1 == pos2)
13144 return isl_basic_map_universe(space);
13145
13146 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
13147 i = isl_basic_map_alloc_equality(bmap);
13148 if (i < 0)
13149 goto error;
13150 isl_seq_clr(bmap->eq[i], 1 + total);
13151 pos1 += isl_basic_map_offset(bmap, type1);
13152 pos2 += isl_basic_map_offset(bmap, type2);
13153 isl_int_set_si(bmap->eq[i][pos1], -1);
13154 isl_int_set_si(bmap->eq[i][pos2], 1);
13155 bmap = isl_basic_map_finalize(bmap);
13156 isl_space_free(space);
13157 return bmap;
13158 error:
13159 isl_space_free(space);
13160 isl_basic_map_free(bmap);
13161 return NULL;
13162 }
13163
13164 /* Add a constraint imposing that the given two dimensions are equal.
13165 */
isl_basic_map_equate(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13166 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
13167 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13168 {
13169 isl_basic_map *eq;
13170
13171 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13172
13173 bmap = isl_basic_map_intersect(bmap, eq);
13174
13175 return bmap;
13176 }
13177
13178 /* Add a constraint imposing that the given two dimensions are equal.
13179 */
isl_map_equate(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13180 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
13181 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13182 {
13183 isl_basic_map *bmap;
13184
13185 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
13186
13187 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13188
13189 return map;
13190 }
13191
13192 /* Add a constraint imposing that the given two dimensions have opposite values.
13193 */
isl_map_oppose(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13194 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
13195 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13196 {
13197 isl_basic_map *bmap = NULL;
13198 int i;
13199 isl_size total;
13200
13201 if (isl_map_check_range(map, type1, pos1, 1) < 0)
13202 return isl_map_free(map);
13203 if (isl_map_check_range(map, type2, pos2, 1) < 0)
13204 return isl_map_free(map);
13205
13206 total = isl_map_dim(map, isl_dim_all);
13207 if (total < 0)
13208 return isl_map_free(map);
13209 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
13210 i = isl_basic_map_alloc_equality(bmap);
13211 if (i < 0)
13212 goto error;
13213 isl_seq_clr(bmap->eq[i], 1 + total);
13214 pos1 += isl_basic_map_offset(bmap, type1);
13215 pos2 += isl_basic_map_offset(bmap, type2);
13216 isl_int_set_si(bmap->eq[i][pos1], 1);
13217 isl_int_set_si(bmap->eq[i][pos2], 1);
13218 bmap = isl_basic_map_finalize(bmap);
13219
13220 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13221
13222 return map;
13223 error:
13224 isl_basic_map_free(bmap);
13225 isl_map_free(map);
13226 return NULL;
13227 }
13228
13229 /* Construct a constraint imposing that the value of the first dimension is
13230 * greater than or equal to that of the second.
13231 */
constraint_order_ge(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13232 static __isl_give isl_constraint *constraint_order_ge(
13233 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
13234 enum isl_dim_type type2, int pos2)
13235 {
13236 isl_constraint *c;
13237
13238 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13239 isl_space_check_range(space, type2, pos2, 1) < 0)
13240 space = isl_space_free(space);
13241 if (!space)
13242 return NULL;
13243
13244 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
13245
13246 if (type1 == type2 && pos1 == pos2)
13247 return c;
13248
13249 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
13250 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
13251
13252 return c;
13253 }
13254
13255 /* Add a constraint imposing that the value of the first dimension is
13256 * greater than or equal to that of the second.
13257 */
isl_basic_map_order_ge(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13258 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
13259 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13260 {
13261 isl_constraint *c;
13262 isl_space *space;
13263
13264 if (type1 == type2 && pos1 == pos2)
13265 return bmap;
13266 space = isl_basic_map_get_space(bmap);
13267 c = constraint_order_ge(space, type1, pos1, type2, pos2);
13268 bmap = isl_basic_map_add_constraint(bmap, c);
13269
13270 return bmap;
13271 }
13272
13273 /* Add a constraint imposing that the value of the first dimension is
13274 * greater than or equal to that of the second.
13275 */
isl_map_order_ge(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13276 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
13277 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13278 {
13279 isl_constraint *c;
13280 isl_space *space;
13281
13282 if (type1 == type2 && pos1 == pos2)
13283 return map;
13284 space = isl_map_get_space(map);
13285 c = constraint_order_ge(space, type1, pos1, type2, pos2);
13286 map = isl_map_add_constraint(map, c);
13287
13288 return map;
13289 }
13290
13291 /* Add a constraint imposing that the value of the first dimension is
13292 * less than or equal to that of the second.
13293 */
isl_map_order_le(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13294 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
13295 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13296 {
13297 return isl_map_order_ge(map, type2, pos2, type1, pos1);
13298 }
13299
13300 /* Construct a basic map where the value of the first dimension is
13301 * greater than that of the second.
13302 */
greator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13303 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
13304 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13305 {
13306 isl_basic_map *bmap = NULL;
13307 int i;
13308 isl_size total;
13309
13310 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13311 isl_space_check_range(space, type2, pos2, 1) < 0)
13312 goto error;
13313
13314 if (type1 == type2 && pos1 == pos2)
13315 return isl_basic_map_empty(space);
13316
13317 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
13318 total = isl_basic_map_dim(bmap, isl_dim_all);
13319 i = isl_basic_map_alloc_inequality(bmap);
13320 if (total < 0 || i < 0)
13321 return isl_basic_map_free(bmap);
13322 isl_seq_clr(bmap->ineq[i], 1 + total);
13323 pos1 += isl_basic_map_offset(bmap, type1);
13324 pos2 += isl_basic_map_offset(bmap, type2);
13325 isl_int_set_si(bmap->ineq[i][pos1], 1);
13326 isl_int_set_si(bmap->ineq[i][pos2], -1);
13327 isl_int_set_si(bmap->ineq[i][0], -1);
13328 bmap = isl_basic_map_finalize(bmap);
13329
13330 return bmap;
13331 error:
13332 isl_space_free(space);
13333 isl_basic_map_free(bmap);
13334 return NULL;
13335 }
13336
13337 /* Add a constraint imposing that the value of the first dimension is
13338 * greater than that of the second.
13339 */
isl_basic_map_order_gt(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13340 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
13341 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13342 {
13343 isl_basic_map *gt;
13344
13345 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13346
13347 bmap = isl_basic_map_intersect(bmap, gt);
13348
13349 return bmap;
13350 }
13351
13352 /* Add a constraint imposing that the value of the first dimension is
13353 * greater than that of the second.
13354 */
isl_map_order_gt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13355 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
13356 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13357 {
13358 isl_basic_map *bmap;
13359
13360 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
13361
13362 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13363
13364 return map;
13365 }
13366
13367 /* Add a constraint imposing that the value of the first dimension is
13368 * smaller than that of the second.
13369 */
isl_map_order_lt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13370 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
13371 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13372 {
13373 return isl_map_order_gt(map, type2, pos2, type1, pos1);
13374 }
13375
isl_basic_map_get_div(__isl_keep isl_basic_map * bmap,int pos)13376 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
13377 int pos)
13378 {
13379 isl_aff *div;
13380 isl_local_space *ls;
13381
13382 if (!bmap)
13383 return NULL;
13384
13385 if (!isl_basic_map_divs_known(bmap))
13386 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13387 "some divs are unknown", return NULL);
13388
13389 ls = isl_basic_map_get_local_space(bmap);
13390 div = isl_local_space_get_div(ls, pos);
13391 isl_local_space_free(ls);
13392
13393 return div;
13394 }
13395
isl_basic_set_get_div(__isl_keep isl_basic_set * bset,int pos)13396 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
13397 int pos)
13398 {
13399 return isl_basic_map_get_div(bset, pos);
13400 }
13401
13402 /* Plug in "subs" for dimension "type", "pos" of "bset".
13403 *
13404 * Let i be the dimension to replace and let "subs" be of the form
13405 *
13406 * f/d
13407 *
13408 * Any integer division with a non-zero coefficient for i,
13409 *
13410 * floor((a i + g)/m)
13411 *
13412 * is replaced by
13413 *
13414 * floor((a f + d g)/(m d))
13415 *
13416 * Constraints of the form
13417 *
13418 * a i + g
13419 *
13420 * are replaced by
13421 *
13422 * a f + d g
13423 *
13424 * We currently require that "subs" is an integral expression.
13425 * Handling rational expressions may require us to add stride constraints
13426 * as we do in isl_basic_set_preimage_multi_aff.
13427 */
isl_basic_set_substitute(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)13428 __isl_give isl_basic_set *isl_basic_set_substitute(
13429 __isl_take isl_basic_set *bset,
13430 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13431 {
13432 int i;
13433 isl_int v;
13434 isl_ctx *ctx;
13435 isl_size n_div;
13436
13437 if (bset && isl_basic_set_plain_is_empty(bset))
13438 return bset;
13439
13440 bset = isl_basic_set_cow(bset);
13441 if (!bset || !subs)
13442 goto error;
13443
13444 ctx = isl_basic_set_get_ctx(bset);
13445 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
13446 isl_die(ctx, isl_error_invalid,
13447 "spaces don't match", goto error);
13448 n_div = isl_local_space_dim(subs->ls, isl_dim_div);
13449 if (n_div < 0)
13450 goto error;
13451 if (n_div != 0)
13452 isl_die(ctx, isl_error_unsupported,
13453 "cannot handle divs yet", goto error);
13454 if (!isl_int_is_one(subs->v->el[0]))
13455 isl_die(ctx, isl_error_invalid,
13456 "can only substitute integer expressions", goto error);
13457
13458 pos += isl_basic_set_offset(bset, type);
13459
13460 isl_int_init(v);
13461
13462 for (i = 0; i < bset->n_eq; ++i) {
13463 if (isl_int_is_zero(bset->eq[i][pos]))
13464 continue;
13465 isl_int_set(v, bset->eq[i][pos]);
13466 isl_int_set_si(bset->eq[i][pos], 0);
13467 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
13468 v, subs->v->el + 1, subs->v->size - 1);
13469 }
13470
13471 for (i = 0; i < bset->n_ineq; ++i) {
13472 if (isl_int_is_zero(bset->ineq[i][pos]))
13473 continue;
13474 isl_int_set(v, bset->ineq[i][pos]);
13475 isl_int_set_si(bset->ineq[i][pos], 0);
13476 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
13477 v, subs->v->el + 1, subs->v->size - 1);
13478 }
13479
13480 for (i = 0; i < bset->n_div; ++i) {
13481 if (isl_int_is_zero(bset->div[i][1 + pos]))
13482 continue;
13483 isl_int_set(v, bset->div[i][1 + pos]);
13484 isl_int_set_si(bset->div[i][1 + pos], 0);
13485 isl_seq_combine(bset->div[i] + 1,
13486 subs->v->el[0], bset->div[i] + 1,
13487 v, subs->v->el + 1, subs->v->size - 1);
13488 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
13489 }
13490
13491 isl_int_clear(v);
13492
13493 bset = isl_basic_set_simplify(bset);
13494 return isl_basic_set_finalize(bset);
13495 error:
13496 isl_basic_set_free(bset);
13497 return NULL;
13498 }
13499
13500 /* Plug in "subs" for dimension "type", "pos" of "set".
13501 */
isl_set_substitute(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)13502 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
13503 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13504 {
13505 int i;
13506
13507 if (set && isl_set_plain_is_empty(set))
13508 return set;
13509
13510 set = isl_set_cow(set);
13511 if (!set || !subs)
13512 goto error;
13513
13514 for (i = set->n - 1; i >= 0; --i) {
13515 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
13516 set = set_from_map(remove_if_empty(set_to_map(set), i));
13517 if (!set)
13518 return NULL;
13519 }
13520
13521 return set;
13522 error:
13523 isl_set_free(set);
13524 return NULL;
13525 }
13526
13527 /* Check if the range of "ma" is compatible with the domain or range
13528 * (depending on "type") of "bmap".
13529 */
check_basic_map_compatible_range_multi_aff(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13530 static isl_stat check_basic_map_compatible_range_multi_aff(
13531 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
13532 __isl_keep isl_multi_aff *ma)
13533 {
13534 isl_bool m;
13535 isl_space *ma_space;
13536
13537 ma_space = isl_multi_aff_get_space(ma);
13538
13539 m = isl_space_has_equal_params(bmap->dim, ma_space);
13540 if (m < 0)
13541 goto error;
13542 if (!m)
13543 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13544 "parameters don't match", goto error);
13545 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
13546 if (m < 0)
13547 goto error;
13548 if (!m)
13549 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13550 "spaces don't match", goto error);
13551
13552 isl_space_free(ma_space);
13553 return isl_stat_ok;
13554 error:
13555 isl_space_free(ma_space);
13556 return isl_stat_error;
13557 }
13558
13559 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
13560 * coefficients before the transformed range of dimensions,
13561 * the "n_after" coefficients after the transformed range of dimensions
13562 * and the coefficients of the other divs in "bmap".
13563 */
set_ma_divs(__isl_take isl_basic_map * bmap,__isl_keep isl_multi_aff * ma,int n_before,int n_after,int n_div)13564 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
13565 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
13566 {
13567 int i;
13568 isl_size n_param;
13569 isl_size n_set;
13570 isl_local_space *ls;
13571
13572 if (n_div == 0)
13573 return bmap;
13574
13575 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
13576 n_param = isl_local_space_dim(ls, isl_dim_param);
13577 n_set = isl_local_space_dim(ls, isl_dim_set);
13578 if (n_param < 0 || n_set < 0)
13579 return isl_basic_map_free(bmap);
13580
13581 for (i = 0; i < n_div; ++i) {
13582 int o_bmap = 0, o_ls = 0;
13583
13584 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
13585 o_bmap += 1 + 1 + n_param;
13586 o_ls += 1 + 1 + n_param;
13587 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
13588 o_bmap += n_before;
13589 isl_seq_cpy(bmap->div[i] + o_bmap,
13590 ls->div->row[i] + o_ls, n_set);
13591 o_bmap += n_set;
13592 o_ls += n_set;
13593 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
13594 o_bmap += n_after;
13595 isl_seq_cpy(bmap->div[i] + o_bmap,
13596 ls->div->row[i] + o_ls, n_div);
13597 o_bmap += n_div;
13598 o_ls += n_div;
13599 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
13600 bmap = isl_basic_map_add_div_constraints(bmap, i);
13601 if (!bmap)
13602 goto error;
13603 }
13604
13605 isl_local_space_free(ls);
13606 return bmap;
13607 error:
13608 isl_local_space_free(ls);
13609 return isl_basic_map_free(bmap);
13610 }
13611
13612 /* How many stride constraints does "ma" enforce?
13613 * That is, how many of the affine expressions have a denominator
13614 * different from one?
13615 */
multi_aff_strides(__isl_keep isl_multi_aff * ma)13616 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
13617 {
13618 int i;
13619 int strides = 0;
13620
13621 for (i = 0; i < ma->n; ++i)
13622 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
13623 strides++;
13624
13625 return strides;
13626 }
13627
13628 /* For each affine expression in ma of the form
13629 *
13630 * x_i = (f_i y + h_i)/m_i
13631 *
13632 * with m_i different from one, add a constraint to "bmap"
13633 * of the form
13634 *
13635 * f_i y + h_i = m_i alpha_i
13636 *
13637 * with alpha_i an additional existentially quantified variable.
13638 *
13639 * The input variables of "ma" correspond to a subset of the variables
13640 * of "bmap". There are "n_before" variables in "bmap" before this
13641 * subset and "n_after" variables after this subset.
13642 * The integer divisions of the affine expressions in "ma" are assumed
13643 * to have been aligned. There are "n_div_ma" of them and
13644 * they appear first in "bmap", straight after the "n_after" variables.
13645 */
add_ma_strides(__isl_take isl_basic_map * bmap,__isl_keep isl_multi_aff * ma,int n_before,int n_after,int n_div_ma)13646 static __isl_give isl_basic_map *add_ma_strides(
13647 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
13648 int n_before, int n_after, int n_div_ma)
13649 {
13650 int i, k;
13651 int div;
13652 isl_size total;
13653 isl_size n_param;
13654 isl_size n_in;
13655
13656 total = isl_basic_map_dim(bmap, isl_dim_all);
13657 n_param = isl_multi_aff_dim(ma, isl_dim_param);
13658 n_in = isl_multi_aff_dim(ma, isl_dim_in);
13659 if (total < 0 || n_param < 0 || n_in < 0)
13660 return isl_basic_map_free(bmap);
13661 for (i = 0; i < ma->n; ++i) {
13662 int o_bmap = 0, o_ma = 1;
13663
13664 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
13665 continue;
13666 div = isl_basic_map_alloc_div(bmap);
13667 k = isl_basic_map_alloc_equality(bmap);
13668 if (div < 0 || k < 0)
13669 goto error;
13670 isl_int_set_si(bmap->div[div][0], 0);
13671 isl_seq_cpy(bmap->eq[k] + o_bmap,
13672 ma->u.p[i]->v->el + o_ma, 1 + n_param);
13673 o_bmap += 1 + n_param;
13674 o_ma += 1 + n_param;
13675 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
13676 o_bmap += n_before;
13677 isl_seq_cpy(bmap->eq[k] + o_bmap,
13678 ma->u.p[i]->v->el + o_ma, n_in);
13679 o_bmap += n_in;
13680 o_ma += n_in;
13681 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
13682 o_bmap += n_after;
13683 isl_seq_cpy(bmap->eq[k] + o_bmap,
13684 ma->u.p[i]->v->el + o_ma, n_div_ma);
13685 o_bmap += n_div_ma;
13686 o_ma += n_div_ma;
13687 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
13688 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
13689 total++;
13690 }
13691
13692 return bmap;
13693 error:
13694 isl_basic_map_free(bmap);
13695 return NULL;
13696 }
13697
13698 /* Replace the domain or range space (depending on "type) of "space" by "set".
13699 */
isl_space_set(__isl_take isl_space * space,enum isl_dim_type type,__isl_take isl_space * set)13700 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
13701 enum isl_dim_type type, __isl_take isl_space *set)
13702 {
13703 if (type == isl_dim_in) {
13704 space = isl_space_range(space);
13705 space = isl_space_map_from_domain_and_range(set, space);
13706 } else {
13707 space = isl_space_domain(space);
13708 space = isl_space_map_from_domain_and_range(space, set);
13709 }
13710
13711 return space;
13712 }
13713
13714 /* Compute the preimage of the domain or range (depending on "type")
13715 * of "bmap" under the function represented by "ma".
13716 * In other words, plug in "ma" in the domain or range of "bmap".
13717 * The result is a basic map that lives in the same space as "bmap"
13718 * except that the domain or range has been replaced by
13719 * the domain space of "ma".
13720 *
13721 * If bmap is represented by
13722 *
13723 * A(p) + S u + B x + T v + C(divs) >= 0,
13724 *
13725 * where u and x are input and output dimensions if type == isl_dim_out
13726 * while x and v are input and output dimensions if type == isl_dim_in,
13727 * and ma is represented by
13728 *
13729 * x = D(p) + F(y) + G(divs')
13730 *
13731 * then the result is
13732 *
13733 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
13734 *
13735 * The divs in the input set are similarly adjusted.
13736 * In particular
13737 *
13738 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
13739 *
13740 * becomes
13741 *
13742 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
13743 * B_i G(divs') + c_i(divs))/n_i)
13744 *
13745 * If bmap is not a rational map and if F(y) involves any denominators
13746 *
13747 * x_i = (f_i y + h_i)/m_i
13748 *
13749 * then additional constraints are added to ensure that we only
13750 * map back integer points. That is we enforce
13751 *
13752 * f_i y + h_i = m_i alpha_i
13753 *
13754 * with alpha_i an additional existentially quantified variable.
13755 *
13756 * We first copy over the divs from "ma".
13757 * Then we add the modified constraints and divs from "bmap".
13758 * Finally, we add the stride constraints, if needed.
13759 */
isl_basic_map_preimage_multi_aff(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13760 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
13761 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
13762 __isl_take isl_multi_aff *ma)
13763 {
13764 int i, k;
13765 isl_space *space;
13766 isl_basic_map *res = NULL;
13767 isl_size n_before, n_after, n_div_bmap, n_div_ma;
13768 isl_int f, c1, c2, g;
13769 isl_bool rational;
13770 int strides;
13771
13772 isl_int_init(f);
13773 isl_int_init(c1);
13774 isl_int_init(c2);
13775 isl_int_init(g);
13776
13777 ma = isl_multi_aff_align_divs(ma);
13778 if (!bmap || !ma)
13779 goto error;
13780 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
13781 goto error;
13782
13783 if (type == isl_dim_in) {
13784 n_before = 0;
13785 n_after = isl_basic_map_dim(bmap, isl_dim_out);
13786 } else {
13787 n_before = isl_basic_map_dim(bmap, isl_dim_in);
13788 n_after = 0;
13789 }
13790 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
13791 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
13792 if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
13793 goto error;
13794
13795 space = isl_multi_aff_get_domain_space(ma);
13796 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
13797 rational = isl_basic_map_is_rational(bmap);
13798 strides = rational ? 0 : multi_aff_strides(ma);
13799 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
13800 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
13801 if (rational)
13802 res = isl_basic_map_set_rational(res);
13803
13804 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
13805 if (isl_basic_map_alloc_div(res) < 0)
13806 goto error;
13807
13808 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
13809 if (!res)
13810 goto error;
13811
13812 for (i = 0; i < bmap->n_eq; ++i) {
13813 k = isl_basic_map_alloc_equality(res);
13814 if (k < 0)
13815 goto error;
13816 if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13817 n_after, n_div_ma, n_div_bmap,
13818 f, c1, c2, g, 0) < 0)
13819 goto error;
13820 }
13821
13822 for (i = 0; i < bmap->n_ineq; ++i) {
13823 k = isl_basic_map_alloc_inequality(res);
13824 if (k < 0)
13825 goto error;
13826 if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13827 n_after, n_div_ma, n_div_bmap,
13828 f, c1, c2, g, 0) < 0)
13829 goto error;
13830 }
13831
13832 for (i = 0; i < bmap->n_div; ++i) {
13833 if (isl_int_is_zero(bmap->div[i][0])) {
13834 isl_int_set_si(res->div[n_div_ma + i][0], 0);
13835 continue;
13836 }
13837 if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13838 n_before, n_after, n_div_ma, n_div_bmap,
13839 f, c1, c2, g, 1) < 0)
13840 goto error;
13841 }
13842
13843 if (strides)
13844 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13845
13846 isl_int_clear(f);
13847 isl_int_clear(c1);
13848 isl_int_clear(c2);
13849 isl_int_clear(g);
13850 isl_basic_map_free(bmap);
13851 isl_multi_aff_free(ma);
13852 res = isl_basic_map_simplify(res);
13853 return isl_basic_map_finalize(res);
13854 error:
13855 isl_int_clear(f);
13856 isl_int_clear(c1);
13857 isl_int_clear(c2);
13858 isl_int_clear(g);
13859 isl_basic_map_free(bmap);
13860 isl_multi_aff_free(ma);
13861 isl_basic_map_free(res);
13862 return NULL;
13863 }
13864
13865 /* Compute the preimage of "bset" under the function represented by "ma".
13866 * In other words, plug in "ma" in "bset". The result is a basic set
13867 * that lives in the domain space of "ma".
13868 */
isl_basic_set_preimage_multi_aff(__isl_take isl_basic_set * bset,__isl_take isl_multi_aff * ma)13869 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13870 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13871 {
13872 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13873 }
13874
13875 /* Compute the preimage of the domain of "bmap" under the function
13876 * represented by "ma".
13877 * In other words, plug in "ma" in the domain of "bmap".
13878 * The result is a basic map that lives in the same space as "bmap"
13879 * except that the domain has been replaced by the domain space of "ma".
13880 */
isl_basic_map_preimage_domain_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13881 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13882 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13883 {
13884 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13885 }
13886
13887 /* Compute the preimage of the range of "bmap" under the function
13888 * represented by "ma".
13889 * In other words, plug in "ma" in the range of "bmap".
13890 * The result is a basic map that lives in the same space as "bmap"
13891 * except that the range has been replaced by the domain space of "ma".
13892 */
isl_basic_map_preimage_range_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13893 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13894 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13895 {
13896 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13897 }
13898
13899 /* Check if the range of "ma" is compatible with the domain or range
13900 * (depending on "type") of "map".
13901 * Return isl_stat_error if anything is wrong.
13902 */
check_map_compatible_range_multi_aff(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13903 static isl_stat check_map_compatible_range_multi_aff(
13904 __isl_keep isl_map *map, enum isl_dim_type type,
13905 __isl_keep isl_multi_aff *ma)
13906 {
13907 isl_bool m;
13908 isl_space *ma_space;
13909
13910 ma_space = isl_multi_aff_get_space(ma);
13911 m = isl_map_space_tuple_is_equal(map, type, ma_space, isl_dim_out);
13912 isl_space_free(ma_space);
13913 if (m < 0)
13914 return isl_stat_error;
13915 if (!m)
13916 isl_die(isl_map_get_ctx(map), isl_error_invalid,
13917 "spaces don't match", return isl_stat_error);
13918 return isl_stat_ok;
13919 }
13920
13921 /* Compute the preimage of the domain or range (depending on "type")
13922 * of "map" under the function represented by "ma".
13923 * In other words, plug in "ma" in the domain or range of "map".
13924 * The result is a map that lives in the same space as "map"
13925 * except that the domain or range has been replaced by
13926 * the domain space of "ma".
13927 *
13928 * The parameters are assumed to have been aligned.
13929 */
map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13930 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13931 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13932 {
13933 int i;
13934 isl_space *space;
13935
13936 map = isl_map_cow(map);
13937 ma = isl_multi_aff_align_divs(ma);
13938 if (!map || !ma)
13939 goto error;
13940 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13941 goto error;
13942
13943 for (i = 0; i < map->n; ++i) {
13944 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13945 isl_multi_aff_copy(ma));
13946 if (!map->p[i])
13947 goto error;
13948 }
13949
13950 space = isl_multi_aff_get_domain_space(ma);
13951 space = isl_space_set(isl_map_get_space(map), type, space);
13952
13953 isl_space_free(isl_map_take_space(map));
13954 map = isl_map_restore_space(map, space);
13955 if (!map)
13956 goto error;
13957
13958 isl_multi_aff_free(ma);
13959 if (map->n > 1)
13960 ISL_F_CLR(map, ISL_MAP_DISJOINT);
13961 ISL_F_CLR(map, ISL_SET_NORMALIZED);
13962 return map;
13963 error:
13964 isl_multi_aff_free(ma);
13965 isl_map_free(map);
13966 return NULL;
13967 }
13968
13969 /* Compute the preimage of the domain or range (depending on "type")
13970 * of "map" under the function represented by "ma".
13971 * In other words, plug in "ma" in the domain or range of "map".
13972 * The result is a map that lives in the same space as "map"
13973 * except that the domain or range has been replaced by
13974 * the domain space of "ma".
13975 */
isl_map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13976 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13977 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13978 {
13979 isl_bool aligned;
13980
13981 if (!map || !ma)
13982 goto error;
13983
13984 aligned = isl_map_space_has_equal_params(map, ma->space);
13985 if (aligned < 0)
13986 goto error;
13987 if (aligned)
13988 return map_preimage_multi_aff(map, type, ma);
13989
13990 if (isl_map_check_named_params(map) < 0)
13991 goto error;
13992 if (!isl_space_has_named_params(ma->space))
13993 isl_die(map->ctx, isl_error_invalid,
13994 "unaligned unnamed parameters", goto error);
13995 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13996 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13997
13998 return map_preimage_multi_aff(map, type, ma);
13999 error:
14000 isl_multi_aff_free(ma);
14001 return isl_map_free(map);
14002 }
14003
14004 /* Compute the preimage of "set" under the function represented by "ma".
14005 * In other words, plug in "ma" in "set". The result is a set
14006 * that lives in the domain space of "ma".
14007 */
isl_set_preimage_multi_aff(__isl_take isl_set * set,__isl_take isl_multi_aff * ma)14008 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
14009 __isl_take isl_multi_aff *ma)
14010 {
14011 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
14012 }
14013
14014 /* Compute the preimage of the domain of "map" under the function
14015 * represented by "ma".
14016 * In other words, plug in "ma" in the domain of "map".
14017 * The result is a map that lives in the same space as "map"
14018 * except that the domain has been replaced by the domain space of "ma".
14019 */
isl_map_preimage_domain_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)14020 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
14021 __isl_take isl_multi_aff *ma)
14022 {
14023 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
14024 }
14025
14026 /* Compute the preimage of the range of "map" under the function
14027 * represented by "ma".
14028 * In other words, plug in "ma" in the range of "map".
14029 * The result is a map that lives in the same space as "map"
14030 * except that the range has been replaced by the domain space of "ma".
14031 */
isl_map_preimage_range_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)14032 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
14033 __isl_take isl_multi_aff *ma)
14034 {
14035 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
14036 }
14037
14038 /* Compute the preimage of "map" under the function represented by "pma".
14039 * In other words, plug in "pma" in the domain or range of "map".
14040 * The result is a map that lives in the same space as "map",
14041 * except that the space of type "type" has been replaced by
14042 * the domain space of "pma".
14043 *
14044 * The parameters of "map" and "pma" are assumed to have been aligned.
14045 */
isl_map_preimage_pw_multi_aff_aligned(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14046 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
14047 __isl_take isl_map *map, enum isl_dim_type type,
14048 __isl_take isl_pw_multi_aff *pma)
14049 {
14050 int i;
14051 isl_map *res;
14052
14053 if (!pma)
14054 goto error;
14055
14056 if (pma->n == 0) {
14057 isl_pw_multi_aff_free(pma);
14058 res = isl_map_empty(isl_map_get_space(map));
14059 isl_map_free(map);
14060 return res;
14061 }
14062
14063 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14064 isl_multi_aff_copy(pma->p[0].maff));
14065 if (type == isl_dim_in)
14066 res = isl_map_intersect_domain(res,
14067 isl_map_copy(pma->p[0].set));
14068 else
14069 res = isl_map_intersect_range(res,
14070 isl_map_copy(pma->p[0].set));
14071
14072 for (i = 1; i < pma->n; ++i) {
14073 isl_map *res_i;
14074
14075 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14076 isl_multi_aff_copy(pma->p[i].maff));
14077 if (type == isl_dim_in)
14078 res_i = isl_map_intersect_domain(res_i,
14079 isl_map_copy(pma->p[i].set));
14080 else
14081 res_i = isl_map_intersect_range(res_i,
14082 isl_map_copy(pma->p[i].set));
14083 res = isl_map_union(res, res_i);
14084 }
14085
14086 isl_pw_multi_aff_free(pma);
14087 isl_map_free(map);
14088 return res;
14089 error:
14090 isl_pw_multi_aff_free(pma);
14091 isl_map_free(map);
14092 return NULL;
14093 }
14094
14095 /* Compute the preimage of "map" under the function represented by "pma".
14096 * In other words, plug in "pma" in the domain or range of "map".
14097 * The result is a map that lives in the same space as "map",
14098 * except that the space of type "type" has been replaced by
14099 * the domain space of "pma".
14100 */
isl_map_preimage_pw_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14101 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
14102 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
14103 {
14104 isl_bool aligned;
14105
14106 if (!map || !pma)
14107 goto error;
14108
14109 aligned = isl_map_space_has_equal_params(map, pma->dim);
14110 if (aligned < 0)
14111 goto error;
14112 if (aligned)
14113 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14114
14115 if (isl_map_check_named_params(map) < 0)
14116 goto error;
14117 if (isl_pw_multi_aff_check_named_params(pma) < 0)
14118 goto error;
14119 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
14120 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
14121
14122 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14123 error:
14124 isl_pw_multi_aff_free(pma);
14125 return isl_map_free(map);
14126 }
14127
14128 /* Compute the preimage of "set" under the function represented by "pma".
14129 * In other words, plug in "pma" in "set". The result is a set
14130 * that lives in the domain space of "pma".
14131 */
isl_set_preimage_pw_multi_aff(__isl_take isl_set * set,__isl_take isl_pw_multi_aff * pma)14132 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
14133 __isl_take isl_pw_multi_aff *pma)
14134 {
14135 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
14136 }
14137
14138 /* Compute the preimage of the domain of "map" under the function
14139 * represented by "pma".
14140 * In other words, plug in "pma" in the domain of "map".
14141 * The result is a map that lives in the same space as "map",
14142 * except that domain space has been replaced by the domain space of "pma".
14143 */
isl_map_preimage_domain_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14144 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
14145 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14146 {
14147 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
14148 }
14149
14150 /* Compute the preimage of the range of "map" under the function
14151 * represented by "pma".
14152 * In other words, plug in "pma" in the range of "map".
14153 * The result is a map that lives in the same space as "map",
14154 * except that range space has been replaced by the domain space of "pma".
14155 */
isl_map_preimage_range_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14156 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
14157 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14158 {
14159 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
14160 }
14161
14162 /* Compute the preimage of "map" under the function represented by "mpa".
14163 * In other words, plug in "mpa" in the domain or range of "map".
14164 * The result is a map that lives in the same space as "map",
14165 * except that the space of type "type" has been replaced by
14166 * the domain space of "mpa".
14167 *
14168 * If the map does not involve any constraints that refer to the
14169 * dimensions of the substituted space, then the only possible
14170 * effect of "mpa" on the map is to map the space to a different space.
14171 * We create a separate isl_multi_aff to effectuate this change
14172 * in order to avoid spurious splitting of the map along the pieces
14173 * of "mpa".
14174 * If "mpa" has a non-trivial explicit domain, however,
14175 * then the full substitution should be performed.
14176 */
isl_map_preimage_multi_pw_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_pw_aff * mpa)14177 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
14178 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
14179 {
14180 isl_size n;
14181 isl_bool full;
14182 isl_pw_multi_aff *pma;
14183
14184 n = isl_map_dim(map, type);
14185 if (n < 0 || !mpa)
14186 goto error;
14187
14188 full = isl_map_involves_dims(map, type, 0, n);
14189 if (full >= 0 && !full)
14190 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
14191 if (full < 0)
14192 goto error;
14193 if (!full) {
14194 isl_space *space;
14195 isl_multi_aff *ma;
14196
14197 space = isl_multi_pw_aff_get_space(mpa);
14198 isl_multi_pw_aff_free(mpa);
14199 ma = isl_multi_aff_zero(space);
14200 return isl_map_preimage_multi_aff(map, type, ma);
14201 }
14202
14203 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
14204 return isl_map_preimage_pw_multi_aff(map, type, pma);
14205 error:
14206 isl_map_free(map);
14207 isl_multi_pw_aff_free(mpa);
14208 return NULL;
14209 }
14210
14211 /* Compute the preimage of "map" under the function represented by "mpa".
14212 * In other words, plug in "mpa" in the domain "map".
14213 * The result is a map that lives in the same space as "map",
14214 * except that domain space has been replaced by the domain space of "mpa".
14215 */
isl_map_preimage_domain_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * mpa)14216 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
14217 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
14218 {
14219 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
14220 }
14221
14222 /* Compute the preimage of "set" by the function represented by "mpa".
14223 * In other words, plug in "mpa" in "set".
14224 */
isl_set_preimage_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * mpa)14225 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
14226 __isl_take isl_multi_pw_aff *mpa)
14227 {
14228 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
14229 }
14230
14231 /* Return a copy of the equality constraints of "bset" as a matrix.
14232 */
isl_basic_set_extract_equalities(__isl_keep isl_basic_set * bset)14233 __isl_give isl_mat *isl_basic_set_extract_equalities(
14234 __isl_keep isl_basic_set *bset)
14235 {
14236 isl_ctx *ctx;
14237 isl_size total;
14238
14239 total = isl_basic_set_dim(bset, isl_dim_all);
14240 if (total < 0)
14241 return NULL;
14242
14243 ctx = isl_basic_set_get_ctx(bset);
14244 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
14245 }
14246
14247 /* Are the "n" "coefficients" starting at "first" of the integer division
14248 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
14249 * to each other?
14250 * The "coefficient" at position 0 is the denominator.
14251 * The "coefficient" at position 1 is the constant term.
14252 */
isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map * bmap1,int pos1,__isl_keep isl_basic_map * bmap2,int pos2,unsigned first,unsigned n)14253 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
14254 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
14255 unsigned first, unsigned n)
14256 {
14257 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
14258 return isl_bool_error;
14259 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
14260 return isl_bool_error;
14261 return isl_seq_eq(bmap1->div[pos1] + first,
14262 bmap2->div[pos2] + first, n);
14263 }
14264
14265 /* Are the integer division expressions at position "pos1" in "bmap1" and
14266 * "pos2" in "bmap2" equal to each other, except that the constant terms
14267 * are different?
14268 */
isl_basic_map_equal_div_expr_except_constant(__isl_keep isl_basic_map * bmap1,int pos1,__isl_keep isl_basic_map * bmap2,int pos2)14269 isl_bool isl_basic_map_equal_div_expr_except_constant(
14270 __isl_keep isl_basic_map *bmap1, int pos1,
14271 __isl_keep isl_basic_map *bmap2, int pos2)
14272 {
14273 isl_bool equal;
14274 isl_size total, total2;
14275
14276 total = isl_basic_map_dim(bmap1, isl_dim_all);
14277 total2 = isl_basic_map_dim(bmap2, isl_dim_all);
14278 if (total < 0 || total2 < 0)
14279 return isl_bool_error;
14280 if (total != total2)
14281 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
14282 "incomparable div expressions", return isl_bool_error);
14283 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14284 0, 1);
14285 if (equal < 0 || !equal)
14286 return equal;
14287 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14288 1, 1);
14289 if (equal < 0 || equal)
14290 return isl_bool_not(equal);
14291 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14292 2, total);
14293 }
14294
14295 /* Replace the numerator of the constant term of the integer division
14296 * expression at position "div" in "bmap" by "value".
14297 * The caller guarantees that this does not change the meaning
14298 * of the input.
14299 */
isl_basic_map_set_div_expr_constant_num_si_inplace(__isl_take isl_basic_map * bmap,int div,int value)14300 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
14301 __isl_take isl_basic_map *bmap, int div, int value)
14302 {
14303 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
14304 return isl_basic_map_free(bmap);
14305
14306 isl_int_set_si(bmap->div[div][1], value);
14307
14308 return bmap;
14309 }
14310
14311 /* Is the point "inner" internal to inequality constraint "ineq"
14312 * of "bset"?
14313 * The point is considered to be internal to the inequality constraint,
14314 * if it strictly lies on the positive side of the inequality constraint,
14315 * or if it lies on the constraint and the constraint is lexico-positive.
14316 */
is_internal(__isl_keep isl_vec * inner,__isl_keep isl_basic_set * bset,int ineq)14317 static isl_bool is_internal(__isl_keep isl_vec *inner,
14318 __isl_keep isl_basic_set *bset, int ineq)
14319 {
14320 isl_ctx *ctx;
14321 int pos;
14322 isl_size total;
14323
14324 if (!inner || !bset)
14325 return isl_bool_error;
14326
14327 ctx = isl_basic_set_get_ctx(bset);
14328 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
14329 &ctx->normalize_gcd);
14330 if (!isl_int_is_zero(ctx->normalize_gcd))
14331 return isl_int_is_nonneg(ctx->normalize_gcd);
14332
14333 total = isl_basic_set_dim(bset, isl_dim_all);
14334 if (total < 0)
14335 return isl_bool_error;
14336 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
14337 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
14338 }
14339
14340 /* Tighten the inequality constraints of "bset" that are outward with respect
14341 * to the point "vec".
14342 * That is, tighten the constraints that are not satisfied by "vec".
14343 *
14344 * "vec" is a point internal to some superset S of "bset" that is used
14345 * to make the subsets of S disjoint, by tightening one half of the constraints
14346 * that separate two subsets. In particular, the constraints of S
14347 * are all satisfied by "vec" and should not be tightened.
14348 * Of the internal constraints, those that have "vec" on the outside
14349 * are tightened. The shared facet is included in the adjacent subset
14350 * with the opposite constraint.
14351 * For constraints that saturate "vec", this criterion cannot be used
14352 * to determine which of the two sides should be tightened.
14353 * Instead, the sign of the first non-zero coefficient is used
14354 * to make this choice. Note that this second criterion is never used
14355 * on the constraints of S since "vec" is interior to "S".
14356 */
isl_basic_set_tighten_outward(__isl_take isl_basic_set * bset,__isl_keep isl_vec * vec)14357 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
14358 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
14359 {
14360 int j;
14361
14362 bset = isl_basic_set_cow(bset);
14363 if (!bset)
14364 return NULL;
14365 for (j = 0; j < bset->n_ineq; ++j) {
14366 isl_bool internal;
14367
14368 internal = is_internal(vec, bset, j);
14369 if (internal < 0)
14370 return isl_basic_set_free(bset);
14371 if (internal)
14372 continue;
14373 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
14374 }
14375
14376 return bset;
14377 }
14378
14379 /* Replace the variables x of type "type" starting at "first" in "bmap"
14380 * by x' with x = M x' with M the matrix trans.
14381 * That is, replace the corresponding coefficients c by c M.
14382 *
14383 * The transformation matrix should be a square matrix.
14384 */
isl_basic_map_transform_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14385 __isl_give isl_basic_map *isl_basic_map_transform_dims(
14386 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
14387 __isl_take isl_mat *trans)
14388 {
14389 unsigned pos;
14390
14391 bmap = isl_basic_map_cow(bmap);
14392 if (!bmap || !trans)
14393 goto error;
14394
14395 if (trans->n_row != trans->n_col)
14396 isl_die(trans->ctx, isl_error_invalid,
14397 "expecting square transformation matrix", goto error);
14398 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
14399 goto error;
14400
14401 pos = isl_basic_map_offset(bmap, type) + first;
14402
14403 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
14404 isl_mat_copy(trans)) < 0)
14405 goto error;
14406 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
14407 isl_mat_copy(trans)) < 0)
14408 goto error;
14409 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
14410 isl_mat_copy(trans)) < 0)
14411 goto error;
14412
14413 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
14414 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
14415
14416 isl_mat_free(trans);
14417 return bmap;
14418 error:
14419 isl_mat_free(trans);
14420 isl_basic_map_free(bmap);
14421 return NULL;
14422 }
14423
14424 /* Replace the variables x of type "type" starting at "first" in "bset"
14425 * by x' with x = M x' with M the matrix trans.
14426 * That is, replace the corresponding coefficients c by c M.
14427 *
14428 * The transformation matrix should be a square matrix.
14429 */
isl_basic_set_transform_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14430 __isl_give isl_basic_set *isl_basic_set_transform_dims(
14431 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
14432 __isl_take isl_mat *trans)
14433 {
14434 return isl_basic_map_transform_dims(bset, type, first, trans);
14435 }
14436