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 #undef BASE
6868 #define BASE val
6869 #include "isl_map_bound_templ.c"
6870
6871 /* Apply "map_bound" to "set" with the corresponding value in "bound"
6872 * for each set dimension, by treating the set as a map.
6873 */
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))6874 static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,
6875 __isl_take isl_multi_val *bound,
6876 __isl_give isl_map *map_bound(__isl_take isl_map *map,
6877 unsigned pos, __isl_take isl_val *value))
6878 {
6879 isl_map *map;
6880
6881 map = set_to_map(set);
6882 return set_from_map(map_bound_multi_val(map, bound, map_bound));
6883 }
6884
6885 #undef BASE
6886 #define BASE pw_aff
6887 #include "isl_map_bound_templ.c"
6888
6889 /* Apply "map_bound" to "set" with the corresponding value in "bound"
6890 * for each set dimension, by converting the set and the bound
6891 * to objects living in a map space.
6892 */
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))6893 static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,
6894 __isl_take isl_multi_pw_aff *bound,
6895 __isl_give isl_map *set_bound(__isl_take isl_map *map,
6896 unsigned pos, __isl_take TYPE *value))
6897 {
6898 isl_map *map;
6899
6900 map = isl_map_from_range(set);
6901 bound = isl_multi_pw_aff_from_range(bound);
6902 map = map_bound_multi_pw_aff(map, bound, set_bound);
6903 return isl_map_range(map);
6904 }
6905
6906 /* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,
6907 * setting a bound on the given output dimension.
6908 */
map_lower_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)6909 static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,
6910 unsigned pos, __isl_take isl_val *v)
6911 {
6912 return isl_map_lower_bound_val(map, isl_dim_out, pos, v);
6913 }
6914
6915 /* Force the values of the set dimensions of "set"
6916 * to be no smaller than the corresponding values in "lower".
6917 */
isl_set_lower_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * lower)6918 __isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
6919 __isl_take isl_multi_val *lower)
6920 {
6921 return set_bound_multi_val(set, lower, &map_lower_bound_val);
6922 }
6923
6924 /* Force the values of the output dimensions of "map"
6925 * to be no smaller than the corresponding values in "lower".
6926 */
isl_map_lower_bound_multi_val(__isl_take isl_map * map,__isl_take isl_multi_val * lower)6927 __isl_give isl_map *isl_map_lower_bound_multi_val(__isl_take isl_map *map,
6928 __isl_take isl_multi_val *lower)
6929 {
6930 return map_bound_multi_val(map, lower, &map_lower_bound_val);
6931 }
6932
6933 /* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,
6934 * setting a bound on the given output dimension.
6935 */
map_upper_bound_val(__isl_take isl_map * map,unsigned pos,__isl_take isl_val * v)6936 static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,
6937 unsigned pos, __isl_take isl_val *v)
6938 {
6939 return isl_map_upper_bound_val(map, isl_dim_out, pos, v);
6940 }
6941
6942 /* Force the values of the set dimensions of "set"
6943 * to be no greater than the corresponding values in "upper".
6944 */
isl_set_upper_bound_multi_val(__isl_take isl_set * set,__isl_take isl_multi_val * upper)6945 __isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
6946 __isl_take isl_multi_val *upper)
6947 {
6948 return set_bound_multi_val(set, upper, &map_upper_bound_val);
6949 }
6950
6951 /* Force the values of the set dimensions of "set"
6952 * to be no greater than the corresponding values in "upper".
6953 */
isl_map_upper_bound_multi_val(__isl_take isl_map * map,__isl_take isl_multi_val * upper)6954 __isl_give isl_map *isl_map_upper_bound_multi_val(__isl_take isl_map *map,
6955 __isl_take isl_multi_val *upper)
6956 {
6957 return map_bound_multi_val(map, upper, &map_upper_bound_val);
6958 }
6959
6960 /* Force the symbolic constant expression "bound"
6961 * to satisfy the relation "order" with respect to
6962 * the output variable at position "pos" of "map".
6963 *
6964 * Create an affine expression representing the output variable
6965 * in terms of the range and
6966 * compare it using "order" to "bound" (defined on the domain).
6967 * The result is a relation between elements in domain and range that
6968 * can be intersected with "map".
6969 */
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))6970 static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,
6971 unsigned pos, __isl_take isl_pw_aff *bound,
6972 __isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,
6973 __isl_take isl_pw_aff *pa2))
6974 {
6975 isl_space *space;
6976 isl_local_space *ls;
6977 isl_pw_aff *var;
6978
6979 space = isl_space_range(isl_map_get_space(map));
6980 ls = isl_local_space_from_space(space);
6981 var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);
6982 map = isl_map_intersect(map, order(bound, var));
6983 return map;
6984 }
6985
6986 /* Force the values of the output variable at position "pos" of "map"
6987 * to be no smaller than the symbolic constant expression "lower".
6988 */
map_lower_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * lower)6989 static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,
6990 unsigned pos, __isl_take isl_pw_aff *lower)
6991 {
6992 return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);
6993 }
6994
6995 /* Force the values of the output variable at position "pos" of "map"
6996 * to be no greater than the symbolic constant expression "upper".
6997 */
map_upper_bound_pw_aff(__isl_take isl_map * map,unsigned pos,__isl_take isl_pw_aff * upper)6998 static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,
6999 unsigned pos, __isl_take isl_pw_aff *upper)
7000 {
7001 return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);
7002 }
7003
7004 /* Force the values of the set dimensions of "set"
7005 * to be no smaller than the corresponding constant symbolic expressions
7006 * in "lower".
7007 */
isl_set_lower_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * lower)7008 __isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
7009 __isl_take isl_multi_pw_aff *lower)
7010 {
7011 return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);
7012 }
7013
7014 /* Force the values of the set dimensions of "set"
7015 * to be no greater than the corresponding constant symbolic expressions
7016 * in "upper".
7017 */
isl_set_upper_bound_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * upper)7018 __isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
7019 __isl_take isl_multi_pw_aff *upper)
7020 {
7021 return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);
7022 }
7023
7024 /* Force the values of the output dimensions of "map"
7025 * to be no smaller than the corresponding constant symbolic expressions
7026 * in "lower".
7027 */
isl_map_lower_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * lower)7028 __isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
7029 __isl_take isl_multi_pw_aff *lower)
7030 {
7031 return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);
7032 }
7033
7034 /* Force the values of the output dimensions of "map"
7035 * to be no greater than the corresponding constant symbolic expressions
7036 * in "upper".
7037 */
isl_map_upper_bound_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * upper)7038 __isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
7039 __isl_take isl_multi_pw_aff *upper)
7040 {
7041 return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);
7042 }
7043
7044 /* Bound the given variable of "bset" from below (or above is "upper"
7045 * is set) to "value".
7046 */
isl_basic_set_bound(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,isl_int value,int upper)7047 static __isl_give isl_basic_set *isl_basic_set_bound(
7048 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7049 isl_int value, int upper)
7050 {
7051 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
7052 type, pos, value, upper));
7053 }
7054
7055 /* Bound the given variable of "bset" from below (or above is "upper"
7056 * is set) to "value".
7057 */
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)7058 static __isl_give isl_basic_set *isl_basic_set_bound_val(
7059 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7060 __isl_take isl_val *value, int upper)
7061 {
7062 if (!value)
7063 goto error;
7064 if (!isl_val_is_int(value))
7065 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
7066 "expecting integer value", goto error);
7067 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
7068 isl_val_free(value);
7069 return bset;
7070 error:
7071 isl_val_free(value);
7072 isl_basic_set_free(bset);
7073 return NULL;
7074 }
7075
7076 /* Bound the given variable of "bset" from below to "value".
7077 */
isl_basic_set_lower_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7078 __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
7079 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7080 __isl_take isl_val *value)
7081 {
7082 return isl_basic_set_bound_val(bset, type, pos, value, 0);
7083 }
7084
7085 /* Bound the given variable of "bset" from above to "value".
7086 */
isl_basic_set_upper_bound_val(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_take isl_val * value)7087 __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
7088 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7089 __isl_take isl_val *value)
7090 {
7091 return isl_basic_set_bound_val(bset, type, pos, value, 1);
7092 }
7093
isl_map_reverse(__isl_take isl_map * map)7094 __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
7095 {
7096 return isl_map_transform(map, &isl_space_reverse,
7097 &isl_basic_map_reverse);
7098 }
7099
7100 /* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).
7101 */
isl_map_range_reverse(__isl_take isl_map * map)7102 __isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)
7103 {
7104 return isl_map_transform(map, &isl_space_range_reverse,
7105 &isl_basic_map_range_reverse);
7106 }
7107
7108 #undef TYPE
7109 #define TYPE isl_pw_multi_aff
7110 #undef SUFFIX
7111 #define SUFFIX _pw_multi_aff
7112 #undef EMPTY
7113 #define EMPTY isl_pw_multi_aff_empty
7114 #undef ADD
7115 #define ADD isl_pw_multi_aff_union_add
7116 #include "isl_map_lexopt_templ.c"
7117
7118 /* Given a map "map", compute the lexicographically minimal
7119 * (or maximal) image element for each domain element in dom,
7120 * in the form of an isl_pw_multi_aff.
7121 * If "empty" is not NULL, then set *empty to those elements in dom that
7122 * do not have an image element.
7123 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7124 * should be computed over the domain of "map". "empty" is also NULL
7125 * in this case.
7126 *
7127 * We first compute the lexicographically minimal or maximal element
7128 * in the first basic map. This results in a partial solution "res"
7129 * and a subset "todo" of dom that still need to be handled.
7130 * We then consider each of the remaining maps in "map" and successively
7131 * update both "res" and "todo".
7132 * If "empty" is NULL, then the todo sets are not needed and therefore
7133 * also not computed.
7134 */
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)7135 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
7136 __isl_take isl_map *map, __isl_take isl_set *dom,
7137 __isl_give isl_set **empty, unsigned flags)
7138 {
7139 int i;
7140 int full;
7141 isl_pw_multi_aff *res;
7142 isl_set *todo;
7143
7144 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7145 if (!map || (!full && !dom))
7146 goto error;
7147
7148 if (isl_map_plain_is_empty(map)) {
7149 if (empty)
7150 *empty = dom;
7151 else
7152 isl_set_free(dom);
7153 return isl_pw_multi_aff_from_map(map);
7154 }
7155
7156 res = basic_map_partial_lexopt_pw_multi_aff(
7157 isl_basic_map_copy(map->p[0]),
7158 isl_set_copy(dom), empty, flags);
7159
7160 if (empty)
7161 todo = *empty;
7162 for (i = 1; i < map->n; ++i) {
7163 isl_pw_multi_aff *res_i;
7164
7165 res_i = basic_map_partial_lexopt_pw_multi_aff(
7166 isl_basic_map_copy(map->p[i]),
7167 isl_set_copy(dom), empty, flags);
7168
7169 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
7170 res = isl_pw_multi_aff_union_lexmax(res, res_i);
7171 else
7172 res = isl_pw_multi_aff_union_lexmin(res, res_i);
7173
7174 if (empty)
7175 todo = isl_set_intersect(todo, *empty);
7176 }
7177
7178 isl_set_free(dom);
7179 isl_map_free(map);
7180
7181 if (empty)
7182 *empty = todo;
7183
7184 return res;
7185 error:
7186 if (empty)
7187 *empty = NULL;
7188 isl_set_free(dom);
7189 isl_map_free(map);
7190 return NULL;
7191 }
7192
7193 #undef TYPE
7194 #define TYPE isl_map
7195 #undef SUFFIX
7196 #define SUFFIX
7197 #undef EMPTY
7198 #define EMPTY isl_map_empty
7199 #undef ADD
7200 #define ADD isl_map_union_disjoint
7201 #include "isl_map_lexopt_templ.c"
7202
7203 /* Given a map "map", compute the lexicographically minimal
7204 * (or maximal) image element for each domain element in "dom",
7205 * in the form of an isl_map.
7206 * If "empty" is not NULL, then set *empty to those elements in "dom" that
7207 * do not have an image element.
7208 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7209 * should be computed over the domain of "map". "empty" is also NULL
7210 * in this case.
7211 *
7212 * If the input consists of more than one disjunct, then first
7213 * compute the desired result in the form of an isl_pw_multi_aff and
7214 * then convert that into an isl_map.
7215 *
7216 * This function used to have an explicit implementation in terms
7217 * of isl_maps, but it would continually intersect the domains of
7218 * partial results with the complement of the domain of the next
7219 * partial solution, potentially leading to an explosion in the number
7220 * of disjuncts if there are several disjuncts in the input.
7221 * An even earlier implementation of this function would look for
7222 * better results in the domain of the partial result and for extra
7223 * results in the complement of this domain, which would lead to
7224 * even more splintering.
7225 */
isl_map_partial_lexopt_aligned(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty,unsigned flags)7226 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
7227 __isl_take isl_map *map, __isl_take isl_set *dom,
7228 __isl_give isl_set **empty, unsigned flags)
7229 {
7230 int full;
7231 struct isl_map *res;
7232 isl_pw_multi_aff *pma;
7233
7234 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7235 if (!map || (!full && !dom))
7236 goto error;
7237
7238 if (isl_map_plain_is_empty(map)) {
7239 if (empty)
7240 *empty = dom;
7241 else
7242 isl_set_free(dom);
7243 return map;
7244 }
7245
7246 if (map->n == 1) {
7247 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
7248 dom, empty, flags);
7249 isl_map_free(map);
7250 return res;
7251 }
7252
7253 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
7254 flags);
7255 return isl_map_from_pw_multi_aff_internal(pma);
7256 error:
7257 if (empty)
7258 *empty = NULL;
7259 isl_set_free(dom);
7260 isl_map_free(map);
7261 return NULL;
7262 }
7263
isl_map_partial_lexmax(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7264 __isl_give isl_map *isl_map_partial_lexmax(
7265 __isl_take isl_map *map, __isl_take isl_set *dom,
7266 __isl_give isl_set **empty)
7267 {
7268 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
7269 }
7270
isl_map_partial_lexmin(__isl_take isl_map * map,__isl_take isl_set * dom,__isl_give isl_set ** empty)7271 __isl_give isl_map *isl_map_partial_lexmin(
7272 __isl_take isl_map *map, __isl_take isl_set *dom,
7273 __isl_give isl_set **empty)
7274 {
7275 return isl_map_partial_lexopt(map, dom, empty, 0);
7276 }
7277
isl_set_partial_lexmin(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7278 __isl_give isl_set *isl_set_partial_lexmin(
7279 __isl_take isl_set *set, __isl_take isl_set *dom,
7280 __isl_give isl_set **empty)
7281 {
7282 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
7283 dom, empty));
7284 }
7285
isl_set_partial_lexmax(__isl_take isl_set * set,__isl_take isl_set * dom,__isl_give isl_set ** empty)7286 __isl_give isl_set *isl_set_partial_lexmax(
7287 __isl_take isl_set *set, __isl_take isl_set *dom,
7288 __isl_give isl_set **empty)
7289 {
7290 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
7291 dom, empty));
7292 }
7293
7294 /* Compute the lexicographic minimum (or maximum if "flags" includes
7295 * ISL_OPT_MAX) of "bset" over its parametric domain.
7296 */
isl_basic_set_lexopt(__isl_take isl_basic_set * bset,unsigned flags)7297 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
7298 unsigned flags)
7299 {
7300 return isl_basic_map_lexopt(bset, flags);
7301 }
7302
isl_basic_map_lexmax(__isl_take isl_basic_map * bmap)7303 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
7304 {
7305 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
7306 }
7307
isl_basic_set_lexmin(__isl_take isl_basic_set * bset)7308 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
7309 {
7310 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
7311 }
7312
isl_basic_set_lexmax(__isl_take isl_basic_set * bset)7313 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
7314 {
7315 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
7316 }
7317
7318 /* Compute the lexicographic minimum of "bset" over its parametric domain
7319 * for the purpose of quantifier elimination.
7320 * That is, find an explicit representation for all the existentially
7321 * quantified variables in "bset" by computing their lexicographic
7322 * minimum.
7323 */
isl_basic_set_lexmin_compute_divs(__isl_take isl_basic_set * bset)7324 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
7325 __isl_take isl_basic_set *bset)
7326 {
7327 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
7328 }
7329
7330 /* Given a basic map with one output dimension, compute the minimum or
7331 * maximum of that dimension as an isl_pw_aff.
7332 *
7333 * Compute the optimum as a lexicographic optimum over the single
7334 * output dimension and extract the single isl_pw_aff from the result.
7335 */
basic_map_dim_opt(__isl_keep isl_basic_map * bmap,int max)7336 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
7337 int max)
7338 {
7339 isl_pw_multi_aff *pma;
7340 isl_pw_aff *pwaff;
7341
7342 bmap = isl_basic_map_copy(bmap);
7343 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
7344 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
7345 isl_pw_multi_aff_free(pma);
7346
7347 return pwaff;
7348 }
7349
7350 /* Compute the minimum or maximum of the given output dimension
7351 * as a function of the parameters and the input dimensions,
7352 * but independently of the other output dimensions.
7353 *
7354 * We first project out the other output dimension and then compute
7355 * the "lexicographic" maximum in each basic map, combining the results
7356 * using isl_pw_aff_union_max.
7357 */
map_dim_opt(__isl_take isl_map * map,int pos,int max)7358 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
7359 int max)
7360 {
7361 int i;
7362 isl_pw_aff *pwaff;
7363 isl_size n_out;
7364
7365 n_out = isl_map_dim(map, isl_dim_out);
7366 if (n_out < 0)
7367 map = isl_map_free(map);
7368 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7369 map = isl_map_project_out(map, isl_dim_out, 0, pos);
7370 if (!map)
7371 return NULL;
7372
7373 if (map->n == 0) {
7374 isl_space *space = isl_map_get_space(map);
7375 isl_map_free(map);
7376 return isl_pw_aff_empty(space);
7377 }
7378
7379 pwaff = basic_map_dim_opt(map->p[0], max);
7380 for (i = 1; i < map->n; ++i) {
7381 isl_pw_aff *pwaff_i;
7382
7383 pwaff_i = basic_map_dim_opt(map->p[i], max);
7384 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7385 }
7386
7387 isl_map_free(map);
7388
7389 return pwaff;
7390 }
7391
7392 /* Compute the minimum of the given output dimension as a function of the
7393 * parameters and input dimensions, but independently of
7394 * the other output dimensions.
7395 */
isl_map_dim_min(__isl_take isl_map * map,int pos)7396 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7397 {
7398 return map_dim_opt(map, pos, 0);
7399 }
7400
7401 /* Compute the maximum of the given output dimension as a function of the
7402 * parameters and input dimensions, but independently of
7403 * the other output dimensions.
7404 */
isl_map_dim_max(__isl_take isl_map * map,int pos)7405 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7406 {
7407 return map_dim_opt(map, pos, 1);
7408 }
7409
7410 /* Compute the minimum or maximum of the given set dimension
7411 * as a function of the parameters,
7412 * but independently of the other set dimensions.
7413 */
set_dim_opt(__isl_take isl_set * set,int pos,int max)7414 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7415 int max)
7416 {
7417 return map_dim_opt(set, pos, max);
7418 }
7419
7420 /* Compute the maximum of the given set dimension as a function of the
7421 * parameters, but independently of the other set dimensions.
7422 */
isl_set_dim_max(__isl_take isl_set * set,int pos)7423 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7424 {
7425 return set_dim_opt(set, pos, 1);
7426 }
7427
7428 /* Compute the minimum of the given set dimension as a function of the
7429 * parameters, but independently of the other set dimensions.
7430 */
isl_set_dim_min(__isl_take isl_set * set,int pos)7431 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7432 {
7433 return set_dim_opt(set, pos, 0);
7434 }
7435
7436 /* Apply a preimage specified by "mat" on the parameters of "bset".
7437 * bset is assumed to have only parameters and divs.
7438 */
basic_set_parameter_preimage(__isl_take isl_basic_set * bset,__isl_take isl_mat * mat)7439 static __isl_give isl_basic_set *basic_set_parameter_preimage(
7440 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7441 {
7442 isl_size nparam;
7443
7444 nparam = isl_basic_set_dim(bset, isl_dim_param);
7445 if (nparam < 0 || !mat)
7446 goto error;
7447
7448 bset->dim = isl_space_cow(bset->dim);
7449 if (!bset->dim)
7450 goto error;
7451
7452 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7453
7454 bset->dim->nparam = 0;
7455 bset->dim->n_out = nparam;
7456 bset = isl_basic_set_preimage(bset, mat);
7457 if (bset) {
7458 bset->dim->nparam = bset->dim->n_out;
7459 bset->dim->n_out = 0;
7460 }
7461 return bset;
7462 error:
7463 isl_mat_free(mat);
7464 isl_basic_set_free(bset);
7465 return NULL;
7466 }
7467
7468 /* Apply a preimage specified by "mat" on the parameters of "set".
7469 * set is assumed to have only parameters and divs.
7470 */
set_parameter_preimage(__isl_take isl_set * set,__isl_take isl_mat * mat)7471 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7472 __isl_take isl_mat *mat)
7473 {
7474 isl_space *space;
7475 isl_size nparam;
7476
7477 nparam = isl_set_dim(set, isl_dim_param);
7478 if (nparam < 0 || !mat)
7479 goto error;
7480
7481 if (mat->n_row != 1 + nparam)
7482 isl_die(isl_set_get_ctx(set), isl_error_internal,
7483 "unexpected number of rows", goto error);
7484
7485 space = isl_set_get_space(set);
7486 space = isl_space_move_dims(space, isl_dim_set, 0,
7487 isl_dim_param, 0, nparam);
7488 set = isl_set_reset_space(set, space);
7489 set = isl_set_preimage(set, mat);
7490 nparam = isl_set_dim(set, isl_dim_out);
7491 if (nparam < 0)
7492 set = isl_set_free(set);
7493 space = isl_set_get_space(set);
7494 space = isl_space_move_dims(space, isl_dim_param, 0,
7495 isl_dim_out, 0, nparam);
7496 set = isl_set_reset_space(set, space);
7497 return set;
7498 error:
7499 isl_mat_free(mat);
7500 isl_set_free(set);
7501 return NULL;
7502 }
7503
7504 /* Intersect the basic set "bset" with the affine space specified by the
7505 * equalities in "eq".
7506 */
basic_set_append_equalities(__isl_take isl_basic_set * bset,__isl_take isl_mat * eq)7507 static __isl_give isl_basic_set *basic_set_append_equalities(
7508 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7509 {
7510 int i, k;
7511 unsigned len;
7512
7513 if (!bset || !eq)
7514 goto error;
7515
7516 bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);
7517 if (!bset)
7518 goto error;
7519
7520 len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7521 for (i = 0; i < eq->n_row; ++i) {
7522 k = isl_basic_set_alloc_equality(bset);
7523 if (k < 0)
7524 goto error;
7525 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7526 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7527 }
7528 isl_mat_free(eq);
7529
7530 bset = isl_basic_set_gauss(bset, NULL);
7531 bset = isl_basic_set_finalize(bset);
7532
7533 return bset;
7534 error:
7535 isl_mat_free(eq);
7536 isl_basic_set_free(bset);
7537 return NULL;
7538 }
7539
7540 /* Intersect the set "set" with the affine space specified by the
7541 * equalities in "eq".
7542 */
set_append_equalities(__isl_take isl_set * set,__isl_take isl_mat * eq)7543 static __isl_give isl_set *set_append_equalities(__isl_take isl_set *set,
7544 __isl_take isl_mat *eq)
7545 {
7546 int i;
7547
7548 if (!set || !eq)
7549 goto error;
7550
7551 for (i = 0; i < set->n; ++i) {
7552 set->p[i] = basic_set_append_equalities(set->p[i],
7553 isl_mat_copy(eq));
7554 if (!set->p[i])
7555 goto error;
7556 }
7557 isl_mat_free(eq);
7558 return set;
7559 error:
7560 isl_mat_free(eq);
7561 isl_set_free(set);
7562 return NULL;
7563 }
7564
7565 /* Given a basic set "bset" that only involves parameters and existentially
7566 * quantified variables, return the index of the first equality
7567 * that only involves parameters. If there is no such equality then
7568 * return bset->n_eq.
7569 *
7570 * This function assumes that isl_basic_set_gauss has been called on "bset".
7571 */
first_parameter_equality(__isl_keep isl_basic_set * bset)7572 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7573 {
7574 int i, j;
7575 isl_size nparam, n_div;
7576
7577 nparam = isl_basic_set_dim(bset, isl_dim_param);
7578 n_div = isl_basic_set_dim(bset, isl_dim_div);
7579 if (nparam < 0 || n_div < 0)
7580 return -1;
7581
7582 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7583 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7584 ++i;
7585 }
7586
7587 return i;
7588 }
7589
7590 /* Compute an explicit representation for the existentially quantified
7591 * variables in "bset" by computing the "minimal value" of the set
7592 * variables. Since there are no set variables, the computation of
7593 * the minimal value essentially computes an explicit representation
7594 * of the non-empty part(s) of "bset".
7595 *
7596 * The input only involves parameters and existentially quantified variables.
7597 * All equalities among parameters have been removed.
7598 *
7599 * Since the existentially quantified variables in the result are in general
7600 * going to be different from those in the input, we first replace
7601 * them by the minimal number of variables based on their equalities.
7602 * This should simplify the parametric integer programming.
7603 */
base_compute_divs(__isl_take isl_basic_set * bset)7604 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7605 {
7606 isl_morph *morph1, *morph2;
7607 isl_set *set;
7608 isl_size n;
7609
7610 if (!bset)
7611 return NULL;
7612 if (bset->n_eq == 0)
7613 return isl_basic_set_lexmin_compute_divs(bset);
7614
7615 morph1 = isl_basic_set_parameter_compression(bset);
7616 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7617 bset = isl_basic_set_lift(bset);
7618 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7619 bset = isl_morph_basic_set(morph2, bset);
7620 n = isl_basic_set_dim(bset, isl_dim_set);
7621 if (n < 0)
7622 bset = isl_basic_set_free(bset);
7623 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7624
7625 set = isl_basic_set_lexmin_compute_divs(bset);
7626
7627 set = isl_morph_set(isl_morph_inverse(morph1), set);
7628
7629 return set;
7630 }
7631
7632 /* Project the given basic set onto its parameter domain, possibly introducing
7633 * new, explicit, existential variables in the constraints.
7634 * The input has parameters and (possibly implicit) existential variables.
7635 * The output has the same parameters, but only
7636 * explicit existentially quantified variables.
7637 *
7638 * The actual projection is performed by pip, but pip doesn't seem
7639 * to like equalities very much, so we first remove the equalities
7640 * among the parameters by performing a variable compression on
7641 * the parameters. Afterward, an inverse transformation is performed
7642 * and the equalities among the parameters are inserted back in.
7643 *
7644 * The variable compression on the parameters may uncover additional
7645 * equalities that were only implicit before. We therefore check
7646 * if there are any new parameter equalities in the result and
7647 * if so recurse. The removal of parameter equalities is required
7648 * for the parameter compression performed by base_compute_divs.
7649 */
parameter_compute_divs(__isl_take isl_basic_set * bset)7650 static __isl_give isl_set *parameter_compute_divs(
7651 __isl_take isl_basic_set *bset)
7652 {
7653 int i;
7654 struct isl_mat *eq;
7655 struct isl_mat *T, *T2;
7656 struct isl_set *set;
7657 isl_size nparam;
7658
7659 bset = isl_basic_set_cow(bset);
7660 if (!bset)
7661 return NULL;
7662
7663 if (bset->n_eq == 0)
7664 return base_compute_divs(bset);
7665
7666 bset = isl_basic_set_gauss(bset, NULL);
7667 if (!bset)
7668 return NULL;
7669 if (isl_basic_set_plain_is_empty(bset))
7670 return isl_set_from_basic_set(bset);
7671
7672 i = first_parameter_equality(bset);
7673 if (i == bset->n_eq)
7674 return base_compute_divs(bset);
7675
7676 nparam = isl_basic_set_dim(bset, isl_dim_param);
7677 if (nparam < 0)
7678 return isl_set_from_basic_set(isl_basic_set_free(bset));
7679 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7680 0, 1 + nparam);
7681 eq = isl_mat_cow(eq);
7682 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7683 if (T && T->n_col == 0) {
7684 isl_mat_free(T);
7685 isl_mat_free(T2);
7686 isl_mat_free(eq);
7687 bset = isl_basic_set_set_to_empty(bset);
7688 return isl_set_from_basic_set(bset);
7689 }
7690 bset = basic_set_parameter_preimage(bset, T);
7691
7692 i = first_parameter_equality(bset);
7693 if (!bset)
7694 set = NULL;
7695 else if (i == bset->n_eq)
7696 set = base_compute_divs(bset);
7697 else
7698 set = parameter_compute_divs(bset);
7699 set = set_parameter_preimage(set, T2);
7700 set = set_append_equalities(set, eq);
7701 return set;
7702 }
7703
7704 /* Insert the divs from "ls" before those of "bmap".
7705 *
7706 * The number of columns is not changed, which means that the last
7707 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7708 * The caller is responsible for removing the same number of dimensions
7709 * from the space of "bmap".
7710 */
insert_divs_from_local_space(__isl_take isl_basic_map * bmap,__isl_keep isl_local_space * ls)7711 static __isl_give isl_basic_map *insert_divs_from_local_space(
7712 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7713 {
7714 int i;
7715 isl_size n_div;
7716 int old_n_div;
7717
7718 n_div = isl_local_space_dim(ls, isl_dim_div);
7719 if (n_div < 0)
7720 return isl_basic_map_free(bmap);
7721 if (n_div == 0)
7722 return bmap;
7723
7724 old_n_div = bmap->n_div;
7725 bmap = insert_div_rows(bmap, n_div);
7726 if (!bmap)
7727 return NULL;
7728
7729 for (i = 0; i < n_div; ++i) {
7730 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7731 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7732 }
7733
7734 return bmap;
7735 }
7736
7737 /* Replace the space of "bmap" by the space and divs of "ls".
7738 *
7739 * If "ls" has any divs, then we simplify the result since we may
7740 * have discovered some additional equalities that could simplify
7741 * the div expressions.
7742 */
basic_replace_space_by_local_space(__isl_take isl_basic_map * bmap,__isl_take isl_local_space * ls)7743 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7744 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7745 {
7746 isl_size n_div;
7747
7748 bmap = isl_basic_map_cow(bmap);
7749 n_div = isl_local_space_dim(ls, isl_dim_div);
7750 if (!bmap || n_div < 0)
7751 goto error;
7752
7753 bmap = insert_divs_from_local_space(bmap, ls);
7754 if (!bmap)
7755 goto error;
7756
7757 isl_space_free(bmap->dim);
7758 bmap->dim = isl_local_space_get_space(ls);
7759 if (!bmap->dim)
7760 goto error;
7761
7762 isl_local_space_free(ls);
7763 if (n_div > 0)
7764 bmap = isl_basic_map_simplify(bmap);
7765 bmap = isl_basic_map_finalize(bmap);
7766 return bmap;
7767 error:
7768 isl_basic_map_free(bmap);
7769 isl_local_space_free(ls);
7770 return NULL;
7771 }
7772
7773 /* Replace the space of "map" by the space and divs of "ls".
7774 */
replace_space_by_local_space(__isl_take isl_map * map,__isl_take isl_local_space * ls)7775 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7776 __isl_take isl_local_space *ls)
7777 {
7778 int i;
7779
7780 map = isl_map_cow(map);
7781 if (!map || !ls)
7782 goto error;
7783
7784 for (i = 0; i < map->n; ++i) {
7785 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7786 isl_local_space_copy(ls));
7787 if (!map->p[i])
7788 goto error;
7789 }
7790 isl_space_free(isl_map_take_space(map));
7791 map = isl_map_restore_space(map, isl_local_space_get_space(ls));
7792
7793 isl_local_space_free(ls);
7794 return map;
7795 error:
7796 isl_local_space_free(ls);
7797 isl_map_free(map);
7798 return NULL;
7799 }
7800
7801 /* Compute an explicit representation for the existentially
7802 * quantified variables for which do not know any explicit representation yet.
7803 *
7804 * We first sort the existentially quantified variables so that the
7805 * existentially quantified variables for which we already have an explicit
7806 * representation are placed before those for which we do not.
7807 * The input dimensions, the output dimensions and the existentially
7808 * quantified variables for which we already have an explicit
7809 * representation are then turned into parameters.
7810 * compute_divs returns a map with the same parameters and
7811 * no input or output dimensions and the dimension specification
7812 * is reset to that of the input, including the existentially quantified
7813 * variables for which we already had an explicit representation.
7814 */
compute_divs(__isl_take isl_basic_map * bmap)7815 static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7816 {
7817 struct isl_basic_set *bset;
7818 struct isl_set *set;
7819 struct isl_map *map;
7820 isl_space *space;
7821 isl_local_space *ls;
7822 isl_size nparam;
7823 isl_size n_in;
7824 isl_size n_out;
7825 int n_known;
7826 int i;
7827
7828 bmap = isl_basic_map_sort_divs(bmap);
7829 bmap = isl_basic_map_cow(bmap);
7830 if (!bmap)
7831 return NULL;
7832
7833 n_known = isl_basic_map_first_unknown_div(bmap);
7834 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7835 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7836 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7837 if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
7838 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7839
7840 space = isl_space_set_alloc(bmap->ctx,
7841 nparam + n_in + n_out + n_known, 0);
7842 if (!space)
7843 goto error;
7844
7845 ls = isl_basic_map_get_local_space(bmap);
7846 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7847 n_known, bmap->n_div - n_known);
7848 if (n_known > 0) {
7849 for (i = n_known; i < bmap->n_div; ++i)
7850 swap_div(bmap, i - n_known, i);
7851 bmap->n_div -= n_known;
7852 bmap->extra -= n_known;
7853 }
7854 bmap = isl_basic_map_reset_space(bmap, space);
7855 bset = bset_from_bmap(bmap);
7856
7857 set = parameter_compute_divs(bset);
7858 map = set_to_map(set);
7859 map = replace_space_by_local_space(map, ls);
7860
7861 return map;
7862 error:
7863 isl_basic_map_free(bmap);
7864 return NULL;
7865 }
7866
7867 /* Remove the explicit representation of local variable "div",
7868 * if there is any.
7869 */
isl_basic_map_mark_div_unknown(__isl_take isl_basic_map * bmap,int div)7870 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7871 __isl_take isl_basic_map *bmap, int div)
7872 {
7873 isl_bool unknown;
7874
7875 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7876 if (unknown < 0)
7877 return isl_basic_map_free(bmap);
7878 if (unknown)
7879 return bmap;
7880
7881 bmap = isl_basic_map_cow(bmap);
7882 if (!bmap)
7883 return NULL;
7884 isl_int_set_si(bmap->div[div][0], 0);
7885 return bmap;
7886 }
7887
7888 /* Is local variable "div" of "bmap" marked as not having an explicit
7889 * representation?
7890 * Note that even if "div" is not marked in this way and therefore
7891 * has an explicit representation, this representation may still
7892 * depend (indirectly) on other local variables that do not
7893 * have an explicit representation.
7894 */
isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map * bmap,int div)7895 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7896 int div)
7897 {
7898 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7899 return isl_bool_error;
7900 return isl_int_is_zero(bmap->div[div][0]);
7901 }
7902
7903 /* Return the position of the first local variable that does not
7904 * have an explicit representation.
7905 * Return the total number of local variables if they all have
7906 * an explicit representation.
7907 * Return -1 on error.
7908 */
isl_basic_map_first_unknown_div(__isl_keep isl_basic_map * bmap)7909 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7910 {
7911 int i;
7912
7913 if (!bmap)
7914 return -1;
7915
7916 for (i = 0; i < bmap->n_div; ++i) {
7917 if (!isl_basic_map_div_is_known(bmap, i))
7918 return i;
7919 }
7920 return bmap->n_div;
7921 }
7922
7923 /* Return the position of the first local variable that does not
7924 * have an explicit representation.
7925 * Return the total number of local variables if they all have
7926 * an explicit representation.
7927 * Return -1 on error.
7928 */
isl_basic_set_first_unknown_div(__isl_keep isl_basic_set * bset)7929 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7930 {
7931 return isl_basic_map_first_unknown_div(bset);
7932 }
7933
7934 /* Does "bmap" have an explicit representation for all local variables?
7935 */
isl_basic_map_divs_known(__isl_keep isl_basic_map * bmap)7936 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7937 {
7938 int first;
7939 isl_size n;
7940
7941 n = isl_basic_map_dim(bmap, isl_dim_div);
7942 first = isl_basic_map_first_unknown_div(bmap);
7943 if (n < 0 || first < 0)
7944 return isl_bool_error;
7945 return first == n;
7946 }
7947
7948 /* Do all basic maps in "map" have an explicit representation
7949 * for all local variables?
7950 */
isl_map_divs_known(__isl_keep isl_map * map)7951 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7952 {
7953 int i;
7954
7955 if (!map)
7956 return isl_bool_error;
7957
7958 for (i = 0; i < map->n; ++i) {
7959 int known = isl_basic_map_divs_known(map->p[i]);
7960 if (known <= 0)
7961 return known;
7962 }
7963
7964 return isl_bool_true;
7965 }
7966
7967 /* If bmap contains any unknown divs, then compute explicit
7968 * expressions for them. However, this computation may be
7969 * quite expensive, so first try to remove divs that aren't
7970 * strictly needed.
7971 */
isl_basic_map_compute_divs(__isl_take isl_basic_map * bmap)7972 __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7973 {
7974 int known;
7975 struct isl_map *map;
7976
7977 known = isl_basic_map_divs_known(bmap);
7978 if (known < 0)
7979 goto error;
7980 if (known)
7981 return isl_map_from_basic_map(bmap);
7982
7983 bmap = isl_basic_map_drop_redundant_divs(bmap);
7984
7985 known = isl_basic_map_divs_known(bmap);
7986 if (known < 0)
7987 goto error;
7988 if (known)
7989 return isl_map_from_basic_map(bmap);
7990
7991 map = compute_divs(bmap);
7992 return map;
7993 error:
7994 isl_basic_map_free(bmap);
7995 return NULL;
7996 }
7997
isl_map_compute_divs(__isl_take isl_map * map)7998 __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7999 {
8000 int i;
8001 int known;
8002 struct isl_map *res;
8003
8004 if (!map)
8005 return NULL;
8006 if (map->n == 0)
8007 return map;
8008
8009 known = isl_map_divs_known(map);
8010 if (known < 0) {
8011 isl_map_free(map);
8012 return NULL;
8013 }
8014 if (known)
8015 return map;
8016
8017 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
8018 for (i = 1 ; i < map->n; ++i) {
8019 struct isl_map *r2;
8020 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
8021 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
8022 res = isl_map_union_disjoint(res, r2);
8023 else
8024 res = isl_map_union(res, r2);
8025 }
8026 isl_map_free(map);
8027
8028 return res;
8029 }
8030
isl_basic_set_compute_divs(__isl_take isl_basic_set * bset)8031 __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
8032 {
8033 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
8034 }
8035
isl_set_compute_divs(__isl_take isl_set * set)8036 __isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set)
8037 {
8038 return set_from_map(isl_map_compute_divs(set_to_map(set)));
8039 }
8040
isl_map_domain(__isl_take isl_map * map)8041 __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
8042 {
8043 isl_space *space;
8044 isl_size n_out;
8045
8046 n_out = isl_map_dim(map, isl_dim_out);
8047 if (n_out < 0)
8048 return set_from_map(isl_map_free(map));
8049 space = isl_space_domain(isl_map_get_space(map));
8050
8051 map = isl_map_project_out(map, isl_dim_out, 0, n_out);
8052
8053 return set_from_map(isl_map_reset_space(map, space));
8054 }
8055
8056 /* Return the union of "map1" and "map2", where we assume for now that
8057 * "map1" and "map2" are disjoint. Note that the basic maps inside
8058 * "map1" or "map2" may not be disjoint from each other.
8059 * Also note that this function is also called from isl_map_union,
8060 * which takes care of handling the situation where "map1" and "map2"
8061 * may not be disjoint.
8062 *
8063 * If one of the inputs is empty, we can simply return the other input.
8064 * Similarly, if one of the inputs is universal, then it is equal to the union.
8065 */
map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8066 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
8067 __isl_take isl_map *map2)
8068 {
8069 int i;
8070 unsigned flags = 0;
8071 struct isl_map *map = NULL;
8072 int is_universe;
8073
8074 if (isl_map_check_equal_space(map1, map2) < 0)
8075 goto error;
8076
8077 if (map1->n == 0) {
8078 isl_map_free(map1);
8079 return map2;
8080 }
8081 if (map2->n == 0) {
8082 isl_map_free(map2);
8083 return map1;
8084 }
8085
8086 is_universe = isl_map_plain_is_universe(map1);
8087 if (is_universe < 0)
8088 goto error;
8089 if (is_universe) {
8090 isl_map_free(map2);
8091 return map1;
8092 }
8093
8094 is_universe = isl_map_plain_is_universe(map2);
8095 if (is_universe < 0)
8096 goto error;
8097 if (is_universe) {
8098 isl_map_free(map1);
8099 return map2;
8100 }
8101
8102 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
8103 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
8104 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8105
8106 map = isl_map_alloc_space(isl_space_copy(map1->dim),
8107 map1->n + map2->n, flags);
8108 if (!map)
8109 goto error;
8110 for (i = 0; i < map1->n; ++i) {
8111 map = isl_map_add_basic_map(map,
8112 isl_basic_map_copy(map1->p[i]));
8113 if (!map)
8114 goto error;
8115 }
8116 for (i = 0; i < map2->n; ++i) {
8117 map = isl_map_add_basic_map(map,
8118 isl_basic_map_copy(map2->p[i]));
8119 if (!map)
8120 goto error;
8121 }
8122 isl_map_free(map1);
8123 isl_map_free(map2);
8124 return map;
8125 error:
8126 isl_map_free(map);
8127 isl_map_free(map1);
8128 isl_map_free(map2);
8129 return NULL;
8130 }
8131
8132 /* Return the union of "map1" and "map2", where "map1" and "map2" are
8133 * guaranteed to be disjoint by the caller.
8134 *
8135 * Note that this functions is called from within isl_map_make_disjoint,
8136 * so we have to be careful not to touch the constraints of the inputs
8137 * in any way.
8138 */
isl_map_union_disjoint(__isl_take isl_map * map1,__isl_take isl_map * map2)8139 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
8140 __isl_take isl_map *map2)
8141 {
8142 isl_map_align_params_bin(&map1, &map2);
8143 return map_union_disjoint(map1, map2);
8144 }
8145
8146 /* Return the union of "map1" and "map2", where "map1" and "map2" may
8147 * not be disjoint.
8148 *
8149 * We currently simply call map_union_disjoint, the internal operation
8150 * of which does not really depend on the inputs being disjoint.
8151 * If the result contains more than one basic map, then we clear
8152 * the disjoint flag since the result may contain basic maps from
8153 * both inputs and these are not guaranteed to be disjoint.
8154 *
8155 * As a special case, if "map1" and "map2" are obviously equal,
8156 * then we simply return "map1".
8157 */
isl_map_union(__isl_take isl_map * map1,__isl_take isl_map * map2)8158 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
8159 __isl_take isl_map *map2)
8160 {
8161 int equal;
8162
8163 if (isl_map_align_params_bin(&map1, &map2) < 0)
8164 goto error;
8165
8166 equal = isl_map_plain_is_equal(map1, map2);
8167 if (equal < 0)
8168 goto error;
8169 if (equal) {
8170 isl_map_free(map2);
8171 return map1;
8172 }
8173
8174 map1 = map_union_disjoint(map1, map2);
8175 if (!map1)
8176 return NULL;
8177 if (map1->n > 1)
8178 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
8179 return map1;
8180 error:
8181 isl_map_free(map1);
8182 isl_map_free(map2);
8183 return NULL;
8184 }
8185
isl_set_union_disjoint(__isl_take isl_set * set1,__isl_take isl_set * set2)8186 __isl_give isl_set *isl_set_union_disjoint(
8187 __isl_take isl_set *set1, __isl_take isl_set *set2)
8188 {
8189 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
8190 set_to_map(set2)));
8191 }
8192
isl_set_union(__isl_take isl_set * set1,__isl_take isl_set * set2)8193 __isl_give isl_set *isl_set_union(__isl_take isl_set *set1,
8194 __isl_take isl_set *set2)
8195 {
8196 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
8197 }
8198
8199 /* Apply "fn" to pairs of elements from "map" and "set" and collect
8200 * the results in a map living in "space".
8201 *
8202 * "map" and "set" are assumed to be compatible and non-NULL.
8203 */
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))8204 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
8205 __isl_take isl_space *space, __isl_take isl_set *set,
8206 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
8207 __isl_take isl_basic_set *bset))
8208 {
8209 unsigned flags = 0;
8210 struct isl_map *result;
8211 int i, j;
8212
8213 if (isl_set_plain_is_universe(set)) {
8214 isl_set_free(set);
8215 return isl_map_reset_equal_dim_space(map, space);
8216 }
8217
8218 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
8219 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
8220 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8221
8222 result = isl_map_alloc_space(space, map->n * set->n, flags);
8223 for (i = 0; result && i < map->n; ++i)
8224 for (j = 0; j < set->n; ++j) {
8225 result = isl_map_add_basic_map(result,
8226 fn(isl_basic_map_copy(map->p[i]),
8227 isl_basic_set_copy(set->p[j])));
8228 if (!result)
8229 break;
8230 }
8231
8232 isl_map_free(map);
8233 isl_set_free(set);
8234 return result;
8235 }
8236
isl_map_intersect_range(__isl_take isl_map * map,__isl_take isl_set * set)8237 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
8238 __isl_take isl_set *set)
8239 {
8240 isl_bool ok;
8241 isl_space *space;
8242
8243 isl_map_align_params_set(&map, &set);
8244 ok = isl_map_compatible_range(map, set);
8245 if (ok < 0)
8246 goto error;
8247 if (!ok)
8248 isl_die(set->ctx, isl_error_invalid,
8249 "incompatible spaces", goto error);
8250
8251 space = isl_map_get_space(map);
8252 return map_intersect_set(map, space, set,
8253 &isl_basic_map_intersect_range);
8254 error:
8255 isl_map_free(map);
8256 isl_set_free(set);
8257 return NULL;
8258 }
8259
8260 /* Intersect the domain of "map" with "set".
8261 *
8262 * If the domain dimensions of "map" do not have any identifiers,
8263 * then copy them over from "set".
8264 */
isl_map_intersect_domain(__isl_take isl_map * map,__isl_take isl_set * set)8265 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
8266 __isl_take isl_set *set)
8267 {
8268 isl_bool ok;
8269 isl_space *space;
8270
8271 isl_map_align_params_set(&map, &set);
8272 ok = isl_map_compatible_domain(map, set);
8273 if (ok < 0)
8274 goto error;
8275 if (!ok)
8276 isl_die(set->ctx, isl_error_invalid,
8277 "incompatible spaces", goto error);
8278
8279 space = isl_map_get_space(map);
8280 space = isl_space_copy_ids_if_unset(space, isl_dim_in,
8281 isl_set_peek_space(set), isl_dim_set);
8282 return map_intersect_set(map, space, set,
8283 &isl_basic_map_intersect_domain);
8284 error:
8285 isl_map_free(map);
8286 isl_set_free(set);
8287 return NULL;
8288 }
8289
8290 /* Data structure that specifies how isl_map_intersect_factor
8291 * should operate.
8292 *
8293 * "preserve_type" is the tuple where the factor differs from
8294 * the input map and of which the identifiers needs
8295 * to be preserved explicitly.
8296 * "other_factor" is used to extract the space of the other factor
8297 * from the space of the product ("map").
8298 * "product" is used to combine the given factor and a universe map
8299 * in the space returned by "other_factor" to produce a map
8300 * that lives in the same space as the input map.
8301 */
8302 struct isl_intersect_factor_control {
8303 enum isl_dim_type preserve_type;
8304 __isl_give isl_space *(*other_factor)(__isl_take isl_space *space);
8305 __isl_give isl_map *(*product)(__isl_take isl_map *factor,
8306 __isl_take isl_map *other);
8307 };
8308
8309 /* Given a map "map" in some product space and a map "factor"
8310 * living in some factor space, return the intersection.
8311 *
8312 * After aligning the parameters,
8313 * the map "factor" is first extended to a map living in the same space
8314 * as "map" and then a regular intersection is computed.
8315 *
8316 * Note that the extension is computed as a product, which is anonymous
8317 * by default. If "map" has an identifier on the corresponding tuple,
8318 * then this identifier needs to be set on the product
8319 * before the intersection is computed.
8320 */
isl_map_intersect_factor(__isl_take isl_map * map,__isl_take isl_map * factor,struct isl_intersect_factor_control * control)8321 static __isl_give isl_map *isl_map_intersect_factor(
8322 __isl_take isl_map *map, __isl_take isl_map *factor,
8323 struct isl_intersect_factor_control *control)
8324 {
8325 isl_bool equal, has_id;
8326 isl_id *id;
8327 isl_space *space;
8328 isl_map *other, *product;
8329
8330 equal = isl_map_has_equal_params(map, factor);
8331 if (equal < 0)
8332 goto error;
8333 if (!equal) {
8334 map = isl_map_align_params(map, isl_map_get_space(factor));
8335 factor = isl_map_align_params(factor, isl_map_get_space(map));
8336 }
8337
8338 space = isl_map_get_space(map);
8339 has_id = isl_space_has_tuple_id(space, control->preserve_type);
8340 if (has_id < 0)
8341 space = isl_space_free(space);
8342 else if (has_id)
8343 id = isl_space_get_tuple_id(space, control->preserve_type);
8344
8345 other = isl_map_universe(control->other_factor(space));
8346 product = control->product(factor, other);
8347
8348 if (has_id >= 0 && has_id)
8349 product = isl_map_set_tuple_id(product,
8350 control->preserve_type, id);
8351
8352 return map_intersect(map, product);
8353 error:
8354 isl_map_free(map);
8355 isl_map_free(factor);
8356 return NULL;
8357 }
8358
8359 /* Return the domain product of "map2" and "map1".
8360 */
isl_map_reverse_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8361 static __isl_give isl_map *isl_map_reverse_domain_product(
8362 __isl_take isl_map *map1, __isl_take isl_map *map2)
8363 {
8364 return isl_map_domain_product(map2, map1);
8365 }
8366
8367 /* Return the range product of "map2" and "map1".
8368 */
isl_map_reverse_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)8369 static __isl_give isl_map *isl_map_reverse_range_product(
8370 __isl_take isl_map *map1, __isl_take isl_map *map2)
8371 {
8372 return isl_map_range_product(map2, map1);
8373 }
8374
8375 /* Given a map "map" in a space [A -> B] -> C and a map "factor"
8376 * in the space B -> C, return the intersection.
8377 */
isl_map_intersect_domain_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8378 __isl_give isl_map *isl_map_intersect_domain_factor_range(
8379 __isl_take isl_map *map, __isl_take isl_map *factor)
8380 {
8381 struct isl_intersect_factor_control control = {
8382 .preserve_type = isl_dim_in,
8383 .other_factor = isl_space_domain_factor_domain,
8384 .product = isl_map_reverse_domain_product,
8385 };
8386
8387 return isl_map_intersect_factor(map, factor, &control);
8388 }
8389
8390 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8391 * in the space A -> B, return the intersection.
8392 */
isl_map_intersect_range_factor_domain(__isl_take isl_map * map,__isl_take isl_map * factor)8393 __isl_give isl_map *isl_map_intersect_range_factor_domain(
8394 __isl_take isl_map *map, __isl_take isl_map *factor)
8395 {
8396 struct isl_intersect_factor_control control = {
8397 .preserve_type = isl_dim_out,
8398 .other_factor = isl_space_range_factor_range,
8399 .product = isl_map_range_product,
8400 };
8401
8402 return isl_map_intersect_factor(map, factor, &control);
8403 }
8404
8405 /* Given a map "map" in a space A -> [B -> C] and a map "factor"
8406 * in the space A -> C, return the intersection.
8407 */
isl_map_intersect_range_factor_range(__isl_take isl_map * map,__isl_take isl_map * factor)8408 __isl_give isl_map *isl_map_intersect_range_factor_range(
8409 __isl_take isl_map *map, __isl_take isl_map *factor)
8410 {
8411 struct isl_intersect_factor_control control = {
8412 .preserve_type = isl_dim_out,
8413 .other_factor = isl_space_range_factor_domain,
8414 .product = isl_map_reverse_range_product,
8415 };
8416
8417 return isl_map_intersect_factor(map, factor, &control);
8418 }
8419
8420 /* Given a set "set" in a space [A -> B] and a set "domain"
8421 * in the space A, return the intersection.
8422 *
8423 * The set "domain" is first extended to a set living in the space
8424 * [A -> B] and then a regular intersection is computed.
8425 */
isl_set_intersect_factor_domain(__isl_take isl_set * set,__isl_take isl_set * domain)8426 __isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
8427 __isl_take isl_set *domain)
8428 {
8429 struct isl_intersect_factor_control control = {
8430 .preserve_type = isl_dim_set,
8431 .other_factor = isl_space_factor_range,
8432 .product = isl_map_range_product,
8433 };
8434
8435 return set_from_map(isl_map_intersect_factor(set_to_map(set),
8436 set_to_map(domain), &control));
8437 }
8438
8439 /* Given a set "set" in a space [A -> B] and a set "range"
8440 * in the space B, return the intersection.
8441 *
8442 * The set "range" is first extended to a set living in the space
8443 * [A -> B] and then a regular intersection is computed.
8444 */
isl_set_intersect_factor_range(__isl_take isl_set * set,__isl_take isl_set * range)8445 __isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
8446 __isl_take isl_set *range)
8447 {
8448 struct isl_intersect_factor_control control = {
8449 .preserve_type = isl_dim_set,
8450 .other_factor = isl_space_factor_domain,
8451 .product = isl_map_reverse_range_product,
8452 };
8453
8454 return set_from_map(isl_map_intersect_factor(set_to_map(set),
8455 set_to_map(range), &control));
8456 }
8457
isl_map_apply_domain(__isl_take isl_map * map1,__isl_take isl_map * map2)8458 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8459 __isl_take isl_map *map2)
8460 {
8461 if (isl_map_align_params_bin(&map1, &map2) < 0)
8462 goto error;
8463 map1 = isl_map_reverse(map1);
8464 map1 = isl_map_apply_range(map1, map2);
8465 return isl_map_reverse(map1);
8466 error:
8467 isl_map_free(map1);
8468 isl_map_free(map2);
8469 return NULL;
8470 }
8471
isl_map_apply_range(__isl_take isl_map * map1,__isl_take isl_map * map2)8472 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8473 __isl_take isl_map *map2)
8474 {
8475 isl_space *space;
8476 struct isl_map *result;
8477 int i, j;
8478
8479 if (isl_map_align_params_bin(&map1, &map2) < 0)
8480 goto error;
8481
8482 space = isl_space_join(isl_space_copy(map1->dim),
8483 isl_space_copy(map2->dim));
8484
8485 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
8486 if (!result)
8487 goto error;
8488 for (i = 0; i < map1->n; ++i)
8489 for (j = 0; j < map2->n; ++j) {
8490 result = isl_map_add_basic_map(result,
8491 isl_basic_map_apply_range(
8492 isl_basic_map_copy(map1->p[i]),
8493 isl_basic_map_copy(map2->p[j])));
8494 if (!result)
8495 goto error;
8496 }
8497 isl_map_free(map1);
8498 isl_map_free(map2);
8499 if (result && result->n <= 1)
8500 ISL_F_SET(result, ISL_MAP_DISJOINT);
8501 return result;
8502 error:
8503 isl_map_free(map1);
8504 isl_map_free(map2);
8505 return NULL;
8506 }
8507
8508 /* Is "bmap" a transformation, i.e.,
8509 * does it relate elements from the same space.
8510 */
isl_basic_map_is_transformation(__isl_keep isl_basic_map * bmap)8511 isl_bool isl_basic_map_is_transformation(__isl_keep isl_basic_map *bmap)
8512 {
8513 isl_space *space;
8514
8515 space = isl_basic_map_peek_space(bmap);
8516 return isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8517 }
8518
8519 /* Check that "bmap" is a transformation, i.e.,
8520 * that it relates elements from the same space.
8521 */
isl_basic_map_check_transformation(__isl_keep isl_basic_map * bmap)8522 static isl_stat isl_basic_map_check_transformation(
8523 __isl_keep isl_basic_map *bmap)
8524 {
8525 isl_bool equal;
8526
8527 equal = isl_basic_map_is_transformation(bmap);
8528 if (equal < 0)
8529 return isl_stat_error;
8530 if (!equal)
8531 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
8532 "domain and range don't match", return isl_stat_error);
8533 return isl_stat_ok;
8534 }
8535
8536 /*
8537 * returns range - domain
8538 */
isl_basic_map_deltas(__isl_take isl_basic_map * bmap)8539 __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8540 {
8541 isl_space *target_space;
8542 struct isl_basic_set *bset;
8543 isl_size dim;
8544 isl_size nparam;
8545 isl_size total;
8546 int i;
8547
8548 if (isl_basic_map_check_transformation(bmap) < 0)
8549 return isl_basic_map_free(bmap);
8550 dim = isl_basic_map_dim(bmap, isl_dim_in);
8551 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8552 if (dim < 0 || nparam < 0)
8553 goto error;
8554 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8555 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8556 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8557 total = isl_basic_map_dim(bmap, isl_dim_all);
8558 if (total < 0)
8559 bmap = isl_basic_map_free(bmap);
8560 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8561 for (i = 0; i < dim; ++i) {
8562 int j = isl_basic_map_alloc_equality(bmap);
8563 if (j < 0) {
8564 bmap = isl_basic_map_free(bmap);
8565 break;
8566 }
8567 isl_seq_clr(bmap->eq[j], 1 + total);
8568 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8569 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8570 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8571 }
8572 bset = isl_basic_map_domain(bmap);
8573 bset = isl_basic_set_reset_space(bset, target_space);
8574 return bset;
8575 error:
8576 isl_basic_map_free(bmap);
8577 return NULL;
8578 }
8579
8580 /* Is the tuple of type "type1" of "map" the same as
8581 * the tuple of type "type2" of "space"?
8582 */
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)8583 isl_bool isl_map_space_tuple_is_equal(__isl_keep isl_map *map,
8584 enum isl_dim_type type1, __isl_keep isl_space *space,
8585 enum isl_dim_type type2)
8586 {
8587 isl_space *map_space;
8588
8589 map_space = isl_map_peek_space(map);
8590 return isl_space_tuple_is_equal(map_space, type1, space, type2);
8591 }
8592
8593 /* Is the tuple of type "type1" of "map1" the same as
8594 * the tuple of type "type2" of "map2"?
8595 */
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)8596 isl_bool isl_map_tuple_is_equal(__isl_keep isl_map *map1,
8597 enum isl_dim_type type1, __isl_keep isl_map *map2,
8598 enum isl_dim_type type2)
8599 {
8600 isl_space *space1, *space2;
8601
8602 space1 = isl_map_peek_space(map1);
8603 space2 = isl_map_peek_space(map2);
8604 return isl_space_tuple_is_equal(space1, type1, space2, type2);
8605 }
8606
8607 /* Check that "map" is a transformation, i.e.,
8608 * that it relates elements from the same space.
8609 */
isl_map_check_transformation(__isl_keep isl_map * map)8610 isl_stat isl_map_check_transformation(__isl_keep isl_map *map)
8611 {
8612 isl_bool equal;
8613
8614 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
8615 if (equal < 0)
8616 return isl_stat_error;
8617 if (!equal)
8618 isl_die(isl_map_get_ctx(map), isl_error_invalid,
8619 "domain and range don't match", return isl_stat_error);
8620 return isl_stat_ok;
8621 }
8622
8623 /*
8624 * returns range - domain
8625 */
isl_map_deltas(__isl_take isl_map * map)8626 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8627 {
8628 int i;
8629 isl_space *space;
8630 struct isl_set *result;
8631
8632 if (isl_map_check_transformation(map) < 0)
8633 goto error;
8634 space = isl_map_get_space(map);
8635 space = isl_space_domain(space);
8636 result = isl_set_alloc_space(space, map->n, 0);
8637 if (!result)
8638 goto error;
8639 for (i = 0; i < map->n; ++i)
8640 result = isl_set_add_basic_set(result,
8641 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8642 isl_map_free(map);
8643 return result;
8644 error:
8645 isl_map_free(map);
8646 return NULL;
8647 }
8648
8649 /*
8650 * returns [domain -> range] -> range - domain
8651 */
isl_basic_map_deltas_map(__isl_take isl_basic_map * bmap)8652 __isl_give isl_basic_map *isl_basic_map_deltas_map(
8653 __isl_take isl_basic_map *bmap)
8654 {
8655 int i, k;
8656 isl_space *space;
8657 isl_basic_map *domain;
8658 isl_size nparam, n;
8659 isl_size total;
8660
8661 if (isl_basic_map_check_transformation(bmap) < 0)
8662 return isl_basic_map_free(bmap);
8663
8664 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8665 n = isl_basic_map_dim(bmap, isl_dim_in);
8666 if (nparam < 0 || n < 0)
8667 return isl_basic_map_free(bmap);
8668
8669 space = isl_basic_map_get_space(bmap);
8670 space = isl_space_from_range(isl_space_domain(space));
8671 domain = isl_basic_map_universe(space);
8672
8673 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8674 bmap = isl_basic_map_apply_range(bmap, domain);
8675 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8676
8677 total = isl_basic_map_dim(bmap, isl_dim_all);
8678 if (total < 0)
8679 return isl_basic_map_free(bmap);
8680
8681 for (i = 0; i < n; ++i) {
8682 k = isl_basic_map_alloc_equality(bmap);
8683 if (k < 0)
8684 goto error;
8685 isl_seq_clr(bmap->eq[k], 1 + total);
8686 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8687 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8688 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8689 }
8690
8691 bmap = isl_basic_map_gauss(bmap, NULL);
8692 return isl_basic_map_finalize(bmap);
8693 error:
8694 isl_basic_map_free(bmap);
8695 return NULL;
8696 }
8697
8698 /*
8699 * returns [domain -> range] -> range - domain
8700 */
isl_map_deltas_map(__isl_take isl_map * map)8701 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8702 {
8703 if (isl_map_check_transformation(map) < 0)
8704 return isl_map_free(map);
8705
8706 return isl_map_transform(map, &isl_space_range_map,
8707 &isl_basic_map_deltas_map);
8708 }
8709
isl_basic_map_identity(__isl_take isl_space * space)8710 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8711 {
8712 isl_size n_in, n_out;
8713
8714 n_in = isl_space_dim(space, isl_dim_in);
8715 n_out = isl_space_dim(space, isl_dim_out);
8716 if (n_in < 0 || n_out < 0)
8717 goto error;
8718 if (n_in != n_out)
8719 isl_die(space->ctx, isl_error_invalid,
8720 "number of input and output dimensions needs to be "
8721 "the same", goto error);
8722 return isl_basic_map_equal(space, n_in);
8723 error:
8724 isl_space_free(space);
8725 return NULL;
8726 }
8727
isl_map_identity(__isl_take isl_space * space)8728 __isl_give isl_map *isl_map_identity(__isl_take isl_space *space)
8729 {
8730 return isl_map_from_basic_map(isl_basic_map_identity(space));
8731 }
8732
isl_set_identity(__isl_take isl_set * set)8733 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8734 {
8735 isl_space *space = isl_set_get_space(set);
8736 isl_map *id;
8737 id = isl_map_identity(isl_space_map_from_set(space));
8738 return isl_map_intersect_range(id, set);
8739 }
8740
8741 /* Construct a basic set with all set dimensions having only non-negative
8742 * values.
8743 */
isl_basic_set_positive_orthant(__isl_take isl_space * space)8744 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
8745 __isl_take isl_space *space)
8746 {
8747 int i;
8748 isl_size nparam;
8749 isl_size dim;
8750 isl_size total;
8751 struct isl_basic_set *bset;
8752
8753 nparam = isl_space_dim(space, isl_dim_param);
8754 dim = isl_space_dim(space, isl_dim_set);
8755 total = isl_space_dim(space, isl_dim_all);
8756 if (nparam < 0 || dim < 0 || total < 0)
8757 space = isl_space_free(space);
8758 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8759 if (!bset)
8760 return NULL;
8761 for (i = 0; i < dim; ++i) {
8762 int k = isl_basic_set_alloc_inequality(bset);
8763 if (k < 0)
8764 goto error;
8765 isl_seq_clr(bset->ineq[k], 1 + total);
8766 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8767 }
8768 return bset;
8769 error:
8770 isl_basic_set_free(bset);
8771 return NULL;
8772 }
8773
8774 /* Construct the half-space x_pos >= 0.
8775 */
nonneg_halfspace(__isl_take isl_space * space,int pos)8776 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8777 int pos)
8778 {
8779 int k;
8780 isl_size total;
8781 isl_basic_set *nonneg;
8782
8783 total = isl_space_dim(space, isl_dim_all);
8784 if (total < 0)
8785 space = isl_space_free(space);
8786 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8787 k = isl_basic_set_alloc_inequality(nonneg);
8788 if (k < 0)
8789 goto error;
8790 isl_seq_clr(nonneg->ineq[k], 1 + total);
8791 isl_int_set_si(nonneg->ineq[k][pos], 1);
8792
8793 return isl_basic_set_finalize(nonneg);
8794 error:
8795 isl_basic_set_free(nonneg);
8796 return NULL;
8797 }
8798
8799 /* Construct the half-space x_pos <= -1.
8800 */
neg_halfspace(__isl_take isl_space * space,int pos)8801 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8802 int pos)
8803 {
8804 int k;
8805 isl_size total;
8806 isl_basic_set *neg;
8807
8808 total = isl_space_dim(space, isl_dim_all);
8809 if (total < 0)
8810 space = isl_space_free(space);
8811 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8812 k = isl_basic_set_alloc_inequality(neg);
8813 if (k < 0)
8814 goto error;
8815 isl_seq_clr(neg->ineq[k], 1 + total);
8816 isl_int_set_si(neg->ineq[k][0], -1);
8817 isl_int_set_si(neg->ineq[k][pos], -1);
8818
8819 return isl_basic_set_finalize(neg);
8820 error:
8821 isl_basic_set_free(neg);
8822 return NULL;
8823 }
8824
isl_set_split_dims(__isl_take isl_set * set,enum isl_dim_type type,unsigned first,unsigned n)8825 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8826 enum isl_dim_type type, unsigned first, unsigned n)
8827 {
8828 int i;
8829 unsigned offset;
8830 isl_basic_set *nonneg;
8831 isl_basic_set *neg;
8832
8833 if (n == 0)
8834 return set;
8835
8836 if (isl_set_check_range(set, type, first, n) < 0)
8837 return isl_set_free(set);
8838
8839 offset = pos(set->dim, type);
8840 for (i = 0; i < n; ++i) {
8841 nonneg = nonneg_halfspace(isl_set_get_space(set),
8842 offset + first + i);
8843 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8844
8845 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8846 }
8847
8848 return set;
8849 }
8850
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)8851 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8852 int len,
8853 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8854 void *user)
8855 {
8856 isl_set *half;
8857
8858 if (!set)
8859 return isl_stat_error;
8860 if (isl_set_plain_is_empty(set)) {
8861 isl_set_free(set);
8862 return isl_stat_ok;
8863 }
8864 if (first == len)
8865 return fn(set, signs, user);
8866
8867 signs[first] = 1;
8868 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8869 1 + first));
8870 half = isl_set_intersect(half, isl_set_copy(set));
8871 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8872 goto error;
8873
8874 signs[first] = -1;
8875 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8876 1 + first));
8877 half = isl_set_intersect(half, set);
8878 return foreach_orthant(half, signs, first + 1, len, fn, user);
8879 error:
8880 isl_set_free(set);
8881 return isl_stat_error;
8882 }
8883
8884 /* Call "fn" on the intersections of "set" with each of the orthants
8885 * (except for obviously empty intersections). The orthant is identified
8886 * by the signs array, with each entry having value 1 or -1 according
8887 * to the sign of the corresponding variable.
8888 */
isl_set_foreach_orthant(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_set * orthant,int * signs,void * user),void * user)8889 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8890 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8891 void *user)
8892 {
8893 isl_size nparam;
8894 isl_size nvar;
8895 int *signs;
8896 isl_stat r;
8897
8898 if (!set)
8899 return isl_stat_error;
8900 if (isl_set_plain_is_empty(set))
8901 return isl_stat_ok;
8902
8903 nparam = isl_set_dim(set, isl_dim_param);
8904 nvar = isl_set_dim(set, isl_dim_set);
8905 if (nparam < 0 || nvar < 0)
8906 return isl_stat_error;
8907
8908 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8909
8910 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8911 fn, user);
8912
8913 free(signs);
8914
8915 return r;
8916 }
8917
isl_set_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)8918 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8919 {
8920 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8921 }
8922
isl_basic_map_is_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8923 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8924 __isl_keep isl_basic_map *bmap2)
8925 {
8926 isl_bool is_subset;
8927 struct isl_map *map1;
8928 struct isl_map *map2;
8929
8930 if (!bmap1 || !bmap2)
8931 return isl_bool_error;
8932
8933 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8934 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8935
8936 is_subset = isl_map_is_subset(map1, map2);
8937
8938 isl_map_free(map1);
8939 isl_map_free(map2);
8940
8941 return is_subset;
8942 }
8943
isl_basic_set_is_subset(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8944 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8945 __isl_keep isl_basic_set *bset2)
8946 {
8947 return isl_basic_map_is_subset(bset1, bset2);
8948 }
8949
isl_basic_map_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)8950 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8951 __isl_keep isl_basic_map *bmap2)
8952 {
8953 isl_bool is_subset;
8954
8955 if (!bmap1 || !bmap2)
8956 return isl_bool_error;
8957 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8958 if (is_subset != isl_bool_true)
8959 return is_subset;
8960 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8961 return is_subset;
8962 }
8963
isl_basic_set_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)8964 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8965 __isl_keep isl_basic_set *bset2)
8966 {
8967 return isl_basic_map_is_equal(
8968 bset_to_bmap(bset1), bset_to_bmap(bset2));
8969 }
8970
isl_map_is_empty(__isl_keep isl_map * map)8971 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
8972 {
8973 int i;
8974 int is_empty;
8975
8976 if (!map)
8977 return isl_bool_error;
8978 for (i = 0; i < map->n; ++i) {
8979 is_empty = isl_basic_map_is_empty(map->p[i]);
8980 if (is_empty < 0)
8981 return isl_bool_error;
8982 if (!is_empty)
8983 return isl_bool_false;
8984 }
8985 return isl_bool_true;
8986 }
8987
isl_map_plain_is_empty(__isl_keep isl_map * map)8988 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
8989 {
8990 return map ? map->n == 0 : isl_bool_error;
8991 }
8992
isl_set_plain_is_empty(__isl_keep isl_set * set)8993 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
8994 {
8995 return set ? set->n == 0 : isl_bool_error;
8996 }
8997
isl_set_is_empty(__isl_keep isl_set * set)8998 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
8999 {
9000 return isl_map_is_empty(set_to_map(set));
9001 }
9002
9003 #undef TYPE
9004 #define TYPE isl_basic_map
9005
9006 static
9007 #include "isl_type_has_equal_space_bin_templ.c"
9008 #include "isl_type_check_equal_space_templ.c"
9009
9010 /* Check that "bset1" and "bset2" live in the same space,
9011 * reporting an error if they do not.
9012 */
isl_basic_set_check_equal_space(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)9013 isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
9014 __isl_keep isl_basic_set *bset2)
9015 {
9016 return isl_basic_map_check_equal_space(bset_to_bmap(bset1),
9017 bset_to_bmap(bset1));
9018 }
9019
9020 #undef TYPE
9021 #define TYPE isl_map
9022
9023 #include "isl_type_has_equal_space_bin_templ.c"
9024 #include "isl_type_check_equal_space_templ.c"
9025
isl_set_has_equal_space(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9026 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
9027 __isl_keep isl_set *set2)
9028 {
9029 return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));
9030 }
9031
9032 #undef TYPE1
9033 #define TYPE1 isl_map
9034 #undef TYPE2
9035 #define TYPE2 isl_basic_map
9036 #undef TYPE_PAIR
9037 #define TYPE_PAIR isl_map_basic_map
9038
9039 static
9040 #include "isl_type_has_equal_space_templ.c"
9041 #include "isl_type_check_equal_space_templ.c"
9042
9043 /* Check that "set" and "bset" live in the same space,
9044 * reporting an error if they do not.
9045 */
isl_set_basic_set_check_equal_space(__isl_keep isl_set * set,__isl_keep isl_basic_set * bset)9046 isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
9047 __isl_keep isl_basic_set *bset)
9048 {
9049 return isl_map_basic_map_check_equal_space(set_to_map(set),
9050 bset_to_bmap(bset));
9051 }
9052
map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9053 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9054 {
9055 isl_bool is_subset;
9056
9057 if (!map1 || !map2)
9058 return isl_bool_error;
9059 is_subset = isl_map_is_subset(map1, map2);
9060 if (is_subset != isl_bool_true)
9061 return is_subset;
9062 is_subset = isl_map_is_subset(map2, map1);
9063 return is_subset;
9064 }
9065
9066 /* Is "map1" equal to "map2"?
9067 *
9068 * First check if they are obviously equal.
9069 * If not, then perform a more detailed analysis.
9070 */
isl_map_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9071 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9072 {
9073 isl_bool equal;
9074
9075 equal = isl_map_plain_is_equal(map1, map2);
9076 if (equal < 0 || equal)
9077 return equal;
9078 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
9079 }
9080
isl_basic_map_is_strict_subset(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)9081 isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
9082 __isl_keep isl_basic_map *bmap2)
9083 {
9084 isl_bool is_subset;
9085
9086 if (!bmap1 || !bmap2)
9087 return isl_bool_error;
9088 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9089 if (is_subset != isl_bool_true)
9090 return is_subset;
9091 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9092 return isl_bool_not(is_subset);
9093 }
9094
isl_map_is_strict_subset(__isl_keep isl_map * map1,__isl_keep isl_map * map2)9095 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
9096 __isl_keep isl_map *map2)
9097 {
9098 isl_bool is_subset;
9099
9100 if (!map1 || !map2)
9101 return isl_bool_error;
9102 is_subset = isl_map_is_subset(map1, map2);
9103 if (is_subset != isl_bool_true)
9104 return is_subset;
9105 is_subset = isl_map_is_subset(map2, map1);
9106 return isl_bool_not(is_subset);
9107 }
9108
isl_set_is_strict_subset(__isl_keep isl_set * set1,__isl_keep isl_set * set2)9109 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
9110 __isl_keep isl_set *set2)
9111 {
9112 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
9113 }
9114
9115 /* Is "bmap" obviously equal to the universe with the same space?
9116 *
9117 * That is, does it not have any constraints?
9118 */
isl_basic_map_plain_is_universe(__isl_keep isl_basic_map * bmap)9119 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
9120 {
9121 if (!bmap)
9122 return isl_bool_error;
9123 return bmap->n_eq == 0 && bmap->n_ineq == 0;
9124 }
9125
9126 /* Is "bset" obviously equal to the universe with the same space?
9127 */
isl_basic_set_plain_is_universe(__isl_keep isl_basic_set * bset)9128 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
9129 {
9130 return isl_basic_map_plain_is_universe(bset);
9131 }
9132
9133 /* If "c" does not involve any existentially quantified variables,
9134 * then set *univ to false and abort
9135 */
involves_divs(__isl_take isl_constraint * c,void * user)9136 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
9137 {
9138 isl_bool *univ = user;
9139 isl_size n;
9140
9141 n = isl_constraint_dim(c, isl_dim_div);
9142 if (n < 0)
9143 c = isl_constraint_free(c);
9144 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
9145 isl_constraint_free(c);
9146 if (*univ < 0 || !*univ)
9147 return isl_stat_error;
9148 return isl_stat_ok;
9149 }
9150
9151 /* Is "bmap" equal to the universe with the same space?
9152 *
9153 * First check if it is obviously equal to the universe.
9154 * If not and if there are any constraints not involving
9155 * existentially quantified variables, then it is certainly
9156 * not equal to the universe.
9157 * Otherwise, check if the universe is a subset of "bmap".
9158 */
isl_basic_map_is_universe(__isl_keep isl_basic_map * bmap)9159 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
9160 {
9161 isl_size n_div;
9162 isl_bool univ;
9163 isl_basic_map *test;
9164
9165 univ = isl_basic_map_plain_is_universe(bmap);
9166 if (univ < 0 || univ)
9167 return univ;
9168 n_div = isl_basic_map_dim(bmap, isl_dim_div);
9169 if (n_div < 0)
9170 return isl_bool_error;
9171 if (n_div == 0)
9172 return isl_bool_false;
9173 univ = isl_bool_true;
9174 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
9175 univ)
9176 return isl_bool_error;
9177 if (univ < 0 || !univ)
9178 return univ;
9179 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
9180 univ = isl_basic_map_is_subset(test, bmap);
9181 isl_basic_map_free(test);
9182 return univ;
9183 }
9184
9185 /* Is "bset" equal to the universe with the same space?
9186 */
isl_basic_set_is_universe(__isl_keep isl_basic_set * bset)9187 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
9188 {
9189 return isl_basic_map_is_universe(bset);
9190 }
9191
isl_map_plain_is_universe(__isl_keep isl_map * map)9192 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
9193 {
9194 int i;
9195
9196 if (!map)
9197 return isl_bool_error;
9198
9199 for (i = 0; i < map->n; ++i) {
9200 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
9201 if (r < 0 || r)
9202 return r;
9203 }
9204
9205 return isl_bool_false;
9206 }
9207
isl_set_plain_is_universe(__isl_keep isl_set * set)9208 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
9209 {
9210 return isl_map_plain_is_universe(set_to_map(set));
9211 }
9212
isl_basic_map_is_empty(__isl_keep isl_basic_map * bmap)9213 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
9214 {
9215 struct isl_basic_set *bset = NULL;
9216 struct isl_vec *sample = NULL;
9217 isl_bool empty, non_empty;
9218
9219 if (!bmap)
9220 return isl_bool_error;
9221
9222 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
9223 return isl_bool_true;
9224
9225 if (isl_basic_map_plain_is_universe(bmap))
9226 return isl_bool_false;
9227
9228 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
9229 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
9230 copy = isl_basic_map_remove_redundancies(copy);
9231 empty = isl_basic_map_plain_is_empty(copy);
9232 isl_basic_map_free(copy);
9233 return empty;
9234 }
9235
9236 non_empty = isl_basic_map_plain_is_non_empty(bmap);
9237 if (non_empty < 0)
9238 return isl_bool_error;
9239 if (non_empty)
9240 return isl_bool_false;
9241 isl_vec_free(bmap->sample);
9242 bmap->sample = NULL;
9243 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
9244 if (!bset)
9245 return isl_bool_error;
9246 sample = isl_basic_set_sample_vec(bset);
9247 if (!sample)
9248 return isl_bool_error;
9249 empty = sample->size == 0;
9250 isl_vec_free(bmap->sample);
9251 bmap->sample = sample;
9252 if (empty)
9253 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
9254
9255 return empty;
9256 }
9257
isl_basic_map_plain_is_empty(__isl_keep isl_basic_map * bmap)9258 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
9259 {
9260 if (!bmap)
9261 return isl_bool_error;
9262 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
9263 }
9264
isl_basic_set_plain_is_empty(__isl_keep isl_basic_set * bset)9265 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
9266 {
9267 if (!bset)
9268 return isl_bool_error;
9269 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
9270 }
9271
9272 /* Is "bmap" known to be non-empty?
9273 *
9274 * That is, is the cached sample still valid?
9275 */
isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map * bmap)9276 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
9277 {
9278 isl_size total;
9279
9280 if (!bmap)
9281 return isl_bool_error;
9282 if (!bmap->sample)
9283 return isl_bool_false;
9284 total = isl_basic_map_dim(bmap, isl_dim_all);
9285 if (total < 0)
9286 return isl_bool_error;
9287 if (bmap->sample->size != 1 + total)
9288 return isl_bool_false;
9289 return isl_basic_map_contains(bmap, bmap->sample);
9290 }
9291
isl_basic_set_is_empty(__isl_keep isl_basic_set * bset)9292 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
9293 {
9294 return isl_basic_map_is_empty(bset_to_bmap(bset));
9295 }
9296
isl_basic_map_union(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)9297 __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
9298 __isl_take isl_basic_map *bmap2)
9299 {
9300 struct isl_map *map;
9301
9302 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
9303 goto error;
9304
9305 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
9306 if (!map)
9307 goto error;
9308 map = isl_map_add_basic_map(map, bmap1);
9309 map = isl_map_add_basic_map(map, bmap2);
9310 return map;
9311 error:
9312 isl_basic_map_free(bmap1);
9313 isl_basic_map_free(bmap2);
9314 return NULL;
9315 }
9316
isl_basic_set_union(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)9317 __isl_give isl_set *isl_basic_set_union(__isl_take isl_basic_set *bset1,
9318 __isl_take isl_basic_set *bset2)
9319 {
9320 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
9321 bset_to_bmap(bset2)));
9322 }
9323
9324 /* Order divs such that any div only depends on previous divs */
isl_basic_map_order_divs(__isl_take isl_basic_map * bmap)9325 __isl_give isl_basic_map *isl_basic_map_order_divs(
9326 __isl_take isl_basic_map *bmap)
9327 {
9328 int i;
9329 isl_size off;
9330
9331 off = isl_basic_map_var_offset(bmap, isl_dim_div);
9332 if (off < 0)
9333 return isl_basic_map_free(bmap);
9334
9335 for (i = 0; i < bmap->n_div; ++i) {
9336 int pos;
9337 if (isl_int_is_zero(bmap->div[i][0]))
9338 continue;
9339 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
9340 bmap->n_div-i);
9341 if (pos == -1)
9342 continue;
9343 if (pos == 0)
9344 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
9345 "integer division depends on itself",
9346 return isl_basic_map_free(bmap));
9347 bmap = isl_basic_map_swap_div(bmap, i, i + pos);
9348 if (!bmap)
9349 return NULL;
9350 --i;
9351 }
9352 return bmap;
9353 }
9354
isl_map_order_divs(__isl_take isl_map * map)9355 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
9356 {
9357 int i;
9358
9359 if (!map)
9360 return 0;
9361
9362 for (i = 0; i < map->n; ++i) {
9363 map->p[i] = isl_basic_map_order_divs(map->p[i]);
9364 if (!map->p[i])
9365 goto error;
9366 }
9367
9368 return map;
9369 error:
9370 isl_map_free(map);
9371 return NULL;
9372 }
9373
9374 /* Sort the local variables of "bset".
9375 */
isl_basic_set_sort_divs(__isl_take isl_basic_set * bset)9376 __isl_give isl_basic_set *isl_basic_set_sort_divs(
9377 __isl_take isl_basic_set *bset)
9378 {
9379 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
9380 }
9381
9382 /* Apply the expansion computed by isl_merge_divs.
9383 * The expansion itself is given by "exp" while the resulting
9384 * list of divs is given by "div".
9385 *
9386 * Move the integer divisions of "bmap" into the right position
9387 * according to "exp" and then introduce the additional integer
9388 * divisions, adding div constraints.
9389 * The moving should be done first to avoid moving coefficients
9390 * in the definitions of the extra integer divisions.
9391 */
isl_basic_map_expand_divs(__isl_take isl_basic_map * bmap,__isl_take isl_mat * div,int * exp)9392 __isl_give isl_basic_map *isl_basic_map_expand_divs(
9393 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
9394 {
9395 int i, j;
9396 int n_div;
9397
9398 bmap = isl_basic_map_cow(bmap);
9399 if (!bmap || !div)
9400 goto error;
9401
9402 if (div->n_row < bmap->n_div)
9403 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
9404 "not an expansion", goto error);
9405
9406 n_div = bmap->n_div;
9407 bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,
9408 2 * (div->n_row - n_div));
9409
9410 for (i = n_div; i < div->n_row; ++i)
9411 if (isl_basic_map_alloc_div(bmap) < 0)
9412 goto error;
9413
9414 for (j = n_div - 1; j >= 0; --j) {
9415 if (exp[j] == j)
9416 break;
9417 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
9418 if (!bmap)
9419 goto error;
9420 }
9421 j = 0;
9422 for (i = 0; i < div->n_row; ++i) {
9423 if (j < n_div && exp[j] == i) {
9424 j++;
9425 } else {
9426 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
9427 if (isl_basic_map_div_is_marked_unknown(bmap, i))
9428 continue;
9429 bmap = isl_basic_map_add_div_constraints(bmap, i);
9430 if (!bmap)
9431 goto error;
9432 }
9433 }
9434
9435 isl_mat_free(div);
9436 return bmap;
9437 error:
9438 isl_basic_map_free(bmap);
9439 isl_mat_free(div);
9440 return NULL;
9441 }
9442
9443 /* Apply the expansion computed by isl_merge_divs.
9444 * The expansion itself is given by "exp" while the resulting
9445 * list of divs is given by "div".
9446 */
isl_basic_set_expand_divs(__isl_take isl_basic_set * bset,__isl_take isl_mat * div,int * exp)9447 __isl_give isl_basic_set *isl_basic_set_expand_divs(
9448 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
9449 {
9450 return isl_basic_map_expand_divs(bset, div, exp);
9451 }
9452
9453 /* Look for a div in dst that corresponds to the div "div" in src.
9454 * The divs before "div" in src and dst are assumed to be the same.
9455 *
9456 * Return the position of the corresponding div in dst
9457 * if there is one. Otherwise, return a position beyond the integer divisions.
9458 * Return -1 on error.
9459 */
find_div(__isl_keep isl_basic_map * dst,__isl_keep isl_basic_map * src,unsigned div)9460 static int find_div(__isl_keep isl_basic_map *dst,
9461 __isl_keep isl_basic_map *src, unsigned div)
9462 {
9463 int i;
9464 isl_size n_div;
9465 isl_size v_div;
9466
9467 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9468 n_div = isl_basic_map_dim(dst, isl_dim_div);
9469 if (n_div < 0 || v_div < 0)
9470 return -1;
9471 isl_assert(dst->ctx, div <= n_div, return -1);
9472 for (i = div; i < n_div; ++i)
9473 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
9474 isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
9475 n_div - div) == -1)
9476 return i;
9477 return n_div;
9478 }
9479
9480 /* Align the divs of "dst" to those of "src", adding divs from "src"
9481 * if needed. That is, make sure that the first src->n_div divs
9482 * of the result are equal to those of src.
9483 *
9484 * The result is not finalized as by design it will have redundant
9485 * divs if any divs from "src" were copied.
9486 */
isl_basic_map_align_divs(__isl_take isl_basic_map * dst,__isl_keep isl_basic_map * src)9487 __isl_give isl_basic_map *isl_basic_map_align_divs(
9488 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
9489 {
9490 int i;
9491 isl_bool known;
9492 int extended;
9493 isl_size v_div;
9494 isl_size dst_n_div;
9495
9496 if (!dst || !src)
9497 return isl_basic_map_free(dst);
9498
9499 if (src->n_div == 0)
9500 return dst;
9501
9502 known = isl_basic_map_divs_known(src);
9503 if (known < 0)
9504 return isl_basic_map_free(dst);
9505 if (!known)
9506 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9507 "some src divs are unknown",
9508 return isl_basic_map_free(dst));
9509
9510 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9511 if (v_div < 0)
9512 return isl_basic_map_free(dst);
9513
9514 src = isl_basic_map_order_divs(isl_basic_map_copy(src));
9515 if (!src)
9516 return isl_basic_map_free(dst);
9517
9518 extended = 0;
9519 dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
9520 if (dst_n_div < 0)
9521 dst = isl_basic_map_free(dst);
9522 for (i = 0; i < src->n_div; ++i) {
9523 int j = find_div(dst, src, i);
9524 if (j < 0)
9525 dst = isl_basic_map_free(dst);
9526 if (j == dst_n_div) {
9527 if (!extended) {
9528 int extra = src->n_div - i;
9529 dst = isl_basic_map_cow(dst);
9530 if (!dst)
9531 goto error;
9532 dst = isl_basic_map_extend(dst,
9533 extra, 0, 2 * extra);
9534 extended = 1;
9535 }
9536 j = isl_basic_map_alloc_div(dst);
9537 if (j < 0)
9538 goto error;
9539 isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
9540 isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
9541 dst_n_div++;
9542 dst = isl_basic_map_add_div_constraints(dst, j);
9543 if (!dst)
9544 goto error;
9545 }
9546 if (j != i)
9547 dst = isl_basic_map_swap_div(dst, i, j);
9548 if (!dst)
9549 goto error;
9550 }
9551 isl_basic_map_free(src);
9552 return dst;
9553 error:
9554 isl_basic_map_free(src);
9555 isl_basic_map_free(dst);
9556 return NULL;
9557 }
9558
isl_map_align_divs_internal(__isl_take isl_map * map)9559 __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9560 {
9561 int i;
9562
9563 if (!map)
9564 return NULL;
9565 if (map->n == 0)
9566 return map;
9567 map = isl_map_compute_divs(map);
9568 map = isl_map_cow(map);
9569 if (!map)
9570 return NULL;
9571
9572 for (i = 1; i < map->n; ++i)
9573 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9574 for (i = 1; i < map->n; ++i) {
9575 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9576 if (!map->p[i])
9577 return isl_map_free(map);
9578 }
9579
9580 map = isl_map_unmark_normalized(map);
9581 return map;
9582 }
9583
isl_map_align_divs(__isl_take isl_map * map)9584 __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9585 {
9586 return isl_map_align_divs_internal(map);
9587 }
9588
isl_set_align_divs(__isl_take isl_set * set)9589 __isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set)
9590 {
9591 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9592 }
9593
9594 /* Align the divs of the basic maps in "map" to those
9595 * of the basic maps in "list", as well as to the other basic maps in "map".
9596 * The elements in "list" are assumed to have known divs.
9597 */
isl_map_align_divs_to_basic_map_list(__isl_take isl_map * map,__isl_keep isl_basic_map_list * list)9598 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9599 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9600 {
9601 int i;
9602 isl_size n;
9603
9604 n = isl_basic_map_list_n_basic_map(list);
9605 map = isl_map_compute_divs(map);
9606 map = isl_map_cow(map);
9607 if (!map || n < 0)
9608 return isl_map_free(map);
9609 if (map->n == 0)
9610 return map;
9611
9612 for (i = 0; i < n; ++i) {
9613 isl_basic_map *bmap;
9614
9615 bmap = isl_basic_map_list_get_basic_map(list, i);
9616 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9617 isl_basic_map_free(bmap);
9618 }
9619 if (!map->p[0])
9620 return isl_map_free(map);
9621
9622 return isl_map_align_divs_internal(map);
9623 }
9624
9625 /* Align the divs of each element of "list" to those of "bmap".
9626 * Both "bmap" and the elements of "list" are assumed to have known divs.
9627 */
isl_basic_map_list_align_divs_to_basic_map(__isl_take isl_basic_map_list * list,__isl_keep isl_basic_map * bmap)9628 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9629 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9630 {
9631 int i;
9632 isl_size n;
9633
9634 n = isl_basic_map_list_n_basic_map(list);
9635 if (n < 0 || !bmap)
9636 return isl_basic_map_list_free(list);
9637
9638 for (i = 0; i < n; ++i) {
9639 isl_basic_map *bmap_i;
9640
9641 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9642 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9643 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9644 }
9645
9646 return list;
9647 }
9648
isl_set_apply(__isl_take isl_set * set,__isl_take isl_map * map)9649 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9650 __isl_take isl_map *map)
9651 {
9652 isl_bool ok;
9653
9654 isl_map_align_params_set(&map, &set);
9655 ok = isl_map_compatible_domain(map, set);
9656 if (ok < 0)
9657 goto error;
9658 if (!ok)
9659 isl_die(isl_set_get_ctx(set), isl_error_invalid,
9660 "incompatible spaces", goto error);
9661 map = isl_map_intersect_domain(map, set);
9662 set = isl_map_range(map);
9663 return set;
9664 error:
9665 isl_set_free(set);
9666 isl_map_free(map);
9667 return NULL;
9668 }
9669
9670 /* There is no need to cow as removing empty parts doesn't change
9671 * the meaning of the set.
9672 */
isl_map_remove_empty_parts(__isl_take isl_map * map)9673 __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9674 {
9675 int i;
9676
9677 if (!map)
9678 return NULL;
9679
9680 for (i = map->n - 1; i >= 0; --i)
9681 map = remove_if_empty(map, i);
9682
9683 return map;
9684 }
9685
isl_set_remove_empty_parts(__isl_take isl_set * set)9686 __isl_give isl_set *isl_set_remove_empty_parts(__isl_take isl_set *set)
9687 {
9688 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9689 }
9690
9691 /* Create a binary relation that maps the shared initial "pos" dimensions
9692 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9693 */
join_initial(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9694 static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9695 __isl_keep isl_basic_set *bset2, int pos)
9696 {
9697 isl_basic_map *bmap1;
9698 isl_basic_map *bmap2;
9699
9700 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9701 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9702 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9703 isl_dim_out, 0, pos);
9704 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9705 isl_dim_out, 0, pos);
9706 return isl_basic_map_range_product(bmap1, bmap2);
9707 }
9708
9709 /* Given two basic sets bset1 and bset2, compute the maximal difference
9710 * between the values of dimension pos in bset1 and those in bset2
9711 * for any common value of the parameters and dimensions preceding pos.
9712 */
basic_set_maximal_difference_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos,isl_int * opt)9713 static enum isl_lp_result basic_set_maximal_difference_at(
9714 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9715 int pos, isl_int *opt)
9716 {
9717 isl_basic_map *bmap1;
9718 struct isl_ctx *ctx;
9719 struct isl_vec *obj;
9720 isl_size total;
9721 isl_size nparam;
9722 isl_size dim1;
9723 enum isl_lp_result res;
9724
9725 nparam = isl_basic_set_dim(bset1, isl_dim_param);
9726 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9727 if (nparam < 0 || dim1 < 0 || !bset2)
9728 return isl_lp_error;
9729
9730 bmap1 = join_initial(bset1, bset2, pos);
9731 total = isl_basic_map_dim(bmap1, isl_dim_all);
9732 if (total < 0)
9733 return isl_lp_error;
9734
9735 ctx = bmap1->ctx;
9736 obj = isl_vec_alloc(ctx, 1 + total);
9737 if (!obj)
9738 goto error;
9739 isl_seq_clr(obj->block.data, 1 + total);
9740 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9741 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9742 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9743 opt, NULL, NULL);
9744 isl_basic_map_free(bmap1);
9745 isl_vec_free(obj);
9746 return res;
9747 error:
9748 isl_basic_map_free(bmap1);
9749 return isl_lp_error;
9750 }
9751
9752 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
9753 * for any common value of the parameters and dimensions preceding pos
9754 * in both basic sets, the values of dimension pos in bset1 are
9755 * smaller or larger than those in bset2.
9756 *
9757 * Returns
9758 * 1 if bset1 follows bset2
9759 * -1 if bset1 precedes bset2
9760 * 0 if bset1 and bset2 are incomparable
9761 * -2 if some error occurred.
9762 */
isl_basic_set_compare_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9763 int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9764 __isl_keep isl_basic_set *bset2, int pos)
9765 {
9766 isl_int opt;
9767 enum isl_lp_result res;
9768 int cmp;
9769
9770 isl_int_init(opt);
9771
9772 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9773
9774 if (res == isl_lp_empty)
9775 cmp = 0;
9776 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9777 res == isl_lp_unbounded)
9778 cmp = 1;
9779 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9780 cmp = -1;
9781 else
9782 cmp = -2;
9783
9784 isl_int_clear(opt);
9785 return cmp;
9786 }
9787
9788 /* Given two basic sets bset1 and bset2, check whether
9789 * for any common value of the parameters and dimensions preceding pos
9790 * there is a value of dimension pos in bset1 that is larger
9791 * than a value of the same dimension in bset2.
9792 *
9793 * Return
9794 * 1 if there exists such a pair
9795 * 0 if there is no such pair, but there is a pair of equal values
9796 * -1 otherwise
9797 * -2 if some error occurred.
9798 */
isl_basic_set_follows_at(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2,int pos)9799 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9800 __isl_keep isl_basic_set *bset2, int pos)
9801 {
9802 isl_bool empty;
9803 isl_basic_map *bmap;
9804 isl_size dim1;
9805
9806 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9807 if (dim1 < 0)
9808 return -2;
9809 bmap = join_initial(bset1, bset2, pos);
9810 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9811 isl_dim_out, dim1 - pos);
9812 empty = isl_basic_map_is_empty(bmap);
9813 if (empty < 0)
9814 goto error;
9815 if (empty) {
9816 isl_basic_map_free(bmap);
9817 return -1;
9818 }
9819 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9820 isl_dim_out, dim1 - pos);
9821 empty = isl_basic_map_is_empty(bmap);
9822 if (empty < 0)
9823 goto error;
9824 isl_basic_map_free(bmap);
9825 if (empty)
9826 return 0;
9827 return 1;
9828 error:
9829 isl_basic_map_free(bmap);
9830 return -2;
9831 }
9832
9833 /* Given two sets set1 and set2, check whether
9834 * for any common value of the parameters and dimensions preceding pos
9835 * there is a value of dimension pos in set1 that is larger
9836 * than a value of the same dimension in set2.
9837 *
9838 * Return
9839 * 1 if there exists such a pair
9840 * 0 if there is no such pair, but there is a pair of equal values
9841 * -1 otherwise
9842 * -2 if some error occurred.
9843 */
isl_set_follows_at(__isl_keep isl_set * set1,__isl_keep isl_set * set2,int pos)9844 int isl_set_follows_at(__isl_keep isl_set *set1,
9845 __isl_keep isl_set *set2, int pos)
9846 {
9847 int i, j;
9848 int follows = -1;
9849
9850 if (!set1 || !set2)
9851 return -2;
9852
9853 for (i = 0; i < set1->n; ++i)
9854 for (j = 0; j < set2->n; ++j) {
9855 int f;
9856 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9857 if (f == 1 || f == -2)
9858 return f;
9859 if (f > follows)
9860 follows = f;
9861 }
9862
9863 return follows;
9864 }
9865
isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map * bmap,unsigned pos,isl_int * val)9866 static isl_bool isl_basic_map_plain_has_fixed_var(
9867 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9868 {
9869 int i;
9870 int d;
9871 isl_size total;
9872
9873 total = isl_basic_map_dim(bmap, isl_dim_all);
9874 if (total < 0)
9875 return isl_bool_error;
9876 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9877 for (; d+1 > pos; --d)
9878 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9879 break;
9880 if (d != pos)
9881 continue;
9882 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9883 return isl_bool_false;
9884 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9885 return isl_bool_false;
9886 if (!isl_int_is_one(bmap->eq[i][1+d]))
9887 return isl_bool_false;
9888 if (val)
9889 isl_int_neg(*val, bmap->eq[i][0]);
9890 return isl_bool_true;
9891 }
9892 return isl_bool_false;
9893 }
9894
isl_map_plain_has_fixed_var(__isl_keep isl_map * map,unsigned pos,isl_int * val)9895 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9896 unsigned pos, isl_int *val)
9897 {
9898 int i;
9899 isl_int v;
9900 isl_int tmp;
9901 isl_bool fixed;
9902
9903 if (!map)
9904 return isl_bool_error;
9905 if (map->n == 0)
9906 return isl_bool_false;
9907 if (map->n == 1)
9908 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9909 isl_int_init(v);
9910 isl_int_init(tmp);
9911 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9912 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9913 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9914 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9915 fixed = isl_bool_false;
9916 }
9917 if (val)
9918 isl_int_set(*val, v);
9919 isl_int_clear(tmp);
9920 isl_int_clear(v);
9921 return fixed;
9922 }
9923
isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set * bset,unsigned pos,isl_int * val)9924 static isl_bool isl_basic_set_plain_has_fixed_var(
9925 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9926 {
9927 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9928 pos, val);
9929 }
9930
isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,isl_int * val)9931 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9932 enum isl_dim_type type, unsigned pos, isl_int *val)
9933 {
9934 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9935 return isl_bool_error;
9936 return isl_basic_map_plain_has_fixed_var(bmap,
9937 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9938 }
9939
9940 /* If "bmap" obviously lies on a hyperplane where the given dimension
9941 * has a fixed value, then return that value.
9942 * Otherwise return NaN.
9943 */
isl_basic_map_plain_get_val_if_fixed(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)9944 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9945 __isl_keep isl_basic_map *bmap,
9946 enum isl_dim_type type, unsigned pos)
9947 {
9948 isl_ctx *ctx;
9949 isl_val *v;
9950 isl_bool fixed;
9951
9952 if (!bmap)
9953 return NULL;
9954 ctx = isl_basic_map_get_ctx(bmap);
9955 v = isl_val_alloc(ctx);
9956 if (!v)
9957 return NULL;
9958 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9959 if (fixed < 0)
9960 return isl_val_free(v);
9961 if (fixed) {
9962 isl_int_set_si(v->d, 1);
9963 return v;
9964 }
9965 isl_val_free(v);
9966 return isl_val_nan(ctx);
9967 }
9968
isl_map_plain_is_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos,isl_int * val)9969 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
9970 enum isl_dim_type type, unsigned pos, isl_int *val)
9971 {
9972 if (isl_map_check_range(map, type, pos, 1) < 0)
9973 return isl_bool_error;
9974 return isl_map_plain_has_fixed_var(map,
9975 map_offset(map, type) - 1 + pos, val);
9976 }
9977
9978 /* If "map" obviously lies on a hyperplane where the given dimension
9979 * has a fixed value, then return that value.
9980 * Otherwise return NaN.
9981 */
isl_map_plain_get_val_if_fixed(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)9982 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
9983 enum isl_dim_type type, unsigned pos)
9984 {
9985 isl_ctx *ctx;
9986 isl_val *v;
9987 isl_bool fixed;
9988
9989 if (!map)
9990 return NULL;
9991 ctx = isl_map_get_ctx(map);
9992 v = isl_val_alloc(ctx);
9993 if (!v)
9994 return NULL;
9995 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
9996 if (fixed < 0)
9997 return isl_val_free(v);
9998 if (fixed) {
9999 isl_int_set_si(v->d, 1);
10000 return v;
10001 }
10002 isl_val_free(v);
10003 return isl_val_nan(ctx);
10004 }
10005
10006 /* If "set" obviously lies on a hyperplane where the given dimension
10007 * has a fixed value, then return that value.
10008 * Otherwise return NaN.
10009 */
isl_set_plain_get_val_if_fixed(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)10010 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
10011 enum isl_dim_type type, unsigned pos)
10012 {
10013 return isl_map_plain_get_val_if_fixed(set, type, pos);
10014 }
10015
10016 /* Return a sequence of values in the same space as "set"
10017 * that are equal to the corresponding set dimensions of "set"
10018 * for those set dimensions that obviously lie on a hyperplane
10019 * where the dimension has a fixed value.
10020 * The other elements are set to NaN.
10021 */
isl_set_get_plain_multi_val_if_fixed(__isl_keep isl_set * set)10022 __isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
10023 __isl_keep isl_set *set)
10024 {
10025 int i;
10026 isl_size n;
10027 isl_space *space;
10028 isl_multi_val *mv;
10029
10030 space = isl_space_drop_all_params(isl_set_get_space(set));
10031 mv = isl_multi_val_alloc(space);
10032 n = isl_multi_val_size(mv);
10033 if (n < 0)
10034 return isl_multi_val_free(mv);
10035
10036 for (i = 0; i < n; ++i) {
10037 isl_val *v;
10038
10039 v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);
10040 mv = isl_multi_val_set_val(mv, i, v);
10041 }
10042
10043 return mv;
10044 }
10045
10046 /* Check if dimension dim has fixed value and if so and if val is not NULL,
10047 * then return this fixed value in *val.
10048 */
isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set * bset,unsigned dim,isl_int * val)10049 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
10050 unsigned dim, isl_int *val)
10051 {
10052 isl_size nparam;
10053
10054 nparam = isl_basic_set_dim(bset, isl_dim_param);
10055 if (nparam < 0)
10056 return isl_bool_error;
10057 return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
10058 }
10059
10060 /* Return -1 if the constraint "c1" should be sorted before "c2"
10061 * and 1 if it should be sorted after "c2".
10062 * Return 0 if the two constraints are the same (up to the constant term).
10063 *
10064 * In particular, if a constraint involves later variables than another
10065 * then it is sorted after this other constraint.
10066 * uset_gist depends on constraints without existentially quantified
10067 * variables sorting first.
10068 *
10069 * For constraints that have the same latest variable, those
10070 * with the same coefficient for this latest variable (first in absolute value
10071 * and then in actual value) are grouped together.
10072 * This is useful for detecting pairs of constraints that can
10073 * be chained in their printed representation.
10074 *
10075 * Finally, within a group, constraints are sorted according to
10076 * their coefficients (excluding the constant term).
10077 */
sort_constraint_cmp(const void * p1,const void * p2,void * arg)10078 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
10079 {
10080 isl_int **c1 = (isl_int **) p1;
10081 isl_int **c2 = (isl_int **) p2;
10082 int l1, l2;
10083 unsigned size = *(unsigned *) arg;
10084 int cmp;
10085
10086 l1 = isl_seq_last_non_zero(*c1 + 1, size);
10087 l2 = isl_seq_last_non_zero(*c2 + 1, size);
10088
10089 if (l1 != l2)
10090 return l1 - l2;
10091
10092 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10093 if (cmp != 0)
10094 return cmp;
10095 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10096 if (cmp != 0)
10097 return -cmp;
10098
10099 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
10100 }
10101
10102 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
10103 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
10104 * and 0 if the two constraints are the same (up to the constant term).
10105 */
isl_basic_map_constraint_cmp(__isl_keep isl_basic_map * bmap,isl_int * c1,isl_int * c2)10106 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
10107 isl_int *c1, isl_int *c2)
10108 {
10109 isl_size total;
10110 unsigned size;
10111
10112 total = isl_basic_map_dim(bmap, isl_dim_all);
10113 if (total < 0)
10114 return -2;
10115 size = total;
10116 return sort_constraint_cmp(&c1, &c2, &size);
10117 }
10118
isl_basic_map_sort_constraints(__isl_take isl_basic_map * bmap)10119 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
10120 __isl_take isl_basic_map *bmap)
10121 {
10122 isl_size total;
10123 unsigned size;
10124
10125 if (!bmap)
10126 return NULL;
10127 if (bmap->n_ineq == 0)
10128 return bmap;
10129 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
10130 return bmap;
10131 total = isl_basic_map_dim(bmap, isl_dim_all);
10132 if (total < 0)
10133 return isl_basic_map_free(bmap);
10134 size = total;
10135 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
10136 &sort_constraint_cmp, &size) < 0)
10137 return isl_basic_map_free(bmap);
10138 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
10139 return bmap;
10140 }
10141
isl_basic_set_sort_constraints(__isl_take isl_basic_set * bset)10142 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
10143 __isl_take isl_basic_set *bset)
10144 {
10145 isl_basic_map *bmap = bset_to_bmap(bset);
10146 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
10147 }
10148
isl_basic_map_normalize(__isl_take isl_basic_map * bmap)10149 __isl_give isl_basic_map *isl_basic_map_normalize(
10150 __isl_take isl_basic_map *bmap)
10151 {
10152 bmap = isl_basic_map_remove_redundancies(bmap);
10153 bmap = isl_basic_map_sort_constraints(bmap);
10154 return bmap;
10155 }
isl_basic_map_plain_cmp(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10156 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
10157 __isl_keep isl_basic_map *bmap2)
10158 {
10159 int i, cmp;
10160 isl_size total;
10161 isl_space *space1, *space2;
10162
10163 if (!bmap1 || !bmap2)
10164 return -1;
10165
10166 if (bmap1 == bmap2)
10167 return 0;
10168 space1 = isl_basic_map_peek_space(bmap1);
10169 space2 = isl_basic_map_peek_space(bmap2);
10170 cmp = isl_space_cmp(space1, space2);
10171 if (cmp)
10172 return cmp;
10173 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
10174 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
10175 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
10176 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
10177 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10178 return 0;
10179 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
10180 return 1;
10181 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10182 return -1;
10183 if (bmap1->n_eq != bmap2->n_eq)
10184 return bmap1->n_eq - bmap2->n_eq;
10185 if (bmap1->n_ineq != bmap2->n_ineq)
10186 return bmap1->n_ineq - bmap2->n_ineq;
10187 if (bmap1->n_div != bmap2->n_div)
10188 return bmap1->n_div - bmap2->n_div;
10189 total = isl_basic_map_dim(bmap1, isl_dim_all);
10190 if (total < 0)
10191 return -1;
10192 for (i = 0; i < bmap1->n_eq; ++i) {
10193 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
10194 if (cmp)
10195 return cmp;
10196 }
10197 for (i = 0; i < bmap1->n_ineq; ++i) {
10198 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
10199 if (cmp)
10200 return cmp;
10201 }
10202 for (i = 0; i < bmap1->n_div; ++i) {
10203 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
10204 if (cmp)
10205 return cmp;
10206 }
10207 return 0;
10208 }
10209
isl_basic_set_plain_cmp(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10210 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
10211 __isl_keep isl_basic_set *bset2)
10212 {
10213 return isl_basic_map_plain_cmp(bset1, bset2);
10214 }
10215
isl_set_plain_cmp(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10216 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
10217 {
10218 int i, cmp;
10219
10220 if (set1 == set2)
10221 return 0;
10222 if (set1->n != set2->n)
10223 return set1->n - set2->n;
10224
10225 for (i = 0; i < set1->n; ++i) {
10226 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
10227 if (cmp)
10228 return cmp;
10229 }
10230
10231 return 0;
10232 }
10233
isl_basic_map_plain_is_equal(__isl_keep isl_basic_map * bmap1,__isl_keep isl_basic_map * bmap2)10234 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
10235 __isl_keep isl_basic_map *bmap2)
10236 {
10237 if (!bmap1 || !bmap2)
10238 return isl_bool_error;
10239 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
10240 }
10241
isl_basic_set_plain_is_equal(__isl_keep isl_basic_set * bset1,__isl_keep isl_basic_set * bset2)10242 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
10243 __isl_keep isl_basic_set *bset2)
10244 {
10245 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
10246 bset_to_bmap(bset2));
10247 }
10248
qsort_bmap_cmp(const void * p1,const void * p2)10249 static int qsort_bmap_cmp(const void *p1, const void *p2)
10250 {
10251 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
10252 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
10253
10254 return isl_basic_map_plain_cmp(bmap1, bmap2);
10255 }
10256
10257 /* Sort the basic maps of "map" and remove duplicate basic maps.
10258 *
10259 * While removing basic maps, we make sure that the basic maps remain
10260 * sorted because isl_map_normalize expects the basic maps of the result
10261 * to be sorted.
10262 */
sort_and_remove_duplicates(__isl_take isl_map * map)10263 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
10264 {
10265 int i, j;
10266
10267 map = isl_map_remove_empty_parts(map);
10268 if (!map)
10269 return NULL;
10270 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
10271 for (i = map->n - 1; i >= 1; --i) {
10272 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
10273 continue;
10274 isl_basic_map_free(map->p[i-1]);
10275 for (j = i; j < map->n; ++j)
10276 map->p[j - 1] = map->p[j];
10277 map->n--;
10278 }
10279
10280 return map;
10281 }
10282
10283 /* Remove obvious duplicates among the basic maps of "map".
10284 *
10285 * Unlike isl_map_normalize, this function does not remove redundant
10286 * constraints and only removes duplicates that have exactly the same
10287 * constraints in the input. It does sort the constraints and
10288 * the basic maps to ease the detection of duplicates.
10289 *
10290 * If "map" has already been normalized or if the basic maps are
10291 * disjoint, then there can be no duplicates.
10292 */
isl_map_remove_obvious_duplicates(__isl_take isl_map * map)10293 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
10294 {
10295 int i;
10296 isl_basic_map *bmap;
10297
10298 if (!map)
10299 return NULL;
10300 if (map->n <= 1)
10301 return map;
10302 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
10303 return map;
10304 for (i = 0; i < map->n; ++i) {
10305 bmap = isl_basic_map_copy(map->p[i]);
10306 bmap = isl_basic_map_sort_constraints(bmap);
10307 if (!bmap)
10308 return isl_map_free(map);
10309 isl_basic_map_free(map->p[i]);
10310 map->p[i] = bmap;
10311 }
10312
10313 map = sort_and_remove_duplicates(map);
10314 return map;
10315 }
10316
10317 /* We normalize in place, but if anything goes wrong we need
10318 * to return NULL, so we need to make sure we don't change the
10319 * meaning of any possible other copies of map.
10320 */
isl_map_normalize(__isl_take isl_map * map)10321 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
10322 {
10323 int i;
10324 struct isl_basic_map *bmap;
10325
10326 if (!map)
10327 return NULL;
10328 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
10329 return map;
10330 for (i = 0; i < map->n; ++i) {
10331 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
10332 if (!bmap)
10333 goto error;
10334 isl_basic_map_free(map->p[i]);
10335 map->p[i] = bmap;
10336 }
10337
10338 map = sort_and_remove_duplicates(map);
10339 if (map)
10340 ISL_F_SET(map, ISL_MAP_NORMALIZED);
10341 return map;
10342 error:
10343 isl_map_free(map);
10344 return NULL;
10345 }
10346
isl_set_normalize(__isl_take isl_set * set)10347 __isl_give isl_set *isl_set_normalize(__isl_take isl_set *set)
10348 {
10349 return set_from_map(isl_map_normalize(set_to_map(set)));
10350 }
10351
isl_map_plain_is_equal(__isl_keep isl_map * map1,__isl_keep isl_map * map2)10352 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
10353 __isl_keep isl_map *map2)
10354 {
10355 int i;
10356 isl_bool equal;
10357
10358 if (!map1 || !map2)
10359 return isl_bool_error;
10360
10361 if (map1 == map2)
10362 return isl_bool_true;
10363 equal = isl_map_has_equal_space(map1, map2);
10364 if (equal < 0 || !equal)
10365 return equal;
10366
10367 map1 = isl_map_copy(map1);
10368 map2 = isl_map_copy(map2);
10369 map1 = isl_map_normalize(map1);
10370 map2 = isl_map_normalize(map2);
10371 if (!map1 || !map2)
10372 goto error;
10373 equal = map1->n == map2->n;
10374 for (i = 0; equal && i < map1->n; ++i) {
10375 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
10376 if (equal < 0)
10377 goto error;
10378 }
10379 isl_map_free(map1);
10380 isl_map_free(map2);
10381 return equal;
10382 error:
10383 isl_map_free(map1);
10384 isl_map_free(map2);
10385 return isl_bool_error;
10386 }
10387
isl_set_plain_is_equal(__isl_keep isl_set * set1,__isl_keep isl_set * set2)10388 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
10389 __isl_keep isl_set *set2)
10390 {
10391 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
10392 }
10393
10394 /* Return the basic maps in "map" as a list.
10395 */
isl_map_get_basic_map_list(__isl_keep isl_map * map)10396 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
10397 __isl_keep isl_map *map)
10398 {
10399 int i;
10400 isl_ctx *ctx;
10401 isl_basic_map_list *list;
10402
10403 if (!map)
10404 return NULL;
10405 ctx = isl_map_get_ctx(map);
10406 list = isl_basic_map_list_alloc(ctx, map->n);
10407
10408 for (i = 0; i < map->n; ++i) {
10409 isl_basic_map *bmap;
10410
10411 bmap = isl_basic_map_copy(map->p[i]);
10412 list = isl_basic_map_list_add(list, bmap);
10413 }
10414
10415 return list;
10416 }
10417
10418 /* Return the intersection of the elements in the non-empty list "list".
10419 * All elements are assumed to live in the same space.
10420 */
isl_basic_map_list_intersect(__isl_take isl_basic_map_list * list)10421 __isl_give isl_basic_map *isl_basic_map_list_intersect(
10422 __isl_take isl_basic_map_list *list)
10423 {
10424 int i;
10425 isl_size n;
10426 isl_basic_map *bmap;
10427
10428 n = isl_basic_map_list_n_basic_map(list);
10429 if (n < 0)
10430 goto error;
10431 if (n < 1)
10432 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
10433 "expecting non-empty list", goto error);
10434
10435 bmap = isl_basic_map_list_get_basic_map(list, 0);
10436 for (i = 1; i < n; ++i) {
10437 isl_basic_map *bmap_i;
10438
10439 bmap_i = isl_basic_map_list_get_basic_map(list, i);
10440 bmap = isl_basic_map_intersect(bmap, bmap_i);
10441 }
10442
10443 isl_basic_map_list_free(list);
10444 return bmap;
10445 error:
10446 isl_basic_map_list_free(list);
10447 return NULL;
10448 }
10449
10450 /* Return the intersection of the elements in the non-empty list "list".
10451 * All elements are assumed to live in the same space.
10452 */
isl_basic_set_list_intersect(__isl_take isl_basic_set_list * list)10453 __isl_give isl_basic_set *isl_basic_set_list_intersect(
10454 __isl_take isl_basic_set_list *list)
10455 {
10456 return isl_basic_map_list_intersect(list);
10457 }
10458
10459 /* Return the union of the elements of "list".
10460 * The list is required to have at least one element.
10461 */
isl_basic_set_list_union(__isl_take isl_basic_set_list * list)10462 __isl_give isl_set *isl_basic_set_list_union(
10463 __isl_take isl_basic_set_list *list)
10464 {
10465 int i;
10466 isl_size n;
10467 isl_space *space;
10468 isl_basic_set *bset;
10469 isl_set *set;
10470
10471 n = isl_basic_set_list_n_basic_set(list);
10472 if (n < 0)
10473 goto error;
10474 if (n < 1)
10475 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
10476 "expecting non-empty list", goto error);
10477
10478 bset = isl_basic_set_list_get_basic_set(list, 0);
10479 space = isl_basic_set_get_space(bset);
10480 isl_basic_set_free(bset);
10481
10482 set = isl_set_alloc_space(space, n, 0);
10483 for (i = 0; i < n; ++i) {
10484 bset = isl_basic_set_list_get_basic_set(list, i);
10485 set = isl_set_add_basic_set(set, bset);
10486 }
10487
10488 isl_basic_set_list_free(list);
10489 return set;
10490 error:
10491 isl_basic_set_list_free(list);
10492 return NULL;
10493 }
10494
10495 /* Return the union of the elements in the non-empty list "list".
10496 * All elements are assumed to live in the same space.
10497 */
isl_set_list_union(__isl_take isl_set_list * list)10498 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
10499 {
10500 int i;
10501 isl_size n;
10502 isl_set *set;
10503
10504 n = isl_set_list_n_set(list);
10505 if (n < 0)
10506 goto error;
10507 if (n < 1)
10508 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
10509 "expecting non-empty list", goto error);
10510
10511 set = isl_set_list_get_set(list, 0);
10512 for (i = 1; i < n; ++i) {
10513 isl_set *set_i;
10514
10515 set_i = isl_set_list_get_set(list, i);
10516 set = isl_set_union(set, set_i);
10517 }
10518
10519 isl_set_list_free(list);
10520 return set;
10521 error:
10522 isl_set_list_free(list);
10523 return NULL;
10524 }
10525
isl_basic_map_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10526 __isl_give isl_basic_map *isl_basic_map_product(
10527 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10528 {
10529 isl_space *space_result = NULL;
10530 struct isl_basic_map *bmap;
10531 unsigned in1, in2, out1, out2, nparam, total, pos;
10532 struct isl_dim_map *dim_map1, *dim_map2;
10533
10534 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10535 goto error;
10536 space_result = isl_space_product(isl_space_copy(bmap1->dim),
10537 isl_space_copy(bmap2->dim));
10538
10539 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10540 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10541 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10542 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10543 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10544
10545 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
10546 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10547 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10548 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10549 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10550 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10551 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10552 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10553 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10554 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10555 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10556
10557 bmap = isl_basic_map_alloc_space(space_result,
10558 bmap1->n_div + bmap2->n_div,
10559 bmap1->n_eq + bmap2->n_eq,
10560 bmap1->n_ineq + bmap2->n_ineq);
10561 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10562 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10563 bmap = isl_basic_map_simplify(bmap);
10564 return isl_basic_map_finalize(bmap);
10565 error:
10566 isl_basic_map_free(bmap1);
10567 isl_basic_map_free(bmap2);
10568 return NULL;
10569 }
10570
isl_basic_map_flat_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10571 __isl_give isl_basic_map *isl_basic_map_flat_product(
10572 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10573 {
10574 isl_basic_map *prod;
10575
10576 prod = isl_basic_map_product(bmap1, bmap2);
10577 prod = isl_basic_map_flatten(prod);
10578 return prod;
10579 }
10580
isl_basic_set_flat_product(__isl_take isl_basic_set * bset1,__isl_take isl_basic_set * bset2)10581 __isl_give isl_basic_set *isl_basic_set_flat_product(
10582 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10583 {
10584 return isl_basic_map_flat_range_product(bset1, bset2);
10585 }
10586
isl_basic_map_domain_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10587 __isl_give isl_basic_map *isl_basic_map_domain_product(
10588 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10589 {
10590 isl_space *space1, *space2;
10591 isl_space *space_result = NULL;
10592 isl_basic_map *bmap;
10593 isl_size in1, in2, out, nparam;
10594 unsigned total, pos;
10595 struct isl_dim_map *dim_map1, *dim_map2;
10596
10597 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10598 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10599 out = isl_basic_map_dim(bmap1, isl_dim_out);
10600 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10601 if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
10602 goto error;
10603
10604 space1 = isl_basic_map_get_space(bmap1);
10605 space2 = isl_basic_map_get_space(bmap2);
10606 space_result = isl_space_domain_product(space1, space2);
10607
10608 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10609 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10610 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10611 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10612 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10613 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10614 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10615 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10616 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10617 isl_dim_map_div(dim_map1, bmap1, pos += out);
10618 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10619
10620 bmap = isl_basic_map_alloc_space(space_result,
10621 bmap1->n_div + bmap2->n_div,
10622 bmap1->n_eq + bmap2->n_eq,
10623 bmap1->n_ineq + bmap2->n_ineq);
10624 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10625 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10626 bmap = isl_basic_map_simplify(bmap);
10627 return isl_basic_map_finalize(bmap);
10628 error:
10629 isl_basic_map_free(bmap1);
10630 isl_basic_map_free(bmap2);
10631 return NULL;
10632 }
10633
isl_basic_map_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10634 __isl_give isl_basic_map *isl_basic_map_range_product(
10635 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10636 {
10637 isl_bool rational;
10638 isl_space *space_result = NULL;
10639 isl_basic_map *bmap;
10640 isl_size in, out1, out2, nparam;
10641 unsigned total, pos;
10642 struct isl_dim_map *dim_map1, *dim_map2;
10643
10644 rational = isl_basic_map_is_rational(bmap1);
10645 if (rational >= 0 && rational)
10646 rational = isl_basic_map_is_rational(bmap2);
10647 in = isl_basic_map_dim(bmap1, isl_dim_in);
10648 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10649 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10650 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10651 if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
10652 goto error;
10653
10654 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10655 goto error;
10656
10657 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10658 isl_space_copy(bmap2->dim));
10659
10660 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10661 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10662 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10663 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10664 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10665 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10666 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10667 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10668 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10669 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10670 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10671
10672 bmap = isl_basic_map_alloc_space(space_result,
10673 bmap1->n_div + bmap2->n_div,
10674 bmap1->n_eq + bmap2->n_eq,
10675 bmap1->n_ineq + bmap2->n_ineq);
10676 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10677 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10678 if (rational)
10679 bmap = isl_basic_map_set_rational(bmap);
10680 bmap = isl_basic_map_simplify(bmap);
10681 return isl_basic_map_finalize(bmap);
10682 error:
10683 isl_basic_map_free(bmap1);
10684 isl_basic_map_free(bmap2);
10685 return NULL;
10686 }
10687
isl_basic_map_flat_range_product(__isl_take isl_basic_map * bmap1,__isl_take isl_basic_map * bmap2)10688 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
10689 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10690 {
10691 isl_basic_map *prod;
10692
10693 prod = isl_basic_map_range_product(bmap1, bmap2);
10694 prod = isl_basic_map_flatten_range(prod);
10695 return prod;
10696 }
10697
10698 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10699 * and collect the results.
10700 * The result live in the space obtained by calling "space_product"
10701 * on the spaces of "map1" and "map2".
10702 * If "remove_duplicates" is set then the result may contain duplicates
10703 * (even if the inputs do not) and so we try and remove the obvious
10704 * duplicates.
10705 */
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)10706 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10707 __isl_take isl_map *map2,
10708 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10709 __isl_take isl_space *right),
10710 __isl_give isl_basic_map *(*basic_map_product)(
10711 __isl_take isl_basic_map *left,
10712 __isl_take isl_basic_map *right),
10713 int remove_duplicates)
10714 {
10715 unsigned flags = 0;
10716 struct isl_map *result;
10717 int i, j;
10718 isl_bool m;
10719
10720 m = isl_map_has_equal_params(map1, map2);
10721 if (m < 0)
10722 goto error;
10723 if (!m)
10724 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10725 "parameters don't match", goto error);
10726
10727 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10728 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10729 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10730
10731 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10732 isl_space_copy(map2->dim)),
10733 map1->n * map2->n, flags);
10734 if (!result)
10735 goto error;
10736 for (i = 0; i < map1->n; ++i)
10737 for (j = 0; j < map2->n; ++j) {
10738 struct isl_basic_map *part;
10739 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10740 isl_basic_map_copy(map2->p[j]));
10741 if (isl_basic_map_is_empty(part))
10742 isl_basic_map_free(part);
10743 else
10744 result = isl_map_add_basic_map(result, part);
10745 if (!result)
10746 goto error;
10747 }
10748 if (remove_duplicates)
10749 result = isl_map_remove_obvious_duplicates(result);
10750 isl_map_free(map1);
10751 isl_map_free(map2);
10752 return result;
10753 error:
10754 isl_map_free(map1);
10755 isl_map_free(map2);
10756 return NULL;
10757 }
10758
10759 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10760 */
isl_map_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10761 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10762 __isl_take isl_map *map2)
10763 {
10764 isl_map_align_params_bin(&map1, &map2);
10765 return map_product(map1, map2, &isl_space_product,
10766 &isl_basic_map_product, 0);
10767 }
10768
10769 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10770 */
isl_map_flat_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10771 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10772 __isl_take isl_map *map2)
10773 {
10774 isl_map *prod;
10775
10776 prod = isl_map_product(map1, map2);
10777 prod = isl_map_flatten(prod);
10778 return prod;
10779 }
10780
10781 /* Given two set A and B, construct its Cartesian product A x B.
10782 */
isl_set_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10783 __isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
10784 __isl_take isl_set *set2)
10785 {
10786 return isl_map_range_product(set1, set2);
10787 }
10788
isl_set_flat_product(__isl_take isl_set * set1,__isl_take isl_set * set2)10789 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10790 __isl_take isl_set *set2)
10791 {
10792 return isl_map_flat_range_product(set1, set2);
10793 }
10794
10795 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10796 */
isl_map_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10797 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10798 __isl_take isl_map *map2)
10799 {
10800 isl_map_align_params_bin(&map1, &map2);
10801 return map_product(map1, map2, &isl_space_domain_product,
10802 &isl_basic_map_domain_product, 1);
10803 }
10804
10805 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10806 */
isl_map_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10807 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10808 __isl_take isl_map *map2)
10809 {
10810 isl_map_align_params_bin(&map1, &map2);
10811 return map_product(map1, map2, &isl_space_range_product,
10812 &isl_basic_map_range_product, 1);
10813 }
10814
10815 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10816 */
isl_map_factor_domain(__isl_take isl_map * map)10817 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10818 {
10819 isl_space *space;
10820 isl_size total1, keep1, total2, keep2;
10821
10822 total1 = isl_map_dim(map, isl_dim_in);
10823 total2 = isl_map_dim(map, isl_dim_out);
10824 if (total1 < 0 || total2 < 0)
10825 return isl_map_free(map);
10826 if (!isl_space_domain_is_wrapping(map->dim) ||
10827 !isl_space_range_is_wrapping(map->dim))
10828 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10829 "not a product", return isl_map_free(map));
10830
10831 space = isl_map_get_space(map);
10832 space = isl_space_factor_domain(space);
10833 keep1 = isl_space_dim(space, isl_dim_in);
10834 keep2 = isl_space_dim(space, isl_dim_out);
10835 if (keep1 < 0 || keep2 < 0)
10836 map = isl_map_free(map);
10837 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10838 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10839 map = isl_map_reset_space(map, space);
10840
10841 return map;
10842 }
10843
10844 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10845 */
isl_map_factor_range(__isl_take isl_map * map)10846 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10847 {
10848 isl_space *space;
10849 isl_size total1, keep1, total2, keep2;
10850
10851 total1 = isl_map_dim(map, isl_dim_in);
10852 total2 = isl_map_dim(map, isl_dim_out);
10853 if (total1 < 0 || total2 < 0)
10854 return isl_map_free(map);
10855 if (!isl_space_domain_is_wrapping(map->dim) ||
10856 !isl_space_range_is_wrapping(map->dim))
10857 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10858 "not a product", return isl_map_free(map));
10859
10860 space = isl_map_get_space(map);
10861 space = isl_space_factor_range(space);
10862 keep1 = isl_space_dim(space, isl_dim_in);
10863 keep2 = isl_space_dim(space, isl_dim_out);
10864 if (keep1 < 0 || keep2 < 0)
10865 map = isl_map_free(map);
10866 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10867 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10868 map = isl_map_reset_space(map, space);
10869
10870 return map;
10871 }
10872
10873 /* Given a map of the form [A -> B] -> C, return the map A -> C.
10874 */
isl_map_domain_factor_domain(__isl_take isl_map * map)10875 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10876 {
10877 isl_space *space;
10878 isl_size total, keep;
10879
10880 total = isl_map_dim(map, isl_dim_in);
10881 if (total < 0)
10882 return isl_map_free(map);
10883 if (!isl_space_domain_is_wrapping(map->dim))
10884 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10885 "domain is not a product", return isl_map_free(map));
10886
10887 space = isl_map_get_space(map);
10888 space = isl_space_domain_factor_domain(space);
10889 keep = isl_space_dim(space, isl_dim_in);
10890 if (keep < 0)
10891 map = isl_map_free(map);
10892 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10893 map = isl_map_reset_space(map, space);
10894
10895 return map;
10896 }
10897
10898 /* Given a map of the form [A -> B] -> C, return the map B -> C.
10899 */
isl_map_domain_factor_range(__isl_take isl_map * map)10900 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10901 {
10902 isl_space *space;
10903 isl_size total, keep;
10904
10905 total = isl_map_dim(map, isl_dim_in);
10906 if (total < 0)
10907 return isl_map_free(map);
10908 if (!isl_space_domain_is_wrapping(map->dim))
10909 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10910 "domain is not a product", return isl_map_free(map));
10911
10912 space = isl_map_get_space(map);
10913 space = isl_space_domain_factor_range(space);
10914 keep = isl_space_dim(space, isl_dim_in);
10915 if (keep < 0)
10916 map = isl_map_free(map);
10917 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10918 map = isl_map_reset_space(map, space);
10919
10920 return map;
10921 }
10922
10923 /* Given a map A -> [B -> C], extract the map A -> B.
10924 */
isl_map_range_factor_domain(__isl_take isl_map * map)10925 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10926 {
10927 isl_space *space;
10928 isl_size total, keep;
10929
10930 total = isl_map_dim(map, isl_dim_out);
10931 if (total < 0)
10932 return isl_map_free(map);
10933 if (!isl_space_range_is_wrapping(map->dim))
10934 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10935 "range is not a product", return isl_map_free(map));
10936
10937 space = isl_map_get_space(map);
10938 space = isl_space_range_factor_domain(space);
10939 keep = isl_space_dim(space, isl_dim_out);
10940 if (keep < 0)
10941 map = isl_map_free(map);
10942 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10943 map = isl_map_reset_space(map, space);
10944
10945 return map;
10946 }
10947
10948 /* Given a map A -> [B -> C], extract the map A -> C.
10949 */
isl_map_range_factor_range(__isl_take isl_map * map)10950 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10951 {
10952 isl_space *space;
10953 isl_size total, keep;
10954
10955 total = isl_map_dim(map, isl_dim_out);
10956 if (total < 0)
10957 return isl_map_free(map);
10958 if (!isl_space_range_is_wrapping(map->dim))
10959 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10960 "range is not a product", return isl_map_free(map));
10961
10962 space = isl_map_get_space(map);
10963 space = isl_space_range_factor_range(space);
10964 keep = isl_space_dim(space, isl_dim_out);
10965 if (keep < 0)
10966 map = isl_map_free(map);
10967 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
10968 map = isl_map_reset_space(map, space);
10969
10970 return map;
10971 }
10972
10973 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
10974 */
isl_map_flat_domain_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10975 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
10976 __isl_take isl_map *map2)
10977 {
10978 isl_map *prod;
10979
10980 prod = isl_map_domain_product(map1, map2);
10981 prod = isl_map_flatten_domain(prod);
10982 return prod;
10983 }
10984
10985 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
10986 */
isl_map_flat_range_product(__isl_take isl_map * map1,__isl_take isl_map * map2)10987 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
10988 __isl_take isl_map *map2)
10989 {
10990 isl_map *prod;
10991
10992 prod = isl_map_range_product(map1, map2);
10993 prod = isl_map_flatten_range(prod);
10994 return prod;
10995 }
10996
isl_basic_map_get_hash(__isl_keep isl_basic_map * bmap)10997 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
10998 {
10999 int i;
11000 uint32_t hash = isl_hash_init();
11001 isl_size total;
11002
11003 if (!bmap)
11004 return 0;
11005 bmap = isl_basic_map_copy(bmap);
11006 bmap = isl_basic_map_normalize(bmap);
11007 total = isl_basic_map_dim(bmap, isl_dim_all);
11008 if (total < 0)
11009 return 0;
11010 isl_hash_byte(hash, bmap->n_eq & 0xFF);
11011 for (i = 0; i < bmap->n_eq; ++i) {
11012 uint32_t c_hash;
11013 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
11014 isl_hash_hash(hash, c_hash);
11015 }
11016 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
11017 for (i = 0; i < bmap->n_ineq; ++i) {
11018 uint32_t c_hash;
11019 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
11020 isl_hash_hash(hash, c_hash);
11021 }
11022 isl_hash_byte(hash, bmap->n_div & 0xFF);
11023 for (i = 0; i < bmap->n_div; ++i) {
11024 uint32_t c_hash;
11025 if (isl_int_is_zero(bmap->div[i][0]))
11026 continue;
11027 isl_hash_byte(hash, i & 0xFF);
11028 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
11029 isl_hash_hash(hash, c_hash);
11030 }
11031 isl_basic_map_free(bmap);
11032 return hash;
11033 }
11034
isl_basic_set_get_hash(__isl_keep isl_basic_set * bset)11035 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
11036 {
11037 return isl_basic_map_get_hash(bset_to_bmap(bset));
11038 }
11039
isl_map_get_hash(__isl_keep isl_map * map)11040 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
11041 {
11042 int i;
11043 uint32_t hash;
11044
11045 if (!map)
11046 return 0;
11047 map = isl_map_copy(map);
11048 map = isl_map_normalize(map);
11049 if (!map)
11050 return 0;
11051
11052 hash = isl_hash_init();
11053 for (i = 0; i < map->n; ++i) {
11054 uint32_t bmap_hash;
11055 bmap_hash = isl_basic_map_get_hash(map->p[i]);
11056 isl_hash_hash(hash, bmap_hash);
11057 }
11058
11059 isl_map_free(map);
11060
11061 return hash;
11062 }
11063
isl_set_get_hash(__isl_keep isl_set * set)11064 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
11065 {
11066 return isl_map_get_hash(set_to_map(set));
11067 }
11068
11069 /* Return the number of basic maps in the (current) representation of "map".
11070 */
isl_map_n_basic_map(__isl_keep isl_map * map)11071 isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
11072 {
11073 return map ? map->n : isl_size_error;
11074 }
11075
isl_set_n_basic_set(__isl_keep isl_set * set)11076 isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
11077 {
11078 return set ? set->n : isl_size_error;
11079 }
11080
isl_map_foreach_basic_map(__isl_keep isl_map * map,isl_stat (* fn)(__isl_take isl_basic_map * bmap,void * user),void * user)11081 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
11082 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
11083 {
11084 int i;
11085
11086 if (!map)
11087 return isl_stat_error;
11088
11089 for (i = 0; i < map->n; ++i)
11090 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
11091 return isl_stat_error;
11092
11093 return isl_stat_ok;
11094 }
11095
isl_set_foreach_basic_set(__isl_keep isl_set * set,isl_stat (* fn)(__isl_take isl_basic_set * bset,void * user),void * user)11096 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
11097 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
11098 {
11099 int i;
11100
11101 if (!set)
11102 return isl_stat_error;
11103
11104 for (i = 0; i < set->n; ++i)
11105 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
11106 return isl_stat_error;
11107
11108 return isl_stat_ok;
11109 }
11110
11111 /* Does "test" succeed on every basic set in "set"?
11112 */
isl_set_every_basic_set(__isl_keep isl_set * set,isl_bool (* test)(__isl_keep isl_basic_set * bset,void * user),void * user)11113 isl_bool isl_set_every_basic_set(__isl_keep isl_set *set,
11114 isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),
11115 void *user)
11116 {
11117 int i;
11118
11119 if (!set)
11120 return isl_bool_error;
11121
11122 for (i = 0; i < set->n; ++i) {
11123 isl_bool r;
11124
11125 r = test(set->p[i], user);
11126 if (r < 0 || !r)
11127 return r;
11128 }
11129
11130 return isl_bool_true;
11131 }
11132
11133 /* Return a list of basic sets, the union of which is equal to "set".
11134 */
isl_set_get_basic_set_list(__isl_keep isl_set * set)11135 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
11136 __isl_keep isl_set *set)
11137 {
11138 int i;
11139 isl_basic_set_list *list;
11140
11141 if (!set)
11142 return NULL;
11143
11144 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
11145 for (i = 0; i < set->n; ++i) {
11146 isl_basic_set *bset;
11147
11148 bset = isl_basic_set_copy(set->p[i]);
11149 list = isl_basic_set_list_add(list, bset);
11150 }
11151
11152 return list;
11153 }
11154
isl_basic_set_lift(__isl_take isl_basic_set * bset)11155 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
11156 {
11157 isl_space *space;
11158
11159 if (!bset)
11160 return NULL;
11161
11162 bset = isl_basic_set_cow(bset);
11163 if (!bset)
11164 return NULL;
11165
11166 space = isl_basic_set_get_space(bset);
11167 space = isl_space_lift(space, bset->n_div);
11168 if (!space)
11169 goto error;
11170 isl_space_free(bset->dim);
11171 bset->dim = space;
11172 bset->extra -= bset->n_div;
11173 bset->n_div = 0;
11174
11175 bset = isl_basic_set_finalize(bset);
11176
11177 return bset;
11178 error:
11179 isl_basic_set_free(bset);
11180 return NULL;
11181 }
11182
isl_set_lift(__isl_take isl_set * set)11183 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
11184 {
11185 int i;
11186 isl_space *space;
11187 unsigned n_div;
11188
11189 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
11190
11191 if (!set)
11192 return NULL;
11193
11194 set = isl_set_cow(set);
11195 if (!set)
11196 return NULL;
11197
11198 n_div = set->p[0]->n_div;
11199 space = isl_set_get_space(set);
11200 space = isl_space_lift(space, n_div);
11201 if (!space)
11202 goto error;
11203 isl_space_free(set->dim);
11204 set->dim = space;
11205
11206 for (i = 0; i < set->n; ++i) {
11207 set->p[i] = isl_basic_set_lift(set->p[i]);
11208 if (!set->p[i])
11209 goto error;
11210 }
11211
11212 return set;
11213 error:
11214 isl_set_free(set);
11215 return NULL;
11216 }
11217
isl_basic_set_size(__isl_keep isl_basic_set * bset)11218 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
11219 {
11220 isl_size dim;
11221 int size = 0;
11222
11223 dim = isl_basic_set_dim(bset, isl_dim_all);
11224 if (dim < 0)
11225 return -1;
11226 size += bset->n_eq * (1 + dim);
11227 size += bset->n_ineq * (1 + dim);
11228 size += bset->n_div * (2 + dim);
11229
11230 return size;
11231 }
11232
isl_set_size(__isl_keep isl_set * set)11233 int isl_set_size(__isl_keep isl_set *set)
11234 {
11235 int i;
11236 int size = 0;
11237
11238 if (!set)
11239 return -1;
11240
11241 for (i = 0; i < set->n; ++i)
11242 size += isl_basic_set_size(set->p[i]);
11243
11244 return size;
11245 }
11246
11247 /* Check if there is any lower bound (if lower == 0) and/or upper
11248 * bound (if upper == 0) on the specified dim.
11249 */
basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos,int lower,int upper)11250 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11251 enum isl_dim_type type, unsigned pos, int lower, int upper)
11252 {
11253 int i;
11254
11255 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
11256 return isl_bool_error;
11257
11258 pos += isl_basic_map_offset(bmap, type);
11259
11260 for (i = 0; i < bmap->n_div; ++i) {
11261 if (isl_int_is_zero(bmap->div[i][0]))
11262 continue;
11263 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
11264 return isl_bool_true;
11265 }
11266
11267 for (i = 0; i < bmap->n_eq; ++i)
11268 if (!isl_int_is_zero(bmap->eq[i][pos]))
11269 return isl_bool_true;
11270
11271 for (i = 0; i < bmap->n_ineq; ++i) {
11272 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
11273 if (sgn > 0)
11274 lower = 1;
11275 if (sgn < 0)
11276 upper = 1;
11277 }
11278
11279 return lower && upper;
11280 }
11281
isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11282 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11283 enum isl_dim_type type, unsigned pos)
11284 {
11285 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
11286 }
11287
isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11288 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
11289 enum isl_dim_type type, unsigned pos)
11290 {
11291 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
11292 }
11293
isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,unsigned pos)11294 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
11295 enum isl_dim_type type, unsigned pos)
11296 {
11297 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
11298 }
11299
isl_map_dim_is_bounded(__isl_keep isl_map * map,enum isl_dim_type type,unsigned pos)11300 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
11301 enum isl_dim_type type, unsigned pos)
11302 {
11303 int i;
11304
11305 if (!map)
11306 return isl_bool_error;
11307
11308 for (i = 0; i < map->n; ++i) {
11309 isl_bool bounded;
11310 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
11311 if (bounded < 0 || !bounded)
11312 return bounded;
11313 }
11314
11315 return isl_bool_true;
11316 }
11317
11318 /* Return true if the specified dim is involved in both an upper bound
11319 * and a lower bound.
11320 */
isl_set_dim_is_bounded(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11321 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
11322 enum isl_dim_type type, unsigned pos)
11323 {
11324 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
11325 }
11326
11327 /* Does "map" have a bound (according to "fn") for any of its basic maps?
11328 */
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))11329 static isl_bool has_any_bound(__isl_keep isl_map *map,
11330 enum isl_dim_type type, unsigned pos,
11331 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11332 enum isl_dim_type type, unsigned pos))
11333 {
11334 int i;
11335
11336 if (!map)
11337 return isl_bool_error;
11338
11339 for (i = 0; i < map->n; ++i) {
11340 isl_bool bounded;
11341 bounded = fn(map->p[i], type, pos);
11342 if (bounded < 0 || bounded)
11343 return bounded;
11344 }
11345
11346 return isl_bool_false;
11347 }
11348
11349 /* Return 1 if the specified dim is involved in any lower bound.
11350 */
isl_set_dim_has_any_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11351 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
11352 enum isl_dim_type type, unsigned pos)
11353 {
11354 return has_any_bound(set, type, pos,
11355 &isl_basic_map_dim_has_lower_bound);
11356 }
11357
11358 /* Return 1 if the specified dim is involved in any upper bound.
11359 */
isl_set_dim_has_any_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11360 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
11361 enum isl_dim_type type, unsigned pos)
11362 {
11363 return has_any_bound(set, type, pos,
11364 &isl_basic_map_dim_has_upper_bound);
11365 }
11366
11367 /* Does "map" have a bound (according to "fn") for all of its basic maps?
11368 */
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))11369 static isl_bool has_bound(__isl_keep isl_map *map,
11370 enum isl_dim_type type, unsigned pos,
11371 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11372 enum isl_dim_type type, unsigned pos))
11373 {
11374 int i;
11375
11376 if (!map)
11377 return isl_bool_error;
11378
11379 for (i = 0; i < map->n; ++i) {
11380 isl_bool bounded;
11381 bounded = fn(map->p[i], type, pos);
11382 if (bounded < 0 || !bounded)
11383 return bounded;
11384 }
11385
11386 return isl_bool_true;
11387 }
11388
11389 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
11390 */
isl_set_dim_has_lower_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11391 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
11392 enum isl_dim_type type, unsigned pos)
11393 {
11394 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
11395 }
11396
11397 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
11398 */
isl_set_dim_has_upper_bound(__isl_keep isl_set * set,enum isl_dim_type type,unsigned pos)11399 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
11400 enum isl_dim_type type, unsigned pos)
11401 {
11402 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
11403 }
11404
11405 /* For each of the "n" variables starting at "first", determine
11406 * the sign of the variable and put the results in the first "n"
11407 * elements of the array "signs".
11408 * Sign
11409 * 1 means that the variable is non-negative
11410 * -1 means that the variable is non-positive
11411 * 0 means the variable attains both positive and negative values.
11412 */
isl_basic_set_vars_get_sign(__isl_keep isl_basic_set * bset,unsigned first,unsigned n,int * signs)11413 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
11414 unsigned first, unsigned n, int *signs)
11415 {
11416 isl_vec *bound = NULL;
11417 struct isl_tab *tab = NULL;
11418 struct isl_tab_undo *snap;
11419 int i;
11420 isl_size total;
11421
11422 total = isl_basic_set_dim(bset, isl_dim_all);
11423 if (total < 0 || !signs)
11424 return isl_stat_error;
11425
11426 bound = isl_vec_alloc(bset->ctx, 1 + total);
11427 tab = isl_tab_from_basic_set(bset, 0);
11428 if (!bound || !tab)
11429 goto error;
11430
11431 isl_seq_clr(bound->el, bound->size);
11432 isl_int_set_si(bound->el[0], -1);
11433
11434 snap = isl_tab_snap(tab);
11435 for (i = 0; i < n; ++i) {
11436 int empty;
11437
11438 isl_int_set_si(bound->el[1 + first + i], -1);
11439 if (isl_tab_add_ineq(tab, bound->el) < 0)
11440 goto error;
11441 empty = tab->empty;
11442 isl_int_set_si(bound->el[1 + first + i], 0);
11443 if (isl_tab_rollback(tab, snap) < 0)
11444 goto error;
11445
11446 if (empty) {
11447 signs[i] = 1;
11448 continue;
11449 }
11450
11451 isl_int_set_si(bound->el[1 + first + i], 1);
11452 if (isl_tab_add_ineq(tab, bound->el) < 0)
11453 goto error;
11454 empty = tab->empty;
11455 isl_int_set_si(bound->el[1 + first + i], 0);
11456 if (isl_tab_rollback(tab, snap) < 0)
11457 goto error;
11458
11459 signs[i] = empty ? -1 : 0;
11460 }
11461
11462 isl_tab_free(tab);
11463 isl_vec_free(bound);
11464 return isl_stat_ok;
11465 error:
11466 isl_tab_free(tab);
11467 isl_vec_free(bound);
11468 return isl_stat_error;
11469 }
11470
isl_basic_set_dims_get_sign(__isl_keep isl_basic_set * bset,enum isl_dim_type type,unsigned first,unsigned n,int * signs)11471 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
11472 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
11473 {
11474 if (!bset || !signs)
11475 return isl_stat_error;
11476 if (isl_basic_set_check_range(bset, type, first, n) < 0)
11477 return isl_stat_error;
11478
11479 first += pos(bset->dim, type) - 1;
11480 return isl_basic_set_vars_get_sign(bset, first, n, signs);
11481 }
11482
11483 /* Is it possible for the integer division "div" to depend (possibly
11484 * indirectly) on any output dimensions?
11485 *
11486 * If the div is undefined, then we conservatively assume that it
11487 * may depend on them.
11488 * Otherwise, we check if it actually depends on them or on any integer
11489 * divisions that may depend on them.
11490 */
div_may_involve_output(__isl_keep isl_basic_map * bmap,int div)11491 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
11492 {
11493 int i;
11494 isl_size n_out, n_div;
11495 unsigned o_out, o_div;
11496
11497 if (isl_int_is_zero(bmap->div[div][0]))
11498 return isl_bool_true;
11499
11500 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11501 if (n_out < 0)
11502 return isl_bool_error;
11503 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11504
11505 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
11506 return isl_bool_true;
11507
11508 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11509 if (n_div < 0)
11510 return isl_bool_error;
11511 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11512
11513 for (i = 0; i < n_div; ++i) {
11514 isl_bool may_involve;
11515
11516 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
11517 continue;
11518 may_involve = div_may_involve_output(bmap, i);
11519 if (may_involve < 0 || may_involve)
11520 return may_involve;
11521 }
11522
11523 return isl_bool_false;
11524 }
11525
11526 /* Return the first integer division of "bmap" in the range
11527 * [first, first + n[ that may depend on any output dimensions and
11528 * that has a non-zero coefficient in "c" (where the first coefficient
11529 * in "c" corresponds to integer division "first").
11530 */
first_div_may_involve_output(__isl_keep isl_basic_map * bmap,isl_int * c,int first,int n)11531 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
11532 isl_int *c, int first, int n)
11533 {
11534 int k;
11535
11536 if (!bmap)
11537 return -1;
11538
11539 for (k = first; k < first + n; ++k) {
11540 isl_bool may_involve;
11541
11542 if (isl_int_is_zero(c[k]))
11543 continue;
11544 may_involve = div_may_involve_output(bmap, k);
11545 if (may_involve < 0)
11546 return -1;
11547 if (may_involve)
11548 return k;
11549 }
11550
11551 return first + n;
11552 }
11553
11554 /* Look for a pair of inequality constraints in "bmap" of the form
11555 *
11556 * -l + i >= 0 or i >= l
11557 * and
11558 * n + l - i >= 0 or i <= l + n
11559 *
11560 * with n < "m" and i the output dimension at position "pos".
11561 * (Note that n >= 0 as otherwise the two constraints would conflict.)
11562 * Furthermore, "l" is only allowed to involve parameters, input dimensions
11563 * and earlier output dimensions, as well as integer divisions that do
11564 * not involve any of the output dimensions.
11565 *
11566 * Return the index of the first inequality constraint or bmap->n_ineq
11567 * if no such pair can be found.
11568 */
find_modulo_constraint_pair(__isl_keep isl_basic_map * bmap,int pos,isl_int m)11569 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
11570 int pos, isl_int m)
11571 {
11572 int i, j;
11573 isl_ctx *ctx;
11574 isl_size total;
11575 isl_size n_div, n_out;
11576 unsigned o_div, o_out;
11577 int less;
11578
11579 total = isl_basic_map_dim(bmap, isl_dim_all);
11580 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11581 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11582 if (total < 0 || n_out < 0 || n_div < 0)
11583 return -1;
11584
11585 ctx = isl_basic_map_get_ctx(bmap);
11586 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11587 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11588 for (i = 0; i < bmap->n_ineq; ++i) {
11589 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
11590 continue;
11591 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
11592 n_out - (pos + 1)) != -1)
11593 continue;
11594 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11595 0, n_div) < n_div)
11596 continue;
11597 for (j = i + 1; j < bmap->n_ineq; ++j) {
11598 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11599 ctx->one))
11600 continue;
11601 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11602 bmap->ineq[j] + 1, total))
11603 continue;
11604 break;
11605 }
11606 if (j >= bmap->n_ineq)
11607 continue;
11608 isl_int_add(bmap->ineq[i][0],
11609 bmap->ineq[i][0], bmap->ineq[j][0]);
11610 less = isl_int_abs_lt(bmap->ineq[i][0], m);
11611 isl_int_sub(bmap->ineq[i][0],
11612 bmap->ineq[i][0], bmap->ineq[j][0]);
11613 if (!less)
11614 continue;
11615 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11616 return i;
11617 else
11618 return j;
11619 }
11620
11621 return bmap->n_ineq;
11622 }
11623
11624 /* Return the index of the equality of "bmap" that defines
11625 * the output dimension "pos" in terms of earlier dimensions.
11626 * The equality may also involve integer divisions, as long
11627 * as those integer divisions are defined in terms of
11628 * parameters or input dimensions.
11629 * In this case, *div is set to the number of integer divisions and
11630 * *ineq is set to the number of inequality constraints (provided
11631 * div and ineq are not NULL).
11632 *
11633 * The equality may also involve a single integer division involving
11634 * the output dimensions (typically only output dimension "pos") as
11635 * long as the coefficient of output dimension "pos" is 1 or -1 and
11636 * there is a pair of constraints i >= l and i <= l + n, with i referring
11637 * to output dimension "pos", l an expression involving only earlier
11638 * dimensions and n smaller than the coefficient of the integer division
11639 * in the equality. In this case, the output dimension can be defined
11640 * in terms of a modulo expression that does not involve the integer division.
11641 * *div is then set to this single integer division and
11642 * *ineq is set to the index of constraint i >= l.
11643 *
11644 * Return bmap->n_eq if there is no such equality.
11645 * Return -1 on error.
11646 */
isl_basic_map_output_defining_equality(__isl_keep isl_basic_map * bmap,int pos,int * div,int * ineq)11647 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11648 int pos, int *div, int *ineq)
11649 {
11650 int j, k, l;
11651 isl_size n_div, n_out;
11652 unsigned o_div, o_out;
11653
11654 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11655 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11656 if (n_out < 0 || n_div < 0)
11657 return -1;
11658
11659 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11660 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11661
11662 if (ineq)
11663 *ineq = bmap->n_ineq;
11664 if (div)
11665 *div = n_div;
11666 for (j = 0; j < bmap->n_eq; ++j) {
11667 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11668 continue;
11669 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11670 n_out - (pos + 1)) != -1)
11671 continue;
11672 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11673 0, n_div);
11674 if (k >= n_div)
11675 return j;
11676 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11677 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11678 continue;
11679 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11680 k + 1, n_div - (k+1)) < n_div)
11681 continue;
11682 l = find_modulo_constraint_pair(bmap, pos,
11683 bmap->eq[j][o_div + k]);
11684 if (l < 0)
11685 return -1;
11686 if (l >= bmap->n_ineq)
11687 continue;
11688 if (div)
11689 *div = k;
11690 if (ineq)
11691 *ineq = l;
11692 return j;
11693 }
11694
11695 return bmap->n_eq;
11696 }
11697
11698 /* Check if the given basic map is obviously single-valued.
11699 * In particular, for each output dimension, check that there is
11700 * an equality that defines the output dimension in terms of
11701 * earlier dimensions.
11702 */
isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map * bmap)11703 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11704 {
11705 int i;
11706 isl_size n_out;
11707
11708 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11709 if (n_out < 0)
11710 return isl_bool_error;
11711
11712 for (i = 0; i < n_out; ++i) {
11713 int eq;
11714
11715 eq = isl_basic_map_output_defining_equality(bmap, i,
11716 NULL, NULL);
11717 if (eq < 0)
11718 return isl_bool_error;
11719 if (eq >= bmap->n_eq)
11720 return isl_bool_false;
11721 }
11722
11723 return isl_bool_true;
11724 }
11725
11726 /* Check if the given basic map is single-valued.
11727 * We simply compute
11728 *
11729 * M \circ M^-1
11730 *
11731 * and check if the result is a subset of the identity mapping.
11732 */
isl_basic_map_is_single_valued(__isl_keep isl_basic_map * bmap)11733 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11734 {
11735 isl_space *space;
11736 isl_basic_map *test;
11737 isl_basic_map *id;
11738 isl_bool sv;
11739
11740 sv = isl_basic_map_plain_is_single_valued(bmap);
11741 if (sv < 0 || sv)
11742 return sv;
11743
11744 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11745 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11746
11747 space = isl_basic_map_get_space(bmap);
11748 space = isl_space_map_from_set(isl_space_range(space));
11749 id = isl_basic_map_identity(space);
11750
11751 sv = isl_basic_map_is_subset(test, id);
11752
11753 isl_basic_map_free(test);
11754 isl_basic_map_free(id);
11755
11756 return sv;
11757 }
11758
11759 /* Check if the given map is obviously single-valued.
11760 */
isl_map_plain_is_single_valued(__isl_keep isl_map * map)11761 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11762 {
11763 if (!map)
11764 return isl_bool_error;
11765 if (map->n == 0)
11766 return isl_bool_true;
11767 if (map->n >= 2)
11768 return isl_bool_false;
11769
11770 return isl_basic_map_plain_is_single_valued(map->p[0]);
11771 }
11772
11773 /* Check if the given map is single-valued.
11774 * We simply compute
11775 *
11776 * M \circ M^-1
11777 *
11778 * and check if the result is a subset of the identity mapping.
11779 */
isl_map_is_single_valued(__isl_keep isl_map * map)11780 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11781 {
11782 isl_space *space;
11783 isl_map *test;
11784 isl_map *id;
11785 isl_bool sv;
11786
11787 sv = isl_map_plain_is_single_valued(map);
11788 if (sv < 0 || sv)
11789 return sv;
11790
11791 test = isl_map_reverse(isl_map_copy(map));
11792 test = isl_map_apply_range(test, isl_map_copy(map));
11793
11794 space = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11795 id = isl_map_identity(space);
11796
11797 sv = isl_map_is_subset(test, id);
11798
11799 isl_map_free(test);
11800 isl_map_free(id);
11801
11802 return sv;
11803 }
11804
isl_map_is_injective(__isl_keep isl_map * map)11805 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11806 {
11807 isl_bool in;
11808
11809 map = isl_map_copy(map);
11810 map = isl_map_reverse(map);
11811 in = isl_map_is_single_valued(map);
11812 isl_map_free(map);
11813
11814 return in;
11815 }
11816
11817 /* Check if the given map is obviously injective.
11818 */
isl_map_plain_is_injective(__isl_keep isl_map * map)11819 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11820 {
11821 isl_bool in;
11822
11823 map = isl_map_copy(map);
11824 map = isl_map_reverse(map);
11825 in = isl_map_plain_is_single_valued(map);
11826 isl_map_free(map);
11827
11828 return in;
11829 }
11830
isl_map_is_bijective(__isl_keep isl_map * map)11831 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11832 {
11833 isl_bool sv;
11834
11835 sv = isl_map_is_single_valued(map);
11836 if (sv < 0 || !sv)
11837 return sv;
11838
11839 return isl_map_is_injective(map);
11840 }
11841
isl_set_is_singleton(__isl_keep isl_set * set)11842 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11843 {
11844 return isl_map_is_single_valued(set_to_map(set));
11845 }
11846
11847 /* Does "map" only map elements to themselves?
11848 *
11849 * If the domain and range spaces are different, then "map"
11850 * is considered not to be an identity relation, even if it is empty.
11851 * Otherwise, construct the maximal identity relation and
11852 * check whether "map" is a subset of this relation.
11853 */
isl_map_is_identity(__isl_keep isl_map * map)11854 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11855 {
11856 isl_map *id;
11857 isl_bool equal, is_identity;
11858
11859 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
11860 if (equal < 0 || !equal)
11861 return equal;
11862
11863 id = isl_map_identity(isl_map_get_space(map));
11864 is_identity = isl_map_is_subset(map, id);
11865 isl_map_free(id);
11866
11867 return is_identity;
11868 }
11869
isl_map_is_translation(__isl_keep isl_map * map)11870 int isl_map_is_translation(__isl_keep isl_map *map)
11871 {
11872 int ok;
11873 isl_set *delta;
11874
11875 delta = isl_map_deltas(isl_map_copy(map));
11876 ok = isl_set_is_singleton(delta);
11877 isl_set_free(delta);
11878
11879 return ok;
11880 }
11881
unique(isl_int * p,unsigned pos,unsigned len)11882 static int unique(isl_int *p, unsigned pos, unsigned len)
11883 {
11884 if (isl_seq_first_non_zero(p, pos) != -1)
11885 return 0;
11886 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11887 return 0;
11888 return 1;
11889 }
11890
isl_basic_set_is_box(__isl_keep isl_basic_set * bset)11891 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11892 {
11893 int i, j;
11894 isl_size nvar, n_div;
11895 unsigned ovar;
11896
11897 n_div = isl_basic_set_dim(bset, isl_dim_div);
11898 if (n_div < 0)
11899 return isl_bool_error;
11900 if (n_div != 0)
11901 return isl_bool_false;
11902
11903 nvar = isl_basic_set_dim(bset, isl_dim_set);
11904 if (nvar < 0)
11905 return isl_bool_error;
11906 ovar = isl_space_offset(bset->dim, isl_dim_set);
11907 for (j = 0; j < nvar; ++j) {
11908 int lower = 0, upper = 0;
11909 for (i = 0; i < bset->n_eq; ++i) {
11910 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11911 continue;
11912 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11913 return isl_bool_false;
11914 break;
11915 }
11916 if (i < bset->n_eq)
11917 continue;
11918 for (i = 0; i < bset->n_ineq; ++i) {
11919 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11920 continue;
11921 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11922 return isl_bool_false;
11923 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11924 lower = 1;
11925 else
11926 upper = 1;
11927 }
11928 if (!lower || !upper)
11929 return isl_bool_false;
11930 }
11931
11932 return isl_bool_true;
11933 }
11934
isl_set_is_box(__isl_keep isl_set * set)11935 isl_bool isl_set_is_box(__isl_keep isl_set *set)
11936 {
11937 if (!set)
11938 return isl_bool_error;
11939 if (set->n != 1)
11940 return isl_bool_false;
11941
11942 return isl_basic_set_is_box(set->p[0]);
11943 }
11944
isl_basic_set_is_wrapping(__isl_keep isl_basic_set * bset)11945 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11946 {
11947 if (!bset)
11948 return isl_bool_error;
11949
11950 return isl_space_is_wrapping(bset->dim);
11951 }
11952
isl_set_is_wrapping(__isl_keep isl_set * set)11953 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11954 {
11955 if (!set)
11956 return isl_bool_error;
11957
11958 return isl_space_is_wrapping(set->dim);
11959 }
11960
11961 /* Modify the space of "map" through a call to "change".
11962 * If "can_change" is set (not NULL), then first call it to check
11963 * if the modification is allowed, printing the error message "cannot_change"
11964 * if it is not.
11965 */
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))11966 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
11967 isl_bool (*can_change)(__isl_keep isl_map *map),
11968 const char *cannot_change,
11969 __isl_give isl_space *(*change)(__isl_take isl_space *space))
11970 {
11971 isl_bool ok;
11972 isl_space *space;
11973
11974 if (!map)
11975 return NULL;
11976
11977 ok = can_change ? can_change(map) : isl_bool_true;
11978 if (ok < 0)
11979 return isl_map_free(map);
11980 if (!ok)
11981 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
11982 return isl_map_free(map));
11983
11984 space = change(isl_map_get_space(map));
11985 map = isl_map_reset_space(map, space);
11986
11987 return map;
11988 }
11989
11990 /* Is the domain of "map" a wrapped relation?
11991 */
isl_map_domain_is_wrapping(__isl_keep isl_map * map)11992 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
11993 {
11994 if (!map)
11995 return isl_bool_error;
11996
11997 return isl_space_domain_is_wrapping(map->dim);
11998 }
11999
12000 /* Does "map" have a wrapped relation in both domain and range?
12001 */
isl_map_is_product(__isl_keep isl_map * map)12002 isl_bool isl_map_is_product(__isl_keep isl_map *map)
12003 {
12004 return isl_space_is_product(isl_map_peek_space(map));
12005 }
12006
12007 /* Is the range of "map" a wrapped relation?
12008 */
isl_map_range_is_wrapping(__isl_keep isl_map * map)12009 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
12010 {
12011 if (!map)
12012 return isl_bool_error;
12013
12014 return isl_space_range_is_wrapping(map->dim);
12015 }
12016
isl_basic_map_wrap(__isl_take isl_basic_map * bmap)12017 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
12018 {
12019 isl_space *space;
12020
12021 space = isl_basic_map_take_space(bmap);
12022 space = isl_space_wrap(space);
12023 bmap = isl_basic_map_restore_space(bmap, space);
12024
12025 bmap = isl_basic_map_finalize(bmap);
12026
12027 return bset_from_bmap(bmap);
12028 }
12029
12030 /* Given a map A -> B, return the set (A -> B).
12031 */
isl_map_wrap(__isl_take isl_map * map)12032 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
12033 {
12034 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
12035 }
12036
isl_basic_set_unwrap(__isl_take isl_basic_set * bset)12037 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
12038 {
12039 bset = isl_basic_set_cow(bset);
12040 if (!bset)
12041 return NULL;
12042
12043 bset->dim = isl_space_unwrap(bset->dim);
12044 if (!bset->dim)
12045 goto error;
12046
12047 bset = isl_basic_set_finalize(bset);
12048
12049 return bset_to_bmap(bset);
12050 error:
12051 isl_basic_set_free(bset);
12052 return NULL;
12053 }
12054
12055 /* Given a set (A -> B), return the map A -> B.
12056 * Error out if "set" is not of the form (A -> B).
12057 */
isl_set_unwrap(__isl_take isl_set * set)12058 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
12059 {
12060 return isl_map_change_space(set, &isl_set_is_wrapping,
12061 "not a wrapping set", &isl_space_unwrap);
12062 }
12063
isl_basic_map_reset(__isl_take isl_basic_map * bmap,enum isl_dim_type type)12064 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
12065 enum isl_dim_type type)
12066 {
12067 isl_space *space;
12068
12069 space = isl_basic_map_take_space(bmap);
12070 space = isl_space_reset(space, type);
12071 bmap = isl_basic_map_restore_space(bmap, space);
12072
12073 bmap = isl_basic_map_mark_final(bmap);
12074
12075 return bmap;
12076 }
12077
isl_map_reset(__isl_take isl_map * map,enum isl_dim_type type)12078 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
12079 enum isl_dim_type type)
12080 {
12081 int i;
12082 isl_space *space;
12083
12084 if (!map)
12085 return NULL;
12086
12087 if (!isl_space_is_named_or_nested(map->dim, type))
12088 return map;
12089
12090 map = isl_map_cow(map);
12091 if (!map)
12092 return NULL;
12093
12094 for (i = 0; i < map->n; ++i) {
12095 map->p[i] = isl_basic_map_reset(map->p[i], type);
12096 if (!map->p[i])
12097 goto error;
12098 }
12099
12100 space = isl_map_take_space(map);
12101 space = isl_space_reset(space, type);
12102 map = isl_map_restore_space(map, space);
12103
12104 return map;
12105 error:
12106 isl_map_free(map);
12107 return NULL;
12108 }
12109
isl_basic_map_flatten(__isl_take isl_basic_map * bmap)12110 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
12111 {
12112 isl_space *space;
12113
12114 space = isl_basic_map_take_space(bmap);
12115 space = isl_space_flatten(space);
12116 bmap = isl_basic_map_restore_space(bmap, space);
12117
12118 bmap = isl_basic_map_mark_final(bmap);
12119
12120 return bmap;
12121 }
12122
isl_basic_set_flatten(__isl_take isl_basic_set * bset)12123 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
12124 {
12125 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
12126 }
12127
isl_basic_map_flatten_domain(__isl_take isl_basic_map * bmap)12128 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
12129 __isl_take isl_basic_map *bmap)
12130 {
12131 isl_space *space;
12132
12133 space = isl_basic_map_take_space(bmap);
12134 space = isl_space_flatten_domain(space);
12135 bmap = isl_basic_map_restore_space(bmap, space);
12136
12137 bmap = isl_basic_map_mark_final(bmap);
12138
12139 return bmap;
12140 }
12141
isl_basic_map_flatten_range(__isl_take isl_basic_map * bmap)12142 __isl_give isl_basic_map *isl_basic_map_flatten_range(
12143 __isl_take isl_basic_map *bmap)
12144 {
12145 isl_space *space;
12146
12147 space = isl_basic_map_take_space(bmap);
12148 space = isl_space_flatten_range(space);
12149 bmap = isl_basic_map_restore_space(bmap, space);
12150
12151 bmap = isl_basic_map_mark_final(bmap);
12152
12153 return bmap;
12154 }
12155
12156 /* Remove any internal structure from the spaces of domain and range of "map".
12157 */
isl_map_flatten(__isl_take isl_map * map)12158 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
12159 {
12160 if (!map)
12161 return NULL;
12162
12163 if (!map->dim->nested[0] && !map->dim->nested[1])
12164 return map;
12165
12166 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
12167 }
12168
isl_set_flatten(__isl_take isl_set * set)12169 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
12170 {
12171 return set_from_map(isl_map_flatten(set_to_map(set)));
12172 }
12173
isl_set_flatten_map(__isl_take isl_set * set)12174 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
12175 {
12176 isl_space *space, *flat_space;
12177 isl_map *map;
12178
12179 space = isl_set_get_space(set);
12180 flat_space = isl_space_flatten(isl_space_copy(space));
12181 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
12182 flat_space));
12183 map = isl_map_intersect_domain(map, set);
12184
12185 return map;
12186 }
12187
12188 /* Remove any internal structure from the space of the domain of "map".
12189 */
isl_map_flatten_domain(__isl_take isl_map * map)12190 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
12191 {
12192 if (!map)
12193 return NULL;
12194
12195 if (!map->dim->nested[0])
12196 return map;
12197
12198 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
12199 }
12200
12201 /* Remove any internal structure from the space of the range of "map".
12202 */
isl_map_flatten_range(__isl_take isl_map * map)12203 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
12204 {
12205 if (!map)
12206 return NULL;
12207
12208 if (!map->dim->nested[1])
12209 return map;
12210
12211 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
12212 }
12213
12214 /* Reorder the dimensions of "bmap" according to the given dim_map
12215 * and set the dimension specification to "space" and
12216 * perform Gaussian elimination on the result.
12217 */
isl_basic_map_realign(__isl_take isl_basic_map * bmap,__isl_take isl_space * space,__isl_take struct isl_dim_map * dim_map)12218 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
12219 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
12220 {
12221 isl_basic_map *res;
12222 unsigned flags;
12223 isl_size n_div;
12224
12225 n_div = isl_basic_map_dim(bmap, isl_dim_div);
12226 if (n_div < 0 || !space || !dim_map)
12227 goto error;
12228
12229 flags = bmap->flags;
12230 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
12231 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
12232 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
12233 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
12234 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
12235 if (res)
12236 res->flags = flags;
12237 res = isl_basic_map_gauss(res, NULL);
12238 res = isl_basic_map_finalize(res);
12239 return res;
12240 error:
12241 isl_dim_map_free(dim_map);
12242 isl_basic_map_free(bmap);
12243 isl_space_free(space);
12244 return NULL;
12245 }
12246
12247 /* Reorder the dimensions of "map" according to given reordering.
12248 */
isl_map_realign(__isl_take isl_map * map,__isl_take isl_reordering * r)12249 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
12250 __isl_take isl_reordering *r)
12251 {
12252 int i;
12253 struct isl_dim_map *dim_map;
12254
12255 map = isl_map_cow(map);
12256 dim_map = isl_dim_map_from_reordering(r);
12257 if (!map || !r || !dim_map)
12258 goto error;
12259
12260 for (i = 0; i < map->n; ++i) {
12261 struct isl_dim_map *dim_map_i;
12262 isl_space *space;
12263
12264 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
12265
12266 space = isl_reordering_get_space(r);
12267 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
12268
12269 if (!map->p[i])
12270 goto error;
12271 }
12272
12273 map = isl_map_reset_space(map, isl_reordering_get_space(r));
12274 map = isl_map_unmark_normalized(map);
12275
12276 isl_reordering_free(r);
12277 isl_dim_map_free(dim_map);
12278 return map;
12279 error:
12280 isl_dim_map_free(dim_map);
12281 isl_map_free(map);
12282 isl_reordering_free(r);
12283 return NULL;
12284 }
12285
isl_set_realign(__isl_take isl_set * set,__isl_take isl_reordering * r)12286 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
12287 __isl_take isl_reordering *r)
12288 {
12289 return set_from_map(isl_map_realign(set_to_map(set), r));
12290 }
12291
isl_map_align_params(__isl_take isl_map * map,__isl_take isl_space * model)12292 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
12293 __isl_take isl_space *model)
12294 {
12295 isl_ctx *ctx;
12296 isl_bool aligned;
12297
12298 if (!map || !model)
12299 goto error;
12300
12301 ctx = isl_space_get_ctx(model);
12302 if (!isl_space_has_named_params(model))
12303 isl_die(ctx, isl_error_invalid,
12304 "model has unnamed parameters", goto error);
12305 if (isl_map_check_named_params(map) < 0)
12306 goto error;
12307 aligned = isl_map_space_has_equal_params(map, model);
12308 if (aligned < 0)
12309 goto error;
12310 if (!aligned) {
12311 isl_reordering *exp;
12312
12313 exp = isl_parameter_alignment_reordering(map->dim, model);
12314 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
12315 map = isl_map_realign(map, exp);
12316 }
12317
12318 isl_space_free(model);
12319 return map;
12320 error:
12321 isl_space_free(model);
12322 isl_map_free(map);
12323 return NULL;
12324 }
12325
isl_set_align_params(__isl_take isl_set * set,__isl_take isl_space * model)12326 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
12327 __isl_take isl_space *model)
12328 {
12329 return isl_map_align_params(set, model);
12330 }
12331
12332 /* Align the parameters of "bmap" to those of "model", introducing
12333 * additional parameters if needed.
12334 */
isl_basic_map_align_params(__isl_take isl_basic_map * bmap,__isl_take isl_space * model)12335 __isl_give isl_basic_map *isl_basic_map_align_params(
12336 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
12337 {
12338 isl_ctx *ctx;
12339 isl_bool equal_params;
12340
12341 if (!bmap || !model)
12342 goto error;
12343
12344 ctx = isl_space_get_ctx(model);
12345 if (!isl_space_has_named_params(model))
12346 isl_die(ctx, isl_error_invalid,
12347 "model has unnamed parameters", goto error);
12348 if (isl_basic_map_check_named_params(bmap) < 0)
12349 goto error;
12350 equal_params = isl_space_has_equal_params(bmap->dim, model);
12351 if (equal_params < 0)
12352 goto error;
12353 if (!equal_params) {
12354 isl_reordering *exp;
12355 struct isl_dim_map *dim_map;
12356
12357 exp = isl_parameter_alignment_reordering(bmap->dim, model);
12358 exp = isl_reordering_extend_space(exp,
12359 isl_basic_map_get_space(bmap));
12360 dim_map = isl_dim_map_from_reordering(exp);
12361 bmap = isl_basic_map_realign(bmap,
12362 isl_reordering_get_space(exp),
12363 isl_dim_map_extend(dim_map, bmap));
12364 isl_reordering_free(exp);
12365 isl_dim_map_free(dim_map);
12366 }
12367
12368 isl_space_free(model);
12369 return bmap;
12370 error:
12371 isl_space_free(model);
12372 isl_basic_map_free(bmap);
12373 return NULL;
12374 }
12375
12376 /* Do "bset" and "space" have the same parameters?
12377 */
isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set * bset,__isl_keep isl_space * space)12378 isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
12379 __isl_keep isl_space *space)
12380 {
12381 isl_space *bset_space;
12382
12383 bset_space = isl_basic_set_peek_space(bset);
12384 return isl_space_has_equal_params(bset_space, space);
12385 }
12386
12387 /* Do "map" and "space" have the same parameters?
12388 */
isl_map_space_has_equal_params(__isl_keep isl_map * map,__isl_keep isl_space * space)12389 isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
12390 __isl_keep isl_space *space)
12391 {
12392 isl_space *map_space;
12393
12394 map_space = isl_map_peek_space(map);
12395 return isl_space_has_equal_params(map_space, space);
12396 }
12397
12398 /* Do "set" and "space" have the same parameters?
12399 */
isl_set_space_has_equal_params(__isl_keep isl_set * set,__isl_keep isl_space * space)12400 isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
12401 __isl_keep isl_space *space)
12402 {
12403 return isl_map_space_has_equal_params(set_to_map(set), space);
12404 }
12405
12406 /* Align the parameters of "bset" to those of "model", introducing
12407 * additional parameters if needed.
12408 */
isl_basic_set_align_params(__isl_take isl_basic_set * bset,__isl_take isl_space * model)12409 __isl_give isl_basic_set *isl_basic_set_align_params(
12410 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
12411 {
12412 return isl_basic_map_align_params(bset, model);
12413 }
12414
12415 /* Drop all parameters not referenced by "map".
12416 */
isl_map_drop_unused_params(__isl_take isl_map * map)12417 __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
12418 {
12419 int i;
12420 isl_size n;
12421
12422 n = isl_map_dim(map, isl_dim_param);
12423 if (isl_map_check_named_params(map) < 0 || n < 0)
12424 return isl_map_free(map);
12425
12426 for (i = n - 1; i >= 0; i--) {
12427 isl_bool involves;
12428
12429 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
12430 if (involves < 0)
12431 return isl_map_free(map);
12432 if (!involves)
12433 map = isl_map_project_out(map, isl_dim_param, i, 1);
12434 }
12435
12436 return map;
12437 }
12438
12439 /* Drop all parameters not referenced by "set".
12440 */
isl_set_drop_unused_params(__isl_take isl_set * set)12441 __isl_give isl_set *isl_set_drop_unused_params(
12442 __isl_take isl_set *set)
12443 {
12444 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
12445 }
12446
12447 /* Drop all parameters not referenced by "bmap".
12448 */
isl_basic_map_drop_unused_params(__isl_take isl_basic_map * bmap)12449 __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
12450 __isl_take isl_basic_map *bmap)
12451 {
12452 isl_size nparam;
12453 int i;
12454
12455 nparam = isl_basic_map_dim(bmap, isl_dim_param);
12456 if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)
12457 return isl_basic_map_free(bmap);
12458
12459 for (i = nparam - 1; i >= 0; i--) {
12460 isl_bool involves;
12461
12462 involves = isl_basic_map_involves_dims(bmap,
12463 isl_dim_param, i, 1);
12464 if (involves < 0)
12465 return isl_basic_map_free(bmap);
12466 if (!involves)
12467 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
12468 }
12469
12470 return bmap;
12471 }
12472
12473 /* Drop all parameters not referenced by "bset".
12474 */
isl_basic_set_drop_unused_params(__isl_take isl_basic_set * bset)12475 __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
12476 __isl_take isl_basic_set *bset)
12477 {
12478 return bset_from_bmap(isl_basic_map_drop_unused_params(
12479 bset_to_bmap(bset)));
12480 }
12481
12482 /* Given a tuple of identifiers "tuple" in a space that corresponds
12483 * to that of "set", if any of those identifiers appear as parameters
12484 * in "set", then equate those parameters with the corresponding
12485 * set dimensions and project out the parameters.
12486 * The result therefore has no such parameters.
12487 */
equate_params(__isl_take isl_set * set,__isl_keep isl_multi_id * tuple)12488 static __isl_give isl_set *equate_params(__isl_take isl_set *set,
12489 __isl_keep isl_multi_id *tuple)
12490 {
12491 int i;
12492 isl_size n;
12493 isl_space *set_space, *tuple_space;
12494
12495 set_space = isl_set_peek_space(set);
12496 tuple_space = isl_multi_id_peek_space(tuple);
12497 if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
12498 return isl_set_free(set);
12499 n = isl_multi_id_size(tuple);
12500 if (n < 0)
12501 return isl_set_free(set);
12502 for (i = 0; i < n; ++i) {
12503 isl_id *id;
12504 int pos;
12505
12506 id = isl_multi_id_get_at(tuple, i);
12507 if (!id)
12508 return isl_set_free(set);
12509 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
12510 isl_id_free(id);
12511 if (pos < 0)
12512 continue;
12513 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
12514 set = isl_set_project_out(set, isl_dim_param, pos, 1);
12515 }
12516 return set;
12517 }
12518
12519 /* Bind the set dimensions of "set" to parameters with identifiers
12520 * specified by "tuple", living in the same space as "set".
12521 *
12522 * If no parameters with these identifiers appear in "set" already,
12523 * then the set dimensions are simply reinterpreted as parameters.
12524 * Otherwise, the parameters are first equated to the corresponding
12525 * set dimensions.
12526 */
isl_set_bind(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12527 __isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
12528 __isl_take isl_multi_id *tuple)
12529 {
12530 isl_space *space;
12531
12532 set = equate_params(set, tuple);
12533 space = isl_set_get_space(set);
12534 space = isl_space_bind_set(space, tuple);
12535 isl_multi_id_free(tuple);
12536 set = isl_set_reset_space(set, space);
12537
12538 return set;
12539 }
12540
12541 /* Given a tuple of identifiers "tuple" in a space that corresponds
12542 * to the domain of "map", if any of those identifiers appear as parameters
12543 * in "map", then equate those parameters with the corresponding
12544 * input dimensions and project out the parameters.
12545 * The result therefore has no such parameters.
12546 */
map_equate_params(__isl_take isl_map * map,__isl_keep isl_multi_id * tuple)12547 static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
12548 __isl_keep isl_multi_id *tuple)
12549 {
12550 int i;
12551 isl_size n;
12552 isl_space *map_space, *tuple_space;
12553
12554 map_space = isl_map_peek_space(map);
12555 tuple_space = isl_multi_id_peek_space(tuple);
12556 if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
12557 return isl_map_free(map);
12558 n = isl_multi_id_size(tuple);
12559 if (n < 0)
12560 return isl_map_free(map);
12561 for (i = 0; i < n; ++i) {
12562 isl_id *id;
12563 int pos;
12564
12565 id = isl_multi_id_get_at(tuple, i);
12566 if (!id)
12567 return isl_map_free(map);
12568 pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
12569 isl_id_free(id);
12570 if (pos < 0)
12571 continue;
12572 map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
12573 map = isl_map_project_out(map, isl_dim_param, pos, 1);
12574 }
12575 return map;
12576 }
12577
12578 /* Bind the input dimensions of "map" to parameters with identifiers
12579 * specified by "tuple", living in the domain space of "map".
12580 *
12581 * If no parameters with these identifiers appear in "map" already,
12582 * then the input dimensions are simply reinterpreted as parameters.
12583 * Otherwise, the parameters are first equated to the corresponding
12584 * input dimensions.
12585 */
isl_map_bind_domain(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12586 __isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
12587 __isl_take isl_multi_id *tuple)
12588 {
12589 isl_space *space;
12590 isl_set *set;
12591
12592 map = map_equate_params(map, tuple);
12593 space = isl_map_get_space(map);
12594 space = isl_space_bind_map_domain(space, tuple);
12595 isl_multi_id_free(tuple);
12596 set = set_from_map(isl_map_reset_space(map, space));
12597
12598 return set;
12599 }
12600
12601 /* Bind the output dimensions of "map" to parameters with identifiers
12602 * specified by "tuple", living in the range space of "map".
12603 *
12604 * Since binding is more easily implemented on the domain,
12605 * bind the input dimensions of the inverse of "map".
12606 */
isl_map_bind_range(__isl_take isl_map * map,__isl_take isl_multi_id * tuple)12607 __isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
12608 __isl_take isl_multi_id *tuple)
12609 {
12610 return isl_map_bind_domain(isl_map_reverse(map), tuple);
12611 }
12612
12613 /* Insert a domain corresponding to "tuple"
12614 * into the nullary or unary relation "set".
12615 * The result has an extra initial tuple and is therefore
12616 * either a unary or binary relation.
12617 * Any parameters with identifiers in "tuple" are reinterpreted
12618 * as the corresponding domain dimensions.
12619 */
unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12620 static __isl_give isl_map *unbind_params_insert_domain(
12621 __isl_take isl_set *set, __isl_take isl_multi_id *tuple)
12622 {
12623 isl_space *space;
12624 isl_reordering *r;
12625
12626 space = isl_set_peek_space(set);
12627 r = isl_reordering_unbind_params_insert_domain(space, tuple);
12628 isl_multi_id_free(tuple);
12629
12630 return isl_map_realign(set_to_map(set), r);
12631 }
12632
12633 /* Construct a set with "tuple" as domain from the parameter domain "set".
12634 * Any parameters with identifiers in "tuple" are reinterpreted
12635 * as the corresponding set dimensions.
12636 */
isl_set_unbind_params(__isl_take isl_set * set,__isl_take isl_multi_id * tuple)12637 __isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
12638 __isl_take isl_multi_id *tuple)
12639 {
12640 isl_bool is_params;
12641
12642 is_params = isl_set_is_params(set);
12643 if (is_params < 0)
12644 set = isl_set_free(set);
12645 else if (!is_params)
12646 isl_die(isl_set_get_ctx(set), isl_error_invalid,
12647 "expecting parameter domain", set = isl_set_free(set));
12648 return set_from_map(unbind_params_insert_domain(set, tuple));
12649 }
12650
12651 /* Check that "set" is a proper set, i.e., that it is not a parameter domain.
12652 */
isl_set_check_is_set(__isl_keep isl_set * set)12653 static isl_stat isl_set_check_is_set(__isl_keep isl_set *set)
12654 {
12655 isl_bool is_params;
12656
12657 is_params = isl_set_is_params(set);
12658 if (is_params < 0)
12659 return isl_stat_error;
12660 else if (is_params)
12661 isl_die(isl_set_get_ctx(set), isl_error_invalid,
12662 "expecting proper set", return isl_stat_error);
12663
12664 return isl_stat_ok;
12665 }
12666
12667 /* Construct a map with "domain" as domain and "set" as range.
12668 * Any parameters with identifiers in "domain" are reinterpreted
12669 * as the corresponding domain dimensions.
12670 */
isl_set_unbind_params_insert_domain(__isl_take isl_set * set,__isl_take isl_multi_id * domain)12671 __isl_give isl_map *isl_set_unbind_params_insert_domain(
12672 __isl_take isl_set *set, __isl_take isl_multi_id *domain)
12673 {
12674 if (isl_set_check_is_set(set) < 0)
12675 set = isl_set_free(set);
12676 return unbind_params_insert_domain(set, domain);
12677 }
12678
12679 /* Construct a map with "domain" as domain and "set" as range.
12680 */
isl_set_insert_domain(__isl_take isl_set * set,__isl_take isl_space * domain)12681 __isl_give isl_map *isl_set_insert_domain(__isl_take isl_set *set,
12682 __isl_take isl_space *domain)
12683 {
12684 isl_size dim;
12685 isl_space *space;
12686 isl_map *map;
12687
12688 if (isl_set_check_is_set(set) < 0 || isl_space_check_is_set(domain) < 0)
12689 domain = isl_space_free(domain);
12690 dim = isl_space_dim(domain, isl_dim_set);
12691 if (dim < 0)
12692 domain = isl_space_free(domain);
12693 space = isl_set_get_space(set);
12694 domain = isl_space_replace_params(domain, space);
12695 space = isl_space_map_from_domain_and_range(domain, space);
12696
12697 map = isl_map_from_range(set);
12698 map = isl_map_add_dims(map, isl_dim_in, dim);
12699 map = isl_map_reset_space(map, space);
12700
12701 return map;
12702 }
12703
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)12704 __isl_give isl_mat *isl_basic_map_equalities_matrix(
12705 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12706 enum isl_dim_type c2, enum isl_dim_type c3,
12707 enum isl_dim_type c4, enum isl_dim_type c5)
12708 {
12709 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12710 struct isl_mat *mat;
12711 int i, j, k;
12712 int pos;
12713 isl_size total;
12714
12715 total = isl_basic_map_dim(bmap, isl_dim_all);
12716 if (total < 0)
12717 return NULL;
12718 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
12719 if (!mat)
12720 return NULL;
12721 for (i = 0; i < bmap->n_eq; ++i)
12722 for (j = 0, pos = 0; j < 5; ++j) {
12723 int off = isl_basic_map_offset(bmap, c[j]);
12724 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12725 if (dim < 0)
12726 return isl_mat_free(mat);
12727 for (k = 0; k < dim; ++k) {
12728 isl_int_set(mat->row[i][pos],
12729 bmap->eq[i][off + k]);
12730 ++pos;
12731 }
12732 }
12733
12734 return mat;
12735 }
12736
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)12737 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
12738 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12739 enum isl_dim_type c2, enum isl_dim_type c3,
12740 enum isl_dim_type c4, enum isl_dim_type c5)
12741 {
12742 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12743 struct isl_mat *mat;
12744 int i, j, k;
12745 int pos;
12746 isl_size total;
12747
12748 total = isl_basic_map_dim(bmap, isl_dim_all);
12749 if (total < 0)
12750 return NULL;
12751 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
12752 if (!mat)
12753 return NULL;
12754 for (i = 0; i < bmap->n_ineq; ++i)
12755 for (j = 0, pos = 0; j < 5; ++j) {
12756 int off = isl_basic_map_offset(bmap, c[j]);
12757 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12758 if (dim < 0)
12759 return isl_mat_free(mat);
12760 for (k = 0; k < dim; ++k) {
12761 isl_int_set(mat->row[i][pos],
12762 bmap->ineq[i][off + k]);
12763 ++pos;
12764 }
12765 }
12766
12767 return mat;
12768 }
12769
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)12770 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
12771 __isl_take isl_space *space,
12772 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12773 enum isl_dim_type c2, enum isl_dim_type c3,
12774 enum isl_dim_type c4, enum isl_dim_type c5)
12775 {
12776 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12777 isl_basic_map *bmap = NULL;
12778 isl_size dim;
12779 unsigned total;
12780 unsigned extra;
12781 int i, j, k, l;
12782 int pos;
12783
12784 dim = isl_space_dim(space, isl_dim_all);
12785 if (dim < 0 || !eq || !ineq)
12786 goto error;
12787
12788 if (eq->n_col != ineq->n_col)
12789 isl_die(space->ctx, isl_error_invalid,
12790 "equalities and inequalities matrices should have "
12791 "same number of columns", goto error);
12792
12793 total = 1 + dim;
12794
12795 if (eq->n_col < total)
12796 isl_die(space->ctx, isl_error_invalid,
12797 "number of columns too small", goto error);
12798
12799 extra = eq->n_col - total;
12800
12801 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
12802 eq->n_row, ineq->n_row);
12803 if (!bmap)
12804 goto error;
12805 for (i = 0; i < extra; ++i) {
12806 k = isl_basic_map_alloc_div(bmap);
12807 if (k < 0)
12808 goto error;
12809 isl_int_set_si(bmap->div[k][0], 0);
12810 }
12811 for (i = 0; i < eq->n_row; ++i) {
12812 l = isl_basic_map_alloc_equality(bmap);
12813 if (l < 0)
12814 goto error;
12815 for (j = 0, pos = 0; j < 5; ++j) {
12816 int off = isl_basic_map_offset(bmap, c[j]);
12817 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12818 if (dim < 0)
12819 goto error;
12820 for (k = 0; k < dim; ++k) {
12821 isl_int_set(bmap->eq[l][off + k],
12822 eq->row[i][pos]);
12823 ++pos;
12824 }
12825 }
12826 }
12827 for (i = 0; i < ineq->n_row; ++i) {
12828 l = isl_basic_map_alloc_inequality(bmap);
12829 if (l < 0)
12830 goto error;
12831 for (j = 0, pos = 0; j < 5; ++j) {
12832 int off = isl_basic_map_offset(bmap, c[j]);
12833 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12834 if (dim < 0)
12835 goto error;
12836 for (k = 0; k < dim; ++k) {
12837 isl_int_set(bmap->ineq[l][off + k],
12838 ineq->row[i][pos]);
12839 ++pos;
12840 }
12841 }
12842 }
12843
12844 isl_space_free(space);
12845 isl_mat_free(eq);
12846 isl_mat_free(ineq);
12847
12848 bmap = isl_basic_map_simplify(bmap);
12849 return isl_basic_map_finalize(bmap);
12850 error:
12851 isl_space_free(space);
12852 isl_mat_free(eq);
12853 isl_mat_free(ineq);
12854 isl_basic_map_free(bmap);
12855 return NULL;
12856 }
12857
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)12858 __isl_give isl_mat *isl_basic_set_equalities_matrix(
12859 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12860 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12861 {
12862 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12863 c1, c2, c3, c4, isl_dim_in);
12864 }
12865
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)12866 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
12867 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12868 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12869 {
12870 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12871 c1, c2, c3, c4, isl_dim_in);
12872 }
12873
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)12874 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12875 __isl_take isl_space *space,
12876 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12877 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12878 {
12879 isl_basic_map *bmap;
12880 bmap = isl_basic_map_from_constraint_matrices(space, eq, ineq,
12881 c1, c2, c3, c4, isl_dim_in);
12882 return bset_from_bmap(bmap);
12883 }
12884
isl_basic_map_can_zip(__isl_keep isl_basic_map * bmap)12885 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12886 {
12887 if (!bmap)
12888 return isl_bool_error;
12889
12890 return isl_space_can_zip(bmap->dim);
12891 }
12892
isl_map_can_zip(__isl_keep isl_map * map)12893 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12894 {
12895 if (!map)
12896 return isl_bool_error;
12897
12898 return isl_space_can_zip(map->dim);
12899 }
12900
12901 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12902 * (A -> C) -> (B -> D).
12903 */
isl_basic_map_zip(__isl_take isl_basic_map * bmap)12904 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12905 {
12906 unsigned pos;
12907 isl_size n_in;
12908 isl_size n1;
12909 isl_size n2;
12910
12911 if (!bmap)
12912 return NULL;
12913
12914 if (!isl_basic_map_can_zip(bmap))
12915 isl_die(bmap->ctx, isl_error_invalid,
12916 "basic map cannot be zipped", goto error);
12917 n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12918 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12919 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12920 if (n_in < 0 || n1 < 0 || n2 < 0)
12921 return isl_basic_map_free(bmap);
12922 pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
12923 bmap = isl_basic_map_cow(bmap);
12924 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12925 if (!bmap)
12926 return NULL;
12927 bmap->dim = isl_space_zip(bmap->dim);
12928 if (!bmap->dim)
12929 goto error;
12930 bmap = isl_basic_map_mark_final(bmap);
12931 return bmap;
12932 error:
12933 isl_basic_map_free(bmap);
12934 return NULL;
12935 }
12936
12937 /* Given a map (A -> B) -> (C -> D), return the corresponding map
12938 * (A -> C) -> (B -> D).
12939 */
isl_map_zip(__isl_take isl_map * map)12940 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12941 {
12942 if (!map)
12943 return NULL;
12944
12945 if (!isl_map_can_zip(map))
12946 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12947 goto error);
12948
12949 return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);
12950 error:
12951 isl_map_free(map);
12952 return NULL;
12953 }
12954
12955 /* Can we apply isl_basic_map_curry to "bmap"?
12956 * That is, does it have a nested relation in its domain?
12957 */
isl_basic_map_can_curry(__isl_keep isl_basic_map * bmap)12958 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12959 {
12960 if (!bmap)
12961 return isl_bool_error;
12962
12963 return isl_space_can_curry(bmap->dim);
12964 }
12965
12966 /* Can we apply isl_map_curry to "map"?
12967 * That is, does it have a nested relation in its domain?
12968 */
isl_map_can_curry(__isl_keep isl_map * map)12969 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
12970 {
12971 if (!map)
12972 return isl_bool_error;
12973
12974 return isl_space_can_curry(map->dim);
12975 }
12976
12977 /* Given a basic map (A -> B) -> C, return the corresponding basic map
12978 * A -> (B -> C).
12979 */
isl_basic_map_curry(__isl_take isl_basic_map * bmap)12980 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
12981 {
12982
12983 if (!bmap)
12984 return NULL;
12985
12986 if (!isl_basic_map_can_curry(bmap))
12987 isl_die(bmap->ctx, isl_error_invalid,
12988 "basic map cannot be curried", goto error);
12989 bmap = isl_basic_map_cow(bmap);
12990 if (!bmap)
12991 return NULL;
12992 bmap->dim = isl_space_curry(bmap->dim);
12993 if (!bmap->dim)
12994 goto error;
12995 bmap = isl_basic_map_mark_final(bmap);
12996 return bmap;
12997 error:
12998 isl_basic_map_free(bmap);
12999 return NULL;
13000 }
13001
13002 /* Given a map (A -> B) -> C, return the corresponding map
13003 * A -> (B -> C).
13004 */
isl_map_curry(__isl_take isl_map * map)13005 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
13006 {
13007 return isl_map_change_space(map, &isl_map_can_curry,
13008 "map cannot be curried", &isl_space_curry);
13009 }
13010
13011 /* Can isl_map_range_curry be applied to "map"?
13012 * That is, does it have a nested relation in its range,
13013 * the domain of which is itself a nested relation?
13014 */
isl_map_can_range_curry(__isl_keep isl_map * map)13015 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
13016 {
13017 if (!map)
13018 return isl_bool_error;
13019
13020 return isl_space_can_range_curry(map->dim);
13021 }
13022
13023 /* Given a map A -> ((B -> C) -> D), return the corresponding map
13024 * A -> (B -> (C -> D)).
13025 */
isl_map_range_curry(__isl_take isl_map * map)13026 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
13027 {
13028 return isl_map_change_space(map, &isl_map_can_range_curry,
13029 "map range cannot be curried",
13030 &isl_space_range_curry);
13031 }
13032
13033 /* Can we apply isl_basic_map_uncurry to "bmap"?
13034 * That is, does it have a nested relation in its domain?
13035 */
isl_basic_map_can_uncurry(__isl_keep isl_basic_map * bmap)13036 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
13037 {
13038 if (!bmap)
13039 return isl_bool_error;
13040
13041 return isl_space_can_uncurry(bmap->dim);
13042 }
13043
13044 /* Can we apply isl_map_uncurry to "map"?
13045 * That is, does it have a nested relation in its domain?
13046 */
isl_map_can_uncurry(__isl_keep isl_map * map)13047 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
13048 {
13049 if (!map)
13050 return isl_bool_error;
13051
13052 return isl_space_can_uncurry(map->dim);
13053 }
13054
13055 /* Given a basic map A -> (B -> C), return the corresponding basic map
13056 * (A -> B) -> C.
13057 */
isl_basic_map_uncurry(__isl_take isl_basic_map * bmap)13058 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
13059 {
13060
13061 if (!bmap)
13062 return NULL;
13063
13064 if (!isl_basic_map_can_uncurry(bmap))
13065 isl_die(bmap->ctx, isl_error_invalid,
13066 "basic map cannot be uncurried",
13067 return isl_basic_map_free(bmap));
13068 bmap = isl_basic_map_cow(bmap);
13069 if (!bmap)
13070 return NULL;
13071 bmap->dim = isl_space_uncurry(bmap->dim);
13072 if (!bmap->dim)
13073 return isl_basic_map_free(bmap);
13074 bmap = isl_basic_map_mark_final(bmap);
13075 return bmap;
13076 }
13077
13078 /* Given a map A -> (B -> C), return the corresponding map
13079 * (A -> B) -> C.
13080 */
isl_map_uncurry(__isl_take isl_map * map)13081 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
13082 {
13083 return isl_map_change_space(map, &isl_map_can_uncurry,
13084 "map cannot be uncurried", &isl_space_uncurry);
13085 }
13086
isl_set_equate(__isl_take isl_set * set,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13087 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
13088 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13089 {
13090 return isl_map_equate(set, type1, pos1, type2, pos2);
13091 }
13092
13093 /* Construct a basic map where the given dimensions are equal to each other.
13094 */
equator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13095 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
13096 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13097 {
13098 isl_basic_map *bmap = NULL;
13099 int i;
13100 isl_size total;
13101
13102 total = isl_space_dim(space, isl_dim_all);
13103 if (total < 0 ||
13104 isl_space_check_range(space, type1, pos1, 1) < 0 ||
13105 isl_space_check_range(space, type2, pos2, 1) < 0)
13106 goto error;
13107
13108 if (type1 == type2 && pos1 == pos2)
13109 return isl_basic_map_universe(space);
13110
13111 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
13112 i = isl_basic_map_alloc_equality(bmap);
13113 if (i < 0)
13114 goto error;
13115 isl_seq_clr(bmap->eq[i], 1 + total);
13116 pos1 += isl_basic_map_offset(bmap, type1);
13117 pos2 += isl_basic_map_offset(bmap, type2);
13118 isl_int_set_si(bmap->eq[i][pos1], -1);
13119 isl_int_set_si(bmap->eq[i][pos2], 1);
13120 bmap = isl_basic_map_finalize(bmap);
13121 isl_space_free(space);
13122 return bmap;
13123 error:
13124 isl_space_free(space);
13125 isl_basic_map_free(bmap);
13126 return NULL;
13127 }
13128
13129 /* Add a constraint imposing that the given two dimensions are equal.
13130 */
isl_basic_map_equate(__isl_take isl_basic_map * bmap,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13131 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
13132 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13133 {
13134 isl_basic_map *eq;
13135
13136 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13137
13138 bmap = isl_basic_map_intersect(bmap, eq);
13139
13140 return bmap;
13141 }
13142
13143 /* Add a constraint imposing that the given two dimensions are equal.
13144 */
isl_map_equate(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13145 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
13146 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13147 {
13148 isl_basic_map *bmap;
13149
13150 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
13151
13152 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13153
13154 return map;
13155 }
13156
13157 /* Add a constraint imposing that the given two dimensions have opposite values.
13158 */
isl_map_oppose(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13159 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
13160 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13161 {
13162 isl_basic_map *bmap = NULL;
13163 int i;
13164 isl_size total;
13165
13166 if (isl_map_check_range(map, type1, pos1, 1) < 0)
13167 return isl_map_free(map);
13168 if (isl_map_check_range(map, type2, pos2, 1) < 0)
13169 return isl_map_free(map);
13170
13171 total = isl_map_dim(map, isl_dim_all);
13172 if (total < 0)
13173 return isl_map_free(map);
13174 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
13175 i = isl_basic_map_alloc_equality(bmap);
13176 if (i < 0)
13177 goto error;
13178 isl_seq_clr(bmap->eq[i], 1 + total);
13179 pos1 += isl_basic_map_offset(bmap, type1);
13180 pos2 += isl_basic_map_offset(bmap, type2);
13181 isl_int_set_si(bmap->eq[i][pos1], 1);
13182 isl_int_set_si(bmap->eq[i][pos2], 1);
13183 bmap = isl_basic_map_finalize(bmap);
13184
13185 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13186
13187 return map;
13188 error:
13189 isl_basic_map_free(bmap);
13190 isl_map_free(map);
13191 return NULL;
13192 }
13193
13194 /* Construct a constraint imposing that the value of the first dimension is
13195 * greater than or equal to that of the second.
13196 */
constraint_order_ge(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13197 static __isl_give isl_constraint *constraint_order_ge(
13198 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
13199 enum isl_dim_type type2, int pos2)
13200 {
13201 isl_constraint *c;
13202
13203 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13204 isl_space_check_range(space, type2, pos2, 1) < 0)
13205 space = isl_space_free(space);
13206 if (!space)
13207 return NULL;
13208
13209 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
13210
13211 if (type1 == type2 && pos1 == pos2)
13212 return c;
13213
13214 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
13215 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
13216
13217 return c;
13218 }
13219
13220 /* Add a constraint imposing that the value of the first dimension is
13221 * greater than or equal to that of the second.
13222 */
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)13223 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
13224 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13225 {
13226 isl_constraint *c;
13227 isl_space *space;
13228
13229 if (type1 == type2 && pos1 == pos2)
13230 return bmap;
13231 space = isl_basic_map_get_space(bmap);
13232 c = constraint_order_ge(space, type1, pos1, type2, pos2);
13233 bmap = isl_basic_map_add_constraint(bmap, c);
13234
13235 return bmap;
13236 }
13237
13238 /* Add a constraint imposing that the value of the first dimension is
13239 * greater than or equal to that of the second.
13240 */
isl_map_order_ge(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13241 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
13242 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13243 {
13244 isl_constraint *c;
13245 isl_space *space;
13246
13247 if (type1 == type2 && pos1 == pos2)
13248 return map;
13249 space = isl_map_get_space(map);
13250 c = constraint_order_ge(space, type1, pos1, type2, pos2);
13251 map = isl_map_add_constraint(map, c);
13252
13253 return map;
13254 }
13255
13256 /* Add a constraint imposing that the value of the first dimension is
13257 * less than or equal to that of the second.
13258 */
isl_map_order_le(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13259 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
13260 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13261 {
13262 return isl_map_order_ge(map, type2, pos2, type1, pos1);
13263 }
13264
13265 /* Construct a basic map where the value of the first dimension is
13266 * greater than that of the second.
13267 */
greator(__isl_take isl_space * space,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13268 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
13269 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13270 {
13271 isl_basic_map *bmap = NULL;
13272 int i;
13273 isl_size total;
13274
13275 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13276 isl_space_check_range(space, type2, pos2, 1) < 0)
13277 goto error;
13278
13279 if (type1 == type2 && pos1 == pos2)
13280 return isl_basic_map_empty(space);
13281
13282 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
13283 total = isl_basic_map_dim(bmap, isl_dim_all);
13284 i = isl_basic_map_alloc_inequality(bmap);
13285 if (total < 0 || i < 0)
13286 return isl_basic_map_free(bmap);
13287 isl_seq_clr(bmap->ineq[i], 1 + total);
13288 pos1 += isl_basic_map_offset(bmap, type1);
13289 pos2 += isl_basic_map_offset(bmap, type2);
13290 isl_int_set_si(bmap->ineq[i][pos1], 1);
13291 isl_int_set_si(bmap->ineq[i][pos2], -1);
13292 isl_int_set_si(bmap->ineq[i][0], -1);
13293 bmap = isl_basic_map_finalize(bmap);
13294
13295 return bmap;
13296 error:
13297 isl_space_free(space);
13298 isl_basic_map_free(bmap);
13299 return NULL;
13300 }
13301
13302 /* Add a constraint imposing that the value of the first dimension is
13303 * greater than that of the second.
13304 */
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)13305 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
13306 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13307 {
13308 isl_basic_map *gt;
13309
13310 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13311
13312 bmap = isl_basic_map_intersect(bmap, gt);
13313
13314 return bmap;
13315 }
13316
13317 /* Add a constraint imposing that the value of the first dimension is
13318 * greater than that of the second.
13319 */
isl_map_order_gt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13320 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
13321 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13322 {
13323 isl_basic_map *bmap;
13324
13325 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
13326
13327 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13328
13329 return map;
13330 }
13331
13332 /* Add a constraint imposing that the value of the first dimension is
13333 * smaller than that of the second.
13334 */
isl_map_order_lt(__isl_take isl_map * map,enum isl_dim_type type1,int pos1,enum isl_dim_type type2,int pos2)13335 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
13336 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13337 {
13338 return isl_map_order_gt(map, type2, pos2, type1, pos1);
13339 }
13340
isl_basic_map_get_div(__isl_keep isl_basic_map * bmap,int pos)13341 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
13342 int pos)
13343 {
13344 isl_aff *div;
13345 isl_local_space *ls;
13346
13347 if (!bmap)
13348 return NULL;
13349
13350 if (!isl_basic_map_divs_known(bmap))
13351 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13352 "some divs are unknown", return NULL);
13353
13354 ls = isl_basic_map_get_local_space(bmap);
13355 div = isl_local_space_get_div(ls, pos);
13356 isl_local_space_free(ls);
13357
13358 return div;
13359 }
13360
isl_basic_set_get_div(__isl_keep isl_basic_set * bset,int pos)13361 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
13362 int pos)
13363 {
13364 return isl_basic_map_get_div(bset, pos);
13365 }
13366
13367 /* Plug in "subs" for dimension "type", "pos" of "bset".
13368 *
13369 * Let i be the dimension to replace and let "subs" be of the form
13370 *
13371 * f/d
13372 *
13373 * Any integer division with a non-zero coefficient for i,
13374 *
13375 * floor((a i + g)/m)
13376 *
13377 * is replaced by
13378 *
13379 * floor((a f + d g)/(m d))
13380 *
13381 * Constraints of the form
13382 *
13383 * a i + g
13384 *
13385 * are replaced by
13386 *
13387 * a f + d g
13388 *
13389 * We currently require that "subs" is an integral expression.
13390 * Handling rational expressions may require us to add stride constraints
13391 * as we do in isl_basic_set_preimage_multi_aff.
13392 */
isl_basic_set_substitute(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)13393 __isl_give isl_basic_set *isl_basic_set_substitute(
13394 __isl_take isl_basic_set *bset,
13395 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13396 {
13397 int i;
13398 isl_int v;
13399 isl_ctx *ctx;
13400 isl_size n_div;
13401
13402 if (bset && isl_basic_set_plain_is_empty(bset))
13403 return bset;
13404
13405 bset = isl_basic_set_cow(bset);
13406 if (!bset || !subs)
13407 goto error;
13408
13409 ctx = isl_basic_set_get_ctx(bset);
13410 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
13411 isl_die(ctx, isl_error_invalid,
13412 "spaces don't match", goto error);
13413 n_div = isl_local_space_dim(subs->ls, isl_dim_div);
13414 if (n_div < 0)
13415 goto error;
13416 if (n_div != 0)
13417 isl_die(ctx, isl_error_unsupported,
13418 "cannot handle divs yet", goto error);
13419 if (!isl_int_is_one(subs->v->el[0]))
13420 isl_die(ctx, isl_error_invalid,
13421 "can only substitute integer expressions", goto error);
13422
13423 pos += isl_basic_set_offset(bset, type);
13424
13425 isl_int_init(v);
13426
13427 for (i = 0; i < bset->n_eq; ++i) {
13428 if (isl_int_is_zero(bset->eq[i][pos]))
13429 continue;
13430 isl_int_set(v, bset->eq[i][pos]);
13431 isl_int_set_si(bset->eq[i][pos], 0);
13432 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
13433 v, subs->v->el + 1, subs->v->size - 1);
13434 }
13435
13436 for (i = 0; i < bset->n_ineq; ++i) {
13437 if (isl_int_is_zero(bset->ineq[i][pos]))
13438 continue;
13439 isl_int_set(v, bset->ineq[i][pos]);
13440 isl_int_set_si(bset->ineq[i][pos], 0);
13441 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
13442 v, subs->v->el + 1, subs->v->size - 1);
13443 }
13444
13445 for (i = 0; i < bset->n_div; ++i) {
13446 if (isl_int_is_zero(bset->div[i][1 + pos]))
13447 continue;
13448 isl_int_set(v, bset->div[i][1 + pos]);
13449 isl_int_set_si(bset->div[i][1 + pos], 0);
13450 isl_seq_combine(bset->div[i] + 1,
13451 subs->v->el[0], bset->div[i] + 1,
13452 v, subs->v->el + 1, subs->v->size - 1);
13453 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
13454 }
13455
13456 isl_int_clear(v);
13457
13458 bset = isl_basic_set_simplify(bset);
13459 return isl_basic_set_finalize(bset);
13460 error:
13461 isl_basic_set_free(bset);
13462 return NULL;
13463 }
13464
13465 /* Plug in "subs" for dimension "type", "pos" of "set".
13466 */
isl_set_substitute(__isl_take isl_set * set,enum isl_dim_type type,unsigned pos,__isl_keep isl_aff * subs)13467 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
13468 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13469 {
13470 int i;
13471
13472 if (set && isl_set_plain_is_empty(set))
13473 return set;
13474
13475 set = isl_set_cow(set);
13476 if (!set || !subs)
13477 goto error;
13478
13479 for (i = set->n - 1; i >= 0; --i) {
13480 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
13481 set = set_from_map(remove_if_empty(set_to_map(set), i));
13482 if (!set)
13483 return NULL;
13484 }
13485
13486 return set;
13487 error:
13488 isl_set_free(set);
13489 return NULL;
13490 }
13491
13492 /* Check if the range of "ma" is compatible with the domain or range
13493 * (depending on "type") of "bmap".
13494 */
check_basic_map_compatible_range_multi_aff(__isl_keep isl_basic_map * bmap,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13495 static isl_stat check_basic_map_compatible_range_multi_aff(
13496 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
13497 __isl_keep isl_multi_aff *ma)
13498 {
13499 isl_bool m;
13500 isl_space *ma_space;
13501
13502 ma_space = isl_multi_aff_get_space(ma);
13503
13504 m = isl_space_has_equal_params(bmap->dim, ma_space);
13505 if (m < 0)
13506 goto error;
13507 if (!m)
13508 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13509 "parameters don't match", goto error);
13510 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
13511 if (m < 0)
13512 goto error;
13513 if (!m)
13514 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13515 "spaces don't match", goto error);
13516
13517 isl_space_free(ma_space);
13518 return isl_stat_ok;
13519 error:
13520 isl_space_free(ma_space);
13521 return isl_stat_error;
13522 }
13523
13524 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
13525 * coefficients before the transformed range of dimensions,
13526 * the "n_after" coefficients after the transformed range of dimensions
13527 * and the coefficients of the other divs in "bmap".
13528 */
set_ma_divs(__isl_take isl_basic_map * bmap,__isl_keep isl_multi_aff * ma,int n_before,int n_after,int n_div)13529 static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
13530 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
13531 {
13532 int i;
13533 isl_size n_param;
13534 isl_size n_set;
13535 isl_local_space *ls;
13536
13537 if (n_div == 0)
13538 return bmap;
13539
13540 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
13541 n_param = isl_local_space_dim(ls, isl_dim_param);
13542 n_set = isl_local_space_dim(ls, isl_dim_set);
13543 if (n_param < 0 || n_set < 0)
13544 return isl_basic_map_free(bmap);
13545
13546 for (i = 0; i < n_div; ++i) {
13547 int o_bmap = 0, o_ls = 0;
13548
13549 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
13550 o_bmap += 1 + 1 + n_param;
13551 o_ls += 1 + 1 + n_param;
13552 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
13553 o_bmap += n_before;
13554 isl_seq_cpy(bmap->div[i] + o_bmap,
13555 ls->div->row[i] + o_ls, n_set);
13556 o_bmap += n_set;
13557 o_ls += n_set;
13558 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
13559 o_bmap += n_after;
13560 isl_seq_cpy(bmap->div[i] + o_bmap,
13561 ls->div->row[i] + o_ls, n_div);
13562 o_bmap += n_div;
13563 o_ls += n_div;
13564 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
13565 bmap = isl_basic_map_add_div_constraints(bmap, i);
13566 if (!bmap)
13567 goto error;
13568 }
13569
13570 isl_local_space_free(ls);
13571 return bmap;
13572 error:
13573 isl_local_space_free(ls);
13574 return isl_basic_map_free(bmap);
13575 }
13576
13577 /* How many stride constraints does "ma" enforce?
13578 * That is, how many of the affine expressions have a denominator
13579 * different from one?
13580 */
multi_aff_strides(__isl_keep isl_multi_aff * ma)13581 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
13582 {
13583 int i;
13584 int strides = 0;
13585
13586 for (i = 0; i < ma->n; ++i)
13587 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
13588 strides++;
13589
13590 return strides;
13591 }
13592
13593 /* For each affine expression in ma of the form
13594 *
13595 * x_i = (f_i y + h_i)/m_i
13596 *
13597 * with m_i different from one, add a constraint to "bmap"
13598 * of the form
13599 *
13600 * f_i y + h_i = m_i alpha_i
13601 *
13602 * with alpha_i an additional existentially quantified variable.
13603 *
13604 * The input variables of "ma" correspond to a subset of the variables
13605 * of "bmap". There are "n_before" variables in "bmap" before this
13606 * subset and "n_after" variables after this subset.
13607 * The integer divisions of the affine expressions in "ma" are assumed
13608 * to have been aligned. There are "n_div_ma" of them and
13609 * they appear first in "bmap", straight after the "n_after" variables.
13610 */
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)13611 static __isl_give isl_basic_map *add_ma_strides(
13612 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
13613 int n_before, int n_after, int n_div_ma)
13614 {
13615 int i, k;
13616 int div;
13617 isl_size total;
13618 isl_size n_param;
13619 isl_size n_in;
13620
13621 total = isl_basic_map_dim(bmap, isl_dim_all);
13622 n_param = isl_multi_aff_dim(ma, isl_dim_param);
13623 n_in = isl_multi_aff_dim(ma, isl_dim_in);
13624 if (total < 0 || n_param < 0 || n_in < 0)
13625 return isl_basic_map_free(bmap);
13626 for (i = 0; i < ma->n; ++i) {
13627 int o_bmap = 0, o_ma = 1;
13628
13629 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
13630 continue;
13631 div = isl_basic_map_alloc_div(bmap);
13632 k = isl_basic_map_alloc_equality(bmap);
13633 if (div < 0 || k < 0)
13634 goto error;
13635 isl_int_set_si(bmap->div[div][0], 0);
13636 isl_seq_cpy(bmap->eq[k] + o_bmap,
13637 ma->u.p[i]->v->el + o_ma, 1 + n_param);
13638 o_bmap += 1 + n_param;
13639 o_ma += 1 + n_param;
13640 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
13641 o_bmap += n_before;
13642 isl_seq_cpy(bmap->eq[k] + o_bmap,
13643 ma->u.p[i]->v->el + o_ma, n_in);
13644 o_bmap += n_in;
13645 o_ma += n_in;
13646 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
13647 o_bmap += n_after;
13648 isl_seq_cpy(bmap->eq[k] + o_bmap,
13649 ma->u.p[i]->v->el + o_ma, n_div_ma);
13650 o_bmap += n_div_ma;
13651 o_ma += n_div_ma;
13652 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
13653 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
13654 total++;
13655 }
13656
13657 return bmap;
13658 error:
13659 isl_basic_map_free(bmap);
13660 return NULL;
13661 }
13662
13663 /* Replace the domain or range space (depending on "type) of "space" by "set".
13664 */
isl_space_set(__isl_take isl_space * space,enum isl_dim_type type,__isl_take isl_space * set)13665 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
13666 enum isl_dim_type type, __isl_take isl_space *set)
13667 {
13668 if (type == isl_dim_in) {
13669 space = isl_space_range(space);
13670 space = isl_space_map_from_domain_and_range(set, space);
13671 } else {
13672 space = isl_space_domain(space);
13673 space = isl_space_map_from_domain_and_range(space, set);
13674 }
13675
13676 return space;
13677 }
13678
13679 /* Compute the preimage of the domain or range (depending on "type")
13680 * of "bmap" under the function represented by "ma".
13681 * In other words, plug in "ma" in the domain or range of "bmap".
13682 * The result is a basic map that lives in the same space as "bmap"
13683 * except that the domain or range has been replaced by
13684 * the domain space of "ma".
13685 *
13686 * If bmap is represented by
13687 *
13688 * A(p) + S u + B x + T v + C(divs) >= 0,
13689 *
13690 * where u and x are input and output dimensions if type == isl_dim_out
13691 * while x and v are input and output dimensions if type == isl_dim_in,
13692 * and ma is represented by
13693 *
13694 * x = D(p) + F(y) + G(divs')
13695 *
13696 * then the result is
13697 *
13698 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
13699 *
13700 * The divs in the input set are similarly adjusted.
13701 * In particular
13702 *
13703 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
13704 *
13705 * becomes
13706 *
13707 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
13708 * B_i G(divs') + c_i(divs))/n_i)
13709 *
13710 * If bmap is not a rational map and if F(y) involves any denominators
13711 *
13712 * x_i = (f_i y + h_i)/m_i
13713 *
13714 * then additional constraints are added to ensure that we only
13715 * map back integer points. That is we enforce
13716 *
13717 * f_i y + h_i = m_i alpha_i
13718 *
13719 * with alpha_i an additional existentially quantified variable.
13720 *
13721 * We first copy over the divs from "ma".
13722 * Then we add the modified constraints and divs from "bmap".
13723 * Finally, we add the stride constraints, if needed.
13724 */
isl_basic_map_preimage_multi_aff(__isl_take isl_basic_map * bmap,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13725 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
13726 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
13727 __isl_take isl_multi_aff *ma)
13728 {
13729 int i, k;
13730 isl_space *space;
13731 isl_basic_map *res = NULL;
13732 isl_size n_before, n_after, n_div_bmap, n_div_ma;
13733 isl_int f, c1, c2, g;
13734 isl_bool rational;
13735 int strides;
13736
13737 isl_int_init(f);
13738 isl_int_init(c1);
13739 isl_int_init(c2);
13740 isl_int_init(g);
13741
13742 ma = isl_multi_aff_align_divs(ma);
13743 if (!bmap || !ma)
13744 goto error;
13745 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
13746 goto error;
13747
13748 if (type == isl_dim_in) {
13749 n_before = 0;
13750 n_after = isl_basic_map_dim(bmap, isl_dim_out);
13751 } else {
13752 n_before = isl_basic_map_dim(bmap, isl_dim_in);
13753 n_after = 0;
13754 }
13755 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
13756 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
13757 if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
13758 goto error;
13759
13760 space = isl_multi_aff_get_domain_space(ma);
13761 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
13762 rational = isl_basic_map_is_rational(bmap);
13763 strides = rational ? 0 : multi_aff_strides(ma);
13764 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
13765 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
13766 if (rational)
13767 res = isl_basic_map_set_rational(res);
13768
13769 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
13770 if (isl_basic_map_alloc_div(res) < 0)
13771 goto error;
13772
13773 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
13774 if (!res)
13775 goto error;
13776
13777 for (i = 0; i < bmap->n_eq; ++i) {
13778 k = isl_basic_map_alloc_equality(res);
13779 if (k < 0)
13780 goto error;
13781 if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13782 n_after, n_div_ma, n_div_bmap,
13783 f, c1, c2, g, 0) < 0)
13784 goto error;
13785 }
13786
13787 for (i = 0; i < bmap->n_ineq; ++i) {
13788 k = isl_basic_map_alloc_inequality(res);
13789 if (k < 0)
13790 goto error;
13791 if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13792 n_after, n_div_ma, n_div_bmap,
13793 f, c1, c2, g, 0) < 0)
13794 goto error;
13795 }
13796
13797 for (i = 0; i < bmap->n_div; ++i) {
13798 if (isl_int_is_zero(bmap->div[i][0])) {
13799 isl_int_set_si(res->div[n_div_ma + i][0], 0);
13800 continue;
13801 }
13802 if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13803 n_before, n_after, n_div_ma, n_div_bmap,
13804 f, c1, c2, g, 1) < 0)
13805 goto error;
13806 }
13807
13808 if (strides)
13809 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13810
13811 isl_int_clear(f);
13812 isl_int_clear(c1);
13813 isl_int_clear(c2);
13814 isl_int_clear(g);
13815 isl_basic_map_free(bmap);
13816 isl_multi_aff_free(ma);
13817 res = isl_basic_map_simplify(res);
13818 return isl_basic_map_finalize(res);
13819 error:
13820 isl_int_clear(f);
13821 isl_int_clear(c1);
13822 isl_int_clear(c2);
13823 isl_int_clear(g);
13824 isl_basic_map_free(bmap);
13825 isl_multi_aff_free(ma);
13826 isl_basic_map_free(res);
13827 return NULL;
13828 }
13829
13830 /* Compute the preimage of "bset" under the function represented by "ma".
13831 * In other words, plug in "ma" in "bset". The result is a basic set
13832 * that lives in the domain space of "ma".
13833 */
isl_basic_set_preimage_multi_aff(__isl_take isl_basic_set * bset,__isl_take isl_multi_aff * ma)13834 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13835 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13836 {
13837 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13838 }
13839
13840 /* Compute the preimage of the domain of "bmap" under the function
13841 * represented by "ma".
13842 * In other words, plug in "ma" in the domain of "bmap".
13843 * The result is a basic map that lives in the same space as "bmap"
13844 * except that the domain has been replaced by the domain space of "ma".
13845 */
isl_basic_map_preimage_domain_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13846 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13847 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13848 {
13849 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13850 }
13851
13852 /* Compute the preimage of the range of "bmap" under the function
13853 * represented by "ma".
13854 * In other words, plug in "ma" in the range of "bmap".
13855 * The result is a basic map that lives in the same space as "bmap"
13856 * except that the range has been replaced by the domain space of "ma".
13857 */
isl_basic_map_preimage_range_multi_aff(__isl_take isl_basic_map * bmap,__isl_take isl_multi_aff * ma)13858 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13859 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13860 {
13861 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13862 }
13863
13864 /* Check if the range of "ma" is compatible with the domain or range
13865 * (depending on "type") of "map".
13866 * Return isl_stat_error if anything is wrong.
13867 */
check_map_compatible_range_multi_aff(__isl_keep isl_map * map,enum isl_dim_type type,__isl_keep isl_multi_aff * ma)13868 static isl_stat check_map_compatible_range_multi_aff(
13869 __isl_keep isl_map *map, enum isl_dim_type type,
13870 __isl_keep isl_multi_aff *ma)
13871 {
13872 isl_bool m;
13873 isl_space *ma_space;
13874
13875 ma_space = isl_multi_aff_get_space(ma);
13876 m = isl_map_space_tuple_is_equal(map, type, ma_space, isl_dim_out);
13877 isl_space_free(ma_space);
13878 if (m < 0)
13879 return isl_stat_error;
13880 if (!m)
13881 isl_die(isl_map_get_ctx(map), isl_error_invalid,
13882 "spaces don't match", return isl_stat_error);
13883 return isl_stat_ok;
13884 }
13885
13886 /* Compute the preimage of the domain or range (depending on "type")
13887 * of "map" under the function represented by "ma".
13888 * In other words, plug in "ma" in the domain or range of "map".
13889 * The result is a map that lives in the same space as "map"
13890 * except that the domain or range has been replaced by
13891 * the domain space of "ma".
13892 *
13893 * The parameters are assumed to have been aligned.
13894 */
map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13895 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13896 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13897 {
13898 int i;
13899 isl_space *space;
13900
13901 map = isl_map_cow(map);
13902 ma = isl_multi_aff_align_divs(ma);
13903 if (!map || !ma)
13904 goto error;
13905 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13906 goto error;
13907
13908 for (i = 0; i < map->n; ++i) {
13909 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13910 isl_multi_aff_copy(ma));
13911 if (!map->p[i])
13912 goto error;
13913 }
13914
13915 space = isl_multi_aff_get_domain_space(ma);
13916 space = isl_space_set(isl_map_get_space(map), type, space);
13917
13918 isl_space_free(isl_map_take_space(map));
13919 map = isl_map_restore_space(map, space);
13920 if (!map)
13921 goto error;
13922
13923 isl_multi_aff_free(ma);
13924 if (map->n > 1)
13925 ISL_F_CLR(map, ISL_MAP_DISJOINT);
13926 ISL_F_CLR(map, ISL_SET_NORMALIZED);
13927 return map;
13928 error:
13929 isl_multi_aff_free(ma);
13930 isl_map_free(map);
13931 return NULL;
13932 }
13933
13934 /* Compute the preimage of the domain or range (depending on "type")
13935 * of "map" under the function represented by "ma".
13936 * In other words, plug in "ma" in the domain or range of "map".
13937 * The result is a map that lives in the same space as "map"
13938 * except that the domain or range has been replaced by
13939 * the domain space of "ma".
13940 */
isl_map_preimage_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_aff * ma)13941 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13942 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13943 {
13944 isl_bool aligned;
13945
13946 if (!map || !ma)
13947 goto error;
13948
13949 aligned = isl_map_space_has_equal_params(map, ma->space);
13950 if (aligned < 0)
13951 goto error;
13952 if (aligned)
13953 return map_preimage_multi_aff(map, type, ma);
13954
13955 if (isl_map_check_named_params(map) < 0)
13956 goto error;
13957 if (!isl_space_has_named_params(ma->space))
13958 isl_die(map->ctx, isl_error_invalid,
13959 "unaligned unnamed parameters", goto error);
13960 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13961 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13962
13963 return map_preimage_multi_aff(map, type, ma);
13964 error:
13965 isl_multi_aff_free(ma);
13966 return isl_map_free(map);
13967 }
13968
13969 /* Compute the preimage of "set" under the function represented by "ma".
13970 * In other words, plug in "ma" in "set". The result is a set
13971 * that lives in the domain space of "ma".
13972 */
isl_set_preimage_multi_aff(__isl_take isl_set * set,__isl_take isl_multi_aff * ma)13973 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
13974 __isl_take isl_multi_aff *ma)
13975 {
13976 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
13977 }
13978
13979 /* Compute the preimage of the domain of "map" under the function
13980 * represented by "ma".
13981 * In other words, plug in "ma" in the domain of "map".
13982 * The result is a map that lives in the same space as "map"
13983 * except that the domain has been replaced by the domain space of "ma".
13984 */
isl_map_preimage_domain_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)13985 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
13986 __isl_take isl_multi_aff *ma)
13987 {
13988 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
13989 }
13990
13991 /* Compute the preimage of the range of "map" under the function
13992 * represented by "ma".
13993 * In other words, plug in "ma" in the range of "map".
13994 * The result is a map that lives in the same space as "map"
13995 * except that the range has been replaced by the domain space of "ma".
13996 */
isl_map_preimage_range_multi_aff(__isl_take isl_map * map,__isl_take isl_multi_aff * ma)13997 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
13998 __isl_take isl_multi_aff *ma)
13999 {
14000 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
14001 }
14002
14003 /* Compute the preimage of "map" under the function represented by "pma".
14004 * In other words, plug in "pma" in the domain or range of "map".
14005 * The result is a map that lives in the same space as "map",
14006 * except that the space of type "type" has been replaced by
14007 * the domain space of "pma".
14008 *
14009 * The parameters of "map" and "pma" are assumed to have been aligned.
14010 */
isl_map_preimage_pw_multi_aff_aligned(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14011 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
14012 __isl_take isl_map *map, enum isl_dim_type type,
14013 __isl_take isl_pw_multi_aff *pma)
14014 {
14015 int i;
14016 isl_map *res;
14017
14018 if (!pma)
14019 goto error;
14020
14021 if (pma->n == 0) {
14022 isl_pw_multi_aff_free(pma);
14023 res = isl_map_empty(isl_map_get_space(map));
14024 isl_map_free(map);
14025 return res;
14026 }
14027
14028 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14029 isl_multi_aff_copy(pma->p[0].maff));
14030 if (type == isl_dim_in)
14031 res = isl_map_intersect_domain(res,
14032 isl_map_copy(pma->p[0].set));
14033 else
14034 res = isl_map_intersect_range(res,
14035 isl_map_copy(pma->p[0].set));
14036
14037 for (i = 1; i < pma->n; ++i) {
14038 isl_map *res_i;
14039
14040 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14041 isl_multi_aff_copy(pma->p[i].maff));
14042 if (type == isl_dim_in)
14043 res_i = isl_map_intersect_domain(res_i,
14044 isl_map_copy(pma->p[i].set));
14045 else
14046 res_i = isl_map_intersect_range(res_i,
14047 isl_map_copy(pma->p[i].set));
14048 res = isl_map_union(res, res_i);
14049 }
14050
14051 isl_pw_multi_aff_free(pma);
14052 isl_map_free(map);
14053 return res;
14054 error:
14055 isl_pw_multi_aff_free(pma);
14056 isl_map_free(map);
14057 return NULL;
14058 }
14059
14060 /* Compute the preimage of "map" under the function represented by "pma".
14061 * In other words, plug in "pma" in the domain or range of "map".
14062 * The result is a map that lives in the same space as "map",
14063 * except that the space of type "type" has been replaced by
14064 * the domain space of "pma".
14065 */
isl_map_preimage_pw_multi_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_pw_multi_aff * pma)14066 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
14067 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
14068 {
14069 isl_bool aligned;
14070
14071 if (!map || !pma)
14072 goto error;
14073
14074 aligned = isl_map_space_has_equal_params(map, pma->dim);
14075 if (aligned < 0)
14076 goto error;
14077 if (aligned)
14078 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14079
14080 if (isl_map_check_named_params(map) < 0)
14081 goto error;
14082 if (isl_pw_multi_aff_check_named_params(pma) < 0)
14083 goto error;
14084 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
14085 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
14086
14087 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14088 error:
14089 isl_pw_multi_aff_free(pma);
14090 return isl_map_free(map);
14091 }
14092
14093 /* Compute the preimage of "set" under the function represented by "pma".
14094 * In other words, plug in "pma" in "set". The result is a set
14095 * that lives in the domain space of "pma".
14096 */
isl_set_preimage_pw_multi_aff(__isl_take isl_set * set,__isl_take isl_pw_multi_aff * pma)14097 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
14098 __isl_take isl_pw_multi_aff *pma)
14099 {
14100 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
14101 }
14102
14103 /* Compute the preimage of the domain of "map" under the function
14104 * represented by "pma".
14105 * In other words, plug in "pma" in the domain of "map".
14106 * The result is a map that lives in the same space as "map",
14107 * except that domain space has been replaced by the domain space of "pma".
14108 */
isl_map_preimage_domain_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14109 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
14110 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14111 {
14112 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
14113 }
14114
14115 /* Compute the preimage of the range of "map" under the function
14116 * represented by "pma".
14117 * In other words, plug in "pma" in the range of "map".
14118 * The result is a map that lives in the same space as "map",
14119 * except that range space has been replaced by the domain space of "pma".
14120 */
isl_map_preimage_range_pw_multi_aff(__isl_take isl_map * map,__isl_take isl_pw_multi_aff * pma)14121 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
14122 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14123 {
14124 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
14125 }
14126
14127 /* Compute the preimage of "map" under the function represented by "mpa".
14128 * In other words, plug in "mpa" in the domain or range of "map".
14129 * The result is a map that lives in the same space as "map",
14130 * except that the space of type "type" has been replaced by
14131 * the domain space of "mpa".
14132 *
14133 * If the map does not involve any constraints that refer to the
14134 * dimensions of the substituted space, then the only possible
14135 * effect of "mpa" on the map is to map the space to a different space.
14136 * We create a separate isl_multi_aff to effectuate this change
14137 * in order to avoid spurious splitting of the map along the pieces
14138 * of "mpa".
14139 * If "mpa" has a non-trivial explicit domain, however,
14140 * then the full substitution should be performed.
14141 */
isl_map_preimage_multi_pw_aff(__isl_take isl_map * map,enum isl_dim_type type,__isl_take isl_multi_pw_aff * mpa)14142 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
14143 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
14144 {
14145 isl_size n;
14146 isl_bool full;
14147 isl_pw_multi_aff *pma;
14148
14149 n = isl_map_dim(map, type);
14150 if (n < 0 || !mpa)
14151 goto error;
14152
14153 full = isl_map_involves_dims(map, type, 0, n);
14154 if (full >= 0 && !full)
14155 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
14156 if (full < 0)
14157 goto error;
14158 if (!full) {
14159 isl_space *space;
14160 isl_multi_aff *ma;
14161
14162 space = isl_multi_pw_aff_get_space(mpa);
14163 isl_multi_pw_aff_free(mpa);
14164 ma = isl_multi_aff_zero(space);
14165 return isl_map_preimage_multi_aff(map, type, ma);
14166 }
14167
14168 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
14169 return isl_map_preimage_pw_multi_aff(map, type, pma);
14170 error:
14171 isl_map_free(map);
14172 isl_multi_pw_aff_free(mpa);
14173 return NULL;
14174 }
14175
14176 /* Compute the preimage of "map" under the function represented by "mpa".
14177 * In other words, plug in "mpa" in the domain "map".
14178 * The result is a map that lives in the same space as "map",
14179 * except that domain space has been replaced by the domain space of "mpa".
14180 */
isl_map_preimage_domain_multi_pw_aff(__isl_take isl_map * map,__isl_take isl_multi_pw_aff * mpa)14181 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
14182 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
14183 {
14184 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
14185 }
14186
14187 /* Compute the preimage of "set" by the function represented by "mpa".
14188 * In other words, plug in "mpa" in "set".
14189 */
isl_set_preimage_multi_pw_aff(__isl_take isl_set * set,__isl_take isl_multi_pw_aff * mpa)14190 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
14191 __isl_take isl_multi_pw_aff *mpa)
14192 {
14193 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
14194 }
14195
14196 /* Return a copy of the equality constraints of "bset" as a matrix.
14197 */
isl_basic_set_extract_equalities(__isl_keep isl_basic_set * bset)14198 __isl_give isl_mat *isl_basic_set_extract_equalities(
14199 __isl_keep isl_basic_set *bset)
14200 {
14201 isl_ctx *ctx;
14202 isl_size total;
14203
14204 total = isl_basic_set_dim(bset, isl_dim_all);
14205 if (total < 0)
14206 return NULL;
14207
14208 ctx = isl_basic_set_get_ctx(bset);
14209 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
14210 }
14211
14212 /* Are the "n" "coefficients" starting at "first" of the integer division
14213 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
14214 * to each other?
14215 * The "coefficient" at position 0 is the denominator.
14216 * The "coefficient" at position 1 is the constant term.
14217 */
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)14218 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
14219 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
14220 unsigned first, unsigned n)
14221 {
14222 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
14223 return isl_bool_error;
14224 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
14225 return isl_bool_error;
14226 return isl_seq_eq(bmap1->div[pos1] + first,
14227 bmap2->div[pos2] + first, n);
14228 }
14229
14230 /* Are the integer division expressions at position "pos1" in "bmap1" and
14231 * "pos2" in "bmap2" equal to each other, except that the constant terms
14232 * are different?
14233 */
isl_basic_map_equal_div_expr_except_constant(__isl_keep isl_basic_map * bmap1,int pos1,__isl_keep isl_basic_map * bmap2,int pos2)14234 isl_bool isl_basic_map_equal_div_expr_except_constant(
14235 __isl_keep isl_basic_map *bmap1, int pos1,
14236 __isl_keep isl_basic_map *bmap2, int pos2)
14237 {
14238 isl_bool equal;
14239 isl_size total, total2;
14240
14241 total = isl_basic_map_dim(bmap1, isl_dim_all);
14242 total2 = isl_basic_map_dim(bmap2, isl_dim_all);
14243 if (total < 0 || total2 < 0)
14244 return isl_bool_error;
14245 if (total != total2)
14246 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
14247 "incomparable div expressions", return isl_bool_error);
14248 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14249 0, 1);
14250 if (equal < 0 || !equal)
14251 return equal;
14252 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14253 1, 1);
14254 if (equal < 0 || equal)
14255 return isl_bool_not(equal);
14256 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14257 2, total);
14258 }
14259
14260 /* Replace the numerator of the constant term of the integer division
14261 * expression at position "div" in "bmap" by "value".
14262 * The caller guarantees that this does not change the meaning
14263 * of the input.
14264 */
isl_basic_map_set_div_expr_constant_num_si_inplace(__isl_take isl_basic_map * bmap,int div,int value)14265 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
14266 __isl_take isl_basic_map *bmap, int div, int value)
14267 {
14268 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
14269 return isl_basic_map_free(bmap);
14270
14271 isl_int_set_si(bmap->div[div][1], value);
14272
14273 return bmap;
14274 }
14275
14276 /* Is the point "inner" internal to inequality constraint "ineq"
14277 * of "bset"?
14278 * The point is considered to be internal to the inequality constraint,
14279 * if it strictly lies on the positive side of the inequality constraint,
14280 * or if it lies on the constraint and the constraint is lexico-positive.
14281 */
is_internal(__isl_keep isl_vec * inner,__isl_keep isl_basic_set * bset,int ineq)14282 static isl_bool is_internal(__isl_keep isl_vec *inner,
14283 __isl_keep isl_basic_set *bset, int ineq)
14284 {
14285 isl_ctx *ctx;
14286 int pos;
14287 isl_size total;
14288
14289 if (!inner || !bset)
14290 return isl_bool_error;
14291
14292 ctx = isl_basic_set_get_ctx(bset);
14293 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
14294 &ctx->normalize_gcd);
14295 if (!isl_int_is_zero(ctx->normalize_gcd))
14296 return isl_int_is_nonneg(ctx->normalize_gcd);
14297
14298 total = isl_basic_set_dim(bset, isl_dim_all);
14299 if (total < 0)
14300 return isl_bool_error;
14301 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
14302 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
14303 }
14304
14305 /* Tighten the inequality constraints of "bset" that are outward with respect
14306 * to the point "vec".
14307 * That is, tighten the constraints that are not satisfied by "vec".
14308 *
14309 * "vec" is a point internal to some superset S of "bset" that is used
14310 * to make the subsets of S disjoint, by tightening one half of the constraints
14311 * that separate two subsets. In particular, the constraints of S
14312 * are all satisfied by "vec" and should not be tightened.
14313 * Of the internal constraints, those that have "vec" on the outside
14314 * are tightened. The shared facet is included in the adjacent subset
14315 * with the opposite constraint.
14316 * For constraints that saturate "vec", this criterion cannot be used
14317 * to determine which of the two sides should be tightened.
14318 * Instead, the sign of the first non-zero coefficient is used
14319 * to make this choice. Note that this second criterion is never used
14320 * on the constraints of S since "vec" is interior to "S".
14321 */
isl_basic_set_tighten_outward(__isl_take isl_basic_set * bset,__isl_keep isl_vec * vec)14322 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
14323 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
14324 {
14325 int j;
14326
14327 bset = isl_basic_set_cow(bset);
14328 if (!bset)
14329 return NULL;
14330 for (j = 0; j < bset->n_ineq; ++j) {
14331 isl_bool internal;
14332
14333 internal = is_internal(vec, bset, j);
14334 if (internal < 0)
14335 return isl_basic_set_free(bset);
14336 if (internal)
14337 continue;
14338 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
14339 }
14340
14341 return bset;
14342 }
14343
14344 /* Replace the variables x of type "type" starting at "first" in "bmap"
14345 * by x' with x = M x' with M the matrix trans.
14346 * That is, replace the corresponding coefficients c by c M.
14347 *
14348 * The transformation matrix should be a square matrix.
14349 */
isl_basic_map_transform_dims(__isl_take isl_basic_map * bmap,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14350 __isl_give isl_basic_map *isl_basic_map_transform_dims(
14351 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
14352 __isl_take isl_mat *trans)
14353 {
14354 unsigned pos;
14355
14356 bmap = isl_basic_map_cow(bmap);
14357 if (!bmap || !trans)
14358 goto error;
14359
14360 if (trans->n_row != trans->n_col)
14361 isl_die(trans->ctx, isl_error_invalid,
14362 "expecting square transformation matrix", goto error);
14363 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
14364 goto error;
14365
14366 pos = isl_basic_map_offset(bmap, type) + first;
14367
14368 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
14369 isl_mat_copy(trans)) < 0)
14370 goto error;
14371 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
14372 isl_mat_copy(trans)) < 0)
14373 goto error;
14374 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
14375 isl_mat_copy(trans)) < 0)
14376 goto error;
14377
14378 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
14379 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
14380
14381 isl_mat_free(trans);
14382 return bmap;
14383 error:
14384 isl_mat_free(trans);
14385 isl_basic_map_free(bmap);
14386 return NULL;
14387 }
14388
14389 /* Replace the variables x of type "type" starting at "first" in "bset"
14390 * by x' with x = M x' with M the matrix trans.
14391 * That is, replace the corresponding coefficients c by c M.
14392 *
14393 * The transformation matrix should be a square matrix.
14394 */
isl_basic_set_transform_dims(__isl_take isl_basic_set * bset,enum isl_dim_type type,unsigned first,__isl_take isl_mat * trans)14395 __isl_give isl_basic_set *isl_basic_set_transform_dims(
14396 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
14397 __isl_take isl_mat *trans)
14398 {
14399 return isl_basic_map_transform_dims(bset, type, first, trans);
14400 }
14401