drop deprecated isl_set_dim_is_unique
[isl.git] / isl_map.c
blob3d9df5974638d70bcd63465eef988dcb474e5083
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
9 * Use of this software is governed by the MIT license
11 * Written by Sven Verdoolaege, K.U.Leuven, Departement
12 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
13 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
14 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
15 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
16 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
17 * B.P. 105 - 78153 Le Chesnay, France
18 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
19 * CS 42112, 75589 Paris Cedex 12, France
22 #include <string.h>
23 #include <isl_ctx_private.h>
24 #include <isl_map_private.h>
25 #include <isl_blk.h>
26 #include <isl/constraint.h>
27 #include "isl_space_private.h"
28 #include "isl_equalities.h"
29 #include <isl_lp_private.h>
30 #include <isl_seq.h>
31 #include <isl/set.h>
32 #include <isl/map.h>
33 #include <isl_reordering.h>
34 #include "isl_sample.h"
35 #include <isl_sort.h>
36 #include "isl_tab.h"
37 #include <isl/vec.h>
38 #include <isl_mat_private.h>
39 #include <isl_vec_private.h>
40 #include <isl_dim_map.h>
41 #include <isl_local_space_private.h>
42 #include <isl_aff_private.h>
43 #include <isl_options_private.h>
44 #include <isl_morph.h>
45 #include <isl_val_private.h>
46 #include <isl/deprecated/map_int.h>
47 #include <isl/deprecated/set_int.h>
49 #include <bset_to_bmap.c>
50 #include <bset_from_bmap.c>
51 #include <set_to_map.c>
52 #include <set_from_map.c>
54 static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
56 switch (type) {
57 case isl_dim_param: return dim->nparam;
58 case isl_dim_in: return dim->n_in;
59 case isl_dim_out: return dim->n_out;
60 case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
61 default: return 0;
65 static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
67 switch (type) {
68 case isl_dim_param: return 1;
69 case isl_dim_in: return 1 + dim->nparam;
70 case isl_dim_out: return 1 + dim->nparam + dim->n_in;
71 default: return 0;
75 unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
76 enum isl_dim_type type)
78 if (!bmap)
79 return 0;
80 switch (type) {
81 case isl_dim_cst: return 1;
82 case isl_dim_param:
83 case isl_dim_in:
84 case isl_dim_out: return isl_space_dim(bmap->dim, type);
85 case isl_dim_div: return bmap->n_div;
86 case isl_dim_all: return isl_basic_map_total_dim(bmap);
87 default: return 0;
91 unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
93 return map ? n(map->dim, type) : 0;
96 unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
98 return set ? n(set->dim, type) : 0;
101 unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
102 enum isl_dim_type type)
104 isl_space *space;
106 if (!bmap)
107 return 0;
109 space = bmap->dim;
110 switch (type) {
111 case isl_dim_cst: return 0;
112 case isl_dim_param: return 1;
113 case isl_dim_in: return 1 + space->nparam;
114 case isl_dim_out: return 1 + space->nparam + space->n_in;
115 case isl_dim_div: return 1 + space->nparam + space->n_in +
116 space->n_out;
117 default: return 0;
121 unsigned isl_basic_set_offset(struct isl_basic_set *bset,
122 enum isl_dim_type type)
124 return isl_basic_map_offset(bset, type);
127 static unsigned map_offset(struct isl_map *map, enum isl_dim_type type)
129 return pos(map->dim, type);
132 unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
133 enum isl_dim_type type)
135 return isl_basic_map_dim(bset, type);
138 unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
140 return isl_basic_set_dim(bset, isl_dim_set);
143 unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
145 return isl_basic_set_dim(bset, isl_dim_param);
148 unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset)
150 if (!bset)
151 return 0;
152 return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
155 unsigned isl_set_n_dim(__isl_keep isl_set *set)
157 return isl_set_dim(set, isl_dim_set);
160 unsigned isl_set_n_param(__isl_keep isl_set *set)
162 return isl_set_dim(set, isl_dim_param);
165 unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap)
167 return bmap ? bmap->dim->n_in : 0;
170 unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap)
172 return bmap ? bmap->dim->n_out : 0;
175 unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap)
177 return bmap ? bmap->dim->nparam : 0;
180 unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap)
182 return bmap ? bmap->n_div : 0;
185 unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap)
187 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
190 unsigned isl_map_n_in(const struct isl_map *map)
192 return map ? map->dim->n_in : 0;
195 unsigned isl_map_n_out(const struct isl_map *map)
197 return map ? map->dim->n_out : 0;
200 unsigned isl_map_n_param(const struct isl_map *map)
202 return map ? map->dim->nparam : 0;
205 isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
206 __isl_keep isl_set *set)
208 isl_bool m;
209 if (!map || !set)
210 return isl_bool_error;
211 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
212 if (m < 0 || !m)
213 return m;
214 return isl_space_tuple_is_equal(map->dim, isl_dim_in,
215 set->dim, isl_dim_set);
218 isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
219 __isl_keep isl_basic_set *bset)
221 isl_bool m;
222 if (!bmap || !bset)
223 return isl_bool_error;
224 m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
225 if (m < 0 || !m)
226 return m;
227 return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
228 bset->dim, isl_dim_set);
231 isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
232 __isl_keep isl_set *set)
234 isl_bool m;
235 if (!map || !set)
236 return isl_bool_error;
237 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
238 if (m < 0 || !m)
239 return m;
240 return isl_space_tuple_is_equal(map->dim, isl_dim_out,
241 set->dim, isl_dim_set);
244 isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
245 __isl_keep isl_basic_set *bset)
247 isl_bool m;
248 if (!bmap || !bset)
249 return isl_bool_error;
250 m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
251 if (m < 0 || !m)
252 return m;
253 return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
254 bset->dim, isl_dim_set);
257 isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
259 return bmap ? bmap->ctx : NULL;
262 isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
264 return bset ? bset->ctx : NULL;
267 isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
269 return map ? map->ctx : NULL;
272 isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
274 return set ? set->ctx : NULL;
277 __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
279 if (!bmap)
280 return NULL;
281 return isl_space_copy(bmap->dim);
284 __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
286 if (!bset)
287 return NULL;
288 return isl_space_copy(bset->dim);
291 /* Extract the divs in "bmap" as a matrix.
293 __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
295 int i;
296 isl_ctx *ctx;
297 isl_mat *div;
298 unsigned total;
299 unsigned cols;
301 if (!bmap)
302 return NULL;
304 ctx = isl_basic_map_get_ctx(bmap);
305 total = isl_space_dim(bmap->dim, isl_dim_all);
306 cols = 1 + 1 + total + bmap->n_div;
307 div = isl_mat_alloc(ctx, bmap->n_div, cols);
308 if (!div)
309 return NULL;
311 for (i = 0; i < bmap->n_div; ++i)
312 isl_seq_cpy(div->row[i], bmap->div[i], cols);
314 return div;
317 /* Extract the divs in "bset" as a matrix.
319 __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
321 return isl_basic_map_get_divs(bset);
324 __isl_give isl_local_space *isl_basic_map_get_local_space(
325 __isl_keep isl_basic_map *bmap)
327 isl_mat *div;
329 if (!bmap)
330 return NULL;
332 div = isl_basic_map_get_divs(bmap);
333 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
336 __isl_give isl_local_space *isl_basic_set_get_local_space(
337 __isl_keep isl_basic_set *bset)
339 return isl_basic_map_get_local_space(bset);
342 /* For each known div d = floor(f/m), add the constraints
344 * f - m d >= 0
345 * -(f-(m-1)) + m d >= 0
347 * Do not finalize the result.
349 static __isl_give isl_basic_map *add_known_div_constraints(
350 __isl_take isl_basic_map *bmap)
352 int i;
353 unsigned n_div;
355 if (!bmap)
356 return NULL;
357 n_div = isl_basic_map_dim(bmap, isl_dim_div);
358 if (n_div == 0)
359 return bmap;
360 bmap = isl_basic_map_cow(bmap);
361 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
362 if (!bmap)
363 return NULL;
364 for (i = 0; i < n_div; ++i) {
365 if (isl_int_is_zero(bmap->div[i][0]))
366 continue;
367 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
368 return isl_basic_map_free(bmap);
371 return bmap;
374 __isl_give isl_basic_map *isl_basic_map_from_local_space(
375 __isl_take isl_local_space *ls)
377 int i;
378 int n_div;
379 isl_basic_map *bmap;
381 if (!ls)
382 return NULL;
384 n_div = isl_local_space_dim(ls, isl_dim_div);
385 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
386 n_div, 0, 2 * n_div);
388 for (i = 0; i < n_div; ++i)
389 if (isl_basic_map_alloc_div(bmap) < 0)
390 goto error;
392 for (i = 0; i < n_div; ++i)
393 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
394 bmap = add_known_div_constraints(bmap);
396 isl_local_space_free(ls);
397 return bmap;
398 error:
399 isl_local_space_free(ls);
400 isl_basic_map_free(bmap);
401 return NULL;
404 __isl_give isl_basic_set *isl_basic_set_from_local_space(
405 __isl_take isl_local_space *ls)
407 return isl_basic_map_from_local_space(ls);
410 __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
412 if (!map)
413 return NULL;
414 return isl_space_copy(map->dim);
417 __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
419 if (!set)
420 return NULL;
421 return isl_space_copy(set->dim);
424 __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
425 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
427 bmap = isl_basic_map_cow(bmap);
428 if (!bmap)
429 return NULL;
430 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
431 if (!bmap->dim)
432 goto error;
433 bmap = isl_basic_map_finalize(bmap);
434 return bmap;
435 error:
436 isl_basic_map_free(bmap);
437 return NULL;
440 __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
441 __isl_take isl_basic_set *bset, const char *s)
443 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
446 const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
447 enum isl_dim_type type)
449 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
452 __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
453 enum isl_dim_type type, const char *s)
455 int i;
457 map = isl_map_cow(map);
458 if (!map)
459 return NULL;
461 map->dim = isl_space_set_tuple_name(map->dim, type, s);
462 if (!map->dim)
463 goto error;
465 for (i = 0; i < map->n; ++i) {
466 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
467 if (!map->p[i])
468 goto error;
471 return map;
472 error:
473 isl_map_free(map);
474 return NULL;
477 /* Replace the identifier of the tuple of type "type" by "id".
479 __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
480 __isl_take isl_basic_map *bmap,
481 enum isl_dim_type type, __isl_take isl_id *id)
483 bmap = isl_basic_map_cow(bmap);
484 if (!bmap)
485 goto error;
486 bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
487 if (!bmap->dim)
488 return isl_basic_map_free(bmap);
489 bmap = isl_basic_map_finalize(bmap);
490 return bmap;
491 error:
492 isl_id_free(id);
493 return NULL;
496 /* Replace the identifier of the tuple by "id".
498 __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
499 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
501 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
504 /* Does the input or output tuple have a name?
506 isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
508 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
511 const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
512 enum isl_dim_type type)
514 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
517 __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
518 const char *s)
520 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
521 isl_dim_set, s));
524 __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
525 enum isl_dim_type type, __isl_take isl_id *id)
527 map = isl_map_cow(map);
528 if (!map)
529 goto error;
531 map->dim = isl_space_set_tuple_id(map->dim, type, id);
533 return isl_map_reset_space(map, isl_space_copy(map->dim));
534 error:
535 isl_id_free(id);
536 return NULL;
539 __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
540 __isl_take isl_id *id)
542 return isl_map_set_tuple_id(set, isl_dim_set, id);
545 __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
546 enum isl_dim_type type)
548 map = isl_map_cow(map);
549 if (!map)
550 return NULL;
552 map->dim = isl_space_reset_tuple_id(map->dim, type);
554 return isl_map_reset_space(map, isl_space_copy(map->dim));
557 __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
559 return isl_map_reset_tuple_id(set, isl_dim_set);
562 isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
564 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
567 __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
568 enum isl_dim_type type)
570 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
573 isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
575 return isl_map_has_tuple_id(set, isl_dim_set);
578 __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
580 return isl_map_get_tuple_id(set, isl_dim_set);
583 /* Does the set tuple have a name?
585 isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
587 if (!set)
588 return isl_bool_error;
589 return isl_space_has_tuple_name(set->dim, isl_dim_set);
593 const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
595 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
598 const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
600 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
603 const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
604 enum isl_dim_type type, unsigned pos)
606 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
609 const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
610 enum isl_dim_type type, unsigned pos)
612 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
615 /* Does the given dimension have a name?
617 isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
618 enum isl_dim_type type, unsigned pos)
620 if (!map)
621 return isl_bool_error;
622 return isl_space_has_dim_name(map->dim, type, pos);
625 const char *isl_map_get_dim_name(__isl_keep isl_map *map,
626 enum isl_dim_type type, unsigned pos)
628 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
631 const char *isl_set_get_dim_name(__isl_keep isl_set *set,
632 enum isl_dim_type type, unsigned pos)
634 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
637 /* Does the given dimension have a name?
639 isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
640 enum isl_dim_type type, unsigned pos)
642 if (!set)
643 return isl_bool_error;
644 return isl_space_has_dim_name(set->dim, type, pos);
647 __isl_give isl_basic_map *isl_basic_map_set_dim_name(
648 __isl_take isl_basic_map *bmap,
649 enum isl_dim_type type, unsigned pos, const char *s)
651 bmap = isl_basic_map_cow(bmap);
652 if (!bmap)
653 return NULL;
654 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
655 if (!bmap->dim)
656 goto error;
657 return isl_basic_map_finalize(bmap);
658 error:
659 isl_basic_map_free(bmap);
660 return NULL;
663 __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
664 enum isl_dim_type type, unsigned pos, const char *s)
666 int i;
668 map = isl_map_cow(map);
669 if (!map)
670 return NULL;
672 map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
673 if (!map->dim)
674 goto error;
676 for (i = 0; i < map->n; ++i) {
677 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
678 if (!map->p[i])
679 goto error;
682 return map;
683 error:
684 isl_map_free(map);
685 return NULL;
688 __isl_give isl_basic_set *isl_basic_set_set_dim_name(
689 __isl_take isl_basic_set *bset,
690 enum isl_dim_type type, unsigned pos, const char *s)
692 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
693 type, pos, s));
696 __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
697 enum isl_dim_type type, unsigned pos, const char *s)
699 return set_from_map(isl_map_set_dim_name(set_to_map(set),
700 type, pos, s));
703 isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
704 enum isl_dim_type type, unsigned pos)
706 if (!bmap)
707 return isl_bool_error;
708 return isl_space_has_dim_id(bmap->dim, type, pos);
711 __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
712 enum isl_dim_type type, unsigned pos)
714 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
717 isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
718 enum isl_dim_type type, unsigned pos)
720 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
723 __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
724 enum isl_dim_type type, unsigned pos)
726 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
729 isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
730 enum isl_dim_type type, unsigned pos)
732 return isl_map_has_dim_id(set, type, pos);
735 __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
736 enum isl_dim_type type, unsigned pos)
738 return isl_map_get_dim_id(set, type, pos);
741 __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
742 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
744 map = isl_map_cow(map);
745 if (!map)
746 goto error;
748 map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
750 return isl_map_reset_space(map, isl_space_copy(map->dim));
751 error:
752 isl_id_free(id);
753 return NULL;
756 __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
757 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
759 return isl_map_set_dim_id(set, type, pos, id);
762 int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
763 __isl_keep isl_id *id)
765 if (!map)
766 return -1;
767 return isl_space_find_dim_by_id(map->dim, type, id);
770 int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
771 __isl_keep isl_id *id)
773 return isl_map_find_dim_by_id(set, type, id);
776 /* Return the position of the dimension of the given type and name
777 * in "bmap".
778 * Return -1 if no such dimension can be found.
780 int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
781 enum isl_dim_type type, const char *name)
783 if (!bmap)
784 return -1;
785 return isl_space_find_dim_by_name(bmap->dim, type, name);
788 int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
789 const char *name)
791 if (!map)
792 return -1;
793 return isl_space_find_dim_by_name(map->dim, type, name);
796 int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
797 const char *name)
799 return isl_map_find_dim_by_name(set, type, name);
802 /* Reset the user pointer on all identifiers of parameters and tuples
803 * of the space of "map".
805 __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
807 isl_space *space;
809 space = isl_map_get_space(map);
810 space = isl_space_reset_user(space);
811 map = isl_map_reset_space(map, space);
813 return map;
816 /* Reset the user pointer on all identifiers of parameters and tuples
817 * of the space of "set".
819 __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
821 return isl_map_reset_user(set);
824 isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
826 if (!bmap)
827 return isl_bool_error;
828 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
831 /* Has "map" been marked as a rational map?
832 * In particular, have all basic maps in "map" been marked this way?
833 * An empty map is not considered to be rational.
834 * Maps where only some of the basic maps are marked rational
835 * are not allowed.
837 isl_bool isl_map_is_rational(__isl_keep isl_map *map)
839 int i;
840 isl_bool rational;
842 if (!map)
843 return isl_bool_error;
844 if (map->n == 0)
845 return isl_bool_false;
846 rational = isl_basic_map_is_rational(map->p[0]);
847 if (rational < 0)
848 return rational;
849 for (i = 1; i < map->n; ++i) {
850 isl_bool rational_i;
852 rational_i = isl_basic_map_is_rational(map->p[i]);
853 if (rational_i < 0)
854 return rational_i;
855 if (rational != rational_i)
856 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
857 "mixed rational and integer basic maps "
858 "not supported", return isl_bool_error);
861 return rational;
864 /* Has "set" been marked as a rational set?
865 * In particular, have all basic set in "set" been marked this way?
866 * An empty set is not considered to be rational.
867 * Sets where only some of the basic sets are marked rational
868 * are not allowed.
870 isl_bool isl_set_is_rational(__isl_keep isl_set *set)
872 return isl_map_is_rational(set);
875 int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
877 return isl_basic_map_is_rational(bset);
880 /* Does "bmap" contain any rational points?
882 * If "bmap" has an equality for each dimension, equating the dimension
883 * to an integer constant, then it has no rational points, even if it
884 * is marked as rational.
886 isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
888 isl_bool has_rational = isl_bool_true;
889 unsigned total;
891 if (!bmap)
892 return isl_bool_error;
893 if (isl_basic_map_plain_is_empty(bmap))
894 return isl_bool_false;
895 if (!isl_basic_map_is_rational(bmap))
896 return isl_bool_false;
897 bmap = isl_basic_map_copy(bmap);
898 bmap = isl_basic_map_implicit_equalities(bmap);
899 if (!bmap)
900 return isl_bool_error;
901 total = isl_basic_map_total_dim(bmap);
902 if (bmap->n_eq == total) {
903 int i, j;
904 for (i = 0; i < bmap->n_eq; ++i) {
905 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
906 if (j < 0)
907 break;
908 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
909 !isl_int_is_negone(bmap->eq[i][1 + j]))
910 break;
911 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
912 total - j - 1);
913 if (j >= 0)
914 break;
916 if (i == bmap->n_eq)
917 has_rational = isl_bool_false;
919 isl_basic_map_free(bmap);
921 return has_rational;
924 /* Does "map" contain any rational points?
926 isl_bool isl_map_has_rational(__isl_keep isl_map *map)
928 int i;
929 isl_bool has_rational;
931 if (!map)
932 return isl_bool_error;
933 for (i = 0; i < map->n; ++i) {
934 has_rational = isl_basic_map_has_rational(map->p[i]);
935 if (has_rational < 0 || has_rational)
936 return has_rational;
938 return isl_bool_false;
941 /* Does "set" contain any rational points?
943 isl_bool isl_set_has_rational(__isl_keep isl_set *set)
945 return isl_map_has_rational(set);
948 /* Is this basic set a parameter domain?
950 isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
952 if (!bset)
953 return isl_bool_error;
954 return isl_space_is_params(bset->dim);
957 /* Is this set a parameter domain?
959 isl_bool isl_set_is_params(__isl_keep isl_set *set)
961 if (!set)
962 return isl_bool_error;
963 return isl_space_is_params(set->dim);
966 /* Is this map actually a parameter domain?
967 * Users should never call this function. Outside of isl,
968 * a map can never be a parameter domain.
970 isl_bool isl_map_is_params(__isl_keep isl_map *map)
972 if (!map)
973 return isl_bool_error;
974 return isl_space_is_params(map->dim);
977 static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
978 struct isl_basic_map *bmap, unsigned extra,
979 unsigned n_eq, unsigned n_ineq)
981 int i;
982 size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
984 bmap->ctx = ctx;
985 isl_ctx_ref(ctx);
987 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
988 if (isl_blk_is_error(bmap->block))
989 goto error;
991 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
992 if ((n_ineq + n_eq) && !bmap->ineq)
993 goto error;
995 if (extra == 0) {
996 bmap->block2 = isl_blk_empty();
997 bmap->div = NULL;
998 } else {
999 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1000 if (isl_blk_is_error(bmap->block2))
1001 goto error;
1003 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1004 if (!bmap->div)
1005 goto error;
1008 for (i = 0; i < n_ineq + n_eq; ++i)
1009 bmap->ineq[i] = bmap->block.data + i * row_size;
1011 for (i = 0; i < extra; ++i)
1012 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1014 bmap->ref = 1;
1015 bmap->flags = 0;
1016 bmap->c_size = n_eq + n_ineq;
1017 bmap->eq = bmap->ineq + n_ineq;
1018 bmap->extra = extra;
1019 bmap->n_eq = 0;
1020 bmap->n_ineq = 0;
1021 bmap->n_div = 0;
1022 bmap->sample = NULL;
1024 return bmap;
1025 error:
1026 isl_basic_map_free(bmap);
1027 return NULL;
1030 struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
1031 unsigned nparam, unsigned dim, unsigned extra,
1032 unsigned n_eq, unsigned n_ineq)
1034 struct isl_basic_map *bmap;
1035 isl_space *space;
1037 space = isl_space_set_alloc(ctx, nparam, dim);
1038 if (!space)
1039 return NULL;
1041 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1042 return bset_from_bmap(bmap);
1045 struct isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
1046 unsigned extra, unsigned n_eq, unsigned n_ineq)
1048 struct isl_basic_map *bmap;
1049 if (!dim)
1050 return NULL;
1051 isl_assert(dim->ctx, dim->n_in == 0, goto error);
1052 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1053 return bset_from_bmap(bmap);
1054 error:
1055 isl_space_free(dim);
1056 return NULL;
1059 struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
1060 unsigned extra, unsigned n_eq, unsigned n_ineq)
1062 struct isl_basic_map *bmap;
1064 if (!dim)
1065 return NULL;
1066 bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
1067 if (!bmap)
1068 goto error;
1069 bmap->dim = dim;
1071 return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
1072 error:
1073 isl_space_free(dim);
1074 return NULL;
1077 struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
1078 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1079 unsigned n_eq, unsigned n_ineq)
1081 struct isl_basic_map *bmap;
1082 isl_space *dim;
1084 dim = isl_space_alloc(ctx, nparam, in, out);
1085 if (!dim)
1086 return NULL;
1088 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1089 return bmap;
1092 static void dup_constraints(
1093 struct isl_basic_map *dst, struct isl_basic_map *src)
1095 int i;
1096 unsigned total = isl_basic_map_total_dim(src);
1098 for (i = 0; i < src->n_eq; ++i) {
1099 int j = isl_basic_map_alloc_equality(dst);
1100 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1103 for (i = 0; i < src->n_ineq; ++i) {
1104 int j = isl_basic_map_alloc_inequality(dst);
1105 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1108 for (i = 0; i < src->n_div; ++i) {
1109 int j = isl_basic_map_alloc_div(dst);
1110 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1112 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1115 struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap)
1117 struct isl_basic_map *dup;
1119 if (!bmap)
1120 return NULL;
1121 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1122 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1123 if (!dup)
1124 return NULL;
1125 dup_constraints(dup, bmap);
1126 dup->flags = bmap->flags;
1127 dup->sample = isl_vec_copy(bmap->sample);
1128 return dup;
1131 struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
1133 struct isl_basic_map *dup;
1135 dup = isl_basic_map_dup(bset_to_bmap(bset));
1136 return bset_from_bmap(dup);
1139 struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset)
1141 if (!bset)
1142 return NULL;
1144 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1145 bset->ref++;
1146 return bset;
1148 return isl_basic_set_dup(bset);
1151 struct isl_set *isl_set_copy(struct isl_set *set)
1153 if (!set)
1154 return NULL;
1156 set->ref++;
1157 return set;
1160 struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap)
1162 if (!bmap)
1163 return NULL;
1165 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1166 bmap->ref++;
1167 return bmap;
1169 bmap = isl_basic_map_dup(bmap);
1170 if (bmap)
1171 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1172 return bmap;
1175 struct isl_map *isl_map_copy(struct isl_map *map)
1177 if (!map)
1178 return NULL;
1180 map->ref++;
1181 return map;
1184 __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1186 if (!bmap)
1187 return NULL;
1189 if (--bmap->ref > 0)
1190 return NULL;
1192 isl_ctx_deref(bmap->ctx);
1193 free(bmap->div);
1194 isl_blk_free(bmap->ctx, bmap->block2);
1195 free(bmap->ineq);
1196 isl_blk_free(bmap->ctx, bmap->block);
1197 isl_vec_free(bmap->sample);
1198 isl_space_free(bmap->dim);
1199 free(bmap);
1201 return NULL;
1204 __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1206 return isl_basic_map_free(bset_to_bmap(bset));
1209 static int room_for_con(struct isl_basic_map *bmap, unsigned n)
1211 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1214 __isl_give isl_map *isl_map_align_params_map_map_and(
1215 __isl_take isl_map *map1, __isl_take isl_map *map2,
1216 __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
1217 __isl_take isl_map *map2))
1219 if (!map1 || !map2)
1220 goto error;
1221 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1222 return fn(map1, map2);
1223 if (!isl_space_has_named_params(map1->dim) ||
1224 !isl_space_has_named_params(map2->dim))
1225 isl_die(map1->ctx, isl_error_invalid,
1226 "unaligned unnamed parameters", goto error);
1227 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1228 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1229 return fn(map1, map2);
1230 error:
1231 isl_map_free(map1);
1232 isl_map_free(map2);
1233 return NULL;
1236 isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1237 __isl_keep isl_map *map2,
1238 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1240 isl_bool r;
1242 if (!map1 || !map2)
1243 return isl_bool_error;
1244 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
1245 return fn(map1, map2);
1246 if (!isl_space_has_named_params(map1->dim) ||
1247 !isl_space_has_named_params(map2->dim))
1248 isl_die(map1->ctx, isl_error_invalid,
1249 "unaligned unnamed parameters", return isl_bool_error);
1250 map1 = isl_map_copy(map1);
1251 map2 = isl_map_copy(map2);
1252 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1253 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1254 r = fn(map1, map2);
1255 isl_map_free(map1);
1256 isl_map_free(map2);
1257 return r;
1260 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
1262 struct isl_ctx *ctx;
1263 if (!bmap)
1264 return -1;
1265 ctx = bmap->ctx;
1266 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1267 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1268 return -1);
1269 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1270 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1271 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1272 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1273 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1274 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1275 isl_int *t;
1276 int j = isl_basic_map_alloc_inequality(bmap);
1277 if (j < 0)
1278 return -1;
1279 t = bmap->ineq[j];
1280 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1281 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1282 bmap->eq[-1] = t;
1283 bmap->n_eq++;
1284 bmap->n_ineq--;
1285 bmap->eq--;
1286 return 0;
1288 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
1289 bmap->extra - bmap->n_div);
1290 return bmap->n_eq++;
1293 int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
1295 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1298 int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
1300 if (!bmap)
1301 return -1;
1302 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
1303 bmap->n_eq -= n;
1304 return 0;
1307 int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
1309 return isl_basic_map_free_equality(bset_to_bmap(bset), n);
1312 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
1314 isl_int *t;
1315 if (!bmap)
1316 return -1;
1317 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1319 if (pos != bmap->n_eq - 1) {
1320 t = bmap->eq[pos];
1321 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
1322 bmap->eq[bmap->n_eq - 1] = t;
1324 bmap->n_eq--;
1325 return 0;
1328 /* Turn inequality "pos" of "bmap" into an equality.
1330 * In particular, we move the inequality in front of the equalities
1331 * and move the last inequality in the position of the moved inequality.
1332 * Note that isl_tab_make_equalities_explicit depends on this particular
1333 * change in the ordering of the constraints.
1335 void isl_basic_map_inequality_to_equality(
1336 struct isl_basic_map *bmap, unsigned pos)
1338 isl_int *t;
1340 t = bmap->ineq[pos];
1341 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1342 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1343 bmap->eq[-1] = t;
1344 bmap->n_eq++;
1345 bmap->n_ineq--;
1346 bmap->eq--;
1347 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1348 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1349 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1350 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1353 static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
1355 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1358 int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap)
1360 struct isl_ctx *ctx;
1361 if (!bmap)
1362 return -1;
1363 ctx = bmap->ctx;
1364 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1365 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1366 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1367 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1368 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1369 isl_seq_clr(bmap->ineq[bmap->n_ineq] +
1370 1 + isl_basic_map_total_dim(bmap),
1371 bmap->extra - bmap->n_div);
1372 return bmap->n_ineq++;
1375 int isl_basic_set_alloc_inequality(struct isl_basic_set *bset)
1377 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1380 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
1382 if (!bmap)
1383 return -1;
1384 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
1385 bmap->n_ineq -= n;
1386 return 0;
1389 int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
1391 return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
1394 int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
1396 isl_int *t;
1397 if (!bmap)
1398 return -1;
1399 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1401 if (pos != bmap->n_ineq - 1) {
1402 t = bmap->ineq[pos];
1403 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1404 bmap->ineq[bmap->n_ineq - 1] = t;
1405 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1407 bmap->n_ineq--;
1408 return 0;
1411 int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
1413 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1416 __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1417 isl_int *eq)
1419 int k;
1421 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1422 if (!bmap)
1423 return NULL;
1424 k = isl_basic_map_alloc_equality(bmap);
1425 if (k < 0)
1426 goto error;
1427 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
1428 return bmap;
1429 error:
1430 isl_basic_map_free(bmap);
1431 return NULL;
1434 __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1435 isl_int *eq)
1437 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1440 __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1441 isl_int *ineq)
1443 int k;
1445 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1446 if (!bmap)
1447 return NULL;
1448 k = isl_basic_map_alloc_inequality(bmap);
1449 if (k < 0)
1450 goto error;
1451 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
1452 return bmap;
1453 error:
1454 isl_basic_map_free(bmap);
1455 return NULL;
1458 __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1459 isl_int *ineq)
1461 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1464 int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
1466 if (!bmap)
1467 return -1;
1468 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1469 isl_seq_clr(bmap->div[bmap->n_div] +
1470 1 + 1 + isl_basic_map_total_dim(bmap),
1471 bmap->extra - bmap->n_div);
1472 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1473 return bmap->n_div++;
1476 int isl_basic_set_alloc_div(struct isl_basic_set *bset)
1478 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1481 /* Check that there are "n" dimensions of type "type" starting at "first"
1482 * in "bmap".
1484 static isl_stat isl_basic_map_check_range(__isl_keep isl_basic_map *bmap,
1485 enum isl_dim_type type, unsigned first, unsigned n)
1487 unsigned dim;
1489 if (!bmap)
1490 return isl_stat_error;
1491 dim = isl_basic_map_dim(bmap, type);
1492 if (first + n > dim || first + n < first)
1493 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1494 "position or range out of bounds",
1495 return isl_stat_error);
1496 return isl_stat_ok;
1499 /* Insert an extra integer division, prescribed by "div", to "bmap"
1500 * at (integer division) position "pos".
1502 * The integer division is first added at the end and then moved
1503 * into the right position.
1505 __isl_give isl_basic_map *isl_basic_map_insert_div(
1506 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1508 int i, k;
1510 bmap = isl_basic_map_cow(bmap);
1511 if (!bmap || !div)
1512 return isl_basic_map_free(bmap);
1514 if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
1515 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1516 "unexpected size", return isl_basic_map_free(bmap));
1517 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1518 return isl_basic_map_free(bmap);
1520 bmap = isl_basic_map_extend_space(bmap,
1521 isl_basic_map_get_space(bmap), 1, 0, 2);
1522 k = isl_basic_map_alloc_div(bmap);
1523 if (k < 0)
1524 return isl_basic_map_free(bmap);
1525 isl_seq_cpy(bmap->div[k], div->el, div->size);
1526 isl_int_set_si(bmap->div[k][div->size], 0);
1528 for (i = k; i > pos; --i)
1529 isl_basic_map_swap_div(bmap, i, i - 1);
1531 return bmap;
1534 isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
1536 if (!bmap)
1537 return isl_stat_error;
1538 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1539 bmap->n_div -= n;
1540 return isl_stat_ok;
1543 /* Copy constraint from src to dst, putting the vars of src at offset
1544 * dim_off in dst and the divs of src at offset div_off in dst.
1545 * If both sets are actually map, then dim_off applies to the input
1546 * variables.
1548 static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
1549 struct isl_basic_map *src_map, isl_int *src,
1550 unsigned in_off, unsigned out_off, unsigned div_off)
1552 unsigned src_nparam = isl_basic_map_n_param(src_map);
1553 unsigned dst_nparam = isl_basic_map_n_param(dst_map);
1554 unsigned src_in = isl_basic_map_n_in(src_map);
1555 unsigned dst_in = isl_basic_map_n_in(dst_map);
1556 unsigned src_out = isl_basic_map_n_out(src_map);
1557 unsigned dst_out = isl_basic_map_n_out(dst_map);
1558 isl_int_set(dst[0], src[0]);
1559 isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
1560 if (dst_nparam > src_nparam)
1561 isl_seq_clr(dst+1+src_nparam,
1562 dst_nparam - src_nparam);
1563 isl_seq_clr(dst+1+dst_nparam, in_off);
1564 isl_seq_cpy(dst+1+dst_nparam+in_off,
1565 src+1+src_nparam,
1566 isl_min(dst_in-in_off, src_in));
1567 if (dst_in-in_off > src_in)
1568 isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
1569 dst_in - in_off - src_in);
1570 isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
1571 isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
1572 src+1+src_nparam+src_in,
1573 isl_min(dst_out-out_off, src_out));
1574 if (dst_out-out_off > src_out)
1575 isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
1576 dst_out - out_off - src_out);
1577 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
1578 isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
1579 src+1+src_nparam+src_in+src_out,
1580 isl_min(dst_map->extra-div_off, src_map->n_div));
1581 if (dst_map->n_div-div_off > src_map->n_div)
1582 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
1583 div_off+src_map->n_div,
1584 dst_map->n_div - div_off - src_map->n_div);
1587 static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
1588 struct isl_basic_map *src_map, isl_int *src,
1589 unsigned in_off, unsigned out_off, unsigned div_off)
1591 isl_int_set(dst[0], src[0]);
1592 copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
1595 static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1,
1596 struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos)
1598 int i;
1599 unsigned div_off;
1601 if (!bmap1 || !bmap2)
1602 goto error;
1604 div_off = bmap1->n_div;
1606 for (i = 0; i < bmap2->n_eq; ++i) {
1607 int i1 = isl_basic_map_alloc_equality(bmap1);
1608 if (i1 < 0)
1609 goto error;
1610 copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
1611 i_pos, o_pos, div_off);
1614 for (i = 0; i < bmap2->n_ineq; ++i) {
1615 int i1 = isl_basic_map_alloc_inequality(bmap1);
1616 if (i1 < 0)
1617 goto error;
1618 copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
1619 i_pos, o_pos, div_off);
1622 for (i = 0; i < bmap2->n_div; ++i) {
1623 int i1 = isl_basic_map_alloc_div(bmap1);
1624 if (i1 < 0)
1625 goto error;
1626 copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
1627 i_pos, o_pos, div_off);
1630 isl_basic_map_free(bmap2);
1632 return bmap1;
1634 error:
1635 isl_basic_map_free(bmap1);
1636 isl_basic_map_free(bmap2);
1637 return NULL;
1640 struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
1641 struct isl_basic_set *bset2, unsigned pos)
1643 return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
1644 bset_to_bmap(bset2), 0, pos));
1647 struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base,
1648 __isl_take isl_space *dim, unsigned extra,
1649 unsigned n_eq, unsigned n_ineq)
1651 struct isl_basic_map *ext;
1652 unsigned flags;
1653 int dims_ok;
1655 if (!dim)
1656 goto error;
1658 if (!base)
1659 goto error;
1661 dims_ok = isl_space_is_equal(base->dim, dim) &&
1662 base->extra >= base->n_div + extra;
1664 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1665 room_for_ineq(base, n_ineq)) {
1666 isl_space_free(dim);
1667 return base;
1670 isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
1671 isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
1672 isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
1673 extra += base->extra;
1674 n_eq += base->n_eq;
1675 n_ineq += base->n_ineq;
1677 ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
1678 dim = NULL;
1679 if (!ext)
1680 goto error;
1682 if (dims_ok)
1683 ext->sample = isl_vec_copy(base->sample);
1684 flags = base->flags;
1685 ext = add_constraints(ext, base, 0, 0);
1686 if (ext) {
1687 ext->flags = flags;
1688 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1691 return ext;
1693 error:
1694 isl_space_free(dim);
1695 isl_basic_map_free(base);
1696 return NULL;
1699 struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base,
1700 __isl_take isl_space *dim, unsigned extra,
1701 unsigned n_eq, unsigned n_ineq)
1703 return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
1704 dim, extra, n_eq, n_ineq));
1707 struct isl_basic_map *isl_basic_map_extend_constraints(
1708 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1710 if (!base)
1711 return NULL;
1712 return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
1713 0, n_eq, n_ineq);
1716 struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
1717 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
1718 unsigned n_eq, unsigned n_ineq)
1720 struct isl_basic_map *bmap;
1721 isl_space *dim;
1723 if (!base)
1724 return NULL;
1725 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
1726 if (!dim)
1727 goto error;
1729 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
1730 return bmap;
1731 error:
1732 isl_basic_map_free(base);
1733 return NULL;
1736 struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
1737 unsigned nparam, unsigned dim, unsigned extra,
1738 unsigned n_eq, unsigned n_ineq)
1740 return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
1741 nparam, 0, dim, extra, n_eq, n_ineq));
1744 struct isl_basic_set *isl_basic_set_extend_constraints(
1745 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1747 isl_basic_map *bmap = bset_to_bmap(base);
1748 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1749 return bset_from_bmap(bmap);
1752 struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset)
1754 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1757 struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap)
1759 if (!bmap)
1760 return NULL;
1762 if (bmap->ref > 1) {
1763 bmap->ref--;
1764 bmap = isl_basic_map_dup(bmap);
1766 if (bmap) {
1767 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
1768 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
1770 return bmap;
1773 /* Clear all cached information in "map", either because it is about
1774 * to be modified or because it is being freed.
1775 * Always return the same pointer that is passed in.
1776 * This is needed for the use in isl_map_free.
1778 static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
1780 isl_basic_map_free(map->cached_simple_hull[0]);
1781 isl_basic_map_free(map->cached_simple_hull[1]);
1782 map->cached_simple_hull[0] = NULL;
1783 map->cached_simple_hull[1] = NULL;
1784 return map;
1787 struct isl_set *isl_set_cow(struct isl_set *set)
1789 return isl_map_cow(set);
1792 /* Return an isl_map that is equal to "map" and that has only
1793 * a single reference.
1795 * If the original input already has only one reference, then
1796 * simply return it, but clear all cached information, since
1797 * it may be rendered invalid by the operations that will be
1798 * performed on the result.
1800 * Otherwise, create a duplicate (without any cached information).
1802 struct isl_map *isl_map_cow(struct isl_map *map)
1804 if (!map)
1805 return NULL;
1807 if (map->ref == 1)
1808 return clear_caches(map);
1809 map->ref--;
1810 return isl_map_dup(map);
1813 static void swap_vars(struct isl_blk blk, isl_int *a,
1814 unsigned a_len, unsigned b_len)
1816 isl_seq_cpy(blk.data, a+a_len, b_len);
1817 isl_seq_cpy(blk.data+b_len, a, a_len);
1818 isl_seq_cpy(a, blk.data, b_len+a_len);
1821 static __isl_give isl_basic_map *isl_basic_map_swap_vars(
1822 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
1824 int i;
1825 struct isl_blk blk;
1827 if (!bmap)
1828 goto error;
1830 isl_assert(bmap->ctx,
1831 pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
1833 if (n1 == 0 || n2 == 0)
1834 return bmap;
1836 bmap = isl_basic_map_cow(bmap);
1837 if (!bmap)
1838 return NULL;
1840 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
1841 if (isl_blk_is_error(blk))
1842 goto error;
1844 for (i = 0; i < bmap->n_eq; ++i)
1845 swap_vars(blk,
1846 bmap->eq[i] + pos, n1, n2);
1848 for (i = 0; i < bmap->n_ineq; ++i)
1849 swap_vars(blk,
1850 bmap->ineq[i] + pos, n1, n2);
1852 for (i = 0; i < bmap->n_div; ++i)
1853 swap_vars(blk,
1854 bmap->div[i]+1 + pos, n1, n2);
1856 isl_blk_free(bmap->ctx, blk);
1858 ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
1859 bmap = isl_basic_map_gauss(bmap, NULL);
1860 return isl_basic_map_finalize(bmap);
1861 error:
1862 isl_basic_map_free(bmap);
1863 return NULL;
1866 struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap)
1868 int i = 0;
1869 unsigned total;
1870 if (!bmap)
1871 goto error;
1872 total = isl_basic_map_total_dim(bmap);
1873 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
1874 return isl_basic_map_free(bmap);
1875 isl_basic_map_free_inequality(bmap, bmap->n_ineq);
1876 if (bmap->n_eq > 0)
1877 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
1878 else {
1879 i = isl_basic_map_alloc_equality(bmap);
1880 if (i < 0)
1881 goto error;
1883 isl_int_set_si(bmap->eq[i][0], 1);
1884 isl_seq_clr(bmap->eq[i]+1, total);
1885 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
1886 isl_vec_free(bmap->sample);
1887 bmap->sample = NULL;
1888 return isl_basic_map_finalize(bmap);
1889 error:
1890 isl_basic_map_free(bmap);
1891 return NULL;
1894 struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset)
1896 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
1899 /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
1900 * of "bmap").
1902 static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
1904 isl_int *t = bmap->div[a];
1905 bmap->div[a] = bmap->div[b];
1906 bmap->div[b] = t;
1909 /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
1910 * div definitions accordingly.
1912 void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
1914 int i;
1915 unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
1917 swap_div(bmap, a, b);
1919 for (i = 0; i < bmap->n_eq; ++i)
1920 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
1922 for (i = 0; i < bmap->n_ineq; ++i)
1923 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
1925 for (i = 0; i < bmap->n_div; ++i)
1926 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
1927 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
1930 /* Swap divs "a" and "b" in "bset" and adjust the constraints and
1931 * div definitions accordingly.
1933 void isl_basic_set_swap_div(__isl_keep isl_basic_set *bset, int a, int b)
1935 isl_basic_map_swap_div(bset, a, b);
1938 /* Eliminate the specified n dimensions starting at first from the
1939 * constraints, without removing the dimensions from the space.
1940 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1942 __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
1943 enum isl_dim_type type, unsigned first, unsigned n)
1945 int i;
1947 if (!map)
1948 return NULL;
1949 if (n == 0)
1950 return map;
1952 if (first + n > isl_map_dim(map, type) || first + n < first)
1953 isl_die(map->ctx, isl_error_invalid,
1954 "index out of bounds", goto error);
1956 map = isl_map_cow(map);
1957 if (!map)
1958 return NULL;
1960 for (i = 0; i < map->n; ++i) {
1961 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
1962 if (!map->p[i])
1963 goto error;
1965 return map;
1966 error:
1967 isl_map_free(map);
1968 return NULL;
1971 /* Eliminate the specified n dimensions starting at first from the
1972 * constraints, without removing the dimensions from the space.
1973 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1975 __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
1976 enum isl_dim_type type, unsigned first, unsigned n)
1978 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
1981 /* Eliminate the specified n dimensions starting at first from the
1982 * constraints, without removing the dimensions from the space.
1983 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
1985 __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
1986 unsigned first, unsigned n)
1988 return isl_set_eliminate(set, isl_dim_set, first, n);
1991 __isl_give isl_basic_map *isl_basic_map_remove_divs(
1992 __isl_take isl_basic_map *bmap)
1994 if (!bmap)
1995 return NULL;
1996 bmap = isl_basic_map_eliminate_vars(bmap,
1997 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
1998 if (!bmap)
1999 return NULL;
2000 bmap->n_div = 0;
2001 return isl_basic_map_finalize(bmap);
2004 __isl_give isl_basic_set *isl_basic_set_remove_divs(
2005 __isl_take isl_basic_set *bset)
2007 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2010 __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2012 int i;
2014 if (!map)
2015 return NULL;
2016 if (map->n == 0)
2017 return map;
2019 map = isl_map_cow(map);
2020 if (!map)
2021 return NULL;
2023 for (i = 0; i < map->n; ++i) {
2024 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2025 if (!map->p[i])
2026 goto error;
2028 return map;
2029 error:
2030 isl_map_free(map);
2031 return NULL;
2034 __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2036 return isl_map_remove_divs(set);
2039 struct isl_basic_map *isl_basic_map_remove_dims(struct isl_basic_map *bmap,
2040 enum isl_dim_type type, unsigned first, unsigned n)
2042 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2043 return isl_basic_map_free(bmap);
2044 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2045 return bmap;
2046 bmap = isl_basic_map_eliminate_vars(bmap,
2047 isl_basic_map_offset(bmap, type) - 1 + first, n);
2048 if (!bmap)
2049 return bmap;
2050 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2051 return bmap;
2052 bmap = isl_basic_map_drop(bmap, type, first, n);
2053 return bmap;
2056 /* Return true if the definition of the given div (recursively) involves
2057 * any of the given variables.
2059 static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2060 unsigned first, unsigned n)
2062 int i;
2063 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2065 if (isl_int_is_zero(bmap->div[div][0]))
2066 return isl_bool_false;
2067 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2068 return isl_bool_true;
2070 for (i = bmap->n_div - 1; i >= 0; --i) {
2071 isl_bool involves;
2073 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2074 continue;
2075 involves = div_involves_vars(bmap, i, first, n);
2076 if (involves < 0 || involves)
2077 return involves;
2080 return isl_bool_false;
2083 /* Try and add a lower and/or upper bound on "div" to "bmap"
2084 * based on inequality "i".
2085 * "total" is the total number of variables (excluding the divs).
2086 * "v" is a temporary object that can be used during the calculations.
2087 * If "lb" is set, then a lower bound should be constructed.
2088 * If "ub" is set, then an upper bound should be constructed.
2090 * The calling function has already checked that the inequality does not
2091 * reference "div", but we still need to check that the inequality is
2092 * of the right form. We'll consider the case where we want to construct
2093 * a lower bound. The construction of upper bounds is similar.
2095 * Let "div" be of the form
2097 * q = floor((a + f(x))/d)
2099 * We essentially check if constraint "i" is of the form
2101 * b + f(x) >= 0
2103 * so that we can use it to derive a lower bound on "div".
2104 * However, we allow a slightly more general form
2106 * b + g(x) >= 0
2108 * with the condition that the coefficients of g(x) - f(x) are all
2109 * divisible by d.
2110 * Rewriting this constraint as
2112 * 0 >= -b - g(x)
2114 * adding a + f(x) to both sides and dividing by d, we obtain
2116 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2118 * Taking the floor on both sides, we obtain
2120 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2122 * or
2124 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2126 * In the case of an upper bound, we construct the constraint
2128 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2131 static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2132 __isl_take isl_basic_map *bmap, int div, int i,
2133 unsigned total, isl_int v, int lb, int ub)
2135 int j;
2137 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2138 if (lb) {
2139 isl_int_sub(v, bmap->ineq[i][1 + j],
2140 bmap->div[div][1 + 1 + j]);
2141 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2143 if (ub) {
2144 isl_int_add(v, bmap->ineq[i][1 + j],
2145 bmap->div[div][1 + 1 + j]);
2146 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2149 if (!lb && !ub)
2150 return bmap;
2152 bmap = isl_basic_map_cow(bmap);
2153 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2154 if (lb) {
2155 int k = isl_basic_map_alloc_inequality(bmap);
2156 if (k < 0)
2157 goto error;
2158 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2159 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2160 bmap->div[div][1 + j]);
2161 isl_int_cdiv_q(bmap->ineq[k][j],
2162 bmap->ineq[k][j], bmap->div[div][0]);
2164 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2166 if (ub) {
2167 int k = isl_basic_map_alloc_inequality(bmap);
2168 if (k < 0)
2169 goto error;
2170 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2171 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2172 bmap->div[div][1 + j]);
2173 isl_int_fdiv_q(bmap->ineq[k][j],
2174 bmap->ineq[k][j], bmap->div[div][0]);
2176 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2179 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2180 return bmap;
2181 error:
2182 isl_basic_map_free(bmap);
2183 return NULL;
2186 /* This function is called right before "div" is eliminated from "bmap"
2187 * using Fourier-Motzkin.
2188 * Look through the constraints of "bmap" for constraints on the argument
2189 * of the integer division and use them to construct constraints on the
2190 * integer division itself. These constraints can then be combined
2191 * during the Fourier-Motzkin elimination.
2192 * Note that it is only useful to introduce lower bounds on "div"
2193 * if "bmap" already contains upper bounds on "div" as the newly
2194 * introduce lower bounds can then be combined with the pre-existing
2195 * upper bounds. Similarly for upper bounds.
2196 * We therefore first check if "bmap" contains any lower and/or upper bounds
2197 * on "div".
2199 * It is interesting to note that the introduction of these constraints
2200 * can indeed lead to more accurate results, even when compared to
2201 * deriving constraints on the argument of "div" from constraints on "div".
2202 * Consider, for example, the set
2204 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2206 * The second constraint can be rewritten as
2208 * 2 * [(-i-2j+3)/4] + k >= 0
2210 * from which we can derive
2212 * -i - 2j + 3 >= -2k
2214 * or
2216 * i + 2j <= 3 + 2k
2218 * Combined with the first constraint, we obtain
2220 * -3 <= 3 + 2k or k >= -3
2222 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2223 * the first constraint, we obtain
2225 * [(i + 2j)/4] >= [-3/4] = -1
2227 * Combining this constraint with the second constraint, we obtain
2229 * k >= -2
2231 static __isl_give isl_basic_map *insert_bounds_on_div(
2232 __isl_take isl_basic_map *bmap, int div)
2234 int i;
2235 int check_lb, check_ub;
2236 isl_int v;
2237 unsigned total;
2239 if (!bmap)
2240 return NULL;
2242 if (isl_int_is_zero(bmap->div[div][0]))
2243 return bmap;
2245 total = isl_space_dim(bmap->dim, isl_dim_all);
2247 check_lb = 0;
2248 check_ub = 0;
2249 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2250 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
2251 if (s > 0)
2252 check_ub = 1;
2253 if (s < 0)
2254 check_lb = 1;
2257 if (!check_lb && !check_ub)
2258 return bmap;
2260 isl_int_init(v);
2262 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2263 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
2264 continue;
2266 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
2267 check_lb, check_ub);
2270 isl_int_clear(v);
2272 return bmap;
2275 /* Remove all divs (recursively) involving any of the given dimensions
2276 * in their definitions.
2278 __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2279 __isl_take isl_basic_map *bmap,
2280 enum isl_dim_type type, unsigned first, unsigned n)
2282 int i;
2284 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2285 return isl_basic_map_free(bmap);
2286 first += isl_basic_map_offset(bmap, type);
2288 for (i = bmap->n_div - 1; i >= 0; --i) {
2289 isl_bool involves;
2291 involves = div_involves_vars(bmap, i, first, n);
2292 if (involves < 0)
2293 return isl_basic_map_free(bmap);
2294 if (!involves)
2295 continue;
2296 bmap = insert_bounds_on_div(bmap, i);
2297 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2298 if (!bmap)
2299 return NULL;
2300 i = bmap->n_div;
2303 return bmap;
2306 __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2307 __isl_take isl_basic_set *bset,
2308 enum isl_dim_type type, unsigned first, unsigned n)
2310 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2313 __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2314 enum isl_dim_type type, unsigned first, unsigned n)
2316 int i;
2318 if (!map)
2319 return NULL;
2320 if (map->n == 0)
2321 return map;
2323 map = isl_map_cow(map);
2324 if (!map)
2325 return NULL;
2327 for (i = 0; i < map->n; ++i) {
2328 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2329 type, first, n);
2330 if (!map->p[i])
2331 goto error;
2333 return map;
2334 error:
2335 isl_map_free(map);
2336 return NULL;
2339 __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2340 enum isl_dim_type type, unsigned first, unsigned n)
2342 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2343 type, first, n));
2346 /* Does the description of "bmap" depend on the specified dimensions?
2347 * We also check whether the dimensions appear in any of the div definitions.
2348 * In principle there is no need for this check. If the dimensions appear
2349 * in a div definition, they also appear in the defining constraints of that
2350 * div.
2352 isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2353 enum isl_dim_type type, unsigned first, unsigned n)
2355 int i;
2357 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2358 return isl_bool_error;
2360 first += isl_basic_map_offset(bmap, type);
2361 for (i = 0; i < bmap->n_eq; ++i)
2362 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2363 return isl_bool_true;
2364 for (i = 0; i < bmap->n_ineq; ++i)
2365 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2366 return isl_bool_true;
2367 for (i = 0; i < bmap->n_div; ++i) {
2368 if (isl_int_is_zero(bmap->div[i][0]))
2369 continue;
2370 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2371 return isl_bool_true;
2374 return isl_bool_false;
2377 isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2378 enum isl_dim_type type, unsigned first, unsigned n)
2380 int i;
2382 if (!map)
2383 return isl_bool_error;
2385 if (first + n > isl_map_dim(map, type))
2386 isl_die(map->ctx, isl_error_invalid,
2387 "index out of bounds", return isl_bool_error);
2389 for (i = 0; i < map->n; ++i) {
2390 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2391 type, first, n);
2392 if (involves < 0 || involves)
2393 return involves;
2396 return isl_bool_false;
2399 isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2400 enum isl_dim_type type, unsigned first, unsigned n)
2402 return isl_basic_map_involves_dims(bset, type, first, n);
2405 isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2406 enum isl_dim_type type, unsigned first, unsigned n)
2408 return isl_map_involves_dims(set, type, first, n);
2411 /* Drop all constraints in bmap that involve any of the dimensions
2412 * first to first+n-1.
2414 static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2415 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2417 int i;
2419 if (n == 0)
2420 return bmap;
2422 bmap = isl_basic_map_cow(bmap);
2424 if (!bmap)
2425 return NULL;
2427 for (i = bmap->n_eq - 1; i >= 0; --i) {
2428 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2429 continue;
2430 isl_basic_map_drop_equality(bmap, i);
2433 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2434 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2435 continue;
2436 isl_basic_map_drop_inequality(bmap, i);
2439 bmap = isl_basic_map_add_known_div_constraints(bmap);
2440 return bmap;
2443 /* Drop all constraints in bset that involve any of the dimensions
2444 * first to first+n-1.
2446 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
2447 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2449 return isl_basic_map_drop_constraints_involving(bset, first, n);
2452 /* Drop all constraints in bmap that do not involve any of the dimensions
2453 * first to first + n - 1 of the given type.
2455 __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
2456 __isl_take isl_basic_map *bmap,
2457 enum isl_dim_type type, unsigned first, unsigned n)
2459 int i;
2461 if (n == 0) {
2462 isl_space *space = isl_basic_map_get_space(bmap);
2463 isl_basic_map_free(bmap);
2464 return isl_basic_map_universe(space);
2466 bmap = isl_basic_map_cow(bmap);
2467 if (!bmap)
2468 return NULL;
2470 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2471 return isl_basic_map_free(bmap);
2473 first += isl_basic_map_offset(bmap, type) - 1;
2475 for (i = bmap->n_eq - 1; i >= 0; --i) {
2476 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
2477 continue;
2478 isl_basic_map_drop_equality(bmap, i);
2481 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2482 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
2483 continue;
2484 isl_basic_map_drop_inequality(bmap, i);
2487 bmap = isl_basic_map_add_known_div_constraints(bmap);
2488 return bmap;
2491 /* Drop all constraints in bset that do not involve any of the dimensions
2492 * first to first + n - 1 of the given type.
2494 __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
2495 __isl_take isl_basic_set *bset,
2496 enum isl_dim_type type, unsigned first, unsigned n)
2498 return isl_basic_map_drop_constraints_not_involving_dims(bset,
2499 type, first, n);
2502 /* Drop all constraints in bmap that involve any of the dimensions
2503 * first to first + n - 1 of the given type.
2505 __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
2506 __isl_take isl_basic_map *bmap,
2507 enum isl_dim_type type, unsigned first, unsigned n)
2509 if (!bmap)
2510 return NULL;
2511 if (n == 0)
2512 return bmap;
2514 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2515 return isl_basic_map_free(bmap);
2517 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
2518 first += isl_basic_map_offset(bmap, type) - 1;
2519 return isl_basic_map_drop_constraints_involving(bmap, first, n);
2522 /* Drop all constraints in bset that involve any of the dimensions
2523 * first to first + n - 1 of the given type.
2525 __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
2526 __isl_take isl_basic_set *bset,
2527 enum isl_dim_type type, unsigned first, unsigned n)
2529 return isl_basic_map_drop_constraints_involving_dims(bset,
2530 type, first, n);
2533 /* Drop constraints from "map" by applying "drop" to each basic map.
2535 static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
2536 enum isl_dim_type type, unsigned first, unsigned n,
2537 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
2538 enum isl_dim_type type, unsigned first, unsigned n))
2540 int i;
2541 unsigned dim;
2543 if (!map)
2544 return NULL;
2546 dim = isl_map_dim(map, type);
2547 if (first + n > dim || first + n < first)
2548 isl_die(isl_map_get_ctx(map), isl_error_invalid,
2549 "index out of bounds", return isl_map_free(map));
2551 map = isl_map_cow(map);
2552 if (!map)
2553 return NULL;
2555 for (i = 0; i < map->n; ++i) {
2556 map->p[i] = drop(map->p[i], type, first, n);
2557 if (!map->p[i])
2558 return isl_map_free(map);
2561 if (map->n > 1)
2562 ISL_F_CLR(map, ISL_MAP_DISJOINT);
2564 return map;
2567 /* Drop all constraints in map that involve any of the dimensions
2568 * first to first + n - 1 of the given type.
2570 __isl_give isl_map *isl_map_drop_constraints_involving_dims(
2571 __isl_take isl_map *map,
2572 enum isl_dim_type type, unsigned first, unsigned n)
2574 if (n == 0)
2575 return map;
2576 return drop_constraints(map, type, first, n,
2577 &isl_basic_map_drop_constraints_involving_dims);
2580 /* Drop all constraints in "map" that do not involve any of the dimensions
2581 * first to first + n - 1 of the given type.
2583 __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
2584 __isl_take isl_map *map,
2585 enum isl_dim_type type, unsigned first, unsigned n)
2587 if (n == 0) {
2588 isl_space *space = isl_map_get_space(map);
2589 isl_map_free(map);
2590 return isl_map_universe(space);
2592 return drop_constraints(map, type, first, n,
2593 &isl_basic_map_drop_constraints_not_involving_dims);
2596 /* Drop all constraints in set that involve any of the dimensions
2597 * first to first + n - 1 of the given type.
2599 __isl_give isl_set *isl_set_drop_constraints_involving_dims(
2600 __isl_take isl_set *set,
2601 enum isl_dim_type type, unsigned first, unsigned n)
2603 return isl_map_drop_constraints_involving_dims(set, type, first, n);
2606 /* Drop all constraints in "set" that do not involve any of the dimensions
2607 * first to first + n - 1 of the given type.
2609 __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
2610 __isl_take isl_set *set,
2611 enum isl_dim_type type, unsigned first, unsigned n)
2613 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
2616 /* Does local variable "div" of "bmap" have a complete explicit representation?
2617 * Having a complete explicit representation requires not only
2618 * an explicit representation, but also that all local variables
2619 * that appear in this explicit representation in turn have
2620 * a complete explicit representation.
2622 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
2624 int i;
2625 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2626 isl_bool marked;
2628 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
2629 if (marked < 0 || marked)
2630 return isl_bool_not(marked);
2632 for (i = bmap->n_div - 1; i >= 0; --i) {
2633 isl_bool known;
2635 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2636 continue;
2637 known = isl_basic_map_div_is_known(bmap, i);
2638 if (known < 0 || !known)
2639 return known;
2642 return isl_bool_true;
2645 /* Remove all divs that are unknown or defined in terms of unknown divs.
2647 __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
2648 __isl_take isl_basic_map *bmap)
2650 int i;
2652 if (!bmap)
2653 return NULL;
2655 for (i = bmap->n_div - 1; i >= 0; --i) {
2656 if (isl_basic_map_div_is_known(bmap, i))
2657 continue;
2658 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2659 if (!bmap)
2660 return NULL;
2661 i = bmap->n_div;
2664 return bmap;
2667 /* Remove all divs that are unknown or defined in terms of unknown divs.
2669 __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
2670 __isl_take isl_basic_set *bset)
2672 return isl_basic_map_remove_unknown_divs(bset);
2675 __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
2677 int i;
2679 if (!map)
2680 return NULL;
2681 if (map->n == 0)
2682 return map;
2684 map = isl_map_cow(map);
2685 if (!map)
2686 return NULL;
2688 for (i = 0; i < map->n; ++i) {
2689 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
2690 if (!map->p[i])
2691 goto error;
2693 return map;
2694 error:
2695 isl_map_free(map);
2696 return NULL;
2699 __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
2701 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
2704 __isl_give isl_basic_set *isl_basic_set_remove_dims(
2705 __isl_take isl_basic_set *bset,
2706 enum isl_dim_type type, unsigned first, unsigned n)
2708 isl_basic_map *bmap = bset_to_bmap(bset);
2709 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
2710 return bset_from_bmap(bmap);
2713 struct isl_map *isl_map_remove_dims(struct isl_map *map,
2714 enum isl_dim_type type, unsigned first, unsigned n)
2716 int i;
2718 if (n == 0)
2719 return map;
2721 map = isl_map_cow(map);
2722 if (!map)
2723 return NULL;
2724 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
2726 for (i = 0; i < map->n; ++i) {
2727 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
2728 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
2729 if (!map->p[i])
2730 goto error;
2732 map = isl_map_drop(map, type, first, n);
2733 return map;
2734 error:
2735 isl_map_free(map);
2736 return NULL;
2739 __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
2740 enum isl_dim_type type, unsigned first, unsigned n)
2742 return set_from_map(isl_map_remove_dims(set_to_map(bset),
2743 type, first, n));
2746 /* Project out n inputs starting at first using Fourier-Motzkin */
2747 struct isl_map *isl_map_remove_inputs(struct isl_map *map,
2748 unsigned first, unsigned n)
2750 return isl_map_remove_dims(map, isl_dim_in, first, n);
2753 static void dump_term(struct isl_basic_map *bmap,
2754 isl_int c, int pos, FILE *out)
2756 const char *name;
2757 unsigned in = isl_basic_map_n_in(bmap);
2758 unsigned dim = in + isl_basic_map_n_out(bmap);
2759 unsigned nparam = isl_basic_map_n_param(bmap);
2760 if (!pos)
2761 isl_int_print(out, c, 0);
2762 else {
2763 if (!isl_int_is_one(c))
2764 isl_int_print(out, c, 0);
2765 if (pos < 1 + nparam) {
2766 name = isl_space_get_dim_name(bmap->dim,
2767 isl_dim_param, pos - 1);
2768 if (name)
2769 fprintf(out, "%s", name);
2770 else
2771 fprintf(out, "p%d", pos - 1);
2772 } else if (pos < 1 + nparam + in)
2773 fprintf(out, "i%d", pos - 1 - nparam);
2774 else if (pos < 1 + nparam + dim)
2775 fprintf(out, "o%d", pos - 1 - nparam - in);
2776 else
2777 fprintf(out, "e%d", pos - 1 - nparam - dim);
2781 static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
2782 int sign, FILE *out)
2784 int i;
2785 int first;
2786 unsigned len = 1 + isl_basic_map_total_dim(bmap);
2787 isl_int v;
2789 isl_int_init(v);
2790 for (i = 0, first = 1; i < len; ++i) {
2791 if (isl_int_sgn(c[i]) * sign <= 0)
2792 continue;
2793 if (!first)
2794 fprintf(out, " + ");
2795 first = 0;
2796 isl_int_abs(v, c[i]);
2797 dump_term(bmap, v, i, out);
2799 isl_int_clear(v);
2800 if (first)
2801 fprintf(out, "0");
2804 static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
2805 const char *op, FILE *out, int indent)
2807 int i;
2809 fprintf(out, "%*s", indent, "");
2811 dump_constraint_sign(bmap, c, 1, out);
2812 fprintf(out, " %s ", op);
2813 dump_constraint_sign(bmap, c, -1, out);
2815 fprintf(out, "\n");
2817 for (i = bmap->n_div; i < bmap->extra; ++i) {
2818 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
2819 continue;
2820 fprintf(out, "%*s", indent, "");
2821 fprintf(out, "ERROR: unused div coefficient not zero\n");
2822 abort();
2826 static void dump_constraints(struct isl_basic_map *bmap,
2827 isl_int **c, unsigned n,
2828 const char *op, FILE *out, int indent)
2830 int i;
2832 for (i = 0; i < n; ++i)
2833 dump_constraint(bmap, c[i], op, out, indent);
2836 static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
2838 int j;
2839 int first = 1;
2840 unsigned total = isl_basic_map_total_dim(bmap);
2842 for (j = 0; j < 1 + total; ++j) {
2843 if (isl_int_is_zero(exp[j]))
2844 continue;
2845 if (!first && isl_int_is_pos(exp[j]))
2846 fprintf(out, "+");
2847 dump_term(bmap, exp[j], j, out);
2848 first = 0;
2852 static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
2854 int i;
2856 dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
2857 dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
2859 for (i = 0; i < bmap->n_div; ++i) {
2860 fprintf(out, "%*s", indent, "");
2861 fprintf(out, "e%d = [(", i);
2862 dump_affine(bmap, bmap->div[i]+1, out);
2863 fprintf(out, ")/");
2864 isl_int_print(out, bmap->div[i][0], 0);
2865 fprintf(out, "]\n");
2869 void isl_basic_set_print_internal(struct isl_basic_set *bset,
2870 FILE *out, int indent)
2872 if (!bset) {
2873 fprintf(out, "null basic set\n");
2874 return;
2877 fprintf(out, "%*s", indent, "");
2878 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
2879 bset->ref, bset->dim->nparam, bset->dim->n_out,
2880 bset->extra, bset->flags);
2881 dump(bset_to_bmap(bset), out, indent);
2884 void isl_basic_map_print_internal(struct isl_basic_map *bmap,
2885 FILE *out, int indent)
2887 if (!bmap) {
2888 fprintf(out, "null basic map\n");
2889 return;
2892 fprintf(out, "%*s", indent, "");
2893 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
2894 "flags: %x, n_name: %d\n",
2895 bmap->ref,
2896 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
2897 bmap->extra, bmap->flags, bmap->dim->n_id);
2898 dump(bmap, out, indent);
2901 int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
2903 unsigned total;
2904 if (!bmap)
2905 return -1;
2906 total = isl_basic_map_total_dim(bmap);
2907 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
2908 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
2909 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
2910 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
2911 return 0;
2914 __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
2915 unsigned flags)
2917 if (!space)
2918 return NULL;
2919 if (isl_space_dim(space, isl_dim_in) != 0)
2920 isl_die(isl_space_get_ctx(space), isl_error_invalid,
2921 "set cannot have input dimensions", goto error);
2922 return isl_map_alloc_space(space, n, flags);
2923 error:
2924 isl_space_free(space);
2925 return NULL;
2928 /* Make sure "map" has room for at least "n" more basic maps.
2930 struct isl_map *isl_map_grow(struct isl_map *map, int n)
2932 int i;
2933 struct isl_map *grown = NULL;
2935 if (!map)
2936 return NULL;
2937 isl_assert(map->ctx, n >= 0, goto error);
2938 if (map->n + n <= map->size)
2939 return map;
2940 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
2941 if (!grown)
2942 goto error;
2943 for (i = 0; i < map->n; ++i) {
2944 grown->p[i] = isl_basic_map_copy(map->p[i]);
2945 if (!grown->p[i])
2946 goto error;
2947 grown->n++;
2949 isl_map_free(map);
2950 return grown;
2951 error:
2952 isl_map_free(grown);
2953 isl_map_free(map);
2954 return NULL;
2957 /* Make sure "set" has room for at least "n" more basic sets.
2959 struct isl_set *isl_set_grow(struct isl_set *set, int n)
2961 return set_from_map(isl_map_grow(set_to_map(set), n));
2964 struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset)
2966 return isl_map_from_basic_map(bset);
2969 struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap)
2971 struct isl_map *map;
2973 if (!bmap)
2974 return NULL;
2976 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
2977 return isl_map_add_basic_map(map, bmap);
2980 __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
2981 __isl_take isl_basic_set *bset)
2983 return set_from_map(isl_map_add_basic_map(set_to_map(set),
2984 bset_to_bmap(bset)));
2987 __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
2989 return isl_map_free(set);
2992 void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
2994 int i;
2996 if (!set) {
2997 fprintf(out, "null set\n");
2998 return;
3001 fprintf(out, "%*s", indent, "");
3002 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3003 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3004 set->flags);
3005 for (i = 0; i < set->n; ++i) {
3006 fprintf(out, "%*s", indent, "");
3007 fprintf(out, "basic set %d:\n", i);
3008 isl_basic_set_print_internal(set->p[i], out, indent+4);
3012 void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
3014 int i;
3016 if (!map) {
3017 fprintf(out, "null map\n");
3018 return;
3021 fprintf(out, "%*s", indent, "");
3022 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3023 "flags: %x, n_name: %d\n",
3024 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3025 map->dim->n_out, map->flags, map->dim->n_id);
3026 for (i = 0; i < map->n; ++i) {
3027 fprintf(out, "%*s", indent, "");
3028 fprintf(out, "basic map %d:\n", i);
3029 isl_basic_map_print_internal(map->p[i], out, indent+4);
3033 struct isl_basic_map *isl_basic_map_intersect_domain(
3034 struct isl_basic_map *bmap, struct isl_basic_set *bset)
3036 struct isl_basic_map *bmap_domain;
3038 if (!bmap || !bset)
3039 goto error;
3041 isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
3042 bset->dim, isl_dim_param), goto error);
3044 if (isl_space_dim(bset->dim, isl_dim_set) != 0)
3045 isl_assert(bset->ctx,
3046 isl_basic_map_compatible_domain(bmap, bset), goto error);
3048 bmap = isl_basic_map_cow(bmap);
3049 if (!bmap)
3050 goto error;
3051 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3052 bset->n_div, bset->n_eq, bset->n_ineq);
3053 bmap_domain = isl_basic_map_from_domain(bset);
3054 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3056 bmap = isl_basic_map_simplify(bmap);
3057 return isl_basic_map_finalize(bmap);
3058 error:
3059 isl_basic_map_free(bmap);
3060 isl_basic_set_free(bset);
3061 return NULL;
3064 /* Check that the space of "bset" is the same as that of the range of "bmap".
3066 static isl_stat isl_basic_map_check_compatible_range(
3067 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3069 isl_bool ok;
3071 ok = isl_basic_map_compatible_range(bmap, bset);
3072 if (ok < 0)
3073 return isl_stat_error;
3074 if (!ok)
3075 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3076 "incompatible spaces", return isl_stat_error);
3078 return isl_stat_ok;
3081 struct isl_basic_map *isl_basic_map_intersect_range(
3082 struct isl_basic_map *bmap, struct isl_basic_set *bset)
3084 struct isl_basic_map *bmap_range;
3086 if (!bmap || !bset)
3087 goto error;
3089 isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
3090 bset->dim, isl_dim_param), goto error);
3092 if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
3093 isl_basic_map_check_compatible_range(bmap, bset) < 0)
3094 goto error;
3096 if (isl_basic_set_plain_is_universe(bset)) {
3097 isl_basic_set_free(bset);
3098 return bmap;
3101 bmap = isl_basic_map_cow(bmap);
3102 if (!bmap)
3103 goto error;
3104 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
3105 bset->n_div, bset->n_eq, bset->n_ineq);
3106 bmap_range = bset_to_bmap(bset);
3107 bmap = add_constraints(bmap, bmap_range, 0, 0);
3109 bmap = isl_basic_map_simplify(bmap);
3110 return isl_basic_map_finalize(bmap);
3111 error:
3112 isl_basic_map_free(bmap);
3113 isl_basic_set_free(bset);
3114 return NULL;
3117 isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3118 __isl_keep isl_vec *vec)
3120 int i;
3121 unsigned total;
3122 isl_int s;
3124 if (!bmap || !vec)
3125 return isl_bool_error;
3127 total = 1 + isl_basic_map_total_dim(bmap);
3128 if (total != vec->size)
3129 return isl_bool_false;
3131 isl_int_init(s);
3133 for (i = 0; i < bmap->n_eq; ++i) {
3134 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
3135 if (!isl_int_is_zero(s)) {
3136 isl_int_clear(s);
3137 return isl_bool_false;
3141 for (i = 0; i < bmap->n_ineq; ++i) {
3142 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
3143 if (isl_int_is_neg(s)) {
3144 isl_int_clear(s);
3145 return isl_bool_false;
3149 isl_int_clear(s);
3151 return isl_bool_true;
3154 isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3155 __isl_keep isl_vec *vec)
3157 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3160 struct isl_basic_map *isl_basic_map_intersect(
3161 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
3163 struct isl_vec *sample = NULL;
3165 if (!bmap1 || !bmap2)
3166 goto error;
3168 isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
3169 bmap2->dim, isl_dim_param), goto error);
3170 if (isl_space_dim(bmap1->dim, isl_dim_all) ==
3171 isl_space_dim(bmap1->dim, isl_dim_param) &&
3172 isl_space_dim(bmap2->dim, isl_dim_all) !=
3173 isl_space_dim(bmap2->dim, isl_dim_param))
3174 return isl_basic_map_intersect(bmap2, bmap1);
3176 if (isl_space_dim(bmap2->dim, isl_dim_all) !=
3177 isl_space_dim(bmap2->dim, isl_dim_param))
3178 isl_assert(bmap1->ctx,
3179 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
3181 if (isl_basic_map_plain_is_empty(bmap1)) {
3182 isl_basic_map_free(bmap2);
3183 return bmap1;
3185 if (isl_basic_map_plain_is_empty(bmap2)) {
3186 isl_basic_map_free(bmap1);
3187 return bmap2;
3190 if (bmap1->sample &&
3191 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3192 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3193 sample = isl_vec_copy(bmap1->sample);
3194 else if (bmap2->sample &&
3195 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3196 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3197 sample = isl_vec_copy(bmap2->sample);
3199 bmap1 = isl_basic_map_cow(bmap1);
3200 if (!bmap1)
3201 goto error;
3202 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
3203 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3204 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3206 if (!bmap1)
3207 isl_vec_free(sample);
3208 else if (sample) {
3209 isl_vec_free(bmap1->sample);
3210 bmap1->sample = sample;
3213 bmap1 = isl_basic_map_simplify(bmap1);
3214 return isl_basic_map_finalize(bmap1);
3215 error:
3216 if (sample)
3217 isl_vec_free(sample);
3218 isl_basic_map_free(bmap1);
3219 isl_basic_map_free(bmap2);
3220 return NULL;
3223 struct isl_basic_set *isl_basic_set_intersect(
3224 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
3226 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3227 bset_to_bmap(bset2)));
3230 __isl_give isl_basic_set *isl_basic_set_intersect_params(
3231 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3233 return isl_basic_set_intersect(bset1, bset2);
3236 /* Special case of isl_map_intersect, where both map1 and map2
3237 * are convex, without any divs and such that either map1 or map2
3238 * contains a single constraint. This constraint is then simply
3239 * added to the other map.
3241 static __isl_give isl_map *map_intersect_add_constraint(
3242 __isl_take isl_map *map1, __isl_take isl_map *map2)
3244 isl_assert(map1->ctx, map1->n == 1, goto error);
3245 isl_assert(map2->ctx, map1->n == 1, goto error);
3246 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3247 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3249 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3250 return isl_map_intersect(map2, map1);
3252 map1 = isl_map_cow(map1);
3253 if (!map1)
3254 goto error;
3255 if (isl_map_plain_is_empty(map1)) {
3256 isl_map_free(map2);
3257 return map1;
3259 map1->p[0] = isl_basic_map_cow(map1->p[0]);
3260 if (map2->p[0]->n_eq == 1)
3261 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3262 else
3263 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3264 map2->p[0]->ineq[0]);
3266 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3267 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3268 if (!map1->p[0])
3269 goto error;
3271 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3272 isl_basic_map_free(map1->p[0]);
3273 map1->n = 0;
3276 isl_map_free(map2);
3278 return map1;
3279 error:
3280 isl_map_free(map1);
3281 isl_map_free(map2);
3282 return NULL;
3285 /* map2 may be either a parameter domain or a map living in the same
3286 * space as map1.
3288 static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3289 __isl_take isl_map *map2)
3291 unsigned flags = 0;
3292 isl_map *result;
3293 int i, j;
3295 if (!map1 || !map2)
3296 goto error;
3298 if ((isl_map_plain_is_empty(map1) ||
3299 isl_map_plain_is_universe(map2)) &&
3300 isl_space_is_equal(map1->dim, map2->dim)) {
3301 isl_map_free(map2);
3302 return map1;
3304 if ((isl_map_plain_is_empty(map2) ||
3305 isl_map_plain_is_universe(map1)) &&
3306 isl_space_is_equal(map1->dim, map2->dim)) {
3307 isl_map_free(map1);
3308 return map2;
3311 if (map1->n == 1 && map2->n == 1 &&
3312 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3313 isl_space_is_equal(map1->dim, map2->dim) &&
3314 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3315 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3316 return map_intersect_add_constraint(map1, map2);
3318 if (isl_space_dim(map2->dim, isl_dim_all) !=
3319 isl_space_dim(map2->dim, isl_dim_param))
3320 isl_assert(map1->ctx,
3321 isl_space_is_equal(map1->dim, map2->dim), goto error);
3323 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3324 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3325 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3327 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3328 map1->n * map2->n, flags);
3329 if (!result)
3330 goto error;
3331 for (i = 0; i < map1->n; ++i)
3332 for (j = 0; j < map2->n; ++j) {
3333 struct isl_basic_map *part;
3334 part = isl_basic_map_intersect(
3335 isl_basic_map_copy(map1->p[i]),
3336 isl_basic_map_copy(map2->p[j]));
3337 if (isl_basic_map_is_empty(part) < 0)
3338 part = isl_basic_map_free(part);
3339 result = isl_map_add_basic_map(result, part);
3340 if (!result)
3341 goto error;
3343 isl_map_free(map1);
3344 isl_map_free(map2);
3345 return result;
3346 error:
3347 isl_map_free(map1);
3348 isl_map_free(map2);
3349 return NULL;
3352 static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3353 __isl_take isl_map *map2)
3355 if (!map1 || !map2)
3356 goto error;
3357 if (!isl_space_is_equal(map1->dim, map2->dim))
3358 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
3359 "spaces don't match", goto error);
3360 return map_intersect_internal(map1, map2);
3361 error:
3362 isl_map_free(map1);
3363 isl_map_free(map2);
3364 return NULL;
3367 __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3368 __isl_take isl_map *map2)
3370 return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
3373 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
3375 return set_from_map(isl_map_intersect(set_to_map(set1),
3376 set_to_map(set2)));
3379 /* map_intersect_internal accepts intersections
3380 * with parameter domains, so we can just call that function.
3382 static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
3383 __isl_take isl_set *params)
3385 return map_intersect_internal(map, params);
3388 __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
3389 __isl_take isl_map *map2)
3391 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
3394 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3395 __isl_take isl_set *params)
3397 return isl_map_intersect_params(set, params);
3400 struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap)
3402 isl_space *space;
3403 unsigned pos, n1, n2;
3405 if (!bmap)
3406 return NULL;
3407 bmap = isl_basic_map_cow(bmap);
3408 if (!bmap)
3409 return NULL;
3410 space = isl_space_reverse(isl_space_copy(bmap->dim));
3411 pos = isl_basic_map_offset(bmap, isl_dim_in);
3412 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3413 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3414 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3415 return isl_basic_map_reset_space(bmap, space);
3418 static __isl_give isl_basic_map *basic_map_space_reset(
3419 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3421 isl_space *space;
3423 if (!bmap)
3424 return NULL;
3425 if (!isl_space_is_named_or_nested(bmap->dim, type))
3426 return bmap;
3428 space = isl_basic_map_get_space(bmap);
3429 space = isl_space_reset(space, type);
3430 bmap = isl_basic_map_reset_space(bmap, space);
3431 return bmap;
3434 __isl_give isl_basic_map *isl_basic_map_insert_dims(
3435 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3436 unsigned pos, unsigned n)
3438 isl_bool rational;
3439 isl_space *res_dim;
3440 struct isl_basic_map *res;
3441 struct isl_dim_map *dim_map;
3442 unsigned total, off;
3443 enum isl_dim_type t;
3445 if (n == 0)
3446 return basic_map_space_reset(bmap, type);
3448 if (!bmap)
3449 return NULL;
3451 res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n);
3453 total = isl_basic_map_total_dim(bmap) + n;
3454 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3455 off = 0;
3456 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3457 if (t != type) {
3458 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3459 } else {
3460 unsigned size = isl_basic_map_dim(bmap, t);
3461 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3462 0, pos, off);
3463 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3464 pos, size - pos, off + pos + n);
3466 off += isl_space_dim(res_dim, t);
3468 isl_dim_map_div(dim_map, bmap, off);
3470 res = isl_basic_map_alloc_space(res_dim,
3471 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3472 rational = isl_basic_map_is_rational(bmap);
3473 if (rational < 0)
3474 res = isl_basic_map_free(res);
3475 if (rational)
3476 res = isl_basic_map_set_rational(res);
3477 if (isl_basic_map_plain_is_empty(bmap)) {
3478 isl_basic_map_free(bmap);
3479 free(dim_map);
3480 return isl_basic_map_set_to_empty(res);
3482 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3483 return isl_basic_map_finalize(res);
3486 __isl_give isl_basic_set *isl_basic_set_insert_dims(
3487 __isl_take isl_basic_set *bset,
3488 enum isl_dim_type type, unsigned pos, unsigned n)
3490 return isl_basic_map_insert_dims(bset, type, pos, n);
3493 __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
3494 enum isl_dim_type type, unsigned n)
3496 if (!bmap)
3497 return NULL;
3498 return isl_basic_map_insert_dims(bmap, type,
3499 isl_basic_map_dim(bmap, type), n);
3502 __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
3503 enum isl_dim_type type, unsigned n)
3505 if (!bset)
3506 return NULL;
3507 isl_assert(bset->ctx, type != isl_dim_in, goto error);
3508 return isl_basic_map_add_dims(bset, type, n);
3509 error:
3510 isl_basic_set_free(bset);
3511 return NULL;
3514 static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
3515 enum isl_dim_type type)
3517 isl_space *space;
3519 if (!map || !isl_space_is_named_or_nested(map->dim, type))
3520 return map;
3522 space = isl_map_get_space(map);
3523 space = isl_space_reset(space, type);
3524 map = isl_map_reset_space(map, space);
3525 return map;
3528 __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
3529 enum isl_dim_type type, unsigned pos, unsigned n)
3531 int i;
3533 if (n == 0)
3534 return map_space_reset(map, type);
3536 map = isl_map_cow(map);
3537 if (!map)
3538 return NULL;
3540 map->dim = isl_space_insert_dims(map->dim, type, pos, n);
3541 if (!map->dim)
3542 goto error;
3544 for (i = 0; i < map->n; ++i) {
3545 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
3546 if (!map->p[i])
3547 goto error;
3550 return map;
3551 error:
3552 isl_map_free(map);
3553 return NULL;
3556 __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
3557 enum isl_dim_type type, unsigned pos, unsigned n)
3559 return isl_map_insert_dims(set, type, pos, n);
3562 __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
3563 enum isl_dim_type type, unsigned n)
3565 if (!map)
3566 return NULL;
3567 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
3570 __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
3571 enum isl_dim_type type, unsigned n)
3573 if (!set)
3574 return NULL;
3575 isl_assert(set->ctx, type != isl_dim_in, goto error);
3576 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
3577 error:
3578 isl_set_free(set);
3579 return NULL;
3582 __isl_give isl_basic_map *isl_basic_map_move_dims(
3583 __isl_take isl_basic_map *bmap,
3584 enum isl_dim_type dst_type, unsigned dst_pos,
3585 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3587 struct isl_dim_map *dim_map;
3588 struct isl_basic_map *res;
3589 enum isl_dim_type t;
3590 unsigned total, off;
3592 if (!bmap)
3593 return NULL;
3594 if (n == 0)
3595 return bmap;
3597 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
3598 return isl_basic_map_free(bmap);
3600 if (dst_type == src_type && dst_pos == src_pos)
3601 return bmap;
3603 isl_assert(bmap->ctx, dst_type != src_type, goto error);
3605 if (pos(bmap->dim, dst_type) + dst_pos ==
3606 pos(bmap->dim, src_type) + src_pos +
3607 ((src_type < dst_type) ? n : 0)) {
3608 bmap = isl_basic_map_cow(bmap);
3609 if (!bmap)
3610 return NULL;
3612 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3613 src_type, src_pos, n);
3614 if (!bmap->dim)
3615 goto error;
3617 bmap = isl_basic_map_finalize(bmap);
3619 return bmap;
3622 total = isl_basic_map_total_dim(bmap);
3623 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3625 off = 0;
3626 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3627 unsigned size = isl_space_dim(bmap->dim, t);
3628 if (t == dst_type) {
3629 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3630 0, dst_pos, off);
3631 off += dst_pos;
3632 isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
3633 src_pos, n, off);
3634 off += n;
3635 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3636 dst_pos, size - dst_pos, off);
3637 off += size - dst_pos;
3638 } else if (t == src_type) {
3639 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3640 0, src_pos, off);
3641 off += src_pos;
3642 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3643 src_pos + n, size - src_pos - n, off);
3644 off += size - src_pos - n;
3645 } else {
3646 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3647 off += size;
3650 isl_dim_map_div(dim_map, bmap, off);
3652 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3653 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3654 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3655 if (!bmap)
3656 goto error;
3658 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
3659 src_type, src_pos, n);
3660 if (!bmap->dim)
3661 goto error;
3663 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
3664 bmap = isl_basic_map_gauss(bmap, NULL);
3665 bmap = isl_basic_map_finalize(bmap);
3667 return bmap;
3668 error:
3669 isl_basic_map_free(bmap);
3670 return NULL;
3673 __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
3674 enum isl_dim_type dst_type, unsigned dst_pos,
3675 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3677 isl_basic_map *bmap = bset_to_bmap(bset);
3678 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
3679 src_type, src_pos, n);
3680 return bset_from_bmap(bmap);
3683 __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
3684 enum isl_dim_type dst_type, unsigned dst_pos,
3685 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3687 if (!set)
3688 return NULL;
3689 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
3690 return set_from_map(isl_map_move_dims(set_to_map(set),
3691 dst_type, dst_pos, src_type, src_pos, n));
3692 error:
3693 isl_set_free(set);
3694 return NULL;
3697 __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
3698 enum isl_dim_type dst_type, unsigned dst_pos,
3699 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
3701 int i;
3703 if (!map)
3704 return NULL;
3705 if (n == 0)
3706 return map;
3708 isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type),
3709 goto error);
3711 if (dst_type == src_type && dst_pos == src_pos)
3712 return map;
3714 isl_assert(map->ctx, dst_type != src_type, goto error);
3716 map = isl_map_cow(map);
3717 if (!map)
3718 return NULL;
3720 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
3721 if (!map->dim)
3722 goto error;
3724 for (i = 0; i < map->n; ++i) {
3725 map->p[i] = isl_basic_map_move_dims(map->p[i],
3726 dst_type, dst_pos,
3727 src_type, src_pos, n);
3728 if (!map->p[i])
3729 goto error;
3732 return map;
3733 error:
3734 isl_map_free(map);
3735 return NULL;
3738 /* Move the specified dimensions to the last columns right before
3739 * the divs. Don't change the dimension specification of bmap.
3740 * That's the responsibility of the caller.
3742 static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
3743 enum isl_dim_type type, unsigned first, unsigned n)
3745 struct isl_dim_map *dim_map;
3746 struct isl_basic_map *res;
3747 enum isl_dim_type t;
3748 unsigned total, off;
3750 if (!bmap)
3751 return NULL;
3752 if (pos(bmap->dim, type) + first + n ==
3753 1 + isl_space_dim(bmap->dim, isl_dim_all))
3754 return bmap;
3756 total = isl_basic_map_total_dim(bmap);
3757 dim_map = isl_dim_map_alloc(bmap->ctx, total);
3759 off = 0;
3760 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3761 unsigned size = isl_space_dim(bmap->dim, t);
3762 if (t == type) {
3763 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3764 0, first, off);
3765 off += first;
3766 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3767 first, n, total - bmap->n_div - n);
3768 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3769 first + n, size - (first + n), off);
3770 off += size - (first + n);
3771 } else {
3772 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3773 off += size;
3776 isl_dim_map_div(dim_map, bmap, off + n);
3778 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
3779 bmap->n_div, bmap->n_eq, bmap->n_ineq);
3780 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
3781 return res;
3784 /* Insert "n" rows in the divs of "bmap".
3786 * The number of columns is not changed, which means that the last
3787 * dimensions of "bmap" are being reintepreted as the new divs.
3788 * The space of "bmap" is not adjusted, however, which means
3789 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
3790 * from the space of "bmap" is the responsibility of the caller.
3792 static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
3793 int n)
3795 int i;
3796 size_t row_size;
3797 isl_int **new_div;
3798 isl_int *old;
3800 bmap = isl_basic_map_cow(bmap);
3801 if (!bmap)
3802 return NULL;
3804 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
3805 old = bmap->block2.data;
3806 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
3807 (bmap->extra + n) * (1 + row_size));
3808 if (!bmap->block2.data)
3809 return isl_basic_map_free(bmap);
3810 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
3811 if (!new_div)
3812 return isl_basic_map_free(bmap);
3813 for (i = 0; i < n; ++i) {
3814 new_div[i] = bmap->block2.data +
3815 (bmap->extra + i) * (1 + row_size);
3816 isl_seq_clr(new_div[i], 1 + row_size);
3818 for (i = 0; i < bmap->extra; ++i)
3819 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
3820 free(bmap->div);
3821 bmap->div = new_div;
3822 bmap->n_div += n;
3823 bmap->extra += n;
3825 return bmap;
3828 /* Drop constraints from "bmap" that only involve the variables
3829 * of "type" in the range [first, first + n] that are not related
3830 * to any of the variables outside that interval.
3831 * These constraints cannot influence the values for the variables
3832 * outside the interval, except in case they cause "bmap" to be empty.
3833 * Only drop the constraints if "bmap" is known to be non-empty.
3835 static __isl_give isl_basic_map *drop_irrelevant_constraints(
3836 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3837 unsigned first, unsigned n)
3839 int i;
3840 int *groups;
3841 unsigned dim, n_div;
3842 isl_bool non_empty;
3844 non_empty = isl_basic_map_plain_is_non_empty(bmap);
3845 if (non_empty < 0)
3846 return isl_basic_map_free(bmap);
3847 if (!non_empty)
3848 return bmap;
3850 dim = isl_basic_map_dim(bmap, isl_dim_all);
3851 n_div = isl_basic_map_dim(bmap, isl_dim_div);
3852 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
3853 if (!groups)
3854 return isl_basic_map_free(bmap);
3855 first += isl_basic_map_offset(bmap, type) - 1;
3856 for (i = 0; i < first; ++i)
3857 groups[i] = -1;
3858 for (i = first + n; i < dim - n_div; ++i)
3859 groups[i] = -1;
3861 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
3863 return bmap;
3866 /* Turn the n dimensions of type type, starting at first
3867 * into existentially quantified variables.
3869 * If a subset of the projected out variables are unrelated
3870 * to any of the variables that remain, then the constraints
3871 * involving this subset are simply dropped first.
3873 __isl_give isl_basic_map *isl_basic_map_project_out(
3874 __isl_take isl_basic_map *bmap,
3875 enum isl_dim_type type, unsigned first, unsigned n)
3877 if (n == 0)
3878 return basic_map_space_reset(bmap, type);
3879 if (type == isl_dim_div)
3880 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3881 "cannot project out existentially quantified variables",
3882 return isl_basic_map_free(bmap));
3884 bmap = drop_irrelevant_constraints(bmap, type, first, n);
3885 if (!bmap)
3886 return NULL;
3888 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
3889 return isl_basic_map_remove_dims(bmap, type, first, n);
3891 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3892 return isl_basic_map_free(bmap);
3894 bmap = move_last(bmap, type, first, n);
3895 bmap = isl_basic_map_cow(bmap);
3896 bmap = insert_div_rows(bmap, n);
3897 if (!bmap)
3898 return NULL;
3900 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
3901 if (!bmap->dim)
3902 goto error;
3903 bmap = isl_basic_map_simplify(bmap);
3904 bmap = isl_basic_map_drop_redundant_divs(bmap);
3905 return isl_basic_map_finalize(bmap);
3906 error:
3907 isl_basic_map_free(bmap);
3908 return NULL;
3911 /* Turn the n dimensions of type type, starting at first
3912 * into existentially quantified variables.
3914 struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
3915 enum isl_dim_type type, unsigned first, unsigned n)
3917 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
3918 type, first, n));
3921 /* Turn the n dimensions of type type, starting at first
3922 * into existentially quantified variables.
3924 __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
3925 enum isl_dim_type type, unsigned first, unsigned n)
3927 int i;
3929 if (!map)
3930 return NULL;
3932 if (n == 0)
3933 return map_space_reset(map, type);
3935 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
3937 map = isl_map_cow(map);
3938 if (!map)
3939 return NULL;
3941 map->dim = isl_space_drop_dims(map->dim, type, first, n);
3942 if (!map->dim)
3943 goto error;
3945 for (i = 0; i < map->n; ++i) {
3946 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
3947 if (!map->p[i])
3948 goto error;
3951 return map;
3952 error:
3953 isl_map_free(map);
3954 return NULL;
3957 /* Turn the n dimensions of type type, starting at first
3958 * into existentially quantified variables.
3960 __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
3961 enum isl_dim_type type, unsigned first, unsigned n)
3963 return set_from_map(isl_map_project_out(set_to_map(set),
3964 type, first, n));
3967 /* Return a map that projects the elements in "set" onto their
3968 * "n" set dimensions starting at "first".
3969 * "type" should be equal to isl_dim_set.
3971 __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
3972 enum isl_dim_type type, unsigned first, unsigned n)
3974 int i;
3975 int dim;
3976 isl_map *map;
3978 if (!set)
3979 return NULL;
3980 if (type != isl_dim_set)
3981 isl_die(isl_set_get_ctx(set), isl_error_invalid,
3982 "only set dimensions can be projected out", goto error);
3983 dim = isl_set_dim(set, isl_dim_set);
3984 if (first + n > dim || first + n < first)
3985 isl_die(isl_set_get_ctx(set), isl_error_invalid,
3986 "index out of bounds", goto error);
3988 map = isl_map_from_domain(set);
3989 map = isl_map_add_dims(map, isl_dim_out, n);
3990 for (i = 0; i < n; ++i)
3991 map = isl_map_equate(map, isl_dim_in, first + i,
3992 isl_dim_out, i);
3993 return map;
3994 error:
3995 isl_set_free(set);
3996 return NULL;
3999 static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
4001 int i, j;
4003 for (i = 0; i < n; ++i) {
4004 j = isl_basic_map_alloc_div(bmap);
4005 if (j < 0)
4006 goto error;
4007 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
4009 return bmap;
4010 error:
4011 isl_basic_map_free(bmap);
4012 return NULL;
4015 struct isl_basic_map *isl_basic_map_apply_range(
4016 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4018 isl_space *dim_result = NULL;
4019 struct isl_basic_map *bmap;
4020 unsigned n_in, n_out, n, nparam, total, pos;
4021 struct isl_dim_map *dim_map1, *dim_map2;
4023 if (!bmap1 || !bmap2)
4024 goto error;
4025 if (!isl_space_match(bmap1->dim, isl_dim_param,
4026 bmap2->dim, isl_dim_param))
4027 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4028 "parameters don't match", goto error);
4029 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
4030 bmap2->dim, isl_dim_in))
4031 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4032 "spaces don't match", goto error);
4034 dim_result = isl_space_join(isl_space_copy(bmap1->dim),
4035 isl_space_copy(bmap2->dim));
4037 n_in = isl_basic_map_n_in(bmap1);
4038 n_out = isl_basic_map_n_out(bmap2);
4039 n = isl_basic_map_n_out(bmap1);
4040 nparam = isl_basic_map_n_param(bmap1);
4042 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4043 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4044 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4045 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4046 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4047 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4048 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4049 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4050 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4051 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4052 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4054 bmap = isl_basic_map_alloc_space(dim_result,
4055 bmap1->n_div + bmap2->n_div + n,
4056 bmap1->n_eq + bmap2->n_eq,
4057 bmap1->n_ineq + bmap2->n_ineq);
4058 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4059 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4060 bmap = add_divs(bmap, n);
4061 bmap = isl_basic_map_simplify(bmap);
4062 bmap = isl_basic_map_drop_redundant_divs(bmap);
4063 return isl_basic_map_finalize(bmap);
4064 error:
4065 isl_basic_map_free(bmap1);
4066 isl_basic_map_free(bmap2);
4067 return NULL;
4070 struct isl_basic_set *isl_basic_set_apply(
4071 struct isl_basic_set *bset, struct isl_basic_map *bmap)
4073 if (!bset || !bmap)
4074 goto error;
4076 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
4077 goto error);
4079 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4080 bmap));
4081 error:
4082 isl_basic_set_free(bset);
4083 isl_basic_map_free(bmap);
4084 return NULL;
4087 struct isl_basic_map *isl_basic_map_apply_domain(
4088 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4090 if (!bmap1 || !bmap2)
4091 goto error;
4093 if (!isl_space_match(bmap1->dim, isl_dim_param,
4094 bmap2->dim, isl_dim_param))
4095 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4096 "parameters don't match", goto error);
4097 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4098 bmap2->dim, isl_dim_in))
4099 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4100 "spaces don't match", goto error);
4102 bmap1 = isl_basic_map_reverse(bmap1);
4103 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4104 return isl_basic_map_reverse(bmap1);
4105 error:
4106 isl_basic_map_free(bmap1);
4107 isl_basic_map_free(bmap2);
4108 return NULL;
4111 /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4112 * A \cap B -> f(A) + f(B)
4114 struct isl_basic_map *isl_basic_map_sum(
4115 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
4117 unsigned n_in, n_out, nparam, total, pos;
4118 struct isl_basic_map *bmap = NULL;
4119 struct isl_dim_map *dim_map1, *dim_map2;
4120 int i;
4122 if (!bmap1 || !bmap2)
4123 goto error;
4125 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
4126 goto error);
4128 nparam = isl_basic_map_n_param(bmap1);
4129 n_in = isl_basic_map_n_in(bmap1);
4130 n_out = isl_basic_map_n_out(bmap1);
4132 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4133 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4134 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4135 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4136 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4137 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4138 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4139 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4140 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4141 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4142 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4144 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4145 bmap1->n_div + bmap2->n_div + 2 * n_out,
4146 bmap1->n_eq + bmap2->n_eq + n_out,
4147 bmap1->n_ineq + bmap2->n_ineq);
4148 for (i = 0; i < n_out; ++i) {
4149 int j = isl_basic_map_alloc_equality(bmap);
4150 if (j < 0)
4151 goto error;
4152 isl_seq_clr(bmap->eq[j], 1+total);
4153 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4154 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4155 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4157 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4158 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4159 bmap = add_divs(bmap, 2 * n_out);
4161 bmap = isl_basic_map_simplify(bmap);
4162 return isl_basic_map_finalize(bmap);
4163 error:
4164 isl_basic_map_free(bmap);
4165 isl_basic_map_free(bmap1);
4166 isl_basic_map_free(bmap2);
4167 return NULL;
4170 /* Given two maps A -> f(A) and B -> g(B), construct a map
4171 * A \cap B -> f(A) + f(B)
4173 struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2)
4175 struct isl_map *result;
4176 int i, j;
4178 if (!map1 || !map2)
4179 goto error;
4181 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
4183 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4184 map1->n * map2->n, 0);
4185 if (!result)
4186 goto error;
4187 for (i = 0; i < map1->n; ++i)
4188 for (j = 0; j < map2->n; ++j) {
4189 struct isl_basic_map *part;
4190 part = isl_basic_map_sum(
4191 isl_basic_map_copy(map1->p[i]),
4192 isl_basic_map_copy(map2->p[j]));
4193 if (isl_basic_map_is_empty(part))
4194 isl_basic_map_free(part);
4195 else
4196 result = isl_map_add_basic_map(result, part);
4197 if (!result)
4198 goto error;
4200 isl_map_free(map1);
4201 isl_map_free(map2);
4202 return result;
4203 error:
4204 isl_map_free(map1);
4205 isl_map_free(map2);
4206 return NULL;
4209 __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4210 __isl_take isl_set *set2)
4212 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4215 /* Given a basic map A -> f(A), construct A -> -f(A).
4217 struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap)
4219 int i, j;
4220 unsigned off, n;
4222 bmap = isl_basic_map_cow(bmap);
4223 if (!bmap)
4224 return NULL;
4226 n = isl_basic_map_dim(bmap, isl_dim_out);
4227 off = isl_basic_map_offset(bmap, isl_dim_out);
4228 for (i = 0; i < bmap->n_eq; ++i)
4229 for (j = 0; j < n; ++j)
4230 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4231 for (i = 0; i < bmap->n_ineq; ++i)
4232 for (j = 0; j < n; ++j)
4233 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4234 for (i = 0; i < bmap->n_div; ++i)
4235 for (j = 0; j < n; ++j)
4236 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4237 bmap = isl_basic_map_gauss(bmap, NULL);
4238 return isl_basic_map_finalize(bmap);
4241 __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4243 return isl_basic_map_neg(bset);
4246 /* Given a map A -> f(A), construct A -> -f(A).
4248 struct isl_map *isl_map_neg(struct isl_map *map)
4250 int i;
4252 map = isl_map_cow(map);
4253 if (!map)
4254 return NULL;
4256 for (i = 0; i < map->n; ++i) {
4257 map->p[i] = isl_basic_map_neg(map->p[i]);
4258 if (!map->p[i])
4259 goto error;
4262 return map;
4263 error:
4264 isl_map_free(map);
4265 return NULL;
4268 __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4270 return set_from_map(isl_map_neg(set_to_map(set)));
4273 /* Given a basic map A -> f(A) and an integer d, construct a basic map
4274 * A -> floor(f(A)/d).
4276 struct isl_basic_map *isl_basic_map_floordiv(struct isl_basic_map *bmap,
4277 isl_int d)
4279 unsigned n_in, n_out, nparam, total, pos;
4280 struct isl_basic_map *result = NULL;
4281 struct isl_dim_map *dim_map;
4282 int i;
4284 if (!bmap)
4285 return NULL;
4287 nparam = isl_basic_map_n_param(bmap);
4288 n_in = isl_basic_map_n_in(bmap);
4289 n_out = isl_basic_map_n_out(bmap);
4291 total = nparam + n_in + n_out + bmap->n_div + n_out;
4292 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4293 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4294 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4295 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4296 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4298 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4299 bmap->n_div + n_out,
4300 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4301 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4302 result = add_divs(result, n_out);
4303 for (i = 0; i < n_out; ++i) {
4304 int j;
4305 j = isl_basic_map_alloc_inequality(result);
4306 if (j < 0)
4307 goto error;
4308 isl_seq_clr(result->ineq[j], 1+total);
4309 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4310 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4311 j = isl_basic_map_alloc_inequality(result);
4312 if (j < 0)
4313 goto error;
4314 isl_seq_clr(result->ineq[j], 1+total);
4315 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4316 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4317 isl_int_sub_ui(result->ineq[j][0], d, 1);
4320 result = isl_basic_map_simplify(result);
4321 return isl_basic_map_finalize(result);
4322 error:
4323 isl_basic_map_free(result);
4324 return NULL;
4327 /* Given a map A -> f(A) and an integer d, construct a map
4328 * A -> floor(f(A)/d).
4330 struct isl_map *isl_map_floordiv(struct isl_map *map, isl_int d)
4332 int i;
4334 map = isl_map_cow(map);
4335 if (!map)
4336 return NULL;
4338 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4339 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
4340 for (i = 0; i < map->n; ++i) {
4341 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4342 if (!map->p[i])
4343 goto error;
4346 return map;
4347 error:
4348 isl_map_free(map);
4349 return NULL;
4352 /* Given a map A -> f(A) and an integer d, construct a map
4353 * A -> floor(f(A)/d).
4355 __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
4356 __isl_take isl_val *d)
4358 if (!map || !d)
4359 goto error;
4360 if (!isl_val_is_int(d))
4361 isl_die(isl_val_get_ctx(d), isl_error_invalid,
4362 "expecting integer denominator", goto error);
4363 map = isl_map_floordiv(map, d->n);
4364 isl_val_free(d);
4365 return map;
4366 error:
4367 isl_map_free(map);
4368 isl_val_free(d);
4369 return NULL;
4372 static struct isl_basic_map *var_equal(struct isl_basic_map *bmap, unsigned pos)
4374 int i;
4375 unsigned nparam;
4376 unsigned n_in;
4378 i = isl_basic_map_alloc_equality(bmap);
4379 if (i < 0)
4380 goto error;
4381 nparam = isl_basic_map_n_param(bmap);
4382 n_in = isl_basic_map_n_in(bmap);
4383 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
4384 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
4385 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
4386 return isl_basic_map_finalize(bmap);
4387 error:
4388 isl_basic_map_free(bmap);
4389 return NULL;
4392 /* Add a constraint to "bmap" expressing i_pos < o_pos
4394 static struct isl_basic_map *var_less(struct isl_basic_map *bmap, unsigned pos)
4396 int i;
4397 unsigned nparam;
4398 unsigned n_in;
4400 i = isl_basic_map_alloc_inequality(bmap);
4401 if (i < 0)
4402 goto error;
4403 nparam = isl_basic_map_n_param(bmap);
4404 n_in = isl_basic_map_n_in(bmap);
4405 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4406 isl_int_set_si(bmap->ineq[i][0], -1);
4407 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4408 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4409 return isl_basic_map_finalize(bmap);
4410 error:
4411 isl_basic_map_free(bmap);
4412 return NULL;
4415 /* Add a constraint to "bmap" expressing i_pos <= o_pos
4417 static __isl_give isl_basic_map *var_less_or_equal(
4418 __isl_take isl_basic_map *bmap, unsigned pos)
4420 int i;
4421 unsigned nparam;
4422 unsigned n_in;
4424 i = isl_basic_map_alloc_inequality(bmap);
4425 if (i < 0)
4426 goto error;
4427 nparam = isl_basic_map_n_param(bmap);
4428 n_in = isl_basic_map_n_in(bmap);
4429 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4430 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
4431 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
4432 return isl_basic_map_finalize(bmap);
4433 error:
4434 isl_basic_map_free(bmap);
4435 return NULL;
4438 /* Add a constraint to "bmap" expressing i_pos > o_pos
4440 static struct isl_basic_map *var_more(struct isl_basic_map *bmap, unsigned pos)
4442 int i;
4443 unsigned nparam;
4444 unsigned n_in;
4446 i = isl_basic_map_alloc_inequality(bmap);
4447 if (i < 0)
4448 goto error;
4449 nparam = isl_basic_map_n_param(bmap);
4450 n_in = isl_basic_map_n_in(bmap);
4451 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4452 isl_int_set_si(bmap->ineq[i][0], -1);
4453 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4454 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4455 return isl_basic_map_finalize(bmap);
4456 error:
4457 isl_basic_map_free(bmap);
4458 return NULL;
4461 /* Add a constraint to "bmap" expressing i_pos >= o_pos
4463 static __isl_give isl_basic_map *var_more_or_equal(
4464 __isl_take isl_basic_map *bmap, unsigned pos)
4466 int i;
4467 unsigned nparam;
4468 unsigned n_in;
4470 i = isl_basic_map_alloc_inequality(bmap);
4471 if (i < 0)
4472 goto error;
4473 nparam = isl_basic_map_n_param(bmap);
4474 n_in = isl_basic_map_n_in(bmap);
4475 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
4476 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
4477 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
4478 return isl_basic_map_finalize(bmap);
4479 error:
4480 isl_basic_map_free(bmap);
4481 return NULL;
4484 __isl_give isl_basic_map *isl_basic_map_equal(
4485 __isl_take isl_space *dim, unsigned n_equal)
4487 int i;
4488 struct isl_basic_map *bmap;
4489 bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
4490 if (!bmap)
4491 return NULL;
4492 for (i = 0; i < n_equal && bmap; ++i)
4493 bmap = var_equal(bmap, i);
4494 return isl_basic_map_finalize(bmap);
4497 /* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
4499 __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
4500 unsigned pos)
4502 int i;
4503 struct isl_basic_map *bmap;
4504 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4505 if (!bmap)
4506 return NULL;
4507 for (i = 0; i < pos && bmap; ++i)
4508 bmap = var_equal(bmap, i);
4509 if (bmap)
4510 bmap = var_less(bmap, pos);
4511 return isl_basic_map_finalize(bmap);
4514 /* Return a relation on "dim" expressing i_[0..pos] <<= o_[0..pos]
4516 __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
4517 __isl_take isl_space *dim, unsigned pos)
4519 int i;
4520 isl_basic_map *bmap;
4522 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4523 for (i = 0; i < pos; ++i)
4524 bmap = var_equal(bmap, i);
4525 bmap = var_less_or_equal(bmap, pos);
4526 return isl_basic_map_finalize(bmap);
4529 /* Return a relation on "dim" expressing i_pos > o_pos
4531 __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
4532 unsigned pos)
4534 int i;
4535 struct isl_basic_map *bmap;
4536 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4537 if (!bmap)
4538 return NULL;
4539 for (i = 0; i < pos && bmap; ++i)
4540 bmap = var_equal(bmap, i);
4541 if (bmap)
4542 bmap = var_more(bmap, pos);
4543 return isl_basic_map_finalize(bmap);
4546 /* Return a relation on "dim" expressing i_[0..pos] >>= o_[0..pos]
4548 __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
4549 __isl_take isl_space *dim, unsigned pos)
4551 int i;
4552 isl_basic_map *bmap;
4554 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
4555 for (i = 0; i < pos; ++i)
4556 bmap = var_equal(bmap, i);
4557 bmap = var_more_or_equal(bmap, pos);
4558 return isl_basic_map_finalize(bmap);
4561 static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
4562 unsigned n, int equal)
4564 struct isl_map *map;
4565 int i;
4567 if (n == 0 && equal)
4568 return isl_map_universe(dims);
4570 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4572 for (i = 0; i + 1 < n; ++i)
4573 map = isl_map_add_basic_map(map,
4574 isl_basic_map_less_at(isl_space_copy(dims), i));
4575 if (n > 0) {
4576 if (equal)
4577 map = isl_map_add_basic_map(map,
4578 isl_basic_map_less_or_equal_at(dims, n - 1));
4579 else
4580 map = isl_map_add_basic_map(map,
4581 isl_basic_map_less_at(dims, n - 1));
4582 } else
4583 isl_space_free(dims);
4585 return map;
4588 static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
4590 if (!dims)
4591 return NULL;
4592 return map_lex_lte_first(dims, dims->n_out, equal);
4595 __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
4597 return map_lex_lte_first(dim, n, 0);
4600 __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
4602 return map_lex_lte_first(dim, n, 1);
4605 __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
4607 return map_lex_lte(isl_space_map_from_set(set_dim), 0);
4610 __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
4612 return map_lex_lte(isl_space_map_from_set(set_dim), 1);
4615 static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
4616 unsigned n, int equal)
4618 struct isl_map *map;
4619 int i;
4621 if (n == 0 && equal)
4622 return isl_map_universe(dims);
4624 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
4626 for (i = 0; i + 1 < n; ++i)
4627 map = isl_map_add_basic_map(map,
4628 isl_basic_map_more_at(isl_space_copy(dims), i));
4629 if (n > 0) {
4630 if (equal)
4631 map = isl_map_add_basic_map(map,
4632 isl_basic_map_more_or_equal_at(dims, n - 1));
4633 else
4634 map = isl_map_add_basic_map(map,
4635 isl_basic_map_more_at(dims, n - 1));
4636 } else
4637 isl_space_free(dims);
4639 return map;
4642 static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
4644 if (!dims)
4645 return NULL;
4646 return map_lex_gte_first(dims, dims->n_out, equal);
4649 __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
4651 return map_lex_gte_first(dim, n, 0);
4654 __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
4656 return map_lex_gte_first(dim, n, 1);
4659 __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
4661 return map_lex_gte(isl_space_map_from_set(set_dim), 0);
4664 __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
4666 return map_lex_gte(isl_space_map_from_set(set_dim), 1);
4669 __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
4670 __isl_take isl_set *set2)
4672 isl_map *map;
4673 map = isl_map_lex_le(isl_set_get_space(set1));
4674 map = isl_map_intersect_domain(map, set1);
4675 map = isl_map_intersect_range(map, set2);
4676 return map;
4679 __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
4680 __isl_take isl_set *set2)
4682 isl_map *map;
4683 map = isl_map_lex_lt(isl_set_get_space(set1));
4684 map = isl_map_intersect_domain(map, set1);
4685 map = isl_map_intersect_range(map, set2);
4686 return map;
4689 __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
4690 __isl_take isl_set *set2)
4692 isl_map *map;
4693 map = isl_map_lex_ge(isl_set_get_space(set1));
4694 map = isl_map_intersect_domain(map, set1);
4695 map = isl_map_intersect_range(map, set2);
4696 return map;
4699 __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
4700 __isl_take isl_set *set2)
4702 isl_map *map;
4703 map = isl_map_lex_gt(isl_set_get_space(set1));
4704 map = isl_map_intersect_domain(map, set1);
4705 map = isl_map_intersect_range(map, set2);
4706 return map;
4709 __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
4710 __isl_take isl_map *map2)
4712 isl_map *map;
4713 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
4714 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4715 map = isl_map_apply_range(map, isl_map_reverse(map2));
4716 return map;
4719 __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
4720 __isl_take isl_map *map2)
4722 isl_map *map;
4723 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
4724 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4725 map = isl_map_apply_range(map, isl_map_reverse(map2));
4726 return map;
4729 __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
4730 __isl_take isl_map *map2)
4732 isl_map *map;
4733 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
4734 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4735 map = isl_map_apply_range(map, isl_map_reverse(map2));
4736 return map;
4739 __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
4740 __isl_take isl_map *map2)
4742 isl_map *map;
4743 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
4744 map = isl_map_apply_domain(map, isl_map_reverse(map1));
4745 map = isl_map_apply_range(map, isl_map_reverse(map2));
4746 return map;
4749 /* For a div d = floor(f/m), add the constraint
4751 * f - m d >= 0
4753 static isl_stat add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
4754 unsigned pos, isl_int *div)
4756 int i;
4757 unsigned total = isl_basic_map_total_dim(bmap);
4759 i = isl_basic_map_alloc_inequality(bmap);
4760 if (i < 0)
4761 return isl_stat_error;
4762 isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
4763 isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
4765 return isl_stat_ok;
4768 /* For a div d = floor(f/m), add the constraint
4770 * -(f-(m-1)) + m d >= 0
4772 static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
4773 unsigned pos, isl_int *div)
4775 int i;
4776 unsigned total = isl_basic_map_total_dim(bmap);
4778 i = isl_basic_map_alloc_inequality(bmap);
4779 if (i < 0)
4780 return isl_stat_error;
4781 isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
4782 isl_int_set(bmap->ineq[i][1 + pos], div[0]);
4783 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
4784 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
4786 return isl_stat_ok;
4789 /* For a div d = floor(f/m), add the constraints
4791 * f - m d >= 0
4792 * -(f-(m-1)) + m d >= 0
4794 * Note that the second constraint is the negation of
4796 * f - m d >= m
4798 int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
4799 unsigned pos, isl_int *div)
4801 if (add_upper_div_constraint(bmap, pos, div) < 0)
4802 return -1;
4803 if (add_lower_div_constraint(bmap, pos, div) < 0)
4804 return -1;
4805 return 0;
4808 int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
4809 unsigned pos, isl_int *div)
4811 return isl_basic_map_add_div_constraints_var(bset_to_bmap(bset),
4812 pos, div);
4815 int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
4817 unsigned total = isl_basic_map_total_dim(bmap);
4818 unsigned div_pos = total - bmap->n_div + div;
4820 return isl_basic_map_add_div_constraints_var(bmap, div_pos,
4821 bmap->div[div]);
4824 /* For each known div d = floor(f/m), add the constraints
4826 * f - m d >= 0
4827 * -(f-(m-1)) + m d >= 0
4829 * Remove duplicate constraints in case of some these div constraints
4830 * already appear in "bmap".
4832 __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
4833 __isl_take isl_basic_map *bmap)
4835 unsigned n_div;
4837 if (!bmap)
4838 return NULL;
4839 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4840 if (n_div == 0)
4841 return bmap;
4843 bmap = add_known_div_constraints(bmap);
4844 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
4845 bmap = isl_basic_map_finalize(bmap);
4846 return bmap;
4849 /* Add the div constraint of sign "sign" for div "div" of "bmap".
4851 * In particular, if this div is of the form d = floor(f/m),
4852 * then add the constraint
4854 * f - m d >= 0
4856 * if sign < 0 or the constraint
4858 * -(f-(m-1)) + m d >= 0
4860 * if sign > 0.
4862 int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
4863 unsigned div, int sign)
4865 unsigned total;
4866 unsigned div_pos;
4868 if (!bmap)
4869 return -1;
4871 total = isl_basic_map_total_dim(bmap);
4872 div_pos = total - bmap->n_div + div;
4874 if (sign < 0)
4875 return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
4876 else
4877 return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
4880 struct isl_basic_set *isl_basic_map_underlying_set(
4881 struct isl_basic_map *bmap)
4883 if (!bmap)
4884 goto error;
4885 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
4886 bmap->n_div == 0 &&
4887 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
4888 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
4889 return bset_from_bmap(bmap);
4890 bmap = isl_basic_map_cow(bmap);
4891 if (!bmap)
4892 goto error;
4893 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
4894 if (!bmap->dim)
4895 goto error;
4896 bmap->extra -= bmap->n_div;
4897 bmap->n_div = 0;
4898 bmap = isl_basic_map_finalize(bmap);
4899 return bset_from_bmap(bmap);
4900 error:
4901 isl_basic_map_free(bmap);
4902 return NULL;
4905 __isl_give isl_basic_set *isl_basic_set_underlying_set(
4906 __isl_take isl_basic_set *bset)
4908 return isl_basic_map_underlying_set(bset_to_bmap(bset));
4911 /* Replace each element in "list" by the result of applying
4912 * isl_basic_map_underlying_set to the element.
4914 __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
4915 __isl_take isl_basic_map_list *list)
4917 int i, n;
4919 if (!list)
4920 return NULL;
4922 n = isl_basic_map_list_n_basic_map(list);
4923 for (i = 0; i < n; ++i) {
4924 isl_basic_map *bmap;
4925 isl_basic_set *bset;
4927 bmap = isl_basic_map_list_get_basic_map(list, i);
4928 bset = isl_basic_set_underlying_set(bmap);
4929 list = isl_basic_set_list_set_basic_set(list, i, bset);
4932 return list;
4935 struct isl_basic_map *isl_basic_map_overlying_set(
4936 struct isl_basic_set *bset, struct isl_basic_map *like)
4938 struct isl_basic_map *bmap;
4939 struct isl_ctx *ctx;
4940 unsigned total;
4941 int i;
4943 if (!bset || !like)
4944 goto error;
4945 ctx = bset->ctx;
4946 isl_assert(ctx, bset->n_div == 0, goto error);
4947 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
4948 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
4949 goto error);
4950 if (like->n_div == 0) {
4951 isl_space *space = isl_basic_map_get_space(like);
4952 isl_basic_map_free(like);
4953 return isl_basic_map_reset_space(bset, space);
4955 bset = isl_basic_set_cow(bset);
4956 if (!bset)
4957 goto error;
4958 total = bset->dim->n_out + bset->extra;
4959 bmap = bset_to_bmap(bset);
4960 isl_space_free(bmap->dim);
4961 bmap->dim = isl_space_copy(like->dim);
4962 if (!bmap->dim)
4963 goto error;
4964 bmap->n_div = like->n_div;
4965 bmap->extra += like->n_div;
4966 if (bmap->extra) {
4967 unsigned ltotal;
4968 isl_int **div;
4969 ltotal = total - bmap->extra + like->extra;
4970 if (ltotal > total)
4971 ltotal = total;
4972 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
4973 bmap->extra * (1 + 1 + total));
4974 if (isl_blk_is_error(bmap->block2))
4975 goto error;
4976 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
4977 if (!div)
4978 goto error;
4979 bmap->div = div;
4980 for (i = 0; i < bmap->extra; ++i)
4981 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
4982 for (i = 0; i < like->n_div; ++i) {
4983 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
4984 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
4986 bmap = isl_basic_map_add_known_div_constraints(bmap);
4988 isl_basic_map_free(like);
4989 bmap = isl_basic_map_simplify(bmap);
4990 bmap = isl_basic_map_finalize(bmap);
4991 return bmap;
4992 error:
4993 isl_basic_map_free(like);
4994 isl_basic_set_free(bset);
4995 return NULL;
4998 struct isl_basic_set *isl_basic_set_from_underlying_set(
4999 struct isl_basic_set *bset, struct isl_basic_set *like)
5001 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5002 bset_to_bmap(like)));
5005 struct isl_set *isl_map_underlying_set(struct isl_map *map)
5007 int i;
5009 map = isl_map_cow(map);
5010 if (!map)
5011 return NULL;
5012 map->dim = isl_space_cow(map->dim);
5013 if (!map->dim)
5014 goto error;
5016 for (i = 1; i < map->n; ++i)
5017 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5018 goto error);
5019 for (i = 0; i < map->n; ++i) {
5020 map->p[i] = bset_to_bmap(
5021 isl_basic_map_underlying_set(map->p[i]));
5022 if (!map->p[i])
5023 goto error;
5025 if (map->n == 0)
5026 map->dim = isl_space_underlying(map->dim, 0);
5027 else {
5028 isl_space_free(map->dim);
5029 map->dim = isl_space_copy(map->p[0]->dim);
5031 if (!map->dim)
5032 goto error;
5033 return set_from_map(map);
5034 error:
5035 isl_map_free(map);
5036 return NULL;
5039 /* Replace the space of "bmap" by "space".
5041 * If the space of "bmap" is identical to "space" (including the identifiers
5042 * of the input and output dimensions), then simply return the original input.
5044 __isl_give isl_basic_map *isl_basic_map_reset_space(
5045 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5047 isl_bool equal;
5049 if (!bmap)
5050 goto error;
5051 equal = isl_space_is_equal(bmap->dim, space);
5052 if (equal >= 0 && equal)
5053 equal = isl_space_match(bmap->dim, isl_dim_in,
5054 space, isl_dim_in);
5055 if (equal >= 0 && equal)
5056 equal = isl_space_match(bmap->dim, isl_dim_out,
5057 space, isl_dim_out);
5058 if (equal < 0)
5059 goto error;
5060 if (equal) {
5061 isl_space_free(space);
5062 return bmap;
5064 bmap = isl_basic_map_cow(bmap);
5065 if (!bmap || !space)
5066 goto error;
5068 isl_space_free(bmap->dim);
5069 bmap->dim = space;
5071 bmap = isl_basic_map_finalize(bmap);
5073 return bmap;
5074 error:
5075 isl_basic_map_free(bmap);
5076 isl_space_free(space);
5077 return NULL;
5080 __isl_give isl_basic_set *isl_basic_set_reset_space(
5081 __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
5083 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5084 dim));
5087 __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5088 __isl_take isl_space *dim)
5090 int i;
5092 map = isl_map_cow(map);
5093 if (!map || !dim)
5094 goto error;
5096 for (i = 0; i < map->n; ++i) {
5097 map->p[i] = isl_basic_map_reset_space(map->p[i],
5098 isl_space_copy(dim));
5099 if (!map->p[i])
5100 goto error;
5102 isl_space_free(map->dim);
5103 map->dim = dim;
5105 return map;
5106 error:
5107 isl_map_free(map);
5108 isl_space_free(dim);
5109 return NULL;
5112 __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5113 __isl_take isl_space *dim)
5115 return set_from_map(isl_map_reset_space(set_to_map(set), dim));
5118 /* Compute the parameter domain of the given basic set.
5120 __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5122 isl_bool is_params;
5123 isl_space *space;
5124 unsigned n;
5126 is_params = isl_basic_set_is_params(bset);
5127 if (is_params < 0)
5128 return isl_basic_set_free(bset);
5129 if (is_params)
5130 return bset;
5132 n = isl_basic_set_dim(bset, isl_dim_set);
5133 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5134 space = isl_basic_set_get_space(bset);
5135 space = isl_space_params(space);
5136 bset = isl_basic_set_reset_space(bset, space);
5137 return bset;
5140 /* Construct a zero-dimensional basic set with the given parameter domain.
5142 __isl_give isl_basic_set *isl_basic_set_from_params(
5143 __isl_take isl_basic_set *bset)
5145 isl_space *space;
5146 space = isl_basic_set_get_space(bset);
5147 space = isl_space_set_from_params(space);
5148 bset = isl_basic_set_reset_space(bset, space);
5149 return bset;
5152 /* Compute the parameter domain of the given set.
5154 __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5156 isl_space *space;
5157 unsigned n;
5159 if (isl_set_is_params(set))
5160 return set;
5162 n = isl_set_dim(set, isl_dim_set);
5163 set = isl_set_project_out(set, isl_dim_set, 0, n);
5164 space = isl_set_get_space(set);
5165 space = isl_space_params(space);
5166 set = isl_set_reset_space(set, space);
5167 return set;
5170 /* Construct a zero-dimensional set with the given parameter domain.
5172 __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5174 isl_space *space;
5175 space = isl_set_get_space(set);
5176 space = isl_space_set_from_params(space);
5177 set = isl_set_reset_space(set, space);
5178 return set;
5181 /* Compute the parameter domain of the given map.
5183 __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5185 isl_space *space;
5186 unsigned n;
5188 n = isl_map_dim(map, isl_dim_in);
5189 map = isl_map_project_out(map, isl_dim_in, 0, n);
5190 n = isl_map_dim(map, isl_dim_out);
5191 map = isl_map_project_out(map, isl_dim_out, 0, n);
5192 space = isl_map_get_space(map);
5193 space = isl_space_params(space);
5194 map = isl_map_reset_space(map, space);
5195 return map;
5198 struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
5200 isl_space *space;
5201 unsigned n_out;
5203 if (!bmap)
5204 return NULL;
5205 space = isl_space_domain(isl_basic_map_get_space(bmap));
5207 n_out = isl_basic_map_n_out(bmap);
5208 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5210 return isl_basic_map_reset_space(bmap, space);
5213 isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5215 if (!bmap)
5216 return isl_bool_error;
5217 return isl_space_may_be_set(bmap->dim);
5220 /* Is this basic map actually a set?
5221 * Users should never call this function. Outside of isl,
5222 * the type should indicate whether something is a set or a map.
5224 isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5226 if (!bmap)
5227 return isl_bool_error;
5228 return isl_space_is_set(bmap->dim);
5231 struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
5233 isl_bool is_set;
5235 is_set = isl_basic_map_is_set(bmap);
5236 if (is_set < 0)
5237 goto error;
5238 if (is_set)
5239 return bmap;
5240 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5241 error:
5242 isl_basic_map_free(bmap);
5243 return NULL;
5246 __isl_give isl_basic_map *isl_basic_map_domain_map(
5247 __isl_take isl_basic_map *bmap)
5249 int i;
5250 isl_space *dim;
5251 isl_basic_map *domain;
5252 int nparam, n_in, n_out;
5254 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5255 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5256 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5258 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
5259 domain = isl_basic_map_universe(dim);
5261 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5262 bmap = isl_basic_map_apply_range(bmap, domain);
5263 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5265 for (i = 0; i < n_in; ++i)
5266 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5267 isl_dim_out, i);
5269 bmap = isl_basic_map_gauss(bmap, NULL);
5270 return isl_basic_map_finalize(bmap);
5273 __isl_give isl_basic_map *isl_basic_map_range_map(
5274 __isl_take isl_basic_map *bmap)
5276 int i;
5277 isl_space *dim;
5278 isl_basic_map *range;
5279 int nparam, n_in, n_out;
5281 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5282 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5283 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5285 dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
5286 range = isl_basic_map_universe(dim);
5288 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5289 bmap = isl_basic_map_apply_range(bmap, range);
5290 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
5292 for (i = 0; i < n_out; ++i)
5293 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
5294 isl_dim_out, i);
5296 bmap = isl_basic_map_gauss(bmap, NULL);
5297 return isl_basic_map_finalize(bmap);
5300 int isl_map_may_be_set(__isl_keep isl_map *map)
5302 if (!map)
5303 return -1;
5304 return isl_space_may_be_set(map->dim);
5307 /* Is this map actually a set?
5308 * Users should never call this function. Outside of isl,
5309 * the type should indicate whether something is a set or a map.
5311 isl_bool isl_map_is_set(__isl_keep isl_map *map)
5313 if (!map)
5314 return isl_bool_error;
5315 return isl_space_is_set(map->dim);
5318 struct isl_set *isl_map_range(struct isl_map *map)
5320 int i;
5321 isl_bool is_set;
5322 struct isl_set *set;
5324 is_set = isl_map_is_set(map);
5325 if (is_set < 0)
5326 goto error;
5327 if (is_set)
5328 return set_from_map(map);
5330 map = isl_map_cow(map);
5331 if (!map)
5332 goto error;
5334 set = set_from_map(map);
5335 set->dim = isl_space_range(set->dim);
5336 if (!set->dim)
5337 goto error;
5338 for (i = 0; i < map->n; ++i) {
5339 set->p[i] = isl_basic_map_range(map->p[i]);
5340 if (!set->p[i])
5341 goto error;
5343 ISL_F_CLR(set, ISL_MAP_DISJOINT);
5344 ISL_F_CLR(set, ISL_SET_NORMALIZED);
5345 return set;
5346 error:
5347 isl_map_free(map);
5348 return NULL;
5351 __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
5353 int i;
5355 map = isl_map_cow(map);
5356 if (!map)
5357 return NULL;
5359 map->dim = isl_space_domain_map(map->dim);
5360 if (!map->dim)
5361 goto error;
5362 for (i = 0; i < map->n; ++i) {
5363 map->p[i] = isl_basic_map_domain_map(map->p[i]);
5364 if (!map->p[i])
5365 goto error;
5367 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5368 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5369 return map;
5370 error:
5371 isl_map_free(map);
5372 return NULL;
5375 __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
5377 int i;
5378 isl_space *range_dim;
5380 map = isl_map_cow(map);
5381 if (!map)
5382 return NULL;
5384 range_dim = isl_space_range(isl_map_get_space(map));
5385 range_dim = isl_space_from_range(range_dim);
5386 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
5387 map->dim = isl_space_join(map->dim, range_dim);
5388 if (!map->dim)
5389 goto error;
5390 for (i = 0; i < map->n; ++i) {
5391 map->p[i] = isl_basic_map_range_map(map->p[i]);
5392 if (!map->p[i])
5393 goto error;
5395 ISL_F_CLR(map, ISL_MAP_DISJOINT);
5396 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5397 return map;
5398 error:
5399 isl_map_free(map);
5400 return NULL;
5403 /* Given a wrapped map of the form A[B -> C],
5404 * return the map A[B -> C] -> B.
5406 __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
5408 isl_id *id;
5409 isl_map *map;
5411 if (!set)
5412 return NULL;
5413 if (!isl_set_has_tuple_id(set))
5414 return isl_map_domain_map(isl_set_unwrap(set));
5416 id = isl_set_get_tuple_id(set);
5417 map = isl_map_domain_map(isl_set_unwrap(set));
5418 map = isl_map_set_tuple_id(map, isl_dim_in, id);
5420 return map;
5423 __isl_give isl_basic_map *isl_basic_map_from_domain(
5424 __isl_take isl_basic_set *bset)
5426 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
5429 __isl_give isl_basic_map *isl_basic_map_from_range(
5430 __isl_take isl_basic_set *bset)
5432 isl_space *space;
5433 space = isl_basic_set_get_space(bset);
5434 space = isl_space_from_range(space);
5435 bset = isl_basic_set_reset_space(bset, space);
5436 return bset_to_bmap(bset);
5439 /* Create a relation with the given set as range.
5440 * The domain of the created relation is a zero-dimensional
5441 * flat anonymous space.
5443 __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
5445 isl_space *space;
5446 space = isl_set_get_space(set);
5447 space = isl_space_from_range(space);
5448 set = isl_set_reset_space(set, space);
5449 return set_to_map(set);
5452 /* Create a relation with the given set as domain.
5453 * The range of the created relation is a zero-dimensional
5454 * flat anonymous space.
5456 __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
5458 return isl_map_reverse(isl_map_from_range(set));
5461 __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
5462 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
5464 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
5467 __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
5468 __isl_take isl_set *range)
5470 return isl_map_apply_range(isl_map_reverse(domain), range);
5473 /* Return a newly allocated isl_map with given space and flags and
5474 * room for "n" basic maps.
5475 * Make sure that all cached information is cleared.
5477 __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
5478 unsigned flags)
5480 struct isl_map *map;
5482 if (!space)
5483 return NULL;
5484 if (n < 0)
5485 isl_die(space->ctx, isl_error_internal,
5486 "negative number of basic maps", goto error);
5487 map = isl_calloc(space->ctx, struct isl_map,
5488 sizeof(struct isl_map) +
5489 (n - 1) * sizeof(struct isl_basic_map *));
5490 if (!map)
5491 goto error;
5493 map->ctx = space->ctx;
5494 isl_ctx_ref(map->ctx);
5495 map->ref = 1;
5496 map->size = n;
5497 map->n = 0;
5498 map->dim = space;
5499 map->flags = flags;
5500 return map;
5501 error:
5502 isl_space_free(space);
5503 return NULL;
5506 __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim)
5508 struct isl_basic_map *bmap;
5509 bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
5510 bmap = isl_basic_map_set_to_empty(bmap);
5511 return bmap;
5514 __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim)
5516 struct isl_basic_set *bset;
5517 bset = isl_basic_set_alloc_space(dim, 0, 1, 0);
5518 bset = isl_basic_set_set_to_empty(bset);
5519 return bset;
5522 __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim)
5524 struct isl_basic_map *bmap;
5525 bmap = isl_basic_map_alloc_space(dim, 0, 0, 0);
5526 bmap = isl_basic_map_finalize(bmap);
5527 return bmap;
5530 __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim)
5532 struct isl_basic_set *bset;
5533 bset = isl_basic_set_alloc_space(dim, 0, 0, 0);
5534 bset = isl_basic_set_finalize(bset);
5535 return bset;
5538 __isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
5540 int i;
5541 unsigned total = isl_space_dim(dim, isl_dim_all);
5542 isl_basic_map *bmap;
5544 bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
5545 for (i = 0; i < total; ++i) {
5546 int k = isl_basic_map_alloc_inequality(bmap);
5547 if (k < 0)
5548 goto error;
5549 isl_seq_clr(bmap->ineq[k], 1 + total);
5550 isl_int_set_si(bmap->ineq[k][1 + i], 1);
5552 return bmap;
5553 error:
5554 isl_basic_map_free(bmap);
5555 return NULL;
5558 __isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
5560 return isl_basic_map_nat_universe(dim);
5563 __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
5565 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
5568 __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
5570 return isl_map_nat_universe(dim);
5573 __isl_give isl_map *isl_map_empty(__isl_take isl_space *dim)
5575 return isl_map_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5578 __isl_give isl_set *isl_set_empty(__isl_take isl_space *dim)
5580 return isl_set_alloc_space(dim, 0, ISL_MAP_DISJOINT);
5583 __isl_give isl_map *isl_map_universe(__isl_take isl_space *dim)
5585 struct isl_map *map;
5586 if (!dim)
5587 return NULL;
5588 map = isl_map_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5589 map = isl_map_add_basic_map(map, isl_basic_map_universe(dim));
5590 return map;
5593 __isl_give isl_set *isl_set_universe(__isl_take isl_space *dim)
5595 struct isl_set *set;
5596 if (!dim)
5597 return NULL;
5598 set = isl_set_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
5599 set = isl_set_add_basic_set(set, isl_basic_set_universe(dim));
5600 return set;
5603 struct isl_map *isl_map_dup(struct isl_map *map)
5605 int i;
5606 struct isl_map *dup;
5608 if (!map)
5609 return NULL;
5610 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
5611 for (i = 0; i < map->n; ++i)
5612 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
5613 return dup;
5616 __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
5617 __isl_take isl_basic_map *bmap)
5619 if (!bmap || !map)
5620 goto error;
5621 if (isl_basic_map_plain_is_empty(bmap)) {
5622 isl_basic_map_free(bmap);
5623 return map;
5625 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
5626 isl_assert(map->ctx, map->n < map->size, goto error);
5627 map->p[map->n] = bmap;
5628 map->n++;
5629 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5630 return map;
5631 error:
5632 if (map)
5633 isl_map_free(map);
5634 if (bmap)
5635 isl_basic_map_free(bmap);
5636 return NULL;
5639 __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
5641 int i;
5643 if (!map)
5644 return NULL;
5646 if (--map->ref > 0)
5647 return NULL;
5649 clear_caches(map);
5650 isl_ctx_deref(map->ctx);
5651 for (i = 0; i < map->n; ++i)
5652 isl_basic_map_free(map->p[i]);
5653 isl_space_free(map->dim);
5654 free(map);
5656 return NULL;
5659 static struct isl_basic_map *isl_basic_map_fix_pos_si(
5660 struct isl_basic_map *bmap, unsigned pos, int value)
5662 int j;
5664 bmap = isl_basic_map_cow(bmap);
5665 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5666 j = isl_basic_map_alloc_equality(bmap);
5667 if (j < 0)
5668 goto error;
5669 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5670 isl_int_set_si(bmap->eq[j][pos], -1);
5671 isl_int_set_si(bmap->eq[j][0], value);
5672 bmap = isl_basic_map_simplify(bmap);
5673 return isl_basic_map_finalize(bmap);
5674 error:
5675 isl_basic_map_free(bmap);
5676 return NULL;
5679 static __isl_give isl_basic_map *isl_basic_map_fix_pos(
5680 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
5682 int j;
5684 bmap = isl_basic_map_cow(bmap);
5685 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
5686 j = isl_basic_map_alloc_equality(bmap);
5687 if (j < 0)
5688 goto error;
5689 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
5690 isl_int_set_si(bmap->eq[j][pos], -1);
5691 isl_int_set(bmap->eq[j][0], value);
5692 bmap = isl_basic_map_simplify(bmap);
5693 return isl_basic_map_finalize(bmap);
5694 error:
5695 isl_basic_map_free(bmap);
5696 return NULL;
5699 struct isl_basic_map *isl_basic_map_fix_si(struct isl_basic_map *bmap,
5700 enum isl_dim_type type, unsigned pos, int value)
5702 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
5703 return isl_basic_map_free(bmap);
5704 return isl_basic_map_fix_pos_si(bmap,
5705 isl_basic_map_offset(bmap, type) + pos, value);
5708 __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
5709 enum isl_dim_type type, unsigned pos, isl_int value)
5711 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
5712 return isl_basic_map_free(bmap);
5713 return isl_basic_map_fix_pos(bmap,
5714 isl_basic_map_offset(bmap, type) + pos, value);
5717 /* Fix the value of the variable at position "pos" of type "type" of "bmap"
5718 * to be equal to "v".
5720 __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
5721 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5723 if (!bmap || !v)
5724 goto error;
5725 if (!isl_val_is_int(v))
5726 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
5727 "expecting integer value", goto error);
5728 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
5729 goto error;
5730 pos += isl_basic_map_offset(bmap, type);
5731 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
5732 isl_val_free(v);
5733 return bmap;
5734 error:
5735 isl_basic_map_free(bmap);
5736 isl_val_free(v);
5737 return NULL;
5740 /* Fix the value of the variable at position "pos" of type "type" of "bset"
5741 * to be equal to "v".
5743 __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
5744 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5746 return isl_basic_map_fix_val(bset, type, pos, v);
5749 struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
5750 enum isl_dim_type type, unsigned pos, int value)
5752 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
5753 type, pos, value));
5756 __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
5757 enum isl_dim_type type, unsigned pos, isl_int value)
5759 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
5760 type, pos, value));
5763 struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
5764 unsigned input, int value)
5766 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
5769 struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
5770 unsigned dim, int value)
5772 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
5773 isl_dim_set, dim, value));
5776 static int remove_if_empty(__isl_keep isl_map *map, int i)
5778 int empty = isl_basic_map_plain_is_empty(map->p[i]);
5780 if (empty < 0)
5781 return -1;
5782 if (!empty)
5783 return 0;
5785 isl_basic_map_free(map->p[i]);
5786 if (i != map->n - 1) {
5787 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5788 map->p[i] = map->p[map->n - 1];
5790 map->n--;
5792 return 0;
5795 /* Perform "fn" on each basic map of "map", where we may not be holding
5796 * the only reference to "map".
5797 * In particular, "fn" should be a semantics preserving operation
5798 * that we want to apply to all copies of "map". We therefore need
5799 * to be careful not to modify "map" in a way that breaks "map"
5800 * in case anything goes wrong.
5802 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
5803 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
5805 struct isl_basic_map *bmap;
5806 int i;
5808 if (!map)
5809 return NULL;
5811 for (i = map->n - 1; i >= 0; --i) {
5812 bmap = isl_basic_map_copy(map->p[i]);
5813 bmap = fn(bmap);
5814 if (!bmap)
5815 goto error;
5816 isl_basic_map_free(map->p[i]);
5817 map->p[i] = bmap;
5818 if (remove_if_empty(map, i) < 0)
5819 goto error;
5822 return map;
5823 error:
5824 isl_map_free(map);
5825 return NULL;
5828 struct isl_map *isl_map_fix_si(struct isl_map *map,
5829 enum isl_dim_type type, unsigned pos, int value)
5831 int i;
5833 map = isl_map_cow(map);
5834 if (!map)
5835 return NULL;
5837 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5838 for (i = map->n - 1; i >= 0; --i) {
5839 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
5840 if (remove_if_empty(map, i) < 0)
5841 goto error;
5843 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5844 return map;
5845 error:
5846 isl_map_free(map);
5847 return NULL;
5850 __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
5851 enum isl_dim_type type, unsigned pos, int value)
5853 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
5856 __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
5857 enum isl_dim_type type, unsigned pos, isl_int value)
5859 int i;
5861 map = isl_map_cow(map);
5862 if (!map)
5863 return NULL;
5865 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5866 for (i = 0; i < map->n; ++i) {
5867 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
5868 if (!map->p[i])
5869 goto error;
5871 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5872 return map;
5873 error:
5874 isl_map_free(map);
5875 return NULL;
5878 __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
5879 enum isl_dim_type type, unsigned pos, isl_int value)
5881 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
5884 /* Fix the value of the variable at position "pos" of type "type" of "map"
5885 * to be equal to "v".
5887 __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
5888 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5890 int i;
5892 map = isl_map_cow(map);
5893 if (!map || !v)
5894 goto error;
5896 if (!isl_val_is_int(v))
5897 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5898 "expecting integer value", goto error);
5899 if (pos >= isl_map_dim(map, type))
5900 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5901 "index out of bounds", goto error);
5902 for (i = map->n - 1; i >= 0; --i) {
5903 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
5904 isl_val_copy(v));
5905 if (remove_if_empty(map, i) < 0)
5906 goto error;
5908 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
5909 isl_val_free(v);
5910 return map;
5911 error:
5912 isl_map_free(map);
5913 isl_val_free(v);
5914 return NULL;
5917 /* Fix the value of the variable at position "pos" of type "type" of "set"
5918 * to be equal to "v".
5920 __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
5921 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
5923 return isl_map_fix_val(set, type, pos, v);
5926 struct isl_map *isl_map_fix_input_si(struct isl_map *map,
5927 unsigned input, int value)
5929 return isl_map_fix_si(map, isl_dim_in, input, value);
5932 struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
5934 return set_from_map(isl_map_fix_si(set_to_map(set),
5935 isl_dim_set, dim, value));
5938 static __isl_give isl_basic_map *basic_map_bound_si(
5939 __isl_take isl_basic_map *bmap,
5940 enum isl_dim_type type, unsigned pos, int value, int upper)
5942 int j;
5944 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
5945 return isl_basic_map_free(bmap);
5946 pos += isl_basic_map_offset(bmap, type);
5947 bmap = isl_basic_map_cow(bmap);
5948 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
5949 j = isl_basic_map_alloc_inequality(bmap);
5950 if (j < 0)
5951 goto error;
5952 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
5953 if (upper) {
5954 isl_int_set_si(bmap->ineq[j][pos], -1);
5955 isl_int_set_si(bmap->ineq[j][0], value);
5956 } else {
5957 isl_int_set_si(bmap->ineq[j][pos], 1);
5958 isl_int_set_si(bmap->ineq[j][0], -value);
5960 bmap = isl_basic_map_simplify(bmap);
5961 return isl_basic_map_finalize(bmap);
5962 error:
5963 isl_basic_map_free(bmap);
5964 return NULL;
5967 __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
5968 __isl_take isl_basic_map *bmap,
5969 enum isl_dim_type type, unsigned pos, int value)
5971 return basic_map_bound_si(bmap, type, pos, value, 0);
5974 /* Constrain the values of the given dimension to be no greater than "value".
5976 __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
5977 __isl_take isl_basic_map *bmap,
5978 enum isl_dim_type type, unsigned pos, int value)
5980 return basic_map_bound_si(bmap, type, pos, value, 1);
5983 static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
5984 enum isl_dim_type type, unsigned pos, int value, int upper)
5986 int i;
5988 map = isl_map_cow(map);
5989 if (!map)
5990 return NULL;
5992 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
5993 for (i = 0; i < map->n; ++i) {
5994 map->p[i] = basic_map_bound_si(map->p[i],
5995 type, pos, value, upper);
5996 if (!map->p[i])
5997 goto error;
5999 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
6000 return map;
6001 error:
6002 isl_map_free(map);
6003 return NULL;
6006 __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6007 enum isl_dim_type type, unsigned pos, int value)
6009 return map_bound_si(map, type, pos, value, 0);
6012 __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6013 enum isl_dim_type type, unsigned pos, int value)
6015 return map_bound_si(map, type, pos, value, 1);
6018 __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6019 enum isl_dim_type type, unsigned pos, int value)
6021 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6022 type, pos, value));
6025 __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6026 enum isl_dim_type type, unsigned pos, int value)
6028 return isl_map_upper_bound_si(set, type, pos, value);
6031 /* Bound the given variable of "bmap" from below (or above is "upper"
6032 * is set) to "value".
6034 static __isl_give isl_basic_map *basic_map_bound(
6035 __isl_take isl_basic_map *bmap,
6036 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6038 int j;
6040 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6041 return isl_basic_map_free(bmap);
6042 pos += isl_basic_map_offset(bmap, type);
6043 bmap = isl_basic_map_cow(bmap);
6044 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6045 j = isl_basic_map_alloc_inequality(bmap);
6046 if (j < 0)
6047 goto error;
6048 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
6049 if (upper) {
6050 isl_int_set_si(bmap->ineq[j][pos], -1);
6051 isl_int_set(bmap->ineq[j][0], value);
6052 } else {
6053 isl_int_set_si(bmap->ineq[j][pos], 1);
6054 isl_int_neg(bmap->ineq[j][0], value);
6056 bmap = isl_basic_map_simplify(bmap);
6057 return isl_basic_map_finalize(bmap);
6058 error:
6059 isl_basic_map_free(bmap);
6060 return NULL;
6063 /* Bound the given variable of "map" from below (or above is "upper"
6064 * is set) to "value".
6066 static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6067 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6069 int i;
6071 map = isl_map_cow(map);
6072 if (!map)
6073 return NULL;
6075 if (pos >= isl_map_dim(map, type))
6076 isl_die(map->ctx, isl_error_invalid,
6077 "index out of bounds", goto error);
6078 for (i = map->n - 1; i >= 0; --i) {
6079 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6080 if (remove_if_empty(map, i) < 0)
6081 goto error;
6083 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
6084 return map;
6085 error:
6086 isl_map_free(map);
6087 return NULL;
6090 __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6091 enum isl_dim_type type, unsigned pos, isl_int value)
6093 return map_bound(map, type, pos, value, 0);
6096 __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6097 enum isl_dim_type type, unsigned pos, isl_int value)
6099 return map_bound(map, type, pos, value, 1);
6102 __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6103 enum isl_dim_type type, unsigned pos, isl_int value)
6105 return isl_map_lower_bound(set, type, pos, value);
6108 __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6109 enum isl_dim_type type, unsigned pos, isl_int value)
6111 return isl_map_upper_bound(set, type, pos, value);
6114 /* Force the values of the variable at position "pos" of type "type" of "set"
6115 * to be no smaller than "value".
6117 __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6118 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6120 if (!value)
6121 goto error;
6122 if (!isl_val_is_int(value))
6123 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6124 "expecting integer value", goto error);
6125 set = isl_set_lower_bound(set, type, pos, value->n);
6126 isl_val_free(value);
6127 return set;
6128 error:
6129 isl_val_free(value);
6130 isl_set_free(set);
6131 return NULL;
6134 /* Force the values of the variable at position "pos" of type "type" of "set"
6135 * to be no greater than "value".
6137 __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6138 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6140 if (!value)
6141 goto error;
6142 if (!isl_val_is_int(value))
6143 isl_die(isl_set_get_ctx(set), isl_error_invalid,
6144 "expecting integer value", goto error);
6145 set = isl_set_upper_bound(set, type, pos, value->n);
6146 isl_val_free(value);
6147 return set;
6148 error:
6149 isl_val_free(value);
6150 isl_set_free(set);
6151 return NULL;
6154 struct isl_map *isl_map_reverse(struct isl_map *map)
6156 int i;
6158 map = isl_map_cow(map);
6159 if (!map)
6160 return NULL;
6162 map->dim = isl_space_reverse(map->dim);
6163 if (!map->dim)
6164 goto error;
6165 for (i = 0; i < map->n; ++i) {
6166 map->p[i] = isl_basic_map_reverse(map->p[i]);
6167 if (!map->p[i])
6168 goto error;
6170 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
6171 return map;
6172 error:
6173 isl_map_free(map);
6174 return NULL;
6177 #undef TYPE
6178 #define TYPE isl_pw_multi_aff
6179 #undef SUFFIX
6180 #define SUFFIX _pw_multi_aff
6181 #undef EMPTY
6182 #define EMPTY isl_pw_multi_aff_empty
6183 #undef ADD
6184 #define ADD isl_pw_multi_aff_union_add
6185 #include "isl_map_lexopt_templ.c"
6187 /* Given a map "map", compute the lexicographically minimal
6188 * (or maximal) image element for each domain element in dom,
6189 * in the form of an isl_pw_multi_aff.
6190 * If "empty" is not NULL, then set *empty to those elements in dom that
6191 * do not have an image element.
6192 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6193 * should be computed over the domain of "map". "empty" is also NULL
6194 * in this case.
6196 * We first compute the lexicographically minimal or maximal element
6197 * in the first basic map. This results in a partial solution "res"
6198 * and a subset "todo" of dom that still need to be handled.
6199 * We then consider each of the remaining maps in "map" and successively
6200 * update both "res" and "todo".
6201 * If "empty" is NULL, then the todo sets are not needed and therefore
6202 * also not computed.
6204 static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
6205 __isl_take isl_map *map, __isl_take isl_set *dom,
6206 __isl_give isl_set **empty, unsigned flags)
6208 int i;
6209 int full;
6210 isl_pw_multi_aff *res;
6211 isl_set *todo;
6213 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6214 if (!map || (!full && !dom))
6215 goto error;
6217 if (isl_map_plain_is_empty(map)) {
6218 if (empty)
6219 *empty = dom;
6220 else
6221 isl_set_free(dom);
6222 return isl_pw_multi_aff_from_map(map);
6225 res = basic_map_partial_lexopt_pw_multi_aff(
6226 isl_basic_map_copy(map->p[0]),
6227 isl_set_copy(dom), empty, flags);
6229 if (empty)
6230 todo = *empty;
6231 for (i = 1; i < map->n; ++i) {
6232 isl_pw_multi_aff *res_i;
6234 res_i = basic_map_partial_lexopt_pw_multi_aff(
6235 isl_basic_map_copy(map->p[i]),
6236 isl_set_copy(dom), empty, flags);
6238 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
6239 res = isl_pw_multi_aff_union_lexmax(res, res_i);
6240 else
6241 res = isl_pw_multi_aff_union_lexmin(res, res_i);
6243 if (empty)
6244 todo = isl_set_intersect(todo, *empty);
6247 isl_set_free(dom);
6248 isl_map_free(map);
6250 if (empty)
6251 *empty = todo;
6253 return res;
6254 error:
6255 if (empty)
6256 *empty = NULL;
6257 isl_set_free(dom);
6258 isl_map_free(map);
6259 return NULL;
6262 #undef TYPE
6263 #define TYPE isl_map
6264 #undef SUFFIX
6265 #define SUFFIX
6266 #undef EMPTY
6267 #define EMPTY isl_map_empty
6268 #undef ADD
6269 #define ADD isl_map_union_disjoint
6270 #include "isl_map_lexopt_templ.c"
6272 /* Given a map "map", compute the lexicographically minimal
6273 * (or maximal) image element for each domain element in "dom",
6274 * in the form of an isl_map.
6275 * If "empty" is not NULL, then set *empty to those elements in "dom" that
6276 * do not have an image element.
6277 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
6278 * should be computed over the domain of "map". "empty" is also NULL
6279 * in this case.
6281 * If the input consists of more than one disjunct, then first
6282 * compute the desired result in the form of an isl_pw_multi_aff and
6283 * then convert that into an isl_map.
6285 * This function used to have an explicit implementation in terms
6286 * of isl_maps, but it would continually intersect the domains of
6287 * partial results with the complement of the domain of the next
6288 * partial solution, potentially leading to an explosion in the number
6289 * of disjuncts if there are several disjuncts in the input.
6290 * An even earlier implementation of this function would look for
6291 * better results in the domain of the partial result and for extra
6292 * results in the complement of this domain, which would lead to
6293 * even more splintering.
6295 static __isl_give isl_map *isl_map_partial_lexopt_aligned(
6296 __isl_take isl_map *map, __isl_take isl_set *dom,
6297 __isl_give isl_set **empty, unsigned flags)
6299 int full;
6300 struct isl_map *res;
6301 isl_pw_multi_aff *pma;
6303 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
6304 if (!map || (!full && !dom))
6305 goto error;
6307 if (isl_map_plain_is_empty(map)) {
6308 if (empty)
6309 *empty = dom;
6310 else
6311 isl_set_free(dom);
6312 return map;
6315 if (map->n == 1) {
6316 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
6317 dom, empty, flags);
6318 isl_map_free(map);
6319 return res;
6322 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
6323 flags);
6324 return isl_map_from_pw_multi_aff(pma);
6325 error:
6326 if (empty)
6327 *empty = NULL;
6328 isl_set_free(dom);
6329 isl_map_free(map);
6330 return NULL;
6333 __isl_give isl_map *isl_map_partial_lexmax(
6334 __isl_take isl_map *map, __isl_take isl_set *dom,
6335 __isl_give isl_set **empty)
6337 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
6340 __isl_give isl_map *isl_map_partial_lexmin(
6341 __isl_take isl_map *map, __isl_take isl_set *dom,
6342 __isl_give isl_set **empty)
6344 return isl_map_partial_lexopt(map, dom, empty, 0);
6347 __isl_give isl_set *isl_set_partial_lexmin(
6348 __isl_take isl_set *set, __isl_take isl_set *dom,
6349 __isl_give isl_set **empty)
6351 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
6352 dom, empty));
6355 __isl_give isl_set *isl_set_partial_lexmax(
6356 __isl_take isl_set *set, __isl_take isl_set *dom,
6357 __isl_give isl_set **empty)
6359 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
6360 dom, empty));
6363 /* Compute the lexicographic minimum (or maximum if "flags" includes
6364 * ISL_OPT_MAX) of "bset" over its parametric domain.
6366 __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
6367 unsigned flags)
6369 return isl_basic_map_lexopt(bset, flags);
6372 __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
6374 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
6377 __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
6379 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
6382 __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
6384 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
6387 /* Compute the lexicographic minimum of "bset" over its parametric domain
6388 * for the purpose of quantifier elimination.
6389 * That is, find an explicit representation for all the existentially
6390 * quantified variables in "bset" by computing their lexicographic
6391 * minimum.
6393 static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
6394 __isl_take isl_basic_set *bset)
6396 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
6399 /* Extract the first and only affine expression from list
6400 * and then add it to *pwaff with the given dom.
6401 * This domain is known to be disjoint from other domains
6402 * because of the way isl_basic_map_foreach_lexmax works.
6404 static isl_stat update_dim_opt(__isl_take isl_basic_set *dom,
6405 __isl_take isl_aff_list *list, void *user)
6407 isl_ctx *ctx = isl_basic_set_get_ctx(dom);
6408 isl_aff *aff;
6409 isl_pw_aff **pwaff = user;
6410 isl_pw_aff *pwaff_i;
6412 if (!list)
6413 goto error;
6414 if (isl_aff_list_n_aff(list) != 1)
6415 isl_die(ctx, isl_error_internal,
6416 "expecting single element list", goto error);
6418 aff = isl_aff_list_get_aff(list, 0);
6419 pwaff_i = isl_pw_aff_alloc(isl_set_from_basic_set(dom), aff);
6421 *pwaff = isl_pw_aff_add_disjoint(*pwaff, pwaff_i);
6423 isl_aff_list_free(list);
6425 return isl_stat_ok;
6426 error:
6427 isl_basic_set_free(dom);
6428 isl_aff_list_free(list);
6429 return isl_stat_error;
6432 /* Given a basic map with one output dimension, compute the minimum or
6433 * maximum of that dimension as an isl_pw_aff.
6435 * The isl_pw_aff is constructed by having isl_basic_map_foreach_lexopt
6436 * call update_dim_opt on each leaf of the result.
6438 static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
6439 int max)
6441 isl_space *dim = isl_basic_map_get_space(bmap);
6442 isl_pw_aff *pwaff;
6443 isl_stat r;
6445 dim = isl_space_from_domain(isl_space_domain(dim));
6446 dim = isl_space_add_dims(dim, isl_dim_out, 1);
6447 pwaff = isl_pw_aff_empty(dim);
6449 r = isl_basic_map_foreach_lexopt(bmap, max, &update_dim_opt, &pwaff);
6450 if (r < 0)
6451 return isl_pw_aff_free(pwaff);
6453 return pwaff;
6456 /* Compute the minimum or maximum of the given output dimension
6457 * as a function of the parameters and the input dimensions,
6458 * but independently of the other output dimensions.
6460 * We first project out the other output dimension and then compute
6461 * the "lexicographic" maximum in each basic map, combining the results
6462 * using isl_pw_aff_union_max.
6464 static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
6465 int max)
6467 int i;
6468 isl_pw_aff *pwaff;
6469 unsigned n_out;
6471 n_out = isl_map_dim(map, isl_dim_out);
6472 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
6473 map = isl_map_project_out(map, isl_dim_out, 0, pos);
6474 if (!map)
6475 return NULL;
6477 if (map->n == 0) {
6478 isl_space *dim = isl_map_get_space(map);
6479 isl_map_free(map);
6480 return isl_pw_aff_empty(dim);
6483 pwaff = basic_map_dim_opt(map->p[0], max);
6484 for (i = 1; i < map->n; ++i) {
6485 isl_pw_aff *pwaff_i;
6487 pwaff_i = basic_map_dim_opt(map->p[i], max);
6488 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
6491 isl_map_free(map);
6493 return pwaff;
6496 /* Compute the minimum of the given output dimension as a function of the
6497 * parameters and input dimensions, but independently of
6498 * the other output dimensions.
6500 __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
6502 return map_dim_opt(map, pos, 0);
6505 /* Compute the maximum of the given output dimension as a function of the
6506 * parameters and input dimensions, but independently of
6507 * the other output dimensions.
6509 __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
6511 return map_dim_opt(map, pos, 1);
6514 /* Compute the minimum or maximum of the given set dimension
6515 * as a function of the parameters,
6516 * but independently of the other set dimensions.
6518 static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
6519 int max)
6521 return map_dim_opt(set, pos, max);
6524 /* Compute the maximum of the given set dimension as a function of the
6525 * parameters, but independently of the other set dimensions.
6527 __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
6529 return set_dim_opt(set, pos, 1);
6532 /* Compute the minimum of the given set dimension as a function of the
6533 * parameters, but independently of the other set dimensions.
6535 __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
6537 return set_dim_opt(set, pos, 0);
6540 /* Apply a preimage specified by "mat" on the parameters of "bset".
6541 * bset is assumed to have only parameters and divs.
6543 static struct isl_basic_set *basic_set_parameter_preimage(
6544 struct isl_basic_set *bset, struct isl_mat *mat)
6546 unsigned nparam;
6548 if (!bset || !mat)
6549 goto error;
6551 bset->dim = isl_space_cow(bset->dim);
6552 if (!bset->dim)
6553 goto error;
6555 nparam = isl_basic_set_dim(bset, isl_dim_param);
6557 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
6559 bset->dim->nparam = 0;
6560 bset->dim->n_out = nparam;
6561 bset = isl_basic_set_preimage(bset, mat);
6562 if (bset) {
6563 bset->dim->nparam = bset->dim->n_out;
6564 bset->dim->n_out = 0;
6566 return bset;
6567 error:
6568 isl_mat_free(mat);
6569 isl_basic_set_free(bset);
6570 return NULL;
6573 /* Apply a preimage specified by "mat" on the parameters of "set".
6574 * set is assumed to have only parameters and divs.
6576 static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
6577 __isl_take isl_mat *mat)
6579 isl_space *space;
6580 unsigned nparam;
6582 if (!set || !mat)
6583 goto error;
6585 nparam = isl_set_dim(set, isl_dim_param);
6587 if (mat->n_row != 1 + nparam)
6588 isl_die(isl_set_get_ctx(set), isl_error_internal,
6589 "unexpected number of rows", goto error);
6591 space = isl_set_get_space(set);
6592 space = isl_space_move_dims(space, isl_dim_set, 0,
6593 isl_dim_param, 0, nparam);
6594 set = isl_set_reset_space(set, space);
6595 set = isl_set_preimage(set, mat);
6596 nparam = isl_set_dim(set, isl_dim_out);
6597 space = isl_set_get_space(set);
6598 space = isl_space_move_dims(space, isl_dim_param, 0,
6599 isl_dim_out, 0, nparam);
6600 set = isl_set_reset_space(set, space);
6601 return set;
6602 error:
6603 isl_mat_free(mat);
6604 isl_set_free(set);
6605 return NULL;
6608 /* Intersect the basic set "bset" with the affine space specified by the
6609 * equalities in "eq".
6611 static struct isl_basic_set *basic_set_append_equalities(
6612 struct isl_basic_set *bset, struct isl_mat *eq)
6614 int i, k;
6615 unsigned len;
6617 if (!bset || !eq)
6618 goto error;
6620 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
6621 eq->n_row, 0);
6622 if (!bset)
6623 goto error;
6625 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
6626 for (i = 0; i < eq->n_row; ++i) {
6627 k = isl_basic_set_alloc_equality(bset);
6628 if (k < 0)
6629 goto error;
6630 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
6631 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
6633 isl_mat_free(eq);
6635 bset = isl_basic_set_gauss(bset, NULL);
6636 bset = isl_basic_set_finalize(bset);
6638 return bset;
6639 error:
6640 isl_mat_free(eq);
6641 isl_basic_set_free(bset);
6642 return NULL;
6645 /* Intersect the set "set" with the affine space specified by the
6646 * equalities in "eq".
6648 static struct isl_set *set_append_equalities(struct isl_set *set,
6649 struct isl_mat *eq)
6651 int i;
6653 if (!set || !eq)
6654 goto error;
6656 for (i = 0; i < set->n; ++i) {
6657 set->p[i] = basic_set_append_equalities(set->p[i],
6658 isl_mat_copy(eq));
6659 if (!set->p[i])
6660 goto error;
6662 isl_mat_free(eq);
6663 return set;
6664 error:
6665 isl_mat_free(eq);
6666 isl_set_free(set);
6667 return NULL;
6670 /* Given a basic set "bset" that only involves parameters and existentially
6671 * quantified variables, return the index of the first equality
6672 * that only involves parameters. If there is no such equality then
6673 * return bset->n_eq.
6675 * This function assumes that isl_basic_set_gauss has been called on "bset".
6677 static int first_parameter_equality(__isl_keep isl_basic_set *bset)
6679 int i, j;
6680 unsigned nparam, n_div;
6682 if (!bset)
6683 return -1;
6685 nparam = isl_basic_set_dim(bset, isl_dim_param);
6686 n_div = isl_basic_set_dim(bset, isl_dim_div);
6688 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
6689 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
6690 ++i;
6693 return i;
6696 /* Compute an explicit representation for the existentially quantified
6697 * variables in "bset" by computing the "minimal value" of the set
6698 * variables. Since there are no set variables, the computation of
6699 * the minimal value essentially computes an explicit representation
6700 * of the non-empty part(s) of "bset".
6702 * The input only involves parameters and existentially quantified variables.
6703 * All equalities among parameters have been removed.
6705 * Since the existentially quantified variables in the result are in general
6706 * going to be different from those in the input, we first replace
6707 * them by the minimal number of variables based on their equalities.
6708 * This should simplify the parametric integer programming.
6710 static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
6712 isl_morph *morph1, *morph2;
6713 isl_set *set;
6714 unsigned n;
6716 if (!bset)
6717 return NULL;
6718 if (bset->n_eq == 0)
6719 return isl_basic_set_lexmin_compute_divs(bset);
6721 morph1 = isl_basic_set_parameter_compression(bset);
6722 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
6723 bset = isl_basic_set_lift(bset);
6724 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
6725 bset = isl_morph_basic_set(morph2, bset);
6726 n = isl_basic_set_dim(bset, isl_dim_set);
6727 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
6729 set = isl_basic_set_lexmin_compute_divs(bset);
6731 set = isl_morph_set(isl_morph_inverse(morph1), set);
6733 return set;
6736 /* Project the given basic set onto its parameter domain, possibly introducing
6737 * new, explicit, existential variables in the constraints.
6738 * The input has parameters and (possibly implicit) existential variables.
6739 * The output has the same parameters, but only
6740 * explicit existentially quantified variables.
6742 * The actual projection is performed by pip, but pip doesn't seem
6743 * to like equalities very much, so we first remove the equalities
6744 * among the parameters by performing a variable compression on
6745 * the parameters. Afterward, an inverse transformation is performed
6746 * and the equalities among the parameters are inserted back in.
6748 * The variable compression on the parameters may uncover additional
6749 * equalities that were only implicit before. We therefore check
6750 * if there are any new parameter equalities in the result and
6751 * if so recurse. The removal of parameter equalities is required
6752 * for the parameter compression performed by base_compute_divs.
6754 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
6756 int i;
6757 struct isl_mat *eq;
6758 struct isl_mat *T, *T2;
6759 struct isl_set *set;
6760 unsigned nparam;
6762 bset = isl_basic_set_cow(bset);
6763 if (!bset)
6764 return NULL;
6766 if (bset->n_eq == 0)
6767 return base_compute_divs(bset);
6769 bset = isl_basic_set_gauss(bset, NULL);
6770 if (!bset)
6771 return NULL;
6772 if (isl_basic_set_plain_is_empty(bset))
6773 return isl_set_from_basic_set(bset);
6775 i = first_parameter_equality(bset);
6776 if (i == bset->n_eq)
6777 return base_compute_divs(bset);
6779 nparam = isl_basic_set_dim(bset, isl_dim_param);
6780 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
6781 0, 1 + nparam);
6782 eq = isl_mat_cow(eq);
6783 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
6784 if (T && T->n_col == 0) {
6785 isl_mat_free(T);
6786 isl_mat_free(T2);
6787 isl_mat_free(eq);
6788 bset = isl_basic_set_set_to_empty(bset);
6789 return isl_set_from_basic_set(bset);
6791 bset = basic_set_parameter_preimage(bset, T);
6793 i = first_parameter_equality(bset);
6794 if (!bset)
6795 set = NULL;
6796 else if (i == bset->n_eq)
6797 set = base_compute_divs(bset);
6798 else
6799 set = parameter_compute_divs(bset);
6800 set = set_parameter_preimage(set, T2);
6801 set = set_append_equalities(set, eq);
6802 return set;
6805 /* Insert the divs from "ls" before those of "bmap".
6807 * The number of columns is not changed, which means that the last
6808 * dimensions of "bmap" are being reintepreted as the divs from "ls".
6809 * The caller is responsible for removing the same number of dimensions
6810 * from the space of "bmap".
6812 static __isl_give isl_basic_map *insert_divs_from_local_space(
6813 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
6815 int i;
6816 int n_div;
6817 int old_n_div;
6819 n_div = isl_local_space_dim(ls, isl_dim_div);
6820 if (n_div == 0)
6821 return bmap;
6823 old_n_div = bmap->n_div;
6824 bmap = insert_div_rows(bmap, n_div);
6825 if (!bmap)
6826 return NULL;
6828 for (i = 0; i < n_div; ++i) {
6829 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
6830 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
6833 return bmap;
6836 /* Replace the space of "bmap" by the space and divs of "ls".
6838 * If "ls" has any divs, then we simplify the result since we may
6839 * have discovered some additional equalities that could simplify
6840 * the div expressions.
6842 static __isl_give isl_basic_map *basic_replace_space_by_local_space(
6843 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
6845 int n_div;
6847 bmap = isl_basic_map_cow(bmap);
6848 if (!bmap || !ls)
6849 goto error;
6851 n_div = isl_local_space_dim(ls, isl_dim_div);
6852 bmap = insert_divs_from_local_space(bmap, ls);
6853 if (!bmap)
6854 goto error;
6856 isl_space_free(bmap->dim);
6857 bmap->dim = isl_local_space_get_space(ls);
6858 if (!bmap->dim)
6859 goto error;
6861 isl_local_space_free(ls);
6862 if (n_div > 0)
6863 bmap = isl_basic_map_simplify(bmap);
6864 bmap = isl_basic_map_finalize(bmap);
6865 return bmap;
6866 error:
6867 isl_basic_map_free(bmap);
6868 isl_local_space_free(ls);
6869 return NULL;
6872 /* Replace the space of "map" by the space and divs of "ls".
6874 static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
6875 __isl_take isl_local_space *ls)
6877 int i;
6879 map = isl_map_cow(map);
6880 if (!map || !ls)
6881 goto error;
6883 for (i = 0; i < map->n; ++i) {
6884 map->p[i] = basic_replace_space_by_local_space(map->p[i],
6885 isl_local_space_copy(ls));
6886 if (!map->p[i])
6887 goto error;
6889 isl_space_free(map->dim);
6890 map->dim = isl_local_space_get_space(ls);
6891 if (!map->dim)
6892 goto error;
6894 isl_local_space_free(ls);
6895 return map;
6896 error:
6897 isl_local_space_free(ls);
6898 isl_map_free(map);
6899 return NULL;
6902 /* Compute an explicit representation for the existentially
6903 * quantified variables for which do not know any explicit representation yet.
6905 * We first sort the existentially quantified variables so that the
6906 * existentially quantified variables for which we already have an explicit
6907 * representation are placed before those for which we do not.
6908 * The input dimensions, the output dimensions and the existentially
6909 * quantified variables for which we already have an explicit
6910 * representation are then turned into parameters.
6911 * compute_divs returns a map with the same parameters and
6912 * no input or output dimensions and the dimension specification
6913 * is reset to that of the input, including the existentially quantified
6914 * variables for which we already had an explicit representation.
6916 static struct isl_map *compute_divs(struct isl_basic_map *bmap)
6918 struct isl_basic_set *bset;
6919 struct isl_set *set;
6920 struct isl_map *map;
6921 isl_space *dim;
6922 isl_local_space *ls;
6923 unsigned nparam;
6924 unsigned n_in;
6925 unsigned n_out;
6926 int n_known;
6927 int i;
6929 bmap = isl_basic_map_sort_divs(bmap);
6930 bmap = isl_basic_map_cow(bmap);
6931 if (!bmap)
6932 return NULL;
6934 n_known = isl_basic_map_first_unknown_div(bmap);
6935 if (n_known < 0)
6936 return isl_map_from_basic_map(isl_basic_map_free(bmap));
6938 nparam = isl_basic_map_dim(bmap, isl_dim_param);
6939 n_in = isl_basic_map_dim(bmap, isl_dim_in);
6940 n_out = isl_basic_map_dim(bmap, isl_dim_out);
6941 dim = isl_space_set_alloc(bmap->ctx,
6942 nparam + n_in + n_out + n_known, 0);
6943 if (!dim)
6944 goto error;
6946 ls = isl_basic_map_get_local_space(bmap);
6947 ls = isl_local_space_drop_dims(ls, isl_dim_div,
6948 n_known, bmap->n_div - n_known);
6949 if (n_known > 0) {
6950 for (i = n_known; i < bmap->n_div; ++i)
6951 swap_div(bmap, i - n_known, i);
6952 bmap->n_div -= n_known;
6953 bmap->extra -= n_known;
6955 bmap = isl_basic_map_reset_space(bmap, dim);
6956 bset = bset_from_bmap(bmap);
6958 set = parameter_compute_divs(bset);
6959 map = set_to_map(set);
6960 map = replace_space_by_local_space(map, ls);
6962 return map;
6963 error:
6964 isl_basic_map_free(bmap);
6965 return NULL;
6968 /* Remove the explicit representation of local variable "div",
6969 * if there is any.
6971 __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
6972 __isl_take isl_basic_map *bmap, int div)
6974 isl_bool unknown;
6976 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
6977 if (unknown < 0)
6978 return isl_basic_map_free(bmap);
6979 if (unknown)
6980 return bmap;
6982 bmap = isl_basic_map_cow(bmap);
6983 if (!bmap)
6984 return NULL;
6985 isl_int_set_si(bmap->div[div][0], 0);
6986 return bmap;
6989 /* Is local variable "div" of "bmap" marked as not having an explicit
6990 * representation?
6991 * Note that even if "div" is not marked in this way and therefore
6992 * has an explicit representation, this representation may still
6993 * depend (indirectly) on other local variables that do not
6994 * have an explicit representation.
6996 isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
6997 int div)
6999 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7000 return isl_bool_error;
7001 return isl_int_is_zero(bmap->div[div][0]);
7004 /* Return the position of the first local variable that does not
7005 * have an explicit representation.
7006 * Return the total number of local variables if they all have
7007 * an explicit representation.
7008 * Return -1 on error.
7010 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7012 int i;
7014 if (!bmap)
7015 return -1;
7017 for (i = 0; i < bmap->n_div; ++i) {
7018 if (!isl_basic_map_div_is_known(bmap, i))
7019 return i;
7021 return bmap->n_div;
7024 /* Return the position of the first local variable that does not
7025 * have an explicit representation.
7026 * Return the total number of local variables if they all have
7027 * an explicit representation.
7028 * Return -1 on error.
7030 int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7032 return isl_basic_map_first_unknown_div(bset);
7035 /* Does "bmap" have an explicit representation for all local variables?
7037 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7039 int first, n;
7041 n = isl_basic_map_dim(bmap, isl_dim_div);
7042 first = isl_basic_map_first_unknown_div(bmap);
7043 if (first < 0)
7044 return isl_bool_error;
7045 return first == n;
7048 /* Do all basic maps in "map" have an explicit representation
7049 * for all local variables?
7051 isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7053 int i;
7055 if (!map)
7056 return isl_bool_error;
7058 for (i = 0; i < map->n; ++i) {
7059 int known = isl_basic_map_divs_known(map->p[i]);
7060 if (known <= 0)
7061 return known;
7064 return isl_bool_true;
7067 /* If bmap contains any unknown divs, then compute explicit
7068 * expressions for them. However, this computation may be
7069 * quite expensive, so first try to remove divs that aren't
7070 * strictly needed.
7072 struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap)
7074 int known;
7075 struct isl_map *map;
7077 known = isl_basic_map_divs_known(bmap);
7078 if (known < 0)
7079 goto error;
7080 if (known)
7081 return isl_map_from_basic_map(bmap);
7083 bmap = isl_basic_map_drop_redundant_divs(bmap);
7085 known = isl_basic_map_divs_known(bmap);
7086 if (known < 0)
7087 goto error;
7088 if (known)
7089 return isl_map_from_basic_map(bmap);
7091 map = compute_divs(bmap);
7092 return map;
7093 error:
7094 isl_basic_map_free(bmap);
7095 return NULL;
7098 struct isl_map *isl_map_compute_divs(struct isl_map *map)
7100 int i;
7101 int known;
7102 struct isl_map *res;
7104 if (!map)
7105 return NULL;
7106 if (map->n == 0)
7107 return map;
7109 known = isl_map_divs_known(map);
7110 if (known < 0) {
7111 isl_map_free(map);
7112 return NULL;
7114 if (known)
7115 return map;
7117 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
7118 for (i = 1 ; i < map->n; ++i) {
7119 struct isl_map *r2;
7120 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
7121 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
7122 res = isl_map_union_disjoint(res, r2);
7123 else
7124 res = isl_map_union(res, r2);
7126 isl_map_free(map);
7128 return res;
7131 struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset)
7133 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
7136 struct isl_set *isl_set_compute_divs(struct isl_set *set)
7138 return set_from_map(isl_map_compute_divs(set_to_map(set)));
7141 struct isl_set *isl_map_domain(struct isl_map *map)
7143 int i;
7144 struct isl_set *set;
7146 if (!map)
7147 goto error;
7149 map = isl_map_cow(map);
7150 if (!map)
7151 return NULL;
7153 set = set_from_map(map);
7154 set->dim = isl_space_domain(set->dim);
7155 if (!set->dim)
7156 goto error;
7157 for (i = 0; i < map->n; ++i) {
7158 set->p[i] = isl_basic_map_domain(map->p[i]);
7159 if (!set->p[i])
7160 goto error;
7162 ISL_F_CLR(set, ISL_MAP_DISJOINT);
7163 ISL_F_CLR(set, ISL_SET_NORMALIZED);
7164 return set;
7165 error:
7166 isl_map_free(map);
7167 return NULL;
7170 /* Return the union of "map1" and "map2", where we assume for now that
7171 * "map1" and "map2" are disjoint. Note that the basic maps inside
7172 * "map1" or "map2" may not be disjoint from each other.
7173 * Also note that this function is also called from isl_map_union,
7174 * which takes care of handling the situation where "map1" and "map2"
7175 * may not be disjoint.
7177 * If one of the inputs is empty, we can simply return the other input.
7178 * Similarly, if one of the inputs is universal, then it is equal to the union.
7180 static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
7181 __isl_take isl_map *map2)
7183 int i;
7184 unsigned flags = 0;
7185 struct isl_map *map = NULL;
7186 int is_universe;
7188 if (!map1 || !map2)
7189 goto error;
7191 if (!isl_space_is_equal(map1->dim, map2->dim))
7192 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
7193 "spaces don't match", goto error);
7195 if (map1->n == 0) {
7196 isl_map_free(map1);
7197 return map2;
7199 if (map2->n == 0) {
7200 isl_map_free(map2);
7201 return map1;
7204 is_universe = isl_map_plain_is_universe(map1);
7205 if (is_universe < 0)
7206 goto error;
7207 if (is_universe) {
7208 isl_map_free(map2);
7209 return map1;
7212 is_universe = isl_map_plain_is_universe(map2);
7213 if (is_universe < 0)
7214 goto error;
7215 if (is_universe) {
7216 isl_map_free(map1);
7217 return map2;
7220 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
7221 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
7222 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7224 map = isl_map_alloc_space(isl_space_copy(map1->dim),
7225 map1->n + map2->n, flags);
7226 if (!map)
7227 goto error;
7228 for (i = 0; i < map1->n; ++i) {
7229 map = isl_map_add_basic_map(map,
7230 isl_basic_map_copy(map1->p[i]));
7231 if (!map)
7232 goto error;
7234 for (i = 0; i < map2->n; ++i) {
7235 map = isl_map_add_basic_map(map,
7236 isl_basic_map_copy(map2->p[i]));
7237 if (!map)
7238 goto error;
7240 isl_map_free(map1);
7241 isl_map_free(map2);
7242 return map;
7243 error:
7244 isl_map_free(map);
7245 isl_map_free(map1);
7246 isl_map_free(map2);
7247 return NULL;
7250 /* Return the union of "map1" and "map2", where "map1" and "map2" are
7251 * guaranteed to be disjoint by the caller.
7253 * Note that this functions is called from within isl_map_make_disjoint,
7254 * so we have to be careful not to touch the constraints of the inputs
7255 * in any way.
7257 __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
7258 __isl_take isl_map *map2)
7260 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
7263 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7264 * not be disjoint. The parameters are assumed to have been aligned.
7266 * We currently simply call map_union_disjoint, the internal operation
7267 * of which does not really depend on the inputs being disjoint.
7268 * If the result contains more than one basic map, then we clear
7269 * the disjoint flag since the result may contain basic maps from
7270 * both inputs and these are not guaranteed to be disjoint.
7272 * As a special case, if "map1" and "map2" are obviously equal,
7273 * then we simply return "map1".
7275 static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
7276 __isl_take isl_map *map2)
7278 int equal;
7280 if (!map1 || !map2)
7281 goto error;
7283 equal = isl_map_plain_is_equal(map1, map2);
7284 if (equal < 0)
7285 goto error;
7286 if (equal) {
7287 isl_map_free(map2);
7288 return map1;
7291 map1 = map_union_disjoint(map1, map2);
7292 if (!map1)
7293 return NULL;
7294 if (map1->n > 1)
7295 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
7296 return map1;
7297 error:
7298 isl_map_free(map1);
7299 isl_map_free(map2);
7300 return NULL;
7303 /* Return the union of "map1" and "map2", where "map1" and "map2" may
7304 * not be disjoint.
7306 __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
7307 __isl_take isl_map *map2)
7309 return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
7312 struct isl_set *isl_set_union_disjoint(
7313 struct isl_set *set1, struct isl_set *set2)
7315 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
7316 set_to_map(set2)));
7319 struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
7321 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
7324 /* Apply "fn" to pairs of elements from "map" and "set" and collect
7325 * the results.
7327 * "map" and "set" are assumed to be compatible and non-NULL.
7329 static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
7330 __isl_take isl_set *set,
7331 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
7332 __isl_take isl_basic_set *bset))
7334 unsigned flags = 0;
7335 struct isl_map *result;
7336 int i, j;
7338 if (isl_set_plain_is_universe(set)) {
7339 isl_set_free(set);
7340 return map;
7343 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
7344 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
7345 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
7347 result = isl_map_alloc_space(isl_space_copy(map->dim),
7348 map->n * set->n, flags);
7349 for (i = 0; result && i < map->n; ++i)
7350 for (j = 0; j < set->n; ++j) {
7351 result = isl_map_add_basic_map(result,
7352 fn(isl_basic_map_copy(map->p[i]),
7353 isl_basic_set_copy(set->p[j])));
7354 if (!result)
7355 break;
7358 isl_map_free(map);
7359 isl_set_free(set);
7360 return result;
7363 static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
7364 __isl_take isl_set *set)
7366 isl_bool ok;
7368 ok = isl_map_compatible_range(map, set);
7369 if (ok < 0)
7370 goto error;
7371 if (!ok)
7372 isl_die(set->ctx, isl_error_invalid,
7373 "incompatible spaces", goto error);
7375 return map_intersect_set(map, set, &isl_basic_map_intersect_range);
7376 error:
7377 isl_map_free(map);
7378 isl_set_free(set);
7379 return NULL;
7382 __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
7383 __isl_take isl_set *set)
7385 return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
7388 static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
7389 __isl_take isl_set *set)
7391 isl_bool ok;
7393 ok = isl_map_compatible_domain(map, set);
7394 if (ok < 0)
7395 goto error;
7396 if (!ok)
7397 isl_die(set->ctx, isl_error_invalid,
7398 "incompatible spaces", goto error);
7400 return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
7401 error:
7402 isl_map_free(map);
7403 isl_set_free(set);
7404 return NULL;
7407 __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
7408 __isl_take isl_set *set)
7410 return isl_map_align_params_map_map_and(map, set,
7411 &map_intersect_domain);
7414 static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
7415 __isl_take isl_map *map2)
7417 if (!map1 || !map2)
7418 goto error;
7419 map1 = isl_map_reverse(map1);
7420 map1 = isl_map_apply_range(map1, map2);
7421 return isl_map_reverse(map1);
7422 error:
7423 isl_map_free(map1);
7424 isl_map_free(map2);
7425 return NULL;
7428 __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
7429 __isl_take isl_map *map2)
7431 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
7434 static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
7435 __isl_take isl_map *map2)
7437 isl_space *dim_result;
7438 struct isl_map *result;
7439 int i, j;
7441 if (!map1 || !map2)
7442 goto error;
7444 dim_result = isl_space_join(isl_space_copy(map1->dim),
7445 isl_space_copy(map2->dim));
7447 result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
7448 if (!result)
7449 goto error;
7450 for (i = 0; i < map1->n; ++i)
7451 for (j = 0; j < map2->n; ++j) {
7452 result = isl_map_add_basic_map(result,
7453 isl_basic_map_apply_range(
7454 isl_basic_map_copy(map1->p[i]),
7455 isl_basic_map_copy(map2->p[j])));
7456 if (!result)
7457 goto error;
7459 isl_map_free(map1);
7460 isl_map_free(map2);
7461 if (result && result->n <= 1)
7462 ISL_F_SET(result, ISL_MAP_DISJOINT);
7463 return result;
7464 error:
7465 isl_map_free(map1);
7466 isl_map_free(map2);
7467 return NULL;
7470 __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
7471 __isl_take isl_map *map2)
7473 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
7477 * returns range - domain
7479 struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap)
7481 isl_space *target_space;
7482 struct isl_basic_set *bset;
7483 unsigned dim;
7484 unsigned nparam;
7485 int i;
7487 if (!bmap)
7488 goto error;
7489 isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7490 bmap->dim, isl_dim_out),
7491 goto error);
7492 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
7493 dim = isl_basic_map_n_in(bmap);
7494 nparam = isl_basic_map_n_param(bmap);
7495 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
7496 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
7497 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
7498 for (i = 0; i < dim; ++i) {
7499 int j = isl_basic_map_alloc_equality(bmap);
7500 if (j < 0) {
7501 bmap = isl_basic_map_free(bmap);
7502 break;
7504 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7505 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7506 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
7507 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
7509 bset = isl_basic_map_domain(bmap);
7510 bset = isl_basic_set_reset_space(bset, target_space);
7511 return bset;
7512 error:
7513 isl_basic_map_free(bmap);
7514 return NULL;
7518 * returns range - domain
7520 __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
7522 int i;
7523 isl_space *dim;
7524 struct isl_set *result;
7526 if (!map)
7527 return NULL;
7529 isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
7530 map->dim, isl_dim_out),
7531 goto error);
7532 dim = isl_map_get_space(map);
7533 dim = isl_space_domain(dim);
7534 result = isl_set_alloc_space(dim, map->n, 0);
7535 if (!result)
7536 goto error;
7537 for (i = 0; i < map->n; ++i)
7538 result = isl_set_add_basic_set(result,
7539 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
7540 isl_map_free(map);
7541 return result;
7542 error:
7543 isl_map_free(map);
7544 return NULL;
7548 * returns [domain -> range] -> range - domain
7550 __isl_give isl_basic_map *isl_basic_map_deltas_map(
7551 __isl_take isl_basic_map *bmap)
7553 int i, k;
7554 isl_space *dim;
7555 isl_basic_map *domain;
7556 int nparam, n;
7557 unsigned total;
7559 if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
7560 bmap->dim, isl_dim_out))
7561 isl_die(bmap->ctx, isl_error_invalid,
7562 "domain and range don't match", goto error);
7564 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7565 n = isl_basic_map_dim(bmap, isl_dim_in);
7567 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
7568 domain = isl_basic_map_universe(dim);
7570 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
7571 bmap = isl_basic_map_apply_range(bmap, domain);
7572 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
7574 total = isl_basic_map_total_dim(bmap);
7576 for (i = 0; i < n; ++i) {
7577 k = isl_basic_map_alloc_equality(bmap);
7578 if (k < 0)
7579 goto error;
7580 isl_seq_clr(bmap->eq[k], 1 + total);
7581 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
7582 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
7583 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
7586 bmap = isl_basic_map_gauss(bmap, NULL);
7587 return isl_basic_map_finalize(bmap);
7588 error:
7589 isl_basic_map_free(bmap);
7590 return NULL;
7594 * returns [domain -> range] -> range - domain
7596 __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
7598 int i;
7599 isl_space *domain_dim;
7601 if (!map)
7602 return NULL;
7604 if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
7605 map->dim, isl_dim_out))
7606 isl_die(map->ctx, isl_error_invalid,
7607 "domain and range don't match", goto error);
7609 map = isl_map_cow(map);
7610 if (!map)
7611 return NULL;
7613 domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
7614 map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
7615 map->dim = isl_space_join(map->dim, domain_dim);
7616 if (!map->dim)
7617 goto error;
7618 for (i = 0; i < map->n; ++i) {
7619 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
7620 if (!map->p[i])
7621 goto error;
7623 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
7624 return map;
7625 error:
7626 isl_map_free(map);
7627 return NULL;
7630 static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
7632 struct isl_basic_map *bmap;
7633 unsigned nparam;
7634 unsigned dim;
7635 int i;
7637 if (!dims)
7638 return NULL;
7640 nparam = dims->nparam;
7641 dim = dims->n_out;
7642 bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
7643 if (!bmap)
7644 goto error;
7646 for (i = 0; i < dim; ++i) {
7647 int j = isl_basic_map_alloc_equality(bmap);
7648 if (j < 0)
7649 goto error;
7650 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
7651 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
7652 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
7654 return isl_basic_map_finalize(bmap);
7655 error:
7656 isl_basic_map_free(bmap);
7657 return NULL;
7660 __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
7662 if (!dim)
7663 return NULL;
7664 if (dim->n_in != dim->n_out)
7665 isl_die(dim->ctx, isl_error_invalid,
7666 "number of input and output dimensions needs to be "
7667 "the same", goto error);
7668 return basic_map_identity(dim);
7669 error:
7670 isl_space_free(dim);
7671 return NULL;
7674 __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
7676 return isl_map_from_basic_map(isl_basic_map_identity(dim));
7679 __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
7681 isl_space *dim = isl_set_get_space(set);
7682 isl_map *id;
7683 id = isl_map_identity(isl_space_map_from_set(dim));
7684 return isl_map_intersect_range(id, set);
7687 /* Construct a basic set with all set dimensions having only non-negative
7688 * values.
7690 __isl_give isl_basic_set *isl_basic_set_positive_orthant(
7691 __isl_take isl_space *space)
7693 int i;
7694 unsigned nparam;
7695 unsigned dim;
7696 struct isl_basic_set *bset;
7698 if (!space)
7699 return NULL;
7700 nparam = space->nparam;
7701 dim = space->n_out;
7702 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
7703 if (!bset)
7704 return NULL;
7705 for (i = 0; i < dim; ++i) {
7706 int k = isl_basic_set_alloc_inequality(bset);
7707 if (k < 0)
7708 goto error;
7709 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
7710 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
7712 return bset;
7713 error:
7714 isl_basic_set_free(bset);
7715 return NULL;
7718 /* Construct the half-space x_pos >= 0.
7720 static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
7721 int pos)
7723 int k;
7724 isl_basic_set *nonneg;
7726 nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7727 k = isl_basic_set_alloc_inequality(nonneg);
7728 if (k < 0)
7729 goto error;
7730 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
7731 isl_int_set_si(nonneg->ineq[k][pos], 1);
7733 return isl_basic_set_finalize(nonneg);
7734 error:
7735 isl_basic_set_free(nonneg);
7736 return NULL;
7739 /* Construct the half-space x_pos <= -1.
7741 static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
7743 int k;
7744 isl_basic_set *neg;
7746 neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
7747 k = isl_basic_set_alloc_inequality(neg);
7748 if (k < 0)
7749 goto error;
7750 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
7751 isl_int_set_si(neg->ineq[k][0], -1);
7752 isl_int_set_si(neg->ineq[k][pos], -1);
7754 return isl_basic_set_finalize(neg);
7755 error:
7756 isl_basic_set_free(neg);
7757 return NULL;
7760 __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
7761 enum isl_dim_type type, unsigned first, unsigned n)
7763 int i;
7764 unsigned offset;
7765 isl_basic_set *nonneg;
7766 isl_basic_set *neg;
7768 if (!set)
7769 return NULL;
7770 if (n == 0)
7771 return set;
7773 isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
7775 offset = pos(set->dim, type);
7776 for (i = 0; i < n; ++i) {
7777 nonneg = nonneg_halfspace(isl_set_get_space(set),
7778 offset + first + i);
7779 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
7781 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
7784 return set;
7785 error:
7786 isl_set_free(set);
7787 return NULL;
7790 static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
7791 int len,
7792 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7793 void *user)
7795 isl_set *half;
7797 if (!set)
7798 return isl_stat_error;
7799 if (isl_set_plain_is_empty(set)) {
7800 isl_set_free(set);
7801 return isl_stat_ok;
7803 if (first == len)
7804 return fn(set, signs, user);
7806 signs[first] = 1;
7807 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
7808 1 + first));
7809 half = isl_set_intersect(half, isl_set_copy(set));
7810 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
7811 goto error;
7813 signs[first] = -1;
7814 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
7815 1 + first));
7816 half = isl_set_intersect(half, set);
7817 return foreach_orthant(half, signs, first + 1, len, fn, user);
7818 error:
7819 isl_set_free(set);
7820 return isl_stat_error;
7823 /* Call "fn" on the intersections of "set" with each of the orthants
7824 * (except for obviously empty intersections). The orthant is identified
7825 * by the signs array, with each entry having value 1 or -1 according
7826 * to the sign of the corresponding variable.
7828 isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
7829 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
7830 void *user)
7832 unsigned nparam;
7833 unsigned nvar;
7834 int *signs;
7835 isl_stat r;
7837 if (!set)
7838 return isl_stat_error;
7839 if (isl_set_plain_is_empty(set))
7840 return isl_stat_ok;
7842 nparam = isl_set_dim(set, isl_dim_param);
7843 nvar = isl_set_dim(set, isl_dim_set);
7845 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
7847 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
7848 fn, user);
7850 free(signs);
7852 return r;
7855 isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
7857 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
7860 isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
7861 __isl_keep isl_basic_map *bmap2)
7863 int is_subset;
7864 struct isl_map *map1;
7865 struct isl_map *map2;
7867 if (!bmap1 || !bmap2)
7868 return isl_bool_error;
7870 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
7871 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
7873 is_subset = isl_map_is_subset(map1, map2);
7875 isl_map_free(map1);
7876 isl_map_free(map2);
7878 return is_subset;
7881 isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
7882 __isl_keep isl_basic_set *bset2)
7884 return isl_basic_map_is_subset(bset1, bset2);
7887 isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
7888 __isl_keep isl_basic_map *bmap2)
7890 isl_bool is_subset;
7892 if (!bmap1 || !bmap2)
7893 return isl_bool_error;
7894 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
7895 if (is_subset != isl_bool_true)
7896 return is_subset;
7897 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
7898 return is_subset;
7901 isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
7902 __isl_keep isl_basic_set *bset2)
7904 return isl_basic_map_is_equal(
7905 bset_to_bmap(bset1), bset_to_bmap(bset2));
7908 isl_bool isl_map_is_empty(__isl_keep isl_map *map)
7910 int i;
7911 int is_empty;
7913 if (!map)
7914 return isl_bool_error;
7915 for (i = 0; i < map->n; ++i) {
7916 is_empty = isl_basic_map_is_empty(map->p[i]);
7917 if (is_empty < 0)
7918 return isl_bool_error;
7919 if (!is_empty)
7920 return isl_bool_false;
7922 return isl_bool_true;
7925 isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
7927 return map ? map->n == 0 : isl_bool_error;
7930 isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
7932 return set ? set->n == 0 : isl_bool_error;
7935 isl_bool isl_set_is_empty(__isl_keep isl_set *set)
7937 return isl_map_is_empty(set_to_map(set));
7940 isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
7941 __isl_keep isl_map *map2)
7943 if (!map1 || !map2)
7944 return isl_bool_error;
7946 return isl_space_is_equal(map1->dim, map2->dim);
7949 isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
7950 __isl_keep isl_set *set2)
7952 if (!set1 || !set2)
7953 return isl_bool_error;
7955 return isl_space_is_equal(set1->dim, set2->dim);
7958 static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7960 isl_bool is_subset;
7962 if (!map1 || !map2)
7963 return isl_bool_error;
7964 is_subset = isl_map_is_subset(map1, map2);
7965 if (is_subset != isl_bool_true)
7966 return is_subset;
7967 is_subset = isl_map_is_subset(map2, map1);
7968 return is_subset;
7971 /* Is "map1" equal to "map2"?
7973 * First check if they are obviously equal.
7974 * If not, then perform a more detailed analysis.
7976 isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
7978 isl_bool equal;
7980 equal = isl_map_plain_is_equal(map1, map2);
7981 if (equal < 0 || equal)
7982 return equal;
7983 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
7986 isl_bool isl_basic_map_is_strict_subset(
7987 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
7989 isl_bool is_subset;
7991 if (!bmap1 || !bmap2)
7992 return isl_bool_error;
7993 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
7994 if (is_subset != isl_bool_true)
7995 return is_subset;
7996 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
7997 if (is_subset == isl_bool_error)
7998 return is_subset;
7999 return !is_subset;
8002 isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
8003 __isl_keep isl_map *map2)
8005 isl_bool is_subset;
8007 if (!map1 || !map2)
8008 return isl_bool_error;
8009 is_subset = isl_map_is_subset(map1, map2);
8010 if (is_subset != isl_bool_true)
8011 return is_subset;
8012 is_subset = isl_map_is_subset(map2, map1);
8013 if (is_subset == isl_bool_error)
8014 return is_subset;
8015 return !is_subset;
8018 isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
8019 __isl_keep isl_set *set2)
8021 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
8024 /* Is "bmap" obviously equal to the universe with the same space?
8026 * That is, does it not have any constraints?
8028 isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
8030 if (!bmap)
8031 return isl_bool_error;
8032 return bmap->n_eq == 0 && bmap->n_ineq == 0;
8035 /* Is "bset" obviously equal to the universe with the same space?
8037 isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
8039 return isl_basic_map_plain_is_universe(bset);
8042 /* If "c" does not involve any existentially quantified variables,
8043 * then set *univ to false and abort
8045 static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
8047 isl_bool *univ = user;
8048 unsigned n;
8050 n = isl_constraint_dim(c, isl_dim_div);
8051 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
8052 isl_constraint_free(c);
8053 if (*univ < 0 || !*univ)
8054 return isl_stat_error;
8055 return isl_stat_ok;
8058 /* Is "bmap" equal to the universe with the same space?
8060 * First check if it is obviously equal to the universe.
8061 * If not and if there are any constraints not involving
8062 * existentially quantified variables, then it is certainly
8063 * not equal to the universe.
8064 * Otherwise, check if the universe is a subset of "bmap".
8066 isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
8068 isl_bool univ;
8069 isl_basic_map *test;
8071 univ = isl_basic_map_plain_is_universe(bmap);
8072 if (univ < 0 || univ)
8073 return univ;
8074 if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
8075 return isl_bool_false;
8076 univ = isl_bool_true;
8077 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
8078 univ)
8079 return isl_bool_error;
8080 if (univ < 0 || !univ)
8081 return univ;
8082 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
8083 univ = isl_basic_map_is_subset(test, bmap);
8084 isl_basic_map_free(test);
8085 return univ;
8088 /* Is "bset" equal to the universe with the same space?
8090 isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
8092 return isl_basic_map_is_universe(bset);
8095 isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
8097 int i;
8099 if (!map)
8100 return isl_bool_error;
8102 for (i = 0; i < map->n; ++i) {
8103 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
8104 if (r < 0 || r)
8105 return r;
8108 return isl_bool_false;
8111 isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
8113 return isl_map_plain_is_universe(set_to_map(set));
8116 isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
8118 struct isl_basic_set *bset = NULL;
8119 struct isl_vec *sample = NULL;
8120 isl_bool empty, non_empty;
8122 if (!bmap)
8123 return isl_bool_error;
8125 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
8126 return isl_bool_true;
8128 if (isl_basic_map_plain_is_universe(bmap))
8129 return isl_bool_false;
8131 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
8132 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
8133 copy = isl_basic_map_remove_redundancies(copy);
8134 empty = isl_basic_map_plain_is_empty(copy);
8135 isl_basic_map_free(copy);
8136 return empty;
8139 non_empty = isl_basic_map_plain_is_non_empty(bmap);
8140 if (non_empty < 0)
8141 return isl_bool_error;
8142 if (non_empty)
8143 return isl_bool_false;
8144 isl_vec_free(bmap->sample);
8145 bmap->sample = NULL;
8146 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
8147 if (!bset)
8148 return isl_bool_error;
8149 sample = isl_basic_set_sample_vec(bset);
8150 if (!sample)
8151 return isl_bool_error;
8152 empty = sample->size == 0;
8153 isl_vec_free(bmap->sample);
8154 bmap->sample = sample;
8155 if (empty)
8156 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
8158 return empty;
8161 isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
8163 if (!bmap)
8164 return isl_bool_error;
8165 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
8168 isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
8170 if (!bset)
8171 return isl_bool_error;
8172 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
8175 /* Is "bmap" known to be non-empty?
8177 * That is, is the cached sample still valid?
8179 isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
8181 unsigned total;
8183 if (!bmap)
8184 return isl_bool_error;
8185 if (!bmap->sample)
8186 return isl_bool_false;
8187 total = 1 + isl_basic_map_total_dim(bmap);
8188 if (bmap->sample->size != total)
8189 return isl_bool_false;
8190 return isl_basic_map_contains(bmap, bmap->sample);
8193 isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
8195 return isl_basic_map_is_empty(bset_to_bmap(bset));
8198 struct isl_map *isl_basic_map_union(
8199 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
8201 struct isl_map *map;
8202 if (!bmap1 || !bmap2)
8203 goto error;
8205 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
8207 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
8208 if (!map)
8209 goto error;
8210 map = isl_map_add_basic_map(map, bmap1);
8211 map = isl_map_add_basic_map(map, bmap2);
8212 return map;
8213 error:
8214 isl_basic_map_free(bmap1);
8215 isl_basic_map_free(bmap2);
8216 return NULL;
8219 struct isl_set *isl_basic_set_union(
8220 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
8222 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
8223 bset_to_bmap(bset2)));
8226 /* Order divs such that any div only depends on previous divs */
8227 struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap)
8229 int i;
8230 unsigned off;
8232 if (!bmap)
8233 return NULL;
8235 off = isl_space_dim(bmap->dim, isl_dim_all);
8237 for (i = 0; i < bmap->n_div; ++i) {
8238 int pos;
8239 if (isl_int_is_zero(bmap->div[i][0]))
8240 continue;
8241 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
8242 bmap->n_div-i);
8243 if (pos == -1)
8244 continue;
8245 if (pos == 0)
8246 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
8247 "integer division depends on itself",
8248 return isl_basic_map_free(bmap));
8249 isl_basic_map_swap_div(bmap, i, i + pos);
8250 --i;
8252 return bmap;
8255 struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
8257 return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
8260 __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
8262 int i;
8264 if (!map)
8265 return 0;
8267 for (i = 0; i < map->n; ++i) {
8268 map->p[i] = isl_basic_map_order_divs(map->p[i]);
8269 if (!map->p[i])
8270 goto error;
8273 return map;
8274 error:
8275 isl_map_free(map);
8276 return NULL;
8279 /* Sort the local variables of "bset".
8281 __isl_give isl_basic_set *isl_basic_set_sort_divs(
8282 __isl_take isl_basic_set *bset)
8284 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
8287 /* Apply the expansion computed by isl_merge_divs.
8288 * The expansion itself is given by "exp" while the resulting
8289 * list of divs is given by "div".
8291 * Move the integer divisions of "bmap" into the right position
8292 * according to "exp" and then introduce the additional integer
8293 * divisions, adding div constraints.
8294 * The moving should be done first to avoid moving coefficients
8295 * in the definitions of the extra integer divisions.
8297 __isl_give isl_basic_map *isl_basic_map_expand_divs(
8298 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
8300 int i, j;
8301 int n_div;
8303 bmap = isl_basic_map_cow(bmap);
8304 if (!bmap || !div)
8305 goto error;
8307 if (div->n_row < bmap->n_div)
8308 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
8309 "not an expansion", goto error);
8311 n_div = bmap->n_div;
8312 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
8313 div->n_row - n_div, 0,
8314 2 * (div->n_row - n_div));
8316 for (i = n_div; i < div->n_row; ++i)
8317 if (isl_basic_map_alloc_div(bmap) < 0)
8318 goto error;
8320 for (j = n_div - 1; j >= 0; --j) {
8321 if (exp[j] == j)
8322 break;
8323 isl_basic_map_swap_div(bmap, j, exp[j]);
8325 j = 0;
8326 for (i = 0; i < div->n_row; ++i) {
8327 if (j < n_div && exp[j] == i) {
8328 j++;
8329 } else {
8330 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
8331 if (isl_basic_map_div_is_marked_unknown(bmap, i))
8332 continue;
8333 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
8334 goto error;
8338 isl_mat_free(div);
8339 return bmap;
8340 error:
8341 isl_basic_map_free(bmap);
8342 isl_mat_free(div);
8343 return NULL;
8346 /* Apply the expansion computed by isl_merge_divs.
8347 * The expansion itself is given by "exp" while the resulting
8348 * list of divs is given by "div".
8350 __isl_give isl_basic_set *isl_basic_set_expand_divs(
8351 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
8353 return isl_basic_map_expand_divs(bset, div, exp);
8356 /* Look for a div in dst that corresponds to the div "div" in src.
8357 * The divs before "div" in src and dst are assumed to be the same.
8359 * Returns -1 if no corresponding div was found and the position
8360 * of the corresponding div in dst otherwise.
8362 static int find_div(struct isl_basic_map *dst,
8363 struct isl_basic_map *src, unsigned div)
8365 int i;
8367 unsigned total = isl_space_dim(src->dim, isl_dim_all);
8369 isl_assert(dst->ctx, div <= dst->n_div, return -1);
8370 for (i = div; i < dst->n_div; ++i)
8371 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
8372 isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
8373 dst->n_div - div) == -1)
8374 return i;
8375 return -1;
8378 /* Align the divs of "dst" to those of "src", adding divs from "src"
8379 * if needed. That is, make sure that the first src->n_div divs
8380 * of the result are equal to those of src.
8382 * The result is not finalized as by design it will have redundant
8383 * divs if any divs from "src" were copied.
8385 __isl_give isl_basic_map *isl_basic_map_align_divs(
8386 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
8388 int i;
8389 int known, extended;
8390 unsigned total;
8392 if (!dst || !src)
8393 return isl_basic_map_free(dst);
8395 if (src->n_div == 0)
8396 return dst;
8398 known = isl_basic_map_divs_known(src);
8399 if (known < 0)
8400 return isl_basic_map_free(dst);
8401 if (!known)
8402 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
8403 "some src divs are unknown",
8404 return isl_basic_map_free(dst));
8406 src = isl_basic_map_order_divs(src);
8408 extended = 0;
8409 total = isl_space_dim(src->dim, isl_dim_all);
8410 for (i = 0; i < src->n_div; ++i) {
8411 int j = find_div(dst, src, i);
8412 if (j < 0) {
8413 if (!extended) {
8414 int extra = src->n_div - i;
8415 dst = isl_basic_map_cow(dst);
8416 if (!dst)
8417 return NULL;
8418 dst = isl_basic_map_extend_space(dst,
8419 isl_space_copy(dst->dim),
8420 extra, 0, 2 * extra);
8421 extended = 1;
8423 j = isl_basic_map_alloc_div(dst);
8424 if (j < 0)
8425 return isl_basic_map_free(dst);
8426 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
8427 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
8428 if (isl_basic_map_add_div_constraints(dst, j) < 0)
8429 return isl_basic_map_free(dst);
8431 if (j != i)
8432 isl_basic_map_swap_div(dst, i, j);
8434 return dst;
8437 struct isl_map *isl_map_align_divs(struct isl_map *map)
8439 int i;
8441 if (!map)
8442 return NULL;
8443 if (map->n == 0)
8444 return map;
8445 map = isl_map_compute_divs(map);
8446 map = isl_map_cow(map);
8447 if (!map)
8448 return NULL;
8450 for (i = 1; i < map->n; ++i)
8451 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
8452 for (i = 1; i < map->n; ++i) {
8453 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
8454 if (!map->p[i])
8455 return isl_map_free(map);
8458 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
8459 return map;
8462 struct isl_set *isl_set_align_divs(struct isl_set *set)
8464 return set_from_map(isl_map_align_divs(set_to_map(set)));
8467 /* Align the divs of the basic maps in "map" to those
8468 * of the basic maps in "list", as well as to the other basic maps in "map".
8469 * The elements in "list" are assumed to have known divs.
8471 __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
8472 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
8474 int i, n;
8476 map = isl_map_compute_divs(map);
8477 map = isl_map_cow(map);
8478 if (!map || !list)
8479 return isl_map_free(map);
8480 if (map->n == 0)
8481 return map;
8483 n = isl_basic_map_list_n_basic_map(list);
8484 for (i = 0; i < n; ++i) {
8485 isl_basic_map *bmap;
8487 bmap = isl_basic_map_list_get_basic_map(list, i);
8488 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
8489 isl_basic_map_free(bmap);
8491 if (!map->p[0])
8492 return isl_map_free(map);
8494 return isl_map_align_divs(map);
8497 /* Align the divs of each element of "list" to those of "bmap".
8498 * Both "bmap" and the elements of "list" are assumed to have known divs.
8500 __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
8501 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
8503 int i, n;
8505 if (!list || !bmap)
8506 return isl_basic_map_list_free(list);
8508 n = isl_basic_map_list_n_basic_map(list);
8509 for (i = 0; i < n; ++i) {
8510 isl_basic_map *bmap_i;
8512 bmap_i = isl_basic_map_list_get_basic_map(list, i);
8513 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
8514 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
8517 return list;
8520 static __isl_give isl_set *set_apply( __isl_take isl_set *set,
8521 __isl_take isl_map *map)
8523 isl_bool ok;
8525 ok = isl_map_compatible_domain(map, set);
8526 if (ok < 0)
8527 goto error;
8528 if (!ok)
8529 isl_die(isl_set_get_ctx(set), isl_error_invalid,
8530 "incompatible spaces", goto error);
8531 map = isl_map_intersect_domain(map, set);
8532 set = isl_map_range(map);
8533 return set;
8534 error:
8535 isl_set_free(set);
8536 isl_map_free(map);
8537 return NULL;
8540 __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
8541 __isl_take isl_map *map)
8543 return isl_map_align_params_map_map_and(set, map, &set_apply);
8546 /* There is no need to cow as removing empty parts doesn't change
8547 * the meaning of the set.
8549 struct isl_map *isl_map_remove_empty_parts(struct isl_map *map)
8551 int i;
8553 if (!map)
8554 return NULL;
8556 for (i = map->n - 1; i >= 0; --i)
8557 remove_if_empty(map, i);
8559 return map;
8562 struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
8564 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
8567 static __isl_give isl_basic_map *map_copy_basic_map(__isl_keep isl_map *map)
8569 struct isl_basic_map *bmap;
8570 if (!map || map->n == 0)
8571 return NULL;
8572 bmap = map->p[map->n-1];
8573 isl_assert(map->ctx, ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL), return NULL);
8574 return isl_basic_map_copy(bmap);
8577 __isl_give isl_basic_map *isl_map_copy_basic_map(__isl_keep isl_map *map)
8579 return map_copy_basic_map(map);
8582 struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set)
8584 return bset_from_bmap(map_copy_basic_map(set_to_map(set)));
8587 static __isl_give isl_map *map_drop_basic_map(__isl_take isl_map *map,
8588 __isl_keep isl_basic_map *bmap)
8590 int i;
8592 if (!map || !bmap)
8593 goto error;
8594 for (i = map->n-1; i >= 0; --i) {
8595 if (map->p[i] != bmap)
8596 continue;
8597 map = isl_map_cow(map);
8598 if (!map)
8599 goto error;
8600 isl_basic_map_free(map->p[i]);
8601 if (i != map->n-1) {
8602 ISL_F_CLR(map, ISL_SET_NORMALIZED);
8603 map->p[i] = map->p[map->n-1];
8605 map->n--;
8606 return map;
8608 return map;
8609 error:
8610 isl_map_free(map);
8611 return NULL;
8614 __isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map,
8615 __isl_keep isl_basic_map *bmap)
8617 return map_drop_basic_map(map, bmap);
8620 struct isl_set *isl_set_drop_basic_set(struct isl_set *set,
8621 struct isl_basic_set *bset)
8623 return set_from_map(map_drop_basic_map(set_to_map(set),
8624 bset_to_bmap(bset)));
8627 /* Given two basic sets bset1 and bset2, compute the maximal difference
8628 * between the values of dimension pos in bset1 and those in bset2
8629 * for any common value of the parameters and dimensions preceding pos.
8631 static enum isl_lp_result basic_set_maximal_difference_at(
8632 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
8633 int pos, isl_int *opt)
8635 isl_basic_map *bmap1;
8636 isl_basic_map *bmap2;
8637 struct isl_ctx *ctx;
8638 struct isl_vec *obj;
8639 unsigned total;
8640 unsigned nparam;
8641 unsigned dim1;
8642 enum isl_lp_result res;
8644 if (!bset1 || !bset2)
8645 return isl_lp_error;
8647 nparam = isl_basic_set_n_param(bset1);
8648 dim1 = isl_basic_set_n_dim(bset1);
8650 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
8651 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
8652 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
8653 isl_dim_out, 0, pos);
8654 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
8655 isl_dim_out, 0, pos);
8656 bmap1 = isl_basic_map_range_product(bmap1, bmap2);
8657 if (!bmap1)
8658 return isl_lp_error;
8660 total = isl_basic_map_total_dim(bmap1);
8661 ctx = bmap1->ctx;
8662 obj = isl_vec_alloc(ctx, 1 + total);
8663 if (!obj)
8664 goto error;
8665 isl_seq_clr(obj->block.data, 1 + total);
8666 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
8667 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
8668 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
8669 opt, NULL, NULL);
8670 isl_basic_map_free(bmap1);
8671 isl_vec_free(obj);
8672 return res;
8673 error:
8674 isl_basic_map_free(bmap1);
8675 return isl_lp_error;
8678 /* Given two _disjoint_ basic sets bset1 and bset2, check whether
8679 * for any common value of the parameters and dimensions preceding pos
8680 * in both basic sets, the values of dimension pos in bset1 are
8681 * smaller or larger than those in bset2.
8683 * Returns
8684 * 1 if bset1 follows bset2
8685 * -1 if bset1 precedes bset2
8686 * 0 if bset1 and bset2 are incomparable
8687 * -2 if some error occurred.
8689 int isl_basic_set_compare_at(struct isl_basic_set *bset1,
8690 struct isl_basic_set *bset2, int pos)
8692 isl_int opt;
8693 enum isl_lp_result res;
8694 int cmp;
8696 isl_int_init(opt);
8698 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8700 if (res == isl_lp_empty)
8701 cmp = 0;
8702 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8703 res == isl_lp_unbounded)
8704 cmp = 1;
8705 else if (res == isl_lp_ok && isl_int_is_neg(opt))
8706 cmp = -1;
8707 else
8708 cmp = -2;
8710 isl_int_clear(opt);
8711 return cmp;
8714 /* Given two basic sets bset1 and bset2, check whether
8715 * for any common value of the parameters and dimensions preceding pos
8716 * there is a value of dimension pos in bset1 that is larger
8717 * than a value of the same dimension in bset2.
8719 * Return
8720 * 1 if there exists such a pair
8721 * 0 if there is no such pair, but there is a pair of equal values
8722 * -1 otherwise
8723 * -2 if some error occurred.
8725 int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
8726 __isl_keep isl_basic_set *bset2, int pos)
8728 isl_int opt;
8729 enum isl_lp_result res;
8730 int cmp;
8732 isl_int_init(opt);
8734 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
8736 if (res == isl_lp_empty)
8737 cmp = -1;
8738 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
8739 res == isl_lp_unbounded)
8740 cmp = 1;
8741 else if (res == isl_lp_ok && isl_int_is_neg(opt))
8742 cmp = -1;
8743 else if (res == isl_lp_ok)
8744 cmp = 0;
8745 else
8746 cmp = -2;
8748 isl_int_clear(opt);
8749 return cmp;
8752 /* Given two sets set1 and set2, check whether
8753 * for any common value of the parameters and dimensions preceding pos
8754 * there is a value of dimension pos in set1 that is larger
8755 * than a value of the same dimension in set2.
8757 * Return
8758 * 1 if there exists such a pair
8759 * 0 if there is no such pair, but there is a pair of equal values
8760 * -1 otherwise
8761 * -2 if some error occurred.
8763 int isl_set_follows_at(__isl_keep isl_set *set1,
8764 __isl_keep isl_set *set2, int pos)
8766 int i, j;
8767 int follows = -1;
8769 if (!set1 || !set2)
8770 return -2;
8772 for (i = 0; i < set1->n; ++i)
8773 for (j = 0; j < set2->n; ++j) {
8774 int f;
8775 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
8776 if (f == 1 || f == -2)
8777 return f;
8778 if (f > follows)
8779 follows = f;
8782 return follows;
8785 static isl_bool isl_basic_map_plain_has_fixed_var(
8786 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
8788 int i;
8789 int d;
8790 unsigned total;
8792 if (!bmap)
8793 return isl_bool_error;
8794 total = isl_basic_map_total_dim(bmap);
8795 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
8796 for (; d+1 > pos; --d)
8797 if (!isl_int_is_zero(bmap->eq[i][1+d]))
8798 break;
8799 if (d != pos)
8800 continue;
8801 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
8802 return isl_bool_false;
8803 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
8804 return isl_bool_false;
8805 if (!isl_int_is_one(bmap->eq[i][1+d]))
8806 return isl_bool_false;
8807 if (val)
8808 isl_int_neg(*val, bmap->eq[i][0]);
8809 return isl_bool_true;
8811 return isl_bool_false;
8814 static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
8815 unsigned pos, isl_int *val)
8817 int i;
8818 isl_int v;
8819 isl_int tmp;
8820 isl_bool fixed;
8822 if (!map)
8823 return isl_bool_error;
8824 if (map->n == 0)
8825 return isl_bool_false;
8826 if (map->n == 1)
8827 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
8828 isl_int_init(v);
8829 isl_int_init(tmp);
8830 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
8831 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
8832 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
8833 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
8834 fixed = isl_bool_false;
8836 if (val)
8837 isl_int_set(*val, v);
8838 isl_int_clear(tmp);
8839 isl_int_clear(v);
8840 return fixed;
8843 static isl_bool isl_basic_set_plain_has_fixed_var(
8844 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
8846 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
8847 pos, val);
8850 isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
8851 enum isl_dim_type type, unsigned pos, isl_int *val)
8853 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
8854 return isl_bool_error;
8855 return isl_basic_map_plain_has_fixed_var(bmap,
8856 isl_basic_map_offset(bmap, type) - 1 + pos, val);
8859 /* If "bmap" obviously lies on a hyperplane where the given dimension
8860 * has a fixed value, then return that value.
8861 * Otherwise return NaN.
8863 __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
8864 __isl_keep isl_basic_map *bmap,
8865 enum isl_dim_type type, unsigned pos)
8867 isl_ctx *ctx;
8868 isl_val *v;
8869 isl_bool fixed;
8871 if (!bmap)
8872 return NULL;
8873 ctx = isl_basic_map_get_ctx(bmap);
8874 v = isl_val_alloc(ctx);
8875 if (!v)
8876 return NULL;
8877 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
8878 if (fixed < 0)
8879 return isl_val_free(v);
8880 if (fixed) {
8881 isl_int_set_si(v->d, 1);
8882 return v;
8884 isl_val_free(v);
8885 return isl_val_nan(ctx);
8888 isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
8889 enum isl_dim_type type, unsigned pos, isl_int *val)
8891 if (pos >= isl_map_dim(map, type))
8892 isl_die(isl_map_get_ctx(map), isl_error_invalid,
8893 "position out of bounds", return isl_bool_error);
8894 return isl_map_plain_has_fixed_var(map,
8895 map_offset(map, type) - 1 + pos, val);
8898 /* If "map" obviously lies on a hyperplane where the given dimension
8899 * has a fixed value, then return that value.
8900 * Otherwise return NaN.
8902 __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
8903 enum isl_dim_type type, unsigned pos)
8905 isl_ctx *ctx;
8906 isl_val *v;
8907 isl_bool fixed;
8909 if (!map)
8910 return NULL;
8911 ctx = isl_map_get_ctx(map);
8912 v = isl_val_alloc(ctx);
8913 if (!v)
8914 return NULL;
8915 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
8916 if (fixed < 0)
8917 return isl_val_free(v);
8918 if (fixed) {
8919 isl_int_set_si(v->d, 1);
8920 return v;
8922 isl_val_free(v);
8923 return isl_val_nan(ctx);
8926 /* If "set" obviously lies on a hyperplane where the given dimension
8927 * has a fixed value, then return that value.
8928 * Otherwise return NaN.
8930 __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
8931 enum isl_dim_type type, unsigned pos)
8933 return isl_map_plain_get_val_if_fixed(set, type, pos);
8936 isl_bool isl_set_plain_is_fixed(__isl_keep isl_set *set,
8937 enum isl_dim_type type, unsigned pos, isl_int *val)
8939 return isl_map_plain_is_fixed(set, type, pos, val);
8942 /* Check if dimension dim has fixed value and if so and if val is not NULL,
8943 * then return this fixed value in *val.
8945 isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
8946 unsigned dim, isl_int *val)
8948 return isl_basic_set_plain_has_fixed_var(bset,
8949 isl_basic_set_n_param(bset) + dim, val);
8952 /* Return -1 if the constraint "c1" should be sorted before "c2"
8953 * and 1 if it should be sorted after "c2".
8954 * Return 0 if the two constraints are the same (up to the constant term).
8956 * In particular, if a constraint involves later variables than another
8957 * then it is sorted after this other constraint.
8958 * uset_gist depends on constraints without existentially quantified
8959 * variables sorting first.
8961 * For constraints that have the same latest variable, those
8962 * with the same coefficient for this latest variable (first in absolute value
8963 * and then in actual value) are grouped together.
8964 * This is useful for detecting pairs of constraints that can
8965 * be chained in their printed representation.
8967 * Finally, within a group, constraints are sorted according to
8968 * their coefficients (excluding the constant term).
8970 static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
8972 isl_int **c1 = (isl_int **) p1;
8973 isl_int **c2 = (isl_int **) p2;
8974 int l1, l2;
8975 unsigned size = *(unsigned *) arg;
8976 int cmp;
8978 l1 = isl_seq_last_non_zero(*c1 + 1, size);
8979 l2 = isl_seq_last_non_zero(*c2 + 1, size);
8981 if (l1 != l2)
8982 return l1 - l2;
8984 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
8985 if (cmp != 0)
8986 return cmp;
8987 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
8988 if (cmp != 0)
8989 return -cmp;
8991 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
8994 /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
8995 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
8996 * and 0 if the two constraints are the same (up to the constant term).
8998 int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
8999 isl_int *c1, isl_int *c2)
9001 unsigned total;
9003 if (!bmap)
9004 return -2;
9005 total = isl_basic_map_total_dim(bmap);
9006 return sort_constraint_cmp(&c1, &c2, &total);
9009 __isl_give isl_basic_map *isl_basic_map_sort_constraints(
9010 __isl_take isl_basic_map *bmap)
9012 unsigned total;
9014 if (!bmap)
9015 return NULL;
9016 if (bmap->n_ineq == 0)
9017 return bmap;
9018 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9019 return bmap;
9020 total = isl_basic_map_total_dim(bmap);
9021 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
9022 &sort_constraint_cmp, &total) < 0)
9023 return isl_basic_map_free(bmap);
9024 return bmap;
9027 __isl_give isl_basic_set *isl_basic_set_sort_constraints(
9028 __isl_take isl_basic_set *bset)
9030 isl_basic_map *bmap = bset_to_bmap(bset);
9031 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
9034 struct isl_basic_map *isl_basic_map_normalize(struct isl_basic_map *bmap)
9036 if (!bmap)
9037 return NULL;
9038 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
9039 return bmap;
9040 bmap = isl_basic_map_remove_redundancies(bmap);
9041 bmap = isl_basic_map_sort_constraints(bmap);
9042 if (bmap)
9043 ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
9044 return bmap;
9046 int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
9047 __isl_keep isl_basic_map *bmap2)
9049 int i, cmp;
9050 unsigned total;
9052 if (!bmap1 || !bmap2)
9053 return -1;
9055 if (bmap1 == bmap2)
9056 return 0;
9057 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
9058 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
9059 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
9060 if (isl_basic_map_n_param(bmap1) != isl_basic_map_n_param(bmap2))
9061 return isl_basic_map_n_param(bmap1) - isl_basic_map_n_param(bmap2);
9062 if (isl_basic_map_n_in(bmap1) != isl_basic_map_n_in(bmap2))
9063 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
9064 if (isl_basic_map_n_out(bmap1) != isl_basic_map_n_out(bmap2))
9065 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
9066 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
9067 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9068 return 0;
9069 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
9070 return 1;
9071 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
9072 return -1;
9073 if (bmap1->n_eq != bmap2->n_eq)
9074 return bmap1->n_eq - bmap2->n_eq;
9075 if (bmap1->n_ineq != bmap2->n_ineq)
9076 return bmap1->n_ineq - bmap2->n_ineq;
9077 if (bmap1->n_div != bmap2->n_div)
9078 return bmap1->n_div - bmap2->n_div;
9079 total = isl_basic_map_total_dim(bmap1);
9080 for (i = 0; i < bmap1->n_eq; ++i) {
9081 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
9082 if (cmp)
9083 return cmp;
9085 for (i = 0; i < bmap1->n_ineq; ++i) {
9086 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
9087 if (cmp)
9088 return cmp;
9090 for (i = 0; i < bmap1->n_div; ++i) {
9091 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
9092 if (cmp)
9093 return cmp;
9095 return 0;
9098 int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
9099 __isl_keep isl_basic_set *bset2)
9101 return isl_basic_map_plain_cmp(bset1, bset2);
9104 int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
9106 int i, cmp;
9108 if (set1 == set2)
9109 return 0;
9110 if (set1->n != set2->n)
9111 return set1->n - set2->n;
9113 for (i = 0; i < set1->n; ++i) {
9114 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
9115 if (cmp)
9116 return cmp;
9119 return 0;
9122 isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
9123 __isl_keep isl_basic_map *bmap2)
9125 if (!bmap1 || !bmap2)
9126 return isl_bool_error;
9127 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
9130 isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
9131 __isl_keep isl_basic_set *bset2)
9133 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
9134 bset_to_bmap(bset2));
9137 static int qsort_bmap_cmp(const void *p1, const void *p2)
9139 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
9140 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
9142 return isl_basic_map_plain_cmp(bmap1, bmap2);
9145 /* Sort the basic maps of "map" and remove duplicate basic maps.
9147 * While removing basic maps, we make sure that the basic maps remain
9148 * sorted because isl_map_normalize expects the basic maps of the result
9149 * to be sorted.
9151 static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
9153 int i, j;
9155 map = isl_map_remove_empty_parts(map);
9156 if (!map)
9157 return NULL;
9158 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
9159 for (i = map->n - 1; i >= 1; --i) {
9160 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
9161 continue;
9162 isl_basic_map_free(map->p[i-1]);
9163 for (j = i; j < map->n; ++j)
9164 map->p[j - 1] = map->p[j];
9165 map->n--;
9168 return map;
9171 /* Remove obvious duplicates among the basic maps of "map".
9173 * Unlike isl_map_normalize, this function does not remove redundant
9174 * constraints and only removes duplicates that have exactly the same
9175 * constraints in the input. It does sort the constraints and
9176 * the basic maps to ease the detection of duplicates.
9178 * If "map" has already been normalized or if the basic maps are
9179 * disjoint, then there can be no duplicates.
9181 __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
9183 int i;
9184 isl_basic_map *bmap;
9186 if (!map)
9187 return NULL;
9188 if (map->n <= 1)
9189 return map;
9190 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
9191 return map;
9192 for (i = 0; i < map->n; ++i) {
9193 bmap = isl_basic_map_copy(map->p[i]);
9194 bmap = isl_basic_map_sort_constraints(bmap);
9195 if (!bmap)
9196 return isl_map_free(map);
9197 isl_basic_map_free(map->p[i]);
9198 map->p[i] = bmap;
9201 map = sort_and_remove_duplicates(map);
9202 return map;
9205 /* We normalize in place, but if anything goes wrong we need
9206 * to return NULL, so we need to make sure we don't change the
9207 * meaning of any possible other copies of map.
9209 __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
9211 int i;
9212 struct isl_basic_map *bmap;
9214 if (!map)
9215 return NULL;
9216 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
9217 return map;
9218 for (i = 0; i < map->n; ++i) {
9219 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
9220 if (!bmap)
9221 goto error;
9222 isl_basic_map_free(map->p[i]);
9223 map->p[i] = bmap;
9226 map = sort_and_remove_duplicates(map);
9227 if (map)
9228 ISL_F_SET(map, ISL_MAP_NORMALIZED);
9229 return map;
9230 error:
9231 isl_map_free(map);
9232 return NULL;
9235 struct isl_set *isl_set_normalize(struct isl_set *set)
9237 return set_from_map(isl_map_normalize(set_to_map(set)));
9240 isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
9241 __isl_keep isl_map *map2)
9243 int i;
9244 isl_bool equal;
9246 if (!map1 || !map2)
9247 return isl_bool_error;
9249 if (map1 == map2)
9250 return isl_bool_true;
9251 if (!isl_space_is_equal(map1->dim, map2->dim))
9252 return isl_bool_false;
9254 map1 = isl_map_copy(map1);
9255 map2 = isl_map_copy(map2);
9256 map1 = isl_map_normalize(map1);
9257 map2 = isl_map_normalize(map2);
9258 if (!map1 || !map2)
9259 goto error;
9260 equal = map1->n == map2->n;
9261 for (i = 0; equal && i < map1->n; ++i) {
9262 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
9263 if (equal < 0)
9264 goto error;
9266 isl_map_free(map1);
9267 isl_map_free(map2);
9268 return equal;
9269 error:
9270 isl_map_free(map1);
9271 isl_map_free(map2);
9272 return isl_bool_error;
9275 isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
9276 __isl_keep isl_set *set2)
9278 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
9281 /* Return the basic maps in "map" as a list.
9283 __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
9284 __isl_keep isl_map *map)
9286 int i;
9287 isl_ctx *ctx;
9288 isl_basic_map_list *list;
9290 if (!map)
9291 return NULL;
9292 ctx = isl_map_get_ctx(map);
9293 list = isl_basic_map_list_alloc(ctx, map->n);
9295 for (i = 0; i < map->n; ++i) {
9296 isl_basic_map *bmap;
9298 bmap = isl_basic_map_copy(map->p[i]);
9299 list = isl_basic_map_list_add(list, bmap);
9302 return list;
9305 /* Return the intersection of the elements in the non-empty list "list".
9306 * All elements are assumed to live in the same space.
9308 __isl_give isl_basic_map *isl_basic_map_list_intersect(
9309 __isl_take isl_basic_map_list *list)
9311 int i, n;
9312 isl_basic_map *bmap;
9314 if (!list)
9315 return NULL;
9316 n = isl_basic_map_list_n_basic_map(list);
9317 if (n < 1)
9318 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
9319 "expecting non-empty list", goto error);
9321 bmap = isl_basic_map_list_get_basic_map(list, 0);
9322 for (i = 1; i < n; ++i) {
9323 isl_basic_map *bmap_i;
9325 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9326 bmap = isl_basic_map_intersect(bmap, bmap_i);
9329 isl_basic_map_list_free(list);
9330 return bmap;
9331 error:
9332 isl_basic_map_list_free(list);
9333 return NULL;
9336 /* Return the intersection of the elements in the non-empty list "list".
9337 * All elements are assumed to live in the same space.
9339 __isl_give isl_basic_set *isl_basic_set_list_intersect(
9340 __isl_take isl_basic_set_list *list)
9342 return isl_basic_map_list_intersect(list);
9345 /* Return the union of the elements of "list".
9346 * The list is required to have at least one element.
9348 __isl_give isl_set *isl_basic_set_list_union(
9349 __isl_take isl_basic_set_list *list)
9351 int i, n;
9352 isl_space *space;
9353 isl_basic_set *bset;
9354 isl_set *set;
9356 if (!list)
9357 return NULL;
9358 n = isl_basic_set_list_n_basic_set(list);
9359 if (n < 1)
9360 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
9361 "expecting non-empty list", goto error);
9363 bset = isl_basic_set_list_get_basic_set(list, 0);
9364 space = isl_basic_set_get_space(bset);
9365 isl_basic_set_free(bset);
9367 set = isl_set_alloc_space(space, n, 0);
9368 for (i = 0; i < n; ++i) {
9369 bset = isl_basic_set_list_get_basic_set(list, i);
9370 set = isl_set_add_basic_set(set, bset);
9373 isl_basic_set_list_free(list);
9374 return set;
9375 error:
9376 isl_basic_set_list_free(list);
9377 return NULL;
9380 /* Return the union of the elements in the non-empty list "list".
9381 * All elements are assumed to live in the same space.
9383 __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
9385 int i, n;
9386 isl_set *set;
9388 if (!list)
9389 return NULL;
9390 n = isl_set_list_n_set(list);
9391 if (n < 1)
9392 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
9393 "expecting non-empty list", goto error);
9395 set = isl_set_list_get_set(list, 0);
9396 for (i = 1; i < n; ++i) {
9397 isl_set *set_i;
9399 set_i = isl_set_list_get_set(list, i);
9400 set = isl_set_union(set, set_i);
9403 isl_set_list_free(list);
9404 return set;
9405 error:
9406 isl_set_list_free(list);
9407 return NULL;
9410 struct isl_basic_map *isl_basic_map_product(
9411 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
9413 isl_space *dim_result = NULL;
9414 struct isl_basic_map *bmap;
9415 unsigned in1, in2, out1, out2, nparam, total, pos;
9416 struct isl_dim_map *dim_map1, *dim_map2;
9418 if (!bmap1 || !bmap2)
9419 goto error;
9421 isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
9422 bmap2->dim, isl_dim_param), goto error);
9423 dim_result = isl_space_product(isl_space_copy(bmap1->dim),
9424 isl_space_copy(bmap2->dim));
9426 in1 = isl_basic_map_n_in(bmap1);
9427 in2 = isl_basic_map_n_in(bmap2);
9428 out1 = isl_basic_map_n_out(bmap1);
9429 out2 = isl_basic_map_n_out(bmap2);
9430 nparam = isl_basic_map_n_param(bmap1);
9432 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
9433 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9434 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9435 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9436 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9437 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9438 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9439 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9440 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9441 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9442 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9444 bmap = isl_basic_map_alloc_space(dim_result,
9445 bmap1->n_div + bmap2->n_div,
9446 bmap1->n_eq + bmap2->n_eq,
9447 bmap1->n_ineq + bmap2->n_ineq);
9448 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9449 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9450 bmap = isl_basic_map_simplify(bmap);
9451 return isl_basic_map_finalize(bmap);
9452 error:
9453 isl_basic_map_free(bmap1);
9454 isl_basic_map_free(bmap2);
9455 return NULL;
9458 __isl_give isl_basic_map *isl_basic_map_flat_product(
9459 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9461 isl_basic_map *prod;
9463 prod = isl_basic_map_product(bmap1, bmap2);
9464 prod = isl_basic_map_flatten(prod);
9465 return prod;
9468 __isl_give isl_basic_set *isl_basic_set_flat_product(
9469 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
9471 return isl_basic_map_flat_range_product(bset1, bset2);
9474 __isl_give isl_basic_map *isl_basic_map_domain_product(
9475 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9477 isl_space *space_result = NULL;
9478 isl_basic_map *bmap;
9479 unsigned in1, in2, out, nparam, total, pos;
9480 struct isl_dim_map *dim_map1, *dim_map2;
9482 if (!bmap1 || !bmap2)
9483 goto error;
9485 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
9486 isl_space_copy(bmap2->dim));
9488 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
9489 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
9490 out = isl_basic_map_dim(bmap1, isl_dim_out);
9491 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
9493 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
9494 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9495 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9496 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9497 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9498 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9499 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
9500 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
9501 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
9502 isl_dim_map_div(dim_map1, bmap1, pos += out);
9503 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9505 bmap = isl_basic_map_alloc_space(space_result,
9506 bmap1->n_div + bmap2->n_div,
9507 bmap1->n_eq + bmap2->n_eq,
9508 bmap1->n_ineq + bmap2->n_ineq);
9509 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9510 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9511 bmap = isl_basic_map_simplify(bmap);
9512 return isl_basic_map_finalize(bmap);
9513 error:
9514 isl_basic_map_free(bmap1);
9515 isl_basic_map_free(bmap2);
9516 return NULL;
9519 __isl_give isl_basic_map *isl_basic_map_range_product(
9520 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9522 isl_bool rational;
9523 isl_space *dim_result = NULL;
9524 isl_basic_map *bmap;
9525 unsigned in, out1, out2, nparam, total, pos;
9526 struct isl_dim_map *dim_map1, *dim_map2;
9528 rational = isl_basic_map_is_rational(bmap1);
9529 if (rational >= 0 && rational)
9530 rational = isl_basic_map_is_rational(bmap2);
9531 if (!bmap1 || !bmap2 || rational < 0)
9532 goto error;
9534 if (!isl_space_match(bmap1->dim, isl_dim_param,
9535 bmap2->dim, isl_dim_param))
9536 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
9537 "parameters don't match", goto error);
9539 dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
9540 isl_space_copy(bmap2->dim));
9542 in = isl_basic_map_dim(bmap1, isl_dim_in);
9543 out1 = isl_basic_map_n_out(bmap1);
9544 out2 = isl_basic_map_n_out(bmap2);
9545 nparam = isl_basic_map_n_param(bmap1);
9547 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
9548 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
9549 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
9550 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
9551 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
9552 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
9553 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
9554 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
9555 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
9556 isl_dim_map_div(dim_map1, bmap1, pos += out2);
9557 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
9559 bmap = isl_basic_map_alloc_space(dim_result,
9560 bmap1->n_div + bmap2->n_div,
9561 bmap1->n_eq + bmap2->n_eq,
9562 bmap1->n_ineq + bmap2->n_ineq);
9563 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
9564 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
9565 if (rational)
9566 bmap = isl_basic_map_set_rational(bmap);
9567 bmap = isl_basic_map_simplify(bmap);
9568 return isl_basic_map_finalize(bmap);
9569 error:
9570 isl_basic_map_free(bmap1);
9571 isl_basic_map_free(bmap2);
9572 return NULL;
9575 __isl_give isl_basic_map *isl_basic_map_flat_range_product(
9576 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
9578 isl_basic_map *prod;
9580 prod = isl_basic_map_range_product(bmap1, bmap2);
9581 prod = isl_basic_map_flatten_range(prod);
9582 return prod;
9585 /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
9586 * and collect the results.
9587 * The result live in the space obtained by calling "space_product"
9588 * on the spaces of "map1" and "map2".
9589 * If "remove_duplicates" is set then the result may contain duplicates
9590 * (even if the inputs do not) and so we try and remove the obvious
9591 * duplicates.
9593 static __isl_give isl_map *map_product(__isl_take isl_map *map1,
9594 __isl_take isl_map *map2,
9595 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
9596 __isl_take isl_space *right),
9597 __isl_give isl_basic_map *(*basic_map_product)(
9598 __isl_take isl_basic_map *left,
9599 __isl_take isl_basic_map *right),
9600 int remove_duplicates)
9602 unsigned flags = 0;
9603 struct isl_map *result;
9604 int i, j;
9606 if (!map1 || !map2)
9607 goto error;
9609 isl_assert(map1->ctx, isl_space_match(map1->dim, isl_dim_param,
9610 map2->dim, isl_dim_param), goto error);
9612 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
9613 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
9614 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
9616 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
9617 isl_space_copy(map2->dim)),
9618 map1->n * map2->n, flags);
9619 if (!result)
9620 goto error;
9621 for (i = 0; i < map1->n; ++i)
9622 for (j = 0; j < map2->n; ++j) {
9623 struct isl_basic_map *part;
9624 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
9625 isl_basic_map_copy(map2->p[j]));
9626 if (isl_basic_map_is_empty(part))
9627 isl_basic_map_free(part);
9628 else
9629 result = isl_map_add_basic_map(result, part);
9630 if (!result)
9631 goto error;
9633 if (remove_duplicates)
9634 result = isl_map_remove_obvious_duplicates(result);
9635 isl_map_free(map1);
9636 isl_map_free(map2);
9637 return result;
9638 error:
9639 isl_map_free(map1);
9640 isl_map_free(map2);
9641 return NULL;
9644 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
9646 static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
9647 __isl_take isl_map *map2)
9649 return map_product(map1, map2, &isl_space_product,
9650 &isl_basic_map_product, 0);
9653 __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
9654 __isl_take isl_map *map2)
9656 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
9659 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
9661 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
9662 __isl_take isl_map *map2)
9664 isl_map *prod;
9666 prod = isl_map_product(map1, map2);
9667 prod = isl_map_flatten(prod);
9668 return prod;
9671 /* Given two set A and B, construct its Cartesian product A x B.
9673 struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
9675 return isl_map_range_product(set1, set2);
9678 __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
9679 __isl_take isl_set *set2)
9681 return isl_map_flat_range_product(set1, set2);
9684 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
9686 static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
9687 __isl_take isl_map *map2)
9689 return map_product(map1, map2, &isl_space_domain_product,
9690 &isl_basic_map_domain_product, 1);
9693 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
9695 static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
9696 __isl_take isl_map *map2)
9698 return map_product(map1, map2, &isl_space_range_product,
9699 &isl_basic_map_range_product, 1);
9702 __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
9703 __isl_take isl_map *map2)
9705 return isl_map_align_params_map_map_and(map1, map2,
9706 &map_domain_product_aligned);
9709 __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
9710 __isl_take isl_map *map2)
9712 return isl_map_align_params_map_map_and(map1, map2,
9713 &map_range_product_aligned);
9716 /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
9718 __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
9720 isl_space *space;
9721 int total1, keep1, total2, keep2;
9723 if (!map)
9724 return NULL;
9725 if (!isl_space_domain_is_wrapping(map->dim) ||
9726 !isl_space_range_is_wrapping(map->dim))
9727 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9728 "not a product", return isl_map_free(map));
9730 space = isl_map_get_space(map);
9731 total1 = isl_space_dim(space, isl_dim_in);
9732 total2 = isl_space_dim(space, isl_dim_out);
9733 space = isl_space_factor_domain(space);
9734 keep1 = isl_space_dim(space, isl_dim_in);
9735 keep2 = isl_space_dim(space, isl_dim_out);
9736 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
9737 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
9738 map = isl_map_reset_space(map, space);
9740 return map;
9743 /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
9745 __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
9747 isl_space *space;
9748 int total1, keep1, total2, keep2;
9750 if (!map)
9751 return NULL;
9752 if (!isl_space_domain_is_wrapping(map->dim) ||
9753 !isl_space_range_is_wrapping(map->dim))
9754 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9755 "not a product", return isl_map_free(map));
9757 space = isl_map_get_space(map);
9758 total1 = isl_space_dim(space, isl_dim_in);
9759 total2 = isl_space_dim(space, isl_dim_out);
9760 space = isl_space_factor_range(space);
9761 keep1 = isl_space_dim(space, isl_dim_in);
9762 keep2 = isl_space_dim(space, isl_dim_out);
9763 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
9764 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
9765 map = isl_map_reset_space(map, space);
9767 return map;
9770 /* Given a map of the form [A -> B] -> C, return the map A -> C.
9772 __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
9774 isl_space *space;
9775 int total, keep;
9777 if (!map)
9778 return NULL;
9779 if (!isl_space_domain_is_wrapping(map->dim))
9780 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9781 "domain is not a product", return isl_map_free(map));
9783 space = isl_map_get_space(map);
9784 total = isl_space_dim(space, isl_dim_in);
9785 space = isl_space_domain_factor_domain(space);
9786 keep = isl_space_dim(space, isl_dim_in);
9787 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
9788 map = isl_map_reset_space(map, space);
9790 return map;
9793 /* Given a map of the form [A -> B] -> C, return the map B -> C.
9795 __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
9797 isl_space *space;
9798 int total, keep;
9800 if (!map)
9801 return NULL;
9802 if (!isl_space_domain_is_wrapping(map->dim))
9803 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9804 "domain is not a product", return isl_map_free(map));
9806 space = isl_map_get_space(map);
9807 total = isl_space_dim(space, isl_dim_in);
9808 space = isl_space_domain_factor_range(space);
9809 keep = isl_space_dim(space, isl_dim_in);
9810 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
9811 map = isl_map_reset_space(map, space);
9813 return map;
9816 /* Given a map A -> [B -> C], extract the map A -> B.
9818 __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
9820 isl_space *space;
9821 int total, keep;
9823 if (!map)
9824 return NULL;
9825 if (!isl_space_range_is_wrapping(map->dim))
9826 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9827 "range is not a product", return isl_map_free(map));
9829 space = isl_map_get_space(map);
9830 total = isl_space_dim(space, isl_dim_out);
9831 space = isl_space_range_factor_domain(space);
9832 keep = isl_space_dim(space, isl_dim_out);
9833 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
9834 map = isl_map_reset_space(map, space);
9836 return map;
9839 /* Given a map A -> [B -> C], extract the map A -> C.
9841 __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
9843 isl_space *space;
9844 int total, keep;
9846 if (!map)
9847 return NULL;
9848 if (!isl_space_range_is_wrapping(map->dim))
9849 isl_die(isl_map_get_ctx(map), isl_error_invalid,
9850 "range is not a product", return isl_map_free(map));
9852 space = isl_map_get_space(map);
9853 total = isl_space_dim(space, isl_dim_out);
9854 space = isl_space_range_factor_range(space);
9855 keep = isl_space_dim(space, isl_dim_out);
9856 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
9857 map = isl_map_reset_space(map, space);
9859 return map;
9862 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
9864 __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
9865 __isl_take isl_map *map2)
9867 isl_map *prod;
9869 prod = isl_map_domain_product(map1, map2);
9870 prod = isl_map_flatten_domain(prod);
9871 return prod;
9874 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
9876 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
9877 __isl_take isl_map *map2)
9879 isl_map *prod;
9881 prod = isl_map_range_product(map1, map2);
9882 prod = isl_map_flatten_range(prod);
9883 return prod;
9886 uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
9888 int i;
9889 uint32_t hash = isl_hash_init();
9890 unsigned total;
9892 if (!bmap)
9893 return 0;
9894 bmap = isl_basic_map_copy(bmap);
9895 bmap = isl_basic_map_normalize(bmap);
9896 if (!bmap)
9897 return 0;
9898 total = isl_basic_map_total_dim(bmap);
9899 isl_hash_byte(hash, bmap->n_eq & 0xFF);
9900 for (i = 0; i < bmap->n_eq; ++i) {
9901 uint32_t c_hash;
9902 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
9903 isl_hash_hash(hash, c_hash);
9905 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
9906 for (i = 0; i < bmap->n_ineq; ++i) {
9907 uint32_t c_hash;
9908 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
9909 isl_hash_hash(hash, c_hash);
9911 isl_hash_byte(hash, bmap->n_div & 0xFF);
9912 for (i = 0; i < bmap->n_div; ++i) {
9913 uint32_t c_hash;
9914 if (isl_int_is_zero(bmap->div[i][0]))
9915 continue;
9916 isl_hash_byte(hash, i & 0xFF);
9917 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
9918 isl_hash_hash(hash, c_hash);
9920 isl_basic_map_free(bmap);
9921 return hash;
9924 uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
9926 return isl_basic_map_get_hash(bset_to_bmap(bset));
9929 uint32_t isl_map_get_hash(__isl_keep isl_map *map)
9931 int i;
9932 uint32_t hash;
9934 if (!map)
9935 return 0;
9936 map = isl_map_copy(map);
9937 map = isl_map_normalize(map);
9938 if (!map)
9939 return 0;
9941 hash = isl_hash_init();
9942 for (i = 0; i < map->n; ++i) {
9943 uint32_t bmap_hash;
9944 bmap_hash = isl_basic_map_get_hash(map->p[i]);
9945 isl_hash_hash(hash, bmap_hash);
9948 isl_map_free(map);
9950 return hash;
9953 uint32_t isl_set_get_hash(__isl_keep isl_set *set)
9955 return isl_map_get_hash(set_to_map(set));
9958 /* Check if the value for dimension dim is completely determined
9959 * by the values of the other parameters and variables.
9960 * That is, check if dimension dim is involved in an equality.
9962 int isl_basic_set_dim_is_unique(struct isl_basic_set *bset, unsigned dim)
9964 int i;
9965 unsigned nparam;
9967 if (!bset)
9968 return -1;
9969 nparam = isl_basic_set_n_param(bset);
9970 for (i = 0; i < bset->n_eq; ++i)
9971 if (!isl_int_is_zero(bset->eq[i][1 + nparam + dim]))
9972 return 1;
9973 return 0;
9976 /* Return the number of basic maps in the (current) representation of "map".
9978 int isl_map_n_basic_map(__isl_keep isl_map *map)
9980 return map ? map->n : 0;
9983 int isl_set_n_basic_set(__isl_keep isl_set *set)
9985 return set ? set->n : 0;
9988 isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
9989 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
9991 int i;
9993 if (!map)
9994 return isl_stat_error;
9996 for (i = 0; i < map->n; ++i)
9997 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
9998 return isl_stat_error;
10000 return isl_stat_ok;
10003 isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
10004 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
10006 int i;
10008 if (!set)
10009 return isl_stat_error;
10011 for (i = 0; i < set->n; ++i)
10012 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
10013 return isl_stat_error;
10015 return isl_stat_ok;
10018 /* Return a list of basic sets, the union of which is equal to "set".
10020 __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
10021 __isl_keep isl_set *set)
10023 int i;
10024 isl_basic_set_list *list;
10026 if (!set)
10027 return NULL;
10029 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
10030 for (i = 0; i < set->n; ++i) {
10031 isl_basic_set *bset;
10033 bset = isl_basic_set_copy(set->p[i]);
10034 list = isl_basic_set_list_add(list, bset);
10037 return list;
10040 __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
10042 isl_space *dim;
10044 if (!bset)
10045 return NULL;
10047 bset = isl_basic_set_cow(bset);
10048 if (!bset)
10049 return NULL;
10051 dim = isl_basic_set_get_space(bset);
10052 dim = isl_space_lift(dim, bset->n_div);
10053 if (!dim)
10054 goto error;
10055 isl_space_free(bset->dim);
10056 bset->dim = dim;
10057 bset->extra -= bset->n_div;
10058 bset->n_div = 0;
10060 bset = isl_basic_set_finalize(bset);
10062 return bset;
10063 error:
10064 isl_basic_set_free(bset);
10065 return NULL;
10068 __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
10070 int i;
10071 isl_space *dim;
10072 unsigned n_div;
10074 set = isl_set_align_divs(set);
10076 if (!set)
10077 return NULL;
10079 set = isl_set_cow(set);
10080 if (!set)
10081 return NULL;
10083 n_div = set->p[0]->n_div;
10084 dim = isl_set_get_space(set);
10085 dim = isl_space_lift(dim, n_div);
10086 if (!dim)
10087 goto error;
10088 isl_space_free(set->dim);
10089 set->dim = dim;
10091 for (i = 0; i < set->n; ++i) {
10092 set->p[i] = isl_basic_set_lift(set->p[i]);
10093 if (!set->p[i])
10094 goto error;
10097 return set;
10098 error:
10099 isl_set_free(set);
10100 return NULL;
10103 int isl_basic_set_size(__isl_keep isl_basic_set *bset)
10105 unsigned dim;
10106 int size = 0;
10108 if (!bset)
10109 return -1;
10111 dim = isl_basic_set_total_dim(bset);
10112 size += bset->n_eq * (1 + dim);
10113 size += bset->n_ineq * (1 + dim);
10114 size += bset->n_div * (2 + dim);
10116 return size;
10119 int isl_set_size(__isl_keep isl_set *set)
10121 int i;
10122 int size = 0;
10124 if (!set)
10125 return -1;
10127 for (i = 0; i < set->n; ++i)
10128 size += isl_basic_set_size(set->p[i]);
10130 return size;
10133 /* Check if there is any lower bound (if lower == 0) and/or upper
10134 * bound (if upper == 0) on the specified dim.
10136 static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10137 enum isl_dim_type type, unsigned pos, int lower, int upper)
10139 int i;
10141 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
10142 return isl_bool_error;
10144 pos += isl_basic_map_offset(bmap, type);
10146 for (i = 0; i < bmap->n_div; ++i) {
10147 if (isl_int_is_zero(bmap->div[i][0]))
10148 continue;
10149 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
10150 return isl_bool_true;
10153 for (i = 0; i < bmap->n_eq; ++i)
10154 if (!isl_int_is_zero(bmap->eq[i][pos]))
10155 return isl_bool_true;
10157 for (i = 0; i < bmap->n_ineq; ++i) {
10158 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
10159 if (sgn > 0)
10160 lower = 1;
10161 if (sgn < 0)
10162 upper = 1;
10165 return lower && upper;
10168 isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
10169 enum isl_dim_type type, unsigned pos)
10171 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
10174 isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
10175 enum isl_dim_type type, unsigned pos)
10177 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
10180 isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
10181 enum isl_dim_type type, unsigned pos)
10183 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
10186 isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
10187 enum isl_dim_type type, unsigned pos)
10189 int i;
10191 if (!map)
10192 return isl_bool_error;
10194 for (i = 0; i < map->n; ++i) {
10195 isl_bool bounded;
10196 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
10197 if (bounded < 0 || !bounded)
10198 return bounded;
10201 return isl_bool_true;
10204 /* Return true if the specified dim is involved in both an upper bound
10205 * and a lower bound.
10207 isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
10208 enum isl_dim_type type, unsigned pos)
10210 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
10213 /* Does "map" have a bound (according to "fn") for any of its basic maps?
10215 static isl_bool has_any_bound(__isl_keep isl_map *map,
10216 enum isl_dim_type type, unsigned pos,
10217 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10218 enum isl_dim_type type, unsigned pos))
10220 int i;
10222 if (!map)
10223 return isl_bool_error;
10225 for (i = 0; i < map->n; ++i) {
10226 isl_bool bounded;
10227 bounded = fn(map->p[i], type, pos);
10228 if (bounded < 0 || bounded)
10229 return bounded;
10232 return isl_bool_false;
10235 /* Return 1 if the specified dim is involved in any lower bound.
10237 isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
10238 enum isl_dim_type type, unsigned pos)
10240 return has_any_bound(set, type, pos,
10241 &isl_basic_map_dim_has_lower_bound);
10244 /* Return 1 if the specified dim is involved in any upper bound.
10246 isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
10247 enum isl_dim_type type, unsigned pos)
10249 return has_any_bound(set, type, pos,
10250 &isl_basic_map_dim_has_upper_bound);
10253 /* Does "map" have a bound (according to "fn") for all of its basic maps?
10255 static isl_bool has_bound(__isl_keep isl_map *map,
10256 enum isl_dim_type type, unsigned pos,
10257 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
10258 enum isl_dim_type type, unsigned pos))
10260 int i;
10262 if (!map)
10263 return isl_bool_error;
10265 for (i = 0; i < map->n; ++i) {
10266 isl_bool bounded;
10267 bounded = fn(map->p[i], type, pos);
10268 if (bounded < 0 || !bounded)
10269 return bounded;
10272 return isl_bool_true;
10275 /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
10277 isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
10278 enum isl_dim_type type, unsigned pos)
10280 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
10283 /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
10285 isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
10286 enum isl_dim_type type, unsigned pos)
10288 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
10291 /* For each of the "n" variables starting at "first", determine
10292 * the sign of the variable and put the results in the first "n"
10293 * elements of the array "signs".
10294 * Sign
10295 * 1 means that the variable is non-negative
10296 * -1 means that the variable is non-positive
10297 * 0 means the variable attains both positive and negative values.
10299 isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
10300 unsigned first, unsigned n, int *signs)
10302 isl_vec *bound = NULL;
10303 struct isl_tab *tab = NULL;
10304 struct isl_tab_undo *snap;
10305 int i;
10307 if (!bset || !signs)
10308 return isl_stat_error;
10310 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
10311 tab = isl_tab_from_basic_set(bset, 0);
10312 if (!bound || !tab)
10313 goto error;
10315 isl_seq_clr(bound->el, bound->size);
10316 isl_int_set_si(bound->el[0], -1);
10318 snap = isl_tab_snap(tab);
10319 for (i = 0; i < n; ++i) {
10320 int empty;
10322 isl_int_set_si(bound->el[1 + first + i], -1);
10323 if (isl_tab_add_ineq(tab, bound->el) < 0)
10324 goto error;
10325 empty = tab->empty;
10326 isl_int_set_si(bound->el[1 + first + i], 0);
10327 if (isl_tab_rollback(tab, snap) < 0)
10328 goto error;
10330 if (empty) {
10331 signs[i] = 1;
10332 continue;
10335 isl_int_set_si(bound->el[1 + first + i], 1);
10336 if (isl_tab_add_ineq(tab, bound->el) < 0)
10337 goto error;
10338 empty = tab->empty;
10339 isl_int_set_si(bound->el[1 + first + i], 0);
10340 if (isl_tab_rollback(tab, snap) < 0)
10341 goto error;
10343 signs[i] = empty ? -1 : 0;
10346 isl_tab_free(tab);
10347 isl_vec_free(bound);
10348 return isl_stat_ok;
10349 error:
10350 isl_tab_free(tab);
10351 isl_vec_free(bound);
10352 return isl_stat_error;
10355 isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
10356 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
10358 if (!bset || !signs)
10359 return isl_stat_error;
10360 isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
10361 return isl_stat_error);
10363 first += pos(bset->dim, type) - 1;
10364 return isl_basic_set_vars_get_sign(bset, first, n, signs);
10367 /* Is it possible for the integer division "div" to depend (possibly
10368 * indirectly) on any output dimensions?
10370 * If the div is undefined, then we conservatively assume that it
10371 * may depend on them.
10372 * Otherwise, we check if it actually depends on them or on any integer
10373 * divisions that may depend on them.
10375 static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
10377 int i;
10378 unsigned n_out, o_out;
10379 unsigned n_div, o_div;
10381 if (isl_int_is_zero(bmap->div[div][0]))
10382 return isl_bool_true;
10384 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10385 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10387 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
10388 return isl_bool_true;
10390 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10391 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10393 for (i = 0; i < n_div; ++i) {
10394 isl_bool may_involve;
10396 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
10397 continue;
10398 may_involve = div_may_involve_output(bmap, i);
10399 if (may_involve < 0 || may_involve)
10400 return may_involve;
10403 return isl_bool_false;
10406 /* Return the first integer division of "bmap" in the range
10407 * [first, first + n[ that may depend on any output dimensions and
10408 * that has a non-zero coefficient in "c" (where the first coefficient
10409 * in "c" corresponds to integer division "first").
10411 static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
10412 isl_int *c, int first, int n)
10414 int k;
10416 if (!bmap)
10417 return -1;
10419 for (k = first; k < first + n; ++k) {
10420 isl_bool may_involve;
10422 if (isl_int_is_zero(c[k]))
10423 continue;
10424 may_involve = div_may_involve_output(bmap, k);
10425 if (may_involve < 0)
10426 return -1;
10427 if (may_involve)
10428 return k;
10431 return first + n;
10434 /* Look for a pair of inequality constraints in "bmap" of the form
10436 * -l + i >= 0 or i >= l
10437 * and
10438 * n + l - i >= 0 or i <= l + n
10440 * with n < "m" and i the output dimension at position "pos".
10441 * (Note that n >= 0 as otherwise the two constraints would conflict.)
10442 * Furthermore, "l" is only allowed to involve parameters, input dimensions
10443 * and earlier output dimensions, as well as integer divisions that do
10444 * not involve any of the output dimensions.
10446 * Return the index of the first inequality constraint or bmap->n_ineq
10447 * if no such pair can be found.
10449 static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
10450 int pos, isl_int m)
10452 int i, j;
10453 isl_ctx *ctx;
10454 unsigned total;
10455 unsigned n_div, o_div;
10456 unsigned n_out, o_out;
10457 int less;
10459 if (!bmap)
10460 return -1;
10462 ctx = isl_basic_map_get_ctx(bmap);
10463 total = isl_basic_map_total_dim(bmap);
10464 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10465 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10466 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10467 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10468 for (i = 0; i < bmap->n_ineq; ++i) {
10469 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
10470 continue;
10471 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
10472 n_out - (pos + 1)) != -1)
10473 continue;
10474 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
10475 0, n_div) < n_div)
10476 continue;
10477 for (j = i + 1; j < bmap->n_ineq; ++j) {
10478 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
10479 ctx->one))
10480 continue;
10481 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
10482 bmap->ineq[j] + 1, total))
10483 continue;
10484 break;
10486 if (j >= bmap->n_ineq)
10487 continue;
10488 isl_int_add(bmap->ineq[i][0],
10489 bmap->ineq[i][0], bmap->ineq[j][0]);
10490 less = isl_int_abs_lt(bmap->ineq[i][0], m);
10491 isl_int_sub(bmap->ineq[i][0],
10492 bmap->ineq[i][0], bmap->ineq[j][0]);
10493 if (!less)
10494 continue;
10495 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
10496 return i;
10497 else
10498 return j;
10501 return bmap->n_ineq;
10504 /* Return the index of the equality of "bmap" that defines
10505 * the output dimension "pos" in terms of earlier dimensions.
10506 * The equality may also involve integer divisions, as long
10507 * as those integer divisions are defined in terms of
10508 * parameters or input dimensions.
10509 * In this case, *div is set to the number of integer divisions and
10510 * *ineq is set to the number of inequality constraints (provided
10511 * div and ineq are not NULL).
10513 * The equality may also involve a single integer division involving
10514 * the output dimensions (typically only output dimension "pos") as
10515 * long as the coefficient of output dimension "pos" is 1 or -1 and
10516 * there is a pair of constraints i >= l and i <= l + n, with i referring
10517 * to output dimension "pos", l an expression involving only earlier
10518 * dimensions and n smaller than the coefficient of the integer division
10519 * in the equality. In this case, the output dimension can be defined
10520 * in terms of a modulo expression that does not involve the integer division.
10521 * *div is then set to this single integer division and
10522 * *ineq is set to the index of constraint i >= l.
10524 * Return bmap->n_eq if there is no such equality.
10525 * Return -1 on error.
10527 int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
10528 int pos, int *div, int *ineq)
10530 int j, k, l;
10531 unsigned n_out, o_out;
10532 unsigned n_div, o_div;
10534 if (!bmap)
10535 return -1;
10537 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10538 o_out = isl_basic_map_offset(bmap, isl_dim_out);
10539 n_div = isl_basic_map_dim(bmap, isl_dim_div);
10540 o_div = isl_basic_map_offset(bmap, isl_dim_div);
10542 if (ineq)
10543 *ineq = bmap->n_ineq;
10544 if (div)
10545 *div = n_div;
10546 for (j = 0; j < bmap->n_eq; ++j) {
10547 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
10548 continue;
10549 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
10550 n_out - (pos + 1)) != -1)
10551 continue;
10552 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10553 0, n_div);
10554 if (k >= n_div)
10555 return j;
10556 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
10557 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
10558 continue;
10559 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
10560 k + 1, n_div - (k+1)) < n_div)
10561 continue;
10562 l = find_modulo_constraint_pair(bmap, pos,
10563 bmap->eq[j][o_div + k]);
10564 if (l < 0)
10565 return -1;
10566 if (l >= bmap->n_ineq)
10567 continue;
10568 if (div)
10569 *div = k;
10570 if (ineq)
10571 *ineq = l;
10572 return j;
10575 return bmap->n_eq;
10578 /* Check if the given basic map is obviously single-valued.
10579 * In particular, for each output dimension, check that there is
10580 * an equality that defines the output dimension in terms of
10581 * earlier dimensions.
10583 isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
10585 int i;
10586 unsigned n_out;
10588 if (!bmap)
10589 return isl_bool_error;
10591 n_out = isl_basic_map_dim(bmap, isl_dim_out);
10593 for (i = 0; i < n_out; ++i) {
10594 int eq;
10596 eq = isl_basic_map_output_defining_equality(bmap, i,
10597 NULL, NULL);
10598 if (eq < 0)
10599 return isl_bool_error;
10600 if (eq >= bmap->n_eq)
10601 return isl_bool_false;
10604 return isl_bool_true;
10607 /* Check if the given basic map is single-valued.
10608 * We simply compute
10610 * M \circ M^-1
10612 * and check if the result is a subset of the identity mapping.
10614 isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
10616 isl_space *space;
10617 isl_basic_map *test;
10618 isl_basic_map *id;
10619 isl_bool sv;
10621 sv = isl_basic_map_plain_is_single_valued(bmap);
10622 if (sv < 0 || sv)
10623 return sv;
10625 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
10626 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
10628 space = isl_basic_map_get_space(bmap);
10629 space = isl_space_map_from_set(isl_space_range(space));
10630 id = isl_basic_map_identity(space);
10632 sv = isl_basic_map_is_subset(test, id);
10634 isl_basic_map_free(test);
10635 isl_basic_map_free(id);
10637 return sv;
10640 /* Check if the given map is obviously single-valued.
10642 isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
10644 if (!map)
10645 return isl_bool_error;
10646 if (map->n == 0)
10647 return isl_bool_true;
10648 if (map->n >= 2)
10649 return isl_bool_false;
10651 return isl_basic_map_plain_is_single_valued(map->p[0]);
10654 /* Check if the given map is single-valued.
10655 * We simply compute
10657 * M \circ M^-1
10659 * and check if the result is a subset of the identity mapping.
10661 isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
10663 isl_space *dim;
10664 isl_map *test;
10665 isl_map *id;
10666 isl_bool sv;
10668 sv = isl_map_plain_is_single_valued(map);
10669 if (sv < 0 || sv)
10670 return sv;
10672 test = isl_map_reverse(isl_map_copy(map));
10673 test = isl_map_apply_range(test, isl_map_copy(map));
10675 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
10676 id = isl_map_identity(dim);
10678 sv = isl_map_is_subset(test, id);
10680 isl_map_free(test);
10681 isl_map_free(id);
10683 return sv;
10686 isl_bool isl_map_is_injective(__isl_keep isl_map *map)
10688 isl_bool in;
10690 map = isl_map_copy(map);
10691 map = isl_map_reverse(map);
10692 in = isl_map_is_single_valued(map);
10693 isl_map_free(map);
10695 return in;
10698 /* Check if the given map is obviously injective.
10700 isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
10702 isl_bool in;
10704 map = isl_map_copy(map);
10705 map = isl_map_reverse(map);
10706 in = isl_map_plain_is_single_valued(map);
10707 isl_map_free(map);
10709 return in;
10712 isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
10714 isl_bool sv;
10716 sv = isl_map_is_single_valued(map);
10717 if (sv < 0 || !sv)
10718 return sv;
10720 return isl_map_is_injective(map);
10723 isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
10725 return isl_map_is_single_valued(set_to_map(set));
10728 /* Does "map" only map elements to themselves?
10730 * If the domain and range spaces are different, then "map"
10731 * is considered not to be an identity relation, even if it is empty.
10732 * Otherwise, construct the maximal identity relation and
10733 * check whether "map" is a subset of this relation.
10735 isl_bool isl_map_is_identity(__isl_keep isl_map *map)
10737 isl_space *space;
10738 isl_map *id;
10739 isl_bool equal, is_identity;
10741 space = isl_map_get_space(map);
10742 equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
10743 isl_space_free(space);
10744 if (equal < 0 || !equal)
10745 return equal;
10747 id = isl_map_identity(isl_map_get_space(map));
10748 is_identity = isl_map_is_subset(map, id);
10749 isl_map_free(id);
10751 return is_identity;
10754 int isl_map_is_translation(__isl_keep isl_map *map)
10756 int ok;
10757 isl_set *delta;
10759 delta = isl_map_deltas(isl_map_copy(map));
10760 ok = isl_set_is_singleton(delta);
10761 isl_set_free(delta);
10763 return ok;
10766 static int unique(isl_int *p, unsigned pos, unsigned len)
10768 if (isl_seq_first_non_zero(p, pos) != -1)
10769 return 0;
10770 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
10771 return 0;
10772 return 1;
10775 isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
10777 int i, j;
10778 unsigned nvar;
10779 unsigned ovar;
10781 if (!bset)
10782 return isl_bool_error;
10784 if (isl_basic_set_dim(bset, isl_dim_div) != 0)
10785 return isl_bool_false;
10787 nvar = isl_basic_set_dim(bset, isl_dim_set);
10788 ovar = isl_space_offset(bset->dim, isl_dim_set);
10789 for (j = 0; j < nvar; ++j) {
10790 int lower = 0, upper = 0;
10791 for (i = 0; i < bset->n_eq; ++i) {
10792 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
10793 continue;
10794 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
10795 return isl_bool_false;
10796 break;
10798 if (i < bset->n_eq)
10799 continue;
10800 for (i = 0; i < bset->n_ineq; ++i) {
10801 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
10802 continue;
10803 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
10804 return isl_bool_false;
10805 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
10806 lower = 1;
10807 else
10808 upper = 1;
10810 if (!lower || !upper)
10811 return isl_bool_false;
10814 return isl_bool_true;
10817 isl_bool isl_set_is_box(__isl_keep isl_set *set)
10819 if (!set)
10820 return isl_bool_error;
10821 if (set->n != 1)
10822 return isl_bool_false;
10824 return isl_basic_set_is_box(set->p[0]);
10827 isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
10829 if (!bset)
10830 return isl_bool_error;
10832 return isl_space_is_wrapping(bset->dim);
10835 isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
10837 if (!set)
10838 return isl_bool_error;
10840 return isl_space_is_wrapping(set->dim);
10843 /* Modify the space of "map" through a call to "change".
10844 * If "can_change" is set (not NULL), then first call it to check
10845 * if the modification is allowed, printing the error message "cannot_change"
10846 * if it is not.
10848 static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
10849 isl_bool (*can_change)(__isl_keep isl_map *map),
10850 const char *cannot_change,
10851 __isl_give isl_space *(*change)(__isl_take isl_space *space))
10853 isl_bool ok;
10854 isl_space *space;
10856 if (!map)
10857 return NULL;
10859 ok = can_change ? can_change(map) : isl_bool_true;
10860 if (ok < 0)
10861 return isl_map_free(map);
10862 if (!ok)
10863 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
10864 return isl_map_free(map));
10866 space = change(isl_map_get_space(map));
10867 map = isl_map_reset_space(map, space);
10869 return map;
10872 /* Is the domain of "map" a wrapped relation?
10874 isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
10876 if (!map)
10877 return isl_bool_error;
10879 return isl_space_domain_is_wrapping(map->dim);
10882 /* Is the range of "map" a wrapped relation?
10884 isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
10886 if (!map)
10887 return isl_bool_error;
10889 return isl_space_range_is_wrapping(map->dim);
10892 __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
10894 bmap = isl_basic_map_cow(bmap);
10895 if (!bmap)
10896 return NULL;
10898 bmap->dim = isl_space_wrap(bmap->dim);
10899 if (!bmap->dim)
10900 goto error;
10902 bmap = isl_basic_map_finalize(bmap);
10904 return bset_from_bmap(bmap);
10905 error:
10906 isl_basic_map_free(bmap);
10907 return NULL;
10910 /* Given a map A -> B, return the set (A -> B).
10912 __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
10914 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
10917 __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
10919 bset = isl_basic_set_cow(bset);
10920 if (!bset)
10921 return NULL;
10923 bset->dim = isl_space_unwrap(bset->dim);
10924 if (!bset->dim)
10925 goto error;
10927 bset = isl_basic_set_finalize(bset);
10929 return bset_to_bmap(bset);
10930 error:
10931 isl_basic_set_free(bset);
10932 return NULL;
10935 /* Given a set (A -> B), return the map A -> B.
10936 * Error out if "set" is not of the form (A -> B).
10938 __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
10940 return isl_map_change_space(set, &isl_set_is_wrapping,
10941 "not a wrapping set", &isl_space_unwrap);
10944 __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
10945 enum isl_dim_type type)
10947 if (!bmap)
10948 return NULL;
10950 if (!isl_space_is_named_or_nested(bmap->dim, type))
10951 return bmap;
10953 bmap = isl_basic_map_cow(bmap);
10954 if (!bmap)
10955 return NULL;
10957 bmap->dim = isl_space_reset(bmap->dim, type);
10958 if (!bmap->dim)
10959 goto error;
10961 bmap = isl_basic_map_finalize(bmap);
10963 return bmap;
10964 error:
10965 isl_basic_map_free(bmap);
10966 return NULL;
10969 __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
10970 enum isl_dim_type type)
10972 int i;
10974 if (!map)
10975 return NULL;
10977 if (!isl_space_is_named_or_nested(map->dim, type))
10978 return map;
10980 map = isl_map_cow(map);
10981 if (!map)
10982 return NULL;
10984 for (i = 0; i < map->n; ++i) {
10985 map->p[i] = isl_basic_map_reset(map->p[i], type);
10986 if (!map->p[i])
10987 goto error;
10989 map->dim = isl_space_reset(map->dim, type);
10990 if (!map->dim)
10991 goto error;
10993 return map;
10994 error:
10995 isl_map_free(map);
10996 return NULL;
10999 __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
11001 if (!bmap)
11002 return NULL;
11004 if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
11005 return bmap;
11007 bmap = isl_basic_map_cow(bmap);
11008 if (!bmap)
11009 return NULL;
11011 bmap->dim = isl_space_flatten(bmap->dim);
11012 if (!bmap->dim)
11013 goto error;
11015 bmap = isl_basic_map_finalize(bmap);
11017 return bmap;
11018 error:
11019 isl_basic_map_free(bmap);
11020 return NULL;
11023 __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
11025 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
11028 __isl_give isl_basic_map *isl_basic_map_flatten_domain(
11029 __isl_take isl_basic_map *bmap)
11031 if (!bmap)
11032 return NULL;
11034 if (!bmap->dim->nested[0])
11035 return bmap;
11037 bmap = isl_basic_map_cow(bmap);
11038 if (!bmap)
11039 return NULL;
11041 bmap->dim = isl_space_flatten_domain(bmap->dim);
11042 if (!bmap->dim)
11043 goto error;
11045 bmap = isl_basic_map_finalize(bmap);
11047 return bmap;
11048 error:
11049 isl_basic_map_free(bmap);
11050 return NULL;
11053 __isl_give isl_basic_map *isl_basic_map_flatten_range(
11054 __isl_take isl_basic_map *bmap)
11056 if (!bmap)
11057 return NULL;
11059 if (!bmap->dim->nested[1])
11060 return bmap;
11062 bmap = isl_basic_map_cow(bmap);
11063 if (!bmap)
11064 return NULL;
11066 bmap->dim = isl_space_flatten_range(bmap->dim);
11067 if (!bmap->dim)
11068 goto error;
11070 bmap = isl_basic_map_finalize(bmap);
11072 return bmap;
11073 error:
11074 isl_basic_map_free(bmap);
11075 return NULL;
11078 /* Remove any internal structure from the spaces of domain and range of "map".
11080 __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
11082 if (!map)
11083 return NULL;
11085 if (!map->dim->nested[0] && !map->dim->nested[1])
11086 return map;
11088 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
11091 __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
11093 return set_from_map(isl_map_flatten(set_to_map(set)));
11096 __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
11098 isl_space *dim, *flat_dim;
11099 isl_map *map;
11101 dim = isl_set_get_space(set);
11102 flat_dim = isl_space_flatten(isl_space_copy(dim));
11103 map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
11104 map = isl_map_intersect_domain(map, set);
11106 return map;
11109 /* Remove any internal structure from the space of the domain of "map".
11111 __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
11113 if (!map)
11114 return NULL;
11116 if (!map->dim->nested[0])
11117 return map;
11119 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
11122 /* Remove any internal structure from the space of the range of "map".
11124 __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
11126 if (!map)
11127 return NULL;
11129 if (!map->dim->nested[1])
11130 return map;
11132 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
11135 /* Reorder the dimensions of "bmap" according to the given dim_map
11136 * and set the dimension specification to "dim" and
11137 * perform Gaussian elimination on the result.
11139 __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
11140 __isl_take isl_space *dim, __isl_take struct isl_dim_map *dim_map)
11142 isl_basic_map *res;
11143 unsigned flags;
11145 bmap = isl_basic_map_cow(bmap);
11146 if (!bmap || !dim || !dim_map)
11147 goto error;
11149 flags = bmap->flags;
11150 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
11151 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
11152 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
11153 res = isl_basic_map_alloc_space(dim,
11154 bmap->n_div, bmap->n_eq, bmap->n_ineq);
11155 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
11156 if (res)
11157 res->flags = flags;
11158 res = isl_basic_map_gauss(res, NULL);
11159 res = isl_basic_map_finalize(res);
11160 return res;
11161 error:
11162 free(dim_map);
11163 isl_basic_map_free(bmap);
11164 isl_space_free(dim);
11165 return NULL;
11168 /* Reorder the dimensions of "map" according to given reordering.
11170 __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
11171 __isl_take isl_reordering *r)
11173 int i;
11174 struct isl_dim_map *dim_map;
11176 map = isl_map_cow(map);
11177 dim_map = isl_dim_map_from_reordering(r);
11178 if (!map || !r || !dim_map)
11179 goto error;
11181 for (i = 0; i < map->n; ++i) {
11182 struct isl_dim_map *dim_map_i;
11184 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
11186 map->p[i] = isl_basic_map_realign(map->p[i],
11187 isl_space_copy(r->dim), dim_map_i);
11189 if (!map->p[i])
11190 goto error;
11193 map = isl_map_reset_space(map, isl_space_copy(r->dim));
11195 isl_reordering_free(r);
11196 free(dim_map);
11197 return map;
11198 error:
11199 free(dim_map);
11200 isl_map_free(map);
11201 isl_reordering_free(r);
11202 return NULL;
11205 __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
11206 __isl_take isl_reordering *r)
11208 return set_from_map(isl_map_realign(set_to_map(set), r));
11211 __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
11212 __isl_take isl_space *model)
11214 isl_ctx *ctx;
11216 if (!map || !model)
11217 goto error;
11219 ctx = isl_space_get_ctx(model);
11220 if (!isl_space_has_named_params(model))
11221 isl_die(ctx, isl_error_invalid,
11222 "model has unnamed parameters", goto error);
11223 if (!isl_space_has_named_params(map->dim))
11224 isl_die(ctx, isl_error_invalid,
11225 "relation has unnamed parameters", goto error);
11226 if (!isl_space_match(map->dim, isl_dim_param, model, isl_dim_param)) {
11227 isl_reordering *exp;
11229 model = isl_space_drop_dims(model, isl_dim_in,
11230 0, isl_space_dim(model, isl_dim_in));
11231 model = isl_space_drop_dims(model, isl_dim_out,
11232 0, isl_space_dim(model, isl_dim_out));
11233 exp = isl_parameter_alignment_reordering(map->dim, model);
11234 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
11235 map = isl_map_realign(map, exp);
11238 isl_space_free(model);
11239 return map;
11240 error:
11241 isl_space_free(model);
11242 isl_map_free(map);
11243 return NULL;
11246 __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
11247 __isl_take isl_space *model)
11249 return isl_map_align_params(set, model);
11252 /* Align the parameters of "bmap" to those of "model", introducing
11253 * additional parameters if needed.
11255 __isl_give isl_basic_map *isl_basic_map_align_params(
11256 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
11258 isl_ctx *ctx;
11260 if (!bmap || !model)
11261 goto error;
11263 ctx = isl_space_get_ctx(model);
11264 if (!isl_space_has_named_params(model))
11265 isl_die(ctx, isl_error_invalid,
11266 "model has unnamed parameters", goto error);
11267 if (!isl_space_has_named_params(bmap->dim))
11268 isl_die(ctx, isl_error_invalid,
11269 "relation has unnamed parameters", goto error);
11270 if (!isl_space_match(bmap->dim, isl_dim_param, model, isl_dim_param)) {
11271 isl_reordering *exp;
11272 struct isl_dim_map *dim_map;
11274 model = isl_space_drop_dims(model, isl_dim_in,
11275 0, isl_space_dim(model, isl_dim_in));
11276 model = isl_space_drop_dims(model, isl_dim_out,
11277 0, isl_space_dim(model, isl_dim_out));
11278 exp = isl_parameter_alignment_reordering(bmap->dim, model);
11279 exp = isl_reordering_extend_space(exp,
11280 isl_basic_map_get_space(bmap));
11281 dim_map = isl_dim_map_from_reordering(exp);
11282 bmap = isl_basic_map_realign(bmap,
11283 exp ? isl_space_copy(exp->dim) : NULL,
11284 isl_dim_map_extend(dim_map, bmap));
11285 isl_reordering_free(exp);
11286 free(dim_map);
11289 isl_space_free(model);
11290 return bmap;
11291 error:
11292 isl_space_free(model);
11293 isl_basic_map_free(bmap);
11294 return NULL;
11297 /* Align the parameters of "bset" to those of "model", introducing
11298 * additional parameters if needed.
11300 __isl_give isl_basic_set *isl_basic_set_align_params(
11301 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
11303 return isl_basic_map_align_params(bset, model);
11306 __isl_give isl_mat *isl_basic_map_equalities_matrix(
11307 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11308 enum isl_dim_type c2, enum isl_dim_type c3,
11309 enum isl_dim_type c4, enum isl_dim_type c5)
11311 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11312 struct isl_mat *mat;
11313 int i, j, k;
11314 int pos;
11316 if (!bmap)
11317 return NULL;
11318 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
11319 isl_basic_map_total_dim(bmap) + 1);
11320 if (!mat)
11321 return NULL;
11322 for (i = 0; i < bmap->n_eq; ++i)
11323 for (j = 0, pos = 0; j < 5; ++j) {
11324 int off = isl_basic_map_offset(bmap, c[j]);
11325 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11326 isl_int_set(mat->row[i][pos],
11327 bmap->eq[i][off + k]);
11328 ++pos;
11332 return mat;
11335 __isl_give isl_mat *isl_basic_map_inequalities_matrix(
11336 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
11337 enum isl_dim_type c2, enum isl_dim_type c3,
11338 enum isl_dim_type c4, enum isl_dim_type c5)
11340 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11341 struct isl_mat *mat;
11342 int i, j, k;
11343 int pos;
11345 if (!bmap)
11346 return NULL;
11347 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
11348 isl_basic_map_total_dim(bmap) + 1);
11349 if (!mat)
11350 return NULL;
11351 for (i = 0; i < bmap->n_ineq; ++i)
11352 for (j = 0, pos = 0; j < 5; ++j) {
11353 int off = isl_basic_map_offset(bmap, c[j]);
11354 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11355 isl_int_set(mat->row[i][pos],
11356 bmap->ineq[i][off + k]);
11357 ++pos;
11361 return mat;
11364 __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
11365 __isl_take isl_space *dim,
11366 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11367 enum isl_dim_type c2, enum isl_dim_type c3,
11368 enum isl_dim_type c4, enum isl_dim_type c5)
11370 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
11371 isl_basic_map *bmap;
11372 unsigned total;
11373 unsigned extra;
11374 int i, j, k, l;
11375 int pos;
11377 if (!dim || !eq || !ineq)
11378 goto error;
11380 if (eq->n_col != ineq->n_col)
11381 isl_die(dim->ctx, isl_error_invalid,
11382 "equalities and inequalities matrices should have "
11383 "same number of columns", goto error);
11385 total = 1 + isl_space_dim(dim, isl_dim_all);
11387 if (eq->n_col < total)
11388 isl_die(dim->ctx, isl_error_invalid,
11389 "number of columns too small", goto error);
11391 extra = eq->n_col - total;
11393 bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
11394 eq->n_row, ineq->n_row);
11395 if (!bmap)
11396 goto error;
11397 for (i = 0; i < extra; ++i) {
11398 k = isl_basic_map_alloc_div(bmap);
11399 if (k < 0)
11400 goto error;
11401 isl_int_set_si(bmap->div[k][0], 0);
11403 for (i = 0; i < eq->n_row; ++i) {
11404 l = isl_basic_map_alloc_equality(bmap);
11405 if (l < 0)
11406 goto error;
11407 for (j = 0, pos = 0; j < 5; ++j) {
11408 int off = isl_basic_map_offset(bmap, c[j]);
11409 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11410 isl_int_set(bmap->eq[l][off + k],
11411 eq->row[i][pos]);
11412 ++pos;
11416 for (i = 0; i < ineq->n_row; ++i) {
11417 l = isl_basic_map_alloc_inequality(bmap);
11418 if (l < 0)
11419 goto error;
11420 for (j = 0, pos = 0; j < 5; ++j) {
11421 int off = isl_basic_map_offset(bmap, c[j]);
11422 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
11423 isl_int_set(bmap->ineq[l][off + k],
11424 ineq->row[i][pos]);
11425 ++pos;
11430 isl_space_free(dim);
11431 isl_mat_free(eq);
11432 isl_mat_free(ineq);
11434 bmap = isl_basic_map_simplify(bmap);
11435 return isl_basic_map_finalize(bmap);
11436 error:
11437 isl_space_free(dim);
11438 isl_mat_free(eq);
11439 isl_mat_free(ineq);
11440 return NULL;
11443 __isl_give isl_mat *isl_basic_set_equalities_matrix(
11444 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11445 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11447 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
11448 c1, c2, c3, c4, isl_dim_in);
11451 __isl_give isl_mat *isl_basic_set_inequalities_matrix(
11452 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
11453 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11455 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
11456 c1, c2, c3, c4, isl_dim_in);
11459 __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
11460 __isl_take isl_space *dim,
11461 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
11462 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
11464 isl_basic_map *bmap;
11465 bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
11466 c1, c2, c3, c4, isl_dim_in);
11467 return bset_from_bmap(bmap);
11470 isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
11472 if (!bmap)
11473 return isl_bool_error;
11475 return isl_space_can_zip(bmap->dim);
11478 isl_bool isl_map_can_zip(__isl_keep isl_map *map)
11480 if (!map)
11481 return isl_bool_error;
11483 return isl_space_can_zip(map->dim);
11486 /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
11487 * (A -> C) -> (B -> D).
11489 __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
11491 unsigned pos;
11492 unsigned n1;
11493 unsigned n2;
11495 if (!bmap)
11496 return NULL;
11498 if (!isl_basic_map_can_zip(bmap))
11499 isl_die(bmap->ctx, isl_error_invalid,
11500 "basic map cannot be zipped", goto error);
11501 pos = isl_basic_map_offset(bmap, isl_dim_in) +
11502 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
11503 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
11504 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
11505 bmap = isl_basic_map_cow(bmap);
11506 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
11507 if (!bmap)
11508 return NULL;
11509 bmap->dim = isl_space_zip(bmap->dim);
11510 if (!bmap->dim)
11511 goto error;
11512 bmap = isl_basic_map_mark_final(bmap);
11513 return bmap;
11514 error:
11515 isl_basic_map_free(bmap);
11516 return NULL;
11519 /* Given a map (A -> B) -> (C -> D), return the corresponding map
11520 * (A -> C) -> (B -> D).
11522 __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
11524 int i;
11526 if (!map)
11527 return NULL;
11529 if (!isl_map_can_zip(map))
11530 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
11531 goto error);
11533 map = isl_map_cow(map);
11534 if (!map)
11535 return NULL;
11537 for (i = 0; i < map->n; ++i) {
11538 map->p[i] = isl_basic_map_zip(map->p[i]);
11539 if (!map->p[i])
11540 goto error;
11543 map->dim = isl_space_zip(map->dim);
11544 if (!map->dim)
11545 goto error;
11547 return map;
11548 error:
11549 isl_map_free(map);
11550 return NULL;
11553 /* Can we apply isl_basic_map_curry to "bmap"?
11554 * That is, does it have a nested relation in its domain?
11556 isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
11558 if (!bmap)
11559 return isl_bool_error;
11561 return isl_space_can_curry(bmap->dim);
11564 /* Can we apply isl_map_curry to "map"?
11565 * That is, does it have a nested relation in its domain?
11567 isl_bool isl_map_can_curry(__isl_keep isl_map *map)
11569 if (!map)
11570 return isl_bool_error;
11572 return isl_space_can_curry(map->dim);
11575 /* Given a basic map (A -> B) -> C, return the corresponding basic map
11576 * A -> (B -> C).
11578 __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
11581 if (!bmap)
11582 return NULL;
11584 if (!isl_basic_map_can_curry(bmap))
11585 isl_die(bmap->ctx, isl_error_invalid,
11586 "basic map cannot be curried", goto error);
11587 bmap = isl_basic_map_cow(bmap);
11588 if (!bmap)
11589 return NULL;
11590 bmap->dim = isl_space_curry(bmap->dim);
11591 if (!bmap->dim)
11592 goto error;
11593 bmap = isl_basic_map_mark_final(bmap);
11594 return bmap;
11595 error:
11596 isl_basic_map_free(bmap);
11597 return NULL;
11600 /* Given a map (A -> B) -> C, return the corresponding map
11601 * A -> (B -> C).
11603 __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
11605 return isl_map_change_space(map, &isl_map_can_curry,
11606 "map cannot be curried", &isl_space_curry);
11609 /* Can isl_map_range_curry be applied to "map"?
11610 * That is, does it have a nested relation in its range,
11611 * the domain of which is itself a nested relation?
11613 isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
11615 if (!map)
11616 return isl_bool_error;
11618 return isl_space_can_range_curry(map->dim);
11621 /* Given a map A -> ((B -> C) -> D), return the corresponding map
11622 * A -> (B -> (C -> D)).
11624 __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
11626 return isl_map_change_space(map, &isl_map_can_range_curry,
11627 "map range cannot be curried",
11628 &isl_space_range_curry);
11631 /* Can we apply isl_basic_map_uncurry to "bmap"?
11632 * That is, does it have a nested relation in its domain?
11634 isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
11636 if (!bmap)
11637 return isl_bool_error;
11639 return isl_space_can_uncurry(bmap->dim);
11642 /* Can we apply isl_map_uncurry to "map"?
11643 * That is, does it have a nested relation in its domain?
11645 isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
11647 if (!map)
11648 return isl_bool_error;
11650 return isl_space_can_uncurry(map->dim);
11653 /* Given a basic map A -> (B -> C), return the corresponding basic map
11654 * (A -> B) -> C.
11656 __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
11659 if (!bmap)
11660 return NULL;
11662 if (!isl_basic_map_can_uncurry(bmap))
11663 isl_die(bmap->ctx, isl_error_invalid,
11664 "basic map cannot be uncurried",
11665 return isl_basic_map_free(bmap));
11666 bmap = isl_basic_map_cow(bmap);
11667 if (!bmap)
11668 return NULL;
11669 bmap->dim = isl_space_uncurry(bmap->dim);
11670 if (!bmap->dim)
11671 return isl_basic_map_free(bmap);
11672 bmap = isl_basic_map_mark_final(bmap);
11673 return bmap;
11676 /* Given a map A -> (B -> C), return the corresponding map
11677 * (A -> B) -> C.
11679 __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
11681 return isl_map_change_space(map, &isl_map_can_uncurry,
11682 "map cannot be uncurried", &isl_space_uncurry);
11685 /* Construct a basic map mapping the domain of the affine expression
11686 * to a one-dimensional range prescribed by the affine expression.
11687 * If "rational" is set, then construct a rational basic map.
11689 * A NaN affine expression cannot be converted to a basic map.
11691 static __isl_give isl_basic_map *isl_basic_map_from_aff2(
11692 __isl_take isl_aff *aff, int rational)
11694 int k;
11695 int pos;
11696 isl_bool is_nan;
11697 isl_local_space *ls;
11698 isl_basic_map *bmap = NULL;
11700 if (!aff)
11701 return NULL;
11702 is_nan = isl_aff_is_nan(aff);
11703 if (is_nan < 0)
11704 goto error;
11705 if (is_nan)
11706 isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
11707 "cannot convert NaN", goto error);
11709 ls = isl_aff_get_local_space(aff);
11710 bmap = isl_basic_map_from_local_space(ls);
11711 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
11712 k = isl_basic_map_alloc_equality(bmap);
11713 if (k < 0)
11714 goto error;
11716 pos = isl_basic_map_offset(bmap, isl_dim_out);
11717 isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos);
11718 isl_int_neg(bmap->eq[k][pos], aff->v->el[0]);
11719 isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos,
11720 aff->v->size - (pos + 1));
11722 isl_aff_free(aff);
11723 if (rational)
11724 bmap = isl_basic_map_set_rational(bmap);
11725 bmap = isl_basic_map_finalize(bmap);
11726 return bmap;
11727 error:
11728 isl_aff_free(aff);
11729 isl_basic_map_free(bmap);
11730 return NULL;
11733 /* Construct a basic map mapping the domain of the affine expression
11734 * to a one-dimensional range prescribed by the affine expression.
11736 __isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff)
11738 return isl_basic_map_from_aff2(aff, 0);
11741 /* Construct a map mapping the domain of the affine expression
11742 * to a one-dimensional range prescribed by the affine expression.
11744 __isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff)
11746 isl_basic_map *bmap;
11748 bmap = isl_basic_map_from_aff(aff);
11749 return isl_map_from_basic_map(bmap);
11752 /* Construct a basic map mapping the domain the multi-affine expression
11753 * to its range, with each dimension in the range equated to the
11754 * corresponding affine expression.
11755 * If "rational" is set, then construct a rational basic map.
11757 __isl_give isl_basic_map *isl_basic_map_from_multi_aff2(
11758 __isl_take isl_multi_aff *maff, int rational)
11760 int i;
11761 isl_space *space;
11762 isl_basic_map *bmap;
11764 if (!maff)
11765 return NULL;
11767 if (isl_space_dim(maff->space, isl_dim_out) != maff->n)
11768 isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal,
11769 "invalid space", goto error);
11771 space = isl_space_domain(isl_multi_aff_get_space(maff));
11772 bmap = isl_basic_map_universe(isl_space_from_domain(space));
11773 if (rational)
11774 bmap = isl_basic_map_set_rational(bmap);
11776 for (i = 0; i < maff->n; ++i) {
11777 isl_aff *aff;
11778 isl_basic_map *bmap_i;
11780 aff = isl_aff_copy(maff->p[i]);
11781 bmap_i = isl_basic_map_from_aff2(aff, rational);
11783 bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11786 bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff));
11788 isl_multi_aff_free(maff);
11789 return bmap;
11790 error:
11791 isl_multi_aff_free(maff);
11792 return NULL;
11795 /* Construct a basic map mapping the domain the multi-affine expression
11796 * to its range, with each dimension in the range equated to the
11797 * corresponding affine expression.
11799 __isl_give isl_basic_map *isl_basic_map_from_multi_aff(
11800 __isl_take isl_multi_aff *ma)
11802 return isl_basic_map_from_multi_aff2(ma, 0);
11805 /* Construct a map mapping the domain the multi-affine expression
11806 * to its range, with each dimension in the range equated to the
11807 * corresponding affine expression.
11809 __isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff)
11811 isl_basic_map *bmap;
11813 bmap = isl_basic_map_from_multi_aff(maff);
11814 return isl_map_from_basic_map(bmap);
11817 /* Construct a basic map mapping a domain in the given space to
11818 * to an n-dimensional range, with n the number of elements in the list,
11819 * where each coordinate in the range is prescribed by the
11820 * corresponding affine expression.
11821 * The domains of all affine expressions in the list are assumed to match
11822 * domain_dim.
11824 __isl_give isl_basic_map *isl_basic_map_from_aff_list(
11825 __isl_take isl_space *domain_dim, __isl_take isl_aff_list *list)
11827 int i;
11828 isl_space *dim;
11829 isl_basic_map *bmap;
11831 if (!list)
11832 return NULL;
11834 dim = isl_space_from_domain(domain_dim);
11835 bmap = isl_basic_map_universe(dim);
11837 for (i = 0; i < list->n; ++i) {
11838 isl_aff *aff;
11839 isl_basic_map *bmap_i;
11841 aff = isl_aff_copy(list->p[i]);
11842 bmap_i = isl_basic_map_from_aff(aff);
11844 bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
11847 isl_aff_list_free(list);
11848 return bmap;
11851 __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
11852 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11854 return isl_map_equate(set, type1, pos1, type2, pos2);
11857 /* Construct a basic map where the given dimensions are equal to each other.
11859 static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
11860 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11862 isl_basic_map *bmap = NULL;
11863 int i;
11865 if (!space)
11866 return NULL;
11868 if (pos1 >= isl_space_dim(space, type1))
11869 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11870 "index out of bounds", goto error);
11871 if (pos2 >= isl_space_dim(space, type2))
11872 isl_die(isl_space_get_ctx(space), isl_error_invalid,
11873 "index out of bounds", goto error);
11875 if (type1 == type2 && pos1 == pos2)
11876 return isl_basic_map_universe(space);
11878 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
11879 i = isl_basic_map_alloc_equality(bmap);
11880 if (i < 0)
11881 goto error;
11882 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11883 pos1 += isl_basic_map_offset(bmap, type1);
11884 pos2 += isl_basic_map_offset(bmap, type2);
11885 isl_int_set_si(bmap->eq[i][pos1], -1);
11886 isl_int_set_si(bmap->eq[i][pos2], 1);
11887 bmap = isl_basic_map_finalize(bmap);
11888 isl_space_free(space);
11889 return bmap;
11890 error:
11891 isl_space_free(space);
11892 isl_basic_map_free(bmap);
11893 return NULL;
11896 /* Add a constraint imposing that the given two dimensions are equal.
11898 __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
11899 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11901 isl_basic_map *eq;
11903 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
11905 bmap = isl_basic_map_intersect(bmap, eq);
11907 return bmap;
11910 /* Add a constraint imposing that the given two dimensions are equal.
11912 __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
11913 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11915 isl_basic_map *bmap;
11917 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
11919 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11921 return map;
11924 /* Add a constraint imposing that the given two dimensions have opposite values.
11926 __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
11927 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11929 isl_basic_map *bmap = NULL;
11930 int i;
11932 if (!map)
11933 return NULL;
11935 if (pos1 >= isl_map_dim(map, type1))
11936 isl_die(map->ctx, isl_error_invalid,
11937 "index out of bounds", goto error);
11938 if (pos2 >= isl_map_dim(map, type2))
11939 isl_die(map->ctx, isl_error_invalid,
11940 "index out of bounds", goto error);
11942 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
11943 i = isl_basic_map_alloc_equality(bmap);
11944 if (i < 0)
11945 goto error;
11946 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
11947 pos1 += isl_basic_map_offset(bmap, type1);
11948 pos2 += isl_basic_map_offset(bmap, type2);
11949 isl_int_set_si(bmap->eq[i][pos1], 1);
11950 isl_int_set_si(bmap->eq[i][pos2], 1);
11951 bmap = isl_basic_map_finalize(bmap);
11953 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
11955 return map;
11956 error:
11957 isl_basic_map_free(bmap);
11958 isl_map_free(map);
11959 return NULL;
11962 /* Construct a constraint imposing that the value of the first dimension is
11963 * greater than or equal to that of the second.
11965 static __isl_give isl_constraint *constraint_order_ge(
11966 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
11967 enum isl_dim_type type2, int pos2)
11969 isl_constraint *c;
11971 if (!space)
11972 return NULL;
11974 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
11976 if (pos1 >= isl_constraint_dim(c, type1))
11977 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
11978 "index out of bounds", return isl_constraint_free(c));
11979 if (pos2 >= isl_constraint_dim(c, type2))
11980 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
11981 "index out of bounds", return isl_constraint_free(c));
11983 if (type1 == type2 && pos1 == pos2)
11984 return c;
11986 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
11987 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
11989 return c;
11992 /* Add a constraint imposing that the value of the first dimension is
11993 * greater than or equal to that of the second.
11995 __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
11996 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
11998 isl_constraint *c;
11999 isl_space *space;
12001 if (type1 == type2 && pos1 == pos2)
12002 return bmap;
12003 space = isl_basic_map_get_space(bmap);
12004 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12005 bmap = isl_basic_map_add_constraint(bmap, c);
12007 return bmap;
12010 /* Add a constraint imposing that the value of the first dimension is
12011 * greater than or equal to that of the second.
12013 __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
12014 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12016 isl_constraint *c;
12017 isl_space *space;
12019 if (type1 == type2 && pos1 == pos2)
12020 return map;
12021 space = isl_map_get_space(map);
12022 c = constraint_order_ge(space, type1, pos1, type2, pos2);
12023 map = isl_map_add_constraint(map, c);
12025 return map;
12028 /* Add a constraint imposing that the value of the first dimension is
12029 * less than or equal to that of the second.
12031 __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
12032 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12034 return isl_map_order_ge(map, type2, pos2, type1, pos1);
12037 /* Construct a basic map where the value of the first dimension is
12038 * greater than that of the second.
12040 static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
12041 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12043 isl_basic_map *bmap = NULL;
12044 int i;
12046 if (!space)
12047 return NULL;
12049 if (pos1 >= isl_space_dim(space, type1))
12050 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12051 "index out of bounds", goto error);
12052 if (pos2 >= isl_space_dim(space, type2))
12053 isl_die(isl_space_get_ctx(space), isl_error_invalid,
12054 "index out of bounds", goto error);
12056 if (type1 == type2 && pos1 == pos2)
12057 return isl_basic_map_empty(space);
12059 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
12060 i = isl_basic_map_alloc_inequality(bmap);
12061 if (i < 0)
12062 return isl_basic_map_free(bmap);
12063 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
12064 pos1 += isl_basic_map_offset(bmap, type1);
12065 pos2 += isl_basic_map_offset(bmap, type2);
12066 isl_int_set_si(bmap->ineq[i][pos1], 1);
12067 isl_int_set_si(bmap->ineq[i][pos2], -1);
12068 isl_int_set_si(bmap->ineq[i][0], -1);
12069 bmap = isl_basic_map_finalize(bmap);
12071 return bmap;
12072 error:
12073 isl_space_free(space);
12074 isl_basic_map_free(bmap);
12075 return NULL;
12078 /* Add a constraint imposing that the value of the first dimension is
12079 * greater than that of the second.
12081 __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
12082 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12084 isl_basic_map *gt;
12086 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
12088 bmap = isl_basic_map_intersect(bmap, gt);
12090 return bmap;
12093 /* Add a constraint imposing that the value of the first dimension is
12094 * greater than that of the second.
12096 __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
12097 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12099 isl_basic_map *bmap;
12101 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
12103 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
12105 return map;
12108 /* Add a constraint imposing that the value of the first dimension is
12109 * smaller than that of the second.
12111 __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
12112 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
12114 return isl_map_order_gt(map, type2, pos2, type1, pos1);
12117 __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
12118 int pos)
12120 isl_aff *div;
12121 isl_local_space *ls;
12123 if (!bmap)
12124 return NULL;
12126 if (!isl_basic_map_divs_known(bmap))
12127 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12128 "some divs are unknown", return NULL);
12130 ls = isl_basic_map_get_local_space(bmap);
12131 div = isl_local_space_get_div(ls, pos);
12132 isl_local_space_free(ls);
12134 return div;
12137 __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
12138 int pos)
12140 return isl_basic_map_get_div(bset, pos);
12143 /* Plug in "subs" for dimension "type", "pos" of "bset".
12145 * Let i be the dimension to replace and let "subs" be of the form
12147 * f/d
12149 * Any integer division with a non-zero coefficient for i,
12151 * floor((a i + g)/m)
12153 * is replaced by
12155 * floor((a f + d g)/(m d))
12157 * Constraints of the form
12159 * a i + g
12161 * are replaced by
12163 * a f + d g
12165 * We currently require that "subs" is an integral expression.
12166 * Handling rational expressions may require us to add stride constraints
12167 * as we do in isl_basic_set_preimage_multi_aff.
12169 __isl_give isl_basic_set *isl_basic_set_substitute(
12170 __isl_take isl_basic_set *bset,
12171 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12173 int i;
12174 isl_int v;
12175 isl_ctx *ctx;
12177 if (bset && isl_basic_set_plain_is_empty(bset))
12178 return bset;
12180 bset = isl_basic_set_cow(bset);
12181 if (!bset || !subs)
12182 goto error;
12184 ctx = isl_basic_set_get_ctx(bset);
12185 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
12186 isl_die(ctx, isl_error_invalid,
12187 "spaces don't match", goto error);
12188 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
12189 isl_die(ctx, isl_error_unsupported,
12190 "cannot handle divs yet", goto error);
12191 if (!isl_int_is_one(subs->v->el[0]))
12192 isl_die(ctx, isl_error_invalid,
12193 "can only substitute integer expressions", goto error);
12195 pos += isl_basic_set_offset(bset, type);
12197 isl_int_init(v);
12199 for (i = 0; i < bset->n_eq; ++i) {
12200 if (isl_int_is_zero(bset->eq[i][pos]))
12201 continue;
12202 isl_int_set(v, bset->eq[i][pos]);
12203 isl_int_set_si(bset->eq[i][pos], 0);
12204 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
12205 v, subs->v->el + 1, subs->v->size - 1);
12208 for (i = 0; i < bset->n_ineq; ++i) {
12209 if (isl_int_is_zero(bset->ineq[i][pos]))
12210 continue;
12211 isl_int_set(v, bset->ineq[i][pos]);
12212 isl_int_set_si(bset->ineq[i][pos], 0);
12213 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
12214 v, subs->v->el + 1, subs->v->size - 1);
12217 for (i = 0; i < bset->n_div; ++i) {
12218 if (isl_int_is_zero(bset->div[i][1 + pos]))
12219 continue;
12220 isl_int_set(v, bset->div[i][1 + pos]);
12221 isl_int_set_si(bset->div[i][1 + pos], 0);
12222 isl_seq_combine(bset->div[i] + 1,
12223 subs->v->el[0], bset->div[i] + 1,
12224 v, subs->v->el + 1, subs->v->size - 1);
12225 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
12228 isl_int_clear(v);
12230 bset = isl_basic_set_simplify(bset);
12231 return isl_basic_set_finalize(bset);
12232 error:
12233 isl_basic_set_free(bset);
12234 return NULL;
12237 /* Plug in "subs" for dimension "type", "pos" of "set".
12239 __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
12240 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
12242 int i;
12244 if (set && isl_set_plain_is_empty(set))
12245 return set;
12247 set = isl_set_cow(set);
12248 if (!set || !subs)
12249 goto error;
12251 for (i = set->n - 1; i >= 0; --i) {
12252 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
12253 if (remove_if_empty(set, i) < 0)
12254 goto error;
12257 return set;
12258 error:
12259 isl_set_free(set);
12260 return NULL;
12263 /* Check if the range of "ma" is compatible with the domain or range
12264 * (depending on "type") of "bmap".
12266 static isl_stat check_basic_map_compatible_range_multi_aff(
12267 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
12268 __isl_keep isl_multi_aff *ma)
12270 isl_bool m;
12271 isl_space *ma_space;
12273 ma_space = isl_multi_aff_get_space(ma);
12275 m = isl_space_match(bmap->dim, isl_dim_param, ma_space, isl_dim_param);
12276 if (m < 0)
12277 goto error;
12278 if (!m)
12279 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12280 "parameters don't match", goto error);
12281 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
12282 if (m < 0)
12283 goto error;
12284 if (!m)
12285 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
12286 "spaces don't match", goto error);
12288 isl_space_free(ma_space);
12289 return isl_stat_ok;
12290 error:
12291 isl_space_free(ma_space);
12292 return isl_stat_error;
12295 /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
12296 * coefficients before the transformed range of dimensions,
12297 * the "n_after" coefficients after the transformed range of dimensions
12298 * and the coefficients of the other divs in "bmap".
12300 static int set_ma_divs(__isl_keep isl_basic_map *bmap,
12301 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
12303 int i;
12304 int n_param;
12305 int n_set;
12306 isl_local_space *ls;
12308 if (n_div == 0)
12309 return 0;
12311 ls = isl_aff_get_domain_local_space(ma->p[0]);
12312 if (!ls)
12313 return -1;
12315 n_param = isl_local_space_dim(ls, isl_dim_param);
12316 n_set = isl_local_space_dim(ls, isl_dim_set);
12317 for (i = 0; i < n_div; ++i) {
12318 int o_bmap = 0, o_ls = 0;
12320 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
12321 o_bmap += 1 + 1 + n_param;
12322 o_ls += 1 + 1 + n_param;
12323 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
12324 o_bmap += n_before;
12325 isl_seq_cpy(bmap->div[i] + o_bmap,
12326 ls->div->row[i] + o_ls, n_set);
12327 o_bmap += n_set;
12328 o_ls += n_set;
12329 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
12330 o_bmap += n_after;
12331 isl_seq_cpy(bmap->div[i] + o_bmap,
12332 ls->div->row[i] + o_ls, n_div);
12333 o_bmap += n_div;
12334 o_ls += n_div;
12335 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
12336 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
12337 goto error;
12340 isl_local_space_free(ls);
12341 return 0;
12342 error:
12343 isl_local_space_free(ls);
12344 return -1;
12347 /* How many stride constraints does "ma" enforce?
12348 * That is, how many of the affine expressions have a denominator
12349 * different from one?
12351 static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
12353 int i;
12354 int strides = 0;
12356 for (i = 0; i < ma->n; ++i)
12357 if (!isl_int_is_one(ma->p[i]->v->el[0]))
12358 strides++;
12360 return strides;
12363 /* For each affine expression in ma of the form
12365 * x_i = (f_i y + h_i)/m_i
12367 * with m_i different from one, add a constraint to "bmap"
12368 * of the form
12370 * f_i y + h_i = m_i alpha_i
12372 * with alpha_i an additional existentially quantified variable.
12374 * The input variables of "ma" correspond to a subset of the variables
12375 * of "bmap". There are "n_before" variables in "bmap" before this
12376 * subset and "n_after" variables after this subset.
12377 * The integer divisions of the affine expressions in "ma" are assumed
12378 * to have been aligned. There are "n_div_ma" of them and
12379 * they appear first in "bmap", straight after the "n_after" variables.
12381 static __isl_give isl_basic_map *add_ma_strides(
12382 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
12383 int n_before, int n_after, int n_div_ma)
12385 int i, k;
12386 int div;
12387 int total;
12388 int n_param;
12389 int n_in;
12391 total = isl_basic_map_total_dim(bmap);
12392 n_param = isl_multi_aff_dim(ma, isl_dim_param);
12393 n_in = isl_multi_aff_dim(ma, isl_dim_in);
12394 for (i = 0; i < ma->n; ++i) {
12395 int o_bmap = 0, o_ma = 1;
12397 if (isl_int_is_one(ma->p[i]->v->el[0]))
12398 continue;
12399 div = isl_basic_map_alloc_div(bmap);
12400 k = isl_basic_map_alloc_equality(bmap);
12401 if (div < 0 || k < 0)
12402 goto error;
12403 isl_int_set_si(bmap->div[div][0], 0);
12404 isl_seq_cpy(bmap->eq[k] + o_bmap,
12405 ma->p[i]->v->el + o_ma, 1 + n_param);
12406 o_bmap += 1 + n_param;
12407 o_ma += 1 + n_param;
12408 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
12409 o_bmap += n_before;
12410 isl_seq_cpy(bmap->eq[k] + o_bmap,
12411 ma->p[i]->v->el + o_ma, n_in);
12412 o_bmap += n_in;
12413 o_ma += n_in;
12414 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
12415 o_bmap += n_after;
12416 isl_seq_cpy(bmap->eq[k] + o_bmap,
12417 ma->p[i]->v->el + o_ma, n_div_ma);
12418 o_bmap += n_div_ma;
12419 o_ma += n_div_ma;
12420 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
12421 isl_int_neg(bmap->eq[k][1 + total], ma->p[i]->v->el[0]);
12422 total++;
12425 return bmap;
12426 error:
12427 isl_basic_map_free(bmap);
12428 return NULL;
12431 /* Replace the domain or range space (depending on "type) of "space" by "set".
12433 static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
12434 enum isl_dim_type type, __isl_take isl_space *set)
12436 if (type == isl_dim_in) {
12437 space = isl_space_range(space);
12438 space = isl_space_map_from_domain_and_range(set, space);
12439 } else {
12440 space = isl_space_domain(space);
12441 space = isl_space_map_from_domain_and_range(space, set);
12444 return space;
12447 /* Compute the preimage of the domain or range (depending on "type")
12448 * of "bmap" under the function represented by "ma".
12449 * In other words, plug in "ma" in the domain or range of "bmap".
12450 * The result is a basic map that lives in the same space as "bmap"
12451 * except that the domain or range has been replaced by
12452 * the domain space of "ma".
12454 * If bmap is represented by
12456 * A(p) + S u + B x + T v + C(divs) >= 0,
12458 * where u and x are input and output dimensions if type == isl_dim_out
12459 * while x and v are input and output dimensions if type == isl_dim_in,
12460 * and ma is represented by
12462 * x = D(p) + F(y) + G(divs')
12464 * then the result is
12466 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
12468 * The divs in the input set are similarly adjusted.
12469 * In particular
12471 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
12473 * becomes
12475 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
12476 * B_i G(divs') + c_i(divs))/n_i)
12478 * If bmap is not a rational map and if F(y) involves any denominators
12480 * x_i = (f_i y + h_i)/m_i
12482 * then additional constraints are added to ensure that we only
12483 * map back integer points. That is we enforce
12485 * f_i y + h_i = m_i alpha_i
12487 * with alpha_i an additional existentially quantified variable.
12489 * We first copy over the divs from "ma".
12490 * Then we add the modified constraints and divs from "bmap".
12491 * Finally, we add the stride constraints, if needed.
12493 __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
12494 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
12495 __isl_take isl_multi_aff *ma)
12497 int i, k;
12498 isl_space *space;
12499 isl_basic_map *res = NULL;
12500 int n_before, n_after, n_div_bmap, n_div_ma;
12501 isl_int f, c1, c2, g;
12502 isl_bool rational;
12503 int strides;
12505 isl_int_init(f);
12506 isl_int_init(c1);
12507 isl_int_init(c2);
12508 isl_int_init(g);
12510 ma = isl_multi_aff_align_divs(ma);
12511 if (!bmap || !ma)
12512 goto error;
12513 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
12514 goto error;
12516 if (type == isl_dim_in) {
12517 n_before = 0;
12518 n_after = isl_basic_map_dim(bmap, isl_dim_out);
12519 } else {
12520 n_before = isl_basic_map_dim(bmap, isl_dim_in);
12521 n_after = 0;
12523 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
12524 n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
12526 space = isl_multi_aff_get_domain_space(ma);
12527 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
12528 rational = isl_basic_map_is_rational(bmap);
12529 strides = rational ? 0 : multi_aff_strides(ma);
12530 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
12531 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
12532 if (rational)
12533 res = isl_basic_map_set_rational(res);
12535 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
12536 if (isl_basic_map_alloc_div(res) < 0)
12537 goto error;
12539 if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
12540 goto error;
12542 for (i = 0; i < bmap->n_eq; ++i) {
12543 k = isl_basic_map_alloc_equality(res);
12544 if (k < 0)
12545 goto error;
12546 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
12547 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12550 for (i = 0; i < bmap->n_ineq; ++i) {
12551 k = isl_basic_map_alloc_inequality(res);
12552 if (k < 0)
12553 goto error;
12554 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
12555 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
12558 for (i = 0; i < bmap->n_div; ++i) {
12559 if (isl_int_is_zero(bmap->div[i][0])) {
12560 isl_int_set_si(res->div[n_div_ma + i][0], 0);
12561 continue;
12563 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
12564 n_before, n_after, n_div_ma, n_div_bmap,
12565 f, c1, c2, g, 1);
12568 if (strides)
12569 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
12571 isl_int_clear(f);
12572 isl_int_clear(c1);
12573 isl_int_clear(c2);
12574 isl_int_clear(g);
12575 isl_basic_map_free(bmap);
12576 isl_multi_aff_free(ma);
12577 res = isl_basic_map_simplify(res);
12578 return isl_basic_map_finalize(res);
12579 error:
12580 isl_int_clear(f);
12581 isl_int_clear(c1);
12582 isl_int_clear(c2);
12583 isl_int_clear(g);
12584 isl_basic_map_free(bmap);
12585 isl_multi_aff_free(ma);
12586 isl_basic_map_free(res);
12587 return NULL;
12590 /* Compute the preimage of "bset" under the function represented by "ma".
12591 * In other words, plug in "ma" in "bset". The result is a basic set
12592 * that lives in the domain space of "ma".
12594 __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
12595 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
12597 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
12600 /* Compute the preimage of the domain of "bmap" under the function
12601 * represented by "ma".
12602 * In other words, plug in "ma" in the domain of "bmap".
12603 * The result is a basic map that lives in the same space as "bmap"
12604 * except that the domain has been replaced by the domain space of "ma".
12606 __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
12607 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12609 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
12612 /* Compute the preimage of the range of "bmap" under the function
12613 * represented by "ma".
12614 * In other words, plug in "ma" in the range of "bmap".
12615 * The result is a basic map that lives in the same space as "bmap"
12616 * except that the range has been replaced by the domain space of "ma".
12618 __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
12619 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
12621 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
12624 /* Check if the range of "ma" is compatible with the domain or range
12625 * (depending on "type") of "map".
12626 * Return isl_stat_error if anything is wrong.
12628 static isl_stat check_map_compatible_range_multi_aff(
12629 __isl_keep isl_map *map, enum isl_dim_type type,
12630 __isl_keep isl_multi_aff *ma)
12632 isl_bool m;
12633 isl_space *ma_space;
12635 ma_space = isl_multi_aff_get_space(ma);
12636 m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
12637 isl_space_free(ma_space);
12638 if (m < 0)
12639 return isl_stat_error;
12640 if (!m)
12641 isl_die(isl_map_get_ctx(map), isl_error_invalid,
12642 "spaces don't match", return isl_stat_error);
12643 return isl_stat_ok;
12646 /* Compute the preimage of the domain or range (depending on "type")
12647 * of "map" under the function represented by "ma".
12648 * In other words, plug in "ma" in the domain or range of "map".
12649 * The result is a map that lives in the same space as "map"
12650 * except that the domain or range has been replaced by
12651 * the domain space of "ma".
12653 * The parameters are assumed to have been aligned.
12655 static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
12656 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12658 int i;
12659 isl_space *space;
12661 map = isl_map_cow(map);
12662 ma = isl_multi_aff_align_divs(ma);
12663 if (!map || !ma)
12664 goto error;
12665 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
12666 goto error;
12668 for (i = 0; i < map->n; ++i) {
12669 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
12670 isl_multi_aff_copy(ma));
12671 if (!map->p[i])
12672 goto error;
12675 space = isl_multi_aff_get_domain_space(ma);
12676 space = isl_space_set(isl_map_get_space(map), type, space);
12678 isl_space_free(map->dim);
12679 map->dim = space;
12680 if (!map->dim)
12681 goto error;
12683 isl_multi_aff_free(ma);
12684 if (map->n > 1)
12685 ISL_F_CLR(map, ISL_MAP_DISJOINT);
12686 ISL_F_CLR(map, ISL_SET_NORMALIZED);
12687 return map;
12688 error:
12689 isl_multi_aff_free(ma);
12690 isl_map_free(map);
12691 return NULL;
12694 /* Compute the preimage of the domain or range (depending on "type")
12695 * of "map" under the function represented by "ma".
12696 * In other words, plug in "ma" in the domain or range of "map".
12697 * The result is a map that lives in the same space as "map"
12698 * except that the domain or range has been replaced by
12699 * the domain space of "ma".
12701 __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
12702 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
12704 if (!map || !ma)
12705 goto error;
12707 if (isl_space_match(map->dim, isl_dim_param, ma->space, isl_dim_param))
12708 return map_preimage_multi_aff(map, type, ma);
12710 if (!isl_space_has_named_params(map->dim) ||
12711 !isl_space_has_named_params(ma->space))
12712 isl_die(map->ctx, isl_error_invalid,
12713 "unaligned unnamed parameters", goto error);
12714 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
12715 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
12717 return map_preimage_multi_aff(map, type, ma);
12718 error:
12719 isl_multi_aff_free(ma);
12720 return isl_map_free(map);
12723 /* Compute the preimage of "set" under the function represented by "ma".
12724 * In other words, plug in "ma" in "set". The result is a set
12725 * that lives in the domain space of "ma".
12727 __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
12728 __isl_take isl_multi_aff *ma)
12730 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
12733 /* Compute the preimage of the domain of "map" under the function
12734 * represented by "ma".
12735 * In other words, plug in "ma" in the domain of "map".
12736 * The result is a map that lives in the same space as "map"
12737 * except that the domain has been replaced by the domain space of "ma".
12739 __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
12740 __isl_take isl_multi_aff *ma)
12742 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
12745 /* Compute the preimage of the range of "map" under the function
12746 * represented by "ma".
12747 * In other words, plug in "ma" in the range of "map".
12748 * The result is a map that lives in the same space as "map"
12749 * except that the range has been replaced by the domain space of "ma".
12751 __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
12752 __isl_take isl_multi_aff *ma)
12754 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
12757 /* Compute the preimage of "map" under the function represented by "pma".
12758 * In other words, plug in "pma" in the domain or range of "map".
12759 * The result is a map that lives in the same space as "map",
12760 * except that the space of type "type" has been replaced by
12761 * the domain space of "pma".
12763 * The parameters of "map" and "pma" are assumed to have been aligned.
12765 static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
12766 __isl_take isl_map *map, enum isl_dim_type type,
12767 __isl_take isl_pw_multi_aff *pma)
12769 int i;
12770 isl_map *res;
12772 if (!pma)
12773 goto error;
12775 if (pma->n == 0) {
12776 isl_pw_multi_aff_free(pma);
12777 res = isl_map_empty(isl_map_get_space(map));
12778 isl_map_free(map);
12779 return res;
12782 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
12783 isl_multi_aff_copy(pma->p[0].maff));
12784 if (type == isl_dim_in)
12785 res = isl_map_intersect_domain(res,
12786 isl_map_copy(pma->p[0].set));
12787 else
12788 res = isl_map_intersect_range(res,
12789 isl_map_copy(pma->p[0].set));
12791 for (i = 1; i < pma->n; ++i) {
12792 isl_map *res_i;
12794 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
12795 isl_multi_aff_copy(pma->p[i].maff));
12796 if (type == isl_dim_in)
12797 res_i = isl_map_intersect_domain(res_i,
12798 isl_map_copy(pma->p[i].set));
12799 else
12800 res_i = isl_map_intersect_range(res_i,
12801 isl_map_copy(pma->p[i].set));
12802 res = isl_map_union(res, res_i);
12805 isl_pw_multi_aff_free(pma);
12806 isl_map_free(map);
12807 return res;
12808 error:
12809 isl_pw_multi_aff_free(pma);
12810 isl_map_free(map);
12811 return NULL;
12814 /* Compute the preimage of "map" under the function represented by "pma".
12815 * In other words, plug in "pma" in the domain or range of "map".
12816 * The result is a map that lives in the same space as "map",
12817 * except that the space of type "type" has been replaced by
12818 * the domain space of "pma".
12820 __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
12821 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
12823 if (!map || !pma)
12824 goto error;
12826 if (isl_space_match(map->dim, isl_dim_param, pma->dim, isl_dim_param))
12827 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
12829 if (!isl_space_has_named_params(map->dim) ||
12830 !isl_space_has_named_params(pma->dim))
12831 isl_die(map->ctx, isl_error_invalid,
12832 "unaligned unnamed parameters", goto error);
12833 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
12834 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
12836 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
12837 error:
12838 isl_pw_multi_aff_free(pma);
12839 return isl_map_free(map);
12842 /* Compute the preimage of "set" under the function represented by "pma".
12843 * In other words, plug in "pma" in "set". The result is a set
12844 * that lives in the domain space of "pma".
12846 __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
12847 __isl_take isl_pw_multi_aff *pma)
12849 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
12852 /* Compute the preimage of the domain of "map" under the function
12853 * represented by "pma".
12854 * In other words, plug in "pma" in the domain of "map".
12855 * The result is a map that lives in the same space as "map",
12856 * except that domain space has been replaced by the domain space of "pma".
12858 __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
12859 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
12861 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
12864 /* Compute the preimage of the range of "map" under the function
12865 * represented by "pma".
12866 * In other words, plug in "pma" in the range of "map".
12867 * The result is a map that lives in the same space as "map",
12868 * except that range space has been replaced by the domain space of "pma".
12870 __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
12871 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
12873 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
12876 /* Compute the preimage of "map" under the function represented by "mpa".
12877 * In other words, plug in "mpa" in the domain or range of "map".
12878 * The result is a map that lives in the same space as "map",
12879 * except that the space of type "type" has been replaced by
12880 * the domain space of "mpa".
12882 * If the map does not involve any constraints that refer to the
12883 * dimensions of the substituted space, then the only possible
12884 * effect of "mpa" on the map is to map the space to a different space.
12885 * We create a separate isl_multi_aff to effectuate this change
12886 * in order to avoid spurious splitting of the map along the pieces
12887 * of "mpa".
12889 __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
12890 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
12892 int n;
12893 isl_pw_multi_aff *pma;
12895 if (!map || !mpa)
12896 goto error;
12898 n = isl_map_dim(map, type);
12899 if (!isl_map_involves_dims(map, type, 0, n)) {
12900 isl_space *space;
12901 isl_multi_aff *ma;
12903 space = isl_multi_pw_aff_get_space(mpa);
12904 isl_multi_pw_aff_free(mpa);
12905 ma = isl_multi_aff_zero(space);
12906 return isl_map_preimage_multi_aff(map, type, ma);
12909 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
12910 return isl_map_preimage_pw_multi_aff(map, type, pma);
12911 error:
12912 isl_map_free(map);
12913 isl_multi_pw_aff_free(mpa);
12914 return NULL;
12917 /* Compute the preimage of "map" under the function represented by "mpa".
12918 * In other words, plug in "mpa" in the domain "map".
12919 * The result is a map that lives in the same space as "map",
12920 * except that domain space has been replaced by the domain space of "mpa".
12922 __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
12923 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
12925 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
12928 /* Compute the preimage of "set" by the function represented by "mpa".
12929 * In other words, plug in "mpa" in "set".
12931 __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
12932 __isl_take isl_multi_pw_aff *mpa)
12934 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
12937 /* Are the "n" "coefficients" starting at "first" of the integer division
12938 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
12939 * to each other?
12940 * The "coefficient" at position 0 is the denominator.
12941 * The "coefficient" at position 1 is the constant term.
12943 isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
12944 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
12945 unsigned first, unsigned n)
12947 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
12948 return isl_bool_error;
12949 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
12950 return isl_bool_error;
12951 return isl_seq_eq(bmap1->div[pos1] + first,
12952 bmap2->div[pos2] + first, n);
12955 /* Are the integer division expressions at position "pos1" in "bmap1" and
12956 * "pos2" in "bmap2" equal to each other, except that the constant terms
12957 * are different?
12959 isl_bool isl_basic_map_equal_div_expr_except_constant(
12960 __isl_keep isl_basic_map *bmap1, int pos1,
12961 __isl_keep isl_basic_map *bmap2, int pos2)
12963 isl_bool equal;
12964 unsigned total;
12966 if (!bmap1 || !bmap2)
12967 return isl_bool_error;
12968 total = isl_basic_map_total_dim(bmap1);
12969 if (total != isl_basic_map_total_dim(bmap2))
12970 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
12971 "incomparable div expressions", return isl_bool_error);
12972 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
12973 0, 1);
12974 if (equal < 0 || !equal)
12975 return equal;
12976 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
12977 1, 1);
12978 if (equal < 0 || equal)
12979 return isl_bool_not(equal);
12980 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
12981 2, total);
12984 /* Replace the numerator of the constant term of the integer division
12985 * expression at position "div" in "bmap" by "value".
12986 * The caller guarantees that this does not change the meaning
12987 * of the input.
12989 __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
12990 __isl_take isl_basic_map *bmap, int div, int value)
12992 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
12993 return isl_basic_map_free(bmap);
12995 isl_int_set_si(bmap->div[div][1], value);
12997 return bmap;
13000 /* Is the point "inner" internal to inequality constraint "ineq"
13001 * of "bset"?
13002 * The point is considered to be internal to the inequality constraint,
13003 * if it strictly lies on the positive side of the inequality constraint,
13004 * or if it lies on the constraint and the constraint is lexico-positive.
13006 static isl_bool is_internal(__isl_keep isl_vec *inner,
13007 __isl_keep isl_basic_set *bset, int ineq)
13009 isl_ctx *ctx;
13010 int pos;
13011 unsigned total;
13013 if (!inner || !bset)
13014 return isl_bool_error;
13016 ctx = isl_basic_set_get_ctx(bset);
13017 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
13018 &ctx->normalize_gcd);
13019 if (!isl_int_is_zero(ctx->normalize_gcd))
13020 return isl_int_is_nonneg(ctx->normalize_gcd);
13022 total = isl_basic_set_dim(bset, isl_dim_all);
13023 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
13024 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
13027 /* Tighten the inequality constraints of "bset" that are outward with respect
13028 * to the point "vec".
13029 * That is, tighten the constraints that are not satisfied by "vec".
13031 * "vec" is a point internal to some superset S of "bset" that is used
13032 * to make the subsets of S disjoint, by tightening one half of the constraints
13033 * that separate two subsets. In particular, the constraints of S
13034 * are all satisfied by "vec" and should not be tightened.
13035 * Of the internal constraints, those that have "vec" on the outside
13036 * are tightened. The shared facet is included in the adjacent subset
13037 * with the opposite constraint.
13038 * For constraints that saturate "vec", this criterion cannot be used
13039 * to determine which of the two sides should be tightened.
13040 * Instead, the sign of the first non-zero coefficient is used
13041 * to make this choice. Note that this second criterion is never used
13042 * on the constraints of S since "vec" is interior to "S".
13044 __isl_give isl_basic_set *isl_basic_set_tighten_outward(
13045 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
13047 int j;
13049 bset = isl_basic_set_cow(bset);
13050 if (!bset)
13051 return NULL;
13052 for (j = 0; j < bset->n_ineq; ++j) {
13053 isl_bool internal;
13055 internal = is_internal(vec, bset, j);
13056 if (internal < 0)
13057 return isl_basic_set_free(bset);
13058 if (internal)
13059 continue;
13060 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
13063 return bset;